/* Locale-dependent presentation: first-paint flash suppression, per-language
   font stacks, and the direction-mirroring rules that logical properties in the
   other stylesheets cannot express on their own. */

/* i18n-boot.js sets .i18n-pending for non-English visitors; initI18n() clears it
   once the catalog has been applied. The animation is a failsafe: if i18n.js
   fails to load the page still reveals itself (in English) after 2.5s rather
   than staying blank forever. */
.i18n-pending body {
  visibility: hidden;
  animation: i18n-reveal 0s linear 2.5s forwards;
}

@keyframes i18n-reveal {
  to { visibility: visible; }
}

@media (prefers-reduced-motion: reduce) {
  /* animation-* is still honoured with reduced motion, but be explicit that this
     is a visibility failsafe rather than decoration. */
  .i18n-pending body { animation-duration: 0s; }
}

/* ---------------------------------------------------------------------------
   Persian webfont
   Naming Vazirmatn in the stack is not enough — nothing served it, so Persian
   visitors silently fell back to the platform default (Geeza Pro on macOS,
   Tahoma on Windows): thin strokes, colliding dots, and no weight above 700.
   The variable woff2 below is vendored under static/fonts/ (no CDN, per the
   project's asset policy) and covers 100–900 in one 111 KB file.
   Vazirmatn v33.003 — SIL OFL 1.1, licence text alongside the font.
   --------------------------------------------------------------------------- */
@font-face {
  font-family: "Vazirmatn";
  /* Plain format("woff2") — the legacy "woff2-variations" token is rejected by
     some parsers, and every engine that supports variable fonts reads the axes
     out of the woff2 itself. The font-weight range below is what unlocks them. */
  src: url("/static/fonts/vazirmatn-var.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  /* swap, not block: i18n-boot.js already hides the document for non-English
     visitors until the catalog applies, so the swap happens behind that veil. */
  font-display: swap;
  /* Restricted to the Arabic script, which is load-bearing rather than cosmetic:
     Vazirmatn sits in the *default* --font-sans as a fallback for every locale,
     and it also carries a full Latin set. Without this range an English visitor
     would fall through to it (IBM Plex is not served either), silently
     re-typesetting the English page and downloading 111 KB to do it. Scoped this
     way the browser fetches the file only when Arabic codepoints are actually on
     the page — so Persian text renders correctly wherever it appears, including
     inside an otherwise-English UI, and Latin-only pages never touch it.
     U+200C-200D are the ZWNJ/ZWJ that Persian orthography depends on; they belong
     in the same range so a word like «می‌کنند» shapes as one run. */
  unicode-range: U+0600-06FF, U+0750-077F, U+0870-088E, U+08A0-08FF, U+200C-200D,
                 U+FB50-FDFF, U+FE70-FEFF;
}

/* The same file again under a second family name, this time covering Latin.
   Vazirmatn's Latin is drawn to the same vertical metrics as its Arabic, so on a
   Persian page the Latin runs threaded through the copy — "GraphrAI", model IDs,
   token counts, R1–R4 on the hero graph — sit on the same baseline at the same
   apparent size instead of jumping to the platform UI face mid-sentence.

   It has to be a separate family rather than a widened unicode-range on the face
   above, because that face is reachable from the *default* --font-sans and would
   then re-typeset every English page. A distinct name can only be opted into, and
   only the Persian stack below does. Non-Persian locales never name it, so they
   never fetch it.

   Both faces point at one URL, so the Persian page still makes a single request —
   the second face resolves against the same in-flight fetch. */
@font-face {
  font-family: "Vazirmatn Latin";
  src: url("/static/fonts/vazirmatn-var.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
  /* Latin, its extensions, punctuation, currency and arrows. Over-declaring is
     safe: a codepoint in range that the font has no glyph for still falls through
     to the next family in the stack. Arabic is deliberately absent so the
     Arabic-scoped face above stays the one that shapes Persian. */
  unicode-range: U+0000-024F, U+0250-02AF, U+2000-206F, U+2070-209F, U+20A0-20CF,
                 U+2100-214F, U+2190-21FF, U+2212, U+FFFD;
}

/* Vazirmatn carries a complete Persian glyph set with matching metrics; IBM Plex
   Sans does not, so Persian leads with Vazirmatn for the script and its Latin
   companion for everything else. The remaining entries are unreachable in
   practice and kept only as a floor if the webfont ever fails to load. */
:root[data-locale="fa"] {
  --font-sans: "Vazirmatn", "Vazirmatn Latin", "IBM Plex Sans", "Inter", system-ui, sans-serif;
}

/* ---------------------------------------------------------------------------
   Persian typographic tuning

   The Latin type scale does not transfer to Arabic script. Three corrections
   apply everywhere Persian is set:

   1. Tracking is destructive. Arabic script is cursive — adjacent letters join
      along a baseline stroke. Positive letter-spacing prises those joins apart
      and negative tracking crushes the dots into the letters above them. Every
      letter-spacing value in the Latin sheets must be neutralised, not scaled.
   2. Persian needs more leading. Ascenders (ا ل ک), descenders (ج ی ن) and the
      dot cloud above and below the baseline occupy far more vertical space than
      Latin x-height typography assumes; 1.6 for body copy reads as cramped.
   3. Persian sets optically larger. Vazirmatn's glyph bodies fill more of the em
      than IBM Plex's do, so display sizes tuned for Latin come out oversized and
      must be pulled back, while small UI text must be pushed up to stay legible.
   --------------------------------------------------------------------------- */

/* Rule 1, applied at the root: no Latin tracking value survives into Persian. */
:root[data-locale="fa"] body,
:root[data-locale="fa"] h1,
:root[data-locale="fa"] h2,
:root[data-locale="fa"] h3,
:root[data-locale="fa"] h4,
:root[data-locale="fa"] button,
:root[data-locale="fa"] .btn-primary,
:root[data-locale="fa"] .btn-secondary,
:root[data-locale="fa"] .nav-link-text,
:root[data-locale="fa"] .section-title,
:root[data-locale="fa"] .hero-badge,
:root[data-locale="fa"] .graph-badge {
  letter-spacing: normal;
}

/* Rule 2, applied at the root. */
:root[data-locale="fa"] body {
  line-height: 1.85;
  /* Vazirmatn's connecting strokes are a single hairline at UI sizes, and
     -webkit-font-smoothing:antialiased thins them until they break up on the
     light landing background. Subpixel rendering keeps the joins solid. */
  -webkit-font-smoothing: auto;
}

/* Persian numerals are visually distinct from the Latin digits used in costs,
   token counts and model names. Intl is pinned to Latin digits in i18n.js; this
   keeps hand-written numeric markup consistent with that. */
:root[data-locale="fa"] .mono,
:root[data-locale="fa"] code,
:root[data-locale="fa"] pre {
  font-family: var(--font-mono);
  direction: ltr;
  unicode-bidi: isolate;
}

/* Landing page — rule 3, the size corrections.
   These override landing.css (loaded before this sheet) by locale specificity;
   they are listed separately from the app chrome because the landing page is the
   only place the type scale climbs into display sizes. */

:root[data-locale="fa"] .hero-content h1 {
  /* 52px of Vazirmatn sets about as large as 60px of Plex, so the ceiling comes
     down. 800 is available in the variable font but reads as a solid slab in
     Persian — the counters close up — so the headline settles at 700. */
  font-size: clamp(27px, 3.9vw, 45px);
  font-weight: 700;
  line-height: 1.62;
  /* Persian headlines break badly on width alone; balance evens the two lines
     around the explicit <br> in the catalog string. */
  text-wrap: balance;
}

:root[data-locale="fa"] .hero-content p {
  font-size: 16.5px;
  line-height: 1.95;
  /* Latin measure is counted in characters; Persian words run longer, so the
     same 520px holds too few words per line for comfortable tracking back. */
  max-width: 560px;
}

/* Uppercase is a no-op on Persian and the pill was carrying 0.04em of tracking,
   which is what split the badge into loose fragments. */
:root[data-locale="fa"] .hero-badge,
:root[data-locale="fa"] .graph-badge {
  font-size: 13px;
  font-weight: 500;
  text-transform: none;
}

:root[data-locale="fa"] .section-title {
  font-size: clamp(22px, 2.9vw, 33px);
  line-height: 1.55;
  text-wrap: balance;
}

:root[data-locale="fa"] .section-subtitle {
  font-size: 15.5px;
  line-height: 1.9;
}

:root[data-locale="fa"] .proof-item {
  font-size: 13.5px;
}

/* Buttons and nav sit on a fixed height, so they take leading back rather than
   inheriting the 1.85 body value and pushing their own labels off-centre. */
:root[data-locale="fa"] .btn-primary,
:root[data-locale="fa"] .btn-secondary,
:root[data-locale="fa"] .nav-link-text,
:root[data-locale="fa"] .lang-switcher-button {
  line-height: 1.4;
  font-weight: 500;
}

/* The hero graph is drawn at a fixed 480px viewBox with 7–10px labels, sized for
   three-letter Latin abbreviations. Persian words at that size lose their dots
   entirely, so the localised labels — and only those; R1–R4 stay Latin — get
   their own sizes. */
:root[data-locale="fa"] .graph-svg text[data-i18n] {
  font-size: 9px;
  font-weight: 600;
}

:root[data-locale="fa"] .graph-labels text {
  font-size: 10px;
}

/* ---------------------------------------------------------------------------
   RTL mirroring
   Layout stylesheets use logical properties (margin-inline-start, inset-inline)
   which flip on their own. The rules below cover what logical properties cannot:
   transforms, background positions, shadows, and content that must stay LTR.
   --------------------------------------------------------------------------- */

/* Directional glyphs (chevrons, arrows, back/forward carets) point the wrong way
   under RTL. Mirroring the element is more reliable than swapping every icon. */
:root[dir="rtl"] .icon-directional,
:root[dir="rtl"] .breadcrumb-sep,
:root[dir="rtl"] .chevron,
:root[dir="rtl"] .collapse-toggle svg {
  transform: scaleX(-1);
}

/* panel-tabs-scroll's fade (layout.css) marks its trailing edge in reading
   order — that's the left in RTL, not the right the LTR gradient assumes. */
:root[dir="rtl"] .panel-tabs-scroll {
  mask-image: linear-gradient(to left, black calc(100% - 16px), transparent 100%);
  -webkit-mask-image: linear-gradient(to left, black calc(100% - 16px), transparent 100%);
}

/* The DAG is a spatial diagram, not prose: node coordinates, edge paths and the
   pan/zoom transform are all computed in LTR space in dag.js. Mirroring it would
   invert the graph's meaning (parents would render right of children), so the
   canvas keeps LTR while its text labels follow the document language. Its
   absolutely-positioned chrome (legend, guide, zoom) inherits this, which is why
   those rules in advanced.css can keep using physical left/right. */
:root[dir="rtl"] .dag-canvas,
:root[dir="rtl"] .graph-canvas,
:root[dir="rtl"] .mode-graph,
:root[dir="rtl"] .topology-canvas {
  direction: ltr;
}

/* Off-canvas drawers (mobile) are placed with inset-inline-*, so they already
   sit on the correct edge under RTL — but they are hidden with translateX,
   which is a physical axis and does not flip. Without these the sidebar would
   slide out through the screen instead of tucking away behind its own edge. */
@media (max-width: 767px) {
  :root[dir="rtl"] .sidebar {
    transform: translateX(100%);
  }

  :root[dir="rtl"] .right-panel {
    transform: translateX(-100%);
  }

  :root[dir="rtl"] .sidebar.sidebar-open,
  :root[dir="rtl"] .right-panel.right-panel-open {
    transform: translateX(0);
  }
}

/* Identifiers, URLs, file paths, model strings and API keys are LTR sequences.
   Isolating them stops the bidi algorithm from reordering trailing punctuation
   when they sit inside a Persian sentence. */
:root[dir="rtl"] .model-id,
:root[dir="rtl"] .session-id,
:root[dir="rtl"] .api-key,
:root[dir="rtl"] .ltr-text,
:root[dir="rtl"] input[type="email"],
:root[dir="rtl"] input[type="url"],
:root[dir="rtl"] input[type="password"] {
  direction: ltr;
  text-align: start;
  unicode-bidi: isolate;
}

/* Numeric columns stay left-aligned-in-reading-order so decimal points line up
   regardless of direction. */
:root[dir="rtl"] .num,
:root[dir="rtl"] td.num {
  direction: ltr;
  unicode-bidi: isolate;
}

/* Language switcher --------------------------------------------------------- */

.lang-switcher {
  position: relative;
  display: inline-flex;
  align-items: center;
}

.lang-switcher-button {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 36px;
  padding: 6px 10px;
  background: transparent;
  border: 1px solid var(--color-border-interactive);
  border-radius: var(--radius-md, 6px);
  color: var(--color-text);
  font-size: var(--font-size-sm);
  transition: all 0.15s ease;
}

.lang-switcher-button:hover {
  border-color: var(--color-primary);
}

.lang-switcher-button:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

.lang-switcher-menu {
  position: absolute;
  inset-block-start: calc(100% + 4px);
  inset-inline-end: 0;
  z-index: 200;
  min-inline-size: 160px;
  padding: 4px;
  background: var(--glass-bg-strong);
  backdrop-filter: var(--glass-filter);
  -webkit-backdrop-filter: var(--glass-filter);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
}

.lang-switcher-menu[hidden] {
  display: none;
}

.lang-switcher-option {
  display: flex;
  align-items: center;
  justify-content: space-between;
  inline-size: 100%;
  min-height: 36px;
  padding: 8px 10px;
  background: transparent;
  border: 0;
  border-radius: var(--radius-sm, 4px);
  color: var(--color-text);
  font-size: var(--font-size-base);
  text-align: start;
  transition: all 0.15s ease;
}

.lang-switcher-option:hover {
  background: var(--color-surface-hover);
}

.lang-switcher-option:focus-visible {
  outline: 2px solid var(--color-focus-ring);
  outline-offset: -2px;
}

.lang-switcher-option[aria-selected="true"] {
  color: var(--color-primary);
  font-weight: 600;
}

/* Each option is written in its own language, so it must render in its own
   direction rather than inheriting the page's. */
.lang-switcher-option[data-locale="fa"] {
  direction: rtl;
}

/* On an English/Spanish/French page this «فارسی» label is the only Arabic on the
   whole document — and it is enough to match the Vazirmatn unicode-range and pull
   down 111 KB for one word. Dropping Vazirmatn from this one element's stack
   means non-Persian visitors never fetch the font at all; the label falls back to
   the platform's Arabic face, which is perfectly legible for a menu item. A
   Persian visitor is excluded because their page loads the font regardless, and
   the switcher should match the rest of their UI. */
:root:not([data-locale="fa"]) .lang-switcher-option[data-locale="fa"] {
  font-family: "IBM Plex Sans", "Inter", system-ui, sans-serif;
}
