/* Listing detail pages (server-rendered at /listings/<mls-number>).
   =========================================================================
   Loaded only by those pages, so it stays out of main.css and off every other
   page on the site. It uses the site's own custom properties rather than new
   colours, so a future palette change carries through here automatically.

   Written for build/call-51 and the netlify/functions/listing.js renderer. */

/* .container narrow: a reading-width column for the sparse pages (off market,
   not found). main.css has .container but no .narrow. */
.container.narrow { max-width: 760px; }

/* ----------------------------------------------------------- the headline */
.listing-head {
  background: var(--navy);
  color: var(--on-dark);
  padding: 34px 0 30px;
}
.listing-back {
  display: inline-block;
  font-family: var(--label);
  font-size: 11.5px;
  letter-spacing: .07em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--on-dark-dim);
  text-decoration: none;
  margin-bottom: 18px;
}
.listing-back:hover { color: #fff; }
.listing-headline {
  display: flex;
  flex-wrap: wrap;
  gap: 18px 32px;
  align-items: flex-end;
  justify-content: space-between;
}
.listing-head h1 {
  color: #fff;
  font-size: clamp(1.5rem, 3.4vw, 2.5rem);
  line-height: 1.15;
  margin: 0;
  max-width: 22ch;
}
.listing-sub {
  margin-top: 10px;
  color: var(--on-dark-dim);
  font-family: var(--label);
  font-size: 12.5px;
  letter-spacing: .05em;
  text-transform: uppercase;
}
.listing-price-wrap { text-align: right; }
@media (max-width: 720px) {
  .listing-price-wrap { text-align: left; }
}
.listing-price {
  font-family: var(--display);
  font-size: clamp(1.6rem, 4vw, 2.3rem);
  color: #fff;
  line-height: 1;
}
.listing-status,
.listing-ours {
  display: inline-block;
  margin-top: 10px;
  margin-left: 6px;
  font-family: var(--label);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  padding: 6px 12px;
  border-radius: 20px;
}
.listing-status { background: var(--periwinkle); color: var(--navy); }
.listing-ours { border: 1px solid var(--on-dark-line); color: var(--on-dark-dim); }
.listing-withheld {
  margin-top: 18px;
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--on-dark-dim);
  max-width: 62ch;
}

/* The off-market state. Stated plainly, at the top, before anything else. */
.listing-head-off { background: var(--slate-deep); }
.listing-off-banner {
  background: rgba(255, 255, 255, .08);
  border: 1px solid var(--on-dark-line);
  border-radius: 12px;
  padding: 16px 20px;
  margin-bottom: 22px;
  font-size: 15px;
  line-height: 1.6;
  color: var(--on-dark);
}
.listing-off-banner strong { color: #fff; display: block; margin-bottom: 4px; }
.listing-off-help {
  font-size: 16px;
  line-height: 1.7;
  color: var(--ink-soft);
  max-width: 62ch;
  margin-bottom: 22px;
}

/* -------------------------------------------------------------- gallery */
.listing-gallery { padding: 0; background: var(--bg-soft); }
.gallery-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
  padding: 8px 0;
}
.gallery-grid figure { margin: 0; overflow: hidden; border-radius: 10px; }
.gallery-grid img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.gallery-lead { grid-column: span 4; aspect-ratio: 3 / 2; }
.gallery-thumb { aspect-ratio: 3 / 2; }
@media (min-width: 860px) {
  .gallery-lead { grid-column: span 2; grid-row: span 2; }
}
@media (max-width: 560px) {
  .gallery-grid { grid-template-columns: repeat(2, 1fr); }
  .gallery-lead { grid-column: span 2; }
}
.gallery-more {
  padding: 14px 0 18px;
  font-size: 13.5px;
  color: var(--ink-soft);
}

/* ----------------------------------------------------------------- body */
.listing-main { padding: 46px 0 56px; }
.listing-cols {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: 44px;
  align-items: start;
}
@media (max-width: 940px) {
  .listing-cols { grid-template-columns: 1fr; gap: 34px; }
}

.listing-facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 1px;
  background: var(--border);
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow: hidden;
  margin: 0 0 34px;
}
.listing-facts > div { background: #fff; padding: 16px 18px; }
.listing-facts dt {
  font-family: var(--label);
  font-size: 10.5px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--steel);
  font-weight: 600;
  margin-bottom: 6px;
}
.listing-facts dd {
  margin: 0;
  font-size: 17px;
  font-weight: 600;
  color: var(--ink);
}

.listing-remarks h2,
.listing-details > summary,
.listing-details h2 { font-size: 22px; margin: 0 0 14px; }
.listing-remarks p {
  font-size: 16px;
  line-height: 1.75;
  color: var(--ink-soft);
  margin: 0 0 14px;
}
.listing-details { margin-top: 38px; }
.listing-detail-group { margin-top: 22px; }
.listing-detail-group h3 {
  font-family: var(--label);
  font-size: 11.5px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--steel);
  margin: 0 0 10px;
}
.listing-detail-group dl {
  margin: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 8px 26px;
}
.listing-detail-group dl > div {
  display: flex;
  gap: 10px;
  font-size: 14.5px;
  line-height: 1.55;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--border-soft);
}
.listing-detail-group dt { color: var(--steel); min-width: 40%; }
.listing-detail-group dd { margin: 0; color: var(--ink); }

/* ---------------------------------------------------------------- aside */
.listing-aside { position: sticky; top: 92px; }
@media (max-width: 940px) {
  .listing-aside { position: static; }
}
.listing-cta {
  background: var(--bg-soft-2);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 26px 24px;
}
.listing-cta h2 { font-size: 20px; margin: 0 0 8px; }
.listing-cta p {
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--ink-soft);
  margin: 0 0 18px;
}
.listing-cta .btn { width: 100%; text-align: center; }
.listing-call {
  display: block;
  margin-top: 12px;
  text-align: center;
  font-size: 13.5px;
  color: var(--steel);
  text-decoration: none;
}
.listing-call:hover { color: var(--navy); }

/* Required by the MLS on every detail view: the listing office and the
   update timestamp. Styled quietly, but never hidden. */
.listing-attribution {
  margin-top: 22px;
  padding-top: 18px;
  border-top: 1px solid var(--border);
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--ink-soft);
}
.listing-courtesy { font-weight: 600; color: var(--ink); }
.listing-updated { margin-top: 4px; }

/* -------------------------------------------------------------- similar */
.listing-similar { padding: 10px 0 56px; background: var(--bg-soft); }
.listing-similar .section-head { margin-bottom: 26px; }
.listing-similar .prop-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 290px), 1fr));
  gap: 24px;
}
.listing-similar .prop-media img {
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  display: block;
}

.listing-disclaimer-band { padding: 0 0 40px; background: var(--bg-soft); }

/* =======================================================================
   SHORTENING THE PHONE SCROLL  (2026-09-23)
   Geoff reported a long scroll on the listing pages. Measured on a 390px
   phone: 8,633px, about ten screens. Where it went:
       4,012px  description, facts and spec list
       1,817px  three "similar properties" cards, stacked
       1,590px  the footer
         791px  the photo gallery
   The gallery was never the problem. Everything was simply expanded.
   ===================================================================== */

/* The spec list is a <details> that ships open and is folded by script on
   narrow screens, so no-JS visitors and crawlers still get all of it. On
   desktop the summary is hidden entirely and it reads as an ordinary
   heading, exactly as before. */
.listing-details > summary {
  display: block;
  cursor: pointer;
  list-style: none;
}
.listing-details > summary::-webkit-details-marker { display: none; }
.details-count { display: none; }

@media (max-width: 940px) {
  .listing-details > summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin: 0;
    padding: 16px 0;
    border-top: 1px solid var(--border);
    border-bottom: 1px solid var(--border);
    font-size: 18px;
  }
  /* A chevron that turns, so it is obvious the row is a control. */
  .listing-details > summary::after {
    content: "";
    flex: 0 0 auto;
    width: 9px;
    height: 9px;
    border-right: 2px solid var(--steel);
    border-bottom: 2px solid var(--steel);
    transform: rotate(45deg);
    transition: transform .2s var(--ease, ease);
  }
  .listing-details[open] > summary::after { transform: rotate(-135deg); }
  .details-count {
    display: inline;
    margin-left: auto;
    font-family: var(--label);
    font-size: 11px;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--steel);
    font-weight: 600;
  }
  .listing-details { margin-top: 30px; }
  .listing-details-body { padding-top: 6px; }
}

/* The description: clamped to about eight lines on a phone with a real
   button to open it. The class is added by script only when the text is
   actually long enough to be worth folding, so short listings are left
   alone rather than gaining a pointless "read more". */
.listing-remarks-text.is-clamped {
  display: -webkit-box;
  -webkit-line-clamp: 8;
  -webkit-box-orient: vertical;
  overflow: hidden;
  /* A fade, so it reads as continuing rather than as a hard cut. */
  mask-image: linear-gradient(180deg, #000 72%, transparent 100%);
  -webkit-mask-image: linear-gradient(180deg, #000 72%, transparent 100%);
}
.remarks-toggle {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  margin: 2px 0 18px;
  padding: 0;
  background: none;
  border: 0;
  font-family: var(--label);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--navy);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* "Similar properties" was 1,817px on a phone: three full cards stacked,
   more than two screens, for a suggestion. On narrow screens it becomes one
   swipeable row instead, so it costs about a third of a screen and the cards
   stay full size and legible. */
@media (max-width: 720px) {
  .listing-similar .prop-grid {
    display: flex;
    gap: 14px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    /* Bleed to the screen edges so it reads as a scrollable row, with the
       container's own gutter restored as padding. */
    margin: 0 -20px;
    padding: 4px 20px 18px;
    scrollbar-width: none;
  }
  .listing-similar .prop-grid::-webkit-scrollbar { display: none; }
  /* The flex item is the .prop-card, NOT the anchor around it. Each card is
     wrapped in <a style="display:contents">, so the anchor generates no box
     and its child becomes the flex child. Sizing the anchor would also fail
     because an inline style attribute beats any rule in this file. */
  .listing-similar .prop-grid .prop-card {
    flex: 0 0 78%;
    scroll-snap-align: start;
  }
  .listing-similar { padding-bottom: 34px; }
}

/* Search results on a phone: a compact row instead of a stacked card.
   Measured 2026-09-23: 24 results ran to 12,880px, about 15 screens, at
   roughly 536px per card. Laid out as a row with the photo beside the text
   each result is about 150px, so the same 24 results come to about a third
   of the scrolling and a visitor can actually compare them.

   The photo stays large enough to judge a property by, which is why this is
   a 38/62 split rather than a thumbnail. Above 560px the cards go back to a
   grid, where there is room for them. */
@media (max-width: 560px) {
  .search-grid { display: flex; flex-direction: column; gap: 12px; }
  .search-grid .prop-card {
    display: grid;
    grid-template-columns: 38% 1fr;
    align-items: stretch;
    gap: 0;
  }
  .search-grid .prop-media { aspect-ratio: auto; height: 100%; min-height: 128px; }
  .search-grid .prop-media img {
    width: 100%;
    height: 100%;
    aspect-ratio: auto;
    object-fit: cover;
  }
  .search-grid .prop-body { padding: 13px 14px; }
  .search-grid .prop-price { font-size: 19px; }
  .search-grid .prop-addr { font-size: 13.5px; line-height: 1.4; margin-top: 3px; }
  .search-grid .prop-meta { margin-top: 7px; gap: 4px 10px; font-size: 12px; }
  .search-grid .prop-updated { margin-top: 6px; font-size: 10px; }
  /* The "View listing" cue is redundant when the whole row is the link, and
     it costs a line on every result. */
  .search-grid .prop-cue { display: none; }
  /* The status badge sits over a much smaller photo now. */
  .search-grid .prop-tag { font-size: 9.5px; padding: 4px 7px; }
}

/* =======================================================================
   /search  (netlify/functions/search.js)
   Replaces the "Live MLS Search, Coming Soon" panel that sat on listings.html
   promising these exact features.
   ===================================================================== */
.search-head { background: var(--navy); color: var(--on-dark); padding: 46px 0 40px; }
.search-head h1 {
  color: #fff;
  font-size: clamp(1.7rem, 3.6vw, 2.7rem);
  line-height: 1.14;
  margin: 14px 0 0;
  max-width: 26ch;
}
.search-lede {
  margin-top: 16px;
  color: var(--on-dark-dim);
  font-size: 16px;
  line-height: 1.7;
  max-width: 62ch;
}

.search-form-band { background: var(--bg-soft-2); border-bottom: 1px solid var(--border); padding: 22px 0; }
.search-form { display: flex; flex-direction: column; gap: 14px; }
.sf-row { display: flex; flex-wrap: wrap; gap: 14px; }
.sf-field { display: flex; flex-direction: column; gap: 5px; min-width: 120px; flex: 1 1 130px; }
.sf-grow { flex: 3 1 240px; }
.sf-field > span {
  font-family: var(--label);
  font-size: 10.5px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--steel);
  font-weight: 600;
}
.sf-field input,
.sf-field select {
  width: 100%;
  font: inherit;
  font-size: 15px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: #fff;
  color: var(--ink);
  /* 16px on iOS or Safari zooms the page when the field is focused. */
  min-height: 42px;
}
.sf-field input:focus,
.sf-field select:focus { outline: 2px solid var(--periwinkle); outline-offset: 1px; }
.sf-actions { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }
.sf-reset { font-size: 13.5px; color: var(--steel); text-decoration: underline; }
@media (max-width: 560px) {
  .sf-field, .sf-grow { flex: 1 1 100%; }
  .sf-actions .btn { width: 100%; text-align: center; }
}

.search-results { padding: 30px 0 56px; }
.search-count {
  font-size: 14.5px;
  color: var(--ink-soft);
  margin-bottom: 22px;
}
.search-count strong { color: var(--ink); font-size: 17px; }
.search-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr));
  gap: 26px;
}
.search-grid .prop-media img {
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  display: block;
}
.search-empty {
  background: var(--bg-soft-2);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 40px 32px;
  max-width: 62ch;
}
.search-empty h2 { font-size: 22px; margin: 0 0 12px; }
.search-empty p { font-size: 15px; line-height: 1.7; color: var(--ink-soft); margin: 0 0 16px; }

.search-pager {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  margin: 40px 0 10px;
}
.search-pager .pg {
  min-width: 42px;
  min-height: 42px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0 14px;
  border: 1px solid var(--border);
  border-radius: 8px;
  font-size: 14.5px;
  color: var(--ink);
  text-decoration: none;
  background: #fff;
}
.search-pager a.pg:hover { border-color: var(--navy); color: var(--navy); }
.search-pager .pg-now { background: var(--navy); border-color: var(--navy); color: #fff; font-weight: 700; }

/* ---- iOS zoom-on-focus (build/call-54) ---------------------------- */
/* The /search form's own fields. Same reason as main.css: below 16px, iOS
   Safari zooms on focus. `.mls-quick` is NOT handled here, despite appearing
   on the listings page, because that page loads main.css and never loads this
   file. It is covered in main.css instead. */
@media (max-width: 900px) {
  .sf-field input, .sf-field select, .search-form input, .search-form select {
    font-size: 16px;
  }
}

/* The sweep measured this at 22px tall. Apple asks for 44. */
.sf-reset {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 4px;
}
