@import url("fonts.css");

/* ==========================================================================
   Kinetic Sculptures
   Мир: латунный астрономический прибор. Ночная синь взята с неба на самих
   фотографиях, латунь — с полированной меди. Страница устроена как альманах:
   гравированные линии, шкалы с делениями, таблицы показаний. Одна сигнатура —
   лимб (круговая шкала) в первом экране, который проворачивается от скролла.
   ========================================================================== */

:root {
  /* Ночь: три ступени глубины, все с синим подтоном — серого на странице нет */
  --night: #060f1e;
  --night-2: #0a1729;
  --night-3: #102340;
  --night-line: #1b3355;

  /* Латунь: гравировка, подсветка, тень */
  --brass: #c98b4b;
  --brass-lit: #edc08a;
  --brass-deep: #7d5730;

  /* Текст тонирован от неба, а не разбавлен серым */
  --text: #dae2ee;
  --text-dim: #93a7c2;
  --text-faint: #6b809c;

  --measure: 64ch;
  --edge: clamp(1.25rem, 4vw, 4rem);
  --rule: 1px solid var(--night-line);

  /* Кривые: встроенные CSS-easing слишком вялые для интерфейса */
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
  /* Якорь не должен приводить раздел под фиксированную шапку */
  scroll-padding-block-start: 5rem;
  /* Только на body мобильные браузеры это правило игнорируют: страницу всё
     равно можно утянуть вбок. Нужны оба элемента. */
  overflow-x: hidden;
}

body {
  margin: 0;
  background: var(--night);
  color: var(--text);
  font-family: Spectral, Georgia, serif;
  font-size: clamp(1.0625rem, 0.98rem + 0.42vw, 1.1875rem);
  line-height: 1.65;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}

/* Тонкая латунная сетка поверх фона: страница читается как лист прибора,
   а не как пустая тёмная плоскость. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background-image: linear-gradient(var(--night-line) 1px, transparent 1px);
  background-size: 100% 9.5rem;
  opacity: 0.16;
  mask-image: linear-gradient(to bottom, transparent, #000 20%, #000 80%, transparent);
}

/* --- Поле роторов --------------------------------------------------------- */

/* Фон страницы — не плоскость, а глубина, в которой что-то вращается. Роторы
   идут на пороге видимости: движение замечаешь раньше, чем сами фигуры.
   Прокрутка их подкручивает — прибор отзывается на то, что делает читатель. */
.field {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
  color: var(--brass);
}

.field__rotor {
  position: absolute;
  aspect-ratio: 1;
  /* linear: у ветра нет фаз разгона, вращение равномерное */
  animation: rotor-spin var(--spin, 120s) linear infinite;
}

.field__rotor svg {
  width: 100%;
  height: 100%;
}

/* Прокрутка добавляет оборот поверх постоянного вращения. Работает как у лимба:
   time-based анимация крутит transform, scroll-based — rotate, они складываются,
   поэтому во время листания фигуры идут заметно быстрее. */
@supports (animation-timeline: scroll()) {
  .field__rotor {
    animation: rotor-spin var(--spin, 120s) linear infinite,
      rotor-scroll 1s linear both;
    /* Источник указан явно. Голый scroll() берёт ближайшего предка с
       overflow — то есть саму .field, которая не прокручивается никогда,
       и доворот молча остаётся нулевым. */
    animation-timeline: auto, scroll(root block);
  }
}

@keyframes rotor-spin {
  to {
    transform: rotate(360deg);
  }
}

@keyframes rotor-scroll {
  to {
    rotate: var(--sweep, 420deg);
  }
}

.field__rotor--1 {
  width: 46vw;
  inset-block-start: -12vw;
  inset-inline-start: -13vw;
  opacity: 0.042;
  --spin: 150s;
  --sweep: 400deg;
}

.field__rotor--2 {
  width: 30vw;
  inset-block-start: 46vh;
  inset-inline-end: -9vw;
  opacity: 0.038;
  --spin: 95s;
  --sweep: -520deg;
}

.field__rotor--3 {
  width: 54vw;
  inset-block-end: -22vw;
  inset-inline-start: 12vw;
  opacity: 0.03;
  --spin: 190s;
  --sweep: 330deg;
}

.field__rotor--4 {
  width: 22vw;
  inset-block-start: 8vh;
  inset-inline-end: 16vw;
  opacity: 0.036;
  --spin: 70s;
  --sweep: -640deg;
}

/* На телефоне остаются два: остальные на такой ширине наползают друг на друга
   и превращаются в шум под текстом. */
@media (max-width: 47.99rem) {
  .field__rotor--1 {
    width: 82vw;
    inset-block-start: -18vw;
    inset-inline-start: -26vw;
  }

  .field__rotor--2 {
    width: 62vw;
    inset-inline-end: -22vw;
  }

  .field__rotor--3,
  .field__rotor--4 {
    display: none;
  }
}

img {
  max-width: 100%;
  display: block;
}

a {
  color: inherit;
}

::selection {
  background: var(--brass);
  color: var(--night);
}

:focus-visible {
  outline: 2px solid var(--brass-lit);
  outline-offset: 3px;
}

/* --- Типографика ---------------------------------------------------------- */

h1,
h2,
h3 {
  font-family: Podkova, Georgia, serif;
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -0.01em;
  text-wrap: balance;
  margin: 0;
}

h2 {
  font-size: clamp(2rem, 1.35rem + 3.1vw, 3.75rem);
}

h3 {
  font-size: clamp(1.375rem, 1.2rem + 0.85vw, 1.875rem);
  line-height: 1.15;
}

p {
  margin: 0;
}

/* Технические подписи — шкала прибора: показания, единицы, номера.
   Моноширинный убран целиком: это тот самый костюм «технологичности», в
   который одевается любая нейросетевая генерация. Гравировка на латуни
   набрана тем же старостильным текстовым шрифтом, что и остальная страница. */
.data {
  font-family: Spectral, Georgia, serif;
  font-size: 0.6875rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--brass);
  font-weight: 600;
}

.lead {
  max-width: var(--measure);
  color: var(--text-dim);
  font-size: clamp(1.0625rem, 1rem + 0.5vw, 1.3125rem);
  line-height: 1.6;
}

/* Незаполненные заказчиком факты. Видно, что это заглушка, но не орёт. */
.todo {
  color: var(--text-faint);
  border-bottom: 1px dashed var(--brass-deep);
}

/* --- Каркас --------------------------------------------------------------- */

.shell {
  position: relative;
  z-index: 1;
  max-width: 84rem;
  margin-inline: auto;
  padding-inline: var(--edge);
}

section {
  position: relative;
  z-index: 1;
  padding-block: clamp(4rem, 2.6rem + 5.6vw, 7rem);
}

/* Заголовок секции: над ним воздуха больше, чем под ним */
.head {
  display: grid;
  gap: 1.25rem;
  margin-bottom: clamp(2.25rem, 1.6rem + 2.6vw, 3.5rem);
}

/* --- Шапка ---------------------------------------------------------------- */

.top {
  position: fixed;
  inset-block-start: 0;
  inset-inline: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.85rem var(--edge);
  background: color-mix(in srgb, var(--night) 82%, transparent);
  backdrop-filter: blur(14px);
  border-bottom: var(--rule);
}

.top__mark {
  font-family: Podkova, serif;
  font-weight: 600;
  font-size: clamp(0.9375rem, 0.87rem + 0.35vw, 1rem);
  letter-spacing: 0.02em;
  text-decoration: none;
  white-space: nowrap;
  /* Имя сжимается первым, если строка всё же окажется тесной */
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

.top__side {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex: none;
}

.top__nav {
  display: none;
  gap: clamp(1rem, 2.4vw, 2.25rem);
}

@media (min-width: 62rem) {
  .top__nav {
    display: flex;
  }
}

.top__nav a {
  text-decoration: none;
  color: var(--text-dim);
  transition: color 160ms ease;
}

@media (hover: hover) and (pointer: fine) {
  .top__nav a:hover {
    color: var(--brass-lit);
  }
}

.langs {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex: none;
}

.langs a {
  text-decoration: none;
  color: var(--text-faint);
  transition: color 160ms ease;
  white-space: nowrap;
}

.langs a[aria-current="true"] {
  color: var(--brass-lit);
}

@media (hover: hover) and (pointer: fine) {
  .langs a:hover {
    color: var(--text);
  }
}

/* До 48rem в шапке стоят коды RU/EN/AR: полные названия языков там просто
   не помещаются рядом с именем и выталкивают строку за край экрана. */
.langs__short {
  display: none;
}

@media (max-width: 47.99rem) {
  .langs {
    gap: 0.55rem;
  }

  .langs__full {
    display: none;
  }

  .langs__short {
    display: inline;
  }
}

/* --- Разделы на телефоне --------------------------------------------------- */

.top__menu {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  margin-inline-end: -0.5rem;
  padding: 0;
  border: none;
  background: transparent;
  color: var(--text-dim);
  cursor: pointer;
  transition: color 160ms ease;
}

.top__menu svg {
  width: 1.375rem;
  height: 1.375rem;
}

@media (min-width: 62rem) {
  .top__menu {
    display: none;
  }
}

.sheet {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: grid;
  background: color-mix(in srgb, var(--night) 92%, transparent);
  backdrop-filter: blur(18px);
  visibility: hidden;
  opacity: 0;
  transition: opacity 240ms var(--ease-out), visibility 0s linear 240ms;
}

.sheet[data-open="true"] {
  visibility: visible;
  opacity: 1;
  transition: opacity 240ms var(--ease-out), visibility 0s;
}

.sheet__panel {
  display: grid;
  align-content: start;
  gap: 0;
  padding: 1rem var(--edge) 2rem;
}

.sheet__close {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  justify-self: end;
  padding: 0.5rem 0;
  border: none;
  background: transparent;
  color: var(--text-faint);
  cursor: pointer;
}

.sheet__close svg {
  width: 1.125rem;
  height: 1.125rem;
}

.sheet__nav {
  display: grid;
  margin-block-start: 1.5rem;
  border-block-start: var(--rule);
}

.sheet__nav a {
  padding-block: 1.15rem;
  border-block-end: var(--rule);
  text-decoration: none;
  font-family: Podkova, serif;
  font-weight: 600;
  font-size: 1.5rem;
  color: var(--text);
  /* Разделы въезжают лесенкой — тот же порядок, что и в шкале этапов */
  opacity: 0;
  translate: 0 0.75rem;
}

.sheet[data-open="true"] .sheet__nav a {
  animation: sheet-item 380ms var(--ease-out) both;
}

.sheet[data-open="true"] .sheet__nav a:nth-child(2) {
  animation-delay: 45ms;
}
.sheet[data-open="true"] .sheet__nav a:nth-child(3) {
  animation-delay: 90ms;
}
.sheet[data-open="true"] .sheet__nav a:nth-child(4) {
  animation-delay: 135ms;
}
.sheet[data-open="true"] .sheet__nav a:nth-child(5) {
  animation-delay: 180ms;
}

@keyframes sheet-item {
  to {
    opacity: 1;
    translate: 0 0;
  }
}

/* --- Кнопка --------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.9rem 1.6rem;
  border: 1px solid var(--brass);
  background: transparent;
  color: var(--brass-lit);
  font-family: Spectral, Georgia, serif;
  font-weight: 600;
  font-size: 0.8125rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  transition: transform 160ms var(--ease-out), background-color 200ms ease,
    color 200ms ease, border-color 200ms ease;
}

.btn svg {
  width: 1.05em;
  height: 1.05em;
  flex: none;
}

@media (hover: hover) and (pointer: fine) {
  .btn:hover {
    background: var(--brass);
    color: var(--night);
  }
}

.btn:active {
  transform: scale(0.97);
}

.btn--solid {
  background: var(--brass);
  color: var(--night);
  border-color: var(--brass);
}

@media (hover: hover) and (pointer: fine) {
  .btn--solid:hover {
    background: var(--brass-lit);
    border-color: var(--brass-lit);
  }
}

/* --- Первый экран --------------------------------------------------------- */

.hero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  min-height: 100svh;
  display: grid;
  align-items: center;
  /* Верхний отступ отсчитывается от фиксированной шапки, а не задан на глаз:
     на телефоне лишние сантиметры пустоты съедают первый экран. */
  padding-block: clamp(5.5rem, 4.5rem + 3vw, 7rem) clamp(2rem, 1.4rem + 2vw, 3rem);
}

.hero__video {
  position: absolute;
  inset: 0;
  overflow: hidden;
  z-index: 0;
}

/* Два слоя, а не один: горизонтальный гасит фон под колонкой с текстом и
   отпускает правую часть кадра, где стоит лимб, вертикальный сажает низ на
   цвет страницы, чтобы первый экран не обрывался швом. Ровная заливка сверху
   мутила видео целиком и оставляла заголовок на пёстрой каше. */
.hero__video::after {
  content: '';
  position: absolute;
  inset: 0;
  background:
    linear-gradient(
      to right,
      rgb(6 15 30 / 0.88) 0%,
      rgb(6 15 30 / 0.66) 38%,
      rgb(6 15 30 / 0.42) 100%
    ),
    linear-gradient(
      to bottom,
      rgb(6 15 30 / 0.55) 0%,
      rgb(6 15 30 / 0.42) 45%,
      rgb(6 15 30 / 0.88) 100%
    );
  pointer-events: none;
}

/* В арабской версии колонка с текстом уезжает вправо, а градиент задан
   физическим направлением и остаётся гасить левый край — то есть пустой.
   Логических ключевых слов у linear-gradient нет, поэтому направление
   переопределяется явно. Та же природа, что у стрелки из урока 4. */
[dir="rtl"] .hero__video::after {
  background:
    linear-gradient(
      to left,
      rgb(6 15 30 / 0.88) 0%,
      rgb(6 15 30 / 0.66) 38%,
      rgb(6 15 30 / 0.42) 100%
    ),
    linear-gradient(
      to bottom,
      rgb(6 15 30 / 0.55) 0%,
      rgb(6 15 30 / 0.42) 45%,
      rgb(6 15 30 / 0.88) 100%
    );
}

.hero__video video {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 100vw;
  height: 100vh;
  min-width: 177.77vh;
  min-height: 56.25vw;
  transform: translate(-50%, -50%);
  object-fit: cover;
  pointer-events: none;
}

/* Растягивать первый экран до полной высоты имеет смысл там, где текст и
   фотография стоят рядом. На телефоне они идут друг за другом, и жёсткая
   высота лишь отодвигает скульптуру за нижний край. */
@media (max-width: 61.99rem) {
  .hero {
    min-height: 0;
  }
}

.hero__grid {
  position: relative;
  z-index: 1;
  display: grid;
  gap: clamp(2.5rem, 1rem + 7vw, 5rem);
  align-items: center;
}

@media (min-width: 62rem) {
  .hero__grid {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  }
}

.hero h1 {
  font-size: clamp(3.25rem, 1.6rem + 7.4vw, 7rem);
  line-height: 0.92;
  letter-spacing: -0.03em;
  margin-bottom: 1.75rem;
}

.hero h1 span {
  display: block;
}

.hero h1 span + span {
  color: var(--brass);
}

.hero .lead {
  margin-bottom: 2.5rem;
}

.hero__lead--mobile {
  display: none;
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1.25rem 2rem;
  margin-bottom: clamp(2rem, 1.4rem + 2vw, 3rem);
}

/* На телефоне обращение в WhatsApp занимает всю ширину: это главное действие
   страницы и единственная цель встречи, ради которой её открывают. */
@media (max-width: 34rem) {
  .hero__actions {
    display: grid;
    justify-items: start;
    gap: 1.1rem;
  }

  .hero__actions .btn {
    width: 100%;
    justify-content: center;
  }
}

/* Не «вторая кнопка», а подпись со стрелкой: она уводит вниз по странице,
   а не спорит с обращением в WhatsApp. */
.hero__scroll {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  padding-block: 0.35rem;
  text-decoration: none;
  color: var(--text-faint);
  border-block-end: 1px solid var(--brass-deep);
  transition: color 160ms ease, border-color 160ms ease;
}

.hero__scroll::after {
  content: "";
  width: 0.5rem;
  height: 0.5rem;
  /* Физические стороны, а не логические: вниз — это вниз и в арабской
     версии, где логические границы зеркалятся вместе с текстом. */
  border-right: 1px solid currentColor;
  border-bottom: 1px solid currentColor;
  rotate: 45deg;
  translate: 0 -0.15rem;
  /* Стрелка подрагивает вниз — то же движение, что предлагают пальцу */
  animation: scroll-hint 2.6s var(--ease-in-out) infinite;
}

@keyframes scroll-hint {
  0%,
  70%,
  100% {
    translate: 0 -0.15rem;
  }
  85% {
    translate: 0 0.2rem;
  }
}

@media (hover: hover) and (pointer: fine) {
  .hero__scroll:hover {
    color: var(--brass-lit);
  }
}

/* Показания прибора: не «карточки со статистикой», а строка отсчётов */
.readout {
  display: grid;
  gap: 0;
  border-block-start: var(--rule);
}

@media (min-width: 34rem) {
  .readout {
    /* Доли считаны по фактической длине значений, а не «первой побольше»:
       после правок заказчика самым длинным стал привод («Ветер и электрический
       привод»), и при 1.5fr 1fr 1fr он ломался на три строки против одной у
       соседей. Эксплуатация — самое короткое, ей и меньше всех. */
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 1.45fr) minmax(0, 0.85fr);
  }
}

.readout div {
  padding-block: 0.9rem;
  border-block-end: var(--rule);
}

/* На телефоне показания идут строками «подпись — значение», как в таблице
   прибора: втрое компактнее столбика и оставляет первому экрану место под
   саму скульптуру — ради неё страницу и открывают. */
@media (max-width: 33.99rem) {
  .readout div {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    padding-block: 0.7rem;
  }

  .readout dt {
    margin-bottom: 0;
  }

  .readout dd {
    text-align: end;
  }
}

@media (min-width: 34rem) {
  .readout div {
    border-block-end: none;
    padding-inline-end: 1rem;
  }
}

.readout dt {
  color: var(--text-faint);
  margin-bottom: 0.35rem;
}

/* Подпись — шкала прибора, значение — обычный текст: капслоком в моноширинном
   кириллица разъезжается и «Медь, нержавеющая сталь» ломается на три строки. */
.readout dd {
  margin: 0;
  font-family: Spectral, Georgia, serif;
  font-size: 1rem;
  letter-spacing: normal;
  text-transform: none;
  color: var(--text);
}

/* --- Лимб: сигнатура страницы --------------------------------------------- */

.limb {
  position: relative;
  aspect-ratio: 1;
  width: min(100%, 34rem);
  margin-inline: auto;
}

/* Круг под текстом не должен занимать телефон целиком: он читается как
   деталь прибора, а не как отдельный экран. */
@media (max-width: 47.99rem) {
  .limb {
    width: min(84%, 20rem);
  }
}

.limb__dial {
  position: absolute;
  inset: 0;
  color: var(--brass);
  /* Постоянное вращение — это ветер, который не прекращается. linear, потому
     что равномерное движение не имеет фаз разгона. Скорость подобрана так,
     чтобы движение было заметно за пару секунд, но не мельтешило. */
  animation: limb-spin 100s linear infinite;
}

/* Проворот от скролла: страница листается — прибор отзывается. Там, где
   scroll-driven анимации не поддержаны, остаётся базовое вращение выше. */
@supports (animation-timeline: scroll()) {
  .limb__dial {
    animation: limb-spin 100s linear infinite, limb-scroll 1s linear both;
    /* scroll(root block), а не scroll(): из-за overflow-x на body голый
       scroll() цеплялся к body и не двигался вовсе. */
    animation-timeline: auto, scroll(root block);
  }
}

@keyframes limb-spin {
  to {
    transform: rotate(360deg);
  }
}

@keyframes limb-scroll {
  to {
    rotate: 150deg;
  }
}

.limb__photo {
  position: absolute;
  inset: 11%;
  border-radius: 50%;
  overflow: hidden;
  box-shadow: 0 2.5rem 5rem -1.5rem rgb(3 8 18 / 0.85);
}

.limb__photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* На телефоне первый экран — законченная композиция высотой в viewport.
   Видео уже показывает объект, поэтому второй круглый портрет только дублировал
   сюжет и торчал обрезанным снизу. Характеристики остаются одним компактным
   доказательным блоком у нижней кромки, а не отдельной таблицей. */
@media (max-width: 47.99rem) {
  /* Блок стоит по центру экрана, а не прижат к верхней кромке. Прежняя раскладка
     (align-items: stretch плюс верхний отступ в 5.35rem) сажала всю композицию под
     шапку, и под ней оставалась яма пустого видео высотой в треть экрана: воздух
     был, но весь с одной стороны. Отступы держат блок в стороне от шапки сверху и
     от кромки снизу, остальное распределяет центрирование. */
  .hero {
    min-height: 100svh;
    /* Шапка непрозрачна и занимает 4.25rem, поэтому верхний отступ = её высота
       плюс нижний отступ: только при таком равенстве центрирование даёт на
       экране одинаковый зазор над блоком и под ним. Просто симметричные
       padding'и оставляли сверху на высоту шапки меньше, чем снизу. */
    padding-block: 7rem 2.75rem;
    align-items: center;
  }

  /* Тёмное там, где лежит текст, — то есть в средней полосе; у верхней и нижней
     кромки завеса отпускается, и видно, что за текстом действительно вращается
     объект. Самый низ снова уходит в цвет страницы, чтобы экран не обрывался швом. */
  .hero__video::after {
    background:
      linear-gradient(
        to bottom,
        rgb(6 15 30 / 0.55) 0%,
        rgb(6 15 30 / 0.74) 32%,
        rgb(6 15 30 / 0.74) 68%,
        rgb(6 15 30 / 0.92) 100%
      ),
      linear-gradient(to right, rgb(6 15 30 / 0.55), transparent 92%);
  }

  [dir="rtl"] .hero__video::after {
    background:
      linear-gradient(
        to bottom,
        rgb(6 15 30 / 0.55) 0%,
        rgb(6 15 30 / 0.74) 32%,
        rgb(6 15 30 / 0.74) 68%,
        rgb(6 15 30 / 0.92) 100%
      ),
      linear-gradient(to left, rgb(6 15 30 / 0.55), transparent 92%);
  }

  .hero__video video {
    width: 100%;
    height: 100%;
    min-width: 0;
    min-height: 0;
    object-position: 52% center;
    /* Кадр снят в пасмурный день и на телефоне выглядел вымытым до серого */
    filter: contrast(1.1) saturate(1.08);
  }

  .hero__grid {
    display: block;
    width: 100%;
    min-height: 0;
  }

  .hero__grid > div:first-child {
    display: block;
    min-height: 0;
  }

  .hero h1 {
    max-width: 7.5ch;
    margin-bottom: 1.5rem;
    font-size: clamp(3.1rem, 15vw, 4.25rem);
    line-height: 0.88;
    letter-spacing: -0.02em;
  }

  .hero__lead--desktop {
    display: none;
  }

  .hero__lead--mobile {
    display: block;
    max-width: 30ch;
    margin-bottom: 1.9rem;
    font-size: 1rem;
    line-height: 1.5;
    color: color-mix(in srgb, var(--text) 84%, transparent);
  }

  .hero__actions {
    display: block;
    margin-bottom: 0;
  }

  .hero__actions .btn {
    width: auto;
    padding: 0.75rem 1rem;
    justify-content: flex-start;
    box-shadow: none;
  }

  /* Обращение в WhatsApp остаётся залитым латунью и на телефоне. Прозрачный
     вариант с блюром экономил фон, но телефон — то самое устройство, ради
     которого страницу открывают на встрече, и единственное целевое действие
     на нём оказывалось слабее, чем на десктопе. Тень отделяет кнопку от видео. */
  .hero__actions .btn--solid {
    box-shadow: 0 1rem 2rem -0.75rem rgb(3 8 18 / 0.85);
  }

  /* Под первым экраном лежит ещё семь разделов, а на телефоне о них ничто не
     сообщало: подпись со стрелкой была скрыта, и внизу оставалось пустое видео. */
  .hero__scroll {
    display: inline-flex;
    margin-top: 1.5rem;
  }

  /* Показания читаются строками «подпись — значение». Прежняя раскладка прятала
     подписи (dt: none) и уводила третий пункт в отдельную колонку: на экране
     оставались три фразы без ключей, а «Круглый год» висел справа сам по себе и
     выглядел промахом вёрстки, а не композицией. */
  .readout {
    display: grid;
    gap: 0;
    max-width: 30rem;
    margin-top: 1.85rem;
    padding-inline-start: 0.95rem;
    border-block-start: 0;
    border-inline-start: 1px solid rgb(201 139 75 / 0.58);
  }

  .readout div,
  .readout div:nth-child(n) {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.5rem 0;
    border: 0;
  }

  .readout dt {
    display: block;
    margin-bottom: 0;
    font-size: 0.625rem;
    color: var(--text-faint);
  }

  .readout dd {
    font-size: 0.8125rem;
    line-height: 1.35;
    color: var(--text);
    text-align: end;
  }

  .limb {
    display: none;
  }
}

/* Короткий экран (SE и подобные): та же центрированная композиция, но воздух
   и кегль поджаты — иначе блок перестаёт помещаться в 100svh и центрирование
   начинает срезать его сверху и снизу разом. */
@media (max-width: 47.99rem) and (max-height: 43rem) {
  .hero {
    padding-block: 4.75rem 0.5rem;
  }

  .hero h1 {
    margin-bottom: 0.8rem;
    font-size: clamp(2.65rem, 12.75vw, 3.15rem);
  }

  .hero__lead--mobile {
    margin-bottom: 1rem;
    font-size: 0.9375rem;
    line-height: 1.4;
  }

  .hero__actions .btn {
    padding-block: 0.68rem;
  }

  .hero__scroll {
    margin-top: 0.85rem;
  }

  .readout {
    margin-top: 0.95rem;
  }

  .readout div,
  .readout div:nth-child(n) {
    padding: 0.3rem 0;
  }
}

/* --- Пять этапов: вертикальная шкала с делениями -------------------------- */

.cycle {
  display: grid;
  gap: 0;
  border-block-start: var(--rule);
}

.cycle__step {
  display: grid;
  gap: 0.5rem 2rem;
  padding-block: clamp(1.5rem, 1.1rem + 1.2vw, 2.25rem);
  border-block-end: var(--rule);
  align-items: start;
}

/* Номер — метка на шкале, а не колонка: ему хватает своей ширины, и между ним
   и заголовком не должно быть провала в полтора сантиметра. Освободившееся
   отдано заголовку — при 15rem «Расчёт кинематики» не помещался и ломался
   надвое, тогда как соседние этапы стояли в одну строку. */
@media (min-width: 48rem) {
  .cycle__step {
    grid-template-columns: 2.25rem minmax(0, 17rem) minmax(0, 1fr);
    gap: 0 clamp(1.25rem, 2.2vw, 2.25rem);
  }
}

.cycle__n {
  color: var(--brass-deep);
  padding-block-start: 0.4rem;
}

.cycle__step h3 {
  font-size: clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem);
}

.cycle__step p {
  color: var(--text-dim);
  max-width: 68ch;
}

/* --- Заказчики: реестр ---------------------------------------------------- */

.clients {
  display: grid;
  gap: clamp(2.5rem, 1.5rem + 4vw, 5rem);
}

@media (min-width: 62rem) {
  .clients {
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
  }
}

.registry {
  border-block-start: 1px solid var(--brass-deep);
}

.registry div {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 2rem;
  padding-block: 1.1rem;
  border-block-end: var(--rule);
}

.registry dt {
  color: var(--text-dim);
  font-size: 0.9375rem;
}

.registry dd {
  margin: 0;
  font-family: Podkova, serif;
  font-weight: 600;
  font-size: clamp(1.5rem, 1.2rem + 1.2vw, 2.25rem);
  color: var(--brass-lit);
  line-height: 1;
}

.note {
  margin-block-start: 2rem;
  padding-inline-start: 1.25rem;
  border-inline-start: 1px solid var(--brass-deep);
  color: var(--text-dim);
  font-size: 1rem;
}

/* --- Каталог: чередующиеся полосы ----------------------------------------- */

.type {
  display: grid;
  gap: clamp(1.5rem, 0.9rem + 3vw, 3.25rem);
  align-items: center;
  padding-block: clamp(2rem, 1.3rem + 2.6vw, 3.25rem);
  border-block-start: var(--rule);
}

@media (min-width: 56rem) {
  .type {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
  }

  .type:nth-child(even) .type__media {
    order: -1;
  }
}

.type__media {
  position: relative;
  overflow: hidden;
  background: var(--night-2);
}

.type__media img,
.type__media video {
  width: 100%;
  /* Явный height обязателен: у тега уже есть HTML width/height от исходника
     (для CLS), и без CSS height браузер берёт их как презентационную
     подсказку — оба измерения становятся «определёнными», aspect-ratio
     ниже перестаёт работать, и портретное фото растягивается на всю высоту. */
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  transition: transform 700ms var(--ease-out);
}

/* Кадр чуть уводит в сторону, как объект уводит порывом — не «зум по ховеру» */
@media (hover: hover) and (pointer: fine) {
  .type:hover .type__media img,
  .type:hover .type__media video {
    transform: scale(1.04) rotate(0.7deg);
  }
}

.type__sub {
  color: var(--brass);
  margin-block: 0.75rem 1.25rem;
  font-size: 1rem;
}

.type__body p {
  color: var(--text-dim);
  max-width: 54ch;
}

.specs {
  margin-block-start: 1.75rem;
  border-block-start: var(--rule);
}

.specs div {
  display: flex;
  gap: 1.5rem;
  justify-content: space-between;
  padding-block: 0.7rem;
  border-block-end: var(--rule);
  font-size: 0.9375rem;
}

.specs dt {
  color: var(--text-faint);
}

.specs dd {
  margin: 0;
  color: var(--text);
  text-align: end;
}

/* --- Галереи -------------------------------------------------------------- */

/* Колонки сохраняют исходную пропорцию каждого кадра. Раньше все снимки
   загонялись в одинаковую плитку 3:4 через object-fit: cover — у кинетических
   объектов это срезало лопасти, стержни и контекст площадки. */
.gallery {
  column-count: 2;
  column-gap: 0.5rem;
}

/* column-count и column-width вместе дают минимум из двух — поэтому прежний
   column-width: 15rem не работал вовсе, страница оставалась на двух колонках,
   и на 1440px кадры раздувались до 700px с рваными дырами внизу. Здесь счёт
   колонок отдан браузеру: 2 → 3 → 4 по мере ширины. */
@media (min-width: 40rem) {
  .gallery {
    column-count: auto;
    column-width: 20rem;
    column-gap: 0.75rem;
  }
}

.shot {
  position: relative;
  display: inline-block;
  width: 100%;
  margin-block-end: 0.5rem;
  padding: 0;
  border: none;
  background: var(--night-2);
  overflow: hidden;
  cursor: pointer;
  break-inside: avoid;
  /* Кадр галереи — <button>, а у кнопки шрифт задан стилем самого браузера
     (Arial). Без этой строки подпись внутри наследует Arial от кнопки, и на
     странице появляется единственный гротеск — тот самый признак халтуры. */
  font: inherit;
  color: inherit;
}

@media (min-width: 40rem) {
  .shot {
    margin-block-end: 0.75rem;
  }
}

.shot img {
  width: 100%;
  height: auto;
  object-fit: contain;
  transition: transform 600ms var(--ease-out), opacity 300ms ease;
}

@media (hover: hover) and (pointer: fine) {
  .shot:hover img {
    transform: scale(1.04);
  }
}

.gallery__title {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1.5rem;
  padding-block-end: 0.9rem;
  margin-block: clamp(2.5rem, 1.5rem + 3vw, 4rem) 1.25rem;
  border-block-end: 1px solid var(--brass-deep);
}

.gallery__title h3 {
  font-size: clamp(1.25rem, 1.1rem + 0.6vw, 1.5rem);
}

/* Счётчик кадров. Трекинг .data в 0.18em разрывает двузначное число: «10»
   читалось как «1 0». Цифрам разрядка не нужна — она для капса подписей. */
.gallery__title .data {
  letter-spacing: normal;
  font-variant-numeric: tabular-nums;
}

/* --- В движении ------------------------------------------------------------ */

/* Подсекция того же #works, без отдельного пункта меню. По просьбе заказчика
   видео идёт первым, фото — уже после, как дополнение к тому, чего нет
   в ролике: стандартного .head хватает, отдельный класс не нужен. */

/* Ровный грид, не masonry: карточки все 1:1, колонкам ловить нечего. */
.motion__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.5rem;
}

@media (min-width: 30rem) {
  .motion__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.75rem;
  }
}

@media (min-width: 60rem) {
  .motion__grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

.motion__card {
  position: relative;
  aspect-ratio: 1;
  overflow: hidden;
  background: var(--night-2);
}

.motion__card video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Подпись видна всегда, а не по наведению: без неё на десктопе весь раздел
   «Установлено и работает» стоял безымянным — доказательство без адреса.
   Скрим уходит в прозрачность на середине кадра, чтобы не срезать композицию,
   и подстрахован тенью на самом тексте: под подписью бывает и светлое небо,
   и жёлтая листва. Общий селектор с .motion__card — рецепт тот же и для видео,
   держит текст поверх движущегося кадра, а не только поверх первого. */
.shot figcaption,
.motion__card figcaption {
  position: absolute;
  inset-block-end: 0;
  inset-inline: 0;
  padding: 2.75rem 0.9rem 0.75rem;
  text-align: start;
  background: linear-gradient(
    to top,
    rgb(4 10 22 / 0.92),
    rgb(4 10 22 / 0.55) 42%,
    transparent
  );
  color: var(--text);
  font-family: Spectral, Georgia, serif;
  font-size: 0.8125rem;
  line-height: 1.3;
  letter-spacing: normal;
  text-shadow: 0 1px 3px rgb(4 10 22 / 0.9);
}

/* --- Как это работает ----------------------------------------------------- */

.facts {
  display: grid;
  gap: 0;
  border-block-start: var(--rule);
}

@media (min-width: 48rem) {
  .facts {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: clamp(2rem, 5vw, 5rem);
  }
}

.fact {
  padding-block: clamp(1.5rem, 1.1rem + 1.4vw, 2.25rem);
  border-block-end: var(--rule);
}

.fact h3 {
  font-size: clamp(1.125rem, 1.05rem + 0.5vw, 1.375rem);
  margin-bottom: 0.6rem;
}

.fact p {
  color: var(--text-dim);
  font-size: 1rem;
  max-width: 46ch;
}

/* --- Контакты ------------------------------------------------------------- */

.contact {
  border-block-start: 1px solid var(--brass-deep);
}

.contact h2 {
  max-width: 18ch;
}

.contact__grid {
  display: grid;
  gap: clamp(2.5rem, 1.5rem + 4vw, 5rem);
  align-items: end;
}

@media (min-width: 56rem) {
  .contact__grid {
    grid-template-columns: minmax(0, 1fr) auto;
  }
}

.phone {
  display: block;
  margin-block: 0.5rem 1.75rem;
  font-family: Podkova, serif;
  font-weight: 600;
  font-size: clamp(1.75rem, 1.3rem + 2.1vw, 2.75rem);
  color: var(--brass-lit);
  text-decoration: none;
  white-space: nowrap;
  transition: color 200ms ease;
}

@media (hover: hover) and (pointer: fine) {
  .phone:hover {
    color: var(--text);
  }
}

.foot {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem 2rem;
  justify-content: space-between;
  padding-block: 2rem 3rem;
  border-block-start: var(--rule);
  color: var(--text-faint);
}

/* --- Лайтбокс ------------------------------------------------------------- */

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: grid;
  grid-template-rows: auto 1fr auto;
  background: color-mix(in srgb, var(--night) 96%, #000);
  opacity: 0;
  visibility: hidden;
  transition: opacity 200ms var(--ease-out), visibility 200ms;
}

.lightbox[data-open="true"] {
  opacity: 1;
  visibility: visible;
}

.lightbox__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  padding: 1rem var(--edge);
  border-block-end: var(--rule);
}

.lightbox__stage {
  display: grid;
  place-items: center;
  padding: 1rem var(--edge);
  min-height: 0;
}

/* На телефоне поля по краям только отнимают у кадра ширину — а по ширине он
   как раз и упирается. */
@media (max-width: 47.99rem) {
  .lightbox__stage {
    padding-inline: 0;
  }
}

.lightbox__stage img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  /* Ничто в реальном мире не появляется из ничего: старт с 0.96, не с нуля */
  transform: scale(0.96);
  opacity: 0;
  transition: transform 240ms var(--ease-out), opacity 240ms var(--ease-out);
}

.lightbox[data-open="true"] .lightbox__stage img {
  transform: scale(1);
  opacity: 1;
}

.lightbox__nav {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  padding: 1rem var(--edge) 1.75rem;
}

.icon-btn {
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  /* На телефоне hover не бывает — крестик должен читаться как кнопка сам по
     себе, без наведения. night-line здесь слишком близок по тону к фону
     лайтбокса и на экране телефона на встрече практически терялся. */
  border: 1px solid var(--brass-deep);
  background: color-mix(in srgb, var(--night) 60%, transparent);
  color: var(--text-dim);
  cursor: pointer;
  transition: transform 160ms var(--ease-out), color 200ms ease,
    border-color 200ms ease, background 200ms ease;
}

.icon-btn svg {
  width: 1.1rem;
  height: 1.1rem;
}

@media (hover: hover) and (pointer: fine) {
  .icon-btn:hover {
    color: var(--brass-lit);
    border-color: var(--brass);
  }
}

.icon-btn:active {
  transform: scale(0.94);
}

/* --- Появление при прокрутке ---------------------------------------------- */

/* Кадр проявляется снизу вверх, как проявляется отпечаток. Сделано на
   scroll-driven анимации, а не на IntersectionObserver: анимация живёт вне
   основного потока, а там, где браузер её не знает, контент просто виден —
   пустой страницы не бывает ни при каком отказе. */
@keyframes reveal-in {
  from {
    opacity: 0;
    translate: 0 1.5rem;
  }
  to {
    opacity: 1;
    translate: 0 0;
  }
}

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .reveal {
      animation: reveal-in linear both;
      animation-timeline: view();
      animation-range: entry 2% cover 22%;
    }

  }
}

/* --- Арабская версия ------------------------------------------------------ */

[dir="rtl"] body,
[dir="rtl"] .lead,
[dir="rtl"] p {
  font-family: Amiri, "Times New Roman", serif;
}

[dir="rtl"] h1,
[dir="rtl"] h2,
[dir="rtl"] h3 {
  font-family: Amiri, serif;
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: 0;
}

/* Латинское имя бренда остаётся латинским и в арабской версии */
[dir="rtl"] .hero h1,
[dir="rtl"] .top__mark {
  font-family: Podkova, serif;
  font-weight: 600;
}

[dir="rtl"] .data,
[dir="rtl"] .btn {
  letter-spacing: 0;
  font-family: Amiri, serif;
  font-weight: 700;
}

/* Арабо-индийские цифры моноширинный рисует мелко и криво — номера этапов
   отдаём Amiri, который знает эти знаки. */
[dir="rtl"] .cycle__n {
  font-family: Amiri, serif;
  font-size: 1.25rem;
  color: var(--brass);
}

[dir="rtl"] .specs dd {
  text-align: start;
}

/* --- Меньше движения ------------------------------------------------------ */

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  .limb__dial,
  .hero__scroll::after,
  .field__rotor {
    animation: none;
  }

  .sheet[data-open="true"] .sheet__nav a {
    animation: none;
    opacity: 1;
    translate: none;
  }

  .type__media img,
  .type__media video,
  .shot img {
    transition: none;
  }
}
