/* ══ Newest rail — the homepage "Newly listed" strip ═══════
   A horizontally scrolling rail of listing cards, ordered by list_date. Two
   motions, chosen per site (Admin → Settings → Homepage Search):

     carousel  the track slides one card at a time on a timer. The script only
               sets the track's transform; the movement is a CSS transition.
               Prev/next buttons step it by hand.
     marquee   the track drifts continuously in a seamless loop, driven entirely
               by a CSS keyframes animation (the script only clones the cards so
               the loop has something to wrap into).

   Both motions move the track with `transform`, so the rail never relies on a
   native scroll container: the rail clips, the transform slides. That is also
   why there is no side fade — the rail is a clean clip.

   The rail fills its own container (`#home-rail-block`), and shows as many cards
   as fit that width; the card itself keeps a fixed size (`--newest-card-w`), so a
   wider container simply shows more of them. The nav arrows are inset by the same
   left cutoff the first card starts at, so they sit inside the rail rather than
   at an edge a parent may clip.

   The rail is theme-independent: it lives under themes/_static and sizes its own
   cards, so it renders the same in any theme — including one whose layout has no
   .listing-card rules (the default theme). It expects the shared card markup from
   src/views.js (renderListingResults). */

/* ── Shared sizing tokens ───────────────────────────────────────────────
   The card size and gap are the same for the rail and the per-type grids, so a
   card is the same size in both. */
.newest-rail,
.home-type-grid {
    --newest-gap: 20px;
    /* The grid card size — `.listing-grid` is `repeat(auto-fill, minmax(320px, 1fr))`
       — so a card is exactly as wide as a grid card. */
    --newest-card-w: 320px;
    /* The card image's shape, as a ratio rather than a fixed height: the rail's
       cards are a fixed width but the type-grid cards stretch to fill their
       column, so a fixed image height left the wider grid cards looking
       letterboxed. A ratio keeps the image the same shape at any card width. */
    --newest-card-ratio: 4 / 3;
}

.newest-rail {
    /* The left cutoff: the inset the first card starts at. One value, shared by
       the rail's padding and the nav arrows' insets, so they cannot drift apart. */
    --newest-pad: 1em;
    position: relative;
    /* The rail fits its own container (`#home-rail-block`, which already carries
       the page-column inset), so it never bleeds past a parent that clips it —
       that was what pushed the right arrow out of view. `overflow: hidden` is the
       clip for cards past the right edge — no side fade/blur. The vertical
       padding gives the cards' hover lift and shadow room inside the clip. */
    padding: 4px 0 12px var(--newest-pad);
    overflow: hidden;
}

.newest-rail-track {
    display: flex;
    gap: var(--newest-gap);
    /* Without JS the track is a plain horizontally scrollable row, so every card
       stays reachable. The script adds `is-enhanced` to switch to the
       transform-driven motion below. */
    overflow-x: auto;
    scrollbar-width: none;
}
.newest-rail-track::-webkit-scrollbar { display: none; }

/* ── Card sizing ────────────────────────────────────────────────────────────
   One fixed size, so the number shown is whatever fits the width — a wider
   screen shows more cards, a narrow one fewer, with no breakpoint bookkeeping. */
.newest-rail .listing-card {
    flex: 0 0 var(--newest-card-w);
    min-width: 0;
}

/* The card is styled by the theme's own .listing-card rules where they exist;
   these only guarantee a sane box in a theme that has none. Shared by the rail
   and the per-type grids, so a card looks the same in either. */
.newest-rail .listing-card,
.home-type-grid .listing-card {
    background: #fff;
    border: 1px solid #eceeec;
    border-radius: 14px;
    overflow: hidden;
    display: flex;
    flex-direction: column;
}
/* The image is sized by the shared ratio, so it is the same shape whether the
   card is the rail's fixed width or a grid card stretched to its column. The
   two-class selector outranks the theme's own `.listing-card-img` height. */
.newest-rail .listing-card-img,
.newest-rail .listing-card-img--empty,
.home-type-grid .listing-card-img,
.home-type-grid .listing-card-img--empty {
    width: 100%;
    height: auto;
    aspect-ratio: var(--newest-card-ratio);
    object-fit: cover;
    display: block;
}
.newest-rail .listing-card-img--empty,
.home-type-grid .listing-card-img--empty {
    background: linear-gradient(135deg, #eef2ee, #e3eae3);
    display: flex;
    align-items: center;
    justify-content: center;
    color: #9aa69c;
    font-size: 14px;
}

/* ── Enhanced (JS present): transform-driven motion ─────────────────────── */
/* The track stops being a scroll container; the rail's clip hides the overflow
   and the script slides the track with an inline transform. The transition here
   is what animates that transform, so the motion itself is CSS — a glide between
   one card position and the next rather than an instant jump. */
.newest-rail.is-enhanced .newest-rail-track {
    overflow: visible;
    transition: transform .8s cubic-bezier(.25, .8, .25, 1);
    will-change: transform;
}

/* ── Heading row: title left, "See all" right ─────────────────────────── */
.home-section-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 18px;
}
.home-section-head .section-heading { margin-bottom: 0; }
.section-see-all {
    font-size: 13.5px;
    font-weight: 600;
    color: #1e6b2a;
    white-space: nowrap;
    text-decoration: none;
}
.section-see-all:hover { text-decoration: underline; }

/* ── "Latest For Rent / For Sale" grids under the rail ──────────────────
   One per listing type, each in its own `.home-type-grid` container. The
   container caps its width (1100px) and centres — self-contained, so it stays a
   page column even when dropped outside the layout's own `.page-container`; the
   grid inside lays its cards out at the same fixed size as the rail, wrapping and
   scrolling down as needed, so a card looks identical in both. Each grid pages on
   its own param (`rent_page` / `sale_page`) via server-rendered links (a full
   page load), so paging one leaves the rail and the other grid in place. */
.home-type-grid {
    max-width: 1100px;
    margin: clamp(30px, 4vw, 46px) auto 0;
    /* The grid's pagination links carry `#home-type-<key>`, so a full-page pager
       lands on this section rather than the page top. The scroll margin keeps the
       sticky header from covering its heading. */
    scroll-margin-top: 72px;
}
.home-type-grid .listing-grid {
    display: grid;
    /* Cards are the rail's fixed size, but never wider than the column — on a
       narrow screen the grid collapses to one column instead of overflowing. */
    grid-template-columns: repeat(auto-fill, minmax(min(100%, var(--newest-card-w)), 1fr));
    gap: var(--newest-gap);
}
/* The pagination bar's classes are styled by each theme's own layout elsewhere;
   these keep the bar looking right in a theme that has no such rules. */
.home-type-grid .listing-pagination-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    padding: 10px 0;
}
.home-type-grid .lpg-count { font-size: 13px; color: #7c867d; }
.home-type-grid .lpg-nav { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.home-type-grid .lpg-btn,
.home-type-grid .lpg-page {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 34px;
    height: 34px;
    padding: 0 10px;
    border: 1px solid #dbe3db;
    border-radius: 8px;
    font-size: 13px;
    font-weight: 600;
    color: #3f4a41;
    text-decoration: none;
    background: #fff;
}
.home-type-grid .lpg-btn:hover,
.home-type-grid .lpg-page:hover { border-color: #9cc79c; color: #1e6b2a; text-decoration: none; }
.home-type-grid .lpg-btn.is-disabled { opacity: 0.45; pointer-events: none; }
.home-type-grid .lpg-pages { display: flex; align-items: center; gap: 4px; }
.home-type-grid .lpg-page.lpg-current { background: #1e6b2a; border-color: #1e6b2a; color: #fff; }

/* Homepage pagination setting off (Admin → Settings → Homepage): the hero grid's
   pager bars are hidden. They stay in the DOM (the <listing-pagination>
   component drives the in-place AJAX search), so this only hides them — it does
   not remove them. The count is dropped at render time, in the template. */
.home-no-pagination listing-pagination { display: none; }

/* ── Carousel: prev/next arrows overlaid on the rail ────────────────────
   The rail clips its overflow, so the controls live inside it. Both arrows are
   inset by `--newest-pad` — the same left cutoff the first card starts at — so
   the left arrow sits with the content and the right arrow stays clear of the
   viewport edge (the full-bleed rail reaches 100vw, which includes the
   scrollbar). The container ignores pointer events (cards stay clickable) while
   the buttons take them back. */
.newest-rail-nav {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 var(--newest-pad);
    pointer-events: none;
}
.newest-rail-btn {
    pointer-events: auto;
    width: 34px;
    height: 34px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid #dbe3db;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.92);
    color: #3f4a41;
    font-size: 18px;
    line-height: 1;
    cursor: pointer;
    padding: 0;
    box-shadow: 0 1px 4px rgba(20, 40, 24, 0.15);
    transition: border-color .15s, color .15s, background .15s, opacity .15s;
}
.newest-rail-btn:hover { border-color: #9cc79c; color: #1e6b2a; background: #fff; }
.newest-rail-btn:disabled { opacity: 0; pointer-events: none; }

/* ── Marquee: the track drifts; the cloned half makes it seamless ────────── */
.newest-rail[data-style="marquee"].is-enhanced .newest-rail-track {
    animation: newest-rail-scroll var(--newest-duration, 40s) linear infinite;
}
.newest-rail[data-style="marquee"]:hover .newest-rail-track,
.newest-rail[data-style="marquee"]:focus-within .newest-rail-track {
    animation-play-state: paused;
}
@keyframes newest-rail-scroll {
    /* The script sets --newest-from / --newest-to. `from` is 0 (the first card
       starts at the rail's left edge, which is the page column) and `to` is one
       card set to the left, so the loop wraps seamlessly. A plain var() is used
       (not calc over a var) because browsers drop a calc() over a custom property
       inside @keyframes, and the values must be set before the animation starts
       (see setupMarquee). */
    from { transform: translateX(var(--newest-from, 0px)); }
    to { transform: translateX(var(--newest-to, -50%)); }
}

/* On a narrow screen a fixed card would leave an awkward sliver of the next one,
   so one card takes most of the width. */
@media (max-width: 560px) {
    .newest-rail { --newest-card-w: 80vw; }
}

/* ── Price-change tag (beside a price) ───────────────────────────────────
   The last move in the listing's own price series, so one that was repriced says
   so at a glance.

   The base rules are deliberately NOT scoped to a container: the same tag is
   rendered on listing cards and on the detail page's price, and scoping here left
   the detail-page copy unstyled (bare text with a stray icon). Only the per-context
   SIZE adjustments below are scoped.

   A 10% tint of the tone, no border, 6px radius. Direction is carried by the arrow
   and the tone; the figure itself is unsigned, so it stays a single short token.

   `tabular-nums` keeps the digits from shifting as the value changes. */
.lc-change {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    margin-left: 6px;
    padding: 2px 6px;
    border-radius: 6px;
    font-size: 11px;
    font-weight: 700;
    line-height: 1;
    white-space: nowrap;
    vertical-align: middle;
    font-variant-numeric: tabular-nums;
}
/* The tone is its own pair of classes, independent of the direction classes the
   markup also carries (`--up` / `--down`). Which tone means which direction is
   then a single decision made in priceChangeBadge (see views.js), not something
   baked into the selectors — so changing it is one line rather than a rename
   through the CSS, the markup and the tests.

   The classes name the SENTIMENT, not the hue, so re-colouring one is a change to
   this block alone and never leaves a name that lies:

   `--attention`  a rise — amber. Warm and noticeable, but reads as "worth
                  noticing" rather than "bad". A price going up is bad for a
                  renter and neutral-to-good for an owner, so the tag must not
                  pass judgement on their behalf.
   `--favourable` a fall — emerald. Reads as good news for whoever is looking.

   The admin Price changes tab keeps its own pair (#1a7f37/#e6f4ea and
   #c62828/#fdecea): it is an analyst view on a plain table, where red-for-up is
   the expected convention. */
.lc-change--attention {
    color: #b45309;
    background: rgba(245, 158, 11, 0.12);
}
.lc-change--favourable {
    color: #059669;
    background: rgba(16, 185, 129, 0.1);
}
.lc-change-arrow {
    width: 12px;
    height: 12px;
    flex: none;
    fill: none;
    stroke: currentColor;
    stroke-width: 2.2;
    stroke-linecap: round;
    stroke-linejoin: round;
}
/* The detail page's price is much larger (1.4–1.6em) than a card's, so the tag
   steps up with it — same shape and tone as the card's, just a size bigger. Kept
   close to the card's 11px/2px 6px rather than proportionally scaled, so the two
   read as the same element. */
.price .lc-change { margin-left: 8px; padding: 3px 8px; font-size: 12px; border-radius: 6px; }
.price .lc-change-arrow { width: 13px; height: 13px; }

/* The compact card's price is much larger than the standard card's, so the tag
   steps up with it rather than sitting lost beside it. That row aligns on the
   baseline, which a padded tag cannot usefully share (its first child is an SVG,
   with no text baseline of its own), so the tag centres against the price. */
.listing-card--compact .listing-card-price .lc-change { font-size: 11.5px; margin-left: 8px; align-self: center; }
.listing-card--compact .listing-card-price .lc-change-arrow { width: 12px; height: 12px; }

/* ── "Recently viewed" rail ────────────────────────────────────────────────
   A second rail (the homepage's most-viewed listings) reusing the whole
   component: its cards are smaller and it never auto-scrolls (the markup sets
   `data-rail-autoplay="off"`). It sits in its own capped `.home-container`, like
   the other homepage sections, so it keeps the rail's standard left inset. */
.home-recently-viewed {
    margin-top: clamp(24px, 3vw, 40px);
}
/* ── Compact card (the "Recently viewed" rail) ────────────────────────────
   Trulia-style: image, price, a bed/bath/area line and the location. Tighter
   than the shared card and with no composed title, agency row or "View details"
   link, so nothing competes with the price. Two-class selectors so these beat a
   theme's own single-class .listing-card rules. */
.listing-card.listing-card--compact { border-radius: 12px; /* Don't stretch to the tallest card in the rail — a shorter card would then show a blank gap below its content. */ align-self: flex-start; }
.listing-card--compact .listing-card-body { flex: 0 0 auto; padding: 10px 12px 12px; display: flex; flex-direction: column; gap: 7px; }
/* One row, never wrapped: a second line would make the card taller than its
   neighbours in the rail. The price side may shrink and clip; the tag and the
   type marker keep their size. */
.listing-card--compact .listing-card-price { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; margin: 0; flex-wrap: nowrap; min-width: 0; }
.listing-card--compact .listing-card-price .lc-price { font-size: 1.3rem; font-weight: 800; color: #1e6b2a; letter-spacing: -0.01em; min-width: 0; overflow: hidden; white-space: nowrap; }
.listing-card .lc-type-icon { display: inline-flex; align-items: center; align-self: center; flex: none; color: #556a00; }
.listing-card .lc-type-icon--rent { color: #a16207; }
.listing-card--compact .listing-card-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; color: #3d434a; font-size: 12.5px; }
.listing-card--compact .listing-card-meta > span { display: inline-flex; align-items: center; gap: 4px; background: none; padding: 0; border-radius: 0; }
.listing-card--compact .listing-card-location { display: flex; align-items: center; gap: 4px; margin: 0; color: #767b81; font-size: 12.5px; min-width: 0; overflow: hidden; }
/* One line, truncated: the text span owns the ellipsis, so a long hierarchy
   cannot wrap the row and make the card taller. */
.listing-card .listing-card-location-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The rent frequency trailing a card's price ("/ Monthly"). Smaller and bolder
   than the amount, so it reads as a qualifier rather than part of the figure.
   The shared card had no rule for it at all — only the older per-page templates
   did — so on the home/browse/location cards it inherited the full price size. */
.listing-card .listing-card-price .rent-frequency { font-size: 0.66em; font-weight: bolder; }

/* The relative age ("3 days ago") a card carries for a recent listing
   (Admin → Settings → Listing settings). A plain caption over the photo, not a
   pill — the image already carries the property-type and locality tags, and a
   third filled chip read as one pill too many. All its styling is inline (the
   server owns the look); the theme's own single-class card rules must not turn
   it into a body row. Its containing block is the media box, so the tags anchor
   to the photo rather than to the rail. */
.listing-card-media { position: relative; }
.listing-card-media .listing-card-time-ago { position: absolute; }
.newest-rail.newest-rail--compact {
    /* A little smaller than the standard rail card, but not tiny. The image keeps
       the shared --newest-card-ratio (4/3): the ratio is deliberately NOT
       overridden here, so a compact card has the same shape as a standard card. */
    --newest-card-w: 240px;
}
@media (max-width: 560px) {
    .newest-rail.newest-rail--compact { --newest-card-w: 72vw; }
}

/* NOTE: the rail deliberately does NOT drop its motion under
   `prefers-reduced-motion`. Both styles exist to be seen moving (the admin picks
   the rail style on purpose), and disabling the motion per-OS made the rail look
   broken — the carousel jumped between cards and the marquee stood still. If
   reduced-motion support is wanted later, scale the durations rather than
   removing the transition/animation. */
