/* ==========================================================================
   styles.css
   Forest land landing page — mobile-first, no framework, no build step.

   Contents
     01  Tokens (colour, type, spacing)
     02  Reset & base
     03  Typography helpers
     04  Buttons
     05  Header, nav, language picker, translation-accuracy banner
     06  Hero
     07  Sections & layout shells
     08  About + stats
     09  Location (map/satellite, distances)
     10  Vision / concept cards
     11  Lightbox
     12  Why / reasons
     13  Contact + form
     14  Footer
     15  Reveal animations
     16  Reduced motion / print
     17  Right-to-left (Arabic)
   ========================================================================== */


/* 01 — TOKENS ============================================================= */
:root {
  /* Colour: deep forest, warm wood, cream, muted gold */
  --forest-900: #101a15;
  --forest-800: #16241d;
  --forest-700: #1d3126;
  --forest-600: #2b4636;
  --moss:       #3f5a45;
  --moss-soft:  #6f8874;

  --wood-900:   #3a2a1d;
  --wood-700:   #5c4330;
  --wood-500:   #7d5c3f;

  --cream:      #f7f3ea;
  --cream-200:  #efe8da;
  --cream-300:  #e3d9c6;

  --gold:       #b28a4c;
  --gold-soft:  #d8bd8d;

  --ink:        #1b1a17;
  --ink-soft:   #4a4740;
  --ink-faint:  #7c776c;

  /* Type */
  --serif: 'Cormorant Garamond', 'Iowan Old Style', Georgia, 'Times New Roman', serif;
  --sans:  'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;

  /* Spacing / layout */
  --wrap: 1200px;
  --gutter: 1.5rem;
  --section-y: 5rem;
  --radius: 2px;                  /* nearly square — reads as architectural */

  /* Every pill-shaped control in the header is exactly this tall, rather than
     each one arriving at its own height via padding + line-height. Change it
     here and the Inquire button and the language switcher move together. */
  --control-h: 2.375rem;          /* 38px */

  /* --- Card system -----------------------------------------------------
     The stat grids in About, Location and the concept-figures panel were
     built at different times. These tokens keep their metrics identical so
     they read as one component in three colourways. Only the ground colour
     is allowed to differ between them. */
  --cell-pad-y: 1.5rem;
  --cell-pad-x: 1.25rem;
  --cell-label: .68rem;
  --cell-label-track: .16em;
  --cell-value: clamp(1.35rem, 4vw, 1.9rem);
  --cell-note: .82rem;

  --ease: cubic-bezier(.22, .61, .36, 1);
}

@media (min-width: 768px) {
  :root {
    --gutter: 2.5rem;
    --section-y: 8rem;
    --cell-pad-y: 2rem;
    --cell-pad-x: 1.5rem;
  }
}
@media (min-width: 1200px) {
  :root { --gutter: 3rem; --section-y: 10rem; }
}


/* 02 — RESET & BASE ======================================================= */
*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 5rem;       /* so anchors clear the sticky header */
}

body {
  margin: 0;
  background: var(--cream);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 1rem;
  font-weight: 300;
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img, svg, iframe, video { display: block; max-width: 100%; }
img, video { height: auto; }

a { color: inherit; text-decoration: none; }

button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }

:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 3px;
}

.skip-link {
  position: absolute; inset-inline-start: -9999px; top: 0; z-index: 200;
  background: var(--forest-800); color: var(--cream);
  padding: .75rem 1.25rem;
}
.skip-link:focus { inset-inline-start: 0; }

.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* Screen-reader-only honeypot field */
.hp {
  position: absolute; width: 1px; height: 1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
}


/* 03 — TYPOGRAPHY ========================================================= */
.eyebrow {
  margin: 0 0 1.25rem;
  font-size: .72rem;
  font-weight: 400;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--gold);
}
.eyebrow--light { color: var(--gold-soft); }

.h2 {
  margin: 0;
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(2rem, 6vw, 3.4rem);
  line-height: 1.12;
  letter-spacing: -.01em;
  color: var(--forest-900);
  text-wrap: balance;
}
.h2--light { color: var(--cream); }

/* Section-level heading one step below .h2 (used by the safety block) */
.h3 {
  margin: 0 0 .75rem;
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(1.5rem, 3.5vw, 2rem);
  line-height: 1.2;
  color: var(--forest-900);
}

.lede {
  margin: 1.5rem 0 0;
  max-width: 46ch;
  font-size: 1.05rem;
  color: var(--ink-soft);
  text-wrap: pretty;
}
.lede--light { color: rgba(247, 243, 234, .72); }

.prose p {
  margin: 0 0 1.4em;
  max-width: 60ch;
  color: var(--ink-soft);
  text-wrap: pretty;
}
.prose p:last-child { margin-bottom: 0; }

.footnote {
  margin: 3rem 0 0;
  font-size: .8rem;
  letter-spacing: .04em;
  color: var(--ink-faint);
}
.footnote--light { color: rgba(247, 243, 234, .55); }


/* 04 — BUTTONS ============================================================ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  padding: 1rem 2rem;
  border-radius: var(--radius);
  font-size: .78rem;
  font-weight: 400;
  letter-spacing: .16em;
  text-transform: uppercase;
  transition: background-color .35s var(--ease), color .35s var(--ease),
              border-color .35s var(--ease), transform .35s var(--ease);
}
.btn:hover,
.btn:focus-visible { transform: translateY(-2px); }
.btn:active { transform: translateY(0); }

.btn--gold {
  background: var(--gold);
  color: #fff;
  border: 1px solid var(--gold);
}
.btn--gold:hover,
.btn--gold:focus-visible { background: #9d7840; border-color: #9d7840; }

.btn--ghost {
  border: 1px solid rgba(247, 243, 234, .45);
  color: var(--cream);
}
.btn--ghost:hover,
.btn--ghost:focus-visible { background: rgba(247, 243, 234, .1); border-color: var(--cream); }

.btn--full { width: 100%; }


/* 05 — HEADER ============================================================= */
.header {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 100;
  transition: background-color .4s var(--ease), box-shadow .4s var(--ease);
}
/* Solid state, applied by main.js once the hero is scrolled past */
.header.is-stuck {
  background: rgba(16, 26, 21, .93);
  backdrop-filter: blur(10px);
  box-shadow: 0 1px 0 rgba(247, 243, 234, .1);
}

.header__inner {
  max-width: var(--wrap);
  margin-inline: auto;
  padding: 1.1rem var(--gutter);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

/* --- The header's internal z-index ladder ---
   .nav is position:fixed inset:0 on mobile, so once it is open it covers
   the whole viewport — including the burger that has to close it again.
   A positioned element with z-index:auto paints above its non-positioned
   siblings whatever the source order, so the drawer used to bury the
   burger and swallow the tap: the menu opened and then would not close.

   Everything in the header bar is therefore positioned and given an
   explicit layer above the drawer:

     90   .nav                 the drawer itself
     100  .header__brand       logo stays legible over it
     110  .header__right       burger + language button stay tappable
     120  .langpicker__menu    the dropdown, above all of the above

   Do not remove these. The drawer is only reachable while it covers the
   screen, which is exactly when the controls need to outrank it. */
.header__brand {
  position: relative;
  z-index: 100;
  display: flex;
  align-items: center;
  gap: .65rem;
  color: var(--cream);
}
.header__mark { display: block; width: 18px; color: var(--gold-soft); }
.header__mark svg { width: 100%; height: auto; }
.header__brandtext {
  font-family: var(--serif);
  font-size: 1rem;
  letter-spacing: .06em;
  white-space: nowrap;
}
/* On narrow phones the mark alone carries the brand */
@media (max-width: 479px) { .header__brandtext { display: none; } }

/* --- Nav --- */
.nav { display: none; }

.nav a {
  position: relative;
  font-size: .78rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: rgba(247, 243, 234, .82);
  transition: color .3s var(--ease);
}
.nav a::after {
  content: '';
  position: absolute;
  left: 0; bottom: -6px;
  width: 100%; height: 1px;
  background: var(--gold-soft);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .4s var(--ease);
}
.nav a:hover,
.nav a:focus-visible { color: var(--cream); }
.nav a:hover::after,
.nav a:focus-visible::after,
.nav a.is-active::after { transform: scaleX(1); }

/* Inquire button. Height comes from --control-h, not from padding, so it
   matches the language switcher exactly in every language. */
.nav__cta {
  display: inline-flex;
  align-items: center;
  height: var(--control-h);
  padding-inline: 1.1rem;
  border: 1px solid rgba(247, 243, 234, .4);
  border-radius: var(--radius);
  color: var(--cream) !important;
  transition: background-color .3s var(--ease), border-color .3s var(--ease);
}
.nav__cta::after { display: none; }
.nav__cta:hover,
.nav__cta:focus-visible {
  background: rgba(247, 243, 234, .12);
  border-color: var(--cream);
}

.header__right { position: relative; z-index: 110; display: flex; align-items: center; gap: 1rem; }

/* --- Language picker (dropdown) --------------------------------------
   Used twice: in the header and in the footer (.langpicker--up opens
   upward). Options are injected by main.js from the LANGUAGES registry.
   -------------------------------------------------------------------- */
.langpicker { position: relative; }

/* Same fixed height as .nav__cta — see --control-h. The button shows only the
   two-letter code, never the native name, so no language can stretch it. */
.langpicker__btn {
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  height: var(--control-h);
  padding-inline: .7rem;
  border: 1px solid rgba(247, 243, 234, .22);
  border-radius: var(--radius);
  color: rgba(247, 243, 234, .8);
  font-size: .76rem;
  letter-spacing: .1em;
  transition: border-color .3s var(--ease), color .3s var(--ease),
              background-color .3s var(--ease);
}
.langpicker__btn:hover,
.langpicker__btn:focus-visible {
  color: var(--cream);
  border-color: rgba(247, 243, 234, .45);
  background: rgba(247, 243, 234, .06);
}
.langpicker__globe { width: 14px; height: 14px; flex: none; opacity: .8; }
.langpicker__current { min-width: 1.6em; text-align: center; }
.langpicker__chev {
  width: 12px; height: 12px;
  transition: transform .3s var(--ease);
}
.langpicker.is-open .langpicker__chev { transform: rotate(180deg); }

.langpicker__menu {
  position: absolute;
  top: calc(100% + .5rem);
  inset-inline-end: 0;             /* mirrors automatically in RTL */
  z-index: 120;
  min-width: 12.5rem;
  margin: 0;
  padding: .4rem;
  list-style: none;
  background: rgba(16, 26, 21, .97);
  backdrop-filter: blur(12px);
  border: 1px solid rgba(247, 243, 234, .15);
  border-radius: var(--radius);
  box-shadow: 0 18px 40px rgba(0, 0, 0, .45);
  animation: pickerIn .22s var(--ease);
}
.langpicker__menu[hidden] { display: none; }

/* Footer picker opens upward so it never runs off the bottom of the page */
.langpicker--up .langpicker__menu {
  top: auto;
  bottom: calc(100% + .5rem);
}

@keyframes pickerIn {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}
.langpicker--up .langpicker__menu { animation-name: pickerInUp; }
@keyframes pickerInUp {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

.langpicker__opt {
  display: flex;
  align-items: baseline;
  gap: .75rem;
  padding: .6rem .75rem;
  border-radius: var(--radius);
  cursor: pointer;
  color: rgba(247, 243, 234, .72);
  transition: background-color .2s var(--ease), color .2s var(--ease);
}
.langpicker__opt:hover,
.langpicker__opt:focus-visible { background: rgba(247, 243, 234, .08); color: var(--cream); }
.langpicker__opt.is-active { color: var(--gold-soft); }

/* A hairline marks the current language without adding an icon */
.langpicker__opt.is-active .langpicker__code {
  border-bottom: 1px solid currentColor;
}
.langpicker__code {
  min-width: 2em;
  font-size: .72rem;
  letter-spacing: .12em;
}
.langpicker__native {
  font-family: var(--serif);
  font-size: 1rem;
  letter-spacing: normal;
}
/* The Arabic option must render in an Arabic face even on the other four
   versions of the site, where the RTL overrides below do not apply. */
.langpicker__native[lang="ar"] {
  font-family: 'Noto Naskh Arabic', 'Segoe UI', Tahoma, sans-serif;
}


/* --- Translation accuracy banner (Turkish & German only) ---------------
   Sits inside the fixed header, directly under the nav bar, so it needs no
   layout offset and scrolls with nothing. Deliberately quiet: small type,
   muted rule, no colour beyond the existing gold.
   -------------------------------------------------------------------- */
.advisory {
  background: rgba(16, 26, 21, .94);
  backdrop-filter: blur(10px);
  border-top: 1px solid rgba(247, 243, 234, .1);
  border-bottom: 1px solid rgba(178, 138, 76, .35);
  animation: advisoryIn .5s var(--ease);
}
.advisory[hidden] { display: none; }

/* The full-screen mobile drawer would otherwise have the bar floating on top */
body.menu-open .advisory { display: none; }

@keyframes advisoryIn {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}

.advisory__inner {
  max-width: var(--wrap);
  margin-inline: auto;
  padding: .55rem var(--gutter);
  display: flex;
  /* Top-aligned, not centred: once the sentence wraps to two or three lines
     on a phone, a vertically centred icon floats away from the text it
     belongs to. This was the layout bug. */
  align-items: flex-start;
  gap: .6rem;
}

.advisory__icon {
  flex: 0 0 auto;                  /* never shrinks, never stretches */
  width: 14px; height: 14px;
  margin-top: .2em;                /* optically aligns with the first line */
  color: var(--gold-soft);
}

.advisory p {
  /* flex-grow so it takes the space left over, and min-width:0 so it is
     allowed to shrink below its content width and wrap instead of pushing
     the close button off the edge. */
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
  font-size: .72rem;
  line-height: 1.45;
  color: rgba(247, 243, 234, .62);
  overflow-wrap: anywhere;         /* no long token can ever overflow */
  text-wrap: pretty;
}

.advisory__close {
  flex: 0 0 auto;
  width: 24px; height: 24px;
  margin: -.15rem -.4rem 0 0;      /* pulls the hit area flush to the gutter */
  margin-inline-start: .25rem;
  font-size: 1.15rem;
  line-height: 1;
  color: rgba(247, 243, 234, .45);
  transition: color .3s var(--ease);
}
.advisory__close:hover,
.advisory__close:focus-visible { color: var(--cream); }

/* Phones: tighter still, and the banner is capped so it can never grow tall
   enough to swallow the hero behind the fixed header. */
@media (max-width: 599px) {
  .advisory__inner { padding: .5rem var(--gutter); gap: .5rem; }
  .advisory p { font-size: .68rem; line-height: 1.4; }
  .advisory__icon { width: 13px; height: 13px; }
}

/* --- Burger (mobile) --- */
/* 44px is the minimum reliable touch target. The bars stay 28px wide —
   the extra is padding, so the button looks identical and simply catches
   the near-misses that used to land on nothing. */
.burger {
  width: 44px; height: 44px;
  margin-inline-end: -8px;      /* keep the optical alignment it had */
  display: grid; align-content: center; justify-content: center; gap: 6px;
  color: var(--cream);
}
.burger span {
  display: block; height: 1px; width: 28px;
  background: currentColor;
  transition: transform .35s var(--ease), opacity .35s var(--ease);
}
.burger[aria-expanded="true"] span:first-child { transform: translateY(3.5px) rotate(45deg); }
.burger[aria-expanded="true"] span:last-child  { transform: translateY(-3.5px) rotate(-45deg); }

/* Mobile drawer */
@media (max-width: 899px) {
  .nav {
    position: fixed;
    inset: 0;
    z-index: 90;                 /* under the header controls — see the ladder above */
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    justify-content: center;

    /* Long labels are the norm, not the exception: "Was hier entstehen
       kann" and "Neler İnşa Edebilirsiniz" are three times the length of
       "Location". The drawer therefore scrolls rather than centring a
       column that cannot fit, and the top padding clears the fixed header
       bar so the first item never hides behind the logo. */
    gap: 1.5rem;
    padding: 5.5rem var(--gutter) 2.5rem;
    overflow-y: auto;
    overscroll-behavior: contain;  /* no scroll chaining to the locked page */
    -webkit-overflow-scrolling: touch;

    background: var(--forest-900);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-1rem);
    transition: opacity .4s var(--ease), transform .4s var(--ease), visibility .4s;
  }
  /* Centre the items when they fit, top-align them when they do not */
  .nav::before,
  .nav::after { content: ""; margin-block: auto; }

  .nav.is-open { opacity: 1; visibility: visible; transform: none; }

  .nav a {
    font-size: 1.1rem;
    letter-spacing: .1em;
    /* Wrap rather than clip, and stay a 44px-tall target either way. */
    max-width: 100%;
    min-height: 44px;
    display: flex;
    align-items: center;
    line-height: 1.3;
    text-wrap: pretty;
  }
  /* The underline is drawn at the foot of the box; with a taller box and
     wrapped text it has to follow the text, not the box. */
  .nav a::after { bottom: 2px; }

  .nav__cta { margin-top: .5rem; }
}

@media (min-width: 900px) {
  .nav { display: flex; align-items: center; gap: 2.2rem; }
  .burger { display: none; }
}


/* 06 — HERO =============================================================== */
.hero {
  position: relative;
  min-height: 100svh;
  display: flex;
  align-items: flex-end;
  padding: 8rem 0 4rem;
  overflow: hidden;
  background: var(--forest-900);
}

.hero__media { position: absolute; inset: 0; }
.hero__media img,
.hero__media video {
  width: 100%; height: 100%;
  object-fit: cover;
  /* hero.jpg is a wide aerial (1642x958). On a tall phone the height fills
     exactly and only the sides are cropped, leaving the middle third — ridge
     line, valley and the switchback road — which is the strongest part of the
     frame, so horizontal centring is right. On wide desktops the crop is
     vertical instead; biasing slightly past centre keeps the road and valley
     and gives up empty sky at the top rather than the terrain at the bottom. */
  object-position: center 55%;
  /* Slow, barely-there zoom keeps a static photo feeling alive */
  animation: heroDrift 24s var(--ease) forwards;
}
@keyframes heroDrift {
  from { transform: scale(1.08); }
  to   { transform: scale(1); }
}

/* Dimming overlay: darker at the bottom where the type sits */
.hero__scrim {
  position: absolute; inset: 0;
  background:
    linear-gradient(to top, rgba(16, 26, 21, .92) 0%, rgba(16, 26, 21, .45) 45%, rgba(16, 26, 21, .35) 100%),
    radial-gradient(120% 80% at 50% 0%, rgba(0, 0, 0, .25), transparent 60%);
}

.hero__content {
  position: relative;
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.hero__title {
  margin: 0;
  font-family: var(--serif);
  font-weight: 300;
  font-size: clamp(2.8rem, 11vw, 6.5rem);
  line-height: 1.02;
  letter-spacing: -.02em;
  color: var(--cream);
}

.hero__sub {
  margin: 1.5rem 0 0;
  max-width: 34ch;
  font-size: clamp(1rem, 2.4vw, 1.15rem);
  color: rgba(247, 243, 234, .8);
}

.hero__actions {
  margin-top: 2.5rem;
  display: flex;
  flex-wrap: wrap;
  gap: .85rem;
}

.hero__scroll {
  position: absolute;
  inset-inline-end: var(--gutter);
  bottom: 4rem;
  display: none;
  align-items: center;
  gap: .75rem;
  font-size: .68rem;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: rgba(247, 243, 234, .55);
}
.hero__scroll i {
  display: block; width: 48px; height: 1px;
  background: rgba(247, 243, 234, .4);
  position: relative; overflow: hidden;
}
.hero__scroll i::after {
  content: ''; position: absolute; inset: 0;
  background: var(--gold-soft);
  animation: scrollLine 2.4s var(--ease) infinite;
}
@keyframes scrollLine {
  0%   { transform: translateX(-100%); }
  60%,
  100% { transform: translateX(100%); }
}
@media (min-width: 900px) { .hero__scroll { display: flex; } }



/* 06b — CONCEPT TEASER ====================================================
   Sits between the hero and the About section. Dark ground so it separates
   cleanly from the photographic hero above and the cream facts below, but
   it is deliberately under half a normal section's height — this is a hook
   before the substantive content, not a section competing with the hero.
   No .section class here on purpose: that would give it full section
   padding and it would read as a second hero.
   ========================================================================= */
.teaser {
  background: var(--forest-800);
  padding-block: calc(var(--section-y) * .5);
}

.teaser__inner {
  display: grid;
  gap: 1.75rem;
  align-items: center;
}

@media (min-width: 860px) {
  .teaser__inner {
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
    gap: 3.5rem;
  }
}

.teaser__media {
  position: relative;
  margin: 0;
  overflow: hidden;
  border-radius: var(--radius);
}
/* Capped by aspect ratio rather than by height, so the whole block stays
   well inside one viewport at every width. */
.teaser__media img {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

/* The concept warning. Same idea as .concept__tag on the flagship cover,
   one step louder: down there the reader has already passed the vision
   intro, up here they have passed nothing, so the chip carries a border and
   a near-opaque ground and must stay legible at this reduced scale. Not a
   substitute for the full disclaimers — those stay with the figures. */
.teaser__tag {
  position: absolute;
  top: .75rem;
  inset-inline-start: .75rem;
  z-index: 2;
  max-width: calc(100% - 1.5rem);
  padding: .4rem .7rem;
  background: rgba(8, 15, 12, .85);
  border: 1px solid rgba(216, 189, 141, .5);
  border-radius: var(--radius);
  color: var(--gold-soft);
  font-family: var(--sans);
  font-size: .62rem;
  font-weight: 400;
  line-height: 1.45;
  letter-spacing: .12em;
  text-transform: uppercase;
}

.teaser__line {
  margin: 0;
  max-width: 26ch;
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(1.5rem, 3.4vw, 2.2rem);
  line-height: 1.25;
  color: var(--cream);
  text-wrap: pretty;
}

.teaser__ctawrap { margin: 1.75rem 0 0; }

/* A rule-under link rather than a .btn — the hero already owns the buttons
   directly above, and a second pair of them here would read as a rival. */
.teaser__cta {
  display: inline-flex;
  align-items: center;
  gap: .55rem;
  padding-bottom: .3rem;
  border-bottom: 1px solid rgba(216, 189, 141, .45);
  color: var(--gold-soft);
  font-size: .74rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  transition: color .35s var(--ease), border-color .35s var(--ease);
}
.teaser__cta:hover,
.teaser__cta:focus-visible {
  color: var(--cream);
  border-color: var(--cream);
}

.teaser__arrow { transition: transform .35s var(--ease); }
.teaser__cta:hover .teaser__arrow,
.teaser__cta:focus-visible .teaser__arrow { transform: translateY(3px); }

/* 07 — SECTIONS =========================================================== */
.section { padding-block: var(--section-y); }

.section--cream { background: var(--cream); }
.section--dark  { background: var(--forest-800); }
.section--wood  { background: var(--wood-900); }

/* Subtle paper texture on the cream sections, drawn in CSS (no image weight) */
.section--cream {
  background-image: radial-gradient(rgba(122, 106, 79, .05) 1px, transparent 1px);
  background-size: 22px 22px;
}

.section__head { margin-bottom: 3.5rem; max-width: 52ch; }
.section__head--center {
  margin-inline: auto;
  text-align: center;
}
.section__head--center .lede { margin-inline: auto; }

@media (min-width: 768px) { .section__head { margin-bottom: 5rem; } }


/* 08 — ABOUT + STATS ====================================================== */

/* --- Asking price -----------------------------------------------------
   Set above the stat grid, on its own. It is the first thing every buyer
   scrolls for, so it is not buried among the other facts — but the figure
   itself is no longer published: `price.value` is a short phrase ("On
   request"), which is why the value below is set smaller than the display
   size a six-digit number wanted.
   -------------------------------------------------------------------- */
.price {
  margin-bottom: 3rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--cream-300);
}
.price__label {
  display: block;
  margin-bottom: .5rem;
  font-size: .68rem;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.price__figures {
  display: flex;
  flex-wrap: wrap;                 /* stacks on narrow phones */
  align-items: baseline;
  gap: .35rem .9rem;
  margin: 0;
}
.price__value {
  font-family: var(--serif);
  font-size: clamp(1.65rem, 5vw, 2.25rem);
  line-height: 1.15;
  color: var(--forest-900);
}
/* Currency footnote. It reads as fine print *under* the figures, not as a
   second column beside them — the old two-column arrangement left a ragged
   block of small text floating next to the price and a gap under it. Full
   width also means German, which runs longest here, simply takes another
   line instead of squeezing a narrow column. */
.price__note {
  margin: 1rem 0 0;
  max-width: 96ch;      /* wide enough to read as a footnote band, not a column */
  font-size: .8rem;
  line-height: 1.65;
  color: var(--ink-faint);
  text-wrap: pretty;
}
/* One stacked column at every width: label, value, footnote. */
@media (min-width: 700px) {
  .price__figures { gap: .5rem 1.25rem; }
}

.stats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1px;
  background: var(--cream-300);          /* becomes the hairline grid */
  border: 1px solid var(--cream-300);
  border-radius: var(--radius);
  overflow: hidden;
  margin-bottom: 4rem;
}
.stat {
  background: var(--cream);
  padding: var(--cell-pad-y) var(--cell-pad-x);
  display: flex;
  flex-direction: column;
  gap: .35rem;
  min-width: 0;
  overflow-wrap: break-word;   /* long German compounds must not overflow */
}
.stat__label {
  font-size: var(--cell-label);
  letter-spacing: var(--cell-label-track);
  text-transform: uppercase;
  color: var(--ink-faint);
}
.stat__value {
  font-family: var(--serif);
  font-size: var(--cell-value);
  line-height: 1.15;
  color: var(--forest-800);
}
.stat__note { font-size: var(--cell-note); line-height: 1.6; color: var(--ink-faint); }

@media (min-width: 700px)  { .stats { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

/* A single measured column of narrative under the stat grid. The supporting
   image was removed when the land photo moved to the Location section. */
.about__body .prose p { max-width: 66ch; }


/* 09 — LOCATION ===========================================================
   One visual: the live Leaflet map, with the Street View link as a chip on
   it, the real ground-level photo as a small secondary aside, and every
   distance in one scannable two-column table. Everything here is real
   imagery of the real site — no concept-render styling may leak in.

   There used to be a tablist here (Boundary / Satellite / Map) over three
   stacked panels. The two static ones were cut: the map's own layer switch
   already offers Map vs Satellite, and its versions pan and zoom. The stage
   keeps its fixed aspect ratio and absolutely-positioned panel even with one
   panel left — that is what reserves the map's height before Leaflet loads.
   ========================================================================= */
.geo { display: grid; gap: 2.5rem; }
@media (min-width: 900px) {
  .geo {
    grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
    gap: 3rem;
    align-items: start;
  }
}

/* --- The visual itself --- */
.geo__stage {
  position: relative;
  overflow: hidden;
  border: 1px solid rgba(247, 243, 234, .15);
  border-radius: var(--radius);
  background: var(--forest-700);
  aspect-ratio: 4 / 3;
}
@media (min-width: 700px) { .geo__stage { aspect-ratio: 16 / 10; } }

/* Absolute inside the fixed-ratio stage: it is what gives Leaflet a sized
   box to mount into before any tile has arrived. */
.geo__panel { position: absolute; inset: 0; }

/* The note under the map describes the surveyed cadastral polygon drawn on
   it — fact, not an estimate — so it is not greyed back the way a caption is. */
.geo__note--strong { color: rgba(247, 243, 234, .78); }

/* --- The Leaflet map ---------------------------------------------------
   One custom property feeds the polygon stroke (set in main.js) and the
   legend swatch, so the legend cannot end up describing a colour the map is
   not drawing. */
:root { --parcel: #b28a4c; }

#map-frame {
  width: 100%;
  height: 100%;
  background: var(--forest-700);
}

/* Only the tiles are muted, so the map sits inside the palette instead of
   shouting. The overlay pane is deliberately excluded: the whole point of
   the boundary is that it stands out, and desaturating it would defeat the
   casing that keeps it readable on satellite imagery. Imagery tiles are left
   alone too — muting an aerial photograph just makes it harder to read. */
#map-frame.is-streets .leaflet-tile-pane { filter: saturate(.6) contrast(.95) brightness(.94); }
.leaflet-container { background: var(--forest-700); }

/* Leaflet ships its own type; bring it back into the site's. */
.leaflet-container {
  font-family: var(--sans);
  font-size: .75rem;
}
.leaflet-container a { color: var(--wood-700); }

.leaflet-control-attribution {
  background: rgba(247, 243, 234, .82);
  font-size: .62rem;
  /* Attribution is Latin text and URLs whatever the page language is, so it
     is pinned LTR rather than left to mirror into nonsense in Arabic. */
  direction: ltr;
  text-align: left;
}

.leaflet-control-zoom a {
  color: var(--forest-900);
  font-family: var(--sans);
}

/* Fallback when vendor/leaflet.js cannot be loaded at all */
.map__fallback {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  padding: 2rem;
  color: var(--cream);
  font-size: .85rem;
  text-align: center;
  text-decoration: underline;
  text-underline-offset: 4px;
}

/* --- View switch -------------------------------------------------------
   Map · Satellite · Street View: three views of the stage, on their own line
   above it rather than floating in its corner. Sitting on the section's dark
   ground instead of on imagery, it takes the same treatment the old
   Boundary/Satellite/Map tablist had here — a light hairline trough with the
   active view filled in — which is legible without needing a scrim.

   flex-wrap, not nowrap: three uppercase labels are wider than two, and on a
   narrow phone the third would otherwise push out past the stage edge. */
.maplayers {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 1px;
  margin-bottom: .9rem;
  padding: 2px;
  background: rgba(247, 243, 234, .12);
  border-radius: var(--radius);
}
.maplayers__btn {
  padding: .5rem 1.1rem;
  border-radius: var(--radius);
  background: transparent;
  color: rgba(247, 243, 234, .62);
  font-size: .7rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  white-space: nowrap;
  transition: background-color .3s var(--ease), color .3s var(--ease);
}
.maplayers__btn:hover,
.maplayers__btn:focus-visible { color: var(--cream); }
.maplayers__btn.is-active {
  background: var(--forest-600);
  color: var(--cream);
}
@media (max-width: 420px) {
  .maplayers__btn { padding: .5rem .7rem; font-size: .64rem; letter-spacing: .06em; }
}

/* --- Legend ------------------------------------------------------------
   Alone in the map's top inline-start corner since the view switch moved out
   above the stage. z-index clears Leaflet's panes (400–700) but stays under
   .mapsv (1000), so Street View covers it — it labels a line that only the
   map draws. pointer-events: none keeps it from eating map drags: it is a
   caption, and there is nothing on it to click. */
.maplegend {
  position: absolute;
  top: .75rem;
  inset-inline-start: .75rem;
  z-index: 800;
  pointer-events: none;
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  margin: 0;
  max-width: calc(100% - 1.5rem);
  padding: .45rem .7rem;
  background: rgba(8, 15, 12, .78);
  border: 1px solid rgba(247, 243, 234, .22);
  border-radius: var(--radius);
  color: var(--cream);
  font-size: .66rem;
  line-height: 1.4;
  text-wrap: pretty;
}
.maplegend__swatch {
  flex: none;
  width: 1.1rem;
  height: .55rem;
  border: 2px solid var(--parcel);
  border-radius: 1px;
  background: rgba(178, 138, 76, .18);
}

/* The stack must never grow tall enough to reach the attribution bar in the
   opposite corner, so the legend wraps rather than running the full width. */
.maplegend { max-width: 22ch; }
/* Hidden in Street View, where there is no polygon for it to label. */
.maplegend[hidden] { display: none; }

/* --- Street View panel -------------------------------------------------
   Covers the map instead of replacing it, so Leaflet keeps its size and
   needs no re-measure on the way back. z-index clears Leaflet's panes
   (400–700) and the legend (800); the view switch is outside the stage, so
   nothing here can cover it. This is also why Street View no longer flickers
   when the base layers swap: it used to be a chip at z-index 2, *below* the
   tile pane, and showed through for a frame while the tiles were swapped. */
.mapsv {
  position: absolute;
  inset: 0;
  z-index: 1000;
  background: var(--forest-800);
}
.mapsv[hidden] { display: none; }

.mapsv__frame {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
}

/* Sits over the iframe, in the corner the old chip used to hold. Always
   painted, so if the embed is ever blocked this is still a working way to
   the panorama rather than a blank rectangle. */
.mapsv__out {
  position: absolute;
  bottom: .75rem;
  inset-inline-end: .75rem;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  padding: .5rem .8rem;
  background: rgba(8, 15, 12, .78);
  border: 1px solid rgba(247, 243, 234, .22);
  border-radius: var(--radius);
  color: var(--cream);
  font-size: .64rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  transition: background-color .3s var(--ease), border-color .3s var(--ease);
}
.mapsv__out:hover,
.mapsv__out:focus-visible {
  background: rgba(8, 15, 12, .95);
  border-color: var(--gold-soft);
}
.mapsv__out-icon { display: inline-flex; width: 13px; flex: none; }
.mapsv__out-icon svg { width: 100%; height: auto; }

.geo__note {
  margin: .9rem 0 0;
  font-size: .78rem;
  line-height: 1.6;
  color: rgba(247, 243, 234, .5);
  text-wrap: pretty;
}

/* --- Secondary column: the one real ground-level photo --- */
.geo__photo { margin: 0; }
.geo__photo-btn {
  display: block;
  width: 100%;
  padding: 0;
  overflow: hidden;
  border: 1px solid rgba(247, 243, 234, .15);
  border-radius: var(--radius);
  cursor: zoom-in;
}
.geo__photo-btn img {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  transition: transform 1.2s var(--ease);
}
.geo__photo-btn:hover img,
.geo__photo-btn:focus-visible img { transform: scale(1.04); }

.geo__photo figcaption {
  margin-top: .75rem;
  font-size: .8rem;
  line-height: 1.6;
  color: rgba(247, 243, 234, .55);
  text-wrap: pretty;
}

.geo__heritage {
  margin: 1.75rem 0 0;
  padding-top: 1.5rem;
  border-top: 1px solid rgba(247, 243, 234, .15);
  font-size: .86rem;
  line-height: 1.7;
  color: rgba(247, 243, 234, .6);
  text-wrap: pretty;
}

/* --- DISTANCES ---
   The old "Nearby" list and the "Within Reach" cards, merged. Two columns of
   name/value rows: the fastest thing on the page to scan, and far shorter
   than six cards plus a five-row list. */
.dist {
  margin-top: 3.5rem;
  padding-top: 3rem;
  border-top: 1px solid rgba(247, 243, 234, .15);
}
@media (min-width: 900px) { .dist { margin-top: 4.5rem; padding-top: 3.5rem; } }

.dist__head { max-width: 46ch; margin-bottom: 2rem; }
.dist__title {
  margin: .5rem 0 0;
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(1.5rem, 3.6vw, 2.2rem);
  line-height: 1.2;
  color: var(--cream);
  text-wrap: balance;
}

.dist__list {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0 3.5rem;
  margin: 0;
}
/* Column-major, so each column reads as its own ascending run of distances
   rather than the eye having to zig-zag across rows to follow the order. */
@media (min-width: 760px) {
  .dist__list {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-template-rows: repeat(5, auto);
    grid-auto-flow: column;
  }
}

.dist__list > div {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  padding: .85rem 0;
  border-bottom: 1px solid rgba(247, 243, 234, .12);
}
.dist__list dt {
  font-size: .78rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: rgba(247, 243, 234, .55);
}
.dist__list dd {
  margin: 0;
  min-width: 0;
  overflow-wrap: break-word;
  text-align: end;
  color: var(--cream);
  font-size: .95rem;
}

.dist > .footnote { margin-top: 1.5rem; }


/* 10 — VISION / CONCEPTS ================================================== */
.concepts { display: grid; gap: 3.5rem; }

/* The two-column alternating lookbook rows that used to live here went with
   the four secondary concept cards — one card cannot alternate with itself,
   and .concept--feature lays itself out (display: block, see below). If a
   second concept is ever added back, that rule comes back with it. */

.concept__media {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius);
  background: var(--cream-200);
}
.concept__media img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  transition: transform 1.2s var(--ease), filter 1.2s var(--ease);
}
.concept:hover .concept__media img { transform: scale(1.05); }

@media (min-width: 900px) {
  .concept__media img { aspect-ratio: 5 / 4; }
}

.concept__text { padding-top: .5rem; }

.concept__title {
  margin: 0 0 1rem;
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(1.5rem, 4vw, 2.2rem);
  line-height: 1.2;
  color: var(--forest-900);
}
.concept__text p {
  margin: 0;
  max-width: 46ch;
  color: var(--ink-soft);
  text-wrap: pretty;
}

/* --- Flagship concept ---
   The resort is the most ambitious of the five, so it breaks the alternating
   two-column rhythm. The card and the figures panel share ONE container, so
   they read as a single continuous block instead of two things separated by
   the .concepts grid gap. All the spacing between them is set here. */
.flagship {
  --flagship-pad: 1rem;
  background: var(--cream-200);
  border: 1px solid rgba(178, 138, 76, .35);
  border-radius: var(--radius);
  overflow: hidden;             /* lets the flag strip and disclaimer bleed */
}

@media (min-width: 900px) { .flagship { --flagship-pad: 1.75rem; } }

.concept--feature { padding: var(--flagship-pad); }
@media (min-width: 900px) {
  /* Override the lookbook grid — this one is stacked, not side by side */
  .concept--feature { display: block; }
}

.concept--feature .concept__media img { aspect-ratio: 16 / 9; }
@media (min-width: 900px) {
  .concept--feature .concept__media img { aspect-ratio: 21 / 9; }
}

/* Description and gallery thumbnails share the row. Giving the second column
   a real job is what stops the paragraph from trailing off into dead space. */
.concept__lower { display: grid; gap: 2rem; padding-top: 1.75rem; }
@media (min-width: 900px) {
  .concept__lower {
    grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr);
    gap: 3rem;
    align-items: start;
  }
}

.concept--feature .concept__text { padding-top: 0; }
.concept--feature .concept__title { font-size: clamp(1.9rem, 5vw, 3rem); }
/* Full width of its own column — the column does the constraining now */
.concept--feature .concept__text p { max-width: none; }


/* --- Flagship cover as a gallery trigger --- */
.concept__media--btn { display: block; width: 100%; padding: 0; cursor: zoom-in; }

/* The artist's-concept label is burned into the cover as well as into every
   lightbox caption — it must survive wherever the image is seen. */
.concept__tag {
  position: absolute;
  top: .75rem;
  inset-inline-start: .75rem;
  z-index: 2;
  padding: .35rem .6rem;
  background: rgba(8, 15, 12, .7);
  border-radius: var(--radius);
  color: var(--gold-soft);
  font-family: var(--sans);
  font-size: .6rem;
  letter-spacing: .12em;
  text-transform: uppercase;
}

.concept__more {
  position: absolute;
  bottom: .75rem;
  inset-inline-end: .75rem;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  padding: .5rem .8rem;
  background: rgba(8, 15, 12, .72);
  border: 1px solid rgba(247, 243, 234, .2);
  border-radius: var(--radius);
  color: var(--cream);
  font-size: .68rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  transition: background .35s var(--ease);
}
.concept__media--btn:hover .concept__more,
.concept__media--btn:focus-visible .concept__more { background: rgba(8, 15, 12, .9); }
.concept__more-icon { display: inline-flex; width: 15px; }
.concept__more-icon svg { width: 100%; height: auto; }

.concept__gallerycta {
  display: inline-flex;
  align-items: baseline;
  gap: .6rem;
  margin-top: 1.75rem;
  padding: .8rem 1.4rem;
  border: 1px solid rgba(178, 138, 76, .5);
  border-radius: var(--radius);
  color: var(--gold);
  font-size: .72rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  transition: background .35s var(--ease), border-color .35s var(--ease);
}
.concept__gallerycta:hover,
.concept__gallerycta:focus-visible {
  background: rgba(178, 138, 76, .1);
  border-color: var(--gold);
}
.concept__gallerycta-count { color: var(--ink-faint); letter-spacing: .1em; }

/* --- Gallery thumbnail strip ---
   The rest of the set, visible on the page instead of hidden behind a badge.
   Each thumbnail opens the lightbox at its own image. A 2x2 block beside the
   text on desktop; a four-across strip under it on narrow screens. */
/* Six 1:1 squares crammed four-across came out around 70px each on a
   phone — too small to tell a pool from a tennis court. On mobile they
   are now a horizontally scrolled strip of large 4:3 frames, one and a
   bit in view at a time, which reads at a glance and invites the swipe;
   on desktop they stay a grid, two across but much taller. */
.thumbs {
  display: flex;
  gap: .6rem;
  margin: 0;
  padding: 0 0 .5rem;
  list-style: none;
  overflow-x: auto;
  overscroll-behavior-inline: contain;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
}
.thumbs > li {
  flex: 0 0 72%;
  scroll-snap-align: start;
}
@media (min-width: 560px) { .thumbs > li { flex-basis: 44%; } }
@media (min-width: 900px) {
  .thumbs {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: .75rem;
    padding: 0;
    overflow: visible;
  }
  .thumbs > li { flex: none; }
}

.thumb {
  display: block;
  width: 100%;
  padding: 0;
  overflow: hidden;
  border: 1px solid rgba(178, 138, 76, .3);
  border-radius: var(--radius);
  background: var(--cream-300);
  cursor: zoom-in;
}
.thumb img {
  display: block;
  width: 100%;
  /* 4:3, not 1:1 — these are landscape renders, and a square crop was
     cutting the lodge and the court in half. */
  aspect-ratio: 4 / 3;
  object-fit: cover;
  transition: transform .8s var(--ease), opacity .4s var(--ease);
}
.thumb:hover img,
.thumb:focus-visible img { transform: scale(1.06); opacity: .9; }
.thumb:hover,
.thumb:focus-visible { border-color: var(--gold); }


/* 10b — CONCEPT OVERVIEW ("by the numbers") ===============================
   Speculative figures for the flagship concept. Visually a *panel*, not part
   of the page's factual furniture: its own bordered ground, a warning strip
   across the top and a disclaimer block at the bottom. Nothing here shares
   styling with .stats in the About section, which carries confirmed facts —
   the two must never be mistaken for one another.
   ========================================================================= */
/* No margin and no border of its own: .flagship supplies the frame, and a
   single rule separates the figures from the card above. This is what makes
   the two read as one continuous block — do not reintroduce a gap here. */
.numbers { border-top: 1px solid rgba(178, 138, 76, .35); }

/* The warning strip is the first thing read, and it is not dismissible */
.numbers__flag {
  display: flex;
  align-items: flex-start;
  gap: .75rem;
  padding: 1rem var(--flagship-pad);
  background: var(--wood-900);
  color: var(--cream);
}
.numbers__flag p {
  margin: 0;
  font-size: .82rem;
  line-height: 1.5;
  letter-spacing: .01em;
}
.numbers__flag-icon { display: block; width: 20px; flex: none; margin-top: .1rem; color: var(--gold-soft); }
.numbers__flag-icon svg { width: 100%; height: auto; }

.numbers__head { padding: 2rem var(--flagship-pad) 0; }

.numbers__title {
  margin: .5rem 0 .75rem;
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(1.4rem, 3.5vw, 2rem);
  line-height: 1.2;
  color: var(--forest-900);
}
.numbers__intro {
  margin: 0;
  max-width: 62ch;
  font-size: .92rem;
  line-height: 1.7;
  color: var(--ink-soft);
  text-wrap: pretty;
}

.numbers__block { padding: 2rem var(--flagship-pad) 0; }

.numbers__blocktitle {
  margin: 0 0 1.25rem;
  font-family: var(--sans);
  font-size: .7rem;
  font-weight: 500;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--gold);
}

.numbers__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 1px;
  margin: 0;
  padding: 0;
  list-style: none;
  background: rgba(178, 138, 76, .3);
  border: 1px solid rgba(178, 138, 76, .3);
  border-radius: var(--radius);
  overflow: hidden;
}
@media (min-width: 620px) {
  .numbers__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.nstat {
  display: flex;
  flex-direction: column;
  gap: .35rem;
  padding: var(--cell-pad-y) var(--cell-pad-x);
  background: var(--cream);
}
@media (min-width: 620px) { .nstat--wide { grid-column: 1 / -1; } }

.nstat__label {
  font-size: var(--cell-label);
  letter-spacing: var(--cell-label-track);
  text-transform: uppercase;
  color: var(--ink-faint);
}
.nstat__value {
  font-family: var(--serif);
  font-size: var(--cell-value);
  line-height: 1.15;
  color: var(--forest-900);
}
.nstat__note {
  font-size: var(--cell-note);
  line-height: 1.6;
  color: var(--ink-soft);
  text-wrap: pretty;
}

/* --- Itemised construction cost ------------------------------------------
   The cost block carries two caveats that must stay visually distinct, since
   they make different claims. .numbers__sketch sits ABOVE the table and flags
   the source (nobody qualified priced this); .numbers__caveat sits BELOW and
   flags the reliability. The sketch line is given a rule and a warmer ground
   so it reads as a stamp on the table rather than as more body copy. */
.numbers__sketch {
  margin: 0 0 1.25rem;
  max-width: 72ch;
  padding: .85rem 1rem;
  border-inline-start: 3px solid var(--gold);
  background: var(--cream-200);
  border-radius: var(--radius);
  font-size: .82rem;
  line-height: 1.65;
  color: var(--wood-900);
  text-wrap: pretty;
}

/* Safety net only — the table is built to fit without it (see below) */
.costtable__wrap { overflow-x: auto; }

.costtable {
  width: 100%;
  border-collapse: collapse;
  border: 1px solid rgba(178, 138, 76, .3);
  border-radius: var(--radius);
  background: var(--cream);
}

.costtable th,
.costtable td {
  padding: .7rem var(--cell-pad-x);
  text-align: start;                /* mirrors on its own in RTL */
  vertical-align: baseline;
  border-bottom: 1px solid rgba(178, 138, 76, .22);
}

/* Labels wrap; only the figures are held on one line. That pairing is what
   keeps the table inside a 320px viewport without a horizontal scrollbar. */
.costtable tbody th {
  font-weight: 400;
  font-size: .86rem;
  line-height: 1.5;
  color: var(--ink-soft);
}
.costtable tbody td {
  text-align: end;
  white-space: nowrap;
  font-family: var(--serif);
  font-size: 1.05rem;
  color: var(--forest-900);
}

/* The un-costed tennis row: a sentence, so it must wrap and must not be
   dressed as a figure, or it reads as a number that happens to be missing. */
.costtable__row--note td {
  white-space: normal;
  font-family: var(--sans);
  font-size: .78rem;
  font-style: italic;
  line-height: 1.55;
  color: var(--ink-faint);
}

.costtable tfoot th,
.costtable tfoot td {
  border-bottom: 0;
  border-top: 2px solid var(--gold);
  background: var(--cream-200);
}
.costtable tfoot th {
  font-size: var(--cell-label);
  font-weight: 400;
  letter-spacing: var(--cell-label-track);
  text-transform: uppercase;
  color: var(--wood-900);
}
.costtable tfoot td {
  text-align: end;
  white-space: nowrap;
  font-family: var(--serif);
  font-size: clamp(1.15rem, 3vw, 1.5rem);
  color: var(--forest-900);
}

/* Narrow screens: the row is too wide to hold label and figure side by side,
   and side-scrolling a price list is a bad way to read one. Below 560px each
   row becomes a stacked block — label, then figure underneath — so the whole
   table reads top to bottom with nothing cropped and nothing to swipe. The
   figures also lose their nowrap here, since they now own the full width. */
@media (max-width: 560px) {
  .costtable__wrap { overflow-x: visible; }

  .costtable,
  .costtable tbody,
  .costtable tfoot,
  .costtable tr,
  .costtable th,
  .costtable td {
    display: block;
    width: 100%;
  }

  /* The row carries the padding and the rule now that the cells are blocks. */
  .costtable tr {
    padding: .8rem var(--cell-pad-x);
    border-bottom: 1px solid rgba(178, 138, 76, .22);
  }
  .costtable tr:last-child { border-bottom: 0; }

  .costtable th,
  .costtable td {
    padding: 0;
    border-bottom: 0;
  }

  .costtable tbody td {
    margin-top: .2rem;
    text-align: start;
    white-space: normal;
  }

  .costtable tfoot tr {
    border-top: 2px solid var(--gold);
    background: var(--cream-200);
  }
  .costtable tfoot th,
  .costtable tfoot td {
    border-top: 0;
    background: none;
  }
  .costtable tfoot td {
    margin-top: .25rem;
    text-align: start;
    white-space: normal;
  }
}

/* Land reference. Deliberately a pointer at the Asking Price, not a second
   figure in the table — the two must never be summed into a package price. */
.numbers__landref {
  margin: 1rem 0 0;
  max-width: 78ch;
  font-size: .82rem;
  line-height: 1.7;
  color: var(--ink-soft);
  text-wrap: pretty;
}
.numbers__landref a {
  color: var(--wood-700);
  border-bottom: 1px solid rgba(124, 119, 108, .5);
}
.numbers__landref a:hover,
.numbers__landref a:focus-visible { color: var(--gold); border-color: var(--gold); }

/* Per-block caveat, sitting immediately under the figures it qualifies */
.numbers__caveat {
  margin: 1rem 0 0;
  max-width: 78ch;
  font-size: .8rem;
  line-height: 1.7;
  color: var(--ink-soft);
  text-wrap: pretty;
}

.numbers__disclaimer {
  margin-top: 2.5rem;
  padding: 2rem var(--flagship-pad);
  border-top: 2px solid var(--gold);
  background: var(--cream-300);
}

.numbers__disclaimer h5 {
  margin: 0 0 .75rem;
  font-family: var(--sans);
  font-size: .7rem;
  font-weight: 500;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--wood-900);
}
.numbers__disclaimer p {
  margin: 0;
  max-width: 82ch;
  font-size: .88rem;
  line-height: 1.75;
  color: var(--ink);
  text-wrap: pretty;
}


/* 11 — LIGHTBOX ===========================================================
   The standalone Gallery section is gone; its tile grid went with it. The
   lightbox itself stays — it is shared by the resort concept gallery and the
   real-imagery set in the Location section.
   ========================================================================= */
/* --- Lightbox --- */
.lightbox {
  position: fixed;
  inset: 0;
  /* Above everything, with room to spare. It was 300, which the map UI
     (1001, over Leaflet's own controls) quietly began painting through
     once the Leaflet map replaced the old iframe. The lightbox is the
     topmost surface on this page; nothing else may outrank it. */
  z-index: 2000;
  display: grid;
  place-items: center;
  /* Tight on a phone: 1.5rem all round left the image barely wider than
     the gap between the two arrows sitting on top of it. */
  padding: 3.5rem .5rem 1rem;
  background: rgba(10, 14, 11, .95);
  opacity: 0;
  transition: opacity .3s var(--ease);
}
@media (min-width: 768px) { .lightbox { padding: 1.5rem; } }
.lightbox.is-open { opacity: 1; }
.lightbox[hidden] { display: none; }

.lightbox__fig { margin: 0; max-width: min(1100px, 100%); }

/* The stage clips the image while it is zoomed, so a magnified render is
   panned inside a fixed frame instead of spilling over the whole viewport. */
.lightbox__stage {
  overflow: hidden;
  border-radius: var(--radius);
  line-height: 0;
}
.lightbox__stage img {
  display: block;
  width: 100%;
  /* Leave room for the caption and the close button rather than letting a
     tall render push the caption off the bottom of a phone screen. */
  max-height: 62svh;
  object-fit: contain;
  transform-origin: 50% 50%;
  will-change: transform;
  user-select: none;
  -webkit-user-drag: none;
}
@media (min-width: 768px) { .lightbox__stage img { max-height: 78svh; } }

/* While a swipe is in progress the image follows the finger; the inline
   transform is set in JS, so all this does is keep it from fighting a
   transition. */
.lightbox__stage.is-swiping img { transition: none; }

/* Only zoomable sets get the affordance — and the browser must hand us the
   touch events rather than pinch-zooming the page itself. */
.lightbox__stage.is-zoomable { cursor: zoom-in; touch-action: none; }
.lightbox__stage.is-zoomable.is-zoomed { cursor: zoom-out; }

.lightbox__fig figcaption {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: baseline;
  gap: .25rem .75rem;
  margin-top: 1rem;
  text-align: center;
  font-size: .82rem;
  color: rgba(247, 243, 234, .65);
}
.lightbox__count {
  font-size: .72rem;
  letter-spacing: .1em;
  color: rgba(247, 243, 234, .4);
}

/* The controls sit over the image, which is itself interactive (tap to
   zoom, drag to swipe). They need to win that overlap explicitly rather
   than by source order, and they need a ground of their own — a pale
   glyph over a bright render is invisible exactly when it is needed. */
.lightbox__close,
.lightbox__nav {
  position: absolute;
  z-index: 3;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: rgba(10, 14, 11, .55);
  backdrop-filter: blur(4px);
  color: rgba(247, 243, 234, .85);
  transition: background-color .25s var(--ease), color .25s var(--ease);
}
.lightbox__close:hover, .lightbox__close:focus-visible,
.lightbox__nav:hover,   .lightbox__nav:focus-visible {
  background: rgba(10, 14, 11, .8);
  color: var(--cream);
}

.lightbox__close {
  top: .6rem; inset-inline-end: .6rem;
  width: 44px; height: 44px;
  font-size: 1.75rem; line-height: 1;
}

/* 48px is over the 44px floor, and the hit area is padded out to 56px on
   a phone where the thumb is less precise and the arrow sits on the
   image rather than beside it. */
.lightbox__nav {
  top: 50%;
  transform: translateY(-50%);
  width: 56px; height: 56px;
  font-size: 2.2rem; line-height: 1;
}
.lightbox__nav[hidden] { display: none; }
.lightbox__nav--prev { inset-inline-start: .5rem; }
.lightbox__nav--next { inset-inline-end: .5rem; }
@media (min-width: 768px) {
  .lightbox__nav { width: 48px; height: 48px; }
  .lightbox__nav--prev { inset-inline-start: 2rem; }
  .lightbox__nav--next { inset-inline-end: 2rem; }
}


/* 11b — SAFETY & MINE CLEARANCE ===========================================
   Deliberately understated: one calm paragraph in a bordered block, no red,
   no warning iconography. It reassures; it must not alarm.
   ========================================================================= */
.section--tight { padding-block: calc(var(--section-y) * .55); }

.safety {
  display: grid;
  gap: 1.25rem;
  max-width: 68ch;
  margin-inline: auto;
  padding: 2rem;
  background: rgba(63, 90, 69, .06);
  border: 1px solid var(--cream-300);
  border-radius: var(--radius);
}
@media (min-width: 700px) {
  .safety {
    grid-template-columns: auto minmax(0, 1fr);
    gap: 1.75rem;
    padding: 2.5rem 2.75rem;
  }
}

.safety__icon { width: 28px; color: var(--moss); }
.safety__icon svg { width: 100%; height: auto; }

.safety__text .eyebrow { margin-bottom: .75rem; }
.safety__text p {
  margin: 0;
  color: var(--ink-soft);
  text-wrap: pretty;
}
.safety__note {
  margin-top: 1rem !important;
  padding-top: 1rem;
  border-top: 1px solid var(--cream-300);
  font-size: .84rem;
  color: var(--ink-faint) !important;
}


/* 12 — WHY / REASONS ====================================================== */
.reasons {
  display: grid;
  gap: 2.5rem;
}
/* Two columns, not three. The redundancy pass cut this grid from seven cards
   to four, and 4-across-3 leaves a single orphan on the second row. Two gives
   a clean 2×2 and lets each of the four remaining arguments run longer. */
@media (min-width: 700px)  { .reasons { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 3rem 2.5rem; } }
@media (min-width: 1000px) { .reasons { gap: 3.5rem 4rem; } }

.reason { padding-top: 1.75rem; border-top: 1px solid var(--cream-300); }
.reason__icon { display: block; width: 26px; margin-bottom: 1.25rem; color: var(--gold); }
.reason__icon svg { width: 100%; height: auto; }
.reason h3 {
  margin: 0 0 .6rem;
  font-family: var(--serif);
  font-weight: 500;
  font-size: 1.3rem;
  color: var(--forest-900);
}
.reason p { margin: 0; font-size: .95rem; color: var(--ink-soft); text-wrap: pretty; }


/* 13 — CONTACT + FORM ===================================================== */
.contact { display: grid; gap: 3.5rem; }
@media (min-width: 900px) {
  .contact { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 5rem; align-items: start; }
}

.contact__details { margin-top: 3rem; }
.contact__details h3 {
  margin: 0 0 1.25rem;
  font-size: .72rem;
  font-weight: 400;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--gold-soft);
}
.contact__details ul { list-style: none; margin: 0; padding: 0; }
.contact__details li {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: .8rem 0;
  border-bottom: 1px solid rgba(247, 243, 234, .12);
  font-size: .95rem;
}
.contact__details li > span {
  color: rgba(247, 243, 234, .55);
  font-size: .8rem;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.contact__details a,
.contact__details em {
  min-width: 0;
  overflow-wrap: break-word;
  color: var(--cream);
  font-style: normal;
  text-align: end;
  border-bottom: 1px solid transparent;
  transition: border-color .3s var(--ease);
}
.contact__details a:hover,
.contact__details a:focus-visible { border-bottom-color: var(--gold-soft); }

/* Phone row: number with a small qualifier underneath ("Canadian number —
   call, text or WhatsApp"). align-items:flex-end follows the text direction,
   so this right-aligns in LTR and left-aligns in Arabic without extra rules. */
/* Selector must out-specify `.contact__details li > span` (0,1,2), which
   otherwise imposes the uppercase label styling on this wrapper. */
.contact__details li > span.contact__stack {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  min-width: 0;
  font-size: inherit;
  letter-spacing: normal;
  text-transform: none;
  color: inherit;
}
/* Phone numbers, emails and URLs are inherently left-to-right. Inside an
   Arabic (RTL) line the bidi algorithm keeps each digit group internally LTR
   but reverses the ORDER of the groups, so "+1 639 571 1352" renders as
   "1352 571 639 1+" — wrong, and un-dialable. Isolating these as LTR runs
   fixes it without affecting the surrounding Arabic. */
.contact__details a[href^="tel:"],
.contact__details a[href^="mailto:"],
.contact__details a[href^="https://wa.me"] {
  direction: ltr;
  unicode-bidi: isolate;
}

.contact__hint {
  margin-top: .15rem;
  font-size: .74rem;
  line-height: 1.4;
  font-style: normal;
  color: rgba(247, 243, 234, .42) !important;
}

/* --- Form --- */
.form {
  background: rgba(247, 243, 234, .04);
  border: 1px solid rgba(247, 243, 234, .12);
  border-radius: var(--radius);
  padding: 1.75rem;
}
@media (min-width: 768px) { .form { padding: 2.5rem; } }

.field { margin-bottom: 1.35rem; }
.field label {
  display: flex;
  align-items: baseline;
  gap: .5rem;
  margin-bottom: .5rem;
  font-size: .72rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: rgba(247, 243, 234, .65);
}
.field label i {
  font-style: normal;
  text-transform: none;
  letter-spacing: .02em;
  font-size: .72rem;
  color: rgba(247, 243, 234, .35);
}

.field input,
.field textarea {
  width: 100%;
  padding: .85rem 1rem;
  background: rgba(16, 26, 21, .45);
  border: 1px solid rgba(247, 243, 234, .18);
  border-radius: var(--radius);
  color: var(--cream);
  font-family: inherit;
  font-size: .95rem;
  transition: border-color .3s var(--ease), background-color .3s var(--ease);
}
.field textarea { resize: vertical; min-height: 120px; }

.field input::placeholder,
.field textarea::placeholder { color: rgba(247, 243, 234, .3); }

.field input:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--gold);
  background: rgba(16, 26, 21, .7);
}

.field__err {
  display: none;
  margin-top: .4rem;
  font-size: .78rem;
  color: #e0a08a;
}
.field.has-error .field__err { display: block; }
.field.has-error input,
.field.has-error textarea { border-color: #c47a62; }

.form__status {
  margin: 1rem 0 0;
  min-height: 1.2em;
  font-size: .88rem;
  color: var(--gold-soft);
}
.form__privacy {
  margin: 1.25rem 0 0;
  font-size: .76rem;
  line-height: 1.6;
  color: rgba(247, 243, 234, .4);
}


/* 14 — FOOTER ============================================================= */
.footer {
  background: var(--forest-900);
  color: rgba(247, 243, 234, .6);
  padding-block: 4rem 2.5rem;
  font-size: .85rem;
}

.footer__inner { display: grid; gap: 2rem; }

.footer__brand { display: flex; align-items: flex-start; gap: .8rem; }
.footer__brand p { margin: 0; max-width: 34ch; color: rgba(247, 243, 234, .7); }

.footer__lang {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  padding-block: 1.5rem;
  border-block: 1px solid rgba(247, 243, 234, .1);
}
.footer__top {
  font-size: .72rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: rgba(247, 243, 234, .5);
  transition: color .3s var(--ease);
}
.footer__top:hover,
.footer__top:focus-visible { color: var(--cream); }

/* A confirmed fact, so it is set brighter than the disclaimer beneath it
   and carries the gold rule — it is a closing reassurance, not fine print. */
.footer__minestatus {
  margin: 0;
  max-width: 78ch;
  padding-inline-start: .8rem;
  border-inline-start: 2px solid var(--gold);
  font-size: .78rem;
  line-height: 1.6;
  color: rgba(247, 243, 234, .72);
}

.footer__disclaimer {
  margin: 0;
  max-width: 78ch;
  font-size: .74rem;
  line-height: 1.65;
  color: rgba(247, 243, 234, .35);
}
.footer__copy { margin: 0; font-size: .74rem; color: rgba(247, 243, 234, .35); }

@media (min-width: 900px) {
  .footer__inner {
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: start;
    gap: 2rem 4rem;
  }
  .footer__lang { border: 0; padding: 0; justify-content: flex-end; }
  .footer__minestatus,
  .footer__disclaimer,
  .footer__copy { grid-column: 1 / -1; }
  /* The rule that used to open the disclaimer now opens the clearance line,
     since that is the first full-width row in the footer. */
  .footer__minestatus { padding-top: 1.5rem; border-top: 1px solid rgba(247, 243, 234, .1); }
}


/* 15 — REVEAL ANIMATIONS ==================================================
   Elements marked .reveal start slightly low and faded; main.js adds
   .is-visible via IntersectionObserver. Children of .reveal-group are
   staggered with an inline --d delay set in JS.
   ========================================================================= */
.reveal {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity .9s var(--ease), transform .9s var(--ease);
  transition-delay: var(--d, 0ms);
  will-change: opacity, transform;
}
.reveal.is-visible {
  opacity: 1;
  transform: none;
}

/* Hero copy animates on load rather than on scroll */
.hero .reveal { transition-duration: 1.1s; }


/* 16 — REDUCED MOTION / PRINT ============================================= */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  .reveal { opacity: 1; transform: none; }
  .hero__media img, .hero__media video { animation: none; }
}

@media print {
  .header, .hero__scroll, .lightbox, .burger, .form { display: none !important; }
  body { background: #fff; color: #000; }
  .section, .teaser { padding-block: 1.5rem; break-inside: avoid; }
}


/* 17 — RIGHT-TO-LEFT (ARABIC) =============================================
   main.js sets dir="rtl" on <html> when Arabic is selected. Almost all of
   the mirroring is already handled, because the layout uses flexbox, grid
   and logical properties (inset-inline-*, padding-inline-*, text-align:
   start/end) rather than left/right. What remains are three things CSS
   cannot mirror on its own:

     a) FONTS — Cormorant Garamond and Inter contain no Arabic glyphs.
     b) LETTER-SPACING — Arabic script is cursive; tracking breaks the
        joins between letters and must be reset to normal.
     c) GLYPHS AND ANIMATIONS THAT POINT — chevrons and the sliding scroll
        rule are drawn pointing one way and need flipping.

   RULE OF THUMB FOR FUTURE EDITS: never add `left:` or `right:` —
   use `inset-inline-start` / `inset-inline-end`. Never add `text-align:
   left/right` — use `start` / `end`. Then this section stays this short.
   ========================================================================= */

/* (a) Arabic type stack. Overriding the two variables on the root element
       re-points every rule in the file at once. Noto Naskh Arabic carries
       the headline voice (the closest Arabic equivalent to a refined
       serif); Cairo handles body text. Loaded on demand by main.js. */
[dir="rtl"] {
  --serif: 'Noto Naskh Arabic', 'Amiri', 'Times New Roman', serif;
  --sans:  'Cairo', 'Noto Sans Arabic', 'Segoe UI', Tahoma, sans-serif;
}

[dir="rtl"] body {
  line-height: 1.85;              /* Arabic needs more room between lines */
  font-weight: 400;               /* 300 renders too thin in most Arabic faces */
}

/* Arabic numerals and headline sizes read a touch small at the same values */
[dir="rtl"] .hero__title { line-height: 1.2; }
[dir="rtl"] .h2 { line-height: 1.3; }
[dir="rtl"] .teaser__line { line-height: 1.5; }

/* (b) Kill tracking everywhere it was added for Latin display type. */
[dir="rtl"] .eyebrow,
[dir="rtl"] .btn,
[dir="rtl"] .nav a,
[dir="rtl"] .header__brandtext,
[dir="rtl"] .hero__scroll,
[dir="rtl"] .stat__label,
[dir="rtl"] .contact__details h3,
[dir="rtl"] .contact__details li > span,
[dir="rtl"] .field label,
[dir="rtl"] .form__status,
[dir="rtl"] .advisory p,
[dir="rtl"] .footnote,
[dir="rtl"] .footer__top,
[dir="rtl"] .h2,
[dir="rtl"] .h3,
[dir="rtl"] .lede,
[dir="rtl"] .prose p,
[dir="rtl"] .price__label,
[dir="rtl"] .price__value,
[dir="rtl"] .safety__text p,
[dir="rtl"] .dist__list dt,
[dir="rtl"] .dist__title,
[dir="rtl"] .mapsv__out,
[dir="rtl"] .geo__note,
[dir="rtl"] .geo__photo figcaption,
[dir="rtl"] .geo__heritage,
[dir="rtl"] .teaser__tag,
[dir="rtl"] .teaser__cta,
[dir="rtl"] .concept__tag,
[dir="rtl"] .concept__more,
[dir="rtl"] .concept__gallerycta,
[dir="rtl"] .numbers__flag p,
[dir="rtl"] .numbers__intro,
[dir="rtl"] .numbers__blocktitle,
[dir="rtl"] .nstat__label,
[dir="rtl"] .nstat__value,
[dir="rtl"] .nstat__note,
[dir="rtl"] .costtable tfoot th,
[dir="rtl"] .numbers__caveat,
[dir="rtl"] .numbers__disclaimer h5,
[dir="rtl"] .numbers__disclaimer p,
[dir="rtl"] .lightbox__count {
  letter-spacing: normal;
}

/* The language codes stay Latin, so they keep their tracking */
[dir="rtl"] .langpicker__code { letter-spacing: .12em; }

/* (c) Directional glyphs and motion */

/* Nav underline grows from the inline start, which is the right in RTL */
[dir="rtl"] .nav a::after { transform-origin: right; }

/* ‹ and › are drawn pointing a fixed way; the buttons themselves have
   already swapped sides via inset-inline-*, so mirror the glyphs to match. */
[dir="rtl"] .lightbox__nav { transform: translateY(-50%) scaleX(-1); }

/* The hero's sliding rule should travel toward the inline end */
[dir="rtl"] .hero__scroll i { transform: scaleX(-1); }

/* Menus align to the inline end already; the dropdown shadow and the
   advisory close button follow suit through margin-inline-start: auto. */

/* Concept rows alternate by grid order, which is direction-aware, so the
   lookbook mirrors on its own — nothing to do here. */

/* Leaflet positions its own controls with literal left/right and does not
   mirror. Our layer switch and legend use inset-inline-* and mirror by
   themselves; these three do not, so they are swapped by hand. The map canvas
   itself needs no mirroring — a map is not a text flow, and flipping it would
   put north-east in the wrong corner. */
[dir="rtl"] .leaflet-left  { left: auto; right: 0; }
[dir="rtl"] .leaflet-right { right: auto; left: 0; }
[dir="rtl"] .leaflet-control-attribution { text-align: right; }

/* Uppercase tracking breaks Arabic joins, as everywhere else on the page */
[dir="rtl"] .maplayers__btn { letter-spacing: normal; }

/* The teaser needs no mirroring of its own: the chip is placed with
   inset-inline-start, the grid columns reverse with the writing direction,
   and its CTA arrow points down rather than along the inline axis, so —
   unlike .lightbox__nav — it must NOT be flipped. */
