/* ==========================================================================
   MIR Architecture Office — shared design system

   Loaded by all five public pages. Each page keeps its own page-specific CSS;
   this file owns the tokens, the navigation, the motion system and anything
   that must stay identical across the site.
   ========================================================================== */

@font-face {
  font-family: 'Farhang2';
  src: url('/assets/fonts/farhang2-regular.woff2') format('woff2');
  font-style: normal;
  font-weight: 100 600;
  font-display: swap;
}
@font-face {
  font-family: 'Farhang2';
  src: url('/assets/fonts/farhang2-bold.woff2') format('woff2');
  font-style: normal;
  font-weight: 700 900;
  font-display: swap;
}


/* Bundled rather than pulled from Google Fonts: the studio's audience is in
   Iran, where the CDN is unreliable, and Farhang2 is already served locally for
   the same reason. One variable file covers both weights. */
@font-face {
  font-family: 'Noto Naskh Arabic';
  src: url('/assets/fonts/noto-naskh-arabic.woff2') format('woff2');
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  unicode-range: U+0600-06FF, U+0750-077F, U+0870-088E, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF;
}

/* ── tokens ─────────────────────────────────────────────────────────────── */
:root {
  /* Brand. The palette is the studio's and is deliberately narrow: near-black
     ground, warm off-white text, one orange accent used sparingly. */
  --black:      #090909;
  --black-soft: #0e0e0e;
  --surface:    #121212;
  --surface-2:  #171717;
  --white:      #f3f2ee;
  --muted:      #8d8c87;
  --dim:        #4e4e4e;
  --orange:     #ff6a1a;
  --orange-dim: #c9501010;
  --line:       #1e1e1e;
  --line-2:     #242424;

  /* Shared matte black paper. The layers are intentionally very faint so the
     surface reads as fine Fabriano card rather than animated digital noise. */
  --paper-black: #080909;
  --paper-texture:
    radial-gradient(ellipse at 18% 12%, rgba(255,255,255,.022), transparent 38%),
    radial-gradient(ellipse at 82% 74%, rgba(0,0,0,.2), transparent 44%),
    radial-gradient(circle at 30% 40%, rgba(255,255,255,.032) 0 .45px, transparent .7px),
    repeating-linear-gradient(12deg, rgba(255,255,255,.012) 0 1px, transparent 1px 4px),
    repeating-linear-gradient(102deg, rgba(0,0,0,.09) 0 1px, transparent 1px 6px);
  --paper-size: auto, auto, 4px 5px, 7px 9px, 9px 11px;

  /* Type families.
     English pairs a high-contrast display serif with a neutral UI sans. Farsi
     needs the same two registers: Vazirmatn is the best free Persian screen
     sans, but it has no serif counterpart — so Farsi headings previously fell
     back to a sans while English headings got Cormorant, which read as a
     downgrade in the Farsi layout. Noto Naskh Arabic is a modulated Naskh
     designed to sit alongside serif Latin faces, and restores that pairing. */
  --serif:    'Farhang2', Tahoma, sans-serif;
  --sans:     'Farhang2', Tahoma, sans-serif;
  --fa:       'Farhang2', Tahoma, sans-serif;
  /* Farhang2 is a Persian typeface: its glyph set and proportions are drawn for
     Persian, and it carries the Persian-specific letters (گ چ پ ژ) that Arabic
     does not use. Arabic gets a Naskh face designed for it, so the script reads
     as Arabic rather than as Persian set in a Persian font. */
  --ar:       'Noto Naskh Arabic', 'Noto Sans Arabic', 'Segoe UI', Tahoma, serif;
  --fa-serif: 'Farhang2', Tahoma, sans-serif;

  /* Fluid type scale. clamp() removes the need for per-step media queries and
     keeps headings from overwhelming a 320px screen. */
  --step--1: clamp(0.75rem, 0.71rem + 0.20vw, 0.84rem);
  --step-0:  clamp(0.94rem, 0.90rem + 0.20vw, 1.05rem);
  --step-1:  clamp(1.13rem, 1.04rem + 0.42vw, 1.38rem);
  --step-2:  clamp(1.41rem, 1.25rem + 0.80vw, 1.94rem);
  --step-3:  clamp(1.76rem, 1.47rem + 1.44vw, 2.72rem);
  --step-4:  clamp(2.20rem, 1.70rem + 2.48vw, 3.82rem);
  --step-5:  clamp(2.75rem, 1.92rem + 4.15vw, 5.35rem);

  /* Spacing scale (1.5x steps) */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 3rem;
  --space-8: 4rem;
  --space-9: 6rem;
  --space-10: 8rem;

  /* Layout */
  --nav-h: 132px;
  --gutter: clamp(1.25rem, 4vw, 4rem);
  --measure: 68ch;

  /* Motion. Durations are grouped by intent so the whole site shares a
     rhythm instead of every component inventing its own timing. */
  --ease-out:  cubic-bezier(0.22, 1, 0.36, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --dur-fast:  180ms;
  --dur-base:  320ms;
  --dur-slow:  620ms;
  --dur-cine:  1100ms;

  --z-nav: 100;
  --z-drawer: 110;
  --z-cursor: 200;
}

/* ── reset ──────────────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  /* Keep the fixed header on the same physical center line on short pages and
     long scrolling pages. Symmetric gutters prevent a classic scrollbar from
     shifting the 50%-positioned brand and navigation sideways. */
  scrollbar-gutter: stable both-edges;
  /* Fixed nav must not hide the target of an anchor link. */
  scroll-padding-top: var(--nav-h);
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--black);
  color: var(--white);
  font-family: var(--sans);
  font-size: var(--step-0);
  line-height: 1.65;
  /* The single most common cause of mobile horizontal scroll. */
  overflow-x: hidden;
}

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

/* Visible focus is a hard accessibility requirement; never remove it. */
:focus-visible {
  outline: 2px solid var(--orange);
  outline-offset: 3px;
  border-radius: 2px;
}
:focus:not(:focus-visible) { outline: none; }

.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ── navigation ─────────────────────────────────────────────────────────── */
.site-nav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: var(--z-nav);
  height: var(--nav-h);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  gap: 0;
  padding-inline: 0;
  background: transparent;
  transition: background var(--dur-base) var(--ease-out),
              border-color var(--dur-base) var(--ease-out),
              height var(--dur-base) var(--ease-out);
  border-bottom: 1px solid transparent;
}

/* Solidifies once the page scrolls so text never sits on a busy image. */
.site-nav.scrolled {
  background: rgba(8, 9, 9, 0.92);
  background: color-mix(in srgb, var(--black) 88%, transparent);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-bottom-color: var(--line);
  height: var(--nav-h);
}

/* Mobile Safari can place its collapsing browser toolbar over content above
   the visual viewport. Extend the scrolled header glass upward so a passing
   project image can never show through that browser-chrome area. */
@media (max-width: 1180px) {
  .site-nav.scrolled {
    background: transparent;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }

  .site-nav.scrolled::before {
    content: '';
    position: absolute;
    z-index: -1;
    top: -240px;
    right: auto;
    bottom: -1px;
    left: 50%;
    width: 100vw;
    transform: translateX(-50%);
    pointer-events: none;
    background: rgba(8, 9, 9, 0.94);
    backdrop-filter: blur(18px) saturate(0.85);
    -webkit-backdrop-filter: blur(18px) saturate(0.85);
  }
}

.nav-brand {
  position: absolute;
  top: 10px;
  left: 50%;
  display: flex;
  align-items: center;
  gap: 7px;
  width: 189px;
  min-height: 58px;
  text-decoration: none;
  color: inherit;
  flex-shrink: 0;
  transform: translateX(-50%);
  direction: ltr;
  unicode-bidi: isolate;
}
.nav-brand img {
  /* The source is 1536x1024 — exactly 3:2. The previous 100x59 box was 1.695:1,
     so the mark sat letterboxed inside a wrongly-shaped slot and read as
     squashed. Declaring the true ratio and deriving height keeps it correct at
     every width, and reserving the box up front avoids layout shift on load. */
  width: clamp(64px, 7vw, 100px);
  aspect-ratio: 3 / 2;
  height: auto;
  object-fit: contain;
}
.nav-brand-text {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  min-width: 82px;
  line-height: 1;
  color: var(--white);
  text-align: left;
}
.nav-brand-main {
  font-family: var(--sans);
  font-size: 22px;
  font-weight: 600;
  line-height: 0.92;
  letter-spacing: 0.12em;
}
.nav-brand-sub {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  margin-top: 3px;
  font: 400 8.5px/1.08 var(--sans);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--white);
}

.nav-links {
  position: absolute;
  top: 84px;
  left: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(22px, 3vw, 46px);
  transform: translateX(-50%);
}

.nav-link {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 41px;
  color: rgba(247, 246, 242, 0.9);
  text-decoration: none;
  min-width: 72px;
  font-size: 13px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  /* Padding, not just line-height, is what makes the tap target real. */
  padding: 0 2px;
  text-align: center;
  text-shadow: none;
  transition: color var(--dur-fast) var(--ease-out);
}
.nav-link::after {
  content: '';
  position: absolute;
  left: 50%; bottom: 4px;
  width: 28px;
  height: 1px;
  background: var(--orange);
  transform: translateX(-50%) scaleX(0);
  transform-origin: center;
  transition: transform var(--dur-base) var(--ease-out);
}
.nav-link:hover, .nav-link:focus-visible { color: var(--white); }
.nav-link:hover::after, .nav-link.active::after { transform: translateX(-50%) scaleX(1); transform-origin: center; }
.nav-link.active { color: var(--white); }

.language-picker {
  position: fixed;
  top: 13px;
  right: 26px;
  z-index: calc(var(--z-nav) + 2);
  flex: 0 0 auto;
  font-family: var(--sans);
}
.lang-toggle {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: rgba(247, 246, 242, 0.9);
  padding: 10px;
  cursor: pointer;
  box-shadow: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  transition: color var(--dur-fast) ease, transform var(--dur-fast) ease;
}
.lang-toggle:hover,
.language-picker:focus-within .lang-toggle,
.language-picker.is-open .lang-toggle {
  color: var(--white);
  background: transparent;
  transform: translateY(-1px);
}
.lang-toggle svg {
  width: 21px;
  height: 21px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.35;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.lang-menu {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  width: 132px;
  padding: 6px;
  background: linear-gradient(145deg, rgba(32,32,32,0.72), rgba(8,8,8,0.82));
  border: 1px solid rgba(255,255,255,0.2);
  border-radius: 12px;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.16), 0 18px 46px rgba(0,0,0,0.42);
  backdrop-filter: blur(22px) saturate(1.3);
  -webkit-backdrop-filter: blur(22px) saturate(1.3);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-4px);
  transition: opacity var(--dur-fast) ease, transform var(--dur-fast) ease, visibility var(--dur-fast);
}
.language-picker.is-open .lang-menu {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}
.lang-option {
  display: block;
  width: 100%;
  min-height: 38px;
  padding: 7px 10px;
  border: 0;
  border-radius: 2px;
  background: transparent;
  color: #aaa;
  font: 300 0.82rem/1.4 var(--sans);
  text-align: center;
  cursor: pointer;
  transition: color var(--dur-fast) ease, background var(--dur-fast) ease;
}
.lang-option[data-lang='fa'],
.lang-option[data-lang='ar'] { font-family: var(--fa); direction: rtl; }
.lang-option:hover,
.lang-option:focus-visible { color: var(--white); background: #181818; }
.lang-option.active { color: var(--orange); }

/* The navigation remains visible at every width; no mobile drawer is used. */
.nav-toggle {
  display: none !important;
  width: 46px; height: 46px;
  align-items: center; justify-content: center;
  background: none;
  border: 1px solid var(--line-2);
  border-radius: 4px;
  cursor: pointer;
  flex-shrink: 0;
}
.nav-toggle-bars { position: relative; width: 20px; height: 12px; }
.nav-toggle-bars span {
  position: absolute; left: 0;
  width: 100%; height: 1.5px;
  background: var(--white);
  transition: transform var(--dur-base) var(--ease-out), opacity var(--dur-fast) linear;
}
.nav-toggle-bars span:nth-child(1) { top: 0; }
.nav-toggle-bars span:nth-child(2) { top: 5px; }
.nav-toggle-bars span:nth-child(3) { top: 10px; }
.nav-toggle[aria-expanded='true'] .nav-toggle-bars span:nth-child(1) { transform: translateY(5px) rotate(45deg); }
.nav-toggle[aria-expanded='true'] .nav-toggle-bars span:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded='true'] .nav-toggle-bars span:nth-child(3) { transform: translateY(-5px) rotate(-45deg); }

.nav-scrim {
  position: fixed;
  inset: 0;
  z-index: calc(var(--z-drawer) - 1);
  background: rgba(0, 0, 0, 0.6);
  backdrop-filter: blur(2px);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-base) var(--ease-out);
}
body.nav-open .nav-scrim { opacity: 1; pointer-events: auto; }

/* ── mobile navigation ──────────────────────────────────────────────────── */
@media (max-width: 899px) {
  :root { --nav-h: 116px; }

  .site-nav,
  .site-nav.scrolled { height: var(--nav-h); }
  .nav-brand { top: 8px; gap: 6px; width: 150px; min-height: 48px; }
  /* Width only — height follows from the aspect-ratio declared above. */
  .nav-brand img { width: 76px; }
  .nav-brand-text { min-width: 68px; }
  .nav-brand-main { font-size: 16px; letter-spacing: 0.1em; }
  .nav-brand-sub { margin-top: 2px; font-size: 7px; letter-spacing: 0.06em; }

  .nav-links {
    top: 64px;
    width: calc(100% - 16px);
    gap: 2px;
  }
  .nav-link {
    flex: 1 1 0;
    min-width: 0;
    padding: 9px 0;
    font-size: clamp(10px, 2.9vw, 12px);
    font-weight: 500;
    letter-spacing: 0.03em;
    white-space: nowrap;
  }
  .nav-link::after { bottom: 6px; }

  .language-picker { top: 7px; right: 7px; margin: 0; }
  .lang-toggle { width: 38px; height: 38px; padding: 9px; }
  .lang-menu { right: 0; left: auto; top: calc(100% + 4px); transform: translateY(-4px); }
  .language-picker.is-open .lang-menu { transform: translateY(0); }
}

/* ── motion system ──────────────────────────────────────────────────────── */
/* Elements marked .reveal start hidden and are shown by IntersectionObserver
   in site.js. The no-js/no-observer fallback is handled there by adding
   .is-visible immediately, so content is never permanently invisible. */
.reveal {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity var(--dur-slow) var(--ease-out),
              transform var(--dur-slow) var(--ease-out);
  transition-delay: var(--reveal-delay, 0ms);
  will-change: opacity, transform;
}
.reveal.is-visible { opacity: 1; transform: none; }

.reveal-stagger > * {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity var(--dur-slow) var(--ease-out),
              transform var(--dur-slow) var(--ease-out);
}
.reveal-stagger.is-visible > * { opacity: 1; transform: none; }
.reveal-stagger.is-visible > *:nth-child(1) { transition-delay: 0ms; }
.reveal-stagger.is-visible > *:nth-child(2) { transition-delay: 70ms; }
.reveal-stagger.is-visible > *:nth-child(3) { transition-delay: 140ms; }
.reveal-stagger.is-visible > *:nth-child(4) { transition-delay: 210ms; }
.reveal-stagger.is-visible > *:nth-child(5) { transition-delay: 280ms; }
.reveal-stagger.is-visible > *:nth-child(6) { transition-delay: 350ms; }

/* ── media loading ──────────────────────────────────────────────────────── */
/* Reserving the aspect ratio up front is what keeps CLS near zero. */
.media {
  position: relative;
  overflow: hidden;
  background: var(--surface);
  aspect-ratio: var(--media-ratio, 3 / 2);
}
.media img { width: 100%; height: 100%; object-fit: cover; }

.media-img {
  opacity: 0;
  transition: opacity var(--dur-slow) var(--ease-out);
}
.media-img.loaded { opacity: 1; }

.media-placeholder {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background: var(--surface);
  transition: opacity var(--dur-base) var(--ease-out);
}
.media-placeholder img { width: 42px; opacity: 0.22; animation: mir-pulse 1.9s var(--ease-in-out) infinite; }
.media-placeholder.loaded { opacity: 0; pointer-events: none; }

@keyframes mir-pulse {
  0%, 100% { opacity: 0.14; transform: scale(0.97); }
  50%      { opacity: 0.34; transform: scale(1.02); }
}

/* ── state blocks ───────────────────────────────────────────────────────── */
.state {
  padding: var(--space-8) var(--gutter);
  text-align: center;
  color: var(--muted);
}
.state-title { font-family: var(--serif); font-size: var(--step-2); color: var(--white); margin: 0 0 var(--space-2); }
.state-body { margin: 0 auto; max-width: 46ch; font-size: var(--step-0); }
.state-action {
  margin-top: var(--space-5);
  display: inline-flex; align-items: center; gap: var(--space-2);
  min-height: 44px; padding: 0 var(--space-5);
  border: 1px solid var(--orange);
  color: var(--orange);
  background: none;
  font: inherit;
  font-size: var(--step--1);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.state-action:hover { background: var(--orange); color: var(--black); }

/* ── RTL ────────────────────────────────────────────────────────────────── */
html.lang-rtl body { font-family: var(--fa); }

/* Farsi display type.
   Each page's inline <style> already sets `font-family: var(--fa)` on these
   headings at specificity (0,2,1), and inline styles are parsed after this
   linked sheet — so an equal-specificity rule here would lose the cascade.
   Adding `body` to the chain raises this to (0,2,2) and makes it win without
   resorting to !important. */
html.lang-rtl body :is(
  h1, h2, h3,
  .hero-title, .card-title, .section-title, .intro-title,
  .founder-name, .stat-num, .headline, .contact-headline, .state-title,
  .value-title, .values-label
) {
  font-family: var(--fa-serif);
  /* Only the family, rhythm and tracking change here. Font size is deliberately
     NOT touched: each page sets its own clamp() scale, and overriding it with a
     relative unit resolves against the parent rather than the element, which
     collapsed headings below their own subtitles. */
  line-height: 1.5;
  letter-spacing: 0;
}

/* Latin numerals inside Farsi headings keep the Latin face so figures stay
   even in width. */
html.lang-rtl body .stat-num { font-family: var(--serif); }

html.lang-rtl .nav-link {
  min-width: 84px;
  font-size: 16px;
  font-weight: 400;
  line-height: 1.35;
  letter-spacing: 0;
}
@media (max-width: 899px) {
  html.lang-rtl .nav-link {
    min-width: 0;
    font-size: clamp(12px, 3.4vw, 14px);
    line-height: 1.35;
  }
}
html.lang-rtl [data-en] { direction: rtl; text-align: inherit; }

/* Farhang is supplied from the local webfont files and contains both Persian
   and Latin glyphs, so every public language uses the same typeface. */
html.lang-fa {
  --fa: 'Farhang2', Tahoma, sans-serif;
  --fa-serif: 'Farhang2', Tahoma, sans-serif;
  --fa-font: 'Farhang2', Tahoma, sans-serif;
}
html.lang-fa body :is(
  h1, h2, h3,
  .hero-title, .card-title, .section-title, .intro-title,
  .founder-name, .headline, .contact-headline, .state-title,
  .value-title, .caption-title
) { font-weight: 700; }
html.lang-fa body :is(p, .intro-text, .founder-bio, .value-desc) { font-weight: 400; }

/* The old/new language cross-fade is shared by every page. Page-specific
   content rebuilt on mir:langchange is covered by the page-content targets. */
[data-en],
#mir-caption,
#page-root,
#projects-grid,
.contact-wrap {
  transition-property: opacity, filter;
  transition-duration: 260ms;
  transition-timing-function: ease;
}
html.lang-is-fading :is([data-en], #mir-caption, #page-root, #projects-grid, .contact-wrap) {
  opacity: 0;
  filter: blur(2px);
}

/* Farsi body copy reads better slightly looser than the Latin default. */
html.lang-rtl p, html.lang-rtl .intro-text { line-height: 1.95; }
html.lang-rtl body .intro-text p,
html.lang-rtl body .founder-bio,
html.lang-rtl body .value-desc { font-family: var(--fa); }

/* Small tracked labels work at 10px in Latin capitals, but Persian script has
   no uppercase and relies on fine joins, so the same size becomes unreadable.
   These get a floor and lose the tracking that pulls the glyphs apart. */
html.lang-rtl body :is(
  .hero-cat-label, .hero-loc, .card-cat, .card-loc,
  .spec-label, .isr-label, .caption-cat, .scroll-cue-label,
  .group-label, .phone-name, .footer-text, .footer-link
) {
  font-size: max(0.75rem, 1em);
  letter-spacing: 0;
}

/* ── bidirectional isolation ────────────────────────────────────────────────
   Latin and numeric runs inside an RTL paragraph must be isolated, or the
   Unicode bidi algorithm resolves their neutral characters (+ @ . : / and
   spaces) against the surrounding RTL direction. That is what turned
   "+98 912 155 3424" into "3424 155 912 98+" and "@emadshahrokh" into
   "emadshahrokh@" — the glyphs were right, the ordering was not.

   `unicode-bidi: isolate` treats the element as its own bidi run so the
   surrounding direction cannot reorder anything inside it, while the element's
   own box still sits at the correct RTL edge. */
:is(
  a[href^='tel:'],
  a[href^='mailto:'],
  a[href*='instagram.com'],
  .external-link,
  .phone-num,
  .stat-num,
  .stat-unit,
  [data-ltr]
) {
  direction: ltr;
  unicode-bidi: isolate;
}

/* Any element explicitly marked LTR gets the same isolation, so a mixed
   Farsi/Latin string never reflows. */
[dir='ltr'] { unicode-bidi: isolate; }

/* Tabular figures keep phone numbers and stats from shifting width as digits
   change, which reads as sloppy in a column of numbers. */
html.lang-rtl body :is(a[href^='tel:'], .stat-num, .spec-value) {
  font-variant-numeric: tabular-nums;
}

/* The site uses one upright Farhang family in every language. Browsers can fake
   which breaks the joins and reads as a rendering fault rather than emphasis —
   so emphasis is carried by colour and weight instead of synthetic slanting. */
html body {
  font-family: 'Farhang2', Tahoma, sans-serif;
  font-synthesis: none;
  background-color: var(--paper-black);
  background-image: var(--paper-texture);
  background-size: var(--paper-size);
}
/* A very light moving grain sits above the static paper fibres. The canvas tile
   is created once in site.js; only this oversized compositor layer moves. */
@keyframes mir-paper-grain {
  0%, 100% { transform: translate3d(0,0,0); }
  10% { transform: translate3d(-2%,-3%,0); }
  20% { transform: translate3d(3%,1%,0); }
  30% { transform: translate3d(-1%,4%,0); }
  40% { transform: translate3d(4%,-2%,0); }
  50% { transform: translate3d(-3%,2%,0); }
  60% { transform: translate3d(2%,-3%,0); }
  70% { transform: translate3d(-3%,1%,0); }
  80% { transform: translate3d(2%,-2%,0); }
  90% { transform: translate3d(-1%,3%,0); }
}
#grain-overlay {
  display: block !important;
  position: fixed !important;
  inset: -50% !important;
  width: 200% !important;
  height: 200% !important;
  z-index: 70 !important;
  pointer-events: none !important;
  opacity: .14 !important;
  background-repeat: repeat !important;
  mix-blend-mode: screen !important;
  animation: mir-paper-grain .42s steps(1) infinite !important;
  will-change: transform;
  contain: strict;
}
html body :is(button, input, textarea, select, option) {
  font-family: 'Farhang2', Tahoma, sans-serif;
}
html body :is(em, i, cite, blockquote, .hero-subtitle) {
  font-family: 'Farhang2', Tahoma, sans-serif;
  font-style: normal !important;
}

/* ── reduced motion ─────────────────────────────────────────────────────── */
/* High-severity accessibility requirement: present the final readable state
   rather than a degraded animation. Reveal elements must end up visible. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  #grain-overlay { animation: none !important; }

  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }

  .reveal,
  .reveal-stagger > * {
    opacity: 1 !important;
    transform: none !important;
  }
  .media-img { opacity: 1 !important; }
  .media-placeholder { display: none; }
}

/* ── polish ─────────────────────────────────────────────────────────────── */
/* Small, system-wide touches. Each is cheap and applies everywhere, which is
   what makes the site feel considered rather than assembled. */

::selection { background: var(--orange); color: var(--black); }

/* The default light scrollbar is jarring against a near-black page. */
html {
  scrollbar-color: var(--line-2) var(--black);
  scrollbar-width: thin;
}
::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-track { background: var(--black); }
::-webkit-scrollbar-thumb {
  background: var(--line-2);
  border: 3px solid var(--black);
  border-radius: 999px;
}
::-webkit-scrollbar-thumb:hover { background: var(--dim); }

/* Links that leave the site. Replaces the inline mouseover handlers that were
   doing this per-element. */
.external-link,
a[target='_blank'] {
  transition: color var(--dur-fast) var(--ease-out);
}
.external-link:hover,
.external-link:focus-visible { color: var(--orange); }

/* Contact-style detail links: underline only on interaction, so the resting
   state stays as quiet as the rest of the page. */
a[href^='mailto:'],
a[href^='tel:'] {
  text-decoration: none;
  background-image: linear-gradient(var(--orange), var(--orange));
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 0% 1px;
  transition: background-size var(--dur-base) var(--ease-out),
              color var(--dur-fast) var(--ease-out);
}
a[href^='mailto:']:hover, a[href^='mailto:']:focus-visible,
a[href^='tel:']:hover, a[href^='tel:']:focus-visible {
  color: var(--orange);
  background-size: 100% 1px;
}
html.lang-rtl :is(a[href^='mailto:'], a[href^='tel:']) { background-position: 100% 100%; }

/* A short fade on first paint hides the moment before webfonts settle and the
   API-driven content lands, which otherwise reads as a flash. */
@media (prefers-reduced-motion: no-preference) {
  body { animation: page-enter var(--dur-slow) var(--ease-out) both; }
}
@keyframes page-enter {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* Keeps long Farsi and English words from breaking the grid on narrow screens. */
h1, h2, h3, p, .card-title, .hero-title { overflow-wrap: break-word; }

/* ── print ──────────────────────────────────────────────────────────────── */
@media print {
  .site-nav, .nav-scrim, .media-placeholder { display: none !important; }
  html body { background: #fff !important; background-image: none !important; color: #000; }
}

/* ── Arabic ─────────────────────────────────────────────────────────────────
   Arabic was inheriting the Persian treatment wholesale: the Persian typeface,
   Persian metrics, and Persian text wherever a data-ar value was missing. The
   two scripts share an alphabet but not a typographic tradition — Naskh sets
   larger on the line, needs more leading, and Arabic uses its own digit forms
   (٠١٢٣٤٥٦٧٨٩ against Persian ۰۱۲۳۴۵۶۷۸۹, which differ at 4, 5 and 6).

   `lang="ar"` is already set on <html>, so declaring an Arabic-first stack is
   what lets the shaper pick Arabic letterforms and digits. */
html.lang-ar body,
html.lang-ar body :is(p, span, div, a, li, td, h1, h2, h3, h4, button, input, textarea, select),
html.lang-ar body :is(.hero-title, .founder-name, .card-title, .contact-headline, .page-intro h2, .value-title, .founder-role, .values-label, .spec-value, .spec-label) {
  font-family: var(--ar);
}

/* Naskh has taller ascenders and deeper descenders than Farhang2, so the
   Persian leading leaves it cramped. */
html.lang-ar body :is(p, .founder-bio, .intro-text, .value-desc, .contact-sub) {
  line-height: 2.05;
}
html.lang-ar body :is(h1, h2, h3, .hero-title, .founder-name, .card-title, .contact-headline) {
  line-height: 1.55;
  /* Naskh joins are broken by tracking; Arabic display type is set solid. */
  letter-spacing: 0;
}

/* Arabic has no uppercase, so the small tracked Latin-style eyebrow labels
   become unreadable. Same floor the Persian pass applies. */
html.lang-ar body :is(
  .hero-cat-label, .hero-loc, .card-cat, .card-loc, .spec-label,
  .group-label, .phone-name, .values-label, .page-intro-label,
  .founder-role, .footer-text, .footer-link, .scroll-cue-label
) {
  font-size: max(0.8125rem, 1em);
  letter-spacing: 0;
  text-transform: none;
}

/* Arabic has no italic; browsers fake one by shearing, which breaks the joins. */
html.lang-ar body :is(em, i, blockquote) { font-style: normal; }

/* Latin and numeric runs inside Arabic need the same bidi isolation Persian
   gets, or the neutral characters reorder against the paragraph. */
html.lang-ar :is(a[href^='tel:'], a[href^='mailto:'], .stat-num, .stat-unit, [dir='ltr']) {
  direction: ltr;
  unicode-bidi: isolate;
}
