/* ==========================================================================
   SabaCell — Growth Engine
   One stylesheet, both locales. Layout uses logical properties throughout,
   so the Persian/RTL page needs almost no overrides.
   ========================================================================== */

/* ---------- fonts ----------
   Self-hosted. No third-party requests anywhere on this site.
   Archivo and Vazirmatn are single variable files covering 100–900;
   IBM Plex ships as static instances, so only the two weights we use.
   unicode-range means the Persian page never downloads the Latin-only
   families, and the English page never downloads the Arabic subset.
   Licences: assets/fonts/LICENSE-*.txt (all SIL OFL 1.1). */

@font-face {
  font-family: "Archivo";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("../fonts/archivo-latin-var.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/ibm-plex-sans-400.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/ibm-plex-sans-500.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/ibm-plex-mono-400.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* Five glyphs of Vazirmatn, for the word "فارسی" in the English page's
   language switcher. Without it the English page would pull the full 46 KB
   Arabic face to render one link. */
@font-face {
  font-family: "Vazirmatn Nav";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("../fonts/vazirmatn-nav-subset.woff2") format("woff2");
  unicode-range: U+0600-06FF, U+200C;
}

@font-face {
  font-family: "Vazirmatn";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("../fonts/vazirmatn-arabic-var.woff2") format("woff2");
  unicode-range: U+0600-06FF, U+0750-077F, U+0870-088E, U+0890-0891, U+0897-08E1, U+08E3-08FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE70-FE74, U+FE76-FEFC;
}
@font-face {
  font-family: "Vazirmatn";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("../fonts/vazirmatn-latin-var.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ---------- tokens ---------- */
:root {
  --red: #d2313c;
  --red-deep: #8e1f27;
  --ink: #16181c;
  --slate: #5c6169;
  --quiet: #6e747c;
  --muted: #8e939b;
  --paper: #f7f4f0;
  --paper-deep: #ede8e1;
  --white: #fff;

  --line: rgba(22, 24, 28, 0.12);
  --line-dark: rgba(255, 255, 255, 0.1);
  --on-dark: rgba(255, 255, 255, 0.72);
  --on-dark-quiet: rgba(255, 255, 255, 0.56);

  --font-display: "Archivo", ui-sans-serif, system-ui, "Segoe UI", sans-serif;
  --font-body: "IBM Plex Sans", ui-sans-serif, system-ui, "Segoe UI", sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, "SF Mono", "Cascadia Mono", monospace;

  --gutter: 24px;
  --margin: clamp(20px, 6vw, 88px);
  --section-y: clamp(64px, 8vw, 116px);
  --maxw: 1440px;

  --ease: cubic-bezier(0.2, 0.7, 0.2, 1);
}

/* Persian: different family, no negative tracking, more leading.
   --font-mono is remapped too — IBM Plex Mono has no Persian digits, and
   loading it for the two-letter "EN" link would be a wasted request. */
[lang="fa"] {
  --font-display: "Vazirmatn", ui-sans-serif, system-ui, "Segoe UI", Tahoma, sans-serif;
  --font-body: "Vazirmatn", ui-sans-serif, system-ui, "Segoe UI", Tahoma, sans-serif;
  --font-mono: "Vazirmatn", ui-sans-serif, system-ui, "Segoe UI", Tahoma, sans-serif;
}

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  /* the containing block for the background field, which spans the whole page */
  position: relative;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, h4 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 600;
  letter-spacing: -0.022em;
  text-wrap: balance;
}

[lang="fa"] h1,
[lang="fa"] h2,
[lang="fa"] h3,
[lang="fa"] h4 { letter-spacing: 0; font-weight: 700; line-height: 1.3; }

[lang="fa"] p,
[lang="fa"] li { line-height: 1.85; font-weight: 300; }

p { margin: 0; text-wrap: pretty; }
/* <address> is italic in every UA stylesheet. The class rule further down sets
   this too; it is repeated here on the bare element because a phone reported
   the head-office address rendering in italics, and a rule this early survives
   anything that goes wrong further down the file. */
address { font-style: normal; }
img, svg { max-width: 100%; }
a { color: var(--red); text-decoration: none; }
a:hover { color: var(--red-deep); }

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

.dark :focus-visible { outline-color: #fff; }

/* Moved with transform, not an off-canvas offset — a negative inset-inline-start
   becomes a positive right offset under dir="rtl" and drags the page sideways. */
.skip {
  position: absolute;
  top: 0;
  inset-inline-start: 0;
  z-index: 100;
  padding: 12px 20px;
  background: var(--red);
  color: #fff;
  transform: translateY(-200%);
}
.skip:focus { transform: none; color: #fff; }

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

/* ---------- layout ---------- */
.wrap {
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--margin);
}

.section { padding-block: var(--section-y); }
.section--paper { background: var(--paper); }
.section--deep { background: var(--paper-deep); }
.section--white { background: var(--white); }
.section--dark { background: var(--ink); color: #fff; }

.dark, .section--dark { color: #fff; }
.section--dark p { color: var(--on-dark); }
.section--dark h2, .section--dark h3 { color: #fff; }

.grid12 {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--gutter);
}

.stack { display: flex; flex-direction: column; }

/* ---------- the background field ----------------------------------------
   The hero's network spread thin over the whole page, so the page has a
   texture rather than a second picture. tools/build-field-art.py draws it and
   explains the shape; what matters here is the compositing.

   ONE LAYER, BOTH PALETTES. The drawing is mid-grey and blends with
   `difference`, so over paper it comes out dark and over graphite it comes
   out light. One file, no per-section variants, and no JavaScript deciding
   which colour it is sitting on.

   IT CROSSES THE WORDS. The layer is above the section backgrounds, so it
   also passes over the text. The alternative — a copy per section, each told
   its own offset so the drawing lines up across the joins — is a great deal
   of machinery for a decoration. At this strength a line crossing a glyph
   moves it by about 14 of 255, measured against a screenshot with the layer
   off; text contrast stays far inside AA. If that ever stops being true, the
   knob is the opacity below and nothing else.

   Everything that must stay clean sits above it: the header (50), the
   language menu (60), the skip link (100), and the hero (4) — the hero has
   its own network and does not want a second one behind it.

   `pointer-events: none` on both layers, so neither can ever eat a click. */
.bg-net,
.bg-sigs {
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  /* The drawing is cropped by the page, so a signal out on the cropped part
     is a positioned element sitting outside the layer — which would widen the
     document and hand the page a horizontal scrollbar on a phone. Clip it. */
  overflow: hidden;
}

/* INLINE SVG, NOT A BACKGROUND IMAGE — and this one is not a style choice.
   As `background-image` the drawing has to become a bitmap, and the bitmap is
   sized to the box it covers. On a phone that box is about 375 x 10,000 CSS
   px, `cover` widens the image to ~1,630 CSS px to fill it, and at device
   pixel ratio 2 that is a request to rasterise about 65 million pixels. Mobile
   Safari gives up somewhere above 16 million and simply paints nothing — no
   error, no warning, just a page with no field on it. Retina desktops are only
   a little better off. Inline, it is drawn as vectors: a thousand-odd line
   segments, no bitmap, no ceiling.

   `preserveAspectRatio="xMidYMin slice"` on the <svg> is exactly what
   `background-size: cover` with `background-position: center top` used to do —
   scale by whichever axis needs more, centre the overspill, pin the top — so
   the arithmetic in `site.js` that puts the signals on the lines is unchanged.

   Bucketed into about a dozen <path>s by opacity rather than one per line;
   1,058 elements inline in two pages was not worth the fidelity. */
.bg-net {
  mix-blend-mode: difference;
  opacity: 0.16;
}
.bg-net__art {
  display: block;
  width: 100%;
  height: 100%;
}

/* The signals are a layer of their own, unblended, so they can be the brand
   red — `difference` would turn red into cyan over pale paper. */
.bg-sig {
  position: absolute;
  width: 18px;
  height: 18px;
  /* centres the dot on its point; physical margins to match the physical
     `left`/`top` below, so this is the same under dir="rtl" */
  margin: -9px 0 0 -9px;
  border-radius: 50%;
  background: radial-gradient(circle,
    rgba(210, 49, 60, 0.95) 0 13%,
    rgba(210, 49, 60, 0.40) 33%,
    rgba(210, 49, 60, 0) 68%);
  opacity: 0.6;
}

.hero { position: relative; z-index: 4; }

/* ---------- type ---------- */
.eyebrow {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--red);
}
[lang="fa"] .eyebrow {
  font-family: var(--font-body);
  letter-spacing: 0;
  text-transform: none;
  font-size: 13px;
  font-weight: 500;
}

.h-hero {
  font-size: clamp(52px, 7.6vw, 108px);
  line-height: 0.94;
  letter-spacing: -0.035em;
}
[lang="fa"] .h-hero { font-size: clamp(44px, 6.6vw, 92px); line-height: 1.18; letter-spacing: 0; }

.h-section { font-size: clamp(32px, 3.8vw, 52px); line-height: 1.06; }
[lang="fa"] .h-section { font-size: clamp(28px, 3.4vw, 46px); line-height: 1.34; }

.lede { font-size: clamp(16.5px, 1.4vw, 20px); line-height: 1.58; color: var(--slate); }
.section--dark .lede { color: var(--on-dark); }

.body-sm { font-size: 15px; line-height: 1.62; color: var(--slate); }
.meta { font-size: 13px; line-height: 1.55; color: var(--quiet); }

/* ---------- header ---------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--ink);
  border-bottom: 1px solid var(--line-dark);
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  min-height: 72px;
  padding-block: 8px;
}

/* The logo is the real lockup, reversed (white wordmark) for the dark header.
   width/height are on the <img> so it reserves its space before it loads. */
.brand { display: inline-flex; align-items: center; color: #fff; }
.brand:hover { color: #fff; }
.brand__logo { display: block; height: 38px; width: auto; }

@media (max-width: 760px) {
  .brand__logo { height: 32px; }
}

.nav { display: flex; align-items: center; gap: clamp(16px, 2vw, 34px); }
.nav a {
  font-size: 14px;
  color: var(--on-dark);
  padding-block: 10px;
}
.nav a:hover { color: #fff; }

.header__end { display: flex; align-items: center; gap: 16px; }

/* ---------- language picker ----------
   A <details> element, so it opens and closes with zero JavaScript.
   site.js only adds outside-click and Escape dismissal. */
.langpicker { position: relative; }

.langpicker__toggle {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 44px;
  padding-inline: 10px;
  color: var(--on-dark-quiet);
  cursor: pointer;
  user-select: none;
  list-style: none;
  transition: color 140ms var(--ease);
}
.langpicker__toggle::-webkit-details-marker { display: none; }
.langpicker__toggle::marker { content: ""; }
.langpicker__toggle:hover,
.langpicker[open] .langpicker__toggle { color: #fff; }

.langpicker__globe { width: 20px; height: 20px; flex-shrink: 0; }
.langpicker__code {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
}
[lang="fa"] .langpicker__code { letter-spacing: 0; font-size: 14px; }
.langpicker__caret {
  width: 11px;
  height: 11px;
  flex-shrink: 0;
  transition: transform 160ms var(--ease);
}
.langpicker[open] .langpicker__caret { transform: rotate(180deg); }

.langpicker__menu {
  position: absolute;
  top: calc(100% + 8px);
  inset-inline-end: 0;
  z-index: 60;
  min-width: 184px;
  margin: 0;
  padding: 6px;
  list-style: none;
  background: #1e2127;
  border: 1px solid rgba(255, 255, 255, 0.14);
  box-shadow: 0 14px 36px rgba(0, 0, 0, 0.45);
}

.langpicker__opt {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  min-height: 44px;
  padding-inline: 12px;
  font-size: 15px;
  color: rgba(255, 255, 255, 0.78);
}
.langpicker__opt:hover { background: rgba(255, 255, 255, 0.07); color: #fff; }
.langpicker__opt[aria-current="true"] { color: #fff; }
.langpicker__check { width: 15px; height: 15px; flex-shrink: 0; color: var(--red); }

/* Each locale's menu names the other language in its own script. On the English
   page «فارسی» is the only Persian text on the page — serve it the 5 KB subset
   rather than the full 46 KB Arabic face. */
html[lang="en"] .langpicker__opt[lang="fa"] { font-family: "Vazirmatn Nav", Tahoma, sans-serif; }
/* On the Persian page "English" is drawn by Vazirmatn's own Latin subset,
   which that page already loads — so it costs nothing extra. */

.nav-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 44px; height: 44px;
  background: none;
  border: 0;
  cursor: pointer;
  color: #fff;
}

/* ---------- buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 52px;
  padding-inline: 28px;
  font-size: 15px;
  font-weight: 500;
  border: 1px solid transparent;
  transition: background-color 160ms var(--ease), border-color 160ms var(--ease);
}
.btn--primary { background: var(--red); color: #fff; }
.btn--primary:hover { background: var(--red-deep); color: #fff; }
.btn--ghost-dark { border-color: rgba(255, 255, 255, 0.24); color: #fff; }
.btn--ghost-dark:hover { border-color: #fff; color: #fff; }
.btn--ghost { border-color: rgba(22, 24, 28, 0.28); color: var(--ink); }
.btn--ghost:hover { border-color: var(--ink); color: var(--ink); }
.btn--sm { min-height: 44px; padding-inline: 22px; font-size: 14px; }

/* A status, not a control. Same height as the buttons beside it so the row
   still aligns, but outlined rather than filled and with no hover or pointer,
   so nobody tries to click it.
   Selector is `p.badge`, not `.badge`: `.section--dark p` would otherwise win
   on specificity and dim it back to body-copy grey. */
p.badge {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-height: 52px;
  padding-inline: 22px;
  border: 1px solid rgba(210, 49, 60, 0.5);
  background: rgba(210, 49, 60, 0.1);
  color: #fff;
  font-size: 15px;
  font-weight: 500;
  cursor: default;
}
.badge__dot {
  width: 7px;
  height: 7px;
  flex-shrink: 0;
  border-radius: 50%;
  background: var(--red);
}

.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  font-size: 15px;
  font-weight: 500;
  color: var(--ink);
}
.link-arrow:hover { color: var(--red-deep); }
.link-arrow svg { flex-shrink: 0; }
[dir="rtl"] .link-arrow svg { transform: scaleX(-1); }
.link-arrow--on-dark { color: #fff; }
.link-arrow--on-dark:hover { color: #fff; }

/* ---------- hero ---------- */
.hero { background: var(--ink); color: #fff; padding-block: clamp(44px, 6vw, 96px) clamp(40px, 6vw, 104px); }
.hero__grid { align-items: center; }
/* 6/6 rather than 7/5. The headline still fits — "Built for" at its largest is
   about 450px and the column is 620 — and the artwork stops floating in a
   column too small for it. */
.hero__copy { grid-column: span 6; display: flex; flex-direction: column; gap: clamp(24px, 2.6vw, 34px); }
.hero__art { grid-column: span 6; display: flex; justify-content: flex-end; }
[dir="rtl"] .hero__art { justify-content: flex-end; }
/* Scale proportionally instead of letterboxing inside a fixed 470px box. */
.hero__art svg { width: 100%; max-width: 760px; height: auto; }

.hero__kicker {
  display: flex;
  align-items: center;
  gap: 14px;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--on-dark-quiet);
}
[lang="fa"] .hero__kicker {
  font-family: var(--font-body);
  letter-spacing: 0;
  text-transform: none;
  font-size: 14px;
}
.hero__rule { width: 28px; height: 1px; background: var(--red); flex-shrink: 0; }
.hero__lede { max-width: 560px; color: var(--on-dark); }
.hero__cta { display: flex; flex-wrap: wrap; align-items: center; gap: 16px; }

.hero__strip {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px clamp(24px, 3vw, 48px);
  /* Was clamp(48px, 6vw, 86px). That plus the dead space inside the artwork's
     box left a hole under BUILD about as tall as the strip itself. */
  margin-top: clamp(18px, 2.4vw, 38px);
  padding-top: 28px;
  border-top: 1px solid var(--line-dark);
}
.hero__strip-label {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--on-dark-quiet);
}
[lang="fa"] .hero__strip-label { font-family: var(--font-body); letter-spacing: 0; text-transform: none; font-size: 13px; }
.hero__strip-list {
  display: flex;
  flex-wrap: wrap;
  gap: 10px clamp(20px, 2.6vw, 44px);
  font-family: var(--font-display);
  font-size: 17px;
  font-weight: 500;
  color: rgba(255, 255, 255, 0.6);
}
.hero__strip-list .is-ours { color: var(--red); }
/* The three operating businesses link out. Resting state is deliberately
   unchanged — this strip is a list of names, not a nav, and underlining three
   of four items would make the fourth look broken. The affordance arrives on
   hover and focus, in the same underline the contact email uses. */
.hero__strip-list a {
  color: inherit;
  text-decoration: none;
}
.hero__strip-list a:hover,
.hero__strip-list a:focus-visible {
  color: #fff;
  text-decoration: underline;
  text-underline-offset: 5px;
}

/* ---------- section head ---------- */
.sechead { margin-bottom: clamp(38px, 5vw, 68px); }
.sechead__label { grid-column: span 4; }
.sechead__body { grid-column: span 8; display: flex; flex-direction: column; gap: 22px; }
.sechead__body .lede { max-width: 640px; }

/* ---------- how we work ---------- */
.verbs {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1px;
  background: var(--line);
  border-block: 1px solid var(--line);
}
.verb {
  display: flex;
  flex-direction: column;
  gap: 26px;
  padding: 40px clamp(20px, 2.4vw, 34px) 44px;
  background: var(--paper);
}
.verb__icon { width: 52px; height: 52px; }
.verb h3 { font-size: 24px; }

/* ---------- enterprise AI ---------- */
.cards3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--gutter); }
.aicard {
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 34px 30px 38px;
  background: rgba(255, 255, 255, 0.04);
  border-top: 2px solid rgba(255, 255, 255, 0.2);
}
.aicard--lead { border-top-color: var(--red); }
.aicard__n { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.14em; color: rgba(255, 255, 255, 0.5); }
[lang="fa"] .aicard__n { letter-spacing: 0; font-size: 12.5px; }
.aicard h3 { font-size: 21px; }
.aicard p { font-size: 15px; line-height: 1.62; color: rgba(255, 255, 255, 0.66); }

.section__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  margin-top: 56px;
  padding-top: 34px;
  border-top: 1px solid var(--line-dark);
}
.section__foot p:not(.badge) { max-width: 620px; color: rgba(255, 255, 255, 0.55); }

/* ---------- businesses ---------- */
.biz { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px; }
.bizcard {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 40px;
  min-height: 268px;
  padding: 36px clamp(22px, 2.4vw, 34px);
  background: var(--white);
  border: 1px solid rgba(22, 24, 28, 0.1);
}
.bizcard--ours { background: var(--ink); border-color: var(--ink); }
.bizcard--ours p { color: rgba(255, 255, 255, 0.66); }
.bizcard__top { display: flex; align-items: center; justify-content: space-between; gap: 20px; flex-wrap: wrap; }
.bizcard__name {
  font-family: var(--font-display);
  font-size: clamp(24px, 2.2vw, 30px);
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--ink);
}
[lang="fa"] .bizcard__name { letter-spacing: 0; }
/* The brand name is the obvious click target, so it links too. It keeps the ink
   colour — red would read as a link before it reads as a brand — and only
   colours on hover. */
.bizcard__name a { color: inherit; }
.bizcard__name a:hover { color: var(--red); }
.bizcard--ours .bizcard__name { color: #fff; font-weight: 600; font-size: clamp(21px, 1.9vw, 26px); }
.bizcard__role {
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--quiet);
  white-space: nowrap;
}
[lang="fa"] .bizcard__role { font-family: var(--font-body); letter-spacing: 0; text-transform: none; font-size: 12px; }
.bizcard--ours .bizcard__role { color: var(--red); }
.bizcard p { font-size: 16px; line-height: 1.6; color: var(--slate); max-width: 460px; }
.bizcard__id { display: flex; align-items: center; gap: 12px; }

/* ---------- track record ---------- */
.ventures { display: flex; flex-direction: column; border-top: 1px solid rgba(22, 24, 28, 0.14); }
.venture {
  display: grid;
  grid-template-columns: 220px minmax(0, 1fr) 200px;
  gap: 32px;
  align-items: center;
  padding-block: 30px;
  border-bottom: 1px solid rgba(22, 24, 28, 0.14);
}
.venture:last-child { border-bottom: 0; padding-block: 24px; }
.venture__name {
  font-family: var(--font-display);
  font-size: 26px;
  font-weight: 600;
  letter-spacing: -0.02em;
}
[lang="fa"] .venture__name { letter-spacing: 0; font-weight: 700; }
/* Same treatment as the business cards: the name carries the link, colour is
   inherited so the .venture--quiet / --faint hierarchy still decides how loud
   each one is, and red arrives only on hover. */
.venture__name a { color: inherit; }
.venture__name a:hover,
.venture__name a:focus-visible { color: var(--red); }
.venture p { font-size: 16px; line-height: 1.55; color: var(--slate); }
.venture__status { display: flex; justify-content: flex-end; }
[dir="rtl"] .venture__status { justify-content: flex-start; }

.venture--quiet .venture__name { font-size: 22px; font-weight: 500; color: #454a52; }
.venture--quiet p { font-size: 15px; color: var(--slate); }
.venture--faint .venture__name { font-size: 17px; font-weight: 500; color: var(--quiet); }
.venture--faint p { font-size: 14px; color: var(--quiet); }

.status {
  display: inline-flex;
  align-items: center;
  min-height: 30px;
  padding-inline: 14px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  white-space: nowrap;
}
[lang="fa"] .status { font-family: var(--font-body); letter-spacing: 0; text-transform: none; font-size: 12px; }
.status--solid { background: var(--red); color: #fff; }
.status--outline { border: 1px solid var(--ink); color: var(--ink); }
.status--quiet { border: 1px solid rgba(22, 24, 28, 0.28); color: var(--slate); }
.status--bare { padding-inline: 0; color: var(--quiet); font-size: 10.5px; }

/* ---------- story ---------- */
.story {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 20px;
  padding-top: 34px;
  border-top: 1px solid rgba(22, 24, 28, 0.14);
  /* These three were an inline style on the <ol>. They live here now so the
     horizontal mode further down can set padding-inline without an inline
     declaration beating it. */
  list-style: none;
  margin: 0;
  padding-inline-start: 0;
}

/* `.story` is a SIBLING of `.wrap`, not a child of it. It has to be: the
   sideways rail is full-bleed and cannot live inside a centred, padded column.
   The cost is that the plain-timeline fallback had no margins at all — on a
   wide screen with the sideways mode off, the five panels ran edge to edge and
   the first and last were cut in half by the window, which is exactly what was
   reported from a remote desktop. It carries the wrap's geometry itself. The
   sideways block further down overrides all three. */
.hscroll .story {
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--margin);
}

/* The hint and the progress bar exist only for the horizontal mode. Off by
   default, so a browser that never enters that mode never advertises a
   sideways scroll that isn't going to happen. */
.hscroll__hint,
.hscroll__progress { display: none; }
.step { display: flex; flex-direction: column; gap: 14px; }
.step__bar { height: 3px; background: rgba(22, 24, 28, 0.16); }
.step--now .step__bar, .step--first .step__bar { background: var(--red); }
.step__when { font-family: var(--font-mono); font-size: 12px; letter-spacing: 0.1em; color: var(--quiet); }
[lang="fa"] .step__when { font-family: var(--font-body); letter-spacing: 0; }
.step--first .step__when { color: var(--ink); }
.step--now .step__when { color: var(--red); }
.step h3 { font-size: 19px; }
.step p { font-size: 14.5px; line-height: 1.6; color: var(--slate); }

/* ---------- beyond business ---------- */
.beyond__intro { grid-column: span 4; display: flex; flex-direction: column; gap: 20px; }
.beyond__intro h2 { font-size: clamp(28px, 2.6vw, 36px); line-height: 1.12; }
.beyond__item { grid-column: span 4; display: flex; flex-direction: column; gap: 14px; border-top: 2px solid rgba(22, 24, 28, 0.16); }
.beyond__item--lead { border-top-color: var(--red); }
.beyond__item h3 { font-size: 21px; padding-top: 16px; }
.beyond__item h3 a { color: inherit; }
.beyond__item h3 a:hover { color: var(--red); }
.beyond__item p { font-size: 15.5px; line-height: 1.62; color: var(--slate); }

/* ---------- contact / footer ---------- */
.contact { background: var(--ink); color: #fff; padding-block: clamp(56px, 7vw, 104px) 44px; }
.contact__grid { padding-bottom: clamp(40px, 5vw, 72px); border-bottom: 1px solid var(--line-dark); }
.contact__lead { grid-column: span 7; display: flex; flex-direction: column; gap: 26px; }
.contact__lead h2 { font-size: clamp(34px, 4.2vw, 58px); line-height: 1.02; }
[lang="fa"] .contact__lead h2 { line-height: 1.26; }
.contact__lead p { max-width: 500px; color: rgba(255, 255, 255, 0.6); }
.contact__details { grid-column: span 5; display: flex; flex-direction: column; gap: 30px; padding-top: clamp(0px, 3vw, 46px); }
.contact__label {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.5);
}
[lang="fa"] .contact__label { font-family: var(--font-body); letter-spacing: 0; text-transform: none; font-size: 12.5px; }
.contact__email {
  font-family: var(--font-display);
  font-size: clamp(20px, 2vw, 26px);
  font-weight: 500;
  color: #fff;
}
.contact__email:hover { color: #fff; text-decoration: underline; text-underline-offset: 4px; }
.contact__address {
  font-style: normal;               /* <address> italicises by default */
  font-size: 16px;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.78);
}
.contact__tel {
  font-size: 16px;
  color: rgba(255, 255, 255, 0.78);
  font-variant-numeric: tabular-nums;
}
.contact__tel:hover { color: #fff; }
[lang="fa"] .contact__tel { font-family: var(--font-mono); }
.contact__social { display: flex; flex-wrap: wrap; gap: 12px; }

.colophon {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px;
  padding-top: 34px;
}
.colophon__left { display: flex; flex-direction: column; gap: 10px; }
.colophon__brand { display: flex; align-items: center; }
.colophon__logo { display: block; height: 30px; width: auto; }
.colophon__line { font-size: 13px; color: rgba(255, 255, 255, 0.52); }
.colophon__legal { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 28px; font-size: 12.5px; color: rgba(255, 255, 255, 0.52); }
.colophon__legal a { color: rgba(255, 255, 255, 0.65); }
.colophon__legal a:hover { color: #fff; }

/* ---------- motion ----------
   Every animated element is visible by default; JS adds .is-armed to the
   document, which is the only thing that hides them before they reveal.
   No JS, no animation, no missing content. */
.js .reveal { opacity: 0; transform: translateY(10px); }
.js .reveal.is-in {
  opacity: 1;
  transform: none;
  transition: opacity 620ms var(--ease), transform 620ms var(--ease);
  transition-delay: var(--d, 0ms);
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .js .reveal, .js .reveal.is-in { opacity: 1; transform: none; transition: none; }
  /* The hero figure stops turning too — site.js checks the same query and
     never starts, leaving the frame that ships in the markup. */
}

/* ---------- responsive ---------- */
@media (max-width: 1080px) {
  .hero__copy, .hero__art { grid-column: span 12; }
  .hero__art { justify-content: flex-start; }
  [dir="rtl"] .hero__art { justify-content: flex-start; }
  .sechead__label, .sechead__body { grid-column: span 12; }
  .verbs { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .cards3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .story { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 32px 20px; }
  .contact__lead, .contact__details { grid-column: span 12; }
  .contact__details { padding-top: 0; }
  .beyond__intro, .beyond__item { grid-column: span 6; }
}

@media (max-width: 760px) {
  .nav {
    display: none;
    position: absolute;
    inset-inline: 0;
    top: 100%;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: 8px var(--margin) 20px;
    background: var(--ink);
    border-bottom: 1px solid var(--line-dark);
  }
  .nav.is-open { display: flex; }
  .nav a { min-height: 48px; display: flex; align-items: center; font-size: 16px; }
  .nav-toggle { display: inline-flex; }
  .site-header__inner { position: relative; }

  .verbs { grid-template-columns: minmax(0, 1fr); }
  .cards3 { grid-template-columns: minmax(0, 1fr); }
  .biz { grid-template-columns: minmax(0, 1fr); }
  .story { grid-template-columns: minmax(0, 1fr); }
  .beyond__intro, .beyond__item { grid-column: span 12; }

  .venture { grid-template-columns: minmax(0, 1fr); gap: 12px; }
  .venture__status { justify-content: flex-start; }
  [dir="rtl"] .venture__status { justify-content: flex-start; }

  /* The header can't hold brand + language + CTA + toggle at this width.
     The CTA is repeated in the hero and the Enterprise AI section, so drop it here. */
  .header__end > .btn { display: none; }
  .header__end { gap: 8px; }

  .hero__cta { flex-direction: column; align-items: stretch; }
  .hero__cta .btn { width: 100%; }
  .hero__cta .badge { width: 100%; justify-content: center; }
}

/* ---------- 06 · the sideways section ----------------------------------------

   Section 06 turns the page sideways: you scroll down, the section takes over
   the screen and the story runs left to right, then the page carries on down.

   Three nested elements, each with exactly one job:

     .hscroll__track   a tall block. Its height IS the length of the detour.
     .hscroll__stage   sticks to the viewport while the track passes through it.
     .story (the rail) a row wider than the screen, slid by the scroll position.

   No JavaScript. No scroll listener, no requestAnimationFrame, no library —
   a CSS scroll-driven animation, which the browser runs off the main thread,
   so it can't stutter the way a JS-driven pin does.

   The pin lasts exactly as long as the track takes to cross the viewport, and
   `animation-range: contain` is the same interval expressed as a timeline, so
   the rail finishes its travel on the exact frame the stage unsticks. Neither
   number needs tuning against the other.

   This block sits last on purpose: it has to win over the responsive rules
   above, which reshape .story for narrow screens.

   THE SITE DOES NOT DEPEND ON ANY OF IT. Three separate conditions have to
   hold before a single line here applies — the browser must support
   scroll-driven animations, the viewport must be wide enough for panels to
   make sense, and the visitor must not have asked for less motion. Fail any
   one and section 06 is the plain five-column timeline it has always been,
   with the same markup and the same words. Hijacking someone's scroll is a
   thing to do carefully, and never to someone who has switched it off.

   AND A FOURTH CONDITION, CHECKED AT RUNTIME. `@supports` proved not to be
   enough: some browsers answer yes to it and then never attach the timeline,
   which leaves the rail laid out as a row wider than the screen, pinned, and
   never sliding — the first and last panels clipped off the edges with no way
   to reach them. So every selector below is wrapped in
   `:where(html:not(.no-sideways))`, which costs no specificity, and `site.js`
   adds that class if it finds the rail animating on no timeline. The two
   `[lang=]`/`[dir=]` rules are left unwrapped on purpose: those attributes sit
   on <html> itself, so an html ancestor in front of them would never match. */

@supports (animation-timeline: view()) {
  @media (min-width: 900px) and (prefers-reduced-motion: no-preference) {

    :where(html:not(.no-sideways)) .hscroll {
      /* the stage supplies the vertical rhythm now — the section must not
         also pay for it, or the pin starts below the fold */
      padding-block: 0;
    }

    :where(html:not(.no-sideways)) .hscroll__track {
      /* One screenful to pin, plus 3.2 panel-widths of detour. Tying the
         length to the panel width rather than to vh keeps the feel constant:
         a wider screen shows more panels at once and needs less scrolling,
         and this scales with it automatically. */
      --panel: min(520px, 46vw);
      height: calc(100vh + 3.2 * var(--panel));
      view-timeline-name: --story-track;
      view-timeline-axis: block;
    }

    :where(html:not(.no-sideways)) .hscroll__stage {
      position: sticky;
      top: 0;
      height: 100vh;
      display: flex;
      flex-direction: column;
      justify-content: center;
      gap: clamp(24px, 4vh, 52px);
      overflow: hidden;
    }

    /* .wrap carries margin-inline:auto, and an auto cross-axis margin on a
       flex item beats align-items:stretch — the wrap would shrink to its
       content and centre, throwing the heading off the panel grid. */
    :where(html:not(.no-sideways)) .hscroll__stage > .wrap { width: 100%; }

    :where(html:not(.no-sideways)) .hscroll__head { margin-bottom: 0; }

    :where(html:not(.no-sideways)) .hscroll .story {
      display: flex;
      width: max-content;
      gap: var(--gutter);
      /* The vertical timeline draws one rule across the top of the whole row.
         Here each panel already carries its own, and the five of them read as
         the axis — two parallel lines 35px apart just looked like a mistake. */
      border-top: 0;
      padding-top: 0;
      /* Line the first panel up with the heading above it. The percentage
         resolves against the stage, which is the viewport's width. */
      padding-inline: max(var(--margin), calc((100% - var(--maxw)) / 2));
      /* undo the fallback geometry added above — the rail is full-bleed */
      max-width: none;
      margin-inline: 0;
      animation: hscroll-rail linear both;
      animation-timeline: --story-track;
      animation-range: contain 0% contain 100%;
    }

    :where(html:not(.no-sideways)) .hscroll .step {
      flex: 0 0 var(--panel, min(520px, 46vw));
      min-height: min(34vh, 264px);
      gap: 18px;
    }
    /* Rule stays at the top of the panel, the words drop to a shared baseline.
       Five panels of unequal text then line up along the bottom instead of
       ragging off the top, which is what makes the row read as one band. */
    :where(html:not(.no-sideways)) .hscroll .step__bar { margin-bottom: auto; }
    :where(html:not(.no-sideways)) .hscroll .step h3 { font-size: clamp(21px, 2vw, 30px); }
    :where(html:not(.no-sideways)) .hscroll .step p { font-size: clamp(15px, 1.1vw, 17px); }

    /* Tells the reader what just happened to their scroll, then gets out of
       the way once they've seen it move. */
    :where(html:not(.no-sideways)) .hscroll__hint {
      display: flex;
      align-items: center;
      gap: 10px;
      font-family: var(--font-mono);
      font-size: 12px;
      letter-spacing: 0.1em;
      text-transform: uppercase;
      color: var(--quiet);
      animation: hscroll-hint linear both;
      animation-timeline: --story-track;
      animation-range: contain 0% contain 18%;
    }
    [lang="fa"] .hscroll__hint { font-family: var(--font-body); letter-spacing: 0; text-transform: none; }
    :where(html:not(.no-sideways)) .hscroll__hint svg { flex-shrink: 0; }
    [dir="rtl"] .hscroll__hint svg { transform: scaleX(-1); }

    :where(html:not(.no-sideways)) .hscroll__progress {
      display: block;
      height: 2px;
      margin-inline: max(var(--margin), calc((100% - var(--maxw)) / 2));
      background: rgba(22, 24, 28, 0.14);
    }
    :where(html:not(.no-sideways)) .hscroll__progress > span {
      display: block;
      height: 100%;
      background: var(--red);
      transform: scaleX(0);
      transform-origin: left center;
      animation: hscroll-progress linear both;
      animation-timeline: --story-track;
      animation-range: contain 0% contain 100%;
    }
    [dir="rtl"] .hscroll__progress > span { transform-origin: right center; }
  }
}

/* 100% is the rail's own width; 100vw is the viewport. The difference is how
   far it has to travel. RTL lays the rail out from the right and it has to
   travel the other way, which is all --hdir does.

   100vw counts the classic scrollbar and the rail's travel doesn't, so the
   last panel can stop up to a scrollbar's width early. The trailing padding on
   the rail is far wider than any scrollbar, so it is never visible. */
@keyframes hscroll-rail {
  to { transform: translateX(calc((100vw - 100%) * var(--hdir, 1))); }
}
[dir="rtl"] .hscroll .story { --hdir: -1; }

@keyframes hscroll-progress { to { transform: scaleX(1); } }
@keyframes hscroll-hint { to { opacity: 0; transform: translateY(-6px); } }

@media print {
  .site-header, .hero__art, .nav-toggle { display: none; }
  body { background: #fff; color: #000; }
}
