/* mail-thread — чтение разговора. Стили этого куска почты складывают сюда, а
   не в app.css: над разделом работают в несколько рук, и общий файл означает,
   что правки затирают друг друга.

   Лист подключён **после** `app.css` (см. `web/index.html`), поэтому правила
   с той же силой отсюда перекрывают тамошние. Ради этого он и подключён
   последним: старые правила разговора никуда не делись, они просто уточняются
   здесь. */

/* ---------- тело письма: свой текст, цитата, подпись ---------- */

.mail-text { display: flex; flex-direction: column; gap: 6px; }
/* Спрятанный кусок письма обязан пропасть: `display: flex` сильнее
   браузерного правила для `[hidden]`, и без этого текст оставался бы на
   экране рядом с рамкой «как в почте». */
.mail-text[hidden] { display: none; }

/* Подпись — приглушённая и мельче. Она остаётся только в виде «письмами»
   (в чат-виде её не рисуют вовсе), и там читают её редко: реквизиты нужны,
   когда за ними пришли, а не в каждом письме разговора. */
.mail-body--sign {
  font-size: 12.5px; line-height: 1.45; color: var(--text-faint);
  padding-top: 6px; border-top: 1px solid var(--border);
}
/* Черта над подписью в своём пузыре — из чернил самого пузыря, а не белая.
   Белая была верна, пока свой пузырь был синим; в светлой теме он зелёный и
   светлее любой белой вуали, и черта пропадала совсем — 1,01 к пузырю, то
   есть ничего. Стало 1,50.

   `--chat-out-text` разведён по темам сам, и вуаль из него сама разворачивается
   в нужную сторону. Про долю см. разбор у кнопки цитаты ниже. */
.mail-msg--out .mail-body--sign {
  color: var(--chat-out-faint);
  border-top-color: color-mix(in srgb, var(--chat-out-text) 20%, transparent);
}

/* Ссылка в письме — живая ссылка, а не синий текст: её нажимают. Подчёркиваем
   не всегда, а по наведению: в письме ссылок бывает десяток подряд (подпись с
   сайтом, соцсети, отписка), и десять подчёркнутых строк читаются как забор. */
.mail-link { color: var(--accent-text); text-decoration: none; word-break: break-word; }
.mail-link:hover { text-decoration: underline; }
.mail-body a { color: var(--accent-text); word-break: break-word; }
.mail-msg--out .mail-body a, .mail-msg--out .mail-link { color: inherit; text-decoration: underline; }

/* Цитата за многоточием — приём Gmail. Кнопка мелкая и серая: это не действие,
   а свёрнутый кусок текста, и выглядеть кнопкой действия она не должна. */
.mail-quote { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }
.mail-quote__dots {
  padding: 0 7px; line-height: 15px; min-height: 17px;
  border: 0; border-radius: 9px; cursor: pointer;
  background: var(--surface-3, var(--surface-2)); color: var(--text-faint);
  font: inherit; font-size: 13px; letter-spacing: 1px;
  transition: background-color var(--speed), color var(--speed);
}
.mail-quote__dots:hover { background: var(--accent-soft); color: var(--accent-text); }
.mail-quote__dots.is-open { background: var(--accent-soft); color: var(--accent-text); }
/* Сама цитата — полоской слева, как везде в проекте: по ней видно, где чужой
   текст кончается, без чтения самого текста. */
.mail-quote__text, .mail-quote__html {
  border-left: 2px solid var(--border-strong);
  padding-left: 9px; color: var(--text-soft); font-size: 13px;
}
/* Цитата письма разметкой (`htmlQuoteNode`) — во всю ширину листа: колонка
   `.mail-quote` выравнивает детей по левому краю и сжала бы её до слова. */
.mail-quote__html { align-self: stretch; }
/* В своём пузыре серое из общей палитры не читается — цвета берём от самого
   пузыря. Раньше вуаль была полупрозрачной белой, и это было верно, пока свой
   пузырь был синим. В светлой теме он зелёный и светлее любой белой вуали:
   кнопка цитаты и полоска цитаты растворялись в подложке — 1,01 и 1,02 к
   пузырю, то есть не видно вовсе.

   Теперь вуаль из чернил пузыря: `--chat-out-text` разведён по темам сам —
   на светлой он тёмный, на тёмной почти белый, — и вуаль сама разворачивается
   в нужную сторону. Светлая получает видимую плашку: 1,01 → 1,44 у кнопки,
   1,02 → 2,13 у полоски цитаты.

   Доли выросли на пару пунктов против прежних (16 → 18, 28 → 31, 32 → 35), и
   это не вкусовая правка, а возврат к прежнему. Чернила тёмной темы не чистый
   белый, а #EDEEF0, и та же доля дала бы вуаль слабее, чем была: 1,53 против
   1,53, 2,04 против 2,03, 2,24 против 2,24 — с добавкой тёмная тема остаётся
   ровно там, где стояла. */
.mail-msg--out .mail-quote__dots {
  background: color-mix(in srgb, var(--chat-out-text) 18%, transparent);
  color: var(--chat-out-text);
}
.mail-msg--out .mail-quote__dots:hover,
.mail-msg--out .mail-quote__dots.is-open {
  background: color-mix(in srgb, var(--chat-out-text) 31%, transparent);
}
.mail-msg--out .mail-quote__text {
  border-left-color: color-mix(in srgb, var(--chat-out-text) 35%, transparent);
  color: inherit; opacity: .85;
}

/* ---------- пузырь разворачивается нажатием ----------

   Роман: «сделай это по клику на пузырик, не отдельной графой показать полную
   форму, а просто клик. Так работает Spike». Мишень — весь пузырь целиком,
   поэтому у длинного развёрнутого письма работает и его верх.

   Рука-указатель стоит только там, где есть что разворачивать: на письме без
   цитаты и подписи она обещала бы несуществующее. Само же тело письма
   выделяется мышью и внутри мишени — номер счёта из него копируют, и
   `cursor: text` там обязан остаться (нажатие с выделением пузырь не трогает,
   это разведено в `mailMessage.js`). */
.mail-msg__bubble--more { cursor: pointer; }
.mail-msg__bubble--more .mail-body { cursor: text; }
/* Подсказка о том, что письмо не всё, — тенью, а не значком и не строкой:
   значок в пузыре занял бы место у текста, а строка была бы той самой
   «отдельной графой», от которой просили уйти.

   Высота тут покойная (`--shadow`), а не наведённая: пузырь под курсором
   должен едва оторваться от ленты — подсказку несёт кольцо, тень только
   отделяет край. */
.mail-msg__bubble--more:hover {
  box-shadow: var(--shadow), 0 0 0 1px var(--accent-soft);
}
.mail-msg__bubble--more.is-open:hover { box-shadow: var(--shadow); }
.mail-msg__text { display: block; }

/* Многоточие «письмо показано не целиком» — тот же знак, что у свёрнутой
   цитаты, и все его цвета (в том числе в своём тёмном пузыре) достаются ему
   от неё. Стоит отдельной строкой под текстом: внутри строки его прочли бы
   как часть фразы, а не как кнопку. */


/* ---------- разговор по-гугловски: свёрнутые строчки ---------- */

/* Между письмами меньше воздуха, чем было: строчек в разговоре теперь семь, и
   прежние 12 точек между ними растягивали разговор на лишний экран. */
.mail-feed--letters { gap: 7px; }
.mail-slot { display: block; }

.mail-letter--folded { padding: 0; overflow: hidden; }
.mail-letter--folded:hover { border-color: var(--border-strong); }
.mail-letter__row {
  display: flex; align-items: center; gap: 9px; width: 100%;
  padding: 7px 14px; border: 0; background: none; cursor: pointer;
  font: inherit; text-align: left; color: var(--text);
}
/* Лицо в свёрнутой строчке мельче: тридцать четыре точки задавали бы строке
   рост карточки, а вся её польза в том, что она низкая. */
.mail-letter__row .mail-face { width: 24px; height: 24px; font-size: 11px; }
.mail-letter__rowname {
  flex: 0 0 auto; max-width: 34%; font-weight: 600; font-size: 13px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mail-letter--folded.is-new .mail-letter__rowname { color: var(--accent-text); }
/* Первые слова — одной строкой и без переноса: строчка обязана остаться
   строчкой, иначе свёрнутое письмо занимает столько же, сколько развёрнутое. */
.mail-letter__rowsnip {
  flex: 1; min-width: 0; font-size: 13px; color: var(--text-faint);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Дата и время — одной строкой и целиком: «31.08, 10:27» перенесённое
   пополам читается двумя разными числами. Цифры моноширинные, чтобы столбец
   дат в списке карточки стоял ровно, а не плясал на единицах. */
.mail-letter__rowtime {
  flex: 0 0 auto; font-size: 11.5px; color: var(--text-faint);
  white-space: nowrap; font-variant-numeric: tabular-nums;
}
.mail-letter__row .icon { flex: 0 0 auto; color: var(--text-faint); }

/* Шапка развёрнутого письма нажимается и сворачивает его — как в Gmail.
   Другого места для этого нет: кнопка «свернуть» в углу карточки читалась бы
   как «закрыть», а закрывать здесь нечего. */
.mail-letter__head { cursor: pointer; align-items: center; }

/* Полная шапка «От / Кому / Копия / Когда» — по стрелке. Нужна она раз в
   месяц (проверить, ушла ли копия бухгалтеру), а место занимала в каждом
   письме. */
.mail-letter__more {
  flex: 0 0 auto; width: 24px; height: 24px; display: grid; place-items: center;
  border: 0; border-radius: 7px; background: none; cursor: pointer;
  color: var(--text-faint);
  transition: background-color var(--speed), color var(--speed), transform var(--speed);
}
.mail-letter__more:hover { background: var(--surface-2); color: var(--accent-text); }
.mail-letter__more.is-open { transform: rotate(180deg); color: var(--accent-text); }
.mail-letter__details {
  margin: 0 0 10px; padding: 8px 10px; border-radius: 9px;
  background: var(--surface-2); color: var(--text-soft);
  font-size: 12.5px; line-height: 1.6;
  word-break: break-word;
}
.mail-letter__details b { color: var(--text-faint); font-weight: 600; }

/* ---------- строка ответа: кнопка сжимается до значка ----------

   Пустое поле — кнопка со словом: по одному бумажному самолётику человек не
   догадывается, что отсюда уходит письмо, а не сообщение в чат. Пошёл текст —
   слово уезжает, и сотня точек ширины достаётся строке, ровно когда она
   нужнее всего.

   Сжимается слово, а не кнопка: у слова свой потолок ширины, и переход идёт
   по нему. Ширину самой кнопки не трогаем — она считается от содержимого, и
   разметка прыгала бы на каждой букве. */
.mail-reply__send { gap: 0; }
.mail-reply__word {
  display: inline-block; overflow: hidden; white-space: nowrap;
  max-width: 90px; margin-left: 7px; opacity: 1;
  transition: max-width 180ms ease, margin-left 180ms ease, opacity 110ms ease;
}
.mail-reply.is-typing .mail-reply__word { max-width: 0; margin-left: 0; opacity: 0; }

/* Движение выключаем тем, кто просил его выключить. Правило системное, и
   почта — не то место, где его стоит обходить. */
@media (prefers-reduced-motion: reduce) {
  .mail-reply__word { transition: none; }
  .mail-letter__more { transition: none; }
  .mail-letter__acts { transition: none; }
}

/* Выход из разговора. На столе его нет: список стоит рядом, и стрелка «назад»
   отвечала бы на вопрос, которого никто не задаёт. Показывается она в
   `mail-phone.css`, где разговор ложится поверх списка и выйти иначе нельзя. */
.mail-head__back { display: none; }


/* ---------- отправка: часы, галочка, две галочки ----------

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

   Своей краски у состояний нет намеренно. Зелёная галочка в почте читается
   как «доставлено получателю», а мы этого не знаем и знать не можем: SMTP
   отвечает за приём письма, а не за его прочтение. Обещать зелёным то, чего
   система не знает, — худший вид вранья, потому что его не проверить.
*/
.mail-msg__sent {
  display: inline-flex; align-items: center; margin-left: 5px;
  vertical-align: -2px; opacity: .75;
}
.mail-msg__sent.is-copied { opacity: 1; }

/* Письмо в очереди. Приглушено вдвое и без тени: оно ещё не письмо, и
   выглядеть законченным ему рано. Кнопка отмены стоит прямо в пузыре, а не
   полоской внизу экрана, как у окна «Написать»: там письмо уходит из
   закрытого окна и деться отмене больше некуда, а здесь человек смотрит
   ровно на то место, где письмо и появилось. */
.mail-msg__bubble--wait { opacity: .68; box-shadow: none; }
/* Приглушён весь ряд, а не один пузырь. Лицо ящика рядом с письмом в очереди
   появилось 02.09.2026 — до этого ряд собирался без него, и письмо на глазах
   меняло ширину, когда отмена кончалась (`ownRow` в `mailMessage.js`). Кружок
   в полную яркость над выцветшим пузырём читался бы как недорисованное. */
.mail-msg--wait .mail-face { opacity: .68; }
.mail-msg__wait-count { margin-left: 4px; }

/* Крестик вместо слова «Отменить»: в пузыре на две строки слово занимало
   больше места, чем само письмо. Мишень при этом остаётся пальцевой — 22
   точки, — хотя знак в ней 13: маленький значок и маленькая кнопка это
   разные вещи, и вторая на телефоне не нажимается. */
.mail-msg__wait-cancel {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; margin-left: 6px; padding: 0;
  border: 0; border-radius: 50%; background: transparent;
  color: inherit; cursor: pointer; opacity: .8;
  transition: background var(--speed), opacity var(--speed), transform var(--speed);
}
/* Подложка под курсором — из чернил пузыря, а не белая: письмо в очереди
   всегда своё, а свой пузырь в светлой теме зелёный, и белое пятно по нему не
   видно вовсе (1,01 к пузырю, стало 1,50). Тёмная остаётся как была — разбор
   долей у кнопки цитаты выше. */
.mail-msg__wait-cancel:hover {
  background: color-mix(in srgb, var(--chat-out-text) 20%, transparent);
  opacity: 1; transform: rotate(90deg);
}
.mail-msg__wait-cancel:disabled { cursor: default; opacity: .4; transform: none; }

/* Полоска обратного отсчёта. Цифру читают, полоску видят краем глаза — и
   вместе они отвечают на единственный вопрос этих десяти секунд: «успею ли
   передумать».

   Ход у неё сплошной, а не посекундный, и это правка 28.08.2026. Прежде
   полоска убывала ступенями по 10% — Роман: «прогресс-бар странный, как-то
   подлагивал». Ступень раз в секунду глаз и читает как рывок: убывание
   видно только тогда, когда оно непрерывно.

   Едет `transform: scaleX`, а не ширина. Ширина — это раскладка: браузер
   пересчитал бы её каждый кадр по всему пузырю и по ленте под ним, и на
   телефоне это тот самый подлаг. `transform` живёт на своём слое.

   Ростом полоска чуть выше прежнего: две точки на телефоне при убывании до
   нуля просто теряются. Само время задаёт js — только он знает срок. */
/* Жёлоб полоски — тоже из чернил пузыря. Белым он в светлой теме не виден, и
   убывающая полоса ехала по пустому месту: видно, сколько осталось, но не
   видно, из скольки. 1,01 → 1,50 к пузырю. */
.mail-msg__wait-bar {
  height: 3px; margin: 7px 0 2px; border-radius: 3px;
  background: color-mix(in srgb, var(--chat-out-text) 20%, transparent);
  overflow: hidden;
}
.mail-msg__wait-line {
  display: block; height: 100%; width: 100%; border-radius: 3px;
  transform-origin: left center;
  background: linear-gradient(90deg,
    color-mix(in srgb, var(--accent) 70%, white) 0%, var(--accent) 100%);
}
.mail-msg--wait .mail-msg__time { display: flex; align-items: center; justify-content: flex-end; }

/* ---------- ответ на выбранное письмо ----------

   Плашка над строкой ответа — та же, что в чате: полоска акцентом, имя и
   первые слова того, на что отвечают. Стоит она только при ответе не на
   последнее письмо: у последнего это и так очевидно.

   Ответ при этом уходит в почту обычным письмом с «Re:» — вид чата не
   должен менять то, что увидит собеседник в своём Outlook. */
/* ---------- строка ответа: тема, вложения, перетаскивание ----------

   Строка собрана столбиком: тема, плашка «отвечаю на это», плитки вложений и
   само поле. Скрепка и «Отправить» стоят по краям и держатся низа — столбик
   между ними тянется. */
.mail-reply__stack { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.mail-reply__stack > .input { width: 100%; }

/* Тема — мелко и серо, как в Spike: она отвечает на «под какой шапкой уйдёт
   написанное», а не спорит с самим полем ответа. Поле без рамки: рамка
   сделала бы из подписи вторую форму. */
.mail-reply__subj { display: flex; align-items: center; gap: 6px; min-width: 0; padding: 0 2px; }
.mail-reply__subj-input {
  flex: 1 1 auto; min-width: 0; padding: 0;
  border: 0; background: none; color: var(--text-soft);
  font: inherit; font-size: 12.5px; font-weight: 550;
  text-overflow: ellipsis;
}
.mail-reply__subj-input:focus { outline: none; color: var(--text); }
.mail-reply__subj-input::placeholder { color: var(--text-faint); }
/* Поправленная тема — акцентом, и рядом сказано, чем это кончится: письмо
   уйдёт новым разговором, а не в эту переписку. */
.mail-reply__subj.is-new .mail-reply__subj-input { color: var(--accent-text); }
.mail-reply__subj-note { flex: 0 0 auto; font-size: 11.5px; color: var(--amber); }
/* Крестик возвращает тему разговора. Появляется только когда её меняли: в
   покое возвращать нечего, а кнопка без дела читается как «закрыть». */
.mail-reply__subj-reset {
  flex: 0 0 auto; display: none; place-items: center;
  width: 18px; height: 18px; padding: 0;
  border: 0; border-radius: 50%; background: var(--surface-3); color: var(--text-soft);
  cursor: pointer;
}
.mail-reply__subj.is-new .mail-reply__subj-reset { display: grid; }
.mail-reply__subj-reset:hover { background: var(--surface); color: var(--text); }

/* Строка ответа, пока разговор едет.

   Отправлять ей нечего и некому: адресаты и тема считаются по письмам, а их
   ещё нет на руках. Поэтому «Отправить» погашена (это делает разметка), а
   тема прячется `visibility`, а не `display`, — место под неё остаётся
   занятым, и приехавшая тема не подкидывает поле ввода вместе со всей лентой
   над ним. Сама строка при этом жива: набранное дождётся писем, а запертое
   поле в тот единственный миг, когда человек уже решил ответить, читается как
   зависшая почта. */
.mail-reply.is-blind .mail-reply__subj { visibility: hidden; }

.mail-reply__files { display: flex; flex-wrap: wrap; gap: 6px; }

/* Скрепка слева — того же размера, что и «Отправить», и на одной с ней
   высоте: два действия одной строки не должны стоять лесенкой. */
.mail-reply__clip {
  flex: 0 0 auto; width: 36px; height: 36px; padding: 0;
  display: grid; place-items: center;
  border: 0; border-radius: 10px; background: transparent; color: var(--text-soft);
  cursor: pointer;
  transition: background-color var(--speed), color var(--speed);
}
.mail-reply__clip:hover { background: var(--surface-3); color: var(--text); }
.mail-reply__clip:focus-visible { outline: none; box-shadow: var(--ring); }

/* Файл тащат на разговор целиком, а подсвечивается строка ответа: она и есть
   то место, куда файл ляжет. */
.mail-reply.is-dropping {
  background: color-mix(in srgb, var(--accent) 12%, var(--surface));
  box-shadow: inset 0 0 0 2px var(--accent);
}

.mail-reply__quote {
  display: flex; align-items: flex-start; gap: 8px; width: 100%;
  margin-bottom: 6px; padding: 6px 8px;
  border-radius: 8px; background: var(--surface-2);
}
.mail-reply__quote-line {
  flex: none; width: 3px; align-self: stretch; border-radius: 3px; background: var(--accent);
}
.mail-reply__quote-body { flex: 1; min-width: 0; }
.mail-reply__quote-who { font-size: 12px; font-weight: 600; color: var(--accent-text); }
.mail-reply__quote-text {
  font-size: 12px; color: var(--text-faint);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mail-reply__quote-drop {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; padding: 0; border: 0; border-radius: 50%;
  background: transparent; color: var(--text-faint); cursor: pointer;
}
.mail-reply__quote-drop:hover { background: var(--surface-3); color: var(--text); }

/* Строка ответа с плашкой перестраивается в колонку: поле и кнопка стоят
   под ней, а не рядом — иначе плашка ужала бы поле ввода вдвое. */
.mail-reply:has(.mail-reply__quote) { flex-wrap: wrap; }


/* ---------- шапка письма: имя, адрес, действия ----------

   Просьбы Романа 27.08.2026, все четыре про одну строку шапки: адрес не
   показывать сразу, копировать его значком по наведению, по имени открывать
   меню, то же меню на получателе, и рядом — ряд действий, тоже по наведению.
   Разметка для этого в `mailMessage.js`. */

/* Одно имя, без адреса рядом. Строка не переносится: имя длинное ужимается
   многоточием, а сам адрес читают в меню, которое это имя и открывает. */
.mail-letter__name {
  display: flex; align-items: baseline; gap: 6px; min-width: 0;
}
/* Имя — мишень меню, но кнопкой не выглядит: в шапке письма читают имя, а не
   ищут кнопку. Подчёркивание приходит по наведению — как у ссылки в тексте. */
.mail-letter__whoname {
  flex: 0 1 auto; min-width: 0; max-width: 100%;
  padding: 0; border: 0; background: none; cursor: pointer;
  font: inherit; font-weight: 600; font-size: 14px; color: inherit;
  text-align: left; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.mail-letter__whoname:hover { text-decoration: underline; text-underline-offset: 2px; }

/* Выезжавшего по наведению адреса (`.mail-letter__addrbox`) здесь больше нет:
   28.08.2026 он переехал первой строкой в меню имени (`.mail-menu__addr` в
   `mail-list.css`). Разворачиваясь под мышью, он отъедал у имени половину
   строки ровно тогда, когда в имя целятся, — и всё равно обрывался
   многоточием, то есть прочесть его было нельзя. */

/* Получатель — та же мишень, что имя и адрес. Строку «кому» читают, а не
   жмут, поэтому и она остаётся текстом, пока на неё не навели. */
.mail-letter__peer {
  padding: 0; border: 0; background: none; cursor: pointer;
  font: inherit; font-size: 12px; color: inherit;
}
.mail-letter__peer:hover { color: var(--text); text-decoration: underline; }

/* Ряд действий. Появляется по наведению на шапку — так просил Роман, и так
   письмо остаётся письмом, пока в него не целятся. `focus-within` выводит ряд
   и с клавиатуры: наведения там нет, а действия те же. */
.mail-letter__acts {
  flex: 0 0 auto; display: flex; align-items: center; gap: 2px;
  opacity: 0; transition: opacity var(--speed);
}
.mail-letter__head:hover .mail-letter__acts,
.mail-letter__acts:focus-within { opacity: 1; }
.mail-letter__act {
  flex: 0 0 auto; width: 26px; height: 26px; display: grid; place-items: center;
  padding: 0; border: 0; border-radius: 7px; background: none;
  color: var(--text-faint); cursor: pointer;
  transition: background-color var(--speed), color var(--speed);
}
.mail-letter__act:hover { background: var(--surface-2); color: var(--accent-text); }
/* «Ещё» на столе не нужна: там весь ряд на виду, а правая кнопка открывает то
   же меню целиком. */
.mail-letter__act--more { display: none; }

/* Где наведения нет, ряда нет тоже: четыре значка отняли бы у имени половину
   узкой шапки. Вместо них одна кнопка «Ещё» — то же меню, и стоит она всегда.
   Долгое нажатие по шапке при этом работает как работало.

   Адрес там же остаётся на виду: спрятанное «до наведения» на телефоне
   спрятано навсегда, а адрес отправителя — то, ради чего в шапку и смотрят. */
@media (hover: none) {
  .mail-letter__acts { opacity: 1; }
  .mail-letter__act { display: none; }
  .mail-letter__act--more { display: grid; }
  .mail-letter__name { flex-wrap: wrap; }
  .mail-letter__whoname { white-space: normal; }
}


/* ---------- закрыть разговор ----------

   Крестик стоит последним в ряду и за волоском отбивки: закрытие в любом окне
   живёт в правом углу, и искать его глазами не приходится. Отбивка отделяет
   его от кнопок вида — те переключают, этот уносит.

   Соседняя «во весь экран» остаётся: кнопки делают не похожее, а обратное —
   одна отдаёт разговору место двух колонок, другая убирает сам разговор. */
.mail-head__close { position: relative; margin-left: 7px; }
.mail-head__close::before {
  content: ''; position: absolute; left: -4px; top: 6px; bottom: 6px;
  width: 1px; background: var(--border);
}

@media (max-width: 820px) {
  /* На телефоне закрытие уже есть — стрелка «назад» в той же шапке слева.
     Второй крестик рядом с ней отнял бы у темы сорок точек ни за что.
     Сила правила выше нужной нарочно: `mail-phone.css` подключён после этого
     листа, и одного класса ему не хватило бы. */
  .mail-head .mail-head__close { display: none; }
}


/* ---------- смена темы в чат-виде ----------

   Строка-указатель между письмами: разговор перешёл на другой заказ. Сделана
   тише заголовка дня — дата отвечает на «когда», а тема на «о чём», и второй
   вопрос в переписке возникает реже. Отсюда и вид: без подложки, тонкой
   чертой по бокам, чтобы строка читалась разделителем, а не письмом. */
/* Тема письма выделяется мышью — как почта и телефон в карточке, и по той же
   причине: её не столько читают, сколько уносят в другое окно. В поиск по
   переписке, в заявку подрядчику, в сообщение коллеге. Раньше тему
   переписывали руками с экрана.

   Кнопки копирования рядом нет намеренно: Роман 31.08.2026 — «лучше
   кареткой». Кнопка берёт всю строку целиком, а из темы чаще нужен кусок —
   номер заказа или название изделия. */
.mail-topic {
  display: flex; align-items: center; gap: 10px;
  margin: 14px 0 8px; padding: 0 6px;
  font-size: 12px; color: var(--text-faint);
  user-select: text; -webkit-user-select: text;
  cursor: text;
}
.mail-topic::before,
.mail-topic::after {
  content: ''; flex: 1; height: 1px; background: var(--border);
}
/* ---------- уголок в шапке и кнопка промотки вниз ----------

   Шапка разговора нажимается и открывает панель переписки (`mailPeople.js`).
   Примета этому одна — уголок в теме: строка «нажмите сюда» в шапке была бы
   подписью к тому, что и так делают нажатием, а лишняя кнопка в правом ряду
   стала бы пятой по счёту.

   Тема при этом остаётся строкой с многоточием: обрезается **текст**, а
   уголок стоит после него и не уезжает — оттого текст уехал во вложенный
   узел, а сама тема стала рядом. */
/* Тема в шапке — тоже выделяемая. Уголок рядом с ней из выделения исключён:
   он часть кнопки, а не текста, и в буфере от него остаётся пустота, которую
   человек не видит и вставляет вместе с темой. */
.mail-head__subject {
  display: flex; align-items: center; gap: 6px;
  user-select: text; -webkit-user-select: text;
  cursor: text;
}
/* Уголку возвращаем указатель: каретка над ним обещала бы текст, а он —
   единственная примета, что шапка нажимается. */
.mail-head__peek { user-select: none; -webkit-user-select: none; cursor: pointer; }
.mail-head__subject > span {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mail-head__peek {
  flex: 0 0 auto; color: var(--text-faint);
  transition: transform var(--speed), color var(--speed);
}
/* Чипы стоят справа от имени, в одной строке с ним, — и потому шапка ровно
   такой же высоты, как шапка списка слева.

   До 07.09.2026 они лежали вторым ярусом под темой, и ярус этот держал рост
   даже пустым: клиента и заказ считают по письмам разговора, до ответа
   сервера их честно нет, а без распорки шапка подрастала на девять точек ровно
   в тот миг, когда человек начал читать (чип клиента ждёт `talk-facts` и
   приезжает вторым заходом — `clientChip` в `mailThread.js`).

   Распорка от подскока спасала, но платила за это постоянной высотой в 66
   точек против 52 у шапки списка. Роман 07.09.2026: «мне очень режет глаз этот
   стык и неровные плашки… возможно их стоит вынести справа от контакта, чтобы
   плашка стала компактней».

   **Одна строка снимает обе беды разом, а не меняет одну на другую.** Рост
   строки задаёт тема (22,5 точки), чип ниже её на волосок — то есть приезд
   чипов не двигает ничего и без распорки. А вся шапка при этом складывается в
   38 точек содержимого и встаёт на свой минимум `--mail-head-h`, общий у неё с
   шапкой списка, с колонками чата и с панелью переписки.

   **Чипы жмутся к имени, а не к правому краю.** Ни один из двух не растёт
   (`flex-grow: 0`), и запас строки остаётся справа от пары — то есть читаются
   они как одно целое: с кем разговор и чей он. Растяни тему на всю ширину — и
   чипы уехали бы к кнопкам вида, а между ними и именем встала бы пустая
   ладонь, из-за которой чип читается как часть правого ряда.

   Место кончилось — ужимаются оба, но тема заметно быстрее: `flex-shrink`
   считает от собственной ширины, а имя человека всемеро длиннее пилюли. Уходит
   она многоточием (`> span` выше). Чипам при этом отдана половина строки, не
   больше: у клиента бывает имя в шесть слов, и без потолка оно вытеснило бы из
   шапки то, ради чего её читают, — с кем разговор. */
.mail-head__main {
  display: flex; align-items: center; gap: 10px;
  min-width: 0;
}
.mail-head__subject { flex: 0 1 auto; min-width: 0; }
.mail-head__sub {
  flex: 0 1 auto; min-width: 0; max-width: 50%;
  margin-top: 0; flex-wrap: nowrap;
}
/* Имя клиента внутри чипа обрывается многоточием, а не распирает чип: в строке
   ему деваться некуда. Обрывается вложенный узел, не сам чип, — чип раскладка
   флексом, и `text-overflow` на нём не сработал бы вовсе. */
.mail-head__chip { flex: 0 1 auto; min-width: 0; }
.mail-head__chip > span {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Чип клиента приезжает вторым заходом и потому лежит в своей обёртке
   (`clientChip` в `mailThread.js`). Обёртку растворяем: иначе ужимался бы
   не чип, а она, и многоточие в имени не появилось бы никогда. */
.mail-head__chip-slot { display: contents; }

/* На телефоне чипы остаются ярусом ниже: строки там полтораста точек, и имя
   с чипом в неё не встают вдвоём (сетка шапки — в `mail-phone.css`). Значит,
   там же остаётся и распорка под пустой ярус — с прежним счётом от частей
   самого чипа: кегль 12 на полтора, четыре точки поля сверху и снизу, рамка.

   И там же чип по-прежнему переносит имя внутри себя, а не обрывает: ужиматься
   ему нечем, а огрызок именем не бывает (разбор — в `mail-phone.css`). */
@media (max-width: 820px) {
  .mail-head__sub {
    max-width: none; flex-wrap: wrap;
    min-height: calc(12px * 1.45 + 10px);
  }
  .mail-head__chip > span { overflow: visible; white-space: normal; }
}

.mail-head__main { cursor: pointer; }
.mail-head__main:hover .mail-head__peek { color: var(--accent-text); }
.mail-head__main.is-open .mail-head__peek {
  transform: rotate(180deg); color: var(--accent-text);
}
/* Шапка нажимается целиком — рука обязана говорить это над всей полосой, а не
   только над её серединой: на телефоне середины как коробки нет вовсе. */
.mail-head { cursor: pointer; }
/* Чипы под темой ведут своей дорогой (карточка клиента, заказ), и рука над
   ними обязана говорить про них, а не про шапку. */
.mail-head__chip, .mail-head__chip--ghost { cursor: pointer; }
/* Что чип нажимается, видно до нажатия: под курсором у него проступает
   рамка — та же, что у чипа-призрака «Привязать к заказу», чтобы два чипа
   в одном ярусе отвечали на руку одинаково. Подчёркивание общего правила
   `a:hover` снято по той же причине, что у плитки вложения: подчёркивают
   слово в тексте, а не пилюлю. */
a.mail-head__chip:hover { border-color: var(--accent); text-decoration: none; }
.mail-head__main:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 8px;
}

/* Кнопка промотки — та же, что в ленте Флоу.Чата (`.chat__down` в app.css):
   размер, круг и порядок появления повторены до значения, а тень взята общая
   для всплывающего слоя (`--shadow-pop`): кнопка висит над лентой, и высота у
   неё та же, что у меню и попапов. Разница одна и вынужденная — место: у
   чата под лентой полоса ввода в три ряда, у почты строка ответа в один, и
   96 точек снизу подняли бы кнопку в середину разговора.

   `z-index` с запасом и `touch-action`: в чате кнопка однажды перестала
   нажиматься ровно потому, что лента с подложенным фоном оказалась над ней,
   а браузер придерживал касание, приняв его за начало прокрутки. */
.mail-down {
  position: absolute; right: 18px; bottom: 78px; z-index: 15;
  touch-action: manipulation;
  width: 42px; height: 42px; border-radius: 50%;
  background: var(--surface-3); border: 1px solid var(--border-strong); color: var(--text);
  box-shadow: var(--shadow-pop);
  display: grid; place-items: center; cursor: pointer;
  opacity: 0; pointer-events: none;
  transition: opacity var(--speed), transform var(--speed), right var(--speed);
}
.mail-down:hover { background: var(--surface-2); transform: translateY(-1px); }
.mail-down.is-visible { opacity: 1; pointer-events: auto; }
/* Панель переписки ложится на правый край разговора — кнопка отходит от неё,
   а не прячется под ней: лента под панелью живая, и промотать её оттуда
   человек вправе. Ширину панели задаёт `mail-people.css`; запасное число
   здесь на случай, если лист почему-то не подключён. */
.mail__view.has-people .mail-down { right: calc(var(--mail-people-w, 320px) + 18px); }
/* На узком окне панель занимает экран целиком, и кнопка под ней — это
   кнопка, промотавшая невидимое. */
@media (max-width: 820px) {
  .mail__view.has-people .mail-down { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .mail-head__peek { transition: none; }
  .mail-down { transition: none; }
}
/* ---------- окно ленты ----------

   Сторож истории и распорка — узлы без вида: первый ловит подъём к началу
   ленты, вторая держит место снятых снизу писем. Сторожу нужна хоть какая-то
   высота, иначе наблюдатель не считает его показавшимся.

   Распорка объявлена блоком нарочно: `<i>` — строчный узел, и высота на нём
   не работала бы вовсе. */
/* `flex: 0 0 auto` обязателен, и это не перестраховка: вид «письмами» —
   колонка flex, а в ней пустой узел сжимается до нуля, потому что своего
   содержимого у него нет. Распорка при этом честно хранит высоту в
   `style`, а на экране её не занимает — лента съезжала бы на высоту
   снятых писем при каждом снятии. Снято глазами: в чат-виде (обычный
   блок) всё было верно, а в «письмами» лента прыгала. */
.mail-feed__mark { display: block; flex: 0 0 auto; height: 1px; }
.mail-feed__gap { display: block; flex: 0 0 auto; }

/* Начало присланного куска переписки. Не «загружаю» и не пустота: сервер
   отдал последние письма, за более старыми ходить пока нечем — и сказать об
   этом честной строкой лучше, чем оставить человека гадать, вся ли это
   переписка. Приглушена вдвое: это оговорка, а не письмо. */
.mail-feed__older {
  margin: 4px 0 12px; padding: 0 6px;
  font-size: 12px; color: var(--text-faint); text-align: center; line-height: 1.5;
}
/* Место прокрутки держим сами — браузерное «якорение» тут только мешает.

   Chrome, когда над видимым куском что-то появляется или исчезает, сам
   двигает прокрутку, чтобы человек остался смотреть на то же место. Ровно
   это делает и `mountFeed`, поправляя `scrollTop` на высоту приехавшей
   пачки, — и две поправки складываются. Снято глазами: лента, уведённая
   ползунком в самый верх, за три подгрузки уезжала обратно в самый низ.

   Своя поправка надёжнее чужой: якорения нет в Safari вовсе, и лента,
   которая держится за место только в Chrome, — это лента, которая в
   половине браузеров прыгает. */
.mail-feed { overflow-anchor: none; }

/* ---------- окно привязки письма ----------

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

   Высота списка ограничена и прокручивается сама: находок бывает два десятка,
   а окно, растущее до края экрана, уводит кнопку «Отмена» за него. */
/* Обёртка окна зовётся `.mail-pick`, а не `.mail-link`, и это не вкусовщина.
   Именем `.mail-link` выше названа ссылка в теле письма, и у неё есть
   `:hover { text-decoration: underline }`. Подчёркивание наследуется и
   протягивается через всех потомков — отменить его изнутри нельзя вовсе. То
   есть стоило подвести мышь к окну привязки, и подчёркнутым становилось всё:
   подпись поля, набранное в нём слово, каждая строка находки и подсказка
   внизу (Роман 28.08.2026: «подчеркиваются ссылки зачем то»). Два разных
   смысла под одним классом — так и получается. */
.mail-pick { display: flex; flex-direction: column; gap: 10px; }
.mail-link__rows {
  display: flex; flex-direction: column; gap: 2px;
  max-height: 46vh; overflow-y: auto;
  margin: 0 -4px; padding: 0 4px;
}
.mail-link__row { display: flex; align-items: stretch; gap: 4px; }
.mail-link__pick {
  flex: 1 1 auto; min-width: 0;
  display: flex; align-items: center; gap: 8px;
  padding: 8px 10px; border: 0; border-radius: 8px;
  background: transparent; color: var(--text);
  font: inherit; font-size: 14px; text-align: left; cursor: pointer;
}
.mail-link__pick:hover { background: var(--surface-3); }
.mail-link__pick > svg { flex: 0 0 auto; color: var(--text-faint); }
/* Имя ужимается, приписки — нет: по ним и различают две одинаково названные
   строки, и обрезанная приписка не различает ничего. */
.mail-link__name {
  flex: 0 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mail-link__sub { flex: 0 0 auto; font-size: 12px; color: var(--text-faint); }
.mail-link__closed {
  flex: 0 0 auto; margin-left: auto;
  font-size: 11px; color: var(--text-faint);
}
.mail-link__bare {
  flex: 0 0 auto; padding: 0 10px;
  border: 1px solid var(--border); border-radius: 8px;
  background: transparent; color: var(--text-soft);
  font: inherit; font-size: 12.5px; cursor: pointer;
}
.mail-link__bare:hover { border-color: var(--accent); color: var(--accent-text); }
.mail-link__back {
  display: flex; align-items: center; gap: 6px;
  padding: 6px 10px; border: 0; border-radius: 8px;
  background: transparent; color: var(--text-soft);
  font: inherit; font-size: 13px; cursor: pointer;
}
.mail-link__back:hover { background: var(--surface-3); }
.mail-link__empty { padding: 14px 10px; font-size: 13.5px; color: var(--text-faint); }

/* =========================================================
   Переход между разговорами
   ========================================================= */

/* Роман 28.08.2026: «анимация затухания между не только вкладками Флоу.Почты
   (входящие/отправленные), но и между тредами писем — в чатовом режиме и в
   обычном строковом».

   Той же манерой и той же длительностью, что список писем (`.mail__rows` в
   `mail-list.css`) и лента чата (`.chat__feed` в `app.css`): прежнее гаснет
   мгновенно (`transition: none` у самого класса), новое проявляется за
   150 мс. Растворять их друг в друге нельзя — два разговора на эти доли
   секунды читались бы как один перемешанный, а в почте это опаснее, чем в
   чате: человек отвечает тому, чьё письмо видит.

   Именно прозрачность, а не сдвиг и не размытие: прозрачность браузер делает
   на видеокарте даром, а в панели разговора стоят двадцать пять писем с
   телами, плитками и снимками.

   Занавес вешается только на смену разговора и вида (`viewCut` в
   `mailThread.js`). Ответ, открытие панели переписки, пришедшее письмо
   перерисовывают панель тем же кодом — и мигать там нечему.

   Занавес обязан быть **посчитан** до того, как его снимут: лента
   собирается заново на каждую перерисовку, и без принудительного пересчёта
   (`revealFeed`) переходу не от чего идти. Ровно эта грабля описана в
   разделе 101 HANDOFF. */
/* Гаснет **лента**, а не вся панель. Прежде занавес висел на `.mail__view` и
   уносил в темноту заодно шапку и строку ответа — ровно те две зоны, на
   которые Роман 29.08.2026 и показал: «при переходе от диалога к диалогу
   мелькают плашки». К содержимому переписки обе не относятся: имя разговора
   известно из строки списка ещё до запроса, а строка ответа — неизменная
   обвязка. Теперь они переживают переключение целыми (`renderView` держит их
   узлы), и гасить остаётся одну ленту.

   Так это и сделано в чате: `.chat__feed.is-swapping` в `app.css`. */
.mail-feed { transition: opacity 150ms ease-out; }
.mail-feed.is-swapping { opacity: 0; transition: none; }

/* Кому движение мешает — тому его нет. Разговор при этом не пропадает и не
   замирает: он просто встаёт сразу готовым — и занавеса тоже нет, иначе
   без перехода он превратился бы в один пустой кадр, то есть в мигание
   вместо плавности. */
@media (prefers-reduced-motion: reduce) {
  .mail-feed { transition: none; }
  .mail-feed.is-swapping { opacity: 1; }
}

/* ---------- почему у переписки нет заглушки ----------

   Полдня она здесь стояла: серые пузыри с полосами внутри, покрашенные
   отдельной приглушённой краской, потому что общая `.skel` считает подложку
   от `--surface-2` — тона рабочей области, — а пузырь своего письма акцентный,
   и полоса ложилась на него чёрным по синему (Роман 28.08.2026: «вообще ужас,
   черное на синем»).

   Краску подобрали, и назавтра заказчик посмотрел на итог целиком (29.08.2026):
   «уж лучше как в Флоу.Чат сделать просто проявление писем и пузырей, чем
   делать эти блики в окне просмотра переписки в почте. Может так лучше
   сделаем? Будет проще».

   И правда проще, а главное — честнее. Заглушка ценна тем, что обещает форму
   будущего содержимого, но у письма формы нет: одно в две строки, другое с
   цитатой, подписью и четырьмя плитками вложений. Четыре одинаковых пузыря не
   угадывают ни одного из них, то есть обещают не то, — а такая заглушка хуже
   пустоты. Ровно поэтому её нет и в ленте чата (`chatPanel.js`), где пузыри
   такие же разные.

   Взамен — проявление: лента на время подмены уходит под занавес и появляется
   готовой (`.mail-feed.is-swapping` выше). Ждать под ним нечего: шапка со
   строкой ответа стоят на местах с первого мига, и пустует одна лента.

   В списке писем и в окне поиска заглушки остались, и это не разнобой: там
   строка одной высоты у всех писем — форму как раз можно обещать, — а
   ожидание самое долгое за весь сеанс. Их разбор — в `mail-list.css`. */

/* Номер заказа у письма — приметой в строке времени, а не чипом в пузыре.
   Строка эта и так последняя, и глаз доходит до неё, дочитав письмо: там
   вопрос «а это про какой заказ» и возникает. Приглушена, как время: она
   отвечает на вопрос, а не требует внимания. */
/* Примета — ссылка в заказ, и под курсором она это показывает. Подчёркивание
   снимаем: общее правило системы (`a:hover`) протянуло бы его через всю
   строку времени, вместе с часами и галочками. */
a.mail-msg__deal { text-decoration: none; cursor: pointer; }
a.mail-msg__deal:hover {
  background: color-mix(in oklab, var(--accent) 30%, transparent);
  color: var(--accent-text);
}
.mail-msg--out a.mail-msg__deal:hover {
  background: color-mix(in srgb, var(--chat-out-text) 33%, transparent);
}
.mail-msg__deal {
  margin-right: auto; padding: 1px 6px; border-radius: 6px;
  background: var(--accent-soft); color: var(--accent-text);
  font-size: 10.5px; font-weight: 600; letter-spacing: .2px;
}
/* В строке времени всё прижато вправо, а номер — влево: он про письмо, а
   время и галочки про его судьбу, и мешать их в одну кучу незачем.

   `justify-content` здесь появился 29.08.2026 и чинит давнюю мелочь: прижимал
   всё вправо один `margin-right: auto` у номера заказа, а номер есть дай бог
   у каждого пятого письма. У остальных строка оставалась флексом без
   выравнивания — то есть время стояло у **левого** края пузыря, под первой
   буквой текста. Роман: «указывай дату получения, отправки письма всегда в
   правом нижнем углу пузыря». Правило теперь на самой строке, и номер
   по-прежнему уходит влево своим `auto`. */
.mail-msg__time { display: flex; align-items: center; justify-content: flex-end; gap: 6px; }

/* ---------- полная дата рядом с пузырём ----------

   Роман 29.08.2026: «я бы сделал показ времени и даты… при наведении курсора
   на письмо — так и сорить не будем этими данными и сделаем удобный запрос по
   этой информации».

   Полоса между пузырём и краем ленты. Она есть всегда: пузырь занимает самое
   большее 72% ширины (`.mail-msg__bubble` в app.css), и остаток — свободное
   место, в котором никогда ничего не стоит.

   **Место держится постоянно, гаснет только краска.** Узел, появляющийся по
   наведению из ничего, раздвигал бы строку под рукой: пузырь дёргался бы
   вбок на каждом проходе мыши, а лента — на каждой строке подряд. Поэтому
   `opacity`, а не `display`: раскладка посчитана один раз и не меняется
   вовсе.

   `flex: 0 0 auto` и `nowrap` — чтобы дата не переносилась на вторую строку и
   не тянула пузырь: у неё своё место, а не доля от строки. */
.mail-msg__when {
  flex: 0 0 auto;
  align-self: flex-end;
  max-width: 40%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  padding-bottom: 4px;
  color: var(--text-faint);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  opacity: 0;
  transition: opacity 140ms ease;
}
.mail-msg:hover .mail-msg__when { opacity: 1; }
/* У своего письма свободна левая полоса: пузырь прижат к правому краю.
   Порядком, а не второй веткой в разметке, — узел один и тот же. */
.mail-msg--out .mail-msg__when { order: -1; }

@media (hover: none) {
  /* Наведения нет — нет и полосы: место она держала бы, а показать себя не
     могла бы ничем. Время в пузыре при этом остаётся, а полная дата у письма
     спрашивается там же, где и всё прочее о нём, — в меню по долгому
     нажатию. */
  .mail-msg__when { display: none; }
}
/* На своём пузыре акцентная подложка сливается с ним — там берём вуаль из
   чернил пузыря, ту же, что у прочих приписок своего письма. Белой она быть
   не может: в светлой теме свой пузырь зелёный и светлее белой вуали, и номер
   заказа лежал на пустом месте — 1,01 к пузырю, стало 1,50. */
.mail-msg--out .mail-msg__deal {
  background: color-mix(in srgb, var(--chat-out-text) 20%, transparent);
  color: var(--chat-out-text);
}

/* ---------- новое письмо въезжает в открытую ленту ----------

   Роман 16.09.2026: «рефрешим только тогда, когда отправляется/приходит новое
   письмо, и в идеале не через мерцание всего окна раздела конкретного
   флоу.почты, а через анимацию как в флоу чате — выдвигание нового сообщения
   с письмом со сдвигом остальных вниз».

   Лента больше не собирается заново на каждое письмо (`mergeFeed` в
   `mailThread.js`): новое письмо встаёт в неё одним узлом, а прежние
   доезжают до своих новых мест. Места считает скрипт — рост письма знает
   только он и только в миг вставки, — а обе половины движения живут здесь.

   **Выезд** — со стороны свежего края: снизу в «Чате» и «Gmail», сверху в
   перевёрнутой ленте «Mail Ru». Сторону ставит скрипт переменной `--rise`,
   чтобы правило было одно на все три вида.

   **Сдвиг** — трансформом, а не высотой, по той же причине, что у строки
   списка (`mail-list.css`): высота пересчитывает раскладку всей ленты на
   каждом кадре и не умеет оттяжки. Длится столько же, 280 мс, и той же
   пружиной — одно движение в двух колонках одного раздела обязано быть одним.

   Появление — анимацией, а не переходом: письмо само по себе видимое, а
   прозрачным его делает анимация. Тогда `animation: none` под
   `prefers-reduced-motion` возвращает ему его собственный вид — письмо просто
   оказывается в ленте. */
@keyframes mail-letter-in {
  from { opacity: 0; transform: translateY(var(--rise, 14px)); }
  to { opacity: 1; transform: none; }
}
.mail-feed > .is-arriving { animation: mail-letter-in 280ms var(--ease, ease-out) both; }
.mail-feed > .is-gap { transition: transform 280ms var(--spring, ease); }

@media (prefers-reduced-motion: reduce) {
  .mail-feed > .is-arriving { animation: none; }
  .mail-feed > .is-gap { transition: none; }
}
