  /* ============================================================
     FR-SITE40 — страница «About me» (/about/, RU-версия в /about/ru/).
     Десктоп: слева видео-колонка (фиксированная), справа — ЧИТАЕМЫЙ текст
     со своей прокруткой; за текстом еле заметные знаки глав (тигр, шапочка,
     монеты, ракета, процессор) по очереди слева и справа.
     Мобилка: только текст + круглая «говорящая голова» внизу слева —
     как на страницах лекций.
     Дизайн-система с главной: JetBrains Mono, #050505, #8854F3/#F97316.
     ============================================================ */
  *, *::before, *::after { box-sizing: border-box; }
  html, body { margin: 0; padding: 0; background: #050505; color-scheme: dark;
    font-family: 'JetBrains Mono', monospace; color: #E5E7EB;
    -webkit-text-size-adjust: 100%; text-size-adjust: 100%;
    -webkit-tap-highlight-color: transparent; overscroll-behavior: none;
    /* биография листается ЭКРАНАМИ, как главная: страница не прокручивается,
       экраны сменяют друг друга анимацией (колесо, свайп, стрелки, меню) */
    overflow: hidden; width: 100vw; height: 100vh; height: 100dvh;
    /* отступ колонки текста: от него же считается растушёвка ролика */
    --read-left: 56%;
    /* диаметр кружка с роликом на телефоне: от него считается нижнее поле глав */
    /* считается от МЕНЬШЕЙ стороны окна — см. комментарий в strategy.css */
    --vid-d: clamp(88px, min(34vw, 18vh), 168px); }
  a { color: inherit; text-decoration: none; }
  *:focus-visible { outline: 2px solid #8854F3; outline-offset: 2px; }
  ::selection { background: #8854F3; color: #ffffff; }
  /* как на главной: на больших экранах поднимаем весь макет целиком */
  @media (min-width:1600px) { body { zoom: 1.15; } }
  @media (min-width:1900px) { body { zoom: 1.3; } }
  @media (min-width:2300px) { body { zoom: 1.5; } }

  /* ===== Grain overlay (как на главной) ===== */
  .grain { position: fixed; inset: 0; z-index: 4; pointer-events: none; opacity: 0.06; mix-blend-mode: screen;
    background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E");
    background-size: 180px 180px; }

  /* ===== Прогресс чтения ===== */
  .progress { position: fixed; top: 0; left: 0; height: 2px; width: 0; z-index: 60; pointer-events: none;
    background: linear-gradient(90deg, #8854F3 0%, #F97316 100%); box-shadow: 0 0 12px rgba(136,84,243,0.6); transition: width 0.1s linear; }

  /* ===== Header (повторяет главную) ===== */
  header { position: fixed; top: 0; left: 0; right: 0; z-index: 30; pointer-events: none; padding: 1.1rem; }
  /* Текст уезжает ПОД шапку, и раньше он просвечивал сквозь неё. Плотная
     растушёвка в чёрное закрывает его строго над колонкой чтения: на десктопе
     она начинается там же, где колонка (44%), чтобы не затемнять лицо в ролике. */
  .top-fade { position: fixed; top: 0; left: 0; right: 0; height: 6.5rem; z-index: 29; pointer-events: none;
    background: linear-gradient(to bottom, #050505 0%, #050505 46%, rgba(5,5,5,0.88) 66%, rgba(5,5,5,0) 100%); }
  @media (min-width:1024px) { .top-fade { left: var(--read-left); height: 9.5rem; } }
  @media (min-width:1024px) { header { padding: 2rem; } }
  .header-row { position: relative; display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; }
  .header-left { pointer-events: auto; display: flex; align-items: center; gap: 0.6rem; min-width: 0; }
  .header-right { pointer-events: auto; display: flex; align-items: center; gap: 0.4rem; flex-shrink: 0; }
  .logo-btn { cursor: pointer; flex-shrink: 0; display: block; }
  .logo-img { width: clamp(2.85rem, 12vw, 3.7rem); height: clamp(2.85rem, 12vw, 3.7rem); object-fit: contain; filter: drop-shadow(0 4px 8px rgba(0,0,0,0.4)); }
  @media (min-width:1024px) { .logo-img { width: 3.6rem; height: 3.6rem; } }
  .brand-name { font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; color: #ffffff; white-space: nowrap; }
  @media (max-width:1149px) { .brand-name { display: none; } }

  /* Навигация: на десктопе пилюля, ниже 1150px — полноэкранное меню (как на главной) */
  .nav { display: none; }
  @media (min-width:1150px) {
    .nav { display: flex; align-items: center; gap: 0.3rem; position: absolute; left: calc(50% - 3.5rem); top: 50%; transform: translate(-50%, -50%);
      height: 2.85rem; background: rgba(10,10,16,0.5); border: 1px solid rgba(255,255,255,0.10); border-radius: 999px; padding: 0 1rem;
      -webkit-backdrop-filter: blur(16px); backdrop-filter: blur(16px); box-shadow: 0 4px 30px rgba(0,0,0,0.3); pointer-events: auto; }
  }
  .nav-tab { background: transparent; border: 0; cursor: pointer; text-transform: uppercase; font-weight: 700; white-space: nowrap;
    color: #cbd5e1; padding: 0.55rem 1rem; font-size: 26px; letter-spacing: 0.12em; transition: color 0.3s ease; display: flex; }
  .nav-tab.active { color: #ffffff; }
  @media (hover:hover) { .nav-tab:hover { color: var(--hover, #8854F3); } }
  .nav-ic, .nav-go, .nav-divider { display: none; }
  @media (min-width:1150px) {
    .nav-tab { font-size: clamp(12.5px, 1.05vw, 14px); font-weight: 500; letter-spacing: 0.015em; padding: 0.3rem 0.45rem; color: #94a3b8; }
    .nav-tab.active { color: #ffffff; background: linear-gradient(var(--ul), var(--ul)) no-repeat bottom center / 70% 2px; }
    .nav-divider { display: inline; color: rgba(255,255,255,0.22); font-size: 12px; padding: 0 0.06rem; user-select: none; }
  }
  @media (min-width:1150px) and (max-width:1439px) {
    .nav { left: calc(50% - 5rem); gap: 0.12rem; padding-left: 0.7rem; padding-right: 0.7rem; }
    .nav-tab { letter-spacing: 0; padding-left: 0.3rem; padding-right: 0.3rem; }
  }
  @media (max-width:1149px) {
    .nav.open { position: fixed; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 0;
      padding: clamp(6rem, 12vh, 7.5rem) 1.75rem calc(8rem + env(safe-area-inset-bottom, 0px)); z-index: 50; background: #050505; overflow-y: auto; pointer-events: auto; }
    .nav.open .nav-tab { display: flex; align-items: center; gap: 1.15rem; width: 100%; max-width: 23rem; text-align: left;
      border-top: 1px solid rgba(255,255,255,0.14); padding: clamp(0.7rem, 2.2vh, 1.4rem) 0.25rem;
      color: #ffffff; font-size: clamp(16px, 2.3vh, 20px); letter-spacing: 0.1em; }
    .nav.open .nav-tab:last-of-type { border-bottom: 1px solid rgba(255,255,255,0.14); }
    .nav.open .nav-ic { display: inline-flex; align-items: center; justify-content: center; width: 2rem; flex-shrink: 0; font-size: clamp(17px, 2.3vh, 21px); color: var(--ic); }
    .nav.open .nav-label { flex: 1; min-width: 0; }
    .nav.open .nav-go { display: inline-flex; align-items: center; justify-content: center; width: 1.4rem; flex-shrink: 0; font-size: 13px; color: rgba(255,255,255,0.45); }
    .nav.open .nav-tab.active .nav-label, .nav.open .nav-tab.active .nav-go { color: var(--ic); }
    .nav.open .nav-brand { display: flex; align-items: center; justify-content: center; gap: 0.7rem; position: absolute; top: clamp(4.3rem, 8vh, 5rem); left: 1.1rem; right: 1.1rem; pointer-events: none; }
    .nav.open .nav-brand-img { width: clamp(2.6rem, 11.5vw, 3.4rem); height: clamp(2.6rem, 11.5vw, 3.4rem); object-fit: contain; flex-shrink: 0; }
    .nav.open .nav-brand-name { font-size: clamp(14px, 4.6vw, 19px); font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; color: #ffffff; white-space: nowrap; }
    .nav.open .nav-close { display: flex; position: absolute; top: 1.35rem; right: 1.35rem; width: 2.6rem; height: 2.6rem; align-items: center; justify-content: center;
      background: transparent; border: 0; color: #ffffff; cursor: pointer; }
    .nav.open .nav-foot { display: flex; flex-direction: column; align-items: center; gap: 0.8rem;
      position: absolute; left: 1.5rem; right: 1.5rem; bottom: calc(1.3rem + env(safe-area-inset-bottom, 0px)); }
  }
  @media (max-width:1149px) and (max-height:700px) { .nav.open .nav-tab { padding-top: 0.5rem; padding-bottom: 0.5rem; } }
  .nav-brand, .nav-close, .nav-foot { display: none; }
  .nav-social { display: flex; align-items: center; justify-content: center; gap: 1.1rem; }
  .social { color: rgba(255,255,255,0.75); font-size: 18px; transition: color 0.3s ease, transform 0.3s ease; }
  @media (hover:hover) { .social:hover { color: var(--brand); transform: translateY(-2px); } }
  .nav-legal { display: flex; align-items: center; justify-content: center; gap: 0.7rem; }
  .nav-legal-link { color: rgba(255,255,255,0.5); font-size: 12px; text-transform: uppercase; letter-spacing: 0.12em; font-weight: 600; white-space: nowrap; }
  .nav-legal-sep { color: rgba(255,255,255,0.3); font-size: 12px; }
  .nav-copy { margin: 0; font-size: 10px; text-transform: uppercase; letter-spacing: 0.1em; color: rgba(255,255,255,0.45); text-align: center; }

  .lang-switch { display: flex; align-items: center; gap: 0.3rem; margin-right: clamp(0.5rem, 3.5vw, 1.4rem); flex-shrink: 0; }
  @media (max-width:1023px) { .header-right { flex: 1 0 auto; } .lang-switch { margin-left: clamp(0.5rem, 2.2vw, 1.5rem); margin-right: auto; } }
  .lang-opt { background: none; border: 0; padding: 0.2rem 0.05rem; cursor: pointer; font-size: 11px; font-weight: 500;
    letter-spacing: 0.08em; color: rgba(255,255,255,0.45); transition: color 0.3s ease; display: inline-block; }
  .lang-opt.active { color: #ffffff; font-weight: 700; }
  @media (hover:hover) { .lang-opt:hover { color: #ffffff; } }
  .lang-sep { color: rgba(255,255,255,0.25); font-size: 10px; user-select: none; }
  @media (min-width:1024px) { .lang-opt { font-size: 12px; } .lang-switch { margin-right: 2rem; } }
  @media (min-width:1024px) and (max-width:1319px) { .lang-switch { gap: 0.12rem; margin-right: 1rem; } .lang-opt { font-size: 11px; letter-spacing: 0; } }

  .menu-btn { display: flex; align-items: center; justify-content: center; width: clamp(2.5rem, 11vw, 3.3rem); height: clamp(2.5rem, 11vw, 3.3rem); border-radius: 999px;
    background: rgba(10,10,16,0.55); border: 1px solid rgba(255,255,255,0.10); -webkit-backdrop-filter: blur(16px); backdrop-filter: blur(16px);
    color: #ffffff; box-shadow: 0 8px 24px rgba(0,0,0,0.35); cursor: pointer; flex-shrink: 0; }
  @media (min-width:1024px) { .menu-btn { width: 2.85rem; height: 2.85rem; } }
  @media (min-width:1150px) { .menu-btn { display: none; } }

  .btn-white { background: #ffffff; color: #050505; border: 1px solid rgba(255,255,255,0.1); border-radius: 999px; font-weight: 700; text-transform: uppercase;
    display: inline-flex; align-items: center; justify-content: center; gap: 0.6rem; box-shadow: 0 4px 15px rgba(0,0,0,0.18); cursor: pointer; transition: all 0.3s ease; white-space: nowrap; }
  @media (hover:hover) { .btn-white:hover { background: linear-gradient(100deg, #8854F3 0%, #F97316 50%, #8854F3 100%); background-size: 250% 250%; color: #ffffff; border-color: transparent;
      box-shadow: 0 10px 25px -5px rgba(136,84,243,0.45); transform: translateY(-2px); animation: gradientShimmer 4.5s ease infinite; } }
  @keyframes gradientShimmer { 0% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } 100% { background-position: 0% 50%; } }
  .cta { padding: clamp(0.62rem, 2.2vw, 0.95rem) clamp(0.85rem, 3.2vw, 1.35rem); font-size: clamp(9px, 2.7vw, 12.5px); letter-spacing: clamp(0.06em, 0.4vw, 0.1em); gap: clamp(0.4rem, 1.2vw, 0.6rem); }
  @media (min-width:1024px) { .cta { height: 2.85rem; padding: 0 1.4rem; font-size: 11.5px; letter-spacing: 0.15em; gap: 0.55rem; } }
  @media (min-width:1024px) and (max-width:1319px) { .cta { padding: 0 0.95rem; font-size: 10.5px; letter-spacing: 0.08em; gap: 0.4rem; } }
  @media (max-width:380px) {
    header { padding: 0.85rem 0.6rem; }
    .header-right { flex: 0 0 auto; gap: 0.3rem; }
    .lang-switch { margin-left: 0; margin-right: 0.25rem; gap: 0.12rem; }
    .lang-opt { font-size: 10px; letter-spacing: 0.03em; }
    .logo-img { width: 2.5rem; height: 2.5rem; }
    .menu-btn { width: 2.3rem; height: 2.3rem; }
    .cta { padding: 0.6rem 0.55rem; font-size: 8px; letter-spacing: 0.02em; }
  }

  /* ===== Видео: колонка слева (десктоп) → кружок внизу слева (мобилка) ===== */
  /* На стыке ролика и чёрной колонки блестела светлая полоска: градиент
     доходил до #050505 ровно на краю, и крайний столбец пикселей кадра
     просвечивал. Теперь ролик заходит на 2px под колонку, а чёрное в
     градиенте начинается раньше — шва не остаётся. */
  /* Пропорции как на главной в вебе: ролик 67%, колонка текста 44%
     (--read-left: 56%). Кадр сдвинут влево ровно как #hero-video на главной —
     иначе лицо стоит по центру колонки и жмётся к тексту. */
  .media { position: fixed; top: 0; left: 0; width: 67%; height: 100dvh; overflow: hidden; background: #050505; z-index: 2; }
  .media video { transform: translateX(-6%); }
  .media video { width: 100%; height: 100%; object-fit: cover; object-position: center center; display: block; cursor: pointer; }
  /* Растушёвка — ровно как на главной (FR-SITE17): много стопов, лицо не
     затемняется вовсе, чернота набирается только в хвосте колонки. Колонка
     при этом ШИРЕ отступа текста, поэтому и шов кадра, и край видео уходят
     под чёрное, а лицо остаётся чистым. */
  /* Растушёвка отсчитывается от ЛЕВОГО КРАЯ КОЛОНКИ ТЕКСТА, а не от края
     колонки ролика. Прежние стопы (35% … 88% ширины колонки) были скопированы
     из ЛАНДШАФТНОГО мобильного правила главной и на вебе гасили лицо почти с
     середины: замер по столбцам яркости давал на 36% ширины 60 против 124 у
     главной. Теперь чернота набирается ровно к тексту при любой ширине. */
  .media-shadow { position: absolute; inset: 0; pointer-events: none;
    background: linear-gradient(to right,
      rgba(5,5,5,0)    calc(var(--read-left) * 0.746),
      rgba(5,5,5,0.08) calc(var(--read-left) * 0.896),
      rgba(5,5,5,0.20) calc(var(--read-left) * 1.020),
      rgba(5,5,5,0.40) calc(var(--read-left) * 1.144),
      rgba(5,5,5,0.60) calc(var(--read-left) * 1.269),
      rgba(5,5,5,0.82) calc(var(--read-left) * 1.393),
      #050505          calc(var(--read-left) * 1.493)); }
  /* Мобилка (и узкий планшет): та же <video>, но формой — «говорящая голова»
     в кружке внизу слева, как на страницах лекций. Кадр размыт, пока не нажали. */
  /* селекторы с .media — чтобы правила бейджа/затемнения ниже их не перебили */
  @media (max-width:1023px) {
    /* touch-action: none — кружок таскают пальцем; при manipulation браузер
       забирает жест себе и pointermove до элемента не доходит */
    .media { touch-action: none;
      top: auto; left: clamp(0.85rem, 4vw, 1.4rem); bottom: calc(clamp(0.85rem, 4vw, 1.4rem) + env(safe-area-inset-bottom, 0px));
      width: var(--vid-d); height: var(--vid-d); border-radius: 50%; z-index: 25; cursor: pointer;
      border: 1px solid rgba(255,255,255,0.18); box-shadow: 0 14px 34px rgba(0,0,0,0.55); }
    .media video { object-position: center 18%; filter: blur(5px); transform: scale(1.08); transition: filter 0.25s ease, transform 0.25s ease; }
    .media.is-playing video { transform: none; }
    .media.is-playing video { filter: none; transform: none; }
    .media .media-shadow, .media .speaker { display: none; }
    .media .bubble-play { display: flex; }
    .media.is-playing .bubble-play { opacity: 0; }
  }
  /* значок play поверх кружка: пока голова не включена — виден всегда */
  .bubble-play { display: none; position: absolute; inset: 0; align-items: center; justify-content: center; pointer-events: none;
    color: #ffffff; font-size: 2.2rem; text-shadow: 0 4px 14px rgba(0,0,0,0.6); transition: opacity 0.25s ease; }

  /* бейдж спикера над видео — как на главной (только десктоп) */
  .speaker { position: absolute; left: 50%; bottom: 8%; transform: translateX(-50%); z-index: 5;
    display: flex; align-items: center; gap: 0.6rem; background: rgba(0,0,0,0.45);
    -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px); border: 1px solid rgba(255,255,255,0.10);
    color: #ffffff; padding: 0.375rem 0.375rem 0.375rem 0.9rem; border-radius: 999px; box-shadow: 0 8px 24px rgba(0,0,0,0.35); white-space: nowrap; }
  .speaker h3 { margin: 0; font-size: 13px; font-weight: 700; line-height: 1; }
  .speaker-emoji { font-size: 11.5px; line-height: 1; position: relative; top: -0.03em; }
  .speaker .sep { color: rgba(255,255,255,0.3); font-size: 13px; line-height: 1; }
  .speaker .role { margin: 0; font-size: 13px; color: rgba(255,255,255,0.8); text-transform: uppercase; letter-spacing: 0.08em; line-height: 1; }
  .mic-btn { width: 2.25rem; height: 2.25rem; border-radius: 999px; background: #000000; border: 1px solid rgba(255,255,255,0.05); color: #ffffff;
    display: flex; align-items: center; justify-content: center; cursor: pointer; flex-shrink: 0; box-shadow: inset 0 2px 6px rgba(0,0,0,0.6); padding: 0; position: relative; }
  @media (hover:hover) { .mic-btn:hover { background: #111111; } }
  .mic-wave { position: absolute; inset: 0; display: none; }
  .mic-wave::before, .mic-wave::after { content: ''; position: absolute; inset: 0; border-radius: 50%; border: 1px solid #8854F3; animation: soundWave 2s infinite cubic-bezier(0.4, 0, 0.2, 1); }
  .mic-wave::after { animation-delay: 1s; }
  @keyframes soundWave { 0% { transform: scale(1); opacity: 0.8; } 100% { transform: scale(1.9); opacity: 0; } }

  /* ===== Колонка чтения: слой с экранами ===== */
  .read { position: fixed; inset: 0; z-index: 6; overflow: hidden; }
  @media (min-width:1024px) { .read { left: var(--read-left); } }
  .article { position: absolute; inset: 0; }

  /* ===== Экраны =====
     Правило владельца: не простыня, а аккуратные блоки — на каждом экране
     свой текст, и они СМЕНЯЮТ друг друга, как разделы на главной. */
  /* Блок выключен по центру ПО ГОРИЗОНТАЛИ, но прижат к постоянному верху:
     при вертикальном центрировании заголовок главы прыгал от слайда к слайду
     почти на 200px, а владелец просил «чтобы ничего не скакало». */
  /* Глава стоит ПО ЦЕНТРУ экрана (правка владельца). Именно safe center, а не
     center: при выключке center содержимое выше экрана обрезается сверху и
     до него не доскроллить, а safe в этом случае откатывается к началу. */
  .screen { position: absolute; inset: 0; display: none; flex-direction: column;
    justify-content: center; justify-content: safe center;
    align-items: center; touch-action: manipulation;
    padding: 5.5rem clamp(1.1rem, 4vw, 1.8rem) calc(var(--vid-d) * 0.82 / var(--z, 1) + 1rem + env(safe-area-inset-bottom, 0px));
    overflow: hidden; scrollbar-width: none;
    /* контейнер: кегль заголовка первого экрана считается от ширины колонки
       (cqi), чтобы обе его строки влезали при любом окне (FR-SITE82) */
    container-type: inline-size; }
  .screen::-webkit-scrollbar { width: 0; }
  @media (min-width:1024px) {
    /* сверху ровно столько, чтобы текст не лез под шапку: остальное — воздух
       вокруг блока, а не пустота (жалоба владельца: «много нарезал пусто») */
    .screen { padding: clamp(5.9rem, 11vh, 7.4rem) clamp(1.8rem, 3.6vw, 3.4rem) clamp(1.6rem, 4vh, 2.6rem); }
  }

  .screen.active { display: flex; }
  /* блоки не сжимаются: в колоночном флексе они иначе налезали друг на друга */
  .screen > *:not(.wm) { position: relative; z-index: 1; flex-shrink: 0;
    width: 100%; max-width: 54rem; margin-left: auto; margin-right: auto; }
  /* всё в колонке выключено ПО ЛЕВОМУ краю — и надзаголовок, и заголовок
     главы, и абзацы (правка владельца: «ты по середине сделал оглавление,
     надо везде слева»). Раньше заголовок стоял по центру, а надзаголовок и
     текст — слева, и блок выглядел как две разные вёрстки в одном экране. */
  .screen > .eyebrow, .screen > h1, .screen > h2 { text-align: left; }
  .screen > *:last-child { margin-bottom: 0; }
  /* уход и приход экрана — та же анимация, что на главной */
  .article.leaving .screen.active { opacity: 0; transform: translateY(-28px); transition: opacity 0.24s ease, transform 0.24s ease; }
  .article.entering .screen.active { animation: slideInScreen 0.5s cubic-bezier(0.22, 1, 0.36, 1); }
  @keyframes slideInScreen { from { opacity: 0; transform: translateY(44px); } to { opacity: 1; transform: none; } }

  /* точки-индикаторы: где мы внутри биографии */
  .dots { position: fixed; z-index: 20; display: flex; gap: 0.4rem; pointer-events: auto; }
  @media (min-width:1024px) { .dots { right: 1.6rem; top: 50%; transform: translateY(-50%); flex-direction: column; } }
  @media (max-width:1023px) { .dots { left: 50%; transform: translateX(-50%); bottom: calc(1rem + env(safe-area-inset-bottom, 0px)); } }
  .dot { width: 6px; height: 6px; border-radius: 999px; border: 0; padding: 0; cursor: pointer;
    background: rgba(255,255,255,0.22); transition: background 0.3s ease, transform 0.3s ease; }
  .dot.on { background: linear-gradient(120deg, #a071ff, #ff8a33); transform: scale(1.5); }
  @media (hover:hover) { .dot:hover { background: rgba(255,255,255,0.5); } }

  /* ===== Фоновые знаки глав (тигр, шапочка, монеты, ракета, процессор) =====
     Еле заметные, серые, по очереди слева и справа, с разным наклоном.
     На мобилке их нет: там только текст и кружок. */
  /* Правка владельца: знак главы у ВСЕХ глав стоит справа внизу, а не по
     очереди слева и справа посередине колонки. Классы .l/.r в разметке
     оставлены, но на положение больше не влияют. */
  /* Знак повёрнут на --rot, поэтому его квадрат вылезает углами за свою
     рамку. Отступ снизу взят с запасом на этот поворот. */
  .wm { position: absolute; right: 2.5rem; bottom: 2.6rem; left: auto; top: auto;
    z-index: 0; pointer-events: none; user-select: none; color: #ffffff; opacity: 0;
    font-size: min(30vh, 13vw); line-height: 1; transform: translate3d(0, 26px, 0);
    transition: opacity 1.3s ease, transform 1.3s cubic-bezier(0.22, 1, 0.36, 1); }
  .wm > svg, .wm > i { display: block; width: 1em; height: 1em; transform: rotate(var(--rot, 0deg)); }
  .screen.active .wm { opacity: 0.055; transform: none; }
  .wm.l, .wm.r { left: auto; right: 2.5rem; }
  /* Правка владельца: «на мобилках снизу внизу нет больших иконок, а на
     вебе есть» — знак главы теперь виден и на телефоне. Размер считается от
     МЕНЬШЕЙ стороны окна, чтобы в горизонте он не разрастался на пол-экрана,
     и он стоит справа внизу, подальше от кружка с роликом слева. */
  @media (max-width:1023px) {
    /* Правка владельца «на мобилах иконки большие должны быть справа внизу
       прям»: знак стоит в самом углу. Раньше его приходилось поднимать над
       нижней растушёвкой (она закрашивала его в ноль), теперь растушёвки
       нет — FR-SITE82. Кружок с роликом слева, точки по центру — знак с
       ними не сталкивается. */
    .wm { right: 1rem; bottom: calc(1.2rem + env(safe-area-inset-bottom, 0px)); font-size: calc(min(44vw, 30vh) / var(--z, 1)); }
    .screen.active .wm { opacity: 0.075; }
  }
  @media (min-width:1024px) and (max-width:1399px) { .wm { font-size: min(26vh, 13vw); } }

  /* кнопка «назад» — овал НАД надписью «About me» (правка владельца) */
  /* Иконка дома слева в пилюле меню — она заменила кнопку «назад»
     (правка владельца: «вместо кнопки BACK иконку домой рядом с меню») */
  .nav-home { display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
    width: 1.9rem; height: 1.9rem; margin-right: 0.15rem; border-radius: 999px; color: rgba(255,255,255,0.65);
    font-size: 14px; text-decoration: none; transition: color 0.3s ease, background 0.3s ease; }
  @media (hover:hover) { .nav-home:hover { color: #ffffff; background: rgba(136,84,243,0.16); } }

  /* в открытом меню на мобилке «домой» — такая же строка, как остальные пункты */
  .nav.open .nav-home { width: 100%; height: auto; margin: 0; justify-content: center; gap: 0.7rem;
    border-top: 1px solid rgba(255,255,255,0.14); border-radius: 0;
    padding: clamp(0.7rem, 2.2vh, 1.4rem) 0.25rem; color: #ffffff;
    font-size: clamp(16px, 2.3vh, 20px); font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; }
  .nav.open .nav-home::after { content: attr(data-label); }
  .nav.open .nav-home i { font-size: clamp(17px, 2.3vh, 21px); color: #8854F3; }

  .eyebrow { display: inline-flex; align-items: center; gap: 0.55rem; font-size: calc(10.5px * var(--k, 1)); font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.2em; color: #a071ff; margin: 0 0 0.7rem; }
  .eyebrow::after { content: ''; width: clamp(2rem, 8vw, 4rem); height: 1px; background: linear-gradient(90deg, #8854F3, rgba(249,115,22,0)); }
  /* Заголовок первого экрана переносится ТАМ, ГДЕ НАДО: строки размечены
     спанами .l, а не отданы на волю ширины колонки (правило владельца:
     «тайтлы могут в две, но с красивым переносом»). */
  /* подзаголовок ближе к заголовку (правка владельца) */
  /* Правка владельца: «„Я строю…“ в любом случае в две строчки и одинакового
     шрифта и на рус и на англ». Шрифт моноширинный, самая длинная строка —
     английская, 30 знаков по 0.59em (0.6em минус разрядка) = 17.7em; кегль
     = ширина колонки / 17.9 (запас 1%) — один и тот же в обеих версиях. */
  h1 { margin: 0 0 clamp(0.42rem, 1.2vh, 0.75rem); font-size: calc(min(2.7rem, 8vh, 5.58cqi) * var(--k, 1)); font-weight: 800; line-height: 1.18; letter-spacing: -0.01em; color: #ffffff;
    text-wrap: balance; }
  h1 .l { display: block; white-space: nowrap; }
  /* «AI-native» — одно слово: без этого перенос вставал по дефису и на
     768px заголовок читался как «AI- / native» */
  /* Правка владельца «„AI-Native экосистему“ перенос»: термин и его
     существительное уезжают на следующую строку ВМЕСТЕ — иначе «AI-Native»
     повисал в конце строки. Замер: 320–430px обе версии влезают без вылета. */
  .nb { white-space: nowrap; }
  /* Строки, которые владелец разбил сам («— Дальневосточный федеральный
     университет — след. строка», «There is only one of me… — 1 строка»):
     каждая .l начинается с новой строки. Узкая колонка телефона может
     перенести длинную .l ещё раз внутри неё — это нормально, нахлёста нет. */
  .screen p .l, .screen li .l { display: block; }
  /* Без цветного ореола: владелец — «убери это странное свечение везде».
     Цвет слова остаётся, halo вокруг букв снят. */
  .hl-p { color: #a071ff; }
  .hl-o { color: #ff8a33; }
  /* Заголовок главы: без градиентной полоски сверху (правка владельца) и с
     запасом по высоте, иначе иконка обрезалась. На вебе — в одну строку. */
  h2 { margin: 0 0 clamp(0.35rem, 1.05vh, 0.62rem); padding: 0.1rem 0; font-size: calc(clamp(1.05rem, min(2.1vw, 4.7vh), 1.7rem) * var(--k, 1)); font-weight: 800;
    text-transform: uppercase; letter-spacing: 0.03em; color: #ffffff; display: block;
    line-height: 1.35; text-wrap: balance; }
  /* иконка идёт СТРОКОЙ вместе с заголовком: у флекса при переносе текст
     вставал по центру, а иконка висела отдельно у левого края */
  /* Правка владельца «иконки херово болтаются — к тексту прижимаются и
     сверху»: зазор до текста был 0.6rem (9.6px при кегле 28px — треть
     буквы), теперь половина кегля; центр значка стоит на центре строки. */
  h2 i { font-size: 1em; line-height: 1; color: var(--ic, #8854F3); margin-right: 0.5em;
    vertical-align: -0.03em; }
  @media (min-width:1024px) { h2 { white-space: nowrap; } }
  /* Абзацы здесь короткие — два-четыре предложения, — поэтому строки делятся
     РОВНО (balance), а не просто без «сирот» (pretty): иначе в конце абзаца
     повисало одно слово («…the way I work / today:»). Замер на 768 и 1023px
     показывал такие огрызки в шести абзацах. */
  p { margin: 0 0 clamp(0.4rem, 1.15vh, 0.72rem); font-size: calc(clamp(13.5px, min(1.05vw, 2.4vh), 16.5px) * var(--k, 1)); line-height: 1.62; color: #b9c2d0;
    text-wrap: balance; }
  p strong { color: #ffffff; font-weight: 700; }
  .lead { font-size: calc(clamp(15px, min(1.2vw, 2.7vh), 18.5px) * var(--k, 1)); line-height: 1.6; color: #E5E7EB; font-weight: 500; }



  /* ===== Акценты: фиолетово-оранжевые рамки ===== */
  /* градиентная рамка сделана маской по ::before — border-image ломает радиус */
  .quote { position: relative; margin: clamp(0.5rem, 1.5vh, 0.9rem) 0 clamp(0.6rem, 1.8vh, 1.15rem); padding: clamp(0.7rem, 2vh, 1rem) 1.2rem clamp(0.7rem, 2vh, 1rem) 2.9rem; border-radius: 0.9rem;
    background: linear-gradient(135deg, rgba(136,84,243,0.14) 0%, rgba(249,115,22,0.10) 100%); }
  .quote::before { content: ''; position: absolute; inset: 0; border-radius: inherit; padding: 1px;
    background: linear-gradient(120deg, #8854F3 0%, #F97316 100%);
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite: xor;
    mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); mask-composite: exclude; pointer-events: none; }
  .quote::after { content: '\201C'; position: absolute; left: 0.85rem; top: 0.35rem; font-size: 2.6rem; line-height: 1; color: rgba(136,84,243,0.55); font-family: Georgia, serif; }
  .quote p { margin: 0; font-size: calc(clamp(14px, min(1.15vw, 2.6vh), 17.5px) * var(--k, 1)); line-height: 1.6; color: #ffffff; font-weight: 500; font-style: italic; }
  /* правка владельца: цитаты просто стоят на своих местах — нажать,
     выделить или приблизить их нельзя */
  .quote, .note, .stat { pointer-events: none; user-select: none; -webkit-user-select: none;
    -webkit-touch-callout: none; touch-action: manipulation; }

  /* врезка с одной мыслью: цветная полоса слева */
  .note { margin: clamp(0.5rem, 1.5vh, 0.9rem) 0 clamp(0.6rem, 1.8vh, 1.15rem); padding: clamp(0.55rem, 1.6vh, 0.8rem) 1rem; border-radius: 0.2rem 0.9rem 0.9rem 0.2rem;
    border-left: 3px solid var(--c, #8854F3); background: linear-gradient(90deg, rgba(136,84,243,0.12), rgba(136,84,243,0)); }
  .note.o { --c: #F97316; background: linear-gradient(90deg, rgba(249,115,22,0.12), rgba(249,115,22,0)); }
  .note p { margin: 0; color: #E5E7EB; font-weight: 500; }

  /* карточка-цифра */
  .stat { display: flex; align-items: center; gap: 1rem; margin: clamp(0.5rem, 1.5vh, 0.9rem) 0 clamp(0.6rem, 1.8vh, 1.15rem); padding: clamp(0.6rem, 1.8vh, 0.95rem) 1.1rem; border-radius: 0.9rem;
    border: 1px solid rgba(255,255,255,0.10); background: rgba(255,255,255,0.025); }
  .stat-num { font-size: calc(clamp(1.3rem, min(2.6vw, 5.8vh), 2rem) * var(--k, 1)); font-weight: 800; line-height: 1; letter-spacing: -0.02em; white-space: nowrap;
    background: linear-gradient(120deg, #a071ff 0%, #ff8a33 100%); -webkit-background-clip: text; background-clip: text; color: transparent; }
  .stat p { margin: 0; font-size: calc(clamp(13px, min(0.98vw, 2.2vh), 15px) * var(--k, 1)); line-height: 1.55; }
  /* карточка-цифра встаёт столбиком на ВСЕЙ мобильной вёрстке, а не с
     какой-то своей ширины: вёрстки две — веб и мобила */
  @media (max-width:1023px) { .stat { flex-direction: column; align-items: flex-start; gap: 0.7rem; } }

  /* две карточки: «корпорации» и «стартапы» */
  .cards { display: grid; gap: 0.7rem; margin: clamp(0.5rem, 1.5vh, 0.9rem) 0 clamp(0.6rem, 1.8vh, 1.15rem); grid-template-columns: 1fr; }
  /* две колонки — признак ВЕБ-вёрстки, а не просто ширины окна */
  @media (min-width:1024px) { .cards { grid-template-columns: 1fr 1fr; } }
  .card { padding: clamp(0.6rem, 1.8vh, 0.9rem) 1rem; border-radius: 0.9rem; border: 1px solid var(--bc, rgba(136,84,243,0.35));
    background: linear-gradient(160deg, rgba(136,84,243,0.10), rgba(255,255,255,0.01)); }
  .card.o { --bc: rgba(249,115,22,0.35); background: linear-gradient(160deg, rgba(249,115,22,0.10), rgba(255,255,255,0.01)); }
  .card h3 { margin: 0 0 0.6rem; font-size: calc(12px * var(--k, 1)); font-weight: 700; text-transform: uppercase; letter-spacing: 0.16em; color: var(--tc, #a071ff); display: flex; align-items: center; gap: 0.5rem; }
  .card.o h3 { --tc: #ff8a33; }
  .card p { margin: 0; font-size: calc(clamp(13px, min(0.98vw, 2.2vh), 15px) * var(--k, 1)); line-height: 1.55; }

  /* список фактов (образование, проекты) */
  .facts { list-style: none; margin: clamp(0.45rem, 1.4vh, 0.8rem) 0; padding: 0; display: flex; flex-direction: column; gap: clamp(0.3rem, 1vh, 0.55rem); }
  /* короткие пункты (области работы ИИ-сотрудников) стоят сеткой 2×2 */
  .facts.grid { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(0.3rem, 1vh, 0.55rem) 1.2rem; }
  /* Значок и текст пункта стоят на ОДНОЙ линии: раньше значок опускался на
     0.4rem вниз, и на телефоне (где кегль другой) он уезжал с первой строки
     (правка владельца «выровни текст под иконки»). Теперь значок — строка
     той же высоты, что и текст, и центрируется по ней при любом кегле. */
  .facts li { display: flex; align-items: flex-start; gap: 0.7rem; font-size: calc(clamp(13px, min(1vw, 2.3vh), 15.5px) * var(--k, 1)); line-height: 1.55; color: #b9c2d0; }
  /* Кегль значка равен кеглю строки, межстрочный — тот же: только так
     строка значка совпадает со строкой текста при ЛЮБОМ кегле, и значок
     стоит ровно на первой строке пункта (замер: смещение 0px вместо -11). */
  .facts i { color: #8854F3; font-size: 1em; line-height: inherit; flex-shrink: 0; width: 1.15rem; text-align: center; }
  .facts li strong { color: #ffffff; font-weight: 700; }

  /* финальный блок — фиолетово-оранжевая рамка + CTA */
  .finale { position: relative; margin: clamp(0.6rem, 1.8vh, 1rem) 0 0.6rem; padding: clamp(0.9rem, 2.6vh, 1.4rem) 1.3rem; border-radius: 1.1rem; text-align: center;
    background: radial-gradient(120% 130% at 50% 0%, rgba(136,84,243,0.20) 0%, rgba(249,115,22,0.10) 55%, rgba(5,5,5,0) 100%); }
  .finale::before { content: ''; position: absolute; inset: 0; border-radius: inherit; padding: 1px;
    background: linear-gradient(120deg, #8854F3 0%, #F97316 50%, #8854F3 100%);
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite: xor;
    mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); mask-composite: exclude; pointer-events: none; }
  /* Кегль прощания в ВЕБЕ остался прежним, и это замер, а не лень: строки
     здесь уже стояли на пределе колонки. На 1280 по-русски предел равен
     старому кеглю (14.72px при 14.72px), на 1366/1440 запас — четверть
     пиксела. Владелец просил крупнее, но с тем же форматом; на компе эти два
     требования несовместимы, поэтому крупнее стало там, где запас есть, —
     на телефоне и в горизонте. */
  .finale p { margin: 0 0 1rem; font-size: calc(clamp(14px, min(1.15vw, 2.6vh), 18px) * var(--k, 1)); line-height: 1.55; color: #ffffff; font-weight: 500; }
  .finale .btn-white { padding: 0.85rem 1.7rem; letter-spacing: 0.15em; font-size: calc(clamp(11px, 0.9vw, 14px) * var(--k, 1)); gap: 0.75rem; max-width: 100%; white-space: normal; text-align: center; }
  .home-link { display: block; width: fit-content; margin: 0.9rem auto 0; font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.16em; color: rgba(255,255,255,0.45); transition: color 0.3s ease; }
  @media (hover:hover) { .home-link:hover { color: #ffffff; } }

  /* подвал колонки чтения */
  /* Свободную высоту последнего экрана забирает НЕ подвал, а врезка финала:
     иначе текст главы прижимался к верху, а между кнопкой и подвалом зияла
     пустота (правка владельца «смести, чтобы кнопка была ниже»). */
  .finale p .l { display: block; }
  .foot { margin-top: clamp(0.9rem, 3vh, 2rem); padding-top: 1.1rem; border-top: 1px solid rgba(255,255,255,0.08);
    display: flex; flex-direction: column; align-items: center; gap: 0.6rem; }
  /* Правка владельца: «2026 © Andre AI Technologies LTD и иконки должны быть
     внизу». Финальный блок стоит по центру свободного места, подвал — у
     нижнего края: два auto-отступа у финала делят остаток поровну. */
  .screen.final { justify-content: flex-start; }
  /* Прощание теперь живёт на экране «Части одной экосистемы» (правка
     владельца): текст главы и прощание стоят одной группой по центру
     свободного места, подвал — у нижнего края. */
  .screen.final > h2 { margin-top: auto; }
  .screen.final .finale { margin-bottom: auto; }
  /* на мобилке глава длиннее экрана: при отрицательном свободном месте
     margin-top:auto ТЯНЕТ подвал ВВЕРХ и он налезает на финальный блок */
  @media (max-width:1023px) { .foot { margin-top: 1.2rem; } }

  /* ===== Почему здесь больше нет «ступеней плотности» =====
     Раньше на низких окнах кегль и отступы ужимались тремя медиазапросами —
     и глава всё равно уезжала в прокрутку. Правило владельца («внутри экрана
     не листать, только по блокам, и чтобы на мобиле и в вебе одинаково»)
     решается иначе: длинная глава разрезана на несколько коротких экранов
     (tools/build_about.py), а вертикальный ритм задан clamp'ами от высоты
     окна — сжимается воздух, а не буквы. */

  /* ===== Появление при листании =====
     Базовая подача — всплытие с уходящим размытием; --d задаёт JS, чтобы
     блоки, попавшие в экран одновременно, выходили каскадом, а не скопом.
     После появления вешается .done: задержка обнуляется и остаются только
     наведения (иначе hover «просыпался» через задержку каскада). */
  .reveal { opacity: 0; transform: translate3d(0, 20px, 0); filter: blur(5px);
    transition: opacity 0.62s cubic-bezier(0.22, 1, 0.36, 1) var(--d, 0ms),
                transform 0.62s cubic-bezier(0.22, 1, 0.36, 1) var(--d, 0ms),
                filter 0.62s ease var(--d, 0ms); }
  .reveal.in { opacity: 1; transform: none; filter: none; }
  .reveal.done { transition: transform 0.35s ease, box-shadow 0.35s ease, border-color 0.35s ease; transition-delay: 0s; }

  /* цитата выходит крупнее абзаца, кавычка «впрыгивает» следом */
  .quote.reveal { transform: translate3d(0, 26px, 0) scale(0.975); }
  .quote::after { transform: scale(0.6); opacity: 0;
    transition: transform 0.6s cubic-bezier(0.34, 1.56, 0.64, 1) calc(var(--d, 0ms) + 200ms),
                opacity 0.5s ease calc(var(--d, 0ms) + 200ms); }
  .quote.in::after { transform: none; opacity: 1; }

  /* врезка приезжает от своей цветной полосы */
  .note.reveal { transform: translate3d(-18px, 10px, 0); }

  /* карточка с цифрой тяжелее: масштаб + «набегающее» число (счёт ведёт JS) */
  .stat.reveal { transform: translate3d(0, 24px, 0) scale(0.98); }
  .stat-num { display: inline-block; transform-origin: left center; }
  .stat.in .stat-num { animation: numPop 0.7s cubic-bezier(0.34, 1.56, 0.64, 1) calc(var(--d, 0ms) + 120ms) both; }
  @keyframes numPop { 0% { transform: scale(0.84); } 62% { transform: scale(1.04); } 100% { transform: none; } }

  /* Сброс обязан стоять ПОСЛЕ частных правил .quote/.note/.stat: у них та же
     специфичность, и без этого блок навсегда оставался смещённым вниз и
     налезал на следующий абзац (жалоба владельца «чтобы ничего не налипало»). */
  .quote.reveal.in, .note.reveal.in, .stat.reveal.in, .finale.reveal.in { transform: none; }

  /* заголовок главы: линия раскрывается слева направо, иконка подпрыгивает */
  h2.reveal::before { transform: scaleX(0); transform-origin: left center;
    transition: transform 0.95s cubic-bezier(0.22, 1, 0.36, 1) calc(var(--d, 0ms) + 60ms); }
  h2.reveal.in::before { transform: none; }
  h2.reveal i { opacity: 0; transform: translateY(6px) scale(0.8);
    transition: opacity 0.5s ease calc(var(--d, 0ms) + 240ms),
                transform 0.6s cubic-bezier(0.34, 1.56, 0.64, 1) calc(var(--d, 0ms) + 240ms); }
  h2.reveal.in i { opacity: 1; transform: none; }

  /* списки — построчным каскадом, карточки — навстречу друг другу */
  .facts.reveal li { opacity: 0; transform: translate3d(-12px, 8px, 0);
    transition: opacity 0.55s ease, transform 0.55s cubic-bezier(0.22, 1, 0.36, 1); }
  .facts.reveal.in li { opacity: 1; transform: none; }
  .facts.reveal.in li:nth-child(1) { transition-delay: 0.06s; }
  .facts.reveal.in li:nth-child(2) { transition-delay: 0.17s; }
  .facts.reveal.in li:nth-child(3) { transition-delay: 0.28s; }
  .facts.reveal.in li:nth-child(4) { transition-delay: 0.39s; }
  .facts.reveal.in li:nth-child(5) { transition-delay: 0.50s; }
  .cards.reveal .card { opacity: 0; transition: opacity 0.7s ease, transform 0.7s cubic-bezier(0.22, 1, 0.36, 1); }
  .cards.reveal .card:first-child { transform: translate3d(-24px, 12px, 0); }
  .cards.reveal .card:last-child { transform: translate3d(24px, 12px, 0); transition-delay: 0.12s; }
  .cards.reveal.in .card { opacity: 1; transform: none; }

  /* финал: всплывает и один раз «вдыхает» фиолетовым */
  .finale.reveal { transform: translate3d(0, 26px, 0) scale(0.98); }
  .finale.in { animation: finaleGlow 2.8s ease-out calc(var(--d, 0ms) + 300ms) 1; }
  @keyframes finaleGlow {
    0% { box-shadow: 0 0 0 rgba(136,84,243,0); }
    40% { box-shadow: 0 20px 60px -14px rgba(136,84,243,0.45); }
    100% { box-shadow: 0 0 0 rgba(136,84,243,0); }
  }

  /* первый экран: шапка текста поднимается сразу при загрузке */
  .hero-rise { opacity: 0; transform: translate3d(0, 18px, 0); animation: heroRise 0.9s cubic-bezier(0.22, 1, 0.36, 1) both; }
  .eyebrow.hero-rise { animation-delay: 0.12s; }
  h1.hero-rise { animation-delay: 0.24s; }
  @keyframes heroRise { to { opacity: 1; transform: none; } }
  .media { animation: mediaIn 1.1s cubic-bezier(0.22, 1, 0.36, 1) both; }
  /* На десктопе НЕЛЬЗЯ масштабировать колонку ролика при появлении: она
     фиксированная и шире колонки текста, а scale(1.03) от центра выносил её
     правый край ещё правее вместе с растушёвкой — на долю секунды справа
     вспыхивала светлая полоса кадра (жалоба владельца «полоска сверкает,
     когда сайт открываю»). Появление — только прозрачностью. */
  @keyframes mediaIn { from { opacity: 0; } to { opacity: 1; } }
  @media (max-width:1023px) { @keyframes mediaIn { from { opacity: 0; transform: scale(0.8); } to { opacity: 1; transform: none; } } }

  /* наведение — только после появления (класс .done), иначе ждало бы каскад */
  @media (hover:hover) {
    .stat.done:hover { transform: translateY(-2px); border-color: rgba(136,84,243,0.35); box-shadow: 0 16px 34px -20px rgba(136,84,243,0.7); }
    .quote.done:hover { transform: translateY(-2px); }
    .cards.done .card { transition: transform 0.35s ease, box-shadow 0.35s ease, border-color 0.35s ease; transition-delay: 0s; }
    .cards.done .card:hover { transform: translateY(-3px); box-shadow: 0 16px 34px -20px rgba(136,84,243,0.6); }
    .note.done:hover { transform: translateX(3px); }
  }

  @media (prefers-reduced-motion: reduce) {
    .reveal, .wm, .hero-rise, .media, .reveal .card, .facts.reveal li { opacity: 1; transform: none; filter: none; transition: none; animation: none; }
    .wm { opacity: 0.055; }
    .quote::after { opacity: 1; transform: none; }
    h2.reveal i { opacity: 1; transform: none; }
    .mic-wave::before, .mic-wave::after { animation: none; }
  }

/* RU-надписи длиннее английских: в пилюле меню и в футере им нужен
   меньший кегль, иначе строка не помещается (как на главной) */
html[lang="ru"] .nav-legal { gap: 0.45rem; }
html[lang="ru"] .nav-legal-link { font-size: clamp(8px, 2.55vw, 10px); letter-spacing: 0.05em; }
html[lang="ru"] .nav-legal-sep { font-size: 10px; }
@media (min-width:1150px) {
  html[lang="ru"] .nav-tab { font-size: clamp(11.5px, 0.95vw, 13px); letter-spacing: 0; padding-left: 0.3rem; padding-right: 0.3rem; }
}

  /* Нижней растушёвки больше нет (FR-SITE82): внутри экрана ничего не
     прокручивается и под кружок не заезжает — нижнее поле экрана держит
     текст выше него, а плотный экран уменьшается целиком. Растушёвка
     гасила только знак главы, а он теперь стоит в самом углу справа внизу
     (правка владельца «на мобилах иконки большие справа внизу прям»). */

  /* =====================================================================
     МОБИЛЬНАЯ ВЁРСТКА
     Правило владельца: вёрстки ровно две — веб и мобилка, и выглядеть они
     должны ОДИНАКОВО, просто в своём масштабе. Раньше страница на телефоне
     просто ужималась до 11–12px. Здесь задан отдельный крупный масштаб —
     тот же, что на лендинге /ai-strategy/. Блок идёт последним и потому
     перебивает настольные значения при равной специфичности.
     ===================================================================== */
  @media (max-width:1023px) {
    /* Колонка чтения держится телефонной ширины: на 768–1023px строка
       растягивалась на 860px, и в конце абзаца повисал огрызок из одного
       слова. Вёрстки ровно две — веб и мобильная, а всё между ними просто
       центрируется. */
    .screen > *:not(.wm) { max-width: 32rem; }
    /* Две строки при любой ширине телефона (FR-SITE82): кегль = ширина
       колонки / 17.9, потолок 1.78rem — на 600–1023px колонка не шире 32rem */
    h1 { font-size: calc(min(1.78rem, 5.58cqi) * var(--k, 1)); line-height: 1.14; }
    h2 { font-size: calc(clamp(1.15rem, 5.2vw, 1.55rem) * var(--k, 1)); line-height: 1.22; }
    .eyebrow { font-size: calc(12px * var(--k, 1)); letter-spacing: 0.18em; }
    p { font-size: calc(14px * var(--k, 1)); line-height: 1.6; }
    .lead { font-size: calc(clamp(14.5px, 4.1vw, 16px) * var(--k, 1)); line-height: 1.55; }
    .facts li { font-size: calc(13.5px * var(--k, 1)); line-height: 1.5; }
    /* Один левый край (правка владельца «выровни текст под иконки»): значки
       глав и пунктов висят слева, а заголовок, абзацы и пункты начинаются от
       одной линии. Ширина колонки значков = кегль значка + отступ. */
    .screen > p, .screen > .lead { padding-left: 1.85rem; }
    /* На первом экране значков нет, и отступ под их колонку сдвигал «Обо мне»
       и текст на 30px правее заголовка (жалоба владельца «выровни по тексту и
       где „Обо мне“»). Здесь всё стоит от одного края — края колонки. */
    .screen.hero > p, .screen.hero > .lead { padding-left: 0; }
    .facts i { width: 1.15rem; }
    /* Заголовок главы встаёт на ТУ ЖЕ левую линию. Значок главы инлайновый,
       и ширина его глифа гуляет: Font Awesome квантует её по 0.125em, что при
       кегле 20.3px даёт шаг ровно 2.53px — текст заголовка плясал в пределах
       43…53px, тогда как абзацы и пункты стоят намертво на 47.2px. Выносим
       значок в такую же фиксированную колонку, как у пунктов списка. */
    /* Правка владельца «иконки болтаются — к тексту прижимаются и сверху»:
       значок стоял у верха строки (на 3.5px выше центра текста), а широкий
       глиф (1.25em = 25px) вылезал из колонки 18px — до текста оставалось
       7px. Теперь значок 0.82 кегля: самый широкий глиф 21px, до текста
       не меньше 10px, ось — та же, что у значков пунктов списка. По
       вертикали — центр первой строки: поле 0.1rem + (1.22 − 0.82)/2 кегля. */
    h2 { padding-left: 1.85rem; position: relative; }
    h2 i { position: absolute; left: 0; top: calc(0.1rem + 0.2439em); width: 1.15rem;
      font-size: 0.82em; margin-right: 0; text-align: center; }
    .quote p { font-size: calc(14px * var(--k, 1)); }
    .stat p, .card p { font-size: calc(13px * var(--k, 1)); line-height: 1.5; }
    .stat-num { font-size: calc(clamp(1.5rem, 7vw, 2rem) * var(--k, 1)); }
    .card h3 { font-size: calc(12px * var(--k, 1)); }
    /* Крупнее ровно настолько, насколько позволяет колонка: предел без новой
       строки — 20px по-английски и 16.25px по-русски на 390px (замер). */
    .finale p { font-size: calc(17px * var(--k, 1)); }
    html[lang="ru"] .finale p { font-size: calc(16px * var(--k, 1)); }
    .finale .btn-white { font-size: calc(12.5px * var(--k, 1)); padding: 0.85rem 1.4rem; }
    /* Подвал финала — к САМОМУ низу, прямо над точками (правка владельца:
       «оно же блять должно быть внизу, прям перед точками»). Кружку
       разрешено его перекрывать — владелец решил это прямо: «кружок можно
       перемещать, поэтому пофигу что он там закрывает». Пробовали поднимать
       подвал над кружком (запас var(--vid-d) + 1.5rem) — отменено. */
    .screen.final { padding-bottom: calc(2.4rem + env(safe-area-inset-bottom, 0px)); }
  }
  /* На самом узком телефоне надпись кнопки финала ломалась пополам по дефису
     («НАЧАТЬ ИИ- / ТРАНСФОРМАЦИЮ»): виноват был разрядка 0.15em, она добавляла
     к строке 40px. Ужимаем разрядку и поля — надпись встаёт в строку. */
  @media (max-width:380px) {
    .finale .btn-white { font-size: calc(12px * var(--k, 1)); letter-spacing: 0.08em; padding: 0.8rem 1rem; gap: 0.55rem; }
    /* на 320–375px прощание уже впритык: предел 15.5px по-английски и
       14.5px по-русски — ровно столько и ставим */
    .finale p { font-size: calc(15px * var(--k, 1)); }
    html[lang="ru"] .finale p { font-size: calc(14.5px * var(--k, 1)); }
  }

  /* ===== Мобильная вёрстка в БОЛЬШОМ окне (FR-SITE84) =====================
     Правка владельца: «почему вот так получается на веб-экранах, когда не на
     полный экран — просто динамически надо подтягивать отформатированный
     текст». Окно браузера уже 1024px (или планшет) получало мобильную
     вёрстку ТЕЛЕФОННОГО размера: текст 14px в колонке посреди пустого
     экрана. Вёрстка остаётся той же, но целиком крупнее: скрипт ставит
     --z = min(ширина/600, высота/880) в пределах 1…1.8, и шапка, экраны и
     точки масштабируются zoom. Кружок с роликом не масштабируется — его
     тащат пальцем, и координаты должны совпадать с экранными, — поэтому
     всё, что внутри увеличенных слоёв считается от его диаметра и от окна
     (vw/vh), делится на --z. Телефоны (уже 600px) и горизонт не трогаем. */
  @media (min-width:600px) and (max-width:1023px) and (min-height:521px) {
    header, .read, .dots, .top-fade { zoom: var(--z, 1); }
  }

  /* ===== Телефон в ГОРИЗОНТЕ ============================================
     Та же мобильная вёрстка в других пропорциях: места здесь много по
     ШИРИНЕ и мало по высоте, поэтому кружок с роликом уходит влево, текст
     встаёт правее него, а кегль считается от высоты окна. Правка владельца:
     «при переворачивании в горизонталь тоже [чтобы всё было чётко]».
     Порог: телефон в горизонте — это 360–430px высоты, портрет даже у самых
     коротких телефонов от 568px. */
  @media (max-width:1023px) and (min-width:600px) and (max-height:520px) {
    /* Кружок того же размера, что в портрете. Переопределяем на html И body:
       базовое значение объявлено у `html, body`, и при правке только `:root`
       body оставался со старым размером — кружок наследовал его и выходил
       88px вместо 133px (жалоба владельца «схуяли такой маленький»). */
    :root, body { --vid-d: clamp(104px, 34vh, 150px); }
    header { padding: 0.5rem 0.9rem; }
    .logo-img { width: 2.2rem; height: 2.2rem; }
    .menu-btn { width: 2.3rem; height: 2.3rem; }
    .cta { padding: 0.5rem 0.85rem; font-size: 9.5px; letter-spacing: 0.06em; }
    /* всё по центру, справа — вертикальная колонка точек (правка владельца) */
    /* поля СИММЕТРИЧНЫЕ и равны кружку: содержимое стоит ровно по центру
       экрана и при этом не заезжает на кружок слева и на точки справа */
    /* поля сверху и снизу одинаковые — глава ровно по центру окна */
    /* 3.3rem сверху ровно перекрывают ужатую шапку горизонта (замер ~51px),
       а симметрия держит главу по центру окна */
    .screen { padding: 3.3rem calc(var(--vid-d) + 1.6rem); }
    .dots { left: auto; right: 0.7rem; top: 50%; bottom: auto;
      transform: translateY(-50%); flex-direction: column; }
    .screen > *:not(.wm) { max-width: none; }
    h1 { font-size: calc(min(2.3rem, 8vh, 5.58cqi) * var(--k, 1)); line-height: 1.14; }
    h2 { font-size: calc(clamp(1.1rem, 5.8vh, 1.75rem) * var(--k, 1)); margin-bottom: 0.3rem; }
    .eyebrow { font-size: calc(clamp(10.5px, 3vh, 13px) * var(--k, 1)); }
    p { font-size: calc(clamp(11.5px, 3.2vh, 14.5px) * var(--k, 1)); line-height: 1.45; margin-bottom: 0.38rem; }
    .lead { font-size: calc(clamp(12.5px, 3.6vh, 16px) * var(--k, 1)); line-height: 1.42; }
    .quote p { font-size: calc(clamp(12px, 3.3vh, 15px) * var(--k, 1)); }
    .facts li { font-size: calc(clamp(11px, 3vh, 13.5px) * var(--k, 1)); }
    .stat p, .card p { font-size: calc(clamp(11.5px, 3.2vh, 13.5px) * var(--k, 1)); line-height: 1.4; }
    .stat-num { font-size: calc(clamp(1.3rem, 6.4vh, 2rem) * var(--k, 1)); }
    .card h3 { font-size: calc(clamp(10px, 2.7vh, 11.5px) * var(--k, 1)); }
    /* в горизонте запас есть, но на 740x360 по-русски предел 13.85px —
       отсюда 3.8vh вместо 4vh. Русский селектор повторён намеренно: у
       портретного правила html[lang="ru"] .finale p вес выше, и без этого
       оно перебивало горизонт (замер: 16px вместо 13.7px на 740x360). */
    .finale p, html[lang="ru"] .finale p { font-size: calc(clamp(13px, 3.8vh, 17px) * var(--k, 1)); }
    .finale .btn-white { font-size: calc(clamp(10px, 2.7vh, 12px) * var(--k, 1)); padding: 0.6rem 1.1rem; }
    /* блоки главы разворачиваются в ширину — там, где есть место */
    .cards { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.45rem; margin: 0.4rem auto 0.45rem; }
    .card { padding: 0.42rem 0.6rem; }
    .card h3 { margin-bottom: 0.12rem; }
    .card p { line-height: 1.28; }
    h2 { margin-bottom: 0.35rem; }
    .eyebrow { margin-bottom: 0.3rem; }
    /* Колонок столько, чтобы последний ряд НЕ БЫЛ из одного пункта (правка
       владельца: «чтобы не торчал отдельно четвёртый пункт — значит, надо два
       сверху и два снизу»). Количество пунктов в главе известно только
       разметке, поэтому считаем его селектором :has(). */
    /* Весь текст в горизонте выключен ПО ЦЕНТРУ (правка владельца: «на
       горизонталке весь текст по середине по центру должен быть выровнен»);
       колонка значков из вертикали здесь не нужна. */
    .screen > .eyebrow, .screen > h1, .screen > h2, .screen > p, .screen > .lead,
    .note p, .quote p, .stat p, .card h3, .card p {
      text-align: center; padding-left: 0; }
    /* колонка значка из вертикали здесь не нужна: заголовок стоит по центру,
       и значок возвращается В СТРОКУ рядом с текстом */
    h2 { position: static; }
    h2 i { position: static; width: auto; margin-right: 0.5em; font-size: 1em; }
    /* Надзаголовок — не просто текст, а inline-flex (подпись плюс черта
       градиентом), и text-align на него не действует: содержимое флекса
       пакуется к flex-start. Замер на 844×390: «Обо мне» стояло в [158…231]
       при колонке до 686 — на 227px левее центра.
       Та же ловушка у заголовка карточки: .card h3 тоже display:flex, и
       добавленный выше text-align:center его НЕ исправил — замер показал
       чернила заголовка вплотную к левому краю карточки (зазор ровно 0.0px)
       и смещение до −90.6px от центра на 915×412. */
    .screen > .eyebrow, .card h3 { justify-content: center; }
    /* ИСКЛЮЧЕНИЕ, не забыть при следующей правке: пункты списка (.facts li)
       остаются выключенными ВЛЕВО внутри своих ячеек. Владелец просил
       «выровни текст под иконки» (FR-SITE51) — значки соседних строк должны
       стоять на одной вертикали. Центрируется сам БЛОК списка, а не пункты
       в нём. То же у карточек кейсов лендинга: внутри карточки текст слева,
       по центру стоит сетка карточек. */
    /* Строки больше не слипаются: было 0.04rem между рядами — пункты стояли
       вплотную и вторая строка пункта упиралась в следующий (жалоба владельца
       «всё налипает друг на друга»). */
    /* Колонки узкие, а неразрывный дефис (FR-SITE52) делает «бизнес‑информатике»
       одним нерушимым словом шириной 119–127px — оно вылезало из своей ячейки
       на 9px при 844×390 и на 28px при 740×360, то есть заезжало в соседнюю
       колонку. Зазор между колонками и колонка значка ужаты, чтобы слово
       помещалось целиком. */
    .facts { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
      gap: 0.42rem 0.55rem; margin: 0.35rem auto; justify-content: center; }
    /* Страховка на будущее: если слово всё равно длиннее колонки, пусть лучше
       переломится, чем заедет на соседа.
       Именно break-word, а НЕ anywhere: anywhere ломает слово прямо на текущей
       строке, не пробуя сначала перенести его целиком на следующую, и
       «бизнес‑информатике» рвалось на «бизнес‑информат / ике» даже там, где
       на отдельной строке помещалось целиком. break-word ломает только слово,
       которое не влезает в строку ЦЕЛИКОМ. */
    .facts li { overflow-wrap: break-word; }
    .facts:has(li:nth-child(4):last-child) { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .facts:has(li:nth-child(7):last-child) { grid-template-columns: repeat(4, minmax(0, 1fr)); }
    .facts:has(li:nth-child(10):last-child) { grid-template-columns: repeat(5, minmax(0, 1fr)); }
    /* Десять ролей в пять колонок: на 740px в колонку остаётся 83px, из
       которых значок и зазор съедают 26 — «Разработка»/«Engineering» не
       влезали и наезжали на значок соседа (замер: нахлёст 6px). Для этого
       одного списка значок и кегль ужимаются, зазор между колонками меньше. */
    .facts:has(li:nth-child(10):last-child) { gap: 0.3rem 0.5rem; }
    .facts:has(li:nth-child(10):last-child) li { font-size: calc(clamp(9px, 2.4vh, 11.5px) * var(--k, 1)); gap: 0.28rem; }
    .facts:has(li:nth-child(10):last-child) i { width: 0.9rem; }
    .facts li { line-height: 1.38; gap: 0.3rem; }
    .facts i { width: 1rem; }
    .stat { margin: 0.35rem 0 0.4rem; }
    .stat { flex-direction: row; align-items: center; gap: 0.7rem; padding: 0.3rem 0.7rem; margin: 0.24rem 0 0.28rem; }
    .quote { padding: 0.42rem 0.9rem 0.42rem 2.2rem; margin: 0.28rem 0 0.32rem; }
    .finale { padding: 0.7rem 1.1rem; }
    /* Запас снизу задан ЯВНО и равен верхнему: у портретного `.screen.final`
       вес 0,2,0 против 0,1,0 у ландшафтного `.screen`, поэтому без этой
       строки снизу оставалось 2.4rem против 3.3rem сверху и глава стояла на
       14px ниже середины окна — а поля должны быть одинаковыми (FR-SITE50). */
    .screen.final { padding-bottom: 3.3rem; }
    /* Верхняя растушёвка ужата под ужатую шапку горизонта (замер ~51px):
       6.5rem = 104px, из которых 48px глухой черноты, а поле экрана сверху
       всего 3.3rem = 52.8px — заголовок главы центрировался прямо под
       растушёвкой и гас. */
    .top-fade { height: 3.4rem; }
    /* Знак главы — у нижнего края (растушёвки больше нет, FR-SITE82). */
    .wm { bottom: 1.2rem; }
    /* Подвал последнего экрана — одной строкой в нижнем поле: в горизонте
       высоты мало, а поле 3.3rem всё равно пустует. Под кружок (он слева) и
       под точки (справа) строка не заходит. */
    .screen.final .foot { position: absolute; left: 0; right: 0; bottom: 0.55rem;
      width: auto; max-width: none; margin: 0; padding: 0; border-top: 0;
      flex-direction: row; justify-content: center; gap: 1.1rem; }
  }

