@charset "UTF-8";
/* ==========================================================================
   Property cards (.tiles .tile and the .card variant on the home page)
   --------------------------------------------------------------------------
   Loaded after compiled.purged.min.css and style.min.css so it can override
   the legacy card rules without editing those generated files.

   Two problems it fixes, plus one feature it adds:

   1. Ragged rows. `.tiles .tile .text-wrapper .title` had `min-height: 60px`
      and no maximum, so a three- or four-line name grew that card while its
      neighbours stayed short. The cards are floated Bootstrap 3 columns, so
      one tall card shunts the next row's cards sideways and the grid comes
      apart. The title is now exactly two lines, always.

   2. Cropped-from-the-top thumbnails. `.image-wrapper` was
      `max-height: 148px; overflow-y: hidden`, which slices the bottom off a
      tall photo instead of framing it.

   3. The swipeable card gallery — see js/card-gallery.js. Phone only.

   Margins rather than flex `gap` throughout, to match the rest of the site's
   CSS — `gap` is unsupported in IE11, which still gets the html5shiv shim.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Title: two lines, no more, no less
   -------------------------------------------------------------------------- */

.tiles .tile .text-wrapper .title,
.tiles .tile.trans .text-wrapper .title,
.tiles .tile.solid .text-wrapper .title,
.cards .card .text-wrapper .title {
    /* 2 x the 20px line-height the theme already sets. Fixed, not min/max, so
       every card in a row is the same height whatever its name. */
    height: 40px;
    min-height: 0;
    max-height: 40px;
    overflow: hidden;
    /* Clamp with an ellipsis where supported; the height above is what
       actually guarantees the alignment, so browsers without -webkit-box
       (IE11) still get a clean two-line crop, just without the "…". */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    text-overflow: ellipsis;
    word-break: break-word;
}

/* The full name is reachable as a native tooltip: the views put it in a
   title="" on the <h3>.

   There was a CSS reveal here first — the clamp lifted on :hover, the title
   growing in place over the row below it. Two things sank it. It had to paint
   an opaque colour behind itself, and picking that colour by hand put a white
   bar under the title on the home page's yellow cards. And growing the title
   grows the card: measured on /za-prodan, hovering the second of eleven cards
   pushed the eight below it down by 40px, so the grid jumped under the cursor.
   Overlaying instead of growing needs the title out of flow, which collapses
   the card by the same 40px unless every variant's padding is unpicked and
   rebuilt — three different paddings across .tile, .tile.solid and .card, all
   for a hover affordance. The attribute costs nothing and never moves a card. */

/* --------------------------------------------------------------------------
   Thumbnail framing
   -------------------------------------------------------------------------- */

.tiles .tile .image-wrapper {
    position: relative;
    max-height: none;
    /* Every file under uploads/images/gallery/listings/ is 360x200, so 9:5 is
       the whole photo and nothing but the photo. The old `max-height: 148px;
       overflow-y: hidden` cut the bottom 8% off in the 4-up grid and a quarter
       off in the 3-up one — and because it was a *max*, a card whose image was
       shorter than 148px kept its own height and knocked the row out of line. */
    aspect-ratio: 9 / 5;
    overflow: hidden;
    background-color: #f0f0f0;
}

.tiles .tile .image-wrapper > img {
    display: block;
    width: 100%;
    height: 100%;
    /* Fallback for browsers without aspect-ratio: the crop height they had. */
    max-height: 148px;
    -o-object-fit: cover;
    object-fit: cover;
}

/* Once aspect-ratio is in play the wrapper sets the height, so the fallback
   cap has to come back off or wider columns letterbox. */
@supports (aspect-ratio: 9 / 5) {
    .tiles .tile .image-wrapper > img {
        max-height: none;
    }
}

/* Most listing views have no .image-wrapper at all — the thumbnail is a direct
   child of the card's <a>. Those images are the same 360x200 files, so they
   already line up; pinning the ratio means they still line up when one of them
   is an odd size left over from an older import, or fails to load. */
.tiles .tile > img.img-responsive,
.tiles .tile > picture > img.img-responsive,
.cards .card > img.img-responsive,
.cards .card > picture > img.img-responsive {
    width: 100%;
    height: auto;
    aspect-ratio: 9 / 5;
    -o-object-fit: cover;
    object-fit: cover;
    background-color: #f0f0f0;
}

/* --------------------------------------------------------------------------
   Swipeable card gallery (phones)

   js/card-gallery.js wraps the existing thumbnail in .card-gallery and appends
   the rest of the property's photos beside it. Until that runs — and on every
   viewport above 767px — the markup is the plain single <img> it has always
   been.

   Built on scroll-snap rather than a carousel library: it is the native
   gesture, it keeps momentum and rubber-banding, and it costs no JavaScript
   per frame on exactly the devices least able to spare it.
   -------------------------------------------------------------------------- */

.card-gallery {
    position: relative;
    width: 100%;
    height: 100%;
}

/* .tiles cards nest the thumbnail in .image-wrapper, which already sets the
   box. The home page's .card has no wrapper, so the strip sizes itself — same
   9:5 as the 360x200 source files. */
.card-gallery--bare {
    height: auto;
    aspect-ratio: 9 / 5;
    overflow: hidden;
}

.card-gallery__track {
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    -ms-flex-wrap: nowrap;
    flex-wrap: nowrap;
    width: 100%;
    height: 100%;
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    -ms-scroll-snap-type: x mandatory;
    scroll-snap-type: x mandatory;
    /* The dots are the affordance; the bar itself would sit across the photo. */
    scrollbar-width: none;
    -ms-overflow-style: none;
}

.card-gallery__track::-webkit-scrollbar {
    display: none;
}

.card-gallery__slide {
    -webkit-box-flex: 0;
    -ms-flex: 0 0 100%;
    flex: 0 0 100%;
    width: 100%;
    height: 100%;
    scroll-snap-align: center;
    scroll-snap-stop: always;
}

.card-gallery__slide > img {
    display: block;
    width: 100%;
    height: 100%;
    -o-object-fit: cover;
    object-fit: cover;
}

/* Dots. Capped at 8 by the script; past that the strip reads as a smear of
   identical pips and stops telling you anything. */
.card-gallery__dots {
    position: absolute;
    right: 0;
    bottom: 8px;
    left: 0;
    z-index: 2;
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    -webkit-box-pack: center;
    -ms-flex-pack: center;
    justify-content: center;
    -webkit-box-align: center;
    -ms-flex-align: center;
    align-items: center;
    pointer-events: none;
    /* The photo underneath can be any colour; a hairline shadow keeps the
       inactive dots visible on a white wall or a bright sky. */
    -webkit-filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.55));
    filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.55));
}

.card-gallery__dot {
    width: 6px;
    height: 6px;
    margin: 0 3px;
    border-radius: 50%;
    background-color: rgba(255, 255, 255, 0.55);
    -webkit-transition: background-color 0.2s ease, -webkit-transform 0.2s ease;
    transition: background-color 0.2s ease, transform 0.2s ease;
}

.card-gallery__dot.is-active {
    background-color: #fff;
    -webkit-transform: scale(1.35);
    transform: scale(1.35);
}

/* Photo count, top-right. Worth the pixels: it is the only cue that a card has
   more than one photo before you touch it. */
.card-gallery__count {
    position: absolute;
    top: 8px;
    right: 8px;
    z-index: 2;
    padding: 0 8px;
    border-radius: 11px;
    background-color: rgba(0, 0, 0, 0.55);
    color: #fff;
    font-size: 11px;
    line-height: 20px;
    font-weight: 700;
    pointer-events: none;
}

/* Everything that overlays the thumbnail has to be lifted over the strip.
   .card-gallery is `position: relative`, and a positioned element paints above
   the floats and in-flow content that precede it — so without this the badges
   end up *behind* the photo.

   The corner ribbons ("SOLD", "PROMO", "RESERVED") are absolutely positioned
   against the card.

   The "for sale" / "for rent" pill is the more fragile one: it overlays by
   floating right with `margin-bottom: -100%` and `margin-top: -17px`, a
   pre-flexbox trick that only worked because a bare <img> is unpositioned and
   therefore painted underneath it. Its geometry still lands in the right place
   over the strip; it is purely the paint order that needs correcting. */
.tiles .tile .ribbon--red,
.tiles .tile .ribbon--yellow,
.tiles .tile .ribbon--reserved,
.tiles .tile .status,
.tiles .tile .type,
.cards .card .ribbon--red,
.cards .card .ribbon--yellow,
.cards .card .ribbon--reserved,
.cards .card .status,
.cards .card .type {
    z-index: 3;
}

@media (prefers-reduced-motion: reduce) {
    .card-gallery__dot {
        -webkit-transition: none;
        transition: none;
    }
}
