@layer pages {

/*
 * Map-visualization styling, themed to the FindingHome logo:
 * sky blue, dark teal, and mint-green accents on a soft mint background.
 * Uses the app-wide tokens (tokens.css) directly.
 */

/* ---- layout (fixed below the nav; map + sidebar fill the viewport) ---- */
#viz-root {
  position: fixed;
  top: var(--viz-top, 64px);
  left: 0;
  right: 0;
  bottom: var(--footer-height, 0px);
  /* Above the footer, so modal overlays inside #viz-root cover it too, and
     clipped, so the closed mobile search sheet below it doesn't. */
  z-index: 1;
  overflow: clip;
  display: flex;
  text-align: left;
  background: var(--color-bg-subtle);
  color: var(--color-ink);
  font-family: var(--font-family-base);
}

/* The legal links stay visible below the map; #viz-root ends at
   --footer-height, which MapController keeps in sync. */
.site-footer {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  padding: var(--space-2) var(--space-4);
  background: var(--color-bg);
}

#viz-map {
  flex: 1 1 auto;
  height: 100%;
  position: relative;
  background: var(--color-accent-tint);
}

#viz-search-panel {
  flex: 0 0 26%;
  max-width: 26%;
  height: 100%;
  overflow-y: auto;
  box-sizing: border-box;
  padding: 20px 18px 28px;
  background: linear-gradient(180deg, var(--color-bg-subtle) 0%, var(--color-accent-tint) 100%);
  box-shadow: 2px 0 14px rgba(23, 64, 63, 0.1);
}

/* Tinted scrollbar to match the panel. */
#viz-search-panel {
  scrollbar-width: thin;
  scrollbar-color: var(--color-accent) transparent;
}
#viz-search-panel::-webkit-scrollbar {
  width: 9px;
}
#viz-search-panel::-webkit-scrollbar-thumb {
  background: var(--color-accent);
  border-radius: 9px;
}

/* ---- error banner ---- */
#viz-error-banner {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 10;
  display: none;
  padding: 12px 16px;
  background: var(--color-danger);
  color: var(--color-bg);
  font-weight: 700;
  box-shadow: var(--shadow-panel);
}
#viz-error-banner.is-visible {
  display: block;
}
#viz-error-banner button {
  margin-left: 12px;
  border: 0;
  border-radius: 999px;
  padding: 4px 14px;
  background: var(--color-bg);
  color: var(--color-danger);
  font-weight: 700;
  cursor: pointer;
}

/* ---- map legend ---- */
/* Swatches use the same --color-map-* tokens the map layers paint with
   (via mapColor(), map-colors.js), so legend and map always match. */
.viz-map-legend {
  position: absolute;
  left: 10px;
  bottom: 34px;
  z-index: 5;
  margin: 0;
  padding: 8px 12px;
  list-style: none;
  background: rgba(255, 255, 255, 0.92);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-panel);
  font-size: 12px;
  font-weight: 700;
  color: var(--color-ink);
}
.viz-map-legend li {
  display: flex;
  align-items: center;
  gap: 8px;
  white-space: nowrap;
}
.viz-map-legend li + li {
  margin-top: 4px;
}
.viz-legend-swatch {
  width: 14px;
  height: 14px;
  border-radius: 4px;
  flex: 0 0 auto;
}
.viz-legend-swatch--result {
  background: var(--color-map-area);
}
.viz-legend-swatch--place {
  /* 15%: same as the place's isochrone fill-opacity (custom-location-layer.js). */
  background: color-mix(in srgb, var(--color-map-place) 15%, transparent);
  border: 2px dashed var(--color-map-place);
  box-sizing: border-box;
}
.viz-legend-swatch--listing {
  border-radius: 50%;
  background: var(--color-map-listing);
}

/* ---- drawer toggle (mobile) ---- */
#viz-drawer-toggle {
  display: none;
  position: absolute;
  top: 12px;
  left: 12px;
  /* Must stay above #viz-search-panel's own z-index (12 when open on
     mobile, below) so the toggle remains clickable as a close button
     instead of being covered by the open panel. */
  z-index: 13;
  padding: 9px 14px;
  background: var(--color-primary);
  color: var(--color-bg);
  border: 0;
  border-radius: 999px;
  font-weight: 700;
  box-shadow: var(--shadow-panel);
  cursor: pointer;
}

/* ---- search panel content ---- */
#viz-search-panel h2 {
  margin: 0 0 16px;
  font-size: 22px;
  font-weight: 800;
  color: var(--color-ink);
  letter-spacing: 0.2px;
}
#viz-search-panel h2::after {
  content: "";
  display: block;
  width: 56px;
  height: 5px;
  margin-top: 6px;
  border-radius: 999px;
  background: var(--color-accent);
}

/* Category groups and the listing filters: plain sections divided by a
   hairline, with sentence-case headings (cards are reserved for
   listings, see docs/frontend-components.md). */
.sp-category-group,
.sp-listing-filters {
  min-width: 0;
  margin: 0;
  padding: 12px 0 8px;
  border: 0;
  border-top: 1px solid var(--color-line);
}
.sp-category-group:first-child {
  border-top: 0;
  padding-top: 0;
}
/* Floated so the legend sits inside the section instead of cutting into
   its top border (default fieldset rendering). */
.sp-category-group legend,
.sp-listing-filters legend {
  float: left;
  width: 100%;
  margin: 0 0 4px;
  padding: 0;
  font-size: 16px;
  font-weight: 800;
  color: var(--color-ink);
}

/* Subcategory rows. A checked item's travel controls wrap onto their own
   line, indented to start under the item's label (checkbox 20px + 8px
   gap). */
.sp-subcategory {
  clear: both;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  padding: 6px 8px;
  border-radius: var(--radius-md);
}
.sp-subcategory:hover {
  background: var(--color-accent-tint);
}
.sp-subcategory label {
  flex: 1 1 auto;
  font-size: 15px;
  font-weight: 600;
  color: var(--color-ink);
  cursor: pointer;
}
.sp-subcategory-controls {
  display: flex;
  flex: 1 0 calc(100% - 28px);
  gap: 6px;
  margin-left: 28px;
}
.sp-subcategory-controls:empty {
  display: none;
}

/* Custom checkboxes in brand blue. */
.sp-subcategory-checkbox {
  appearance: none;
  -webkit-appearance: none;
  width: 20px;
  height: 20px;
  margin: 0;
  border: 2px solid var(--color-primary);
  border-radius: 6px;
  background: var(--color-bg);
  cursor: pointer;
  position: relative;
  flex: 0 0 auto;
  transition: background 0.15s ease, border-color 0.15s ease;
}
.sp-subcategory-checkbox:checked {
  background: var(--color-primary);
  border-color: var(--color-primary);
}
.sp-subcategory-checkbox:checked::after {
  content: "";
  position: absolute;
  left: 6px;
  top: 2px;
  width: 5px;
  height: 10px;
  border: solid var(--color-bg);
  border-width: 0 2.5px 2.5px 0;
  transform: rotate(45deg);
}
.sp-subcategory-checkbox:focus-visible {
  outline: 3px solid rgba(19, 144, 207, 0.4);
  outline-offset: 1px;
}

/* Dropdowns. */
.sp-travel-mode,
.sp-time-interval,
#sp-place {
  font-family: inherit;
  font-size: 14px;
  color: var(--color-ink);
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 5px 8px;
}
.sp-travel-mode:focus,
.sp-time-interval:focus,
#sp-place:focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px rgba(19, 144, 207, 0.25);
}

/* Listing filters: each filter's label on its own line, then its select
   (full width) or min/max inputs (side by side). */
.sp-listing-filters > div {
  clear: both;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 4px 6px;
  margin-bottom: 10px;
}
.sp-listing-filters > div > label,
.sp-listing-filters > div > span,
#sp-listing-type {
  grid-column: 1 / -1;
}
.sp-listing-filters > div > label,
.sp-listing-filters > div > span {
  font-size: 14px;
  font-weight: 600;
  color: var(--color-ink);
}
#sp-listing-type,
.sp-range input {
  min-width: 0;
  font-family: inherit;
  font-size: 14px;
  color: var(--color-ink);
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 5px 8px;
}

/* "Go to place": moves the map, so it sits above the criteria. */
.sp-place-form {
  margin-bottom: 12px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--color-line);
}
.sp-place-form label {
  display: block;
  margin-bottom: 6px;
  font-weight: 600;
  font-size: 14px;
  color: var(--color-ink);
}
.sp-place-row {
  display: flex;
  gap: 6px;
}
#sp-place {
  flex: 1;
  min-width: 0;
}
.sp-place-message:empty {
  display: none;
}
.sp-place-message {
  margin: 6px 0 0;
  font-size: 13px;
  color: var(--color-danger-strong);
}

/* First-run guide (an actual sequence, so numbered). Hidden via the
   [hidden] attribute once a criterion is selected. */
.sp-guide {
  margin: 0 0 18px;
  padding: 14px 16px 14px 36px;
  border: 2px dashed var(--color-primary);
  border-radius: var(--radius-md);
  color: var(--color-ink);
  font-size: 15px;
}
.sp-guide li + li {
  margin-top: 6px;
}
.sp-guide li::marker {
  color: var(--color-primary);
  font-weight: 800;
}

/* Sticky action footer: keeps Search in view while the criteria list
   scrolls. The negative inline margins and bottom offset cancel
   #viz-search-panel's padding, so the footer spans the panel edge to
   edge and sits flush with its bottom. */
.sp-actions {
  position: sticky;
  bottom: -28px;
  z-index: 1;
  margin: 12px -18px 0;
  padding: 10px 18px 16px;
  border-top: 1px solid var(--color-border);
  background: var(--color-accent-tint);
}

/* Validation message. */
#sp-validation {
  min-height: 0;
  margin: 14px 0 8px;
  color: var(--color-danger);
  font-weight: 700;
  font-size: 14px;
}
#sp-validation:empty {
  display: none;
}

/* Search button. */
#sp-search {
  width: 100%;
  margin-top: 6px;
  padding: 13px 18px;
  border: 0;
  border-radius: 999px;
  background: linear-gradient(180deg, var(--color-primary) 0%, var(--color-primary-strong) 100%);
  color: var(--color-bg);
  font-family: inherit;
  font-size: 16px;
  font-weight: 800;
  letter-spacing: 0.3px;
  cursor: pointer;
  box-shadow: 0 4px 12px rgba(19, 144, 207, 0.35);
  transition: transform 0.08s ease, box-shadow 0.15s ease, filter 0.15s ease;
}
#sp-search:hover:not(:disabled) {
  filter: brightness(1.05);
  box-shadow: 0 6px 16px rgba(19, 144, 207, 0.45);
}
#sp-search:active:not(:disabled) {
  transform: translateY(1px);
}
#sp-search:disabled {
  /* One-off disabled-state grey; no app-wide token is a close enough match. */
  background: #b9cdc6;
  box-shadow: none;
  cursor: not-allowed;
}

/* Loading + results. */
#sp-loading {
  margin-top: 12px;
  font-weight: 700;
  color: var(--color-secondary);
}
#sp-results {
  font-size: 17px;
  font-weight: 800;
  color: var(--color-ink);
}
/* Sits in the sticky footer (tinted), so it takes the white panel card
   look to stand apart from it. */
#sp-results:not(:empty) {
  margin-top: 10px;
  padding: 10px 14px;
  background: var(--color-bg);
  border-radius: var(--radius-md);
}

/* ---- listing results (listing-results-list.js) ---- */
/* Same section rhythm as #viz-custom-panel below. These are listings, so
   they are allowed to be cards (docs/frontend-components.md). The card of
   a hovered marker gets .is-active, the same look as :hover. */
#viz-listing-results {
  margin-top: 22px;
  padding-top: 18px;
  border-top: 2px dashed var(--color-border);
}
#viz-listing-results h2 {
  margin: 0 0 4px;
}
.listing-results__count {
  margin: 0 0 var(--space-3);
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
}
.listing-results {
  display: grid;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}
.listing-alert {
  margin-top: var(--space-3);
  font-size: var(--font-size-sm);
}
.listing-alert--prominent {
  text-align: center;
}
.listing-alert__link {
  padding: 0;
  border: 0;
  background: none;
  color: var(--color-primary);
  font: inherit;
  text-decoration: underline;
  cursor: pointer;
}
.listing-alert__status {
  margin: var(--space-2) 0 0;
  color: var(--color-text-muted);
}
.listing-alert__status:empty {
  display: none;
}
.listing-alert__status.is-error {
  color: var(--color-danger);
}
/* "Find more listings" (SearchRecommendations): one button per change. */
.listing-recommendations {
  margin-top: var(--space-4);
}
.listing-recommendations[hidden] {
  display: none;
}
.listing-recommendations h3 {
  margin: 0 0 var(--space-2);
  font-size: var(--font-size-base);
}
.listing-recommendations ul {
  display: grid;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}
.listing-recommendation {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  min-height: var(--touch-target-min);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-bg);
  color: var(--color-ink);
  font: inherit;
  font-size: var(--font-size-sm);
  text-align: left;
  cursor: pointer;
}
.listing-recommendation:hover,
.listing-recommendation:focus-visible {
  border-color: var(--color-primary);
}
.listing-recommendation__count {
  flex: none;
  color: var(--color-primary);
  font-weight: 800;
}
.listing-result {
  display: grid;
  grid-template-columns: 96px 1fr;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  min-height: var(--touch-target-min);
  padding: var(--space-2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-bg);
  color: var(--color-text);
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.listing-result:hover,
.listing-result.is-active {
  border-color: var(--color-primary);
  box-shadow: inset 0 0 0 1px var(--color-primary);
}
/* The listing whose detail is open; combines with the hover outline. */
.listing-result.is-selected {
  border-color: var(--color-primary);
  background: var(--color-accent-tint);
  box-shadow: inset 4px 0 0 var(--color-accent);
}
.listing-result.is-selected:hover,
.listing-result.is-selected.is-active {
  box-shadow:
    inset 4px 0 0 var(--color-accent),
    inset 0 0 0 1px var(--color-primary);
}
/* Placeholder tint when the listing has no cover photo. */
.listing-result__photo {
  display: block;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  border-radius: var(--radius-sm);
  background: var(--color-accent-tint);
}
.listing-result__photo img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.listing-result__body {
  display: grid;
  gap: var(--space-1);
  min-width: 0;
}
.listing-result__type,
.listing-result__facts {
  font-size: var(--font-size-sm);
}
/* A listing whose address isn't for publication. */
.listing-result__approximate {
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
}
.listing-result__type {
  color: var(--color-text-muted);
}
.listing-result__price {
  color: var(--color-ink);
  font-weight: var(--font-weight-bold);
}

/* ---- map popups (your places) ---- */
.fh-popup {
  font-family: var(--font-family-base);
  color: var(--color-ink);
  font-size: 14px;
  line-height: 1.5;
}
.fh-popup-row strong {
  color: var(--color-ink);
}

/* ---- responsive: mobile bottom sheet ---- */
@media (max-width: 767px) {
  #viz-search-panel {
    position: absolute;
    top: auto;
    left: 0;
    right: 0;
    bottom: 0;
    flex-basis: auto;
    max-width: none;
    /* % of #viz-root's own (fixed) height, not vh of the full viewport --
       #viz-root already excludes the site header via --viz-top below, so a
       vh-based sheet would ignore that and eat further into the remaining
       map area than intended. */
    max-height: 55%;
    z-index: 12;
    /* #viz-drawer-toggle stays pinned to #viz-root's top-left corner (see
       its own rule below), well above this sheet's top edge, so no
       clearance padding is needed here as it was for the old full-height
       left drawer. */
    transform: translateY(100%);
    transition: transform 0.25s ease;
  }
  #viz-search-panel.is-open {
    transform: translateY(0);
  }
  #viz-drawer-toggle {
    display: block;
  }
}

/* ---- custom locations ("My places") panel ---- */
#viz-custom-panel {
  margin-top: 22px;
  padding-top: 18px;
  border-top: 2px dashed var(--color-border);
}
#viz-custom-panel h2 {
  margin: 0 0 4px;
  color: var(--color-ink);
}
.cp-intro {
  margin: 0 0 12px;
  font-size: 0.85rem;
  color: var(--color-secondary);
}
.cp-field {
  display: flex;
  flex-direction: column;
  margin-bottom: 10px;
}
.cp-field label {
  font-size: 0.8rem;
  font-weight: 700;
  margin-bottom: 4px;
  color: var(--color-ink);
}
.cp-field input,
.cp-field select {
  padding: 8px 10px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-bg);
  color: var(--color-ink);
  font: inherit;
}
.cp-pick,
.cp-add {
  width: 100%;
  padding: 9px 12px;
  border: none;
  border-radius: var(--radius-md);
  font-weight: 700;
  cursor: pointer;
  margin-bottom: 8px;
}
.cp-pick {
  background: var(--color-bg);
  color: var(--color-map-place);
  border: 1px solid var(--color-map-place);
}
.cp-pick.is-active {
  background: var(--color-map-place);
  color: var(--color-bg);
}
.cp-add {
  background: var(--color-map-place);
  color: var(--color-bg);
}
.cp-add:disabled {
  opacity: 0.6;
  cursor: default;
}
.cp-status {
  min-height: 1.2em;
  margin: 4px 0;
  font-size: 0.82rem;
  color: var(--color-secondary);
}
.cp-status.is-error {
  color: var(--color-danger);
}
.cp-list {
  list-style: none;
  margin: 8px 0 0;
  padding: 0;
}
.cp-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 8px 10px;
  margin-bottom: 6px;
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-left: 4px solid var(--color-map-place);
  border-radius: var(--radius-md);
}
.cp-item-toggle {
  flex: 0 0 auto;
  accent-color: var(--color-map-place);
  cursor: pointer;
}
.cp-item-info {
  display: flex;
  flex-direction: column;
}
.cp-item-name {
  font-weight: 700;
  color: var(--color-ink);
}
.cp-item-meta {
  font-size: 0.78rem;
  color: var(--color-secondary);
}
.cp-remove {
  border: none;
  background: transparent;
  color: var(--color-danger);
  font-size: 1rem;
  cursor: pointer;
  line-height: 1;
  padding: 4px 6px;
  border-radius: var(--radius-md);
}
.cp-remove:hover {
  background: var(--color-accent-tint);
}

/* ---- share panel (task 4.2) ---- */
/* Same section rhythm as #viz-custom-panel above: a dashed divider
   separates each sidebar section, and the shared #viz-search-panel h2
   rule (swoosh underline) already applies to every h2 in the sidebar. */
#viz-share-panel {
  margin-top: 22px;
  padding-top: 18px;
  border-top: 2px dashed var(--color-border);
}
#viz-share-panel h2 {
  margin: 0 0 4px;
  color: var(--color-ink);
}
.share-btn {
  width: 100%;
  padding: 9px 12px;
  border: none;
  border-radius: var(--radius-md);
  font-weight: 700;
  cursor: pointer;
  margin-bottom: 8px;
  background: var(--color-primary);
  color: var(--color-bg);
}
.share-btn:disabled {
  opacity: 0.6;
  cursor: default;
}
.share-link-wrap {
  display: flex;
  gap: 6px;
  margin-bottom: 6px;
}
.share-link-input {
  flex: 1 1 auto;
  min-width: 0;
  padding: 8px 10px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-bg);
  color: var(--color-ink);
  font: inherit;
}
.share-copy-btn {
  flex: 0 0 auto;
  padding: 8px 12px;
  border: 1px solid var(--color-primary);
  border-radius: var(--radius-md);
  background: var(--color-bg);
  color: var(--color-primary-strong);
  font-weight: 700;
  cursor: pointer;
}
.share-status {
  min-height: 1.2em;
  margin: 4px 0;
  font-size: 0.82rem;
  color: var(--color-secondary);
}
.share-status.is-error {
  color: var(--color-danger);
}

/* ---- saved search actions: save / update / share (task 5) ---- */
/* Same section rhythm as the panels above; name field reuses
   #viz-custom-panel's existing .cp-field (label + input) as-is. */
#viz-saved-search-actions {
  margin-top: 22px;
  padding-top: 18px;
  border-top: 2px dashed var(--color-border);
}
#viz-saved-search-actions h2 {
  margin: 0 0 4px;
  color: var(--color-ink);
}
/* "Resolved" pill (components/state.css's .state-resolved supplies the fill/color;
   this adds the sizing) naming which saved search Update/Share would act
   on -- the same line=searching/fill=found motif the rest of the product
   uses for an in-progress vs. settled state. */
.saved-search-linked-indicator {
  display: inline-block;
  margin: 0 0 12px;
  padding: 5px 12px;
  border-radius: 999px;
  font-size: 0.8rem;
  font-weight: 700;
}
.saved-search-save-btn,
.saved-search-update-btn {
  width: 100%;
  padding: 9px 12px;
  border: none;
  border-radius: var(--radius-md);
  font-weight: 700;
  cursor: pointer;
  margin-bottom: 8px;
  color: var(--color-bg);
}
.saved-search-save-btn {
  background: var(--color-primary);
}
.saved-search-save-btn:hover:not(:disabled) {
  background: var(--color-primary-strong);
}
/* Sage green, not blue: only ever shown once a saved search is linked
   (the same "resolved" state .saved-search-linked-indicator marks), so it
   reads as "confirm changes to this" rather than "start something new"
   (the save button's blue, matching the main #sp-search action). */
.saved-search-update-btn {
  background: var(--color-found-strong);
}
.saved-search-update-btn:hover:not(:disabled) {
  filter: brightness(0.92);
}
.saved-search-save-btn:disabled,
.saved-search-update-btn:disabled {
  opacity: 0.6;
  cursor: default;
}
.saved-search-status {
  min-height: 1.2em;
  margin: 4px 0;
  font-size: 0.82rem;
  color: var(--color-secondary);
}
.saved-search-status.is-error {
  color: var(--color-danger);
}

/* ---- shared-search read-only mode (task 4.3) ---- */
.shared-search-banner {
  padding: 10px 12px;
  margin-bottom: 12px;
  border-radius: var(--radius-md);
  background: var(--color-accent-tint);
  color: var(--color-ink);
  font-weight: 700;
  font-size: 0.88rem;
}
.shared-search-error {
  color: var(--color-danger);
  font-weight: 700;
}
.shared-criteria-list,
.shared-location-list {
  list-style: none;
  margin: 8px 0 16px;
  padding: 0;
}
.shared-criteria-list li,
.shared-location-list li {
  padding: 8px 10px;
  margin-bottom: 6px;
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  font-size: 0.85rem;
}

/* ---- login-time conflict prompt (task 4.4) ---- */
.login-conflict-overlay {
  position: fixed;
  inset: 0;
  background: rgba(23, 64, 63, 0.45);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
}
.login-conflict-dialog {
  background: var(--color-bg);
  color: var(--color-ink);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-panel);
  padding: 24px;
  max-width: 420px;
  width: calc(100% - 40px);
}
.login-conflict-actions {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 16px;
}
.login-conflict-actions button {
  padding: 10px 14px;
  border-radius: var(--radius-md);
  font-weight: 700;
  cursor: pointer;
}
.login-conflict-keep {
  border: none;
  background: var(--color-primary);
  color: var(--color-bg);
}
.login-conflict-use {
  border: 1px solid var(--color-border);
  background: var(--color-bg);
  color: var(--color-ink);
}

/* ---- pre-login save-search nudge ---- */
/* Mirrors #viz-error-banner's floating-banner pattern (z-index one below
   it, so the error banner wins visually if both are ever shown at once).
   Without this, the container renders as an unstyled flex item squeezed
   into #viz-root's row between the search panel and the map.
   Unlike #viz-error-banner (nested inside #viz-map, so its left/right: 0
   is already scoped to the map's width), #viz-save-search-nudge is a
   sibling of #viz-search-panel positioned against #viz-root itself — so
   left must match the search panel's own desktop width (flex: 0 0 26%
   above) or the banner would span over the panel too and cover its
   heading. Overridden back to left: 0 on mobile, where the panel is
   taken out of flow as an off-canvas sheet instead. */
#viz-save-search-nudge {
  position: absolute;
  top: 0;
  left: 26%;
  right: 0;
  z-index: 9;
}
/* This override must stay *after* the base #viz-save-search-nudge rule
   above: both are plain ID selectors of equal specificity, so with a
   media query positioned earlier in the file (like the mobile bottom
   sheet block), the later unconditional rule would otherwise win at
   every viewport width, mobile included. */
@media (max-width: 767px) {
  #viz-save-search-nudge {
    left: 0;
    /* #viz-drawer-toggle sits at top:12px, ~40px tall, over the map on
       mobile (unchanged by the bottom-sheet conversion). At top: 0 the
       nudge would render directly behind/under it, obscuring the
       toggle's own label. Clear it, same idea as the drawer's old
       toggle-clearance padding. */
    top: 60px;
  }
}
.save-search-nudge {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  background: var(--color-accent-tint);
  color: var(--color-ink);
  font-size: 0.88rem;
  font-weight: 700;
}
.save-search-nudge a {
  color: var(--color-primary);
  text-decoration: underline;
}
.save-search-nudge-dismiss {
  margin-left: auto;
  border: none;
  background: transparent;
  color: inherit;
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
}

/* ---- listing detail panel (tasks 5.1/5.2) ---- */
.viz-listing-detail {
  position: absolute;
  top: 16px;
  right: 16px;
  bottom: 16px;
  width: 320px;
  max-width: calc(100% - 32px);
  overflow-y: auto;
  /* A modal: above the open mobile drawer (12) and its toggle (13), since
     a result card in the drawer opens it. */
  z-index: 14;
  background: var(--color-bg);
  color: var(--color-ink);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-panel);
  padding: 20px;
  box-sizing: border-box;
}
/* Order in the panel: gallery (cover first), address, price, facts,
   realtor, actions. */
.viz-listing-detail-gallery {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 6px;
  margin: -4px -4px 16px;
}
/* Each tile is a button that opens the photo viewer; the focus ring comes
   from base.css. */
.viz-listing-detail-photo {
  display: block;
  padding: 0;
  border: none;
  border-radius: var(--radius-md);
  background: none;
  cursor: zoom-in;
}
.viz-listing-detail-photo img {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--radius-md);
}
/* The cover photo spans the panel; the rest follow as thumbnails. */
.viz-listing-detail-photo:first-child {
  grid-column: 1 / -1;
}
.viz-listing-detail-photo:first-child img {
  aspect-ratio: 3 / 2;
}
.viz-listing-detail h2 {
  margin: 0 32px 2px 0;
  font-size: 1.15rem;
}
.viz-listing-detail-address {
  margin: 0 0 12px;
  color: var(--color-secondary);
}
/* In place of the address when it isn't for publication. */
.viz-listing-detail-approximate {
  margin: 0 0 12px;
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
}
/* Status of a listing that is no longer active. */
.viz-listing-detail > .badge {
  margin-bottom: 12px;
}
.viz-listing-detail-price {
  display: flex;
  flex-direction: column;
  margin: 0 0 14px;
}
.viz-listing-detail-price span {
  color: var(--color-text-muted);
  font-size: 0.85rem;
}
.viz-listing-detail-price strong {
  color: var(--color-ink);
  font-size: 1.5rem;
  font-weight: 800;
  line-height: 1.2;
}
.viz-listing-detail-facts {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px 12px;
  margin: 0 0 14px;
  padding: 12px 0;
  border-top: 1px solid var(--color-border);
  border-bottom: 1px solid var(--color-border);
}
.viz-listing-detail-facts dt {
  color: var(--color-text-muted);
  font-size: 0.8rem;
}
.viz-listing-detail-facts dd {
  margin: 0;
  font-weight: 700;
}
/* Costs, details, features, energy certificate, description. */
.viz-listing-detail-section {
  margin: 0 0 14px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--color-border);
}
.viz-listing-detail-section h3 {
  margin: 0 0 8px;
  color: var(--color-ink);
  font-size: 0.95rem;
}
.viz-listing-detail-section p {
  margin: 0;
}
.viz-listing-detail-section-facts {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px 12px;
  margin: 0;
  font-size: 0.9rem;
}
.viz-listing-detail-section-facts > div {
  display: contents;
}
.viz-listing-detail-section-facts dt {
  color: var(--color-text-muted);
}
.viz-listing-detail-section-facts dd {
  margin: 0;
}
.viz-listing-detail-description {
  white-space: pre-line;
}
.viz-listing-detail-realtor {
  margin: 0 0 16px;
  color: var(--color-text-muted);
  font-size: 0.9rem;
}
.viz-listing-detail-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.viz-listing-detail-copy-status {
  margin: 0 0 8px;
  color: var(--color-text-muted);
  font-size: 0.9rem;
  overflow-wrap: anywhere;
}
.viz-listing-detail-copy-status:empty {
  margin: 0;
}
.viz-listing-detail-favorite {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: var(--touch-target-min);
  padding: 6px 14px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--color-ink);
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
}
.viz-listing-detail-favorite__icon {
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
}
.viz-listing-detail-favorite[aria-pressed="true"] {
  border-color: var(--color-secondary);
  color: var(--color-secondary);
}
.viz-listing-detail-favorite[aria-pressed="true"] .viz-listing-detail-favorite__icon {
  fill: currentColor;
}
.viz-listing-detail-favorite:disabled {
  opacity: 0.6;
  cursor: default;
}
/* Sits over the cover photo, so it gets its own backing disc. */
.viz-listing-detail-close {
  position: absolute;
  top: 12px;
  right: 12px;
  z-index: 1;
  width: 32px;
  height: 32px;
  border: none;
  border-radius: 50%;
  background: var(--color-bg);
  box-shadow: var(--shadow-sm);
  color: var(--color-ink);
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
}
.viz-listing-detail-error {
  color: var(--color-danger);
}
.login-conflict-status {
  min-height: 1.2em;
  margin: 10px 0 0;
  font-size: 0.82rem;
  color: var(--color-danger);
}

}
