/* Секции страницы. Порядок блоков совпадает с index.html. */

.wrap{ max-width:var(--maxw); margin:0 auto; padding-left:var(--pad); padding-right:var(--pad); }
section{ position:relative; }

/* ——— 1. Шапка ——— */
/* Шапка. На первом экране — без плашки: название и меню лежат прямо на кадре,
   читаемость держат тень под буквами и градиент в верхней части кадра.
   Ниже первого экрана прозрачная шапка налезала бы на заголовки блоков —
   там под неё подъезжает светлая полоса во всю ширину. */
/* Логотип — вектор, вшит в разметку. Цвет наследуется через currentColor,
   поэтому знак красится одной строкой и в шапке, и в подвале.
   Рябиновый держится в обоих состояниях: на кадре первого экрана его вытягивает
   собственное затемнение героя (замер: худший кадр петли 3,97:1), на светлой
   полосе он работает как подпись, а не как текст. */
.brand{
  position:fixed; left:var(--bleed); top:1.875rem; z-index:30;
  color:var(--ryabina); text-decoration:none;
  font-size:0; line-height:0;
  padding:0.625rem 0; margin:-0.625rem 0;            /* зона нажатия 40px по высоте, как у пунктов меню */
  filter:drop-shadow(0 1px 0.875rem rgba(0,0,0,.45));
}
.brand .lg{ display:block; height:1.625rem; width:auto; }
body.past-hero .brand{ filter:none; }
nav{
  position:fixed; right:var(--bleed); top:1.875rem; z-index:30;
  display:flex; gap:1.875rem; align-items:center;
}
nav a{ color:#fff; font-size:0.875rem; font-weight:400; text-decoration:none; opacity:.86;
  padding:0.625rem 0; margin:-0.625rem 0;            /* зона нажатия 40px по высоте */
  text-shadow:0 1px 1rem rgba(0,0,0,.55); }
nav a:hover{ opacity:1; }

/* полоса под шапкой — только за пределами первого экрана */
.chrome-bg{
  position:fixed; left:0; right:0; top:0; height:4.625rem; z-index:29;
  background:rgba(255,255,255,.90); backdrop-filter:blur(0.875rem);
  border-bottom:1px solid var(--hair);
  opacity:0; pointer-events:none;
}
body.past-hero .chrome-bg{ opacity:1; }
body.past-hero nav a{ color:var(--carbon); text-shadow:none; }

/* шапка уезжает вверх при прокрутке вниз и возвращается при прокрутке вверх */
.brand, nav, .chrome-bg{ transition:transform .35s ease, opacity .35s ease, color .25s ease; }
body.hide-chrome .brand, body.hide-chrome nav, body.hide-chrome .chrome-bg{
  transform:translateY(-140%); opacity:0; pointer-events:none;
}
@media(max-width:900px){
  nav{ display:none; }
  .brand{ top:1.5rem; }
  .brand .lg{ height:1.1875rem; }
  .chrome-bg{ height:3.875rem; }
}

/* ——— 2. Первый экран с видео ——— */
.hero{ height:100svh; min-height:33.75rem; overflow:hidden; background:#151512; }
.hero video, .hero .still{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover; }
.hero .still{ display:none; }
.hero .veil{
  position:absolute; inset:0;
  background:linear-gradient(to top, rgba(18,18,16,.58) 0%, rgba(18,18,16,.08) 46%, rgba(18,18,16,.30) 100%);
}
.hero::after{ content:''; position:absolute; left:0; right:0; top:0; height:11.875rem;
  z-index:4; pointer-events:none;
  background:linear-gradient(to bottom, rgba(14,14,12,.62), rgba(14,14,12,0)); }
.hero .copy{ position:absolute; left:var(--bleed); right:var(--bleed); bottom:var(--v4); color:#fff;
  /* Текст лежит прямо на видео, а видео за петлю успевает стать светлым: на
     плане с полотном (4,0–4,8 с) опоры проваливались до 2,59 при норме 4,5,
     подписи под ними до 1,98. Контраст мы раньше мерили на одном кадре и
     получали 10,2 — кадр был удачный. Плотнее вуаль лечит это дорого: чтобы
     поднять опоры к норме, кадр надо затемнить ещё на 8–12 %, и мутнеет он
     весь ради двух углов; пятна в углах дают только 3,7. Мягкая тень делает
     то же самое даром — она видна лишь там, где под буквой светло, и средняя
     яркость экрана остаётся прежней. Стало 9,87 / 6,18 / 7,07 / 5,32.
     Размеры в em: под титулом 72 px это мягкое пятно в 10 px, под подписью
     12 px — кайма в 1,7 px. */
  text-shadow:0 0.04em 0.14em rgba(10,10,9,.45); }
/* Опоры «1780 · Три площадки · 700+» и метка «Производственная группа · Иваново»
   сняты 14.09 по решению собственника: под титулом теперь одна фраза-подстрочник.
   Опоры ставили 13.09, чтобы связать углы и забрать пустоту над титулом; с
   подстрочником блок читается одной мыслью, а 1780 и 700+ остаются в «Цифрах»
   через два экрана. Правила прежних опор — в снимке sections.css от 13.09
   в _УДАЛИТЬ_ЭТУ_ПАПКУ/2026-09-14 первый экран. */
/* Титул первого экрана. Расстановку выбрал собственник вечером 05.09 из шести:
   три строки «Текстильное / производство / полного цикла», метка ПОД титулом.
   Ширина 16ch держит три строки на любом кегле (ch растёт вместе с буквами).

   Кегль тогда же выбран из шести: 72. Блок занимает 27,5 % экрана 1440×900
   и 30,8 % на 1366×768. Перед этим стояло 92 px с меткой сверху — 29 %
   экрана, «как будто слишком большое»; 80 смотрели в две строки, и дело было
   не в кегле, а в расстановке.

   13.09 кегль поднимали до 80 и вернули обратно в тот же день. Повод был
   бумажный: в `tokens.css` шкала записана как «80 титул и цифры», а титул
   стоял на 72, и показалось, что самый крупный кегль страницы стоит не здесь,
   а на числах через два экрана. Сравнивали не то. Кегль — не масса:
   четырёхзначное число в строку и фраза в три строки при одном кегле разные
   объекты. Площадь самих букв на 1440×900: титул 72 — 13 800 пикселей краски,
   титул 80 — 16 600, самое крупное число в «Цифрах» — 18 600. По массе числа
   тяжелее титула и были, и остались; по занимаемому месту титул и так
   крупнейший объект страницы. Чинить надо было запись в токенах.

   Цена же выше номинала: кегль +11 %, площадь букв +20 % — масса растёт
   квадратом. На 1366×768 блок уезжал к 33,8 %, выше забракованных 29 %.
   Собственник, увидев три кегля рядом: «не сильно огромный?». Вернули 72. */
/* 14.09: кегль 64 (4rem). Собственник, увидев 72 / 64 / 56 рядом с подстрочником,
   выбрал 64: с подстрочником титулу не нужно возвышаться над страницей кеглем —
   он и так крупнейший объект по месту, а блок стал на четверть ниже. На 1920
   это 85 px, на 1366×768 блок с подстрочником — около 24 % экрана. */
.hero .disp{ max-width:16ch; font-size:clamp(2.375rem,5vw,4rem); line-height:.94;
  letter-spacing:-.015em; font-weight:300; }
/* Подстрочник под титулом: одна фраза кеглем лида раздела (18 px), до 46 знаков
   в строке, чуть тише титула. Тень наследует от .copy. Говорит «что и где»;
   «почему без наценки» остаётся разделу «О группе» — повтора между экранами нет. */
.hero .sub{ margin:1.25rem 0 0; max-width:46ch; font-size:1.125rem; line-height:1.5;
  font-weight:400; color:rgba(255,255,255,.88); text-wrap:pretty; }
@media(max-width:900px){ .hero .sub{ font-size:0.9375rem; margin-top:1rem; } }
/* Д · Первый экран не отпускает. Видео остаётся на месте, страница наезжает
   на него сверху: кадр медленно укрупняется, титул уходит вниз и растворяется,
   затемнение набирает плотность. Ни одного лишнего байта — то же видео.
   05.09 закреплённый первый экран уже показывали и сняли (ход В ниже): там
   кадр сжимался в колонку и спорил с шапкой. Здесь кадр остаётся во всю
   ширину и ничего не сжимается; показано живьём и принято 10.09.
   Укрупнение и сдвиг сделаны отдельными свойствами scale и translate, а не
   transform: рядом уже живёт transform у шапки, и они бы затирали друг друга. */
.hero{ position:sticky; top:0; z-index:0; }
.over{ position:relative; z-index:2; background:var(--vellum); }
.hero video, .hero .still{ scale:calc(1 + var(--hp,0) * .14); transform-origin:50% 42%; }
.hero .copy{ translate:0 calc(var(--hp,0) * 4rem);
  opacity:clamp(0, calc(1 - var(--hp,0) * 1.6), 1); }
/* Затемнение держим на полной плотности. 11.09 пробовали растить его вместе
   с прокруткой (0,55 → 1,3): на верху страницы титул терял контраст — 10,80
   против 12,07 по медиане и 7,91 против 9,20 в худшем проценте площади, — а
   прирост внизу не виден, кадр там уже закрыт слоем .over. */
.hero .veil{ opacity:1; }
@media (prefers-reduced-motion:reduce){
  .hero video, .hero .still{ scale:1; }
  .hero .copy{ translate:none; opacity:1; }
  .hero .veil{ opacity:1; }
}
/* 17.09 · На экранах с пальцем первый экран не закреплён и ход Д выключен.
   Собственник 16.09: на iPhone прокрутка первого экрана и аэросъёмки
   дёргалась. Разбирали пробами на его телефоне: без обработчиков прокрутки
   (шапка, линия истории, доля первого экрана) — не помогло; без закрепления
   первого экрана — «намного лучше». То есть виновата не работа скрипта,
   а sticky-видео под страницей: iPhone композитит весь скролл поверх слоя
   с играющим видео и не успевает. Без закрепления ход Д (укрупнение и сдвиг
   титула) теряет смысл, поэтому выключен вместе с ним; на 390 px сдвиг был
   30 пикселей. На ноутбуках и мониторах всё как принято 10.09. */
@media (hover:none) and (pointer:coarse){
  .hero{ position:relative; }
  .hero video, .hero .still{ scale:1; }
  .hero .copy{ translate:none; opacity:1; }
}

/* Кнопок на первом экране нет: это титул презентации, а не лендинг.
   Единственное действие — «Контакты» в шапке и финальный блок внизу страницы.
   Вертикальная подсказка «Листайте» снята 05.09: единственный элемент у правого
   края и приём из лендингов 2015 года. */
@media (prefers-reduced-motion:reduce){
  .hero video{ display:none; }
  .hero .still{ display:block; }
}

/* ——— 3. О группе ——— */
.about{ padding-top:var(--sec); padding-bottom:var(--sec); }
.two{ display:grid; grid-template-columns:1fr 1fr; gap:var(--gap); align-items:start; }
@media(max-width:900px){ .two{ grid-template-columns:1fr; gap:1.5rem; } }

/* ——— 4. Цифры ——— */
.nums{ display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:var(--gap);
  padding-bottom:var(--sec); }
.nums > div{ border-top:1px solid var(--carbon); padding-top:var(--s3); }
.nums .n{ font-weight:300; font-size:clamp(2.75rem,5.6vw,5rem); line-height:.92;
  letter-spacing:-.015em; }
.nums .n .u{ font-size:.34em; letter-spacing:0; margin-left:.2em; }
.nums .c{ margin-top:var(--s3); font-size:0.875rem; line-height:1.4; color:var(--mercury);
  max-width:24ch; }
@media(max-width:820px){ .nums{ grid-template-columns:1fr 1fr; gap:1.75rem; } }

/* ——— 5. Цикл ——— */
.way{ padding-top:var(--sec); padding-bottom:var(--sec); border-top:1px solid var(--hair); }
/* Цепочка, а не таблица: линейка одна на весь ряд, у каждого шага засечка.
   Пятью отдельными линейками блок читался как спецификация в отчёте.
   Якорь — название шага. Крупные номера сюда не ставим: в мозаике
   производства уже есть 01…06, две большие нумерации с разным счётом
   на одной странице спорят друг с другом. */
.steps{ display:grid; grid-template-columns:repeat(6,minmax(0,1fr));
  gap:clamp(1rem,2.2vw,2.125rem); margin-top:var(--v2);
  border-top:1px solid var(--carbon); }
.step{ position:relative; padding-top:var(--s3); }
.step::before{ content:''; position:absolute; left:0; top:0; width:1px; height:0.75rem;
  background:var(--carbon); }
.step .k{ font-size:0.7812rem; letter-spacing:.09em; text-transform:uppercase; color:var(--mercury); }
.step .t{ margin-top:0.875rem; font-size:clamp(1.25rem,2vw,1.75rem); font-weight:300;
  line-height:1.05; letter-spacing:-.005em; }
.step .v{ margin-top:0.75rem; font-size:0.875rem; color:var(--mercury); }
@media(max-width:820px){
  /* В две колонки сплошная линейка сверху накрыла бы только первый ряд,
     поэтому на узком экране возвращаем линейку каждому шагу. */
  .steps{ grid-template-columns:1fr 1fr; gap:1.375rem; border-top:0; }
  .step{ border-top:1px solid var(--carbon); }
  .step::before{ display:none; }
}

/* ——— 6. Производство: мозаика переделов ———
   Шесть переделов сложены в одну неровную сетку: крупный кадр, кадр поменьше
   и текстовая ячейка стоят в ней на равных и стыкуются друг с другом.
   Композиция у каждого передела своя — раскладка задана в разметке через
   grid-area, поэтому блок не читается как шаблон. На телефоне — столбец. */
.prod{ border-top:1px solid var(--hair); padding-top:var(--sec); }
.prod-head{ padding-bottom:var(--v3); }
.prod-head .body{ max-width:52ch; }

/* Мозаика собрана повторяющимся модулем: ведущий кадр во всю ширину передела,
   под ним два поддерживающих, подпись — в узкой колонке слева.
   До этого была одна общая 12-колоночная сетка на все шесть переделов: каждая
   ячейка знала свой grid-area, кадры стыковались встык и блок занимал 38%
   страницы, читаясь сплошной стеной. Модуль дал масштаб ведущему кадру и при
   этом стал короче — 4983px против 5117.
   Ширина 1200 вместо общих 1320: остальные блоки живут с полями, а сетка
   упиралась в края экрана. */
/* Мера мозаики — общая мера страницы. Своя, 1200 вместо 1320, стояла с 03.09,
   пока мозаика была стеной кадров встык: без полей сетка упиралась в края
   экрана. С панелями первым элементом стала текстовая колонка, и она должна
   стоять на той же линии, что заголовок раздела над ней. Замер до правки:
   заголовок 120, текст панели 180. */
.mos{
  padding-bottom:var(--sec);
}
.unit{
  display:grid; grid-template-columns:repeat(12,1fr);
  gap:clamp(0.625rem,1.3vw,1.125rem);
  margin-bottom:clamp(3rem,6vw,5.5rem);
  align-items:start;
}
.unit:last-child{ margin-bottom:0; }
/* Текстовая ячейка занимает 4 колонки из 12, а не 3. На трёх колонках строка
   выходила 257px — 28 знаков, вдвое меньше комфортных 45–75, абзац рвался на
   шесть коротких строк. На четырёх — 348px и 41 знак, как в остальных текстах
   страницы. Ведущий кадр теряет 92px из 806, на глаз это незаметно. */
.mos .tx{ grid-column:1 / 5; }
.mos .c1{ grid-column:5 / 13; aspect-ratio:16 / 7; }
.mos .c2{ grid-column:1 / 7;  aspect-ratio:4 / 3; }
.mos .c3{ grid-column:7 / 13; aspect-ratio:4 / 3; }
/* Упаковка — единственный передел с одним кадром. Пробовали сделать её кадр
   ниже остальных (16/5), чтобы финал не перевешивал: на широком экране кадр
   превращался в щель 806×252, рука с лентой обрезалась, а на телефоне
   оставалось 350×109 — сюжет переставал читаться. Пропорция у всех ведущих
   кадров теперь одна. */

.mos .c{ position:relative; overflow:hidden; background:#E6E3DE no-repeat center/cover;
  line-height:0; }
/* кадры выведены из потока: иначе строка сетки растягивалась бы под высоту
   самой фотографии и вся мозаика разъезжалась */
.mos .c img, .mos .c video{ position:absolute; inset:0; width:100%; height:100%;
  object-fit:cover; display:block; }
.mos .c video{ opacity:0; transition:opacity .6s ease; }
.mos .c video.on{ opacity:1; }

/* Содержимое текстовой ячейки прижато к ВЕРХУ: номер передела встаёт вровень
   с верхней кромкой соседнего кадра. Прижатый к низу текст висел в воздухе
   и не совпадал ни с одной линией мозаики. */
.mos .tx{
  display:flex; flex-direction:column; justify-content:flex-start;
  padding:0 2px 0.25rem; line-height:1.4;
}
/* Начертание 300, не 200: вес ExtraLight на страницу не вшит, и браузер молча
   подставлял Light. Теперь в коде то же, что на экране. */
.mos .tx .no{ font-weight:300; font-size:clamp(2.375rem,3.6vw,3.25rem); line-height:.85; }
.mos .tx h3{ font-weight:300; font-size:clamp(1.25rem,2.1vw,1.625rem); line-height:1;
  letter-spacing:.01em; margin-top:0.75rem; }
.mos .tx .spec{ font-size:0.7812rem; letter-spacing:.07em; text-transform:uppercase;
  color:var(--mercury); margin-top:0.75rem; padding-top:0.5rem; border-top:1px solid var(--hair-soft); }
/* 15px, не 14: это текст, который читают предложениями, а не подпись. Нижний
   порог основного текста на экране по Баттерику — 15. Подписи к кадрам,
   метки цифр и подвал остаются 14: они вторичные. */
.mos .tx p{ font-size:0.9375rem; line-height:1.55; margin-top:0.75rem; color:#4A4540; }

@media(max-width:900px){
  /* на телефоне сетка распадается: каждый передел — обычный блок,
     текст всегда первым, кадры под ним. Порядок в разметке задан
     раскладкой для широкого экрана, поэтому здесь его выправляем. */
  .mos{ padding-bottom:calc(var(--sec) * .6); }
  .unit{ grid-template-columns:1fr; gap:0.625rem; margin-bottom:2.75rem; }
  .unit .tx{ order:-1; padding:0 0 0.375rem; }
  .mos .tx, .mos .c1, .mos .c2, .mos .c3{ grid-column:1 / -1; }
  /* Ведущий кадр должен остаться ведущим и на телефоне. При 16/10 у ведущего
     и 4/3 у поддерживающих он оказывался НИЖЕ них — 219px против 262 — и
     иерархия переворачивалась. Теперь наоборот. */
  .mos .c1{ aspect-ratio:4 / 3; }
  .mos .c2, .mos .c3{ aspect-ratio:16 / 10; }
}

/* Е · Мозаика панелями. Передел занимает ровно экран и читается целиком:
   узкая колонка текста, высокий ведущий кадр, два поддерживающих друг над
   другом. Это раскладка, которая была у горизонтальной ленты, — она и давала
   ощущение собранности, а вовсе не движение вбок. Ленту сняли 11.09 после
   четырёх заходов, раскладку оставили.
   Чётные переделы зеркалятся: текст уходит вправо, кадры влево. Без этого
   шесть панелей подряд снова читаются шестью одинаковыми тактами — с чего
   вся история и начиналась.
   Высота задана в svh, а не пропорцией: пропорция у ведущего кадра здесь не
   работает — сетка считает её раньше, чем знает ширину колонок. */
@media(min-width:901px){
  .mos .unit{ height:76svh; grid-template-rows:1fr 1fr; align-items:stretch;
    margin-bottom:clamp(3.5rem,7vw,6.5rem); }
  /* Текст — четыре доли из двенадцати, не три. На трёх строка выходит 257 px,
     это 28 знаков против комфортных 45–75, и абзац рвётся на шесть коротких
     строк. Проверено и отвергнуто 03.09; в ленте я это правило нарушил. */
  .mos .unit .tx{ grid-column:1 / 5;   grid-row:1 / 3; align-self:center; }
  .mos .unit .c1{ grid-column:5 / 10;  grid-row:1 / 3; aspect-ratio:auto; }
  .mos .unit .c2{ grid-column:10 / 13; grid-row:1; aspect-ratio:auto; }
  .mos .unit .c3{ grid-column:10 / 13; grid-row:2; aspect-ratio:auto; }
  .mos .unit:nth-of-type(even) .tx{ grid-column:9 / 13; }
  .mos .unit:nth-of-type(even) .c1{ grid-column:4 / 9; }
  .mos .unit:nth-of-type(even) .c2,
  .mos .unit:nth-of-type(even) .c3{ grid-column:1 / 4; }
  /* «Упаковка» — единственный передел с одним кадром. Её не зеркалим:
     поддерживающих кадров нет, зеркалить нечего, а правило для последнего
     передела имело ту же специфичность, что и зеркальное, стояло позже и
     побеждало — кадр растягивался на 4–13 и накрывал текст, стоявший в 9–13.
     Замер до правки: текст x 912…1260, кадр x 455…1261. Кадр при этом
     становился самым крупным в блоке, 806 px против 470 у остальных, — при
     том что ролик упаковки самый слабый из четырёх.
     Обычный порядок и обычная ширина; воздух справа читается как конец линии. */
  .mos .unit:last-child .tx{ grid-column:1 / 5; }
  /* Кадр «Упаковки» горизонтальный, а не во всю высоту панели. Поддерживающих
     кадров у неё нет, форма ведущего ничем не связана, а все ролики сняты 16:9 —
     вертикальная рамка резала план до средней трети и растягивала его.
     Широкий кадр показывает сюжет целиком и закрывает раздел. */
  .mos .unit:last-child .c1{ grid-column:5 / 13; grid-row:1 / 3;
    aspect-ratio:16 / 9; height:auto; align-self:center; }
  /* Высота последней панели — по содержимому. Её горизонтальный кадр ниже
     остальных ведущих, и принудительные 76svh давали 282 px пустоты под ним. */
  .mos .unit:last-child{ height:auto; }
}

/* ——— 7. Полоса-цитата ———
   Реплика без кадра. До 11.09 здесь стояло фото во всю ширину — и оно
   повторяло первый экран: та же мягкая светлая ткань в дымке. Плюс счёт:
   полноэкранных тёмных моментов четыре, и три из них идут подряд в хвосте —
   32 % хвоста шло сплошным тёмным пятном, без этого кадра 20 %.
   Перестановку с «Печатью и лазером»
   пробовали, стало хуже: два полноэкранных кадра встали подряд.
   Кадр убран совсем. Осталась фраза на холсте — производство кончилось,
   человек делает вдох, дальше история. Слова не тронуты.
   Линейка сверху отделяет паузу от последнего передела: без неё фраза
   читалась подписью к упаковке. */
.band{ padding-block:var(--v4) var(--sec); }
.band .tx{ padding-inline:var(--edge); color:var(--carbon);
  border-top:1px solid var(--hair); padding-top:var(--v3); }
/* Две ступени. Первая фраза — факт, вторая — ремарка, которая закрывает
   возражение. Одним кеглем вторая читалась как продолжение перечисления
   и гасила саму реплику. */
.band .tx p{ font-weight:300; font-size:clamp(1.75rem,3.9vw,3.5rem); line-height:1.1;
  letter-spacing:-.015em; max-width:20ch; margin-top:var(--v2); }
.band .tx p span{ display:block; margin-top:var(--v2); font-size:1.125rem; line-height:1.4;
  letter-spacing:0; color:var(--mercury); max-width:34ch; }
@media(max-width:720px){
  .band .tx p{ font-size:1.75rem; max-width:none; }
  .band .tx p span{ font-size:1rem; max-width:none; }
}

/* ——— 8. История ———
   Аэросъёмка во всю ширину — это и есть «видно всю фабрику».
   Ниже семь дат одной лентой сверху вниз. */
/* верхней линии нет: границей раздела служит сам край полосы видео */
.hist{ padding-bottom:var(--sec); }
.wide{ position:relative; overflow:hidden; line-height:0;
  height:clamp(18.75rem,58vh,40rem); background:#E6E3DE; }
.wide img, .wide video{ position:absolute; inset:0; width:100%; height:100%;
  object-fit:cover; object-position:50% 50%; }

.hist-head{ padding-top:var(--sec); padding-bottom:var(--v2); }
.hist-head .disp{ max-width:18ch; }
.hist-head .body{ max-width:44ch; margin-left:auto; margin-top:var(--v2); }
/* Одна колонка, а не две. В двух колонках чтение шло по строкам, и хронология
   рассыпалась в зигзаг: 1780 слева, 1863 справа, 1869 снова слева. Лента времени
   обязана читаться сверху вниз, иначе она не лента. Год — якорь строки. */
.tl{ list-style:none; display:grid; grid-template-columns:1fr;
  border-top:1px solid var(--carbon); }
.tl li{ display:grid; grid-template-columns:2.125rem minmax(9.375rem,11.875rem) minmax(0,1fr);
  gap:clamp(0.75rem,2vw,1.625rem); align-items:baseline;
  padding:var(--v2) 0; border-bottom:1px solid var(--hair-soft); }
.tl .no{ font-size:0.75rem; letter-spacing:.1em; color:var(--mercury); }
.tl b{ font-weight:300; font-size:clamp(1.625rem,3vw,2.625rem); line-height:1;
  letter-spacing:-.01em; }
.tl p{ font-size:0.9375rem; line-height:1.55; color:#4A4540; max-width:62ch; }
@media(max-width:900px){
  .tl{ grid-template-columns:1fr; }
  .tl li{ grid-template-columns:1fr; gap:0.625rem; padding:1.25rem 0; }
  .tl .no{ display:none; }
}

/* ——— 9. Бренды ———
   Слева вводка и вертикальный кадр пошива, справа семь марок строками. */
.brands{ border-top:1px solid var(--hair); padding-top:var(--sec); padding-bottom:var(--sec); }
/* Шапка блока вынесена на всю ширину: в колонке 32% заголовок ломался
   на три строки при любом кегле. Сетка ниже осталась прежней. */
.br-head{ display:grid; grid-template-columns:minmax(0,1fr) minmax(0,44%);
  gap:var(--gap); align-items:end; padding-bottom:var(--v3); }
.br-head .disp{ max-width:16ch; }
.br-head .body{ max-width:44ch; }
@media(max-width:900px){ .br-head{ grid-template-columns:1fr; align-items:start; gap:1.5rem; } }

/* Витрина: семь ячеек по четыре в ряд. Каждая — номер, знак, описание.
   Линейка сверху у каждой ячейки, а не одна общая на список: ряды разной
   длины (4 и 3), общая линейка накрыла бы только первый. */
.marks{ list-style:none; display:grid; grid-template-columns:repeat(4,minmax(0,1fr));
  gap:var(--v3) clamp(1.5rem,3vw,2.5rem); }
.marks li{ border-top:1px solid var(--carbon); padding-top:1.25rem; }
.marks .no{ font-size:0.75rem; letter-spacing:.1em; color:var(--mercury); }
/* Знаки приведены к равной оптической площади, размеры проставлены в разметке
   атрибутами width и height — так браузер резервирует место до загрузки
   и строка не дёргается. Здесь только защита от узкого экрана. */
/* Рамка фиксированной высоты: знаки разной пропорции, без неё описания
   встали бы на разных уровнях и ряд рассыпался. */
.marks .k{ height:5.5rem; margin-top:var(--v1); display:flex; align-items:center; }
/* Размер знака задан атрибутами width и height в разметке. Ставить здесь
   width:auto нельзя: авторский стиль перебивает подсказку из атрибутов,
   и картинка разворачивается в свой настоящий размер — а файлы лежат вдвое
   крупнее показа, под ретину. На широком экране это гасила колонка, а на
   телефоне знаки раздувались вдвое: Windslow шёл 350 px вместо 260. */
.marks .k img{ display:block; max-width:100%; max-height:100%; }
.marks p{ margin-top:0.875rem; font-size:0.9375rem; line-height:1.5; color:#4A4540; }
@media(max-width:900px){ .marks{ grid-template-columns:1fr 1fr; } }
@media(max-width:560px){ .marks{ grid-template-columns:1fr; } }

/* Строка изданий под марками. Семь названий в одну строку — это не логотипы:
   чужие знаки в нашей типографике превращаются в свалку начертаний, а прав на
   них у нас нет. Каждое название ведёт на конкретную статью, чтобы журналист
   мог открыть и проверить. Рябиновым названия не красим: на белом он даёт
   2,46:1 и текстом быть не может, поэтому по наведению — подчёркивание. */
.press{ margin-top:var(--v3); border-top:1px solid var(--carbon); padding-top:1.5rem;
  display:flex; flex-wrap:wrap; align-items:baseline; gap:0.75rem clamp(1.5rem,3vw,2.5rem); }
.press .lab{ margin:0; }
.press .names{ display:flex; flex-wrap:wrap; align-items:baseline;
  gap:0.5rem clamp(1rem,2vw,1.75rem); }
/* Отступ сверху и снизу — не для воздуха, а ради минимальной области нажатия
   24×24 px (WCAG 2.5.8 AA). Без него строка давала 23 px. Выключка по базовой
   линии от этого не съезжает: строка собрана флексом по baseline. */
.press .names a{ font-size:0.9375rem; line-height:1.4; color:var(--carbon);
  text-decoration:none; border-bottom:1px solid transparent; padding-block:0.25rem;
  transition:border-color .25s ease; }
.press .names a:hover{ border-bottom-color:var(--carbon); }
@media(max-width:620px){ .press{ gap:0.75rem; } }

/* ——— 10. Финал ——— см. 10a ниже */

/* ——— 11. Подвал ——— */
footer{ background:var(--onyx); color:#fff; padding-top:var(--v4); padding-bottom:1.875rem; }
footer .cols{ display:grid; grid-template-columns:repeat(auto-fit,minmax(11.25rem,1fr));
  gap:var(--gap); padding-bottom:var(--v3); }
footer .h{ font-size:0.8125rem; font-weight:400; letter-spacing:.09em; text-transform:uppercase;
  color:rgba(255,255,255,.62); margin-bottom:1rem; }
footer a, footer span{ display:block; font-size:0.875rem; line-height:1.5; padding:0.75rem 0;
  color:rgba(255,255,255,.86); text-decoration:none; }   /* зона нажатия 40px */
footer a:hover{ color:var(--ryabina); }          /* рябиновый на ониксе 7,83:1 */
footer .rule .mark{ display:block; color:var(--ryabina); font-size:0; }
footer .rule .mark .lg{ display:block; height:1.25rem; width:auto; }
footer .rule{ border-top:1px solid rgba(255,255,255,.14); padding-top:1.5rem;
  display:flex; justify-content:space-between; gap:1.25rem; flex-wrap:wrap;
  font-size:0.7812rem; letter-spacing:.08em; text-transform:uppercase; color:rgba(255,255,255,.72); }

/* ——— 10a. Финальная панель ———
   Последний экран — тёмная плита: кадр ткацкого цеха уходит под затемнение,
   обращение лежит поверх и без шва переходит в подвал. Так страница
   заканчивается одним блоком, а не «фото, потом чёрный подвал».
   05.09 вечером пробовали сплошную рябиновую плиту вместо кадра (тёмные буквы
   6,64:1, раскладка в две колонки) — собственник вернул кадр: «мощности группы
   блок вернул бы как было с фоткой». Не переоткрывать. Единственное, что
   осталось от того захода, — width:100% у .inner: раньше flex сжимал колонку,
   и текст финала стоял на 321 px вместо общих 120. */
.cta.dark{ position:relative; overflow:hidden; border-top:0; padding:0;
  min-height:clamp(28.75rem,74svh,47.5rem); display:flex; align-items:flex-end; }
.cta.dark > img{ position:absolute; inset:0; width:100%; height:100%;
  object-fit:cover; object-position:50% 50%; filter:brightness(.52) contrast(1.06); }
.cta.dark .veil{ position:absolute; inset:0; z-index:2;
  background:linear-gradient(to top, rgba(15,14,18,.92) 0%, rgba(15,14,18,.70) 38%,
             rgba(15,14,18,.34) 70%, rgba(15,14,18,.30) 100%); }
/* Финал работает по правилам первого экрана — значит, и поле у него такое же:
   текст лежит на кадре во всю ширину, а не на бумаге. Потолок колонки снят,
   отступы берутся из --bleed. */
.cta.dark .inner{ position:relative; z-index:3; color:#fff; width:100%; max-width:none;
  padding-left:var(--bleed); padding-right:var(--bleed);
  padding-top:var(--v4); padding-bottom:var(--v4); }
.cta.dark .lab{ color:#fff; opacity:.72; }
/* Последний экран работает по правилам первого: заголовок крупный, кнопки
   весомые. Это единственное место на странице, где человек может что-то
   сделать, — 14-пиксельные капсулы под заголовком читались как сноска. */
.cta.dark .disp{ max-width:14ch; }
.cta.dark .body{ margin-top:var(--v2); max-width:46ch; color:rgba(255,255,255,.82); }
.cta.dark .row{ display:flex; flex-wrap:wrap; gap:0.875rem; margin-top:2.75rem; }
.cta.dark .btn{ font-size:1rem; padding:1.25rem 1.875rem; }
/* Кнопка «Обсудить проект» — единственное действие на странице, поэтому она
   рябиновая: тёмные буквы на рябиновом 6,64:1. Вторая кнопка остаётся
   контурной, иначе приоритет размывается. */
.cta.dark .fill{ background:var(--ryabina); color:#241F1C; }
.cta.dark .fill:hover{ background:#FF9668; color:#241F1C; }
.cta.dark .ghost{ border-color:rgba(255,255,255,.5); color:#fff; }
.cta.dark .ghost:hover{ background:#fff; color:var(--onyx); }

/* ——— проявление ———
   Ячейки внутри передела появляются друг за другом, а не все разом: мозаика
   собирается. Задержки только там, где элементы повторяются. Кадр при этом
   слегка садится в рамку, текст просто подъезжает — разная механика для
   фотографии и для текста. prefers-reduced-motion гасит всё это целиком. */
.mos .unit > .rv:nth-child(1){ transition-delay:0ms; }
.mos .unit > .rv:nth-child(2){ transition-delay:90ms; }
.mos .unit > .rv:nth-child(3){ transition-delay:180ms; }
.mos .unit > .rv:nth-child(4){ transition-delay:270ms; }
.mos .unit > .rv:nth-child(5){ transition-delay:360ms; }
.nums > .rv:nth-child(2){ transition-delay:80ms; }
.nums > .rv:nth-child(3){ transition-delay:160ms; }
.nums > .rv:nth-child(4){ transition-delay:240ms; }
.steps .step:nth-child(2){ transition-delay:70ms; }
.steps .step:nth-child(3){ transition-delay:140ms; }
.steps .step:nth-child(4){ transition-delay:210ms; }
.steps .step:nth-child(5){ transition-delay:280ms; }
.steps .step:nth-child(6){ transition-delay:350ms; }
.mos .c.rv img, .mos .c.rv video{ transform:scale(1.05);
  transition:transform 1s cubic-bezier(.2,.7,.2,1); }
.mos .c.rv.in img, .mos .c.rv.in video{ transform:none; }
@media (prefers-reduced-motion:reduce){
  .mos .unit > .rv, .nums > .rv, .steps .step{ transition-delay:0ms !important; }
  .mos .c.rv img, .mos .c.rv video{ transform:none !important; }
}

/* ——— Ж · кадры дышат ———
   Внутри рамки снимок на 14 % крупнее рамки и медленно едет, пока рамка идёт
   через экран. Сдвиг маленький, пять с половиной процентов: отдельно его не
   замечаешь — замечаешь, что страница перестала быть плоской.
   Сдвиг задан свойством translate, а не transform: у кадров мозаики transform
   уже занят проявлением (scale 1.05 → 1), и два правила затирали бы друг друга.
   Прогресс даёт CSS там, где браузер знает шкалу прокрутки, иначе app.js.
   Внутри ленты шкала view() бесполезна — сетка стоит на месте, — поэтому там
   дыхание считает app.js от того, где панель на экране. */
@property --d{ syntax:'<number>'; inherits:false; initial-value:0; }
.mos .c img, .mos .c video{ height:114%; top:-7%; translate:0 calc(var(--d) * 1%); }
@keyframes tk-breath{ from{ --d:-5.5; } to{ --d:5.5; } }
@supports (animation-timeline: view()){
  .mos .c img, .mos .c video{
    animation:tk-breath linear both; animation-timeline:view();
    animation-range:cover 0% cover 100%; }
}
@media (prefers-reduced-motion:reduce){
  .mos .c img, .mos .c video{ height:100%; top:0; translate:none; animation:none; }
}

/* ——— Интерлиньяж крупного кегля на телефоне ———
   Плотная выключка .96–.98 рассчитана на крупный кегль. Ниже 620px clamp
   упирается в пол — 32 и 38px, — и на этом размере строки сходятся вплотную:
   выносной элемент «р» в «производство» садится на прописную следующей строки.
   Правило стоит в конце файла осознанно: .hero .disp выше в этом же файле
   имеет ту же специфичность, и перебить его можно только порядком. */
@media(max-width:620px){
  .disp{ line-height:1.1; }
  .hero .disp{ line-height:1.06; }
}

/* ——— Фирменный цвет ———
   На белом рябиновый даёт 2,46:1 — текстом он там быть не может, только
   заливкой. Надзаголовки на тёмных блоках пробовали красить в рябиновый — по
   контрасту проходили, но строка капсами в цвет читалась как предупреждение.
   Откачено 03.09, не переоткрывать. Где цвет живёт с 05.09: логотип в шапке и
   подвале, кнопка «Обсудить проект» (11a), линия истории (Б ниже), выделение
   текста и ховер ссылок подвала. Показаны и не приняты: линейки над цифрами
   и сплошная рябиновая плита финала. */

/* ——— Движение: четыре хода ———
   Приняты 05.09: А и Б. Г (линейка глав) и В (закреплённый первый экран)
   собственник снял в тот же день; Б переделан из года-монумента в линию. Ни один не меняет цвет, шрифт, сетку или тексты — только то,
   как страница отвечает на прокрутку. Механика одна на всё: прогресс 0…1
   в переменной, из неё считается геометрия. Прогресс даёт либо CSS
   scroll-driven animation (Chrome, Яндекс, Edge, Safari 26), либо app.js
   тем же расчётом там, где браузер её не понимает. prefers-reduced-motion
   выключает всё. */
@property --k{ syntax:'<number>'; inherits:false; initial-value:1; }

/* А · Кадр открывается. --k: 0 — кадр в мере колонки, 1 — во всю ширину.
   По умолчанию 1: без движения кадр просто широкий, как и был.
   11.09 ход остался у одной аэросъёмки. Финал снял собственник: фон
   «Контрактного производства» должен стоять во всю ширину сразу.
   Полосу-цитату сняли следом и по другой причине: у неё забрали кадр,
   и обрезка резала уже не фотографию, а текст — при 1440 блок въезжал
   с inset(0 179,9px), а строка начинается ровно на 180. */
.hist .wide{
  --k:1;
  clip-path: inset(0 calc((var(--edge) + var(--pad)) * (1 - var(--k))));
}
@keyframes k-open{ from{ --k:0; } to{ --k:1; } }
@media (prefers-reduced-motion: no-preference){
  @supports (animation-timeline: view()){
    .hist .wide{
      animation: k-open linear both; animation-timeline: view();
      animation-range: entry 0% entry 85%;
    }
  }
}
/* 17.09 · На экранах с пальцем ход А выключен. Анимируется переменная, а не
   готовое свойство: расчёт идёт в главном потоке и каждый кадр заново режет
   обрезку поверх играющего видео 1080p. Отдельно от закрепления первого
   экрана (см. выше) его вклад в дёрганье не мерили — выключен заодно, раскрытие
   на 390 px всего по 20 пикселей с каждой стороны, собственник разницы
   не заметил. clip-path:none перекрывает и запасной расчёт из app.js. */
@media (hover:none) and (pointer:coarse){
  .hist .wide{ clip-path:none; animation:none; }
}

/* Б · Линия рисуется. Первая версия — год-монумент: огромная цифра липла
   слева и перескакивала на следующую дату. Собственник 05.09: перескок
   заметнее всего на экране и ничем не мотивирован — человек листает плавно,
   число прыгает. Из трёх замен (барабан, линия, счётчик) выбрана линия:
   семь дат остаются семью датами, ничего не липнет и не считает. Слева
   вертикальная линия заполняется по мере прокрутки (--fill пишет app.js),
   пройденные даты тёмные, будущие светлые. Год в строке 30–44px (было до 56 —
   ушло вместе с общей шкалой 05.09), он единственный акцент блока. */
.tl{ position:relative; border-top:0; padding-left:clamp(1.75rem,3vw,2.75rem); }
.tl::before{ content:""; position:absolute; left:0; top:0; bottom:0; width:1px; background:var(--hair); }
/* Заливка линии и пройденные точки — рябиновые: единственный элемент, который
   рисуется прокруткой, и единственное место в середине страницы, где фирменный
   цвет уместен. Линия декоративная, требований к контрасту нет; 2 px, чтобы
   на белом читалась. */
.tl::after{ content:""; position:absolute; left:-0.5px; top:0; width:2px; height:var(--fill,0px); background:var(--ryabina); }
.tl li{ position:relative; grid-template-columns:2.125rem minmax(9.375rem,13.75rem) minmax(0,1fr); padding:2.125rem 0;
  transition:opacity 300ms cubic-bezier(0,0,.2,1); }
.tl li b{ font-size:clamp(1.875rem,3.1vw,2.75rem); }
.tl li::before{ content:""; position:absolute; left:calc(-1 * clamp(1.75rem,3vw,2.75rem) - 0.1875rem); top:calc(2.125rem + .35em);
  width:0.4375rem; height:0.4375rem; border-radius:50%; background:var(--paper); border:1px solid var(--hair); box-sizing:border-box;
  transition:background-color 300ms cubic-bezier(0,0,.2,1), border-color 300ms cubic-bezier(0,0,.2,1); }
.tl li.future{ opacity:.42; }
.tl li.past::before{ background:var(--ryabina); border-color:var(--ryabina); }
@media (max-width:900px){
  .tl{ padding-left:1.375rem; }
  /* правило выше стоит позже общего мобильного и перебивало его сетку */
  .tl li{ grid-template-columns:1fr; gap:0.625rem; padding:1.375rem 0; }
  .tl li::before{ left:-1.5625rem; top:calc(1.375rem + .35em); }
}
@media (prefers-reduced-motion: reduce){
  .tl li, .tl li::before{ transition:none; }
  .tl li.future{ opacity:1; }
}

/* В · Титул уходит в страницу — СНЯТ 05.09. Первый экран закреплялся, кадр
   сжимался в колонку. Сначала конфликтовала шапка (белая полоса сверху),
   после правки собственник всё равно попросил убрать: «первое видео — мы не
   убрали анимацию». Первый экран статичный, как был. Не переоткрывать. */

