/* Список — второй вид тех же работ, для Telegram и вообще для чтения.
   Общий чёрный фон и Inter из base.css; своих цветов не заводит.

   Отличие от сцены принципиальное: тут страница действительно прокручивается.
   В base.css у html/body стоит overflow: hidden — прокрутка страницы там
   отдана зуму сцены. Класс list-mode на body возвращает её обратно, ровно
   на время, пока список открыт. */

/* Прокручивается сам .list — фиксированный слой поверх сцены; body и html
   остаются нескроллящимися, как в base.css. Так сцена под списком не
   уезжает и возвращается в той же точке, где её оставили. */

.list {
  position: fixed;
  inset: 0;
  z-index: 40;                   /* над сценой, под лайтбоксом и чатом */
  overflow-y: auto;
  overflow-x: hidden;
  background: var(--bg);
  -webkit-overflow-scrolling: touch;
  /* Внутри Telegram потягивание вниз на самом верху закрывает WebApp.
     Свайп мы не отменяем — это нативный жест оболочки, из веба им не
     управляют; но цепочку прокрутки обрываем, чтобы жест, начатый внутри
     ленты или списка, не всплывал наружу лишний раз. */
  overscroll-behavior-y: contain;
  /* Снизу — место под закреплённую строку контактов: она лежит поверх
     списка, и без запаса последний заказчик уезжал бы ей под низ. */
  padding: calc(var(--pad) + env(safe-area-inset-top))
           var(--pad)
           calc(var(--pad) + var(--contacts-clear));
  /* Список читают, а не таскают: запрет выделения из base.css тут снимаем —
     адрес почты и название работодателя должны копироваться. */
  user-select: text;
  -webkit-user-select: text;
}

/* ── шапка: имя автора и чем он занимается ──────────────────────────── */

/* Нижнего отступа нет: под именем сразу идёт заголовок услуг, и
   собственный отступ шапки складывался с отступом .list-services
   в провал на пол-экрана — имя повисало отдельно от всего, что под
   ним. Воздух между ними задаёт только .list-services. */
.list-head {
  max-width: 42rem;
  margin: 0 auto;
  padding: clamp(24px, 8vh, 72px) 0 0;
}

.list-name {
  /* Нижнего отступа нет: под именем сразу идёт профессия (.list-type),
     и отступ в 1.1em отрывал её от имени — она повисала посередине
     между заголовком и блоком описания, не принадлежа ни тому, ни
     другому. Воздух под этой парой держит margin-top у .list-lines. */
  margin: 0;
  font-size: var(--fs-1);
  font-weight: 400;
  letter-spacing: -.02em;
  line-height: 1.05;
}

/* ── строки описания ─────────────────────────────────────────────────
   Разметка общая с ярлыками сцены (.cyc из scene.css отвечает за саму
   анимацию смены фразы), здесь только кегль и раскладка строки. */

/* Зазор между блоками («Период», «Что делал», «Результат») втрое
   больше внутреннего — того, что отделяет подпись от её текста
   (.list-line, .15em). Был .5em, то есть всего втрое, и на глаз три
   блока сливались в один сплошной кусок: расстояния между «Период» и
   его датой и между датой и следующей подписью различались слишком
   мало, чтобы глаз успевал их сгруппировать. Пропорция тут важнее
   абсолютной величины — она и делает блок блоком. */
.list-lines {
  display: flex;
  flex-direction: column;
  gap: 1.35em;
  /* Воздух между строкой «кто это» и блоком описания. Он и разводит
     два серых: тип компании прижат к заголовку, подписи начинаются
     заметно ниже. */
  margin-top: 1.35em;
  color: var(--fg-dim);
  font-size: var(--fs-4);
  line-height: 1.45;
}

/* Строка описания: подпись группы сверху, содержимое под ней.
 *
 *  Раньше тут стоял flex-wrap: wrap, и подпись с пунктами делили одну
 *  строку — перенос случался, только когда не влезало. Короткий список
 *  («A/B Testing, CustDev, CJM») оставался справа от заголовка, длинный
 *  уезжал вниз, и колонка выглядела собранной наугад. Раскладка не должна
 *  зависеть от длины текста: подпись всегда сверху. */
.list-line {
  display: flex;
  flex-direction: column;
  gap: .25em;
}

/* Подпись группы — тише содержимого: она называет раздел, а читают
   то, что под ней.
 *
 *  Цветов в блоке ровно два: подпись серая, содержимое белое. Раньше
 *  подпись стояла на --fg-mute (#4e4c48), и получалась третья ступень
 *  между серым и фоном: у работодателя «Период» уходил в почти-фон,
 *  а текст под ним был серым — то есть строка не была белой нигде и
 *  блок проваливался целиком. Две ступени вместо трёх дают ту же
 *  иерархию, но блок читается. */
.list-line-label {
  color: var(--fg-dim);
}

/* Статичная строка читается наравне с перечислениями: это такой же факт,
   а не сноска под ним. */
.list-line-text { color: var(--fg); }

/* Строка «кто это» под заголовком: профессия у автора, род
   деятельности у заказчика.
 *
 *  Ключевое здесь — отступы, а не цвет. Раньше эта строка стояла на
 *  равном расстоянии от заголовка сверху и от подписи «Период» снизу,
 *  и, будучи с этой подписью одного цвета, читалась как её часть: два
 *  серых подряд слипались в один кусок. Теперь она прижата к
 *  заголовку и отделена воздухом от блока описания — глаз группирует
 *  её с именем, а не с тем, что ниже.
 *
 *  Тире тут стояло в промежуточной версии («AsterEnglish — школа...»),
 *  прямо в строке заголовка. На широком экране читалось хорошо, но на
 *  телефоне заголовок переносится, и приписка отрывалась от имени на
 *  вторую строку: выглядело сломанным. Отдельная строка от ширины
 *  экрана не зависит. */
.list-type {
  margin-top: .2em;
  color: var(--fg-dim);
  font-size: var(--fs-4);
  line-height: 1.35;
}


/* Исключение — чем занимается компания. У заказчика ПЕРВАЯ статичная
   строка — это род его деятельности («Архитектурное бюро»), фон для
   главного: что для него сделано. Белым она спорила с перечислением за
   внимание, хотя читают строку ниже. Приглушаем до серого — порядок
   чтения восстанавливается: имя, чем занимаются, что сделано.
 *
 *  Только первая: у строк с подписью («Период», «Результат») содержимое
 *  обязано остаться белым, иначе серая подпись и серый текст сливаются
 *  в один тон и блок нечем читать. Отсюда :first-child, а не общее
 *  правило на все .list-line-text внутри заказчика. */
/* Правила на первую статичную строку заказчика больше нет: род
   деятельности уехал в заголовок (.list-role), и внутри блока остались
   только строки с подписью — серая подпись, белое содержимое. */

/* Перечисление того, чем занимался: в сцене крутится по одному пункту,
   здесь напечатано целиком через запятую. Белым — это главное, что
   читают в строке, и оно должно весить столько же, сколько соседние
   перечисления, а не выглядеть примечанием. */
.list-line-items {
  color: var(--fg);
  min-width: 0;
}

/* ── работодатели ────────────────────────────────────────────────────── */

/* Подпись над перечнем работодателей.
 *
 *  Без неё блок начинался сразу после строк «о себе» и читался как их
 *  продолжение: первое имя в списке зритель принимал за ещё одну строку
 *  про автора. Кегль — как у строк описания, а не как у заголовка:
 *  это подпись к списку, а не второй заголовок страницы. */
/* Заголовок второй половины страницы. Кегль — тот же, что у
   «Контент-маркетинга» (.services-title): это два равных раздела
   визитки, что умею и с кем работал, и разный кегль ставил бы один
   выше другого. Имя крупнее их обоих и остаётся единственным
   заголовком страницы.

   Мелкой серой строкой он был, пока стоял вплотную к списку и лишь
   подписывал его. Нижний отступ и сейчас мал намеренно: заголовок
   принадлежит списку под собой, весь воздух — сверху. */
.list-items-cap {
  max-width: 42rem;
  margin: clamp(72px, 16vh, 132px) auto .55em;
  color: var(--fg);
  font-size: var(--fs-2);
  font-weight: 400;
  letter-spacing: -.02em;
  line-height: 1.1;
}

.list-items {
  max-width: 42rem;
  margin: 0 auto;
}

/* Разделителей между заказчиками нет: линия через весь экран режет список
   на карточки и спорит с чёрной пустотой, на которой всё держится. Границу
   держит воздух — отступ между блоками больше, чем между строками внутри
   блока, и группировка читается сама. */
/* Колонка, а не блок: кнопке «Работы» внизу нужен align-self, чтобы
   быть шириной со своё слово, а не во всю колонку текста. */
.list-item {
  display: flex;
  flex-direction: column;
  padding: clamp(22px, 5.5vw, 34px) 0;
}

/* Заголовок раскрытием не управляет — он просто заголовок. Кнопка
   «Работы» стоит внизу карточки (.list-more). */
.list-item-head {
  display: flex;
  align-items: center;
  gap: 1em;
  width: 100%;
  margin-bottom: .55em;
}

.list-title {
  font-size: var(--fs-3);
  font-weight: 400;
  letter-spacing: -.01em;
  /* Название заказчика не ломаем по словам — «Viner / Design / Group»
     читается как три слова, а не как имя (то же правило в сцене).
     Род деятельности стоит отдельной строкой ниже (.list-type), так
     что обрезать многоточием тут нечего. */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Кнопка раскрытия — внизу карточки, после описания, и названа словом.
   Почему не заголовок с шевроном, как было, — в list.js.

   Белая и подчёркнутая: подчёркивание — единственный на этой странице
   знак нажимаемого, и здесь он нужен буквально, потому что кроме него
   у кнопки нет ни фона, ни рамки. Выравнивание по левому краю колонки,
   а не растяжка на всю ширину: это ссылка размером со своё слово,
   а не полоса.

   Ширина по содержимому (align-self), но высота в палец: цель для
   тапа больше, чем видимый текст, и это правильно — промахнуться
   по строке в 15px иначе слишком легко. */
.list-more {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  gap: .5em;
  margin-top: 1.1em;
  padding: 0;
  min-height: 44px;
  background: none;
  border: 0;
  color: var(--fg);
  font: inherit;
  font-size: var(--fs-4);
  line-height: 1.3;
  text-align: left;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

/* Подчёркивание — под текстом, а не под всей кнопкой: иначе линия
   тянулась бы и под стрелку, и кнопка читалась бы как ссылка со
   значком внутри. */
.list-more-label {
  text-decoration: underline;
  text-underline-offset: .22em;
  text-decoration-thickness: 1px;
}

.list-chev {
  flex: none;
  width: 9px;
  height: 9px;
  border-right: 1.5px solid var(--fg);
  border-bottom: 1.5px solid var(--fg);
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform .3s cubic-bezier(.4, 0, .2, 1);
}

.list-item.is-open .list-chev {
  transform: rotate(-135deg) translate(-3px, -3px);
}

/* ── гармошка ─────────────────────────────────────────────────────────
   Высоту анимируем через max-height: height: auto не интерполируется,
   а считать точный height джаваскриптом значит пересчитывать его на каждый
   resize и на каждую догрузившуюся картинку. Значение — заведомо больше
   реальной высоты ленты; скорость раскрытия от этого не зависит, потому
   что переход идёт по фактической высоте содержимого до предела. */
.list-panel {
  max-height: 0;
  overflow: hidden;
  opacity: 0;
  transition: max-height .42s cubic-bezier(.4, 0, .2, 1), opacity .3s ease;
}

.list-item.is-open .list-panel {
  /* Больше, чем реальная высота полосы (BAND_H ≤ 520 + отступы): предел
     только ограничивает переход, а не задаёт размер. Занижение обрезало бы
     ленту, поэтому запас взят с избытком. */
  max-height: 680px;
  opacity: 1;
}

/* ── лента работ ──────────────────────────────────────────────────────
   Не полка с превью, а кусок пространства: карточки висят на разной
   глубине, разного размера и едут с разной скоростью (раскладка и
   параллакс — в buildStrip, js/list.js). Отсюда высокая полоса: глубине
   нужно место по вертикали, иначе разница планов не читается.

   Прокрутка родная, overflow-x: жест внутри скролл-контейнера Telegram
   не перехватывает — он отбирает только потягивание от края экрана.
   Самописная карусель тут была бы хуже во всём. */
.list-strip {
  position: relative;
  overflow-x: auto;
  overflow-y: hidden;
  /* Полоса тянется во всю ширину экрана, а не в колонку текста: работы
     должны уезжать за край, иначе пространство упирается в поля. */
  margin: 0 calc(var(--pad) * -1);
  /* Сверху почти без отступа: полоса начинается сразу под описанием, и
     пустая чёрная лента между текстом и работами читалась бы как разрыв
     блока, а не как воздух. */
  padding: 4px var(--pad) 8px;
  /* Жест внутри ленты не должен доводить до вертикальной прокрутки
     страницы и тем более до жеста закрытия WebApp. */
  overscroll-behavior-x: contain;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, .22) transparent;
}

.list-strip::-webkit-scrollbar { height: 3px; }
.list-strip::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, .22);
  border-radius: 2px;
}

/* Трек задаёт скроллируемую ширину; карточки внутри стоят absolute,
   потому что каждая на своей глубине и высоте — потоком это не выразить. */
.list-track {
  position: relative;
}

.list-card {
  position: absolute;
  top: 0;
  left: 0;
  padding: 0;
  border: 0;
  border-radius: 3px;
  overflow: hidden;
  background: #0d0d0d;           /* пока превью не догрузилось */
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: filter .2s ease;
  /* Тень отделяет карточку от соседки там, где они рядом: без неё две
     работы на чёрном сливаются в одну рваную картинку. */
  box-shadow: 0 6px 24px rgba(0, 0, 0, .5);
}

/* will-change здесь НЕ ставим. Он был нужен параллаксу, который переписывал
   transform на каждый кадр прокрутки; теперь карточки стоят неподвижно, и
   постоянный хинт держал бы GPU-текстуру у каждой из полусотни (набор
   выложен трижды) — ровно та беда, из-за которой мигал текст. */

.list-card:active { filter: brightness(.75); }

.list-card img,
.list-card-video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Видео лежит поверх постера и проявляется, когда пошло: подмена картинки
   на первый кадр видео иначе читается как моргание. */
.list-card-video {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity .3s ease;
}

.list-card.has-video .list-card-video { opacity: 1; }

/* Серия: уголок объясняет, что за карточкой не один кадр. Числа больше
   нет — превью само перелистывает слайды, и счётчик дублировал бы то,
   что зритель и так видит. */
.list-card.is-post::after {
  content: '';
  position: absolute;
  right: 7px;
  bottom: 7px;
  width: 14px;
  height: 14px;
  border: 1.5px solid rgba(255, 255, 255, .85);
  border-radius: 2px;
  box-shadow: -4px -4px 0 -1.5px rgba(0, 0, 0, .5),
              -4px -4px 0 0 rgba(255, 255, 255, .55);
  pointer-events: none;
}

/* Подвала со своими контактами у списка больше нет: строка одна на все
   три вида и закреплена в углу (.contacts в base.css). Место под неё
   держит нижний padding .list — см. --contacts-clear выше. */

/* Правило браузера [hidden] { display: none } слабее любого класса, а у
   #chat стоит display: flex — без этой строки скрытая кнопка чата
   продолжала бы висеть поверх списка. Селектор повторяет id, иначе
   не перебить #chat из chat.css. */
#chat[hidden] { display: none; }

/* ── верхняя панель ───────────────────────────────────────────────────
   Две вкладки: визитка и портфолио. Стоит наверху, потому что низ занят
   чатом и контактами, а третий элемент там отвоёвывал бы пиксели у сцены.

   Подсказки под панелью больше нет. Она объясняла, что работы лежат на
   доске, — но объясняла это, пока «Доской» было одним из трёх пунктов
   и терялось между ними. Слово «Портфолио» само говорит, что за ним.

   Живёт снаружи #stage: инверсия mix-blend-mode ей не нужна, а внутри она
   пряталась бы вместе со сценой при переходе в список. */
/* Градиент под панелью: список прокручивается под ней, и заголовок
   заказчика иначе читается сквозь кнопки. Не сплошная плашка — она
   отрезала бы панель от чёрного фона, на котором всё держится. */
.topbar::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom,
    rgba(0, 0, 0, .92) 0%,
    rgba(0, 0, 0, .72) 55%,
    rgba(0, 0, 0, 0) 100%);
  pointer-events: none;
}

.topbar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 60;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: calc(10px + env(safe-area-inset-top)) var(--pad) 22px;
  pointer-events: none;          /* фон панели кликов не ловит */
}

.topbar-nav {
  position: relative;            /* над градиентом ::before */
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 4px;
  border-radius: 999px;
  background: rgba(20, 20, 20, .78);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  pointer-events: auto;
  max-width: 100%;
  overflow-x: auto;
  scrollbar-width: none;
}

.topbar-nav::-webkit-scrollbar { display: none; }

.topbar-btn {
  flex: none;
  padding: 8px 15px;
  border: 0;
  border-radius: 999px;
  background: none;
  color: var(--fg-dim);
  font-size: 13px;
  line-height: 1.2;
  white-space: nowrap;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: color .2s ease, background-color .2s ease;
}

.topbar-btn:hover { color: var(--fg); }

/* Активный вид залит, а не подчёркнут: заливка читается на чёрном
   с любого расстояния, тонкая линия под текстом — нет. */
.topbar-btn.is-active {
  background: rgba(255, 255, 255, .12);
  color: var(--fg);
}

/* Список начинается ниже панели, иначе имя автора уезжает под неё. */
body.list-mode .list {
  padding-top: calc(var(--pad) + env(safe-area-inset-top) + 52px);
}

/* ── услуги: секция визитки ───────────────────────────────────────────
   Были отдельным экраном, третьей вкладкой рядом со списком и доской.
   Делением это оказалось ложным: и список, и услуги отвечают на один
   вопрос — кто это и что он может, — и разносить их по вкладкам значило
   заставлять зрителя искать вторую половину ответа. Теперь это секция
   в конце визитки: сначала что сделано и для кого, потом что заказать.

   Своего фона и прокрутки у неё поэтому нет — она едет вместе со
   страницей, как всё остальное на ней.

   Отделена воздухом, а не линией: разделителей в списке нет нигде
   (см. .list-item), и линия здесь резала бы чёрный лист, на котором
   всё держится. Отступ до секции заметно больше, чем между
   работодателями, — этого хватает, чтобы блок читался как отдельный
   разговор. */
/* Услуги стоят сразу под именем, поэтому отступ сверху небольшой:
   «Контент-маркетинг» — это ответ на имя, а не новый раздел. Разделом
   ниже становится «Работал с», и вот перед ним воздуха много. */
.list-services {
  display: block;
  max-width: 42rem;
  margin: clamp(20px, 4.5vh, 34px) auto 0;
}

.services-head {
  margin: 0;
  padding: 0 0 clamp(20px, 5vh, 40px);
}

/* Кегль ниже, чем был у отдельного экрана: там это был заголовок
   страницы, здесь — заголовок секции, и вровень с именем автора он
   спорил бы с ним за первое место на странице. */
.services-title {
  margin: 0;
  font-size: var(--fs-2);
  font-weight: 400;
  letter-spacing: -.02em;
  line-height: 1.1;
}

/* Одно предложение под заголовком: что именно человек получает.
   Крупнее пунктов ниже и белым — это и есть услуга, а список под ним
   лишь её состав. */
.services-summary {
  margin: .8em 0 0;
  max-width: 34rem;
  color: var(--fg);
  font-size: var(--fs-4);
  line-height: 1.5;
}

/* Состав услуги — плашками, а не строками с заголовками.
 *
 *  Здесь стояли три группы («Маркетинг и стратегия», «Продакшн»,
 *  «Технологические решения») со своими подзаголовками, и заголовок
 *  группы неизбежно читался как отдельная услуга — три предложения
 *  вместо одного. У плашки ранга нет: набор читается как состав того,
 *  что названо сверху, а не как выбор из трёх вариантов.
 *
 *  Обёртка — ul с убранными маркерами: перечень остаётся перечнем для
 *  скринридера, но буллеты на чёрном читались бы как техдокументация. */
/* Подпись над плашками: «Мне можно доверить». Пункты стоят в
   винительном падеже, и подпись с каждым из них складывается во
   фразу — перечень отвечает заказчику, а не перечисляет умения
   в воздух. */
/* Язык — тише описания, отдельным абзацем. Это справка, а не часть
   предложения о том, чем человек занимается. */
.services-langs {
  margin: 1.1em 0 0;
  color: var(--fg-dim);
  font-size: var(--fs-4);
  line-height: 1.5;
}

.services-skills-label {
  max-width: 42rem;
  margin: clamp(20px, 5vh, 36px) auto .9em;
  color: var(--fg);
  font-size: var(--fs-4);
  line-height: 1.4;
}

.services-skills {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  max-width: 42rem;
  margin: 0 auto;
  padding: 0;
  list-style: none;
}

.services-skill {
  /* Плашки левитируют и их можно таскать (js/skillFloat.js). Скрипт
     замеряет места, которые им назначил flex-wrap, и переводит плашки
     в absolute — без JS и при prefers-reduced-motion перечень остаётся
     обычным потоком, просто неподвижным.

     touch-action: none обязателен для перетаскивания пальцем: иначе
     браузер считает жест прокруткой страницы и забирает его себе,
     не доводя pointermove до нас.

     will-change не ставим: плашек десяток, и постоянный слой на каждую
     обходится дороже, чем перерисовка того, что и так композитится
     через translate3d. */
  padding: .5em .85em;
  touch-action: none;
  cursor: grab;
  border: 1px solid var(--fg-mute);
  border-radius: 999px;
  color: var(--fg-dim);
  font-size: var(--fs-4);
  line-height: 1.2;
  white-space: nowrap;
}

/* Дрейф плашек скрипт не запускает при prefers-reduced-motion (см.
   services.js), но смещение могло остаться от прошлого показа — гасим
   и стилем, чтобы перечень наверняка стоял ровно. */
/* Плашка в руке: приподнимаем над остальными и убираем задержку —
   она обязана идти за пальцем кадр в кадр. */
.services-skill.is-held {
  cursor: grabbing;
  z-index: 2;
  border-color: var(--fg-dim);
  color: var(--fg);
}

@media (prefers-reduced-motion: reduce) {
  /* Левитацию скрипт при этой настройке не запускает вовсе (см.
     services.js), но плашки остаются обычным потоком — снимаем и
     курсор-хватку, чтобы не обещать взаимодействия, которого нет. */
  .services-skill { transform: none !important; cursor: default; }
}

/* Приписка про отдельный пункт — тише плашек: это ответ на вопрос,
   а не часть витрины. */
.services-aside {
  max-width: 42rem;
  margin: clamp(28px, 7vh, 52px) auto 0;
  color: var(--fg-dim);
  font-size: var(--fs-4);
  line-height: 1.5;
}

/* Подвала у услуг нет: строка «↓ Объём, сроки, стоимость» убрана вместе
   со своими правилами. Контакты закреплены в углу и видны с любого места
   страницы — указывать на них стрелкой значило подписывать очевидное. */
