@charset "UTF-8";
/* ==========================================================================
   نور — قالب اختصاصی محسن نورمحمدی
   --------------------------------------------------------------------------
   ایده‌ی مرکزی: «جعبه‌ی سیاه و یک منبع نور».
   نام او خودش «نور» را در خود دارد؛ کل سایت همان یک ایده را تکرار می‌کند —
   چیزها از دل سیاهی، با نور، پیدا می‌شوند.

   پالت از خودِ عکس‌ها استخراج شده است، نه از یک تم آماده:
   ۶۳٪ پیکسل‌های آرشیو او سیاه یا سایه‌ی عمیق است، تنها رنگ واقعی
   کهربای نور صحنه (hue ۲۰°–۵۰°) است و یک قرمزِ اشباع (hue ۳۵۰°).

   فهرست:
   ۰۱ توکن‌ها
   ۰۲ فونت‌ها
   ۰۳ پایه و ریست
   ۰۴ تایپوگرافی
   ۰۵ لایه‌های صحنه (نور، دانه، پرده)
   ۰۶ سربرگ و ناوبری
   ۰۷ پرده‌ی یکم — ورود
   ۰۸ پرده‌ی دوم — اجراها
   ۰۹ پرده‌ی سوم — کار
   ۰۹.۵ میان‌پرده — قاب‌ها
   ۱۰ پرده‌ی چهارم — تماس
   ۱۱ صفحه‌ی تکی اجرا
   ۱۲ پابرگ
   ۱۳ حرکت و آشکارسازی
   ۱۴ واکنش‌گرایی
   ۱۵ دسترس‌پذیری و ترجیح کاهش حرکت
   ========================================================================== */

/* ==========================================================================
   ۰۱ — توکن‌ها
   ========================================================================== */

:root {
  /* --- جعبه‌ی سیاه --- */
  --void: #08080a;
  --shadow: #0f0f12;
  --ash: #17171b;
  --iron: #26262c;
  --steel: #3a3a42;
  --smoke: #7c7770;
  --dust: #a9a39a;
  --bone: #ede7dc;

  /* --- نور صحنه (کهربای تنگستن) --- */
  --tungsten: #e9a94f;
  --tungsten-hi: #f5c882;
  --tungsten-dim: #8a6633;
  --glow: rgba(233, 169, 79, 0.13);
  --glow-soft: rgba(233, 169, 79, 0.05);

  /* --- تنها رنگ اشباع آرشیو --- */
  --crimson: #e01b3c;
  /* قرمزِ صحنه روی سیاه فقط ۴.۴:۱ می‌دهد؛ این نسخه‌ی روشن‌تر برای
     متنِ خطا است و ۷.۳:۱ می‌دهد. */
  --crimson-soft: #f08098;

  /* --- نقش‌ها --- */
  --bg: var(--void);
  --fg: var(--bone);
  --muted: var(--dust);
  --line: rgba(237, 231, 220, 0.11);
  --line-soft: rgba(237, 231, 220, 0.06);

  /* --- تایپ --- */
  --font-display: "Estedad", "Vazirmatn", "Tahoma", sans-serif;
  --font-text: "Vazirmatn", "Tahoma", sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, "Courier New", monospace;

  /* مقیاس سیال. ارتفاع خط فارسی سخاوتمندتر از لاتین است چون
     حروفی مثل ج/چ/ح دنباله‌ی عمیق دارند. */
  /* ۲۳vh تقریباً هیچ‌وقت روی نمایشگرِ سالم اثر ندارد (روی ۱۴۴۰×۹۰۰ فرقش
     یک پیکسل است) و فقط وقتی وارد می‌شود که پنجره کوتاه باشد. لازم است
     چون صحنه قفل می‌شود: پرده‌ای که در یک قاب جا نشود، قفل‌شدنش معنا
     ندارد و ته متن بریده می‌شود. */
  --t-hero: clamp(3.4rem, min(15vw, 23vh), 13rem);
  /* میان‌پرده فقط دو کلمه دارد، پس می‌تواند از هیرو هم درشت‌تر برود. */
  --t-strip: clamp(3rem, min(20vw, 26vh), 15rem);
  --t-giant: clamp(2.6rem, 9vw, 7.5rem);
  --t-display: clamp(2rem, 5.5vw, 4.25rem);
  --t-title: clamp(1.5rem, 3.2vw, 2.4rem);
  --t-lead: clamp(1.12rem, 1.9vw, 1.5rem);
  --t-body: clamp(1rem, 1.05vw, 1.09rem);
  --t-small: 0.92rem;
  /* ۱۲ پیکسل، نه کمتر: زیر این اندازه برچسب‌های تک‌عرضِ لاتین
     روی پس‌زمینه‌ی سیاه واقعاً سخت‌خوان می‌شوند. */
  --t-label: 0.75rem;

  /* رنگ «خاموش» عنوان اجراها.
     وسوسه این بود که تا قبل از افتادن نور تقریباً نامرئی باشد (--iron)،
     اما آن حالت نسبت کنتراست ۱.۳:۱ می‌داد یعنی عنوانِ اصلی محتوا عملاً
     خوانده نمی‌شد. این مقدار ۴.۵:۱ می‌دهد و هنوز به‌قدر کافی «در سایه» است
     که روشن‌شدنش زیر نور یک اتفاق واقعی به نظر برسد. */
  --title-rest: #7c7770;

  --lh-hero: 0.98;
  --lh-display: 1.14;
  --lh-title: 1.35;
  --lh-body: 1.95;

  /* --- فاصله (چگالی کم / سخاوتمند) --- */
  --s-1: 0.5rem;
  --s-2: 1rem;
  --s-3: 1.5rem;
  --s-4: 2rem;
  --s-5: 3rem;
  --s-6: 4rem;
  --s-7: 6rem;
  --s-8: 8rem;
  --s-9: 12rem;

  --gutter: clamp(1.25rem, 5vw, 5.5rem);
  --measure: 34rem;
  --max: 96rem;

  /* --- منحنی‌های اختصاصی --- */
  /* بالا آمدن دیمر: سریع شروع، آرام می‌نشیند */
  --ease-dimmer: cubic-bezier(0.16, 1, 0.3, 1);
  /* بلک‌اوت: آرام شروع، ناگهان قطع */
  --ease-blackout: cubic-bezier(0.7, 0, 0.84, 0);
  /* کیو: متعادل، برای جابه‌جایی‌ها */
  --ease-cue: cubic-bezier(0.65, 0, 0.35, 1);
  --ease-soft: cubic-bezier(0.33, 1, 0.68, 1);
  /* بادبزن: کمی از مقصد رد می‌شود و برمی‌گردد — تابِ ورقِ کاغذ */
  --ease-fan: cubic-bezier(0.2, 1.32, 0.36, 1);

  --dur-fast: 180ms;
  --dur: 320ms;
  --dur-slow: 780ms;
  --dur-cue: 1100ms;

  /* مسافتی که صحنه قفل می‌ماند و درها در آن باز می‌شوند. فهرست اجراها
     هم از همین عدد استفاده می‌کند تا دقیقاً سرِ همان لحظه به قاب برسد. */
  --runway: 170svh;
  /* مسافتِ خاموش شدنِ فهرست و بالا آمدنِ نور روی پرده‌ی سوم */
  --lift: 130svh;
  /* مسافتِ اسکرول برای هر ورقِ پشته‌ی اجراها */
  --card-step: 80svh;
  /* مسافتِ «رسیدن» به میان‌پرده: خاموشیِ پرده‌ی سوم، عقب نشستنِ تایپ،
     و بعد باز شدنِ ورق‌ها */
  --arrive: 95svh;
  /* مکثِ بعد از رسیدن */
  --hold: 55svh;

  --z-grain: 60;
  --z-spot: 55;
  --z-header: 70;
  --z-loader: 90;
}

/* ==========================================================================
   ۰۲ — فونت‌ها (محلی، متغیر، زیرمجموعه‌شده)
   ========================================================================== */

@font-face {
  font-family: "Estedad";
  src: url("../fonts/estedad-var.woff2") format("woff2-variations");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0600-06FF, U+200C-200F, U+FB50-FDFF, U+FE70-FEFF, U+0020-007E,
    U+00A0-00FF, U+2000-206F;
}

@font-face {
  font-family: "Vazirmatn";
  src: url("../fonts/vazirmatn-var.woff2") format("woff2-variations");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0600-06FF, U+200C-200F, U+FB50-FDFF, U+FE70-FEFF, U+0020-007E,
    U+00A0-00FF, U+2000-206F;
}

@font-face {
  font-family: "JetBrains Mono";
  src: url("../fonts/jbmono-var.woff2") format("woff2-variations");
  font-weight: 100 800;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0020-007E, U+00A0-00FF, U+2000-206F;
}

/* ==========================================================================
   ۰۳ — پایه و ریست
   ========================================================================== */

*,
*::before,
*::after {
  box-sizing: border-box;
}

* {
  margin: 0;
  padding: 0;
}

html {
  /* نوار اسکرول حذف می‌شود: در قابی که خودش صحنه است، یک میله‌ی خاکستری
     کنارِ کادر همان چیزی است که همه‌ی حس «صفحه‌ی وب معمولی» را برمی‌گرداند. */
  scrollbar-width: none;
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* جبران سربرگ چسبان هنگام پرش به لنگر */
  scroll-padding-top: 6rem;
}

html::-webkit-scrollbar,
body::-webkit-scrollbar {
  inline-size: 0;
  block-size: 0;
  display: none;
}

body {
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-text);
  font-size: var(--t-body);
  font-weight: 400;
  line-height: var(--lh-body);
  /* در خط فارسی هرگز letter-spacing مثبت نمی‌گذاریم؛ اتصال حروف را زشت می‌کند. */
  letter-spacing: 0;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  /* clip است نه hidden: با hidden مرورگر overflow-y را auto حساب می‌کند،
     body یک ظرفِ اسکرول می‌شود و هر position: sticky داخل صفحه از کار
     می‌افتد — از جمله قفل شدنِ صحنه‌ی هیرو. */
  overflow-x: clip;
  /* حاشیه‌ی امن دستگاه‌های دارای بریدگی */
  padding-inline: env(safe-area-inset-right) env(safe-area-inset-left);
}

/* روی لمسی: بدون فلاشِ آبیِ پیش‌فرض و بدون تأخیرِ ۳۰۰ میلی‌ثانیه‌ای
   دابل‌تپ. حالتِ :active خودمان بازخوردِ لمس را می‌دهد. */
a,
button,
label,
summary,
[role="button"] {
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}

img,
picture,
svg,
video {
  display: block;
  max-width: 100%;
  height: auto;
}

img {
  background-color: var(--shadow);
}

a {
  color: inherit;
  text-decoration: none;
}

button,
input,
textarea,
select {
  font: inherit;
  color: inherit;
}

button {
  background: none;
  border: 0;
  cursor: pointer;
}

ul,
ol {
  list-style: none;
}

::selection {
  background: var(--tungsten);
  color: var(--void);
}

.container {
  width: 100%;
  max-width: var(--max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.skip-link {
  position: absolute;
  inset-inline-start: 50%;
  top: -100px;
  transform: translateX(50%);
  z-index: 200;
  background: var(--tungsten);
  color: var(--void);
  padding: 0.75rem 1.5rem;
  border-radius: 2px;
  font-weight: 700;
  transition: top var(--dur) var(--ease-cue);
}

.skip-link:focus {
  top: 1rem;
}

/* ==========================================================================
   ۰۴ — تایپوگرافی
   ========================================================================== */

.display,
h1,
h2,
h3 {
  font-family: var(--font-display);
  font-weight: 800;
  line-height: var(--lh-display);
  letter-spacing: 0;
  text-wrap: balance;
}

.lead {
  font-size: var(--t-lead);
  line-height: 1.8;
  color: var(--fg);
  max-width: var(--measure);
  text-wrap: pretty;
}

.prose p {
  max-width: var(--measure);
  color: var(--muted);
  text-wrap: pretty;
}

.prose p + p {
  margin-top: var(--s-3);
}

/* برچسب فنی: لایه‌ی «تابلوی نور». همیشه لاتین و تک‌عرض.
   این تنها جایی است که tracking مثبت می‌گیریم. */
.label {
  font-family: var(--font-mono);
  font-size: var(--t-label);
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--smoke);
  direction: ltr;
  unicode-bidi: isolate;
  display: inline-flex;
  align-items: center;
  gap: 0.6em;
}

.label--lit {
  color: var(--tungsten);
}

.label::before {
  content: "";
  inline-size: 1.6rem;
  block-size: 1px;
  background: currentColor;
  opacity: 0.55;
  flex: none;
}

.label--bare::before {
  display: none;
}

.num {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  direction: ltr;
  unicode-bidi: isolate;
}

/* ==========================================================================
   ۰۵ — لایه‌های صحنه
   ========================================================================== */

/* --- منبع نور که مکان‌نما را دنبال می‌کند ---
   عمداً یک المان با اندازه‌ی ثابت و گرادیان ثابت است که فقط translate می‌شود.
   اگر به‌جایش موقعیتِ گرادیان را متحرک می‌کردیم، مرورگر هر فریم مجبور بود
   کل ویوپورت را دوباره paint کند. این شکل، کارِ هر فریم فقط روی کامپوزیتور است. */
.spot {
  position: fixed;
  /* عمداً فیزیکی (نه منطقی): جاوااسکریپت مختصات فیزیکی صفحه را می‌نویسد،
     پس این لایه نباید با راست‌چینی جابه‌جا شود. */
  top: 0;
  left: 0;
  inline-size: 30rem;
  block-size: 30rem;
  margin: -15rem 0 0 -15rem;
  z-index: var(--z-spot);
  pointer-events: none;
  opacity: 0;
  will-change: transform, opacity;
  transition: opacity 600ms var(--ease-dimmer);
  background: radial-gradient(
    closest-side,
    var(--glow) 0%,
    var(--glow-soft) 42%,
    transparent 72%
  );
}

.has-pointer .spot {
  opacity: 1;
}

/* --- مکان‌نمای اختصاصی: دیافراگمِ نورافکن ---
   به‌جای فلشِ سیستم، یک حلقه‌ی نور با نقطه‌ای در مرکزش.
   نقطه دقیقاً روی مکان‌نما می‌نشیند (بدون تأخیر) و حلقه کمی عقب می‌ماند —
   همان اینرسی که یک نورافکن واقعی موقع چرخیدن دارد.

   مرکزچینی عمداً با translate(-50%,-50%) انجام می‌شود، نه با margin منفی
   در کنار inset-inline-start. آن ترکیب در سند راست‌چین می‌شکند: خاصیتِ
   منطقی به راست می‌چسبد ولی margin فیزیکی به چپ می‌کشد، و نتیجه‌اش
   نقطه‌ای است که از مرکز حلقه بیرون می‌افتد. */
.cursor,
.cursor-dot {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 80;
  pointer-events: none;
  opacity: 0;
  will-change: transform;
  transition: opacity 260ms var(--ease-cue);
}

.has-cursor .cursor,
.has-cursor .cursor-dot {
  opacity: 1;
}

.cursor__ring {
  position: absolute;
  top: 0;
  left: 0;
  inline-size: 2rem;
  block-size: 2rem;
  border: 1px solid var(--tungsten);
  border-radius: 50%;
  background: transparent;
  box-shadow: 0 0 16px rgba(233, 169, 79, 0.22);
  transform: translate(-50%, -50%) scale(1);
  transition: transform 380ms var(--ease-dimmer),
    background 280ms var(--ease-cue), border-color 280ms var(--ease-cue),
    opacity 260ms var(--ease-cue);
}

.cursor-dot {
  inline-size: 4px;
  block-size: 4px;
  margin: -2px 0 0 -2px;
  border-radius: 50%;
  background: var(--tungsten);
  box-shadow: 0 0 10px 1px rgba(233, 169, 79, 0.75);
  /* عمداً هیچ transition روی transform نیست: موقعیتِ نقطه را جاوااسکریپت
     در هر رویدادِ حرکت می‌نویسد. یک transition این‌جا یعنی نقطه همیشه
     ۲۴۰ میلی‌ثانیه عقب‌تر از مکان‌نما بدود و بعد سرِ توقف بپرد سرِ جایش. */
  transition: opacity 260ms var(--ease-cue);
}

/* روی هر چیز کلیک‌شدنی، دیافراگم کمی باز می‌شود */
.cursor.is-hover .cursor__ring {
  transform: translate(-50%, -50%) scale(1.6);
  border-color: var(--tungsten-hi);
  background: rgba(233, 169, 79, 0.06);
}

/* فشردن کلیک: دیافراگم جمع می‌شود */
.cursor.is-down .cursor__ring {
  transform: translate(-50%, -50%) scale(0.8);
}

/* مکان‌نمای سیستم فقط وقتی پنهان می‌شود که جایگزینش واقعاً فعال باشد */
@media (hover: hover) and (pointer: fine) {
  .has-cursor,
  .has-cursor a,
  .has-cursor button,
  .has-cursor summary,
  .has-cursor [role="button"] {
    cursor: none;
  }

  /* در فیلدهای متنی مکان‌نمای واقعی لازم است، پنهانش نمی‌کنیم */
  .has-cursor input,
  .has-cursor textarea,
  .has-cursor select,
  .has-cursor [contenteditable] {
    cursor: auto;
  }
}

/* --- دانه‌ی فیلم: عکس‌های او دانه دارند، رابط هم باید داشته باشد --- */
.grain {
  position: fixed;
  inset: -50%;
  z-index: var(--z-grain);
  pointer-events: none;
  opacity: 0.05;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.82' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
  will-change: transform;
  animation: grain-shift 6s steps(6) infinite;
}

/* روی لمسی، دانه ثابت می‌ماند. یک لایه‌ی چهاربرابرِ صفحه که تا ابد
   جابه‌جا می‌شود، روی گوشی هم باتری می‌خورد هم گرما می‌سازد — و در آن
   اندازه‌ی صفحه تفاوتش با دانه‌ی ثابت دیده نمی‌شود. */
@media not all and (hover: hover) {
  .grain {
    inset: 0;
    animation: none;
    will-change: auto;
  }
}

@keyframes grain-shift {
  0% {
    transform: translate3d(0, 0, 0);
  }
  20% {
    transform: translate3d(-3%, 2%, 0);
  }
  40% {
    transform: translate3d(2%, -3%, 0);
  }
  60% {
    transform: translate3d(-2%, -2%, 0);
  }
  80% {
    transform: translate3d(3%, 1%, 0);
  }
  100% {
    transform: translate3d(0, 0, 0);
  }
}

/* --- دیمر / صفحه‌ی بارگذاری ---
   مثل فیدرِ تابلوی نور بالا می‌آید. محتوا زیرش رندر شده است،
   پس LCP را عقب نمی‌اندازد. */
.dimmer {
  position: fixed;
  inset: 0;
  z-index: var(--z-loader);
  background: var(--void);
  display: grid;
  place-content: center;
  gap: var(--s-3);
  transition: opacity 700ms var(--ease-blackout), visibility 700ms;
}

.dimmer[hidden] {
  display: grid;
}

.is-lit .dimmer {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

.dimmer__readout {
  font-family: var(--font-mono);
  font-size: var(--t-label);
  letter-spacing: 0.3em;
  color: var(--smoke);
  text-transform: uppercase;
  display: flex;
  justify-content: space-between;
  direction: ltr;
  min-inline-size: min(62vw, 22rem);
}

.dimmer__fader {
  inline-size: min(62vw, 22rem);
  block-size: 2px;
  background: var(--iron);
  overflow: hidden;
}

.dimmer__level {
  display: block;
  block-size: 100%;
  inline-size: 0%;
  background: var(--tungsten);
  box-shadow: 0 0 18px var(--tungsten);
  transition: inline-size 120ms linear;
}

.dimmer__name {
  font-family: var(--font-display);
  font-weight: 900;
  font-size: clamp(1.5rem, 5vw, 2.6rem);
  text-align: center;
  color: var(--iron);
}

.dimmer__name .lit {
  color: var(--tungsten);
}

/* ==========================================================================
   ۰۶ — سربرگ
   ========================================================================== */

.site-header {
  position: fixed;
  inset-block-start: 0;
  inset-inline: 0;
  z-index: var(--z-header);
  display: flex;
  align-items: center;
  /* فقط ناوبری در جریان است؛ نشانِ «نور» مطلق و شناور است، پس
     ناوبری به انتهای منطقی (چپِ فیزیکی در راست‌چین) می‌رود. */
  justify-content: flex-end;
  gap: var(--s-3);
  padding: var(--s-3) var(--gutter);
  padding-block-start: max(var(--s-3), env(safe-area-inset-top));
  min-block-size: 4.75rem;
  transition: background var(--dur) var(--ease-cue),
    border-color var(--dur) var(--ease-cue), padding var(--dur) var(--ease-cue);
  border-block-end: 1px solid transparent;
}

/* --- شیشه‌ی سربرگ ---
   `backdrop-filter` عمداً روی یک شبه‌عنصر است، نه روی خودِ `.site-header`.
   هر عنصری که فیلتر بگیرد برای فرزندانِ `position: fixed`‌اش «قابِ مرجع»
   می‌شود؛ چون نوارِ ناوبریِ پایینِ گوشی داخلِ همین سربرگ است، آن‌طور از
   پایینِ صفحه به زیرِ سربرگ می‌پرید. شبه‌عنصر فرزندی ندارد، پس بی‌خطر است.

   شدت عمداً کم است: لبه‌ی روشن و اشباعِ کمی بالاتر، نه یک شیشه‌ی مات. */
.site-header::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(
    to bottom,
    rgba(255, 255, 255, 0.05),
    rgba(255, 255, 255, 0.012) 55%,
    transparent
  );
  border-block-end: 1px solid rgba(255, 255, 255, 0.07);
  opacity: 0;
  transition: opacity var(--dur) var(--ease-cue);
}

@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .site-header::before {
    -webkit-backdrop-filter: blur(16px) saturate(1.45) brightness(1.03);
    backdrop-filter: blur(16px) saturate(1.45) brightness(1.03);
  }
}

.is-scrolled .site-header::before {
  opacity: 1;
}

/* اگر مرورگر شیشه ندارد، همان پس‌زمینه‌ی توپرِ قبلی */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .is-scrolled .site-header {
    background: rgba(8, 8, 10, 0.92);
  }
}

.is-scrolled .site-header {
  border-block-end-color: var(--line-soft);
  padding-block: var(--s-2);
}

/* --- نشانِ «نور» ---
   بالای صفحه وسطِ هدر می‌ایستد و بزرگ‌تر است: در آن لحظه تنها چیزِ
   هدر همین کلمه است. با اولین اسکرول به لبه‌ی راست سُر می‌خورد،
   کوچک می‌شود و جا را به ناوبری می‌دهد.

   مرکز با left:50% گرفته می‌شود و مقصد با یک calc خالص. زمانی این
   مسافت را جاوااسکریپت اندازه می‌گرفت، چون vw پهنای نوار اسکرول را هم
   می‌شمرد؛ حالا که نوار اسکرول حذف شده، vw دقیقاً برابر عرضِ محتواست و
   آن اندازه‌گیری لازم نیست. مهم‌تر این‌که مقدارِ ثابتِ پیکسلی می‌توانست
   کهنه بماند و روی چرخشِ صفحه یا نمایشگرِ باریک، نشان از لبه بیرون
   می‌زد — این فرمول همیشه خودش را اصلاح می‌کند. */
.brand {
  position: absolute;
  top: 50%;
  left: 50%;
  /* هدفِ لمسی */
  min-block-size: 44px;
  display: grid;
  place-items: center;
  font-family: var(--font-display);
  font-weight: 900;
  font-size: 1.5rem;
  line-height: 1;
  color: var(--tungsten);
  padding: 0.5rem;
  transform: translate(-50%, -50%) scale(1.15);
  transform-origin: center;
  transition: transform 900ms var(--ease-dimmer),
    text-shadow var(--dur) var(--ease-cue);
  text-shadow: 0 0 34px rgba(233, 169, 79, 0.5);
}

.is-scrolled .brand {
  /* ۱۰۰٪ یعنی عرضِ خودِ نشان، پس فرمول با هر طول کلمه و هر فونتی درست
     می‌ماند؛ ۰.۵rem هم padding خودِ لینک را جبران می‌کند تا کلمه با
     بقیه‌ی محتوای صفحه هم‌تراز بنشیند. */
  transform: translate(calc(50vw - var(--gutter) - 100% + 0.5rem), -50%)
    scale(1);
  text-shadow: 0 0 22px rgba(233, 169, 79, 0.3);
}

.brand:hover,
.brand:focus-visible {
  text-shadow: 0 0 40px rgba(233, 169, 79, 0.8);
}

.nav {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 2.4vw, 2.4rem);
  /* تا قبل از اسکرول پنهان است تا «نور» تنها بماند */
  opacity: 0;
  visibility: hidden;
  transform: translate3d(0, -6px, 0);
  transition: opacity 500ms var(--ease-dimmer),
    transform 500ms var(--ease-dimmer), visibility 500ms;
}

.is-scrolled .nav {
  opacity: 1;
  visibility: visible;
  transform: translate3d(0, 0, 0);
}

.nav a {
  font-family: var(--font-mono);
  font-size: var(--t-label);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--smoke);
  position: relative;
  /* هدف لمسی حداقل ۴۴ پیکسل */
  min-block-size: 44px;
  display: inline-flex;
  align-items: center;
  transition: color var(--dur) var(--ease-cue);
}

.nav a .fa {
  font-family: var(--font-text);
  letter-spacing: 0;
  font-size: 0.86rem;
}

.nav a::after {
  content: "";
  position: absolute;
  inset-block-end: 0.7rem;
  inset-inline: 0;
  block-size: 1px;
  background: var(--tungsten);
  transform: scaleX(0);
  transform-origin: var(--to, right);
  transition: transform var(--dur) var(--ease-dimmer);
}

.nav a:hover,
.nav a:focus-visible,
.nav a[aria-current="true"] {
  color: var(--tungsten);
}

.nav a:hover::after,
.nav a:focus-visible::after,
.nav a[aria-current="true"]::after {
  transform: scaleX(1);
}

/* اگر جاوااسکریپت نبود، ناوبری باید از همان اول در دسترس باشد */
.no-js .nav {
  opacity: 1;
  visibility: visible;
  transform: none;
}

.no-js .brand {
  transform: translate(calc(50vw - var(--gutter) - 100% + 0.5rem), -50%)
    scale(1);
}

/* ==========================================================================
   ۰۷ — پرده‌ی یکم: ورود
   ========================================================================== */

.act {
  position: relative;
  padding-block: clamp(5rem, 14vh, 11rem);
}

.act__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-3);
  padding-block-end: var(--s-4);
  margin-block-end: var(--s-6);
  border-block-end: 1px solid var(--line);
  flex-wrap: wrap;
}

.act__title {
  font-size: var(--t-display);
  font-weight: 900;
}

/* --- صحنه و درهایش ---
   با اسکرول، صحنه سرِ جایش قفل می‌شود و دو نیمه‌ی هیرو مثل دو لنگه‌ی در
   از هم باز می‌شوند: نیمه‌ی متن به راست، نیمه‌ی تصویر به چپ. هر دو هم‌زمان
   به سمت بیننده می‌آیند (translateZ) و می‌چرخند، پس لبه‌ی بیرونی‌شان بزرگ و
   نزدیک می‌شود و لبه‌ی درونی به نقطه‌ی گریزِ وسط عقب می‌نشیند. چشم این را
   «جلو رفتن» می‌خواند، نه «کنار رفتن».

   همه‌ی این‌ها را یک متغیر می‌راند: --open از ۰ تا ۱ که جاوااسکریپت از
   پیشرفتِ اسکرول پر می‌کند و روی .hero-stage می‌نشیند. بقیه از همان مشتق
   می‌شوند، پس دو لایه هیچ‌وقت با هم ناهماهنگ نمی‌شوند. */

.hero-stage {
  position: relative;
  /* یک صفحه برای خودِ صحنه، به‌اضافه‌ی مسافتی که در آن باز می‌شود. */
  block-size: calc(100svh + var(--runway));
  z-index: 2;
}

/* بعد از باز شدن، قابِ خالیِ هیرو روی فهرست اجراها می‌افتد. چیزی داخلش
   تعاملی نیست، پس کلیک باید از آن رد شود. سرِ صفحه (قبل از اولین تکان)
   دست‌نخورده می‌ماند تا متن هنوز قابل انتخاب باشد. */
:root.is-opening .hero-stage {
  pointer-events: none;
}

.hero {
  position: sticky;
  inset-block-start: 0;
  block-size: 100svh;
  display: grid;
  align-content: center;
  padding-block: clamp(7rem, 18vh, 12rem) var(--s-6);
  overflow: clip;
  /* عمقِ صحنه. بدون این، چرخشِ درها فقط یک کج‌شدنِ تخت است. */
  perspective: 1200px;
  perspective-origin: 50% 45%;
}

/* --- لنگه‌های در --- */

.hero__door {
  /* یک‌بار حساب می‌شود و هر دو لنگه از آن استفاده می‌کنند. تا یک‌پنجمِ راه
     هنوز کاملاً خواناست، بعد در تاریکی حل می‌شود و پیش از خروج از قاب
     تمام شده است — تا آخرِ مسیر فقط سیاهی بماند و نور. */
  --fade: clamp(0, calc(1.3 - var(--open, 0) * 1.55), 1);
  /* --door-alpha برای موبایل است که پرتره آن‌جا از اول نیمه‌رنگ است */
  opacity: calc(var(--fade) * var(--door-alpha, 1));
  will-change: transform, opacity;
}

.hero__door--text {
  /* لولا روی لبه‌ی چپ است تا لبه‌ی راست — همان‌جا که «نور» نشسته — جلو
     بیاید و انتهای «محمدی» عقب بنشیند. */
  transform-origin: 0% 50%;
  transform: translate3d(
      calc(var(--open, 0) * 34vw),
      0,
      calc(var(--open, 0) * 300px)
    )
    rotateY(calc(var(--open, 0) * -24deg));
}

.hero__door--image {
  transform-origin: 100% 50%;
  transform: translate3d(
      calc(var(--open, 0) * -34vw),
      0,
      calc(var(--open, 0) * 300px)
    )
    rotateY(calc(var(--open, 0) * 24deg));
}

/* تاری فقط وقتی روشن می‌شود که در واقعاً در حال باز شدن است. filter یک
   پاسِ paint اضافه می‌سازد و صحنه‌ی ساکن — همان چیزی که کاربر بیشترین
   وقت را به آن نگاه می‌کند — نباید هزینه‌اش را بدهد. */
:root.is-opening .hero__door {
  filter: blur(calc(var(--open, 0) * var(--open, 0) * 9px))
    brightness(calc(1 - var(--open, 0) * 0.35));
}

.hero__inner {
  position: relative;
  z-index: 2;
}

.hero__eyebrow {
  margin-block-end: var(--s-4);
}

/* نامِ او. «نور» جدا شده و روشن است.
   این برش در خط فارسی بی‌خطر است چون «ر» به حرف بعد نمی‌چسبد. */
.hero__name {
  font-family: var(--font-display);
  font-size: var(--t-hero);
  font-weight: 900;
  line-height: var(--lh-hero);
  letter-spacing: 0;
  margin-block-end: var(--s-4);
}

.hero__name .lit {
  color: var(--tungsten);
  text-shadow: 0 0 60px rgba(233, 169, 79, 0.45);
}

.hero__name .dim {
  color: var(--steel);
  transition: color var(--dur-cue) var(--ease-dimmer);
}

.is-lit .hero__name .dim {
  color: var(--bone);
}

.hero__role {
  font-family: var(--font-display);
  font-size: var(--t-title);
  font-weight: 500;
  color: var(--muted);
  margin-block-end: var(--s-5);
}

.hero__line {
  font-size: var(--t-lead);
  line-height: 1.75;
  max-width: 30rem;
  color: var(--fg);
  border-inline-start: 2px solid var(--tungsten-dim);
  padding-inline-start: var(--s-3);
}

/* --- اجراها: پشتِ لندینگ بوده، حالا از تاریکی بیرون می‌آید ---
   یک صفحه‌ی کامل بالا کشیده می‌شود. آن یک صفحه دقیقاً همان چیزی بود که
   قبلاً بعد از باز شدنِ درها خالی می‌ماند و کاربر باید بی‌دلیل از آن
   رد می‌شد. حالا فهرست همان لحظه‌ای که درها تمام می‌شوند سرِ قاب است.

   z-index یک، پس **پشتِ** صحنه است نه بعد از آن. چون هیرو پس‌زمینه ندارد،
   فهرست از میان همان قابی که درها از آن کنار رفتند دیده می‌شود.

   مقدارِ پیش‌فرضِ --open برابر ۱ است تا بدون جاوااسکریپت بخش سالم و کامل
   رندر شود. */
.works-stage {
  position: relative;
  z-index: 1;
  /* دقیقاً به قدِ صحنه بالا کشیده می‌شود، پس از خطِ صفر شروع می‌کند:
     از همان اولین پیکسل، پشتِ لندینگ نشسته است. */
  margin-block-start: calc(0px - 100svh - var(--runway));
}

/* این باند همان مسافتی است که فهرست سرِ قاب نگه داشته می‌شود؛ بدون آن
   sticky در همان پیکسل اول رها می‌شد. در انتها فاصله‌ای نمی‌سازد، چون
   دقیقاً همان‌قدر که نگه داشته شد مصرف می‌شود. */
.works-stage__runway {
  /* هم مسافتِ باز شدنِ درها، هم مسافتِ ورق زدنِ پشته. قدِ این ستون است
     که تعیین می‌کند sticky چقدر قاب را نگه دارد. */
  block-size: calc(var(--runway) + (var(--n) - 1) * var(--card-step));
}

/* sticky کار را می‌کند، نه جاوااسکریپت: بخش تا لحظه‌ی باز شدنِ کاملِ درها
   سرِ قاب **بی‌حرکت** می‌ماند و همان‌جا از عمق جلو می‌آید. اگر این نگه
   داشتن را با transform در جاوااسکریپت می‌ساختیم، یک فریم عقب افتادن
   کافی بود تا کل بخش بلرزد. */
.works {
  position: sticky;
  inset-block-start: 0;
  /* لنگرِ رشد کمی بالاتر از مرکزِ قاب است، همان‌جا که چشم موقعِ باز شدنِ
     در ایستاده: فهرست از همان نقطه جلو می‌آید، نه از پایینِ صفحه. */
  transform-origin: 50% 45svh;
  /* از ۶۰٪ شروع می‌کند ولی تا ۴۰٪ راه اصلاً دیده نمی‌شود، پس کوچک‌ترین
     اندازه‌ای که چشم می‌بیند ۷۶٪ است — یعنی یک‌سومِ کامل رشد جلوی چشم
     اتفاق می‌افتد، نه پانزده درصد. */
  /* ورود از --open می‌آید و خروج از --dim. ضرب می‌شوند، پس هیچ‌وقت با
     هم دعوا نمی‌کنند و هر کدام مستقل قابل تنظیم است. مقدارِ پیش‌فرضِ
     --dim این‌جا صفر است (هنوز روشن) و در پرده‌ی سوم یک (رسیده) — پس
     بدون جاوااسکریپت هر دو کامل رندر می‌شوند. */
  transform: scale(
    calc((0.6 + var(--open, 1) * 0.4) * (1 - var(--dim, 0) * 0.4))
  );
  /* خاموشی سریع است — مثل یک بلک‌اوتِ واقعی، نه یک محوشدنِ کشدار. تا
     ۱۲٪ از فیدر کاملاً رفته، یعنی حدود یک کلیکِ چرخ. هرچه این کوتاه‌تر
     باشد، فهرست کمتر «اسکرول» می‌شود و بیشتر «خاموش». */
  opacity: calc(
    clamp(0, calc(var(--open, 1) * 2.5 - 1), 1) *
      clamp(0, calc(1 - var(--dim, 0) * 8), 1)
  );
  /* پرشِ لنگرِ «اجراها» باید جایی بیفتد که فهرست کامل روشن شده، نه سرِ
     صفحه — که حالا از نظر چیدمان همان خطِ صفر است. */
  scroll-margin-block-start: calc(0px - var(--runway));
}

/* --- پرتره: در تاریکی هست، ولی نور پیدایش می‌کند ---
   دو لایه‌ی یکسان روی هم:
     پایه  — همیشه دیده می‌شود، تیره و بی‌رنگ. یعنی «او آن‌جاست».
     روشن — با نزدیک شدن مکان‌نما محو‌به‌ظهور می‌رسد.
   فیلترها ثابت‌اند و فقط opacity لایه‌ی بالا تغییر می‌کند، پس این افکت
   کاملاً روی کامپوزیتور می‌ماند. اگر به‌جایش filter را انیمیت می‌کردیم،
   مرورگر باید هر فریم یک تصویر ۶۴۰×۹۳۰ را دوباره paint می‌کرد. */
.hero__portrait {
  position: absolute;
  inset-block: 0;
  inset-inline-end: 0;
  inline-size: min(52%, 44rem);
  z-index: 1;
  pointer-events: none;
  -webkit-mask-image: radial-gradient(
    ellipse 78% 74% at 55% 42%,
    #000 34%,
    transparent 80%
  );
  mask-image: radial-gradient(
    ellipse 78% 74% at 55% 42%,
    #000 34%,
    transparent 80%
  );
}

.hero__portrait img {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  /* صورت کمی بالاتر و سمت راستِ کادر است؛ این نقطه سرش را در قاب نگه می‌دارد */
  object-position: 42% 32%;
}

.hero__portrait .layer-base {
  filter: grayscale(0.85) contrast(1.2) brightness(0.5);
  opacity: 0.34;
}

.hero__portrait .layer-lit {
  filter: grayscale(0.15) contrast(1.1) brightness(1);
  /* --near را جاوااسکریپت از فاصله‌ی مکان‌نما پر می‌کند: ۰ دور، ۱ نزدیک */
  opacity: calc(var(--near, 0) * 0.92);
  transition: opacity 420ms var(--ease-dimmer);
}

.hero__scroll {
  /* با اولین تکانِ در می‌رود؛ دیگر لازم نیست بگوید «اسکرول کن» */
  opacity: clamp(0, calc(1 - var(--open, 0) * 6), 1);
  position: absolute;
  inset-block-end: var(--s-4);
  inset-inline-start: var(--gutter);
  display: inline-flex;
  align-items: center;
  gap: 0.75rem;
  color: var(--smoke);
  z-index: 2;
}

.hero__scroll .rail {
  inline-size: 1px;
  block-size: 3rem;
  background: linear-gradient(to bottom, var(--tungsten), transparent);
  animation: rail 2.4s var(--ease-cue) infinite;
  transform-origin: top;
}

@keyframes rail {
  0% {
    transform: scaleY(0);
    opacity: 0;
  }
  40% {
    transform: scaleY(1);
    opacity: 1;
  }
  100% {
    transform: scaleY(1);
    opacity: 0;
  }
}

/* ==========================================================================
   ۰۸ — پرده‌ی دوم: اجراها
   ========================================================================== */

.works {
  border-block-start: 1px solid var(--line);
  /* قابِ ثابت و دقیقاً یک صفحه. ارتفاعِ پشته از باقی‌مانده گرفته می‌شود
     نه از یک عددِ حدسی، پس روی هیچ اندازه‌ای از قاب بیرون نمی‌زند. */
  block-size: 100svh;
  display: grid;
  align-content: stretch;
  padding-block: clamp(3.5rem, 9vh, 7rem);
  /* ورقِ در حالِ ورود از لبه‌ی چپِ قاب می‌آید و بیرونش بریده می‌شود؛
     بدون این، کارتِ بیرون‌مانده عرضِ سند را درازتر می‌کرد. */
  overflow: clip;
}

.works > .container {
  display: grid;
  grid-template-rows: auto auto 1fr;
  min-block-size: 0;
}

/* --- ریلِ پیشرفت ---
   وقتی فقط یک اجرا در هر لحظه دیده می‌شود، کاربر باید بداند کجای دسته
   است. این نازک‌ترین راهِ گفتنش است. */
.deck-rail {
  position: relative;
  block-size: 1px;
  background: var(--line);
  margin-block-start: calc(0px - var(--s-3));
  margin-block-end: var(--s-4);
}

.deck-rail::after {
  content: "";
  display: block;
  block-size: 100%;
  background: var(--tungsten);
  /* در راست‌چین پیشرفت از راست پر می‌شود */
  transform-origin: 100% 50%;
  transform: scaleX(var(--deck, 1));
}

/* --- شمارِ زنده --- */
/* این عدد تنها چیزی است که در تمام مدتِ پشته ثابت می‌ماند و می‌گوید
   کاربر کجای ده اجراست؛ در اندازه‌ی برچسب‌های فنی گم می‌شد. */
.deck-count {
  display: inline-flex;
  align-items: baseline;
  gap: 0.45rem;
  line-height: 1.15;
  font-size: clamp(1.05rem, 1.7vw, 1.5rem);
  letter-spacing: 0.14em;
  color: var(--dust);
}

.deck-count::before {
  inline-size: 2.4rem;
}

.deck-count__win {
  block-size: 1.15em;
  overflow: hidden;
}

.deck-count__col {
  display: block;
  transform: translateY(
    calc(var(--deck, 1) * (var(--n) - 1) * -1.15em)
  );
}

.deck-count__col > span {
  display: block;
  block-size: 1.15em;
}

.deck-count__sep {
  color: var(--steel);
}

/* --- ستونِ نامرئیِ اندازه‌گیری ---
   از پایانِ باز شدنِ درها شروع می‌شود و به قدِ کلِ مسافتِ پشته است. */
.deck-track {
  position: absolute;
  inset-block-start: var(--runway);
  inset-inline-start: 0;
  inline-size: 1px;
  block-size: calc((var(--n) - 1) * var(--card-step));
  visibility: hidden;
  pointer-events: none;
}

.deck-track > span {
  display: block;
  block-size: 100%;
}

/* --- پشته‌ی اجراها ---
   یک اجرا در هر لحظه. با اسکرول، بعدی مثل یک ورق کاغذ از چپ وارد می‌شود
   و روی دسته می‌نشیند؛ قبلی کمی کوچک و تیره می‌شود و فقط لبه‌اش از زیر
   پیدا می‌ماند.

   همه‌چیز از یک عدد می‌آید: --deck بین ۰ و ۱. برای هر کارت
       t = deck × (n−۱) − k + ۱
   یعنی t=۱ لحظه‌ی نشستنِ کارت است، t<۱ در حالِ ورود، و t>۱ عمقِ آن در
   دسته. هیچ جاوااسکریپتی برای خودِ کارت‌ها لازم نیست — نه کلاسی عوض
   می‌شود، نه گره‌ای جابه‌جا. */
.works-deck {
  position: relative;
  /* بقیه‌ی قاب؛ margin پایین جا برای لبه‌هایی که از زیر بیرون می‌زنند */
  min-block-size: 0;
  margin-block-end: 4rem;
}

.wcard {
  --t: calc(var(--deck, 1) * (var(--n) - 1) - var(--k) + 1);
  /* ورود از چپ: ۰ تا ۱ */
  --in: clamp(0, var(--t), 1);
  /* عمق در دسته؛ بیش از چهار لایه دیده نمی‌شود */
  --d: clamp(0, calc(var(--t) - 1), 4);

  position: absolute;
  inset: 0;
  z-index: calc(10 + var(--k));

  display: grid;
  align-content: center;
  gap: var(--s-2);
  padding: var(--s-5) var(--s-4);

  background: var(--shadow);
  border: 1px solid var(--line);
  border-radius: 3px;
  color: var(--fg);

  /* مبدأ روی لبه‌ی پایین: کوچک شدن تهِ کارت را جابه‌جا نمی‌کند، پس
     فقط جابه‌جاییِ عمدی دیده می‌شود و لبه‌ها منظم پله می‌خورند. */
  transform-origin: 50% 100%;
  transform: translateX(calc((1 - var(--in)) * -108%))
    translateY(calc(var(--d) * 0.9rem))
    scale(calc(1 - var(--d) * 0.035));
  opacity: calc(var(--in) * clamp(0, calc(1 - var(--d) * 0.24), 1));
  will-change: transform, opacity;
}

.wcard__cue {
  font-family: var(--font-mono);
  font-size: var(--t-label);
  letter-spacing: 0.16em;
  color: var(--tungsten);
}

.wcard__title {
  font-family: var(--font-display);
  font-weight: 900;
  font-size: clamp(2.2rem, 6vw, 4.6rem);
  line-height: 1.05;
  color: var(--bone);
  text-wrap: balance;
}

.wcard__meta {
  font-size: var(--t-small);
  color: var(--dust);
}


/* --- پرتوِ نور: تصویرِ اجرا که زیر مکان‌نما روشن می‌شود ---
   فقط transform و opacity انیمیت می‌شوند، روی لایه‌ی مستقل. خودِ ظرف را
   حلقه‌ی rAF جابه‌جا می‌کند (با وزنی سنگین‌تر از مکان‌نما، تا کمی عقب
   بیفتد و حسِ اینرسی بدهد). */
.beam {
  position: fixed;
  /* عمداً فیزیکی: جاوااسکریپت مختصات فیزیکیِ صفحه را می‌نویسد و این لایه
     نباید با راست‌چینی جابه‌جا شود. */
  top: 0;
  left: 0;
  z-index: 40;
  inline-size: 24rem;
  margin: -7.5rem 0 0 -12rem;
  pointer-events: none;
  will-change: transform;
}

/* بیضی، با لبه‌هایی که در سیاهی حل می‌شوند — نه یک مستطیلِ بریده.
   ماسک خودش شکل را می‌سازد، پس نه border-radius لازم است نه سایه:
   سایه از کادرِ مستطیلی پیروی می‌کند و از زیرِ لبه‌ی محو بیرون می‌زد. */
.beam__frame {
  position: relative;
  aspect-ratio: 3 / 2;
  overflow: hidden;
  -webkit-mask-image: radial-gradient(
    closest-side ellipse at 50% 50%,
    #000 46%,
    rgba(0, 0, 0, 0.55) 72%,
    transparent 100%
  );
  mask-image: radial-gradient(
    closest-side ellipse at 50% 50%,
    #000 46%,
    rgba(0, 0, 0, 0.55) 72%,
    transparent 100%
  );
  opacity: 0;
  transform: scale(0.92);
  transition: opacity 380ms var(--ease-dimmer),
    transform 520ms var(--ease-dimmer);
}

.beam.is-on .beam__frame {
  opacity: 1;
  transform: scale(1);
}

.beam img {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  opacity: 0;
  filter: contrast(1.08) brightness(0.92);
  transition: opacity 340ms var(--ease-dimmer);
}

.beam img.is-active {
  opacity: 1;
}

/* روی لمسی محرکی ندارد و فقط یک لایه‌ی بی‌مصرف روی GPU می‌شود */
@media not all and (hover: hover) {
  .beam {
    display: none;
  }
}

/* روی فهرست اجراها مکان‌نما کنار می‌رود: آن‌جا خودِ تصویرِ شناور و
   هاله‌اش کارِ مکان‌نما را می‌کنند و یک حلقه‌ی اضافه فقط جلوی تصویر را
   می‌گیرد. */
.has-cursor.is-view .cursor,
.has-cursor.is-view .cursor-dot {
  opacity: 0;
}

/* بندانگشتیِ داخلِ کارت فقط روی گوشی است */
.wcard__thumb {
  display: none;
}

/* فقط کارتِ رو در دسترسِ هاور است؛ بقیه زیرش‌اند و فقط لبه‌شان بیرون
   می‌زند — و کلیک روی همان لبه هم درست کار می‌کند. */
@media (hover: hover) and (pointer: fine) {
  .wcard:hover .wcard__title,
  .wcard:focus-visible .wcard__title {
    color: var(--tungsten);
  }

  .wcard:focus-visible {
    border-color: var(--tungsten);
  }
}

/* ==========================================================================
   ۰۹ — پرده‌ی سوم: کار
   ========================================================================== */

/* --- گذر از پرده‌ی دوم به سوم: خاموشی، بعد نورِ سرصحنه ---
   این‌جا عمداً «در» تکرار نمی‌شود. در تئاتر بین دو صحنه در باز نمی‌کنند:
   نور پایین می‌آید و جای دیگری بالا می‌آید. --dim همان فیدر است، و مثل
   --open با اسکرول رانده می‌شود و با sticky سرِ قاب قفل می‌ماند — پس
   هیچ‌چیز «از پایین به بالا» نمی‌آید.

   ضرب‌آهنگ روی --dim (چند ضربِ پشت سر هم، نه یک ظهورِ یک‌پارچه):
     ۰ → ۰.۱۲   فهرست خاموش می‌شود
     ۰.۱۲ → ۰.۳۰ سیاهیِ محض — یک مکثِ واقعی، نه هم‌پوشانی
     ۰.۳۴  برچسبِ پرده
     ۰.۳۸  عنوان، کلمه‌به‌کلمه
     ۰.۵۰  پرتره
     ۰.۵۶  مانیفست

   سه ضربِ اول با --dim رانده می‌شوند چون در تمام مدتِ قفل داخلِ قابند.
   پرتره، آمار و نقل‌قول پایین‌ترند — روی موبایل حتی یک صفحه پایین‌تر —
   پس بردنشان به این ضرب‌آهنگ یعنی هدر دادنشان پشتِ لبه‌ی قاب. آن‌ها
   همان آشکارسازیِ معمولیِ سایت را دارند، ولی رصدشان تا نیمه‌ی همین
   فیدر عقب می‌افتد تا زودتر از موقع مصرف نشوند. */

.craft-stage {
  position: relative;
  /* بالای فهرست: فهرست باید زیرِ تاریکی برود، نه رویش */
  z-index: 3;
  /* یک صفحه بالا کشیده می‌شود تا دقیقاً وقتی شروع کند که ته فهرست به
     پایینِ قاب رسیده است. */
  margin-block-start: calc(0px - 100svh);
  /* تا نرسیده روی فهرست افتاده و جلوی کلیک را می‌گیرد */
  pointer-events: none;
  /* دروازه‌ی کلیِ پرده: پرتره و آمار و نقل‌قول با IntersectionObserver
     می‌آیند و کلاسِ is-in آن‌ها برنمی‌گردد. بدون این دروازه، کاربری که
     تا این‌جا آمده و بعد به فهرست برگشته، آمار و پرتره را روی فهرست
     می‌دید. این‌جا هر چیزی که --dim پایین باشد کلاً پنهان است.

     ضربِ دوم هم همین‌جاست: با شروعِ رسیدنِ میان‌پرده، این پرده خاموش
     می‌شود. پس گذر از سه به چهار هم مثل گذر از دو به سه «نور پایین،
     نور بالا» است، نه یک اسکرولِ ساده. */
  opacity: calc(
    clamp(0, calc((var(--dim, 1) - 0.3) * 10), 1) *
      clamp(0, calc(1 - var(--enter, 0) * 3), 1)
  );
}

:root.is-lifted .craft-stage {
  pointer-events: auto;
}

.craft-stage__runway {
  block-size: var(--lift);
}

.craft {
  position: sticky;
  inset-block-start: 0;
  scroll-margin-block-start: calc(0px - var(--lift));
}

.craft .act__head {
  opacity: clamp(0, calc((var(--dim, 1) - 0.34) * 4), 1);
}

/* عنوان کلمه‌به‌کلمه روشن می‌شود — بدون هیچ جابه‌جایی. هر کلمه --i خودش
   را دارد، پس پیشرفتِ محلی‌اش کمی دیرتر شروع می‌شود و نور روی سطر راه
   می‌رود. تازه که روشن می‌شود داغ و پخش است و بعد جمع می‌شود، مثل رشته‌ی
   تنگستن که گرم می‌شود. */
.craft [data-words] .w {
  overflow: visible;
}

.craft [data-words] .w__in {
  --wp: clamp(0, calc((var(--dim, 1) - 0.38 - var(--i, 0) * 0.03) * 8), 1);
  transform: none;
  transition: none;
  opacity: var(--wp);
  text-shadow: 0 0 calc((1 - var(--wp)) * 1.6rem)
    rgba(233, 169, 79, calc(var(--wp) * 0.9));
}

/* پرتره تنها عنصرِ این پرده است که شفافیتِ ذاتی‌اش ۱ است (پرده‌ی خودش
   پنهانش می‌کند، نه opacity). پس باید صریحاً منتظر بماند تا فهرست کامل
   خاموش شود — وگرنه وسطِ خاموشی از پشتش پیدا می‌شود. */
.craft-stage .craft__figure {
  opacity: clamp(0, calc((var(--dim, 1) - 0.5) * 5), 1);
}

/* مانیفست تنها .reveal‌ای است که --dim می‌راند، پس همین‌جا از
   آشکارسازیِ کلاسی جدا می‌شود. */
.craft .prose {
  opacity: clamp(0, calc((var(--dim, 1) - 0.56) * 3.4), 1);
  transform: none;
  transition: none;
}

.craft__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--s-6);
  align-items: start;
}

.craft__title {
  font-size: var(--t-display);
  font-weight: 900;
  max-width: 16ch;
  text-wrap: balance;
  margin-block-end: var(--s-4);
}

/* سطرِ بلند در فارسی خواندن را کند می‌کند؛ این عرض حدود ۶۰ تا ۷۰ نویسه
   در هر سطر می‌دهد که همان بازه‌ی راحتِ چشم است. */
.craft .prose {
  max-inline-size: 42ch;
}

.craft__figure {
  position: relative;
  overflow: hidden;
  background: var(--shadow);
}

.craft__figure img {
  inline-size: 100%;
  /* نسبتِ خودِ عکس (۴۷۸×۶۳۹) است، پس هیچ بخشی از کادر بریده نمی‌شود */
  aspect-ratio: 3 / 4;
  object-fit: cover;
  filter: grayscale(0.55) contrast(1.15) brightness(0.8);
  transition: filter var(--dur-slow) var(--ease-dimmer);
}

/* بزرگ‌نمایی هنگام هاور در بخش ۱۳ یک‌جا مدیریت می‌شود تا با پرده‌ی
   ورودی سر transform دعوا نکند. */
.craft__figure:hover img {
  filter: grayscale(0) contrast(1.1) brightness(0.95);
}

.craft__figure figcaption {
  position: absolute;
  inset-block-end: 0;
  inset-inline: 0;
  padding: var(--s-3);
  background: linear-gradient(to top, rgba(8, 8, 10, 0.9), transparent);
  font-size: var(--t-small);
  color: var(--dust);
}

/* آمار — با ارقام فارسی */
.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(5.5rem, 1fr));
  gap: var(--s-3) var(--s-4);
  margin-block-start: var(--s-5);
  padding-block-start: var(--s-4);
  border-block-start: 1px solid var(--line);
}

.stat__value {
  font-family: var(--font-display);
  font-size: clamp(2.4rem, 5vw, 3.6rem);
  font-weight: 900;
  color: var(--tungsten);
  line-height: 1.15;
}

.stat__label {
  /* روشن‌تر از قبل (‎۷.۶:۱ به‌جای ۴.۵:۱) — این‌ها برچسبِ عددند و باید
     بی‌زحمت خوانده شوند، نه این‌که در سایه گم شوند. */
  font-size: var(--t-label);
  color: var(--dust);
  margin-block-start: 0.35rem;
}

/* --- شمارنده: رقم‌ها مثل فیدر بالا می‌روند ---
   هر رقم یک پنجره است و ستونی از ۰ تا ۹ که دو بار تکرار شده داخلش
   می‌لغزد. چون هر پنجره هر ده رقم را در خود دارد، عرضش برابرِ پهن‌ترین
   رقم می‌شود و ستون‌ها خودبه‌خود هم‌اندازه می‌مانند — بدون نیاز به
   font-variant-numeric که در فونتِ فارسی همیشه در دسترس نیست.
   فقط transform انیمیت می‌شود. */
.odo {
  display: inline-flex;
  /* ارزشِ مکانیِ رقم‌ها در فارسی هم چپ‌به‌راست است */
  direction: ltr;
  line-height: 1.15;
}

.odo__d {
  display: block;
  block-size: 1.15em;
  overflow: hidden;
}

.odo__col {
  display: block;
  transform: translateY(calc(var(--n, 0) * -1.15em));
  transition: transform 1500ms var(--ease-dimmer);
  /* یکان دیرتر می‌نشیند */
  transition-delay: calc(var(--i, 0) * 90ms);
  will-change: transform;
}

.odo__col > span {
  display: block;
  block-size: 1.15em;
}

/* تکرارِ دومِ فهرست: یک چرخِ کامل می‌زند و روی همان رقم می‌ایستد */
.is-in .odo__col {
  transform: translateY(calc((var(--n, 0) + 10) * -1.15em));
}

/* --- کارت تماس ---
   یک قاب با چهار نشانِ گوشه: در یک سو راه‌های ارتباط، در سوی دیگر فرم.
   گوشه‌ها تیزند و نشان‌ها خطِ نازک — همان زبانِ «کاغذِ صحنه» که در
   برچسب‌های ACT و شماره‌ی کیو هم هست. */

.ccard {
  position: relative;
  display: grid;
  grid-template-columns: 1fr;
  border: 1px solid var(--line);
  margin-block-start: var(--s-5);
}

/* نشان‌های گوشه: یک صلیبِ نازک که کمی بیرونِ قاب می‌نشیند */
.ccard__mark {
  position: absolute;
  inline-size: 13px;
  block-size: 13px;
  color: var(--tungsten-dim);
  pointer-events: none;
}

.ccard__mark::before,
.ccard__mark::after {
  content: "";
  position: absolute;
  background: currentColor;
}

.ccard__mark::before {
  inset-block-start: 50%;
  inset-inline: 0;
  block-size: 1px;
  transform: translateY(-50%);
}

.ccard__mark::after {
  inset-inline-start: 50%;
  inset-block: 0;
  inline-size: 1px;
  transform: translateX(-50%);
}

.ccard__mark:nth-of-type(1) {
  inset-block-start: -7px;
  inset-inline-start: -7px;
}
.ccard__mark:nth-of-type(2) {
  inset-block-start: -7px;
  inset-inline-end: -7px;
}
.ccard__mark:nth-of-type(3) {
  inset-block-end: -7px;
  inset-inline-start: -7px;
}
.ccard__mark:nth-of-type(4) {
  inset-block-end: -7px;
  inset-inline-end: -7px;
}

.ccard__main {
  padding: var(--s-5) var(--s-4);
}

.ccard__lead {
  max-inline-size: 42ch;
  margin-block-end: var(--s-5);
}

.ccard__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
}

.ccard__cv {
  margin-block-start: var(--s-5);
}

/* --- کاشیِ هر راه ارتباط --- */

.ctile {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  min-block-size: 56px;
  padding: var(--s-2) var(--s-3);
  background: var(--bg);
  color: var(--fg);
  transition: background var(--dur) var(--ease-cue),
    color var(--dur) var(--ease-cue);
}

.ctile:hover,
.ctile:focus-visible {
  background: var(--shadow);
  color: var(--tungsten);
}

.ctile__icon {
  display: grid;
  place-items: center;
  flex: none;
  inline-size: 2.5rem;
  block-size: 2.5rem;
  border: 1px solid var(--line);
  color: var(--tungsten);
}

.ctile__text {
  display: grid;
  gap: 0.15rem;
  min-inline-size: 0;
}

.ctile__label {
  font-size: var(--t-label);
  color: var(--dust);
}

.ctile__value {
  font-size: var(--t-small);
  /* نشانی‌های بلند می‌شکنند، بریده نمی‌شوند: ایمیل و آی‌دی باید کامل
     خوانده شوند، وگرنه کاشی کارِ خودش را نمی‌کند. */
  overflow-wrap: anywhere;
}

/* --- فرم --- */

.ccard__aside {
  padding: var(--s-4);
  border-block-start: 1px solid var(--line);
  background: var(--shadow);
}

.cform__row {
  display: grid;
  gap: 0.4rem;
  margin-block-end: var(--s-3);
}

.cform__label {
  font-size: var(--t-label);
  color: var(--dust);
}

.cform__field {
  inline-size: 100%;
  min-block-size: 48px;
  padding: 0.7rem 0.9rem;
  background: var(--void);
  border: 1px solid var(--iron);
  border-radius: 2px;
  color: var(--fg);
  font-family: inherit;
  font-size: var(--t-body);
  transition: border-color var(--dur) var(--ease-cue),
    box-shadow var(--dur) var(--ease-cue);
}

.cform__field:focus {
  outline: none;
  border-color: var(--tungsten);
  /* همان هاله‌ی نورِ سایت، این‌بار به‌عنوان نشانه‌ی تمرکز */
  box-shadow: 0 0 0 1px var(--tungsten), 0 0 22px var(--glow);
}

.cform__field--area {
  min-block-size: 7rem;
  resize: vertical;
  line-height: 1.7;
}

.btn--block {
  inline-size: 100%;
  justify-content: center;
}

.cform__note {
  margin-block-end: var(--s-3);
  padding: 0.8rem 1rem;
  font-size: var(--t-small);
  border-inline-start: 2px solid currentColor;
}

.cform__note--ok {
  color: var(--tungsten);
}

.cform__note--bad {
  color: var(--crimson-soft);
}

/* تله‌ی ربات: از دید بیرون، ولی نه با display:none — بعضی ربات‌ها
   فیلدهای مخفی‌شده با display را نادیده می‌گیرند. */
.cform__trap {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

@media (min-width: 62rem) {
  .ccard {
    grid-template-columns: 1.6fr 1fr;
  }

  /* خروجیِ ایستا فرم ندارد، پس کارت یک‌ستونه می‌ماند */
  .ccard--solo {
    grid-template-columns: 1fr;
  }

  .ccard__main {
    padding: var(--s-6);
  }

  .ccard__aside {
    padding: var(--s-6) var(--s-5);
    border-block-start: 0;
    border-inline-start: 1px solid var(--line);
  }
}

/* نقل‌قول بزرگ */
.pull {
  margin-block: var(--s-7);
  padding-inline-start: var(--s-4);
  border-inline-start: 2px solid var(--tungsten);
  font-family: var(--font-display);
  font-size: var(--t-title);
  font-weight: 600;
  line-height: 1.6;
  max-width: 26ch;
  color: var(--bone);
  text-wrap: balance;
}

/* ==========================================================================
   ۰۹.۵ — میان‌پرده: قاب‌ها
   --------------------------------------------------------------------------
   بین «کار» و «تماس» یک نفسِ تصویری لازم بود؛ نه یک بخشِ دیگر با عنوان و
   متن. چهار نوارِ عمودی از قاب‌های کویر مدام از پایین به بالا می‌روند و دو
   کلمه‌ی درشت بینشان ایستاده‌اند.

   عمق با سه چیز هم‌زمان ساخته می‌شود، نه با یکی: نوارِ نزدیک بزرگ‌تر و
   شفاف‌تر و تندتر است، نوارهای دور کوچک‌تر و تارتر و کندتر. همین است که
   چشم آن را «فاصله» می‌خواند نه «سرعتِ متفاوت».

   هزینه‌ی اجرا: هر نوار یک لایه‌ی composite است که فقط translate می‌شود.
   filter روی همان عنصرِ متحرک نشسته (نه روی والدش) تا یک‌بار رستر شود و
   بعد فقط جابه‌جا شود؛ اگر روی والد بود، هر فریم دوباره رستر می‌شد.
   ========================================================================== */

/* --- باندِ رسیدن ---
   همان الگوی همیشگی: یک ستونِ بلندتر از صفحه، یک قابِ sticky، و یک عدد.
   `--enter` از صفر تا یک می‌رود و در همین مسافت سه اتفاق پشت سر هم
   می‌افتد:

     ۰ → ۰.۳۳   پرده‌ی سوم خاموش می‌شود
     ۰ → ۰.۶۲   تایپ از نزدیک عقب می‌نشیند (زوم اوت)
     ۰.۵ → ۱    ورق‌ها آرام باز می‌شوند

   زوم اوت عمدی است و برعکسِ چیزی است که معمولاً می‌بینید: کلمات بزرگ‌تر
   از قاب شروع می‌کنند و جمع می‌شوند، پس چشم آن را «عقب رفتنِ خودم»
   می‌خواند، نه «کوچک شدنِ متن». */

.strip-stage {
  position: relative;
  /* بالای پرده‌ی سوم می‌نشیند و رویش را می‌گیرد */
  z-index: 4;
  margin-block-start: calc(0px - 100svh);
  /* تا نرسیده، روی پرده‌ی سوم افتاده و جلوی کلیک را می‌گیرد */
  pointer-events: none;
}

:root.is-arrived .strip-stage {
  pointer-events: auto;
}

.strip-stage__runway {
  block-size: var(--arrive);
}

/* مکثِ بعد از رسیدن. بدون این، ورق‌ها همان لحظه‌ای که باز می‌شدند شروع
   می‌کردند به رفتن و کاربر فرصتِ نگاه کردن نداشت. */
.strip-stage__hold {
  block-size: var(--hold);
}

.strip {
  position: sticky;
  inset-block-start: 0;
  padding-block: 0;
  scroll-margin-block-start: calc(0px - var(--arrive));
}

.strip__scene {
  position: relative;
  isolation: isolate;
  block-size: 100svh;
  /* روی نمایشگرِ خیلی کوتاه، قاب باید دست‌کم به قدِ تایپ باشد */
  min-block-size: 34rem;
  overflow: clip;
}

.strip__halo {
  position: absolute;
  inset: 0;
  z-index: 0;
  background:
    radial-gradient(62% 48% at 52% 44%, var(--glow) 0%, transparent 72%),
    radial-gradient(120% 80% at 50% 118%, var(--glow-soft), transparent 62%),
    var(--void);
}

/* --- محوشدن در سیاهی، بالا و پایین ---
   قاب‌ها از تاریکی بیرون می‌آیند و در تاریکی می‌روند. دو گرادیانِ ساکن،
   نه ماسک: ماسک روی والدِ عنصرِ متحرک هر فریم رستر دوباره می‌خواهد. */
.strip__scene::before,
.strip__scene::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  z-index: 5;
  block-size: 26%;
  pointer-events: none;
}

.strip__scene::before {
  inset-block-start: 0;
  background: linear-gradient(to bottom, var(--void) 22%, transparent);
}

.strip__scene::after {
  inset-block-end: 0;
  background: linear-gradient(to top, var(--void) 22%, transparent);
}

/* --- بادبزنِ قاب‌ها ---
   دوازده ورق روی هم، هفت‌تایشان دیده می‌شوند. فاصله‌ی هر ورق تا مرکز
   (`d`) همه‌چیزش را تعیین می‌کند: چرخش، مقیاس، افت به پایین، تاری و
   ترتیبِ لایه. جاوااسکریپت فقط همان یک عددِ پیوسته را می‌داند و مقادیر را
   از جدولی خطی درمی‌آورد؛ CSS بقیه را می‌سازد.

   چون `d` پیوسته است (نه هفت جای گسسته)، ورق دقیقاً با انگشت می‌آید و
   موقع رها شدن روی نزدیک‌ترین عدد صحیح می‌نشیند. --- */

.fan {
  position: absolute;
  inset: 0;
  /* روی شیشه (۴) و روی تایپ (۳) */
  z-index: 5;
  display: grid;
  align-content: center;
  justify-items: center;
  /* ضریب‌ها این‌جا زندگی می‌کنند نه در جاوااسکریپت: نقطه‌های شکست جای
     خودشان‌اند و جاوااسکریپت هیچ عددِ ریسپانسیوی نمی‌داند. */
  --fan-w: clamp(9rem, 15vw, 14rem);
  --fan-spread: 0.92;
  --fan-drop: 1;
  /* بادبزن کمی پایین‌تر از مرکز می‌نشیند تا سطرِ بالاییِ تایپ نفس بکشد */
  padding-block-start: clamp(2rem, 9vh, 5.5rem);
  /* ورق‌ها بعد از نشستنِ تایپ می‌آیند، نه با آن */
  opacity: clamp(0, calc((var(--enter, 1) - 0.5) * 2.6), 1);
}

.fan__deck {
  position: relative;
  inline-size: 100%;
  /* ارتفاعِ خودِ ورق، به‌اضافه‌ی جایی که ورق‌های کناری پایین می‌افتند —
     وگرنه ناوبری زیرِ همان ورق‌ها گم می‌شد. */
  block-size: calc(var(--fan-w) * 1.25 + 7rem * var(--fan-drop));
  /* عمود آزاد می‌ماند: کشیدنِ افقی صفحه را قفل نمی‌کند */
  touch-action: pan-y;
  cursor: grab;
  outline-offset: 1rem;
}

.fan__deck:active {
  cursor: grabbing;
}

.fan__card {
  position: absolute;
  inset-block-start: 0;
  inset-inline-start: 50%;
  inline-size: var(--fan-w);
  aspect-ratio: 4 / 5;
  margin-inline-start: calc(var(--fan-w) / -2);
  overflow: hidden;
  border-radius: clamp(10px, calc(var(--fan-w) * 0.085), 30px);
  background: var(--shadow);
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.55);
  transform-origin: 50% 120%;
  /* حالتِ اولیه تا وقتی جاوااسکریپت جایشان را بنویسد */
  opacity: 0;
  will-change: transform;
  transition: transform 620ms var(--ease-fan),
    opacity 420ms var(--ease-cue),
    filter 520ms var(--ease-cue);
  transition-delay: calc(var(--fd, 0) * 22ms);
}

/* موقع کشیدن هیچ تأخیری در کار نیست: ورق باید زیر انگشت باشد، نه دنبالش */
.fan.is-dragging .fan__card {
  transition: none;
}

/* فقط برای همان یک‌بارِ باز شدن: کندتر و با فاصله‌ی بیشتر بین ورق‌ها */
.fan.is-dealing .fan__card {
  transition-duration: 1700ms, 900ms, 900ms;
  transition-delay: calc(var(--fd, 0) * 110ms);
}

.fan__card img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  filter: contrast(1.06) brightness(0.94) saturate(0.9);
  pointer-events: none;
  -webkit-user-drag: none;
  user-select: none;
}

/* --- ناوبریِ بادبزن --- */

.fan__nav {
  position: relative;
  /* ورق‌ها تا z-index بیست بالا می‌روند؛ ناوبری باید بالای همه بماند */
  z-index: 30;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-3);
  margin-block-start: clamp(1.5rem, 4vh, 2.75rem);
}

.fan__arrow {
  display: grid;
  place-items: center;
  /* ۴۴ پیکسل، نه کمتر — همان کفی که کلِ سایت رعایت می‌کند */
  inline-size: 2.75rem;
  block-size: 2.75rem;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: none;
  color: var(--dust);
  cursor: pointer;
  transition: color var(--dur) var(--ease-cue),
    border-color var(--dur) var(--ease-cue),
    transform var(--dur) var(--ease-cue);
}

.fan__arrow:hover {
  color: var(--tungsten);
  border-color: var(--tungsten-dim);
}

.fan__arrow:active {
  transform: scale(0.94);
}

/* نشانه‌ها کیوِ نورند، نه شمارنده: خطِ روشن همان ورقِ وسط است */
.fan__cues {
  display: flex;
  align-items: center;
  gap: 0.3rem;
}

.fan__cue {
  inline-size: 0.5rem;
  block-size: 2px;
  background: var(--iron);
  transition: inline-size var(--dur) var(--ease-cue),
    background var(--dur) var(--ease-cue);
}

.fan__cue.is-on {
  inline-size: 1.25rem;
  background: var(--tungsten);
}

/* --- تایپ --- */

.strip__depth {
  position: absolute;
  inset: 0;
  z-index: 3;
  /* مرزِ «پشت» برای شیشه: هرچه بیرونِ این لایه است دستِ backdrop-filter
     نمی‌رسد. بدون این، شیشه ورق‌های عکس را هم تار می‌کرد. */
  isolation: isolate;
  pointer-events: none;
}

.strip__title {
  position: absolute;
  z-index: 1;
  /* از نزدیک شروع می‌کند و عقب می‌نشیند */
  --tin: clamp(0, calc(var(--enter, 1) / 0.62), 1);
  transform: scale(calc(1.5 - var(--tin) * 0.5));
  transform-origin: 50% 45%;
  opacity: var(--tin);
  inset-block: 0;
  inset-inline: var(--gutter);
  display: grid;
  align-content: center;
  gap: 0;
  font-size: var(--t-strip);
  font-weight: 900;
  /* باز کردنِ دو سطر عمدی است: باندِ میانی جای بادبزن است. با فاصله‌ی
     معمولی، ورق‌ها درست وسطِ کلمات می‌افتادند و هر دو را نصفه می‌کردند؛
     این‌طوری هر کلمه یک لبه‌ی قاب را برای خودش دارد. */
  line-height: 1.95;
  letter-spacing: 0;
  text-wrap: nowrap;
  color: var(--bone);
  /* تایپ عمداً کمی از فوکوس بیرون است: عمقِ میدان، مثل همان عکس‌ها.
     مقدار به اندازه‌ی قلم گره خورده تا در هر ویوپورت همان نسبت بماند. */
  filter: blur(calc(var(--t-strip) * 0.028));
}

/* --- نفس کشیدن ---
   دو کلمه خیلی آرام بالا و پایین می‌روند و تاریشان کم و زیاد می‌شود.

   تاریِ متغیر با انیمیت کردنِ خودِ filter ساخته نشده: آن‌طور مرورگر هر
   فریم باید کل کلمه را از نو رنگ‌آمیزی کند. این‌جا دو نسخه از هر کلمه
   روی هم است — یکی تیز، یکی تارتر — و فقط شفافیتِ نسخه‌ی تار نوسان
   می‌کند. برای GPU همان ترکیبِ دو لایه‌ی آماده است. */

.strip__line {
  display: block;
  position: relative;
  animation: strip-float 11s var(--ease-soft) infinite alternate;
}

.strip__line::after {
  content: attr(data-word);
  position: absolute;
  inset: 0;
  filter: blur(calc(var(--t-strip) * 0.085));
  opacity: 0.12;
  animation: strip-breathe 9s var(--ease-soft) infinite alternate;
}

.strip__line--b {
  animation-duration: 14s;
  animation-delay: -5s;
}

.strip__line--b::after {
  animation-duration: 12s;
  animation-delay: -4s;
}

@keyframes strip-float {
  from {
    transform: translate3d(0, -0.9%, 0);
  }

  to {
    transform: translate3d(0, 1.5%, 0);
  }
}

@keyframes strip-breathe {
  from {
    opacity: 0.06;
  }

  to {
    opacity: 0.52;
  }
}

.strip__line--a {
  text-align: start;
}

.strip__line--b {
  text-align: end;
}

/* --- شیشه‌ی روان ---
   دو لکه‌ی شیشه‌ای که آرام روی کلمات می‌لغزند: پشتشان تار و اشباع‌تر
   می‌شود و لبه‌شان یک خطِ نور دارد. عمداً کم‌جان است — قرار است حس شود،
   نه دیده.

   هزینه: `backdrop-filter` روی لایه‌ای که حرکت می‌کند یعنی تارکردنِ دوباره
   در هر فریم. برای همین لکه‌ها کوچک‌اند، حرکتشان بسیار کند است، تا قبل
   از رسیدنِ میان‌پرده کاملاً خاموش‌اند و روی گوشی اصلاً ساخته نمی‌شوند. */

.strip__glass {
  position: absolute;
  inset: 0;
  /* روی تایپ (۱)، داخلِ همان لایه‌ی جدا */
  z-index: 2;
  pointer-events: none;
  overflow: clip;
  opacity: clamp(0, calc((var(--enter, 1) - 0.25) * 2.4), 1);
}

.strip__glass-blob {
  position: absolute;
  border-radius: 50%;
  /* لبه‌ی لکه عمداً دیده می‌شود: شیشه‌ی واقعی هم لبه دارد. یک رینگِ نازکِ
     روشن و یک درخششِ داخلی، همان چیزی است که چشم «قطره‌ی شیشه» می‌خواند.

     یادداشت: این‌جا `mask` نمی‌گذاریم. ماسک روی عنصری که backdrop-filter
     دارد، در کروم تاری را به کلِ لایه‌ی زیرین می‌کشاند — یعنی عکس‌ها هم
     تار می‌شدند، نه فقط پشتِ خودِ لکه. */
  background: radial-gradient(
    closest-side,
    rgba(255, 255, 255, 0.045),
    rgba(255, 255, 255, 0.01) 55%,
    rgba(255, 255, 255, 0.035) 100%
  );
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.055),
    inset 0 2px 22px rgba(255, 255, 255, 0.035);
  will-change: transform;
}

@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .strip__glass-blob {
    -webkit-backdrop-filter: blur(7px) saturate(1.45) brightness(1.03);
    backdrop-filter: blur(7px) saturate(1.45) brightness(1.03);
  }
}

.strip__glass-blob--a {
  inline-size: 34vw;
  block-size: 34vw;
  inset-block-start: -6%;
  inset-inline-start: 4%;
  animation: glass-a 27s var(--ease-soft) infinite alternate;
}

.strip__glass-blob--b {
  inline-size: 30vw;
  block-size: 30vw;
  inset-block-end: -10%;
  inset-inline-end: 8%;
  animation: glass-b 35s var(--ease-soft) infinite alternate;
}

@keyframes glass-a {
  from {
    transform: translate3d(0, 0, 0) scale(1);
  }

  to {
    transform: translate3d(13vw, 9vh, 0) scale(1.14);
  }
}

@keyframes glass-b {
  from {
    transform: translate3d(0, 0, 0) scale(1.06);
  }

  to {
    transform: translate3d(-10vw, -8vh, 0) scale(0.94);
  }
}

/* --- برچسب‌ها و متن --- */

.strip__chrome {
  position: absolute;
  inset: 0;
  z-index: 6;
  display: grid;
  grid-template-rows: auto 1fr auto;
  grid-template-columns: 1fr 1fr;
  gap: var(--s-3);
  /* سربرگ ثابت است و بالای قاب می‌نشیند؛ برچسب باید از زیرش بیرون بیاید */
  padding: clamp(5rem, 12vh, 7rem) var(--gutter) clamp(1.5rem, 4.5vh, 3rem);
  pointer-events: none;
}

.strip__cue {
  grid-row: 1;
  grid-column: 1;
  justify-self: start;
}

.strip__note {
  grid-row: 1;
  grid-column: 2;
  justify-self: end;
  color: var(--tungsten-dim);
}

.strip__lede {
  grid-row: 3;
  grid-column: 1 / -1;
  align-self: end;
  max-inline-size: 24rem;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--t-lead);
  line-height: 1.65;
  color: var(--fg);
  text-wrap: pretty;
  opacity: clamp(0, calc((var(--enter, 1) - 0.62) * 3), 1);
  transform: translate3d(
    0,
    calc((1 - clamp(0, calc((var(--enter, 1) - 0.62) * 3), 1)) * 14px),
    0
  );
}

.strip__chrome .label {
  opacity: clamp(0, calc((var(--enter, 1) - 0.34) * 4), 1);
}

/* --- قابِ باریک: دو برچسبِ گوشه در ۳۲۰ پیکسل به هم می‌رسیدند ---
   برچسبِ سمت چپ همان جمله‌ای است که در متنِ پایین هم آمده، پس حذفش
   چیزی از دست نمی‌دهد. */
@media (max-width: 26rem) {
  .strip__note {
    display: none;
  }

  /* حالا که همسایه‌اش رفته، برچسب تمام عرض را دارد و دیگر نمی‌شکند */
  .strip__cue {
    grid-column: 1 / -1;
  }

  /* بادبزن جمع‌تر می‌شود تا ورق‌های کناری از لبه بیرون نزنند */
  .fan {
    --fan-spread: 0.28;
  }
}

/* --- قابِ کوتاه: گوشی در حالت افقی، تبلتِ کم‌ارتفاع ---
   قاب دقیقاً یک صفحه است و نباید از آن بلندتر شود، وگرنه ته تایپ و متن
   بیرون می‌ماند. تایپ به ارتفاع گره می‌خورد نه عرض. */
@media (max-height: 34rem) {
  .strip {
    --t-strip: clamp(2rem, 13vh, 5rem);
  }

  .strip__scene {
    min-block-size: 0;
  }

  /* کف ۵.۲۵rem تصادفی نیست: سربرگِ ثابت ۴.۷۵rem است و برچسب باید
     زیرش نرود. */
  .strip__chrome {
    padding-block-start: clamp(5.25rem, 16vh, 6rem);
  }

  /* در قابِ کوچک، شیشه بیشتر شلوغی است تا اثر */
  .strip__glass {
    display: none;
  }

  /* ارتفاع که کم شد، افتادنِ ورق‌های کناری هم باید کم شود */
  .fan {
    --fan-w: clamp(5.5rem, 17vh, 9rem);
    --fan-drop: 0.4;
    align-content: start;
    padding-block-start: clamp(6rem, 17vh, 7rem);
  }

  /* در قابِ پهن و کوتاه، ناوبری زیرِ بادبزن جا ندارد و روی متنِ پایین
     می‌افتاد. این‌جا فلش‌ها به دو لبه‌ی قاب می‌روند — همان‌جایی که دست
     در حالت افقی نگه‌داشتن گوشی هست — و نشانه‌ها که تزئینی‌اند می‌روند. */
  .fan__nav {
    position: absolute;
    inset: 0;
    margin: 0;
    justify-content: space-between;
    padding-inline: var(--gutter);
    pointer-events: none;
  }

  .fan__arrow {
    pointer-events: auto;
  }

  .fan__cues {
    display: none;
  }
}

/* ==========================================================================
   ۱۰ — پرده‌ی چهارم: تماس
   ========================================================================== */

.contact {
  border-block-start: 1px solid var(--line);
}

.contact__call {
  font-family: var(--font-display);
  font-size: var(--t-giant);
  font-weight: 900;
  line-height: 1.1;
  margin-block-end: var(--s-5);
  text-wrap: balance;
}

.contact__call .lit {
  color: var(--tungsten);
}

.links {
  display: grid;
  gap: 0;
  border-block-start: 1px solid var(--line);
  margin-block-start: var(--s-5);
}

.link-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  padding-block: var(--s-3);
  min-block-size: 56px;
  border-block-end: 1px solid var(--line);
  color: var(--fg);
  transition: padding-inline var(--dur) var(--ease-dimmer),
    color var(--dur) var(--ease-cue), background var(--dur) var(--ease-cue);
}

.link-row:hover,
.link-row:focus-visible {
  color: var(--tungsten);
  padding-inline: var(--s-2);
  background: linear-gradient(
    to left,
    var(--glow-soft),
    transparent 70%
  );
}

.link-row__label {
  display: inline-flex;
  align-items: center;
  gap: 0.85rem;
}

.link-row__value {
  font-family: var(--font-mono);
  font-size: var(--t-small);
  color: var(--smoke);
  direction: ltr;
  unicode-bidi: isolate;
  transition: color var(--dur) var(--ease-cue);
  overflow-wrap: anywhere;
}

.link-row:hover .link-row__value {
  color: var(--dust);
}

.link-row .icon {
  flex: none;
  color: var(--smoke);
  transition: color var(--dur) var(--ease-cue);
}

.link-row:hover .icon {
  color: var(--tungsten);
}

.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  min-block-size: 48px;
  padding: 0.85rem 1.6rem;
  border: 1px solid var(--tungsten-dim);
  color: var(--tungsten);
  font-family: var(--font-text);
  font-weight: 600;
  border-radius: 2px;
  position: relative;
  overflow: hidden;
  transition: color var(--dur) var(--ease-cue),
    border-color var(--dur) var(--ease-cue);
}

.btn::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--tungsten);
  transform: scaleX(0);
  transform-origin: right;
  transition: transform var(--dur-slow) var(--ease-dimmer);
  z-index: -1;
}

.btn:hover,
.btn:focus-visible {
  color: var(--void);
  border-color: var(--tungsten);
}

.btn:hover::before,
.btn:focus-visible::before {
  transform: scaleX(1);
}

.btn span,
.btn .icon {
  position: relative;
  z-index: 1;
}

/* ==========================================================================
   ۱۱ — صفحه‌ی تکی اجرا
   ========================================================================== */

.prod-hero {
  padding-block: clamp(8rem, 20vh, 13rem) var(--s-5);
}

.prod-hero__title {
  font-size: var(--t-giant);
  font-weight: 900;
  line-height: 1.05;
  margin-block: var(--s-3) var(--s-4);
}

.prod-facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
  gap: var(--s-4);
  padding-block: var(--s-4);
  border-block: 1px solid var(--line);
  margin-block-end: var(--s-6);
}

.fact__key {
  font-family: var(--font-mono);
  font-size: var(--t-label);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--smoke);
  display: block;
  margin-block-end: 0.4rem;
}

.fact__value {
  font-size: var(--t-body);
  color: var(--fg);
}

.prod-cover {
  position: relative;
  overflow: hidden;
  margin-block-end: var(--s-6);
  background: var(--shadow);
}

.prod-cover img {
  inline-size: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
}

.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr));
  gap: var(--s-2);
  margin-block-start: var(--s-6);
}

.gallery figure {
  position: relative;
  overflow: hidden;
  background: var(--shadow);
}

.gallery img {
  inline-size: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  filter: brightness(0.82) contrast(1.08);
  transition: filter var(--dur-slow) var(--ease-dimmer);
}

.gallery figure:hover img {
  filter: brightness(1) contrast(1.05);
}

/* پیمایش بین اجراها */
.prod-nav {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1px;
  background: var(--line);
  border-block-start: 1px solid var(--line);
  margin-block-start: var(--s-7);
}

.prod-nav a {
  background: var(--void);
  padding: var(--s-4) var(--s-3);
  display: grid;
  gap: 0.5rem;
  transition: background var(--dur) var(--ease-cue);
}

.prod-nav a:hover {
  background: var(--shadow);
}

.prod-nav__title {
  font-family: var(--font-display);
  font-size: var(--t-title);
  font-weight: 800;
  color: var(--fg);
  transition: color var(--dur) var(--ease-cue);
}

.prod-nav a:hover .prod-nav__title {
  color: var(--tungsten);
}

.prod-nav .end {
  text-align: end;
}

/* ==========================================================================
   ۱۲ — پابرگ
   ========================================================================== */

.site-footer {
  border-block-start: 1px solid var(--line);
  padding-block: var(--s-5);
  padding-block-end: max(var(--s-5), env(safe-area-inset-bottom));
  margin-block-start: var(--s-7);
}

.site-footer__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
}

.site-footer p {
  font-size: var(--t-small);
  color: var(--smoke);
}

.socials {
  display: flex;
  gap: 0.5rem;
}

.socials a {
  inline-size: 44px;
  block-size: 44px;
  display: grid;
  place-items: center;
  border: 1px solid var(--line);
  border-radius: 2px;
  color: var(--smoke);
  transition: color var(--dur) var(--ease-cue),
    border-color var(--dur) var(--ease-cue),
    background var(--dur) var(--ease-cue);
}

.socials a:hover,
.socials a:focus-visible {
  color: var(--tungsten);
  border-color: var(--tungsten-dim);
  background: var(--glow-soft);
}

.to-top {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  min-block-size: 44px;
  color: var(--smoke);
  font-family: var(--font-mono);
  font-size: var(--t-label);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  transition: color var(--dur) var(--ease-cue);
}

.to-top:hover,
.to-top:focus-visible {
  color: var(--tungsten);
}

/* ==========================================================================
   ۱۳ — حرکت و آشکارسازی
   --------------------------------------------------------------------------
   همه‌چیز «فید-آپ» است، نه «اسلاید». در تئاتر چیزها از کنار وارد نمی‌شوند؛
   نور رویشان می‌افتد. فقط opacity و transform انیمیت می‌شوند.
   ========================================================================== */

.reveal {
  opacity: 0;
  transform: translate3d(0, 14px, 0);
  transition: opacity var(--dur-cue) var(--ease-dimmer),
    transform var(--dur-cue) var(--ease-dimmer);
  transition-delay: calc(var(--d, 0) * 90ms);
}

.reveal.is-in {
  opacity: 1;
  transform: translate3d(0, 0, 0);
}

/* محتوای پرده‌ی اول هرگز منتظر اسکرول نمی‌ماند: با بالا آمدن نور ظاهر می‌شود.
   وگرنه جمله‌ی آغازین که پایین‌تر از خط فعال‌سازی می‌افتد تا اولین اسکرول
   نامرئی می‌ماند و صفحه‌ی اول ناقص به نظر می‌رسد. */
.is-lit .hero .reveal {
  opacity: 1;
  transform: translate3d(0, 0, 0);
}

/* کلمه‌به‌کلمه: در فارسی هرگز حرف‌به‌حرف نمی‌شکنیم چون اتصال خط از بین می‌رود */
.w {
  display: inline-block;
  overflow: hidden;
  vertical-align: top;
  /* فضای دنباله‌ی حروفی مثل ج/چ/ح که زیر خط کرسی می‌روند */
  padding-block-end: 0.12em;
  margin-block-end: -0.12em;
}

.w__in {
  display: inline-block;
  transform: translate3d(0, 110%, 0);
  transition: transform 900ms var(--ease-dimmer);
  transition-delay: calc(var(--i, 0) * 55ms);
}

.is-in .w__in {
  transform: translate3d(0, 0, 0);
}

/* فقط کلماتِ پرده‌ی اول به نور اولیه گره خورده‌اند، نه همه‌ی عنوان‌های صفحه */
.is-lit .hero .w__in {
  transform: translate3d(0, 0, 0);
}

/* --- پرده‌ی سینمایی روی تصویرها ---
   تصویر با مقیاس بزرگ‌تر شروع می‌کند و می‌نشیند، و هم‌زمان یک پرده‌ی سیاه
   مثل پرده‌ی صحنه بالا می‌رود. لبه‌ی پایینیِ پرده کهربایی است، پس موقع بالا
   رفتن یک خط نور پشت سرش می‌ماند.
   هر دو فقط transform هستند: هیچ layout و paint دوباره‌ای در کار نیست. */
[data-rv="img"] {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}

[data-rv="img"] > img,
[data-rv="img"] > picture > img {
  transform: scale(1.18);
  transition: transform 1600ms var(--ease-dimmer);
  will-change: transform;
}

[data-rv="img"]::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  transform-origin: top;
  transform: scaleY(1);
  transition: transform 1150ms var(--ease-dimmer);
  background: linear-gradient(
    to top,
    rgba(233, 169, 79, 0.55) 0%,
    rgba(233, 169, 79, 0.12) 3%,
    var(--void) 9%,
    var(--void) 100%
  );
}

[data-rv="img"].is-in > img,
[data-rv="img"].is-in > picture > img {
  transform: scale(1);
}

[data-rv="img"].is-in::after {
  transform: scaleY(0);
}

/* بزرگ‌نمایی نرم هنگام هاور — بعد از نشستن پرده، و با همان زبان حرکتی */
@media (hover: hover) and (pointer: fine) {
  [data-rv="img"].is-in:hover > img {
    transform: scale(1.04);
    transition-duration: 1200ms;
  }
}

/* --- ورود پلکانیِ سطرها: مثل بالا آمدن تدریجی نور روی صحنه --- */
[data-rv="up"] {
  opacity: 0;
  transform: translate3d(0, 26px, 0);
  transition: opacity 900ms var(--ease-dimmer),
    transform 900ms var(--ease-dimmer);
  transition-delay: calc(var(--d, 0) * 80ms);
}

[data-rv="up"].is-in {
  opacity: 1;
  transform: translate3d(0, 0, 0);
}

/* خط افقی که مثل کیوِ نور باز می‌شود */
.rule {
  block-size: 1px;
  background: var(--line);
  transform: scaleX(0);
  transform-origin: right;
  transition: transform var(--dur-cue) var(--ease-dimmer);
}

.rule.is-in {
  transform: scaleX(1);
}

/* ==========================================================================
   ۱۴ — واکنش‌گرایی
   --------------------------------------------------------------------------
   موبایل نسخه‌ی فشرده‌ی دسکتاپ نیست: چون مکان‌نما ندارد، عکس‌ها
   مستقیم داخل فهرست می‌آیند و خودشان نقشِ «نور» را بازی می‌کنند.
   ========================================================================== */

@media (max-width: 63.999rem) and (min-width: 48rem) {
  .fan {
    --fan-spread: 0.72;
  }
}

@media (min-width: 48rem) {
  .craft__grid {
    /* ستون تصویر از ۳۰rem بالاتر نمی‌رود: منبعِ این عکس ۴۷۸ پیکسل عرض
       دارد و بزرگ‌تر از آن فقط بزرگ‌نماییِ نرم می‌شود. */
    grid-template-columns: minmax(0, 1fr) minmax(0, 30rem);
    gap: var(--s-7);
  }

  .prod-nav {
    grid-template-columns: 1fr 1fr;
  }
}

@media (min-width: 64rem) {
  .links {
    grid-template-columns: 1fr;
  }
}

/* --- نمایشگرهای کوتاه: لپ‌تاپِ کم‌ارتفاع، تبلتِ افقی ---
   نام خودش با --t-hero کوچک شده؛ این‌جا فقط فاصله‌ها جمع می‌شوند تا
   پرده‌ی یکم راحت داخل یک قاب بنشیند. */
@media (min-width: 48rem) and (max-height: 54rem) {
  .hero {
    padding-block: 4.5rem var(--s-4);
  }

  .hero__eyebrow {
    margin-block-end: var(--s-2);
  }

  .hero__name {
    margin-block-end: var(--s-2);
  }

  .hero__role {
    font-size: clamp(1.5rem, 4.4vh, 2.4rem);
    margin-block-end: var(--s-3);
  }
}

/* --- زیر ۷۶۸ پیکسل --- */
@media (max-width: 47.999rem) {
  /* روی موبایل عکس و متن روی هم‌اند، پس در از بالا و پایین باز می‌شود:
     متن از بالای سرِ بیننده رد می‌شود و پرتره از زیر پایش. همان حس،
     چیدمانِ درست. */
  :root {
    /* روی گوشی، اسکرول با پرتابِ شست انجام می‌شود نه با چرخِ دقیق. همان
       حرکت‌ها می‌مانند ولی مسافتشان حدود ۴۰٪ کوتاه‌تر است تا حس «صفحه
       جلو نمی‌رود» پیش نیاید. */
    --runway: 90svh;
    --lift: 75svh;
    /* برچسب‌های ریز روی صفحه‌ی کوچک یک پله بزرگ‌تر */
    --t-label: 0.8125rem;
    /* حالا که متن بالا رفته و پایینِ قاب آزاد شده، نام می‌تواند بزرگ‌تر
       باشد. تایپوگرافی قرار بود قهرمانِ این صفحه باشد؛ ۱۵vw روی گوشی
       تقریباً به کفِ ۳.۴rem می‌خورد و آن نقش را از دست می‌داد. */
    --t-hero: clamp(3.4rem, min(17.5vw, 26vh), 13rem);
  }

  /* --- ناوبری در دسترسِ شست ---
     همان سه لینک، همان DOM — فقط روی گوشی به لبه‌ی پایین می‌رود، جایی
     که شست بدون جابه‌جا کردنِ گوشی می‌رسد. */
  .nav {
    position: fixed;
    isolation: isolate;
    inset-inline: 0;
    inset-block-end: 0;
    z-index: var(--z-header);
    justify-content: space-around;
    gap: 0;
    padding-inline: var(--gutter);
    /* حاشیه‌ی امنِ آیفون زیرِ نوار نگه داشته می‌شود */
    padding-block: 0.35rem;
    padding-block-end: calc(0.35rem + env(safe-area-inset-bottom));
    background: rgba(8, 8, 10, 0.62);
    border-block-start: 1px solid rgba(255, 255, 255, 0.08);
    transform: translate3d(0, 100%, 0);
  }

  /* شیشه‌ی نوارِ پایین. این‌جا هم روی شبه‌عنصر است، به همان دلیلِ سربرگ
     و یک دلیلِ دیگر: خودِ نوار `transform` می‌گیرد و لایه‌ی فیلترشده‌ی
     متحرک در هر فریم دوباره تار می‌شود. */
  .nav::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background: linear-gradient(
      to top,
      rgba(255, 255, 255, 0.035),
      transparent 70%
    );
  }

  @supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
    .nav::before {
      -webkit-backdrop-filter: blur(18px) saturate(1.4);
      backdrop-filter: blur(18px) saturate(1.4);
    }
  }

  @supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    .nav {
      background: var(--void);
    }
  }

  .is-scrolled .nav {
    transform: translate3d(0, 0, 0);
  }

  .nav a {
    flex: 1;
    justify-content: center;
    min-block-size: 48px;
  }

  /* backdrop-filter روی سربرگ دو مشکل دارد: هر فریمِ اسکرول یک بلورِ
     تمام‌عرض می‌خواهد، و مهم‌تر این‌که سربرگ را به «ظرفِ» عناصر fixed
     تبدیل می‌کند — یعنی نوارِ پایین از پایینِ صفحه به زیرِ سربرگ می‌پرید.
     روی گوشی پس‌زمینه‌ی توپر همان کار را می‌کند و رایگان است. */
  .is-scrolled .site-header {
    background: rgba(8, 8, 10, 0.5);
  }

  /* روی نوارِ پایین برای هر سه جا هست */
  .nav__hide-xs {
    display: inline-flex;
  }

  .nav a::after {
    inset-block-end: 0.35rem;
  }

  /* آخرین بخش زیرِ نوار پنهان نشود */
  .site-footer {
    padding-block-end: calc(4.5rem + env(safe-area-inset-bottom));
  }

  .hero {
    /* روی گوشی متن از بالا آویزان می‌شود، نه وسط‌چین. وسط‌چینی این‌جا
       ۱۸۱ پیکسل فضای مرده بالای «ACT 01» می‌گذاشت و پرتره را هم زیرِ
       متن دفن می‌کرد. با start، متن بالا می‌نشیند و نیمه‌ی پایین قاب
       به عکس می‌رسد. */
    align-content: start;
    padding-block-start: 7.5rem;
    perspective: 900px;
  }

  /* نفس‌های بین سطرها بازتر می‌شود — فضای آزادشده خرجِ ریتم می‌شود،
     نه این‌که به ته قاب منتقل شود. */
  .hero__eyebrow {
    margin-block-end: var(--s-4);
  }

  .hero__name {
    margin-block-end: var(--s-4);
  }

  .hero__role {
    margin-block-end: var(--s-5);
  }

  .hero__line {
    padding-block: var(--s-1);
  }

  .hero__door--text {
    transform-origin: 50% 100%;
    transform: translate3d(
        0,
        calc(var(--open, 0) * -38svh),
        calc(var(--open, 0) * 200px)
      )
      rotateX(calc(var(--open, 0) * -20deg));
  }

  .hero__door--image {
    transform-origin: 50% 0%;
    transform: translate3d(
        0,
        calc(var(--open, 0) * 38svh),
        calc(var(--open, 0) * 200px)
      )
      rotateX(calc(var(--open, 0) * 20deg));
  }

  .hero__portrait {
    inline-size: 100%;
    inset-block-start: auto;
    inset-block-end: 0;
    block-size: 56%;
    /* این عدد در محوشدنِ در ضرب می‌شود، نه این‌که جایش را بگیرد. حالا که
       متن بالا رفته و جلوی عکس را نمی‌گیرد، می‌تواند روشن‌تر باشد. */
    --door-alpha: 0.72;
    -webkit-mask-image: radial-gradient(
      ellipse 80% 70% at 50% 70%,
      #000 20%,
      transparent 72%
    );
    mask-image: radial-gradient(
      ellipse 80% 70% at 50% 70%,
      #000 20%,
      transparent 72%
    );
  }

  .hero__portrait img {
    object-position: 45% 25%;
  }

  /* بدون مکان‌نما «نزدیک شدن» معنا ندارد. به‌جای دو لایه‌ی روی هم که هر
     دو باید رمزگشایی و کامپوزیت شوند، یکی بس است. */
  .hero__portrait .layer-base {
    opacity: 0.62;
  }

  .hero__portrait .layer-lit {
    display: none;
  }

  .hero__line {
    max-width: 100%;
  }

  /* پشته روی گوشی: همان حرکت، مسافتِ کوتاه‌تر برای هر ورق. */
  :root {
    --card-step: 55svh;
  }

  .works-deck {
    margin-block-end: 3rem;
  }

  .wcard {
    padding: var(--s-4) var(--s-3);
    /* لبه‌های کم‌رنگ‌ترِ دسته روی صفحه‌ی کوچک نزدیک‌تر می‌نشینند */
    transform: translateX(calc((1 - var(--in)) * -108%))
      translateY(calc(var(--d) * 0.7rem))
      scale(calc(1 - var(--d) * 0.03));
  }

  .wcard__title {
    font-size: clamp(2rem, 9vw, 3rem);
  }

  /* روی گوشی کارت سه‌چهارمِ بالایش عکس است و متن ته‌نشین می‌شود؛ همان
     فضای خالی که قبلاً بی‌کار بود. */
  .wcard {
    grid-template-rows: minmax(0, 1fr) auto auto auto;
    align-content: stretch;
    gap: 0;
    padding: var(--s-2);
  }

  .wcard__thumb {
    display: block;
    position: relative;
    overflow: hidden;
    border-radius: 2px;
    background: var(--void);
    margin-block-end: var(--s-3);
  }

  .wcard__thumb img {
    inline-size: 100%;
    block-size: 100%;
    object-fit: cover;
    filter: contrast(1.08) brightness(0.82);
  }

  .wcard__cue {
    padding-inline: var(--s-2);
  }

  .wcard__title {
    padding-inline: var(--s-2);
    margin-block-start: 0.15rem;
  }

  .wcard__meta {
    padding-inline: var(--s-2);
    margin-block-start: 0.35rem;
    padding-block-end: var(--s-2);
  }


  .act__head {
    margin-block-end: var(--s-4);
  }

  .pull {
    margin-block: var(--s-5);
    font-size: 1.25rem;
    max-width: 100%;
  }

  .link-row {
    flex-direction: column;
    align-items: flex-start;
    gap: 0.4rem;
    padding-block: var(--s-3);
  }

  /* --- میان‌پرده روی گوشی ---
     روی ۳۹۰ پیکسل، ورقِ بزرگ هر دو کلمه را می‌بلعید. این نسبت‌ها طوری
     چیده شده‌اند که ورقِ وسط از میانه رد شود و از هر کلمه دست‌کم شصت
     درصد بیرون بماند. */
  .strip {
    --t-strip: clamp(2.5rem, 16vw, 6rem);
  }

  .fan {
    --fan-w: clamp(9rem, 42vw, 13rem);
    --fan-spread: 0.42;
  }

  /* روی گوشی چیدمان عوض می‌شود، نه فقط کوچک: ارتفاعِ یک صفحه‌ی گوشی
     جا ندارد که دو کلمه به دو سرِ قاب بچسبند و بادبزن و ناوبری و متن هم
     بینشان جا شوند. این‌جا تایپ یک بلوکِ دوسطری بالای قاب می‌شود و
     بادبزن تمامِ نیمه‌ی پایین را می‌گیرد. */
  /* برچسبِ پرده تا حدود ۱۲۵ پیکسل پایین می‌آید؛ عنوان باید از زیرِ آن
     شروع شود نه رویش. */
  .strip__title {
    align-content: start;
    padding-block-start: clamp(8rem, 19vh, 10rem);
    line-height: 1.06;
  }

  .fan {
    padding-block-start: clamp(7rem, 17vh, 9rem);
  }

  /* روی گوشی شیشه‌ی روان ساخته نمی‌شود: دو لایه‌ی backdrop-filterِ متحرک
     روی GPUِ گوشی گران‌ترین چیزِ کلِ صفحه می‌شد. */
  .strip__glass {
    display: none;
  }

  .strip__scene {
    min-block-size: 30rem;
  }

  /* نوارِ ناوبریِ پایین روی محتوا می‌نشیند؛ متن باید از بالایش رد شود */
  .strip__chrome {
    padding-block-end: calc(4.75rem + env(safe-area-inset-bottom));
  }

  .strip__lede {
    max-inline-size: none;
    font-size: 1rem;
    line-height: 1.75;
  }

  .site-footer__inner {
    flex-direction: column;
    align-items: flex-start;
  }

  .nav {
    gap: 1rem;
  }

  .nav a {
    font-size: 0.62rem;
    letter-spacing: 0.1em;
  }
}

/* ==========================================================================
   ۱۵ — دسترس‌پذیری
   ========================================================================== */

:focus-visible {
  outline: 2px solid var(--tungsten);
  outline-offset: 3px;
  border-radius: 2px;
}

/* هرگز حلقه‌ی فوکوس را حذف نمی‌کنیم؛ فقط برای اشاره‌گر پنهانش می‌کنیم */
:focus:not(:focus-visible) {
  outline: none;
}

.sr-only {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* --- گوشیِ کوتاه (زیر ۶۴۰ پیکسل ارتفاع) ---
   متن که از بالا آویزان شد، روی صفحه‌های کوتاه ته‌اش به «SCROLL» می‌رسید.
   این‌جا فقط ریتم جمع می‌شود؛ چیزی حذف نمی‌شود. */
@media (max-width: 47.999rem) and (max-height: 40rem) {
  .hero {
    padding-block-start: 5.75rem;
  }

  .hero__eyebrow,
  .hero__name {
    margin-block-end: var(--s-3);
  }

  .hero__role {
    margin-block-end: var(--s-4);
  }

  /* --- میان‌پرده روی گوشیِ کوتاه ---
     در ۵۶۸ پیکسل ارتفاع، تایپ و بادبزن و ناوبری و متن با هم جا نمی‌شوند.
     بادبزن از بالا شروع می‌کند (نه از وسط) و کوچک‌تر می‌شود تا ناوبری
     بالای متنِ پایین بایستد؛ تایپ همان‌طور که در دسکتاپ هست پشتِ ورق‌ها
     می‌ماند. */
  .strip {
    --t-strip: clamp(2rem, 12vw, 3.2rem);
  }

  .fan {
    --fan-w: clamp(5rem, 15vh, 7rem);
    --fan-drop: 0.5;
    align-content: start;
    padding-block-start: clamp(11.5rem, 33vh, 13rem);
  }

  .fan__nav {
    margin-block-start: var(--s-1);
  }

  /* زیر برچسبِ پرده، نه رویش */
  .strip__title {
    padding-block-start: clamp(6.25rem, 17vh, 7rem);
  }

  .strip__lede {
    font-size: 0.94rem;
    line-height: 1.7;
  }
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }

  /* همه‌چیز مستقیم در حالت نهاییِ خوانا رندر می‌شود */
  .reveal {
    opacity: 1;
    transform: none;
  }

  .w__in {
    transform: none;
  }

  .rule {
    transform: scaleX(1);
  }

  .grain,
  .spot,
  .beam,
  .cursor,
  .cursor-dot {
    display: none;
  }

  .dimmer {
    display: none;
  }

  .hero__name .dim {
    color: var(--bone);
  }

  .hero__portrait .layer-lit {
    opacity: 0.4;
  }

  /* صحنه قفل نمی‌شود و درها بسته می‌مانند؛ هیرو یک بخشِ معمولی است */
  .hero-stage {
    block-size: auto;
  }

  .hero {
    position: static;
    block-size: auto;
    min-block-size: 100svh;
    perspective: none;
  }

  .hero__door {
    transform: none;
    filter: none;
    opacity: var(--door-alpha, 1);
  }

  .works-stage {
    margin-block-start: 0;
  }

  .works-stage__runway {
    display: none;
  }

  /* قاب دیگر یک صفحه‌ی قفل‌شده نیست؛ باید به قدِ کارت‌ها بلند شود،
     وگرنه overflow: clip بقیه‌ی اجراها را می‌بُرد. */
  .works {
    position: static;
    display: block;
    block-size: auto;
    overflow: visible;
    transform: none;
    opacity: 1;
  }

  .works > .container {
    display: block;
  }

  .craft-stage {
    margin-block-start: 0;
    pointer-events: auto;
    opacity: 1;
  }

  .craft-stage__runway {
    display: none;
  }

  .craft {
    position: static;
  }

  .craft .act__head,
  .craft .prose,
  .craft-stage .craft__figure,
  .craft [data-words] .w__in {
    opacity: 1;
    text-shadow: none;
  }

  .strip-stage {
    margin-block-start: 0;
    pointer-events: auto;
  }

  .strip-stage__runway,
  .strip-stage__hold {
    display: none;
  }

  .strip {
    position: static;
  }

  .strip__glass {
    display: none;
  }

  .strip__title {
    transform: none;
    opacity: 1;
  }

  .strip__line {
    animation: none;
  }

  .strip__line::after {
    display: none;
  }

  .fan {
    opacity: 1;
  }

  .strip__chrome .label {
    opacity: 1;
  }

  /* --- میان‌پرده بدون حرکت ---
     بادبزن باز می‌شود و همان قاب‌ها یک گالریِ سه‌ستونی می‌شوند. کشیدن و
     ورق زدن معنا ندارد، پس ناوبری‌اش هم می‌رود. */
  .strip__scene {
    block-size: auto;
    min-block-size: 0;
    overflow: visible;
    padding-block: var(--s-6);
  }

  .strip__scene::before,
  .strip__scene::after {
    display: none;
  }

  .fan {
    position: static;
    opacity: 1;
    padding-inline: var(--gutter);
  }

  .fan__deck {
    block-size: auto;
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--s-2);
    cursor: auto;
  }

  .fan__card {
    position: static;
    inline-size: auto;
    margin-inline: 0;
    opacity: 1;
    transform: none;
    filter: none;
    transition: none;
    box-shadow: none;
  }

  .fan__nav {
    display: none;
  }

  .strip__title {
    position: static;
    filter: none;
    /* فاصله‌ی بازِ دو سطر برای عبورِ بادبزن بود؛ بادبزن که رفت، عنوان
       دوباره یک عنوانِ معمولی است. */
    line-height: 1.08;
    padding-block: var(--s-5);
    padding-inline: var(--gutter);
  }

  .strip__line {
    opacity: 1;
    transform: none;
  }

  .strip__chrome {
    position: static;
    padding-block: 0;
  }

  .strip__lede {
    opacity: 1;
    transform: none;
  }

  /* پشته باز می‌شود و کارت‌ها یک فهرستِ معمولی می‌شوند */
  .works-deck {
    block-size: auto;
    margin-block-end: 0;
  }

  .wcard {
    position: static;
    transform: none;
    opacity: 1;
    margin-block-end: var(--s-2);
  }

  .deck-track,
  .deck-rail {
    display: none;
  }

  .deck-count__col {
    transform: none;
  }

  /* پرده‌ها بالا رفته، تصویرها در اندازه‌ی نهایی */
  [data-rv="img"]::after {
    transform: scaleY(0);
  }

  [data-rv="img"] > img,
  [data-rv="img"] > picture > img {
    transform: none;
  }

  [data-rv="up"] {
    opacity: 1;
    transform: none;
  }
}

/* اگر جاوااسکریپت نبود، هیچ چیز پنهان نمی‌ماند */
.no-js .reveal {
  opacity: 1;
  transform: none;
}

.no-js .w__in {
  transform: none;
}

.no-js .rule {
  transform: scaleX(1);
}

.no-js .dimmer {
  display: none;
}

.no-js .hero__name .dim {
  color: var(--bone);
}

.no-js .hero__portrait .layer-lit {
  opacity: 0.4;
}

.no-js .hero-stage {
  block-size: auto;
}

.no-js .hero {
  position: static;
  block-size: auto;
  min-block-size: 100svh;
  perspective: none;
}

.no-js .hero__door {
  transform: none;
  filter: none;
  opacity: var(--door-alpha, 1);
}

.no-js .works-stage {
  margin-block-start: 0;
}

.no-js .works-stage__runway {
  display: none;
}

.no-js .works {
  position: static;
  display: block;
  block-size: auto;
  overflow: visible;
  transform: none;
  opacity: 1;
}

.no-js .works > .container {
  display: block;
}

.no-js .works-deck {
  block-size: auto;
  margin-block-end: 0;
}

.no-js .wcard {
  position: static;
  transform: none;
  opacity: 1;
  margin-block-end: var(--s-2);
}

.no-js .deck-track,
.no-js .deck-rail {
  display: none;
}

.no-js .deck-count__col {
  transform: none;
}

.no-js .craft-stage {
  margin-block-start: 0;
  pointer-events: auto;
  opacity: 1;
}

.no-js .craft-stage__runway {
  display: none;
}

.no-js .craft {
  position: static;
}

.no-js [data-rv="img"]::after {
  transform: scaleY(0);
}

.no-js [data-rv="img"] > img,
.no-js [data-rv="img"] > picture > img {
  transform: none;
}

.no-js [data-rv="up"] {
  opacity: 1;
  transform: none;
}

@media (prefers-contrast: more) {
  :root {
    --muted: #d8d2c8;
    --smoke: #b5afa6;
    --line: rgba(237, 231, 220, 0.28);
  }

  .wcard {
    border-color: var(--line);
  }
}

/* --- میان‌پرده بدون حرکت ---
   بادبزن باز می‌شود و همان قاب‌ها یک گالریِ سه‌ستونی می‌شوند. کشیدن و
   ورق زدن معنا ندارد، پس ناوبری‌اش هم می‌رود. */
.no-js .strip-stage {
  margin-block-start: 0;
  pointer-events: auto;
}

.no-js .strip-stage__runway,
.no-js .strip-stage__hold {
  display: none;
}

.no-js .strip {
  position: static;
}

.no-js .strip__glass {
  display: none;
}

.no-js .strip__title {
  transform: none;
  opacity: 1;
}

.no-js .strip__line {
  animation: none;
}

.no-js .strip__line::after {
  display: none;
}

.no-js .fan {
  opacity: 1;
}

.no-js .strip__chrome .label {
  opacity: 1;
}

.no-js .strip__scene {
  block-size: auto;
  min-block-size: 0;
  overflow: visible;
  padding-block: var(--s-6);
}

.no-js .strip__scene::before,
.no-js .strip__scene::after {
  display: none;
}

.no-js .fan {
  position: static;
  opacity: 1;
  padding-inline: var(--gutter);
}

.no-js .fan__deck {
  block-size: auto;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s-2);
  cursor: auto;
}

.no-js .fan__card {
  position: static;
  inline-size: auto;
  margin-inline: 0;
  opacity: 1;
  transform: none;
  filter: none;
  transition: none;
  box-shadow: none;
}

.no-js .fan__nav {
  display: none;
}

.no-js .strip__title {
  position: static;
  filter: none;
  /* فاصله‌ی بازِ دو سطر برای عبورِ بادبزن بود؛ بادبزن که رفت، عنوان
     دوباره یک عنوانِ معمولی است. */
  line-height: 1.08;
  padding-block: var(--s-5);
  padding-inline: var(--gutter);
}

.no-js .strip__line {
  opacity: 1;
  transform: none;
}

.no-js .strip__chrome {
  position: static;
  padding-block: 0;
}

.no-js .strip__lede {
  opacity: 1;
  transform: none;
}

@media print {
  .dimmer,
  .grain,
  .spot,
  .beam,
  .site-header,
  .fan,
  .hero__scroll {
    display: none !important;
  }

  body {
    background: #fff;
    color: #000;
  }
}
