/* Deliberately one small stylesheet, no framework, no build step. The panel is
   two screens for two people; a toolchain would cost more than it returns. */
:root{
  /* Оттенки сняты со скриншота админки Shopify. Ключевое отличие от прежнего
     варианта: фон страницы СЕРЫЙ, карточки белые. На белом фоне белые карточки
     не читаются как отдельные блоки — именно поэтому у них там тень, а не
     рамка: тень отделяет, рамка обводит. */
  --bg:#f1f1f1;          /* фон страницы */
  --surface:#fff;        /* фон карточки */
  --line:#e3e3e3;        /* границы и разделители */
  --fg:#303030;          /* основной текст */
  --dim:#616161;         /* приглушённые подписи */
  --acc:#005bd3;         /* ссылки */
  --warn:#4a2d00; --warnbg:#f8d6a4;
  --bad:#8e1f0b;  --badbg:#fdd;
  --act:#0c5132;  --actbg:#cdfee1;
  /* 🔴 «НУЖНО ДЕЙСТВИЕ» — ОТДЕЛЬНЫЙ ЦВЕТ, И ОН НЕ ЗЕЛЁНЫЙ. До 28.07.2026
     плашка «Спор PayPal — ответить до 01.08.2026 09:59» красилась в --act,
     то есть в зелёный: имя переменной читалось как «action», а краска в ней
     лежала успеха. Срочное дело с дедлайном выглядело как «всё хорошо».

     Сам --act остаётся зелёным и остаётся на месте: им покрашены рост
     показателя и «доставлено» — там зелёный означает ровно то, что должен.

     От --bad отличается не краской, а весом и обводкой: «проигран» — это
     уже случившееся, «ответить до субботы» — то, что ещё можно изменить, и
     на экране оно обязано быть громче. */
  --urge:#8e1f0b; --urgebg:#fdd; --urgeline:#e4a79a;
  /* ══ ЛЕСТНИЦА СВЕТЛОТЫ, СНЯТАЯ ПИПЕТКОЙ С SHOPIFY INBOX ═══════════════
     Владелец обмерил образец; здесь она одним местом, и всё остальное
     выводится отсюда, а не подбирается по месту.

         255  #ffffff  поле переписки и список — самое светлое
         250  #fafafa  выбранный пункт меню (лежит на панели)
         247  #f7f7f7  выбранная строка списка (лежит на белом)
         244  #f4f4f4  облачко сообщения
         241  #f1f1f1  строка в момент нажатия
         235  #ebebeb  фон левой панели — самое тёмное

     🔴 ШАГ НЕ ОДИН И ТОТ ЖЕ — Я ПРОВЕРИЛ АРИФМЕТИКОЙ, ПРЕЖДЕ ЧЕМ ВЫВОДИТЬ
     ЗНАЧЕНИЯ ФОРМУЛОЙ. Владелец сказал «ровные ступени по четыре», но его же
     числа дают другое:

         235 → 241   шаг 6
         241 → 244   шаг 3
         244 → 247   шаг 3
         247 → 250   шаг 3
         250 → 255   шаг 5

     То есть ЧЕТЫРЕ СРЕДНИЕ ступени идут ровно по 3, а края шире: панель на 6
     ниже нижней средней, белое на 5 выше верхней. Вывести все шесть из одного
     шага нельзя — четыре из шести уехали бы от замера. Поэтому значения
     остаются замеренными, а от разъезда их держит не формула, а ПРОВЕРКА
     (`test_the_ladder_keeps_its_measured_steps`): она знает и шаг середины, и
     ширину краёв, и скажет, какая именно ступень поехала. Формулу тоже можно
     переписать не глядя, а проверку — нет.

     🔴 ПРАВИЛО ВЫДЕЛЕНИЯ, И ЗАПИСАНО ОНО ТАК, ЧТОБЫ ОБРАТНОЕ ИЗ НЕГО НЕ
     ВЫВЕЛОСЬ: выбранное отличается от СВОЕГО фона на один небольшой шаг
     светлоты — В ТУ СТОРОНУ, КУДА ЕСТЬ КУДА ШАГАТЬ.

         фон меню серый (235)  → шагать есть куда к белому  → выбранное 250
         фон списка белый (255) → светлее некуда, шаг в серое → выбранное 247

     🔴 «ВЫБРАННОЕ ВСЕГДА СВЕТЛЕЕ ФОНА» — НЕВЕРНО. Эта формулировка выведена из
     одного случая (меню) и на белом фоне даёт прямо противоположное указание.
     Оставлена здесь нарочно, зачёркнутой: следующий читатель наткнётся на
     меню, увидит 250 на 235 и выведет её заново, если не предупредить.

     🔴 ШАГ МАЛЕНЬКИЙ — 8 ЕДИНИЦ НА БЕЛОМ, 15 НА ПАНЕЛИ, — ПОЭТОМУ ТОН НЕ
     ОДИН. Второй признак у выбранного свой: имя в строке жирнее
     (`.m9-sel .m9-who`), у пункта меню — тень, а нажатие отзывается тёмным и
     затухает. Тон подсказывает, вес и тень держат. */
  --paper:#ffffff;       /* поле переписки и список */
  --pick-menu:#fafafa;   /* выбранный пункт меню — на панели */
  --pick-row:#f7f7f7;    /* выбранная строка списка — на белом */
  --bubble-bg:#f4f4f4;   /* облачко сообщения */
  --pressed:#f1f1f1;     /* строка в момент нажатия */
  --rail:#ebebeb;        /* фон левой панели */

  /* ══ ЦВЕТ ГОВОРИТ, ЧТО ЭТО ЗА ЗАПИСЬ. СТОРОНА ГОВОРИТ, ЧЬЯ ОНА ═════════
     На вопрос «кто» отвечает СТОРОНА: клиент слева, мы справа. Цвет отвечает
     на «что это» — владелец просил читать смысл записи, не читая текст.

     🔴 ПЕРЕСЧИТАНО 02.08.2026 ПОСЛЕ ПРИГОВОРА ВЛАДЕЛЬЦА: «читать облачка по
     цвету не достигнуто». Он прав, и вот чем я ошибся.

     Ночью я держал два правила разом: все пять тонов одной светлоты (243–244)
     и ни один не громче голубого (C* 6.5). Из этой пары следовало, что весь
     набор живёт в пятне шириной 6 единиц ΔE — то есть у самого порога
     различимости 2.3. Порог оказался мерой ЛАБОРАТОРНОЙ: он говорит, увидит ли
     человек разницу, если положить два образца рядом и всматриваться. Работа
     устроена иначе — взгляд скользит по ленте, и там нужен не порог, а ЗАПАС.

     🔴 ЧТО ПРИШЛОСЬ ОТДАТЬ: ОДНУ СВЕТЛОТУ НА ВСЕХ. Красный не может быть
     одновременно светлым и насыщенным — при светлоте 243 канал R упирается в
     255, и весь тон умещается в C* 6.5. Замер: в коридоре 238–246 при C* ≥ 8
     во всём пространстве RGB нашлось ВСЕГО 37 красных. Значит выбор был не
     между «ярче» и «спокойнее», а между «читается» и «одна светлота».
     Владелец выбрал первое, и это верно: одинаковая светлота была средством, а
     различимость — целью.

     Серый и голубой НЕ ТРОНУТЫ — владелец назвал их правильными.

     🔴 УБАВЛЕНО НА 8.5% ПО ЗАМЕЧАНИЮ ВЛАДЕЛЬЦА: «чуть-чуть перебрал с
     насыщенностью, может быть на 7-10% меньше». Взята середина названного.
     Убавлена ТОЛЬКО насыщенность — светлота у каждого тона своя и не тронута:
     на ней держится различимость при красно-зелёной слепоте.

     Запас теперь (ΔE, попарно):
        три событийных между собой  минимум 21.4  (было 6.9, до убавления 23.2)
        серый ↔ салатовый                  11.7  (было 6.4, до убавления 13.1)
        серый ↔ красный                    21.4
        серый ↔ жёлтый                     24.4
        серый ↔ голубой                     6.5  ← не тронут, см. ниже

     🔴 ЕДИНСТВЕННАЯ ТЕСНАЯ ПАРА — СЕРЫЙ И ГОЛУБОЙ, И ЭТО НЕ НЕДОРАБОТКА. Они
     оба из семейства РАЗГОВОРА и различаются вторым признаком, который сильнее
     цвета: стороной. Слова клиента всегда слева, наши всегда справа; спутать
     их нельзя, даже не различив оттенка.

     🔴 ПОБОЧНАЯ ПРИБЫЛЬ: КРАСНО-ЗЕЛЁНАЯ СЛЕПОТА. Ночью салатовое и красноватое
     были для дейтеранопа неразличимы (ΔE 1.46 при пороге 2.3), и снятие полос
     оставило таких людей без признака вовсе. Теперь тона расходятся ещё и по
     светлоте, а её видят все: салатовое ↔ красное для дейтеранопа 11.6,
     жёлтое ↔ красное 16.4. Признак вернулся сам, без полос. */
  --mine:#eaf4ff;        /* наше письмо или SMS (не трогать) */
  /* 🔴 ЧИСЛА C* ЗДЕСЬ — ЗАМЕРЕННЫЕ, А НЕ ЗАДУМАННЫЕ, и это поправка 02.08.2026.
     Стояли 12.8 / 26.1 / 19.2 — насыщенность ДО убавления на 8.5%; сами цвета
     давно убавлены, а подписи остались от прежних значений. Мелочь, но того же
     разряда, что совравшая шапка набора значков: по подписи потом отвечают на
     вопрос «какой у нас тон». Теперь их сходство с настоящим цветом стережёт
     `test_the_chroma_notes_match_the_colours`. */
  --event-ok:#daf1e2;    /* рядовое событие заказа (C* 11.3) */
  --money-bg:#fae9bc;    /* деньги: настоящий жёлтый, спокойный (C* 24.0) */
  --event-bad:#f5c8c2;   /* споры, отказы, возвраты (C* 17.5) */

  /* 🔴 ВТОРОЙ ПОЛЮС: ТЕКСТ, КОТОРЫЙ ЧИТАЮТ. Лестница выше — про фоны, и все её
     ступени сидят в светлой полосе 235–255. Тексту письма место на другом
     конце, и он единственный, кому там место.

     Замер владельца по снимку: у Shopify самый тёмный пиксель текста
     сообщения — 69 из 255, у нас было 97. Бледное глаз читает как мелкое —
     отсюда и жалоба «мельче, чем у Shopify», хотя размер у нас даже больше
     (14px в переписке против 13px в списке).

     🔴 ПОЧЕМУ БЫЛО 97, А НЕ 48. `.note-text` своего цвета не имел и наследовал
     его от общего класса `.note` (строка 330) — а тот заведён для мелких
     приглушённых подписей и красит в `--dim`. Совпадение имён: в ленте карточка
     письма это `li.note`, и правило для подписей накрывало текст письма. Теперь
     у текста письма цвет свой и названный. */
  --ink:#454545;         /* текст письма: 69 из 255, замер эталона */
  /* 🔴 ВЫСОТА ШАПКИ КОЛОНКИ — ОДНА НА ВСЕ. Замер до правки: низ шапки списка
     на 87, низ шапки переписки на 96 — девять пикселей, и вместо одной линии
     через всю ширину видно два отрезка на разных уровнях. */
  --head:52px;
  --radius:12px;
  /* 🔴 РАДИУС ОБЛАЧКА — ОДИН НА ВСЕ ТРИ ВИДА (клиент, мы, событие). Форма сама
     должна говорить «реплика», а не «прямоугольник со сбитыми углами»; и
     проставленный числом в трёх местах он разошёлся бы при первой правке. */
  --bubble:14px;
  --shadow:0 1px 0 rgba(0,0,0,.05), 0 0 0 1px rgba(0,0,0,.04);
  --pad:16px;
}
*{box-sizing:border-box}
html,body{height:100%;overflow:hidden}
/* 🔴 СТРАНИЦА — ВЕРТИКАЛЬНЫЙ FLEX, И НИКАКОЙ АРИФМЕТИКИ С ВЫСОТОЙ ШАПКИ.
   Было `calc(100vh - 41px)` у полосы колонок и у меню — то есть обещание, что
   шапка ровно 41px. Стоит шрифту или отступу в ней измениться на пару
   пикселей, и сумма «шапка + колонки» перестаёт совпадать с окном; разница
   вылезает полосой прокрутки у всей страницы, и ищут её потом долго.

   Теперь шапка занимает свою высоту сама, а полоса колонок берёт ОСТАТОК
   (`flex:1`). `min-height:0` при этом обязателен: без него элемент flex не
   даёт детям сжаться меньше содержимого, и высота вылезает наружу — ровно те
   два сантиметра, которые видно полосой справа. */
/* 🔴 ГАРНИТУРА — СИСТЕМНАЯ СТОПКА В ПОРЯДКЕ POLARIS, а не один шрифт. Текст
   рисуется РОДНЫМ шрифтом той машины, где открыт: на macOS `-apple-system`, на
   Windows `Segoe UI`, на Android `Roboto`. У нас первым стоял `Inter` — то
   есть на всех машинах рисовался один и тот же шрифт, и на владельческом маке
   он выглядел чужим среди системного окружения. Порядок взят у Polaris
   целиком, включая запасные. */
body{margin:0;font:13px/1.45 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,
  Inter,"Helvetica Neue",Arial,sans-serif;
  color:var(--fg);background:#0a0a0a;display:flex;flex-direction:column}
.maplink{margin:.15rem 0 .7rem}
.maplink a{color:var(--acc);text-decoration:none}
.maplink a:hover{text-decoration:underline}

/* ── Тёмная полоса сверху ──────────────────────────────────────────────────
   Держится наверху при прокрутке: поиск нужен с любого экрана. Тёмная она не
   ради красоты — с меню слева и серым фоном страница получает рамку с трёх
   сторон и перестаёт выглядеть обрезанной. */
.topbar{position:sticky;top:0;z-index:30;display:flex;align-items:center;gap:1rem;
  padding:.45rem .8rem;background:#0a0a0a;color:#e3e3e3}
.topbar .logo{color:#fff;font-weight:700;letter-spacing:.03em;text-decoration:none;
  flex:0 0 auto;padding-right:.4rem}
.topbar .search{flex:1 1 auto;display:flex;justify-content:center}
/* Место под общий поиск. Заглушка НЕ поле ввода: кликабельное поле, которое
   ничего не ищет, врало бы. Серая плашка говорит «здесь будет», и это правда. */
.topbar .search.slot{max-width:640px;margin:0 auto;padding:.32rem .7rem;
  color:#8a8a8a;background:#282828;border:1px solid #454545;border-radius:8px;
  width:100%;text-align:center;cursor:default;font-size:12px}
.topbar .ro{margin-left:0;flex:0 0 auto;color:#c9c9c9;border-color:#4a4a4a}

/* ── Меню слева ────────────────────────────────────────────────────────────
   Фиксированная колонка, содержимое справа. Полоса не прокручивается вместе со
   страницей: разделов будет шесть с подпунктами, и терять их при прокрутке
   длинного списка заказов нельзя. */
.shell{display:flex;align-items:stretch;width:100%;max-width:100vw;
  flex:1 1 auto;min-height:0;background:var(--bg);
  border-radius:12px;margin:0;overflow:clip}
/* 🔴 ФАЗА 9.1, ПУНКТ 3.1: ЗОН РОВНО ДВЕ. Серая — меню, белая — содержание.
   Тон панели снят пипеткой с Shopify Inbox: #ebebeb. Я до этого углублял его
   до #e6e6e6, чтобы белая плашка выделения отличалась сильнее, — замер
   эталона показал, что там панель светлее, а выделение НЕ белое (#fafafa), и
   разница между ними всего 15 из 255. Возвращаю замеренное. */
/* Меню тянется на всю высоту полосы колонок само (`align-items:stretch`) —
   ни своей высоты, ни `sticky` ему больше не нужно: страница не прокручивается
   вовсе, а прокрутка внутри меню осталась своя. */
.rail{flex:0 0 216px;width:216px;min-height:0;
  display:flex;flex-direction:column;gap:.15rem;padding:.7rem .55rem;
  background:var(--rail);border-right:1px solid #dcdcdc;overflow:auto}
.rail .brand{display:block;font-weight:700;color:var(--fg);text-decoration:none;
  padding:.2rem .5rem .7rem;letter-spacing:.02em}
.rail nav{display:flex;flex-direction:column;gap:.1rem}
.rail .lnk{display:flex;align-items:center;gap:.55rem;padding:.34rem .5rem;
  border-radius:8px;color:var(--fg);text-decoration:none;font-weight:500}
.rail a.lnk:hover{background:#dcdcdc}
.rail .lnk.cur{background:var(--pick-menu);box-shadow:var(--shadow);font-weight:600}
/* 🔴 ОТКРЫТАЯ ГРУППА И ВЫБРАННЫЙ ПУНКТ ОТМЕЧЕНЫ РАЗНЫМ. Заголовок группы не
   выбирается — ему достаётся только вес шрифта; плашка принадлежит пункту.
   Взять для группы плашку потише (второй оттенок) было нельзя: два светлых
   пятна подряд читаются как два выделения, а не как «главное и его часть», —
   именно это владелец и увидел после `420fbdf`. */
.rail .sect.on > .lnk{font-weight:600;color:#000}
.rail .lnk.off{color:#8a8a8a;cursor:default}
.rail .lnk.off .ic{opacity:.6}
.rail .ic{width:16px;height:16px;flex:0 0 16px}
.rail .cnt{margin-left:auto;font-weight:600;font-size:12px;color:var(--dim)}
.rail .subs{display:flex;flex-direction:column;margin:.1rem 0 .3rem}
.rail .subs a{padding:.24rem .5rem .24rem 2.1rem;border-radius:8px;
  color:var(--dim);text-decoration:none}
.rail .subs a:hover{background:#dcdcdc}
/* Папка выделяется ТОЙ ЖЕ белой плашкой, что и раздел: «Входящие» — такой же
   выбор, как «Сообщения клиентов», и выглядеть он обязан так же. Прежний
   #e4e4e4 отличался от фона меню на 7 из 255 и не читался вовсе. */
.rail .subs a.cur{color:var(--fg);font-weight:600;background:var(--pick-menu);
  box-shadow:var(--shadow)}
.railhead{margin:.9rem .5rem .25rem;font-size:11px;letter-spacing:.06em;
  text-transform:uppercase;color:#8a8a8a}
.rail .bottom{margin-top:auto}
.pane{flex:1 1 auto;min-width:0;min-height:0;overflow-x:hidden;overflow-y:auto;
  overscroll-behavior:contain}
.ro{margin-left:auto;font-size:12px;color:var(--dim);border:1px solid var(--line);border-radius:99px;padding:.1rem .6rem}
main{padding:var(--pad);max-width:none;min-width:0}
@media (max-width:900px){
  html,body{height:auto;overflow:auto}
  .shell{display:block}
  .shell{flex:0 1 auto;min-height:auto;overflow:visible}
  .rail{position:static;width:auto;height:auto;flex-direction:row;flex-wrap:wrap;
    align-items:center;border-right:none;border-bottom:1px solid #dcdcdc}
  .pane{height:auto;overflow:visible}
  .rail .subs{flex-direction:row}
  .rail .subs a{padding-left:.5rem}
  .railhead,.rail .bottom{display:none}
}
footer{padding:1rem var(--pad);color:var(--dim);font-size:12px;margin-top:2rem}
h1{font-size:20px;font-weight:650;margin:.1rem 0 .4rem}
h2{font-size:1.05rem;margin:1.6rem 0 .5rem}
h3{font-size:.9rem;margin:0 0 .5rem;color:var(--dim);text-transform:uppercase;letter-spacing:.04em}

.tiles{display:flex;gap:.6rem;flex-wrap:wrap;margin:.6rem 0 1rem}
.tile{border:none;border-radius:var(--radius);padding:.6rem 1rem;min-width:112px;
  background:var(--surface);box-shadow:var(--shadow)}
.tile b{display:block;font-size:1.5rem;line-height:1.1}
.tile span{color:var(--dim);font-size:12px}
.tile.alarm{border-color:var(--bad)}
/* Плитка «требуют внимания» — тем же цветом срочности, что и плашки. */
.tile.act{border-color:var(--urge);background:var(--urgebg)}
.periods{display:flex;gap:.4rem;flex-wrap:wrap}
.chip{padding:.15rem .7rem;border:1px solid var(--line);border-radius:99px;text-decoration:none;color:var(--dim);font-size:12px}
.chip.on{background:var(--fg);color:#fff;border-color:var(--fg)}

.filters{display:flex;gap:.4rem;flex-wrap:wrap;align-items:center;margin:.6rem 0}
.filters input,.filters select{padding:.3rem .5rem;border:1px solid var(--line);border-radius:6px;font:inherit}
/* Поля ввода остаются прямоугольными — они не кнопки; скругление
   отличает «нажать» от «вписать». */
.filters button{padding:.3rem .8rem;border:1px solid var(--line);border-radius:99px;font:inherit}
.filters input[type=search]{min-width:280px}
.filters button{background:var(--fg);color:#fff;border-color:var(--fg);cursor:pointer}
.clear{color:var(--dim);font-size:12px}
.found{color:var(--dim);margin:.4rem 0}
.hint{color:var(--dim);font-size:12px;line-height:1.4;margin:.4rem 0}

table.orders{border-collapse:collapse;width:100%;margin:.4rem 0}
/* Список Shopify — белая поверхность на сером фоне, а не голая сетка.
   `separate` нужен, чтобы скругление не обрезалось collapse-моделью таблицы. */
table.orders.list{border-collapse:separate;border-spacing:0;background:var(--surface);
  border-radius:var(--radius);box-shadow:var(--shadow);overflow:hidden}
table.orders.list thead{background:#f7f7f7}
table.orders.list tbody tr:last-child td{border-bottom:0}
.list-tools{position:sticky;top:0;z-index:18;background:var(--bg);
  overflow:visible;padding:.1rem 0 .45rem;
  box-shadow:0 8px 10px -12px rgba(0,0,0,.55)}
.orders-scroll{width:100%;overflow-x:hidden}
.orders-scroll table.orders.list{width:100%;min-width:0;table-layout:fixed}
table.orders.list th,table.orders.list td{overflow:hidden;text-overflow:ellipsis}
table.orders.list .select-col{width:34px;min-width:34px;max-width:34px;text-align:center;padding-left:.45rem;padding-right:.2rem}
table.orders.list th:nth-child(2){width:88px}
table.orders.list td.ordcell{overflow:visible;text-overflow:clip}
table.orders.list th:nth-child(3){width:82px}
table.orders.list th:nth-child(4){width:58px}
table.orders.list th:nth-child(5){width:105px}
table.orders.list th:nth-child(6){width:92px}
table.orders.list th:nth-child(7){width:142px}
table.orders.list th:nth-child(8){width:120px}
table.orders.list th:nth-child(9){width:155px}
table.orders.list th:nth-child(10){width:54px}
table.orders.list th:nth-child(11){width:110px}
table.orders.list th:nth-child(13){width:95px}
table.orders.list th:nth-child(14){width:125px}
/* Последняя колонка содержит не число, а результат возврата. 74 px обрезали
   плашку до нескольких букв; резервируем ей рабочую ширину. */
table.orders.list th:nth-child(16){width:150px}
table.orders.list .shipping-col{width:145px;min-width:0;max-width:145px}
table.orders.list td.shipping-col{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* Длинный дедлайн спора не имеет права определять ширину всего списка.
   Shopify оставляет служебные статусы компактными: здесь плашка переносится
   внутри своей колонки, а остальная таблица сохраняет рабочую ширину. */
table.orders.list .dispute-col{width:185px;min-width:0;max-width:185px}
table.orders.list td.dispute-col{position:relative;overflow:visible;white-space:nowrap}
table.orders.list .dispute-col .tag{display:block;width:100%;max-width:100%;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.5;
  padding:2px 7px;vertical-align:top}
/* Полный текст открывается поверх соседних колонок, а не растягивает строку.
   Справа места нет, поэтому плашка раскрывается влево от своего края. */
table.orders.list .dispute-col .tag:hover,
table.orders.list .dispute-col .tag:focus{position:absolute;z-index:25;right:.45rem;top:.22rem;
  width:max-content;max-width:360px;white-space:normal;overflow:visible;text-overflow:clip;
  outline:none;box-shadow:0 4px 14px rgba(0,0,0,.18)}
/* Возврат в последней колонке ведёт себя так же: строку не расширяет, но при
   наведении раскрывает всю формулировку и сумму поверх таблицы влево. */
table.orders.list td.money-col{position:relative;overflow:visible;white-space:nowrap}
table.orders.list .money-col .tag{display:block;width:100%;max-width:100%;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.5;
  padding:2px 7px;vertical-align:top}
table.orders.list .money-col .tag:hover,
table.orders.list .money-col .tag:focus{position:absolute;z-index:25;right:.45rem;top:.22rem;
  width:max-content;max-width:360px;white-space:normal;overflow:visible;text-overflow:clip;
  outline:none;box-shadow:0 4px 14px rgba(0,0,0,.18)}
/* «Деньги возвращены» не сокращаем до двусмысленного «Возвращено».
   В таблице чип остаётся компактным, а полный текст открывается поверх
   соседней ячейки при наведении или фокусе — так же, как чип спора. */
table.orders.list .financial-col{width:165px;min-width:165px;max-width:165px}
table.orders.list td.financial-col{position:relative;overflow:visible;white-space:nowrap}
table.orders.list .financial-col .pill{display:block;max-width:100%;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
table.orders.list .financial-col .pill:hover,
table.orders.list .financial-col .pill:focus{position:absolute;z-index:25;left:.45rem;top:.22rem;
  width:max-content;max-width:260px;overflow:visible;text-overflow:clip;outline:none;
  box-shadow:0 4px 14px rgba(0,0,0,.18)}
table.orders th{text-align:left;font-size:12px;color:var(--dim);font-weight:600;border-bottom:1px solid var(--line);padding:.35rem .5rem}
table.orders th a{color:inherit;text-decoration:none}
table.orders td{padding:.35rem .5rem;border-bottom:1px solid var(--line);vertical-align:top}
table.orders tr:hover td{background:#fafafa}
td.num{text-align:right;font-variant-numeric:tabular-nums;white-space:nowrap}
/* 🔴 ЗАГОЛОВОК ВЫРАВНИВАЕТСЯ ТАК ЖЕ, КАК КОЛОНКА. Числа стояли по правому краю,
   а их заголовки — по левому, и при разной ширине колонок «19%» оказывалось не
   под «ставка», а сумма не под «сумма». Одно правило на все таблицы: класс
   колонки задаётся на th И на td, выравнивание берётся из него, а не из типа
   ячейки. */
/* 🔴 СПЕЦИФИЧНОСТЬ, А НЕ ПОРЯДОК. Здесь стояло `th.num{text-align:right}` — и
   не работало: селектор `table.orders th` выше весом (класс + два типа против
   класса + один), поэтому заголовки оставались по левому краю, сколько их ни
   помечай классом. Правку заметил владелец на таблице налогов. Селектор ниже
   специфичнее обоих, и теперь класс колонки действительно решает. */
table.orders th.num,table.sums th.num,table.calc th.num,th.num{text-align:right}
table.orders th.mid,th.mid,td.mid{text-align:center}
/* Ширины фиксированные: иначе колонка «кто платит» с длинной подписью тянет на
   себя место, и числовые колонки съезжают от строки к строке. */
table.fixed{table-layout:fixed}
table.fixed td,table.fixed th{overflow-wrap:anywhere}
td a{color:var(--acc);text-decoration:none}
.empty{color:var(--dim);padding:.6rem 0}
.dim{color:var(--dim)}

.tag{display:inline-block;font-size:12px;line-height:20px;padding:0 8px;border-radius:8px;
  background:#ebebeb;color:var(--dim);white-space:nowrap;margin-right:.25rem}
.tag.warn{background:var(--warnbg);color:var(--warn)}
/* Пометка владельца о закупке. Стоит НАД списком полей площадки и заметнее их:
   остальные шесть — служебные даты площадки, а эта строка написана человеком и
   связывает заказ с покупкой у поставщика. Перенос разрешён: встречается
   «USA Bosch 4085277042» и длиннее. */
.privnote{margin:.2rem 0 .7rem;line-height:1.5;overflow-wrap:anywhere}
.tag.bad{background:var(--badbg);color:var(--bad)}
.tag.act{background:var(--urgebg);color:var(--urge);font-weight:600;
  box-shadow:inset 0 0 0 1px var(--urgeline)}

.group{margin:var(--pad) 0;border:none;border-radius:var(--radius);
  padding:var(--pad);background:var(--surface);box-shadow:var(--shadow)}
.group h2{margin:0 0 .3rem;display:flex;align-items:center;gap:.6rem}
.count{font-size:12px;background:#f3f4f6;border-radius:99px;padding:.05rem .6rem;color:var(--dim)}
.count.alarm{background:var(--badbg);color:var(--bad);font-weight:700}
.sum{font-size:12px;color:var(--dim);margin-left:auto}
.note{color:var(--dim);font-size:12px;margin:.2rem 0 .6rem}
details.secondary{margin-top:.6rem}
details.secondary summary{cursor:pointer;color:var(--dim);font-size:12px}
table.dim td{color:var(--dim)}

.cards{display:flex;gap:.8rem;flex-wrap:wrap}
.card{border:none;border-radius:var(--radius);padding:var(--pad);min-width:270px;
  flex:1;background:var(--surface);box-shadow:var(--shadow)}
.card.money{min-width:340px}
dl{display:grid;grid-template-columns:auto 1fr;gap:.15rem .8rem;margin:0}
dt{color:var(--dim)} dd{margin:0;text-align:right;font-variant-numeric:tabular-nums}
dt.sep,dd.sep{border-top:1px solid var(--line);padding-top:.3rem;margin-top:.3rem}
dt.bad,dd.bad{color:var(--bad)}
.card button{padding:.3rem .8rem;border:1px solid var(--line);background:#fff;border-radius:99px;cursor:pointer;font:inherit}
.alarm-box{background:var(--badbg);color:var(--bad);border-radius:6px;padding:.4rem .6rem;font-size:12px;margin:.5rem 0 0}

.timeline{list-style:none;padding:0;margin:.4rem 0;border-left:2px solid var(--line)}
.timeline li{padding:.15rem 0 .15rem .8rem;font-size:13px}
.timeline li.crit{border-left:2px solid var(--bad);margin-left:-2px}
.timeline .when{color:var(--dim);font-variant-numeric:tabular-nums;margin-right:.6rem}
.pager{display:flex;gap:1rem;align-items:center;color:var(--dim);margin:.8rem 0}

.timeline li.note{border-left:3px solid var(--acc);margin-left:-2px;background:#f5f8ff;
  padding:.35rem .6rem;border-radius:0 6px 6px 0;margin-top:.3rem;margin-bottom:.3rem}
.note-text{white-space:pre-wrap;margin-top:.15rem;font-size:14px;color:var(--ink)}
.ev-text{color:var(--dim);font-size:12px;margin-top:.05rem}
.card.wide{flex:1 1 100%}
.message-box{position:relative;overflow:hidden}
.message-box::before{content:"";position:absolute;inset:0 auto 0 0;width:4px}
.message-box h2{margin-bottom:.55rem}
.message-box p{margin:0;line-height:1.5;white-space:pre-wrap;overflow-wrap:anywhere}
.customer-message::before{background:#f8d6a4}
.seller-message::before{background:#f8eb78}
.shipment-actions{display:flex;justify-content:flex-end;gap:.5rem;
  border-top:1px solid var(--line);margin-top:.8rem;padding-top:.65rem}
.shipment-actions button{border-radius:8px;padding:.42rem .75rem;font:inherit;
  font-size:12px;font-weight:600}
.shipment-actions .secondary{border:1px solid #c9cccf;background:#fff;color:#303030}
.shipment-actions .primary{border:1px solid #1f1f1f;background:#303030;color:#fff;
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.15)}
.shipment-actions button:disabled{cursor:not-allowed;opacity:.58}
table.calc{border-collapse:collapse;width:100%;margin:.3rem 0 .8rem;font-variant-numeric:tabular-nums}
table.calc td{padding:.18rem .5rem;vertical-align:top;border-bottom:1px solid #f0f2f4}
table.calc td.op{width:1.2rem;color:var(--dim);text-align:center}
table.calc td.when{width:6.5rem;color:var(--dim);white-space:nowrap}
table.calc td.num{text-align:right;white-space:nowrap;width:9rem}
table.calc td.why{color:var(--dim);font-size:12px;width:45%}
table.calc tr.sub td{color:var(--dim);padding-left:1.4rem}
table.calc tr.rule td{border-top:2px solid var(--fg);border-bottom:none;padding-top:.3rem}
table.calc tr.warnrow td{background:var(--warnbg)}
table.calc tr.dimrow td{color:var(--dim)}
table.calc td.bad{color:var(--bad)}
h4{margin:1rem 0 .2rem;font-size:.85rem;color:var(--dim);text-transform:uppercase;letter-spacing:.04em}

/* ── Карточка заказа: раскладка Shopify ── */
.ordhead{display:flex;align-items:flex-start;gap:1rem;margin:0 0 1rem;
  padding:.55rem .75rem;background:var(--surface);border-radius:var(--radius);
  box-shadow:var(--shadow)}
.ordhead h1{margin:0 0 .3rem}
.ordhead .sub{color:var(--dim);font-size:12px;margin:.35rem 0 0}
.ordhead .acts{margin-left:auto}
.band{padding:10px 14px;border-radius:8px;margin:0 0 14px;font-size:13px;
  line-height:1.45}
.band.bad{background:var(--badbg);color:var(--bad)}
.band.warn{background:var(--warnbg);color:var(--warn)}
.band code{background:rgba(0,0,0,.06);padding:0 4px;border-radius:4px}
.pills{display:flex;gap:.4rem;flex-wrap:wrap}
.pill{font-size:12px;line-height:20px;padding:0 8px;border-radius:8px;font-weight:550;
  white-space:nowrap;display:inline-flex;align-items:center;gap:5px}
.pill::before{content:'';width:8px;height:8px;border-radius:50%;background:currentColor;
  opacity:.85;flex:0 0 8px}
/* pill-ok/wait/hold — прежняя схема цветов «по статусу»; заменена на схему
   «по состоянию посылки» (pill-grey/yellow/amber/red ниже). Оставлены
   пустыми намеренно НЕ были: классы удалены, чтобы старая разметка не
   могла тихо продолжить работать с прежними цветами. */
.pill-bad{background:var(--badbg);color:var(--bad)}
/* Класс называется -act, потому что означает «нужно действие». Краска в нём
   теперь срочная, а не успешная. */
.pill-act{background:var(--urgebg);color:var(--urge);font-weight:600;
  box-shadow:inset 0 0 0 1px var(--urgeline)}

/* ── Три колонки ───────────────────────────────────────────────────────────
   Центр сузился намеренно: на широком центре между подписью и суммой копилась
   пустота, и блок сумм переставал читаться как единое целое. Освободившееся
   место ушло вправо — во вторую боковую колонку, где живёт доставка. */
.grid{display:flex;gap:.75rem;align-items:flex-start;flex-wrap:wrap;min-width:0;max-width:100%}
/* При изменении доступной ширины растёт вся центральная колонка вместе с
   карточками и суммами внутри неё. */
.main{flex:1 1 620px;min-width:0}
.side{flex:1 1 290px;min-width:260px;max-width:340px}
.box{border:none;border-radius:var(--radius);padding:var(--pad);
  margin-bottom:var(--pad);background:var(--surface);box-shadow:var(--shadow);min-width:0}
.box h2{margin:0 0 .75rem;font-size:14px;font-weight:650;
  display:flex;align-items:center;gap:.5rem}
h3.day{font-size:.8rem;color:var(--dim);text-transform:uppercase;letter-spacing:.04em;margin:1rem 0 .3rem}

ul.items{list-style:none;padding:0;margin:0}
ul.items li{display:flex;gap:.7rem;align-items:center;padding:.5rem 0;border-bottom:1px solid var(--line)}
ul.items li:last-child{border-bottom:none}
.thumb{width:40px;height:40px;flex:0 0 40px;border:1px solid var(--line);border-radius:8px;
  display:flex;align-items:center;justify-content:center;overflow:hidden;background:#fafbfc}
.thumb img{max-width:100%;max-height:100%;object-fit:contain}
.nothumb{font-size:9px;color:var(--dim);text-align:center;line-height:1.1}
ul.items .what{flex:1;min-width:0}
ul.items .name{font-weight:500}
.itemweight{font-size:12px;color:var(--dim);margin-top:.15rem}
/* Закупка стоит рядом с весом и такого же роста: это справка о позиции,
   а не сумма к оплате. `.dim` целиком — когда данных нет. */
.itemcost{font-size:12px;color:var(--fg);margin-top:.15rem}
/* Расхождение оценки со счётом — сигнал к действию, а не справка: сама сумма
   красная, иначе взгляд цепляется за кружок и проходит мимо числа. */
.sums .diffbad{color:var(--bad)}
/* 🔴 Группирующей заливки у трёх строк доставки НЕТ — решение владельца
   31.07.2026: порядок строк сам говорит, что это единый блок, а заливка в
   этой таблице уже значит «итог» (.tot), и второй фон спорил бы с первым. */
/* Отметка «доставлено» со слов человека. Раскрывается по нажатию: обычно она
   не нужна, а постоянно открытая форма рядом с историей перевозчика читается
   как приглашение спорить с ним. */
.markdelivered{margin:.4rem 0}
.markdelivered summary{cursor:pointer;color:var(--link);font-size:13px}
.markdelivered form{display:flex;flex-wrap:wrap;gap:.6rem;align-items:flex-end;margin-top:.5rem}
.markdelivered label{display:flex;flex-direction:column;font-size:12px;color:var(--dim);gap:.2rem}
.markdelivered input[type=text]{min-width:22rem}
.inlineform{display:inline}
.itemcost.dim{color:var(--dim)}
.parcelweight{margin:.7rem 0 0;padding-top:.6rem;border-top:1px solid var(--line);
  font-variant-numeric:tabular-nums}
.parcelmeta{display:flex;flex-direction:column;gap:.12rem;margin:.2rem 0 .7rem;
  font-size:12px;font-variant-numeric:tabular-nums}
ul.items .qty{white-space:nowrap;font-size:12px}
ul.items .num{width:11rem;text-align:right;font-variant-numeric:tabular-nums;
  white-space:nowrap}
/* 🔴 Нетто СВОЕЙ СТРОКОЙ. Инлайновая вторая величина слипалась с итогом:
   «94.66 EUR75.73 EUR без VAT (25%, SE)». Блок разрывает строку сам, не
   полагаясь на пробел, а nowrap не даёт «(25%, SE)» уехать на третью. */
/* 🔴 `display` ЗДЕСЬ БОЛЬШЕ НЕ НАЗЫВАЕТСЯ, И ЭТО ПОЧИНКА, А НЕ УБОРКА. Правило
   старше пометки «без VAT» и перебивало её раскладку по весу селектора: флекс
   не применялся, зазор между словами и числом исчезал, и на экране выходило
   «без VAT8.33 EUR». Раскладка у всех трёх мест одна и живёт в `.net` ниже —
   здесь остаются только шрифт и отступ. */
ul.items .num .net{font-size:12px;color:var(--dim);font-weight:400;
  margin-top:2px;white-space:nowrap}

ul.tl{list-style:none;padding:0;margin:0 0 .4rem}
ul.tl li.sys{display:flex;gap:.6rem;align-items:baseline;padding:.2rem 0}
ul.tl li.sys .dot{width:7px;height:7px;border-radius:50%;background:var(--line);flex:0 0 7px;margin-top:.45rem}
ul.tl li.sys.crit .dot{background:var(--bad)}
ul.tl li.sys .time{margin-left:auto;font-size:12px;white-space:nowrap}
ul.tl li.note{display:flex;gap:.6rem;border:1px solid var(--acc);background:#f5f8ff;
  border-radius:var(--bubble);padding:.5rem .7rem;margin:.4rem 0}
.ava{width:26px;height:26px;flex:0 0 26px;border-radius:50%;background:var(--acc);color:#fff;
  display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:700}

.who{font-weight:600;margin:0 0 .2rem}
dl.contact{grid-template-columns:auto 1fr;font-size:13px;margin-top:.5rem}
dl.contact dd{text-align:right;overflow-wrap:break-word}
p.addr{line-height:1.45;margin:0}

/* ── Ближе к Shopify: три столбца в оплате, подзаголовки в правой колонке ── */
.boxhead{margin-bottom:.7rem}
table.pay{width:100%;border-collapse:collapse;font-variant-numeric:tabular-nums}
table.pay td{padding:.3rem 0;vertical-align:top}
table.pay td.k{width:9rem;color:var(--fg)}
table.pay td.d{color:var(--dim);font-size:13px}
table.pay td.v{text-align:right;white-space:nowrap;width:11rem}
table.pay tr.tot td{font-weight:600;border-top:1px solid var(--line);padding-top:.5rem}
table.pay tbody.paid td{border-top:1px solid var(--line);padding-top:.5rem}
table.pay tr.warnrow td{background:var(--warnbg)}
h3.sh{font-size:13px;font-weight:600;color:var(--fg);text-transform:none;letter-spacing:0;margin:1rem 0 .3rem}
.side p{margin:.15rem 0}
.side p.link{color:var(--acc)}
.side p.small{font-size:12px}
.customer-orders-link{color:var(--acc);text-decoration:none}
.customer-orders-link:hover{text-decoration:underline}
.riskbar{height:5px;border-radius:99px;background:var(--line);overflow:hidden;margin:.4rem 0 .3rem}
.riskbar i{display:block;height:100%;border-radius:99px}
.riskbar i.l0{width:33%;background:#0f9d58}
.riskbar i.l1{width:66%;background:#e8a33d}
.riskbar i.l2{width:100%;background:var(--bad)}
.risklabels{display:flex;justify-content:space-between;font-size:12px;color:var(--dim)}
.risklabels .on{color:var(--fg);font-weight:600}
.ev-ru{font-size:13px;margin-top:.05rem}
.ev-text{color:var(--dim);font-size:12px;margin-top:.05rem}
.switches{display:flex;justify-content:space-between;align-items:center;gap:1rem;flex-wrap:wrap}
.seg{display:inline-flex;border:1px solid var(--line);border-radius:6px;overflow:hidden}
.seg a{padding:.1rem .6rem;color:var(--dim);text-decoration:none;font-size:12px}
.seg a.on{background:var(--fg);color:#fff}
.ways{display:flex;gap:.4rem;flex-wrap:wrap;margin-top:.4rem}
/* 🔴 ОДНА ФОРМА НА ВСЕ КНОПКИ ДЕЙСТВИЯ. Скруглённая — она уже была у
   «Позвонить», и рядом с прямоугольными это выглядело как две разные
   породы кнопок. Селектор перечисляет ОБА вида (ссылка и button),
   потому что «Позвонить» — ссылка tel:, а остальные — кнопки формы. */
a.way,button.way{font-size:12px;border:1px solid var(--line);border-radius:99px;padding:.1rem .6rem;
  color:var(--acc);text-decoration:none}
a.way:hover{border-color:var(--acc)}
.grid{--mainw:620px}
.dragger{position:relative;align-self:stretch;flex:0 0 0;width:0;
  margin-inline:-6px;cursor:col-resize;touch-action:none;z-index:4}
.dragger::before{content:"";position:absolute;inset-block:0;left:3px;width:6px;
  border-radius:99px;background:transparent}
.dragger:hover::before,.dragger.moving::before{background:#c7c7c7}
body.resizing-order{cursor:col-resize;user-select:none}

/* Шапка заказа стоит на сером фоне, поэтому карточкой не оформляется. */
.ordhead{background:transparent;padding:0 0 .2rem}
.side .box,.main .box{overflow:hidden}
table.pay td,table.calc td{font-size:13px}
table.calc td.why,table.pay td.d{font-size:12px}
/* 🔴 РАМКА СТАЛА ЗАЛИВКОЙ. Обводка убрана, а её тон (`--line`) перешёл в фон
   всей карточки: получается бежевое поле — то же, к чему пришёл Shopify со
   своими облачками. Новых цветов не заведено ни одного, тон взят ровно тот,
   что был у рамки.

   🔴 ТРИ УРОВНЯ, А НЕ ДВА ПЯТНА. Колонка переписки белая, карточка письма
   `--line`, цитата и оригинал внутри неё `--bg` — три различимых тона.
   «Фон в фоне» владелец уже ловил однажды, и повторять это нельзя. */
/* 🔴 ТОНА ПЕРЕБРАНЫ 01.08.2026. Сначала облачко залили тоном бывшей рамки
   (`--line`), и владелец сверился со Shopify: там облачко клиента — очень
   светлый серый на белом, «буквально на грани», читается формой и отступом, а
   не цветом. У нас выходило заметно темнее.

   🔴 И УРОВНЕЙ СТАЛО ДВА, А НЕ ТРИ. Прежде облачко было тёмным (`--line`), а
   оригинал внутри — светлым окошком; владелец предложил взять ИМЕННО ЭТОТ
   светлый тон на всё облачко, а внутри разделять линией. Одно решение снимает
   сразу две жалобы: «облачко слишком тёмное» и «окно в окне».

       колонка переписки — `--surface` #fff,
       облачко письма    — `--bg`      #f1f1f1  (на грани, как просили),
       внутри облачка    — ЛИНИЯ `--line`, а не заливка.
   Ни одного нового цвета не заведено. */
ul.tl li.note{border:0;background:var(--bubble-bg);box-shadow:none}
/* Бирка внутри карточки была #ebebeb — на бежевом это тот же тон, и она
   растворилась бы. Белая читается и не спорит с текстом. */
li.note .tag{background:var(--surface)}

/* 🔴 НИТЬ С ТОЧКАМИ. У Shopify события нанизаны на вертикальную линию, и она
   же держит взгляд при прокрутке длинной ленты. Точка «прокалывает» линию
   кольцом цвета фона — иначе линия проходит сквозь неё и точка теряется.
   Кольцо красится в --bg, потому что лента лежит на сером фоне страницы; в
   белой карточке (лента пути) этой нити нет вовсе. */
.tlwrap ul.tl{position:relative;padding-left:0}
/* Нить темнее --line: та рисовалась на белом фоне карточек, а здесь фон серый,
   и #e3e3e3 на #f1f1f1 не видно вовсе — линия была, но её не было на экране. */
.tlwrap ul.tl::before{content:none}
.tlwrap ul.tl li.sys{padding:.35rem 0;position:relative}
.tlwrap ul.tl li.sys .dot{background:#b5b5b5;box-shadow:0 0 0 3px var(--bg)}
.tlwrap ul.tl li.sys.crit .dot{background:var(--bad)}
/* Наша запись — белая карточка поверх нити: она наша, и это видно без подписи. */
.tlwrap ul.tl li.note{position:relative;margin-left:0}
/* Дата стоит над колонкой ТЕКСТА, а не над точками: точки образуют нить, и
   вклинившийся в неё заголовок читается как ещё одно событие. */
.tlwrap h3.day{margin:1.1rem 0 .35rem;padding-left:calc(7px + .6rem)}

/* ── Блоки сумм. Ширина ограничена намеренно ────────────────────────────────
   Проблема была не в колонках, а в ширине: при растяжении на всю центральную
   колонку между пояснением и суммой копится пустота, и строка перестаёт
   читаться как одно целое. Ограничение ширины лечит это без перестройки. */
table.sums{width:100%;max-width:none;border-collapse:collapse;
  font-variant-numeric:tabular-nums}
table.sums td{padding:.35rem .5rem .35rem 0;vertical-align:baseline;
  border-bottom:1px solid var(--line)}
table.sums td.op{width:1rem;color:var(--dim);text-align:center;padding-right:.4rem}
table.sums td.when{width:6rem;color:var(--dim);white-space:nowrap;font-size:12px}
/* Название не переносится, пояснение стоит вплотную за ним и забирает остаток. */
table.sums td.k{white-space:nowrap}
table.sums td.d{width:100%;color:var(--dim);font-size:12px;padding-left:.6rem}
table.sums td.v{text-align:right;white-space:nowrap;padding-right:0}
/* Итог: отделён отступом и весом, а не только линией. */
table.sums tr.tot td{border-top:1px solid var(--fg);border-bottom:none;
  padding-top:.6rem;font-weight:650}
table.sums tr.sub td.k{padding-left:1.2rem;color:var(--dim)}
table.sums tr.sub td{border-bottom:none}
/* Длинное объяснение — строкой под числами, чтобы не растягивать их. */
table.sums tr.why td{color:var(--dim);font-size:12px;padding:.1rem 0 .5rem;
  border-bottom:1px solid var(--line);line-height:1.35}
table.sums tr.warnrow td{background:var(--warnbg)}
table.sums tr.dimrow td{color:var(--dim)}
table.sums td.bad{color:var(--bad)}
table.sums tbody.paid td{border-top:1px solid var(--line);padding-top:.5rem}

/* ── Фильтр списка: один вход вместо ряда выпадающих ────────────────────────
   Раскрытие на <details>, выбор — ссылками. Меню позиционируется абсолютно,
   поэтому оно накрывает таблицу, а не раздвигает её: раздвигание сбивало бы
   строку, на которую человек смотрел. */
.filterbar{display:flex;gap:.5rem;align-items:center;margin:.6rem 0;flex-wrap:wrap}
.quickbar{display:flex;gap:.45rem;align-items:center;flex-wrap:wrap;margin:.25rem 0 .45rem}
.quickbar>.quick{margin:0;display:flex;gap:.35rem;align-items:center;flex-wrap:wrap}
.quickbar>.chips{flex-basis:100%;margin:.1rem 0}
.filterbar details,.quickbar details.fieldpick{position:relative}
.filterbar .all-orders{display:inline-flex;align-items:center;padding:.32rem .8rem;
  background:var(--surface);border:1px solid var(--line);border-radius:8px;
  box-shadow:var(--shadow);color:var(--fg);text-decoration:none;white-space:nowrap}
.filterbar .all-orders:hover{border-color:var(--acc)}
.filterbar summary,.quickbar summary{list-style:none;cursor:pointer;padding:.32rem .8rem;
  background:var(--surface);border:1px solid var(--line);border-radius:8px;
  box-shadow:var(--shadow);white-space:nowrap}
.filterbar summary::-webkit-details-marker,.quickbar summary::-webkit-details-marker{display:none}
.filterbar details[open]>summary,.quickbar details[open]>summary{border-color:var(--acc)}
.filterbar .menu,.quickbar .menu{position:absolute;z-index:80;top:calc(100% + 4px);left:0;
  min-width:270px;max-height:60vh;overflow:auto;padding:.35rem;
  background:var(--surface);border:1px solid var(--line);border-radius:10px;
  box-shadow:0 6px 20px rgba(0,0,0,.14)}
.filterbar .menu>a,.filterbar .vals a,.quickbar .menu>a,.quickbar .vals a{display:block;padding:.3rem .6rem;
  border-radius:6px;color:var(--fg);text-decoration:none}
.filterbar .menu>a:hover,.filterbar .vals a:hover,.quickbar .menu>a:hover,.quickbar .vals a:hover{background:#f1f1f1}
.filterbar .menu .off,.quickbar .menu .off{display:block;padding:.3rem .6rem;color:#8a8a8a;font-size:12px}
.filterbar details.one>summary,.quickbar details.one>summary{border:none;box-shadow:none;background:transparent;
  padding:.3rem .6rem;border-radius:6px}
.filterbar details.one>summary:hover,.quickbar details.one>summary:hover{background:#f1f1f1}
.filterbar details.one[open]>summary,.quickbar details.one[open]>summary{font-weight:600}
.filterbar .vals,.quickbar .vals{padding:.1rem 0 .3rem .8rem}
.filterbar .vals .dim,.quickbar .vals .dim{font-size:12px}
.filterbar .dates,.quickbar .dates{display:flex;gap:.3rem;padding:.2rem .6rem;flex-wrap:wrap}
.filterbar .dates input,.filterbar .dates button,.quickbar .dates input,.quickbar .dates button{padding:.25rem .4rem;font:inherit;
  border:1px solid var(--line);border-radius:6px}
.filterbar .dates button,.quickbar .dates button{background:var(--fg);color:#fff;border-color:var(--fg);cursor:pointer;
  border-radius:99px;padding:.25rem .8rem}
.filterbar .listsearch{flex:1 1 240px;display:flex}
.filterbar .listsearch input{width:100%;padding:.32rem .7rem;font:inherit;
  border:1px solid var(--line);border-radius:8px;background:var(--surface)}

/* Выбранные фильтры — таблетками, каждую можно снять по отдельности. */
.chips{display:flex;gap:.4rem;flex-wrap:wrap;align-items:center;margin:.3rem 0 .6rem}
.chosen{display:inline-flex;gap:.4rem;align-items:center;font-size:12px;
  background:#e3e3e3;border-radius:8px;padding:.12rem .5rem}
.chosen a{color:var(--dim);text-decoration:none;font-weight:700}
.chosen a:hover{color:var(--bad)}

/* Отменённый заказ зачёркнут насквозь — приём из админки Shopify. Он остаётся
   в списке (его всё ещё ищут по номеру), но недействительность видна раньше,
   чем читается статус. Цветом это не передать: серый у нас значит «неважно». */
table.list tr.void td{text-decoration:line-through;color:#8a8a8a}
table.list tr.void td .tag{text-decoration:none}
table.list td{white-space:nowrap}
table.list td.ordcell{white-space:nowrap}
.note-ic{color:var(--dim);font-size:12px}
/* 🔴 .tag.ship УДАЛЁН 28.07.2026: синий на «в пути» не означал ни действия,
   ни его отсутствия, а был четвёртым цветом в палитре из трёх. */

/* ── Полоса показателей ────────────────────────────────────────────────────
   Одна карточка, ячейки разделены тонкими линиями — как в админке Shopify.
   Прокручивается по горизонтали ВНУТРИ себя: на узком экране показатели должны
   уезжать вбок, а не ломать страницу. */
.strip{display:block;position:relative;margin:.2rem 0 .8rem;
  background:var(--surface);border-radius:var(--radius);box-shadow:var(--shadow)}
/* Атрибут hidden ставит крестик. Явный display:block выше не должен его
   перебивать: иначе состояние сохранялось, но полоса визуально оставалась. */
.strip[hidden]{display:none}
.strip-show{margin:.2rem 0 .8rem;padding:.35rem .7rem;border:1px solid var(--line);
  border-radius:8px;background:var(--surface);color:var(--dim);font:inherit;cursor:pointer}
.orders-actions .strip-show{margin:0}
.strip-main{display:flex;align-items:stretch;overflow-x:auto}
.strip-note{margin:0;padding:.4rem .8rem .5rem;border-top:1px solid var(--line);
  color:var(--dim);font-size:11px;line-height:1.35}
.strip .period{display:flex;flex-direction:column;justify-content:center;gap:.15rem;
  padding:.5rem .8rem;border-right:1px solid var(--line);flex:0 0 auto}
.mgroup{display:flex;gap:1.2rem;align-items:flex-start;flex-wrap:wrap;
  padding:0 0 .4rem;border-left:2px solid var(--line);padding-left:.9rem;margin-right:.4rem}
.mgroup .gtitle{font-size:11px;text-transform:uppercase;letter-spacing:.06em;
  color:var(--dim);width:100%;margin-bottom:-.2rem}
.mhint{font-size:11px;color:var(--dim);max-width:15rem;line-height:1.3;margin-top:2px}
.strip .period a{color:var(--dim);text-decoration:none;font-size:12px;
  padding:.05rem .4rem;border-radius:6px}
.strip .period a.on{background:var(--fg);color:#fff}
.metric{flex:1 1 0;min-width:170px;padding:.55rem .9rem;border-right:1px solid var(--line)}
.metric[role=button]{cursor:zoom-in;border-radius:8px;transition:background .12s}
/* 🔴 `outline:none` ЗДЕСЬ БЫЛ НАСТОЯЩИМ ДЕФЕКТОМ: показатель на главной
   доступен с клавиатуры, и обведение фокуса ему снимали совсем — то есть
   человек, идущий табом, не видел, где он. Осталась только подсветка фона. */
.metric[role=button]:hover,.metric[role=button]:focus-visible{background:#f5f7f9}
.metric:last-child{border-right:none}
.mlabel{color:var(--fg);font-weight:600;font-size:12px;margin-bottom:.2rem}
.mrow{display:flex;align-items:center;gap:.5rem}
.mrow b{font-size:1.05rem;font-weight:600;font-variant-numeric:tabular-nums}
.mdelta{font-size:12px;white-space:nowrap}
.mdelta.up{color:var(--act)} .mdelta.down{color:var(--bad)}
.mprev{margin-top:.12rem;color:var(--dim);font-size:11px;font-variant-numeric:tabular-nums}
.mprev b{color:var(--fg);font-weight:600}
.spark{flex:1 1 auto;min-width:48px;height:24px}
.spark polyline{fill:none;stroke:#3b8ce8;stroke-width:1.4;vector-effect:non-scaling-stroke}
.spark polyline.previous{stroke:#aeb7c2;stroke-width:1;stroke-dasharray:3 2}
.metric-dialog{width:min(920px,calc(100vw - 32px));padding:0;border:0;border-radius:14px;
  color:var(--fg);background:var(--surface);box-shadow:0 18px 60px rgba(0,0,0,.3)}
.metric-dialog::backdrop{background:rgba(0,0,0,.46)}
.metric-dialog-head{display:flex;align-items:center;justify-content:space-between;
  padding:.9rem 1.1rem;background:#f1f1f1;border-bottom:1px solid var(--line)}
.metric-dialog-head h2{margin:0;font-size:16px;text-transform:none;letter-spacing:0;color:var(--fg)}
.metric-dialog-head button{width:28px;height:28px;padding:0;border:0;border-radius:7px;
  background:#dedede;color:var(--dim);font-size:19px;cursor:pointer}
.metric-dialog-values{display:grid;grid-template-columns:1fr 1fr;gap:1rem;padding:1rem 1.1rem 0}
.metric-dialog-values>div{display:grid;grid-template-columns:auto 1fr auto;align-items:center;
  gap:.5rem;padding:.7rem .8rem;border-radius:9px;background:#f5f5f5}
.metric-dialog-values span{color:var(--dim);font-size:12px}
.metric-dialog-values b{font-size:16px;font-variant-numeric:tabular-nums}
.legend{display:block;width:18px;height:3px;border-radius:3px;background:#3b8ce8}
.legend.previous{height:0;border-top:2px dashed #9ca7b4;background:transparent}
.metric-chart{display:block;width:calc(100% - 2.2rem);height:320px;margin:1rem 1.1rem 1.2rem;
  border:1px solid var(--line);border-radius:9px;background:repeating-linear-gradient(to bottom,#fff 0,#fff 63px,#eceff2 64px)}
.metric-chart polyline{fill:none;vector-effect:non-scaling-stroke;stroke-linejoin:round;stroke-linecap:round}
.metric-chart .current{stroke:#2383e2;stroke-width:2}
.metric-chart .previous{stroke:#9ca7b4;stroke-width:1.5;stroke-dasharray:5 4}
@media(max-width:600px){.metric-dialog-values{grid-template-columns:1fr}.metric-chart{height:230px}}

/* Заголовок группы комиссий: это платёж, а не слагаемое — поэтому без знака
   минус, с отбивкой сверху и приглушённой суммой. */
table.sums tr.txnrow td{padding-top:.5rem;font-weight:600;border-bottom:none}
table.sums tr.txnrow td.v{font-weight:600;color:var(--dim)}

/* ── Правая колонка: без синевы ────────────────────────────────────────────
   У Shopify имя клиента синее, потому что ведёт в карточку покупателя. У нас
   такой страницы нет, а почта и телефон — обычные mailto:/tel:, которые
   открывают почтовик или звонилку. Подсвечивать нечего: синий и подчёркивание
   обещают переход, которого не будет.

   Кликабельность остаётся — курсор при наведении и говорит, что можно нажать.
*/
.side p.link{color:var(--fg)}
.side a[href^="mailto:"],
.side a[href^="tel:"],
.side a[href^="sms:"]{color:var(--fg);text-decoration:none;cursor:pointer}
.side a[href^="mailto:"]:hover,
.side a[href^="tel:"]:hover,
.side a[href^="sms:"]:hover{text-decoration:none;color:var(--fg)}
/* Контакты — обычный текст: ни цвета, ни подчёркивания, ни перехода. Курсор
   текстовый, потому что здесь именно читают и выделяют, а не нажимают.
   `user-select:text` стоит явно — это и есть требование: email копируют руками. */
.side p.contact{color:var(--fg);word-break:break-word;user-select:text;cursor:text}

/* Кнопки способов связи остаются обведёнными — это уже не текст, а действие,
   и рамка отличает их без цвета. */
a.way,button.way{color:var(--fg);background:var(--surface);cursor:pointer;font:inherit;font-size:12px}
a.way:hover{border-color:var(--fg)}

/* Возврат в выборку и переход по соседям. Стрелка без соседа не исчезает, а
   гаснет: пропадающий элемент сдвигает остальные, и глаз каждый раз ищет их
   заново. */
.ordhead .acts{display:flex;align-items:center;gap:.8rem}
.ordhead .acts a{color:var(--fg);text-decoration:none}
.head-actions{display:flex;align-items:center;gap:.4rem}
.head-action{display:inline-flex;align-items:center;gap:.3rem;min-height:30px;
  padding:.3rem .7rem;border:1px solid var(--line);border-radius:8px;
  background:#e9e9e9;color:var(--fg);font:inherit;font-size:12px;white-space:nowrap}
button.head-action:not(:disabled),.more-actions>summary{cursor:pointer}
button.head-action:disabled{color:#8a8a8a;cursor:not-allowed}
.more-actions{position:relative}
.more-actions>summary{list-style:none}
.more-actions>summary::-webkit-details-marker{display:none}
.more-actions[open]>summary{border-color:#8a8a8a;background:#dedede}
.action-menu{position:absolute;z-index:90;right:0;top:calc(100% + 5px);width:210px;
  padding:.35rem;background:var(--surface);border:1px solid var(--line);
  border-radius:10px;box-shadow:0 8px 24px rgba(0,0,0,.18)}
.action-menu button,.action-menu>a{display:block;width:100%;padding:.42rem .55rem;border:0;
  border-radius:6px;background:transparent;color:var(--fg);font:inherit;
  font-size:13px;text-align:left;cursor:pointer}
.action-menu button:hover:not(:disabled),.action-menu>a:hover{background:#f1f1f1}
.action-menu button:disabled{color:#a0a0a0;cursor:not-allowed}
.action-menu .action-group{margin:.3rem -.35rem 0;padding:.45rem .9rem .2rem;
  border-top:1px solid var(--line);color:var(--dim);font-size:11px}
.ordhead .near{display:inline-flex;align-items:center;gap:.5rem;font-size:12px;
  border:1px solid var(--line);border-radius:8px;padding:.1rem .5rem;
  background:var(--surface)}
.ordhead .near .pos{color:var(--dim);font-variant-numeric:tabular-nums}
.ordhead .near .off{color:#c9c9c9}

@media (max-width:700px){
  .ordhead{flex-wrap:wrap}
  .ordhead .acts{width:100%;justify-content:space-between;flex-wrap:wrap}
}

@media print{
  body,.shell,.pane,main{background:#fff!important}
  .topbar,.rail,footer,.no-print,.ordhead .near,.shipment-actions,
  form.notecard,.switches{display:none!important}
  .shell,.pane,main{display:block!important;width:100%!important;max-width:none!important;
    margin:0!important;padding:0!important}
  .ordhead{break-inside:avoid;margin-bottom:.5rem}
  .grid{display:block!important}
  .dragger{display:none!important}
  .main,.side{width:100%!important;max-width:none!important}
  .box{break-inside:avoid;box-shadow:none!important;border:1px solid #ddd!important}
  a{color:#000!important;text-decoration:none!important}
}

/* Хлебная крошка в заголовке карточки: значок списка, шеврон, номер.
   Область нажатия у значка 40x40 при самом значке в 16px — промах по нему
   уводит со страницы, и цена промаха выше, чем цена лишних пикселей. */
.ordhead h1.crumb{display:flex;align-items:center;gap:.15rem}
.ordhead .tolist{display:inline-flex;align-items:center;justify-content:center;
  width:40px;height:40px;margin-left:-10px;border-radius:8px;color:var(--dim);
  text-decoration:none;flex:0 0 40px}
.ordhead .tolist:hover{background:#e6e6e6;color:var(--fg)}
.ordhead .tolist .ic{width:18px;height:18px}
.ordhead .chev{color:var(--dim);font-weight:400;margin:0 .35rem 0 .1rem}

/* ── Крупная миниатюра в карточке заказа ───────────────────────────────────
   Было 40px — на такой картинке не различить, та ли это деталь. Стало 88px:
   позиция всё ещё строка списка, а не карточка товара, но предмет узнаётся.
   Курсор-указатель и лёгкое приближение при наведении говорят, что можно
   нажать; сам переход открывает полный размер в новой вкладке. */
/* 🔴 110 px, а не 88: под каждой позицией теперь стоят вес и закупка с
   источником, и картинка рядом с этим объёмом текста читалась мелкой.
   Пробовали 140 (великовато) и 120; остановились на 110 — владелец
   смотрел вживую 31.07.2026, а не подбирал число на глаз.
   Запрос картинки не меняем — он и так 240 px (thumb(240) в order.html),
   то есть запас качества был заложен заранее. */
ul.items .thumb{width:110px;height:110px;flex:0 0 110px;border-radius:10px}
ul.items .thumb a{display:flex;align-items:center;justify-content:center;
  width:100%;height:100%;cursor:zoom-in}
ul.items .thumb img{transition:transform .12s ease}
ul.items .thumb a:hover img{transform:scale(1.06)}
ul.items li{padding:.7rem 0}

/* ── Метка способа оплаты ──────────────────────────────────────────────────
   🔴 ПЛАШКА С ФОНОМ, А НЕ ЦВЕТНОЙ ТЕКСТ. Синий у нас занят ссылками (номер
   заказа, трек-номер), и синее слово в той же строке читалось бы как ещё одна
   ссылка. Фон снимает вопрос: нажимают то, что подчёркнуто цветом текста,
   а плашка — это метка.

   Синий — НАШ ссылочный, var(--acc): решение владельца 27.07.2026. Фирменный
   PayPal #003087 на экране читался как «чёрный прямоугольник», а панель и так
   держит один синий на всё. Цвет берётся переменной, не числом: подобранное на
   глаз повторение того же тона расходится при первой же правке палитры. */
/* 🔴 СПОСОБ ОПЛАТЫ НИЧЕГО НЕ СИГНАЛИЗИРУЕТ — это факт, а не тревога.
   Он обязан быть ТИШЕ статусов оплаты и отгрузки, которые требуют
   действия. Поэтому у всех трёх одинаковый вес: бледная подложка,
   различие цветом буквы, а не яркостью пятна. */
.paybadge{display:inline-block;font-size:11px;line-height:18px;padding:0 7px;
  border-radius:6px;white-space:nowrap;font-weight:500;letter-spacing:.01em}
.paybadge.pay-paypal{background:#eaf1fd;color:var(--acc)}
.paybadge.pay-card{background:#ebebeb;color:#303030}
.paybadge.pay-market{background:#e6e0f7;color:#3d2a72}
.paybadge.pay-manual{background:#ffe9c7;color:#5e4200}
.ordhead .paybadge{font-size:12px;line-height:20px;padding:0 9px}

/* Нетто рядом с брутто: второй строкой, приглушённо. Не в отдельной колонке —
   тогда таблица растянулась бы, а мы её ширину только что ограничивали. */
/* То же самое, что у строки позиции: `display` не называется, раскладку задаёт
   `.net`. Здесь этим правилом накрыты ДВЕ строки из трёх — расчёт и «Итого». */
table.sums td.v .net{font-size:12px;color:var(--dim);
  font-weight:400;white-space:nowrap}
table.sums tr.tot td.v .net{font-weight:600}

/* 🔴 Один смысл на цвет. Зелёный — «деньги у нас или товар у покупателя»,
   и больше нигде. Жёлтый — «ждём и не знаем». Красный — «нужно вмешаться». */
/* 🔴 39: прежний #cdfee1 читался как «яркая наклейка». Тон тот же,
   насыщенность ниже — чип должен подсказывать, а не кричать. */
/* 🔴 .pill-green УДАЛЁН 28.07.2026 вместе с зелёным из палитры состояний.
   Нормальное состояние серое; зелёная плашка вернула бы «всё хорошо» туда,
   где сообщать нечего. --act остаётся: им покрашены рост показателя и
   отметка «доставлено» в ленте пути, это не состояния заказа. */
.pill-grey{background:#ebebeb;color:#616161}
.pill-yellow{background:#f8eb78;color:#303000}
/* Янтарный — «движения давно нет». Между зелёным и красным: не
   благополучие, но и не отказ доставки. */
.pill-amber{background:#f8d6a4;color:#4a2d00}
.pill-blue{background:#d5ebff;color:#0b3d62}
.pill-red{background:#fdd;color:#8e1f0b}

/* ── Форма сообщения и история переписки ────────────────────────────────── */
form.msg{display:flex;flex-direction:column;gap:.4rem;margin:.2rem 0 1rem}
form.msg .tabs{display:flex;gap:.8rem;font-size:12px;color:var(--dim)}
form.msg .fld{border:1px solid var(--line);border-radius:6px;padding:.35rem .5rem;
  font:inherit;font-size:13px;width:100%;box-sizing:border-box}
form.msg textarea.fld{resize:vertical}
form.msg button{align-self:flex-start;border:1px solid var(--line);background:var(--surface);
  border-radius:99px;padding:.35rem .9rem;font:inherit;font-size:13px;cursor:pointer}
form.msg button:hover{background:#f6f6f7}
.small{font-size:11px;line-height:1.35}
ul.notes{list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:.5rem}
ul.notes li{border-left:2px solid var(--line);padding-left:.6rem;font-size:13px}
ul.notes li.bad{border-left-color:var(--bad)}

/* ── Модалка отправки ─────────────────────────────────────────────────────
   Раскладка по образцу окна «Contact customer» у Shopify (скриншоты владельца,
   31.07.2026): три яруса — заголовок, прокручиваемая середина, полоса кнопок, —
   поля друг под другом во всю ширину, подписи читаемые, между блоками воздух.
   Пиксель-в-пиксель не копируется намеренно: заимствован подход, а не чужой
   брендинг. */
dialog.sheet{border:none;border-radius:12px;padding:0;width:min(760px,94vw);
  max-height:92vh;box-shadow:0 20px 60px rgba(0,0,0,.25)}
dialog.sheet::backdrop{background:rgba(0,0,0,.35)}
/* Форма — колонка на всю высоту окна: середина прокручивается, кнопки внизу
   остаются на месте. Прежде прокручивалось всё окно целиком, и кнопка
   «Отправить» уезжала за край ровно тогда, когда письмо длинное. */
dialog.sheet form{padding:0;display:flex;flex-direction:column;
  max-height:inherit;overflow:hidden}
/* 🔴 Атрибут `hidden` обязан побеждать раскладку: у блоков ниже есть свои
   display, и без этой строки скрытые поля показались бы всем. */
dialog.sheet [hidden]{display:none}
dialog.sheet .sheet-head{flex:none;padding:1rem 1.4rem;
  border-bottom:1px solid var(--line)}
dialog.sheet h2{margin:0;font-size:16px}
/* min-height:0 — не украшение: без него элемент flex-колонки не сжимается
   ниже своего содержимого, overflow:auto ничего не прокручивает, и полоса
   кнопок всё равно уезжает за нижний край. */
dialog.sheet .sheet-body{flex:1 1 auto;min-height:0;overflow:auto;
  padding:1.1rem 1.4rem 1.3rem;display:flex;flex-direction:column;gap:1.1rem}
dialog.sheet .sheet-fields{display:flex;flex-direction:column;gap:.9rem}
/* Подпись поля — тёмная и не мельче списка: у Shopify она читается наравне со
   значением, а серым набраны только пояснения под ней. Прежде подпись была
   dim и 12px, и «Кому» терялось рядом с адресом. */
dialog.sheet label{display:flex;flex-direction:column;gap:.3rem;font-size:13px;
  color:var(--fg)}
dialog.sheet label .lbl-note{font-size:11px;color:var(--dim);font-weight:400}
dialog.sheet label.check{flex-direction:row;align-items:center;gap:.45rem;
  color:var(--fg)}
/* Поля модалки не были оформлены вовсе: `.fld` описан только внутри form.msg,
   и здесь стояли необрамлённые кнопки-коробки браузера разной ширины. */
dialog.sheet .fld{border:1px solid var(--line);border-radius:8px;
  padding:.5rem .65rem;font:inherit;font-size:14px;width:100%;
  box-sizing:border-box;background:#fff;color:var(--fg)}
dialog.sheet .fld:focus{outline:2px solid var(--acc);outline-offset:1px;
  border-color:var(--acc)}
/* 🔴 ГЛАВНОЕ ТРЕБОВАНИЕ ПУНКТА: поле втрое выше прежнего. Восемь строк — это
   было ~125px, здесь 24rem = 384px. `min()` с высотой окна — не осторожность
   ради осторожности: на низком экране жёсткие 24rem вытолкнули бы кнопки в
   прокрутку, то есть отняли бы ровно то, ради чего высота и добавлена. */
dialog.sheet textarea.fld{min-height:min(24rem,46vh);resize:vertical;
  line-height:1.45}
dialog.sheet .sheet-text{flex:1 0 auto}
/* Кнопки-помощники (перевод). Прежде это были голые <button> без класса —
   квадратные серые кнопки браузера посреди формы; владелец так их и назвал.
   Теперь тот же спокойный вид, что у «Отмены», и своя строка на каждую. */
dialog.sheet .assist{display:flex;align-items:center;gap:.6rem;margin:0 0 .6rem;
  flex-wrap:wrap}
dialog.sheet button.soft{border:1px solid var(--line);background:var(--surface);
  border-radius:99px;padding:.4rem 1rem;font:inherit;font-size:13px;
  cursor:pointer;color:var(--fg)}
dialog.sheet button.soft:hover{background:#f6f6f7}
dialog.sheet #tr-result{display:flex;flex-direction:column;
  align-items:flex-start;gap:.6rem}
/* Полоса кнопок отделена чертой и прижата вниз — как «Cancel / Review email» у
   Shopify. Отступ между ними больше прежнего: две кнопки вплотную читаются как
   один блок, и промахнуться по «Отправить» слишком легко. */
dialog.sheet .acts{flex:none;display:flex;gap:.7rem;justify-content:flex-end;
  padding:.9rem 1.4rem;border-top:1px solid var(--line);background:var(--surface)}
dialog.sheet .acts button{border:1px solid var(--line);background:var(--surface);
  border-radius:99px;padding:.5rem 1.3rem;font:inherit;font-size:13px;cursor:pointer}
dialog.sheet .acts button:hover{background:#f6f6f7}
dialog.sheet .acts button[type=submit]{background:var(--fg);color:#fff;border-color:var(--fg)}
dialog.sheet .acts button[type=submit]:hover{background:#000}
.warnbox{background:var(--warnbg);color:var(--warn);padding:.6rem .8rem;border-radius:8px;
  font-size:13px;margin:0}
.cf-body{background:#f6f6f7;border-radius:8px;padding:.6rem .8rem;font-size:12px;
  white-space:pre-wrap;max-height:12rem;overflow:auto;margin:0}
li.note.own{border-left:2px solid var(--acc);padding-left:.6rem}

/* ── Вход ───────────────────────────────────────────────────────────────── */
.box.login{max-width:22rem;margin:6vh auto}
.box.login form{display:flex;flex-direction:column;gap:.6rem;margin-top:.6rem}
.box.login label{display:flex;flex-direction:column;gap:.25rem;font-size:12px;color:var(--dim)}
.box.login button{border:1px solid var(--fg);background:var(--fg);color:#fff;
  border-radius:99px;padding:.45rem 1.2rem;font:inherit;font-size:13px;cursor:pointer}
.whoami{margin-left:auto;display:flex;align-items:center;gap:.5rem;font-size:12px;color:#c9cdd4}
.whoami form{display:inline}
.whoami button{background:none;border:none;color:#c9cdd4;font:inherit;font-size:12px;
  cursor:pointer;text-decoration:underline}

/* ── Две ленты пути: отправляющая почта и принимающая ────────────────────── */
.legs{display:flex;gap:1.2rem;flex-wrap:wrap;align-items:flex-start}
.leg{flex:1 1 15rem;min-width:14rem}
.leg .legname{font-size:12px;font-weight:600;margin:0 0 .3rem;
  padding-bottom:.2rem;border-bottom:1px solid var(--line)}
.leg .legname .dim{font-weight:400}
ul.tl.path li{padding:.25rem 0}

/* Ключевая цифра карточки: её ищут глазами, а не читают в таблице. */
.bignum{font-size:26px;font-weight:600;margin:.1rem 0 .6rem;line-height:1.1}
.bignum .dim{font-size:13px;font-weight:400}

/* 🔴 Правая колонка узкая, и длинные подписи рвались посреди слова:
   «почта пол / учателя (US)». Ссылка не переносится внутри себя, а список
   ссылок идёт столбиком. */
dd.links{display:flex;flex-direction:column;gap:.15rem}
.nowrap{white-space:nowrap}
/* 🔴 `anywhere` рвал слова посередине — «Nor / way Post», «Зарегистрирова /
   но». Перенос нужен только там, где строка не помещается ЦЕЛИКОМ (длинная
   почта, длинный URL); `break-word` делает ровно это, а короткие слова
   оставляет целыми. */
.contact{overflow-wrap:break-word}

/* ── Лента «Что происходило» ────────────────────────────────────────────────
   🔴 ЛЕНТА ЛЕЖИТ НА СЕРОМ, А НЕ В БЕЛОЙ КАРТОЧКЕ. Снято с ui3.png. Белый
   прямоугольник вокруг всего уравнивал в правах поле ввода и историю: место,
   куда пишут, терялось среди написанного. Теперь белая карточка тут ровно
   одна — поле комментария, и она видна как отдельный предмет.

   Разделять записи линейками не нужно: их разделяет воздух и нить с точками
   слева. Линейки в ленте на 40 событий превращают её в таблицу. */
.tlwrap{margin-bottom:var(--pad)}
h2.tlhead{margin:0 0 .5rem;font-size:14px;font-weight:650;
  display:flex;align-items:center;gap:.5rem}
h2.tlhead .seg{margin-left:auto;font-weight:400}
.tlwrap .switches{margin:0 0 .6rem}
.tl-events{position:relative;margin-left:.35rem;padding-left:1rem}
.tl-events::before{content:"";position:absolute;left:0;top:.35rem;bottom:.35rem;
  width:1px;background:#d8d8d8}
.tl-events ul.tl{border-left:0;margin-left:0}
.tl-events h3.day{position:relative;background:transparent;margin-left:-1rem;
  padding-left:1rem;z-index:auto}
.tl-events li.sys .dot{margin-left:-1.32rem}
.tl-events li.sys.return-event,.tl-events li.sys.dispute-event{
  /* Фон немного отступает от нити, текст совпадает с колонкой обычных
     событий, а точка позиционируется отдельно и остаётся ровно на нити. */
  margin:.22rem 0 .22rem -.35rem;padding:.42rem .55rem .42rem .8rem;border-radius:8px}
.tl-events li.sys.return-event .dot,.tl-events li.sys.dispute-event .dot{
  position:absolute;left:-.95rem;top:.48rem;margin:0;z-index:2}
.tl-events li.sys.return-event>div,.tl-events li.sys.dispute-event>div{margin-left:.35rem}
.tl-events li.sys.return-event .time,.tl-events li.sys.dispute-event .time{
  margin-left:auto;margin-right:.25rem}
.tl-events li.sys.return-event{background:#fff4d6;color:#5c4600}
.tl-events li.sys.dispute-event{background:var(--badbg);color:var(--bad)}
.tl-events li.sys.return-event .dot{background:#c78300}
.tl-events li.sys.dispute-event .dot{background:var(--bad)}
.pill-return{background:#f8d79a;color:#5c4600}
.return-card{border-left:4px solid #d89a22}
.return-card-head{display:flex;align-items:center;justify-content:space-between;
  gap:.8rem;margin-bottom:.7rem}
.return-card-body{display:flex;gap:.65rem;border:1px solid var(--line);
  border-radius:8px;padding:.7rem;line-height:1.45}
.review-return{display:block;margin:.7rem 0 0 auto}
.customer-name-link{color:var(--acc);text-decoration:none}
.customer-name-link:hover{text-decoration:underline}
.customer-page{max-width:1100px;margin:0 auto;padding:var(--pad)}
.customer-head{display:flex;align-items:center;gap:.65rem;margin-bottom:.8rem}
.customer-head h1{font-size:21px;margin:0}
.customer-head>a{text-decoration:none;color:var(--dim);font-size:20px}
.customer-metrics{display:grid;grid-template-columns:repeat(3,1fr);background:var(--surface);
  border-radius:var(--radius);box-shadow:var(--shadow);overflow:hidden;margin-bottom:var(--pad)}
.customer-metrics>div{display:flex;flex-direction:column;gap:.35rem;padding:1rem 1.25rem;
  border-right:1px solid var(--line)}
.customer-metrics>div:last-child{border-right:0}
.customer-metrics span{color:var(--dim)}
.customer-metrics b{font-size:17px}
.customer-grid{display:grid;grid-template-columns:minmax(0,2fr) minmax(270px,1fr);gap:var(--pad)}
.customer-order-list{border:1px solid var(--line);border-radius:8px;overflow:hidden}
.customer-order{display:flex;justify-content:space-between;gap:1rem;padding:.9rem;
  color:inherit;text-decoration:none;border-bottom:1px solid var(--line)}
.customer-order:last-child{border-bottom:0}
.customer-order:hover{background:#f6f6f6}
.customer-order small{display:block;color:var(--dim);margin-top:.35rem}
@media(max-width:760px){.customer-grid{grid-template-columns:1fr}.customer-metrics{grid-template-columns:1fr}
  .customer-metrics>div{border-right:0;border-bottom:1px solid var(--line)}}
.orders-page-head{display:flex;align-items:center;justify-content:space-between;
  gap:1rem;margin:0 0 .65rem}
.orders-title{display:flex;align-items:center;gap:.65rem}
.orders-title h1{font-size:20px;margin:0}
.location-picker{position:relative}
.location-picker summary{list-style:none;cursor:pointer;background:#e4e4e4;
  border-radius:8px;padding:.35rem .7rem}
.location-picker summary::-webkit-details-marker{display:none}
.location-menu{position:absolute;z-index:90;top:calc(100% + 5px);left:0;
  min-width:260px;max-height:70vh;overflow:auto;background:#fff;border:1px solid var(--line);
  border-radius:12px;padding:.45rem;box-shadow:0 8px 24px rgba(0,0,0,.18)}
.location-menu a{display:flex;justify-content:space-between;gap:1rem;color:inherit;
  text-decoration:none;padding:.55rem .65rem;border-radius:8px}
.location-menu a:hover,.location-menu a.on{background:#ededed}
.location-menu a.on::after{content:"✓";margin-left:auto}
.orders-actions{display:flex;gap:.45rem;align-items:center}
.orders-actions .head-action{text-decoration:none;color:inherit;border:0;background:#e8e8e8;
  border-radius:8px;padding:.45rem .75rem;font:inherit}
.orders-actions .head-action.primary{background:#303030;color:#fff}
.orders-actions button:disabled{opacity:.58;cursor:not-allowed}
.bulk-bar{position:fixed;z-index:100;left:50%;bottom:1.2rem;transform:translateX(-50%);
  display:flex;align-items:center;gap:1rem;background:#fff;border:1px solid var(--line);
  border-radius:10px;padding:.65rem 1rem;box-shadow:0 8px 30px rgba(0,0,0,.2)}
.bulk-bar[hidden]{display:none}
.bulk-bar button{border:1px solid var(--line);border-radius:8px;padding:.3rem .7rem}
table.orders input[type=checkbox]{width:16px;height:16px;accent-color:#303030}
@media(max-width:760px){.orders-page-head{align-items:flex-start}.orders-actions{flex-wrap:wrap;justify-content:flex-end}}
.viewmail{margin-top:.35rem}
/* 🔴 ПРАВИЛО, КОТОРОЕ СТОИТ ЗАПИСАТЬ: подчёркнутый текст в панели означает
   ССЫЛКУ, УВОДЯЩУЮ СО СТРАНИЦЫ. Внутри рамки кнопки подчёркивания не бывает —
   рамка уже сказала, что это нажимаемое, и два обещания сразу сбивают.

   `text-decoration:none` стоит ЗДЕСЬ, в объявлении вида, а не отдельной
   строкой поверх каждой кнопки-ссылки. Я уже чинил это точечно у одной кнопки
   в шапке переписки — и подчёркивание осталось у второй такой же в правой
   колонке: точечная правка лечит место, а не класс. Кнопок-ссылок в панели
   четыре (`.textbutton` в шапке переписки, в ряду действий и в правой колонке,
   плюс `.way` у контактов), и все они берут вид отсюда. */
.viewmail summary,.textbutton{display:inline-block;border:1px solid #c9cccf;
  border-radius:8px;background:#fff;color:var(--fg);padding:.28rem .65rem;
  font:inherit;font-size:12px;cursor:pointer;list-style:none;
  text-decoration:none}
.viewmail p{max-width:34rem;color:var(--dim);font-size:12px}
.conversion-summary p{margin:.35rem 0}
.conversion-summary .summary-dot{display:inline-block;width:.42rem;height:.42rem;
  margin:0 .55rem .08rem .08rem;border-radius:50%;background:#5f6368;
  vertical-align:middle}
.conversion-summary .textbutton{border:0;color:var(--acc);padding:.25rem 0}
.conversion-dialog dl{grid-template-columns:10rem minmax(0,1fr)}
.conversion-dialog dd{text-align:left;overflow-wrap:anywhere}
.money-audit summary{color:var(--acc);cursor:pointer;padding:.25rem 0}
table.sums tr.vat-recoverable td{color:#08743b}
.money-received,table.sums tr.money-received-row td.v{color:#08743b;font-weight:700}
table.sums tr.profit-total td{color:#075f35;background:#e6f4ea;border-top-color:#9bcbae;
  border-bottom:1px solid #9bcbae}
table.sums tr.profit-total td:first-child{border-radius:7px 0 0 7px}
table.sums tr.profit-total td:last-child{border-radius:0 7px 7px 0;font-size:15px}
.fulfillment-meta{display:flex;flex-direction:column;gap:.25rem;margin:.55rem 0;
  padding:.55rem .7rem;border:1px solid var(--line);border-radius:8px;font-size:12px}
.conversion-dialog form{padding:0;gap:0}
.conversion-dialog .dialoghead{background:#f1f1f1;border-bottom:1px solid var(--line);
  padding:1rem 1.25rem}
.conversion-stats{display:grid;grid-template-columns:1fr 1fr;gap:1rem;margin:1rem;
  padding:1rem;background:#f3f3f3;border-radius:10px}
.conversion-stats div{display:flex;flex-direction:column;gap:.15rem}
.conversion-stats span{font-size:12px;font-weight:600}
.conversion-stats b{font-size:26px;line-height:1}
.conversion-rows{display:flex;flex-direction:column}
.conversion-row{display:grid;grid-template-columns:1.5rem 1fr;gap:.5rem;padding:.8rem 1rem;
  border-top:1px solid var(--line);align-items:start}
.conversion-row:first-child{border-top:0}
.conversion-row>span:last-child{display:flex;flex-direction:column;gap:.2rem;min-width:0}
.conversion-row small{color:var(--dim)}
.conversion-row a{overflow-wrap:anywhere}
.conversion-dialog .acts{padding:.8rem 1rem;border-top:1px solid var(--line)}

/* Карточка комментария — по образцу Timeline в админке Shopify: белая, с
   тенью, парит над серым фоном ленты. Тень заметнее, чем у обычной карточки,
   именно потому, что она здесь одна и должна читаться как «сюда писать». */
form.notecard{border:1px solid var(--line);border-radius:12px;background:var(--surface);
  margin:.2rem 0 .2rem;box-shadow:0 1px 3px rgba(0,0,0,.08),0 3px 8px rgba(0,0,0,.04)}
form.notecard .notetop{display:flex;gap:.7rem;align-items:flex-start;padding:.8rem .8rem .55rem}
form.notecard textarea{flex:1;border:none;outline:none;resize:vertical;font:inherit;
  font-size:13px;min-height:2.2rem;background:transparent;color:var(--fg)}
/* 🔴 Полоса с кнопкой ТЕМНЕЕ самого поля — как на ui3.png. Сплошной белый
   делал карточку плоской: она читалась как один прямоугольник, а не как поле
   ввода с панелью действий под ним. Оттенок берётся тот же, что у других
   служебных подложек (#f6f6f7 у текста письма), и скругляется снизу, иначе
   углы подложки торчат из-под скругления карточки. */
form.notecard .notebottom{display:flex;justify-content:space-between;align-items:center;
  border-top:1px solid var(--line);padding:.45rem .8rem;
  background:#f6f6f7;border-radius:0 0 9px 9px}
form.notecard .notebottom .note-submit{background:var(--surface)}
form.notecard button{border:1px solid var(--line);background:var(--surface);
  border-radius:99px;padding:.3rem .9rem;font:inherit;font-size:12px;cursor:pointer}
form.notecard button:disabled{opacity:.45;cursor:default}
.avatar-upload{display:none}
.note-tools{display:flex;gap:.15rem}
form.notecard .note-tools button{border:0;background:transparent;color:#6d7175;
  width:28px;height:28px;padding:0;font-size:16px}
form.notecard .note-tools button:hover{background:#ebebeb}
.notehint{font-size:11px;color:var(--dim);margin:.25rem 0 1rem;text-align:right}
.ava{position:relative;overflow:hidden;flex:0 0 auto;width:38px;height:38px;border-radius:8px;background:var(--acc);
  color:#fff;display:inline-flex;align-items:center;justify-content:center;
  font-size:12px;font-weight:600}
.ava img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.avatar-picker{cursor:pointer}
.avatar-picker:hover{box-shadow:0 0 0 2px #fff,0 0 0 4px var(--acc)}
h3.sh.gap{margin-top:1.4rem}
/* 🔴 Своя запись отличается от события Shopify с первого взгляда: полоса
   слева, светлый фон и имя автора. Событие пришло от машины, комментарий
   написал человек — путать их нельзя. */
li.note.own{border-left:3px solid var(--acc);background:#f7f9fe;
  padding:.4rem .6rem;border-radius:0 8px 8px 0}
li.note.own .who{font-weight:600}

/* ── История пути: две ленты, разделённые видимо ─────────────────────────── */
.legs{display:flex;gap:1rem;flex-wrap:wrap;align-items:flex-start}
.leg{flex:1 1 17rem;min-width:15rem;background:#fafafb;border:1px solid var(--line);
  border-radius:10px;padding:.6rem .8rem}
.leg .legname{font-size:14px;font-weight:600;margin:0 0 .4rem;
  padding-bottom:.3rem;border-bottom:1px solid var(--line)}
.leg .legname .legrole{font-size:11px;font-weight:400;color:var(--dim);
  text-transform:uppercase;letter-spacing:.04em;margin-left:.4rem}
/* 🔴 Дата на фиксированном месте: раньше она и текст шли одним потоком, и
   положение зависело от длины предыдущей строки — глаз терял столбец. */
ul.path{list-style:none;padding:0;margin:0}
ul.path li{display:flex;gap:.6rem;align-items:baseline;padding:.18rem 0;font-size:12px}
ul.path .pdate{flex:0 0 8.5rem;color:var(--dim);font-variant-numeric:tabular-nums;
  white-space:nowrap}
ul.path .ptext{flex:1;min-width:0;overflow-wrap:break-word}
ul.path li.last .ptext{font-weight:600}
/* 🔴 В боковой колонке две колонки не помещаются. Ширина её 290–340px, из них
   136px забирала дата, и на текст оставалось меньше половины: слова рвались
   посередине — «Зарегистрирова / но». Здесь дата встаёт НАД строкой, а не
   слева. Правило узкое (только внутри .side), поэтому широкая лента на общей
   странице пути остаётся двухколоночной. */
.side ul.path li{flex-direction:column;gap:0;padding:.3rem 0}
.side ul.path .pdate{flex:none}
/* Финальное подтверждение доставки выделяется ЦЕЛИКОМ: дата, время, статус и
   место. Раньше зелёным было только слово «Доставлено», поэтому две записи
   разных почт визуально не читались как два подтверждения одного вручения. */
ul.path li.last.ok{color:var(--act);background:#eaf5ee;border-radius:7px;
  padding:.3rem .4rem;margin:.08rem -.4rem}
ul.path li.last.ok .pdate,
ul.path li.last.ok .ptext,
ul.path li.last.ok .ptext .dim{color:var(--act)}
ul.path li.last.bad .ptext{color:var(--bad)}
ul.path li.last.warn .ptext{color:var(--warn)}

.buyernote{background:#fffbe9;border-left:3px solid var(--warn);padding:.4rem .6rem;
  border-radius:0 8px 8px 0;font-size:13px;margin:.2rem 0 .8rem}

/* Черта между режимами и списком стран: это разные вещи, и глаз должен их
   различать без чтения. */
hr.valsep{border:none;border-top:1px solid var(--line);margin:.35rem 0}
.vals a.on{font-weight:600}

/* Быстрые фильтры лежат на отдельной белой поверхности: на общем сером фоне
   прежние серо-голубые плашки визуально пропадали. */
.quick{display:flex;gap:.4rem;flex-wrap:wrap;margin:.2rem 0 .4rem;padding:.36rem .45rem;
  background:var(--surface);border:1px solid var(--line);border-radius:10px;
  box-shadow:var(--shadow)}
a.qchip{font-size:12px;line-height:20px;padding:0 .6rem;border-radius:8px;
  background:#e5ebf2;color:#31465d;text-decoration:none;white-space:nowrap;
  border:1px solid #d7dee7}
a.qchip:hover{background:#dbe4ee;border-color:#bfcbd8}
a.qchip.on{background:var(--fg);color:#fff}
a.qchip .qn{opacity:.65;margin-left:.25rem;font-variant-numeric:tabular-nums}
/* «Сбросить» — не чип: он не фильтрует, а снимает. Поэтому без плашки, цветом
   ссылки и с отступом от ряда, чтобы не читался как ещё один фильтр. */
a.qclear{font-size:12px;line-height:20px;margin-left:.4rem;color:var(--acc);
  text-decoration:none;white-space:nowrap}
a.qclear:hover{text-decoration:underline}
.chipform{display:flex;flex-wrap:wrap;gap:.5rem;align-items:center;
  margin:.4rem 0 .8rem;font-size:12px;color:var(--dim)}
.chipform label{display:inline-flex;gap:.25rem;align-items:center}

/* Причина, по которой заказ ещё не закрыт. Показывается под номером в списке
   «Остались дела». Приглушённая: это пояснение к строке, а не её содержание. */
td.ordcell div.why{color:var(--dim);font-size:11px;line-height:1.35;
  margin-top:.15rem;max-width:22rem}

/* ── Слово клиента в ленте заказа ────────────────────────────────────────────
   🔴 ТРЕТИЙ ВИД ЗАПИСИ, И ОТЛИЧАТЬСЯ ОН ОБЯЗАН ОТ ОБОИХ ПРЕЖНИХ. Своя запись
   уже помечена синей полосой слева (li.note.own выше) — «это сделали мы».
   Здесь полоса ЗЕЛЁНАЯ и с другой стороны читается иначе: пришло снаружи,
   написал человек, ответа ждут от нас. Одинаковое оформление у своего и
   чужого слова — ровно та ошибка, ради которой заводилась вся эта лента. */
li.note.client{border-left:3px solid #2e7d5b;background:#f6fbf8;
  padding:.4rem .6rem;border-radius:0 8px 8px 0}
/* Значок канала вместо инициала: у чата имени может не быть вовсе, а канал
   есть всегда — и именно он говорит, можно ли ответить. */
/* 🔴 ЗНАЧОК КАНАЛА — МЕЛКИЙ И В СТРОКЕ ИМЕНИ. Был квадрат 38×38 отдельным
   столбцом слева: он забирал ширину у текста, а сообщал ровно одно — каким
   каналом пришло письмо. В колонке переписки ширина дороже.
   Значок СОСТОЯНИЯ переписки остаётся на своём месте — он в списке слева, на
   другом краю экрана, и с этим они не встречаются. */
li.note.client .client-ava{background:transparent;color:var(--dim);
  width:16px;height:16px;flex:0 0 16px;border-radius:0;font-size:inherit}
li.note.client .client-ava .ic{width:14px;height:14px}
li.note.client .ways{margin:.35rem 0 0}

/* ── Список входящих (/messages) ─────────────────────────────────────────── */
/* Текст сообщения обрезается по высоте, а не по символам: обрезка по символам
   врёт про длину, а три строки дают понять объём и остаются читаемыми. Целиком
   сообщение читается на карточке заказа, где ему и место. */
td.msgtext{max-width:38rem;overflow-wrap:break-word;line-height:1.4;
  display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;
  overflow:hidden}
/* Неотвеченное подсвечено строкой целиком: это очередь, и глаз должен
   находить в ней работу, а не сверять колонку «ответ» построчно. */
tr.unanswered td{background:#fffdf5}

/* Повторы одного и того же текста показаны одной строкой (Фаза 4). Раскрытие —
   обычный <details>: JS здесь не нужен, а список дат должен быть под рукой, не
   на другой странице. Стоит в колонке «от кого», а не в «сообщении»: та
   обрезана по высоте с overflow:hidden, и раскрытый список в ней не поместился
   бы — открылся бы наполовину, что хуже, чем не открыться. */
details.repeats{margin:.3rem 0 0}
details.repeats summary{cursor:pointer;color:var(--acc);font-size:12px}
details.repeats ol{margin:.3rem 0 0;padding-left:1.1rem;font-size:12px;
  color:var(--dim);line-height:1.5}
/* Ручная привязка. Поле узкое намеренно: номер заказа — шесть знаков, и поле
   во всю колонку обещало бы, что сюда можно написать что-то ещё. */
form.linkform{display:flex;gap:.3rem;margin:.3rem 0 0}
form.linkform input{width:5.6rem;padding:.2rem .35rem;border:1px solid var(--line);
  border-radius:6px;font:inherit;font-size:12px}
form.linkform button{padding:.2rem .6rem;border:1px solid var(--fg);
  border-radius:99px;background:var(--fg);color:#fff;font:inherit;font-size:12px;
  cursor:pointer}
/* Исправление уже сделанной привязки спрятано под раскрытие: это редкое
   действие, и кнопка рядом с каждым номером читалась бы как приглашение. */
details.relink summary{cursor:pointer;color:var(--dim);font-size:12px}

/* «Не клиент» (Фаза 5). 🔴 КНОПКА НАМЕРЕННО ТИШЕ СОСЕДНЕЙ: обычная работа на
   этом экране — привязать сообщение к заказу, а убрать его из очереди приходится
   на промахах разбора. Одинаково яркие кнопки рядом читались бы как равный
   выбор, и половина нажатий пришлась бы не туда. Стоит отдельной строкой под
   привязкой — в ряд они складывались бы в плотный квадратный блок. */
form.dropform{margin:.3rem 0 0}
form.dropform button{padding:.2rem .6rem;border:1px solid var(--line);
  border-radius:99px;background:var(--surface);color:var(--dim);font:inherit;
  font-size:12px;cursor:pointer}
form.dropform button:hover{border-color:var(--bad);color:var(--bad)}

/* ═══════════════════════════════════════════════════════════════════════════
   Фаза 9: четырёхколонный вид «Сообщения клиентов».
   🔴 НОВЫЕ КЛАССЫ (`m9-`), СУЩЕСТВУЮЩИЕ ПРАВИЛА НЕ ПЕРЕПИСАНЫ. Старый вид
   (`messages_classic.html`) продолжает пользоваться прежними правилами, и
   путь отката обязан остаться нетронутым — иначе откатываться будет некуда.
   ═══════════════════════════════════════════════════════════════════════ */
/* 🔴 МЕЖДУ КОЛОНКАМИ РОВНО ОДНА ЛИНИЯ, И ОНА ПРИНАДЛЕЖИТ ОДНОЙ ИЗ НИХ.
   Правило: линия — свойство колонки, а не промежутка между двумя. Иначе при
   любой перестановке колонок линии удваиваются.

   Так и вышло. Линии рисовались ЗАЗОРОМ сетки (`gap:1px` поверх серого фона
   контейнера), а между списком и перепиской стоит ещё дорожка нулевой ширины
   под ручку раздвигания — то есть зазора два подряд. Замер: список кончается
   на 550, ручка на 551, переписка начинается с 552. Два пикселя линии вместо
   одного, и правый выглядит толще, потому что к нему прилегает полоса ручки. */
.m9{display:grid;grid-template-columns:180px minmax(320px,1fr) minmax(0,1.4fr) 260px;
  gap:0;border:1px solid var(--line);border-radius:8px;
  overflow:hidden;min-height:60vh}
.m9 > *{background:var(--bg,#fafafa)}

/* 1. Папки */
.m9-folders{display:flex;flex-direction:column;padding:.6rem;gap:.15rem;
  background:var(--surface)}
.m9-folder{display:flex;align-items:center;gap:.5rem;padding:.4rem .6rem;
  border-radius:6px;text-decoration:none;color:inherit;font-size:14px}
.m9-folder:hover{background:var(--line)}
.m9-cur{background:var(--line);font-weight:600}
.m9-ico{width:1.1em;text-align:center;color:var(--dim)}
.m9-name{flex:1}
.m9-cnt{font-size:12px;font-weight:600;color:var(--dim)}
/* Папка, которой база ещё не умеет: видна и названа, а не спрятана. */
.m9-folder-wait{opacity:.55;cursor:default}
.m9-wait{font-size:11px;color:var(--dim);border:1px dashed var(--line);
  border-radius:99px;padding:0 .4rem}
.m9-classic{margin-top:auto;padding:.4rem .6rem;font-size:12px;
  color:var(--dim);text-decoration:none}
.m9-classic:hover{text-decoration:underline}

/* 2. Список переписок */
.m9-list{display:flex;flex-direction:column;background:var(--surface);
  overflow-y:auto}
.m9-filters{display:flex;flex-wrap:nowrap;gap:.5rem;align-items:center;
  height:var(--head);flex:0 0 auto;padding:0 .7rem;
  border-bottom:1px solid var(--line);font-size:12px}
.m9-check{display:flex;align-items:center;gap:.25rem;color:var(--dim)}
/* 🔴 ФАЗА 9.1, ПУНКТ 3: СТРОКИ РАЗДЕЛЯЕТ ВОЗДУХ, А НЕ ЛИНЕЙКИ. Слова
   владельца — «чересчур ребристо», «линий нет, а выделение фоном есть». Линия
   под каждой строкой рисовала таблицу там, где её больше нет: строка списка —
   это карточка, а карточки разделяет отступ. Выбранная заливается фоном на всю
   ширину со скруглением — так видно и с расстояния, и без обводки. */
.m9-threads{list-style:none;margin:0;padding:.25rem}
/* 🔴 ПОКОЙ СВЕТЛЕЕ ДВИЖЕНИЯ, А НЕ НАОБОРОТ. Было перевёрнуто: выбранная
   строка красилась в `--line` (темнее панели слева), а наведение делало её
   светлее — тяжелее всего выглядело то, что просто выбрано и лежит.

   Как у Shopify: выбранная строка спокойная и СВЕТЛЕЕ бежевой панели слева
   (`--bg` #f1f1f1 против #e6e6e6); наведение почти не меняет тон; тёмным
   (`--line`) отзывается только НАЖАТИЕ, и отклик затухает сам — отсюда
   `transition`. Все три тона — наши переменные, новых не заводится. */
/* 🔴 НАВЕДЕНИЕ НЕ МЕНЯЕТ ТОН ВОВСЕ — заметен именно отклик на НАЖАТИЕ.
   Правила `:hover` здесь нет намеренно: строка и так ссылка (курсор говорит,
   что по ней можно), а на наведении при этом проявляется кнопка «В архив».
   Нажатие темнеет до `--pressed` (241, замерено) и плавно возвращается. */
.m9-open{display:block;padding:.55rem .7rem;text-decoration:none;color:inherit;
  border-radius:8px;transition:background .3s ease}
a.m9-open:active{background:var(--pressed);transition:none}
.m9-noorder{cursor:default}
.m9-head{display:flex;align-items:baseline;gap:.4rem}
.m9-chan{color:var(--dim)}
/* 🔴 `min-width:0` — БЕЗ НЕГО МНОГОТОЧИЕ НЕ РАБОТАЕТ. Элемент flex по
   умолчанию не сжимается меньше своего содержимого, и длинное имя
   («Ärikliendítugi teenindus- ja logistikakeskus OÜ») выдавливало бы дату за
   правый край вместо того, чтобы обрезаться. Со значком состояния места в
   строке стало на 15px меньше, и случай стал ближе. */
/* 🔴 ИМЯ ТОГО ЖЕ ТОНА, ЧТО И СУТЬ, И ОТЛИЧАЕТСЯ ТОЛЬКО НАЧЕРТАНИЕМ.
   Обмер владельца по одному снимку: у Shopify самый тёмный пиксель и в имени,
   и в сути одинаковый — 97 из 255. У нас имя было 48, то есть ВДВОЕ темнее
   сути, — отсюда и ощущение, что всё кричит. Тон один (`--dim`, ровно 97),
   ударение даёт вес 600. */
.m9-who{font-weight:600;font-size:14px;color:var(--dim);overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap;min-width:0}
.m9-when{margin-left:auto;font-size:11px;color:var(--dim);white-space:nowrap}
/* Счётчик — число в скобках сразу за именем, обычным начертанием: жирное в
   строке одно, и это имя. */
.m9-rep{font-weight:400;color:var(--dim)}
/* 🔴 ПУНКТ 5.1: СУТЬ ЗАНИМАЕТ ДВЕ СТРОКИ, ВСЕГДА ДВЕ. Слова владельца — «в
   одну строку не влазит»: строка сути делалась на 5–15 слов, и одной строки ей
   чаще всего не хватает, а обрезается она на самом интересном. Обрезка идёт по
   второй строке многоточием.
   `min-height` не украшение: без него короткая суть даёт низкую строку, соседи
   получаются разной высоты, и список прыгает при прокрутке. */
/* 🔴 ПРОСВЕТЫ ПО ОБМЕРУ, А НЕ НА ГЛАЗ. Владелец снял оба столбца с одного
   снимка, поэтому числа сравнимы напрямую:

       между строками сути   у Shopify 20px, у нас было 16–17;
       от имени до сути      у Shopify 24px, у нас было 21;
       строка разговора      у Shopify 88px на две строки, у нас было 79–80.

   Размер шрифта при этом менять НЕ надо — он и так совпадает (13px), и из
   обмера по крайним тёмным пикселям он всё равно не выводится. Разводятся
   ровно просветы: `line-height` 20px и отступ сверху до 24px по просвету.

   `min-height` считается от той же двадцатки: строк сути ровно две, всегда
   две, иначе список запрыгает при прокрутке. */
.m9-gist{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
  margin:.35rem 0 .3rem;font-size:13px;color:var(--dim);line-height:20px;
  min-height:40px;overflow:hidden}
/* Бирки — мелкими под именем, а не колонками через весь экран. */
.m9-tags{display:flex;flex-wrap:wrap;gap:.25rem}
.m9-tag{font-size:11px;border:1px solid var(--line);border-radius:99px;
  padding:0 .45rem;color:var(--dim)}
.m9-tag-warn{border-color:var(--bad);color:var(--bad)}
.m9-tag-ok{opacity:.7}
.m9-tag-dim{opacity:.7}
.m9-empty,.m9-count{padding:.7rem;font-size:12px;color:var(--dim);margin:0}
/* 🔴 СРЕЗ СПИСКА — НЕ ПРИГЛУШЁННАЯ СНОСКА. Это сообщение о том, что часть
   данных на экране ОТСУТСТВУЕТ, и приглушённым цветом оно читалось бы как
   пояснение к списку, а не как изъятие из него. Тот же довод, по которому
   неразобранное движение денег красится тревожным, а не `dimrow`. */
.m9-cut{padding:.6rem .7rem;margin:0;font-size:12px;color:var(--warn);
  background:var(--warnbg);border-radius:var(--radius)}
.m9-count{margin-top:auto;border-top:1px solid var(--line)}

/* 3-4. Области, которые ещё не работают: названы словами, не пусты молча. */
.m9-thread-view,.m9-customer{display:flex;align-items:center;
  justify-content:center;padding:1.2rem;background:var(--surface)}
.m9-placeholder{margin:0;text-align:center;font-size:13px;color:var(--dim)}
.m9-soon{font-size:12px;opacity:.75}

@media (max-width:1100px){
  .m9{grid-template-columns:150px 1fr}
  .m9-thread-view,.m9-customer{display:none}
}

/* Фаза 9, кусок 4: открытая переписка в третьей колонке. */
.m9-thread-view{flex-direction:column;align-items:stretch;justify-content:flex-start;
  overflow-y:auto;padding:0}
/* 🔴 ЗАГРУЗКА НЕ ПЕРЕКРАШИВАЕТ КОЛОНКУ. Было `opacity:.5` на всю область
   переписки: щёлкнул по строке слева — и весь правый столбец менял вид, будто
   выделен целиком. Темнеть должно то, куда нажали (это делает сама строка), а
   про загрузку довольно тонкой полосы сверху. */
.m9-thread-view.m9-loading{position:relative}
.m9-thread-view.m9-loading::before{content:"";position:absolute;top:0;left:0;
  right:0;height:2px;background:var(--acc);opacity:.6;z-index:3}
.m9-thread-head{display:flex;align-items:center;gap:.6rem;flex-wrap:nowrap;
/* 🔴 `flex:0 0 auto` — БЕЗ НЕГО ВЫСОТА НЕ ДЕРЖИТСЯ. Шапка это элемент flex в
   колонке, а элементы flex по умолчанию СЖИМАЮТСЯ, когда содержимого больше,
   чем места. Замер поймал: при длинной переписке шапка садилась с 52 до 32, и
   подчёркивание снова уезжало на другой уровень — при том, что высота задана
   явно. Правило высоты без запрета на сжатие — это пожелание, а не высота. */
  height:var(--head);flex:0 0 auto;padding:0 .9rem;
  border-bottom:1px solid var(--line);background:var(--surface);z-index:1;
  overflow:hidden}
.m9-thread-head h2{margin:0;font-size:15px}
/* 🔴 ПУНКТ 18: В ШАПКЕ ТЕПЕРЬ ИМЯ, А ИМЯ БЫВАЕТ ДЛИННЫМ. «Заказ 881967» было
   шириной в семь знаков и всегда; худшая пара из базы на 02.08.2026 —
   «Pósturinn - Sjálfvirk tilkynning» (32 знака) плюс адрес
   «notif-laposte.info@notif-laposte.info» (37), а шапка не переносится
   (`flex-wrap:nowrap`).
   Замер: при ширине списка по умолчанию имя кончается на 783 при правом крае
   колонки 1020 — запас есть, а стоит владельцу
   утащить ручку до предела (760) — шапка вылезает за колонку на 42 и молча
   срезается, потому что у шапки `overflow:hidden`. Полосы прокрутки при этом
   не появляется, то есть главная проверка ширины такую беду не видит; ловит её
   `test_a_long_name_does_not_push_the_header_out_of_the_column`.
   `min-width:0` обязателен рядом с `text-overflow`: элемент flex по умолчанию
   не сжимается меньше содержимого, и одно правило без другого не работает —
   тот же случай, что у `.m9-who` в списке. */
.m9-thread-who,.m9-thread-head .m9-dim{overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
.m9-thread-head .m9-dim{min-width:0}
/* 🔴 ПУНКТ 50 СДЕЛАЛ ИМЯ СОСЕДОМ, КОТОРОГО ПОДЖИМАЮТ. Раскрытая подпись значка
   просит до 167 пикселей, а в шапке их нет: при узкой колонке всего 290 на имя,
   зазор и пять кнопок. Уступать обязано имя — на значок навели именно затем,
   чтобы прочитать, что он делает; имя к этой секунде уже прочитано, и оно
   обрезается многоточием, а не исчезает.
   `flex-shrink:100` — это «жмите меня первым»: без него флекс делит нехватку по
   величине, и обрезанными оказываются оба. Пол в 5rem — чтобы «поджать» не
   превратилось в «стереть»: замер без пола давал имени ровно ноль пикселей.
   🔴 `min-width` ИМЕНИ ЗАДАН ЗДЕСЬ И БОЛЬШЕ НИГДЕ. Оставить его заодно и в
   правиле выше значило бы, что величину выбирает порядок строк при равном весе
   селекторов, — на этом в проекте горели трижды. */
.m9-thread-who{flex-shrink:100;min-width:5rem}
/* 🔴 ПУНКТ 25: ЧЕТЫРЕ ТОНКИХ ЗНАЧКА СПРАВА В ШАПКЕ — ДЕЙСТВИЯ НАД ПЕРЕПИСКОЙ.
   Жалоба владельца на прежнюю шапку была не про то, что значки там стоят, а
   про то, КАК: «два растянутых во всю высоту значка, смысла не несут». Растянул
   их `align-items:stretch` у шапки-флекса — кнопка без своей высоты занимала
   все 52 пикселя и выглядела колонной.

   Поэтому здесь высота задана явно (28), значок внутри 20 — те же числа, что у
   действий в серой полосе внизу, чтобы два ряда кнопок читались одним языком. */
/* 🔴 ПУНКТ 50 ЗАБРАЛ У РЯДА `flex:0 0 auto`. Ряд обязан УМЕТЬ СЖИМАТЬСЯ: с
   раскрытой подписью он хочет 322 пикселя, а в узкой колонке шапке дано 290.
   Несжимаемый ряд в этом случае вылезает за колонку и молча срезается —
   у шапки `overflow:hidden`. Сжатие упирается в `min-width:auto`, то есть в
   собственную ширину значков: ниже неё ряд не пускает уже не пожелание, а сумма
   нерастворимых кнопок — каждая со своими 28 и несжимаемым значком внутри.

   🔴 `min-width:0` ЗДЕСЬ ОБЯЗАТЕЛЕН, И ЭТО НАШЛОСЬ ЗАМЕРОМ, А НЕ ЧТЕНИЕМ. У
   вложенного флекса `min-width:auto` вычислился в 314 пикселей — в РАСКРЫТУЮ
   ширину ряда, а не в собранную, — и сжатие не начиналось вовсе: ряд вылезал за
   колонку на 19 и срезался о `overflow:hidden` шапки. Ровно та беда, из-за
   которой пункт 50 откатили в прошлую смену. */
.m9-headacts{margin-left:auto;flex:0 1 auto;display:flex;align-items:center;
  gap:.1rem;flex-wrap:nowrap;min-width:0}
/* 🔴 ШИРИНА СТАЛА `min-width`, А ВЫСОТА ОСТАЛАСЬ ЖЁСТКОЙ, и это не послабление
   старой жалобы: она была про ВЫСОТУ («два растянутых во всю высоту значка»).
   Ширине расти теперь нужно — в ней раскрывается подпись.
   `padding:0 4px` вместе с `justify-content:flex-start` даёт в покое ровно тот
   же вид, что прежнее центрирование (4+20+4=28), но при тесноте прижимает
   значок влево, а не режет его с обеих сторон. */
.m9-headacts .m9-act{display:inline-flex;align-items:center;
  justify-content:flex-start;min-width:28px;max-width:100%;height:28px;
  padding:0 4px;border:0;border-radius:8px;cursor:pointer;flex:0 1 auto;
  background:transparent;color:var(--fg)}
.m9-headacts .m9-act:hover{background:rgba(0,0,0,.06)}
/* `flex:0 0 auto` значку — ЗАЩИТА ОТ СРЕЗАНИЯ. Без неё сжатие кнопки съедает
   не подпись, а сам значок: он элемент flex и по умолчанию жмётся. */
.m9-headacts .m9-act .ic{width:20px;height:20px;flex:0 0 auto}
.m9-headacts .m9-act-on{background:rgba(0,0,0,.10)}
.m9-headacts .m9-act-on:hover{background:rgba(0,0,0,.14)}
.m9-full{margin-left:auto;font-size:12px;color:var(--dim)}
.m9-dim{font-size:12px;color:var(--dim)}
.m9-thread-body{padding:.6rem .9rem}
/* Выбранная строка отличается от наведённой не только тоном: тона у них
   теперь почти одинаковые, и «где я» держится ещё и на весе имени. */
.m9-sel{background:var(--pick-row);border-radius:8px}
.m9-sel .m9-who{font-weight:700}
.m9-has-thread .m9-placeholder{display:none}

/* Фаза 9, кусок 5: вложения — только сведения о файле, без скачивания. */
.m9-att{list-style:none;margin:.35rem 0 0;padding:0;display:flex;
  flex-direction:column;gap:.15rem}
.m9-att li{display:flex;align-items:baseline;gap:.4rem;flex-wrap:wrap;
  font-size:12px}
.m9-att-ico{opacity:.7}
.m9-att-name{font-weight:600;word-break:break-all}

/* Пропавшая колонка: дефект кода, а не пустые данные — видно, но не крикливо. */
.m9-gap{font-size:11px;color:var(--bad);border:1px dashed var(--bad);
  border-radius:99px;padding:0 .35rem;margin-right:.3rem}
.m9-gapband{margin:0;padding:.5rem .7rem;border-top:1px solid var(--bad);
  background:var(--badbg);color:var(--bad);font-size:12px}

/* Свёрнутая цитата: история письма за одно нажатие, а не на пол-экрана. */
.m9-quote{margin:.3rem 0 0}
.m9-quote > summary{cursor:pointer;font-size:12px}
/* 🔴 ВНУТРИ ОБЛАЧКА — ЛИНИЯ, А НЕ ТРЕТИЙ ФОН. Цитата и оригинал лежали
   каждый в своей светлой рамке внутри облачка: получалось окно в окне, и таких
   окошек на экране набиралось много. Разделять достаточно тонкой линией
   поперёк — без рамки и без своего фона. */
/* Цитату раскрывают, чтобы прочитать историю письма, — значит и она основным
   цветом, как только показана. */
.m9-quoted{margin-top:.45rem;padding:.35rem 0 0;border-top:1px solid var(--line);
  color:var(--ink);white-space:pre-wrap}

/* ═══════════════════════════════════════════════════════════════════════════
   Фаза 9.1, пункт 1: СТРАНИЦА РОВНО В ОКНО, ПРОКРУТКА — ПОКОЛОНОЧНАЯ.

   🔴 ЗАЧЕМ. Прокручивалась вся страница целиком, и длинное письмо утаскивало
   за собой список и шапку: вернуться к списку можно было, только прокрутив
   всё обратно. У Shopify каждая колонка скроллится сама, и от этого зависит
   ощущение всего экрана.

   🔴 ПРАВИЛА ПРИВЯЗАНЫ К `body.m9-page`, А НЕ К `body`. Высота в окно нужна
   ЭТОМУ экрану и никакому другому; общий `body` держит все страницы панели, и
   переписать его значило бы чинить одно, ломая остальное. Класс ставит только
   `messages.html` (блок `bodyclass`), у прочих страниц он пуст.

   41px — высота `.topbar`; то же число уже стоит у `.rail`, и брать его
   оттуда честнее, чем заводить второе.
   ═══════════════════════════════════════════════════════════════════════ */
body.m9-page{overflow:hidden}
/* 🔴 ПОДВАЛ НА ЭКРАНЕ-ПРИЛОЖЕНИИ НЕ РИСУЕТСЯ. Он лежит ВНУТРИ прокручиваемой
   области, а содержимое здесь уже занимает всю её высоту, — то есть подвал
   добавлял свои ~80px сверх окна. Это и есть те «два сантиметра»: полоса
   принадлежала не странице, а области содержания, и стояла у самого края
   окна, отчего и выглядела страничной. Четыре колонки — экран, а не документ;
   подписи про источник данных место на документных страницах. */
body.m9-page footer{display:none}
body.m9-page .pane{overflow:hidden;display:flex;flex-direction:column}
body.m9-page main{padding:0;flex:1 1 auto;min-height:0;display:flex}
body.m9-page .m9{flex:1;min-height:0;height:100%;border:0;border-radius:0}

/* 🔴 `min-height:0` У КАЖДОЙ КОЛОНКИ — НЕ УКРАШЕНИЕ. Элемент grid по умолчанию
   не даёт себя сжать меньше содержимого, и без этого колонка с длинным письмом
   растянула бы всю сетку, вернув прокрутку страницы — то есть ровно то, от
   чего уходим. */
body.m9-page .m9 > *{min-height:0}
/* 🔴 КОЛОНКИ ПЕРЕПИСКИ В ЭТОМ СПИСКЕ БОЛЬШЕ НЕТ, И ЭТО НЕ УБОРКА. С пункта 6
   она держит три яруса — шапку, ленту и полосу ответа, — и прокручивается
   ровно середина (`.m9-thread-body` ниже). Объявление прокрутки ОСТАВАЛОСЬ и
   здесь: сейчас его перебивает `overflow:hidden` из блока пункта 6, но стоит
   переставить блоки местами — и прокрутчика станет два вложенных, то есть две
   полосы подряд, а шапка с полосой ответа поедут вместе с лентой.
   Одна колонка — одно место, где сказано, что в ней прокручивается. */
body.m9-page .m9-folders,
body.m9-page .m9-list,
body.m9-page .m9-customer{overflow-y:auto;overscroll-behavior:contain}

/* ═══════════════════════════════════════════════════════════════════════════
   Фаза 9.1, пункт 5.2: раскрытие — кнопкой, а не треугольником.

   🔴 ДОВОД СИЛЬНЕЕ ВКУСА. В панели уже есть свой язык кнопок: «Посмотреть
   письмо» в ленте событий, «Ответить», «Переслать». Треугольник-раскрывашка в
   этот язык не входит вовсе — поэтому и терялся: глаз ищет кнопку, а находит
   значок в полбуквы. Вид берётся у `.textbutton`, который делит правило с
   «Посмотреть письмо», — то есть это не новый вид, а тот же самый.

   🔴 ИСКЛЮЧЕНИЕ, КОТОРОЕ НЕЛЬЗЯ ПЕРЕПУТАТЬ: строка сути `summary_ru`
   разворачивается кликом ПО САМОМУ ТЕКСТУ, без кнопки и без вида ссылки.
   Разница осмысленная: строка сути — то же письмо, только коротко, а
   «оригинал» и «переписка целиком» — ДРУГОЕ содержимое, которое надо достать;
   это действие, и ему нужна кнопка.

   Маркер Safari гасится отдельно: `list-style:none` его не убирает, и без
   этого правила треугольник вернулся бы ровно там, где его убирали.
   ═══════════════════════════════════════════════════════════════════════ */
.textbutton::-webkit-details-marker{display:none}
summary.textbutton{list-style:none}
summary.textbutton:hover{border-color:var(--dim)}
.m9-open-block{margin-top:.35rem}
.m9-open-block[open] > summary.textbutton{margin-bottom:.35rem}

/* 5.3: язык клиента виден под переводом — тише основного текста. */
/* Оригинал — вложенный уровень: своя заливка вместо полосы слева (полоса
   была `--line`, то есть ровно цвет карточки, и на ней исчезла бы). */
.m9-orig{margin-top:.45rem;padding-top:.35rem;border-top:1px solid var(--line)}
.m9-orig-peek{font-size:12px;color:var(--dim);opacity:.85;white-space:pre-wrap}
/* Остаток оригинала выглядит ровно как начало: раскрытое должно читаться ОДНИМ
   текстом, продолжающимся с того места, где он был обрезан, — а не вторым
   блоком, начинающимся заново. Ради этого же и полоса слева та же самая. */
.m9-orig-rest{font-size:12px;color:var(--dim);opacity:.85;white-space:pre-wrap;
  margin:0}
/* Кнопка стоит между началом и остатком и в раскрытом виде становится тише:
   она уже сделала свою работу, а текст вокруг важнее её. */
.m9-orig .m9-open-block{margin:.1rem 0}
.m9-orig .m9-open-block[open] > summary{opacity:.55}

/* Страна доставки рядом с оригиналом — контекст, а не утверждение о языке. */
.m9-country{display:inline-block;font-size:11px;font-weight:600;color:var(--dim);
  border:1px solid var(--line);border-radius:4px;padding:0 .3rem;
  margin-bottom:.25rem;letter-spacing:.03em}

/* ═══════════════════════════════════════════════════════════════════════════
   Пояснение слева, число справа, правый край общий.

   🔴 ЗАЧЕМ. Под суммой «126.22 EUR» стояла вторая строка «126.22 EUR без VAT»:
   пометка ПОСЛЕ числа сдвигала его влево, и два числа переставали стоять друг
   под другом. Их сравнивают глазом — а сравнение возможно только когда цифры в
   одной колонке. С пометкой слева правый край общий, и «сколько с VAT» против
   «сколько без» читается сравнением, а не поиском.

   Правило одно на все три места (позиция, строка расчёта, Итого): разнобой в
   двух из трёх читался бы как разные по смыслу строки.
   ═══════════════════════════════════════════════════════════════════════ */
.net{display:flex;justify-content:space-between;gap:.6rem;align-items:baseline}
.netlab{font-weight:400;white-space:nowrap}

/* Артикул-ссылка в каталог поставщика. Выделяется и копируется как обычный
   текст: ссылка не должна отнять у него это. */
/* 🔴 ТОЧЕЧНОЕ ПОДЧЁРКИВАНИЕ СНЯТО 02.08.2026. Владелец увидел артикул и принял
   его за текст с подсказкой, а не за ссылку: пунктир в вебе означает «наведи и
   узнаешь», то есть обещает пояснение, а не переход. Ссылка при этом РАБОЧАЯ —
   href подставляется, — и выглядела она не тем, чем была.

   Приём взят тот же, что у `.m9-quiet` (почта и телефон в переписке), и это не
   совпадение, а одно решение на панель: в покое ссылка неотличима от текста,
   признаки живут на приближении — курсор, подчёркивание при наведении и
   подсказка, которая есть всегда. Цена названа там же: неотличимость от текста
   в покое; платим её сознательно, потому что синева и сплошная черта на каждом
   артикуле шумят сильнее. */
.sku-link{color:inherit;text-decoration:none;text-underline-offset:2px;
  user-select:text;-webkit-user-drag:none}
.sku-link:hover{color:var(--fg);text-decoration:underline}

/* ═══════════════════════════════════════════════════════════════════════════
   Картинка крупно поверх страницы. Один приём на всю панель.

   🔴 ПРОКРУТКА ДЕРЖИТСЯ КЛАССОМ НА <html>, А НЕ INLINE-СТИЛЕМ. На странице
   сообщений `body` уже управляется своим правилом (`body.m9-page`), и запись в
   style при закрытии затёрла бы его. Класс снимается — и остаётся то, что
   говорит CSS, каким бы оно ни было.

   Полоса прокрутки заменяется отступом: без этого страница под подложкой
   дёргается вбок на ширину полосы, и после закрытия видно, что «что-то
   прыгнуло».
   ═══════════════════════════════════════════════════════════════════════ */
html.zoom-open{overflow:hidden;scrollbar-gutter:stable}

dialog.zoom{border:0;padding:0;background:transparent;max-width:100vw;
  max-height:100vh;width:100vw;height:100vh;overflow:hidden}
dialog.zoom::backdrop{background:rgba(0,0,0,.78)}
dialog.zoom img{display:block;margin:auto;max-width:94vw;max-height:94vh;
  width:auto;height:auto;object-fit:contain;cursor:zoom-out;
  border-radius:6px;background:#fff}
/* Телефон и планшет: та же подложка, просто меньше полей. */
@media (max-width:640px){
  dialog.zoom img{max-width:100vw;max-height:100vh;border-radius:0}
}
.thumb a[data-zoom]{cursor:zoom-in}

/* Пункт 2: колонка папок исчезла — областей три, а не четыре. Промежуточный
   оттенок фона ушёл вместе с ней, структурно, а не подбором цвета (3.1). */
/* 🔴 ПУНКТ 5.1: ШИРИНУ СПИСКА МОЖНО ТЯНУТЬ. Вторая дорожка нулевой ширины —
   это ручка: она рисуется поверх шва между колонками, а места в сетке не
   занимает. Запасное значение переменной стоит прямо здесь, поэтому при
   выключенном JS раскладка остаётся ровно прежней. */
/* 🔴 У ПЕРЕПИСКИ ЕСТЬ ПОЛ, И ОН ПОЯВИЛСЯ ВМЕСТЕ С ДЕЙСТВИЯМИ В ШАПКЕ.
   Было `minmax(0,1.4fr)` — колонка сжималась до нуля, и владелец, утащив ручку
   списка до предела (760), оставлял переписке 43 пикселя. Пока в её шапке
   стояло одно имя, это было просто некрасиво; с кнопками они вылезают за
   колонку на 68 (замер) и молча срезаются: у шапки `overflow:hidden`, полосы
   прокрутки не появляется, и главная проверка ширины такого не видит.

   Пол в 320 ничего не отнимает: сетка берёт недостающее из колонки списка,
   которую и тянули. Ручка по-прежнему ходит до 760, но за счёт себя.
   Держит `test_a_long_name_does_not_push_the_header_out_of_the_column`. */
body.m9-page .m9{grid-template-columns:minmax(0,var(--m9listw,1fr)) 0
  minmax(320px,1.4fr) 260px}
/* Граница принадлежит колонке СПРАВА от линии: у списка слева уже есть граница
   меню (`.rail`), и вторую с той же стороны заводить нельзя. */
body.m9-page .m9-thread-view,
body.m9-page .m9-customer{border-left:1px solid var(--line)}
@media (max-width:1100px){
  body.m9-page .m9{grid-template-columns:1fr}
  .m9-drag{display:none}
}
.m9-drag{position:relative;width:0;cursor:col-resize;touch-action:none;z-index:4}
.m9-drag::before{content:"";position:absolute;inset-block:0;left:-3px;width:7px;
  background:transparent}
.m9-drag:hover::before,.m9-drag.moving::before{background:#c7c7c7}
/* Папки в меню: неготовая — приглушена и названа, как было в колонке. */
.rail .subs .off{display:block;padding:.2rem .6rem;color:var(--dim);opacity:.6;
  font-size:12px;cursor:default}
.rail .subs .off em{font-style:normal;border:1px dashed var(--line);
  border-radius:99px;padding:0 .3rem;margin-left:.2rem}

/* ═══════════════════════════════════════════════════════════════════════════
   Фаза 9.1, пункт 6: ПЕРЕПИСКА КАК ЧАТ — ТРИ ЯРУСА, ПОСЛЕДНЕЕ ПИСЬМО ВНИЗУ.

   Слова владельца: «когда я открываю переписку с клиентом, она всегда
   последняя внизу отображается». Отсюда раскладка мессенджера: шапка сверху,
   сама лента посередине и только она прокручивается, полоса ответа прижата к
   нижнему краю колонки и не уезжает вместе с лентой.

   Прокручивается теперь НЕ колонка целиком, а её середина: иначе полосу ответа
   пришлось бы держать `position:sticky`, и она наезжала бы на последнее письмо
   вместо того, чтобы стоять под ним.
   ═══════════════════════════════════════════════════════════════════════ */
body.m9-page .m9-thread-view{overflow:hidden;display:flex;flex-direction:column}
.m9-thread-view .m9-thread-body{flex:1 1 auto;min-height:0;overflow-y:auto;
  overscroll-behavior:contain}
/* 🔴 ЗДЕСЬ СТОЯЛО ВТОРОЕ ОБЪЯВЛЕНИЕ `.m9-compose` С `display:flex`, И ОНО
   ЛОМАЛО ПОЛОСУ ОТВЕТА. Правило ниже по файлу задавало рамку и отступы, но
   `display` не трогало — а этот `flex` ставил два этажа В ОДНУ СТРОКУ: поле для
   письма съёживалось слева, серая полоса со значками вставала справа от него.
   Владелец увидел это сразу: «зачем он сделал в одну линию».

   Третий раз за сутки одна и та же порода: два объявления одного класса в
   разных концах файла, и глазами это не ловится. Живое правило одно и стоит
   вместе с остальным про полосу ответа. */
.m9-compose{flex:0 0 auto}

/* ═══════════════════════════════════════════════════════════════════════════
   Фаза 9.1, пункт 9: ПРАВАЯ КОЛОНКА — СВЕДЕНИЯ О ЗАКАЗЕ.

   Колонка перестала быть обещанием, поэтому и выравнивание другое: содержимое
   идёт сверху вниз, а не висит по центру, как висела одна строка «следующий
   шаг». Прокрутку колонка получила ещё в пункте 1 и здесь не трогается.
   ═══════════════════════════════════════════════════════════════════════ */
/* 🔴 `flex-direction:column` ДОБАВЛЕН 02.08.2026 ВМЕСТЕ С ШАПКОЙ КОЛОНКИ.
   Раньше в колонке был один ребёнок, и направление флекса значения не имело —
   а с появлением шапки два ребёнка встали В СТРОКУ: шапка шириной 124 и
   сведения рядом с ней, вылезающие за колонку на 15 пикселей. Поймал замер, не
   глаз: на глаз это выглядело как «шапка почему-то узкая». */
body.m9-page .m9-customer{flex-direction:column;align-items:stretch;
  justify-content:flex-start;padding:0}
.m9-side{padding:.8rem .9rem;font-size:13px}
.m9-side-h{margin:0 0 .45rem;font-size:14px;font-weight:650;color:var(--fg);
  text-transform:none;letter-spacing:0}
.m9-side-h4{margin:.95rem 0 .25rem;font-size:11px;letter-spacing:.06em;
  text-transform:uppercase;color:#8a8a8a;font-weight:600}
.m9-side-pills{display:flex;flex-wrap:wrap;gap:.3rem}
.m9-side-sum{margin:.5rem 0 0;font-size:17px;font-weight:700}
.m9-side-items{list-style:none;margin:0;padding:0;display:flex;
  flex-direction:column;gap:.2rem}
.m9-side-items li{display:flex;gap:.4rem;align-items:baseline}
.m9-side-qty{color:var(--dim);flex:0 0 auto;font-variant-numeric:tabular-nums}
.m9-side-ship,.m9-side-contact,.m9-side-addr{margin:0;line-height:1.45}
.m9-side-more{margin:1rem 0 0}
/* Отказ запроса состава — тем же видом, что `m9-gap`: пробел кода виден, но
   не кричит. Пустой список означал бы «в заказе ничего нет». */
/* 🔴 ПУНКТ 25: ЛИНИЯ ПОД ШАПКАМИ ИДЁТ ОДНОЙ ЧЕРТОЙ ЧЕРЕЗ ВСЕ ТРИ КОЛОНКИ.
   Прежде подчёркивание было у списка и у переписки, а правая колонка
   начиналась сразу с заголовка — черта обрывалась на её левом краю. Тот же
   случай, что вертикаль между колонками: одна черта — один узел, и высота у
   всех трёх шапок одна (`--head`), иначе отрезки лягут на разных уровнях.

   Заголовок «Заказ NNNNNN» переехал внутрь этой шапки: он и есть ответ на
   вопрос «о чём колонка» (пункт 18, слева — с кем разговор). */
.m9-side-head{position:sticky;top:0;z-index:3;display:flex;align-items:center;
  height:var(--head);flex:0 0 auto;padding:0 .9rem;
  border-bottom:1px solid var(--line);background:var(--surface);overflow:hidden}
.m9-side-head .m9-side-h{margin:0;font-size:15px;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap;min-width:0}
.m9-side-gap{margin:.2rem 0 0;font-size:12px;color:var(--bad);
  border:1px dashed var(--bad);border-radius:8px;padding:.3rem .45rem}

/* Ряд действий под перепиской (Фаза 9.1, пункт 7). Вид взят у `.textbutton` —
   того же, что «Посмотреть письмо» и «Показать оригинал»: это не новый язык
   кнопок, а тот же самый. Будущие действия приглушены, но НЕ `disabled`:
   отключённая кнопка на нажатие не отвечает ничем, а этой есть что сказать. */
.m9-acts{display:flex;flex-wrap:wrap;gap:.35rem;align-items:center}
.m9-act{white-space:nowrap;text-decoration:none}
.m9-act-later{color:var(--dim)}
.m9-act-later:hover{color:var(--fg)}

/* Действие у строки списка (удалить / вернуть). Прячется до наведения: строк
   на экране полсотни, и полсотни кнопок «Удалить» разом — это шум, от которого
   уходит весь пункт 3. Клавиатуру это не отрезает — `:focus-within` показывает
   кнопку тому, кто идёт табом. В Архиве кнопка видна всегда: туда заходят
   нарочно и ровно за ней. */
/* 🔴 ПУНКТ 15: КНОПКА СТОИТ У ПРАВОГО КРАЯ ВТОРОЙ СТРОКИ, А НЕ ПЕРВОЙ.
   Была `top:.45rem` — то есть ровно поверх служебного блока, где номер заказа
   и дата. Замер: номер закрывался на 11×17 пикселей, дата на 36×16.

   Правило, по которому выбрано место (оно же в
   `test_the_hover_action_does_not_cover_the_number_or_the_date`): всплывающее
   при наведении управление вправе закрыть текст, который И ТАК обрезан — суть
   письма обрывается по второй строке многоточием, и её хвост дочитывается
   открытием переписки. ФАКТ так дочитать нельзя: номер и дата либо видны,
   либо их нет, и закрывать их нечем.

   Постоянное место в строке тоже годилось бы, но у него есть цена: колонка
   узкая (ширина запоминается ручкой), и отведённое кнопке место отнималось бы
   у имени и сути ВСЕГДА, а не только под указателем. Поэтому — вторая строка.

   Считается снизу, а не сверху: у сути ровно две строки всегда
   (`min-height:40px`), поэтому низ строки — устойчивая опора, а высота
   верхнего блока зависит от того, есть ли значок состояния и бирка вложения. */
.m9-thread{position:relative}
.m9-rowact{position:absolute;bottom:.45rem;right:.5rem;margin:0;opacity:0;
  transition:opacity .12s}
.m9-thread:hover .m9-rowact,.m9-rowact:focus-within,.m9-rowact-on{opacity:1}
/* 🔴 ПОСТОЯННОЙ КНОПКЕ — ПОСТОЯННОЕ МЕСТО, И ВОТ ЕГО ЦЕНА. В Архиве «Вернуть»
   видна всегда, а не под указателем, и разрешение «закрывать собой обрезанный
   текст» на неё не распространяется: оно куплено тем, что кнопки в покое нет.
   Поэтому строкам Архива суть сжимается справа на ширину кнопки — 4.6rem, из
   них ~4.1 сама кнопка и просвет. Цена: в Архиве суть обрывается раньше на
   несколько знаков. Во Входящих ширина не отнимается вовсе.

   `:has()` здесь не украшение, а способ обойтись без правки шаблона: признак
   постоянной кнопки живёт на самой кнопке. Браузер постарше правило пропустит
   целиком — вернётся сегодняшнее поведение, а не поломка. */
.m9-thread:has(.m9-rowact-on) .m9-gist{padding-right:4.6rem}
.m9-rowact .textbutton{font-size:11px;padding:.12rem .45rem}
/* Сказанное после нажатия — спокойным тоном: это не беда, а отчёт. */
.m9-notice{background:var(--surface);border:1px solid var(--line);
  color:var(--fg);font-size:12px}

/* ═══════════════════════════════════════════════════════════════════════════
   Карточка письма: служебное одной строкой сверху, тело — только текст.

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

   Слева «кто», справа «когда и что с этим» — две группы по краям строки. При
   узкой колонке правая группа переносится вниз (`flex-wrap`), а не режется.
   ═══════════════════════════════════════════════════════════════════════ */
/* 🔴 ПРАВАЯ ЧАСТЬ ДЕРЖИТСЯ НА СЕБЕ, А НЕ НА ДЛИНЕ СОСЕДА. Было
   `justify-content:space-between` при `flex-wrap:wrap`, и место служебной
   строки зависело от того, влезла ли левая часть: влезла — правая уходила к
   краю, не влезла — переносилась на новую строку, где она ОДНА, а одиночку
   `space-between` ставит в начало. Отсюда прыжки влево-вправо между соседними
   письмами: у одного адрес короткий, у другого длинный.
   `margin-left:auto` этим не страдает — одиночка на своей строке всё равно
   прижата вправо. */
.m9-msghead{display:flex;flex-wrap:wrap;align-items:baseline;gap:.15rem .6rem;
  margin-bottom:.2rem}
.m9-msgwho{display:inline-flex;flex-wrap:wrap;align-items:baseline;gap:.35rem;
  flex:1 1 auto;min-width:0}
.m9-msgmail{color:var(--dim);font-size:12px;word-break:break-all}
.m9-msgsvc{color:var(--dim);font-size:12px;white-space:nowrap;
  margin-left:auto;flex:0 0 auto}
/* Бирка страны в строке имени: тот же вид, но без прежнего нижнего отступа —
   он был нужен, когда она стояла над текстом оригинала. */
.m9-msgwho .m9-country{margin-bottom:0}
/* Действия — завершение карточки: отделены воздухом, а не линией (пункт 3). */
.note.client .ways{margin:.55rem 0 0;display:flex;flex-wrap:wrap;gap:.35rem}

/* Значок внутри мелкой бирки: под размер строки, с зазором до числа. Эмодзи
   тянул за собой свой кегль и свой цвет — вектор берёт и то, и другое у
   текста рядом. */
.m9-tag-att{display:inline-flex;align-items:center;gap:.2rem}
.m9-tag-att .ic{width:12px;height:12px}
.m9-att-ico .ic{width:13px;height:13px;vertical-align:-2px}
.client-ava .ic{width:15px;height:15px}

/* Значок состояния в строке списка: место значка канала, смысл другой.
   Пунктирный кружок читается как «ещё в работе», кружок с галочкой — как
   «закрыто»; цвет приглушён, потому что это фон разговора, а не тревога. */
.m9-state{display:inline-flex;align-items:center;color:#8a8a8a;flex:0 0 auto}
.m9-state .ic{width:15px;height:15px}
.m9-state-closed{color:#5a5a5a}
/* Канал в шапке переписки — значок и слово рядом, тише заголовка. */
.m9-thread-chan{display:inline-flex;align-items:center;gap:.3rem;
  font-size:12px;color:var(--dim)}
.m9-thread-chan .ic{width:14px;height:14px}

/* ═══════════════════════════════════════════════════════════════════════════
   Короткий разговор прижат к низу — как в любом мессенджере.

   🔴 ВЁРСТКОЙ, А НЕ СКРИПТОМ. Прокрутка вниз при открытии решает только случай
   «сообщений много»; при коротком разговоре прокручивать нечего, и он висел
   вверху колонки, оставляя пустоту над полем ответа — то есть ровно там, куда
   человек смотрит.

   `margin-top:auto` у обёртки — а НЕ `justify-content:flex-end` у колонки:
   второе при переполнении делает верх ленты недостижимым (старая беда flex,
   первое сообщение просто нельзя прокрутить). Автоматический отступ при
   переполнении схлопывается в ноль, и длинная лента ведёт себя как обычно.
   ═══════════════════════════════════════════════════════════════════════ */
.m9-thread-view .m9-thread-body{display:flex;flex-direction:column}
.m9-thread-body > .m9-feed{margin-top:auto}

/* Полоса прокрутки тонкая: она отъедает ширину у колонки, а колонок три.
   `auto` (а не `scroll`) везде — полоса появляется по надобности; здесь только
   её толщина. */
body.m9-page .m9-list,
body.m9-page .m9-customer,
.m9-thread-view .m9-thread-body{scrollbar-width:thin}

/* ═══════════════════════════════════════════════════════════════════════════
   Оригинал письма — ОДИН блок, который становится выше.

   🔴 Было два вывода одного текста: две строки, кнопка, остаток. Слов не
   дублировалось, но шов посреди текста читался как повтор. Теперь область
   одна, а свёрнутость — это ограничение высоты, которое снимается.

   Галочка скрыта, но остаётся достижимой с клавиатуры (не `display:none`):
   переключатель, недоступный табом, — это отнятая возможность, а не мелочь.
   ═══════════════════════════════════════════════════════════════════════ */
.m9-origtoggle{position:absolute;width:1px;height:1px;opacity:0;margin:0}
.m9-orig-full{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
  overflow:hidden;font-size:12px;color:var(--dim);opacity:.85;white-space:pre-wrap}
/* 🔴 РАЗВЁРНУТЫЙ ОРИГИНАЛ ЧИТАЮТ ЦЕЛИКОМ — значит основным цветом. Свёрнутые
   две строки остаются приглушёнными: их проглядывают, чтобы увидеть язык и
   тон. Правило то же, что у тела письма: приглушённый цвет — для того, что
   проглядывают, основной — для того, что читают. */
.m9-origtoggle:checked ~ .m9-orig .m9-orig-full{display:block;overflow:visible;
  color:var(--ink)}
/* 🔴 ПЕРЕКЛЮЧАТЕЛЬ ЖИВЁТ НА БИРКЕ СТРАНЫ, И ЗА ЭТО НАДО ПЛАТИТЬ ПРИЗНАКАМИ.
   Бирка была подписью и ничего не обещала; сделав её действием, мы прячем
   возможность в том, что выглядит меткой. Поэтому нажимаемость показана тремя
   средствами сразу — курсор, отклик при наведении, подсказка, — а раскрытое
   состояние меняет вид самой бирки: она отвечает и на «можно нажать», и на
   «нажато». Без этого про возможность просто никто не узнает. */
/* `user-select` здесь НЕ отключается: общий сторож запрещает это по всей
   панели, чтобы почту и адреса можно было выделить и скопировать. Двойное
   нажатие по бирке выделит две буквы — мелочь рядом с ценой исключения. */
.m9-origswitch{cursor:pointer}
.m9-origswitch:hover{border-color:#8a8a8a;color:var(--fg)}
.m9-origtoggle:checked ~ .m9-msghead .m9-origswitch{background:var(--fg);
  border-color:var(--fg);color:#fff}
.m9-origtoggle:focus-visible ~ .m9-msghead .m9-origswitch{outline:2px solid var(--acc)}
/* Без страны переключать нечем — тогда маленький значок перевода в конце
   служебной строки, из того же набора, что все остальные. */
.m9-origswitch-icon{display:inline-flex;align-items:center;color:var(--dim);
  border:1px solid var(--line);border-radius:6px;padding:0 .2rem;
  background:var(--surface)}
.m9-origswitch-icon .ic{width:13px;height:13px}

/* ═══════════════════════════════════════════════════════════════════════════
   Отбор в списке — наши элементы, а не браузерные.

   🔴 ПРАВИЛО: голых `select`/`checkbox`/`radio` на экранах панели нет. Они
   рисуются операционной системой — квадратные, серые, своей высоты, — и рядом
   со скруглёнными бирками читаются как форма из другой эпохи. Нужен такой
   элемент — он получает наш вид.
   ═══════════════════════════════════════════════════════════════════════ */
.m9-filters select{appearance:none;-webkit-appearance:none;font:inherit;
  font-size:12px;color:var(--fg);background:var(--surface);
  border:1px solid #c9cccf;border-radius:8px;padding:.2rem 1.5rem .2rem .5rem;
  cursor:pointer;
  background-image:linear-gradient(45deg,transparent 50%,#8a8a8a 50%),
                   linear-gradient(135deg,#8a8a8a 50%,transparent 50%);
  background-position:calc(100% - 12px) 52%,calc(100% - 8px) 52%;
  background-size:4px 4px,4px 4px;background-repeat:no-repeat}
.m9-filters select:hover{border-color:#8a8a8a}
/* Бирка-переключатель: тот же вид, что у бирок в строке письма. Залитая —
   значит отбор включён; ссылка, потому что отбор живёт в адресе. */
/* ═══════════════════════════════════════════════════════════════════════════
   ШАПКА СПИСКА ПРИЖАТА К ВЕРХУ КОЛОНКИ.

   🔴 `sticky` ВНУТРИ УЖЕ СУЩЕСТВУЮЩЕЙ ПРОКРУТКИ, А НЕ ВТОРОЙ ПРОКРУЧИВАЕМЫЙ
   БЛОК. Колонка `.m9-list` сама по себе `overflow-y:auto`; разделив её на
   неподвижную шапку и отдельно прокручиваемый список, мы завели бы ВТОРУЮ
   полосу внутри колонки — ровно то, что уже ловили дважды. При `sticky`
   полоса остаётся одна, колонкина: шапка просто не уезжает.

   🔴 ФОН ОБЯЗАТЕЛЕН. Прижатый элемент без фона пропускает сквозь себя строки
   списка: они едут под ним и просвечивают. Ошибка тихая — видна только при
   прокрутке, а на пустом списке выглядит исправной.

   🔴 ВЫСОТУ ЗАДАЁТ `--head` И НЕ МЕНЯЕТ ЕЁ НИКОГДА. Низ шапки списка обязан
   совпадать с низом шапки переписки, иначе линия под ними идёт двумя
   отрезками на разных уровнях; это замеренное требование, за ним стоит
   проверка в браузере. Отсюда же и `nowrap`: перенос бирок на вторую строку
   увёл бы низ шапки вниз и дёргал бы список при каждом нажатии. */
/* 🔴 ИМЯ КЛАССА СМЕНЕНО 02.08.2026, И ЭТО БЫЛА НАСТОЯЩАЯ ПОЛОМКА. Класс
   `m9-head` УЖЕ БЫЛ ЗАНЯТ: им размечена верхняя строка КАЖДОЙ строки списка
   (имя, номер заказа, дата). Правило `position:sticky` накрыло их все — и
   десятки строк начали липнуть к верху колонки, заезжая поверх настоящей
   шапки. Со стороны это выглядело как просвечивание: сквозь чипы был виден
   адрес клиента и дата.

   🔴 ПОЧЕМУ ПРОВЕРКА МОЛЧАЛА. Она спрашивала `.m9-list .m9-head` — и находила
   ПЕРВЫЙ такой элемент, то есть настоящую шапку. Та и правда была липкой и
   непрозрачной. Проверка стерегла свойство одного узла, а поломка жила в том,
   что узлов оказалось много. Теперь она вдобавок ТЫКАЕТ В ЭКРАН после
   прокрутки и требует, чтобы сверху был именно заголовок. */
.m9-listhead{position:sticky;top:0;z-index:3;background:var(--surface)}
/* Полоса сообщений прижимается ВМЕСТЕ с шапкой: уехав вверх, она унесла бы
   рассказ о том, куда делось письмо, — а он нужен ровно тогда, когда человек
   смотрит в список. */
.m9-list > .m9-band{position:sticky;top:0;z-index:4}

/* ── Раскрывашка отбора: накладка, а не рост шапки ───────────────────────── */
.m9-more{position:relative;display:inline-flex;align-items:center}
.m9-moretoggle{position:absolute;width:1px;height:1px;opacity:0;
  pointer-events:none}
.m9-morelabel{cursor:pointer;white-space:nowrap}
/* 🔴 ВЕС, А НЕ ПОРЯДОК, И ЭТО НЕ ПРИДИРКА — ЗДЕСЬ УЖЕ БЫЛА ОШИБКА. Правило
   `.m9-chips{display:flex}` стоит НИЖЕ по файлу и весит столько же (один
   класс), поэтому короткое `.m9-chips-more{display:none}` ему проигрывало:
   накладка оставалась видимой и занимала ширину. Замер поймал это сразу —
   колонка списка оказалась шире себя на 54px. Селектор из двух классов
   выигрывает независимо от порядка строк. */
.m9-more .m9-chips-more{display:none}
/* 🔴 НАКЛАДКА ПЕРЕКРЫВАЕТ СПИСОК, А НЕ РАЗДВИГАЕТ ЕГО: отсюда `absolute`,
   свой фон и тень. Раскрытие отбора не должно двигать ни одной строки. */
.m9-moretoggle:checked ~ .m9-chips-more{display:flex;flex-wrap:wrap;
  position:absolute;left:0;top:100%;min-width:max-content;max-width:60vw;
  z-index:5;background:var(--paper);border:1px solid var(--line);
  border-radius:var(--radius);box-shadow:var(--shadow);padding:.5rem;
  margin-top:.25rem}
/* Обведение фокуса своё: по раскрывашке ходят с клавиатуры, а сам чекбокс
   спрятан — значит признак фокуса обязан появиться на подписи. */
.m9-moretoggle:focus-visible + .m9-morelabel{outline:2px solid var(--acc);
  outline-offset:2px}

.m9-chips{display:flex;flex-wrap:wrap;gap:.3rem;padding:0 .7rem .5rem}
.m9-chip{font-size:11px;border:1px solid var(--line);border-radius:99px;
  padding:.05rem .5rem;color:var(--dim);text-decoration:none;background:var(--surface)}
.m9-chip:hover{border-color:#8a8a8a;color:var(--fg)}
.m9-chip.on{background:var(--fg);border-color:var(--fg);color:#fff}
/* Кнопка в шапке переписки — та же, что «Ответить» и «Переслать»: подчёркивание
   внутри рамки обещало бы ссылку и кнопку одновременно. */
.m9-full{margin-left:auto;text-decoration:none}

/* Полоса сообщения внутри колонки списка: своя ширина, свой перенос, и она
   НЕ участвует в раскладке сетки — колонки стоят на месте, что бы в ней ни
   было написано. */
.m9-band{margin:0;border-radius:0;font-size:12px;padding:.45rem .7rem;
  flex:0 0 auto}

/* ═══════════════════════════════════════════════════════════════════════════
   Стороны в ленте: клиент слева, мы справа.

   🔴 СТОРОНУ ЗАДАЁТ АВТОР, А НЕ КАНАЛ. В смешанном разговоре (часть в чате,
   часть по почте) это тем более так: говорит человек, а не канал.

   🔴 СОБЫТИЯ ЗАКАЗА СТОРОН НЕ ИМЕЮТ и облачками не становятся. «Отправлен»,
   «трек обновлён», «открыт спор» сообщил Shopify — это ни чья реплика, и
   поставить её на чью-то сторону значило бы приписать авторство. Туда же
   наш внутренний комментарий (`kind='note'`): наружу он не уходил, клиент его
   не видел.

   Ширина облачка — три четверти колонки: сдвиг читается только тогда, когда
   облачко уже колонки. Ровно поэтому же значок стороны стоит СНАРУЖИ облачка,
   у своего края, а не внутри.
   ═══════════════════════════════════════════════════════════════════════ */
/* 🔴 ВЕС СЕЛЕКТОРА ЗДЕСЬ РЕШАЕТ, И ЭТО БЫЛА НАСТОЯЩАЯ ОШИБКА. Правило выше
   (`ul.tl li.note`) весит 0,2,2 и ставит `margin:.4rem 0`; мои `li.note.m9-side-*`
   весили 0,2,1 — то есть проигрывали, и `margin-left:auto` не применялся вовсе.
   У клиента это было незаметно (слева и так слева), а НАШИ письма оставались
   слева, хотя сами про себя писали «письмо от нас». Владелец нашёл по снимку.
   Теперь вес тот же, и побеждает порядок в файле — как у облачек событий. */
ul.tl li.note.m9-side-them{max-width:78%;margin-right:auto;
  border-radius:var(--bubble);width:fit-content}
/* 🔴 НАША СТОРОНА НЕ КРАСИТСЯ ОТДЕЛЬНЫМ ЦВЕТОМ. Здесь стоял придуманный
   мной #e7efe9 — новый цвет, которого в наборе нет. Стороны и так различаются
   средством посильнее краски: положением у своего края, направлением значка и
   выравниванием служебной строки. Тон у обоих облачек один. */
/* 🔴 ПРИЖИМАЕТСЯ САМ БЛОК, А НЕ ТЕКСТ ВНУТРИ НЕГО. Было выровнено содержимое,
   а облачко оставалось во всю ширину — справа висела белая полоса, и сдвиг не
   читался. `width:fit-content` вместе с `margin-left:auto` двигает саму
   карточку, `max-width` не даёт ей дорасти до края. */
/* Наше письмо писал ЧЕЛОВЕК — голубое. Машинное уведомление о том же письме
   («подтверждение заказа отправлено») останется салатовым событием: цвет
   отвечает на вопрос «кто это сделал», и путать их нельзя. */
ul.tl li.note.m9-side-us{max-width:78%;width:fit-content;margin-left:auto;
  margin-right:0;flex-direction:row-reverse;border-radius:var(--bubble);
  background:var(--mine)}
/* Наша сторона читается ещё и выравниванием текста внутри шапки: служебное
   уходит к своему краю, а не к чужому. */
ul.tl li.note.m9-side-us .ways{justify-content:flex-end}

/* ═══════════════════════════════════════════════════════════════════════════
   Выбор письма и действия над ним.

   🔴 ВЫБОР НА СВОЕЙ МИШЕНИ, А НЕ НА СВОБОДНОМ ПОЛЕ КАРТОЧКИ. По карточке уже
   щёлкают ради текста — выделяют адрес, копируют номер, тянут мышью по строке
   оригинала, — и щелчок-выбор молча менял бы состояние экрана при каждом таком
   движении. Мишень своя, видна при наведении и достижима с клавиатуры.

   🔴 ВЫБРАННОЕ ОТЛИЧАЕТСЯ ОБВОДКОЙ, А НЕ ОТТЕНКОМ. После заливки карточек
   бежевым третьему тону в переписке уже тесно: покой, наведение, выбранное —
   различать их яркостью значило бы вернуть «пару процентов», которые глаз не
   ловит. Разные средства вместо разных яркостей одного.
   ═══════════════════════════════════════════════════════════════════════ */
/* Переключатель выбора живёт в СЛУЖЕБНОЙ СТРОКЕ, а не отдельной строкой внизу:
   там он занимал целую строку ради одного слова, а места в переписке мало. */
/* ═══════════════════════════════════════════════════════════════════════════
   ВЫБОР ПИСЬМА — ЩЕЛЧКОМ ПО ОБЛАЧКУ.

   🔴 ПРИЗНАК ВЫБРАННОГО — НЕ ЗАЛИВКА, И ЭТО НЕ ВКУС. Заливка занята: она
   отвечает на вопрос «что это за запись» (пять тонов на ступени облачка).
   Покрасив выбранное, мы завели бы шестой тон и сломали бы правило цвета.
   Поэтому обводка и мягкая тень — измерение, свободное от смысла.

   🔴 ОБВОДКА НЕ СИНЯЯ, И ЭТО ПОЧИНКА, А НЕ ПЕРЕКРАСКА. Владелец назвал
   прежнюю рамку «браузерного вида» — и был прав по ощущению, ошибся в
   причине: рамка была НАША, но красилась в `--acc`, тот же синий, что у
   ссылок и у обведения фокуса. Совпадение цвета и делало её похожей на
   браузерную. Теперь синий остался только за фокусом, а выбранное обводится
   основным тоном текста: два разных вопроса — два разных признака. */
.m9-pickable{cursor:pointer}
.m9-pickinput{position:absolute;width:1px;height:1px;opacity:0;
  pointer-events:none;margin:0}
.m9-pickmark{position:absolute;inset:0;border-radius:var(--bubble);
  pointer-events:none;opacity:0;
  box-shadow:0 0 0 2px var(--fg), 0 2px 8px rgba(0,0,0,.14)}
.m9-pickinput:checked ~ .m9-pickmark{opacity:1}
/* 🔴 ФОКУС ОСТАЁТСЯ ВИДИМЫМ, ХОТЯ САМ ПЕРЕКЛЮЧАТЕЛЬ СПРЯТАН. По переписке
   ходят с клавиатуры, и спрятать переключатель, не перенеся признак фокуса на
   облачко, значило бы отнять способ работать. Синий здесь законен: это и есть
   фокус. */
.m9-pickinput:focus-visible ~ .m9-pickmark{opacity:1;
  box-shadow:0 0 0 2px var(--acc), 0 2px 8px rgba(0,0,0,.14)}
li.note{position:relative}

.visually-hidden{position:absolute;width:1px;height:1px;overflow:hidden;
  clip-path:inset(50%);white-space:nowrap}

/* 🔴 ОБВЕДЕНИЕ ФОКУСА — НАШЕ, НО НЕ УБРАННОЕ. По нему ходят с клавиатуры, и
   снять его значило бы отнять способ работать; браузерное же выглядит чужим.
   Тот же цвет, что у ссылок, и отступ, чтобы обводка не липла к тексту. */
body.m9-page :focus-visible{outline:2px solid var(--acc);outline-offset:2px}
/* 🔴 ВТОРОЕ ОБЪЯВЛЕНИЕ `.m9-pickmark` УБРАНО ОТСЮДА 02.08.2026. Оно осталось
   от квадратика с галочкой и красило накладку в `--acc` — тот самый синий,
   из-за которого владелец принял нашу рамку за браузерную. Живое правило одно
   и стоит выше, вместе с остальным про выбор письма.
   Поймала это проверка, читающая ВСЕ объявления селектора, а не первое: два
   правила с одним именем в разных концах файла глазами не ловятся. */
/* Строка действий существует ВСЕГДА — она не появляется и не раздвигает
   переписку в момент щелчка. Пока ничего не выбрано, в ней подсказка. */
.m9-picked-acts{display:flex;flex-wrap:wrap;align-items:center;gap:.4rem;
  padding:.4rem .9rem 0;margin:0;min-height:1.9rem}
.m9-picked-hint{font-size:12px;color:var(--dim)}

/* ═══════════════════════════════════════════════════════════════════════════
   Строка списка: две части вместо трёх.

   🔴 ЧТО УСТУПАЕТ ПЕРВЫМ, КОГДА ТЕСНО. Справа теперь три вещи разом — номер,
   дата, счётчик, — и при длинном имени они начнут теснить друг друга. Уступает
   ИМЯ: оно сжимается и обрезается многоточием (`min-width:0` + `ellipsis`), а
   служебный блок не переносится и не режется (`white-space:nowrap`,
   `flex:0 0 auto`). Довод: имя видно в открытой переписке, а номер, дата и
   число писем — это то, ПО ЧЕМУ строку выбирают.
   ═══════════════════════════════════════════════════════════════════════ */
.m9-svc{margin-left:auto;flex:0 0 auto;display:inline-flex;align-items:baseline;
  gap:.4rem;white-space:nowrap;font-size:12px;color:var(--dim)}
.m9-num{font-variant-numeric:tabular-nums}
.m9-num-none{opacity:.75}
.m9-att-mark{display:inline-flex;align-items:center;color:#8a8a8a}
.m9-att-mark .ic{width:12px;height:12px}
.m9-why{opacity:.8}

/* ═══════════════════════════════════════════════════════════════════════════
   События заказа — тоже облачками (решение владельца, отменяет прежнее).

   🔴 НО СТОРОНА БЕРЁТСЯ ПО ТОМУ, КТО СОБЫТИЕ ВЫЗВАЛ. Наши уходят вправо и
   красятся салатовым — сразу видно, что это автоматика от нас, а не написанное
   человеком. Клиентские («заказ оформлен», «открыт спор») остаются СЛЕВА и
   зелёными НЕ красятся: зелёное справа означало бы «это сделали мы».
   Незнакомое событие — посередине, во всю ширину, как было.
   ═══════════════════════════════════════════════════════════════════════ */
ul.tl li.sys-us,
ul.tl li.sys-them{align-items:flex-start;max-width:78%;width:fit-content;
  border-radius:var(--bubble);padding:.4rem .7rem;margin:.35rem 0}
/* 🔴 СТОРОНА ЗАДАЁТ ТОЛЬКО ПОЛОЖЕНИЕ. Заливка ушла отсюда 02.08.2026: прежде
   событие на стороне клиента красилось серым, то есть цветом СЛОВ КЛИЕНТА, —
   а событие словами клиента не является. Теперь цвет назначает вид записи
   (`tone-*` ниже), и «слева» больше не значит «серое». */
ul.tl li.sys-us{margin-left:auto}
ul.tl li.sys-them{margin-right:auto}
/* Точка на нити внутри облачка не нужна: облачко само отделяет запись. */
ul.tl li.sys-us .dot,ul.tl li.sys-them .dot{display:none}
/* Тема ведёт строку сути: короткое слово перед ней, тише текста. Отдельной
   бирки нет намеренно — нижний ряд убран, и возвращать его нельзя. */
.m9-topic{font-weight:600;color:var(--fg)}

/* ═══════════════════════════════════════════════════════════════════════════
   Тревожное — светло-красным, и не только цветом.

   🔴 ДВА СИГНАЛА, А НЕ ОДИН. Салатовое и светло-красное для части людей
   выглядят одинаково — дальтонизм на красно-зелёное самый частый. Поэтому
   тревожное отличается ещё и ФОРМОЙ: у него остаётся полоса слева (`--bad`),
   которой нет ни у одного спокойного облачка. Цвет — подсказка, полоса —
   признак.

   Список тревожного узкий и закрытый (`labels.ALARMING`), тот же самый, что
   красит точку события на карточке заказа: два списка «что тревожно»
   разошлись бы, и одно событие выглядело бы бедой на одном экране и обычным
   делом на другом.
   ═══════════════════════════════════════════════════════════════════════ */
/* ═══════════════════════════════════════════════════════════════════════════
   ЦВЕТ ОБЛАЧКА ГОВОРИТ, ЧТО ЭТО ЗА ЗАПИСЬ. Сторона говорит, чья она.

   🔴 ПРАВИЛО ПЕРЕПИСАНО 02.08.2026 ЦЕЛИКОМ, И ПРЕЖНЕЕ УБРАНО, А НЕ ОСТАВЛЕНО
   РЯДОМ: две противоположные записи хуже одной неточной. Прежде цвет отвечал
   на вопрос «кто это сделал», и под этот ответ были заведены полосы слева —
   голубая у денег, красная у тревожного, — потому что цвет был занят.

   Теперь на «кто» отвечает СТОРОНА: клиент слева, мы справа. Она надёжнее
   цвета и видна раньше него. Цвет освободился и отдан вопросу «что это»,
   ради которого владелец его и просил: читать смысл записи, не читая текст.

   🔴 ПОЛОС БОЛЬШЕ НЕТ ВОВСЕ. Обе сняты здесь же, одним заходом с переходом на
   новое правило: полоса стала бы вторым способом сказать то же самое, а
   промежуточного состояния, где действуют оба признака, на экране быть не
   должно.

   Пять тонов, два семейства, все на ступени облачка (светлота 243–244):

       РАЗГОВОР (написал человек)   СОБЫТИЯ (случилось с заказом)
         серый    слова клиента       салатовый  рядовое
         голубой  наше письмо         янтарный   деньги
                                      красноват  споры, отказы, возвраты

   Заливка разговора живёт выше (`li.note`), здесь только события.

   🔴 ЦЕНА, КОТОРУЮ НАДО ЗНАТЬ: КРАСНО-ЗЕЛЁНАЯ СЛЕПОТА. Красную полосу
   тревожного держал отдельный довод — для дейтеранопа салатовое и красноватое
   неразличимы (замер: ΔE 1.46 при пороге 2.3), и полоса была единственным
   признаком, доходившим до такого человека. Сняв её, мы этот признак потеряли:
   системное и проблемное для него стали одним цветом. Владелец предупреждён;
   если понадобится вернуть — возвращать НЕ полосой (она снова заспорит с
   заливкой), а значком: значков в ленте нет ни одного, это свободное
   измерение, и оно переживает любую слепоту на цвет.
   ═══════════════════════════════════════════════════════════════════════ */
ul.tl li.sys-us.tone-system,
ul.tl li.sys-them.tone-system{background:var(--event-ok)}
ul.tl li.sys-us.tone-money,
ul.tl li.sys-them.tone-money{background:var(--money-bg)}
ul.tl li.sys-us.tone-problem,
ul.tl li.sys-them.tone-problem{background:var(--event-bad)}
ul.tl li.sys-us .dot,ul.tl li.sys-them .dot{display:none}

/* ═══════════════════════════════════════════════════════════════════════════
   Длинная ссылка не имеет права распирать колонку.

   🔴 ЗАМЕРЕНО В БРАУЗЕРЕ, А НЕ НА ГЛАЗ: лента переписки была ШИРЕ своей
   колонки на 620px — отсюда и горизонтальная полоса внизу. Виновник с экрана
   владельца: ссылка подтверждения заказа Shopify в 180 знаков без единого
   пробела. По базе самое длинное «слово» — 512 знаков, и таких писем много:
   ссылки DHL и inforu по 154 знака лежат в четырёх десятках писем.

   🔴 ЛЕЧИТСЯ В ДВУХ МЕСТАХ, И ОДНОГО МАЛО.
     * `overflow-wrap:anywhere` — самому тексту: длинное слово переносится, а
       не растёт вправо. Именно `anywhere`, а не `break-all`: рвать разрешено
       ТОЛЬКО когда иначе не влезает, обычные слова остаются целыми.
     * `min-width:0` — колонке содержимого внутри карточки. Элемент flex по
       умолчанию не сжимается меньше своего содержимого, и без этого перенос
       не спасает: карточка всё равно растёт под самое длинное слово.

   🔴 `overflow-x:hidden` ЗДЕСЬ БЫЛО БЫ ЛЕЧЕНИЕМ СИМПТОМА. Полоса исчезла бы, а
   текст остался бы обрезанным справа — и владелец читал бы письмо без хвоста,
   не зная, что хвост есть. Это ровно тот обмен, от которого мы уходим весь
   день: тишина вместо признания.
   ═══════════════════════════════════════════════════════════════════════ */
ul.tl li.note > div,
ul.tl li.sys > div{min-width:0}
.note-text,.m9-orig-full,.m9-quoted,.m9-gist,.m9-msgsvc,
ul.tl li.sys > div{overflow-wrap:anywhere}

/* Тихая ссылка: в покое неотличима от соседнего текста, при наведении
   объявляет себя подчёркиванием и цветом ссылки. Признаки не убраны, а
   перенесены на приближение — иначе нажимаемое стало бы неотличимо от текста,
   и про него никто бы не узнал. */
/* 🔴 ТИХАЯ ССЫЛКА — ОДИН ПРИЁМ НА ВСЮ ПАНЕЛЬ. В покое неотличима от текста,
   признаки живут на приближении: курсор, подчёркивание при наведении и
   подсказка, которая есть всегда.

   🔴 ПРИ НАВЕДЕНИИ БОЛЬШЕ НЕ СИНЕЕТ, 02.08.2026. Владелец жаловался на синеву
   в этих местах, и он прав дважды: во-первых, синий у нас означает ссылку
   ВООБЩЕ и обведение фокуса, а тихая ссылка нарочно от этого признака
   отказалась; во-вторых, у артикула (`.sku-link`) тот же приём давал при
   наведении основной тон — то есть два одинаковых по смыслу места вели себя
   по-разному. Теперь оба темнеют, а не синеют. */
.m9-quiet{color:inherit;text-decoration:none}
.m9-quiet:hover{color:var(--fg);text-decoration:underline}

/* ═══════════════════════════════════════════════════════════════════════════
   Полоса прокрутки: тонкая и скруглённая.

   🔴 ЧТО МЫ МОЖЕМ, А ЧТО РЕШАЕТ СИСТЕМА — сказано честно. Толщину, цвет и
   скругление задаём мы. А вот ЛЕЖИТ полоса поверх содержимого или отнимает
   ширину — решает операционная система: на macOS это настройка «показывать
   полосы прокрутки» (при «автоматически» она наложенная и ширины не отнимает),
   в Linux и Windows по умолчанию отнимает. Обещать здесь наложенность нельзя,
   можно только не делать её толще нужного.
   ═══════════════════════════════════════════════════════════════════════ */
body.m9-page ::-webkit-scrollbar{width:8px;height:8px}
body.m9-page ::-webkit-scrollbar-track{background:transparent}
body.m9-page ::-webkit-scrollbar-thumb{background:#c9c9c9;border-radius:99px;
  border:2px solid transparent;background-clip:content-box}
body.m9-page ::-webkit-scrollbar-thumb:hover{background:#a8a8a8;
  border:2px solid transparent;background-clip:content-box}

/* Ссылка «письмо — в Shopify»: одна на заказ, над лентой событий. Отступ
   такой же, как у строк ленты, чтобы она читалась как её заголовок, а не как
   отдельный блок. Вид — общий тихий (`.m9-quiet`): без синевы и без сплошной
   черты, признаки на наведении. */
.tl-mailout{margin:.6rem 0 .2rem}
.tl-mailout .ic{width:14px;height:14px;margin-right:.35rem;vertical-align:-2px}

/* ═══════════════════════════════════════════════════════════════════════════
   НИЧЬЁ — ПОСЕРЕДИНЕ. Разделитель дат и служебные записи.

   🔴 ДОВОД НЕ ВКУСОВОЙ, И ОН РОВНО ТОТ ЖЕ, ЧТО У СТОРОН. В ленте со сторонами
   левый край ЗАНЯТ — там говорит клиент. Дата, прижатая туда же, читается как
   ещё одна запись слева, то есть как чьё-то сообщение. А она ничья: относится
   к обеим сторонам сразу. Середина — единственное место, не принадлежащее
   никому, поэтому Shopify туда её и ставит.

   Правило у нас уже было записано в коде: `record_side` возвращает пустую
   сторону для записей, у которых её нет. Вёрстка просто его не отражала.

   🔴 ЦЕНА НАЗВАНА: слева даты выстраивались в столбик, по которому глаз бежит
   сверху вниз, ища нужный день. Посередине столбик пропадает. Для чтения
   переписки середина лучше, для поиска по датам — левый край; читают чаще,
   чем ищут по датам, поэтому выбор такой. Знать про потерю стоит.

   🔴 БЕЗ ВОЛОСЯНЫХ ЛИНИЙ ПО БОКАМ, И ЭТО ВЫБОР, А НЕ ЗАБЫВЧИВОСТЬ. Мы копируем
   Shopify Inbox, а там дата стоит голым текстом посередине: в узкой колонке
   между облачками она не «повисает в пустоте» — её держат сами облачка сверху
   и снизу. Линии добавили бы третью горизонталь к тем, что уже есть у шапок.
   Если владелец захочет линии, это одна строка: `.m9-feed h3.day{display:flex}`
   плюс два псевдоэлемента с `border-top`.

   🔴 ТОЛЬКО В КОЛОНКЕ ПЕРЕПИСКИ. На карточке заказа сторон нет вовсе, левый
   край там не занят, и столбик дат остаётся полезным — трогать его незачем. */
.m9-feed h3.day{text-align:center;margin:1.1rem 0 .5rem;padding-left:0;
  text-transform:none;letter-spacing:0;font-weight:400}

/* 🔴 СЛУЖЕБНЫЕ ЗАПИСИ БЕЗ СТОРОНЫ — ТУДА ЖЕ, И ПО ТОЙ ЖЕ ПРИЧИНЕ. «Сверка»,
   «синхронизация», «письмо покупателю отправлено» не принадлежат ни клиенту,
   ни нам. Прежде они шли строкой во всю ширину и от этого читались весомее
   любого облачка — самая широкая запись на экране оказывалась самой
   безразличной.

   Заливка у них теперь тоже своя, по виду записи: до этой правки цвет ставился
   только при наличии стороны, и 62 денежных события (условия оплаты, налог
   площадки) оставались бесцветными — не потому, что мы не знали их вида, а
   потому что вёрстка до них не дотягивалась. */
.m9-feed ul.tl li.sys-none{max-width:78%;width:fit-content;
  margin:.35rem auto;text-align:center;border-radius:var(--bubble);
  padding:.3rem .7rem;font-size:12px}
.m9-feed ul.tl li.sys-none .dot{display:none}
.m9-feed ul.tl li.sys-none.tone-system{background:var(--event-ok)}
.m9-feed ul.tl li.sys-none.tone-money{background:var(--money-bg)}
.m9-feed ul.tl li.sys-none.tone-problem{background:var(--event-bad)}

/* ── Поиск по перепискам ──────────────────────────────────────────────────
   🔴 ПОЛЕ ЗАБИРАЕТ ОСТАТОК ШИРИНЫ, А БИРКИ СВОЁ. Иначе при длинном запросе
   поле растянулось бы и вытолкнуло отбор за край строки — а строка одна,
   переносить некуда. */
.m9-search{flex:1 1 auto;min-width:0;display:flex;margin:0}
.m9-search input{width:100%;min-width:0;font:inherit;font-size:12px;
  padding:.2rem .5rem;border:1px solid var(--line);border-radius:99px;
  background:var(--paper);color:var(--fg)}
.m9-search input:focus{outline:2px solid var(--acc);outline-offset:1px;
  border-color:var(--acc)}
/* 🔴 ПОДСВЕТКА — ФОНОМ, А НЕ ЦВЕТОМ ТЕКСТА. Цвет текста в списке уже занят:
   основной у сути, приглушённый у служебного. Взят янтарный из набора записей
   — он на той же ступени светлоты, что и остальные фоны, и не спорит с ними
   яркостью. Своей краски ради подсветки не заводим. */
mark{background:var(--money-bg);color:inherit;border-radius:3px;padding:0 .1em}

/* ═══════════════════════════════════════════════════════════════════════════
   ПОЛОСА ОТВЕТА — ПО ОБРАЗЦУ ВЛАДЕЛЬЦА.

   Устройство снято с `reference/shopify-inbox-reply-bar.png`: белый верх с
   круглым значком канала и строкой ввода, под ним отдельная серая полоса —
   слева значки действий, справа кнопка отправки. Всё вместе в одной рамке со
   скруглением.

   🔴 НАШИ КНОПКИ — НА СЕРОЙ ПОЛОСЕ, А НЕ НА БЕЛОМ. Белый верх принадлежит
   тексту письма; всё, что не текст, живёт ниже. Раньше наши действия стояли
   вперемешку с полем, и полоса не читалась как две части.

   🔴 КНОПКА ОТПРАВКИ ОЖИВАЕТ ОТ ТЕКСТА. Пустое поле — бледная и мёртвая;
   напечатан знак — тёмная. На образце ровно так, и это ответ на вопрос «можно
   ли уже отправлять», данный ДО нажатия. Делается вёрсткой, без скрипта:
   `:placeholder-shown` истинен, пока поле пусто.
   ═══════════════════════════════════════════════════════════════════════ */
.m9-compose{margin:.5rem .9rem .6rem;border:1px solid var(--line);
  border-radius:var(--radius);overflow:hidden;background:var(--paper)}
.m9-composetop{display:flex;align-items:flex-start;gap:.6rem;
  padding:.6rem .7rem;background:var(--paper)}
/* Круглый обведённый значок канала — как на образце. */
.m9-composechan{flex:0 0 auto;display:inline-flex;align-items:center;
  justify-content:center;width:26px;height:26px;border-radius:50%;
  border:1.5px solid var(--fg);color:var(--fg)}
.m9-composechan .ic{width:14px;height:14px}
.m9-composefield{flex:1 1 auto;min-width:0;resize:none;border:0;outline:none;
  font:inherit;font-size:13px;line-height:1.55;color:var(--ink);
  background:transparent;padding:.15rem 0;min-height:1.7rem;max-height:8rem}
.m9-composefield::placeholder{color:var(--dim)}
/* 🔴 ПРИЗНАК «Я ПИШУ СЮДА» НЕСЁТ ВСЯ КАРТОЧКА, А НЕ ПОЛЕ ВНУТРИ НЕЁ. Владелец
   про прежнее: «страшная заквадраченная синяя рамка». Она была двойной бедой:
   вторая рамка внутри карточки — и синяя, а синий у нас закреплён за обведением
   фокуса и больше ни за чем.

   Теперь темнеет ОДИН общий контур со скруглением — верхний этаж и серая полоса
   вместе, как на образце. Своей рамки у поля нет вовсе.

   🔴 ПРО ДОСТУПНОСТЬ, ЧЕСТНО. Обычный приём «синее кольцо только для
   `:focus-visible`» здесь НЕ РАБОТАЕТ: у текстовых полей браузеры считают
   `:focus-visible` истинным и при щелчке мышью, так что кольцо появлялось бы
   ровно там, где владелец его не хочет. Поэтому признак фокуса — потемнение
   всей карточки; оно видно и при переходе клавишей Tab, то есть способ
   работать с клавиатуры сохранён, просто выглядит иначе. */
.m9-compose:focus-within{border-color:var(--fg)}
/* 🔴 ВЕС СЕЛЕКТОРА, А НЕ ПОРЯДОК СТРОК. ТРЕТИЙ РАЗ ЗА ПРОЕКТ, И ВТОРОЙ РАЗ У
   МЕНЯ. Здесь стояло `.m9-composefield:focus{outline:none}` — и оно НЕ
   РАБОТАЛО: общее правило `body.m9-page :focus-visible` весит (0,2,1), а это
   (0,2,0), и синее кольцо выигрывало одним элементом в селекторе. Владелец
   видел «страшную синюю рамку» ровно поэтому, пока я отчитывался, что она
   убрана.

   🔴 И ПРОВЕРКА МОЯ БЫЛА ВИНОВАТА НЕ МЕНЬШЕ: она спрашивала, есть ли в файле
   строка `outline:none`, — строка была. Спрашивать надо ИСХОД: какого цвета
   обводка у поля в фокусе. Теперь это меряется в браузере
   (`test_the_reply_field_has_no_blue_ring_in_focus`).

   Правило ниже перевешивает общее намеренно: `body.m9-page` добавлен ради
   веса, а не ради области. `:focus-visible` назван рядом с `:focus`, потому
   что у поля ввода браузер считает его истинным и при щелчке мышью — то есть
   без него кольцо вернулось бы ровно там, где его не хотят. */
body.m9-page .m9-composefield:focus,
body.m9-page .m9-composefield:focus-visible{outline:none;box-shadow:none}

/* Серая полоса. Тон — ступень «нажатия» из лестницы, самый тихий серый, какой
   у нас есть: полоса не должна спорить с облачками переписки над ней. */
/* 🔴 ПЕРЕНОС РАЗРЕШЁН ПОЛОСЕ, А НЕ РЯДУ ЗНАЧКОВ, и это перестановка, а не
   новое поведение. Замер узкой колонки (ручка списка на пределе, полосе 288):
   пять значков просят 150, «Отправить письмо» — 142, вместе с зазором 298. Не
   помещалось и ДО пункта 50, и переносился при этом ряд значков — он шёл в две
   строки уже сейчас. Разрывать надо не однородную группу: пусть вниз уезжает
   кнопка отправки целиком, а пять значков остаются одной строкой. Высота полосы
   в этом случае та же, что была. */
.m9-composebar{display:flex;align-items:center;gap:.4rem;flex-wrap:wrap;
  padding:.4rem .6rem;background:var(--pressed);
  border-top:1px solid var(--line)}
/* 🔴 `flex:1 1 0` — ЧТОБЫ РАСКРЫТАЯ ПОДПИСЬ НЕ ТРЕБОВАЛА СЕБЕ МЕСТА, А
   ДОВОЛЬСТВОВАЛАСЬ ТЕМ, ЧТО ЕСТЬ. С `flex-basis:auto` ряд просил столько,
   сколько в нём написано, и при средней ширине колонки замер поймал прыжок:
   наводишь на «Ответ черновиком» — ряд запрашивает 373 вместо 225, места на
   полосе не хватает, и «Отправить письмо» уезжает строкой ниже. Кнопка
   отправки прыгала от наведения на чужой значок.

   Нулевой базис снимает запрос, а пол в 150 пикселей (пять кнопок по 28 плюс
   четыре зазора) оставляет перенос там, где он ЕДИНСТВЕННЫЙ выход: в узкой
   колонке значки и «Отправить письмо» не помещаются рядом ни при каком
   раскрытии. Добавится шестой значок — пол станет мал, и это увидит проверка
   на срезание ряда, а не глаз владельца. */
.m9-composebar .m9-acts{display:flex;align-items:center;gap:.15rem;
  flex:1 1 0;min-width:150px;flex-wrap:nowrap}
/* Числа те же, что в шапке, и по той же причине (пункт 50). Значок здесь 17,
   поэтому и поля другие: 5.5+17+5.5=28 — покой не отличить от прежнего. */
.m9-composebar .m9-act{display:inline-flex;align-items:center;
  justify-content:flex-start;min-width:28px;max-width:100%;height:28px;
  padding:0 5.5px;border:0;border-radius:8px;cursor:pointer;flex:0 1 auto;
  background:transparent;color:var(--fg)}
.m9-composebar .m9-act:hover{background:rgba(0,0,0,.06)}
.m9-composebar .m9-act .ic{width:17px;height:17px;flex:0 0 auto}
/* 🔴 ЭЛЕМЕНТАМИ РЯДА ЯВЛЯЮТСЯ ФОРМЫ, А НЕ КНОПКИ, И ЭТО ГЛАВНАЯ ЛОВУШКА ПУНКТА
   50. `min-width` у кнопки не удерживает ничего, когда сжимают форму вокруг
   неё, — и наоборот, форма не сжимается тогда, когда сжаться нужно.

   🔴 ЧИСЛО 28 ЗДЕСЬ ПОИМЁННО, А НЕ `auto`, И ВОТ ПОЧЕМУ. Замер узкой колонки:
   из пяти значков раскрывались как надо три, а два — те самые, что завёрнуты в
   форму, — не сжимались вовсе, и ряд переполнялся на 57 пикселей (258 против
   201). У формы `min-width:auto` вычислился в её РАСКРЫТУЮ ширину, 139, вместо
   ожидаемых 28: «сжимайся не мельче содержимого» на деле означало «не
   сжимайся». Названное число снимает вопрос в обе стороны — собранная форма
   (28) не жмётся, потому что уже упёрлась в пол, а раскрытая жмётся до него же
   и ни пикселем ниже, так что кнопке внутри всегда есть где стоять.

   Три остальных значка беды не знали: они лежат в ряду напрямую, и их держал
   собственный `min-width:28px`. Поэтому болезнь и выглядела выборочной. */
.m9-actform{display:inline-flex;margin:0;flex:0 1 auto;min-width:28px;
  max-width:100%}

/* 🔴 ВКЛЮЧЁННОЕ СОСТОЯНИЕ — ЗАЛИВКОЙ, А НЕ ЦВЕТОМ ЗНАЧКА. Кнопка блокировки
   единственная в полосе, у которой состояние «уже сделано» держится дольше
   одного нажатия, и её надо отличать в покое. Красным не красится намеренно:
   заблокированный адрес — это НАШЕ РЕШЕНИЕ, а не беда, а красный в панели
   занят проблемными записями (правило пяти тонов). */
.m9-composebar .m9-act-on{background:rgba(0,0,0,.10)}
.m9-composebar .m9-act-on:hover{background:rgba(0,0,0,.14)}
/* Отказ вместо кнопки: у чата адреса нет, и блокировать нечего. Тише кнопок —
   это не действие, а объяснение, почему действия здесь нет. */
.m9-act-none{font-size:11px;color:var(--dim);white-space:nowrap;
  padding:0 .25rem;cursor:default}
/* Разделитель: действия НАД ПЕРЕПИСКОЙ — не про письмо, которое сейчас пишут. */
.m9-actsep{width:1px;height:18px;background:var(--line);margin:0 .25rem}

/* ── ПУНКТ 50: ЗНАЧОК НАЗЫВАЕТ СЕБЯ, КОГДА НА НЕГО СМОТРЯТ ────────────────
   Владелец дословно: «Иконок много, и они начинают путаться, что есть что.
   Наводишь на иконку — иконки как бы разъезжаются в стороны, и появляется
   надпись, что эта иконка делает».

   🔴 ПОДПИСЬ ЗДЕСЬ — ТА ЖЕ САМАЯ, ЧТО ЧИТАЕТ ЭКРАННЫЙ ДИКТОР, а не второй
   текст рядом. Прежде она лежала в `.visually-hidden` и была спрятана
   насовсем; теперь прячется шириной. Двух источников одного имени быть не
   должно: они разойдутся при первой же правке, и разойдутся молча.

   🔴 РАСКРЫТИЕ — УКРАШЕНИЕ, А НЕ ЕДИНСТВЕННЫЙ ПУТЬ К СМЫСЛУ. На касании
   наведения нет вовсе, поэтому `title` остаётся у каждой кнопки и держит
   полный текст — в том числе тогда, когда подпись обрезана многоточием.

   🔴 ДВИЖЕНИЕ ОДНО: ШИРИНА. `max-width` и поле слева — обе величины
   горизонтальные, и обе идут одним переходом. Ни цвет, ни размер значка, ни
   прозрачность не участвуют: прячет подпись `overflow`, а не бледность. */
.m9-act-say{display:block;max-width:0;padding-left:0;overflow:hidden;
  white-space:nowrap;text-overflow:ellipsis;font-size:12px;
  flex:0 1 auto;min-width:0;
  transition:max-width .18s ease, padding-left .18s ease}
/* Клавиатура наравне с мышью: `:focus-visible` — это и есть обход табуляцией.
   Он же и только он, а не `:focus`: щелчок мышью не должен оставлять на
   кнопке раскрытую подпись после того, как палец ушёл. */
.m9-act:hover .m9-act-say,
.m9-act:focus-visible .m9-act-say{max-width:12rem;padding-left:.3rem}
/* 🔴 ПЕРВОЕ В ПАНЕЛИ ПРАВИЛО ПРО УМЕНЬШЕННОЕ ДВИЖЕНИЕ. Подпись появляется
   сразу и целиком: у того, кто просил систему не двигать ничем, разъезжание
   значков — не украшение, а помеха. Смысл при этом не теряется: раскрытие
   остаётся, уходит только его плавность. */
@media (prefers-reduced-motion: reduce){
  .m9-act-say{transition:none}
}

/* 🔴 МЁРТВАЯ, ПОКА НЕ НАПЕЧАТАНО. `:placeholder-shown` истинен ровно тогда,
   когда поле пусто; `:has()` переносит это состояние на соседнюю кнопку.
   Скрипта не нужно — а значит и во вставленном через `innerHTML` фрагменте
   работает без единой оговорки. */
.m9-send{flex:0 0 auto;font:inherit;font-size:12px;font-weight:600;
  padding:.4rem .85rem;border:1px solid transparent;border-radius:8px;
  background:var(--fg);color:#fff;cursor:pointer;white-space:nowrap}
.m9-send:hover{background:#000}
.m9-compose:has(.m9-composefield:placeholder-shown) .m9-send{
  background:#e3e3e3;color:#9a9a9a;cursor:default}
.m9-compose:has(.m9-composefield:placeholder-shown) .m9-send:hover{background:#e3e3e3}
.m9-compose-note{margin:.35rem .9rem 0;font-size:12px;color:var(--dim)}

/* 🔴 НЕПРОЧИТАННОЕ — ВЕСОМ, А НЕ ЗНАЧКОМ И НЕ ЦВЕТОМ. Значков в строке списка
   уже два (состояние переписки и вложения), цвет занят видом записи, а жирное
   начертание у непрочитанного письма — приём, знакомый по любому почтовому
   клиенту, и объяснять его не надо. Пометка личная, поэтому и признак виден
   только тому, кто её поставил. */
.m9-who.m9-unread{font-weight:700}

/* 🔴 «СОВПАЛО, НО НЕ ЗДЕСЬ» — ПРИГЛУШЁННО, НО НЕ НЕЗАМЕТНО. Это не часть
   письма, а наша подсказка, поэтому мельче и тише текста; но она отвечает на
   вопрос «почему это письмо в выдаче», а вопрос настоящий — значит и прятать
   её нельзя. */
.m9-foundelse{margin:.3rem 0 0;font-size:12px;color:var(--dim)}
.m9-foundelse::before{content:"";display:inline-block;width:.5rem;height:.5rem;
  margin-right:.35rem;border-radius:2px;background:var(--money-bg);
  border:1px solid var(--line);vertical-align:baseline}

/* ═══════════════════════════════════════════════════════════════════════════
   ОКНО ПОВЕРХ СТРАНИЦЫ. Один приём на панель, без скрипта.

   🔴 ЗАЧЕМ ОНО ЗАВЕДЕНО. Владелец про прежнюю раскрывашку: «выпадающее вниз
   раскрывающееся меню вообще не в нашем стиле, оно из дизайна 90-х». Помимо
   вида у неё был и порок устройства: `<details>` в потоке раздвигает карточку
   при раскрытии — то же дёрганье, из-за которого мы отказались от растущей
   вглубь шапки списка.

   Держится на скрытом переключателе, как и раскрывашки отбора: два разных
   способа делать одно и то же разошлись бы при первой правке. */
.m9-dialog{display:none}
.m9-moretoggle:checked ~ .m9-dialog{display:block;position:fixed;inset:0;
  z-index:50}
.m9-dialog-veil{position:absolute;inset:0;background:rgba(0,0,0,.32);
  cursor:pointer}
.m9-dialog-box{position:relative;max-width:520px;margin:12vh auto 0;
  background:var(--paper);border-radius:var(--radius);
  box-shadow:0 12px 40px rgba(0,0,0,.22);overflow:hidden}
.m9-dialog-head{display:flex;align-items:center;justify-content:space-between;
  padding:.7rem .9rem;border-bottom:1px solid var(--line);font-size:14px}
.m9-dialog-x{cursor:pointer;color:var(--dim);font-size:18px;line-height:1;
  padding:0 .25rem}
.m9-dialog-x:hover{color:var(--fg)}
.m9-dialog form{padding:.9rem}
.m9-dialog-foot{display:flex;justify-content:flex-end;gap:.5rem;
  margin-top:1rem;padding-top:.8rem;border-top:1px solid var(--line)}

/* Поля — наши: подпись сверху, скругление, наш фокус. Голых браузерных полей
   на экранах панели нет, и окно исключением не становится. */
.m9-field{display:block;margin-bottom:.7rem}
.m9-field-label{display:block;font-size:12px;color:var(--dim);
  margin-bottom:.25rem}
.m9-field input{width:100%;font:inherit;font-size:13px;padding:.45rem .6rem;
  border:1px solid var(--line);border-radius:8px;background:var(--paper);
  color:var(--fg)}
.m9-field input:focus{outline:2px solid var(--acc);outline-offset:1px;
  border-color:var(--acc)}
/* 🔴 СТРЕЛКИ БРАУЗЕРНОГО КАЛЕНДАРЯ УБРАНЫ, а сам `type="date"` оставлен:
   разбор даты руками — классический источник ошибок («05.06» это май или
   июнь?), а отметка о вручении идёт в журнал и в расчёт сроков. Цена названа:
   поле остаётся браузерным внутри, нашим снаружи. */
.m9-field input[type="date"]::-webkit-calendar-picker-indicator{opacity:.35}
.m9-field input[type="date"]::-webkit-inner-spin-button{display:none}

/* Две кнопки одного семейства: светлая — отступ, тёмная — действие. Те же, что
   на образце Shopify, и те же, что у полосы ответа. */
.cardacts{display:flex;justify-content:flex-end;gap:.5rem;margin:.6rem 0 0}
.btn-soft{display:inline-flex;align-items:center;font-size:12px;font-weight:600;
  padding:.4rem .85rem;border:1px solid var(--line);border-radius:8px;
  background:var(--paper);color:var(--fg);cursor:pointer}
.btn-soft:hover{border-color:#8a8a8a}
.btn-dark{display:inline-flex;align-items:center;font:inherit;font-size:12px;
  font-weight:600;padding:.4rem .85rem;border:1px solid var(--fg);
  border-radius:8px;background:var(--fg);color:#fff;cursor:pointer}
.btn-dark:hover{background:#000;border-color:#000}

/* Подзаголовок группы в левом меню: тише названия раздела, но с ним заодно. */
.railhead-sub{margin:.7rem 0 .1rem;padding-left:calc(16px + .55rem);
  font-size:11px;text-transform:uppercase;letter-spacing:.04em;color:var(--dim)}
/* 🔴 КЛАСС СВОЙ, НЕ `cur`, И ЭТО НЕ КОСМЕТИКА. `cur` означает «вы здесь» —
   выделенную ПАПКУ, и она ровно одна; на это стоит проверка, требующая одного
   выделения на экран. Отборы складываются, их бывает несколько разом, и,
   надев чужой класс, они сломали бы и проверку, и смысл: «вы здесь» в четырёх
   местах сразу. Класс остаётся свой, а ВЫГЛЯДЕТЬ он теперь должен иначе.

   🔴 ТОЧКА УБРАНА, ПОТОМУ ЧТО ЕЁ НЕ ВИДНО. Слова владельца: «выбранная опция
   показывается чёрным кружочком — это неочевидно, плохо заметно, что выбрано.
   Просто чёрная точка перед словом не бросается в глаза». Пять пикселей в
   начале строки — самый слабый признак из возможных, и он спорил с плашкой
   папки над собой: два разных языка выделения в одном меню.

   🔴 ТЕПЕРЬ ЭТО ПЛАШКА, КАК У ПАПКИ, НО ТИШЕ, КОРОЧЕ И СО СДВИГОМ — то есть
   подпункт виден ПО ФОРМЕ, а не только по отступу текста:
     тише  — `--bubble-bg` (#f4f4f4) против `--pick-menu` (#fafafa) у папки:
             две ступени той же лестницы, новый цвет не заводится;
     короче и со сдвигом — плашка начинается под текстом (`margin-left`), а не
             у края панели, поэтому она заметно уже плашки папки.

   🔴 ЗАМЕР КОНТРАСТА, И ОН ЧЕСТНО ГОВОРИТ О ПРЕДЕЛЕ ЭТОГО ПРИЁМА.
   На фоне панели (#ebebeb): плашка папки 1.14:1, плашка подпункта 1.08:1.
   Ни та, ни другая не дотягивают до 3:1 — и не могут: вся лестница светлых
   тонов лежит в коридоре 1.05–1.19:1. Значит подсветка НЕ ДЕРЖИТСЯ НА ЦВЕТЕ
   ни у папки, ни здесь, и второй признак обязателен. У папки это жирное
   начертание и тень-кольцо; у подпункта — жирное начертание и ФОРМА (короче,
   сдвинута). Оба признака нецветовые, поэтому различимы и при цветовой
   слепоте: они про светлоту, вес и положение, а не про оттенок.
   Текст на плашке: #303030 на #f4f4f4 — 12.0:1 при нужных 4.5:1. */
.subs-filter a.pick{font-weight:600;color:var(--fg);
  background:var(--bubble-bg);border-radius:8px;
  /* Сдвиг и укорочение: плашка начинается там, где начинается текст. */
  margin-left:1.6rem;padding-left:.5rem}
.subs-filter a.pick:hover{background:#e6e6e6}

/* 🔴 ДОРОЖКА ПОЛОСЫ ПРОКРУТКИ — БЕЛАЯ, А НЕ ПРОЗРАЧНАЯ. `transparent`
   пропускает фон панели (бежеватый `--rail`), и справа у списка шла бежевая
   вертикальная полоса. Владелец доказал, что это дорожка, а не граница
   колонки: при пустом отборе, когда прокручивать нечего, она исчезала и
   оставалась чистая линия. Теперь дорожка того же цвета, что фон списка, и
   видна только ручка. */
body.m9-page ::-webkit-scrollbar-track{background:var(--paper)}
body.m9-page .m9-list{scrollbar-color:#c9c9c9 var(--paper)}

/* Отклик будущей кнопки: пока молчит — не занимает места вовсе. */
.m9-compose-note{margin:.35rem .9rem .1rem;font-size:12px;color:var(--dim)}
.m9-compose-note:empty{display:none}

/* 🔴 ПРОКРУЧИВАЕТСЯ СПИСОК, А НЕ КОЛОНКА. Шапка вышла из прокрутки, и вместе с
   ней ушёл разрыв: раньше полоса прокрутки резервировала 10px справа ВНУТРИ
   колонки, шапка становилась на эти 10px короче, и её подчёркивание не
   доходило до вертикали. Ползунок при этом ездил вверх под неподвижную шапку —
   движущаяся деталь под неподвижной читается как поломка.
   Приём тот же, что у колонки переписки: снаружи `hidden`, внутри один
   прокручиваемый узел. Вторая полоса не появляется. */
body.m9-page .m9-list{overflow:hidden}
.m9-listbody{flex:1 1 auto;min-height:0;overflow-y:auto;overscroll-behavior:contain}
.m9-listhead{position:static}

/* ═══════════════════════════════════════════════════════════════════════════
   ШКАЛА ВРЕМЕНИ ЗАКАЗА (пункт 26): сборка → отправка → доставка.

   🔴 ЧИСЛО ДНЕЙ ВИДНО ВСЕГДА, ЦВЕТ — НЕ ЕДИНСТВЕННЫЙ ПРИЗНАК. Требование
   владельца дословно, и оно определило устройство: у отрезка сперва ЧИСЛО
   крупным, потом слово («в срок», «дольше обычного»), и только потом заливка.
   Отними цвет — шкала читается; отними числа — останется картинка.

   🔴 ЦВЕТА — ТЕ ЖЕ ТРИ, ЧТО У ЗАПИСЕЙ В ЛЕНТЕ, и новых не заводится: салатовый
   `--event-ok`, жёлтый `--money-bg`, красноватый `--event-bad`. Пятый тон
   («деньги») здесь означает «дольше обычного» — не деньги, но ту же ступень
   тревоги, и разводить два жёлтых на экране было бы хуже.

   🔴 «НОРМЫ НЕТ» — ЭТО ОТСУТСТВИЕ ЗАЛИВКИ, А НЕ СЕРАЯ ЗАЛИВКА. Серый читался
   бы как «плохо, но тихо»; отсутствие читается как «не знаем», и слово рядом
   говорит то же самое.
   ═══════════════════════════════════════════════════════════════════════ */
.m9-tl{display:flex;align-items:stretch;gap:0;margin:.35rem 0 0;
  border:1px solid var(--line);border-radius:8px;overflow:hidden}
.m9-tl-leg{flex:1 1 0;min-width:0;padding:.45rem .55rem;display:flex;
  flex-direction:column;gap:.1rem}
.m9-tl-days{font-size:17px;font-weight:700;line-height:1.1;white-space:nowrap}
.m9-tl-unit{font-size:11px;font-weight:400;color:var(--dim)}
.m9-tl-what{font-size:11px;letter-spacing:.06em;text-transform:uppercase;
  color:#8a8a8a;font-weight:600}
.m9-tl-say{font-size:11px;color:var(--dim);overflow-wrap:anywhere}
.m9-tl-ok{background:var(--event-ok)}
.m9-tl-slow{background:var(--money-bg)}
.m9-tl-late{background:var(--event-bad)}
/* Нормы нет — заливки нет. Осталась рамка отрезка и слова внутри. */
.m9-tl-none{background:transparent}
/* 🔴 ГРАНИЦА — ЭТО МОМЕНТ ОТПРАВКИ, И ОНА ПОДПИСАНА ДАТОЙ. Пустой промежуток
   читался бы как «между отрезками ничего не происходило», а там ровно одно
   событие, и оно единственное точно известное на всей шкале. */
.m9-tl-mark{flex:0 0 auto;display:flex;align-items:center;justify-content:center;
  padding:0 .3rem;border-left:1px solid var(--fg);border-right:1px solid var(--line);
  background:var(--surface);font-size:10px;color:var(--dim);white-space:nowrap}
/* Идущий прямо сейчас отрезок — в полоску: он ещё не кончился, и число в нём
   растёт. Признак не цветом, а фактурой: цвет уже занят сравнением с нормой. */
.m9-tl-run{background-image:repeating-linear-gradient(135deg,
  rgba(255,255,255,.45) 0 6px,transparent 6px 12px)}
