/**
 * Edmonton City Homes: Single Listing styles
 * assets/css/single-listing.css
 *
 * Scoped styles for the single-listing.php template. Loaded only on
 * single `listing` posts (see ech_enqueue_single_listing_assets() in
 * functions.php). Everything references design tokens from tokens.css;
 * no new colours, fonts, or spacing values are introduced here.
 *
 * Layout is mobile-first: base rules target small screens, with
 * min-width: 640px and min-width: 900px enhancements to match the
 * breakpoint conventions used in main.css.
 */


/* ============================================================
   1. HERO
   Full-bleed featured image with a bottom gradient scrim so the
   overlaid address stays legible on any photo. The image is an
   absolutely-positioned <img> (object-fit: cover) rather than a
   CSS background so it participates in loading priority hints.
   ============================================================ */

.listing-hero {
  position: relative;
  display: flex;
  align-items: flex-end;
  min-height: 55vh;
  overflow: hidden;
  background: var(--color-surface-inverse); /* Visible while the photo loads, or when there is none. */
}

@media (min-width: 900px) {
  .listing-hero {
    min-height: 70vh;
  }
}

.listing-hero__image {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Gradient scrim: transparent at the top, deep navy at the bottom,
   sitting between the photo and the text. */
.listing-hero__scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to bottom,
    rgba(10, 22, 40, 0) 40%,
    rgba(10, 22, 40, 0.72) 100%
  );
}

.listing-hero__content {
  position: relative;
  width: 100%;
  max-width: var(--container-wide);
  margin: 0 auto;
  padding: var(--space-6) var(--space-4) var(--space-5);
}

@media (min-width: 640px) {
  .listing-hero__content {
    padding: var(--space-8) var(--space-5) var(--space-6);
  }
}

.listing-hero__address {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-tight);
  color: var(--color-ink-inverse);
}

.listing-hero__city {
  margin: var(--space-2) 0 0;
  font-family: var(--font-body);
  font-size: var(--text-lg);
  color: var(--color-ink-inverse);
  opacity: 0.85;
}

/* --- Status badge: only rendered for Pending / Sold --- */

/* Matches the archive card badge (see .listing-archive__card-badge in
   archive-listing.css), scaled up one type step because the hero badge
   sits on a large full width photo rather than a small card. */
.listing-status-badge {
  display: inline-block;
  margin-bottom: var(--space-3);
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-full);
  font-family: var(--font-body);
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.listing-status-badge--pending {
  background: var(--color-warning);
  color: var(--color-ink-strong);
}

.listing-status-badge--sold {
  background: var(--color-danger);
  color: var(--color-ink-inverse);
}


/* ============================================================
   2. STICKY SUB-NAV
   Sticks directly beneath the site header. single-listing.js
   measures the header and sets --listing-header-offset on this
   element; the 0px fallback simply pins it to the viewport top
   if JS is unavailable.
   ============================================================ */

.listing-subnav {
  position: sticky;
  top: var(--listing-header-offset, 0px);
  z-index: 90; /* Below .site-header (100) so the header keeps its shadow on top. */
  background: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
}

.listing-subnav__inner {
  display: flex;
  gap: var(--space-2);
  max-width: var(--container-wide);
  margin: 0 auto;
  padding: 0 var(--space-4);
  overflow-x: auto; /* Horizontal scroll on narrow screens rather than wrapping. */
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}

.listing-subnav__inner::-webkit-scrollbar {
  display: none;
}

@media (min-width: 640px) {
  .listing-subnav__inner {
    gap: var(--space-4);
    padding: 0 var(--space-5);
  }
}

.listing-subnav__link {
  flex-shrink: 0;
  padding: var(--space-3) var(--space-2);
  border-bottom: 2px solid transparent;
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--color-ink-soft);
  text-decoration: none;
  transition:
    color var(--duration-fast) var(--ease-snappy),
    border-color var(--duration-fast) var(--ease-snappy);
}

.listing-subnav__link:hover {
  color: var(--color-ink);
}

.listing-subnav__link:focus-visible {
  outline: none;
  box-shadow: var(--shadow-focus);
  border-radius: var(--radius-sm);
}

/* Scroll-spy active state, toggled by single-listing.js. */
.listing-subnav__link.is-active {
  color: var(--color-accent);
  border-bottom-color: var(--color-accent);
}

/* Anchor targets need breathing room below the sticky header + sub-nav.
   --listing-scroll-offset is set by single-listing.js (header + sub-nav
   height); the fallback covers the no-JS case. */
.listing-gallery,
.listing-video,
.listing-map,
.listing-contact {
  scroll-margin-top: var(--listing-scroll-offset, 7rem);
}


/* ============================================================
   3. KEY FACTS STRIP
   Two-column grid on mobile, flowing row on desktop. Price gets
   display treatment; every other fact is label-over-value.
   ============================================================ */

.listing-facts {
  background: var(--color-surface-elevated);
  border-bottom: 1px solid var(--color-border);
}

.listing-facts__inner {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-4) var(--space-3);
  max-width: var(--container-wide);
  margin: 0 auto;
  padding: var(--space-5) var(--space-4);
}

@media (min-width: 640px) {
  .listing-facts__inner {
    grid-template-columns: repeat(4, 1fr);
    padding: var(--space-5) var(--space-5);
  }
}

@media (min-width: 900px) {
  .listing-facts__inner {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-5) var(--space-7);
  }
}

.listing-fact {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.listing-fact__label {
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-ink-soft);
}

.listing-fact__label sup {
  font-size: 0.65em;
}

.listing-fact__value {
  font-family: var(--font-body);
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  color: var(--color-ink);
}

/* Price leads the strip: display serif, spans the full row on mobile. */
.listing-fact--price {
  grid-column: 1 / -1;
}

@media (min-width: 640px) {
  .listing-fact--price {
    grid-column: auto;
  }
}

.listing-fact--price .listing-fact__value {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: var(--weight-semibold);
  color: var(--color-ink-strong);
  line-height: var(--leading-tight);
}


/* ============================================================
   SHARED: Section heading + section rhythm
   ============================================================ */

.listing-section-heading {
  margin: 0 0 var(--space-4);
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-snug);
  color: var(--color-ink-strong);
}


/* ============================================================
   4. DESCRIPTION
   Reading-width column for the editor content.
   ============================================================ */

.listing-description__inner {
  max-width: var(--container-narrow);
  margin: 0 auto;
  padding: var(--space-6) var(--space-4);
}

@media (min-width: 640px) {
  .listing-description__inner {
    padding: var(--space-7) var(--space-5);
  }
}

.listing-description__content {
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: var(--leading-relaxed);
  color: var(--color-ink);
}

.listing-description__content p {
  margin: 0 0 var(--space-4);
}

.listing-description__content p:last-child {
  margin-bottom: 0;
}


/* ============================================================
   5. PHOTO GALLERY
   Responsive grid: 1 column on mobile, 2 from 640px, 3 from
   900px, uniform 4:3 crops so rows always line up.

   Photos past the first 9 carry .listing-gallery__item--extra and
   are hidden while the viewport has data-expanded="false"; the
   "View all" button (single-listing.js) flips the attribute and
   the revealed items fade in.
   ============================================================ */

.listing-gallery {
  background: var(--color-surface-sunken);
}

.listing-gallery__inner {
  max-width: var(--container-wide);
  margin: 0 auto;
  padding: var(--space-6) var(--space-4);
}

@media (min-width: 640px) {
  .listing-gallery__inner {
    padding: var(--space-7) var(--space-5);
  }
}

.listing-gallery__viewport {
  margin-top: var(--space-4);
}

.listing-gallery__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-3);
  list-style: none;
  margin: 0;
  padding: 0;
}

@media (min-width: 640px) {
  .listing-gallery__grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 900px) {
  .listing-gallery__grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

.listing-gallery__figure {
  margin: 0;
}

/* The whole image is a zoom button; strip default button chrome.
   aspect-ratio crops every thumbnail to the same 4:3 frame. */
.listing-gallery__zoom {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  padding: 0;
  border: none;
  background: none;
  cursor: zoom-in;
  border-radius: var(--radius-md);
  overflow: hidden;
}

.listing-gallery__zoom:focus-visible {
  outline: none;
  box-shadow: var(--shadow-focus);
}

.listing-gallery__img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* --- Collapsed / expanded states --- */

.listing-gallery__viewport[data-expanded="false"] .listing-gallery__item--extra {
  display: none;
}

/* Short fade as the hidden photos reveal on expand. */
.listing-gallery__viewport[data-expanded="true"] .listing-gallery__item--extra {
  animation: listing-gallery-fade var(--duration-slow) var(--ease-smooth) both;
}

@keyframes listing-gallery-fade {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  .listing-gallery__viewport[data-expanded="true"] .listing-gallery__item--extra {
    animation: none;
  }
}

/* --- "View all N photos" / "Show fewer photos" button --- */

.listing-gallery__more {
  margin: var(--space-5) 0 0;
  text-align: center;
}


/* ============================================================
   5b. LIGHTBOX
   Fixed overlay. Hidden via the [hidden] attribute; JS removes
   it to open. Body scroll is locked with .listing-lightbox-open
   on <body> while active.
   ============================================================ */

.listing-lightbox {
  position: fixed;
  inset: 0;
  z-index: 200; /* Above the site header (100). */
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-3);
  background: rgba(10, 22, 40, 0.94); /* --color-ink-strong at near-full opacity. */
}

.listing-lightbox[hidden] {
  display: none;
}

.listing-lightbox__figure {
  margin: 0;
  max-width: 100%;
  max-height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.listing-lightbox__img {
  display: block;
  max-width: 92vw;
  max-height: 82vh;
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
}

.listing-lightbox__close,
.listing-lightbox__arrow {
  position: absolute;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border: none;
  border-radius: var(--radius-full);
  background: rgba(255, 255, 255, 0.12);
  color: var(--color-ink-inverse);
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease-snappy);
}

.listing-lightbox__close:hover,
.listing-lightbox__arrow:hover {
  background: rgba(255, 255, 255, 0.24);
}

.listing-lightbox__close:focus-visible,
.listing-lightbox__arrow:focus-visible {
  outline: none;
  box-shadow: var(--shadow-focus);
}

.listing-lightbox__close {
  top: var(--space-3);
  right: var(--space-3);
}

.listing-lightbox__arrow--prev {
  left: var(--space-2);
  top: 50%;
  transform: translateY(-50%);
}

.listing-lightbox__arrow--next {
  right: var(--space-2);
  top: 50%;
  transform: translateY(-50%);
}

@media (min-width: 640px) {
  .listing-lightbox__arrow--prev {
    left: var(--space-4);
  }

  .listing-lightbox__arrow--next {
    right: var(--space-4);
  }
}

.listing-lightbox__counter {
  position: absolute;
  bottom: var(--space-3);
  left: 50%;
  transform: translateX(-50%);
  margin: 0;
  font-family: var(--font-body);
  font-size: var(--text-sm);
  color: var(--color-ink-inverse);
  opacity: 0.8;
}

/* Lock page scroll while the lightbox is open. */
body.listing-lightbox-open {
  overflow: hidden;
}


/* ============================================================
   6. VIDEO
   Responsive 16:9 frame. Works for oEmbed iframes (YouTube/Vimeo)
   and native <video> alike.
   ============================================================ */

.listing-video__inner {
  max-width: var(--container-max);
  margin: 0 auto;
  padding: var(--space-6) var(--space-4);
}

@media (min-width: 640px) {
  .listing-video__inner {
    padding: var(--space-7) var(--space-5);
  }
}

.listing-video__frame {
  aspect-ratio: 16 / 9;
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--color-surface-inverse);
  box-shadow: var(--shadow-sm);
}

.listing-video__frame iframe,
.listing-video__frame video {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
}


/* ============================================================
   7. MAP
   Static map image links out to Google Maps. The no-key fallback
   is a quiet card with the address and an outbound button.
   ============================================================ */

.listing-map {
  background: var(--color-surface-elevated);
}

.listing-map__inner {
  max-width: var(--container-max);
  margin: 0 auto;
  padding: var(--space-6) var(--space-4);
}

@media (min-width: 640px) {
  .listing-map__inner {
    padding: var(--space-7) var(--space-5);
  }
}

.listing-map__link {
  display: block;
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
  transition: box-shadow var(--duration-base) var(--ease-smooth);
}

.listing-map__link:hover {
  box-shadow: var(--shadow-md);
}

.listing-map__link:focus-visible {
  outline: none;
  box-shadow: var(--shadow-focus);
}

.listing-map__img {
  display: block;
  width: 100%;
  height: auto;
}

.listing-map__fallback {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-5);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-surface);
}

.listing-map__fallback-address {
  margin: 0;
  font-family: var(--font-body);
  font-size: var(--text-base);
  font-weight: var(--weight-medium);
  color: var(--color-ink);
}


/* ============================================================
   8. CONTACT
   Stacked on mobile; agent card beside the form from 900px up.
   Form controls reuse the sitewide .home-form-* / .contact-form
   classes from main.css; only layout is defined here.
   ============================================================ */

.listing-contact__inner {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-6);
  max-width: var(--container-max);
  margin: 0 auto;
  padding: var(--space-6) var(--space-4) var(--space-8);
}

@media (min-width: 900px) {
  .listing-contact__inner {
    grid-template-columns: 2fr 3fr;
    gap: var(--space-7);
    padding: var(--space-7) var(--space-5) var(--space-8);
  }
}

/* --- Agent card --- */

.listing-agent-card {
  display: flex;
  gap: var(--space-4);
  align-items: flex-start;
  padding: var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-surface-elevated);
}

.listing-agent-card__photo img {
  display: block;
  width: 96px;
  height: auto;
  border-radius: var(--radius-md);
}

@media (min-width: 640px) {
  .listing-agent-card__photo img {
    width: 120px;
  }
}

.listing-agent-card__name {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  color: var(--color-ink-strong);
}

.listing-agent-card__title,
.listing-agent-card__brokerage {
  margin: var(--space-1) 0 0;
  font-family: var(--font-body);
  font-size: var(--text-sm);
  color: var(--color-ink-soft);
}

.listing-agent-card__contact {
  list-style: none;
  margin: var(--space-3) 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.listing-agent-card__link {
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--color-accent);
  text-decoration: none;
  transition: color var(--duration-fast) var(--ease-snappy);
}

.listing-agent-card__link:hover {
  color: var(--color-accent-hover);
  text-decoration: underline;
}

.listing-agent-card__link:focus-visible {
  outline: none;
  box-shadow: var(--shadow-focus);
  border-radius: var(--radius-sm);
}
