/* ═══ Адаптивная оболочка веб-клиента MVQ ════════════════════════════════════
 *
 * Один файл на всю оболочку: как продукт выглядит на телефоне и как — на
 * компьютере. Экраны внутри не переписываются ни один: лента, «Обзор»,
 * сообщества, события, профиль, настройки рисуются теми же модулями, что и
 * вчера, и все их адреса и состояния остались на месте. Здесь меняется только
 * то, что вокруг них, — навигация, поля, ритм заголовков и карточек.
 *
 * Подключается ТОЛЬКО из `web.html`. Окно настольной программы (`index.html`)
 * этого файла не грузит, и ни одна строка отсюда его не касается ни при каком
 * размере окна. Откат — снять одну строку из `web.html`.
 *
 * Идёт последним среди стилей: переопределения работают обычным каскадом, по
 * порядку файлов, а не через `!important` и не через раздутые селекторы.
 *
 * # Что здесь решается
 *
 * 1. **Телефон.** Низ — не полка во всю ширину, а два плавающих предмета:
 *    компактная капсула разделов и отдельная кнопка создания. Вокруг них не
 *    должно быть непрозрачной подложки: она превращает плавающий предмет в
 *    приклеенный. Безопасные поля, вырез и клавиатура учитываются везде.
 * 2. **Компьютер.** Слева — навигация в 232 точки: значок и русская подпись у
 *    каждого раздела, ясно видное «вы здесь». Одной кнопкой внизу она
 *    сворачивается до полосы значков и разворачивается обратно; выбор
 *    переживает перезагрузку. По центру — содержимое, которое забирает
 *    освободившееся место, но не растягивает строку текста; справа —
 *    контекст, которого больше нигде нет.
 * 3. **Единый ритм.** Одна высота и одни поля у шапок, одна геометрия у
 *    карточек, один вид у состояний «грузится / пусто / не вышло / нет сети».
 * 4. **Обе темы.** Ни одного своего цвета: всё берётся из токенов, поэтому
 *    светлая, тёмная и «как в системе» получаются сами и не расходятся.
 */

/* ── Токены оболочки: считаются из темы, а не переписываются в третий раз ────
 *
 * ⭐ Здесь чинится настоящая поломка, а не наводится красота.
 *
 * `alpha2.css` задаёт цвета нижней капсулы буквальными числами: светлые на
 * `:root` и тёмные на `:root[data-look-theme="dark"]`. Третьего случая —
 * «тема как в системе, а система тёмная» — там нет вовсе, и у него оставались
 * светлые числа. То есть у человека с системной тёмной темой (это значение по
 * умолчанию, то есть у большинства) поверх тёмной ленты висела **белая
 * непрозрачная капсула**. Ровно то, что видно глазами как «большая светлая
 * подложка внизу».
 *
 * Чинится не четвёртым списком чисел, а отказом от чисел: цвет капсулы — это
 * цвет поверхности, её обводка — линия, заливка активного пункта — мягкая
 * плашка акцента. Все три уже посчитаны токенами для всех трёх случаев темы.
 * Разойтись такому определению не с чем.
 *
 * Селектор `:root` (0,1,0) перебивает одноимённый `:root` из `alpha2.css`
 * порядком файлов. Более сильный `:root[data-look-theme="dark"]` (0,2,0)
 * оттуда остаётся в силе — и это не беда: его числа и есть тёмные токены.
 */
:root {
  --a2-nav-bg: var(--surface);
  --a2-nav-line: var(--line);
  --a2-capsule: var(--accent-soft);
  --a2-capsule-ink: var(--accent-soft-ink);
  --a2-focus: var(--accent);
  --a2-nav-shadow: 0 2px 10px color-mix(in srgb, var(--text) 10%, transparent);

  /* Ширина свёрнутой навигации. Не «сколько влезло»: 76 — это кнопка 52 плюс
   * по 12 полей с каждой стороны, ровно столько, чтобы значок стоял по центру,
   * а не жался к краю. */
  --rail-w: 76px;

  /* Просвет между капсулой и кнопкой создания. Достаточный, чтобы читались
   * как два предмета, и недостаточный, чтобы промахнуться между ними. */
  --dock-gap: 12px;
}

/* Геометрия низа. Числа те же, что в `pwa-shell.css`, — он их и объявляет;
 * здесь пересчитана только высота, от которой всё остальное отмеряет себя.
 *
 * 60 = кнопка 48 + поля капсулы 5×2 + обводка 1×2. Кнопка создания (56) в эту
 * высоту укладывается, и место под низ ленты остаётся верным для обоих
 * предметов сразу. Считать `--nav-h` по формуле из `pwa-shell.css` нельзя:
 * она не знает про обводку, и последняя строка ленты залезала бы под капсулу
 * ровно на два пикселя — то есть выглядела бы обрезанной. */
:root {
  --nav-btn: 48px;
  --nav-pad: 5px;
  --nav-h: 60px;
}

/* ═══ Телефон ═══════════════════════════════════════════════════════════════ */

/* Пристань собирается только в веб-клиенте (`social.js`, `нижняяПристань`).
 * Выше 900 её нет: там работает рейка. */
.a2-dock { display: none; }

@media (max-width: 900px) {
  .a2-dock {
    display: flex;
    align-items: center;
    gap: var(--dock-gap);
    position: fixed;
    left: 50%;
    transform: translateX(-50%);
    /* Над полосой жестов iPhone и над вырезом в альбомной ориентации. */
    bottom: calc(var(--nav-gap) + var(--safe-b));
    z-index: 40;
    max-width: calc(100vw - 16px - var(--safe-l) - var(--safe-r));
    /* Просвет между капсулой и кнопкой — это просвет, а не третий предмет:
     * нажатие в него проходит насквозь в ленту. */
    pointer-events: none;
  }
  .a2-dock > * { pointer-events: auto; }

  /* ── Капсула разделов ──────────────────────────────────────────────────────
   *
   * Была растянута до `min(100vw - 24px, 420px)` — то есть почти во всю
   * ширину экрана, с четырьмя значками, разъехавшимися по её краям. Это уже
   * не капсула, а полка, только со скруглениями.
   *
   * Стала ровно по своему содержимому. Плавающий предмет читается плавающим
   * тогда, когда под ним видно то, над чем он плавает, — поэтому заливка
   * полупрозрачная с размытием, а отделяет её от ленты тень, а не подложка
   * вокруг. */
  .a2-nav {
    position: static;
    transform: none;
    bottom: auto;
    width: auto;
    max-width: 100%;
    min-width: 0;
    justify-content: flex-start;
    gap: 2px;
    padding: var(--nav-pad);
    background: color-mix(in srgb, var(--a2-nav-bg) 84%, transparent);
    -webkit-backdrop-filter: saturate(150%) blur(18px);
    backdrop-filter: saturate(150%) blur(18px);
    border: 1px solid color-mix(in srgb, var(--a2-nav-line) 72%, transparent);
    box-shadow:
      0 10px 30px color-mix(in srgb, #000 24%, transparent),
      0 2px 6px color-mix(in srgb, #000 14%, transparent);
  }

  /* Размытия может не быть (старый браузер, выключено в настройках) — тогда
   * заливка обязана стать честной, иначе сквозь капсулу читается лента и
   * подписи наезжают на текст записи. */
  @supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    .a2-nav { background: var(--a2-nav-bg); }
  }

  /* Просили меньше прозрачности — отдаём сплошную капсулу. Это та же просьба,
   * что и про шапку в `pwa-shell.css`, и ответ на неё должен быть тот же. */
  @media (prefers-reduced-transparency: reduce) {
    .a2-nav {
      background: var(--a2-nav-bg);
      -webkit-backdrop-filter: none;
      backdrop-filter: none;
    }
  }

  /* ── Ровный ряд значков ────────────────────────────────────────────────────
   *
   * Значки — 21 точка, лицо в «Профиле» — 24. В общем ряду четвёртый пункт
   * стоял шире и выше соседей, и ряд читался покосившимся. Клетка постоянного
   * размера ставит их на одну линию: и значок, и лицо центрируются в ней, а
   * высоту строки не диктует ни тот, ни другое. */
  .a2-nav button {
    min-width: var(--nav-btn);
    min-height: var(--nav-btn);
    padding: 0 8px;
    gap: 8px;
    /* Неактивные не сжимаются: зона нажатия — не то, чем платят за длинную
     * подпись соседа. Сжимается подпись активного, и только она. */
    flex: none;
  }
  .a2-nav button.active { flex: 0 1 auto; min-width: 0; }

  .a2-nav .a2-glyph {
    flex: none;
    width: 24px; height: 24px;
    display: grid; place-items: center;
  }
  .a2-nav .a2-glyph .ic { width: 22px; height: 22px; }
  .a2-nav .a2-ava { width: 22px; height: 22px; }

  /* Подпись активного пункта обрезается многоточием, а не выталкивает соседей
   * за край экрана. Это единственное место капсулы, которое имеет право
   * ужаться: при двукратном тексте «Сообщества» шире трёх кнопок. */
  .a2-nav button.active .a2-label {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  /* ── Отдельная кнопка создания ─────────────────────────────────────────────
   *
   * Не пятый пункт капсулы. Пункт навигации отвечает на вопрос «где я»,
   * кнопка — на вопрос «что сделать»; в одном ряду они читаются как пять
   * равных разделов, и человек ищет среди них несуществующий «раздел
   * Создать». Отдельная залитая кнопка говорит о себе сама и не отнимает у
   * четырёх разделов ширину, которой на 320 точках и так впритык. */
  .a2-new {
    flex: none;
    width: 56px; height: 56px;
    display: grid; place-items: center;
    border: 0;
    border-radius: 50%;
    background: var(--accent);
    color: var(--accentText);
    cursor: pointer;
    box-shadow:
      0 10px 26px color-mix(in srgb, var(--accent) 40%, transparent),
      0 2px 6px color-mix(in srgb, #000 18%, transparent);
    transition: transform var(--fast) ease, background var(--fast) ease;
  }
  .a2-new .ic { width: 26px; height: 26px; }
  .a2-new:hover { background: var(--accent-hover); }
  .a2-new:active { transform: scale(.94); }
  @media (prefers-reduced-motion: reduce) {
    .a2-new { transition: none; }
    .a2-new:active { transform: none; }
  }

  /* Клавиатура вылезла — низа нет целиком, вместе с кнопкой создания.
   * `visibility`, а не `display`: скрытое через `display` теряет место в
   * порядке обхода, и диктор перестаёт находить навигацию совсем. */
  :root[data-kb="1"] .a2-dock {
    visibility: hidden;
    pointer-events: none;
  }
}

/* Узкий экран: 320 точек — это четыре пункта, кнопка создания и просвет.
 * Считано, а не подобрано: 12 (поля капсулы с обводкой) + 3×44 + 6 (просветы)
 * + активный пункт с подписью ≈ 240, плюс просвет 8 и кнопка 48 = 296 при
 * доступных 304. */
@media (max-width: 400px) {
  .a2-dock { gap: 8px; max-width: calc(100vw - 12px - var(--safe-l) - var(--safe-r)); }
  .a2-nav { gap: 0; padding: 4px; }
  .a2-nav button { min-width: 44px; padding: 0 4px; gap: 4px; }
  .a2-nav button.active { padding: 0 8px; }
  .a2-nav button.active .a2-label { max-width: 7em; }
  .a2-new { width: 48px; height: 48px; }
  .a2-new .ic { width: 24px; height: 24px; }
}

/* ── Шапка на телефоне ───────────────────────────────────────────────────────
 * Одни поля со списком под ней: заголовок, стоящий левее первой карточки,
 * читается как чужой. */
@media (max-width: 900px) {
  .social-head { padding: 0 12px; gap: 8px; }
  .social-head { padding-left: max(12px, var(--safe-l)); padding-right: max(12px, var(--safe-r)); }

  /* Плюс в шапке на телефоне больше не нужен.
   *
   * Он появился там, когда создание убрали из капсулы и у него не осталось ни
   * одной постоянной двери. Теперь дверь есть, и она заметнее любого значка в
   * шапке — залитая кнопка внизу, под большим пальцем. Две двери в одно и то
   * же на экране в 320 точек — это отнятая у заголовка и отборов ширина, а не
   * забота.
   *
   * `!important` здесь вынужденно: в `alpha2.css` эта кнопка показана таким же
   * образом, и обычным каскадом его не перебить. Случай ровно тот, ради
   * которого исключение и делают, — отмена чужого `!important`, а не победа в
   * споре о специфичности. */
  .social-head .head-compose { display: none !important; }
}

/* ═══ Компьютер ═════════════════════════════════════════════════════════════ */

/* ── Ширина левой колонки ────────────────────────────────────────────────────
 *
 * Раньше здесь была рейка значков и только она. Значки без подписей — это
 * девять одинаковых квадратов: человек, открывший ленту впервые, читает их
 * гаданием, а не глазами, и «Связи» от «Сообществ» отличает наведением
 * указателя. Поэтому по умолчанию колонка широкая и подписанная, а рейка
 * никуда не делась — она стала выбором человека, а не единственной раскладкой.
 *
 * 232 — не «сколько влезло». Задание просит 220–240, а внутри это 12 полей +
 * 24 значок + 12 просвет и до 172 точек на подпись. При обычном размере букв
 * туда с запасом ложится самое длинное имя раздела; при самом крупном
 * (`--scale: 1.26`) «Сообщения» со счётчиком непрочитанного упирается в край и
 * получает многоточие — и это осознанный размен, а не недосмотр: имя целиком
 * остаётся в `title` и `aria-label`, а расширять колонку ради одного случая
 * значит отнимать ширину у ленты во всех остальных.
 *
 * Ширина живёт в одном месте — `--nav-w`, — и её же читает сетка `.social`:
 * одно число на колонку и на её место в сетке, разойтись нечему.
 * Переключается она признаком `data-nav` на корне страницы
 * (`js/shell-nav.js`), а не классом на самой колонке: сетка `.social` —
 * предок колонки, и класс на колонке до неё бы не дотянулся.
 *
 * Сценария нет вовсе (не доехал, выключен) — признака на корне тоже нет, и
 * колонка остаётся широкой и подписанной. Ничего не ломается: пропадает
 * только возможность её свернуть.
 */
:root {
  --nav-wide: 232px;
  --nav-w: var(--nav-wide);
}
:root[data-nav="rail"] { --nav-w: var(--rail-w); }

@media (min-width: 901px) {
  /* ── Общее для обеих раскладок ─────────────────────────────────────────── */

  /* Тканый узор внизу колонки снят в обеих раскладках. На 76 точках от него
   * оставалась полоска шума, а на 232 он приходится ровно на низ столбца — то
   * есть под свою карточку и под переключатель, под текст. Правило у продукта
   * на этот счёт своё и давнее: под длинным текстом и полями узора нет, там он
   * мешает читать. */
  .social-nav::after { display: none; }

  .social-nav {
    gap: 2px;
    padding: 16px 12px 12px;
    border-right: 1px solid var(--line);
    /* Ширину диктует сетка; колонка не растягивается своим содержимым и не
     * заводит вторую полосу прокрутки под ним. */
    overflow-x: hidden;
    overflow-y: auto;
  }

  .social-nav-btn {
    position: relative;
    flex: none;
    border-radius: var(--radius);
  }

  /* Создание — одна и та же залитая кнопка в обеих раскладках и на телефоне:
   * человек, привыкший к одной, не ищет её во второй заново. Меняется только
   * форма — строка со словом или квадрат со значком (ниже).
   *
   * ⚠️ Наведение написано сокращённым `background`, и это важно: `brand.css`
   * кладёт на кнопку фирменную ось `background-image` и повторяет её в своём
   * правиле наведения ровно потому, что сокращённая запись здесь сбрасывает
   * картинку. Развернуть это в `background-color` значило бы тихо удвоить
   * ось под указателем. */
  .rail-new {
    flex: none;
    border: 0;
    background: var(--accent);
    color: var(--accentText);
    cursor: pointer;
    box-shadow: 0 6px 18px color-mix(in srgb, var(--accent) 30%, transparent);
    transition: background var(--fast) ease;
  }
  .rail-new:hover { background: var(--accent-hover); }

  /* Выбранное отличается тремя вещами сразу — заливкой, цветом буквы и
   * волосяной обводкой. Одним цветом состояние передавать нельзя: часть людей
   * его не увидит, а на мягкой плашке в тёмной теме разница с соседями и без
   * того невелика.
   *
   * Заливка мягкая, а не сплошная акцентная, как в `app.css`: сплошная плашка
   * во всю строку на 232 точках читается как выделенный мышью текст, а не как
   * «вы здесь», и рядом с залитой кнопкой «Создать» их становится две ярких.
   *
   * Обводка нарисована внутренней тенью, а не полоской у края колонки: полоска
   * у левого края встаёт вплотную к границе окна и читается обрезанным
   * значком, а не отметкой. Тень же не занимает места и одинаково работает и в
   * широкой колонке, и в свёрнутой. */
  .social-nav-btn.active {
    background: var(--accent-soft);
    color: var(--accent-soft-ink);
    font-weight: 650;
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 30%, transparent);
  }
  .social-nav-btn.active .ic { color: var(--accent-soft-ink); }

  /* Счётчик непрочитанного. В широкой колонке — числом в конце строки, в
   * рейке — меткой на значке (ниже): в рейке конца строки нет. */
  .social-nav-btn .badge { flex: none; }

  /* Своя карточка и переключатель прижаты к низу: это не разделы ленты, а
   * вход в себя и настройка самой колонки. Пустое место между разделами и
   * ними — не отступ, а остаток высоты окна, поэтому `margin-top: auto`. */
  .social-nav .social-me { margin: auto 0 0; }

  /* ── Свернуть/развернуть ───────────────────────────────────────────────────
   *
   * Кнопку ставит `js/shell-nav.js` последним ребёнком колонки. Стоит она
   * внизу, потому что это настройка колонки, а не раздел ленты: наверху она
   * соперничала бы вниманием с «Создать» и с первым разделом. */
  .nav-fold {
    /* Точка отсчёта для слова, спрятанного в свёрнутой колонке (ниже). */
    position: relative;
    flex: none;
    display: flex; align-items: center; gap: 12px;
    min-height: 44px; padding: 8px 12px 0;
    /* Волосок отделяет настройку колонки от разделов ленты. Он же — нижняя
     * граница всего столбца: ниже неё в колонке ничего нет. */
    margin-top: 8px;
    border: 0; border-top: 1px solid var(--line); border-radius: 0;
    background: transparent; color: var(--muted); text-align: left;
    font-size: var(--fs-sm);
    cursor: pointer;
  }
  .nav-fold:hover { background: var(--surface2); color: var(--text); }
  .nav-fold .ic { flex: none; width: 20px; height: 20px; color: inherit; }
  .nav-fold .grow { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

  /* Ширина колонки едет плавно, а не прыгает: человек должен видеть, что
   * колонка сворачивается, а не что страница перерисовалась. Просьбу
   * двигаться меньше выполняют токены — они сводят `--mid` к нулю. */
  .social { transition: grid-template-columns var(--mid) var(--ease); }

  /* ── Широкая колонка: значок и подпись ─────────────────────────────────── */

  /* Знак с именем продукта — во всю ширину, как в макете. */
  :root:not([data-nav="rail"]) .social-brand {
    justify-content: flex-start;
    padding: 2px 4px 16px;
  }
  :root:not([data-nav="rail"]) .social-brand .mvq-mark { height: 30px; width: auto; }

  /* Создание — залитая кнопка во всю ширину и со словом. Слово уже лежит в
   * разметке (`social.js`, `rail-word`) — в рейке оно спрятано для диктора,
   * здесь просто перестаёт прятаться. */
  :root:not([data-nav="rail"]) .rail-new {
    width: 100%; height: 44px;
    display: flex; align-items: center; justify-content: center; gap: 12px;
    margin-bottom: 12px;
    border-radius: var(--radius);
  }
  :root:not([data-nav="rail"]) .rail-new .ic { width: 20px; height: 20px; }
  :root:not([data-nav="rail"]) .rail-word {
    position: static;
    width: auto; height: auto;
    overflow: visible;
    clip-path: none;
    font-size: var(--fs-md); font-weight: 650;
  }

  /* Разделы: значок, просвет 12, подпись. Строка 44, а не 48: на ноутбуке с
   * 768 точками высоты десять разделов вместе со знаком, кнопкой создания,
   * своей карточкой и переключателем занимают ~700 точек и оставляют запас; с
   * рядами по 48 столбец упирается в нижний край и начинает прокручиваться на
   * самой частой высоте экрана. Прокрутка у колонки есть и никуда не делась —
   * но она для крайних случаев, а не для обычного ноутбука. */
  :root:not([data-nav="rail"]) .social-nav-btn {
    width: 100%; min-height: 44px;
    justify-content: flex-start;
    gap: 12px;
    padding: 0 12px;
    font-size: var(--fs);
  }
  /* Подпись занимает остаток строки и обрезается многоточием: длинное имя
   * раздела не имеет права выталкивать счётчик за край колонки. */
  :root:not([data-nav="rail"]) .social-nav-btn .grow {
    display: block;
    min-width: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  :root:not([data-nav="rail"]) .social-nav-btn .ic { flex: none; }

  /* Своя карточка целиком: лицо, имя, короткий адрес и шеврон. */
  :root:not([data-nav="rail"]) .social-nav .social-me {
    width: 100%; min-height: 56px;
    padding: 8px 12px;
    justify-content: flex-start; gap: 12px;
  }
  :root:not([data-nav="rail"]) .social-nav .social-me .grow { display: block; min-width: 0; }
  :root:not([data-nav="rail"]) .social-nav .social-me .ic { display: block; flex: none; }

  /* ── Свёрнутая колонка: одни значки ────────────────────────────────────── */

  :root[data-nav="rail"] .social-nav { align-items: center; padding: 16px 12px 12px; }

  /* Знак без имени продукта. Обрезает его не CSS, а признак
   * `preserveAspectRatio="xMinYMid slice"`, который ставит `js/shell-nav.js`:
   * поле знака в рисунке — ровно первые 48 единиц из 152, и при таком признаке
   * квадрат 32×32 показывает ровно их. Ужать рисунок шириной было нельзя — он
   * съехал бы в середину и уменьшился втрое. */
  :root[data-nav="rail"] .social-brand { justify-content: center; padding: 2px 0 12px; }
  :root[data-nav="rail"] .social-brand .mvq-mark { width: 32px; height: 32px; }

  :root[data-nav="rail"] .rail-new {
    /* Точка отсчёта для спрятанного слова: без неё `position: absolute`
     * цепляется за первого попавшегося предка с позицией и уезжает из
     * кнопки в неизвестном направлении. */
    position: relative;
    width: 52px; height: 52px;
    margin-bottom: 8px;
    display: grid; place-items: center;
    border-radius: var(--r-lg);
  }
  :root[data-nav="rail"] .rail-new .ic { width: 24px; height: 24px; }
  /* Слово «Создать» есть в разметке ради диктора и поиска по странице, но на
   * рейке для него нет ширины: значок плюса не нуждается в переводе. */
  :root[data-nav="rail"] .rail-word {
    position: absolute;
    width: 1px; height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  :root[data-nav="rail"] .social-nav-btn {
    width: 52px; min-height: 48px;
    justify-content: center;
    padding: 0;
    border-radius: var(--r-lg);
  }
  :root[data-nav="rail"] .social-nav-btn .grow { display: none; }
  /* Счётчик непрочитанного — меткой на значке: строки, в конце которой он мог
   * бы встать, здесь нет. */
  :root[data-nav="rail"] .social-nav-btn .badge {
    position: absolute; top: 3px; right: 5px;
    min-width: 17px; height: 17px; padding: 0 4px;
    display: grid; place-items: center;
    border-radius: var(--r-sm);
    background: var(--bad); color: #fff;
    font-size: 10px; font-weight: 700;
  }

  /* Своё лицо — кружком внизу рейки. */
  :root[data-nav="rail"] .social-nav .social-me {
    width: 52px; min-height: 52px;
    padding: 0;
    justify-content: center;
  }
  :root[data-nav="rail"] .social-nav .social-me .grow,
  :root[data-nav="rail"] .social-nav .social-me .ic { display: none; }
  :root[data-nav="rail"] .social-me .face { display: grid; place-items: center; }

  :root[data-nav="rail"] .nav-fold {
    width: 52px; min-height: 44px;
    justify-content: center;
    margin-top: 4px; padding: 0;
    border-top: 0;
    border-radius: var(--r-lg);
  }
  :root[data-nav="rail"] .nav-fold .grow {
    position: absolute;
    width: 1px; height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  /* ── Колонки ───────────────────────────────────────────────────────────────
   *
   * Правая колонка возвращается не «с 1080», а когда после неё центру
   * остаётся не меньше 680 точек — ширины чтения из брифа. С широкой
   * навигацией это 232 + 680 + 320 ≈ 1240, со свёрнутой — 76 + 680 + 320 ≈
   * 1080. Отсюда две ступени, а не одна: свернувший навигацию получает
   * контекст раньше — ровно за то, чем заплатил.
   *
   * ⚠️ Правило «нечего сказать — колонки нет» (`no-side`, его ставит
   * `social.js`) выписано в каждой ступени своей парой, и это не копипаста.
   * `:root[data-nav="rail"] .social` — это (0,2,1), то есть сильнее простого
   * `.social.no-side` (0,2,0); без одноимённой пары внутри ступени пустая
   * правая колонка отвоевала бы себе место обратно. `!important` для этого не
   * нужен — нужна равная специфичность. */
  .social, .social.no-side { grid-template-columns: var(--nav-w) minmax(0, 1fr); }
  .social-side { display: none; }
}

@media (min-width: 1080px) {
  :root[data-nav="rail"] .social {
    grid-template-columns: var(--nav-w) minmax(0, 1fr) minmax(0, var(--side));
  }
  :root[data-nav="rail"] .social-side { display: grid; }
  :root[data-nav="rail"] .social.no-side { grid-template-columns: var(--nav-w) minmax(0, 1fr); }
  :root[data-nav="rail"] .social.no-side .social-side { display: none; }
}

@media (min-width: 1240px) {
  .social { grid-template-columns: var(--nav-w) minmax(0, 1fr) minmax(0, var(--side)); }
  .social-side { display: grid; }
  .social.no-side { grid-template-columns: var(--nav-w) minmax(0, 1fr); }
  .social.no-side .social-side { display: none; }
}

/* ═══ Единый ритм: шапки, поля, карточки ════════════════════════════════════ */

/* Шапка отделена от содержимого волоском, а не пустотой. Пока лента наверху,
 * его не видно — он совпадает с фоном; как только начинается прокрутка, под
 * размытой шапкой появляется граница, и заголовок перестаёт висеть в воздухе
 * поверх едущего текста. */
.social-head {
  box-shadow: 0 1px 0 color-mix(in srgb, var(--line) 65%, transparent);
}

@media (min-width: 901px) {
  /* Одни поля у шапки и у страницы под ней. Разные — это первое, что видно
   * глазом: заголовок стоит левее первой карточки, и обе кажутся чужими. */
  .social-head { padding: 0 24px; }
  .social-page { padding: 12px 24px 32px; }
}

/* Карточки одной геометрии.
 *
 * `.post` и `.side-card` рисовались рамкой и радиусом `--r-lg`, а `.card` —
 * без рамки и с радиусом `--radius × 1.2`. На одном экране (например, в
 * настройках рядом с лентой) видно два разных вида карточки, и разница ничего
 * не значит. Здесь она снимается — но только внутри страниц ленты: окна,
 * листы и меню собраны из тех же классов, и трогать их этот срез не
 * собирался. */
.social-page > .social-page-inner > .card,
.social-page > .social-page-inner > * > .card,
.social-page .settings-body > .card {
  padding: 2px 16px;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
}

/* ── Состояния: грузится, пусто, не вышло, нет сети ──────────────────────────
 *
 * Четыре разных ответа на «почему здесь ничего нет», и человек должен видеть
 * разницу между ними, не вчитываясь. Общее у них — место и ритм: один отступ,
 * один размер значка, одна ширина строки. Разное — сам значок и слова, их
 * ставят экраны. */
.social-page .state {
  padding: 44px 20px;
  gap: 12px;
}
.social-page .state .ic.lg {
  width: 32px; height: 32px;
  opacity: .75;
}
.social-page .state strong { font-size: var(--fs-md); font-weight: 650; }
.social-page .state p { max-width: 46ch; }
.social-page .state .btn { margin-top: 4px; }

/* Заглушки не должны мигать у тех, кто просил не мигать. Движение здесь
 * не украшение — оно говорит «идёт загрузка», — поэтому вместо анимации
 * остаётся спокойная заливка, а не пустое место. */
@media (prefers-reduced-motion: reduce) {
  .skeleton {
    animation: none;
    background: var(--surface2);
  }
}

/* ── Оформление в настройках ─────────────────────────────────────────────────
 * Строка «название — описание — ряд значений». На узком экране ряд значений
 * уходит под описание: втиснутый в остаток строки, он превращается в
 * горизонтальную прокрутку из трёх слов. */
.look-row { flex-wrap: wrap; align-items: flex-start; }
.look-row > .grow { min-width: 12em; }
.look-row .chips { flex: 0 1 auto; flex-wrap: wrap; gap: 8px; }
@media (max-width: 620px) {
  .look-row .chips { width: 100%; }
}
