/* ==========================================================================
   OGANOV — BEYOND FORM
   main.css — единственный источник истины по стилям сайта.

   Порядок слоёв фиксирован: специфичность решается слоем, а не весом
   селектора. Никаких !important (кроме reduced-motion и одной утилиты),
   никаких инлайновых стилей в разметке, кроме динамических --переменных,
   приходящих из data-слоя.

   Слои:
     reset       — нормализация
     tokens      — дизайн-токены (цвет, типографика, ритм, motion, z-index)
     base        — типографика документа
     layout      — сетка, секции, контейнеры
     components  — компоненты интерфейса
     utilities   — короткие модификаторы, всегда последними
   ========================================================================== */

@layer reset, tokens, base, layout, components, utilities;

/* ==========================================================================
   RESET
   ========================================================================== */
@layer reset {
  *,
  *::before,
  *::after { box-sizing: border-box; }

  html { -webkit-text-size-adjust: 100%; }

  body,
  h1, h2, h3, h4, h5, h6,
  p, figure, blockquote, dl, dd, ul, ol { margin: 0; }

  ul[class], ol[class] { list-style: none; padding: 0; }

  img, picture, svg, video { display: block; max-width: 100%; }
  img { height: auto; }

  input, button, textarea, select { font: inherit; color: inherit; }

  button { background: none; border: 0; padding: 0; cursor: pointer; }

  a { color: inherit; }

  :where(h1, h2, h3, h4) { text-wrap: balance; }
  :where(p, li) { text-wrap: pretty; }
}

/* ==========================================================================
   TOKENS
   ========================================================================== */
@layer tokens {
  :root {
    /* ---- Цвет -----------------------------------------------------------
       Правило по бронзе: #CD7F32 на светлом фоне даёт контраст 2.8:1, поэтому
       НИКОГДА не используется для текста на светлом — только для линий, рамок
       и hover-акцентов. Текст на светлом — --c-bronze-ink (5.8:1).
       На чёрном фоне #CD7F32 даёт 6.7:1 и допустим для текста. */
    --c-bg: #f4f4f5;
    --c-surface: #ffffff;
    --c-slab: #e5e7eb;

    --c-ink: #000000;
    --c-ink-2: #1a1c1c;
    --c-ink-muted: #4c4546;   /* 9.0:1 на --c-bg */
    --c-ink-faint: #5f585a;   /* 7.2:1 на --c-bg — минимум для мелкого mono */

    --c-hairline: #d2d2d4;
    --c-hairline-strong: #9a9a9d;
    --c-tab-idle: #87878b;    /* 3.6:1 на белом — минимум для крупного текста */

    --c-bronze: #cd7f32;      /* только линии / рамки / текст на тёмном */
    --c-bronze-ink: #8e4e00;  /* текст на светлом, 5.8:1 */
    --c-accent: var(--c-bronze);
    --c-action-muted: var(--c-ink-faint);

    --c-inverse-bg: #000000;
    /* Подвал чуть светлее чёрного — отделяется от листа без линии */
    --c-footer-bg: #141414;
    /* Лист страницы работы: чуть светлее чистого чёрного */
    --c-page-dark: #0B0B0B;
    --c-inverse-ink: #ffffff;
    --c-inverse-muted: #a0a0a0; /* 7.0:1 на чёрном */
    --c-inverse-faint: #8a8a8a; /* 5.3:1 на чёрном */

    /* Контур фокуса берёт текстовую бронзу: светлая #cd7f32 давала на светлом
       фоне 2.9:1 при норме 3:1. Внутри тёмных секций и на странице работы
       токен уже подменяется на светлую бронзу, там контраст 6.3:1. */
    --c-focus: var(--c-bronze-ink);
    --c-blend-reference: #ffffff;

    /* ---- Гарнитуры ------------------------------------------------------ */
    --f-display: 'Bodoni Moda', 'Playfair Display', Georgia, 'Times New Roman', serif;
    --f-system: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    --f-mono: 'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace;

    /* ---- Шкала кегля (fluid 390 → 1920) --------------------------------- */
    --t-hero: clamp(3.25rem, 0.5rem + 11.3vw, 10.5rem);
    --t-h2: clamp(1.87rem, 0.616rem + 5.192vw, 5.28rem);
    --t-h2-sm: clamp(1.875rem, 1.2rem + 2.8vw, 3.75rem);
    --t-h3: clamp(1.375rem, 1.05rem + 1.35vw, 2.125rem);
    --t-h4: clamp(1.125rem, 0.95rem + 0.75vw, 1.5rem);
    --t-quote: clamp(1.75rem, 0.6rem + 4.7vw, 4.5rem);
    --t-body-lg: clamp(1rem, 0.93rem + 0.3vw, 1.125rem);
    --t-body: 1rem;
    --t-small: 0.875rem;
    --t-mono: 0.75rem;
    --t-mono-sm: 0.6875rem;
    --t-mono-xs: 0.625rem;
    --t-hero-lede: clamp(0.625rem, 0.495rem + 0.4vw, 0.875rem);

    --lh-snug: 1.1;
    --lh-normal: 1.45;

    --ls-display: -0.02em;
    --ls-mono: 0.1em;
    --ls-mono-wide: 0.18em;
    --ls-action: 0.06em;

    /* ---- Ритм ------------------------------------------------------------
       --pad-x — единственный горизонтальный отступ страницы.
       --block — вертикальный шаг между секциями (DESIGN.md: block-gap 160). */
    --pad-x: clamp(1.25rem, 5vw, 6rem);
    /* Шапка живёт по своему отступу — в референсе это px-6 py-8 на всех
       ширинах, поэтому логотип стоит у самого края, а не по колонке. */
    --pad-nav: 1.5rem;
    --nav-hide-distance: 6rem;
    /* Hero frame ends between BEYOND and FORM. It is tied to the same rhythm
       tokens as the content block, so the split survives mobile, desktop and xl
       viewport heights instead of being guessed as a fixed percentage. */
    --hero-content-gap: clamp(3rem, 8vw, 5rem);
    --hero-actions-block: 6.75rem;
    --hero-lede-block: 3.4rem;
    --hero-content-drop: 2.5rem;
    --hero-frame-drop: 1.25rem;
    /* Нижний отступ hero — общий для рамки и для самого блока: на телефоне
       он меньше, поэтому BEYOND FORM стоит ниже. */
    --hero-pad-b: calc(1rem - 15px);
    /* На телефоне заголовок стоит чуть ниже своей строки */
    --hero-title-drop: 5px;
    --hero-frame: calc(
      100svh
      - var(--hero-pad-b)
      - var(--hero-actions-block)
      - var(--hero-content-gap)
      - var(--hero-lede-block)
      - clamp(1.5rem, 3vw, 2.5rem)
      - var(--hero-title-size)
      + var(--hero-frame-drop)
    );
    --work-page-h: 87svh;
    /* Листаемый кадр выше остальных: по нему ведут пальцем вдоль работы,
       и запас высоты даёт крупнее деталь в окне. Держать в паре с
       PHONE_PAGE_VH в inc/config.php — из неё считается sizes. */
    --work-paged-h: 96svh;
    /* Шаг между работами в мобильной ленте */
    --work-gap: 220px;
    /* Телефон: кадр работы выходит за обе границы страницы */
    --work-bleed: calc(var(--pad-x) * -1);
    /* Расстояние от названия работы до «Подробнее». Одно на ленту и на
       страницу работы, чтобы группа выглядела одинаково. */
    --work-more-gap: 0.75rem;
    /* Отступ сверху у блока с названием работы. Живёт на самой подписи,
       поэтому одинаков и под полосой прокрутки, и под кадром без неё. */
    --work-cap-gap: 30px;
    --hero-media-opacity: 0.92;
    /* Мобильный кадр прижат к правому верхнему углу: левая часть снимка
       второстепенна, её и срезает cover. */
    --hero-media-x: 100%;
    --hero-media-y: 0%;
    /* Кегль BEYOND FORM участвует и в расчёте высоты рамки: строки должны
       расходиться ровно по её нижней границе. */
    --hero-title-size: calc(var(--t-hero) * 1.38);
    /* Насколько слой может уехать в своей рамке. Ровно на эту величину он
       выше рамки сверху и снизу, иначе сдвиг открыл бы край. У hero ход
       заметнее, у карточек — почти незаметный.

       Единицы абсолютные, не проценты: у карточки высота выведена из
       aspect-ratio, и процентные top/bottom в такой коробке не разрешаются —
       кадр схлопывался в ноль. Та же ловушка, что с height: 100%. */
    --parallax-range-hero: 0rem;
    --block: clamp(4.5rem, 9vw, 8rem);
    --block-lg: clamp(6rem, 13vw, 12rem);
    --gutter: clamp(1.5rem, 4vw, 6rem);
    --stagger: clamp(2rem, 7vw, 8rem);
    --measure: 34rem;

    /* ---- Границы ---------------------------------------------------------- */
    --bw-hair: 1px;
    --bw-rule: 2px;

    /* ---- Слои -------------------------------------------------------------- */
    --z-media: 1;
    --z-raised: 2;
    --z-overlay: 10;
    --z-nav: 100;
    --z-menu: 200;
    --z-skip: 300;

    /* ---- Движение ----------------------------------------------------------- */
    --dur-fast: 180ms;
    --dur: 380ms;
    /* Проявление снимка. Сейчас нарочно медленное — для проверки эффекта. */
    --dur-reveal: 1200ms;
    --dur-slow: 700ms;
    --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  }

  /* Параллакс включается только там, где движение уместно и есть указатель:
     на сенсорных экранах инерционная прокрутка и так даёт смещение. */
  @media (min-width: 64rem) {
    :root {
      --t-body-lg: 17px;
      --work-cap-gap: 2rem;
    }
  }

  /* Запас под сдвиг hero добавляется только на десктопе: на телефоне он
     увеличивал кадр и съедал края скульптуры при cover. */
  @media (prefers-reduced-motion: no-preference) and (min-width: 64rem) {
    :root { --parallax-range-hero: 5rem; }
  }

  @media (prefers-reduced-motion: reduce) {
    :root { --dur-fast: 1ms; --dur: 1ms; --dur-slow: 1ms; --dur-reveal: 1ms; }
    /* !important здесь обязателен: перекрываем анимации любого происхождения */
    *, *::before, *::after {
      animation-duration: 1ms !important;
      animation-iteration-count: 1 !important;
      transition-duration: 1ms !important;
      scroll-behavior: auto !important;
    }
  }
}

/* ==========================================================================
   BASE
   ========================================================================== */
@layer base {
  html {
    scroll-behavior: smooth;
    scroll-padding-top: 6rem;
  }

  body {
    margin: 0;
    background-color: var(--c-bg);
    color: var(--c-ink-2);
    font-family: var(--f-system);
    font-size: var(--t-body);
    line-height: var(--lh-normal);
    font-weight: 400;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
  }

  ::selection { background-color: var(--c-bronze); color: #fff; }

  :focus-visible {
    outline: var(--bw-hair) solid var(--c-focus);
    outline-offset: 3px;
  }

  h1, h2, h3, h4 {
    font-family: var(--f-system);
    font-weight: 400;
    letter-spacing: var(--ls-display);
    line-height: var(--lh-snug);
  }

  strong, b { font-weight: 600; }
  a { text-underline-offset: 0.2em; }
}

/* ==========================================================================
   LAYOUT
   ========================================================================== */
@layer layout {
  .skip-link {
    position: absolute;
    inset-inline-start: var(--pad-x);
    top: 0;
    z-index: var(--z-skip);
    transform: translateY(-150%);
    padding: 0.75rem 1.25rem;
    background: var(--c-ink);
    color: var(--c-inverse-ink);
    font-family: var(--f-mono);
    font-size: var(--t-mono);
    letter-spacing: var(--ls-mono);
    text-transform: uppercase;
    text-decoration: none;
    transition: transform var(--dur-fast) var(--ease);
  }
  .skip-link:focus-visible { transform: translateY(0); }

  .section {
    position: relative;
    padding-block: var(--block);
    padding-inline: var(--pad-x);
    /* Повёрнутые инвентарные номера намеренно выходят за колонку —
       обрезаем их по границе секции, чтобы не появлялась горизонтальная
       прокрутка. */
    overflow: clip;
  }
  .section--lg { padding-block: var(--block-lg); }
  /* scroll-margin отрицательный: прокрутка по якорю «К выставке» должна
     остановиться на строке [ STATEMENT ], а не на верхнем поле секции. */
  .section--statement {
    padding-block-end: 8.75rem;
    scroll-margin-top: calc(var(--block-lg) * -1);
  }
  .section--statement .prose { margin-top: clamp(4.5rem, 9vw, 5.625rem); }
  .section--dossier { padding-block: 0 var(--block-lg); }

  /* Единственный способ рисовать границу между блоками */
  .section--ruled { border-top: var(--bw-hair) solid var(--c-hairline); }

  .section--surface {
    background-color: var(--c-surface);
    --c-slab: var(--c-bg);
  }

  .section--inverse {
    background-color: var(--c-inverse-bg);
    color: var(--c-inverse-ink);
    --c-ink-2: var(--c-inverse-ink);
    --c-ink-muted: var(--c-inverse-muted);
    --c-ink-faint: var(--c-inverse-faint);
    --c-hairline: #2a2a2a;
    --c-bronze-ink: var(--c-bronze);
    overflow: hidden;
  }

  /* Отложенный рендер нижних секций — прямой вклад в LCP и TBT.
     contain-intrinsic-size обязателен, иначе прыгает полоса прокрутки. */
  /* content-visibility здесь стоял, но давал скачки прокрутки: реальная
     высота секции с работами кратно больше любой заглушки, и в момент
     отрисовки страница дёргалась. Ленивой загрузки снимков достаточно. */

  /* 12-колоночная сетка проекта. Асимметрия задаётся только через
     --col-span / --col-start у детей, а не отдельными сетками. */
  .grid {
    display: grid;
    grid-template-columns: repeat(1, minmax(0, 1fr));
    gap: var(--gutter);
  }
  @media (min-width: 64rem) {
    .grid { grid-template-columns: repeat(12, minmax(0, 1fr)); }
    .grid > * { grid-column: span var(--col-span, 12) / span var(--col-span, 12); }
    .grid > [data-col-start] { grid-column-start: var(--col-start); }
  }
  .grid--center { align-items: center; }
  .grid--top { align-items: start; }

  .stack {
    display: flex;
    flex-direction: column;
    gap: var(--stack-gap, 1.5rem);
  }
}

/* ==========================================================================
   COMPONENTS
   ========================================================================== */
@layer components {

  /* ---- Технические подписи (mono) --------------------------------------- */
  .label {
    display: block;
    font-family: var(--f-mono);
    font-size: var(--t-mono);
    font-weight: 500;
    letter-spacing: var(--ls-mono-wide);
    text-transform: uppercase;
    color: var(--c-ink-faint);
  }
  .label--bronze { color: var(--c-bronze-ink); }
  .label--ink { color: var(--c-ink-2); }

  .meta {
    font-family: var(--f-mono);
    font-size: var(--t-mono);
    font-weight: 400;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--c-ink-faint);
  }

  /* ---- Вертикальная бронзовая нить в начале секции ----------------------- */
  .tick {
    position: absolute;
    top: 0;
    left: var(--pad-x);
    width: var(--bw-hair);
    height: clamp(3rem, 8vw, 8rem);
    background-color: var(--c-bronze);
  }

  /* ---- Навигация ---------------------------------------------------------- */
  .nav {
    position: fixed;
    inset-block-start: 0;
    inset-inline: 0;
    z-index: var(--z-nav);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1.5rem;
    padding: 2rem var(--pad-nav);
    color: var(--c-blend-reference);
    mix-blend-mode: difference;
    pointer-events: none;
    transition: inset-block-start var(--dur) var(--ease);
  }
  .nav--hidden { inset-block-start: calc(var(--nav-hide-distance) * -1); }
  .nav > * { pointer-events: auto; }
  .u-no-scroll .nav { z-index: calc(var(--z-menu) + 1); }

  .loadbar {
    position: fixed;
    inset-block-start: 0;
    inset-inline-start: 0;
    z-index: calc(var(--z-menu) + 2);
    width: 100%;
    height: 1px;
    /* Токен, а не белый: на светлых страницах белая полоса на светлом фоне
       была не видна вовсе. На тёмной странице работы этот же токен сам
       становится светлым. */
    background: var(--c-ink-2);
    pointer-events: none;
    opacity: 0;
    transform: scaleX(0);
    transform-origin: 0 50%;
    transition: opacity 220ms var(--ease);
  }
  .loadbar.is-active { opacity: 1; }

  @supports not (mix-blend-mode: difference) {
    .nav { background: rgba(0, 0, 0, 0.82); }
  }

  .nav__brand {
    display: inline-flex;
    align-items: center;
    line-height: 1;
    padding: 0.625rem;
    margin: -0.625rem;
    text-decoration: none;
  }
  .logo {
    display: block;
    width: auto;
    height: clamp(0.75rem, 1vw, 0.875rem);
  }

  .nav__right {
    display: flex;
    align-items: center;
    gap: clamp(1.25rem, 2.5vw, 2.25rem);
  }
  .nav__work-options { display: none; }

  .nav__btn {
    display: inline-flex;
    align-items: center;
    font-family: var(--f-mono);
    font-size: var(--t-mono);
    font-weight: 500;
    line-height: 1;
    letter-spacing: var(--ls-mono-wide);
    text-transform: uppercase;
    /* Отрицательный margin компенсирует padding: зона нажатия крупнее,
       положение метки в шапке не меняется. */
    padding: 0.625rem;
    margin: -0.625rem;
    transition: opacity var(--dur-fast) var(--ease);
  }
  .nav__btn:hover { opacity: 0.6; }
  /* Надпись переключает только та кнопка, чья панель открыта */
  .nav__btn-label--close { display: none; }
  .nav__btn[aria-expanded='true'] .nav__btn-label--open { display: none; }
  .nav__btn[aria-expanded='true'] .nav__btn-label--close { display: inline; }

  /* ---- Оверлей меню --------------------------------------------------------- */
  /* Открытие: заливка снизу вверх плюс всплывающие пункты со сдвигом.
     Обе анимации — на появлении панели, отдельного класса-состояния не нужно:
     панель показывается снятием hidden. */
  .menu {
    position: fixed;
    inset: 0;
    z-index: var(--z-menu);
    display: flex;
    flex-direction: column;
    background: var(--c-inverse-bg);
    color: var(--c-inverse-ink);
    animation: menu-wipe var(--dur) var(--ease);
  }
  .menu[hidden] { display: none; }

  @keyframes menu-wipe {
    from { clip-path: inset(100% 0 0 0); }
    to   { clip-path: inset(0 0 0 0); }
  }
  @keyframes menu-item {
    from { opacity: 0; transform: translateY(1.5rem); }
    to   { opacity: 1; transform: none; }
  }

  .menu__list {
    display: flex;
    flex-direction: column;
    flex: 1;
    justify-content: center;
    align-items: center;
    gap: clamp(2rem, 5vw, 2.25rem);
    padding: 0 var(--pad-x) var(--block);
    text-align: center;
  }
  /* Пункты выходят по очереди — задержка считается от индекса из разметки */
  .menu__list li {
    animation: menu-item var(--dur) var(--ease) backwards;
    animation-delay: calc(var(--i, 0) * 60ms + 80ms);
  }
  .menu__list a,
  .menu__list span {
    font-family: var(--f-system);
    font-size: calc(var(--t-h2-sm) * 0.9);
    font-weight: 300;
    line-height: 1;
    text-decoration: none;
    transition: color var(--dur-fast) var(--ease);
  }
  .menu__list a:hover,
  .menu__list a:focus-visible { color: var(--c-bronze); }
  /* Текущий пункт — и язык, и раздел: aria-current несёт и смысл, и цвет */
  .menu__list [aria-current] { color: var(--c-bronze); }

  /* ---- Кнопки -------------------------------------------------------------- */
  .btn {
    display: inline-block;
    min-width: 12rem;
    padding: 1rem 1.5rem;
    border: var(--bw-hair) solid currentColor;
    font-family: var(--f-mono);
    font-size: calc(var(--t-mono) - 1px);
    font-weight: 500;
    letter-spacing: var(--ls-mono-wide);
    text-transform: uppercase;
    text-align: center;
    text-decoration: none;
    transition: background-color var(--dur-fast) var(--ease),
                color var(--dur-fast) var(--ease),
                border-color var(--dur-fast) var(--ease);
  }
  /* Единое hover-состояние всех кнопок: заливка чернилами. Текстовая
     .btn--quiet — единственное исключение, оно ниже. */
  .btn:hover,
  .btn:focus-visible {
    background-color: var(--c-ink);
    border-color: var(--c-ink);
    color: var(--c-bg);
  }

  /* Кнопка на hero. Цвет она и раньше получала по наследству от слоя
     смешивания — правило только закрепляет это явно, чтобы класс в разметке
     не ссылался в пустоту. */
  .btn--invert { color: inherit; }

  .btn--quiet { border-color: transparent; }
  .btn--quiet:hover,
  .btn--quiet:focus-visible {
    background-color: transparent;
    border-color: transparent;
    color: var(--c-accent);
  }

  /* «Продолжить» и пагинация ленты: чёрные чернила и рамка. Прежняя серая
     рамка давала 2.6:1 — граница интерактивного элемента так теряется.
     Наведение здесь не заливает кнопку целиком, а лишь подсвечивает фон. */
  .btn--outline {
    min-width: 16rem;
    border-color: var(--c-ink);
    color: var(--c-ink);
  }
  .btn--outline:hover,
  .btn--outline:focus-visible {
    background-color: var(--c-slab);
    border-color: var(--c-ink);
    color: var(--c-ink);
  }

  /* ---- Hero ----------------------------------------------------------------
     Устройство повторяет референс:
       .hero__frame — кадр, обрезанный снизу; под полупрозрачным изображением
       лежит фон страницы, как в reference;
      .hero__heading — текст поверх, с mix-blend-difference.
     Заголовок пересекает нижнюю границу кадра и переворачивается сам:
     на снимке светлый, на странице чёрный. Это один элемент, не две копии.
     ------------------------------------------------------------------------- */
  .hero {
    position: relative;
    display: flex;
    align-items: flex-end;
    min-height: 100svh;
    padding-block: calc(var(--block) + 4rem) var(--hero-pad-b);
    padding-inline: var(--pad-x);
    background-color: var(--c-bg);
    overflow: clip;
  }

  .hero__frame {
    position: absolute;
    inset: 0 0 auto 0;
    z-index: var(--z-media);
    height: var(--hero-frame);
    background-color: var(--c-bg);
    overflow: hidden;
  }

  /* Слой выше рамки на 2 × --parallax-range-hero, чтобы сдвиг не открывал
     край. Двигается сам <img> — так же, как в карточках работ. */
  .hero__media {
    position: absolute;
    inset: calc(var(--parallax-range-hero) * -1) 0;
  }
  .hero__media img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: var(--hero-media-x) var(--hero-media-y);
    opacity: var(--hero-media-opacity);
    filter: grayscale(1) contrast(1.25);
    transform: translate3d(0, var(--parallax, 0px), 0);
  }

  .hero__inner {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--hero-content-gap);
    width: 100%;
  }
  @supports (mix-blend-mode: difference) {
    .hero__heading { mix-blend-mode: difference; }
  }

  .hero__heading {
    position: relative;
    z-index: var(--z-overlay);
    margin: 0;
    color: var(--c-blend-reference);
  }

  /* Вес 400, а не 700: в исходном макете Tailwind сбрасывает жирность
     заголовков на inherit, и BEYOND FORM набран светлым начертанием Bodoni. */
  .hero__title {
    display: block;
    margin-bottom: clamp(1.5rem, 3vw, 2.5rem);
    /* Сдвиг только самого текста: раскладка и чёрный фон остаются на месте */
    translate: 0 var(--hero-title-drop, 0);
    font-family: var(--f-display);
    font-size: var(--hero-title-size);
    font-weight: 400;
    line-height: 0.95;
    letter-spacing: var(--ls-display);
  }

  .hero__lede {
    display: block;
    /* Не в ch: у моноширинного с трекингом 0.08em реальная ширина знака
       больше, чем считает ch, и строка ломалась на третью. */
    max-width: 34rem;
    font-family: var(--f-mono);
    font-size: calc(var(--t-hero-lede) + 1px);
    font-weight: 400;
    line-height: 1.7;
    letter-spacing: 0.08em;
    text-transform: uppercase;
  }

  .hero__actions {
    position: relative;
    z-index: var(--z-overlay);
    display: flex;
    flex-direction: column;
    /* Кнопки прижаты к правому краю — .hero__inner на мобильном тянет детей
       по контенту, поэтому ширину задаём явно. */
    width: 100%;
    align-items: flex-end;
    gap: 1rem;
    color: var(--c-ink);
  }

  @media (min-width: 64rem) {
    :root {
      --hero-actions-block: 0rem;
      --hero-content-gap: 0rem;
      --hero-media-x: 50%;
      --hero-media-y: calc(28% + 40px);
      --hero-title-size: var(--t-hero);
      --hero-pad-b: max(1.25rem, calc(var(--block) - var(--hero-content-drop)));
    }
    .hero__inner { flex-direction: row; align-items: flex-end; }
    .hero__title { translate: none; }
    .hero__lede { font-size: var(--t-hero-lede); }
    .btn { font-size: var(--t-mono); }
  }

  /* ---- Крупный редакционный заголовок -------------------------------------- */
  .display {
    font-family: var(--f-system);
    font-size: calc(var(--t-h2) * 1.2);
    /* На телефоне строки стоят чуть свободнее: кегль там крупнее */
    line-height: 0.98;
    letter-spacing: 0;
  }
  @media (min-width: 64rem) {
    .display {
      font-size: var(--t-h2);
      line-height: 0.88;
    }
  }
  .display > span { display: block; }
  .display__indent-1 { margin-left: clamp(1.5rem, 5vw, 8rem); }
  .display__indent-2 { margin-left: clamp(0.75rem, 2.5vw, 4rem); }
  .display__accent { color: var(--c-bronze-ink); }

  /* Настройка основного текста: интерлиньяж 1.52 и нулевой трекинг —
     у системных гарнитур межбуквенное уже выставлено оптически, свой на
     16–18px только вредит. Мера строки — --measure, около 65 знаков. */
  .prose {
    max-width: var(--measure);
    font-size: var(--t-body-lg);
    font-weight: 300;
    line-height: 1.52;
    letter-spacing: 0;
    color: var(--c-ink-muted);
  }
  .prose h2 {
    font: inherit;
    letter-spacing: inherit;
    color: inherit;
    text-wrap: pretty;
  }
  .prose > * + * { margin-top: 1.25em; }

  /* ---- Досье художника ------------------------------------------------------ */
  .dossier {
    --dossier-frame-height-trim: 10rem;
    --dossier-media-copy-gap: 65px;
    display: grid;
    gap: var(--dossier-media-copy-gap);
  }
  /* На телефоне рамка — обычная колонка: три кадра фиксированной ширины
     с равным шагом. Абсолютная «лесенка» включается с 48rem. */
  .dossier__frame {
    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 30px;
    padding-inline: 30px;
    margin-inline: 0.25rem;
    /* Высота рамки прежняя — меняется только размер самих кадров */
    min-height: calc(clamp(116rem, 488vw, 123.2rem) - var(--dossier-frame-height-trim));
    border: var(--bw-hair) solid var(--c-bronze);
  }
  .dossier__thumb {
    position: static;
    width: 148px;
  }
  .dossier__thumb img {
    position: relative;
    z-index: var(--z-raised);
    width: 100%;
    height: auto;
    filter: grayscale(1) contrast(1.12);
  }
  .dossier__thumb--portrait { top: 16.6%; }
  .dossier__thumb--patina { top: 32.5%; }
  .dossier__thumb--trinity { top: 47.2%; }
  .dossier__fig {
    position: absolute;
    z-index: var(--z-overlay);
    bottom: 1rem;
    left: 1rem;
    padding: 0.35rem 0.7rem;
    background: var(--c-surface);
    border: var(--bw-hair) solid var(--c-hairline);
    color: var(--c-ink-2);
  }
  .dossier__copy > .label {
    padding-bottom: 1rem;
    border-bottom: var(--bw-hair) solid var(--c-hairline);
  }
  @media (min-width: 48rem) {
    .dossier {
      --dossier-frame-width: 39.7%;
      --dossier-copy-width: 41.6%;
      --dossier-column-gap: var(--dossier-media-copy-gap);
      --dossier-thumb-rel-left: 1.6%;
      --dossier-thumb-rel-width: 36%;
      --dossier-thumb-portrait-top: 29%;
      --dossier-thumb-patina-top: 45%;
      --dossier-thumb-trinity-top: 59.5%;
      --dossier-frame-height: calc(clamp(136rem, 188vw, 180.8rem) - var(--dossier-frame-height-trim));
      display: grid;
      grid-template-columns: var(--dossier-frame-width) var(--dossier-copy-width);
      column-gap: var(--dossier-column-gap);
      align-items: center;
      justify-content: center;
      min-height: var(--dossier-frame-height);
    }
    .dossier__frame {
      grid-column: 1;
      display: block;
      padding: 0;
      margin-inline: 0;
      min-height: var(--dossier-frame-height);
    }
    .dossier__thumb {
      position: absolute;
      left: var(--dossier-thumb-rel-left);
      width: var(--dossier-thumb-rel-width);
    }
    .dossier__thumb--portrait { top: var(--dossier-thumb-portrait-top); }
    .dossier__thumb--patina { top: var(--dossier-thumb-patina-top); }
    .dossier__thumb--trinity { top: var(--dossier-thumb-trinity-top); }
    .dossier__fig {
      left: var(--dossier-thumb-rel-left);
      bottom: 0.8%;
    }
    .dossier__copy {
      grid-column: 2;
      align-self: center;
    }
  }

  .link-rule {
    display: inline-flex;
    align-items: center;
    gap: 1rem;
    color: var(--c-bronze-ink);
    font-family: var(--f-mono);
    font-size: calc(var(--t-small) + 2px);
    letter-spacing: 0.06em;
    text-decoration: none;
  }
  .link-rule::after {
    content: '';
    width: 3rem;
    height: var(--bw-hair);
    background: var(--c-bronze);
    transition: width var(--dur) var(--ease);
  }
  .link-rule:hover::after,
  .link-rule:focus-visible::after { width: 4.5rem; }

  /* ---- Цитата ---------------------------------------------------------------- */
  .quote {
    --quote-rule-gap: 3rem;
    --quote-rule-h: 4rem;
    position: relative;
    z-index: var(--z-overlay);
    /* Линия с отступом висит ниже текста, поэтому фигура смещается вниз на
       половину их суммы — так по центру секции оказывается сама цитата. */
    margin: calc((var(--quote-rule-gap) + var(--quote-rule-h)) / 2) auto 0;
    text-align: center;
  }
  .quote blockquote {
    margin: 0;
    font-family: var(--f-system);
    font-size: var(--t-quote);
    line-height: 1.05;
  }
  .quote__rule {
    width: var(--bw-hair);
    height: var(--quote-rule-h);
    margin: var(--quote-rule-gap) auto 0;
    background: var(--c-bronze);
  }
  /* Fixed-параллакс: кадр закреплён во вьюпорте, а секция работает окном —
     clip-path на ней обрезает закреплённый слой, поэтому при прокрутке окно
     ползёт по неподвижному видео. На .section--quote нельзя ставить transform,
     filter или contain: секция станет содержащим блоком и fixed выродится
     в absolute. */
  .section--quote {
    /* На телефоне окно ролика выше: прибавка делится поровну сверху и снизу,
       поэтому цитата остаётся по центру кадра. */
    --quote-pad-extra: 100px;
    clip-path: inset(0);
    padding-block: calc(var(--block-lg) + var(--quote-pad-extra));
    padding-inline: clamp(1.25rem, 5vw, 4.375rem);
  }
  @media (min-width: 64rem) {
    .section--quote { --quote-pad-extra: 0px; }
  }
  .quote__bg {
    position: fixed;
    inset-block-start: 0;
    inset-inline-start: 0;
    width: 100vw;
    height: 100svh;
    opacity: 0.52;
  }
  .quote__poster,
  .quote__poster picture,
  .quote__video {
    position: absolute;
    inset: 0;
  }
  .quote__bg img,
  .quote__video {
    width: 100%;
    height: 100%;
    object-fit: cover;
    filter: grayscale(1);
  }
  .quote__video { z-index: var(--z-raised); }

  /* Источник ролика — мелкая подпись в нижнем левом углу кадра, без плашки */
  .quote__credit {
    position: absolute;
    inset-block-end: var(--pad-x);
    inset-inline-start: var(--pad-x);
    z-index: var(--z-overlay);
    display: flex;
    gap: 0.4rem;
    font-family: var(--f-mono);
    font-size: var(--t-mono-sm);
    letter-spacing: var(--ls-mono);
    text-transform: uppercase;
    color: var(--c-inverse-faint);
  }
  .quote__credit a {
    text-decoration: none;
    transition: color var(--dur-fast) var(--ease);
  }
  .quote__credit a:hover,
  .quote__credit a:focus-visible { color: var(--c-inverse-ink); }
  .quote__side { display: none; }
  @media (min-width: 64rem) {
    .quote {
      display: grid;
      grid-template-columns: auto minmax(0, 1fr) auto;
      align-items: center;
      column-gap: 3rem;
    }
    .quote__side {
      display: block;
      color: var(--c-inverse-muted);
    }
    .quote__rule { grid-column: 1 / -1; }
  }

  /* ---- Шапка раздела «EXHIBIT A» -------------------------------- */
  /* На телефоне разделы идут сплошной лентой: шапка EXHIBIT остаётся только
     в дереве доступности, визуально её нет. Раскладка возвращается с 64rem. */
  .sec-head {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }
  .sec-head--split {
    position: static;
    width: auto;
    height: auto;
    margin: 0;
    overflow: visible;
    clip-path: none;
    white-space: normal;
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: flex-start;
    gap: 1rem;
    padding-bottom: 2rem;
    margin-bottom: var(--block);
    border-bottom: var(--bw-hair) solid var(--c-hairline);
  }
  .sec-head--split { justify-content: space-between; }
  @media (min-width: 64rem) {
    .sec-head {
      position: static;
      width: auto;
      height: auto;
      margin: 0 0 var(--block);
      overflow: visible;
      clip-path: none;
      white-space: normal;
      display: flex;
      padding-bottom: 2rem;
      border-bottom: var(--bw-hair) solid var(--c-hairline);
    }
  }
  .sec-head__title {
    font-size: var(--t-h2-sm);
    line-height: 1;
    letter-spacing: 0.01em;
  }
  /* ---- Сетка работ ------------------------------------------------------------ */
  .works {
    display: grid;
    grid-template-columns: repeat(1, minmax(0, 1fr));
    gap: var(--work-gap) var(--gutter);
  }
  /* Телефон: секции выставки идут без собственных отступов, шаг между всеми
     десятью работами задаёт один токен — лента получается равномерной. */
  .section--exhibit { padding-block: 0; }
  .section--exhibit + .section--exhibit,
  .section--quote + .section--exhibit { margin-top: var(--work-gap); }
  /* Последняя секция выставки заканчивается кнопкой «Продолжить». Отступ под
     ней внутренний: сразу за секцией начинается блок с другой заливкой, и
     внешний отступ ушёл бы в чужой фон. :last-of-type тут не годится —
     секции после выставки идут дальше по странице. */
  .section--exhibit:not(:has(+ .section--exhibit)) { padding-bottom: var(--block); }
  .works + .work,
  .work + .works,
  .grid + .works { margin-top: var(--work-gap); }
  .work-list-page {
    padding-top: calc(var(--block) + 4rem);
    padding-bottom: var(--block);
  }
  .work-list-page__nav {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--gutter);
    margin-top: var(--block);
  }
  @media (min-width: 64rem) {
    .section--exhibit { padding-block: var(--block-lg); }
    .section--exhibit + .section--exhibit,
    .section--quote + .section--exhibit { margin-top: 0; }
    .section--exhibit:not(:has(+ .section--exhibit)) { padding-bottom: var(--block-lg); }
    .works + .work,
    .work + .works,
    .grid + .works { margin-top: var(--block-lg); }
    .work-list-page { padding-top: calc(var(--block-lg) + 4rem); }
    .work-list-page__nav { margin-top: var(--block-lg); }
  }
  @media (min-width: 48rem) {
    .works--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    /* Смещение по вертикали — источник «архитектурной асимметрии» макета.
       Задаётся ТОЛЬКО этим модификатором, не локальными margin-ами. */
    .work--offset { margin-top: var(--stagger); }
    .work--offset-sm { margin-top: calc(var(--stagger) * 0.5); }
  }
  @media (min-width: 64rem) {
    .works--split { grid-template-columns: repeat(12, minmax(0, 1fr)); }
    .works--split > * { grid-column: span var(--col-span, 12); }
  }

  .work { position: relative; }
  /* Кадр ведёт на страницу работы. Ссылка обёрнута вокруг слэба, поэтому
     на телефоне прокрутка кадра по частям остаётся прокруткой — переход
     гасится скриптом, если палец двигался. */
  .work__media-shell { position: relative; }
  .work__link { display: block; color: inherit; text-decoration: none; }

  /* Инвентарный номер и бронзовая линия у кадра сняты: подпись под работой
     несёт всё нужное, а лишняя графика спорит со снимком. */
  .work__inv { display: none; }


  .work__media {
    /* Слэб — контейнер запросов: высота и смещение кадра задаются в cqw,
       то есть в долях ШИРИНЫ слэба. Поэтому пропорции кадра одинаковы на
       десктопе и на телефоне, а ловушка процентной высоты внутри коробки
       с aspect-ratio не срабатывает. */
    container-type: inline-size;
    position: relative;
    display: grid;
    /* Одна ячейка во всю коробку: без явного трека строка сжималась бы по
       контенту и вставала вверху, из-за чего align-self не центрировал. */
    grid-template: minmax(0, 1fr) / minmax(0, 1fr);
    aspect-ratio: var(--ratio, 3 / 4);
    background-color: var(--c-slab);
    overflow: hidden;
  }
  /* Грид-элемент — обёртка <picture> из хелпера, ей и задаются размер и
     положение кадра. display: contents тут не годится: <source> тоже стали бы
     элементами сетки и уводили снимок в лишнюю строку — кадр вставал по
     нижнему краю слэба. */
  .work__media picture {
    display: block;
    width: fit-content;
    max-width: 100%;
    height: var(--img-h, 76cqw);
    justify-self: var(--img-x, center);
    align-self: var(--img-y, center);
    translate: var(--img-dx, 0) var(--img-dy, 0);
  }
  /* Кадр меньше слэба и не кадрируется: высота из данных работы, ширина
     выводится из собственных пропорций снимка. */
  .work__media img {
    width: auto;
    max-width: 100%;
    height: 100%;
    object-fit: contain;
    filter: grayscale(1);
    transition: filter var(--dur-slow) var(--ease);
  }
  /* Снимок заполняет слэб целиком — с кадрированием и без поля вокруг */
  .work__media--fill picture {
    width: 100%;
    height: 100%;
    translate: none;
  }
  .work__media--fill img {
    width: 100%;
    height: 100%;
    object-fit: cover;
  }

  /* ---- Телефон: кадр работы --------------------------------------------
     Работу целиком на телефоне не рассмотреть, поэтому широкий кадр
     показывается в высоком окне и прокручивается по шагам — как карусель,
     только фотография одна. Режим и пропорции приходят из PHP (--m-ratio),
     поэтому высота окна известна до загрузки снимка и лента не дёргается.
     Вертикальный кадр помещается целиком: у него окно по своим пропорциям. */
  @media (max-width: 63.999rem) {
    .work__media--phone-paged,
    .work__media--phone-fit {
      container-type: normal;
      display: block;
      /* Кадр уходит под оба края экрана */
      margin-inline: var(--work-bleed);
      border-left: 0;
    }
    .work__media-shell--paged {
      margin-inline: var(--work-bleed);
    }
    .work__media-shell--paged .work__media--phone-paged {
      margin-inline: 0;
    }
    .work__media--phone-paged {
      aspect-ratio: auto;
      height: var(--work-paged-h);
      overflow-x: auto;
      overflow-y: hidden;
      scroll-snap-type: x mandatory;
      overscroll-behavior-x: contain;
      scrollbar-width: none;
    }
    .work__media--phone-paged::-webkit-scrollbar { display: none; }
    .work__media--phone-fit {
      aspect-ratio: var(--m-ratio);
      height: auto;
    }

    .work__track {
      position: relative;
      /* Ширина ленты = ширина снимка при высоте окна; её ставит JS в px,
         маркеры прилипания расставляются внутри абсолютно. */
      height: 100%;
    }
    /* Пустые маркеры — только точки прилипания; сам снимок лежит поверх них.
       Позиция задаётся из JS, поэтому между частями помещается и центр. */
    .work__page {
      position: absolute;
      inset-block: 0;
      width: 1px;
      scroll-snap-align: start;
    }
    /* Кадр вписан в окно по высоте и никогда не кадрируется: ширина следует
       из его собственных пропорций, лишнее уходит в прокрутку. */
    .work__media--phone-paged picture,
    .work__media--phone-fit picture {
      position: absolute;
      inset-block: 0;
      inset-inline-start: 0;
      width: auto;
      max-width: none;
      height: 100%;
      translate: none;
    }
    .work__media--phone-paged img,
    .work__media--phone-fit img {
      width: auto;
      height: 100%;
      object-fit: contain;
      /* На телефоне работы показываются в цвете: hover-расцвечивания нет,
         а разглядывать деталь нужно сразу. */
      filter: none;
    }
    /* Полоса прокрутки кадра: серая линия по текстовой колонке, пройденная
       часть закрашивается. Кадр уходит под края экрана, полоса — нет:
       она читается как подпись и держит поля страницы. */
    .work__bar {
      position: relative;
      height: 1px;
      margin-block: 16px 0;
      margin-inline: 0;
      background: var(--c-hairline);
    }
    .work__bar-fill {
      position: absolute;
      inset-block: 0;
      inset-inline: 0;
      background: var(--c-ink-2);
      transform-origin: left center;
      transform: scaleX(var(--progress, 0));
      transition: none;
      will-change: transform;
    }
    .work__bar.is-muted {
      opacity: 0;
    }
  }
  /* На десктопе мобильные модификаторы не работают вовсе */
  @media (min-width: 64rem) {
    .work__bar { display: none; }
  }

  /* Появление снимка: короткий мягкий переход по прозрачности, без движения.
     Класс стоит в разметке, поэтому кадр скрыт с первой отрисовки и не
     мелькает недогруженным. Открывает его скрипт — после декодирования. */
  .js picture.is-loading { opacity: 0; }
  .js picture.is-loaded {
    opacity: 1;
    transition: opacity var(--dur-reveal) ease-out;
  }

  /* Расцвечивание — только при наведении на сам кадр: серое поле слэба
     в hover-зону не входит. */
  @media (hover: hover) {
    .work__media picture:hover img { filter: grayscale(0); }
  }
  .work__media picture:focus-within img { filter: grayscale(0); }

  /* Подпись отбивается от того, что стоит над ней, — от кадра или от полосы
     прокрутки. Отступ один и тот же, поэтому лента ровная. */
  .work__media + .work__title,
  .work__media + .work__caption,
  .work__media-shell + .work__title,
  .work__media-shell + .work__caption,
  .work__link + .work__title,
  .work__link + .work__caption,
  .work__bar + .work__title,
  .work__bar + .work__caption { margin-top: var(--work-cap-gap); }

  .work__title { margin-bottom: var(--work-more-gap); font-size: calc((var(--t-h3) - 4px) * 0.8); }
  /* Название ведёт на страницу работы. Вид не меняется: цвет наследуется,
     подчёркивания нет — как и раньше, ссылкой его выдаёт только наведение. */
  .work__title-link {
    color: inherit;
    text-decoration: none;
    transition: color var(--dur-fast) var(--ease);
  }
  .work__title-link:hover,
  .work__title-link:focus-visible { color: var(--c-bronze-ink); }

  /* Под названием — вход на страницу работы. Данные о работе живут там,
     внутри «Подробнее», чтобы лента оставалась тихой. */
  .work__more {
    /* Тот же тип коробки, что у «Подробнее» на странице работы: иначе
       полулидинг строки даёт лишний пиксель и группы не совпадают. */
    display: inline-block;
    font-family: var(--f-mono);
    font-size: var(--t-mono);
    line-height: 1.4;
    letter-spacing: var(--ls-action);
    text-transform: uppercase;
    color: var(--c-action-muted);
    text-decoration: none;
    transition: color var(--dur-fast) var(--ease);
  }
  .work__more:hover { color: var(--c-bronze-ink); }

  /* Две раскладки подписи: под кадром и сбоку от него. Видна всегда одна,
     вторая просто не выводится, поэтому в дереве доступности заголовок
     остаётся единственным. */
  .work__caption--side { display: none; }
  @media (min-width: 64rem) {
    .work__caption--under { display: none; }
    .work__caption--side {
      display: block;
      margin-bottom: 1.5rem;
    }
  }

  /* ---- Табы «Выставки / Награды» ------------------------------------------------ */
  .tabs {
    display: flex;
    flex-wrap: wrap;
    gap: clamp(1.5rem, 4vw, 3rem);
    margin-bottom: var(--block);
  }
  .tab {
    padding-bottom: 0.5rem;
    border-bottom: var(--bw-rule) solid transparent;
    font-family: var(--f-system);
    font-size: calc(var(--t-h2-sm) - 2px);
    line-height: 1;
    color: var(--c-tab-idle);
    transition: color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
  }
  .tab:hover { color: var(--c-ink-muted); }
  .tab[aria-selected='true'] {
    color: var(--c-bronze-ink);
    border-bottom-color: var(--c-bronze);
  }
  .tabpanel[hidden] { display: none; }

  .cards {
    display: grid;
    grid-template-columns: repeat(1, minmax(0, 1fr));
    gap: var(--gutter);
  }
  @media (min-width: 48rem) {
    .cards { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  }
  .card {
    padding-top: 1.5rem;
    border-top: var(--bw-hair) solid var(--c-hairline);
  }
  .card__date { margin-bottom: 0.75rem; }
  .card__title { margin-bottom: 1rem; font-size: var(--t-h4); line-height: 1.2; }
  /* Та же настройка, что у .prose */
  .card__note {
    font-size: var(--t-body-lg);
    font-weight: 300;
    line-height: 1.52;
    letter-spacing: 0;
    color: var(--c-ink-muted);
  }
  /* Карточка-описание рядом с крупным кадром: линейка сверху уже есть у .card */
  .card--aside { border-top-color: var(--c-hairline); }
  /* На телефоне карточка встаёт под кадр, и её линейка читается как разрыв
     ленты работ, а не как связка кадра с текстом. */
  @media (max-width: 63.999rem) {
    .card--aside { border-top: 0; }
  }



  /* ---- Публикации -------------------------------------------------------------- */
  .pubs {
    display: grid;
    grid-template-columns: repeat(1, minmax(0, 1fr));
    /* По вертикали шаг крупнее: в одну колонку публикации иначе слипаются */
    gap: var(--block) var(--gutter);
  }
  @media (min-width: 48rem) {
    .pubs { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  }
  .pub {
    display: block;
    text-decoration: none;
  }
  /* Кадр публикации живёт по тем же правилам, что и кадр работы:
     слэб-паспарту и расцвечивание при наведении. */
  .pub__media {
    display: grid;
    aspect-ratio: 1 / 1;
    margin-bottom: 1.5rem;
    background-color: var(--c-slab);
    overflow: hidden;
  }
  .pub__media img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    filter: grayscale(1);
    transition: filter var(--dur-slow) var(--ease);
  }
  .pub:hover .pub__media img,
  .pub:focus-visible .pub__media img { filter: grayscale(0); }
  .pub__kicker { display: flex; flex-wrap: wrap; gap: 0.75rem; margin-bottom: 0.75rem; }
  .pub__title {
    font-size: var(--t-h4);
    line-height: 1.25;
    transition: color var(--dur-fast) var(--ease);
  }
  .pub:hover .pub__title { color: var(--c-bronze-ink); }

  /* ---- Подвал -------------------------------------------------------------------- */
  .footer {
    position: relative;
    padding-block: var(--block-lg);
    padding-inline: var(--pad-x);
    background: var(--c-footer-bg);
    color: var(--c-inverse-ink);
    overflow: hidden;
  }
  .footer__grid {
    position: relative;
    z-index: var(--z-overlay);
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--gutter);
    margin-bottom: var(--block);
  }
  @media (min-width: 48rem) {
    .footer__grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  }
  .footer__col h2 {
    margin-bottom: 1.25rem;
    font-family: var(--f-mono);
    font-size: var(--t-mono-sm);
    font-weight: 500;
    letter-spacing: var(--ls-mono-wide);
    text-transform: uppercase;
    color: var(--c-inverse-faint);
  }
  .footer__list { display: flex; flex-direction: column; gap: 0.6rem; }
  .footer__col a,
  .footer__col span {
    font-family: var(--f-mono);
    font-size: var(--t-mono);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    text-decoration: none;
    transition: color var(--dur-fast) var(--ease);
  }
  .footer__col a:hover,
  .footer__col a:focus-visible { color: var(--c-bronze); }
  .footer__col [aria-current='true'] { color: var(--c-bronze); }
  .footer__col [aria-disabled='true'] { color: var(--c-inverse-faint); }

  .footer__bar {
    position: relative;
    z-index: var(--z-overlay);
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: 1rem;
    padding-top: 2rem;
    border-top: var(--bw-hair) solid #2a2a2a;
  }
  .footer__bar .meta { color: var(--c-inverse-faint); }

  /* ---- Страница работы ------------------------------------------------------ */
  .page-work {
    background-color: var(--c-page-dark);
    color: var(--c-inverse-ink);
    --c-work-text: #d4d4d4;
    --c-work-text-hover: #ffffff;
    --c-action-muted: #b8b8b8;
    --c-ink-2: var(--c-inverse-ink);
    --c-ink-muted: var(--c-work-text);
    --c-ink-faint: var(--c-inverse-faint);
    --c-hairline: #2a2a2a;
    --c-hairline-strong: #3d3d3d;
    --c-bronze-ink: var(--c-bronze);
    --wp-thumb-size: 2.5rem;
  }
  /* Шапка на странице работы держит только язык и меню: имя выставки здесь
     спорит с заголовком самой работы. */
  .page-work .nav__brand { visibility: hidden; }

  .wp {
    /* На телефоне колонок нет — значения нужны только чтобы calc в правилах
       ниже оставался разрешимым. */
    --wp-col-x: 0px;
    --wp-col-w: 100%;
    /* Телефон: кадр начинается от самого верха экрана. Шапка фиксированная
       и смешивается с ним, поле под неё не нужно. */
    --wp-gap-top: 0px;
    --wp-img-h: var(--work-page-h);
    --wp-ui-bottom-gap: 24px;
    padding: var(--wp-gap-top) var(--pad-x) var(--block);
  }

  .wp__stage { position: relative; display: flex; justify-content: center; min-width: 0; }
  /* Коробка кадра считается от высоты экрана и собственных пропорций снимка
     (--wp-ratio из манифеста). Иначе сетка мерила бы её по исходной ширине
     файла и работа не дотягивалась до полной высоты. */
  .wp__frame {
    position: relative;
    /* Кадр — интерактивная область, а не текст: двойной клик по нему не
       должен ничего выделять. */
    user-select: none;
    aspect-ratio: var(--wp-ratio, 2 / 3);
    height: var(--wp-img-h);
    max-width: 100%;
    transition: opacity var(--dur) var(--ease);
  }
  .wp__frame img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: contain;
  }
  .media-fit-toggle { display: none; }

  /* ---- Миниатюры деталей ---------------------------------------------------
     Мелкие кадры под «Подробнее»: наведение показывает деталь крупно,
     клик открывает галерею. Лежат поверх затемнения, поэтому наведение
     не срывается, когда всплывает крупный кадр. */
  /* Лента миниатюр показывается целиком и один раз, а не по кадру по мере
     загрузки. Класс ставит скрипт, когда все миниатюры готовы; без JS лента
     видна сразу, поэтому правило и висит на .js. */
  .js .wp__thumbs { opacity: 0; }
  .js .wp__thumbs.is-ready {
    opacity: 1;
    transition: opacity var(--dur) var(--ease);
  }

  .wp__thumbs {
    position: relative;
    z-index: calc(var(--z-overlay) + 1);
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin: 2.5rem 0 0;
    padding: 0;
    list-style: none;
  }
  .wp__thumb {
    display: block;
    width: var(--wp-thumb-size);
    height: var(--wp-thumb-size);
    padding: 0;
    border: 0;
    background: none;
    cursor: pointer;
    opacity: 0.55;
    transition: opacity var(--dur-fast) var(--ease);
  }
  .wp__thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
  }
  .wp__thumb:hover,
  .wp__thumb:focus-visible { opacity: 1; }

  /* ---- Показ детали ---------------------------------------------------------
     Деталь выходит справа, остальное приглушается. Слой не в потоке и без
     событий мыши, чтобы не перехватывать наведение с точки. */
  .wp__preview {
    position: fixed;
    inset: 0;
    z-index: var(--z-overlay);
    display: grid;
    place-items: center;
    justify-items: end;
    /* Деталь встаёт вплотную к колонке с текстом — то есть рядом с
       миниатюрой, на которую навели, и поверх приглушённой работы. Правое
       поле равно ширине текстовой колонки, поэтому название, «Подробнее» и
       миниатюры никогда не перекрываются крупным кадром. */
    /* Правое поле = ширина текстовой колонки (экран минус 60vw работы)
       с небольшим зазором, поэтому кадр останавливается перед текстом. */
    padding: var(--block) calc(100vw - var(--wp-col-x) + 1rem) var(--block) var(--pad-x);
    background: rgb(11 11 11 / 0.55);
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity var(--dur) var(--ease), visibility var(--dur) var(--ease);
  }
  .wp__preview img {
    width: auto;
    max-width: min(46vw, 40rem);
    max-height: calc(100dvh - var(--block) * 2);
    object-fit: contain;
    scale: 0.985;
    transition: scale var(--dur) var(--ease);
  }
  .wp.is-previewing .wp__preview {
    opacity: 1;
    visibility: visible;
  }
  .wp.is-previewing .wp__preview img { scale: 1; }

  /* ---- Текст ---------------------------------------------------------------- */
  .wp__text { max-width: var(--measure); margin-top: var(--work-cap-gap); }
  /* Название на этой странице тише, чем в ленте: главный тут снимок */
  .wp__text .work__title {
    font-size: calc((var(--t-h3) - 4px) * 0.8);
    color: var(--c-work-text);
  }
  /* Отступ до «Подробнее» задаёт название — правило общее с лентой */
  .wp__details { margin-top: 0; }
  /* «О работе» набрано так же, как строка под названием */
  .wp__summary {
    display: inline-block;
    cursor: pointer;
    font-family: var(--f-mono);
    font-size: var(--t-mono);
    line-height: 1.4;
    letter-spacing: var(--ls-action);
    text-transform: uppercase;
    color: var(--c-action-muted);
    list-style: none;
    /* Двойной клик по строке-переключателю не должен выделять текст */
    user-select: none;
    transition: color var(--dur-fast) var(--ease);
  }
  .wp__summary::-webkit-details-marker { display: none; }
  .wp__summary:hover { color: var(--c-work-text-hover); }

  /* Плавное раскрытие: без этого <details> открывается рывком. Работает там,
     где браузер умеет анимировать содержимое details; где нет — просто
     открывается сразу, ничего не ломая. */
  @supports (interpolate-size: allow-keywords) {
    :root { interpolate-size: allow-keywords; }
    .wp__details::details-content {
      height: 0;
      overflow: hidden;
      opacity: 0;
      transition: height var(--dur-fast) var(--ease), opacity var(--dur-fast) var(--ease),
                  content-visibility var(--dur-fast) allow-discrete;
    }
    .wp__details[open]::details-content { height: auto; opacity: 1; }
  }

  .wp__body {
    display: grid;
    gap: 1.5rem;
    justify-items: start;
    margin-top: 1.5rem;
    color: var(--c-work-text);
  }
  .wp__body .prose,
  .wp__extra { color: currentColor; }
  /* Кнопка запроса отбита от текста и меняет только контур и цвет букв */
  .wp__body .btn { margin-top: 100px; }
  .wp__body .btn--outline {
    border-color: var(--c-work-text);
    color: var(--c-work-text);
  }
  .wp__body .btn--outline:hover,
  .wp__body .btn--outline:focus-visible {
    background: none;
    border-color: var(--c-work-text-hover);
    color: var(--c-work-text-hover);
  }

  /* ---- Соседние работы ------------------------------------------------------ */
  /* «Главная» стоит ровно по центру ряда независимо от длины названий:
     обычный flex сдвигал бы её вслед за соседями. */
  .wp__nav-home {
    position: absolute;
    left: 50%;
    translate: -50% 0;
    font-family: var(--f-mono);
    font-size: var(--t-small);
    letter-spacing: var(--ls-action);
    color: var(--c-action-muted);
    text-decoration: none;
    transition: color var(--dur-fast) var(--ease);
  }
  .wp__nav-home:hover,
  .wp__nav-home:focus-visible { color: var(--c-work-text-hover); }

  .wp__nav {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    margin-top: var(--block);
  }
  .wp__nav-link {
    display: inline-flex;
    align-items: center;
    gap: 0.75rem;
    color: var(--c-action-muted);
    text-decoration: none;
    transition: color var(--dur-fast) var(--ease);
  }
  .wp__nav-link:hover,
  .wp__nav-link:focus-visible { color: var(--c-work-text-hover); }
  .wp__nav-link svg {
    width: 0.55rem;
    height: 1rem;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.25;
    stroke-linecap: square;
  }
  .wp__nav-title {
    font-family: var(--f-mono);
    font-size: var(--t-small);
    line-height: 1.05;
    letter-spacing: 0.015em;
  }
  .wp__nav-text {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
  }
  .wp__nav-link--next .wp__nav-text {
    align-items: flex-end;
    text-align: right;
  }
  /* Подсказка о стрелках — только на десктопе: на телефоне клавиатуры нет */
  .wp__nav-hint { display: none; }
  @media (min-width: 64rem) {
    .wp__nav-hint {
      display: block;
      font-family: var(--f-mono);
      font-size: var(--t-mono-xs);
      letter-spacing: var(--ls-mono);
      color: currentColor;
      opacity: 0.62;
    }
  }

  /* ---- Десктоп -------------------------------------------------------------- */
  @media (min-width: 64rem) {
    .wp__row {
      display: grid;
      grid-template-columns: var(--wp-img-w) minmax(0, 1fr);
      align-items: start;
      column-gap: var(--wp-col-gap);
    }
    .wp {
      display: block;
      --wp-col-gap: clamp(2rem, 4vw, 4rem);
      --wp-col-w: 20rem;
      --wp-img-w: 66.666vw;
      --wp-side-bottom: 24px;
      --wp-ui-bottom-gap: var(--wp-side-bottom);
      --wp-col-x: calc(var(--wp-img-w) + var(--wp-col-gap) + 2rem);
      --wp-text-margin-left: 2rem;
      --wp-sticky-top: 2rem;
      --wp-ui-inset-right: var(--pad-x);
      --wp-ui-justify: end;
      --wp-overlay-edge: rgb(11 11 11 / 0.78);
      --wp-overlay-mid: rgb(11 11 11 / 0.64);
      --wp-portrait-info-gap: 2.5rem;
      --wp-portrait-info-max: calc(100svh - var(--wp-sticky-top) - var(--wp-ui-bottom-gap) - var(--wp-thumb-size) - var(--wp-portrait-info-gap));
      align-items: start;
      padding: 0;
    }
    .wp--portrait.wp--ui-portrait {
      --wp-col-gap: clamp(1rem, 2vw, 2rem);
      --wp-text-margin-left: 1rem;
      --wp-sticky-top: calc(var(--pad-nav) + 3rem);
    }
    .wp--ui-portrait.is-open .wp__text {
      padding-top: var(--wp-sticky-top);
    }
    .wp__frame {
      width: var(--wp-img-w);
      height: auto;
      max-width: none;
    }
    .wp__stage { justify-content: flex-start; }

    .wp--landscape {
      display: block;
      padding-inline: 0;
      --wp-img-w: 100%;
      --wp-landscape-thumb-gap: clamp(2rem, 4vw, 4rem);
      --wp-landscape-preview-edge: clamp(4rem, 8vw, 8rem);
      --wp-overlay-reach: calc((var(--wp-landscape-thumb-gap) + 5rem) * -1);
      --wp-text-margin-left: var(--wp-col-x);
    }
    .wp--landscape.wp--ui-portrait {
      --wp-text-margin-left: min(calc(66.666vw + var(--wp-col-gap) + 2rem), calc(100vw - var(--pad-x) - var(--wp-col-w)));
    }
    .wp--landscape.wp--ui-portrait .wp__text {
      z-index: var(--z-overlay);
      isolation: isolate;
    }
    .wp--landscape .wp__row {
      position: relative;
      display: grid;
      grid-template-columns: minmax(0, 1fr);
    }
    .wp--landscape .wp__stage,
    .wp--landscape .wp__text {
      grid-area: 1 / 1;
    }
    .wp--landscape .wp__frame {
      width: 100%;
      height: auto;
    }
    .wp--landscape .wp__frame img {
      height: auto;
      object-fit: initial;
    }
    .wp--landscape .wp__stage {
      position: static;
      width: 100%;
    }
    .wp__text {
      position: sticky;
      top: var(--wp-sticky-top);
      display: flex;
      flex-direction: column;
      justify-content: flex-end;
      width: var(--wp-col-w);
      min-height: calc(100svh - var(--wp-sticky-top) - var(--wp-ui-bottom-gap));
      max-width: 100%;
      margin: 0 0 var(--wp-ui-bottom-gap) var(--wp-text-margin-left);
      padding: 0;
    }
    .wp--ui-portrait .wp__text {
      display: grid;
      grid-template-rows: minmax(0, 1fr) auto auto;
      align-content: end;
    }
    .wp--ui-portrait .work__title {
      align-self: end;
    }
    .wp--ui-portrait .wp__details {
      min-width: 0;
    }
    .wp--ui-portrait .wp__thumbs {
      align-self: end;
      margin-top: var(--wp-portrait-info-gap);
    }
    .wp--ui-portrait.is-open .wp__details {
      align-self: end;
      max-height: var(--wp-portrait-info-max);
      overflow: auto;
    }
    .wp--ui-landscape .wp__text {
      position: sticky;
      top: var(--wp-sticky-top);
      left: auto;
      right: auto;
      bottom: auto;
      z-index: var(--z-overlay);
      align-self: start;
      display: grid;
      grid-template-columns: max-content minmax(0, var(--measure));
      grid-template-rows: auto auto;
      align-content: end;
      align-items: end;
      column-gap: var(--wp-landscape-thumb-gap);
      justify-self: var(--wp-ui-justify);
      width: auto;
      min-height: calc(100svh - var(--wp-sticky-top) - var(--wp-ui-bottom-gap));
      max-width: calc(100vw - var(--pad-x) * 2);
      margin: 0 var(--wp-ui-inset-right) var(--wp-ui-bottom-gap) var(--pad-x);
      margin-top: 0;
      padding: 0;
      background: none;
      border: 0;
      isolation: isolate;
      pointer-events: none;
    }
    .wp[data-work="vortex-of-trauma"],
    .wp[data-work="volcano"],
    .wp[data-work="odin"],
    .wp[data-work="desert-wind"],
    .wp[data-work="iron-horse"] {
      --wp-ui-justify: start;
      --wp-ui-inset-right: var(--pad-x);
    }
    .wp--ui-landscape .wp__text::before {
      content: "";
      position: absolute;
      inset: -2rem calc(var(--pad-x) * -1) -2rem var(--wp-overlay-reach);
      z-index: 0;
      background: linear-gradient(270deg, var(--wp-overlay-edge) 0%, var(--wp-overlay-mid) 48%, rgb(11 11 11 / 0) 100%);
      opacity: 0;
      pointer-events: none;
      transition: opacity var(--dur-fast) var(--ease);
    }
    .wp--landscape.wp--ui-portrait .wp__text::before {
      content: "";
      position: fixed;
      inset: 0;
      z-index: 0;
      background: linear-gradient(270deg, var(--wp-overlay-edge) 0%, var(--wp-overlay-mid) 46%, rgb(11 11 11 / 0) 84%);
      opacity: 0;
      pointer-events: none;
      transition: opacity var(--dur-fast) var(--ease);
    }
    .wp[data-work="vortex-of-trauma"] .wp__text::before,
    .wp[data-work="volcano"] .wp__text::before,
    .wp[data-work="odin"] .wp__text::before,
    .wp[data-work="desert-wind"] .wp__text::before,
    .wp[data-work="iron-horse"] .wp__text::before {
      inset: -2rem auto -2rem calc(var(--pad-x) * -1);
      width: 100vw;
    }
    .wp--ui-landscape.is-open .wp__text::before {
      opacity: 1;
    }
    .wp--landscape.wp--ui-portrait.is-open .wp__text::before {
      opacity: 1;
    }
    .wp--ui-landscape .wp__text > * {
      position: relative;
      z-index: 1;
    }
    .wp--landscape.wp--ui-portrait .wp__text > * {
      position: relative;
      z-index: 1;
    }
    .wp--ui-landscape .wp__text .work__title {
      grid-column: 2;
      grid-row: 1;
      color: var(--c-work-text);
      mix-blend-mode: difference;
    }
    .wp--ui-landscape .wp__details {
      grid-column: 2;
      grid-row: 2;
      pointer-events: auto;
    }
    .wp--ui-landscape .wp__body {
      color: var(--c-work-text);
      mix-blend-mode: difference;
    }
    .wp--ui-landscape .wp__summary {
      color: var(--c-action-muted);
      mix-blend-mode: difference;
    }
    .wp--ui-landscape .wp__summary:hover,
    .wp--ui-landscape .wp__summary:focus-visible {
      color: var(--c-work-text-hover);
    }
    .wp--ui-landscape .wp__summary { min-width: 10ch; }
    .wp--ui-landscape .wp__body {
      width: 100%;
      max-width: var(--measure);
    }
    .wp--ui-landscape .wp__thumbs {
      grid-column: 1;
      grid-row: 1 / span 2;
      align-self: end;
      width: auto;
      max-width: none;
      margin: 0;
      pointer-events: auto;
    }
    .wp--landscape .wp__nav { padding-inline: var(--pad-x); }
    .wp--ui-landscape .wp__preview {
      padding-right: var(--wp-landscape-preview-edge);
    }
    .wp__thumbs {
      width: calc(100vw - var(--wp-col-x) - var(--pad-x));
      max-width: none;
    }
    .wp__nav {
      margin-top: 40px;
      margin-bottom: 0;
      padding-block-start: 80px;
      padding-inline: var(--pad-x);
    }

    .page-work .footer { margin-top: var(--block); }
  }

  @media (max-width: 63.999rem) {
    .page-work {
      --work-page-h: 84svh;
      --work-paged-h: 84svh;
      --wp-mobile-bar-thumb-gap: 36px;
      --wp-mobile-thumb-title-gap: 44px;
      --wp-thumb-size: 2.75rem;
    }
    .page-work .nav__brand {
      opacity: 0;
      transform: translateX(-0.875rem);
      pointer-events: none;
      transition: opacity var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease), visibility var(--dur-fast) var(--ease);
    }
    .page-work .nav--work-options-open .nav__brand {
      opacity: 1;
      transform: none;
      visibility: visible;
      pointer-events: auto;
    }
    .page-work .nav__right {
      position: absolute;
      inset-inline-end: var(--pad-nav);
      opacity: 0;
      transform: translateX(0.875rem);
      visibility: hidden;
      pointer-events: none;
      transition: opacity var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease), visibility var(--dur-fast) var(--ease);
    }
    .page-work .nav--work-options-open .nav__right {
      opacity: 1;
      transform: none;
      visibility: visible;
      pointer-events: auto;
    }
    .page-work .nav__work-options {
      display: inline-flex;
      align-items: center;
      gap: 0.3125rem;
      padding: 0.625rem;
      margin: -0.625rem;
      transition: opacity var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease), visibility var(--dur-fast) var(--ease);
    }
    .page-work .nav__work-options span {
      width: 0.25rem;
      height: 0.25rem;
      border-radius: 50%;
      background: currentColor;
    }
    .page-work .nav--work-options-open .nav__work-options {
      opacity: 0;
      transform: translateX(-0.5rem);
      visibility: hidden;
      pointer-events: none;
    }
    /* На телефоне детали открываются в галерее, крупный показ не нужен */
    .wp__preview { display: none; }
    .wp__nav-home { display: none; }
    /* Если у работы есть свой мобильный кадр, коробка берёт его пропорции и
       считается от ширины: иначе снимок висел бы в десктопной коробке,
       высота которой задана экраном, с пустыми полями сверху и снизу. */
    .wp__frame--mob {
      aspect-ratio: var(--wp-ratio-mob, var(--wp-ratio, 2 / 3));
      /* Кадр во всю ширину экрана — тем же приёмом, что кадры в ленте на
         главной: ширину даёт растяжение во флексе, за поля страницы кадр
         выводят отрицательные margin. Через 100vw нельзя: эта единица
         включает ширину полосы прокрутки, и на узком окне десктопа
         страница уезжала вбок. max-width снят, иначе базовое 100%
         обрезало бы коробку обратно до колонки. */
      flex: none;
      align-self: stretch;
      width: auto;
      max-width: none;
      height: auto;
      margin-inline: var(--work-bleed);
    }
    /* Горизонтальный кадр на странице работы листается ровно так же, как в
       ленте на главной: сама прокрутка, остановки и полоса приходят из
       правил .work__media--phone-paged, здесь только размеры коробки. */
    .wp__frame--paged {
      aspect-ratio: auto;
      flex: none;
      align-self: stretch;
      width: auto;
      max-width: none;
      height: var(--work-paged-h);
      margin-inline: var(--work-bleed);
    }
    .js .work__media-shell--paged .media-fit-toggle,
    .js .wp__stage > .media-fit-toggle {
      position: absolute;
      inset-block-end: var(--pad-nav);
      inset-inline-end: var(--pad-nav);
      z-index: calc(var(--z-overlay) + 2);
      display: grid;
      place-items: center;
      width: 2.75rem;
      height: 2.75rem;
      color: rgb(255 255 255 / 0.42);
      opacity: 1;
      touch-action: manipulation;
      transition: color var(--dur-fast) var(--ease), opacity var(--dur-fast) var(--ease);
    }
    .js .work__media-shell--paged .media-fit-toggle {
      inset-inline-end: var(--pad-nav);
    }
    .js .wp__stage > .media-fit-toggle {
      inset-inline-end: calc(var(--work-bleed) + var(--pad-nav));
    }
    .js .work__media-shell--paged .media-fit-toggle:hover,
    .js .work__media-shell--paged .media-fit-toggle:focus-visible,
    .js .wp__stage > .media-fit-toggle:hover,
    .js .wp__stage > .media-fit-toggle:focus-visible {
      color: rgb(255 255 255 / 0.42);
    }
    .media-fit-toggle__icon {
      width: 1.5rem;
      height: 1.5rem;
      background: currentColor;
      mask: url("../assets/icons/002-zoom-out.svg") center / contain no-repeat;
    }
    .media-fit-toggle[aria-pressed="true"] .media-fit-toggle__icon,
    .work__media--phone-paged.is-fit-width ~ .media-fit-toggle .media-fit-toggle__icon,
    .wp__frame--paged.is-fit-width + .media-fit-toggle .media-fit-toggle__icon { mask-image: url("../assets/icons/001-zoom-in.svg"); }
    .work__media--phone-paged.is-fit-width,
    .wp__frame--paged.is-fit-width {
      background: var(--c-page-dark);
      overflow: hidden;
      scroll-snap-type: none;
    }
    .work__media--phone-paged.is-fit-width .work__track,
    .wp__frame--paged.is-fit-width .work__track {
      width: 100%;
      height: 100%;
      display: grid;
      place-items: center;
    }
    .work__media--phone-paged.is-fit-width .work__page,
    .wp__frame--paged.is-fit-width .work__page {
      display: none;
    }
    .work__media--phone-paged.is-fit-width picture,
    .wp__frame--paged.is-fit-width picture {
      position: relative;
      inset: auto;
      width: 100%;
      max-width: 100%;
      height: auto;
      justify-self: center;
      align-self: center;
      translate: none;
      transition: transform var(--dur-fast) var(--ease), opacity var(--dur-fast) var(--ease);
    }
    .work__media--phone-paged.is-fit-width img,
    .wp__frame--paged.is-fit-width img {
      width: 100%;
      max-width: 100%;
      height: auto;
    }
    /* Базовое .wp__frame img растянуло бы снимок по ширине коробки и лента
       перестала бы прокручиваться. */
    .wp__frame--paged img {
      width: auto;
      max-width: none;
    }
    /* Кадр и полоса прокрутки идут друг под другом, а не в ряд */
    .wp__stage { flex-direction: column; }
    /* Порядок на телефоне: кадр, миниатюры, название, «Подробнее» */
    .wp__text {
      display: flex;
      flex-direction: column;
      margin-top: var(--wp-mobile-bar-thumb-gap);
    }
    .wp__thumbs {
      order: -1;
      margin-top: 0;
      margin-bottom: var(--wp-mobile-thumb-title-gap);
    }
    /* Описание раскрыто всегда, поэтому строка-переключатель лишняя */
    .wp__summary { display: none; }
    .wp__body .btn { margin-top: 50px; }
    .wp__nav-title { font-size: calc(var(--t-small) - 1px); }
  }
}

/* ==========================================================================
   UTILITIES — только то, что действительно повторяется
   ========================================================================== */
@layer utilities {
  .u-visually-hidden {
    position: absolute !important; /* единственный допустимый !important: утилита-перекрытие */
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }

  .u-mt-block { margin-top: var(--block); }
  .u-mt-block-lg { margin-top: var(--block-lg); }
  .u-center { text-align: center; }
  .u-phone-only { display: inline-block; }
  .u-desktop-only { display: none; }
  @media (min-width: 64rem) {
    .u-phone-only { display: none; }
    .u-desktop-only { display: inline-block; }
  }
  .u-no-scroll { overflow: hidden; }
}
