/* ============================================================
   REVALUAR - Design System
   Refined editorial bilingual site
   ============================================================ */

/* ---- Teramo (brand primary, EN) - variable + optical-size statics (WOFF2) ---- */
@font-face { font-family:'Teramo'; src:url('fonts/ROHH - Teramo Variable.woff2') format('woff2'); font-weight:100 900; font-display:swap; }

/* Display optical cut - for the largest headlines */
@font-face { font-family:'Teramo Display'; src:url('fonts/Teramo-Light.woff2') format('woff2');   font-weight:300; font-display:swap; }
@font-face { font-family:'Teramo Display'; src:url('fonts/Teramo-Book.woff2') format('woff2');    font-weight:350; font-display:swap; }
@font-face { font-family:'Teramo Display'; src:url('fonts/Teramo-Regular.woff2') format('woff2'); font-weight:400; font-display:swap; }
@font-face { font-family:'Teramo Display'; src:url('fonts/Teramo-Medium.woff2') format('woff2');  font-weight:500; font-display:swap; }
@font-face { font-family:'Teramo Display'; src:url('fonts/Teramo-Bold.woff2') format('woff2');    font-weight:700; font-display:swap; }
@font-face { font-family:'Teramo Display'; src:url('fonts/Teramo-Black.woff2') format('woff2');   font-weight:900; font-display:swap; }

/* Text optical cut - for serif body / lead paragraphs */
@font-face { font-family:'Teramo Text'; src:url('fonts/ROHH - Teramo Text Book.woff2') format('woff2');    font-weight:350; font-display:swap; }
@font-face { font-family:'Teramo Text'; src:url('fonts/ROHH - Teramo Text Regular.woff2') format('woff2'); font-weight:400; font-display:swap; }
@font-face { font-family:'Teramo Text'; src:url('fonts/ROHH - Teramo Text Medium.woff2') format('woff2');  font-weight:500; font-display:swap; }
@font-face { font-family:'Teramo Text'; src:url('fonts/ROHH - Teramo Text Bold.woff2') format('woff2');    font-weight:700; font-display:swap; }

/* ---- Thmanyah Serif Display (Arabic headings) ---- */
@font-face { font-family:'Thmanyah Display'; src:url('fonts/thmanyahserifdisplay/woff2/thmanyahserifdisplay-Light.woff2') format('woff2');   font-weight:300; font-display:swap; }
@font-face { font-family:'Thmanyah Display'; src:url('fonts/thmanyahserifdisplay/woff2/thmanyahserifdisplay-Regular.woff2') format('woff2'); font-weight:400; font-display:swap; }
@font-face { font-family:'Thmanyah Display'; src:url('fonts/thmanyahserifdisplay/woff2/thmanyahserifdisplay-Medium.woff2') format('woff2');  font-weight:500; font-display:swap; }
@font-face { font-family:'Thmanyah Display'; src:url('fonts/thmanyahserifdisplay/woff2/thmanyahserifdisplay-Bold.woff2') format('woff2');    font-weight:700; font-display:swap; }
@font-face { font-family:'Thmanyah Display'; src:url('fonts/thmanyahserifdisplay/woff2/thmanyahserifdisplay-Black.woff2') format('woff2');   font-weight:900; font-display:swap; }


/* ---- Thmanyah Sans (universal UI sans + mono role: body, nav, buttons, eyebrows, labels - EN & AR) ---- */
@font-face { font-family:'Thmanyah Sans'; src:url('fonts/thmanyahsans/woff2/thmanyahsans-Light.woff2') format('woff2');   font-weight:300; font-display:swap; }
@font-face { font-family:'Thmanyah Sans'; src:url('fonts/thmanyahsans/woff2/thmanyahsans-Regular.woff2') format('woff2'); font-weight:400; font-display:swap; }
@font-face { font-family:'Thmanyah Sans'; src:url('fonts/thmanyahsans/woff2/thmanyahsans-Medium.woff2') format('woff2');  font-weight:500 600; font-display:swap; }
@font-face { font-family:'Thmanyah Sans'; src:url('fonts/thmanyahsans/woff2/thmanyahsans-Bold.woff2') format('woff2');    font-weight:700; font-display:swap; }
@font-face { font-family:'Thmanyah Sans'; src:url('fonts/thmanyahsans/woff2/thmanyahsans-Black.woff2') format('woff2');   font-weight:900; font-display:swap; }

:root {
  /* palette */
  --ink:        #402530;   /* plum-black primary */
  --ink-soft:   #5a3f49;
  --paper:      #f4f1ea;   /* warm off-white */
  --paper-2:    #efeae0;
  --white:      #ffffff;
  --sage:       #b6beaa;
  --sage-deep:  #9aa389;
  --yellow:     #ecf163;
  --orange:     #f15d3e;
  /* deep CTA orange: 4.6:1 with white text (WCAG AA). Solid button fills with
     white text use this; decorative accents keep --orange. */
  --orange-cta: #cf4522;
  /* orange TEXT on the light surfaces (REV-101): --orange-cta is only 4.1:1 on paper,
     short of WCAG 1.4.3's 4.5:1 for small text. #a8361a = 5.80:1 on --paper,
     5.46:1 on --paper-2, 6.55:1 on white. */
  --orange-text: #a8361a;

  --line:       rgba(64, 37, 48, 0.16);
  --line-soft:  rgba(64, 37, 48, 0.08);
  --line-strong: rgba(64, 37, 48, 0.2);
  /* status green, the one status colour on the site (REV-125): 5.76:1 on --paper, 4.88:1 on
     the 12% tint (--ok-tint) the .pill-ok status pill sits on. Literal tints, not color-mix,
     because older Android browsers matter here. */
  --ok:         #2f6a33;
  --ok-tint:    #dce1d4;   /* --ok at 12% over --paper */
  --ok-line:    #c1ceba;   /* --ok at 26% over --paper */
  /* the soft drop under a screen (case studies, service pillars) */
  --shadow-media: 0 36px 70px -54px rgba(64, 37, 48, .5);

  /* type - brand fonts are self-hosted (fonts/); the rest are system fallbacks
     shown only for the brief swap window. No third-party (Google) fonts. */
  --serif:  'Teramo Display', 'Teramo', Georgia, 'Times New Roman', serif;
  --serif-text: 'Teramo Text', 'Teramo', Georgia, 'Times New Roman', serif;
  --sans:   'Thmanyah Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  --mono:   'Thmanyah Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  --arabic-display: 'Thmanyah Display', 'Segoe UI', Tahoma, 'Geeza Pro', 'Noto Sans Arabic', sans-serif;
  --arabic-sans:    'Thmanyah Sans',    'Segoe UI', Tahoma, 'Geeza Pro', 'Noto Sans Arabic', sans-serif;

  /* ---- type scale: six steps, one clamp each (REV-71 phase 1) ----
     Every section title, lead and body resolves to one of these - there are no
     per-section font sizes left in pages.css. Arabic overrides only the line
     heights (below), so one scale serves both languages.
     display-1 page and home hero H1 | display-2 section H2 | display-3 card and
     row titles | lead leads and standfirsts | body body copy | label the few
     labels that survive. */
  --fs-d1: clamp(40px, 5vw, 72px);     --lh-d1: 1.02;
  --fs-d2: clamp(30px, 3.6vw, 52px);   --lh-d2: 1.05;
  --fs-d3: clamp(22px, 2.2vw, 30px);   --lh-d3: 1.15;
  --fs-lead: clamp(18px, 1.6vw, 21px); --lh-lead: 1.5;
  --fs-body: 17px;                     --lh-body: 1.6;
  --fs-label: 12.5px;

  /* layout */
  --container: 1320px;
  --pad-x: clamp(22px, 6vw, 84px);
  --section-y: clamp(72px, 11vh, 160px);
  --radius: 18px;
  --radius-lg: 30px;
  /* 12 columns inside the container; every split is 7/5 or 5/7 and every one of
     them uses this gutter - 32px desktop, 20px on phones (REV-71 phase 1) */
  --gutter: 32px;

  --ease: cubic-bezier(0.22, 1, 0.36, 1);

  /* keyboard focus ring colour (REV-125): solid, never a tint (a 50% orange ring fails 3:1).
     Ink surfaces repaint it to paper below, since orange on ink is only ~3:1. */
  --focus: var(--orange-cta);
}
.cta-band, .footer { --focus: var(--paper); }
/* orange-cta on sage is 2.42:1; ink is 7.17:1 */
.contact-book-sec, .region-sec { --focus: var(--ink); }

@media (max-width: 640px) { :root { --gutter: 20px; } }

* { box-sizing: border-box; margin: 0; padding: 0; }

html { scroll-behavior: smooth; -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; overflow-x: hidden; }

body {
  font-family: var(--sans);
  background: var(--paper);
  color: var(--ink);
  line-height: var(--lh-body);
  font-size: var(--fs-body);
  overflow-x: hidden;
  /* clip, not hidden: with html already overflow-x:hidden, a hidden body becomes its own
     (never-scrolling) scroll container, and CSS scroll-driven animations then measure
     against that instead of the viewport. clip keeps the horizontal clipping without
     creating a scroll container. The hidden line above is the fallback where clip is
     unsupported. */
  overflow-x: clip;
}

/* Arabic / RTL */
/* Arabic body is Thmanyah SANS since REV-71 phase 1, so both languages share one
   body register. Leads (.serif-text) and the insights/privacy article bodies
   (.ins-body) joined it on 2026-10-11 (owner, slow Libyan links): Thmanyah Text was
   an ~80 KB file for those two alone, so an Arabic page no longer loads it. */
[dir="rtl"] body,
[dir="rtl"] { font-family: var(--arabic-sans); }
/* one place for the Arabic leading: the scale's line heights, not a per-section
   [dir="rtl"] rule under every heading class */
[dir="rtl"] { --lh-d1: 1.28; --lh-d2: 1.3; --lh-d3: 1.32; }
[dir="rtl"] .display,
[dir="rtl"] .serif { font-family: var(--arabic-display); font-weight: 500; }
/* No Thmanyah Display 700 anywhere (owner, 2026-10-11): the CTA band and footer
   tagline used to be the Bold moment, an extra ~82 KB file on every Arabic page. */
[dir="rtl"] .serif-text,
[dir="rtl"] .ins-body { font-family: var(--arabic-sans); }
[dir="rtl"] .mono { font-family: var(--arabic-sans); letter-spacing: 0; font-weight: 500; }

::selection { background: var(--yellow); color: var(--ink); }

a { color: inherit; text-decoration: none; }
button { font-family: inherit; cursor: pointer; border: none; background: none; }
img { display: block; max-width: 100%; }
ul { list-style: none; }

/* ---------- type helpers ---------- */
.display {
  font-family: var(--serif);
  font-weight: 500;
  line-height: 0.98;
  letter-spacing: -0.015em;
}
.serif { font-family: var(--serif); }
.serif-text { font-family: var(--serif-text); }
.mono {
  font-family: var(--mono);
  font-weight: 500;
  letter-spacing: 0.04em;
}
.eyebrow {
  /* label step (REV-71 phase 1): sentence case, no leading rule, one ration of
     eyebrows per page - the hero plus at most two more */
  font-family: var(--mono);
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: 0.08em;
  color: var(--ink);
  opacity: 0.8; /* was 0.62: ~3.2-4.0:1 on paper/sage; 0.8 clears WCAG AA everywhere */
  display: inline-flex;
  align-items: center;
  gap: 10px;
}
[dir="rtl"] .eyebrow { letter-spacing: 0; }

/* ---------- layout ---------- */
.container {
  width: 100%;
  max-width: var(--container);
  margin: 0 auto;
  padding-inline: var(--pad-x);
}
.section { padding-block: var(--section-y); }

/* ---------- buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--sans);
  font-weight: 600;
  font-size: 15px;
  letter-spacing: 0.01em;
  padding: 15px 26px;
  border-radius: 999px;
  transition: transform .4s var(--ease), background .3s var(--ease), color .3s var(--ease), box-shadow .3s var(--ease);
  will-change: transform;
  white-space: nowrap;
}

@media (max-width: 640px) {
  .btn { padding: 16px 20px; font-size: 14px; }
  .nav-mobile-cta { padding: 16px 20px; }
}
[dir="rtl"] .btn { font-family: var(--arabic-sans); }
.btn .arrow { transition: transform .4s var(--ease); display: inline-block; }
.btn:hover .arrow { transform: translateX(5px); }
[dir="rtl"] .btn:hover .arrow { transform: translateX(-5px) scaleX(-1); }
[dir="rtl"] .btn .arrow { transform: scaleX(-1); }

/* Btn magnet (components.jsx): drift toward the pointer via the `translate` property. */
@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {
  .btn.magnet {
    translate: var(--mgx, 0px) var(--mgy, 0px);
    transition: transform .4s var(--ease), background .3s var(--ease), color .3s var(--ease), box-shadow .3s var(--ease), translate .35s var(--ease);
  }
}
.btn-primary { background: var(--orange-cta); color: var(--white); }
.btn-primary:hover { transform: translateY(-2px); box-shadow: 0 14px 30px -12px rgba(207,69,34,.7); }
.btn-ink { background: var(--ink); color: var(--paper); }
.btn-ink:hover { transform: translateY(-2px); box-shadow: 0 14px 30px -14px rgba(64,37,48,.7); }
.btn-ghost { border: 1px solid var(--line); color: var(--ink); }
.btn-ghost:hover { background: var(--ink); color: var(--paper); border-color: var(--ink); }
/* pressed: after the :hover lifts so it wins at equal specificity. The magnet uses the separate
   `translate` property, so the two compose. */
.btn:active { transform: translateY(1px); transition-duration: .08s; }

.link-arrow {
  display: inline-flex; align-items: center; gap: 8px;
  white-space: nowrap;
  font-weight: 600; font-size: 14.5px;
  border-bottom: 1px solid transparent;
  padding-bottom: 2px;
  position: relative;
  transition: gap .3s var(--ease), border-color .3s var(--ease);
}
/* It is a standalone CTA in several sections ("All services", "More about us",
   the work more-link) and 14.5px of text is a 25px tall target. Grow the HIT
   area by 10px top and bottom without moving the text or the underline, which
   padding would (padding-bottom:2px is what keeps the rule against the text). */
.link-arrow::before { content: ""; position: absolute; inset: -10px 0; }
.link-arrow:hover { gap: 13px; border-color: var(--ink); }
[dir="rtl"] .link-arrow .arrow { transform: scaleX(-1); }

/* ---------- keyboard focus: one indicator for the site's controls (REV-125) ----------
   Outline, not box-shadow: a shadow would lose to the :hover glows on .btn-primary/.btn-ink.
   .field-input keeps its own underline as its indicator. A new control class joins this list;
   anything not listed falls back to the browser's own ring. */
.btn:focus-visible, .link-arrow:focus-visible, .nav-cta:focus-visible, .lang-toggle:focus-visible,
.nav-burger:focus-visible, .nav-links a:focus-visible, .nav-mobile a:focus-visible,
.nav-drop-menu a:focus-visible, .footer-col a:focus-visible, .footer-langlink:focus-visible,
.footer-alt-site:focus-visible, a.footer-regions:focus-visible, .copy-btn:focus-visible,
.pillar-hit:focus-visible, .brand-contact:focus-visible, .proof-dot:focus-visible, .proof-link:focus-visible,
a.ship-row:focus-visible, a.contact-detail-v:focus-visible, .ins-index-list a:focus-visible { outline: 2px solid var(--focus); outline-offset: 3px; }
/* The home link is 144px tall (100px below 400px) but .nav-brand-wrap clips it to the 76px bar,
   which cut an outline down to two side bars (REV-126). The ring is a box inside that band
   instead: the same calc as the wrapper's clip-path, inside its -8px side allowance. */
.nav-brand { position: relative; }
.nav-brand:focus-visible { outline: none; }
.nav-brand:focus-visible::after { content: ""; position: absolute; inset-block: calc((100% - 76px) / 2 + 6px); inset-inline: -5px; border: 2px solid var(--focus); border-radius: 6px; pointer-events: none; }
/* <details> gets overflow:hidden while toggleFaq animates it, so the ring sits inside */
.faq-q:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
/* links resting at reduced opacity would fade their own ring */
.nav-links a:focus-visible, .footer-col a:focus-visible, .footer-langlink:focus-visible,
.footer-alt-site:focus-visible, a.footer-regions:focus-visible { opacity: 1; }
.link-arrow:focus-visible { border-radius: 3px; }

/* ---------- scroll reveal ----------
   The hidden state needs html.js, which the bundle sets as it starts (app.jsx). Until the JS
   arrives, which is seconds on a slow Libyan link, the prerendered page is fully readable
   instead of blank below the hero; with JS off the class never appears at all. */
.reveal { transition: opacity .5s var(--ease), transform .5s var(--ease); }
.js .reveal {
  opacity: 0;
  transform: translateY(20px);
}
.reveal.in { opacity: 1; transform: none; }
/* Above-the-fold: painted at first render, no fade and no rise (LCP fires at
   first paint; the hero rise-in was removed 2026-09-10 at the owner's request). */
.reveal.eager { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .reveal, .js .reveal { opacity: 1; transform: none; transition: none; }
  html { scroll-behavior: auto; }
}

/* ---------- shapes motif ---------- */
.shape-bar   { background: var(--ink); border-radius: 999px 999px 0 0; }
.shape-circle{ background: var(--ink); border-radius: 50%; }
.shape-trap  { background: var(--ink); clip-path: polygon(0 100%, 18% 0, 100% 0, 100% 100%); }

/* ---------- placeholder media ---------- */
.ph {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  background:
    repeating-linear-gradient(135deg, rgba(64,37,48,.05) 0 12px, rgba(64,37,48,0) 12px 24px),
    var(--sage);
  border-radius: var(--radius);
  display: flex; align-items: flex-end;
  color: var(--ink);
}
.ph.dark {
  background:
    repeating-linear-gradient(135deg, rgba(182,190,170,.10) 0 12px, rgba(0,0,0,0) 12px 24px),
    var(--ink);
  color: var(--sage);
}
.ph .ph-tag {
  font-family: var(--mono);
  font-size: 11.5px; letter-spacing: 0.08em;
  padding: 12px 14px;
  opacity: 0.85;
  white-space: nowrap;
}


/* ---------- yellow highlight for inline title words ---------- */
/* gradient trims the top so descenders from the previous line aren't covered */
.hl-yellow {
  background: linear-gradient(to bottom, transparent 0.2em, var(--yellow) 0.2em);
  color: var(--ink);
  padding: 0 4px 0.12em;
  border-radius: 2px;
  font-style: normal;
}

/* utility */
.divider { height: 1px; background: var(--line); border: 0; }

/* ---------- media logo badge - overlaid on all images/placeholders ---------- */
.media-logo-badge {
  position: absolute;
  bottom: 18px;
  left: 22px;
  opacity: 0.72;
  pointer-events: none;
  z-index: 2;
  line-height: 0;
}
[dir="rtl"] .media-logo-badge { left: auto; right: 22px; }
.img-wrap { position: relative; overflow: hidden; isolation: isolate; }

/* ---------- brand image grade - unifies all photography into the palette ---------- */
.ph-img {
  filter: saturate(0.85) sepia(0.18) contrast(1.05) brightness(1.0);
  transition: filter .5s ease;
}
.ph-tint {
  position: absolute; inset: 0; pointer-events: none;
  background: #402531;            /* plum */
  mix-blend-mode: soft-light;
  opacity: 0.5;
}
.ph.dark .ph-tint, .img-wrap.dark .ph-tint { opacity: 0.62; }
.study:hover .ph-img { filter: saturate(0.95) sepia(0.10) contrast(1.04) brightness(1.02); }
.grid { display: grid; gap: clamp(20px, 3vw, 40px); }
.flex { display: flex; }
.muted { opacity: 0.66; }

/* page route transition: .route-fade lives in pages.css (single definition) */

/* ============================================================
   NAV
   ============================================================ */
.nav {
  position: fixed; top: 0; left: 0; right: 0; z-index: 100;
  transition: background .4s var(--ease), box-shadow .4s var(--ease), border-color .4s var(--ease);
  border-bottom: 1px solid transparent;
}
.nav.solid {
  background: rgba(244, 241, 234, 0.86);
  -webkit-backdrop-filter: saturate(140%) blur(14px);
  backdrop-filter: saturate(140%) blur(14px);
  border-bottom-color: var(--line);
}
.nav-inner {
  display: flex; align-items: center; justify-content: space-between;
  height: 76px;
}
.nav-brand { display: inline-flex; align-items: center; gap: 11px; }
.nav-brand .serif { font-size: 25px; font-weight: 500; letter-spacing: -0.01em; }
[dir="rtl"] .nav-brand .serif { font-family: var(--arabic-display); font-weight: 500; }
/* ---- wordmark scatter + "Contact us" (Nav in components.jsx) ----
   .nav-brand-wrap holds the home link (R + wordmark) and a second link, .brand-contact, laid
   over the wordmark's place. Pointer devices only: on hover the seven letters fly apart along
   fixed per-letter offsets and fade, "Contact us" slides in where they were, and it all
   reverses when the pointer leaves. The 120ms delay on opening is hover intent, so sweeping
   across the logo on the way to the nav does not fire it; closing has no delay. Keyboard focus
   opens it too (:has(:focus-visible), so a mouse click that leaves focus on the link does not
   pin it open). Touch and coarse pointers never see it. Reduced motion swaps without moving. */
/* The logo SVG is 144px tall inside a 76px bar, so its box overhangs the bar by 34px above
   and below. Clip the wrapper (not just the link: the wrapper's own box is hit-testable too)
   to the bar's height, or hovering the page just under the header would scatter the
   wordmark. The sides get 8px of slack so the focus ring is not cut. */
.nav-brand-wrap { position: relative; display: inline-flex; clip-path: inset(calc((100% - 76px) / 2) -8px); }
.brand-contact { display: none; }
@media (hover: hover) and (pointer: fine) {
  .wm-l { transform-box: fill-box; transform-origin: center; transition: transform .6s var(--ease), opacity .4s ease; transition-delay: calc(var(--i) * 20ms); }
  .nav-brand-wrap:hover .wm-l, .nav-brand-wrap:has(:focus-visible) .wm-l {
    transform: translate(calc(var(--dx) * 1px), calc(var(--dy) * 1px)) rotate(var(--r)) scale(.55);
    opacity: 0; transition-delay: calc(120ms + var(--i) * 24ms);
  }
  .brand-contact {
    position: absolute; left: 30%; right: 0; top: 53%; z-index: 1;
    display: flex; align-items: center; gap: 8px; white-space: nowrap;
    font-family: var(--serif); font-size: 22px; font-weight: 500; letter-spacing: -0.01em; color: var(--ink);
    opacity: 0; visibility: hidden; pointer-events: none;
    transform: translate(-14px, -50%);
    transition: opacity .25s ease, transform .5s var(--ease), visibility 0s .25s;
  }
  [dir="rtl"] .brand-contact { font-family: var(--arabic-display); font-weight: 500; letter-spacing: 0; }
  .brand-contact .arrow { flex: none; color: var(--orange-cta); }
  [dir="rtl"] .brand-contact .arrow { transform: scaleX(-1); }
  .nav-brand-wrap:hover .brand-contact, .nav-brand-wrap:has(:focus-visible) .brand-contact {
    opacity: 1; visibility: visible; pointer-events: auto; transform: translate(0, -50%);
    transition-delay: .2s, .2s, 0s;
  }
  .brand-contact:hover { color: var(--orange-cta); }
  .brand-contact { border-radius: 4px; }
}
@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: reduce) {
  .wm-l, .brand-contact { transition: none; }
  .nav-brand-wrap:hover .wm-l, .nav-brand-wrap:has(:focus-visible) .wm-l { transform: none; }
  .nav-brand-wrap:hover .brand-contact, .nav-brand-wrap:has(:focus-visible) .brand-contact { transform: translate(0, -50%); }
}

.nav-links { display: flex; gap: clamp(14px, 2vw, 34px); }
.nav-links a {
  position: relative; font-size: 15px; font-weight: 500; padding: 6px 2px; white-space: nowrap;
  opacity: 0.74; transition: opacity .25s var(--ease);
}
.nav-links a::after {
  content: ""; position: absolute; left: 0; bottom: -2px; height: 1.5px; width: 100%;
  background: var(--ink); transform: scaleX(0); transform-origin: left;
  transition: transform .35s var(--ease);
}
[dir="rtl"] .nav-links a::after { transform-origin: right; }
.nav-links a:hover { opacity: 1; }
.nav-links a:hover::after { transform: scaleX(1); }
.nav-links a.active { opacity: 1; }
.nav-links a.active::after { transform: scaleX(1); background: var(--orange); }

.nav-right { display: flex; align-items: center; gap: 12px; }
.lang-toggle {
  display: inline-flex; align-items: center; gap: 7px;
  font-family: var(--mono); font-size: 12.5px; font-weight: 500; letter-spacing: 0.04em;
  padding: 8px 13px; border: 1px solid var(--line); border-radius: 999px;
  color: var(--ink); transition: background .25s var(--ease), color .25s var(--ease), border-color .25s;
  min-height: 44px; display: inline-flex; align-items: center;
}
.lang-toggle .lang-glyph {
  /* --arabic-sans: this is ONE Arabic glyph on every English page, and Thmanyah Sans
     is already loaded for the body copy, so it costs no extra font file. */
  font-family: var(--arabic-sans); font-size: 15px; line-height: 1;
  width: 18px; height: 18px; display: grid; place-items: center;
  background: var(--ink); color: var(--paper); border-radius: 50%;
}
.lang-toggle:hover { border-color: var(--ink); background: var(--ink); color: var(--paper); }
.lang-toggle:hover .lang-glyph { background: var(--yellow); color: var(--ink); }

.nav-cta {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 14.5px; font-weight: 600; padding: 11px 19px; white-space: nowrap;
  background: var(--ink); color: var(--paper); border-radius: 999px;
  transition: transform .35s var(--ease), background .3s;
}
[dir="rtl"] .nav-cta { font-family: var(--arabic-sans); }
.nav-cta:hover { transform: translateY(-2px); background: var(--orange-cta); color: var(--white); }
.nav-cta .arrow { transition: transform .35s var(--ease); }
.nav-cta:hover .arrow { transform: translateX(4px); }
[dir="rtl"] .nav-cta .arrow { transform: scaleX(-1); }
[dir="rtl"] .nav-cta:hover .arrow { transform: translateX(-4px) scaleX(-1); }

/* 22x16 of bars: the padding is what makes the hit area 44x44 (WCAG 2.5.8) */
.nav-burger { display: none; flex-direction: column; gap: 5px; padding: 14px 11px; }
.nav-burger span { width: 22px; height: 2px; background: var(--ink); transition: transform .3s var(--ease), opacity .3s; }
.nav.open .nav-burger span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav.open .nav-burger span:nth-child(2) { opacity: 0; }
.nav.open .nav-burger span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

.nav-mobile {
  display: none; flex-direction: column; gap: 2px;
  /* padding lives on the OPEN state: max-height clips content but not padding,
     so a closed menu with padding paints a 34px paper band below the nav bar
     that occludes whatever scrolls under it (it hid the hero eyebrow's first
     line on phones) */
  padding: 0 var(--pad-x);
  background: var(--paper);
  border-bottom: 0 solid var(--line); /* border also paints when closed - same trap as padding */
  max-height: 0; overflow: hidden;
  /* max-height:0 + overflow:hidden hides the menu visually but keeps its six
     links in the tab order, so a keyboard or screen-reader user tabs through an
     invisible menu on every page. visibility:hidden removes them; it is
     transitioned (not instant) so the closing animation still plays. */
  visibility: hidden;
  transition: max-height .45s var(--ease), padding .45s var(--ease), visibility .45s var(--ease);
}
.nav.open .nav-mobile { max-height: calc(100vh - 76px); padding: 8px var(--pad-x) 26px; border-bottom-width: 1px; visibility: visible; }
.nav-mobile a {
  display: flex; align-items: center; justify-content: space-between;
  padding: 18px 4px; font-size: 22px; font-family: var(--serif); font-weight: 500;
  border-bottom: 1px solid var(--line-soft);
}
[dir="rtl"] .nav-mobile a { font-family: var(--arabic-display); }
[dir="rtl"] .nav-mobile a .arrow { transform: scaleX(-1); }
/* active item: 500 like the rest of the menu, so the closed (visibility:hidden, still laid
   out) menu does not pull a Bold display face (Teramo-Bold / Thmanyah Display Bold) onto
   every phone (owner, 2026-10-11). At 500 it is normal-size text, so it takes
   --orange-text (5.80:1 on paper); --orange-cta (4.1:1) passed only at 700 as large text. */
.nav-mobile a.active { color: var(--orange-text); }
/* `.nav-mobile a` (0,1,1) outranks a bare class, so the CTA needs the same
   compound selector or it inherits the serif menu font + 22px size */
.nav-mobile a.nav-mobile-cta {
  display: flex !important; align-items: center !important; justify-content: center !important;
  margin-top: 18px; font-family: var(--sans); font-size: 15px;
  padding: 15px 26px !important; white-space: normal !important;
  border-bottom: none !important;
}
[dir="rtl"] .nav-mobile a.nav-mobile-cta { font-family: var(--arabic-sans); }
[dir="rtl"] .nav-links a,
[dir="rtl"] .lang-toggle,
[dir="rtl"] .field-input,
[dir="rtl"] .footer-col-h { font-family: var(--arabic-sans); }

/* Burger below 1080px: with six links the one-row bar needs ~1040px in EN and AR (measured
   2026-10-16, REV-131). Below that, links and the CTA used to wrap onto two and three lines. */
@media (max-width: 1080px) {
  .nav-links, .nav-cta { display: none; }
  .nav-burger { display: flex; }
  .nav-mobile { display: flex; }
}
/* The wordmark is a 216x144 inline SVG with flex-shrink:0 (LongLogo sets both as
   presentation attributes), so on a 320px phone the header needs 382px and the
   burger is pushed off the right edge - the menu becomes unreachable. CSS wins
   over an SVG presentation attribute, so one rule fixes both languages. Verify at
   320px after any logo size change. */
@media (max-width: 400px) {
  .nav-brand svg { width: 150px; height: 100px; }
}

/* ============================================================
   THE R ASSEMBLES (motion signature, 2026-09-29)
   The three pieces of the mark fly in and lock, once. Add .assemble to a <Mark> or
   <ShapeCluster>; .assemble-sm shortens the travel for marks inside a column.
   The keyframes only carry a `from`, so the resting state is the finished R with no
   animation at all - reduced motion, no-JS and prerendered HTML all see the plain mark.
   Distances are in viewBox units (1000 = the full mark), scaled by --fly.
   ============================================================ */
.m-e, .m-r, .m-p { transform-box: fill-box; transform-origin: center; }
@media (prefers-reduced-motion: no-preference) {
  .assemble .m-r { transform-origin: 50% 100%; animation: fly-r 1s var(--ease) 0s both; }
  .assemble .m-p { animation: fly-p 1s var(--ease) .14s both; }
  .assemble .m-e { animation: fly-e 1.15s cubic-bezier(.34, 1.45, .64, 1) .3s both; }
}
.assemble-sm { --fly: .35; }

/* Pointer-aware cluster (useParallax in components.jsx): the three pieces lean by different
   amounts, so the cluster loosens and settles. Sized in viewBox units (the cluster is ~130px
   wide, so 130 units is ~17px). Values are 0 until the hook sets --mx/--my, so touch,
   reduced-motion and no-JS all see the static cluster. */
@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {
  .parallax .m-e { transform: translate(calc(var(--mx, 0) * 130px), calc(var(--my, 0) * 130px)); transition: transform .35s var(--ease); }
  .parallax .m-p { transform: translate(calc(var(--mx, 0) * 80px), calc(var(--my, 0) * 80px)); transition: transform .42s var(--ease); }
  .parallax .m-r { transform: translate(calc(var(--mx, 0) * -45px), calc(var(--my, 0) * -45px)); transition: transform .5s var(--ease); }
}
@keyframes fly-r { from { transform: translate(calc(-1300px * var(--fly, 1)), calc(560px * var(--fly, 1))) scaleY(.15); opacity: 0; } 45% { opacity: 1; } }
@keyframes fly-p { from { transform: translate(calc(1100px * var(--fly, 1)), calc(1300px * var(--fly, 1))) rotate(32deg); opacity: 0; } 45% { opacity: 1; } }
@keyframes fly-e { from { transform: translate(calc(950px * var(--fly, 1)), calc(-1200px * var(--fly, 1))) scale(.3); opacity: 0; } 45% { opacity: 1; } }

/* ============================================================
   SHAPE CLUSTER (brand motif)
   ============================================================ */
.shape-cluster {
  display: grid; width: 120px; height: 150px;
  grid-template-columns: 38px 1fr; grid-template-rows: 1fr 1fr;
  gap: 12px; transform-origin: top left;
}
.shape-cluster .shape-bar { grid-row: 1 / 3; border-radius: 999px 999px 0 0; }
.shape-cluster .shape-circle { width: 64px; height: 64px; border-radius: 50%; }
.shape-cluster .shape-trap { clip-path: polygon(0 100%, 16% 0, 100% 0, 100% 100%); }

/* ============================================================
   FOOTER
   ============================================================ */
.footer {
  background: var(--ink); color: var(--paper);
  padding-block: clamp(60px, 8vh, 110px) 34px;
  margin-top: 0;
}
.footer-top {
  display: grid; grid-template-columns: 1.4fr 1fr; gap: 48px;
  padding-bottom: 54px; border-bottom: 1px solid rgba(244,241,234,0.16);
  align-items: start;
}
.footer-mark { margin-bottom: 26px; opacity: 0.95; }
.footer-mark .ft-r { cursor: pointer; } /* the R is a toy: see bounceR in components.jsx */
.footer-tagline {
  font-size: clamp(28px, 4vw, 46px); font-weight: 500;
  /* 1.02 collided on a phone: the tagline wraps to two lines there and the
     descenders of the first sat on the caps of the second */
  max-width: 16ch; line-height: 1.1;
}
.footer-regions {
  display: block; margin-top: 22px; font-size: 13px;
  opacity: 0.6; letter-spacing: 0.1em;
}
/* The phone line in the brand column and the alt-domain link in the bottom bar
   are links inside a block of plain text; 4px of padding takes them from 20px
   and 18.6px to 28px and 27px, clearing the 24px WCAG 2.5.8 minimum this repo
   holds itself to. Not 44px: that would need the surrounding text to move.
   (The footer WhatsApp link is in the contact COLUMN, styled by .footer-col a,
   which got the same treatment with a wider row gap.) */
a.footer-regions, .footer-alt-site { padding-block: 4px; }
/* second line (cities) sits directly under the first (regions), tight gap */
.footer-regions + .footer-regions { margin-top: 6px; }
/* Local-time chip in the brand column (LocalTime in components.jsx). min-height holds the
   line open before the effect fills the time in, so nothing shifts. The colon blinks with
   opacity only; reduced motion stops it. */
.footer-clock {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 14px;
  margin-top: 14px; min-height: 1.7em; font-size: 13px; letter-spacing: 0.1em;
}
.footer-clock-label { opacity: 0.75; }
.footer-clock-time { font-variant-numeric: tabular-nums; font-size: 15px; opacity: 0.95; }
.footer-clock-part { opacity: 0.75; }
.footer-clock-colon { animation: clock-blink 1s step-end infinite; }
@keyframes clock-blink { 50% { opacity: 0.2; } }
@media (prefers-reduced-motion: reduce) { .footer-clock-colon { animation: none; } }
.footer-cols { display: flex; gap: clamp(30px, 6vw, 80px); justify-content: flex-end; }
.footer-col-h { font-size: var(--fs-label); letter-spacing: 0.08em; opacity: 0.7; margin-bottom: 18px; } /* was .5: 4.2:1 on ink; .7 = 6.8:1 (AA) */
/* 16px gap + 4px padding on each link keeps the rows ~44px apart, so a thumb
   cannot hit the neighbouring link on a phone */
.footer-col ul { display: flex; flex-direction: column; gap: 16px; }
.footer-col a, .footer-langlink {
  display: inline-block; padding-block: 4px;
  color: var(--paper); opacity: 0.82; font-size: 15.5px;
  transition: opacity .25s, color .25s; font-family: var(--sans);
}
[dir="rtl"] .footer-col a, [dir="rtl"] .footer-langlink { font-family: var(--arabic-sans); }
.footer-col a:hover, .footer-langlink:hover { opacity: 1; color: var(--yellow); }
.footer-bottom {
  display: flex; justify-content: space-between; align-items: center; gap: 16px;
  padding-top: 26px; flex-wrap: wrap;
}
.footer-bottom .mono { font-size: 12px; letter-spacing: 0.05em; opacity: 0.7; }
.footer-alt-site { transition: opacity 0.2s; }
.footer-alt-site:hover { opacity: 1; color: var(--yellow); }
@media (max-width: 760px) {
  .footer-top { grid-template-columns: 1fr; gap: 40px; }
  .footer-cols { justify-content: flex-start; }
  .footer-mark { display: flex; justify-content: center; }
  .footer-mark svg { width: 100% !important; height: auto !important; }
}

/* ---------- staging badge ----------
   Only rendered by StagingBadge() on non-production hosts (revaluar.fun,
   *.pages.dev). z-index sits above the nav (100) so it survives the sticky
   header; pointer-events:none so it can never intercept a click during
   testing. */
.staging-badge {
  position: fixed; bottom: 14px; inset-inline-start: 14px; z-index: 300;
  pointer-events: none; user-select: none;
  background: var(--ink); color: var(--paper);
  font-family: var(--mono); font-size: 10.5px; font-weight: 600;
  letter-spacing: 0.18em; text-transform: uppercase;
  padding: 6px 11px; border-radius: 999px;
  opacity: 0.82;
}
@media print { .staging-badge { display: none; } }

/* ---------- services dropdown (desktop nav) ---------- */
.nav-drop { position: relative; display: inline-flex; }
.nav-drop-menu {
  position: absolute; top: 100%; left: 50%; transform: translateX(-50%) translateY(6px);
  min-width: 290px; padding: 10px; margin-top: 10px;
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: 0 24px 50px -30px rgba(64,37,48,.55);
  display: flex; flex-direction: column; gap: 2px;
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity .25s var(--ease), transform .25s var(--ease), visibility .25s;
  z-index: 120;
}
/* Visibility has ONE source of truth - the .open class React sets. :focus-within
   was a second, independent one: it kept the menu painted after a click had
   already navigated, because CSS cannot see the state reset. Keyboard opening
   still works - the span's onFocus/onBlur set .open. */
.nav-drop.open .nav-drop-menu {
  opacity: 1; visibility: visible; pointer-events: auto; transform: translateX(-50%) translateY(0);
}
/* Bridges the 10px margin gap between trigger and menu. It is inside the menu's
   own box, and the menu is a DOM child of .nav-drop, so crossing it never fires
   mouseleave on .nav-drop - without it the menu closed before the cursor
   arrived. */
.nav-drop-menu::before {
  content: ""; position: absolute; left: 0; right: 0; top: -12px; height: 12px;
}
.nav-drop-menu a {
  padding: 10px 12px; border-radius: 10px; font-size: 14.5px; line-height: 1.35;
  transition: background .2s var(--ease), color .2s var(--ease);
}
.nav-drop-menu a:hover { background: var(--paper-2); color: var(--orange-cta); }
@media (prefers-reduced-motion: reduce) {
  .nav-drop-menu { transition: opacity .01s, visibility .01s; }
}
