/**
 * listing-detail.css
 *
 * All styling for views/listing-detail.php — loaded only on listing
 * detail pages (see layouts/head.php's $isListingDetailPage check).
 *
 * The gallery (hero image + thumbnail strip) is built client-side by the
 * <script> block at the bottom of views/listing-detail.php, which fetches
 * listing-photos-ajax.php and swaps the placeholder's innerHTML — plain
 * onclick handlers wire up thumbnail clicks, not CSS. Unlike the old
 * CSS-only radio/label gallery this replaced, nothing here needs to vary
 * per photo count, so it's all static and there's no PHP-generated CSS
 * anywhere on this page anymore.
 */

.ld-wrap {
  max-width: 960px;
  margin: 0 auto;
  padding: 24px 16px 48px;
  color: #12233D;
}

.ld-notfound,
.ld-inactive {
  text-align: center;
  padding: 60px 16px;
}

/* ---- Back button, above the address/price block ---- */
/* Plain button styled as a link — no navigation target of its own (see
   the inline onclick="history.back()" in views/listing-detail.php), so
   an <a href> would be misleading here. */
.ld-back-btn {
  display: inline-block;
  margin-bottom: 12px;
  padding: 0;
  border: none;
  background: none;
  color: #4B5A70;
  font-size: 14px;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
}

.ld-back-btn:hover {
  color: #12233D;
  text-decoration: underline;
}

/* ---- New: address + price, above the gallery ---- */
/* The only place price/address show above the fold now — .ld-facts-band
   below (further down this file) used to show its own copy too, removed
   as redundant once this block existed. Laid out as one row: address
   filling the left, price pinned to the right. Markup order matches
   this visual order (address first, then price) — no CSS `order` trick
   needed. Price still reads as the slightly more prominent of the two
   (bigger/bolder), just a smaller gap between them than an earlier pass
   at this block used — feedback was that the size difference read as
   too large.

   .ld-top-price never wraps or shrinks (flex: 0 0 auto + white-space:
   nowrap) — a price must never break across lines, full stop. .ld-wrap's
   960px width leaves plenty of room even for the longest real price
   seen in this project's data ($50,000,000) at this size.
   .ld-top-address instead gets flex: 1 1 auto + min-width: 0,
   which lets its box shrink to whatever room is left after price takes
   what it needs — if a long price and a long address ever landed
   together, the address wraps normally (word boundaries only, never
   mid-word) within its own remaining space rather than forcing the row
   to overflow or the two to collide. This flex role (fixed-nowrap vs.
   shrink-and-wrap) stays tied to price/address respectively regardless
   of which side of the row each one sits on. */
.ld-top-info {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 20px;
  margin-bottom: 20px;
}

.ld-top-address {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 28px;
  font-weight: 700;
  color: #4B5A70;
  line-height: 1.25;
  margin: 0;
}

.ld-top-price {
  flex: 0 0 auto;
  font-size: 34px;
  font-weight: 800;
  color: #12233D;
  line-height: 1.1;
  margin: 0;
  text-align: right;
}

/* ---- Status banner (Pending/ActiveUnderContract/Closed only) ---- */
/* Sits between the back button and .ld-top-info — see
   views/listing-detail.php's own $statusBannerLabel for exactly which
   statuses render this. Active itself never gets one. */
.ld-status-banner {
  display: inline-block;
  margin: 0 0 12px;
  padding: 5px 14px;
  border-radius: 6px;
  font-size: 13px;
  font-weight: 800;
  letter-spacing: 0.04em;
}

.ld-status-banner--under-contract {
  background: #FEF3C7;
  color: #92400E;
}

.ld-status-banner--sold {
  /* Was a light GREEN pairing (#DCFCE7/#166534) — misleadingly read as
     "good news" rather than "sold/unavailable" and didn't match the
     red/yellow/green convention listing-card.php's own status badge
     later established (listingCardStatusBadge(): Closed -> red). Same
     light-background/dark-text pill shape as --under-contract above,
     just red instead of green. */
  background: #FEE2E2;
  color: #991B1B;
}

/* ---- Closed-with-known-sale-price: primary "Sold for $X" line, ---- */
/* ---- list_price demoted to a smaller secondary line beneath it ---- */
/* .ld-top-price itself (above) no longer sets its own white-space —
   these two spans are its only children and set that individually,
   since the secondary line (when present) needs to sit on its own
   line beneath the primary one, not fight it for the same row. */
.ld-top-price-primary {
  display: block;
  white-space: nowrap;
}

.ld-top-price-secondary {
  display: block;
  font-size: 15px;
  font-weight: 600;
  color: #5B6B82;
  margin-top: 2px;
  white-space: nowrap;
}

@media (max-width: 720px) {
  /* Two large bold elements can't share one line on a narrow screen
     regardless of length — same breakpoint this block already used for
     its own font-size step-down, now also switching the row to a
     column so price and address stack instead of fighting for width. */
  .ld-top-info {
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
  }

  .ld-top-address {
    flex: 0 0 auto;
    width: 100%;
    font-size: 20px;
  }

  .ld-top-price {
    font-size: 24px;
  }
}

/* ---- Full-width gallery, facts band below it ---- */
/* The gallery used to share a flex row with a sticky facts sidebar
   (.ld-sidebar, removed) — it's now a plain full-width block, and
   everything that was in that sidebar (price/address/days on market/
   the 6 facts) lives in .ld-facts-band immediately below instead. */

/* Positioning context for .ld-hero-save-btn (position: absolute, top/
   right offsets) — see that rule below. #ld-gallery itself starts flush
   with this box's own top/right edges (no padding here, no margin on
   .ld-hero-wrap), so anchoring to .ld-hero-col lands the button exactly
   in the hero photo's own top-right corner, never the thumbnail strip
   below it. */
.ld-hero-col {
  position: relative;
  margin-bottom: 20px;
}

/* The 7 facts (Beds/Baths/Sq Ft/$-per-Sq-Ft/Acres/Year Built/Days on
   Market), so the whole band stays visible without scrolling right below
   the photos, rather than the old sidebar's tall single-column stack.
   Price/address used to live here too, in their own .ld-facts-band-top
   flex row — removed as redundant now that .ld-top-info above the
   gallery shows both. Days on market used to be its own small-text line
   above this grid (.ld-dom, removed) — it's just the 7th stat now, same
   treatment as the other 6. */
.ld-facts-band {
  border: 1px solid #DCE1E8;
  border-radius: 8px;
  background: #F7F8FA;
  padding: 20px 28px;
  margin-bottom: 32px;
  box-sizing: border-box;
}

/* Flex, not a fixed-column grid — a fixed 2-column grid was tried here
   and reverted: it forced exactly 2 stats per row even on a wide screen
   with plenty of room for all 7 inline, which is a regression from how
   this band always looked. Flex-wrap keeps that original "fits as many
   as the available width allows" behavior (all 7 inline at typical
   desktop widths, wrapping only where a narrower viewport actually
   requires it) — the 7th stat (Days on Market) is just one more item in
   the same flow, no special-casing needed; flex has no fixed column
   count for it to disrupt or leave an empty cell in.
   No margin-top/padding-top/border-top here — those used to separate
   this row from the days-on-market line that sat above it inside the
   same card; now this is the first thing in the card (.ld-facts-band's
   own padding already provides the top gap), so a divider with nothing
   above it to divide from would just be a stray line. */
.ld-facts-band-stats {
  display: flex;
  flex-wrap: wrap;
  gap: 20px 40px;
}

@media (max-width: 720px) {
  .ld-facts-band {
    padding: 16px 20px;
  }

  .ld-facts-band-stats {
    gap: 18px 28px;
  }
}

/* ---- Build Comps button, inside the facts band itself ---- */
/* Was its own row separated from the stats grid by a divider line —
   removed: this is now just one more item in .ld-facts-band-stats's own
   flex row (see views/listing-detail.php), so it reads as one
   continuous card instead of two visually distinct sections.
   align-self: center keeps its own natural (shorter) height rather than
   stretching to match the taller value/label .ld-fact blocks beside it
   (.ld-facts-band-stats sets no align-items of its own, so the flex
   default — stretch — would otherwise apply here). margin-left: auto
   pushes it to the row's right edge, same position it always had,
   without needing a separate wrapper/row element to do that. */
.ld-build-comps-btn {
  align-self: center;
  margin-left: auto;
  display: inline-block;
  font-size: 14px;
  font-weight: 700;
  color: #1E40AF;
  background: #FFFFFF;
  border: 1px solid #1E40AF;
  border-radius: 8px;
  padding: 10px 20px;
  text-decoration: none;
  transition: background 0.15s ease, color 0.15s ease;
}

.ld-build-comps-btn:hover {
  background: #1E40AF;
  color: #FFFFFF;
}

/* ---- Gallery ---- */

.ld-gallery {
  margin-bottom: 0;
}

.ld-gallery-status {
  text-align: center;
  color: #4B5A70;
  font-size: 14px;
  padding: 40px 16px;
  margin: 0;
  background: #F7F8FA;
  border-radius: 8px;
}

.ld-hero-wrap {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 10;
  max-height: 520px;
  border-radius: 8px;
  overflow: hidden;
  background: #F7F8FA;
}

.ld-hero-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  cursor: pointer;
}

/* Prev/Next overlay buttons — plain <button>, not the <label> trick the
   old CSS-only gallery used, since the JS-built gallery already has real
   click handlers and a <button> is the correct native element for one. */
.ld-arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border: none;
  border-radius: 50%;
  background: rgba(18, 35, 61, 0.55);
  color: #FFFFFF;
  font-size: 16px;
  font-family: inherit;
  line-height: 1;
  padding: 0;
  cursor: pointer;
  user-select: none;
  transition: background 0.15s ease;
}

.ld-arrow:hover {
  background: rgba(18, 35, 61, 0.8);
}

.ld-arrow:focus-visible {
  outline: 2px solid #1E40AF;
  outline-offset: 2px;
}

.ld-arrow-prev {
  left: 12px;
}

.ld-arrow-next {
  right: 12px;
}

/* ---- Hero photo: save button overlay ---- */
/* Same semi-transparent dark-navy circle already used for .ld-arrow
   above (rgba(18, 35, 61, ...) is this site's #12233D navy) — proven to
   read clearly against arbitrary photo content, so reused here rather
   than inventing a second treatment for the same hero image. Positioned
   against .ld-hero-col (see above), not #ld-gallery or .ld-hero-wrap —
   both of those get replaced wholesale by the photo-loading script, so
   anchoring there would risk this button vanishing along with them. */
.ld-hero-save-btn {
  position: absolute;
  top: 16px;
  right: 16px;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border: none;
  border-radius: 50%;
  background: rgba(18, 35, 61, 0.55);
  color: #FFFFFF;
  cursor: pointer;
  padding: 0;
  transition: background 0.15s ease, color 0.15s ease;
}

.ld-hero-save-btn svg {
  width: 20px;
  height: 20px;
}

.ld-hero-save-btn:hover {
  background: rgba(18, 35, 61, 0.8);
}

.ld-hero-save-btn.js-save-btn--saved {
  background: rgba(255, 255, 255, 0.9);
  color: #E0245E;
}

.ld-hero-save-btn.js-save-btn--saved svg {
  fill: currentColor;
}

.ld-hero-save-btn:focus-visible {
  outline: 2px solid #FFFFFF;
  outline-offset: 2px;
}

/* Single scrollable row, not a wrapping grid — overflow-x handles photo
   counts that don't fit the viewport width instead of wrapping to a
   second row. */
.ld-thumbs {
  display: flex;
  flex-wrap: nowrap;
  overflow-x: auto;
  gap: 8px;
  margin-top: 8px;
  padding-bottom: 4px;
}

.ld-thumb {
  display: block;
  width: 88px;
  height: 66px;
  flex: 0 0 auto;
  object-fit: cover;
  border-radius: 6px;
  border: 2px solid transparent;
  cursor: pointer;
  transition: border-color 0.15s ease;
}

/* "X of Y" counter, driven by the same currentIndex/totalPhotos JS state
   as .ld-lightbox-counter below — not a second counting mechanism, just
   a second place that same state is rendered. Small and unobtrusive,
   sitting right under the thumbnail strip rather than competing with it. */
.ld-photo-counter {
  font-size: 12px;
  color: #4B5A70;
  margin: 6px 0 0;
}

.ld-thumb:hover {
  border-color: #DCE1E8;
}

.ld-thumb-active {
  border-color: #1E40AF;
}

/* ---- Facts band stat blocks (beds / baths / sqft / $ per sqft / acres / year built / days on market) ---- */
/* Flex container is .ld-facts-band-stats, defined above — these are just
   the individual label+value blocks. */

.ld-fact {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.ld-fact-value {
  font-size: 30px;
  font-weight: 700;
  line-height: 1.2;
}

.ld-fact-label {
  font-size: 12px;
  color: #4B5A70;
  text-transform: uppercase;
  letter-spacing: .04em;
}

/* ---- Details / Features row-lists ---- */
/* Shared by both sections: one full-width row per fact, label on the
   left, value on the right, a thin divider between rows. */

.ld-details h2,
.ld-features h2,
.ld-interior h2,
.ld-exterior h2,
.ld-utilities h2,
.ld-description-section h2,
.ld-price-history h2 {
  font-size: 18px;
  margin: 0 0 12px;
}

/* ---- Price History (last section inside the Description tab panel,
   after Utilities, before the Saved Listings row further down the
   page) ---- */

.ld-price-history {
  margin-bottom: 32px;
}

/* Border + radius live on the wrapper (not the table itself, which keeps
   border-collapse: collapse) so the rounded corners clip cleanly via
   overflow: hidden — same bordered-card treatment as .ld-facts-band/
   .ld-showing-card elsewhere on this page, applied here as a real
   <table> instead of a div stack. */
.ld-price-history-table-wrap {
  border: 1px solid #DCE1E8;
  border-radius: 8px;
  overflow: hidden;
}

/* table-layout: fixed + explicit widths on the first/last columns (below)
   guarantee Date/Event/Price read as three distinct, evenly-separated
   columns regardless of how long any individual cell's text is — auto
   table layout would otherwise let a long Event label steal space from
   its neighbors. */
.ld-price-history-table {
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
  font-size: 14px;
}

.ld-price-history-table th,
.ld-price-history-table td {
  padding: 12px 16px;
  border-bottom: 1px solid #DCE1E8;
  text-align: left;
  vertical-align: middle;
}

.ld-price-history-table th:first-child,
.ld-price-history-table td:first-child {
  width: 32%;
}

.ld-price-history-table th:last-child,
.ld-price-history-table td:last-child {
  width: 26%;
}

/* Muted background on the header row is the visually-distinct-header
   convention already used for this page's other bordered panels
   (.ld-facts-band, .ld-showing-card both use this same #F7F8FA). */
.ld-price-history-table thead th {
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: #4B5A70;
  background: #F7F8FA;
  border-bottom: 1px solid #DCE1E8;
}

.ld-price-history-table tbody tr:last-child td {
  border-bottom: none;
}

/* .ld-price-history-table th/td above (a class + element selector) has
   higher specificity than a bare .ld-price-history-price class would —
   text-align: right would silently lose to that rule's text-align: left
   without also qualifying this selector the same way. */
.ld-price-history-table .ld-price-history-price {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.ld-rowlist {
  margin: 0 0 32px;
}

.ld-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 16px;
  padding: 10px 0;
  border-bottom: 1px solid #DCE1E8;
}

.ld-row:last-child {
  border-bottom: none;
}

.ld-row-label {
  font-size: 12px;
  color: #4B5A70;
  text-transform: uppercase;
  letter-spacing: .04em;
  flex-shrink: 0;
}

.ld-row-value {
  font-size: 15px;
  text-align: right;
  overflow-wrap: break-word;
  min-width: 0;
}

/* ---- Details/Features/Interior/Exterior/Utilities: two-column rows ---- */
/* CSS multi-column layout, not a PHP-side split into two arrays — fills
   the first column top-to-bottom in DOM order, then continues into the
   second, which is exactly "first N/2 rows, then the rest" without any
   server-side row-counting logic. break-inside: avoid keeps a single row
   (label + value) from being split across the column gap. Individual row
   styling (.ld-row/.ld-row-label/.ld-row-value above) is untouched — only
   the list's own layout changes. Single column again under 720px, same
   breakpoint the rest of this page's mobile layout uses. */
.ld-details .ld-rowlist,
.ld-features .ld-rowlist,
.ld-interior .ld-rowlist,
.ld-exterior .ld-rowlist,
.ld-utilities .ld-rowlist {
  column-count: 2;
  column-gap: 32px;
}

.ld-details .ld-rowlist .ld-row,
.ld-features .ld-rowlist .ld-row,
.ld-interior .ld-rowlist .ld-row,
.ld-exterior .ld-rowlist .ld-row,
.ld-utilities .ld-rowlist .ld-row {
  break-inside: avoid;
  -webkit-column-break-inside: avoid;
}

/* The base .ld-row:last-child rule above strips the divider from the
   very last row in DOM order, which lands at the bottom of the second
   column here — undo that so the last row of each column gets the same
   divider as every row above it. The first column's last row already
   has one, since only the true last-child loses it. */
.ld-details .ld-rowlist .ld-row:last-child,
.ld-features .ld-rowlist .ld-row:last-child,
.ld-interior .ld-rowlist .ld-row:last-child,
.ld-exterior .ld-rowlist .ld-row:last-child,
.ld-utilities .ld-rowlist .ld-row:last-child {
  border-bottom: 1px solid #DCE1E8;
}

@media (max-width: 720px) {
  .ld-details .ld-rowlist,
  .ld-features .ld-rowlist,
  .ld-interior .ld-rowlist,
  .ld-exterior .ld-rowlist,
  .ld-utilities .ld-rowlist {
    column-count: 1;
  }
}

/* ---- Tabs: Description / Map / Nearby Listings / Mortgage Calculator
   (right after the hero row) ---- */
/* Same CSS-only radio/label/sibling-selector pattern as market-report.php's
   property-type tabs (see .mw-tab-input etc. in market-report.css) — radios
   sharing one name, :checked toggling both which panel shows and which
   label looks active, via the general sibling combinator. Palette adapted
   to this page's own (#12233D/#DCE1E8/#F7F8FA/#4B5A70/#1E40AF) rather than
   market-report.css's CSS-variable version. The Mortgage Calculator tab
   (#ld-tab-mortgage) is absent from the DOM entirely for rental listings —
   these selectors simply match nothing in that case, same as the other
   three tabs would if their radios were ever absent. */

.ld-tab-input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

/* .ld-tabs-row holds the tab labels AND the share row as one horizontal
   band — tabs left, share icons + Copy Link right-aligned. The border/
   spacing that used to belong to .ld-tabs-nav alone now belongs to this
   outer row, so the divider line spans the full width including the
   share icons, not just the tabs. */
.ld-tabs-row {
  display: flex;
  flex-wrap: wrap;
  /* .ld-tabs-nav (the tab labels) is the taller of the two children, so
     centering leaves it flush at its natural position — same spot the
     active tab's -1px bottom margin needs to overlap this row's
     border-bottom — while lifting the shorter .ld-share-row up into the
     vertical middle instead of letting it sink to the bottom edge. */
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  border-bottom: 2px solid #DCE1E8;
  margin-bottom: 20px;
}

.ld-tabs-nav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
}

.ld-tab-label {
  display: inline-block;
  padding: 10px 18px;
  font-weight: 600;
  font-size: 14px;
  color: #4B5A70;
  background: #F7F8FA;
  /* 1px -> 2px so the tabs read more clearly as distinct, selectable
     elements — margin-bottom below matches it 1:1 so the active tab
     still overlaps .ld-tabs-row's own border-bottom (also now 2px)
     exactly, same visual "merges into the row" effect as before. */
  border: 2px solid #DCE1E8;
  border-bottom: none;
  border-radius: 8px 8px 0 0;
  margin-bottom: -2px;
  cursor: pointer;
  user-select: none;
  transition: background 0.15s ease, color 0.15s ease;
}

.ld-tab-label:hover {
  background: #FFFFFF;
  color: #12233D;
}

.ld-tab-panel {
  display: none;
}

#ld-tab-description:checked ~ .ld-tab-panels #ld-panel-description,
#ld-tab-map:checked ~ .ld-tab-panels #ld-panel-map,
#ld-tab-nearby:checked ~ .ld-tab-panels #ld-panel-nearby,
#ld-tab-mortgage:checked ~ .ld-tab-panels #ld-panel-mortgage {
  display: block;
}

#ld-tab-description:checked ~ .ld-tabs-row .ld-tab-label--description,
#ld-tab-map:checked ~ .ld-tabs-row .ld-tab-label--map,
#ld-tab-nearby:checked ~ .ld-tabs-row .ld-tab-label--nearby,
#ld-tab-mortgage:checked ~ .ld-tabs-row .ld-tab-label--mortgage {
  background: #FFFFFF;
  color: #12233D;
  border-bottom-color: #FFFFFF;
}

#ld-tab-description:focus-visible ~ .ld-tabs-row .ld-tab-label--description,
#ld-tab-map:focus-visible ~ .ld-tabs-row .ld-tab-label--map,
#ld-tab-nearby:focus-visible ~ .ld-tabs-row .ld-tab-label--nearby,
#ld-tab-mortgage:focus-visible ~ .ld-tabs-row .ld-tab-label--mortgage {
  outline: 2px solid #1E40AF;
  outline-offset: 2px;
}

@media (max-width: 720px) {
  /* .ld-tabs-row stops being a flex container entirely here — display:
     block, not flex-direction: column. That matters: as long as
     .ld-tabs-nav is a flex ITEM (which it was under flex-direction:
     column + align-items: stretch), its width comes from flexbox's own
     stretch/min-width:auto sizing math, which turned out not to reliably
     clamp it to the container's width in practice — its content (4
     unwrapped tabs) kept winning, silently widening .ld-tabs-row and
     everything above it, up to the page itself. As a plain block-level
     child of a now block-level parent, .ld-tabs-nav's width is simply
     auto = 100% of .ld-tabs-row's content box, full stop — no stretch
     computation involved at all. It stays display: flex internally
     (for laying out the tab labels themselves in a row), it's just no
     longer a flex ITEM of anything. Block children stack vertically by
     default, so this alone is also what puts the share row on its own
     line below the tabs — no explicit column/stack rule needed for that
     anymore either. */
  .ld-tabs-row {
    display: block;
  }

  /* Same "don't wrap, scroll instead" fix already used for the photo
     thumbnail strip (.ld-thumbs) — "Mortgage Calculator" is long enough
     to force a wrapping tab row onto two lines on most phones no matter
     how much padding/font-size gets trimmed, so this makes the tab bar a
     single horizontally-scrollable row instead. white-space: nowrap on
     the labels themselves guarantees no individual tab's own text wraps
     either, regardless of how flex would otherwise size it. max-width:
     100% is belt-and-suspenders on top of the display: block fix above —
     this box must never exceed its parent's width no matter what its
     (now purely internal, scrollable) content demands. overflow-y:
     hidden is required, not optional decoration — per the CSS Overflow
     spec, setting overflow-x to anything other than visible while
     overflow-y is left at its visible default forces overflow-y to
     compute to auto too, which is exactly what was putting an unwanted
     vertical scrollbar on this horizontal-only strip. */
  .ld-tabs-nav {
    flex-wrap: nowrap;
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    max-width: 100%;
  }

  .ld-tab-label {
    flex: 0 0 auto;
    white-space: nowrap;
  }

  .ld-share-row {
    justify-content: flex-start;
    /* .ld-tabs-row's own gap: 12px (set in its base rule) only works
       while it's a flex/grid container — now that it's display: block
       on mobile (see .ld-tabs-row above), gap has no effect on normal
       block-flow children at all, so without an explicit margin-top
       here this row sits flush against the bottom of the tabs above it
       with zero space between them. */
    margin-top: 12px;
    /* Stacked below the tabs on mobile (see .ld-tabs-row above), sitting
       right against .ld-tabs-row's own border-bottom with nothing else
       to create breathing room — unlike desktop, where the tabs (taller,
       vertically centered against this row) are what keeps this row off
       the border, this needs its own explicit space here instead. */
    margin-bottom: 14px;
  }
}

/* ---- Description (first thing inside the Description tab panel) ---- */
/* Truncated to ~5 lines by default via a pure-CSS checkbox hack: the
   hidden checkbox + label toggle -webkit-line-clamp on the sibling
   .ld-description via the general sibling combinator, no JS. Known,
   acceptable limitation: CSS can't tell whether a given description is
   actually longer than 5 lines, so the "See more" toggle always renders,
   even for short descriptions where clicking it does nothing — most
   descriptions in this data run long enough that this is a rare edge
   case, not worth JS to solve. */

.ld-description-section {
  position: relative;
  margin-bottom: 32px;
}

.ld-description-toggle-input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.ld-description {
  line-height: 1.6;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 5;
  overflow: hidden;
}

.ld-description-toggle-input:checked ~ .ld-description {
  -webkit-line-clamp: unset;
  overflow: visible;
}

.ld-description-toggle-label {
  display: inline-block;
  margin-top: 8px;
  color: #1E40AF;
  font-weight: 600;
  font-size: 14px;
  cursor: pointer;
}

.ld-description-see-less {
  display: none;
}

.ld-description-toggle-input:checked ~ .ld-description-toggle-label .ld-description-see-more {
  display: none;
}

.ld-description-toggle-input:checked ~ .ld-description-toggle-label .ld-description-see-less {
  display: inline;
}

/* ---- Map tab ---- */
/* Leaflet requires an explicit container size — it doesn't naturally fill
   available space the way normal HTML content does, and measures this
   height at construction time (see the invalidateSize() call in the
   listing-detail.php <script> that initializes it). */

.ld-map {
  height: 450px;
  border-radius: 8px;
  overflow: hidden;
  border: 1px solid #DCE1E8;
}

.ld-map-unavailable {
  padding: 40px 0;
  text-align: center;
  color: #4B5A70;
  font-size: 14px;
}

/* Current-listing marker: the map's only marker — a plain colored dot
   (via Leaflet divIcon in the <script>) rather than an external
   marker-icon image, so it doesn't depend on any additional CDN asset. */
.ld-map-current-marker-dot {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: #1E40AF;
  border: 3px solid #FFFFFF;
  box-shadow: 0 1px 4px rgba(18, 35, 61, 0.5);
}

/* ---- Fullscreen lightbox ---- */
/* Built and appended to <body> by the gallery <script> (not present in
   the server-rendered markup) — position: fixed covers the viewport
   regardless of where #ld-gallery sits in the page layout above, and
   appending to <body> keeps it out of any ancestor's own stacking
   context. */

.ld-lightbox {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 1000;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.92);
}

.ld-lightbox-open {
  display: flex;
}

.ld-lightbox-img {
  max-width: 90vw;
  max-height: 90vh;
  object-fit: contain;
}

.ld-lightbox-close {
  position: absolute;
  top: 16px;
  right: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border: none;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.12);
  color: #FFFFFF;
  font-size: 22px;
  font-family: inherit;
  line-height: 1;
  padding: 0;
  cursor: pointer;
  transition: background 0.15s ease;
}

.ld-lightbox-close:hover {
  background: rgba(255, 255, 255, 0.24);
}

.ld-lightbox-arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border: none;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.12);
  color: #FFFFFF;
  font-size: 20px;
  font-family: inherit;
  line-height: 1;
  padding: 0;
  cursor: pointer;
  transition: background 0.15s ease;
}

.ld-lightbox-arrow:hover {
  background: rgba(255, 255, 255, 0.24);
}

.ld-lightbox-close:focus-visible,
.ld-lightbox-arrow:focus-visible {
  outline: 2px solid #FFFFFF;
  outline-offset: 2px;
}

.ld-lightbox-prev {
  left: 16px;
}

.ld-lightbox-next {
  right: 16px;
}

/* Same currentIndex/totalPhotos state as .ld-photo-counter above, just
   rendered here too (see updateCounter() in this page's own <script>) —
   positioned against .ld-lightbox itself (position: fixed, so this is
   its containing block), bottom-centered under the photo regardless of
   the photo's own aspect ratio/size. */
.ld-lightbox-counter {
  position: absolute;
  bottom: 20px;
  left: 50%;
  transform: translateX(-50%);
  margin: 0;
  padding: 4px 12px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.12);
  color: #FFFFFF;
  font-size: 13px;
}

/* ---- Share row ---- */
/* (The save button used to live here too — see .ld-hero-save-btn near
   .ld-arrow above, now overlaid on the hero photo instead.) */

/* Lives inline with the tab row (see .ld-tabs-row), so it needs no top
   border/margin of its own — .ld-tabs-row's own border-bottom is the
   only divider involved. */
.ld-share-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}

.ld-share-label {
  font-size: 12px;
  font-weight: 600;
  color: #4B5A70;
  text-transform: uppercase;
  letter-spacing: .04em;
  margin-right: 4px;
}

.ld-share-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  width: 34px;
  height: 34px;
  border: 1px solid #DCE1E8;
  border-radius: 50%;
  background: #FFFFFF;
  color: #4B5A70;
  text-decoration: none;
  cursor: pointer;
  padding: 0;
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.ld-share-btn svg {
  width: 16px;
  height: 16px;
}

.ld-share-btn:hover {
  border-color: #1E40AF;
  color: #1E40AF;
}

.ld-share-btn:focus-visible {
  outline: 2px solid #1E40AF;
  outline-offset: 2px;
}

/* Copy Link is the one .ld-share-btn wide enough to carry a text label —
   width:auto overrides the circular icon-button sizing above. */
.ld-copy-link-btn {
  width: auto;
  border-radius: 999px;
  padding: 0 12px;
  font-size: 12px;
  font-weight: 600;
  font-family: inherit;
}

.ld-copy-link-copied {
  display: none;
}

.ld-copy-link-btn--copied .ld-copy-link-text {
  display: none;
}

.ld-copy-link-btn--copied .ld-copy-link-copied {
  display: inline;
}

.ld-copy-link-btn--copied {
  border-color: #1E8A4C;
  color: #1E8A4C;
}

/* ---- Request a Showing ---- */
/* Its own full-width block in the main content column now, between the
   hero row and the tab row — always visible (no more <details>/<summary>
   expand-to-reveal). No heading text announcing it anymore (removed) —
   the blue border (this site's established primary blue, same #1E40AF
   as .sr-search-btn/.ld-build-comps-btn elsewhere) is what marks it as a
   clearly-bounded, prominent block instead. */

.ld-showing-card {
  border: 2px solid #1E40AF;
  border-radius: 8px;
  background: #F7F8FA;
  padding: 12px 14px;
  margin-bottom: 32px;
}

.ld-showing-form {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px 10px;
}

.ld-showing-field {
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.ld-showing-field--full,
.ld-showing-submit {
  grid-column: 1 / -1;
}

.ld-showing-field label {
  font-size: 10px;
  font-weight: 600;
  color: #4B5A70;
  text-transform: uppercase;
  letter-spacing: .04em;
}

/* box-sizing: border-box + an explicit height (rather than leaving height
   to font-size/padding math, which native OS control chrome on date/time
   inputs doesn't always respect) is what pins these to a real ~38px —
   the 36-40px target — regardless of input type or browser. */
.ld-showing-field input {
  box-sizing: border-box;
  height: 38px;
  font-size: 13px;
  padding: 0 10px;
  border: 1px solid #DCE1E8;
  border-radius: 6px;
  color: #12233D;
  background: #FFFFFF;
  font-family: inherit;
}

.ld-showing-field textarea {
  box-sizing: border-box;
  font-size: 13px;
  padding: 6px 10px;
  border: 1px solid #DCE1E8;
  border-radius: 6px;
  color: #12233D;
  background: #FFFFFF;
  font-family: inherit;
  min-height: 44px;
  resize: vertical;
}

/* Off-screen, not display:none — see request-showing.php's docblock on
   why a bot filling this in is treated as the same signal either way,
   but this specific hiding technique is what visually removes it for a
   real visitor while leaving it just as fillable by a scripted submit. */
.ld-showing-honeypot {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.ld-showing-submit {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  height: 34px;
  font-size: 13px;
  font-weight: 700;
  background: #1E40AF;
  color: #FFFFFF;
  border: none;
  padding: 0 16px;
  border-radius: 6px;
  cursor: pointer;
}

.ld-showing-submit:hover {
  background: #16327F;
}

.ld-showing-success {
  font-size: 14px;
  color: #1E8A4C;
  font-weight: 600;
  margin: 0;
}

.ld-showing-error {
  font-size: 12px;
  color: #B3261E;
  margin: 0 0 8px;
}

@media (max-width: 480px) {
  .ld-showing-form {
    grid-template-columns: 1fr;
  }
}

/* ---- Mortgage Calculator page ---- */
/* Embeds mortgagecalculator.org's own webmaster widget via iframe rather
   than a custom-built calculator — see views/mortgage-calculator.php. */

.ld-mortgage-calc h2 {
  font-size: 18px;
  margin: 0 0 16px;
}

/* Width and height below were measured empirically against the live
   widget (a same-origin test iframe on mortgagecalculator.org itself, so
   its internals could be read directly), not guessed:

   The widget is a Bootstrap 4 app — its own .container caps at 720px at
   any viewport from 768–991px, 960px from 992–1199px, etc. (their real
   compiled CSS breakpoints: 576/768/992/1200 -> 540/720/960/1140). Our
   old width:100% inside .ld-wrap's 960px cap landed the iframe at
   960px — just under the 992px breakpoint — so the widget's own content
   maxed out at 720px, leaving ~120px of dead space on EACH side. Capping
   the iframe at 800px instead keeps it safely inside the 768–991px tier
   (720px content, ~40px margin per side — Bootstrap's own gutter, not
   excess dead space) while still comfortably clearing 768px so the
   widget keeps its 2-column desktop layout rather than dropping to its
   single-column mobile stack.

   Height: a prior pass here measured ~1000px/~2220px and set 1080px/
   2300px, but a scrollbar still showed up in the standard (non-expanded)
   view — re-measured directly against the live widget across its own
   real width tiers (not just this file's two CSS breakpoints), width by
   width, standard view only (inputs through Monthly vs. Bi-Weekly cards,
   amortization table collapsed):

     - No ?price= (the footer link's case — homevalue/downpayment/
       loanamount all absent, so the widget's own built-in defaults
       apply): its default down payment is under 20%, so a PMI-required
       note (PMI End Date/Total PMI Payments/Monthly Payment after PMI
       ends) renders that a listing-driven ?price= link never shows
       (views/mortgage-calculator.php always computes an exact 20% down
       payment) — taller than every priced scenario tested (any price,
       high or low, all landed shorter once 20% down suppresses that
       note), so the no-price case is this component's real worst case,
       not a priced one.
     - 800px content width (≥832px viewport, this file's true desktop
       ceiling): 1122px.
     - 736px content width (768px viewport — .ld-wrap's own 16px/side
       padding subtracted — the narrow end of this rule's real range
       before the 767px mobile breakpoint below takes over): 1206px,
       taller than 800px's own 1122px. 1200px (no margin) leaves this
       exact case clipped, so the desktop height below is set off the
       true 736px-wide worst case, not the wider 800px one.
     - 288px content width (a 320px-viewport phone, same 32px padding
       subtracted): 2602px — the mobile breakpoint's own worst case,
       same reasoning (narrower phones run taller, not shorter).

   Both heights below carry a further ~90-100px margin on top of those
   measured worst cases, for cross-browser font-rendering variance.
   The "Show Amortization Table" toggle expands well past either height
   regardless of what's chosen — this is a cross-origin iframe, so
   there's no way to read/react to the embedded content's real height;
   that one interaction needing its own internal scroll is an accepted
   limitation, not a bug. */
.ld-mortgage-widget-frame {
  display: block;
  width: 100%;
  max-width: 800px;
  margin: 0 auto;
  height: 1300px;
  border: none;
}

@media (max-width: 767px) {
  .ld-mortgage-widget-frame {
    /* Below the widget's own ~600px breakpoint it drops to a single
       stacked column, tallest at the narrowest supported phone widths
       (measured 2602px at a 320px-viewport phone) — well past 1300px,
       so this tier gets its own taller height rather than clipping
       every mobile visitor. */
    height: 2700px;
  }
}

/* The heights above are sized for the standalone page's own worst case:
   no ?price= at all (the footer-link visitor), where the widget's
   default under-20%-down payment triggers an extra PMI-schedule note
   that a priced scenario never shows (see the big comment above). The
   listing-detail tab below can never hit that case — a for-sale
   listing always has a real list_price, so buildMortgageWidgetUrl()
   always supplies an exact 20%-down homevalue/downpayment/loanamount
   and the shorter "priced" layout is the only one this tab ever
   renders. Re-measured directly against the live widget at this file's
   own 800px desktop width, priced case, several prices from $480k to
   $2.99M (digit count didn't move the height): ~930-950px real content,
   200px+ shorter than the 1122px no-price worst case — 1300px was
   leaving that much dead space below the widget on every listing.
   1100px keeps a similar ~150-170px safety margin to the base rule's
   own (1300 - 1122 = 178px). The mobile-tier figure below is a
   proportional estimate off that same ratio, not independently
   re-measured at that width — kept with extra margin on top of the
   scaling since a clipped calculator is worse than some leftover
   scroll. */
#ld-panel-mortgage .ld-mortgage-widget-frame {
  height: 1100px;
}

@media (max-width: 767px) {
  #ld-panel-mortgage .ld-mortgage-widget-frame {
    height: 2400px;
  }
}

/* ---- Saved Listings row (last content block before the footer) ---- */
/* Same "don't wrap, scroll instead" pattern as .ld-thumbs above, reusing
   listing-card.php's .sr-card-container/.sr-card markup (search.css) —
   just fixed-width per card instead of the search grid's auto-fill
   columns, since a horizontal scroll row has nothing to wrap against.
   Hidden by default in the markup; the script at the bottom of
   views/listing-detail.php only reveals it once it has at least one
   card to show. */
.ld-saved-row {
  margin-top: 40px;
}

.ld-saved-row-title {
  font-size: 20px;
  margin: 0 0 16px;
}

.ld-saved-row-scroll {
  display: flex;
  flex-wrap: nowrap;
  overflow-x: auto;
  gap: 20px;
  padding-bottom: 4px;
}

.ld-saved-row-scroll .sr-card-container {
  flex: 0 0 240px;
  width: 240px;
}

/* ---- IDX attribution block (very bottom of page, above the site footer) ---- */
/* Same muted fine-print treatment as .ld-row-label above — legal/
   informational text, not a visual focal point. */
.ld-idx-attribution {
  margin: 16px 0 0;
}

.ld-idx-logo {
  display: block;
  margin: 0 0 8px;
}

.ld-idx-attribution p {
  font-size: 12px;
  color: #4B5A70;
  margin: 0 0 8px;
}

.ld-idx-attribution p:last-child {
  margin-bottom: 0;
}
