/**
 * Listing detail page
 *
 * The conversion page. Two jobs: let a hunter judge the ground quickly, and
 * keep the way to contact the landowner in reach.
 *
 * The page previously ran on Bootstrap semantic colours used decoratively --
 * five badge colours in the header strip, and border-info / border-danger /
 * border-success / border-primary on cards that had nothing to do with info,
 * danger or success. All of that is gone. Colour means something here or it is
 * not used.
 */

/* ===================================================================
 * Gallery
 * =================================================================== */

.listing-gallery {
    background-color: var(--color-timber-deep);
}

.listing-gallery .carousel-item img {
    width: 100%;
    height: clamp(280px, 52vh, 620px);
    object-fit: cover;
}

/* Hero photo as a control
 *
 * The image is wrapped in a button so the viewer is reachable by keyboard.
 * The button has to be invisible -- the photograph is the affordance, not a
 * chrome button around it -- while still showing a real focus ring. */
.gallery-open {
    display: block;
    width: 100%;
    padding: 0;
    border: 0;
    background: none;
    cursor: zoom-in;
    position: relative;
}

.gallery-open:focus-visible {
    outline: 3px solid var(--color-white);
    outline-offset: -3px;
}

/* Discoverability: nothing about a photograph says "this opens". The hint is
 * always present on touch, where there is no hover to reveal it. */
.gallery-open-hint {
    position: absolute;
    right: var(--spacing-3);
    bottom: var(--spacing-3);
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.35rem 0.75rem;
    border-radius: var(--radius-full);
    background-color: rgb(0 0 0 / 0.62);
    color: var(--color-white);
    font-size: var(--font-size-sm);
    line-height: 1;
    pointer-events: none;
}

@media (hover: hover) {
    .gallery-open-hint {
        opacity: 0;
        transition: opacity 0.15s ease;
    }

    .gallery-open:hover .gallery-open-hint,
    .gallery-open:focus-visible .gallery-open-hint {
        opacity: 1;
    }
}

/* Full-size photo viewer */
.listing-lightbox .modal-content {
    /* Solid, not translucent. At 0.94 the page behind stayed legible through
     * it, and a photo viewer wants a neutral black ground so nothing competes
     * with the image. */
    background-color: #000;
    border: 0;
    border-radius: 0;
    display: grid;
    grid-template-rows: auto 1fr auto;
    height: 100%;
}

.listing-lightbox-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--spacing-3);
    padding: var(--spacing-3) var(--spacing-4);
}

.listing-lightbox-count {
    color: rgb(255 255 255 / 0.75);
    font-family: var(--font-family-mono);
    font-size: var(--font-size-sm);
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.08em;
}

.listing-lightbox-body {
    min-height: 0;
}

.listing-lightbox-body .carousel-inner,
.listing-lightbox-body .carousel-item {
    height: 100%;
}

.listing-lightbox-body .carousel-item {
    display: none;
    align-items: center;
    justify-content: center;
}

.listing-lightbox-body .carousel-item.active,
.listing-lightbox-body .carousel-item-next,
.listing-lightbox-body .carousel-item-prev {
    display: flex;
}

/* contain, not cover. The hero crops to keep listing rows even; the whole
 * point of opening the viewer is to see the frame the crop was hiding. */
.listing-lightbox-body .carousel-item img {
    max-width: 100%;
    max-height: 100%;
    width: auto;
    height: auto;
    object-fit: contain;
}

.listing-lightbox-thumbs {
    display: flex;
    gap: var(--spacing-2);
    overflow-x: auto;
    padding: var(--spacing-3) var(--spacing-4);
    scrollbar-width: thin;
}

.listing-lightbox-thumb {
    flex: 0 0 auto;
    width: 84px;
    height: 56px;
    padding: 0;
    border: 2px solid transparent;
    border-radius: var(--radius-sm);
    background: none;
    opacity: 0.5;
    transition: opacity 0.15s ease, border-color 0.15s ease;
}

.listing-lightbox-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: calc(var(--radius-sm) - 2px);
}

.listing-lightbox-thumb.is-active,
.listing-lightbox-thumb:hover,
.listing-lightbox-thumb:focus-visible {
    opacity: 1;
    border-color: var(--color-white);
}

@media (max-width: 575.98px) {
    .listing-lightbox-thumbs {
        display: none;
    }
}

@media (prefers-reduced-motion: reduce) {
    .gallery-open-hint,
    .listing-lightbox-thumb {
        transition: none;
    }

    .listing-lightbox-body .carousel-item {
        transition: none;
    }
}

.listing-gallery-empty {
    display: flex;
    align-items: center;
    justify-content: center;
    height: clamp(200px, 32vh, 340px);
    color: rgb(255 255 255 / 0.6);
    font-family: var(--font-family-mono);
    font-size: var(--font-size-sm);
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

/* ===================================================================
 * Fact strip
 *
 * Replaces five differently-coloured badges. Set like the caption block
 * on a survey plate: mono, hairline-divided, label above value. One
 * treatment for every fact, so the eye reads them as one object rather
 * than ranking them by colour.
 * =================================================================== */

.listing-facts {
    display: flex;
    flex-wrap: wrap;
    gap: 0 var(--spacing-8);
    margin: 0 0 var(--spacing-8);
    padding: var(--spacing-4) 0;
    border-top: 2px solid var(--color-timber);
    border-bottom: 1px solid var(--color-gray-200);
    list-style: none;
}

.listing-fact {
    padding: var(--spacing-1) 0;
}

.listing-fact dt {
    font-family: var(--font-family-mono);
    font-size: var(--font-size-xs);
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--color-contour);
    margin-bottom: 0.15rem;
}

.listing-fact dd {
    margin: 0;
    font-family: var(--font-family-display);
    font-stretch: var(--font-stretch-display);
    font-weight: var(--font-weight-semibold);
    font-size: var(--font-size-lg);
    color: var(--color-gray-900);
    line-height: 1.2;
}

/* ===================================================================
 * Sections (replacing stacked cards)
 * =================================================================== */

.listing-section {
    margin-bottom: var(--spacing-12);
}

.listing-section > h2 {
    font-size: clamp(1.4rem, 2.6vw, 1.75rem);
    margin-bottom: var(--spacing-4);
}

.listing-section > h3 {
    font-size: var(--font-size-lg);
    margin: var(--spacing-6) 0 var(--spacing-3);
}

.listing-prose {
    max-width: 62ch;
    line-height: 1.7;
    color: var(--color-gray-800);
}

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

/* Lease rules: a definition list, not a row of badges. The yes/no answers are
 * words rather than green ticks and red crosses -- red on a rules list reads as
 * an error when it only means "not permitted". */
.rule-list {
    margin: 0;
    padding: 0;
    list-style: none;
}

.rule-list > li {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: var(--spacing-4);
    padding: 0.6rem 0;
    border-top: 1px solid var(--color-gray-200);
}

.rule-list > li:first-child {
    border-top: 0;
}

.rule-name {
    color: var(--color-gray-700);
}

.rule-value {
    font-weight: var(--font-weight-semibold);
    color: var(--color-gray-900);
}

.rule-value[data-allowed="no"] {
    font-weight: var(--font-weight-normal);
    color: var(--color-gray-500);
}

/* ===================================================================
 * Boundary map
 * =================================================================== */

.boundary-map-wrap {
    position: relative;
    /* isolation creates a stacking context, so the overlay's z-index below is
     * scoped to this box. position:relative alone would not, and a large value
     * would then compete with the navbar. */
    isolation: isolate;
    min-height: 500px;
    border-radius: var(--radius-lg);
    overflow: hidden;
}

.boundary-loading {
    position: absolute;
    inset: 0;
    display: none;
    align-items: center;
    justify-content: center;
    background: rgb(255 255 255 / 0.9);
    z-index: 2;
}

/* ===================================================================
 * Sidebar -- the conversion unit
 *
 * Sticks, so the price, the gate and the primary action stay with the
 * content that motivates them on a long page.
 *
 * Two constraints, both learned the hard way here:
 *   - sticky is a no-op for anything taller than the viewport. With quick
 *     facts and the affiliate skyscraper inside, this measured 1318px
 *     against an 801px viewport and never pinned.
 *   - anything placed after a pinned sticky keeps its flow position and
 *     gets covered by it. So this is the last element in its column, and
 *     the affiliate moved to the foot of the main column.
 *
 * max-height + auto overflow is the backstop for a short viewport or an
 * unusually long contact block: it degrades to scrollable, not un-pinned.
 * =================================================================== */
.listing-aside {
    position: sticky;
    top: var(--spacing-6);
    max-height: calc(100vh - var(--spacing-12));
    overflow-y: auto;
    /* Below Bootstrap dropdowns (1000) and modals (1050), as in blog_detail. */
    z-index: 100;
}

.booking-panel {
    padding: var(--spacing-6);
    background-color: var(--color-frost);
    border-top: 3px solid var(--color-timber);
    border-radius: 0 0 var(--radius-lg) var(--radius-lg);
}

.booking-price {
    font-family: var(--font-family-display);
    font-stretch: var(--font-stretch-display);
    font-weight: 800;
    font-size: clamp(2.25rem, 5vw, 3rem);
    line-height: 1;
    letter-spacing: -0.02em;
    color: var(--color-gray-900);
    font-variant-numeric: tabular-nums;
    margin: 0;
}

.booking-unit {
    font-family: var(--font-family-mono);
    font-size: var(--font-size-xs);
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--color-contour);
    margin: var(--spacing-2) 0 var(--spacing-5);
}

/* The subscription gate. Quiet and factual -- it explains what is behind the
 * wall rather than scolding, and the action next to it is the loud one. */
.listing-gate {
    padding: var(--spacing-5);
    background-color: var(--color-frost);
    border-left: 3px solid var(--color-contour);
    border-radius: 0 var(--radius-lg) var(--radius-lg) 0;
    margin-bottom: var(--spacing-4);
}

.listing-gate p {
    margin: 0;
    color: var(--color-gray-700);
    font-size: var(--font-size-sm);
    line-height: 1.6;
}

.aside-block {
    padding-top: var(--spacing-5);
    margin-top: var(--spacing-5);
    border-top: 1px solid var(--color-gray-200);
}

.aside-block h2 {
    font-size: var(--font-size-base);
    margin-bottom: var(--spacing-3);
}

.contact-lines {
    margin: 0;
    padding: 0;
    list-style: none;
    font-size: var(--font-size-sm);
}

.contact-lines li {
    padding: 0.3rem 0;
}

@media (max-width: 991.98px) {
    /* Sticky in a stacked single column would pin the panel over the content
     * it belongs beside. */
    .listing-aside {
        position: static;
        max-height: none;
        overflow-y: visible;
    }
}

/* ===================================================================
 * Booking calendar (flatpickr)
 *
 * Was hardcoded to Bootstrap blue #0d6efd with !important throughout,
 * which is now the one blue thing left on the site.
 * =================================================================== */

.flatpickr-calendar {
    box-shadow: var(--shadow-md);
    border: 1px solid var(--color-gray-200);
}

.flatpickr-calendar.inline {
    width: 100%;
    max-width: 100%;
}

.flatpickr-months {
    background-color: var(--color-timber);
}

.flatpickr-current-month .flatpickr-monthDropdown-months,
.flatpickr-current-month .numInputWrapper input,
.flatpickr-months .flatpickr-prev-month svg,
.flatpickr-months .flatpickr-next-month svg {
    color: var(--color-white);
    fill: var(--color-white);
}

.flatpickr-weekdays {
    background-color: var(--color-frost);
}

.flatpickr-day.selected,
.flatpickr-day.startRange,
.flatpickr-day.endRange {
    background-color: var(--color-primary);
    border-color: var(--color-primary);
}

.flatpickr-day.inRange {
    background-color: var(--color-primary-light);
    border-color: var(--color-primary-light);
    color: var(--color-white);
    box-shadow: none;
}

/* Unavailable dates. Muted and struck rather than filled red -- a booked date
 * is not an error, and a calendar of red blocks reads as one. */
.flatpickr-day.flatpickr-disabled,
.flatpickr-day.flatpickr-disabled:hover {
    background-color: var(--color-gray-100);
    color: var(--color-gray-400);
    text-decoration: line-through;
    cursor: not-allowed;
}
