/* ==========================================================================
   LUXKEY — Design system
   Palette sampled directly from the company logo:
     purple #532D72 (51.6% of logo ink) · green #0F523F (46.9%) · gold #C3974C (1.5%)
   Gold mirrors its role in the logo: a hairline rule, never a text colour on
   light ground (it only reaches 2.6:1 there). On deep green it clears 4.9:1.
   ========================================================================== */

:root {
  /* Brand */
  --lux-green:        #0F523F;
  --lux-green-deep:   #0A3A2C;
  --lux-green-dark:   #072A20;
  --lux-purple:       #532D72;
  --lux-purple-lift:  #6B3F8C;
  --lux-gold:         #C3974C;
  --lux-gold-soft:    #E0C48A;

  /* Surfaces & ink */
  --lux-ivory:        #FBF9F5;
  --lux-paper:        #FFFFFF;
  --lux-mist:         #F2EFE9;
  --lux-ink:          #14201C;
  --lux-ink-soft:     #4B5A55;
  --lux-line:         #DDD8CF;

  /* Feedback */
  --lux-error:        #A32B2B;
  --lux-success:      #1E6B4A;

  /* Type */
  --font-display: "Fraunces", Georgia, "Times New Roman", serif;
  --font-body:    "Instrument Sans", system-ui, -apple-system, "Segoe UI", sans-serif;

  /* Spacing — 8px rhythm */
  --space-1: 8px;   --space-2: 16px;  --space-3: 24px;  --space-4: 32px;
  --space-5: 48px;  --space-6: 64px;  --space-7: 96px;  --space-8: 128px;

  /* Matches the Elementor pages, so listings, property detail and the built
     pages all share one column width instead of stepping in and out. */
  --wrap: 1440px;
  --radius: 2px;          /* near-square: the logo is architectural, not soft */
  --radius-card: 4px;

  --ease: cubic-bezier(.22,.61,.36,1);

  /* Layered z-index scale */
  --z-base: 1; --z-sticky: 40; --z-header: 60; --z-overlay: 90; --z-modal: 100;
}

/* --------------------------------------------------------------------------
   Reset & base
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--lux-ivory);
  color: var(--lux-ink);
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}

img, svg, video { max-width: 100%; height: auto; display: block; }
a { color: var(--lux-purple); text-underline-offset: 3px; }
a:hover { color: var(--lux-purple-lift); }

:focus-visible {
  outline: 3px solid var(--lux-purple);
  outline-offset: 3px;
  border-radius: var(--radius);
}
.on-dark :focus-visible, .lux-footer :focus-visible, .lux-hero :focus-visible {
  outline-color: var(--lux-gold-soft);
}

.lux-skip {
  position: absolute; left: -9999px; top: 0;
  background: var(--lux-green-deep); color: #fff;
  padding: var(--space-2) var(--space-3); z-index: var(--z-modal);
}
.lux-skip:focus { left: 0; }

.screen-reader-text {
  position: absolute !important; width: 1px; height: 1px;
  overflow: hidden; clip: rect(1px,1px,1px,1px); white-space: nowrap;
}

/* --------------------------------------------------------------------------
   Typography
   -------------------------------------------------------------------------- */
h1, h2, h3, h4 {
  font-family: var(--font-display);
  /* Fraunces carries more weight than Bodoni at the same value; 600 keeps
     headings solid at small sizes and on phones. */
  font-weight: 600;
  font-optical-sizing: auto;
  line-height: 1.15;
  letter-spacing: -0.01em;
  margin: 0 0 var(--space-2);
  text-wrap: balance;
}
h1 { font-size: clamp(2.6rem, 6vw, 4.6rem); }
h2 { font-size: clamp(2rem, 4vw, 3rem); }
h3 { font-size: clamp(1.3rem, 2vw, 1.6rem); }
h4 { font-size: 1.15rem; }
p  { margin: 0 0 var(--space-2); max-width: 68ch; }

/* The wide-tracked uppercase label echoes "LIMITED" in the logo lockup */
/* Wide tracking costs legibility, so these caps need more size than a normal
   label would: 0.72rem measured 11.5px on screen, which was too small to scan. */
.lux-eyebrow {
  font-family: var(--font-body);
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--lux-purple);
  margin: 0 0 var(--space-2);
  display: block;
}

.lux-lede { font-size: 1.18rem; color: var(--lux-ink-soft); max-width: 60ch; }

/* Every dark ground in the theme, not just .on-dark — the hero and the page
   banners set their own background, and purple/slate on deep green fails AA. */
.on-dark .lux-eyebrow,
.lux-hero .lux-eyebrow,
.lux-section--dark .lux-eyebrow { color: var(--lux-gold); }

.on-dark .lux-lede,
.lux-hero .lux-lede,
.lux-section--dark .lux-lede { color: rgba(255,255,255,.86); }

/* Signature device: the gold rule from the logo, notched like a key bit.
   Used to open sections — it encodes "LUXKEY", it isn't decoration. */
.lux-rule {
  --notch: 10px;
  height: 2px; border: 0; margin: 0 0 var(--space-3);
  width: 120px;
  background: var(--lux-gold);
  position: relative;
}
.lux-rule::after {
  content: ""; position: absolute; right: 0; top: -4px;
  width: var(--notch); height: 10px;
  background: var(--lux-gold);
  clip-path: polygon(0 40%, 100% 40%, 100% 100%, 70% 100%, 70% 70%, 45% 70%, 45% 100%, 0 100%);
}

/* --------------------------------------------------------------------------
   Layout
   -------------------------------------------------------------------------- */
.lux-wrap { width: min(100% - var(--space-4), var(--wrap)); margin-inline: auto; }
@media (min-width: 768px) { .lux-wrap { width: min(100% - var(--space-6), var(--wrap)); } }

.lux-section { padding-block: var(--space-6); }
@media (min-width: 768px) { .lux-section { padding-block: var(--space-7); } }

.lux-section--dark { background: var(--lux-green-deep); color: #fff; }
.lux-section--dark h1, .lux-section--dark h2, .lux-section--dark h3 { color: #fff; }
.lux-section--tint { background: var(--lux-mist); }

/* Glass treatment for solid-colour blocks — the dark green hero bands (and
   any card that should read as a pane rather than flat paint). Real
   glassmorphism, not a hint of one: soft glowing colour blooms (brand gold
   and green, never the neon tones of a generic template) sitting behind the
   pane, a bright diagonal gleam sweeping across it, and a lit edge — the
   same device as the reference mood boards, just in LUXKEY's own palette
   instead of theirs. It never sets `background` itself, so whatever colour
   the block already has (set inline or by another class) is exactly what
   shows through underneath all of this. backdrop-filter is inert on a
   full-bleed band with nothing behind it to blur — harmless, and it earns
   its keep the moment anything ever does sit behind one. */
.lux-glass {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid rgba(255,255,255,.16);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.22), 0 24px 60px -20px rgba(7,42,32,.5);
}
.lux-glass::before {
  content: ""; position: absolute; inset: -10%; z-index: 0; pointer-events: none;
  background:
    radial-gradient(closest-side at 88% 8%, rgba(195,151,76,.55), rgba(195,151,76,0) 70%),
    radial-gradient(closest-side at 6% 96%, rgba(255,255,255,.30), rgba(255,255,255,0) 65%),
    linear-gradient(125deg,
      rgba(255,255,255,.28) 0%, rgba(255,255,255,0) 30%,
      rgba(255,255,255,0) 58%, rgba(255,255,255,.10) 100%);
  filter: blur(2px);
}
.lux-glass > * { position: relative; z-index: 1; }

/* On a light/white block the same white gleam and edge would vanish, so both
   lean on ink and the brand green instead, and the gold bloom drops to a
   quieter opacity that reads as warmth rather than a stray yellow patch on
   white. Colour itself is still untouched — same rule as .lux-glass. */
.lux-glass--light {
  border: 1px solid rgba(20,32,28,.10);
  box-shadow: 0 1px 0 rgba(255,255,255,.7) inset, 0 22px 50px -22px rgba(7,42,32,.28);
}
.lux-glass--light::before {
  background:
    radial-gradient(closest-side at 90% 6%, rgba(195,151,76,.48), rgba(195,151,76,0) 72%),
    radial-gradient(closest-side at 4% 100%, rgba(15,82,63,.26), rgba(15,82,63,0) 68%),
    linear-gradient(125deg,
      rgba(255,255,255,.75) 0%, rgba(255,255,255,0) 32%,
      rgba(255,255,255,0) 58%, rgba(15,82,63,.08) 100%);
}

.lux-grid { display: grid; gap: var(--space-3); }
/* Mobile-first order matters here: these rules share specificity, so the wider
   breakpoint must come last. Written the other way round, the 640px rule won at
   desktop and three-column grids silently rendered as two. */
@media (min-width: 640px)  { .lux-grid--2 { grid-template-columns: repeat(2, 1fr); } }

@media (min-width: 640px)  { .lux-grid--3 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 900px)  { .lux-grid--3 { grid-template-columns: repeat(3, 1fr); } }

@media (min-width: 640px)  { .lux-grid--4 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 900px)  { .lux-grid--4 { grid-template-columns: repeat(4, 1fr); } }

.lux-section-head { margin-bottom: var(--space-5); max-width: 46rem; }

/* --------------------------------------------------------------------------
   Buttons
   -------------------------------------------------------------------------- */
.lux-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  min-height: 48px;                       /* touch target */
  padding: 12px var(--space-3);
  font-family: var(--font-body);
  font-size: 0.95rem; font-weight: 600; letter-spacing: 0.02em;
  border: 1.5px solid transparent; border-radius: var(--radius);
  text-decoration: none; cursor: pointer; white-space: nowrap;
  transition: background-color .2s var(--ease), color .2s var(--ease),
              border-color .2s var(--ease), transform .12s var(--ease);
}
.lux-btn:active { transform: translateY(1px); }

.lux-btn--primary   { background: var(--lux-green); color: #fff; }
.lux-btn--primary:hover { background: var(--lux-green-deep); color: #fff; }

.lux-btn--purple    { background: var(--lux-purple); color: #fff; }
.lux-btn--purple:hover { background: var(--lux-purple-lift); color: #fff; }

.lux-btn--ghost     { background: transparent; color: var(--lux-green); border-color: var(--lux-green); }
.lux-btn--ghost:hover { background: var(--lux-green); color: #fff; }

.on-dark .lux-btn--ghost, .lux-hero .lux-btn--ghost {
  color: #fff; border-color: rgba(255,255,255,.55);
}
.on-dark .lux-btn--ghost:hover, .lux-hero .lux-btn--ghost:hover {
  background: #fff; color: var(--lux-green-deep); border-color: #fff;
}

.lux-btn--wa { background: #1FA855; color: #fff; }
.lux-btn--wa:hover { background: #17843F; color: #fff; }

.lux-btn[disabled], .lux-btn[aria-disabled="true"] {
  opacity: .45; cursor: not-allowed; pointer-events: none;
}
.lux-btn-row { display: flex; flex-wrap: wrap; gap: var(--space-2); }

/* --------------------------------------------------------------------------
   Header
   -------------------------------------------------------------------------- */
/* Glass throughout: even at rest the bar is translucent and blurred, so
   whatever sits at the very top of the page (hero photo, a solid colour
   band) reads faintly through it rather than being hidden behind a flat
   ivory strip. A previous version carried a green/gold/purple gradient here;
   three hard colour stops read as a crest, not as luxury. */
.lux-header {
  position: sticky; top: 0; z-index: var(--z-header);
  background: rgba(251,249,245,.82);
  backdrop-filter: blur(10px) saturate(150%);
  -webkit-backdrop-filter: blur(10px) saturate(150%);
  transition:
    background-color .32s var(--ease),
    box-shadow .32s var(--ease),
    backdrop-filter .32s var(--ease);
}
/* A single gold hairline — the rule that sits under LIMITED in the logo. */
.lux-header::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0;
  height: 1px; background: var(--lux-gold); opacity: .38;
  transition: opacity .32s var(--ease);
}

/* Scrolled: the glass reads more emphatically — more blur, less light through,
   separated by shadow rather than by a line. */
.lux-header.is-stuck {
  background: rgba(251,249,245,.72);
  backdrop-filter: blur(16px) saturate(140%);
  -webkit-backdrop-filter: blur(16px) saturate(140%);
  box-shadow: 0 1px 0 rgba(15,82,63,.06), 0 10px 30px -12px rgba(7,42,32,.22);
}
.lux-header.is-stuck::after { opacity: 0; }

/* Browsers without backdrop-filter would show text over a transparent bar
   with the page sliding under it, unreadable in either state. Keep those
   closer to opaque. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .lux-header { background: rgba(251,249,245,.97); }
  .lux-header.is-stuck { background: rgba(251,249,245,.97); }
}

/* The bar itself never moves and never resizes — it is pinned at 88px from
   first paint, and only its background changes on scroll. No condensing, no
   hide-on-scroll-down: the logo and nav stay exactly where the eye left them. */
.lux-header__inner { min-height: 88px; }

@media (prefers-reduced-motion: reduce) {
  .lux-header,
  .lux-header::after { transition: none; }
}
/* The header carries more than the content columns do — brand, six nav items,
   phone and WhatsApp measure ~1215px, which overflows the 1200px content wrap
   and forces the nav to wrap. Give the bar its own wider container. */
.lux-header .lux-wrap { width: min(100% - var(--space-4), 1440px); }
@media (min-width: 768px) { .lux-header .lux-wrap { width: min(100% - var(--space-6), 1440px); } }

.lux-header__inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-3); min-height: 88px; flex-wrap: nowrap;
}
.lux-brand { display: flex; align-items: center; gap: 14px; text-decoration: none; }
/* The mark carries fine detail — the building outline, the K, the key shaft.
   Below ~50px those collapse into a smudge. */
.lux-brand img { height: 56px; width: auto; }

/* An uploaded logo brings its own width/height attributes and WordPress's own
   markup, so constrain it explicitly rather than relying on the wrapper. */
.lux-brand--logo { display: flex; align-items: center; }
.lux-brand--logo .custom-logo-link { display: block; line-height: 0; }
.lux-header .custom-logo {
  height: 56px;
  width: auto;
  max-width: min(340px, 46vw);
  object-fit: contain;
}
@media (max-width: 559px) {
  .lux-header .custom-logo { height: 42px; max-width: 54vw; }
}

/* Reproduces the printed lockup: LUXKEY over LIMITED, a gold rule, then the
   tagline in italic — rather than the wordmark alone. */
.lux-brand__name { white-space: nowrap; display: block; }

.lux-brand__word {
  display: block;
  font-family: var(--font-display); font-size: 1.65rem; line-height: 1;
  letter-spacing: .06em; color: var(--lux-green); font-weight: 700;
}
.lux-brand__limited {
  display: block;
  font-family: var(--font-body); font-size: .66rem; font-weight: 700;
  letter-spacing: .42em; text-transform: uppercase;
  color: var(--lux-green); margin-top: 4px;
}
.lux-brand__name em {
  display: block; position: relative;
  font-family: var(--font-display); font-style: italic;
  font-size: .82rem; letter-spacing: .01em;
  color: var(--lux-purple); margin-top: 7px; padding-top: 7px;
  text-transform: none; font-weight: 500;
}
/* The gold hairline from the logo, sitting between LIMITED and the tagline. */
.lux-brand__name em::before {
  content: ""; position: absolute; top: 0; left: 0; right: 0;
  height: 1px; background: var(--lux-gold);
}

@media (max-width: 900px) {
  .lux-brand__name em { display: none; }
}

.lux-nav ul { display: flex; gap: 30px; list-style: none; margin: 0; padding: 0; }
/* Lighter and smaller than it was, with tracking to open it up. Weight 600 in
   full brand green made every item shout as loudly as the current page. */
.lux-nav a {
  display: block; padding: 10px 2px;
  font-size: .87rem; font-weight: 450; letter-spacing: .045em;
  color: var(--lux-ink);
  text-decoration: none; position: relative;
  white-space: nowrap;              /* "Our Services" must not break in two */
  transition: color .22s var(--ease);
}
.lux-nav a:hover { color: var(--lux-green); }
.lux-nav a::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 2px; height: 1px;
  background: var(--lux-gold); transform: scaleX(0); transform-origin: left;
  transition: transform .22s var(--ease);
}
.lux-nav a:hover::after,
.lux-nav .current-menu-item > a::after,
.lux-nav .current_page_item > a::after { transform: scaleX(1); }
.lux-nav .current-menu-item > a,
.lux-nav .current_page_item > a { color: var(--lux-green); font-weight: 600; }

.lux-header__cta { display: flex; align-items: center; gap: var(--space-2); }

/* The phone number reads as a refined link, not a 210px outlined button.
   The icon carries the gold; the number stays in ink until hovered. */
.lux-tel {
  display: inline-flex; align-items: center; gap: 9px;
  padding: 8px 2px;
  font-size: .92rem; font-weight: 500; letter-spacing: .02em;
  color: var(--lux-ink); text-decoration: none;
  white-space: nowrap;
  transition: color .22s var(--ease);
}
.lux-tel .lux-i { width: 17px; height: 17px; color: var(--lux-gold); transition: color .22s var(--ease); }
.lux-tel:hover { color: var(--lux-green); }
.lux-tel:hover .lux-i { color: var(--lux-green); }
.lux-tel:focus-visible { outline: 2px solid var(--lux-green); outline-offset: 3px; border-radius: 2px; }

.lux-burger {
  display: none; width: 48px; height: 48px; align-items: center; justify-content: center;
  background: transparent; border: 1px solid var(--lux-line); border-radius: var(--radius);
  cursor: pointer;
}
.lux-burger span { display: block; width: 20px; height: 2px; background: var(--lux-ink); position: relative; }
.lux-burger span::before, .lux-burger span::after {
  content: ""; position: absolute; left: 0; width: 20px; height: 2px; background: var(--lux-ink);
  transition: transform .2s var(--ease);
}
.lux-burger span::before { top: -6px; } .lux-burger span::after { top: 6px; }
.lux-burger[aria-expanded="true"] span { background: transparent; }
.lux-burger[aria-expanded="true"] span::before { transform: translateY(6px) rotate(45deg); }
.lux-burger[aria-expanded="true"] span::after  { transform: translateY(-6px) rotate(-45deg); }

@media (max-width: 1023px) {
  .lux-burger { display: flex; }
  /* Anchored to the header itself rather than a hard-coded 88px — the bar
     condenses to 66px once scrolled, and a fixed offset left the panel
     floating in a gap below it. */
  .lux-nav {
    position: absolute; top: 100%; left: 0; right: 0;
    background: var(--lux-ivory); border-bottom: 1px solid var(--lux-line);
    box-shadow: 0 14px 30px -16px rgba(7,42,32,.3);
    padding: var(--space-3); display: none;
    max-height: calc(100dvh - var(--lux-header-h, 88px)); overflow-y: auto;
  }
  .lux-nav.is-open { display: block; }
  .lux-nav ul { flex-direction: column; gap: 0; }
  .lux-nav a { padding: 14px 0; border-bottom: 1px solid var(--lux-line); font-size: 1.05rem; letter-spacing: .02em; }
}

/* Below ~560px the number collides with the wordmark. Keep the tap target and
   the accessible name; show the icon alone. */
@media (max-width: 559px) {
  .lux-tel span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  /* 44×44 minimum once the number is hidden — icon alone left a 32px-wide target. */
  .lux-tel { padding: 12px; min-width: 44px; justify-content: center; }
  .lux-tel .lux-i { width: 20px; height: 20px; }
  .lux-brand img { height: 40px; }
  .lux-brand__word { font-size: 1.25rem; }
  .lux-brand__limited { font-size: .58rem; letter-spacing: .34em; margin-top: 2px; }
}
@media (max-width: 380px) {
  .lux-brand__limited { display: none; }
}

/* --------------------------------------------------------------------------
   Hero + featured slideshow
   -------------------------------------------------------------------------- */
.lux-hero { position: relative; background: var(--lux-green-dark); color: #fff; overflow: hidden; }
.lux-hero__intro { padding-block: var(--space-6) var(--space-4); position: relative; z-index: 2; }
/* Homepage variant: the featured property is the point, so the brand block
   above it stays compact rather than filling the first screen. */
.lux-hero__intro--tight { padding-block: var(--space-5) var(--space-3); }
.lux-hero__intro--tight h1 { font-size: clamp(2.2rem, 4.4vw, 3.4rem); }
.lux-hero__intro--tight .lux-lede { margin-bottom: 0; }
.lux-hero h1 { color: #fff; max-width: 15ch; }
.lux-hero h1 .accent { color: var(--lux-gold-soft); font-style: italic; }

.lux-slides { position: relative; }
.lux-slides__viewport { position: relative; aspect-ratio: 16 / 9; background: var(--lux-green-dark); }
@media (max-width: 767px) { .lux-slides__viewport { aspect-ratio: 4 / 3; } }

/* --------------------------------------------------------------------------
   Full-bleed hero (homepage)
   The property photograph is the hero. The brand line overlays it instead of
   sitting in a band above, so the first screen is the property.
   -------------------------------------------------------------------------- */
.lux-hero--full { position: relative; }

/* Full screen minus whatever the header actually measures. --lux-header-h is set
   by luxkey.js on load and resize, because the header's height changes with the
   logo the client uploads; the 96px fallback covers a no-JS render. */
.lux-hero--full .lux-slides__viewport {
  aspect-ratio: auto;
  min-height: calc(100dvh - var(--lux-header-h, 96px));
}
/* Keep the slideshow controls on screen rather than pushed below the fold. */
.lux-hero--full .lux-slides__nav { margin-top: calc(var(--space-5) * -1); position: relative; z-index: 4; }
@media (max-width: 767px) {
  .lux-hero--full .lux-slides__viewport { min-height: calc(100dvh - var(--lux-header-h, 80px)); }
}

/* Nothing sits at the top of the hero now, so the scrim stays light there and
   lets the photograph carry the screen. It only darkens where the property
   title, price and button need to stay legible. */
.lux-hero--full .lux-slide__scrim {
  background: linear-gradient(
    180deg,
    rgba(7,42,32,.18) 0%,
    rgba(7,42,32,.10) 34%,
    rgba(7,42,32,.52) 68%,
    rgba(7,42,32,.94) 100%
  );
}

/* Give the property block a little more room on a tall hero. */
.lux-hero--full .lux-slide__body { padding-bottom: var(--space-5); }

.lux-slide {
  position: absolute; inset: 0;
  opacity: 0; visibility: hidden;
  overflow: hidden;
  transition: opacity .7s var(--ease), visibility .7s var(--ease);
}
.lux-slide.is-active { opacity: 1; visibility: visible; }
.lux-slide__img { width: 100%; height: 100%; object-fit: cover; transform: scale(1); }
/* Slow "Ken Burns" drift while a slide is showing. Keyed to .is-active so the
   class toggle in luxkey.js (off, then on again next time round) restarts the
   animation from 0% each cycle instead of jumping. Runs longer than the 6.5s
   autoplay DELAY so the crossfade never catches it mid-reset. */
.lux-slide.is-active .lux-slide__img { animation: lux-slide-zoom 8s var(--ease) forwards; }
@keyframes lux-slide-zoom {
  from { transform: scale(1); }
  to   { transform: scale(1.08); }
}
@media (prefers-reduced-motion: reduce) {
  .lux-slide.is-active .lux-slide__img { animation: none; }
}
.lux-slide__scrim {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(7,42,32,.15) 0%, rgba(7,42,32,.55) 55%, rgba(7,42,32,.92) 100%);
}
.lux-slide__body {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: var(--space-4) 0;
}
.lux-slide__meta {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2);
  font-size: .85rem; color: rgba(255,255,255,.85); margin-bottom: 10px;
}
.lux-slide__title { font-size: clamp(1.6rem,3.4vw,2.6rem); color: #fff; margin-bottom: 6px; }
.lux-slide__excerpt {
  color: rgba(255,255,255,.82); font-size: .98rem; line-height: 1.6;
  max-width: 56ch; margin-bottom: var(--space-3);
}
.lux-slide__price {
  font-family: var(--font-display); font-size: 1.5rem; color: var(--lux-gold-soft);
  font-variant-numeric: tabular-nums; margin-bottom: var(--space-3);
}

.lux-badge {
  display: inline-flex; align-items: center; height: 26px; padding: 0 10px;
  font-size: .68rem; font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
  border-radius: var(--radius);
}
.lux-badge--sale { background: var(--lux-gold); color: #2A1E06; }
.lux-badge--rent { background: var(--lux-purple); color: #fff; }
.lux-badge--sold { background: var(--lux-ink); color: var(--lux-ivory); }

/* Slide controls */
.lux-slides__nav {
  display: flex; align-items: center; gap: var(--space-2);
  padding-block: var(--space-2); flex-wrap: wrap;
}
.lux-dots { display: flex; gap: 10px; list-style: none; margin: 0; padding: 0; }
.lux-dot {
  width: 44px; height: 44px; padding: 0; border: 0; background: transparent;
  cursor: pointer; display: grid; place-items: center;
}
.lux-dot::before {
  content: ""; width: 30px; height: 3px; background: rgba(255,255,255,.3);
  transition: background-color .25s var(--ease);
}
.lux-dot[aria-selected="true"]::before { background: var(--lux-gold); }
.lux-dot:hover::before { background: rgba(255,255,255,.6); }

.lux-slides__arrows { display: flex; gap: var(--space-1); margin-left: auto; }
.lux-arrow {
  width: 48px; height: 48px; display: grid; place-items: center;
  background: transparent; color: #fff;
  border: 1px solid rgba(255,255,255,.4); border-radius: var(--radius); cursor: pointer;
  transition: background-color .2s var(--ease);
}
.lux-arrow:hover { background: rgba(255,255,255,.14); }

/* --------------------------------------------------------------------------
   Cards
   -------------------------------------------------------------------------- */
.lux-card {
  background: var(--lux-paper);
  border: 1px solid var(--lux-line);
  border-radius: var(--radius-card);
  overflow: hidden;
  display: flex; flex-direction: column;
  transition: border-color .25s var(--ease), box-shadow .25s var(--ease);
}
.lux-card:hover { border-color: var(--lux-gold); box-shadow: 0 10px 30px rgba(15,82,63,.10); }
.lux-card__media { position: relative; aspect-ratio: 4 / 3; background: var(--lux-mist); overflow: hidden; }
.lux-card__media img { width: 100%; height: 100%; object-fit: cover; transition: transform .5s var(--ease); }
.lux-card:hover .lux-card__media img { transform: scale(1.04); }
.lux-card__badge { position: absolute; top: var(--space-2); left: var(--space-2); }
.lux-card__body { padding: var(--space-3); display: flex; flex-direction: column; flex: 1; gap: 6px; }
.lux-card__title { font-size: 1.3rem; margin: 0; }
.lux-card__title a { color: var(--lux-ink); text-decoration: none; }
.lux-card__title a:hover { color: var(--lux-green); }
.lux-card__loc { font-size: .88rem; color: var(--lux-ink-soft); display: flex; align-items: center; gap: 6px; }
.lux-card__price {
  font-family: var(--font-display); font-size: 1.32rem; color: var(--lux-green);
  font-variant-numeric: tabular-nums; margin-top: 2px;
}
.lux-card__excerpt { font-size: .93rem; color: var(--lux-ink-soft); margin: 0; }
.lux-card__facts {
  display: flex; flex-wrap: wrap; gap: var(--space-2);
  font-size: .84rem; color: var(--lux-ink-soft);
  padding-top: var(--space-2); margin-top: auto;
  border-top: 1px solid var(--lux-line);
}
.lux-card__facts span { display: inline-flex; align-items: center; gap: 5px; }
.lux-card__actions { display: flex; gap: var(--space-1); padding: 0 var(--space-3) var(--space-3); }
.lux-card__actions .lux-btn { flex: 1; }
/* The icon-only WhatsApp action stays square rather than claiming half the row */
.lux-card__actions .lux-btn--wa { flex: 0 0 52px; padding-inline: 0; }

/* Service / value cards */
.lux-tile {
  background: var(--lux-paper); border: 1px solid var(--lux-line);
  border-top: 3px solid var(--lux-green);
  border-radius: var(--radius-card); padding: var(--space-4);
  display: flex; flex-direction: column; gap: 10px;
}
.lux-tile--purple { border-top-color: var(--lux-purple); }
.lux-tile--gold   { border-top-color: var(--lux-gold); }
.lux-tile__icon { width: 40px; height: 40px; color: var(--lux-green); }
.lux-tile--purple .lux-tile__icon { color: var(--lux-purple); }
.lux-tile h3 { margin: 0; }
.lux-tile p { font-size: .95rem; color: var(--lux-ink-soft); margin: 0; }
.lux-tile__link {
  margin-top: auto; padding-top: var(--space-2);
  font-weight: 600; font-size: .9rem; text-decoration: none;
  display: inline-flex; align-items: center; gap: 8px;
}
.lux-tile__link::after { content: "→"; transition: transform .2s var(--ease); }
.lux-tile__link:hover::after { transform: translateX(4px); }

.on-dark .lux-tile {
  background: rgba(255,255,255,.05); border-color: rgba(255,255,255,.16);
  border-top-color: var(--lux-gold); color: #fff;
}
.on-dark .lux-tile p { color: rgba(255,255,255,.78); }
.on-dark .lux-tile__icon { color: var(--lux-gold); }

/* Glass variant — a tile meant to sit on a photo backdrop (see
   .lux-section--photo below) rather than the solid paper background .lux-tile
   sets by default. Pairs with .lux-glass, which adds the blur/bloom/gleam;
   this only overrides the flat background and text colour .lux-tile would
   otherwise impose over them. */
.lux-tile--glass {
  background: rgba(255,255,255,.08);
  border-color: rgba(255,255,255,.22);
  color: #fff;
}
.lux-tile--glass p { color: rgba(255,255,255,.92); }
.lux-tile--glass .lux-tile__icon { color: var(--lux-gold-soft); }

/* A full-bleed photo backdrop for a section, scrimmed dark enough for a
   .lux-glass card to sit on top of and still be legible. */
.lux-section--photo { position: relative; overflow: hidden; color: #fff; }
.lux-section--photo__img {
  position: absolute; inset: 0; z-index: 0;
  width: 100%; height: 100%; object-fit: cover;
}
.lux-section--photo__scrim {
  position: absolute; inset: 0; z-index: 0;
  background: linear-gradient(180deg, rgba(7,42,32,.74) 0%, rgba(7,42,32,.86) 100%);
}

/* --------------------------------------------------------------------------
   Property review scorecard — the signature block.
   The brief's differentiator: properties are reviewed, not just listed.
   -------------------------------------------------------------------------- */
.lux-review {
  background: var(--lux-green-deep); color: #fff;
  border-radius: var(--radius-card); padding: var(--space-4);
}
.lux-review__head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--space-2); flex-wrap: wrap; margin-bottom: var(--space-3);
}
.lux-review__head h3 { color: #fff; margin: 0; }
/* The block carries its own dark ground, so the eyebrow must go gold here even
   when the surrounding section is light — purple on deep green is only ~1.5:1. */
.lux-review .lux-eyebrow { color: var(--lux-gold); }
.lux-review__score {
  font-family: var(--font-display); font-size: 2.4rem; color: var(--lux-gold-soft);
  font-variant-numeric: tabular-nums; line-height: 1;
}
.lux-review__score small { font-size: .9rem; color: rgba(255,255,255,.6); }
.lux-review__list { display: grid; gap: var(--space-3); margin: 0; padding: 0; }
@media (min-width: 700px) { .lux-review__list { grid-template-columns: 1fr 1fr; gap: var(--space-3) var(--space-5); } }

.lux-metric { border-top: 1px solid rgba(255,255,255,.18); padding-top: 12px; }
.lux-metric__top { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); }
.lux-metric__name {
  font-size: .82rem; font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; color: var(--lux-gold);
}
.lux-metric__val { font-size: .92rem; color: rgba(255,255,255,.85); font-variant-numeric: tabular-nums; }
.lux-metric__bar { height: 4px; background: rgba(255,255,255,.16); margin: 10px 0 8px; }
.lux-metric__fill { height: 100%; background: var(--lux-gold); }
.lux-metric p { font-size: .9rem; color: rgba(255,255,255,.82); margin: 0; max-width: none; }

/* --------------------------------------------------------------------------
   Property detail
   -------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------
   Hero brand statement
   -------------------------------------------------------------------------- */
.lux-hero { position: relative; }

.lux-hero__brand {
  position: absolute; inset: 0 0 auto 0;
  z-index: 3;
  padding-top: clamp(var(--space-4), 12vh, var(--space-8));
  /* A scrim, so white type stays legible whatever photograph is behind it.
     Measured against the brightest slide rather than assumed. */
  /* Scrim strength is set from the actual photograph behind it — see
     adaptHeroScrim() in luxkey.js. A pale slide gets a deeper scrim, a dark one
     gets a lighter touch, so the type keeps its contrast without burying the
     picture. Transitioned, so the change reads as part of the slide crossfade. */
  --hero-scrim: .78;
  background: linear-gradient(180deg,
    rgba(7,42,32,var(--hero-scrim)) 0%,
    rgba(7,42,32,calc(var(--hero-scrim) * .68)) 55%,
    rgba(7,42,32,0) 100%);
  transition: --hero-scrim .5s var(--ease), background .5s var(--ease);
  /* Small. The block sits above the slideshow's own property caption and a
     generous bottom padding pushed it 62px into that caption. */
  padding-bottom: var(--space-3);
  /* The slideshow arrows and dots sit underneath; let clicks through except on
     the actual controls. */
  pointer-events: none;
}
.lux-hero__brand a,
.lux-hero__brand .lux-btn-row { pointer-events: auto; }

.lux-hero__title {
  color: #fff;
  font-size: clamp(2.6rem, 7vw, 5.2rem);
  line-height: 1.02;
  margin: 0 0 var(--space-1);
  max-width: 15ch;
}
.lux-hero__sub {
  color: #fff;
  font-size: clamp(1.05rem, 2vw, 1.5rem);
  font-weight: 500;
  margin: 0;
  max-width: none;
}
/* One line on anything wider than a phone. It wrapped mid-sentence at 34ch,
   which broke the rhythm of the statement. */
@media (min-width: 768px) { .lux-hero__sub { white-space: nowrap; } }
.lux-hero__body {
  color: rgba(255,255,255,.82);
  font-size: 1rem;
  line-height: 1.6;
  margin: 0 0 var(--space-2);
  max-width: 52ch;
}
.lux-hero__cta { gap: var(--space-2); }

/* Short and small screens: the photograph and the property caption need the
   room more than a paragraph does. Headline and buttons always survive. */
/* The paragraph is the first thing to go when height is short — the headline,
   the promise and the two buttons always survive. 860px rather than 700px
   because the property caption occupies the lower third of the hero. */
@media (max-width: 640px), (max-height: 860px) {
  .lux-hero__body { display: none; }
}
@media (max-height: 660px) {
  .lux-hero__sub { display: none; }
}
/* On a phone 12vh of top padding is ~97px, which pushed the block down to
   within 5px of the property caption. The hero is tall but the caption owns the
   bottom third, so the brand block starts higher instead. */
@media (max-width: 640px) {
  .lux-hero__brand { padding-top: var(--space-3); }
}
@media (max-width: 480px) {
  .lux-hero__sub { font-size: 1rem; max-width: 28ch; }
  .lux-hero__brand .lux-eyebrow { font-size: .68rem; letter-spacing: .12em; }
}

/* Breadcrumb. The links were 16px tall with no padding — readable, but a poor
   tap target on a phone, where the guideline is 44px. Padding gives them height
   without changing how the trail looks. */
.lux-crumbs { font-size: .85rem; margin-bottom: var(--space-2); }
.lux-crumbs a { display: inline-block; padding: 10px 2px; }
@media (max-width: 767px) {
  .lux-crumbs a { padding: 12px 4px; }
  .lux-crumbs { margin-bottom: var(--space-1); }
}

/* --------------------------------------------------------------------------
   Parallax background bands (About Us)

   Set a background image on any Elementor section of the About page and it
   scrolls at a different rate to the content in front of it. Nothing here needs
   JavaScript, so there is no way for it to hide content if a script fails —
   which is how the Services page went blank twice.

   Desktop and pointer devices only. background-attachment: fixed is genuinely
   broken on iOS Safari and janky on most Android browsers, where it either
   ignores the fix or repaints the whole layer every frame. Below 1024px, and on
   touch, the image simply sits still — which looks fine and costs nothing.

   Elementor's own class is applied to sections and to flexbox containers, so
   both are covered. On an element with no background image this is a no-op.
   -------------------------------------------------------------------------- */
@media (min-width: 1024px) and (prefers-reduced-motion: no-preference) {
  @media (hover: hover) and (pointer: fine) {
    .page-id-14 .elementor-section,
    .page-id-14 .e-con,
    .lux-parallax {
      background-attachment: fixed;
      background-size: cover;
      background-position: center;
    }
  }
}

/* --------------------------------------------------------------------------
   Single post: article left, related reading right
   -------------------------------------------------------------------------- */
.lux-post__layout { display: grid; gap: var(--space-5); }
.lux-post__main { min-width: 0; }

@media (min-width: 1000px) {
  /* The column itself sets the measure — the prose fills it edge to edge.
     Capping the text as well as the column left a band of dead space between
     the last word and the sidebar. So the LAYOUT is narrowed instead: 1120px
     minus the sidebar and gap puts the article at roughly 80 characters, which
     is the width the text then simply fills. */
  .lux-post__layout { grid-template-columns: minmax(0, 1fr) 320px; gap: var(--space-5); align-items: start; max-width: 1120px; margin-inline: auto; }
  .lux-post__layout--solo { grid-template-columns: minmax(0, 1fr); }
  /* Follows the reader down a long article. */
  .lux-post__asideInner { position: sticky; top: calc(var(--lux-header-h, 88px) + var(--space-3)); }
}

/* No second cap inside the column. */
.lux-post__main .lux-article,
.lux-post__main .lux-article--flush { max-width: none; margin-inline: 0; }

.lux-post__asideTitle { font-size: 1.25rem; margin: 0 0 var(--space-3); }

.lux-related { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-3); }
.lux-related__item { display: grid; grid-template-columns: 72px 1fr; gap: var(--space-2); align-items: start; }
.lux-related__media img { width: 72px; height: 72px; object-fit: cover; border-radius: var(--radius); }
.lux-related__title { font-size: 1rem; line-height: 1.3; margin: 0 0 4px; }
.lux-related__title a { color: var(--lux-ink); text-decoration: none; }
.lux-related__title a:hover { color: var(--lux-green); }
.lux-related__meta { font-size: .78rem; color: var(--lux-ink-soft); margin: 0; }

/* Blog index, category and tag archives are card grids, not running text, so
   they take the same wider measure as a property page. The 1440px site measure
   is set for reading and left ~230px of empty ivory each side at 1920.

   Single posts deliberately do NOT get this: the article is already 84
   characters a line, which is the top of the comfortable range. Their bands
   were widened in single.php instead, so the header and featured image fill
   more of the screen while the prose stays readable. */
.blog .lux-wrap,
.archive .lux-wrap,
.search .lux-wrap { width: min(100% - var(--space-4), 1760px); }

/* On a property page the photography IS the product, so it gets the screen.
   The site-wide 1440px measure is set for reading; here it left ~230px of empty
   ivory down each side of the gallery on a wide monitor. Gutters stay small
   rather than zero so the images still read as a composed block, not a banner.

   Deliberately not 100vw: on Windows that includes the scrollbar width and
   introduces a horizontal scroll on the whole page. */
/* 16px each side on phones, matching the rest of the site. Widening the page
   for desktop had quietly tightened the mobile gutter to 12px. */
.single-property .lux-wrap { width: min(100% - var(--space-4), 1760px); }
@media (min-width: 768px) {
  .single-property .lux-wrap { width: min(100% - var(--space-4), 1760px); }
}

.lux-detail__gallery { display: grid; gap: 8px; }
@media (min-width: 800px) {
  .lux-detail__gallery { grid-template-columns: 2fr 1fr; grid-template-rows: 1fr 1fr; height: 560px; }
  .lux-detail__gallery > :first-child { grid-row: span 2; }
  .lux-detail__gallery img { height: 100%; }
}
.lux-detail__gallery img { width: 100%; object-fit: cover; border-radius: var(--radius); }

.lux-detail__layout { display: grid; gap: var(--space-5); }
@media (min-width: 1000px) { .lux-detail__layout { grid-template-columns: minmax(0,1fr) 380px; align-items: start; gap: var(--space-6); } }

.lux-specs { display: grid; grid-template-columns: repeat(2,1fr); gap: var(--space-3); margin: 0 0 var(--space-4); padding: 0; }
@media (min-width: 640px) { .lux-specs { grid-template-columns: repeat(4,1fr); } }
.lux-specs div { border-left: 2px solid var(--lux-gold); padding-left: var(--space-2); }
.lux-specs dt { font-size: .7rem; letter-spacing: .16em; text-transform: uppercase; color: var(--lux-ink-soft); font-weight: 600; }
.lux-specs dd { margin: 4px 0 0; font-family: var(--font-display); font-size: 1.3rem; font-variant-numeric: tabular-nums; }

.lux-amenities { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
@media (min-width: 600px) { .lux-amenities { grid-template-columns: 1fr 1fr; } }
.lux-amenities li { display: flex; gap: 10px; align-items: flex-start; font-size: .95rem; }
.lux-amenities svg { flex: none; width: 18px; height: 18px; color: var(--lux-green); margin-top: 3px; }

/* "+N photos" overlay on the last visible gallery tile */
.lux-detail__gallery a { position: relative; display: block; overflow: hidden; border-radius: var(--radius); }
.lux-detail__gallery a img { transition: transform .5s var(--ease); }
.lux-detail__gallery a:hover img { transform: scale(1.03); }
.lux-gallery-more::after {
  content: attr(data-more);
  position: absolute; inset: 0;
  display: grid; place-items: center;
  background: rgba(7,42,32,.66); color: #fff;
  font-family: var(--font-display); font-size: 1.35rem;
}

/* Lightbox */
.lux-lightbox {
  position: fixed; inset: 0; z-index: var(--z-modal);
  /* Solid, not translucent: at 94% the header still ghosted through and
     competed with the photograph. */
  background: var(--lux-green-dark);
  display: grid; place-items: center; padding: 0;
}
.lux-lightbox[hidden] { display: none; }
/* Fill the viewport rather than sit at natural size. max-width/max-height are
   ceilings, not targets, so a 1280px photo used to float in the middle of a
   1900px screen. width/height with object-fit:contain scales it up to fill while
   keeping the aspect ratio, letterboxing whichever axis is short. */
.lux-lightbox img {
  width: 100%; height: 100dvh;
  max-width: 100%; max-height: 100dvh;
  object-fit: contain;
  border-radius: 0;
}
/* Photo transitions.

   These are CSS *animations*, not transitions from opacity:0, and that is
   deliberate. An animation's final keyframe is the visible state, so the photo
   ends up on screen whether or not anything removes the class, and it is never
   hidden while waiting for script. Content that stays invisible until JS
   rescues it has blanked pages on this site twice.

   The whole block is inside prefers-reduced-motion: no-preference, so a viewer
   who has asked for stillness gets an instant swap and no drift. */
@media (prefers-reduced-motion: no-preference) {
  /*
   * NO fill-mode. This is the whole safety property and an earlier version got
   * it wrong: `both` holds the FROM keyframe whenever the animation is not
   * running, so "not animating" resolved to opacity:0 and the photo sat
   * invisible. With the default fill-mode of `none` the element falls back to
   * its own styles — visible — the instant the animation is over, absent, or
   * cancelled.
   *
   * All three states are a single class ON THE IMAGE, so they share specificity
   * and JS guarantees only one is present. Scoping the open state to the parent
   * (.lux-lightbox.is-opening img) made it outrank the navigation rules and win
   * permanently, because the parent class was never removed.
   */
  .lux-lightbox img.is-in-open { animation: lux-photo-open .44s var(--ease); }
  .lux-lightbox img.is-in-next { animation: lux-photo-next .42s var(--ease); }
  .lux-lightbox img.is-in-prev { animation: lux-photo-prev .42s var(--ease); }
  .lux-lightbox.is-opening     { animation: lux-lb-open .28s var(--ease); }
}

/* Travelling forward: the next photo arrives from the right. */
@keyframes lux-photo-next {
  from { opacity: 0; transform: translateX(34px) scale(.985); }
  to   { opacity: 1; transform: none; }
}
@keyframes lux-photo-prev {
  from { opacity: 0; transform: translateX(-34px) scale(.985); }
  to   { opacity: 1; transform: none; }
}
/* Opening lifts the photo forward rather than sliding it, so the gesture reads
   as "this expanded" rather than "a new thing arrived". */
@keyframes lux-photo-open {
  from { opacity: 0; transform: scale(.94); }
  to   { opacity: 1; transform: none; }
}
@keyframes lux-lb-open {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* Controls must stay above a photo that now reaches the screen edges. */
.lux-lightbox__bar,
.lux-lightbox__nav { z-index: 2; }
/* And stay legible against a light photograph behind them. */
.lux-lightbox__bar { background: linear-gradient(rgba(7,42,32,.62), transparent); }
.lux-lightbox__nav button { background: rgba(7,42,32,.55); backdrop-filter: blur(6px); }
.lux-lightbox__bar {
  position: absolute; top: 0; left: 0; right: 0;
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-2); padding: var(--space-2) var(--space-3);
  color: #fff; font-size: .9rem;
}
.lux-lightbox button {
  width: 48px; height: 48px; display: grid; place-items: center;
  background: rgba(255,255,255,.12); color: #fff;
  border: 1px solid rgba(255,255,255,.32); border-radius: var(--radius); cursor: pointer;
}
.lux-lightbox button:hover { background: rgba(255,255,255,.24); }
.lux-lightbox__nav { position: absolute; left: 0; right: 0; bottom: var(--space-3);
  display: flex; justify-content: center; gap: var(--space-2); }

/* Access & services */
.lux-notes { display: grid; gap: var(--space-3); margin: var(--space-3) 0 0; padding: 0; }
@media (min-width: 700px) { .lux-notes { grid-template-columns: 1fr 1fr; gap: var(--space-3) var(--space-5); } }
.lux-notes > div { border-top: 1px solid var(--lux-line); padding-top: 12px; }
.lux-notes dt {
  display: flex; align-items: center; gap: 8px;
  font-size: .74rem; font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; color: var(--lux-green);
}
.lux-notes__icon { display: inline-flex; color: var(--lux-gold); }
.lux-notes__icon svg { width: 16px; height: 16px; }
.lux-notes dd { margin: 6px 0 0; font-size: .95rem; color: var(--lux-ink-soft); }

/* Listed-by card */
.lux-agent {
  display: flex; align-items: center; gap: var(--space-2);
  margin-top: var(--space-3); padding-top: var(--space-3);
  border-top: 1px solid var(--lux-line);
}
.lux-agent__photo { width: 56px; height: 56px; border-radius: 50%; object-fit: cover; flex: none; }
.lux-agent__name { font-family: var(--font-display); font-size: 1.15rem; margin: 0; }
.lux-agent__title { font-size: .85rem; color: var(--lux-ink-soft); margin: 0; }

/* Agent dashboard */
.lux-status {
  display: inline-flex; align-items: center; height: 24px; padding: 0 10px;
  font-size: .68rem; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  border-radius: 999px;
}
.lux-status--publish { background: rgba(30,107,74,.14); color: var(--lux-success); }
.lux-status--pending { background: rgba(195,151,76,.2); color: #7A5A18; }
.lux-status--draft   { background: var(--lux-mist); color: var(--lux-ink-soft); }

.lux-table { width: 100%; border-collapse: collapse; }
.lux-table th, .lux-table td { text-align: left; padding: 14px 12px; border-bottom: 1px solid var(--lux-line); }
.lux-table th { font-size: .72rem; letter-spacing: .14em; text-transform: uppercase; color: var(--lux-ink-soft); }
.lux-table td { font-size: .95rem; }
.lux-table-wrap { overflow-x: auto; }

.lux-aside {
  position: sticky; top: 108px;   /* clears the 88px sticky header */
  background: var(--lux-paper); border: 1px solid var(--lux-line);
  border-radius: var(--radius-card); padding: var(--space-3);
}
.lux-aside__price { font-family: var(--font-display); font-size: 2rem; color: var(--lux-green); font-variant-numeric: tabular-nums; }

.lux-map { aspect-ratio: 16/10; border: 0; width: 100%; border-radius: var(--radius); }
.lux-video { aspect-ratio: 16/9; width: 100%; border: 0; border-radius: var(--radius); }

/* --------------------------------------------------------------------------
   Filters
   -------------------------------------------------------------------------- */
.lux-filters {
  background: var(--lux-paper); border: 1px solid var(--lux-line);
  border-radius: var(--radius-card);
  padding: var(--space-3);
  margin-bottom: var(--space-5);
}
.lux-filters__eyebrow {
  margin: 0 0 var(--space-2); font-size: .68rem; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: var(--lux-green);
}
.lux-filters__row { display: grid; gap: var(--space-2); }
@media (min-width: 700px)  { .lux-filters__row { grid-template-columns: repeat(2,1fr); } }
@media (min-width: 1000px) { .lux-filters__row { grid-template-columns: repeat(4,1fr) auto; align-items: end; } }

.lux-filters__sort {
  display: flex; gap: var(--space-2); align-items: center; flex-wrap: wrap;
  margin-top: var(--space-2);
}
@media (max-width: 560px) { .lux-filters__sort { flex-direction: column; align-items: stretch; } }

.lux-chiprow { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: var(--space-3); }
.lux-chip {
  display: inline-flex; align-items: center; min-height: 40px; padding: 0 16px;
  font-size: .88rem; font-weight: 600; text-decoration: none;
  color: var(--lux-ink); background: var(--lux-mist);
  border: 1px solid transparent; border-radius: 999px;
  transition: background-color .2s var(--ease), color .2s var(--ease);
}
.lux-chip:hover { background: var(--lux-line); color: var(--lux-ink); }
.lux-chip[aria-current="true"] { background: var(--lux-green); color: #fff; }

/* --------------------------------------------------------------------------
   Forms
   -------------------------------------------------------------------------- */
.lux-field { margin-bottom: var(--space-3); }
.lux-field > label,
.lux-field > .lux-label,
.lux-fieldset > legend {
  display: block; font-size: .82rem; font-weight: 600; letter-spacing: .04em;
  margin-bottom: 8px; color: var(--lux-ink);
}
.lux-req { color: var(--lux-error); margin-left: 2px; }
.lux-help { font-size: .82rem; color: var(--lux-ink-soft); margin: 6px 0 0; }

.lux-input, .lux-select, .lux-textarea {
  width: 100%; min-height: 48px; padding: 12px 14px;
  font-family: var(--font-body); font-size: 1rem; color: var(--lux-ink);
  background: var(--lux-paper);
  border: 1px solid var(--lux-line); border-radius: var(--radius);
  transition: border-color .2s var(--ease), box-shadow .2s var(--ease);
}
.lux-textarea { min-height: 130px; resize: vertical; }
.lux-input:focus, .lux-select:focus, .lux-textarea:focus {
  border-color: var(--lux-green); box-shadow: 0 0 0 3px rgba(15,82,63,.14); outline: none;
}
.lux-input[aria-invalid="true"], .lux-select[aria-invalid="true"], .lux-textarea[aria-invalid="true"] {
  border-color: var(--lux-error); box-shadow: 0 0 0 3px rgba(163,43,43,.12);
}
.lux-error {
  display: flex; align-items: center; gap: 6px;
  font-size: .84rem; color: var(--lux-error); margin-top: 6px; font-weight: 500;
}
.lux-fieldset { border: 0; margin: 0 0 var(--space-3); padding: 0; }

/* Service picker — radio cards. One column: each card now carries a title
   plus a description line, and a two-up grid left no room for either to
   read cleanly — a cluttered single line was a large part of why this
   picker read as unpolished. */
/* Spacing lives on the item (margin-bottom), not a parent `gap` — a CSS
   Grid/Flexbox gap is fixed regardless of a child's own size, so collapsing
   an unchosen card to zero height would still leave a gap-sized blank slot
   next to it. Margin collapses along with the card. */
.lux-choices { display: flex; flex-direction: column; }
.lux-choice { position: relative; margin-bottom: 10px; }
.lux-choice:last-child { margin-bottom: 0; }
.lux-choice input {
  position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer;
}
.lux-choice span {
  display: flex; align-items: flex-start; gap: 14px;
  padding: 14px 16px;
  background: var(--lux-paper); border: 1.5px solid var(--lux-line);
  border-radius: var(--radius); font-weight: 500; font-size: .95rem;
  transition: border-color .2s var(--ease), background-color .2s var(--ease);
}

/* Once a service is picked, the rest collapse away rather than sitting
   there redundant — narrower focus, feels considered rather than just a
   long list. JS-driven only: with no JS every card stays exactly as before. */
.lux-choice {
  max-height: 240px; overflow: hidden;
  transition: max-height .45s var(--ease), opacity .35s var(--ease),
              margin-bottom .45s var(--ease), padding-bottom 0s;
}
.lux-choices.is-narrowed .lux-choice.is-collapsed {
  max-height: 0; opacity: 0; margin-bottom: 0; pointer-events: none;
}
@media (prefers-reduced-motion: reduce) {
  .lux-choice { transition: none; }
}

.lux-choice-change {
  margin-top: 2px; background: none; border: 0; padding: 0;
  font: inherit; font-size: .84rem; font-weight: 600; color: var(--lux-purple);
  cursor: pointer; text-decoration: underline; text-underline-offset: 3px;
}
.lux-choice-change:hover { color: var(--lux-purple-lift); }
.lux-choice-change[hidden] { display: none; }
.lux-choice input:hover + span { border-color: var(--lux-green); }
.lux-choice input:checked + span {
  border-color: var(--lux-green); background: rgba(15,82,63,.06);
}
.lux-choice input:focus-visible + span { outline: 3px solid var(--lux-purple); outline-offset: 2px; }

.lux-choice__icon {
  flex: none; width: 38px; height: 38px; margin-top: 1px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%; background: var(--lux-mist); color: var(--lux-green);
  transition: background-color .2s var(--ease), color .2s var(--ease);
}
.lux-choice__icon .lux-i { width: 18px; height: 18px; }
.lux-choice input:checked + span .lux-choice__icon { background: var(--lux-green); color: var(--lux-ivory); }

.lux-choice__body { display: flex; flex-direction: column; gap: 3px; padding-top: 2px; }
.lux-choice__title { font-weight: 600; font-size: .96rem; color: var(--lux-ink); }
.lux-choice input:checked + span .lux-choice__title { color: var(--lux-green-deep); }
.lux-choice__desc { font-weight: 400; font-size: .82rem; line-height: 1.4; color: var(--lux-ink-soft); }

.lux-branch { display: none; }
.lux-branch.is-active { display: block; animation: luxFade .3s var(--ease); }
@keyframes luxFade { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .lux-branch.is-active { animation: none; } }

.lux-notice {
  padding: var(--space-3); border-radius: var(--radius-card);
  border-left: 3px solid var(--lux-success); background: rgba(30,107,74,.07);
  margin-bottom: var(--space-4);
}
.lux-notice--error { border-left-color: var(--lux-error); background: rgba(163,43,43,.07); }
.lux-notice h3 { margin-top: 0; }

/* --------------------------------------------------------------------------
   Blog
   -------------------------------------------------------------------------- */
.lux-post-card__cat {
  font-size: .7rem; letter-spacing: .16em; text-transform: uppercase;
  font-weight: 700; color: var(--lux-purple); margin-bottom: 8px; display: block;
}
.lux-post-card__meta { font-size: .82rem; color: var(--lux-ink-soft); }
.lux-article { max-width: 720px; margin-inline: auto; }
/* Left-aligned in a column that is already constrained, but still capped: with
   the property page now 1760px wide the overview would otherwise run to about
   180 characters a line, which nobody can read. */
.lux-article--flush { max-width: 62ch; margin-inline: 0; }
.lux-article p, .lux-article li { font-size: 1.06rem; }
/* Article headings, not page headings. The global h2 is clamp(2rem, 4vw, 3rem)
   — up to 48px — which is right for a page title and far too loud for a section
   heading inside a 750px column of body text. These are sized against the prose
   they sit in. */
.lux-article h2 {
  font-size: clamp(1.35rem, 1.9vw, 1.7rem);
  margin-top: var(--space-4);
  margin-bottom: var(--space-2);
}
.lux-article h3 {
  font-size: clamp(1.1rem, 1.4vw, 1.25rem);
  margin-top: var(--space-3);
  margin-bottom: var(--space-1);
}
.lux-article blockquote {
  margin: var(--space-4) 0; padding-left: var(--space-3);
  border-left: 3px solid var(--lux-gold);
  font-family: var(--font-display); font-size: 1.3rem; font-style: italic;
}
.lux-pagination { display: flex; gap: 8px; justify-content: center; margin-top: var(--space-5); }
.lux-pagination .page-numbers {
  display: grid; place-items: center; min-width: 44px; min-height: 44px; padding: 0 12px;
  border: 1px solid var(--lux-line); border-radius: var(--radius);
  text-decoration: none; color: var(--lux-ink);
}
.lux-pagination .page-numbers.current { background: var(--lux-green); color: #fff; border-color: var(--lux-green); }

/* --------------------------------------------------------------------------
   Footer + floating WhatsApp
   -------------------------------------------------------------------------- */
.lux-footer { background: var(--lux-green-dark); color: rgba(255,255,255,.78); padding-block: var(--space-6) var(--space-4); }
.lux-footer h3 { color: #fff; font-family: var(--font-body); font-size: .78rem; letter-spacing: .18em; text-transform: uppercase; margin-bottom: var(--space-2); }
.lux-footer a { color: rgba(255,255,255,.78); text-decoration: none; }
.lux-footer a:hover { color: var(--lux-gold-soft); }
.lux-footer ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.lux-footer__grid { display: grid; gap: var(--space-5); }
@media (min-width: 700px)  { .lux-footer__grid { grid-template-columns: 1.4fr 1fr 1fr; } }
@media (min-width: 1000px) { .lux-footer__grid { grid-template-columns: 1.6fr 1fr 1fr 1.2fr; } }
.lux-footer__logo { height: 88px; width: auto; margin-bottom: var(--space-2); }
.lux-footer__bottom {
  margin-top: var(--space-5); padding-top: var(--space-3);
  border-top: 1px solid rgba(255,255,255,.15);
  display: flex; flex-wrap: wrap; gap: var(--space-2); justify-content: space-between;
  font-size: .85rem;
}

/* --------------------------------------------------------------------------
   Star ratings
   Two stacked rows of five; the filled row is clipped by width, which handles
   halves without a separate half-star glyph.
   -------------------------------------------------------------------------- */
.lux-stars { display: inline-flex; align-items: center; gap: 8px; vertical-align: middle; }
.lux-stars__set { position: relative; display: inline-block; line-height: 0; white-space: nowrap; }
.lux-stars__empty,
.lux-stars__fill { display: block; line-height: 0; white-space: nowrap; }
.lux-stars__empty { color: rgba(15,82,63,.22); }
.lux-stars__fill {
  position: absolute; inset: 0 auto 0 0;
  overflow: hidden; color: var(--lux-gold);
}
.lux-stars svg { width: 1em; height: 1em; display: inline-block; fill: currentColor; }
.lux-stars__num { font-weight: 700; font-variant-numeric: tabular-nums; line-height: 1; }

.lux-stars--sm { font-size: 14px; }
.lux-stars--sm .lux-stars__num { font-size: .84rem; }
.lux-stars--md { font-size: 17px; }
.lux-stars--md .lux-stars__num { font-size: .95rem; }
.lux-stars--lg { font-size: 24px; }
.lux-stars--lg .lux-stars__num { font-size: 1.2rem; }

/* On dark bands the empty stars need to read against the green, not vanish. */
.on-dark .lux-stars__empty,
.lux-hero .lux-stars__empty,
.lux-section--dark .lux-stars__empty { color: rgba(255,255,255,.26); }

/* --------------------------------------------------------------------------
   Measured amenities
   -------------------------------------------------------------------------- */
.lux-geo { margin-top: var(--space-3); }
.lux-geo__group { margin-bottom: var(--space-3); }
.lux-geo__label {
  font-family: var(--font-body);
  font-size: .72rem; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--lux-green); margin: 0 0 8px;
}
.lux-geo__list { list-style: none; margin: 0; padding: 0; }
.lux-geo__list li {
  display: flex; align-items: baseline; gap: var(--space-2);
  padding: 7px 0; border-bottom: 1px solid var(--lux-line);
}
.lux-geo__list li:last-child { border-bottom: none; }
.lux-geo__name { flex: 1 1 auto; min-width: 0; }
/* Tabular figures so the distance column lines up down the list. */
.lux-geo__km {
  flex: 0 0 auto; font-variant-numeric: tabular-nums;
  font-size: .88rem; font-weight: 600; color: var(--lux-ink-soft);
}
.lux-geo__note {
  margin: var(--space-2) 0 0;
  font-size: .78rem; line-height: 1.5; color: var(--lux-ink-soft);
}

@media (min-width: 640px) {
  .lux-geo { display: grid; grid-template-columns: 1fr 1fr; gap: 0 var(--space-4); }
  .lux-geo__note { grid-column: 1 / -1; }
}

/* Video walkthrough + documents held */
.lux-video__frame {
  position: relative; aspect-ratio: 16 / 9;
  border-radius: var(--radius); overflow: hidden;
  background: var(--lux-green-dark);
}
.lux-video__frame iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

.lux-docs__lede { color: var(--lux-ink-soft); max-width: 60ch; }
.lux-docs__list { list-style: none; margin: var(--space-2) 0; padding: 0; display: grid; gap: 8px; }
@media (min-width: 600px) { .lux-docs__list { grid-template-columns: 1fr 1fr; } }
.lux-docs__list li { display: flex; align-items: center; gap: 10px; }
.lux-docs__list .lux-i { color: var(--lux-green); flex: 0 0 auto; }
.lux-docs__note {
  font-size: .88rem; color: var(--lux-ink-soft);
  border-left: 3px solid var(--lux-gold); padding-left: var(--space-2); margin-top: var(--space-3);
}

/* --------------------------------------------------------------------------
   Photography pending
   Has to read as a considered choice, not a failed image load. Brand surface,
   gold rule, centred type — the same vocabulary as the rest of the site.
   -------------------------------------------------------------------------- */
.lux-nophoto {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 10px; width: 100%; height: 100%;
  padding: var(--space-3);
  text-align: center;
  color: rgba(255,255,255,.92);
  background:
    linear-gradient(140deg, var(--lux-green-deep) 0%, var(--lux-green-dark) 100%);
  position: relative;
}
/* The gold hairline from the logo lockup. */
.lux-nophoto::after {
  content: ""; position: absolute; left: 50%; transform: translateX(-50%);
  bottom: 18px; width: 46px; height: 1px; background: var(--lux-gold);
}
.lux-nophoto--card { aspect-ratio: 4 / 3; }
.lux-nophoto--hero { aspect-ratio: 16 / 9; border-radius: var(--radius); }

.lux-nophoto__icon { width: 34px; height: 34px; color: var(--lux-gold); }
.lux-nophoto--hero .lux-nophoto__icon { width: 46px; height: 46px; }

.lux-nophoto__title {
  margin: 0;
  font-family: var(--font-body);
  font-size: .74rem; font-weight: 700;
  letter-spacing: .18em; text-transform: uppercase;
  color: #fff;
}
.lux-nophoto--hero .lux-nophoto__title { font-size: .82rem; }

.lux-nophoto__note {
  margin: 0 0 18px; max-width: 42ch;
  font-size: .84rem; line-height: 1.5;
  color: rgba(255,255,255,.74);
}
.lux-nophoto--hero .lux-nophoto__note { font-size: .95rem; max-width: 54ch; }

/* --------------------------------------------------------------------------
   Featured posts strip + promoted property (blog)
   -------------------------------------------------------------------------- */
.lux-featured-strip { display: grid; gap: var(--space-3); margin-bottom: var(--space-5); }
@media (min-width: 860px) { .lux-featured-strip { grid-template-columns: 1fr 1fr; gap: var(--space-4); } }

.lux-feat {
  display: grid; gap: var(--space-2);
  background: var(--lux-green-deep); color: #fff;
  border-radius: var(--radius-card); overflow: hidden;
}
.lux-feat__media img { width: 100%; aspect-ratio: 16 / 9; object-fit: cover; transition: transform .6s var(--ease); }
.lux-feat:hover .lux-feat__media img { transform: scale(1.04); }
.lux-feat__body { padding: 0 var(--space-3) var(--space-3); }
.lux-feat .lux-eyebrow { color: var(--lux-gold); }
.lux-feat__title { font-size: clamp(1.2rem, 2vw, 1.5rem); line-height: 1.2; margin: 0 0 var(--space-1); }
.lux-feat__title a { color: #fff; text-decoration: none; }
.lux-feat__title a:hover { color: var(--lux-gold-soft); }
.lux-feat__excerpt { color: rgba(255,255,255,.78); font-size: .92rem; margin: 0 0 var(--space-2); }
.lux-feat .lux-post-card__meta { color: rgba(255,255,255,.62); }

/* One promoted listing among the articles. Gold rule so it reads as an
   invitation rather than a stray search result. */
.lux-promo {
  display: grid; gap: var(--space-3);
  margin-top: var(--space-5);
  padding-top: var(--space-4);
  border-top: 2px solid var(--lux-gold);
}
@media (min-width: 760px) { .lux-promo { grid-template-columns: 300px 1fr; align-items: center; gap: var(--space-4); } }
.lux-promo__media { display: block; overflow: hidden; border-radius: var(--radius-card); }
.lux-promo__media img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; }
.lux-promo__title { font-family: var(--font-display); font-size: clamp(1.4rem, 2.4vw, 1.9rem); margin: var(--space-1) 0; }
.lux-promo__title a { color: var(--lux-ink); text-decoration: none; }
.lux-promo__title a:hover { color: var(--lux-green); }
.lux-promo__loc, .lux-promo__facts { color: var(--lux-ink-soft); font-size: .92rem; margin: 0 0 4px; }
.lux-promo__price { font-family: var(--font-display); font-size: 1.35rem; color: var(--lux-green); margin: 0 0 var(--space-2); }

/* A featured listing carries a label, exactly like FOR SALE. Deep green against
   the gold sale badge so the two read as different things, and pinned to the
   opposite corner so they never collide. Unfeatured listings show nothing at
   all — an explicit "not featured" label would be noise. */
.lux-badge--featured { background: var(--lux-green-deep); color: var(--lux-gold-soft); }
.lux-card__badge--featured { left: auto; right: var(--space-2); }

/* Declared questions on the submission form. */
.lux-submit__sub {
  font-family: var(--font-body); font-size: .78rem; font-weight: 700;
  letter-spacing: .14em; text-transform: uppercase; color: var(--lux-green);
  margin: var(--space-3) 0 var(--space-2);
}
.lux-submit__decgrid { display: grid; gap: var(--space-2); }
@media (min-width: 700px) { .lux-submit__decgrid { grid-template-columns: 1fr 1fr; gap: var(--space-2) var(--space-3); } }
.lux-check { display: flex; align-items: center; gap: 10px; min-height: 48px; cursor: pointer; }
.lux-check input { width: 20px; height: 20px; flex: 0 0 auto; }
.lux-check span { font-size: .95rem; }

/* Leaflet map picker on the submission form. */
.lux-map-picker {
  height: 320px; margin: 10px 0 6px;
  border: 1px solid var(--lux-line); border-radius: var(--radius);
  background: var(--lux-mist);
}
@media (max-width: 600px) { .lux-map-picker { height: 260px; } }
/* Leaflet injects its own controls; keep them below the sticky site header. */
.leaflet-pane, .leaflet-top, .leaflet-bottom { z-index: 1 !important; }

/* --------------------------------------------------------------------------
   Blog bento grid

   Four tiles of deliberately unequal weight. A row of identical cards gives
   every article the same importance and reads as a list; unequal tiles tell the
   reader where to start. One tile carries no photograph at all — a still point
   so the block is not four competing images.
   -------------------------------------------------------------------------- */
.lux-bento { display: grid; gap: var(--space-2); }

.lux-bento__tile {
  position: relative; overflow: hidden;
  border-radius: var(--radius-card);
  background: var(--lux-mist);
  display: flex; flex-direction: column;
  min-height: 240px;
}
.lux-bento__media { display: block; position: absolute; inset: 0; }
.lux-bento__media img { width: 100%; height: 100%; object-fit: cover; transition: transform .7s var(--ease); }
.lux-bento__tile:hover .lux-bento__media img { transform: scale(1.05); }

.lux-bento__body { position: relative; z-index: 2; margin-top: auto; padding: var(--space-3); }

/* Any tile with a photo gets light type over a scrim; the text tile sets its
   own colours below. */
.lux-bento__tile:has(.lux-bento__media) .lux-bento__body {
  background: linear-gradient(0deg, rgba(7,42,32,.92) 0%, rgba(7,42,32,.72) 55%, rgba(7,42,32,0) 100%);
  padding-top: var(--space-6);
  color: #fff;
}
.lux-bento__tile:has(.lux-bento__media) .lux-bento__title a { color: #fff; }

.lux-bento__meta {
  margin: 0 0 6px; font-size: .72rem; font-weight: 600;
  letter-spacing: .1em; text-transform: uppercase; opacity: .82;
  display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
}
.lux-bento__cat { color: var(--lux-gold); }
.lux-bento__title { font-size: 1.25rem; line-height: 1.18; margin: 0; }
.lux-bento__title a { color: var(--lux-ink); text-decoration: none; }
.lux-bento__title a:hover { color: var(--lux-gold-soft); }
.lux-bento__excerpt { margin: var(--space-2) 0 0; font-size: .92rem; }

/* The text tile: brand green, no photograph. */
.lux-bento__tile--text { background: var(--lux-green-deep); color: #fff; justify-content: center; }
.lux-bento__tile--text .lux-bento__body { margin: 0; }
.lux-bento__tile--text .lux-bento__title a { color: #fff; }
.lux-bento__tile--text .lux-bento__excerpt { color: rgba(255,255,255,.78); }

@media (min-width: 900px) {
  .lux-bento { grid-template-columns: repeat(4, 1fr); grid-auto-rows: 210px; gap: var(--space-2); }
  .lux-bento__tile--lead  { grid-column: span 2; grid-row: span 2; }
  .lux-bento__tile--text  { grid-column: span 2; grid-row: span 1; }
  .lux-bento__tile--tall  { grid-column: span 1; grid-row: span 1; }
  .lux-bento__tile--small { grid-column: span 1; grid-row: span 1; }

  .lux-bento__tile--lead .lux-bento__title { font-size: clamp(1.6rem, 2.6vw, 2.3rem); }
  .lux-bento__tile--text .lux-bento__title { font-size: clamp(1.4rem, 2.2vw, 1.9rem); }
}

/* --------------------------------------------------------------------------
   Blog — lead article
   -------------------------------------------------------------------------- */
.lux-lead {
  display: grid; gap: var(--space-3);
  margin-bottom: var(--space-5);
  padding-bottom: var(--space-5);
  border-bottom: 1px solid var(--lux-line);
}
.lux-lead__media { display: block; overflow: hidden; border-radius: var(--radius); }
.lux-lead__media img {
  width: 100%; height: 100%; object-fit: cover; aspect-ratio: 16 / 10;
  transition: transform .6s var(--ease);
}
.lux-lead:hover .lux-lead__media img { transform: scale(1.03); }

.lux-lead__body { display: flex; flex-direction: column; justify-content: center; }
.lux-lead__title {
  font-family: var(--font-display);
  font-size: clamp(1.6rem, 3.4vw, 2.5rem);
  line-height: 1.14; margin: var(--space-2) 0 var(--space-2);
}
.lux-lead__title a { color: var(--lux-ink); text-decoration: none; }
.lux-lead__title a:hover { color: var(--lux-green); }
.lux-lead__excerpt {
  font-size: 1.05rem; color: var(--lux-ink-soft); max-width: 58ch;
  margin: 0 0 var(--space-3);
}

@media (min-width: 860px) {
  .lux-lead { grid-template-columns: 1.25fr 1fr; gap: var(--space-5); align-items: stretch; }
}

/* --------------------------------------------------------------------------
   Scroll reveal — opt-in, and fully disabled under reduced motion
   -------------------------------------------------------------------------- */
/* Scoped to .lux-js, which an inline script in header.php sets before the page
   paints. Without that guard the start state is opacity:0 and the content only
   appears if JavaScript runs — one failed script and the blog renders blank.
   That exact failure mode blanked the Services page twice. */
@media (prefers-reduced-motion: no-preference) {
  .lux-js .lux-reveal { opacity: 0; transform: translateY(18px); transition: opacity .6s var(--ease), transform .6s var(--ease); }
  .lux-js .lux-reveal.is-in { opacity: 1; transform: none; }
}

/* --------------------------------------------------------------------------
   Elementor
   Elementor supplies its own sections, containers and spacing. The theme must
   not impose a wrapper width on builder content, but the design tokens above
   still apply, so shortcodes dropped into a page look native.
   -------------------------------------------------------------------------- */
.lux-elementor-content { width: 100%; }

/* Shortcode output inside a builder column should fill that column, not
   re-apply the theme's own page gutter. */
.elementor-widget-shortcode .lux-wrap,
.lux-elementor-content .lux-slides .lux-wrap {
  width: 100%;
  margin-inline: 0;
  padding-inline: var(--space-3);
}

/* Elementor resets heading margins; restore the theme's rhythm inside our blocks. */
.elementor-widget-shortcode .lux-review h3,
.elementor-widget-shortcode .lux-card__title { margin-block: 0 6px; }

/* --------------------------------------------------------------------------
   Front-end listing submission
   -------------------------------------------------------------------------- */
.lux-submit { max-width: 860px; }

/* Section heads act as steps through a long form. */
.lux-submit__step {
  font-family: var(--font-display);
  font-size: clamp(1.35rem, 2.4vw, 1.75rem);
  margin: var(--space-5) 0 var(--space-3);
  padding-bottom: 10px;
  border-bottom: 2px solid var(--lux-gold);
}
.lux-submit__step:first-of-type { margin-top: var(--space-3); }

/* Single column on phones — agents fill these standing in a driveway. */
.lux-submit__row { display: grid; gap: 0 var(--space-3); grid-template-columns: 1fr; }

/* The shared 130px min-height is right for a description, far too tall for the
   short note and review fields, which would push the submit button off-screen. */
.lux-submit .lux-textarea { min-height: 96px; }
.lux-submit #p-desc { min-height: 170px; }

.lux-submit__review { padding: var(--space-3) 0; border-bottom: 1px solid var(--lux-line); }
.lux-submit__review:last-of-type { border-bottom: none; }
.lux-submit__review .lux-field:last-child { margin-bottom: 0; }
.lux-submit__review .lux-input { max-width: 140px; }

.lux-submit__current {
  display: flex; align-items: center; gap: var(--space-2);
  margin-bottom: 10px; padding: 10px;
  background: var(--lux-mist); border-radius: var(--radius);
}
.lux-submit__current img { width: 76px; height: 76px; object-fit: cover; border-radius: 4px; }
.lux-submit__current span { font-size: .84rem; color: var(--lux-ink-soft); }

.lux-submit__thumbs { display: grid; gap: var(--space-2); grid-template-columns: repeat(2, 1fr); }
.lux-submit__thumb {
  display: block; padding: 8px; text-align: center;
  background: var(--lux-mist); border-radius: var(--radius); cursor: pointer;
}
.lux-submit__thumb img { width: 100%; height: 110px; object-fit: cover; border-radius: 4px; }
.lux-submit__thumb span {
  display: block; margin-top: 6px; font-size: .78rem; color: var(--lux-ink-soft);
}
/* Ticked for removal — make the consequence obvious before saving. */
.lux-submit__thumb:has(input:checked) { background: rgba(163,43,43,.1); }
.lux-submit__thumb:has(input:checked) img { opacity: .4; }

.lux-submit__actions {
  margin-top: var(--space-4); padding-top: var(--space-3);
  border-top: 1px solid var(--lux-line);
}

/* A file input inherits .lux-input's 48px box awkwardly; give it room to breathe. */
.lux-submit input[type="file"] { padding: 11px 14px; line-height: 1.5; background: var(--lux-mist); }

@media (min-width: 700px) {
  .lux-submit__row { grid-template-columns: 1fr 1fr; }
  .lux-submit__row--3 { grid-template-columns: repeat(3, 1fr); }
  .lux-submit__review { display: grid; gap: 0 var(--space-3); grid-template-columns: 160px 1fr; }
  .lux-submit__thumbs { grid-template-columns: repeat(4, 1fr); }
}

/* --------------------------------------------------------------------------
   Print
   -------------------------------------------------------------------------- */
@media print {
  .lux-header, .lux-footer, .lux-slides__nav, .lux-card__actions { display: none !important; }
  body { background: #fff; font-size: 12pt; }
}

/* Guided enquiry chat ---------------------------------------------------------
   Placed with [luxkey_chat]. The conversation runs entirely in the browser and
   posts once, so there is no loading state to design for.
   -------------------------------------------------------------------------- */
.lux-chat {
  max-width: 640px; margin-inline: auto;
  border: 1px solid var(--lux-line); border-radius: var(--radius-card);
  background: var(--lux-paper); overflow: hidden;
}

.lux-chat__head {
  display: flex; align-items: center; gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  background: var(--lux-green-deep); color: var(--lux-ivory);
}
.lux-chat__dot {
  width: 9px; height: 9px; border-radius: 50%; flex: none;
  background: var(--lux-gold);
}
.lux-chat__title { margin: 0; font-size: .92rem; font-weight: 600; }
.lux-chat__sub   { margin: 2px 0 0; font-size: .72rem; color: rgba(251,249,245,.66); }

.lux-chat__log {
  padding: var(--space-3);
  max-height: 380px; overflow-y: auto;
  display: flex; flex-direction: column; gap: var(--space-2);
  background: var(--lux-ivory);
}

.lux-msg { display: flex; }
.lux-msg--bot { justify-content: flex-start; }
.lux-msg--you { justify-content: flex-end; }

.lux-msg__bubble {
  margin: 0; padding: 11px 15px; max-width: 84%;
  font-size: .92rem; line-height: 1.55; border-radius: 12px;
}
.lux-msg--bot .lux-msg__bubble {
  background: var(--lux-paper); border: 1px solid var(--lux-line);
  border-bottom-left-radius: 3px; color: var(--lux-ink);
}
.lux-msg--you .lux-msg__bubble {
  background: var(--lux-green); color: var(--lux-ivory);
  border-bottom-right-radius: 3px;
}

.lux-chat__input {
  display: flex; flex-wrap: wrap; gap: 8px;
  padding: var(--space-3); border-top: 1px solid var(--lux-line);
}

/* Answers are buttons, not a free text box, so the value posted is always one
   the lead scorer recognises. */
.lux-chat__opt {
  padding: 10px 16px; font: inherit; font-size: .87rem; font-weight: 500;
  color: var(--lux-green); background: var(--lux-paper); cursor: pointer;
  border: 1px solid var(--lux-green); border-radius: 999px;
  transition: background-color .18s var(--ease), color .18s var(--ease);
}
.lux-chat__opt:hover,
.lux-chat__opt:focus-visible { background: var(--lux-green); color: var(--lux-ivory); }

.lux-chat__entry { display: flex; flex-wrap: wrap; gap: 8px; width: 100%; }
.lux-chat__field {
  flex: 1 1 200px; padding: 11px 14px; font: inherit; font-size: .92rem;
  color: var(--lux-ink); background: var(--lux-paper);
  border: 1px solid var(--lux-line); border-radius: var(--radius);
}
.lux-chat__field:focus-visible { outline: 2px solid var(--lux-gold); outline-offset: 1px; }

.lux-chat__go {
  padding: 11px 20px; font: inherit; font-size: .87rem; font-weight: 600;
  color: var(--lux-ivory); background: var(--lux-green); cursor: pointer;
  border: 1px solid var(--lux-green); border-radius: var(--radius);
}
.lux-chat__go:hover { background: var(--lux-green-deep); }

.lux-chat__skip {
  padding: 11px 14px; font: inherit; font-size: .82rem;
  color: var(--lux-ink-soft); background: none; border: 0; cursor: pointer;
  text-decoration: underline;
}

.lux-chat__summary {
  width: 100%; margin: 0 0 var(--space-2);
  display: grid; grid-template-columns: auto 1fr; gap: 6px var(--space-2);
  font-size: .87rem;
}
.lux-chat__summary dt { color: var(--lux-ink-soft); }
.lux-chat__summary dd { margin: 0; font-weight: 600; color: var(--lux-ink); }

.lux-chat__send { width: 100%; }

.lux-chat__legal {
  margin: 0; padding: 0 var(--space-3) var(--space-3);
  font-size: .72rem; line-height: 1.5; color: var(--lux-ink-soft);
}

@media (max-width: 560px) {
  .lux-chat__log { max-height: 320px; }
  .lux-msg__bubble { max-width: 90%; font-size: .88rem; }
}

@media print { .lux-chat { display: none !important; } }

/* Client-rendered cards for listings whose photographs are still pending. */
.lux-card__nophoto {
  display: grid; place-items: center; height: 100%; min-height: 200px;
  font-size: .78rem; letter-spacing: .1em; text-transform: uppercase;
  color: var(--lux-ink-soft); background: var(--lux-mist);
}

/* Floating chat launcher -------------------------------------------------------
   Shows on every front-end page (see luxkey_chat_float_should_show()). Stands
   alone, bottom-right — WhatsApp moved into the header next to the phone
   number so this bubble reads as its own distinct control, not one of a pair.
   Ships hidden in the markup; JS reveals it once confirmed running.
   ---------------------------------------------------------------------------- */
.lux-chat-float { position: fixed; right: 18px; bottom: 18px; z-index: var(--z-sticky); }
.lux-chat-float[hidden] { display: none; }

.lux-chat-float__btn {
  position: relative; width: 56px; height: 56px; border-radius: 50%;
  background: rgba(15,82,63,.68); color: var(--lux-ivory);
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  border: 1px solid rgba(255,255,255,.16);
  display: grid; place-items: center; cursor: pointer;
  box-shadow: 0 6px 20px rgba(7,42,32,.3);
  transition: transform .2s var(--ease), background-color .2s var(--ease);
}
.lux-chat-float__btn:hover { transform: scale(1.06); background: rgba(10,58,44,.78); }
.lux-chat-float__btn .lux-i { width: 24px; height: 24px; }

/* Browsers without backdrop-filter would show low-contrast icons over a
   68%-transparent circle with the page showing through unpredictably. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .lux-chat-float__btn { background: var(--lux-green); border-color: transparent; }
  .lux-chat-float__btn:hover { background: var(--lux-green-deep); }
}

.lux-chat-float__icon-close { display: none; }
.lux-chat-float.is-open .lux-chat-float__icon-open { display: none; }
.lux-chat-float.is-open .lux-chat-float__icon-close { display: block; }

.lux-chat-float__panel {
  position: absolute; right: 0; bottom: calc(100% + 12px);
  width: min(380px, calc(100vw - 36px));
  max-height: min(560px, calc(100vh - 140px));
  border-radius: var(--radius-card);
  box-shadow: 0 20px 50px -12px rgba(7,42,32,.35);
  overflow: hidden;
}
.lux-chat-float__panel[hidden] { display: none; }

/* Glass shell for the floating panel only — the same widget placed inline
   via [luxkey_chat] elsewhere on the site stays fully opaque, since there it
   sits in the normal page flow rather than floating over other content. The
   message bubbles and input field inside stay solid regardless (see below):
   glassing the chrome and keeping the conversation text on solid ground is
   the legible version of this, not transparency everywhere. */
.lux-chat-float__panel .lux-chat {
  background: rgba(255,255,255,.55);
  backdrop-filter: blur(20px) saturate(160%);
  -webkit-backdrop-filter: blur(20px) saturate(160%);
}
.lux-chat-float__panel .lux-chat__head {
  background: rgba(10,58,44,.7);
  backdrop-filter: blur(20px) saturate(160%);
  -webkit-backdrop-filter: blur(20px) saturate(160%);
}
.lux-chat-float__panel .lux-chat__log { background: rgba(251,249,245,.5); }

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .lux-chat-float__panel .lux-chat      { background: var(--lux-paper); }
  .lux-chat-float__panel .lux-chat__head { background: var(--lux-green-deep); }
  .lux-chat-float__panel .lux-chat__log  { background: var(--lux-ivory); }
}

/* The widget was designed to sit inline on a page; inside the floating panel
   it needs to fill the panel's own bounds instead of carrying its own card
   chrome and fixed log height. */
.lux-chat-float__panel .lux-chat {
  max-width: none; margin: 0; border: 0; border-radius: 0;
  display: flex; flex-direction: column; max-height: min(560px, calc(100vh - 140px));
}
.lux-chat-float__panel .lux-chat__log { flex: 1 1 auto; max-height: none; }

.lux-chat__close {
  margin-left: auto; width: 28px; height: 28px; flex: none;
  display: grid; place-items: center; border-radius: 50%;
  background: rgba(255,255,255,.12); color: inherit; border: none; cursor: pointer;
}
.lux-chat__close:hover { background: rgba(255,255,255,.22); }

@supports (padding: env(safe-area-inset-bottom)) {
  .lux-chat-float { bottom: calc(18px + env(safe-area-inset-bottom)); }
}

@media (max-width: 480px) {
  .lux-chat-float { right: 14px; bottom: 14px; }
  .lux-chat-float__panel { width: calc(100vw - 28px); right: -4px; }
}

@media print { .lux-chat-float { display: none !important; } }
