/* SOLMARA — M1 brand system + reveal overlay
   Palette: marine ink, sand, brushed gold, horizon aqua. */

@font-face {
  font-family: 'Cormorant Garamond';
  src: url('../fonts/cormorant-400.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Cormorant Garamond';
  src: url('../fonts/cormorant-500.woff2') format('woff2');
  font-weight: 500; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Cormorant Garamond';
  src: url('../fonts/cormorant-italic-400.woff2') format('woff2');
  font-weight: 400; font-style: italic; font-display: swap;
}
@font-face {
  font-family: 'Inter';
  src: url('../fonts/inter-400.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Inter';
  src: url('../fonts/inter-600.woff2') format('woff2');
  font-weight: 600; font-style: normal; font-display: swap;
}

/* ---------- RTL faces (ar · he · yi) ----------
   Neither Cormorant nor this Inter subset carries a single Arabic or Hebrew
   glyph, so all three RTL languages would render as tofu without these.
   Amiri (a classical Naskh) and Frank Ruhl Libre (the classic Hebrew book
   serif) stand in for Cormorant's editorial voice; the Noto Sans faces carry
   UI text in place of Inter.
   Yiddish is set in the Hebrew faces — verified, not assumed: see
   fonts/verify-coverage.py, which checks every shipped codepoint (digraphs
   װ ױ ײ and the pasekh/komets/rafe diacritics included) against each cmap.
   These files are fetched only when a language that references them is
   active, because nothing points at these families until :lang() below. */
@font-face {
  font-family: 'Amiri';
  src: url('../fonts/amiri-400.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Amiri';
  src: url('../fonts/amiri-700.woff2') format('woff2');
  font-weight: 700; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Noto Sans Arabic';
  src: url('../fonts/notosansarabic-400.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Noto Sans Arabic';
  src: url('../fonts/notosansarabic-600.woff2') format('woff2');
  font-weight: 600; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Frank Ruhl Libre';
  src: url('../fonts/frankruhl-400.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Frank Ruhl Libre';
  src: url('../fonts/frankruhl-500.woff2') format('woff2');
  font-weight: 500; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Noto Sans Hebrew';
  src: url('../fonts/notosanshebrew-400.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Noto Sans Hebrew';
  src: url('../fonts/notosanshebrew-600.woff2') format('woff2');
  font-weight: 600; font-style: normal; font-display: swap;
}

:root {
  --ink: #071019;
  --deep: #0b1b28;
  --sand: #efe6d6;
  --shell: #f7f2e9;
  --gold: #d4a24e;
  --aqua: #2ea8a0;
  --coral: #e2704a;
  --serif: 'Cormorant Garamond', 'Didot', Georgia, 'Times New Roman', serif;
  --sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}

/* Swapping the two type variables re-faces the ENTIRE site per script — every
   rule already reaches its font through var(--serif) / var(--sans), so there
   is no second set of font rules to keep in sync. The Latin faces stay in each
   stack behind the RTL one: prices, unit codes and the SOLMARA wordmark are
   Latin on every page, and Amiri has no Latin worth setting them in. */
:root:lang(ar) {
  --serif: 'Amiri', 'Cormorant Garamond', Georgia, serif;
  --sans: 'Noto Sans Arabic', 'Inter', -apple-system, sans-serif;
}
:root:lang(he), :root:lang(yi) {
  --serif: 'Frank Ruhl Libre', 'Cormorant Garamond', Georgia, serif;
  --sans: 'Noto Sans Hebrew', 'Inter', -apple-system, sans-serif;
}

/* Inline foreign-script runs on an otherwise-Latin page: the picker naming
   each language in its own script, and the case study naming the languages
   Sol speaks. The :root rules above only fire when the WHOLE page is that
   language, so without this these runs fall back to Cormorant and Inter —
   which carry no Arabic or Hebrew glyph at all, and render as tofu boxes.
   `:not(:root)` keeps this off <html> so it cannot override the variables. */
[lang="ar"]:not(:root) { font-family: 'Noto Sans Arabic', var(--sans); }
[lang="he"]:not(:root), [lang="yi"]:not(:root) { font-family: 'Noto Sans Hebrew', var(--sans); }

* { box-sizing: border-box; margin: 0; }
/* Form controls do NOT inherit font-family — the UA hands them Arial. In Latin
   that was a quiet inconsistency (the filter chips were set in Arial beside
   Inter). Once the page is Arabic or Hebrew it becomes a correctness bug: the
   text falls out of the vendored face onto whatever the system happens to
   have, which for Yiddish pointing and digraphs is often nothing at all.
   Selectors that set a font explicitly still win — they are all higher
   specificity than this. */
button, input, select, textarea { font-family: inherit; }
html { scroll-behavior: auto; }
body {
  background: var(--ink);
  color: var(--sand);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.6;
  overflow-x: hidden;
}
::selection { background: var(--gold); color: var(--ink); }

#stage {
  position: fixed; inset: 0;
  width: 100%; height: 100%;
  display: block;
  z-index: 0;
  opacity: 0; transition: opacity 1.4s ease;
  background: linear-gradient(180deg, #2e3f60 0%, #c9805f 62%, #1b3d52 100%);
}
#stage.ready { opacity: 1; }
body.no3d #stage { display: none; }
body.no3d { background: linear-gradient(180deg, #101a38 0%, #0b1b28 55%, #071019 100%); }

/* ---------- top chrome ---------- */
.top {
  position: fixed; top: 0; left: 0; right: 0; z-index: 20;
  display: flex; align-items: center; gap: 14px;
  padding: 18px 22px;
  pointer-events: none;
}
.top > * { pointer-events: auto; }
.mark {
  display: flex; align-items: center; gap: 10px;
  font-family: var(--sans); font-weight: 600; font-size: 13px;
  letter-spacing: .42em; text-indent: .42em; color: var(--shell);
  text-decoration: none;
}
.mark svg { display: block; }
.badge {
  margin-inline-start: auto;
  font-size: 10px; font-weight: 600;
  letter-spacing: .18em; text-transform: uppercase;
  color: var(--gold);
  border: 1px solid rgba(212, 162, 78, .55);
  border-radius: 99px;
  padding: 6px 13px;
  background: rgba(7, 16, 25, .55);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
#lang {
  font-family: var(--sans); font-weight: 600; font-size: 11px;
  letter-spacing: .14em;
  color: var(--sand);
  background: rgba(7, 16, 25, .55);
  border: 1px solid rgba(239, 230, 214, .35);
  border-radius: 99px;
  padding: 7px 13px;
  cursor: pointer;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  transition: border-color .25s, color .25s;
}
#lang:hover { border-color: var(--gold); color: var(--gold); }

/* Language picker. `.lang-pick` is created at runtime by mountLangPicker(),
   which wraps the existing #lang button — so it inherits `.top > *`'s
   pointer-events and needs no markup change on the pages themselves. */
.lang-pick { position: relative; }
.lang-menu {
  position: absolute; top: calc(100% + 8px); inset-inline-end: 0;
  margin: 0; padding: 6px; list-style: none;
  min-width: 152px; z-index: 40;
  background: rgba(7, 16, 25, .92);
  border: 1px solid rgba(239, 230, 214, .22);
  border-radius: 12px;
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  box-shadow: 0 18px 44px rgba(3, 8, 14, .55);
}
.lang-menu[hidden] { display: none; }
.lang-menu button {
  display: block; width: 100%;
  background: none; border: none; cursor: pointer;
  font-family: var(--sans); font-size: 13.5px; line-height: 1.5;
  color: var(--sand); text-align: start;
  padding: 9px 12px; border-radius: 8px;
  transition: background .18s, color .18s;
}
.lang-menu button:hover { background: rgba(239, 230, 214, .07); color: var(--shell); }
.lang-menu button[aria-selected="true"] { color: var(--gold); }
.navlink {
  font-family: var(--sans); font-weight: 600; font-size: 11px;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--sand); text-decoration: none;
  border: 1px solid rgba(239, 230, 214, .35);
  border-radius: 99px; padding: 7px 13px;
  background: rgba(7, 16, 25, .55);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
.navlink:hover { border-color: var(--gold); color: var(--gold); }
.btn-ghost {
  display: inline-block; font-size: 11px; font-weight: 600;
  letter-spacing: .12em; text-transform: uppercase; color: var(--sand);
  background: none; font-family: var(--sans); cursor: pointer;
  border: 1px solid rgba(239, 230, 214, .35); border-radius: 2px;
  padding: 11px 18px; text-decoration: none;
}
.btn-ghost:hover { border-color: var(--gold); color: var(--gold); }
.cta-actions { display: flex; gap: 12px; align-items: center; justify-content: center; flex-wrap: wrap; margin-top: 22px; }
.cta-actions .btn { margin-top: 0; }

/* ---------- story panels ---------- */
main { position: relative; z-index: 10; }
.panel { position: relative; }
.panel .hold { position: sticky; top: 0; min-height: 100vh; display: flex; align-items: center; padding: 0 6vw; }

#s-hero    { height: 100svh; }
#s-arrival { height: 150vh; }
#s-tower   { height: 190vh; }
#s-days    { height: 215vh; }
#s-night   { height: 150vh; }
#s-cta     { height: 115vh; }

.kicker {
  font-size: 11px; font-weight: 600;
  letter-spacing: .32em; text-transform: uppercase;
  color: var(--gold);
  margin-bottom: 14px;
}

/* hero */
#s-hero .hold { justify-content: center; text-align: center; }
.hero-inner { transform: translateY(-2vh); }
.wordmark {
  font-family: var(--serif); font-weight: 400;
  font-size: clamp(50px, 10vw, 122px);
  letter-spacing: .3em; text-indent: .3em;
  line-height: 1.04;
  color: var(--shell);
  text-shadow: 0 2px 40px rgba(7, 16, 25, .55);
}
.wordmark span {
  display: block;
  font-family: var(--sans); font-weight: 600;
  font-size: clamp(11px, 1.35vw, 15px);
  letter-spacing: .78em; text-indent: .78em;
  color: var(--gold);
  margin-top: 14px;
}
.hero-line {
  font-family: var(--serif); font-style: italic;
  font-size: clamp(20px, 2.6vw, 30px);
  color: var(--sand);
  margin-top: 26px;
}
.hero-sub { font-size: clamp(13px, 1.5vw, 16px); color: rgba(239, 230, 214, .78); margin-top: 8px; }
.cue {
  position: absolute; bottom: 4.5vh; left: 50%; transform: translateX(-50%);
  font-size: 11px; letter-spacing: .22em; text-transform: uppercase;
  color: rgba(239, 230, 214, .6);
  animation: cue-b 2.6s ease-in-out infinite;
}
@keyframes cue-b { 0%,100% { transform: translate(-50%, 0); opacity: .6; } 50% { transform: translate(-50%, 7px); opacity: 1; } }

/* While the tour drives the page, drop backdrop-filter. Re-compositing six
   blurred glass panels over a live WebGL canvas every frame was costing more
   main-thread time than the whole 3D scene (Lighthouse TBT 160ms -> 470ms).
   The blur is imperceptible against a moving backdrop anyway, so the cards
   just carry a slightly more opaque fill for the duration. */
body.touring .card,
body.touring .day,
body.touring .badge,
body.touring #lang,
body.touring .navlink {
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
body.touring .card, body.touring .day { background: rgba(7, 16, 25, .74); }
body.touring .badge, body.touring #lang, body.touring .navlink { background: rgba(7, 16, 25, .8); }

/* tour chip — hands-free auto-scroll (sits just above the scroll cue) */
.tour-chip {
  position: absolute; bottom: 10.5vh; left: 50%; transform: translateX(-50%);
  display: inline-flex; align-items: center; gap: 9px;
  font-family: var(--sans); font-weight: 600; font-size: 10.5px;
  letter-spacing: .2em; text-transform: uppercase;
  color: rgba(239, 230, 214, .85);
  background: rgba(7, 16, 25, .45);
  border: 1px solid rgba(239, 230, 214, .28);
  border-radius: 99px; padding: 9px 17px;
  cursor: pointer;
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  transition: border-color .25s, color .25s, opacity .25s;
}
.tour-chip:hover { border-color: var(--gold); color: var(--gold); }
.tour-chip svg { width: 10px; height: 10px; fill: currentColor; display: block; }
.tour-chip .tc-pause { display: none; }
.tour-chip.on .tc-play { display: none; }
.tour-chip.on .tc-pause { display: block; }
.tour-chip.on { opacity: .55; }
body.clean-cue .tour-chip { display: none; }
@media (prefers-reduced-motion: reduce) { .tour-chip { display: none; } }

/* narrative cards */
.card {
  max-width: 460px;
  padding: 34px 36px;
  background: rgba(7, 16, 25, .5);
  border: 1px solid rgba(239, 230, 214, .12);
  border-radius: 4px;
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  box-shadow: 0 30px 80px rgba(3, 8, 14, .35);
}
.side.right .hold { justify-content: flex-end; }
.card h2 {
  font-family: var(--serif); font-weight: 500;
  font-size: clamp(26px, 3.4vw, 40px);
  line-height: 1.18;
  color: var(--shell);
  margin-bottom: 14px;
}
.card p { color: rgba(239, 230, 214, .82); font-size: 15px; }

.stats {
  display: grid; grid-template-columns: repeat(4, auto);
  gap: 8px 26px;
  margin-top: 26px; padding-top: 22px;
  border-top: 1px solid rgba(212, 162, 78, .35);
}
.stat b {
  display: block;
  font-family: var(--serif); font-weight: 500;
  font-size: 30px; color: var(--gold); line-height: 1;
}
.stat i {
  font-style: normal; font-size: 10px; letter-spacing: .08em;
  text-transform: uppercase; color: rgba(239, 230, 214, .6);
}

/* days */
#s-days .hold { align-items: center; }
.days-wrap { width: 100%; max-width: 1020px; margin: 0 auto; }
.days-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; margin-top: 10px; }
.day {
  padding: 26px 24px 30px;
  background: rgba(7, 16, 25, .5);
  border: 1px solid rgba(239, 230, 214, .12);
  border-radius: 4px;
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}
.day .num { font-family: var(--serif); font-size: 15px; color: var(--aqua); letter-spacing: .2em; }
.day h3 { font-family: var(--serif); font-weight: 500; font-size: 26px; color: var(--shell); margin: 10px 0 8px; }
.day p { font-size: 14px; color: rgba(239, 230, 214, .78); }

/* centered panels */
.center .hold { justify-content: center; text-align: center; }
.center .card { max-width: 560px; background: rgba(7, 16, 25, .42); }

/* CTA */
.btn {
  display: inline-block;
  margin-top: 22px;
  font-family: var(--sans); font-weight: 600; font-size: 13px;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--ink);
  background: linear-gradient(120deg, #e3b566, var(--gold));
  padding: 15px 34px;
  border-radius: 2px;
  text-decoration: none;
  transition: transform .25s, box-shadow .25s;
  box-shadow: 0 12px 34px rgba(212, 162, 78, .25);
}
.btn:hover { transform: translateY(-2px); box-shadow: 0 18px 44px rgba(212, 162, 78, .35); }

/* capture helpers: ?clean strips all chrome for frame grabs; ?cine hides the cue */
body.clean .top, body.clean main { display: none; }
body.clean-cue .cue { display: none; }

/* reveal animation */
.reveal { opacity: 0; transform: translateY(34px); transition: opacity .9s ease, transform .9s ease; }
.reveal.in { opacity: 1; transform: none; }
/* hero copy is the LCP — never hold it at opacity 0; drift it in on transform only */
#s-hero .reveal { opacity: 1; transform: none; animation: hero-in 1.3s cubic-bezier(.2,.6,.2,1) both; }
@keyframes hero-in { from { transform: translateY(26px); } to { transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .reveal { transition: none; transform: none; opacity: 1; }
  .cue { animation: none; }
}

/* ---------- location map ---------- */
#s-map { height: 130vh; }
.map-wrap {
  display: grid; grid-template-columns: 0.9fr 1.15fr; gap: 26px;
  width: 100%; max-width: 1040px; margin: 0 auto; align-items: center;
}
.map-copy h2 {
  font-family: var(--serif); font-weight: 500;
  font-size: clamp(26px, 3.4vw, 40px); line-height: 1.18;
  color: var(--shell); margin-bottom: 12px;
}
.map-copy > p { color: rgba(239, 230, 214, .8); font-size: 15px; max-width: 380px; }
.map-facts { list-style: none; padding: 0; display: flex; gap: 26px; margin: 22px 0 0; }
.map-facts b { display: block; font-family: var(--serif); font-weight: 500; font-size: 30px; color: var(--gold); line-height: 1; }
.map-facts span { font-size: 10px; letter-spacing: .08em; text-transform: uppercase; color: rgba(239, 230, 214, .6); }
.map-note { margin-top: 20px; font-size: 12px; font-style: italic; color: rgba(239, 230, 214, .5); }
#map {
  height: 430px; border-radius: 6px;
  border: 1px solid rgba(212, 162, 78, .4);
  box-shadow: 0 30px 80px rgba(3, 8, 14, .45);
  /* light placeholder: the tiles are CARTO light_all now, so a dark box
     flashed inverted before they loaded */
  background: #e9edf0;
}
.sol-pin {
  display: flex; align-items: center; justify-content: center;
  background: rgba(7, 16, 25, .9); border: 2px solid var(--gold); border-radius: 50%;
  box-shadow: 0 0 0 6px rgba(212, 162, 78, .18), 0 10px 26px rgba(3, 8, 14, .6);
}
.leaflet-popup-content-wrapper { background: #0d1520; color: var(--sand); border: 1px solid rgba(212,162,78,.5); border-radius: 10px; }
.leaflet-popup-content { font-family: var(--sans); font-size: 12.5px; line-height: 1.5; }
.leaflet-popup-tip { background: #0d1520; }
@media (max-width: 820px) {
  .map-wrap { grid-template-columns: 1fr; gap: 16px; }
  #map { height: 320px; }
  #s-map { height: auto; padding: 60px 0; }
  #s-map .hold { min-height: 0; position: static; }
}

/* ---------- developer panel (the real pitch) ---------- */
.dev {
  position: relative; z-index: 10;
  background: var(--sand);
  color: var(--ink);
  padding: 96px 6vw 80px;
}
.dev-inner { max-width: 860px; margin: 0 auto; }
.dev .kicker { color: #7a5518; }
.dev h2 {
  font-family: var(--serif); font-weight: 500;
  font-size: clamp(30px, 4.4vw, 52px);
  line-height: 1.14; color: var(--ink);
  max-width: 700px;
}
.dev p { margin-top: 18px; max-width: 640px; font-size: 16px; color: #2c3540; }
.dev-actions { display: flex; flex-wrap: wrap; gap: 16px; align-items: center; margin-top: 30px; }
.btn2 {
  display: inline-block;
  font-weight: 600; font-size: 13px;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--sand);
  background: var(--ink);
  padding: 15px 30px;
  border-radius: 2px;
  text-decoration: none;
  transition: transform .25s;
}
.btn2:hover { transform: translateY(-2px); }
.mail { font-size: 14px; color: #2c3540; text-decoration: underline; text-underline-offset: 3px; }
.rl { font-weight: 600; letter-spacing: .3em; font-size: 11px; color: #7a5518; margin-top: 54px; }

footer.colophon {
  position: relative; z-index: 10;
  background: var(--ink);
  color: rgba(239, 230, 214, .55);
  font-size: 11.5px;
  text-align: center;
  padding: 26px 8vw 34px;
}

/* ---------- responsive ---------- */
@media (max-width: 820px) {
  .top { padding: 14px 14px; }
  .badge { font-size: 8.5px; padding: 5px 9px; letter-spacing: .12em; }
  .mark { letter-spacing: .3em; text-indent: .3em; font-size: 11px; }
  .panel .hold { padding: 0 18px; }
  .side.right .hold, .side.left .hold { justify-content: center; }
  .card { padding: 26px 22px; max-width: 100%; }
  .stats { grid-template-columns: repeat(2, 1fr); }
  .days-grid { grid-template-columns: 1fr; gap: 12px; }
  #s-days { height: 240vh; }
  .day { padding: 20px 18px 22px; }
}

/* Phone widths. The header ran off the screen in EVERY language — 440px of
   children in English, 454 in Spanish, 334 in Arabic, against 331px of usable
   width — so the last item in the row sat off-screen entirely. Pre-existing
   and mirrored rather than caused by RTL (LTR spilled right, RTL spills left),
   but the last item is now the LANGUAGE PICKER, and a picker you cannot reach
   on a phone is a bad bug on a site whose point is that it speaks five
   languages. Letting the row wrap fixes every language at once without
   hiding anything — and the concept badge, which is a disclosure and must
   never be removed, goes to its own line where it reads as one clean line
   instead of wrapping into a 66-80px tall pill. */
@media (max-width: 560px) {
  .top { flex-wrap: wrap; row-gap: 8px; }
  .badge {
    order: 9; flex-basis: 100%;
    margin-inline-start: 0; text-align: center;
  }
}

/* Footer credit link. It is a SIBLING of the [data-i18n] span, never inside
   it — i18n.js assigns textContent, which would delete a nested anchor on the
   first language switch. */
/* No `opacity` here. The colophon's own colour clears WCAG AA comfortably at
   5.23:1, but dimming the link a further 0.72 dropped it to 3.25 — under the
   4.5 required at this size — and quietly cost the reveal and portal pages the
   accessibility 100 the case study PUBLISHES. Pre-existing since the Rivlux
   link-back shipped; found by re-measuring rather than by looking. The
   underline is what marks it as a link, so the dimming was never doing that
   work anyway. */
.studio-link {
  color: inherit; text-decoration: none;
  border-bottom: 1px solid currentColor;
  white-space: nowrap; margin-inline-start: 2px;
}
.studio-link:hover, .studio-link:focus-visible { opacity: 1; color: var(--gold, #d4a24e); }

/* ---------- RTL (ar · he · yi) ----------
   Everything that mirrors is handled by logical properties in place; this
   block is only for what logical properties cannot express.

   Tracking: Arabic is a JOINING script — letter-spacing severs the cursive
   connections between letterforms, so the wide tracking that gives the Latin
   pages their editorial voice is a rendering DEFECT in Arabic, not a style
   choice. Hebrew and Yiddish do not join, but the same uppercase-tracking
   idiom has no equivalent there either. `!important` is deliberate: 52
   tracked selectors exist across three stylesheets and any new one added
   later must not silently re-break the script. The two Latin wordmarks are
   excluded — "SOLMARA" is a brand name and stays Latin in every language,
   so it keeps its tracking. `text-indent` goes with it: it exists only to
   compensate for the trailing letter-space.
   Italics go with it: neither script has an italic tradition, and no italic
   face was vendored, so `font-style: italic` would make the browser SYNTHESISE
   one by slanting — which on a joined Arabic script reads as a rendering
   fault rather than as emphasis. */
:root[dir="rtl"] :not(.mark, .mark *, .wordmark, .wordmark *) {
  letter-spacing: normal !important;
  text-indent: 0 !important;
  font-style: normal !important;
}

/* Bidi isolation. A Latin/numeric technical string dropped into an RTL
   paragraph gets REORDERED by the bidi algorithm: "$4–6M" renders as "6M–$4"
   and "4+" as "+4", because the leading/trailing symbols are directionally
   neutral and adopt the paragraph direction. These elements hold nothing but
   such strings, so they get their own LTR embedding. Where a technical string
   sits INLINE with translated prose the fix is a <bdi> in the template
   instead — CSS cannot reach part of a text node.
   `.fchip:not([data-i18n])` is exact by construction: a chip WITH the
   attribute holds translated text and must stay RTL; one without holds a
   hardcoded Latin range. Scoped to [dir="rtl"] so LTR is provably untouched. */
[dir="rtl"] :is(
  .ur-price, .ur-code, .d-psf, #d-price, #d-code,
  .fchip:not([data-i18n]),
  .po-row b, .po-row-when, .po-j > span,
  .toast b, .rv-unit b, .rv-unit i
) {
  direction: ltr;
  unicode-bidi: isolate;
}

/* The floor plan is an architectural drawing, not prose. It must never mirror
   — that would flip the apartment itself, putting the terrace on the wrong
   side of the building. Room names inside are single translated words and
   render correctly in either direction. */
[dir="rtl"] .plan-card { direction: ltr; }
