/* ==========================================================================
   Client-requested deviations from the design
   --------------------------------------------------------------------------
   Everything in 04-sections-*.css is GENERATED from the Claude Design export
   and is overwritten by `npm run convert`. Anything hand-edited there is lost
   on the next build — which has already happened twice on this project.

   So deliberate departures from the design live here instead: one file, loaded
   last, every rule dated and attributed. That keeps the generated stylesheets
   a faithful record of the design, and makes it obvious what was changed on
   purpose versus what the design actually specified.

   Loaded after 05-utilities.css, so plain single-class selectors win without
   needing !important or specificity tricks.
   ========================================================================== */


/* --------------------------------------------------------------------------
   The Estate — "A Sanctuary of Calm / Room to Breathe, By Design"
   Requested 2026-07-30: tighten the section vertically.

   The section is a 45% / 55% grid: copy on the left, the sunbird photograph
   filling the right column. Its height is the greater of the copy column
   (content + vertical padding) and the image panel's min-height, so BOTH have
   to come down or the taller one simply holds the old height.

   Note on sharpness: this makes the panel shorter, not narrower. The image is
   sized by the 55% column — 1048px at a 1920px viewport — and object-fit:cover
   scales to the wider edge, so the upscale factor is set by width alone. A
   shorter panel crops more of the photograph but does not sharpen it.
   -------------------------------------------------------------------------- */

.cme-the-estate-shaped-by-nature__row {
  /* was clamp(64px, 8vw, 120px) vertical */
  padding-block: clamp(44px, 5.2vw, 78px);
}

.cme-the-estate-shaped-by-nature__box {
  /* was clamp(380px, 52vw, 760px) */
  min-height: clamp(300px, 34vw, 500px);
}


/* --------------------------------------------------------------------------
   Homepage — the "Only 46 stands still available" card
   Requested 2026-07-31: make it slightly narrower.

   The gold-edged dark card overlapping the bottom-left of the estate
   photograph, in the "A Residential Estate in Clarens, Free State" section.

   Narrowed from 300px to 260px, which lets more of the photograph show
   through behind it while keeping the line "Only 46 stands still available in
   Phase 1." on the same number of lines it wraps to today.

   The inner padding comes in slightly with it, so the card keeps its
   proportions rather than looking cramped at the smaller width.
   -------------------------------------------------------------------------- */

.cme-home-the-estate__overlay {
  max-width: 260px;    /* was 300px */
}

.cme-home-the-estate__box-3 {
  padding: 32px 28px 28px;    /* was 38px 34px 32px */
}


/* --------------------------------------------------------------------------
   Eyebrow text — one pixel larger
   Requested 2026-07-31.

   The small uppercase label above each heading ("Secure Mountain Living",
   "Stands Available for Sale", and so on). There are 21 of them across the
   site and the design set them at four different sizes, so this raises each by
   exactly 1px rather than flattening them to a single value — the small
   deliberate differences, like the hero's fluid size, are kept.

   Matched on the class suffix so an eyebrow added later is covered without
   anyone remembering to extend a list. The outliers follow the general rule
   and therefore win on source order, no specificity games needed.
   -------------------------------------------------------------------------- */

[class*="__eyebrow"] {
  font-size: 14px;    /* was 13px — the size 17 of the 21 use */
}

/* The homepage hero's eyebrow is fluid; both ends move up by one. */
.cme-home-hero__eyebrow {
  font-size: clamp(13px, 1.15vw, 15px);    /* was clamp(12px, 1.15vw, 14px) */
}

.cme-invest-plot-and-plan__eyebrow {
  font-size: 13px;    /* was 12px */
}

/* The smallest of the set: a secondary label inside the Lifestyle cards. */
.cme-home-lifestyle__eyebrow-2 {
  font-size: 12px;    /* was 11px */
}


/* --------------------------------------------------------------------------
   Lifestyle — "Spoilt for Choice / Exploring the Wider Eastern Free State"
   Fixed 2026-07-31: the photograph looked distorted.

   It was not the image. The section is a 50/50 grid with align-items:stretch,
   and that column carries a lot of copy — 1144px tall at a 1440px viewport.
   The media panel stretched to match, giving a 713x1144 box: portrait, ratio
   0.62, holding a 3:2 landscape photograph. object-fit:cover then threw away
   58% of the width, leaving a narrow vertical slice of a wide townscape. Read
   as a squashed image; was actually a savage crop.

   The panel is now bounded and centred in its column. It crops about 28%
   instead of 58%, which a landscape survives. The dark space above and below
   sits on the section's own ink ground, so it reads as margin rather than as
   a gap.

   Not fixed by shrinking the copy: even with zero padding that column is
   ~940px of text, so the panel would still have been portrait.
   -------------------------------------------------------------------------- */

/*
 * Reverted to a full-height panel, per the client: the bounded version left
 * dark space above and below the photograph, which they disliked more than
 * the crop.
 *
 * The panel therefore stretches to the copy column again, which makes it tall
 * and narrow. That is fine — but only with a PORTRAIT source. A landscape
 * photograph here will always be cropped to a vertical slice, whatever its
 * resolution. See the note in DEPLOY.md for the dimensions this slot needs.
 *
 * The copy column's padding stays trimmed: it lowers the panel's height a
 * little, which reduces how portrait the source has to be.
 */
.cme-lifestyle-eastern-free-state__row {
  padding-block: clamp(44px, 5.2vw, 78px);
}


/* --------------------------------------------------------------------------
   Invest — the embedded stand map
   Requested 2026-07-31: inset it slightly and give it the gold border.

   The design ran this iframe edge to edge with no frame, so on the dark
   section it read as a hole in the page rather than a component. Inset on both
   sides and bordered in gold, it matches how the full-screen tool and the
   other bordered panels on the site are treated.

   The inset is applied to the iframe itself rather than to its wrapper: the
   wrapper the converter emits carries only `data-reveal` and no class, so
   styling it would mean a fragile structural selector that breaks the next
   time the design changes.

   box-sizing is border-box globally, so the border sits inside the declared
   height and the panel does not grow.
   -------------------------------------------------------------------------- */

.cme-invest-estate-map__box-2 {
  width: calc(100% - 2 * clamp(14px, 3.2vw, 56px));
  margin-inline: auto;
  border: 2px solid var(--cme-gold);
}


/* --------------------------------------------------------------------------
   Header on pages that open on a LIGHT background
   Requested 2026-07-30.

   The header is transparent over a dark gradient so the light nav links read
   against a full-bleed hero photograph. Privacy Policy and the stand tool open
   on pale sand instead, so that gradient became a dark smear across the top of
   an otherwise light page.

   Those pages get the solid treatment from the start — cream ground, dark
   links, dark logo — separated by the estate's gold rule rather than by a
   shadow, matching how sections are divided everywhere else on the site.

   The page declares this with data-chrome="light" on its opening section and
   PHP turns that into .cme-chrome-light. Inference was tried first and got the
   Gallery page wrong — its opening section is labelled "Gallery Intro" but is
   solid ink, so a guess based on section labels would have put a cream bar
   over a near-black band.
   -------------------------------------------------------------------------- */

.cme-chrome-light .cme-chrome__bar {
  background: var(--cme-cream);
  border-bottom: 2px solid var(--cme-gold);
  box-shadow: none;
  backdrop-filter: none;
}

/* Links and logo must invert too, or they stay light-on-light. */
.cme-chrome-light .cme-chrome__bar .cme-chrome__link-2 {
  color: var(--cme-ink-soft);
}

.cme-chrome-light .cme-chrome__bar .cme-chrome__image--light { opacity: 0; }
.cme-chrome-light .cme-chrome__bar .cme-chrome__image--dark  { opacity: 1; }

/* The burger's bars are drawn light for the dark hero; darken them here.

   No `:not(.is-open)` exception — see the note in 04-chrome-state.css. The
   header is z-index 90 against the mobile panel's 85 and carries its own opaque
   background, so the X is painted on this page's cream bar rather than on the
   dark overlay behind it. It needs to be dark whether the menu is open or not. */
.cme-chrome-light .cme-chrome__bar .cme-chrome__rule-2 {
  background: var(--cme-ink-soft);
}

/* Once scrolled, is-solid takes over — keep the gold rule rather than letting
   it swap to the shadow, so the separation does not change mid-scroll. */
.cme-chrome-light .cme-chrome__bar.is-solid {
  border-bottom: 2px solid var(--cme-gold);
  box-shadow: none;
}


/* --------------------------------------------------------------------------
   Buttons — one hover behaviour, and always readable
   Requested 2026-07-30: on hover the button AND its text should change colour.

   The design authored each button in its own section, so there were five
   different hover behaviours across the site: gold to gold-light, gold to
   gold-alt, ink to ink-soft, transparent to translucent white, and exactly one
   that bothered to change the text as well.

   Several were unreadable. The header's "Find Your Stand" went from gold to a
   paler gold with the text colour untouched — barely a change — and the
   homepage Invest button went from gold to near-black while its text stayed
   dark ink, so the label disappeared entirely on hover.

   Replaced with one rule: buttons INVERT. A gold button becomes ink with pale
   text; a dark button becomes gold with dark text; an outline button fills in.
   Contrast is high in both states, and the change is unmistakable.
   -------------------------------------------------------------------------- */

/* --- Gold buttons: gold ground, dark text -> invert to ink ---------------- */

[data-accent-bg][data-accent-bg]:hover,
.cme-chrome__btn:hover,
.cme-chrome__btn-2:hover,
.cme-home-page__btn:hover,
.cme-home-hero__btn:hover,
.cme-home-contact__btn:hover,
.cme-home-invest__btn:hover,
.cme-the-estate-page__btn:hover,
.cme-the-estate-fees__btn:hover,
.cme-the-estate-discover-cta__btn:hover,
.cme-invest-page__btn:hover,
.cme-lifestyle-page__btn:hover,
.cme-lifestyle-lifestyle-cta__btn:hover,
.cme-contact-page__btn:hover,
.cme-gallery-page__btn:hover {
  background: var(--cme-ink);
  border-color: var(--cme-ink);
  color: var(--cme-off-white);
}

/* --- Dark buttons: ink ground, pale text -> invert to gold ---------------- */

.cme-enquiry__submit:hover,
.cme-contact-enquiry__button:hover,
.cme-standmap__btn:hover {
  background: var(--cme-gold);
  border-color: var(--cme-gold);
  color: var(--cme-ink);
}

/* --- Outline buttons: fill in, text flips -------------------------------- */

/* On the dark hero: pale outline -> solid pale, dark text. */
.cme-home-hero__btn-2:hover {
  background: var(--cme-off-white);
  border-color: var(--cme-off-white);
  color: var(--cme-ink);
}

/* On light grounds: dark outline -> solid dark, pale text. */
.cme-home-gallery__btn:hover,
.cme-invest-invest-cta__btn:hover,
.cme-standmap__btn--ghost:hover {
  background: var(--cme-ink-head);
  border-color: var(--cme-ink-head);
  color: var(--cme-off-white);
}

/*
 * The header CTA was also the only button on the site not using the body font
 * stack or the shared tracking and weight, so it read as a different size and
 * shape from every other button. Matched to the rest.
 */
.cme-chrome__btn,
.cme-chrome__btn-2 {
  font-family: var(--cme-font-body);
  font-weight: 600;
  letter-spacing: .2em;
}

/*
 * The header CTA needs its hover colour restated at higher specificity.
 *
 * The nav walker gives it BOTH `cme-chrome__btn` and `cme-chrome__link-2`, and
 * the scrolled-header rule `.cme-chrome__bar.is-solid .cme-chrome__link-2`
 * sets a dark colour at (0,3,0) — which beats the (0,2,0) hover rule above.
 * So once the header went sticky, "Find Your Stand" hovered to a dark ink
 * background while its label stayed dark ink: invisible.
 *
 * Restated here for the transparent, scrolled and light-page headers alike, so
 * the label is pale on ink in every state the bar can be in.
 */
.cme-chrome__bar .cme-chrome__btn:hover,
.cme-chrome__bar.is-solid .cme-chrome__btn:hover,
.cme-chrome-light .cme-chrome__bar .cme-chrome__btn:hover,
.cme-chrome-light .cme-chrome__bar.is-solid .cme-chrome__btn:hover {
  background: var(--cme-ink);
  border-color: var(--cme-ink);
  color: var(--cme-off-white);
}


/* --------------------------------------------------------------------------
   Lightbox — make the <dialog> actually visible
   Fixed 2026-07-30.

   The design's lightbox was a <div> that JavaScript faded in by toggling
   opacity and pointer-events. It was converted to a native <dialog>, which
   brings focus trapping, Escape-to-close and an inert background for free —
   but which opens via showModal() and adds no class of its own.

   So the generated `opacity: 0; pointer-events: none` never got undone. The
   dialog opened, loaded the right image, and was completely transparent and
   click-through. Tapping a gallery tile appeared to do nothing.

   Worth noting why this survived testing: at opacity 0 the element still has
   a bounding box and the image still reports naturalWidth, so every scripted
   check passed. Only looking at it catches this.

   The [open] attribute is the hook — it is what the platform sets, so the
   visible state is tied to the dialog's real state rather than to a class
   some script has to remember to add.
   -------------------------------------------------------------------------- */

dialog.cme-chrome__row {
  /* The UA stylesheet gives <dialog> width/height: fit-content, which beats
     inset: 0 — without this the overlay is a small box in the top-left
     corner rather than the full-screen viewer the copy promises. */
  width: 100%;
  height: 100%;
  max-width: none;
  max-height: none;
  border: 0;
  overflow: hidden;
}

dialog.cme-chrome__row[open] {
  opacity: 1;
  pointer-events: auto;
}

/* The dialog paints its own dark ground, so the platform backdrop only needs
   to stop the page showing through during the open/close transition. */
dialog.cme-chrome__row::backdrop {
  background: rgba(11, 8, 5, .6);
}


/* --------------------------------------------------------------------------
   Footer — privacy policy link
   Added 2026-07-30. The design's footer bar carried only the copyright line.

   Matched to .cme-footer__text-3 so it reads as part of that line rather than
   as a stray link, with a separator drawn in CSS so no punctuation has to be
   hardcoded into the markup or translated.
   -------------------------------------------------------------------------- */

.cme-footer__legal-link {
  font-family: var(--cme-font-body);
  color: var(--cme-white);
  font-size: 11px;
  letter-spacing: .14em;
  text-decoration: none;
  transition: opacity .3s ease;
}

/* Separator lives in the markup, carrying aria-hidden, rather than in a
   ::before on the link — a pseudo-element there would fall inside the anchor,
   enlarging its clickable area and getting read out as part of the link name
   by some screen readers. */
.cme-footer__legal-sep {
  margin: 0 .7em;
  color: var(--cme-white);
  opacity: .5;
  font-size: 11px;
}

.cme-footer__legal-link:hover {
  opacity: .72;
  text-decoration: underline;
  text-underline-offset: 3px;
}


/* --------------------------------------------------------------------------
   Buttons — one hover behaviour across the whole site
   Requested 2026-07-30: colour change only, no movement.

   The design gave buttons three different kinds of motion: a JS "magnetic"
   effect that slid eight of them toward the cursor, a `transform .25s` in
   their transitions to carry it, and a gap shift on the gallery button that
   slid its arrow outward. Each was authored per section, so no two buttons
   behaved quite the same.

   The magnetic script is gone (see site.js). What remains here is the CSS
   half: a single transition covering only the properties that should change,
   so every button on every page animates colour and nothing else.

   Attribute-substring selectors are used because the generated class names are
   namespaced per page — .cme-home-hero__btn, .cme-the-estate-fees__btn, and so
   on — so there is no single shared class to hook. Matching the __btn/__button
   suffix catches all of them and keeps working as pages are re-converted.
   -------------------------------------------------------------------------- */

[class*="__btn"],
[class*="__button"],
.cme-btn,
.cme-nav__cta {
  /* Colour only. No transform, so nothing can slide, lift or scale. */
  transition: background-color .3s ease, border-color .3s ease, color .3s ease;
}

/*
 * A button that is also a scroll-reveal target needs BOTH transitions.
 *
 * The reveal rule in 02-layout.css is more specific than the one above, so it
 * would otherwise replace the colour transition wholesale and that one button
 * would snap between colours while every other button eased — the exact
 * inconsistency this section exists to remove. Restated here with both, and
 * matching 02-layout.css's 1s reveal timing.
 */
.cme-js [data-reveal][class*="__btn"],
.cme-js [data-reveal][class*="__button"] {
  transition:
    opacity 1s var(--cme-ease-reveal),
    transform 1s var(--cme-ease-reveal),
    background-color .3s ease,
    border-color .3s ease,
    color .3s ease;
}

/* The gallery button widened its gap from 12px to 20px on hover, sliding the
   arrow away from the label. Pinned to its resting value — `inherit` would
   take the PARENT's gap, which is a different number entirely. */
.cme-home-gallery__btn:hover {
  gap: 12px;
}


/* --------------------------------------------------------------------------
   Logo size on mobile
   Requested 2026-07-31, revised the same day.

   The mark is sized `clamp(42px, 5.6vw, 92px)`, and below about 750px the vw
   term is smaller than the floor — so every phone landed on exactly 42px, in
   both states.

   First pass raised only the SCROLLED state to 52px. That was what was asked
   for, but it meant the logo visibly GREW as you scrolled, which reads as a
   glitch: a mark that changes size on scroll looks like something failed to
   load at the right dimensions. Per the client, both states are now 52px, so
   the logo is simply one size on a phone and only the bar around it tightens.

   Sizing both states also retires the height transition — there is no longer a
   height change to ease, and animating a property that never changes is dead
   code the next person has to reason about.

   Bar height: 120px at rest (34px padding, 52px mark), 92px scrolled. The hero's
   top padding below is set against the 120px figure.
   -------------------------------------------------------------------------- */

@media (max-width: 899.98px) {
  .cme-chrome__image {
    height: 52px;    /* was clamp(42px, 5.6vw, 92px), which floored at 42px */
  }
}


/* ==========================================================================
   MOBILE
   Requested 2026-07-31: "make sure the mobile responsiveness is outstanding".

   Found by measuring every page at 360px and 390px rather than by eye — each
   fix below is a real defect with a measured before/after, not a tidy-up.
   ========================================================================== */


/* --------------------------------------------------------------------------
   Homepage hero — "STANDS FOR SALE" was cut off

   The section is `height: 100vh` with `overflow: hidden`, and the content box
   measures 704px tall at 360px wide. Two things then go wrong at once:

   - `vh` is the LARGE viewport — the height the page would have if the browser
     chrome were hidden. While the address bar is showing, the visible area is
     smaller than the box, and
   - `align-items: center` centres the overflow, so it is clipped at BOTH ends.

   The bottom of the box is the button row, so the second button lost its lower
   half. `overflow: hidden` meant it could not even be scrolled to.

   `svh` is the small viewport — the height with the browser chrome VISIBLE,
   which is the one that is safe to fill. Paired with `height: auto` the hero is
   still a full screen on a tall phone and simply grows on a short one instead
   of cropping itself. The `vh` line stays as a fallback for older browsers.
   -------------------------------------------------------------------------- */

@media (max-width: 899.98px) {
  .cme-home-hero__section {
    height: auto;
    min-height: 100vh;
    min-height: 100svh;
  }

  /* Top padding clears the fixed header, which on a phone is 120px tall —
     34px of padding either side of the 52px mark. 124px left only 4px of air
     under it, so the eyebrow sat right on the logo. Bottom padding keeps the
     buttons off the marquee, now that the section is content-sized rather than
     a fixed screen height. */
  .cme-home-hero__box {
    padding-block: 148px 64px;
  }
}


/* --------------------------------------------------------------------------
   Grid columns must be allowed to shrink

   `grid-template-columns: 1fr` is shorthand for `minmax(auto, 1fr)`, and that
   `auto` minimum resolves to the item's MIN-CONTENT width. When a column
   contains something with an intrinsic minimum wider than the phone — here the
   Invest "Begin with the Land" media panel — the column refuses to shrink and
   the whole page scrolls sideways.

   Measured on Invest at 360px: the grid box was 312px wide while its single
   column computed to 344.6px, giving the document a 9px horizontal scroll.

   `min-width: 0` on the items overrides that automatic minimum, which is the
   standard cure and fixes flex children in the same stroke. Scoped to the
   widths where the two-column layouts collapse, so desktop sizing is untouched.
   -------------------------------------------------------------------------- */

@media (max-width: 1024px) {
  [data-split] > *,
  [class*="__grid"] > * {
    min-width: 0;
  }
}

/*
 * ...and this panel needs its width pinned as well.
 *
 * Letting the column shrink was only half of it. This is the one element on the
 * site that combines `aspect-ratio` with `min-height`, and that pairing makes
 * the element's WIDTH a derived value: with no definite width, the browser
 * takes the resolved height and multiplies by the ratio. A 320px floor against
 * 644/598 gives 344.6px — which it then happily painted inside a 312px column,
 * back out through the side of the page.
 *
 * `width: 100%` makes the width definite, so the ratio drives the height
 * instead of the other way round. The photograph is `object-fit: cover`, so the
 * ratio being overridden costs nothing visible.
 *
 * Every other `aspect-ratio` panel on the site is safe: none of them also
 * declare a min-height, so their width always comes from the column.
 */
@media (max-width: 1024px) {
  .cme-invest-begin-with-the-land__media {
    width: 100%;
  }
}


/* --------------------------------------------------------------------------
   Homepage — the "Only 46 stands still available" card ran off the screen

   The card is positioned `left: -42px; bottom: -42px`, deliberately overhanging
   the estate photograph on desktop where the photo is inset from the page edge.
   On a phone the photo is nearly full-bleed, so that same -42px put the card's
   left edge 18px OFF the viewport — measured at both 360px and 390px, with the
   first character of every line lost.

   On mobile it sits inside the photograph instead of overhanging it. Insetting
   both edges also lets it use the full width available rather than the 260px
   desktop cap, so the text wraps to fewer lines.
   -------------------------------------------------------------------------- */

@media (max-width: 767px) {
  .cme-home-the-estate__overlay {
    left: 12px;
    right: 12px;
    bottom: 12px;
    max-width: none;
  }
}


/* --------------------------------------------------------------------------
   Footer on mobile
   Requested 2026-07-31: "the footer needs to look better on mobile".

   Measured at 360px it was 752px tall — most of a screen — with a 116px logo,
   40px of padding on every side leaving only 280px of usable width, and three
   columns that stacked at three different alignments: the brand block centred,
   the other two flush left. It read as a desktop layout that had fallen over
   rather than a mobile footer.

   Now a single centred column. Centring rather than left-aligning everything
   because the brand lockup at the top is already centred and leads the block —
   matching the other two to it is what makes it look composed.

   Tap targets were the bigger problem: the five Explore links measured 75x18px
   and the privacy link 96x14px, against the 44px minimum that WCAG 2.5.5 and
   both platform guidelines ask for. They are padded to 44px rather than made
   larger, so the type size and rhythm are unchanged — the target grows, the
   design does not. Row gaps come down to compensate, so the footer gets
   shorter even though every target got bigger.
   -------------------------------------------------------------------------- */

@media (max-width: 767px) {
  .cme-footer__row {
    padding: 48px 24px 40px;
    gap: 36px;
    justify-content: center;
    text-align: center;
  }

  /* The two link columns are plain <div>s with no class of their own. */
  .cme-footer__row > * {
    width: 100%;
  }

  .cme-footer__image {
    height: 84px;    /* was 116px */
  }

  .cme-footer__copy {
    font-size: 1.35rem;
    max-width: none;
  }

  /* Section headings: the little gold rule and its label, centred as a pair. */
  .cme-footer__row-4 {
    justify-content: center;
    margin-bottom: 18px;
  }

  /* Contact rows — label above value, centred, comfortably tappable. */
  .cme-footer__row-5 {
    gap: 10px;
    align-items: center;
  }

  .cme-footer__link {
    align-items: center;
    min-height: 44px;
    justify-content: center;
    padding-block: 4px;
  }

  /* Explore list: 18px tall links become 44px targets without changing the
     type. Gap shrinks because the padding now supplies the separation. */
  .cme-footer__row-6 {
    align-items: center;
    gap: 2px;
  }

  .cme-footer__link-2 {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 44px;
    width: 100%;
  }

  /* Copyright bar: 40px side padding on a 360px screen wrapped the line. */
  .cme-footer__box-3 {
    padding-inline: 24px;
  }

  .cme-footer__legal-link {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding-inline: 4px;
  }
}


/* --------------------------------------------------------------------------
   Lightbox close button

   Measured 20x32px — the smallest control on the site, and the only way out of
   a full-screen overlay. 44px square, which is also easier to hit with a thumb
   at the top corner of a phone.
   -------------------------------------------------------------------------- */

@media (max-width: 767px) {
  .cme-chrome__overlay-3 {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 44px;
    min-height: 44px;
  }
}


/* --------------------------------------------------------------------------
   Touch targets — the two that are genuinely too small

   Audited every link, button and input on every page at 360px. Most of what
   came back was correctly small and left alone:

   - inline links inside a sentence (the Lifestyle amenities list, the privacy
     policy's cross-references) are explicitly exempted by WCAG 2.5.8, and
     padding them would break the line rhythm of the paragraph they sit in;
   - the contact form's 38x55 input is the HONEYPOT — invisible to people,
     there to be filled in by bots. Making it a comfortable target would be
     precisely wrong.

   These two are real: standalone contact links a visitor is meant to tap.
   -------------------------------------------------------------------------- */

@media (max-width: 767px) {
  /* Measured 223x21 and 254x21 — the estate's email and telephone on the
     Contact page, each its own row rather than part of a sentence. Padding
     rather than a min-height so the text keeps its position in the row. */
  .cme-contact-contact-details__link,
  .cme-contact-contact-details__link-2 {
    padding-block: 12px;
  }

  /* The consent box itself. The whole <label> is clickable and comfortably
     large, so this already passes — but 18px is a small thing to aim at if
     someone goes for the box, and it is the control standing between a
     visitor and a sent enquiry. */
  .cme-enquiry__consent input[type="checkbox"] {
    width: 22px;
    height: 22px;
  }
}


/* --------------------------------------------------------------------------
   Stat dividers when the row stacks
   Reported 2026-07-31: a stat lands on the second line, still carrying the
   divider line beside it, so it does not line up with the first stat.

   Three blocks are built the same way — the homepage "90% / 25km / 46",
   The Estate's stats band and the Contact page's details band. In each, the
   first item is flush and items two and three carry a `border-left` plus left
   padding, which is what draws the hairline BETWEEN columns.

   That only works while all three are on one row. Stacked, the rule turns into
   a stray vertical line hanging off the side of the second and third stats,
   and on the homepage the 18px of left padding indents them against the first
   one. Measured at 360px and 414px: stat 1 at x=24, stats 2 and 3 at x=42.

   Stacked, the divider becomes horizontal — which is what it was always for.

   The homepage grid also gets pinned to one column. It is
   `repeat(auto-fit, minmax(175px, 1fr))`, so between roughly 430px and 650px
   it resolves to TWO columns and drops the third stat alone onto a second row —
   the same stray-divider problem in a form no `:nth-child` rule can catch,
   because CSS cannot see where a grid wrapped. The other two blocks already
   collapse to one column via .cme-invest__grid-2 in 02-layout.css.
   -------------------------------------------------------------------------- */

@media (max-width: 767px) {
  .cme-home-the-estate__grid {
    grid-template-columns: 1fr;
  }

  .cme-home-the-estate__row-3,
  .cme-the-estate-estate-stats__box-3,
  .cme-contact-contact-details__box-3 {
    border-left: 0;
    border-top: 1px solid rgba(201, 169, 110, .22);
    padding-top: 22px;
  }

  /* Only the homepage stat indents its content past the rule; the other two
     are centred with symmetric padding and keep it. */
  .cme-home-the-estate__row-3 {
    padding-left: 0;
  }

  /* The first stat carries a transparent 1px border so it aligns with the
     others on desktop. Stacked, that phantom border is a 1px indent. */
  .cme-home-the-estate__row {
    border-left: 0;
  }
}


/* --------------------------------------------------------------------------
   Homepage stats — centred once they stack
   Requested 2026-07-31: centre "90% / 25km / 1,400m²" on mobile only.

   Each stat is a flex column of three parts — the figure and its unit, the
   label, and a line of copy — left-aligned to sit under the heading above them.
   Stacked one per row that alignment loses its anchor: three short blocks flush
   left in a full-width column read as an unfinished list rather than a set.

   Every part has to be told, not just the wrapper. `text-align` centres the
   label and the copy because they are text, but the figure row is a nested flex
   container and needs `justify-content`; the wrapper needs `align-items` or
   each block stays its own width and sits left inside the column.

   The copy keeps its `max-width: 26ch` and is centred by the wrapper, so lines
   stay a readable length rather than stretching the full width of the phone.

   Mobile only — above 768px they are three columns beside each other, where
   left alignment is what lines them up with the section above.
   -------------------------------------------------------------------------- */

@media (max-width: 767px) {
  .cme-home-the-estate__row,
  .cme-home-the-estate__row-3 {
    align-items: center;
    text-align: center;
  }

  /* The figure and its unit — "90" + "%" — share a baseline-aligned flex row. */
  .cme-home-the-estate__row-2 {
    justify-content: center;
  }
}


/* --------------------------------------------------------------------------
   Short viewports — folding phones, and any handset in landscape
   Reported 2026-07-31: the site did not look right on a Galaxy Z Flip.

   Two viewports matter on a flip, and neither resembles an ordinary phone:

     unfolded      412 x 960   very tall (21:9)
     cover screen  360 x 374   very SHORT

   The tall one is handled by the image work — see background_buckets() in
   class-cme-images.php. This is the short one, where the problem is furniture.

   At 374px tall, the fixed header is 120px and the hero reserves another 148px
   of top padding to clear it. That is 268px of a 374px screen — 72% — before a
   word of content. The page was not broken, it was simply mostly chrome.

   Keyed on height rather than on a device, so a phone held sideways gets the
   same treatment. `max-height` is the right axis: this has nothing to do with
   how wide the screen is.
   -------------------------------------------------------------------------- */

@media (max-height: 520px) {
  /* Header: 120px -> 76px. The mark stays legible; the padding does the work. */
  .cme-chrome__bar {
    padding-block: 14px;
  }

  .cme-chrome__image {
    height: 40px;
  }

  .cme-chrome__bar.is-solid {
    padding-block: 10px;
  }

  /* Hero clears the shorter header and stops reserving a phone's worth of air. */
  .cme-home-hero__box {
    padding-block: 92px 36px;
  }
}


/* --------------------------------------------------------------------------
   Mobile menu on a short screen

   Seven links and the button come to roughly 370px. On a flip's cover screen
   the panel is 374px tall, so the list is taller than the space it has.

   `justify-content: center` — which is what the design uses — centres overflow
   in BOTH directions, pushing the first item above the top edge where it cannot
   be scrolled back to. Content centred out of reach is worse than content that
   simply starts at the top.

   `margin-block: auto` on the nav is the standard fix: the auto margins take up
   the slack and centre it while there IS slack, and collapse to nothing when
   there is not, leaving the list scrollable from its first item.
   -------------------------------------------------------------------------- */

.cme-chrome__overlay-2 {
  justify-content: flex-start;
}

.cme-chrome__overlay-2 > nav {
  margin-block: auto;
  /* Clears the fixed header, which sits above this panel. */
  padding-block: 108px 32px;
}

@media (max-height: 520px) {
  .cme-chrome__overlay-2 > nav {
    padding-block: 84px 24px;
    gap: 2px;
  }

  .cme-chrome__link-3 {
    font-size: 1.35rem;
  }
}


/* ==========================================================================
   Text over photography — legibility floor
   Requested 2026-07-31: hero paragraph text is hard to read on a Galaxy Z Flip,
   and "possibly increase the darkness on the overlays across all images that
   have paragraph text on them across the site".

   Measured rather than eyeballed. For each hero photograph I sampled the band
   the paragraph sits in and took the BRIGHTEST 10% of pixels — the part that
   actually defeats text — then solved for the scrim alpha giving 4.5:1:

     photo                    brightest 10%     alpha needed
     home hero (golden hour)  175,141,116       0.35
     the estate / invest      141,153,89        0.50
     lifestyle (pale sky)     162,211,251       0.65
     hiking CTA               162,152,117       0.51

   Against what the scrims actually delivered where the text sits — 0.14 on the
   homepage, 0.30 on the other heroes — that is 2.99:1 to 4.20:1. Below the AA
   threshold everywhere, and worst exactly where it was reported.

   WHY THE FLIP MADE IT OBVIOUS

   The homepage scrim is a 105deg diagonal, weakest at 70% along its axis. On a
   wide screen the copy sits in the strong end. On a 412x960 phone the gradient
   line runs mostly top-to-bottom, so vertically-centred copy lands in the 0.14
   trough. The design was sound for the canvas it was drawn on.

   TWO CHANGES, NOT ONE

   Darkening alone would have needed 0.65 to cover the pale-sky lifestyle photo,
   which turns every other hero to mud. The heroes set their paragraphs in
   --cme-body-dark (#C8BFB0), a dim grey-beige, and that is half the problem.
   Moving them to --cme-parchment (#EADFCE) — already the homepage hero's colour,
   so this unifies rather than invents — drops the requirement to 0.54.

   A 0.55 floor with parchment text gives 4.72:1 on the worst photograph and
   7-8:1 on the rest, while keeping each gradient's shape and direction.

   Only copy that sits over a PHOTOGRAPH is touched. Body copy on solid dark
   grounds — infrastructure, fees, plot-and-plan, quiet-harmony — keeps
   #C8BFB0, where it was never the problem.
   ========================================================================== */

/* --- Hero paragraphs: parchment, not the dimmer body-dark ----------------- */

.cme-the-estate-hero__copy,
.cme-lifestyle-hero__copy,
.cme-invest-hero__copy,
.cme-lifestyle-hiking-mountain-biking__copy {
  color: var(--cme-parchment);
}

/* --- Scrims: same shape, floored at 0.55 --------------------------------- */

/* Homepage hero. The 105deg direction is kept — it is the design's — but the
   trough that sat at 0.14 is lifted to the floor. */
.cme-home-hero__overlay-2 {
  background: linear-gradient(
    105deg,
    rgba(11, 8, 5, .84) 0%,
    rgba(11, 8, 5, .68) 42%,
    rgba(11, 8, 5, .55) 70%,
    rgba(11, 8, 5, .64) 100%
  );
}

/* The four page heroes share one gradient, whose 0.30 midpoint is exactly
   where a vertically-centred paragraph lands. */
.cme-the-estate-hero__overlay,
.cme-lifestyle-hero__overlay,
.cme-invest-hero__overlay,
.cme-contact-hero__overlay {
  background: linear-gradient(
    to bottom,
    rgba(11, 8, 5, .66) 0%,
    rgba(11, 8, 5, .55) 45%,
    rgba(11, 8, 5, .72) 100%
  );
}

/* Lifestyle's two full-bleed photo panels: a heading and a paragraph on each. */
.cme-lifestyle-hiking-mountain-biking__overlay {
  background: linear-gradient(
    100deg,
    rgba(11, 8, 5, .92) 0%,
    rgba(11, 8, 5, .82) 40%,
    rgba(11, 8, 5, .62) 68%,
    rgba(11, 8, 5, .55) 100%
  );
}

.cme-lifestyle-lifestyle-cta__overlay {
  background: linear-gradient(
    to bottom,
    rgba(11, 8, 5, .62) 0%,
    rgba(11, 8, 5, .55) 45%,
    rgba(11, 8, 5, .70) 100%
  );
}


/* --------------------------------------------------------------------------
   Hero — nothing behind the photograph but flat dark
   Reported 2026-08-06: "other images like background or light show before the
   main hero loads".

   It is not another image. `body` carries

     radial-gradient(ellipse at 50% 30%, #1b160e, #0b0906 70%) fixed

   and the hero section declares no background of its own, so until the
   photograph decodes that gradient is what fills the screen — a lighter patch
   at 50%/30%, which is exactly where the eye is. It reads as a glow that
   appears and then vanishes, and on a slow connection it is on screen for a
   second or more.

   The section now paints its own flat ink. The photograph fades in over a
   surface the same colour as its own darkest corner instead of over a
   gradient, so there is no moment where anything but the image and its scrims
   is visible.

   The body gradient is left alone. It is the design's, it shows on the pale
   inner pages where it belongs, and it is only wrong directly behind a
   full-bleed photograph.
   -------------------------------------------------------------------------- */

.cme-home-hero__section {
  background-color: var(--cme-ink-950);
}

/* Same reasoning for the other pages' heroes, which use the same construction. */
.cme-the-estate-hero__section,
.cme-lifestyle-hero__section,
.cme-invest-hero__section,
.cme-contact-hero__section {
  background-color: var(--cme-ink-950);
}


/* --------------------------------------------------------------------------
   Entrance photograph — anchor the crop to its left edge
   Reported 2026-08-27: the left of the new entrance image is being cut off,
   and the left is the important side.

   It is. The gatehouse carrying the estate's name sits in the left third; the
   right is canopy and mountainside. The photograph is 1672x941 (16:9) and both
   boxes holding it are far squarer, so `object-fit: cover` trims the sides —
   and by default it trims them EVENLY, taking the branding with it:

     The Estate, security   1440px   box ratio 1.08   39% cropped, 221px a side
                             390px   box ratio 1.17   34% cropped,  97px a side
     Homepage, security      1440px   box ratio 1.49   16% cropped,  68px a side
                             390px   box ratio 0.74   58% cropped, 227px a side

   `object-position: left center` moves the whole trim to the right-hand edge,
   so the gatehouse is never lost. What goes instead is mountainside, which
   repeats elsewhere on both pages.

   Horizontal only. At 1024px The Estate's box is WIDER than the photograph
   (ratio 2.40) and crops vertically instead — `center` on the vertical axis
   keeps the horizon where the design put it.

   SCOPING NOTE: on The Estate the image carries `cme-the-estate-hero__image`,
   which the PAGE HERO also uses. Setting it on the class would re-crop the
   hero too, so it is scoped to the security box. The homepage class belongs to
   this one element, so it is targeted directly.
   -------------------------------------------------------------------------- */

.cme-the-estate-security__box img,
.cme-home-lifestyle__image {
  object-position: left center;
}


/* --------------------------------------------------------------------------
   Homepage lifestyle pillars — drop the decorative scrim, recentre the hiker
   Reported 2026-08-27: the three cards (25+ km of Trails / The Village of
   Clarens / Working Towards Self-Sufficiency) look dark, and the hiker in the
   trails photograph cannot be made out.

   1. THE SCRIM. Each card carries a `cme-home-lifestyle__overlay` sitting on
      the photo: linear-gradient(to top, rgba(11,8,5,.55), transparent 46%).
      A scrim like that earns its keep when text is laid over the image — it is
      what keeps the copy legible. Here nothing is: the h4 and paragraph sit
      BELOW the media box, on the sand background. So the gradient is buying
      no legibility at all, and is costing 55% black across the bottom half of
      three photographs. Removed rather than softened, for that reason.

      The class is used by exactly these 3 elements, so this touches nothing
      else. Kept as a background override rather than deleting the div, so the
      section's markup still matches the design document.

   2. THE HIKER. Her real problem was upstream, in the image build, not here.
      The pipeline pre-crops to the role ratio, so the file arriving in this
      box is already 4:5 and `object-fit: cover` has nothing left to trim —
      `object-position` was inert. The crop that lost her was sharp's
      `position: 'attention'`, which scores regions by detail density and
      took the textured valley over the person. Fixed at source with
      `crop: 'left'` on the slot in image-map.mjs.

      This rule survives for one rung only. The source is 1440x960, so at the
      960 rung a 4:5 crop would need 1200px of height that does not exist and
      `withoutEnlargement` clamps it square. That 960x960 file DOES get
      cover-cropped by this 4:5 box — 192px of travel — and it is the rung a
      2x display loads. 25% keeps her off the right edge there.

   SCOPING NOTE: `cme-home-lifestyle__image-2` is shared by all three cards,
   so the position is scoped to the first. `cme-lifestyle__grid` also appears
   on the Invest page (Plot and Plan), hence the `#lifestyle` anchor.
   -------------------------------------------------------------------------- */

.cme-home-lifestyle__overlay {
  background: none;
}

#lifestyle .cme-lifestyle__grid > div:first-child .cme-home-lifestyle__image-2 {
  object-position: 25% center;
}
