/* СИСТЕМА ВИДА МИНИ-ПРИЛОЖЕНИЯ. Редакция 2 — по его референсам 26.08.
 *
 * 🔴 ЧТО СНЯТО С РЕФЕРЕНСОВ 1:1 И ПОЧЕМУ ИМЕННО ЭТО.
 *
 * Он забраковал прежний вид словом «слоп» и приложил два банковских
 * приложения. Разбор дал восемь приёмов, и каждый здесь исполнен:
 *
 *   1. фон — ЧИСТЫЙ ЧЁРНЫЙ. Не «почти чёрный с уклоном»: у обоих #000;
 *   2. главный блок — КАРТОЧКА, ЗАЛИТАЯ АКЦЕНТОМ, текст в ней чёрный;
 *   3. внутри неё — ЧЁРНЫЕ ПИЛЮЛИ со значком в круге, зеркально;
 *   4. действия — ШИРОКИЕ ПЛАШКИ, подпись ПОД плашкой, а не кружки;
 *   5. активная вкладка — ЗАЛИТЫЙ КРУГ, а не подкрашенный значок;
 *   6. строка списка — СПЛОШНОЙ цветной кружок слева, шеврон справа;
 *   7. столбчатый график с выделенным столбцом и биркой над ним;
 *   8. имя в шапке КРУПНО и ЖИРНО, приветствие мелко над ним.
 *
 * 🔴 ЧЕГО У НИХ НЕТ И ПОТОМУ НЕТ ЗДЕСЬ: градиентов, свечения, обводок 1px
 * вокруг карточек. Слои разделяются ТОЛЬКО светлотой. Именно эти три вещи
 * он и назвал «видно работу ИИ» — и был прав: они появляются сами собой,
 * когда вид сочиняют, а не снимают с образца.
 *
 * 🔴 ОРАНЖЕВЫЙ ВЗЯТ ИЗ ЗНАКА: #FF6E40, а не прежний #FF6A2C. Знак — это то,
 * что нельзя подгонять под палитру; подгонять надо палитру под знак.
 */

/* ── ШРИФТ ────────────────────────────────────────────────────────────────
   🔴 ЛЕЖИТ У НАС, А НЕ ГРУЗИТСЯ С GOOGLE FONTS.

   Три довода, и каждый сам по себе решающий:
     1. приложение открывается ВНУТРИ Telegram, часто на мобильном интернете
        в дороге. Лишний домен — это лишний DNS, лишний TLS и шанс, что
        текст поедет системным шрифтом на пол-секунды (FOUT);
     2. `content-security-policy` у нас закрыт на свой домен. Пускать туда
        чужой хост ради шрифта значит расширять дыру, через которую потом
        уедет что-нибудь ещё;
     3. Google Fonts видит IP каждого нашего человека. Нам это не нужно.

   Взяты только две подтаблицы — кириллица и латиница, 49,6 КБ вместе.
   Вариативный: один файл на все веса от 400 до 800, вместо пяти файлов.

   🔴 И РАЗМЕТКА НЕ ЗНАЕТ ПРО ШРИФТ. Ни одного `<link>`: правило
   живёт там же, где палитра, — иначе следующий экран забудут подписать. */
@font-face {
  font-family: "Onest";
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url("/app/fonts/onest-cyrillic.woff2?v=0b4bfaa142d9") format("woff2");
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: "Onest";
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url("/app/fonts/onest-latin.woff2?v=44aca66be9fd") format("woff2");
  unicode-range:
    U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212,
    U+2215, U+FEFF, U+FFFD;
}

:root {
  /* ── Ступени подложки. Разделяются светлотой, не тенью и не обводкой. */
  --чёрный: #000000;
  --низ: #000000;
  --слой-1: #131315; /* карточка */
  --слой-2: #1d1d20; /* плашка, поле ввода, столбец графика */
  --слой-3: #2a2a2e; /* тихий кружок, невыбранный переключатель */

  /* 🔴 Деньги и действие. Один цвет, одна роль, ПЛОСКИЙ — из знака. */
  --деньги: #ff6e40;
  --на-деньгах: #140600;

  /* Состояния заявки. Ступень 400: ступень 600 (#dc2626, #22c55e) считана
     под СВЕТЛЫЙ фон и на чёрном темнеет до бурого и болотного — это и было
     то, что он назвал «старческими цветами». */
  --ждёт: #a78bfa;
  --зачтено: #34d399;
  --идёт: #60a5fa;
  --отказ: #fb7185;

  --текст: #ffffff;
  --текст-2: #a7a7b0;
  /* 🔴 ПОДНЯТ ДО НОРМЫ ЧИТАЕМОСТИ (§249, прицел П6 описи §38).
     Было `#6e6e78` — контраст 3,68 к карточке и 3,33 к плашке при норме
     WCAG AA 4,5:1 для обычного текста. А стоит он 62 раза и на размерах
     11–14 px, то есть это именно обычный текст, а не крупный заголовок,
     которому положено послабление до 3:1.
     Стало `#84848e`: 5,01 к карточке, 4,54 к плашке. Тише основного текста
     он быть не перестал — `--текст-2` даёт 7,77, и разрыв между ними
     сохранён. */
  --текст-тихо: #84848e;

  --р-карты: 24px;
  --р-плашки: 18px;
  --р-пилюли: 999px;

  /* Высота плавающей панели вместе с её отступом от низа. Всё, что считает
     запас снизу, обязано считать ЭТО, а не голую высоту рейки. */
  --низ-панели: 82px;

  /* Меню действий над сообщением (§161) живёт в общем `/common/menu.js` и
     берёт цвета отсюда: у приложения ступени зовутся `--слой-2`, у админки —
     `--поверхность-выше`, общего имени нет. Шесть строк дешевле, чем
     переписанная ради меню тема. */
  --меню-фон: var(--слой-2);
  --меню-обводка: rgba(255, 255, 255, 0.08);
  --меню-текст: var(--текст);
  --меню-текст-тихо: var(--текст-тихо);
  --меню-выбор: var(--слой-3);
  --меню-обвод-фокуса: var(--деньги);
  --меню-опасно: var(--отказ);

  /* Плееры и просмотр (§155) живут в общем `/common/media.js`. Тем же
     приёмом, что у меню: модуль знает имена, а значения даёт тема. */
  --мсвой: var(--деньги);
  --мна-своём: var(--на-деньгах);
  --мподложка: rgba(0, 0, 0, 0.24);
}

* {
  box-sizing: border-box;
  -webkit-tap-highlight-color: transparent;
}

html,
body {
  margin: 0;
  padding: 0;
  background: var(--чёрный);
  color: var(--текст);
  font-family:
    "Onest",
    -apple-system,
    BlinkMacSystemFont,
    "Segoe UI",
    Roboto,
    sans-serif;
  font-size: 15px;
  line-height: 1.45;
  overscroll-behavior-y: none;
  -webkit-font-smoothing: antialiased;
  /* 🔴 iOS сам увеличивает текст при повороте в альбом, если не сказать
     обратного. `100%` — это «не трогай», а НЕ «запрети приближать»:
     значение `none` отняло бы у человека возможность увеличить текст, а
     нам нужно ровно противоположное — чтобы размер не менялся САМ. */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

/* 🔴 ВТОРАЯ ПРИЧИНА ЗУМА, помимо мелкого шрифта в полях: ДВОЙНОЕ КАСАНИЕ.
   iOS приближает страницу, когда по одному месту стукнули дважды подряд, —
   а по кнопке в приложении стучат дважды постоянно, когда ответ идёт
   медленно и кажется, что нажатие не прошло. Человек хотел повторить
   действие, а получил приближённый экран.

   `manipulation` = «прокрутка и щипок можно, двойное касание — нет».
   То есть увеличить страницу по-прежнему МОЖНО щипком, и это важно: у
   `user-scalable=no` отнимается и он тоже, а тут ничего не отнимается.

   Ставим на органы управления, а не на всю страницу нарочно: двойное
   касание по ТЕКСТУ — законный способ его увеличить, и его мы оставляем. */
button,
a,
input,
textarea,
select,
label,
summary,
[role="button"] {
  touch-action: manipulation;
}

/* 🔴 ТАБЛИЧНЫЕ ЦИФРЫ ВЕЗДЕ: на каждом экране столбцы сумм, и при разной
   ширине цифр столбец дёргается на каждом обновлении (§19.3). */
body {
  font-variant-numeric: tabular-nums;
}

/* ── ЛИПКАЯ ШАПКА ────────────────────────────────────────────────────────
   Появляется, когда порог ушёл вверх. Показ переключает наблюдатель
   пересечения — без обработчика прокрутки, то есть без работы на кадр. */
.профиль-порог {
  position: absolute;
  top: 96px;
  height: 1px;
  width: 1px;
  pointer-events: none;
}
.профиль-липкая {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  justify-content: center;
  height: calc(52px + env(safe-area-inset-top, 0px));
  padding-top: env(safe-area-inset-top, 0px);
  font-weight: 650;
  font-size: 16px;
  background: color-mix(in srgb, var(--низ) 82%, transparent);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  opacity: 0;
  transform: translateY(-6px);
  transition:
    opacity 0.18s ease,
    transform 0.18s ease;
  pointer-events: none;
}
.профиль-липкая.видна {
  opacity: 1;
  transform: none;
}
@media (prefers-reduced-motion: reduce) {
  .профиль-липкая {
    transition: none;
  }
}

/* ── ПОЛОСА ИТОГОВ: главное число крупно, спутники мельче ──────────────── */
/* ── ИТОГ: ГЛАВНОЕ ЧИСЛО СВЕРХУ, СПУТНИКИ ПОД ЧЕРТОЙ ───────────────────

   🔴 ПЕРВАЯ РЕДАКЦИЯ ЛОМАЛАСЬ РОВНО ТАК, КАК ОН И СКАЗАЛ.

   Его слова по снимку: «$1 929.30» переносилось на две строки — «$1» сверху,
   «929.30» снизу. Причина: главное число и два спутника стояли В ОДНОМ РЯДУ,
   и на 390 пикселях ряду не хватало ширины. Сумма растёт вместе с человеком,
   то есть блок ломался бы у самых заработавших — у тех, кому он важнее всех.

   Устройство теперь такое, что сломаться нечему:

   • главное число занимает ВСЮ ширину и стоит на своей строке;
   • `white-space: nowrap` запрещает перенос прямо, а не надеется на место;
   • `clamp` сжимает кегль на узком экране вместо переноса;
   • спутники уходят вниз, под черту, в две равные колонки — ширина им
     теперь не конкурент. */
.итог-полоса {
  padding: 16px;
  margin: 0 0 4px;
  background: var(--слой-1);
  border-radius: var(--р-карты);
}
.итог-главное {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.итог-подпись {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--текст-тихо);
}
.итог-число {
  font-size: clamp(28px, 9vw, 36px);
  font-weight: 700;
  letter-spacing: -0.03em;
  line-height: 1.1;
  color: var(--деньги);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.итог-спутники {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
  margin-top: 14px;
  padding-top: 14px;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06);
}
.итог-спутники div {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.итог-спутники b {
  font-size: 18px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.итог-спутники small {
  margin-top: 1px;
  font-size: 12px;
  line-height: 1.3;
  color: var(--текст-тихо);
}

/* ── ГРУППА-СПИСОК ───────────────────────────────────────────────────── */
/* 🔴 ВОЗДУХ МЕЖДУ ГРУППАМИ — ЕГО ПРЕТЕНЗИЯ, И ОНА СПРАВЕДЛИВА.

   Его слова: «блоки все слипшиеся без отступов, бред просто». Было 20 px
   сверху у заголовка при 8 px снизу — то есть между дном одной группы и
   верхом следующей набегало 28 px, из которых половину съедала строка
   самого заголовка. Группы читались как одна длинная лента.

   Три числа теперь работают вместе:
   • 28 px до заголовка — расстояние, на котором глаз видит РАЗРЫВ, а не шов;
   • 10 px после — заголовок принадлежит СВОЕЙ группе, а не предыдущей, и
     ближе к ней, чем к чужой. Иначе подпись читается как хвост верхнего;
   • 4 px по бокам — заголовок стоит чуть внутрь от края карточки, как на
     референсе, а не заподлицо. */
.группа-имя {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin: 28px 4px 10px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--текст-тихо);
}
/* Первый заголовок на экране не отталкивается от пустоты. */
.группа-имя:first-of-type {
  margin-top: 18px;
}
/* Правило `.группа-право .ссылка` снесено (§94): разметки с этим классом
   нет ни одной, а `.ссылка` уходит из проекта целиком. */
/* Счёт справа в заголовке — не кнопка, поэтому и не выглядит кнопкой.
   Одинаковый вид у нажимаемого и ненажимаемого — это способ научить
   человека не верить ни тому ни другому. */
.группа-счёт {
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--текст-тихо);
}
.группа {
  background: var(--слой-1);
  border-radius: var(--р-карты);
  overflow: hidden;
}
/* Две группы подряд без заголовка между ними (так бывает у пустого свода)
   не слипаются. */
.группа + .группа {
  margin-top: 12px;
}

/* 🔴 СТРОКЕ НУЖЕН ВОЗДУХ ВНУТРИ, А НЕ ТОЛЬКО ВЫСОТА.

   Было `padding: 12px 14px` при высоте 52 — и строка с подписью («Созревает
   · будут доступны 28 августа») упиралась текстом в собственные края.
   16 px по бокам ставит содержимое на ту же вертикаль, что и заголовок
   группы, а 14 сверху и снизу дают двум строкам текста дышать. */
.строка {
  display: flex;
  align-items: center;
  gap: 13px;
  width: 100%;
  padding: 14px 16px;
  background: none;
  border: 0;
  color: inherit;
  font: inherit;
  text-align: left;
  /* 🔴 56 px — не «красиво». Нижний предел касания 44, но строка списка
     здесь главный орган управления, и промах по ней стоит человеку
     захода. */
  min-height: 56px;
}
/* 🔴 ЧЕРТА НАЧИНАЕТСЯ ТАМ, ГДЕ НАЧИНАЕТСЯ ТЕКСТ, — приём референса.

   Линия во всю ширину режет карточку на клетки и возвращает нас к таблице.
   Отступ слева на ширину плитки делает её разделителем ВНУТРИ одного
   блока: глаз читает список как целое, а не как строки в сетке.

   И только МЕЖДУ строками: линия под последней превращает низ группы в
   обрыв, а на референсе группы заканчиваются мягко. */
.строка + .строка::before {
  content: "";
  position: absolute;
  left: 59px;
  right: 0;
  top: 0;
  height: 1px;
  background: rgba(255, 255, 255, 0.07);
}
.строка {
  position: relative;
}
.строка.ведёт {
  cursor: pointer;
}
.строка.ведёт:active {
  background: var(--слой-2);
}
.строка.ведёт:focus-visible {
  outline: 2px solid var(--деньги);
  outline-offset: -2px;
}

/* Плитка — квадрат со скруглением, как на референсе, а не круг: круги у нас
   уже заняты состояниями заявки, и путать два словаря нельзя. */
.плитка {
  flex: none;
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: 9px;
  color: var(--на-деньгах);
}
.плитка svg {
  width: 17px;
  height: 17px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.1;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.плитка.п-зачтено {
  background: var(--зачтено);
}
.плитка.п-ждёт {
  background: var(--ждёт);
}
.плитка.п-идёт {
  background: var(--идёт);
}
.плитка.п-отказ {
  background: var(--отказ);
}
.плитка.п-деньги {
  background: var(--деньги);
}
.плитка.п-тихо {
  background: var(--слой-3);
  color: var(--текст-2);
}

.строка .имя {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  font-size: 16px;
}
.строка .имя small {
  margin-top: 1px;
  font-size: 12.5px;
  line-height: 1.35;
  color: var(--текст-тихо);
}
.строка .знач {
  flex: none;
  font-size: 16px;
  font-weight: 600;
  color: var(--текст-2);
  font-variant-numeric: tabular-nums;
}
.строка .шеврон {
  flex: none;
  display: grid;
  place-items: center;
  color: var(--текст-тихо);
}
.строка .шеврон svg {
  width: 15px;
  height: 15px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* Распорка вместо шеврона: держит правый край столбца значений на одной
   линии у всех строк. Ширина ровно та же, что у настоящего шеврона. */
.строка .шеврон.пусто {
  width: 15px;
}
/* Невзятая веха: гаснет строка целиком, а не одна плитка. Полутон — это
   «пока нет», а не «сломано»; для «сломано» у нас есть красный. */
.строка.погасла .имя {
  color: var(--текст-2);
}
.строка.погасла .плитка {
  opacity: 0.55;
}

/* ── ШАПКА ────────────────────────────────────────────────────────────────
   Аватар и приветствие слева, круглая кнопка справа. Имя КРУПНО: у обоих
   референсов имя — самая заметная строка шапки, а «Добрый день» — мелкая
   надстрочная. */
/* 🔴 ШАПКА ЕДЕТ ЗА ЭКРАНОМ, А НЕ ЛЕЖИТ МЁРТВЫМ ГРУЗОМ СВЕРХУ.

   Его слова 26.08: «почему на страницах шапка не следует за экраном красиво,
   а стоит просто вверху мёртвым грузом?»

   Он прав по существу, а не по вкусу. В шапке живут ДВЕ вещи, которые нужны
   в любой миг чтения: стрелка «назад» и остаток на счету. Уехав вверх на
   длинной странице правил, они заставляют прокручивать обратно только чтобы
   выйти — то есть страница запирает человека тем сильнее, чем она длиннее.

   Три вещи, без которых липкая шапка становится хуже обычной:

   • ФОН НЕПРОЗРАЧНЫЙ. Под шапкой едет текст; полупрозрачная без размытия
     даёт кашу из двух слоёв. Берём размытие, а где его нет — сплошной цвет;
   • ГРАНИЦА ПОЯВЛЯЕТСЯ ТОЛЬКО ПРИ ПРОКРУТКЕ. Полоска под шапкой на самом
     верху страницы — лишняя черта в спокойном состоянии;
   • ВЫСОТА НЕ ПРЫГАЕТ. Шапка на прокрутке ужимается по отступам, но не по
     содержимому: скачок высоты дёргает всю страницу под пальцем. */
.шапка {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px 16px;
  background: var(--чёрный);
  /* Размытие там, где браузер умеет; сплошной фон выше — запасной путь. */
  backdrop-filter: saturate(140%) blur(14px);
  -webkit-backdrop-filter: saturate(140%) blur(14px);
  border-bottom: 1px solid transparent;
  transition:
    padding 0.18s ease-out,
    border-color 0.18s ease-out;
}
@supports (backdrop-filter: blur(1px)) {
  .шапка {
    background: color-mix(in srgb, var(--чёрный) 82%, transparent);
  }
}
/* Признак ставит приложение, когда страница ушла вниз хотя бы на несколько
   пикселей: тогда шапка отделяется чертой и слегка поджимается. */
.шапка[data-приподнята="да"] {
  padding-top: 10px;
  padding-bottom: 10px;
  border-bottom-color: var(--слой-3);
}
@media (prefers-reduced-motion: reduce) {
  .шапка {
    transition: none;
  }
}

.аватар {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  flex: none;
  overflow: hidden;
  background: var(--слой-2);
  display: grid;
  place-items: center;
  font-weight: 700;
  font-size: 16px;
  color: var(--текст-2);
}
.аватар img,
.аватар svg {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* Аватар поддержки — корона знака на оранжевом. Раньше здесь стояла буква
   «S», и бренд из приложения не читался вовсе. */
/* 🔴 КОРОНА БЕЗ ПОДЛОЖКИ — ЕГО ПРАВКА 26.08.
   На оранжевом круге тёмный силуэт короны читался как пятно: у знака
   тонкие зубцы, и на цветном фоне они пропадают. Оранжевая корона на
   чёрном — то, как знак нарисован в самом файле. */
.аватар.корона {
  background: none;
  padding: 0;
  color: var(--деньги);
}
.аватар.корона svg {
  object-fit: contain;
  width: 100%;
  height: 100%;
}

.привет {
  flex: 1;
  min-width: 0;
}
.привет small {
  display: block;
  color: var(--текст-тихо);
  font-size: 13px;
  line-height: 1.25;
}
.привет b {
  display: block;
  font-size: 19px;
  font-weight: 700;
  letter-spacing: -0.025em;
  line-height: 1.2;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.привет .живой {
  display: flex;
  align-items: center;
  gap: 5px;
  color: var(--зачтено);
}
.привет .живой i {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  flex: none;
}

/* Заголовок экрана по центру — для страниц, куда пришли «вглубь» (вывод,
   подача): слева стрелка назад, справа распорка того же размера. */
.заголовок-экрана {
  flex: 1;
  text-align: center;
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -0.02em;
}
.распорка {
  width: 42px;
  flex: none;
}

/* Знак целиком — слово с короной. */
.знак {
  display: inline-flex;
  align-items: center;
  height: 26px;
}
.знак svg {
  height: 22px;
  width: auto;
  display: block;
}

/* ── КРУГЛАЯ КНОПКА ШАПКИ ─────────────────────────────────────────────── */
/* 🔴 44, А НЕ 42, И ЭТИ ДВА ПИКСЕЛЯ НЕ ПРИДИРКА.
   Сорок четыре — нижняя граница цели касания у Apple (HIG) и сорок восемь у
   Material. Кругляш стоит В ШАПКЕ, то есть у верхнего края, куда палец
   дотягивается хуже всего и промахивается чаще. Найдено обходом всех
   экранов с замером НАСТОЯЩЕЙ области касания (§147). */
.кругляш {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  flex: none;
  position: relative;
  background: var(--слой-1);
  border: 0;
  padding: 0;
  display: grid;
  place-items: center;
  color: var(--текст);
  cursor: pointer;
  transition: transform 0.16s cubic-bezier(0.23, 1, 0.32, 1);
}
.кругляш:active {
  transform: scale(0.93);
}
.кругляш svg {
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* Точка непрочитанного. Обводка цветом фона — иначе точка сливается с краем
   кнопки и читается как дефект отрисовки. */
.кругляш .точка {
  position: absolute;
  top: 6px;
  right: 6px;
  min-width: 18px;
  height: 18px;
  padding: 0 4px;
  border-radius: var(--р-пилюли);
  background: var(--отказ);
  border: 2.5px solid var(--чёрный);
  font-size: 10.5px;
  font-weight: 700;
  color: #fff;
  display: grid;
  place-items: center;
  line-height: 1;
}
/* Когда непрочитанное есть, но считать нечего — точка без числа. */
.кругляш .точка.пустая {
  top: 7px;
  right: 8px;
  min-width: 9px;
  width: 9px;
  height: 9px;
  padding: 0;
}

/* ── СОДЕРЖИМОЕ ──────────────────────────────────────────────────────────
   🔴 ЗАПАС СНИЗУ СЧИТАЕТ И БЕЗОПАСНУЮ ЗОНУ. Панель плавающая и сама
   добавляет `env(safe-area-inset-bottom)` — то есть на телефоне с чёлкой
   она выше своих 82 пикселей. Запас, не знающий про это, на такой машине
   оказывается меньше панели. */
main {
  padding: 0 16px
    calc(var(--низ-панели) + env(safe-area-inset-bottom, 0px) + 24px);
  max-width: 640px;
  margin: 0 auto;
}

/* ── РАЗДЕЛ: заголовок слева, тихая ссылка справа ────────────────────── */
h2 {
  margin: 0 0 12px;
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -0.025em;
  color: var(--текст);
  text-transform: none;
}
.раздел {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin: 0 0 12px;
}
.раздел h2 {
  margin: 0;
}
/* 🔴 ЗДЕСЬ ЖИЛА `.раздел .ссылка` — КНОПКА, НАРОЧНО ПОХОЖАЯ НА ТЕКСТ (§94).
   Замысел был такой: действие в заголовке раздела второстепенно, значит и
   весить должно немного. Он его забраковал прямо: «почему это не нормальные
   обычные кнопки кастомные, сделай нормльно».

   И он прав по делу, а не по вкусу. Нажимаемое, выглядящее как текст, —
   это ставка на то, что человек догадается. В соседнем правиле у нас про
   это уже написано дословно: «счёт справа не кнопка, поэтому и не выглядит
   кнопкой; одинаковый вид у нажимаемого и ненажимаемого учит не верить ни
   тому ни другому». Обратное верно ровно так же.

   Вместо неё — `тихая мелкая`, настоящая кнопка. Ниже. */

/* ── КАРТОЧКА. Ни обводки, ни тени: только светлота. ──────────────────── */
.карта {
  background: var(--слой-1);
  border: 0;
  border-radius: var(--р-карты);
  overflow: hidden;
  margin-bottom: 12px;
}
.карта.воздух {
  padding: 18px;
}

/* 🔴 ФОРМА — НЕ ОДНА СПЛОШНАЯ ПЛИТА.
   Его слова про экран подачи: «все сплошным цветом и ничего не понятно».
   И верно: форма была одной карточкой, внутри неё поля того же цвета, и
   границ между шагами не читалось вовсе — сплошное серое поле с текстом.
   Теперь форма прозрачна, а карточками стали САМИ поля: каждое видно
   отдельно, между ними воздух. */
form.карта {
  background: none;
  border-radius: 0;
  overflow: visible;
  padding: 0;
  margin-bottom: 0;
}
.карта.выше {
  background: var(--слой-2);
}

/* ── ГЛАВНАЯ КАРТОЧКА, ЗАЛИТАЯ АКЦЕНТОМ ─────────────────────────────────
   Ядро вида: самое яркое пятно экрана — деньги. */
.карта-денег {
  background: var(--деньги);
  color: var(--на-деньгах);
  border-radius: var(--р-карты);
  padding: 20px;
  margin-bottom: 12px;
}
.карта-денег .верх {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}
.карта-денег .число {
  font-size: 40px;
  font-weight: 800;
  letter-spacing: -0.04em;
  line-height: 1.05;
}
.карта-денег .под {
  font-size: 14.5px;
  font-weight: 500;
  opacity: 0.62;
  margin-top: 3px;
}
.карта-денег .значок-угол,
.акция .значок-угол {
  width: 42px;
  height: 42px;
  border-radius: 50%;
  background: #fff;
  flex: none;
  display: grid;
  place-items: center;
  color: var(--на-деньгах);
}
.карта-денег .значок-угол svg,
.акция .значок-угол svg {
  width: 21px;
  height: 21px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Пилюли внутри карточки денег. Зеркальные: у левой значок слева, у правой
   справа — так у них, и так пара читается как «туда и сюда». */
.пилюли {
  display: flex;
  gap: 9px;
  margin-top: 20px;
}
.пилюля {
  flex: 1;
  height: 52px;
  border: 0;
  border-radius: var(--р-пилюли);
  background: #101012;
  color: #fff;
  font: inherit;
  font-size: 14.5px;
  font-weight: 600;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 5px;
  transition: transform 0.16s cubic-bezier(0.23, 1, 0.32, 1);
}
.пилюля:active {
  transform: scale(0.97);
}
.пилюля:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}
.пилюля .кр {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: #fff;
  color: #101012;
  display: grid;
  place-items: center;
  flex: none;
}
.пилюля .кр svg {
  width: 19px;
  height: 19px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.пилюля.вправо {
  justify-content: space-between;
  padding-left: 18px;
}

/* ── БАЛАНС ПО ЦЕНТРУ (выбранный им вариант Б) ────────────────────────── */
.баланс-центр {
  text-align: center;
  padding: 10px 0 22px;
}
/* Лицо над суммой (§89): отвечает «чьи это деньги» до того, как вопрос
   задан. Кружок по центру, с воздухом снизу — иначе он подпирает число и
   читается как часть суммы. */
.аватар.баланс-лицо {
  margin: 0 auto 14px;
  /* Тонкий ободок отделяет лицо от чёрного фона: без него светлая аватарка
     сливается краями, а тёмная теряет форму вовсе. */
  box-shadow: 0 0 0 1px var(--слой-3);
}
.баланс-центр .число {
  font-size: 46px;
  font-weight: 800;
  letter-spacing: -0.045em;
  line-height: 1;
}
.баланс-центр .под {
  color: var(--текст-тихо);
  font-size: 14.5px;
  margin-top: 7px;
}
/* 🔴 «ЕЩЁ $15.00 · ПРИДУТ 3 СЕНТЯБРЯ» — Б4, его заказ 29.08.
   Пилюля, а не третья строка текста. Три подписи столбиком под крупным
   числом читаются как один абзац, и человек перестаёт различать, где
   доступное, а где будущее, — та самая каша, которой он и опасался.
   Пилюля отделена ФОРМОЙ, а не только цветом: на телефоне при ярком свете
   разница в цвете почти не различается, а разница в форме различается
   всегда. */
.баланс-центр .зреет {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 12px;
  padding: 5px 11px 5px 9px;
  border-radius: 999px;
  background: var(--слой-2);
  color: var(--текст-тихо);
  font-size: 13px;
  line-height: 1.2;
  /* Цифры одной ширины: сумма и дата стоят рядом, и прыгающая разрядка
     между ними читается как дрожание. */
  font-variant-numeric: tabular-nums;
  /* Длинная дата на узком экране переносится внутри пилюли, а не выпирает
     за край: 390 точек — это наш нижний предел, и он проверяется. */
  max-width: 100%;
  text-align: left;
}
/* Долг — та же пилюля, другой голос. Красным, но НЕ кричащим: это не
   отказ и не ошибка человека, а состояние, которое пройдёт само. */
.баланс-центр .зреет.долгом {
  background: color-mix(in srgb, var(--отказ) 16%, transparent);
  color: var(--отказ);
}
/* Две пилюли в столбик, а не в строку: рядом они читаются как одна мысль,
   а это две разные — что должен и что придёт. */
.баланс-центр .зреет + .зреет {
  margin-top: 6px;
}
.баланс-центр .зреет svg {
  width: 14px;
  height: 14px;
  /* Значок — пояснение к словам, а не отдельная мысль: он тише текста. */
  opacity: 0.75;
  flex: none;
}

/* ── ШИРОКИЕ ПЛАШКИ ДЕЙСТВИЙ, подпись ПОД плашкой ─────────────────────── */
.плашки {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
  margin-bottom: 24px;
}
.плашки.четыре {
  grid-template-columns: repeat(4, 1fr);
}
.плашка {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
}
.плашка .верх {
  height: 56px;
  border-radius: var(--р-плашки);
  background: var(--слой-1);
  display: grid;
  place-items: center;
  color: var(--текст);
  transition: transform 0.16s cubic-bezier(0.23, 1, 0.32, 1);
}
.плашка:active .верх {
  transform: scale(0.95);
}
.плашка.главная-плашка .верх {
  background: var(--деньги);
  color: var(--на-деньгах);
}
.плашка:disabled {
  cursor: not-allowed;
}
.плашка:disabled .верх {
  background: var(--слой-2);
  color: var(--текст-тихо);
}
.плашка:disabled span {
  color: var(--текст-тихо);
}
.плашка span {
  display: block;
  font-size: 12.5px;
  color: var(--текст-2);
  margin-top: 8px;
}
.плашка .верх svg {
  width: 22px;
  height: 22px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.9;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ── СТРОКА СПИСКА: сплошной цветной кружок слева, шеврон справа ──────── */
.поз {
  display: flex;
  align-items: center;
  gap: 13px;
  padding: 14px 16px;
  width: 100%;
  background: none;
  border: 0;
  border-radius: 0;
  font: inherit;
  font-weight: 400;
  color: inherit;
  text-align: left;
  cursor: default;
}
button.поз {
  cursor: pointer;
}
button.поз:active {
  background: var(--слой-2);
}
.поз + .поз {
  border-top: 1px solid rgba(255, 255, 255, 0.05);
}
.кружок {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  flex: none;
  display: grid;
  place-items: center;
  color: #0a0a0c;
}
.кружок svg {
  width: 19px;
  height: 19px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.кружок.к-деньги {
  background: var(--деньги);
}
.кружок.к-зачтено {
  background: var(--зачтено);
}
.кружок.к-ждёт {
  background: var(--ждёт);
}
.кружок.к-идёт {
  background: var(--идёт);
}
.кружок.к-отказ {
  background: var(--отказ);
}
.кружок.к-тихо {
  background: var(--слой-3);
  color: var(--текст-2);
}
.тело {
  flex: 1;
  min-width: 0;
}
.тело b {
  display: block;
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -0.015em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 🔴 ЗАГОЛОВОК ИЗ ДВУХ ЧАСТЕЙ: ИМЯ СЖИМАЕТСЯ, ЧИСЛО — НЕТ (§299, П5·#3).

   Прежде заголовок был одной строкой с многоточием, и срезалось то, что
   стоит В КОНЦЕ, — само число просмотров. А по нему считаются деньги.
   Замерено на 390×844: «Instagram Reels · 8 40…» (199 px против 175),
   «YouTube Shorts · 12…» (185 против 160). TikTok влезал, две площадки из
   трёх — нет, и 86 400 просмотров на Reels это будни, а не край.

   🔴 Довод уже записан в этом же файле у соседней правки: «обрезать сумму
   многоточием нельзя: „$1 929…“ — это не сокращение, это ДРУГОЕ ЧИСЛО».
   Для числа просмотров он верен ровно так же, а применён не был.

   Площадку сжимать МОЖНО: слева от строки стоит её значок, и по нему она
   узнаётся без слов. Число не узнаётся ничем. */
.тело b:has(.сколько) {
  display: flex;
  align-items: baseline;
}
.тело b .площадка {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.тело b .сколько {
  flex: none;
  white-space: nowrap;
  /* 🔴 ОТСТУП ПОЛЕМ, А НЕ ПРОБЕЛОМ В ТЕКСТЕ. Снимок поймал: в гибкой
     раскладке ведущий пробел элемента отбрасывается, и вышло «TikTok· 125
     000» — слипшееся. Пробел в разметке тут ненадёжен по построению. */
  margin-left: 0.32em;
  /* Цифры одной ширины: столбик чисел читается, а не пересчитывается. */
  font-variant-numeric: tabular-nums;
}

.тело small {
  display: block;
  color: var(--текст-тихо);
  font-size: 13px;
  /* 🔴 ПОДПИСЬ ПЕРЕНОСИТСЯ, А НЕ РЕЖЕТСЯ (§299, находка П5·#1).

     Здесь стояло `nowrap` с многоточием, и на 390×844 срезалось до 250 px:
     «заявка №90060 · станут доступны 3 сентября · 23 авг 21:56» → видно
     «заявка №90060 · станут дост…».

     🔴 И ДОСТАТЬ ОБРЕЗАННОЕ БЫЛО НЕЧЕМ. Строка истории кошелька — обычный
     `div`, не кнопка; ни `title`, ни `aria-label` у неё нет. На телефоне
     наведения не существует. То есть день, когда деньги станут доступны,
     человек не мог узнать НИКАК — а это главный вопрос, с которым на этот
     экран приходят.

     🔴 И ЧЕМ КРУПНЕЕ СУММА СПРАВА, ТЕМ ХУЖЕ: 208 → 198 → 155 px под
     подпись. То есть беда росла ровно у тех, у кого денег больше.

     Две строки хватает на всё встреченное; третья не нужна и была бы шумом.
     Перенос по словам, а не где придётся: дата не должна рваться. */
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
  white-space: normal;
  overflow-wrap: break-word;
}
/* 🔴 И ЗАГОЛОВОК ТОЖЕ УМЕЕТ ПЕРЕНОСИТЬСЯ.
   В списке сумм строку режут многоточием — там важна колонка справа. А в
   правилах заголовок и есть содержание: «Подать можно за 7 дней после
   публ…» — это не правило, это загадка. */
/* Место под сводку у каждой привязки: пока пусто — не занимает ничего,
   с ответом внутри отбивает его от следующей карточки. */
.сводка-места:not(:empty) {
  margin: 10px 0 12px;
}

.поз.длинная .тело b {
  white-space: normal;
  overflow: visible;
  /* Ник FACEIT — токен без пробелов, переносить по пробелам не по чему: с 32
     знаков страница на 390 растягивалась до 485 px (разбор — П1·круг2·Н9). */
  overflow-wrap: anywhere;
}

/* Пояснение, которое обязано читаться целиком, — переносится, а не режется.
   Одно и то же место говорит две разные вещи: примета (режем) и причина
   отказа (не режем).

   🔴 ОТМЕНА ОБРЕЗКИ БЫЛА НАПОЛОВИНУ, И ПОЛОВИНА НЕ РАБОТАЛА (14.09).

   Здесь стояли только `white-space` и `overflow`, а обрезку ставит СЧЁТ
   СТРОК — `-webkit-line-clamp: 2` и `line-clamp: 2` у соседнего правила.
   Ни то, ни другое `overflow: visible` не снимает: счёт строк режет сам, и
   Chrome дорисовывает своё многоточие.

   Замер на живом экране правил, 390×844: коробка 37,7 px при содержимом
   57 px. Обрезалась фраза «в каком углу экрана он стоит — не важно, а вот на
   какой СЕКУНДЕ ролика, важно» — ровно та, из-за которой 14.09 блогеры
   читали противоположное правилу, и ровно её он поймал глазами в приложении.
   Видно на экране было «…он», дальше многоточие.

   🔴 И ЭТО ТРЕТИЙ СЛУЧАЙ ОДНОЙ ПОРОДЫ: комментарий утверждает то, чего в
   коде нет. Правило писалось, когда обрезку ставил только `-webkit-box`;
   стандартное `line-clamp` приехало в Chrome позже и начало резать блоки
   само — молча и у всех, кто полагался на прежнюю отмену.

   Снимаем ОБА счёта и возвращаем блок: `display` соседнего правила тоже
   участвует в обрезке, и оставить его значило бы починить наполовину
   второй раз. */
.тело small.полностью {
  display: block;
  -webkit-line-clamp: none;
  line-clamp: none;
  white-space: normal;
  overflow: visible;
}
/* 🔴 БАН ЧИТАЕТСЯ ЦВЕТОМ, А НЕ ТОЛЬКО СЛОВАМИ (§246).
   Строка снимка серая — так и задумано: «тег на месте · смотрели вчера» это
   спокойная примета. Но «FACEIT забанил» в том же сером неотличимо от неё, а
   рядом стоит «0 ч подтверждено» — и человек видит исправную строку с пустым
   счётом, не понимая связи.
   Цвет отказа здесь не крик, а связь: он тот же, что у кружка слева
   (`к-отказ`), и вместе они читаются как одно состояние карточки.
   🔴 ЦВЕТ — НЕ ЕДИНСТВЕННЫЙ НОСИТЕЛЬ СМЫСЛА: слова «FACEIT забанил» стоят в
   самой строке, поэтому не различающий цвета человек ничего не теряет
   (WCAG 1.4.1). */
.тело small.полностью.бедой {
  color: var(--отказ);
}
/* 🔴 ДВЕ СТРОКИ БЕЗ РАЗДЕЛИТЕЛЯ — И ЭТО ТРЕТЬЯ РЕДАКЦИЯ, КАЖДАЯ КУПЛЕНА
   СНИМКОМ (§246).

   Было: «состояние · смотрели 1 сентября» одной строкой. На 390 точках она не
   влезает НИКОГДА, и браузер переносил её после разделителя — строка
   кончалась висящей точкой: «тег на месте ·».

   Стало (вторая попытка): разделитель уехал в псевдоэлемент второй части,
   чтобы ехать вместе с ней. Снимок показал, что теперь строка НАЧИНАЕТСЯ с
   точки — беда та же, переехавшая на другой край.

   Стало (эта): разделителя нет вовсе, части — две строки. Разделитель нужен
   ровно тогда, когда куски стоят рядом; здесь они рядом не стоят почти
   никогда, и знак, который в девяти случаях из десяти висит на краю, — это
   украшение, а не смысл.

   🔴 НИ ОДНУ ИЗ ДВУХ ПРЕДЫДУЩИХ РЕДАКЦИЙ НЕЛЬЗЯ БЫЛО ОТЛИЧИТЬ ОТ ХОРОШЕЙ ПО
   КОДУ. В разметке обе выглядят безупречно; беда рождается на переносе, то
   есть в браузере и только на узком экране. */
.тело small.полностью .сост,
.тело small.полностью .когда {
  display: block;
}
.справа {
  display: flex;
  align-items: center;
  gap: 7px;
  flex: none;
}
/* 🔴 ЧИСЛО БЕЗ ПОДПИСИ — ЭТО ШУМ, А НЕ СВЕДЕНИЕ (§229).
   Его слова: «что в этой карточке за каша вообще?» Справа стояло голое
   «0 ч» — рядом с ником и рейтингом оно читается как ещё одно случайное
   число. Подпись под ним стоит один раз и снимает вопрос навсегда.

   🔴 ЗВАЛОСЬ `.ур-часы` И ЛЕЧИЛО ТОЛЬКО ЧАСЫ — А БОЛЕЛО ЕЩЁ И У СУММЫ (§241).
   Имя про часы прятало то, что правило общее: «число, а под ним подпись,
   прижаты вправо». Рядом, в той же карточке, сумма с подписью
   «предварительно» стояла БЕЗ него — то есть в СТРОКУ, — и вот что из этого
   выходило на 390 px:

     `.справа` не сжимается (`flex: none`), значит «$3.60 предварительно»
     забирало около 150 px. Тексту оставалось ~125, а у заголовка стоит
     `overflow-wrap: anywhere` (он заведён ниже нарочно — ради ников-токенов
     без пробелов). И заголовок ломался ПОСРЕДИ СЛОВА: «Подтвержде / но 12 ч».

   Видно это было каждому, у кого есть ненулевая сумма к оплате. Найдено
   снимком на 390×844, а не чтением: ни ворота, ни пробы такого не видят.

   Имя теперь общее, и правило применено В ОБОИХ местах — часы и сумма. */
.с-подписью {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  line-height: 1.15;
}
.с-подписью small {
  font-size: 11px;
  color: var(--текст-тихо);
  letter-spacing: 0.02em;
}
.справа .сум {
  font-size: 15px;
  font-weight: 700;
  letter-spacing: -0.02em;
}
/* 🔴 ДВУХ ЭТИХ ПРАВИЛ НЕ БЫЛО ВОВСЕ, И НАШЛА ИХ ПРОБА НА КЛАССЫ-СИРОТЫ (§241).
   Разметка карточки FACEIT с самого начала различала важное и неважное:

     <span class="сум ${час > 0 ? "деньги" : "тихо"}">${час} ч</span>

   а правил `.деньги` и `.тихо` в стилях НЕ СУЩЕСТВОВАЛО. Значит оба
   состояния рисовались одинаково — белым жирным, — и различие, ради которого
   писалось условие, не работало НИ РАЗУ. Ни ворота, ни типы, ни пробы такого
   не видели: и разметка, и стили по отдельности исправны.

   🔴 И это ровно то, про что были его слова «что в этой карточке за каша
   вообще» (§229): сумма к оплате — главное на экране — не отличалась от
   номера версии. Соседнее правило `.сум.плюс` (зачтено, зелёное) написано
   было; эти два — нет.

   Оранжевый здесь тот же, что у кружка `к-деньги` и у главной кнопки: акцент
   у нас ОДИН, и он про деньги. */
.справа .сум.деньги {
  color: var(--деньги);
}
/* 🔴 ПРИГЛУШЕНО — НЕ ЗНАЧИТ НЕЧИТАЕМО, И ЭТО СЧИТАНО, А НЕ ВЫБРАНО НА ГЛАЗ.
   Просился `--текст-тихо` (он и стоит у подписи рядом), но на подложке
   карточки `#131315` он даёт 3,68 : 1. Порог AA для 15 px — 4,5 : 1;
   послабление для крупного текста начинается с 18,7 px, а у нас 15.
   `--текст-2` даёт 7,77 : 1 и приглушает ничуть не хуже. */
.справа .сум.тихо {
  color: var(--текст-2);
}
.справа .сум.плюс {
  color: var(--зачтено);
}
.шеврон {
  color: var(--текст-тихо);
  flex: none;
  width: 17px;
  height: 17px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ── ЧИПЫ-ФИЛЬТРЫ: пилюли, активная — сплошная заливка ────────────────── */
.чипы {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  scrollbar-width: none;
  /* Чипы уходят под край экрана при прокрутке — как у них. Отрицательные
     поля с равным внутренним отступом дают это, не ломая колонку. */
  margin: 0 -16px 14px;
  padding: 2px 16px 0;
}
.чипы::-webkit-scrollbar {
  display: none;
}
/* 🔴 ВЫСОТА 44 — ЦЕЛЬ КАСАНИЯ, А НЕ ВКУС. Отступов 10px хватало на 40px
   при кегле 14: на четыре пикселя ниже границы Apple HIG. Чипы — это отбор
   в списке заявок, по ним бьют пальцем чаще всего на экране. Ставим
   `min-height`, а не увеличиваем отступ: отступ раздул бы и ширину, а по
   ширине запаса и так довольно. */
.чип {
  flex: none;
  border: 0;
  border-radius: var(--р-пилюли);
  padding: 10px 17px;
  min-height: 44px;
  font: inherit;
  font-size: 14px;
  font-weight: 500;
  background: var(--слой-1);
  color: var(--текст-2);
  cursor: pointer;
  white-space: nowrap;
  transition: transform 0.16s cubic-bezier(0.23, 1, 0.32, 1);
}
.чип:active {
  transform: scale(0.96);
}
.чип[aria-pressed="true"] {
  background: var(--текст);
  color: #0a0a0c;
  font-weight: 600;
}
/* Оранжевая заливка — там, где чип означает деньги, а не отбор. */
.чип.денежный[aria-pressed="true"] {
  background: #3d2415;
  color: var(--деньги);
}

/* 🔴 СПОСОБ, ЗАКРЫТЫЙ ПОРОГОМ, ВИДЕН — ГАШЁНЫМ (§207.7).

   Его находка 31.08: «когда баланс меньше 50 то показывается везде что есть
   только способ вывода топскин и это воодит в заблудение». Раньше такой чип
   просто ИСЧЕЗАЛ с экрана, и способ переставал существовать.

   🔴 ГАШЁНЫЙ — НЕ ЗНАЧИТ НЕЧИТАЕМЫЙ. Здравый рефлекс «выключено — это 0.38
   прозрачности» (Material) здесь неверен: чип НЕСЁТ ЧИСЛО («от $50.00»),
   ради которого он и оставлен на экране. Прозрачность съела бы ровно то,
   что мы показываем. Поэтому заливка убрана до обводки — форма читается как
   «пока не активно», — а текст остаётся полноцветным `--текст-2`.

   Курсор не `not-allowed`: нажатие ЗДЕСЬ ОСМЫСЛЕННО — оно печатает, сколько
   не хватает. Кнопка, молчащая на палец, — это то, на что он жаловался
   отдельно. */
.чип.закрыт,
.чип.закрыт[aria-pressed="true"] {
  background: transparent;
  /* Обводка ступенью `--слой-3` — та же, которой в этой теме обозначается
     «невыбранное». Своего цвета для этого состояния не заводим: лишний
     оттенок в палитре живёт дольше, чем повод, ради которого он появился. */
  box-shadow: inset 0 0 0 1px var(--слой-3);
  color: var(--текст-2);
  font-weight: 500;
}

/* ── СОСТОЯНИЯ ──────────────────────────────────────────────────────────
   🔴 ЦВЕТ МЕТКИ И ЦВЕТ ЕЁ ПОДЛОЖКИ — РАЗНЫЕ ВЕЛИЧИНЫ.

   Круг 3 замерил: насыщенный цвет на своей же бледной подложке даёт низкий
   контраст по построению — «отклонена» выходила 3,27:1 при норме 4,5.
   Разводим роли: подложка — тёмная ступень, текст — светлая. */
.метка {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 5px 11px;
  border-radius: var(--р-пилюли);
  font-size: 11.5px;
  font-weight: 600;
  flex: none;
  text-transform: none;
  letter-spacing: 0;
  /* 🔴 МЕТКА ПЕРЕНОСИТСЯ И НЕ ШИРЕ ТРЕТИ — ИНАЧЕ ОНА СЪЕДАЕТ ЧИСЛО (§38·П5).
     Поймано снимком на 390: у заявки с меткой «принята, ждёт проверки»
     заголовок обрезался до «TikTok · 1 4…» — то есть человек не видел, за
     СКОЛЬКО просмотров заявка. А просмотры и есть суть заявки: по ним
     считаются деньги.
     Метка при этом ничего не теряет: состояние продиктовано ещё и цветом
     кружка слева, а слова переносятся на вторую строку целиком.
     `flex: none` остаётся: пилюля не должна сжиматься до нечитаемого — она
     просто перестала быть шире трети строки. */
  max-width: 34%;
  white-space: normal;
  text-align: center;
}
.метка.ждёт {
  color: var(--ждёт);
  background: #251c40;
}
.метка.идёт {
  color: var(--идёт);
  background: #14243d;
}
.метка.зачтено {
  color: var(--зачтено);
  background: #10321f;
}
.метка.отказ {
  color: var(--отказ);
  background: #3a1620;
}

/* ── ОРГАНЫ УПРАВЛЕНИЯ ─────────────────────────────────────────────────── */
button,
.кнопка {
  appearance: none;
  border: 0;
  font: inherit;
  font-weight: 600;
  border-radius: var(--р-плашки);
  padding: 13px 18px;
  cursor: pointer;
  transition: transform 0.14s cubic-bezier(0.23, 1, 0.32, 1);
  /* 🔴 ФОН И ЦВЕТ ЗАДАЮТСЯ ЗДЕСЬ, ХОТЯ ВЫГЛЯДЯТ ЛИШНИМИ (§94).
     Их тут не было, и платформа рисовала кнопку за нас: Chrome на ПК давал
     серую плашку #f0f0f0 с чёрным текстом, WebView iOS — прозрачный фон и
     СИСТЕМНЫЙ СИНИЙ. Он это и увидел: «на пк норм, а на телефоне текст
     кнопок как бы цветом ссылки идёт». Медиазапроса по указателю в файле
     нет ни одного — расходились не наши стили, а умолчания платформ.

     Не «наш фон всем»: прозрачные кнопки (кружки, тумблеры, пузыри, фон
     шторки) сломались бы. Задаём ровно запрет платформе решать. Побочная
     польза: забытый вариант теперь даёт НЕВИДИМУЮ кнопку — беду видно на
     первом же взгляде, а не на чужом телефоне. */
  background: transparent;
  color: inherit;
}

/* Главная кнопка — оранжевая. Их на экране не больше ОДНОЙ: две главные
   кнопки означают, что главной нет. */
.главная {
  width: 100%;
  background: var(--деньги);
  color: var(--на-деньгах);
  padding: 17px;
  font-size: 16px;
  font-weight: 700;
  letter-spacing: -0.015em;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}
.главная:active {
  transform: scale(0.985);
}
.главная:disabled {
  background: var(--слой-2);
  color: var(--текст-тихо);
  cursor: not-allowed;
}

/* 🔴 КНОПКА ВО ВСЮ ШИРИНУ И ЗАЗОР МЕЖДУ ТАКИМИ — ПРАВИЛОМ, А НЕ РУКОЙ (§236).
   Его слова: «на странице фейсита кнопки также слипшиеся, я тебе говорил
   исправить но ты не послушал». Он прав дважды: и что слиплись, и что я чинил
   рядом стоящее (строку со значком), а не это.

   ЗАМЕРЕНО: зазор между «Проверить ник сейчас» и «Посчитать за 14 дней» был
   РОВНО 0.0 px. Кнопки касались, скругления сливали их в одно пятно.

   🔴 И БЕДА ХУЖЕ ВИДА. У `button.мелкая` область касания расширена невидимым
   слоем `::after { inset: -7px -6px }` — вид 32 px, касание 46. При нулевом
   зазоре области ДВУХ кнопок накладываются на 14 пикселей: есть полоса, где
   палец метит в одну кнопку, а нажимается другая. На телефоне это не досада,
   а промах по действию.

   Корень глубже отступа: `.мелкая` придумана для ЧИПА В ЗАГОЛОВКЕ раздела
   (там кнопка обязана быть мелкой, а касание добирается слоем). Здесь ею
   сделано ПОЛНОШИРИННОЕ действие внутри карточки — другая вещь. У базовой
   кнопки `padding: 13px 18px`, то есть ~46 px сама по себе: ей невидимый
   слой не нужен, и накладываться нечему.

   Почему правилом, а не отступом по месту. Полноширинных кнопок в приложении
   двенадцать, пар подряд — три. В двух парах отступ прописан рукой
   (`margin-bottom:8px`), в третьей ЗАБЫТ. Рука забывает, правило нет.

   Восемь пикселей — не вкус: это порог Material на расстояние между целями
   касания. Меньше — палец промахивается. */
.вширь {
  width: 100%;
}
.вширь + .вширь {
  margin-top: 8px;
}

/* 🔴 ТИХАЯ КНОПКА СВЕТЛЕЕ КАРТОЧКИ, А НЕ РАВНА ЕЙ.
   Прежде и карточка, и кнопка внутри неё были одного цвета — кнопка
   «Спросить в поддержке» исчезала на подложке, оставался только текст без
   границ, и нажимать было не на что видимое. */
.тихая {
  background: var(--слой-2);
  color: var(--текст);
  border: 0;
}
.карта .тихая,
.карта.воздух .тихая {
  background: var(--слой-3);
}
.тихая:active {
  transform: scale(0.985);
}

/* 🔴 МЕЛКАЯ — ВТОРОСТЕПЕННОЕ ДЕЙСТВИЕ В ЗАГОЛОВКЕ РАЗДЕЛА (§94).
   «Кошелёк», «Все», «Правила» — переходы на соседний экран. Полноразмерная
   кнопка тут спорила бы с содержимым раздела, а текст-ссылка (как было) не
   читается нажимаемым вовсе.

   Слово `мелкая` взято из админки, где оно уже означает ровно это. Один
   словарь на два места — иначе через месяц у нас две мелкие кнопки с разной
   геометрией и никто не вспомнит, почему. */
button.мелкая {
  position: relative;
  background: var(--слой-2);
  color: var(--текст);
  padding: 7px 12px;
  font-size: 13px;
  font-weight: 600;
  border-radius: var(--р-пилюли);
}
.карта button.мелкая {
  background: var(--слой-3);
}
/* 🔴 ВИД 32 px, ОБЛАСТЬ КАСАНИЯ 46 — И ЭТО НЕ ПЕРЕСТРАХОВКА.
   Заголовок раздела не должен нести кнопку в полпальца высотой; палец при
   этом обязан попадать. Разводим: слой растягивает область нажатия за
   видимые границы, ничего не рисуя. Ровно так же поступает админка, только
   там это сделано отступами — здесь нельзя, отступы двигали бы саму
   таблетку. */
button.мелкая::after {
  content: "";
  position: absolute;
  inset: -7px -6px;
}
button.мелкая:active {
  transform: scale(0.96);
  background: var(--слой-3);
}

label {
  display: block;
  margin-bottom: 8px;
  font-size: 13px;
  font-weight: 500;
  color: var(--текст-тихо);
  text-transform: none;
  letter-spacing: 0;
}

/* 🔴 16 ПИКСЕЛЕЙ — НЕ ВКУС, А ПОРОГ iOS. Его слова 27.08: «когда
   нажимаешь на инпуты страница немного зумится — для приложения это
   неестественно».

   Safari на iPhone ПРИНУДИТЕЛЬНО приближает страницу, когда фокус уходит
   в поле с размером шрифта МЕНЬШЕ 16px. Это правило самого iOS, и
   отключить его нечем, кроме размера: ровно 16 — не зумит, 15.5 — зумит.
   И обратно iOS НЕ отдаляет: человек набрал сумму вывода и остался на
   приближённом экране, где нижняя панель ушла за край.

   Чего здесь делать НЕЛЬЗЯ: `user-scalable=no` и `maximum-scale=1` в
   `viewport`. Они убирают зум ВООБЩЕ — в том числе у тех, кому он нужен,
   чтобы прочитать. Лечим размером, а не запретом.

   🔴 Подменённое окно браузера этот зум НЕ ВОСПРОИЗВОДИТ ВОВСЕ: он живёт в
   iOS, а не в вёрстке. Поэтому правило стережёт `npm run check:zoom` —
   он читает CSS и не даёт опустить ни одно поле ввода ниже 16px. */
input,
textarea,
select {
  width: 100%;
  padding: 16px;
  background: var(--слой-1);
  border: 0;
  border-radius: var(--р-плашки);
  color: var(--текст);
  font: inherit;
  font-size: 16px;
  font-variant-numeric: tabular-nums;
}
input::placeholder,
textarea::placeholder {
  color: var(--текст-тихо);
}
input:focus,
textarea:focus,
select:focus {
  outline: 2px solid var(--деньги);
  outline-offset: 1px;
}
textarea {
  resize: vertical;
  min-height: 88px;
}

.поле {
  margin-bottom: 14px;
}

/* Переключатель, который говорит ДЕЙСТВИЕМ, а не состоянием.
   🔴 `width: 100%` ОБЯЗАТЕЛЕН: у `<button>` ширина по содержимому даже
   когда он `display: flex` и стоит блоком — браузер считает кнопку
   замещаемым элементом. Три тумблера подряд выходили РАЗНОЙ ширины, и
   список читался как случайная россыпь. Видно только глазами. */
.тумблер {
  position: relative;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 15px 16px;
  background: var(--слой-1);
  border: 0;
  border-radius: var(--р-плашки);
  margin-bottom: 10px;
  cursor: pointer;
}
.тумблер[aria-pressed="true"] {
  background: #3d2415;
}
.тумблер .что {
  font-weight: 600;
  color: var(--текст);
  text-align: left;
}
.тумблер .цена {
  font-size: 12.5px;
  color: var(--текст-тихо);
  display: block;
  font-weight: 500;
  text-transform: none;
  letter-spacing: 0;
}
.тумблер[aria-pressed="true"] .цена {
  color: var(--деньги);
}
/* 🔴 ПРОЗРАЧНЫЙ ЦВЕТ ПРЯЧЕТ ОТ ГЛАЗА И НЕ ПРЯЧЕТ ОТ ГОЛОСА.
   Выключенная галка красится в `transparent` — глазом её нет, а в дереве
   доступности она остаётся ЧАСТЬЮ ИМЕНИ кнопки. Читатель экрана произносил:
   «Отметить: ролик про CS2, ставка выше…, ГАЛОЧКА, кнопка, НЕ НАЖАТА» — то
   есть галочка спорила с состоянием в той же фразе.
   Хуже всего это звучало на согласии с правилами: «Правила прочитал и
   согласен… галочка… не нажата».
   Состояние несёт `aria-pressed`, и несёт верно. Значит сам знак —
   украшение, и ему место за `aria-hidden="true"` (проставлен в `app.js`).
   Найдено живым экраном 31.08 (§189): ни типы, ни пробы этого не видят. */
/* 🔴 ТОЛЬКО ДЛЯ ГОЛОСА: видно не глазу, а читателю экрана (§193).
   Приёма в проекте не было, и без него оставался только выбор из двух
   плохих: либо знак читается вслух как ФИГУРА («чёрный круг»), либо он
   прячется и сведения пропадают совсем.
   Прячем ровно так, как принято: рамкой в один пиксель с обрезкой, а НЕ
   `display: none` и не нулевым размером — те убирают элемент и из дерева
   доступности, то есть глушат его вместе с глазом. */
.только-голос {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.галка {
  width: 24px;
  height: 24px;
  flex: 0 0 24px;
  border-radius: 50%;
  background: var(--слой-3);
  display: grid;
  place-items: center;
  color: transparent;
  font-size: 13px;
}
.тумблер[aria-pressed="true"] .галка {
  background: var(--деньги);
  color: var(--на-деньгах);
}

/* ── ПЕРЕПИСКА ПОДДЕРЖКИ — ЛЕНТА, А НЕ ПОЛОТНО ────────────────────────────
   🔴 Его слова: «мне че каждый раз вверх листать в переписке с админом??»
   Свежее ВСЕГДА внизу.

   🔴 У ЛЕНТЫ ЕСТЬ ЗАПАС СНИЗУ — ИНАЧЕ СВЕЖЕЕ ЧИТАТЬ НЕЧЕМ. Круг 3
   промерил: самый свежий пузырь занимал 761–844, а форма письма 712–772 и
   рейка 784–844 накрывали его на 71 пиксель из 83. */
.лента {
  display: flex;
  flex-direction: column;
  gap: 9px;
  margin-bottom: 12px;
  padding-bottom: calc(var(--низ-панели) + 76px);
}
.пузырь {
  max-width: 82%;
  padding: 12px 15px;
  border-radius: 21px;
  font-size: 14.5px;
  line-height: 1.42;
  white-space: pre-wrap;
  word-break: break-word;
}
.пузырь.мой {
  align-self: flex-end;
  background: var(--деньги);
  color: var(--на-деньгах);
  border-bottom-right-radius: 7px;
  font-weight: 500;
}
.пузырь.их {
  align-self: flex-start;
  background: var(--слой-1);
  color: var(--текст);
  border-bottom-left-radius: 7px;
}
.пузырь.служебный {
  align-self: center;
  background: transparent;
  color: var(--текст-тихо);
  font-size: 12px;
  text-align: center;
  padding: 4px 0;
}

/* 🔴 ВЛОЖЕНИЕ В ПУЗЫРЕ. До 26.08 его не рисовали вовсе: пузырь с одним
   временем внутри читался как «ничего не отправилось», и человек слал
   снимок ещё раз. Значок и слово — минимум, по которому видно, что дошло.

   Отступ сверху появляется, только когда рядом есть текст: у голого
   вложения текста нет, и пустая строка над значком выглядела бы промахом
   вёрстки. */
.пузырь .вложение {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  opacity: 0.86;
}
/* 🔴🔴🔴 РАЗМЕР ЗНАЧКА ОБЯЗАТЕЛЕН, И ЭТО НЕ УКРАШЕНИЕ (найдено глазами
   30.08). Здесь стояло одно `flex: none` — и всё.

   `зн()` собирает `<svg viewBox="0 0 24 24">` БЕЗ `width` и `height`: размер
   ему задаёт CSS, и так делают ВСЕ остальные места (`.плитка svg`,
   `.строка .шеврон svg`, `.аватар svg`). Здесь размера не было.

   Что это давало на живом экране: скрепка растягивалась во ВСЮ ШИРИНУ
   пузыря — 353 пикселя высотой, — а текст рядом сжимался до одной буквы в
   строке и читался сверху вниз столбиком.

   🔴 БЕДА НЕ МОЯ И НЕ СЕГОДНЯШНЯЯ: строка `.вложение` живёт с 26.08, и
   ровно так выглядело КАЖДОЕ вложение, кроме снимка. Увидеть её было
   некому — до §113 Ф1 в приложении не было ни одного разговора с видео или
   документом, и никто не открывал такой экран глазами.

   Ни типы, ни линтер, ни 1589 проб этого не видят по построению: разметка
   верна, класс на месте, текст на месте. Видит только глаз. */
.пузырь .вложение svg {
  flex: none;
  width: 15px;
  height: 15px;
}
.пузырь:not(:empty) .вложение {
  margin-top: 2px;
}

/* 🔴 СНИМОК ПРЯМО В ПУЗЫРЕ (§80.5).

   Его слова: «а у пользователя пишет, что картинку надо открыть в боте —
   каком нахуй боте». Теперь картинка видна на месте.

   ТРИ ЧИСЛА ЗДЕСЬ НЕ УКРАШЕНИЕ:

   • `max-height: 320px` — снимок статистики вертикальный, и без потолка он
     занимает три экрана. Человек листает мимо разговора, ища, где текст;
   • `aspect-ratio` не ставим, а высоту задаём — размер картинки заранее
     неизвестен, зато известна её ПРЕДЕЛЬНАЯ высота. Место занимается сразу,
     и лента не прыгает, когда картинка догрузится;
   • `object-fit: cover` с потолком высоты режет длинный снимок, но по тапу
     он открывается целиком — ссылка вокруг для этого и стоит. */
.пузырь .снимок {
  display: block;
  margin-top: 6px;
  border-radius: 10px;
  overflow: hidden;
  line-height: 0;
}
.пузырь .снимок img {
  display: block;
  width: 100%;
  max-width: 260px;
  max-height: 320px;
  min-height: 96px;
  object-fit: cover;
  background: var(--подложка-2, rgba(255, 255, 255, 0.06));
}
/* Снимок «мой» прижат вправо вместе с пузырём — ширину не растягиваем на
   всю ленту, иначе чужой и свой перестают различаться формой. */
.пузырь.мой .снимок img {
  margin-left: auto;
}

/* 🔴🔴🔴 ВИДЕО, ЗВУК И ФАЙЛ — ПРЯМО В РАЗГОВОРЕ (§113 Ф1).

   До этой правки здесь было нечего стилить: всё, кроме снимка, рисовалось
   одной серой строкой «— тяжёлое, откройте в чате с ботом». Он забраковал
   эту фразу 26.08 («каком нахуй боте»), и убрать её стало возможно только со
   своим хранением: пока файл лежал у Telegram, показывать было нечем.

   ЧЕТЫРЕ ЧИСЛА, И НИ ОДНО НЕ НА ГЛАЗОК:

   • `max-width: 260px` — ровно как у снимка выше. Видео и картинка в одной
     ленте обязаны иметь ОДНУ ширину: разная читается как две разные ленты;
   • `max-height: 320px` — тоже как у снимка. Вертикальная запись экрана без
     потолка занимает три экрана, и человек листает мимо разговора;
   • `min-height: 96px` — место занимается ДО того, как приедут метаданные.
     Без него лента прыгает, когда браузер узнаёт размер кадра, — и прыгает
     ровно в тот миг, когда человек читает;
   • радиус 10px — как у снимка, чтобы кадр и картинка были одной породы. */
.пузырь .плеер {
  margin-top: 6px;
  border-radius: 10px;
  overflow: hidden;
  line-height: 0;
  /* Чёрная подложка: у видео с прозрачностью и в паузе между кадрами иначе
     просвечивает цвет пузыря, и кадр выглядит грязным. */
  background: #000;
}
.пузырь .плеер video {
  display: block;
  width: 100%;
  max-width: 260px;
  max-height: 320px;
  min-height: 96px;
  object-fit: contain;
}
.пузырь.мой .плеер {
  margin-left: auto;
  width: fit-content;
}

/* Гифка ведёт себя как картинка: обрезаем по краю, а не вписываем в рамку —
   пустые поля вокруг маленькой гифки читаются как поломка. */
.пузырь .плеер.гифка video {
  object-fit: cover;
  min-height: 0;
}

/* 🔴 ЗВУК ЗАНИМАЕТ ВСЮ ШИРИНУ ПУЗЫРЯ, И ЭТО НЕ ВКУС. Родная панель
   проигрывателя ужимается ползунком: на 180px перемотка становится
   неприцельной, а голосовое слушают именно ради «промотай к тому месту». */
.пузырь .звук {
  margin-top: 6px;
  min-width: 220px;
}
.пузырь .звук audio {
  display: block;
  width: 100%;
  height: 36px;
}
/* 🔴 РОДНАЯ ПАНЕЛЬ ПРОИГРЫВАТЕЛЯ РИСУЕТСЯ БЕЛОЙ, И ЭТО ВИДНО НА СНИМКЕ:
   в тёмном разговоре она читается как чужая наклейка.

   `color-scheme: dark` — это НЕ наш цвет, а просьба к браузеру рисовать
   СВОИ органы тёмными. Одна строка вместо десятка правил `::-webkit-media-*`,
   и она не ломается, когда браузер меняет разметку своей панели.

   🔴 ПОЧЕМУ НЕ СВОЙ ПРОИГРЫВАТЕЛЬ. Родная панель умеет то, чего свой не
   умеет без большой работы: перемотку жестом, скорость, вывод на внешний
   экран, чтение с экрана вслух. Менять это на красивое — плохой размен для
   голосового сообщения в поддержке. */
.пузырь .звук audio,
.пузырь .плеер video {
  color-scheme: dark;
}

/* 🔴 ДОКУМЕНТ — СТРОКОЙ, А НЕ ЗНАЧКОМ. Показать его содержимым нельзя
   (§113.5: чужой HTML открылся бы на нашем происхождении), значит всё, что
   человек может узнать до нажатия, обязано стоять в строке: ЧТО это и
   СКОЛЬКО весит. Вес решает, качать сейчас или дождаться сети.

   Строка — та же плашка, что и везде в приложении (`--р-плашки`), а не
   четвёртый вид кнопки на пятом экране. */
.пузырь .файл-строка {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 6px;
  padding: 9px 11px;
  border-radius: var(--р-плашки);
  background: rgba(255, 255, 255, 0.07);
  color: inherit;
  text-decoration: none;
  /* Длинное имя не должно растягивать пузырь шире ленты. */
  max-width: 100%;
  transition: background 0.16s cubic-bezier(0.23, 1, 0.32, 1);
}
.пузырь.мой .файл-строка {
  background: rgba(0, 0, 0, 0.16);
}
.пузырь .файл-строка:active {
  transform: scale(0.985);
}
@media (hover: hover) {
  .пузырь .файл-строка:hover {
    background: rgba(255, 255, 255, 0.12);
  }
  .пузырь.мой .файл-строка:hover {
    background: rgba(0, 0, 0, 0.24);
  }
}
.пузырь .файл-знак,
.пузырь .файл-вниз {
  flex: none;
  opacity: 0.72;
  line-height: 0;
}
/* Тот же разбор, что у `.вложение svg` выше: без размера значок либо
   растягивается на всю строку, либо (при `line-height: 0`) схлопывается в
   ничто. На живом экране он схлопнулся — строка файла осталась без скрепки
   и без шеврона вовсе. */
.пузырь .файл-знак svg {
  width: 17px;
  height: 17px;
}
.пузырь .файл-вниз svg {
  width: 14px;
  height: 14px;
  transform: rotate(90deg);
}
.пузырь .файл-текст {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
  flex: 1;
}
/* 🔴 ИМЯ РЕЖЕТСЯ МНОГОТОЧИЕМ, А НЕ ПЕРЕНОСИТСЯ. Имя файла бывает в сто
   знаков; перенос на четыре строки превращает разговор в свалку. Целиком
   его видно по долгому нажатию и в скачанном файле. */
.пузырь .файл-текст b {
  font-weight: 600;
  font-size: 13.5px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.пузырь .файл-текст small {
  font-size: 11.5px;
  opacity: 0.66;
}

/* 🔴 «ЕЩЁ НЕ У НАС» ГОВОРИТ О СЕБЕ СЛОВАМИ И ВЫГЛЯДИТ ОЖИДАНИЕМ, А НЕ
   ОТКАЗОМ. Цвет отказа (`--отказ`) здесь был бы враньём: ничего не сломано,
   файл едет. Приглушённый текст — то же, что у «сообщение удалено». */
.пузырь .вложение.ждёт-файла {
  opacity: 0.7;
  font-style: italic;
}

/* Движение уважает выбор человека — как и у появления пузыря выше. */
@media (prefers-reduced-motion: reduce) {
  .пузырь .файл-строка {
    transition: none;
  }
  .пузырь .файл-строка:active {
    transform: none;
  }
  /* Гифка сама по себе движение. Кто просил его убрать — тому и здесь. */
  .пузырь .плеер.гифка video {
    animation-play-state: paused;
  }
}

/* 🔴 НОВОЕ СООБЩЕНИЕ ПОЯВЛЯЕТСЯ ЗАМЕТНО, НО НЕ КРИКЛИВО.

   Живое обновление дописывает пузырь в открытую ленту. Появиться мгновенно
   — значит остаться незамеченным: глаз человека в этот момент на поле
   ввода. Короткий вход снизу говорит «пришло новое» без единого слова.

   `prefers-reduced-motion` уважаем: для кого движение — помеха, тому оно
   помеха и здесь. */
@keyframes пузырь-пришёл {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
.пузырь.свежий {
  animation: пузырь-пришёл 0.22s ease-out;
}
@media (prefers-reduced-motion: reduce) {
  .пузырь.свежий {
    animation: none;
  }
}
/* 🔴 ВРЕМЯ В СВОЁМ ПУЗЫРЕ БЫЛО НЕЧИТАЕМО — 3,66:1 при 10 px. Пересчитано
   по каждому шагу прозрачности: 0,65 → 3,66; 0,75 → 4,50 (ровно на грани);
   0,85 → 5,42. Берём 0,85 и 11 px. */
.когда {
  display: block;
  margin-top: 4px;
  font-size: 11px;
  opacity: 0.85;
}

/* Три точки «печатает» — движение объясняет ожидание. */
.печатает {
  align-self: flex-start;
  display: flex;
  gap: 4px;
  padding: 15px 16px;
  background: var(--слой-1);
  border-radius: 21px;
  border-bottom-left-radius: 7px;
}
.печатает i {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--текст-тихо);
  animation: прыг 1.3s infinite;
}
.печатает i:nth-child(2) {
  animation-delay: 0.18s;
}
.печатает i:nth-child(3) {
  animation-delay: 0.36s;
}
@keyframes прыг {
  0%,
  60%,
  100% {
    opacity: 0.35;
    transform: translateY(0);
  }
  30% {
    opacity: 1;
    transform: translateY(-3px);
  }
}

/* 🔴 ЗАПИСЬ ЭКРАНА — ЭТО ДОКАЗАТЕЛЬСТВО, А НЕ ВЛОЖЕНИЕ. У неё карточка с
   кадром: человек обязан УВИДЕТЬ, что уехало именно то. По этой записи
   разбирается спор о просмотрах (§39.3). */
.запись {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 10px;
  background: var(--слой-1);
  border-radius: var(--р-карты);
  padding: 16px;
}
.запись-верх {
  display: flex;
  align-items: center;
  gap: 13px;
}
.запись-кадр {
  width: 100%;
  max-width: 220px;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  border-radius: 14px;
  background: var(--слой-2);
}
.запись-кадр {
  /* Гнездо кадра — фиксированной ширины и рядом с подписью, а не полосой во
     всю карточку под текстом. Полоса во всю ширину при пустом кадре читается
     как «здесь должно было быть видео, и оно не загрузилось». */
  width: 92px;
  max-width: 92px;
  aspect-ratio: 1 / 1;
  flex: none;
  display: grid;
  place-items: center;
}
.запись-кадр img,
.запись-кадр canvas {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* Пока кадр достают — слово, а не пустота. Пустота читается как поломка. */
.кадр-ждёт {
  font-size: 12px;
  color: var(--текст-тихо);
}
/* Кадр достать не вышло — значок плёнки. Он говорит «файл на месте, картинки
   нет», а пустой прямоугольник говорит «сломалось». */
.кадр-нет {
  color: var(--текст-тихо);
  display: grid;
  place-items: center;
}
.кадр-нет svg {
  width: 26px;
  height: 26px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.ход {
  height: 6px;
  border-radius: var(--р-пилюли);
  background: var(--слой-3);
  overflow: hidden;
}
.ход i {
  display: block;
  height: 100%;
  border-radius: var(--р-пилюли);
  background: var(--деньги);
  transition: width 0.25s ease;
}

.написать {
  position: sticky;
  /* Запас над панелью — 14, а не 8: на живом экране кнопка отправки
     заезжала на рейку углом, и касание попадало то по одной, то по другой. */
  bottom: calc(var(--низ-панели) + 14px);
  display: flex;
  gap: 9px;
  align-items: flex-end;
  padding: 0;
  background: transparent;
  border: 0;
  /* Перенос нужен ради полоски правки: она встаёт ОТДЕЛЬНОЙ строкой над
     полем, а не втискивается между скрепкой и текстом. */
  flex-wrap: wrap;
}

/* 🔴 ПОЛОСКА ПРАВКИ (§97.1). Правим на месте, как в мессенджерах: текст
   уходит в то же поле, а полоска говорит, что происходит.

   `order: -1` вместо перестановки в разметке: разметка описывает СМЫСЛ
   (полоска относится к форме), а порядок на экране — дело слоя вида.
   `flex-basis: 100%` заставляет её занять свою строку целиком. */
.написать .правим {
  order: -1;
  flex-basis: 100%;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 10px 7px 12px;
  margin-bottom: 2px;
  border-radius: 12px;
  /* 🔴 ФОН НЕПРОЗРАЧНЫЙ, И ЭТО НАШЛА ЖИВАЯ ПРОБА НА 390×844.
     Первая редакция брала `rgba(255,255,255,0.06)` — сквозь шесть процентов
     просвечивали пузыри ленты, и слова «Правим сообщение» читались поверх
     чужого текста. Лента прокручивается ПОД липкой формой, и всё, что не
     закрашено насмерть, показывает её насквозь. */
  background: var(--слой-2);
  /* Полоска слева — знак «это про сообщение выше», тот же приём, что у
     цитат в мессенджерах. Цветом берём тот же, что у денег и действий. */
  border-left: 3px solid var(--деньги);
  font-size: 13px;
  line-height: 1.3;
  color: var(--текст-2);
}
/* 🔴 `hidden` — ЭТО ПРОСЬБА, А НЕ ПРИКАЗ, и здесь она была бы перебита
   собственным `display: flex` строкой выше. Ровно эта беда дважды за час
   давала «кашу текста» на его глазах; ворота `check:hidden` её стерегут. */
.написать .правим[hidden] {
  display: none;
}
.написать .правим-знак {
  font-size: 14px;
  color: var(--деньги);
}
.написать .правим-текст {
  flex: 1;
  /* Длинный хвост не растягивает полоску: она обязана остаться в одну
     строку, иначе поле ввода уезжает вниз под клавиатуру. */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Крестик — палец, а не иконка: 32 мало, берём 36 с запасом на промах.
   Меньше 44 сознательно: это отмена, а не действие, и промах по ней стоит
   одного лишнего нажатия, тогда как крупная кнопка съела бы полоску. */
.написать .правим-отмена {
  flex: 0 0 auto;
  width: 36px;
  height: 36px;
  margin: -6px -4px -6px 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0;
  background: transparent;
  color: var(--текст-2);
  font-size: 15px;
  line-height: 1;
  border-radius: 50%;
  cursor: pointer;
}
.написать .правим-отмена:hover {
  color: var(--текст);
}
.написать .правим-отмена:focus-visible {
  outline: 2px solid var(--деньги);
  outline-offset: 1px;
}
/* 🔴 РАЗГОВОР ЗАНИМАЕТ ЭКРАН, А ПОЛЕ СТОИТ ВНИЗУ.
   Найдено рядом с правкой поля: при трёх сообщениях `position: sticky` не
   держал ничего — прижиматься было не к чему, высота `main` равнялась
   высоте содержимого. Поле висело посреди чёрной пустоты, а под ним
   оставалось четыреста пустых точек.

   `svh`, а не `dvh`: `dvh` меняется, когда браузер прячет адресную строку,
   и страница на телефоне дёргается. `svh` — наименьшая высота, она
   постоянна. 72 — шапка, 82 — рейка внизу, 24 — воздух над ней. */
main[data-наэкране="поддержка"] {
  display: flex;
  flex-direction: column;
  /* Высота до самого низа окна (72 — шапка), а НЕ до низа содержимого. */
  min-height: calc(100svh - 72px);
  /* Свой отступ снизу вместо общего: он обязан совпасть с тем, на котором
     стоит липкое поле, иначе между полем и рейкой остаётся дыра. Общий
     отступ у main на 24 точки больше — из-за него дыра и была. */
  padding-bottom: calc(
    var(--низ-панели) + env(safe-area-inset-bottom, 0px) + 14px
  );
}
main[data-наэкране="поддержка"] .написать {
  margin-top: auto;
}

/* 🔴 ПОЛЕ РАСТЁТ САМО, А НЕ ТЯНЕТСЯ ЗА УГОЛОК.
   Общее правило `textarea { resize: vertical }` доставало и сюда, и в углу
   поля висел серый уголок-расширитель. В ленте переписки он лишний вдвойне:
   таскать поле руками никто не будет, а из вида он выбивается — это
   единственная деталь экрана, нарисованная не нами, а браузером.
   Высоту ведёт `подогнатьПоле` в app.js; здесь только потолок и рамки. */
.написать textarea {
  /* 🔴 ОДИН РЯД, А НЕ ТРИ. ЕГО НАХОДКА 30.08: «почему инпут ввода текста и
     кнопки вокруг него стоят в три ряда просто, еще не видел норм
     мессенджера с таким подходом».
     Причина была в ОБЩЕМ правиле выше: `input, textarea, select { width:
     100% }`. В обычной форме это верно, а здесь поле стоит в ряду со
     скрепкой и отправкой, и стопроцентная ширина занимала всю строку —
     соседей выносило переносом (`flex-wrap: wrap`, он нужен полоске
     правки). Три отдельных ряда вместо строки ввода.
     `min-width: 0` обязателен рядом с `flex`: без него поле не сжимается
     ниже своего содержимого, и длинное слово снова ломает ряд. */
  flex: 1 1 0;
  width: auto;
  min-width: 0;
  min-height: 48px;
  max-height: 132px;
  height: 48px;
  border: 0;
  background: var(--слой-1);
  border-radius: 24px;
  padding: 14px 18px;
  resize: none;
  overflow-y: auto;
  /* Скруглить по высоте строки, а не по прямоугольнику: пока текст в одну
     строку, поле остаётся пилюлей, как кнопки рядом. */
  line-height: 20px;
  scrollbar-width: thin;
}
.написать .скрепка {
  width: 48px;
  height: 48px;
  flex: none;
  padding: 0;
  border-radius: 50%;
  background: var(--слой-1);
  color: var(--текст-2);
  display: grid;
  place-items: center;
}
.написать .скрепка svg {
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.9;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.написать .шлём {
  width: 48px;
  height: 48px;
  flex: none;
  padding: 0;
  border-radius: 50%;
  background: var(--деньги);
  color: var(--на-деньгах);
  display: grid;
  place-items: center;
}
.написать .шлём svg {
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.написать .шлём:disabled {
  background: var(--слой-2);
  color: var(--текст-тихо);
}

/* 🔴 ЗАНЯТАЯ КНОПКА-ЗНАЧОК: КОЛЬЦО НА МЕСТЕ СТРЕЛКИ (§82.3).

   Его находка: «нажимаешь на кнопку отправить, стрелка в нём убирается и
   появляется на мгновение какой-то текст». Текст ставился кодом и стирал
   SVG; это починено в app.js. Здесь — то, ЧТО человек видит вместо него.

   ТРИ РЕШЕНИЯ, И КАЖДОЕ ПРОТИВ ОТДЕЛЬНОЙ БЕДЫ:

   • стрелка не удаляется, а ГАСНЕТ (`opacity`) — размер кнопки не меняется,
     и строка ввода не дёргается на каждой отправке;
   • кольцо рисуется псевдоэлементом ПОВЕРХ, а не вместо: нечему пропасть,
     если отправка оборвётся на полпути;
   • `prefers-reduced-motion` останавливает вращение — тем, кому движение
     мешает, остаётся статичное кольцо, а не пустая кнопка. */
.написать .шлём[aria-busy="true"] svg {
  opacity: 0;
}
.написать .шлём[aria-busy="true"]::after {
  content: "";
  position: absolute;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: 2.2px solid currentColor;
  border-top-color: transparent;
  animation: кружение 0.7s linear infinite;
}
.написать .шлём {
  position: relative;
}
@keyframes кружение {
  to {
    transform: rotate(360deg);
  }
}
@media (prefers-reduced-motion: reduce) {
  .написать .шлём[aria-busy="true"]::after {
    animation: none;
    opacity: 0.7;
  }
}

/* ── НИЖНЯЯ ПАНЕЛЬ: выделение ТОЙ ЖЕ ФОРМЫ, ЧТО И ПОДЛОЖКА (§90) ───────── */
/*
   🔴 ЕГО НАХОДКА 27.08: «нижнее меню немного неровно ставит цвет для
   выбранной страницы из-за скругления, и скругление выбранной страниц не
   совпадает с фоном меню и это режет глаз».

   ЗАМЕР В ЖИВОМ БРАУЗЕРЕ (`getComputedStyle` + `getBoundingClientRect`),
   а не на глаз:

     панель ......... 66 px высотой, радиус 999 → по факту 33 px
     выделение ...... КРУГ 46 px, радиус 23 px
     зазор сверху ... 10,00 px
     зазор снизу .... 10,00 px
     зазор по дуге .. МИНУС 2,69 px

   Отрицательный зазор значит, что у крайних вкладок круг ЗАЕЗЖАЛ за
   скруглённый край панели. Он это и увидел.

   🔴 ПОЧЕМУ СДВИНУТЬ НА ТРИ ПИКСЕЛЯ — НЕ ЛЕЧЕНИЕ. Круг и пилюля это две
   разные формы: подложка говорит «мягкая полоса», выделение — «кнопка».
   Совместить их отступом нельзя, потому что у круга и у дуги панели РАЗНЫЕ
   центры, и зазор между ними меняется по всему обводу.

   🔴 ЧТО СДЕЛАНО. Выделение стало таблеткой, вписанной с отступом 8 px, и её
   радиус равен радиусу панели МИНУС этот отступ:

       радиус панели 33 − отступ 8 = радиус таблетки 25

   При равных радиусах-минус-отступ дуги КОНЦЕНТРИЧНЫ, и зазор между ними
   постоянен по всему обводу — ровно 8 px и сверху, и снизу, и по углу. У
   крайней вкладки он теперь такой же, как у средней.
*/
.панель {
  position: fixed;
  left: 14px;
  right: 14px;
  bottom: calc(16px + env(safe-area-inset-bottom, 0px));
  z-index: 20;
  height: 66px;
  max-width: 612px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  align-items: stretch;
  /* 🔴 ФОН НЕПРОЗРАЧНЫЙ, И ЭТО ПОЧИНКА ПО ЖИВОМУ ЭКРАНУ.
     Прозрачная плёнка с размытием выглядела нарядно на макете, где под
     телефоном была светлая доска, — а на настоящем ЧЁРНОМ фоне панель
     слилась с ним начисто: он это и увидел первым делом. Размытие
     оставлено быть не могло — см. ниже. */
  background: #1c1c20;
  /* 🔴 РАЗМЫТИЕ СНЯТО: оно считалось и выбрасывалось целиком (§213).
     `backdrop-filter` стоял ПОД непрозрачным `#1c1c20` — под такой
     подложкой задника не видно по построению, а браузер всё равно заводил
     отдельный слой сборки и пересчитывал гауссово размытие полосы 612×66
     НА КАЖДЫЙ КАДР, пока под панелью едет список. Панель `fixed` и видна на
     всех пяти экранах. Вид не изменился ни на пиксель: закрытое
     непрозрачным цветом увидеть было нельзя.
     Как надо — рядом: `.шапка` делает то же через `@supports` с
     `color-mix(… 82%, transparent)`, там подложка прозрачная. */
  box-shadow: 0 8px 30px -10px #000;
  border-radius: var(--р-пилюли);
  border: 0;
  /* 🔴 ВОСЕМЬ — ЭТО НЕ «НА ГЛАЗ», А ПОЛОВИНА РАЗНИЦЫ РАДИУСОВ. Меняя это
     число, обязательно поменяйте радиус бегунка: они связаны формулой
     `радиус бегунка = 33 − отступ`, и разъехавшись, вернут его находку. */
  padding: 8px;
}

/* Бегунок — таблетка под активной вкладкой. Один элемент на всю панель, а
   не фон у каждой кнопки: так он может ПЕРЕЕЗЖАТЬ, а не мигать. */
.панель .бегунок {
  position: absolute;
  top: 8px;
  bottom: 8px;
  left: 8px;
  width: calc((100% - 16px) / 5);
  border-radius: 25px; /* = радиус панели 33 − отступ 8; см. разбор выше */
  background: var(--деньги);
  transition: transform 0.34s cubic-bezier(0.22, 1, 0.36, 1);
  pointer-events: none;
}

/* 🔴 ПОЗИЦИЯ БЕГУНКА — ЦЕЛИКОМ В CSS. Ни одной записи стиля из JS: на
   переключение вкладки и так приходится перерисовка экрана, и добавлять к
   ней работу в событийном цикле незачем (П-10, П-27).

   `nth-of-type` считает ТОЛЬКО кнопки, поэтому сам бегунок (он span и стоит
   первым) в счёт не идёт. */
.панель:has(button:nth-of-type(2)[aria-current="page"]) .бегунок {
  transform: translateX(100%);
}
.панель:has(button:nth-of-type(3)[aria-current="page"]) .бегунок {
  transform: translateX(200%);
}
.панель:has(button:nth-of-type(4)[aria-current="page"]) .бегунок {
  transform: translateX(300%);
}
.панель:has(button:nth-of-type(5)[aria-current="page"]) .бегунок {
  transform: translateX(400%);
}

/* 🔴 ЗАПАСНОЙ ПУТЬ БЕЗ `:has()`. Telegram живёт и на старых движках, а без
   `:has()` бегунок остался бы под первой вкладкой НАВСЕГДА — то есть врал бы
   о том, где человек находится. Это хуже, чем отсутствие бегунка. Значит там
   он не показывается вовсе, а активную вкладку красит её собственный фон. */
@supports not selector(:has(*)) {
  .панель .бегунок {
    display: none;
  }
  .панель button[aria-current="page"] {
    background: var(--деньги);
    border-radius: 25px;
  }
}

.панель button {
  position: relative;
  background: none;
  border: 0;
  border-radius: 25px;
  padding: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  /* 🔴 НЕ `--текст-тихо`, И ЭТО ЗАМЕР, А НЕ ВКУС. Тихий цвет (#6e6e78) на
     подложке панели даёт контраст 3,37:1 — ниже нормы 4,5:1 для мелкого
     текста (WCAG AA). Пока подписи не было, цвет судил только значок, и
     сходило с рук: у фигуры контраст читается иначе, чем у букв. Появилась
     подпись — и прежний цвет стал дефектом, который внесла эта же правка.
     `--текст-2` даёт 7,12:1. */
  color: var(--текст-2);
  /* Цвет догоняет бегунок, а не опережает его: иначе подпись вспыхивает на
     пустом месте за треть секунды до того, как под неё приедет таблетка. */
  transition: color 0.24s ease 0.06s;
  min-width: 0;
}

/* Гнездо — обёртка двух значков (линейного и залитого). Прежде оно было
   кругом-подложкой; теперь подложку рисует бегунок, и гнезду остаётся одна
   работа — держать значки. Для раскладки оно прозрачно. */
.панель .гнездо {
  display: block;
  line-height: 0;
}

.панель button svg {
  width: 22px;
  height: 22px;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.9;
  stroke-linecap: round;
  stroke-linejoin: round;
  display: block;
}

/* Подпись. 🔴 ЕЁ НЕ БЫЛО НИ У ОДНОЙ ВКЛАДКИ, и раздел опознавался только
   значком — то есть загадкой на каждый заход, которую первым решает новичок.

   Видимое слово ВХОДИТ в `aria-label` кнопки («Подать» ⊂ «Подать ролик»):
   иначе голос и глаз называют разное, и человек, слышащий одно, а видящий
   другое, перестаёт понимать, о чём речь (WCAG 2.5.3, Label in Name). */
.панель .метка {
  font-size: 10px;
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: 0.01em;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Активная вкладка: залитый значок и тёмный текст поверх таблетки. */
.панель button[aria-current="page"] {
  color: var(--на-деньгах);
}
.панель button .зал {
  display: none;
  fill: currentColor;
  stroke: none;
}
.панель button[aria-current="page"] .лин {
  display: none;
}
.панель button[aria-current="page"] .зал {
  display: block;
}

/* Точка непрочитанного. Привязана к ЗНАЧКУ, а не к колонке: смена формы
   выделения двигала бы её, и метка съезжала бы с плеча значка на пустоту.
   Соседа правки надо проверять вместе с ней, а не по очереди. */
.панель button .метка-вкладки {
  position: absolute;
  top: 8px;
  left: 50%;
  margin-left: 8px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--отказ);
  border: 2px solid #1c1c20;
}
/* На залитой таблетке красная точка в тёмной обводке выглядит грязью:
   обводку берём цветом самой таблетки. */
.панель button[aria-current="page"] .метка-вкладки {
  border-color: var(--деньги);
}

/* 🔴 ПОКОЙ ДВИЖЕНИЯ. Переезд гасится, ЦВЕТ ОСТАЁТСЯ: человек, попросивший
   меньше движения, не просил перестать понимать, где он находится. */
@media (prefers-reduced-motion: reduce) {
  .панель .бегунок,
  .панель button {
    transition: none;
  }
}

/* Совсем узкие телефоны (320): подпись ужимается, но НЕ ИСЧЕЗАЕТ — без неё
   значок снова становится загадкой, и первым её разгадывает новичок.

   🔴 8,5 px — ЗАМЕР, А НЕ ВКУС. При 320 колонка вкладки 55,2 px, а самое
   длинное слово («Помощь») требует 63 px при 10 px и 57 px при 9 px — то
   есть на девяти ещё обрезается. На 8,5 выходит 53,6 и остаётся запас.
   Проверено `scrollWidth > clientWidth` в живом браузере на всех пяти. */
@media (max-width: 359px) {
  /* Поля панели уже: на 320 каждый пиксель поля стоит пятой доли колонки. */
  .панель {
    left: 10px;
    right: 10px;
  }
  .панель .метка {
    /* 8,2, а не 8,5: на 8,5 «Помощь» выходила 56 px в колонку 55 — то есть
       ровно на границе, где округление решает за нас. Запас нужен потому,
       что ширину буквы меняет и шрифт устройства, если Onest не загрузился. */
    font-size: 8.2px;
    letter-spacing: -0.01em;
  }
  .панель button svg {
    width: 20px;
    height: 20px;
  }
}

/* ── ШТОРКА-МЕНЮ (три полоски) ───────────────────────────────────────────
   То, что нужно, но не заслуживает места в пяти вкладках: реквизиты,
   сотрудничество, материалы, профиль, уведомления, правила.

   Открывается СЛЕВА, как в референсе. Затемнение — не украшение: без него
   шторка читается как ещё один экран, и человек не понимает, что позади
   осталось прежнее место. */
.шторка-фон {
  position: fixed;
  inset: 0;
  z-index: 30;
  background: rgba(0, 0, 0, 0.6);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.24s ease;
  border: 0;
  padding: 0;
  border-radius: 0;
}
.шторка-фон.открыта {
  opacity: 1;
  pointer-events: auto;
}
.шторка {
  position: fixed;
  top: 0;
  bottom: 0;
  left: 0;
  z-index: 31;
  width: min(310px, 84vw);
  background: var(--слой-1);
  border-radius: 0 26px 26px 0;
  transform: translateX(-102%);
  transition: transform 0.28s cubic-bezier(0.32, 0.72, 0, 1);
  display: flex;
  flex-direction: column;
  padding: max(18px, env(safe-area-inset-top, 0px)) 0
    max(18px, env(safe-area-inset-bottom, 0px));
  overflow-y: auto;
}
.шторка.открыта {
  transform: translateX(0);
}
/* 🔴 ЗАКРЫТОЕ МЕНЮ ОБЯЗАНО БЫТЬ УБРАНО, А НЕ ОТОДВИНУТО (найдено `check:hidden`
   27.08). В разметке на `.шторка` стоит `hidden`, но `display: flex` выше
   сильнее браузерного гашения — и меню оставалось НАРИСОВАННЫМ, просто
   уехавшим за край через `transform`. На экране этого не видно, а замер
   показал: внутри закрытого меню оставались ЧЕТЫРЕ живые кнопки в обходе
   клавиатурой. Человек с клавиатуры уходил фокусом в невидимое, и на экране
   при этом не менялось ничего.
   Код открытия меню написан в расчёте ровно на это: там стоит кадр ожидания
   «чтобы браузер увидел элемент до смены класса» — то есть автор считал, что
   `hidden` гасит. Полтора года не гасил. */
.шторка[hidden] {
  display: none;
}
/* 🔴 ШАПКА ШТОРКИ — ТОТ ЖЕ ПУНКТ МЕНЮ, ТОЛЬКО КРУПНЕЕ (§82.1).

   Его слова: «отличается от всего наведение, клик на верхнюю». Отличалось
   потому, что шапка была отдельным блоком со своими правилами: чужое
   нажатие, чужой отклик, чужая ветка разбора. Теперь она `.пункт-меню` и
   берёт всё поведение оттуда — здесь остаётся ровно то, чем шапка от
   пункта отличается по СМЫСЛУ: крупнее лицо и крупнее имя. */
.пункт-меню.шапка {
  padding: 10px 18px;
  margin-bottom: 6px;
}
.пункт-меню.шапка .аватар {
  width: 44px;
  height: 44px;
  font-size: 17px;
}
.пункт-меню.шапка .подпись b {
  font-size: 17px;
}
/* 🔴 ГАШЕНИЕ ПУНКТА МЕНЮ — СВОИМ ПРАВИЛОМ, НИЖЕ И ТЯЖЕЛЕЕ (§156.4).

   Браузерное `[hidden] { display: none }` перебивается любым авторским
   `display`, а у `.пункт-меню` он `flex`. Это уже случалось дважды на
   `.рост` (§103) и оба раза давало одну и ту же картину: скрытое стоит на
   экране как ни в чём не бывало. Здесь ценой была бы дверь в FACEIT у
   человека, которому FACEIT недоступен, — то есть обещание пустого экрана.

   Вес: `.шторка` + `.пункт-меню` + `[hidden]` — тяжелее одиночного
   `.пункт-меню`, и стоит НИЖЕ него. Стережёт `check:hidden`. */
/* ПЛАШКА «СТАВКИ ИЗМЕНИЛИСЬ» (§98.4).

   🔴 ТИХАЯ, А НЕ ТРЕВОЖНАЯ, И ЭТО РЕШЕНИЕ. Красная полоса поверх остатка
   читается как «с вашими деньгами беда» — а беды нет: ставки поменялись, и
   это обычное дело. Тревожный цвет здесь стоил бы доверия: человек пугается,
   заходит, видит обычные числа и в следующий раз плашку не читает.

   Место — над остатком, потому что это единственная точка, где человек
   смотрит на деньги и ещё не начал ничего делать. */
.полоса-ставки {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  margin: 0 0 14px;
  padding: 12px 14px;
  border: none;
  border-radius: 14px;
  background: var(--слой-2);
  color: var(--текст);
  text-align: left;
  cursor: pointer;
}
.полоса-ставки:active {
  transform: scale(0.99);
}
/* Действующие условия — весть тише, чем предложение: читать, а не отвечать. */
.полоса-ставки.тихая-полоса .полоса-знак {
  color: var(--текст-2);
}

/* ── Индивидуальные условия (§342.4) ─────────────────────────────────── */
/* Пометка у подписи поля: тише подписи и без капса — добавка, а не заголовок. */
.необяз {
  font-weight: 400;
  text-transform: none;
  letter-spacing: normal;
  color: var(--текст-тихо);
}
.условия-карта {
  display: grid;
  gap: 10px;
}
.условия-слова {
  margin: 0;
  font-size: 15px;
  line-height: 1.45;
  color: var(--текст);
  overflow-wrap: anywhere;
}
.условия-строки {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 6px;
  font-size: 14px;
  line-height: 1.4;
  color: var(--текст);
  font-variant-numeric: tabular-nums;
}
.условия-строки li {
  position: relative;
  padding-left: 16px;
  overflow-wrap: anywhere;
}
.условия-строки li::before {
  content: "";
  position: absolute;
  left: 2px;
  top: 0.55em;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--деньги);
}
.предложение-условий {
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--деньги) 45%, transparent);
}
.условия-кнопки {
  gap: 8px;
}
.условия-кнопки button {
  flex: 1 1 140px;
  min-height: 48px;
}
.полоса-знак {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  flex: none;
  border-radius: 50%;
  background: var(--слой-1);
  color: var(--деньги);
}
.полоса-знак svg,
.полоса-стрелка svg {
  width: 18px;
  height: 18px;
}
.полоса-слова {
  flex: 1;
  min-width: 0;
}
.полоса-слова b {
  display: block;
  font-size: 14px;
}
.полоса-слова small {
  display: block;
  color: var(--текст-тихо);
  font-size: 12px;
}
.полоса-стрелка {
  flex: none;
  color: var(--текст-тихо);
}

/* 🔴 КНОПКА, ПЕРЕСПРАШИВАЮЩАЯ ПЕРЕД ОТВЯЗКОЙ (§156.5).

   Класс ставился в разметке и НЕ ИМЕЛ ПРАВИЛА — то есть кнопка меняла слова
   на «Точно отвязать?» и оставалась ровно такой же на вид. Человек читает
   вопрос и не видит, что это уже другое действие.

   Поймано сторожем `check:dead`, который заведён ровно на это: «класс без
   правила не делает НИЧЕГО, а разметка выглядит верной». */
.тревога {
  background: var(--отказ);
  color: #fff;
}

.шторка .пункт-меню[hidden] {
  display: none;
}
.пункт-меню {
  display: flex;
  align-items: center;
  gap: 13px;
  width: 100%;
  padding: 13px 18px;
  background: none;
  border: 0;
  border-radius: 0;
  font: inherit;
  font-weight: 500;
  color: var(--текст);
  text-align: left;
  cursor: pointer;
}
.пункт-меню:active {
  background: var(--слой-2);
}
.пункт-меню .кружок {
  width: 36px;
  height: 36px;
}
.пункт-меню .кружок svg {
  width: 18px;
  height: 18px;
}
.пункт-меню .подпись {
  flex: 1;
  min-width: 0;
}
.пункт-меню .подпись b {
  display: block;
  font-size: 15px;
  font-weight: 600;
}
.пункт-меню .подпись small {
  display: block;
  font-size: 12.5px;
  color: var(--текст-тихо);
}
.шторка-низ {
  margin-top: auto;
  padding: 16px 18px 0;
  color: var(--текст-тихо);
  font-size: 12.5px;
}

/* ── ПУСТО, ОШИБКИ, МЕЛОЧИ ─────────────────────────────────────────────── */
.пусто {
  text-align: center;
  padding: 38px 18px;
  color: var(--текст-тихо);
}
.пусто .круг-пусто {
  width: 58px;
  height: 58px;
  border-radius: 50%;
  margin: 0 auto 14px;
  background: var(--слой-1);
  display: grid;
  place-items: center;
  color: var(--текст-тихо);
}
.пусто .круг-пусто svg {
  width: 24px;
  height: 24px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.пусто strong {
  display: block;
  color: var(--текст);
  font-size: 16px;
  margin-bottom: 6px;
}

.беда {
  background: #3a1620;
  color: #ffd7dd;
  border: 0;
  border-radius: var(--р-плашки);
  padding: 14px 16px;
  margin-bottom: 12px;
  font-size: 14px;
}

.подсказка {
  color: var(--текст-тихо);
  font-size: 12.5px;
  line-height: 1.45;
  margin: 8px 0 0;
}

.ряд {
  display: flex;
  gap: 8px;
}
.ряд > * {
  flex: 1;
}

a {
  color: var(--деньги);
  text-decoration: none;
}

/* Движение — только там, где оно объясняет. Появление ленты снизу вверх
   повторяет то, как приходит сообщение. */
@keyframes всплыть {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
}
.карта,
.карта-денег,
.пузырь {
  animation: всплыть 260ms cubic-bezier(0.23, 1, 0.32, 1) both;
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

/* ── АКЦИИ ──────────────────────────────────────────────────────────────
   Акция — единственное место, где мы что-то ПРЕДЛАГАЕМ, а не отчитываемся.
   Поэтому у неё карточка цвета денег: это и есть «снимите вот так, и будет
   больше». */
.карта.акции {
  padding: 0;
  background: none;
  margin-bottom: 12px;
  overflow: visible;
}
.акция {
  background: var(--деньги);
  color: var(--на-деньгах);
  border-radius: var(--р-карты);
  padding: 18px;
  margin-bottom: 10px;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}
.акция:last-child {
  margin-bottom: 0;
}
.акция-шапка {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.акция-выгода {
  font-size: 30px;
  font-weight: 800;
  letter-spacing: -0.035em;
  line-height: 1.05;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.акция-имя {
  font-weight: 600;
  font-size: 14.5px;
  opacity: 0.75;
}
.акция-текст {
  margin: 6px 0 0;
  font-size: 13px;
  line-height: 1.45;
  opacity: 0.75;
}
.акция-срок {
  margin: 6px 0 0;
  font-size: 12.5px;
  opacity: 0.62;
}

/* ── ЖИВОЙ РАСЧЁТ ПОД ФОРМОЙ ПОДАЧИ ──────────────────────────────────────
   🔴 Это ответ на главный вопрос человека — «сколько мне заплатят», — и
   потому выглядит как ответ, а не как подсказка: сумма крупная, разбор
   мелкий и тихий под ней. */
.подсказка.расчёт-готов {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 18px;
  border-radius: var(--р-карты);
  background: var(--слой-1);
  border: 0;
  color: var(--текст-2);
}
.расчёт-сумма {
  font-size: 28px;
  font-weight: 800;
  letter-spacing: -0.035em;
  line-height: 1.1;
  color: var(--текст);
  font-variant-numeric: tabular-nums;
}
.расчёт-сноска {
  font-size: 12.5px;
  color: var(--текст-тихо);
}
/* Разбор — то, чем человек пересчитает сумму на калькуляторе и убедится,
   что мы не выдумали её. */
.расчёт-разбор {
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--текст-тихо);
}
.расчёт-разбор .ступень {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 2px 0;
}
.расчёт-разбор .ступень b {
  flex: none;
  font-variant-numeric: tabular-nums;
  color: var(--текст);
}

/* Клетки под карточкой заявки: ставка · акция · сумма. */
.клетки {
  display: flex;
  gap: 8px;
  margin-top: 12px;
}
.клетка {
  /* 🔴 Одна клетка не растягивается во всю строку: «Выйдет
     $25 200.00» на всю ширину читается как отдельный блок, а не как одно
     из чисел. Растут они только когда их несколько. */
  flex: 0 1 auto;
  min-width: 96px;
  background: var(--слой-2);
  border-radius: 14px;
  padding: 11px 12px;
  min-width: 0;
}
.клетка small {
  display: block;
  color: var(--текст-тихо);
  font-size: 11.5px;
}
.клетка b {
  font-size: 15px;
  font-weight: 700;
  letter-spacing: -0.02em;
}

/* Строка сводки «название — сумма» внутри карточки (dl). Осталась там, где
   столбец нужен для пересчёта калькулятором. */
.строка {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}
.строка:last-child {
  border-bottom: 0;
}
.строка dt {
  color: var(--текст-тихо);
  font-size: 13.5px;
}
.строка dd {
  margin: 0;
  font-weight: 700;
  color: var(--текст);
  font-variant-numeric: tabular-nums;
}
/* Пояснение прямо под названием строки, а не отдельным абзацем внизу. */
.строка.остаток dt {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.остаток-почему {
  font-size: 11px;
  line-height: 1.4;
  color: var(--текст-тихо);
  max-width: 26ch;
}

/* Примета ролика: площадка, день и ссылка. Ссылка обязана переноситься —
   адреса длиннее экрана, и без переноса карточка разъезжается вбок. */
.примета {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-top: 8px;
  font-size: 12.5px;
  color: var(--текст-тихо);
}
/* 🔴 ССЫЛКА НА РОЛИК — ЭТО ЦЕЛЬ КАСАНИЯ, А НЕ СТРОЧКА ТЕКСТА.
   Строка адреса в 18 пикселей высотой — ровно высота кегля — читалась
   разметкой как подпись, а пальцем по ней БЬЮТ: это единственный путь
   открыть свой ролик из заявки.

   Двадцать шесть пикселей до границы Apple HIG набираются отступами сверху
   и снизу. Отрицательные поля возвращают строку на место: она остаётся там
   же, где стояла, а область нажатия выросла.

   🔴 ОТСТУПЫ, А НЕ `min-height`: строка бывает в две строки при длинном
   адресе, и жёсткая высота обрезала бы вторую. */
.примета a {
  overflow-wrap: anywhere;
  color: var(--текст-2);
  display: inline-block;
  padding: 13px 0;
  margin: -13px 0;
}

/* Метка только для чтения с экрана: поле без метки читается как «правка
   текста», и человек не знает, куда пишет. Прятать через `display:none`
   нельзя — тогда её не прочтёт и читалка. */
.невидимка {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Сколько дойдёт после комиссии — зелёным, когда сумма годится, и красным,
   когда ниже порога: ответ на «нажимать или нет» ДО нажатия. */
#дойдёт.дойдёт-готово {
  color: var(--зачтено);
}
#дойдёт.дойдёт-мало {
  color: var(--отказ);
}

/* ── СТОЛБЧАТЫЙ ГРАФИК ЗАРАБОТКА ────────────────────────────────────────
   Выделенный столбец с биркой — приём второго референса. Столбец метит
   САМЫЙ ДОРОГОЙ день, а не последний: человек ищет глазами свой лучший
   результат, а не хронологию. */
.график {
  padding: 16px 16px 14px;
}

/* 🔴 ТРИ ГНЕЗДА ПОСТОЯННОЙ ВЫСОТЫ — «КОГДА · СКОЛЬКО · ИЗ ЧЕГО».
   Его находка 27.08: «карточка может прыгать когда перебираешь даты». Она и
   прыгала: подписи разной длины меняли высоту шапки, а с ней уезжал весь
   экран под графиком. Высота каждой строки закреплена ЗДЕСЬ и не зависит от
   того, что в неё положили. Перенос запрещён, длинное подрезается многоточием
   — лучше подрезать хвост, чем двигать полэкрана. */
/* 🔴 ПЕРЕКЛЮЧАТЕЛЬ ПЕРИОДА (§319) — НАД СТРОКОЙ «ЗА 7 ДНЕЙ», А НЕ ПОД НЕЙ.

   Порядок чтения сверху вниз: чем смотрим → за сколько → сколько → почему
   столько. Поставленный ниже суммы, переключатель читался бы как подпись к
   ней, а он её МЕНЯЕТ.

   Цель нажатия на пальце — 44 пункта по высоте (правило §299): у чипа своя
   высота 26, остальное добирается отступом-невидимкой через `::after`. Так
   ряд остаётся плотным, а палец не промахивается. */
/* 🔴 КРАЙНИЕ ПОДПИСИ ГРАФИКА — ПРИЖИМАЮТСЯ ВНУТРЬ, А НЕ ЦЕНТРУЮТСЯ (§319).

   Подпись «07.09» шире своего столбца вчетверо: на 320 столбец 9,6 px, а
   подпись 34. Отцентрованная по последнему столбцу, она уезжает за край
   карточки и обрезается — поймано промером, не глазами.

   Сдвиг в долях ШИРИНЫ ПОДПИСИ, а не столбца: столбец меняется от периода к
   периоду, подпись — нет. */
/* Скрытая подпись держит место: ряд не прыгает при смене периода. */
.день-подпись.подпись-скрыта {
  visibility: hidden;
}
/* 🔴 КРАЙНЯЯ ПОДПИСЬ: СДВИГ МЕНЬШЕ ЗАЗОРА (§319). Три попытки, и каждую
   опроверг снимок — числа во всех трёх говорили «всё хорошо».

   1. `translateX(-40%)` — проценты считаются от ширины КОРОБКИ, а она со
      столбец (8 px). Сдвиг вышел 3 px вместо десяти, подпись осталась
      обрезанной до «07.0»;
   2. `translateX(-1.2em)` — 14 px при зазоре между подписями 10: подпись
      стала видна и НАЛЕЗЛА на соседнюю, «02.0*07.09»;
   3. `padding-inline` у ряда — отступ съел ряд, столбцы пропали вовсе.

   Работает пятое, и оно про ДВА числа сразу: подписей должно быть меньше
   (зазор в замере поднят с 6 px до 20 — на 320 это четыре подписи вместо
   шести, с промежутком около 30), и только тогда сдвиг в 1,4em (16 px)
   уводит крайнюю из-под края карточки, не задевая соседку.

   То есть сдвиг лечится не сдвигом, а ЧИСЛОМ ПОДПИСЕЙ. Пока их шесть,
   никакой сдвиг не помещается: 6 × 34 текста в ряду 256 оставляют по 10 px,
   и любой сдвиг съедает зазор целиком.

   🔴 И ВЫВОД ШИРЕ ЭТИХ ВОСЬМИ ПИКСЕЛЕЙ: у подписи, которая шире своей
   коробки, ни один промер не отвечает на вопрос «видно ли её». Коробка
   внутри карточки, текст снаружи; `Range` не знает про сдвиг, а сдвиг не
   знает про соседку. Отвечает только снимок. */
.день-подпись.подпись-справа {
  transform: translateX(-1.4em);
}
.день-подпись.подпись-слева {
  transform: translateX(1.4em);
}

.график-периоды {
  display: flex;
  gap: 6px;
  margin: 0 0 8px;
}
.чип-период {
  position: relative;
  appearance: none;
  border: 0;
  font: inherit;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.04em;
  padding: 5px 10px;
  border-radius: 999px;
  cursor: pointer;
  color: var(--текст-тихо);
  background: var(--низ);
  transition:
    background 140ms ease,
    color 140ms ease;
}
.чип-период.выбран {
  /* 🔴 ТОКЕН СУЩЕСТВУЕТ, А НЕ УГАДЫВАЕТСЯ (§334.27).

     Здесь стояло `var(--фон)` — переменной с таким именем в файле НЕТ
     ни одной, и запасного значения не было. `color` наследуется, значит
     правило просто не применялось и доезжал белый от `body`.

     Счёт: #ffffff на #ff6e40 даёт 2,78 при норме 4,5 — нечитаем ИМЕННО
     выбранный чип, тот, по которому человек понимает, за какой срок ему
     показаны деньги. `--на-деньгах` (#140600) даёт 7,16 и заведён ровно
     для текста поверх денежного цвета. */
  color: var(--на-деньгах, #140600);
  background: var(--деньги);
}
@media (pointer: coarse) {
  /* Невидимая надставка до 44 пунктов: сам чип не растёт, а цель — да. */
  .чип-период::after {
    content: "";
    position: absolute;
    inset: -9px -4px;
  }
}
@media (prefers-reduced-motion: reduce) {
  .чип-период {
    transition: none;
  }
}

.график-когда,
.график-повод {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.график-когда {
  height: 15px;
  line-height: 15px;
  color: var(--текст-тихо);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
}
.график .сумма-графика {
  height: 34px;
  line-height: 34px;
  margin-top: 3px;
  font-size: 28px;
  font-weight: 800;
  letter-spacing: -0.035em;
}
.график-повод {
  height: 18px;
  line-height: 18px;
  margin-top: 1px;
}
.график .рост {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  color: var(--зачтено);
  font-size: 13px;
  font-weight: 600;
}
.график .рост.вниз {
  color: var(--текст-тихо);
}
/* 🔴 ГАШЕНИЕ — ПОСЛЕДНИМ И СИЛЬНЕЕ ВСЕХ. ДВА РАЗА ПОДРЯД НЕ СРАБОТАЛО.
   Первая редакция §103 понадеялась на браузерное `[hidden] { display: none }`
   — его перебивает любой авторский `display`, а у `.рост` стоит
   `inline-flex`. Написал своё правило — и оно тоже проиграло: `.график-повод
   > [hidden]` весит РОВНО столько же, сколько `.график .рост` (два класса), а
   при равном весе побеждает написанное ниже. Моё стояло выше.
   Итог обоих промахов человек читал одинаково: «↑ $1 808.70 к прошлым дням
   1 начисление» — две подписи в одну строку. Поймал он, дважды, за минуты.
   Теперь правило и ТЯЖЕЛЕЕ (три класса), и НИЖЕ. Стережёт `check:hidden`. */
.график .график-повод > [hidden],
.график .график-когда[hidden] {
  display: none;
}
.график .рост svg {
  width: 13px;
  height: 13px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* 🔴 КОЛОНКА ДНЯ — ЦЕЛИКОМ КНОПКА, СВЕРХУ ДОНИЗУ, ВМЕСТЕ С ПОДПИСЬЮ (§103).
   Нарисованный столбец нулевого дня — это 8 пикселей высоты. Повесить
   касание на него значило бы сделать пустой день недостижимым пальцем —
   а именно пустой день и хотят ткнуть: «почему тут ноль».
   Колонка на 390 пикселях выходит 45×136 при пороге 44×44. */
.столбцы {
  display: flex;
  align-items: stretch;
  gap: 1px;
  margin-top: 22px;
}
.день-кн {
  /* 🔴 `flex: 1 1 0` И `min-width: 0`, А НЕ `flex: 1` (§319).

     `flex: 1` — это `flex: 1 1 auto`, то есть базой берётся ШИРИНА
     СОДЕРЖИМОГО. Содержимое здесь — подпись: «Пн» это 20 px, а «13.08» уже
     34. Пока столбцов было семь, ряд помещался (7 × 20 = 140 при 256) и
     никто ничего не замечал. На тридцати столбцах с датами вышло 30 × 34 =
     1020 px в ряду шириной 256 — ряд переполнился, и на экране остался край
     графика: два столбца из тридцати.

     Найдено промером: подписи стояли на 351, 529, 706… при карточке до 304.
     Глазами это читалось как «подписи налезают на край» — то есть я почти
     починил СЛЕДСТВИЕ (прореживание подписей), не тронув причину.

     `1 1 0` заставляет столбцы делить ряд поровну, `min-width: 0` снимает
     запрет сжиматься ниже содержимого. Подпись при этом свободно вылезает
     за свой столбец — она и должна, её прореживает и прижимает подгонка. */
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 9px;
  padding: 0;
  border: 0;
  background: transparent;
  border-radius: 10px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
/* Зазор между СТОЛБЦАМИ живёт внутри касания, а не между кнопками: иначе
   между колонками появлялась мёртвая полоса шириной в промежуток. */
.столб-ложе {
  display: flex;
  align-items: flex-end;
  height: 108px;
  padding: 0 3px;
}
.столб {
  width: 100%;
  background: var(--слой-2);
  border-radius: 7px;
  /* 🔴 ПУСТОЙ ДЕНЬ ВИДЕН. При 4 пикселях столбец нулевого дня
     сливался с фоном, и неделя из одного заработка выглядела как один
     столбец в пустоте — то есть график не читался как неделя вовсе. */
  min-height: 8px;
  transition:
    background-color 0.16s ease-out,
    opacity 0.16s ease-out;
}
.день-подпись {
  color: var(--текст-тихо);
  font-size: 11.5px;
  text-align: center;
  transition: color 0.16s ease-out;
}
/* 🔴 ПУСТОЙ ДЕНЬ И «ЗАРАБОТАЛ КОПЕЙКУ» — РАЗНЫЕ НА ВИД.
   Оба упирались в нижний предел высоты и рисовались одинаковым бруском:
   потолок недели тысяча, доля семи долларов — полпроцента. График врал про
   «ничего». Пустой теперь ниже и глуше, но виден: убрать его совсем значило
   бы, что неделя из двух заработков читается как два дня подряд. */
.столб.столб-пуст {
  min-height: 5px;
  background: color-mix(in srgb, var(--слой-2) 60%, transparent);
}
/* Сегодняшняя подпись ярче прочих: ряд из семи одинаковых сокращений не
   говорит, где в нём «сейчас», и человек ищет свой день пересчётом. */
.день-кн.нынче .день-подпись {
  color: color-mix(in srgb, var(--текст) 55%, var(--текст-тихо));
}
/* Выбор: прочие гаснут, выбранный горит. Приём статистики Telegram и Apple
   Health — сравнение остаётся видимым, внимание уходит на выбранный. */
.столбцы.выбрано .столб {
  opacity: 0.4;
}
.столбцы.выбрано .день-кн[aria-pressed="true"] .столб {
  opacity: 1;
  background: var(--деньги);
}
.столбцы.выбрано .день-кн[aria-pressed="true"] .день-подпись {
  color: var(--текст);
  font-weight: 700;
}
.день-кн:focus-visible {
  outline: 2px solid var(--деньги);
  outline-offset: 2px;
}
.день-кн:active .столб {
  transform: scaleY(0.97);
  transform-origin: bottom;
}
@media (prefers-reduced-motion: reduce) {
  .столб,
  .день-подпись {
    transition: none;
  }
  .день-кн:active .столб {
    transform: none;
  }
}

/* ── КРУПНЫЙ ВВОД СУММЫ ────────────────────────────────────────────────── */
.сумма-ввод {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 48px;
  font-weight: 800;
  letter-spacing: -0.045em;
  padding: 14px 0 6px;
}
.сумма-ввод input {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: inherit;
  text-align: center;
  width: 100%;
  outline: 0;
}
.сумма-ввод input:focus {
  outline: 0;
}

/* ── ЭКРАН ВЫВОДА ───────────────────────────────────────────────────────
   🔴 Всё, что здесь есть, нарисовано НАМИ. Его слова 26.08: «у нас
   даже там селект дефолт браузерный когда все должно быть кастомное и
   красивое». Браузерных органов на экране, где человек забирает свои
   деньги, быть не должно ни одного: они выглядят чужими ровно там, где
   доверие важнее всего. */

/* Подпись группы — та же роль, что у `label`, но группе `label` не
   положен: подписываем через `aria-labelledby`. */
.поле .подпись {
  display: block;
  margin-bottom: 8px;
  font-size: 13px;
  font-weight: 600;
  color: var(--текст-тихо);
}

/* Поле суммы: знак валюты слева, «Всё» справа, ввод посередине и крупный —
   это главное число экрана, и набирают его пальцем. */
.поле-суммы {
  display: flex;
  align-items: center;
  gap: 4px;
  background: var(--слой-1);
  border-radius: var(--р-плашки);
  padding: 0 8px 0 16px;
}
.поле-суммы .знак {
  font-size: 26px;
  font-weight: 800;
  color: var(--текст-тихо);
  line-height: 1;
}
.поле-суммы input {
  flex: 1;
  min-width: 0;
  background: none;
  border: 0;
  padding: 16px 4px;
  font-size: 26px;
  font-weight: 800;
  letter-spacing: -0.03em;
}
.поле-суммы input:focus {
  outline: none;
}
/* Обод рисует ВСЁ поле целиком, а не одну его середину: иначе рамка
   обрезает знак валюты и кнопку, и поле разваливается на три предмета. */
.поле-суммы:focus-within {
  outline: 2px solid var(--деньги);
  outline-offset: 1px;
}
.поле-суммы .всё {
  /* 🔴 ВИД 37 px, КАСАНИЕ 45 (§313 круг 20). Кнопка ставит «всю сумму» на
     экране ВЫВОДА ДЕНЕГ, и мерка §192 требует 44: у неё было 52×37, то есть
     семи точек не хватало. Растить саму кнопку нельзя — она стоит в одной
     строке с полем суммы и разъехалась бы с ним по высоте.

     Приём тот же, что у `button.мелкая` двумя тысячами строк выше: невидимый
     слой поверх. Вид не меняется ни на точку, палец получает своё. */
  position: relative;
  flex: none;
  border: 0;
  background: var(--слой-3);
  color: var(--текст);
  font: inherit;
  font-size: 13px;
  font-weight: 700;
  padding: 9px 14px;
  border-radius: 999px;
  cursor: pointer;
}
.поле-суммы .всё::after {
  content: "";
  position: absolute;
  /* 37 + 2×4 = 45 — с запасом. По ширине 52 и так больше порога. */
  inset: -4px 0;
}
.поле-суммы .всё:active {
  transform: scale(0.95);
}

/* Ссылка на правила — одна на всё приложение (§61). Тихая строка, но
   настоящая кнопка: по ней целятся пальцем, значит ей нужна высота. */
.ссылка-правила {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 14px 0;
  padding: 14px 16px;
  background: var(--слой-1);
  border: 0;
  border-radius: var(--р-плашки);
  color: var(--текст-2);
  font: inherit;
  font-size: 14px;
  text-align: left;
  cursor: pointer;
}
.ссылка-правила .знак {
  display: grid;
  place-items: center;
  color: var(--деньги);
}
.ссылка-правила .знак svg {
  width: 19px;
  height: 19px;
  fill: none;
  stroke: currentColor;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.ссылка-правила .слова {
  flex: 1;
  min-width: 0;
}
.ссылка-правила .стрелка {
  display: grid;
  place-items: center;
  color: var(--текст-тихо);
}
.ссылка-правила .стрелка svg {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.ссылка-правила:active {
  background: var(--слой-2);
}

/* ── ЧИСЛО В КРУЖКЕ ────────────────────────────────────────────────────────
   Кружок по всему приложению носит значок; здесь он носит ЧИСЛО — сколько
   раз показать баннер. Приём тот же, слово другое, поэтому и правило одно:
   табличные цифры, чтобы «1» и «2» стояли одинаково, и вес как у значка.

   🔴 Заменило собой таблицу из трёх колонок с шапкой. Она была приёмом
   большого экрана: на 390 пикселях под колонку «Сколько» оставалось 34
   пикселя, а её же заголовок занимал вдвое больше — и налезал на соседний.
   Ширинами это не лечится, потому что беда не в ширинах, а в форме. */
.кружок.счётный {
  font-size: 15px;
  font-weight: 700;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}

/* ── ШАГИ «КАК СНЯТЬ ПОДТВЕРЖДЕНИЕ» ────────────────────────────────────────
   Нумерация здесь несёт смысл, а не украшает: это настоящая
   последовательность, и порядок в ней — часть правила (запись обязана
   начаться ДО того, как открыт ролик). Поэтому номера крупные и
   собственные, а не браузерные точки. */
.шаги {
  list-style: none;
  counter-reset: шаг;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.шаги li {
  counter-increment: шаг;
  position: relative;
  padding-left: 34px;
  font-size: 14px;
  line-height: 1.45;
}
.шаги li::before {
  content: counter(шаг);
  position: absolute;
  left: 0;
  top: -1px;
  width: 23px;
  height: 23px;
  border-radius: 50%;
  background: var(--слой-2);
  color: var(--деньги);
  font-size: 12px;
  font-weight: 700;
  display: grid;
  place-items: center;
  font-variant-numeric: tabular-nums;
}
.шаги li small {
  display: block;
  margin-top: 3px;
}

/* ── СВЁРНУТАЯ ПАМЯТКА ─────────────────────────────────────────────────────
   Приём тот же, что у списка правил: разделитель, а не рамка. Коробка вокруг
   подсказки на 390 пикселях крадёт две колонки текста и добавляет третий
   уровень вложенности к тому, что и так лежит в карточке внутри поля.

   🔴 СОБСТВЕННЫЙ МАРКЕР УБРАН ЯВНО И ДВАЖДЫ. Chrome убирает его правилом
   `list-style`, Safari — только `::-webkit-details-marker`. Оставь одно —
   и на iPhone рядом со своей стрелкой стоит чужой треугольник. */
.памятка {
  border-top: 1px solid var(--слой-2);
  margin-top: 14px;
  padding-top: 4px;
}
.памятка > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 11px 0;
  cursor: pointer;
  list-style: none;
  font-size: 14px;
  font-weight: 600;
  color: var(--текст-2);
  /* Палец попадает по всей строке, а не по восьми буквам. */
  -webkit-tap-highlight-color: transparent;
}
.памятка > summary::-webkit-details-marker {
  display: none;
}
.памятка > summary:active {
  color: var(--текст);
}
.памятка .стрелка {
  flex: none;
  display: grid;
  place-items: center;
  color: var(--текст-тихо);
  transition: transform 0.18s ease;
}
.памятка[open] > summary .стрелка {
  transform: rotate(180deg);
}
.памятка .стрелка svg {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.памятка .шаги {
  padding-bottom: 6px;
}
@media (prefers-reduced-motion: reduce) {
  .памятка .стрелка {
    transition: none;
  }
}

/* ── СОГЛАСИЕ С ПРАВИЛАМИ (§78) ────────────────────────────────────────────
   Тот же тумблер, что у признаков ролика, но отделён сверху: это не признак
   ролика, а условие подачи. Разделитель говорит об этом без единого слова.

   🔴 Цвет отметки — ДЕНЕЖНЫЙ, как у остальных: согласие тоже влияет на то,
   заплатят ли. Заводить ему свой цвет значило бы сказать, что оно другого
   рода, а оно того же. */
.тумблер.согласие {
  margin-top: 16px;
}
.тумблер.согласие::before {
  content: "";
  display: block;
  position: absolute;
  left: 16px;
  right: 16px;
  top: -8px;
  height: 1px;
  background: var(--слой-2);
}
/* Строка расчёта: пока считать нечего — её нет ВОВСЕ.
   🔴 Найдено замером, а не глазом: у неё стоял `margin: 14px 0` прямо в
   разметке, и пустой блок держал 14 px пустоты между дверью в правила и
   кнопкой. Зазор читался как осознанный разделитель, хотя был призраком
   пустого элемента: соседние флажки стоят на 10. */
.подсказка.расчёт {
  margin: 14px 0;
}
.подсказка.расчёт:empty {
  margin: 0;
}

/* 🔴 ПОГАШЕННАЯ КНОПКА БЕЗ ОБЪЯСНЕНИЯ — ТУПИК (§34). Строка говорит, чего
   не хватает, и стоит там, где человек ищет причину, — под кнопкой.
   (До §85 комментарий это обещал, а строка стояла НАД кнопкой и другим
   цветом; связь «погашена потому что» приходилось додумывать.)

   🔴 ЦВЕТ ТИХИЙ, А НЕ КРАСНЫЙ, И ЭТО ЕГО НАХОДКА 27.08: «блок просто
   стрёмный, и выбивается слишком из дизайна и семантики».

   Красный у нас значит ОТКАЗ — им написаны отклонённые заявки и отрицательные
   суммы. Здесь ничего не отклонено: человек ещё не отправлял, а его уже
   ругают. Значение цвета, употреблённое не по делу, стирается ВЕЗДЕ: если
   красным пишут и отказ, и «вы кое-что не заполнили», то оно перестаёт
   значить «плохо» там, где это правда. */
.подсказка.почему-нельзя {
  color: var(--текст-2);
  margin-top: 10px;
  text-align: center;
}

/* ── РАНГ ─────────────────────────────────────────────────────────────────
   Полоса, а не значок: значок отвечает «кто вы», полоса отвечает ещё и
   «сколько осталось». Второй вопрос человек задаёт чаще. */
.карта
/* Полоса тонкая: она отмечает путь, а не зовёт нажать. Толстая читалась бы
   как орган управления — а нажимать тут нечего. */
.ранг-полоса {
  height: 6px;
  border-radius: 999px;
  background: var(--слой-3);
  overflow: hidden;
}
.ранг-полоса i {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: var(--деньги);
  /* Нулевая доля всё равно видна точкой: пустая полоса читается как
     «сломалось», а не как «вы в начале пути». */
  min-width: 6px;
  transition: width 0.4s ease;
}
@media (prefers-reduced-motion: reduce) {
  .ранг-полоса i {
    transition: none;
  }
}
.ранг-низ {
  display: block;
  margin-top: 8px;
  font-size: 12.5px;
  line-height: 1.4;
  color: var(--текст-тихо);
}

/* 🔴 НА НУЛЕ ПОЛОСА ПУСТАЯ, А НЕ С ТОЧКОЙ.
   Первая редакция ставила `min-width: 6px`, чтобы «полосу было видно». Снял
   экран новичка — вышла одинокая оранжевая точка у левого края, которая
   читается как соринка на экране, а не как «вы в начале пути». Пустая
   полоса на нуле честнее и спокойнее: рядом словами написано, сколько
   осталось. */
.ранг-полоса i[style*="width:0%"] {
  min-width: 0;
}
.ранг-низ {
  display: block;
  color: var(--текст-тихо);
  font-size: 12.5px;
  line-height: 1.45;
}
@media (prefers-reduced-motion: reduce) {
  .ранг-полоса i {
    transition: none;
  }
}

/* ── ТРИ ЧИСЛА В РЯД ──────────────────────────────────────────────────────
   У «.клетки» флекс без переноса: три клетки на 390 пикселях сжимались бы в
   кашу. Трое — это сетка, где каждой достаётся ровно треть. */
.клетки.трое {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
  margin-top: 0;
}
.клетки.трое .клетка {
  min-width: 0;
}
.клетки.трое .клетка b {
  /* 🔴 `display: block` ОБЯЗАТЕЛЕН, И БЕЗ НЕГО ВСЁ НИЖЕ НЕ РАБОТАЕТ.
     `b` по умолчанию СТРОЧНЫЙ, а `overflow` и `text-overflow` на строчные
     боксы не действуют вовсе. Правила стояли, выглядели верно и не делали
     НИЧЕГО: «12 862 000» вытекало из своей клетки на соседнюю и обрезалось
     уже краем карточки. Найдено замером в браузере, не глазами: на снимке
     это читается как «блок выехал», а причина — в типе бокса. */
  display: block;
  font-variant-numeric: tabular-nums;
  /* Длинное число не должно выталкивать соседей: пусть уменьшится оно, а не
     поедет вся сетка. */
  font-size: clamp(13px, 4.2vw, 16px);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Подпись над числом тоже не смеет распирать колонку. */
.клетки.трое .клетка small {
  overflow: hidden;
  text-overflow: ellipsis;
}
/* 🔴 НА УЗКОМ ЭКРАНЕ ТРИ ДЕНЕЖНЫЕ КОЛОНКИ НЕ ПОМЕЩАЮТСЯ — ЭТО ФИЗИКА.
   На 320 пикселях колонка выходит 55 пикселей по содержимому, а «$1 929.30»
   занимает 69. Обрезать сумму многоточием нельзя: «$1 929…» — это не
   сокращение, это другое число. Значит меняется раскладка, а не шрифт:
   деньги занимают всю строку, два счётчика встают под ними. */
@media (max-width: 479px) {
  .клетки.трое {
    grid-template-columns: 1fr 1fr;
  }
  .клетки.трое .клетка:first-child {
    grid-column: 1 / -1;
  }
}

/* ── ВЕХИ ────────────────────────────────────────────────────────────────
   Два столбца: на 390 пикселях один даёт длинную унылую колонку, три —
   обрезанные подписи. */
.вехи {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px;
}
.веха {
  display: flex;
  /* 🔴 ЗНАЧОК ПО ВЕРХУ, А НЕ ПО ЦЕНТРУ. Снято глазами: у плитки с двумя
     строками названия и двумя строками подписи кружок уезжал на середину
     четырёхстрочного блока и вставал напротив пустоты. По верху он стоит
     напротив первой строки — там, где начинают читать. */
  align-items: flex-start;
  gap: 10px;
  min-width: 0;
  padding: 10px;
  border-radius: 14px;
  background: var(--слой-2);
  /* Невзятая — приглушена целиком, а не серым текстом: разница читается с
     одного взгляда, не вчитываясь. */
  opacity: 0.55;
}
.веха.взята {
  opacity: 1;
}
.веха .кружок {
  width: 30px;
  height: 30px;
}
.веха .кружок svg {
  width: 15px;
  height: 15px;
}
.веха-слова {
  min-width: 0;
}
.веха-слова b {
  display: block;
  font-size: 13px;
  font-weight: 600;
  line-height: 1.25;
}
.веха-слова small {
  display: block;
  color: var(--текст-тихо);
  font-size: 11.5px;
  line-height: 1.3;
  margin-top: 2px;
}

/* ═══════════════════════════════════════════════════════════════════════
   ПРОФИЛЬ НАРЕЗЧИКА — ПО ЕГО РЕФЕРЕНСАМ (§82.1)

   Он прислал три снимка профиля Telegram: «должен быть стиль и расположение
   всего и взаимодействие как в соц сети, а у нас какая-то залупка».
   Разобрано ПРИЁМАМИ, а не «похоже на телеграм»:

     обложка-подложка ....... цветная плашка за шапкой, аватар лежит НА ней
     аватар крупно по центру  лицо — главный опознавательный знак
     имя крупным, ник ниже .. два уровня веса, а не один
     карточки-списки ........ скруглённый блок, внутри ряды с чертой
     плитка слева ........... цветной квадрат, узнаётся боковым зрением
     значение справа ........ один ряд отвечает на «что» и «сколько» сразу
     шеврон ................. отличает ПОКАЗ от ДВЕРИ
     подпись над группой .... мелкими прописными
     липкая шапка ........... при прокрутке остаётся полоса с именем

   🔴 ЧЕГО НА РЕФЕРЕНСЕ НЕТ, И ЭТО ТОЖЕ УКАЗАНИЕ: ни одного квадрата с
   числом посередине, ни одного пояснения под цифрой, ни одной ОБВОДКИ.
   Блоки отделены цветом подложки, а не рамкой.

   🔴 ПРИСТАВКА `пр-` У КАЖДОГО ИМЕНИ — НЕ ПЕДАНТИЗМ. Первая редакция
   называла ряд `.строка`, а это имя в файле уже занято карточкой заявки.
   Чужое правило стояло ниже и затирало отступы: в браузере `padding`
   приезжал `10px 0`, а не заданные `14px 16px`. Он это и увидел —
   «блоки слипшиеся без отступов». Общие имена в общем файле — это ловушка
   с задержкой: она срабатывает не там, где написана.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── ШАПКА ───────────────────────────────────────────────────────────── */
.пр-верх {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 0 16px 20px;
  text-align: center;
}

/* Обложка. Оранжевый уведён почти в чёрный: в полную силу он стал бы вторым
   акцентом и отобрал внимание у сумм, а акцент у нас один — «деньги». */
.пр-обложка {
  position: absolute;
  inset: 0 0 auto;
  height: 132px;
  background: radial-gradient(
    120% 140% at 50% 0%,
    #3a231c 0%,
    #1c1517 58%,
    var(--слой-1) 100%
  );
  border-radius: 0 0 28px 28px;
  pointer-events: none;
}

.пр-аватар {
  position: relative;
  width: 104px;
  height: 104px;
  margin-top: 74px;
  border-radius: 50%;
  overflow: hidden;
  font-size: 38px;
  font-weight: 700;
  color: var(--текст-2);
  background: var(--слой-2);
  /* Кольцо цветом ФОНА, а не белым: отделяет лицо от обложки, ничего не
     рисуя. Белая обводка читалась бы как рамка, а рамок на референсе нет. */
  box-shadow: 0 0 0 4px var(--низ);
}
/* Буква лежит ПОД фото: фото может не приехать (приватность, связь, CSP), и
   пустой круг читается как поломка. */
.пр-аватар .буква {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
}
.пр-аватар .фото {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: var(--слой-2);
}

.пр-имя {
  margin: 14px 0 0;
  font-size: 26px;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.15;
  /* Длинное имя переносится, а не режется: имя человека — не то место, где
     уместно «Александ…». */
  overflow-wrap: anywhere;
}

/* Ник и номер одной строкой через точку — приём второго снимка, где так же
   стоят телефон и ник. Номер здесь потому, что его НАЗЫВАЮТ вслух в
   поддержке: это опознавательный знак, а не строка отчёта. */
.пр-ник {
  margin: 5px 0 0;
  font-size: 15px;
  color: var(--текст-2);
  font-variant-numeric: tabular-nums;
}
.пр-роль {
  margin: 12px 0 0;
}
/* 🔴 ПЛАНКА РОЛИ НЕ ОБРЕЗАЕТСЯ ТРЕТЬЮ ЭКРАНА — ЕГО НАХОДКА 02.09 (§270).
   Его слова: «в профиле планка хозяин и возможно другие просто обрезаются и
   плывут».

   Причина ровно в одной строке: у `.метка` стоит `max-width: 34%`. Она
   верна там, где метку заводили, — в шапке заявки, где метка стоит В РЯД с
   названием и числом и без потолка съедала просмотры («TikTok · 1 4…»).

   А в профиле метка стоит ОДНА, в своей строке, и делить ширину ей не с
   кем. Потолок в треть даёт на 390 около ста восемнадцати точек: «Хозяин»
   ещё влезает впритык, «Проверяющий» переносится на две строки, и пилюля
   из ровной становится кривой. Это и есть «плывёт».

   🔴 ПОЧЕМУ ПРАВКА ЗДЕСЬ, А НЕ У `.метка`. Потолок нужен ровно одному месту
   и там он проверен снимком. Снять его у всех значило бы вернуть обрезание
   просмотров в списке заявок — то есть починить одно, сломав другое. Класс
   один, а мест два, и правку получает то место, у которого своя задача. */
.пр-роль .метка {
  max-width: 100%;
  white-space: nowrap;
}

/* ── ЛИПКАЯ ШАПКА ────────────────────────────────────────────────────── */
.пр-порог {
  position: absolute;
  top: 100px;
  width: 1px;
  height: 1px;
  pointer-events: none;
}
.пр-липкая {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  justify-content: center;
  height: calc(52px + env(safe-area-inset-top, 0px));
  padding-top: env(safe-area-inset-top, 0px);
  font-weight: 650;
  font-size: 16px;
  background: rgba(0, 0, 0, 0.82);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  opacity: 0;
  transform: translateY(-6px);
  transition:
    opacity 0.18s ease,
    transform 0.18s ease;
  pointer-events: none;
}
.пр-липкая.видна {
  opacity: 1;
  transform: none;
}
@media (prefers-reduced-motion: reduce) {
  .пр-липкая {
    transition: none;
  }
}

/* ── РАНГ ────────────────────────────────────────────────────────────── */
.пр-ранг {
  padding: 15px 18px 17px;
  margin: 0 0 12px;
  background: var(--слой-1);
  border-radius: var(--р-карты);
}
.пр-ранг-верх {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 11px;
}
.пр-ранг-имя {
  font-size: 17px;
  font-weight: 650;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.пр-ранг-число {
  flex: none;
  font-size: 13px;
  color: var(--текст-тихо);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
/* Полоса тонкая: она отмечает путь, а не зовёт нажать. Толстая читалась бы
   как орган управления — а нажимать тут нечего. */
.пр-ранг-полоса {
  height: 6px;
  border-radius: 999px;
  background: var(--слой-3);
  overflow: hidden;
}
.пр-ранг-полоса i {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: var(--деньги);
  /* Нулевая доля видна точкой: пустая полоса читается как «сломалось», а не
     как «вы в начале пути». */
  min-width: 6px;
  transition: width 0.4s ease;
}
@media (prefers-reduced-motion: reduce) {
  .пр-ранг-полоса i {
    transition: none;
  }
}
.пр-ранг-низ {
  display: block;
  margin-top: 9px;
  font-size: 12.5px;
  line-height: 1.4;
  color: var(--текст-тихо);
}

/* ── ИТОГ: ГЛАВНОЕ ЧИСЛО СВЕРХУ, СПУТНИКИ ПОД ЧЕРТОЙ ─────────────────────

   🔴 ПЕРВАЯ РЕДАКЦИЯ ЛОМАЛАСЬ РОВНО ТАК, КАК ОН И ПОКАЗАЛ НА СНИМКЕ:
   «$1 929.30» переносилось на две строки — «$1» сверху, «929.30» снизу.
   Причина: главное число и два спутника стояли В ОДНОМ РЯДУ, и на 390
   пикселях ряду не хватало ширины. Сумма растёт вместе с человеком — то
   есть блок ломался бы у самых заработавших, у кого он важнее всех.

   Теперь сломаться нечему: число занимает всю ширину, `nowrap` запрещает
   перенос прямо, `clamp` сжимает кегль вместо переноса, спутники ушли под
   черту в две равные колонки. */
.пр-итог {
  padding: 16px 18px 18px;
  margin: 0 0 4px;
  background: var(--слой-1);
  border-radius: var(--р-карты);
}
.пр-итог-подпись {
  display: block;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--текст-тихо);
}
.пр-итог-число {
  display: block;
  margin-top: 3px;
  font-size: clamp(28px, 9vw, 36px);
  font-weight: 700;
  letter-spacing: -0.03em;
  line-height: 1.1;
  color: var(--деньги);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.пр-итог-спутники {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
  margin-top: 15px;
  padding-top: 15px;
  border-top: 1px solid rgba(255, 255, 255, 0.07);
}
.пр-итог-спутники div {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.пр-итог-спутники b {
  font-size: 18px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.пр-итог-спутники small {
  margin-top: 2px;
  font-size: 12px;
  line-height: 1.3;
  color: var(--текст-тихо);
}

/* ── ЗАГОЛОВОК ГРУППЫ ────────────────────────────────────────────────────

   🔴 ВОЗДУХ МЕЖДУ ГРУППАМИ — ЕГО ПРЕТЕНЗИЯ, И ОНА СПРАВЕДЛИВА.
   28 px до заголовка — расстояние, на котором глаз видит РАЗРЫВ, а не шов.
   10 px после — заголовок принадлежит СВОЕЙ группе и стоит к ней ближе,
   чем к чужой; иначе читается как хвост верхней. */
.пр-заголовок {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin: 28px 6px 10px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--текст-тихо);
}
/* Кнопка в заголовке профиля — та же `тихая мелкая`, что и везде. Здесь
   осталось только снять наследие заголовка: он набран капителью с трекингом,
   а слово на кнопке читается обычным. */
.пр-заголовок button.мелкая {
  letter-spacing: 0;
  text-transform: none;
}
/* Счёт справа — не кнопка, поэтому и не выглядит кнопкой. Одинаковый вид у
   нажимаемого и ненажимаемого учит не верить ни тому ни другому. */
.пр-счёт {
  flex: none;
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--текст-тихо);
  font-variant-numeric: tabular-nums;
}

/* ── ГРУППА И РЯД ────────────────────────────────────────────────────── */
.пр-группа {
  background: var(--слой-1);
  border-radius: var(--р-карты);
  overflow: hidden;
}
.пр-группа + .пр-группа {
  margin-top: 12px;
}

.пр-ряд {
  position: relative;
  display: flex;
  align-items: center;
  gap: 13px;
  width: 100%;
  padding: 14px 16px;
  background: none;
  border: 0;
  color: inherit;
  font: inherit;
  text-align: left;
  /* 🔴 56 px — не «красиво». Нижний предел касания 44, но ряд списка здесь
     главный орган управления, и промах по нему стоит человеку захода. */
  min-height: 56px;
}
/* 🔴 ЧЕРТА НАЧИНАЕТСЯ ТАМ, ГДЕ НАЧИНАЕТСЯ ТЕКСТ, — приём референса.
   Линия во всю ширину режет карточку на клетки и возвращает нас к таблице.
   Отступ слева на ширину плитки делает её разделителем ВНУТРИ одного блока.
   И только МЕЖДУ рядами: линия под последним превращает низ группы в
   обрыв, а на референсе группы заканчиваются мягко. */
.пр-ряд + .пр-ряд::before {
  content: "";
  position: absolute;
  left: 59px;
  right: 0;
  top: 0;
  height: 1px;
  background: rgba(255, 255, 255, 0.07);
}
.пр-ряд.ведёт {
  cursor: pointer;
}
.пр-ряд.ведёт:active {
  background: var(--слой-2);
}
.пр-ряд.ведёт:focus-visible {
  outline: 2px solid var(--деньги);
  outline-offset: -2px;
}

/* Плитка — квадрат со скруглением, как на референсе, а не круг: круги у нас
   заняты состояниями заявки, и путать два словаря нельзя. */
.пр-плитка {
  flex: none;
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: 9px;
  color: var(--на-деньгах);
}
.пр-плитка svg {
  width: 17px;
  height: 17px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.1;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.пр-плитка.п-зачтено {
  background: var(--зачтено);
}
.пр-плитка.п-ждёт {
  background: var(--ждёт);
}
.пр-плитка.п-идёт {
  background: var(--идёт);
}
.пр-плитка.п-отказ {
  background: var(--отказ);
}
.пр-плитка.п-деньги {
  background: var(--деньги);
}
.пр-плитка.п-тихо {
  background: var(--слой-3);
  color: var(--текст-2);
}

.пр-текст {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  font-size: 16px;
  line-height: 1.25;
}
/* 🔴 ПОДПИСЬ В ОДНУ СТРОКУ — ОТ ЭТОГО И «СКАКАЛИ» РЯДЫ.

   Его слова: «в блоке на скрине в профиле немного всё скачет». Причина не
   в правом крае: подпись под именем переносилась на вторую строку, ряд
   становился на 17 px выше соседей, и столбец значений шёл лесенкой.

   Обрезаем многоточием. Это тот случай, когда обрезка честна: подпись —
   пояснение, а не содержание. Полное содержание («№1», «$1 728.00») стоит
   справа и не режется никогда. */
.пр-текст small {
  margin-top: 2px;
  font-size: 12.5px;
  line-height: 1.35;
  color: var(--текст-тихо);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Имя тоже: длинное название площадки не смеет ломать высоту ряда. */
.пр-текст > :first-child,
.пр-текст {
  overflow-wrap: normal;
}
.пр-знач {
  flex: none;
  font-size: 16px;
  font-weight: 600;
  color: var(--текст-2);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.пр-шеврон {
  flex: none;
  width: 15px;
  display: grid;
  place-items: center;
  color: var(--текст-тихо);
}
.пр-шеврон svg {
  width: 15px;
  height: 15px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* Невзятая веха: гаснет ряд целиком, а не одна плитка. Полутон — это «пока
   нет», а не «сломано»; для «сломано» у нас есть красный. */
.пр-ряд.погас .пр-текст {
  color: var(--текст-2);
}
.пр-ряд.погас .пр-плитка {
  opacity: 0.55;
}

/* Шапка «по чему идёт разговор» — та же группа-список, что в профиле, и
   отдельным видом плашки она быть не должна: третий вид карточки на
   четвёртом экране — это уже не система, а набор случаев. */
.пр-группа.предмет {
  /* Отступ сверху — его находка 27.08: плашка была прижата к шапке экрана
     вплотную. Снизу столько же: разговор ниже начинается своим блоком. */
  margin: 12px 0 14px;
}

/* ── ПРАВКА И СКРЫТИЕ СООБЩЕНИЙ (§65) ─────────────────────────────────────
   Его заказ 26.08: «можно ли удалять отправленные сообщения, редактировать
   их?». Правка оставляет обе редакции, «удаление» — это скрытие: строка
   остаётся, текст заменяется словами. */

/* Пометка «изменено» — как у самого Telegram. Правка, о которой не сказано,
   это тихая подмена доказательства. */
.пузырь .правлено {
  font-size: 11px;
  color: var(--текст-тихо);
  margin-left: 6px;
  opacity: 0.85;
}

/* Скрытое читается как скрытое, а не как поломка приложения. */
.пузырь.убрано {
  opacity: 0.65;
}
.пузырь.убрано i {
  color: var(--текст-тихо);
  font-size: 13px;
}

/* 🔴 ОРГАНЫ ПРАВКИ ВИДНЫ ВСЕГДА, А НЕ ПО НАВЕДЕНИЮ. На телефоне наведения
   НЕТ ВОВСЕ: кнопка, появляющаяся на `:hover`, для пальца не существует.
   Поэтому они просто тихие — и становятся ярче при касании. */
/* Подвал пузыря: время, пометка «изменено» и органы — В ОДНОЙ СТРОКЕ.
   Найдено живым снимком: `.когда` блочная, и кнопки падали на следующую
   строку, а у последнего сообщения уходили под поле ввода. */
.пузырь-подвал {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 2px;
}
.пузырь-подвал .когда {
  display: inline;
  margin: 0;
}
.пузырь-органы {
  display: inline-flex;
  gap: 2px;
  margin-left: auto;
}
.пузырь-кнопка {
  /* 🔴 ОБЛАСТЬ НАЖАТИЯ ШИРЕ ЗНАЧКА (`::after` ниже): промах по кнопке правки
     означает промах по кнопке скрытия рядом, а они делают разное. */
  width: 26px;
  height: 26px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: none;
  /* 🔴 ЦВЕТ ОТ ФОНА ПУЗЫРЯ, А НЕ ОДИН НА ВСЕХ. Замер показал: тихий серый
     (#6e6e78) на оранжевом пузыре почти не читается — оба тона средней
     яркости. Наследуем цвет пузыря и гасим прозрачностью: тогда на оранжевом
     кнопки тёмные, на сером — светлые, и обе видны. */
  color: inherit;
  opacity: 0.55;
  font-size: 13px;
  line-height: 1;
  cursor: pointer;
  position: relative;
}
.пузырь-кнопка::after {
  content: "";
  position: absolute;
  /* 🔴 БЫЛО −7 px, ТО ЕСТЬ 40 ПУНКТОВ ВМЕСТО 44 (§299, находка П5·#15).
     Замысел «область шире значка» тут был с самого начала и записан строкой
     выше — не хватило четырёх пунктов до порога, за которым палец перестаёт
     промахиваться. Значок остаётся 26 px: растёт только область. */
  inset: -9px;
}
.пузырь-кнопка:active {
  opacity: 1;
  background: rgba(0, 0, 0, 0.15);
}
.пузырь-кнопка:focus-visible {
  opacity: 1;
  outline: 2px solid currentColor;
  outline-offset: 1px;
}

/* ── ЗАПЕРТАЯ ДВЕРЬ (§93) ───────────────────────────────────────────────
   Пропуск Telegram состарился, и внутрь не пускают. Это состояние ВСЕГО
   приложения, а не плашка в экране: живой экран показал, что шапка при этом
   здоровается («Доброе утро, Никита» + колокольчик), а нижнее меню даёт
   ПЯТЬ дорог в тот же отказ. Одна верная кнопка против пяти неверных — это
   тот же тупик, только нарядный.

   Прячем оболочку целиком и ставим состояние по центру: на экране остаётся
   ровно одно действие, и оно же единственное, которое помогает. */
body.заперто .шапка,
body.заперто .панель,
body.заперто .шторка,
body.заперто .шторка-фон {
  display: none;
}
body.заперто main {
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  /* Панели внизу больше нет — её место под текстом не нужно. */
  padding-bottom: calc(24px + env(safe-area-inset-bottom, 0px));
}
body.заперто .пусто {
  padding: 0 4px;
}
body.заперто .пусто strong {
  font-size: 22px;
}
body.заперто .пусто p {
  margin: 10px 0 26px;
  /* 🔴 ЯРЧЕ ОБЫЧНОГО ТИХОГО ТЕКСТА, И ЭТО НЕ ВКУС. На запертом экране этот
     абзац — ЕДИНСТВЕННОЕ объяснение происходящего: ни шапки, ни меню, ни
     соседнего содержимого рядом нет. Тихий цвет годится там, где текст
     второстепенен; здесь он главный. */
  color: var(--текст);
}

/* 🔴 ПОДТВЕРЖДЕНИЕ УДАЛЕНИЯ — В САМОМ ПУЗЫРЕ (§97.1, §115).
   Прежде спрашивал родной `confirm()`: на телефоне это серое окно во весь
   экран, закрывающее собой ТО САМОЕ сообщение, про которое оно спрашивает.
   Здесь вопрос стоит под текстом — видно, что именно исчезнет. */
.убрать-точно {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid rgba(255, 255, 255, 0.12);
  font-size: 12.5px;
  line-height: 1.35;
  color: var(--текст-2);
}
.убрать-точно span {
  flex: 1 1 100%;
}
/* Обе кнопки — 36 в высоту: это подтверждение внутри пузыря, а не главное
   действие экрана. Ниже 44 сознательно, зато они не разрывают ленту. */
.убрать-точно button {
  min-height: 36px;
  padding: 0 14px;
  border-radius: 10px;
  border: 1px solid rgba(255, 255, 255, 0.16);
  background: transparent;
  color: var(--текст);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}
/* 🔴 ОПАСНОЕ ДЕЙСТВИЕ ОТЛИЧАЕТСЯ НЕ ТОЛЬКО ЦВЕТОМ. Цвет — подсказка, а
   несущее различие даёт слово на кнопке: «Убрать» против «Отмена». Так
   правило про «не цветом единым» соблюдается без лишних значков. */
.убрать-точно .убрать-да {
  border-color: var(--отказ);
  color: var(--отказ);
  font-weight: 700;
}

/* 🔴 НА СВОЁМ ПУЗЫРЕ ЦВЕТА ДРУГИЕ, И ЭТО НЕ ПРИДИРКА.
   Свои сообщения оранжевые, и розовый `--отказ` на оранжевом не читается —
   на живом снимке слово «Убрать» выцвело до нечитаемого. Внутри своего
   пузыря берём тёмный текст: он и есть родной цвет надписей на деньгах. */
.мой .убрать-точно {
  border-top-color: rgba(0, 0, 0, 0.22);
  color: color-mix(in srgb, var(--на-деньгах) 78%, transparent);
}
.мой .убрать-точно button {
  border-color: rgba(0, 0, 0, 0.3);
  color: var(--на-деньгах);
}
.мой .убрать-точно .убрать-да {
  border-color: var(--на-деньгах);
  color: var(--на-деньгах);
}
.мой .убрать-точно button:focus-visible {
  outline-color: var(--на-деньгах);
}
.убрать-точно button:focus-visible {
  outline: 2px solid var(--деньги);
  outline-offset: 1px;
}
/* ══════════════════════════════════════════════════════════════════════════
   ЗАСТАВКА И СКЕЛЕТОНЫ (§157, §158)

   🔴 ПОЧЕМУ ЗДЕСЬ ДВИЖЕТСЯ ТОЛЬКО `transform` И `opacity`.

   Это единственное, что крутится ДО прихода данных, — то есть ровно тогда,
   когда нить занята разбором ответа и сборкой экрана. Любое другое свойство
   (`width`, `background-position`, `left`) заставляет браузер пересчитывать
   раскладку или заново красить КАЖДЫЙ кадр, и заставка начинает воровать
   время у того, чего человек ждёт. Приём тот же, что у бегунка нижней
   панели: ни строчки в событийном цикле.
   ══════════════════════════════════════════════════════════════════════ */

.заставка {
  /* НАКЛАДКА поверх всего: она закрывает и шапку, и нижнюю панель. Иначе
     человек видел бы приветствие «Доброе утро» и пять живых вкладок над
     приложением, которое ещё не знает про него ничего. */
  position: fixed;
  inset: 0;
  z-index: 90;
  background: var(--низ);
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 26px;
  padding: 24px;
  /* Гаснет ЗА 260 мс и снимается из разметки: `visibility` в паре с
     `opacity` нужен, чтобы погасшая накладка перестала ловить нажатия
     раньше, чем её уберут. */
  transition:
    opacity 0.26s ease-out,
    visibility 0.26s;
}
.заставка.ушла {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

.заставка-знак {
  width: 148px;
  height: auto;
  color: var(--текст);
  /* Появление, а не мигание: знак проступает за 420 мс. Без этого при
     мгновенном ответе сервера он вспыхивает и пропадает. */
  animation: знак-проступает 0.42s cubic-bezier(0.23, 1, 0.32, 1) both;
}

@keyframes знак-проступает {
  from {
    opacity: 0;
    transform: scale(0.96);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* Нить вместо кружка-вертушки.

   🔴 ВЕРТУШКА ВРЁТ ПРО ВРЕМЯ, НИТЬ НЕТ. Крутящийся кружок читается как «идёт
   работа неизвестной длины» и на четвёртой секунде — как «зависло». Тонкая
   нить с бегущим отрезком говорит ровно то, что правда: ждём ответа. */
.заставка-нить {
  width: 132px;
  height: 2px;
  border-radius: 2px;
  background: var(--слой-2);
  overflow: hidden;
  position: relative;
}

.заставка-нить i {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: var(--деньги);
  transform: translateX(-100%);
  animation: нить-бежит 1.15s cubic-bezier(0.65, 0, 0.35, 1) infinite;
}

@keyframes нить-бежит {
  0% {
    transform: translateX(-100%);
  }
  100% {
    transform: translateX(100%);
  }
}

/* ── СКЕЛЕТОНЫ ────────────────────────────────────────────────────────────

   Скелетон держит РАСКЛАДКУ и обещает ФОРМУ. Текст «Загружаю…» занимал одну
   строку, а приходил список из десяти карточек — экран прыгал под пальцем. */

.скелет {
  position: relative;
  overflow: hidden;
  background: var(--слой-2);
  border-radius: 8px;
  /* Скелетон — это картинка ожидания, а не текст. Читателю экрана он не
     нужен: про ожидание уже сказано через `aria-busy` на самом экране. */
}

.скелет::after {
  content: "";
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(
    90deg,
    transparent,
    rgba(255, 255, 255, 0.055),
    transparent
  );
  animation: блик 1.45s infinite;
}

@keyframes блик {
  to {
    transform: translateX(100%);
  }
}

.ск-строка {
  height: 12px;
  border-radius: 6px;
}
.ск-строка.высокая {
  height: 16px;
}
.ск-строка.крупно {
  height: 34px;
  border-radius: 10px;
}
.ск-круг {
  border-radius: 50%;
  width: 46px;
  height: 46px;
  flex: 0 0 auto;
}
.ск-карта {
  border-radius: var(--р-карты);
  height: 76px;
}
.ск-плашка {
  border-radius: var(--р-плашки);
  height: 54px;
}

.ск-стопка {
  display: grid;
  gap: 12px;
  padding: 4px 0 8px;
}
.ск-ряд {
  display: flex;
  align-items: center;
  gap: 12px;
}
.ск-столбик {
  display: grid;
  gap: 8px;
  flex: 1 1 auto;
  min-width: 0;
}

/* 🔴 ШИРИНЫ СТРОК РАЗНЫЕ НАРОЧНО. Одинаковые полоски читаются как таблица и
   обещают то, чего не будет; разные — как текст, которым список и является. */
.ск-строка.д70 {
  width: 70%;
}
.ск-строка.д52 {
  width: 52%;
}
.ск-строка.д40 {
  width: 40%;
}
.ск-строка.д34 {
  width: 34%;
}

/* ── УВАЖЕНИЕ К ПРОСЬБЕ «МЕНЬШЕ ДВИЖЕНИЯ» ─────────────────────────────────

   🔴 ГАСНЕТ ДВИЖЕНИЕ, А НЕ СКЕЛЕТОН. Убрать сам скелетон значило бы вернуть
   человеку с вестибулярными нарушениями прыгающий экран — то есть починить
   одно, сломав другое, ровно тому, кому и так труднее. Форма остаётся,
   бежит только тишина. Нить замирает наполовину: она по-прежнему говорит
   «ждём», но не движется. */
@media (prefers-reduced-motion: reduce) {
  .заставка-знак {
    animation: none;
  }
  .скелет::after {
    animation: none;
    opacity: 0;
  }
  .заставка-нить i {
    animation: none;
    transform: translateX(-52%);
  }
}

/* 🔴 ЗНАК НА ЭКРАНЕ ЗАПЕРТОЙ ДВЕРИ (§157).

   Единственный экран, который видит человек, НЕ вошедший внутрь. Знак стоит
   НАД сообщением, а не под ним: сперва «куда я попал», потом «что не так».
   Обратный порядок читается как ошибка неизвестного сайта. */
.знак-на-экране {
  display: block;
  width: 132px;
  height: auto;
  margin: 0 auto 26px;
  color: var(--текст);
}

/* ══ ЗНАК ВНУТРИ ПРИЛОЖЕНИЯ (§157.7) ══════════════════════════════════════

   Три места, где человек бывает постоянно, а знака не было: шапка главного,
   пустые состояния и меню. Все три берут один и тот же `<symbol>` — ноль
   лишних запросов и ни одной копии контура.
   ══════════════════════════════════════════════════════════════════════ */

/* Корона в строке приветствия. Размер по букве, а не «на глаз»: 1em держит
   её вровень с текстом при любом масштабе шрифта у человека. */
.корона-строкой {
  width: 1em;
  height: 1em;
  vertical-align: -0.12em;
  margin-right: 5px;
  color: var(--деньги);
}

/* Бледная корона над словами пустого состояния. */
.пусто-знак {
  display: block;
  width: 46px;
  height: 46px;
  margin: 0 auto 14px;
  color: var(--деньги);
  opacity: 0.14;
}

/* Знак в низу шторки. Блок .шторка-низ существовал и держал слово "topskin"
   текстом; теперь в нём марка. Своего блока не завожу: два подвала в одном
   меню — это и был дубль, который поймал снимок. */
.шторка-знак {
  /* 🔴 БЛОКОМ И ПО СЕРЕДИНЕ — ЕГО ЗАКАЗ 31.08 (§206).
     Дословно: «иконка топскин в меню выезжающем слева стоит, отцентруй её,
     потому что сверху появилась кнопка открыть сайт топскин и теперь она
     слева не подходит».

     Он прав, и причина именно в соседстве. Пока знак стоял один, слева он
     читался как подпись — так подписи и ставят. Кнопка «Открыть сайт
     topskin» отцентрована (`text-align: center` у `.шторка-сайт`), и рядом
     с ней подпись слева перестала быть подписью и стала перекосом: два
     элемента одного блока по разным осям.

     `display: block` обязателен: SVG по умолчанию строчный, и одним
     `margin-inline: auto` его не сдвинуть — правило молча не сработало бы. */
  display: block;
  width: 104px;
  height: auto;
  margin-inline: auto;
  color: var(--текст);
  opacity: 0.28;
}

/* ══ ВХОД В МЕНЮ НАД СООБЩЕНИЕМ (§161) ═══════════════════════════════════

   Здесь стояли два значка — ✎ и ✕ — и жили ровно пятнадцать минут. Теперь
   кнопка одна и стоит всегда: окно судит ПУНКТЫ меню, а не сам вход.
   Стиль `.пузырь-кнопка` тот же, что был у пары; ниже — только то, чем
   одиночная кнопка от неё отличается.
   ═════════════════════════════════════════════════════════════════════ */
.пузырь-органы .пузырь-кнопка {
  /* Три точки шире галочки: строка «⋯» рисуется по центру своей клетки, и
     без сдвига вверх она садится на базовую линию времени рядом. */
  font-size: 17px;
  line-height: 1;
}

/* ══ ПУЗЫРЬ-ЗАГОТОВКА НА ВРЕМЯ ЗАГРУЗКИ (§97·#8) ══════════════════════════

   Его слова: «пользователю вообще непонятно когда файл грузится или нет у
   него ничего красиво не отображается а потом его сообщение спавнится
   просто». Было ровно так: гасла скрепка — и всё; минуту на телефонной
   сети экран не менялся вовсе.
   ═════════════════════════════════════════════════════════════════════ */
.пузырь.шлётся {
  /* Приглушён, пока не ушло: половина прозрачности отличает \отправляется     от \отправлено\ быстрее любой подписи. */
  opacity: 0.72;
}
.шлётся-кадр {
  display: block;
  width: 100%;
  max-width: 240px;
  max-height: 200px;
  object-fit: cover;
  border-radius: 12px;
}
.шлётся-полоса {
  height: 3px;
  margin-top: 8px;
  border-radius: 2px;
  background: rgba(0, 0, 0, 0.25);
  overflow: hidden;
}
.шлётся-полоса i {
  display: block;
  height: 100%;
  width: 0%;
  border-radius: 2px;
  background: currentColor;
  /* Плавность нужна: события прогресса приходят рывками по 64 КБ, и без
     перехода полоса дёргается скачками вместо движения. */
  transition: width 180ms ease-out;
}
.пузырь.сорвалось {
  opacity: 1;
  outline: 1px solid var(--отказ);
}
/* 🔴 ЦВЕТ ОТКАЗА БЕРЁТСЯ ОТ ФОНА ПУЗЫРЯ, А НЕ ОДИН НА ВСЕХ.
   Первая редакция красила слова в --отказ (#fb7185); на оранжевом пузыре это
   два тона средней яркости, и «не отправилось» не читалось вовсе — при том
   что сама надпись и есть всё сообщение. Поймал снимок, а не разбор.
   Тот же случай, что у кнопок пузыря выше: на своём (оранжевом) пишем
   тёмным, на чужом (сером) — красным. */
.пузырь.сорвалось .когда {
  opacity: 1;
  font-weight: 600;
}
.пузырь.мой.сорвалось .когда {
  color: var(--на-деньгах);
}
.пузырь.их.сорвалось .когда,
.пузырь.служебный.сорвалось .когда {
  color: var(--отказ);
}
@media (prefers-reduced-motion: reduce) {
  .шлётся-полоса i {
    transition: none;
  }
}

/* ══ ПОКА ВАС НЕ БЫЛО (§98) ═══════════════════════════════════════════════

   Его заказ: «когда он заходит после выдачи ему должны попапы всплывать что
   произошло». До этого приложение не сообщало НИ О ЧЁМ: письмо уходило в
   бота, а в приложении человек узнавал о событии, только если сам открывал
   колокольчик.

   🔴 КАРТОЧКА СНИЗУ, А НЕ ОКНО ПО ЦЕНТРУ. Приложение живёт в Telegram на
   телефоне: низ экрана — там, где палец, а центр приходится закрывать
   тянущейся через весь экран рукой. Так же встают листы у самого Telegram.
   ═════════════════════════════════════════════════════════════════════ */
.догон-фон {
  position: fixed;
  inset: 0;
  z-index: 130;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  background: rgba(0, 0, 0, 0.6);
  animation: догон-фон-пришёл 160ms ease-out;
}
.догон {
  width: 100%;
  max-width: 520px;
  padding: 20px 18px calc(18px + env(safe-area-inset-bottom, 0px));
  border-radius: var(--р-карты) var(--р-карты) 0 0;
  background: var(--слой-1);
  /* Лист выезжает снизу — движение объясняет, откуда он взялся. Появление
     без движения читается как подмена экрана. */
  animation: догон-пришёл 260ms cubic-bezier(0.23, 1, 0.32, 1);
}
@keyframes догон-фон-пришёл {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}
@keyframes догон-пришёл {
  from {
    transform: translateY(22px);
    opacity: 0;
  }
  to {
    transform: translateY(0);
    opacity: 1;
  }
}
.догон h2 {
  margin: 0 0 14px;
  font-size: 19px;
  font-weight: 700;
}
.догон-список {
  list-style: none;
  margin: 0 0 18px;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.догон-строка {
  display: flex;
  align-items: center;
  gap: 11px;
}
.догон-знак {
  flex: none;
  width: 34px;
  height: 34px;
  border-radius: 12px;
  background: var(--слой-2);
  color: var(--текст-2);
  display: grid;
  place-items: center;
}
.догон-знак svg {
  width: 17px;
  height: 17px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.догон-слова {
  flex: 1;
  min-width: 0;
  font-size: 14px;
  line-height: 1.35;
}
.догон-слова small {
  display: block;
  font-size: 12px;
  color: var(--текст-тихо);
  /* Подробность в одну строку: причина отказа бывает длинной, и на трёх
     строках карточка перестаёт помещаться на 390×844 вместе со списком. */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.догон-сум {
  flex: none;
  font-size: 15px;
  font-weight: 700;
}
.догон-сум.плюс {
  color: var(--зачтено);
}
.догон-кнопки {
  display: flex;
  gap: 10px;
}
.догон-туда,
.догон-потом {
  flex: 1;
  min-height: 48px;
  border: 0;
  border-radius: var(--р-плашки);
  font: inherit;
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
}
.догон-туда {
  background: var(--деньги);
  color: var(--на-деньгах);
}
.догон-потом {
  background: var(--слой-2);
  color: var(--текст);
}
.догон-туда:focus-visible,
.догон-потом:focus-visible {
  outline: 2px solid var(--деньги);
  outline-offset: 2px;
}
.догон-туда:active,
.догон-потом:active {
  transform: scale(0.985);
}
@media (prefers-reduced-motion: reduce) {
  .догон-фон,
  .догон {
    animation: none;
  }
  .догон-туда:active,
  .догон-потом:active {
    transform: none;
  }
}

/* ══ НАМЕРЕНИЕ: ТЕМА, КОТОРАЯ ЕЩЁ НЕ ВСТАЛА (§100.3) ══════════════════════

   Человек нажал «Отказ ошибочный» и пришёл в переписку. Тема обращения на
   сервере ПОКА прежняя — она сменится с первым сообщением, и это правильно:
   заход на экран не смеет переписывать чужую переписку.

   🔴 НО ВЫГЛЯДЕТЬ ОБЕЩАНИЕ ОБЯЗАНО ИНАЧЕ, ЧЕМ ФАКТ. Без своего вида шапка
   намерения неотличима от настоящей темы, и человек, закрывший экран не
   написав, унесёт с собой уверенность, что тема сменилась. Пунктир — самый
   короткий способ сказать «ещё не закреплено»; так же рисуют черновики.
   ═════════════════════════════════════════════════════════════════════ */
.предмет.намерение {
  border: 1px dashed color-mix(in srgb, var(--деньги) 55%, transparent);
  background: color-mix(in srgb, var(--деньги) 7%, var(--слой-1));
}
.предмет.намерение small {
  color: var(--деньги);
}

/* ══ ССЫЛКА НА САЙТ (§164) ════════════════════════════════════════════════

   Его заказ 30.08: «на основной проект нигде нет ссылок». Теперь есть — в
   пояснении к ID выплаты, на экране подачи и отдельной строкой в правилах.

   🔴 ПОДЧЁРКИВАНИЕ ОБЯЗАТЕЛЬНО, А НЕ ОДИН ЦВЕТ. Внутри серого пояснения
   оранжевое слово читается как выделение, а не как дорога: человек его
   заметит и не нажмёт. Подчёркивание — единственный признак ссылки, который
   узнают все, включая тех, кто не различает цвета.
   ═════════════════════════════════════════════════════════════════════ */
.ссылка-сайт {
  color: var(--деньги);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.ссылка-сайт:focus-visible {
  outline: 2px solid var(--деньги);
  outline-offset: 2px;
  border-radius: 4px;
}
/* Ссылка в подвале меню — над знаком, тем же тихим тоном, что и пункты. */
.шторка-сайт {
  display: block;
  padding: 12px 8px;
  margin-bottom: 6px;
  text-align: center;
  font-size: 14px;
  color: var(--текст-2);
  text-decoration: none;
  border-radius: var(--р-плашки);
  background: var(--слой-2);
}
.шторка-сайт:active {
  transform: scale(0.985);
}
.шторка-сайт:focus-visible {
  outline: 2px solid var(--деньги);
  outline-offset: 2px;
}
.сайт-строка {
  margin-top: 2px;
}

/* ── УРОВЕНЬ FACEIT (§208.В) ──────────────────────────────────────────────

   Его заказ 31.08: «показывать лвл на фейсите и другую статистику чела на
   странице фейсита и в профиле лвл показывать, в кошельке лвл показывать и
   оригинальными иконками уровней».

   Значок — подлинный (провенанс в `web/faceit/levels/README.md`). Здесь только посадка: размер, выравнивание
   и соседство с ником и рейтингом. */

/* 🔴 ИМЯ ТЕГА В СЕЛЕКТОРЕ — ЭТО ПОЧИНКА, А НЕ ПЕДАНТИЗМ (§229).
   Его слова: «что в этой карточке за каша вообще?»

   В карточке FACEIT строка лежит внутри `<b>`, а двумя тысячами строк выше
   стоит `.тело b { display: block }`. Вес у него 0-1-1, у `.ур-строка` —
   0-1-0, и `block` ПОБЕЖДАЛ. Флекса не было вовсе:

     • `gap: 7px` не работал → ник и «ELO» слипались в одно слово;
     • значок с `display: block` уходил на СВОЮ СТРОКУ над ником.

   Снаружи это выглядело как каша, а по коду — как исправная разметка: оба
   правила верны по отдельности и дерутся только вместе. Ни типы, ни ворота,
   ни разбор такого не видят — видит глаз.

   `.тело b.ур-строка` даёт 0-2-1 и снимает спор навсегда, а не до следующей
   правки соседнего файла. */
.ур-строка,
.тело b.ур-строка {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-width: 0;

  /* 🔴 ПО СЕРЕДИНЕ СТРОКИ, А НЕ ПО БАЗОВОЙ ЛИНИИ. Его вторые слова: «иконка
     лвла в карточке фейсит неровно стоит относительно текста».

     У `inline-flex` базовая линия берётся от ПЕРВОГО элемента — а первый тут
     картинка, и её базовая линия это нижний край. Значит весь блок садился
     ниже подписи ряда ровно на разницу между высотой значка и высотой букв.
     `middle` убирает блок из выравнивания по базовой линии совсем. */
  vertical-align: middle;
}
/* 🔴 РАЗМЕР ЗАДАН И В РАЗМЕТКЕ, И ЗДЕСЬ — И ЭТО НЕ ДУБЛЬ.
   `width`/`height` в теге держат МЕСТО до загрузки картинки (иначе строка
   дёргается на глазах — это и есть сдвиг макета); правило здесь держит
   размер, когда шрифт крупнее обычного. */
.ур-faceit {
  flex: none;
  width: 20px;
  height: 20px;
  display: block;
}
/* Ник рядом со значком: длинный ник обязан обрезаться, а не выпихивать
   рейтинг за край. На 390 точках ников по 12 знаков хватает с запасом. */
/* 🔴 ДВА МЕСТА — ДВА ПОВЕДЕНИЯ, И ЭТО ПРАВКА ПО СНИМКУ (§246).

   `.ур-строка` живёт в ДВУХ местах: заголовком карточки FACEIT (`<b>`, своя
   строка во всю ширину) и значением строки списка «Деньги» (`<span>`, узкая
   колонка справа от подписи).

   Первая редакция этой правки разрешила перенос ВЕЗДЕ — и снимок показал, во
   что превратился список: подпись «Ваш ник на FACEIT» разорвало на четыре
   строки, ник распёр колонку, рейтинг уехал за край. Соседа сломали, чиня
   карточку.

   Поэтому обрезка остаётся умолчанием (она верна там, где места нет), а
   перенос включается ТОЛЬКО в карточке — ниже, отдельным правилом. */
.ур-ник {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* 🔴 В КАРТОЧКЕ НИК ВИДЕН ЦЕЛИКОМ — ОН ОТВЕЧАЕТ НА ВОПРОС «ТОТ ЛИ АККАУНТ».
   Обрезанный до «ник…», он на него не отвечает, и человеку остаётся верить
   нам на слово — на экране, где считают его деньги. Здесь ширина есть: ряд
   переносится, длинному нику достаётся вся строка, рейтинг уезжает под него.
   Короткие ники (а их большинство) как стояли в одну строку, так и стоят. */
.тело b.ур-строка {
  flex-wrap: wrap;
}
.тело b.ур-строка .ур-ник {
  overflow: visible;
  white-space: normal;
  overflow-wrap: anywhere;
}
/* 🔴 В СПИСКЕ У НИКА ЕСТЬ ПОТОЛОК ШИРИНЫ — И БЕЗ НЕГО ОБРЕЗКА НЕ РАБОТАЛА
   ВОВСЕ (§246, найдено снимком).

   Правая колонка `.пр-знач` стоит `flex: none` — и правильно: числа сжимать
   нельзя, они станут нечитаемы. Но у неё оказался ОДИН случай, где значение
   бывает длинным: ник FACEIT. Он распирал колонку изнутри, подпись слева
   сжималась до нуля («Ваш / ник / на / FACEIT» в четыре строки), а рейтинг
   уезжал за край экрана.

   Многоточие при этом стояло и не срабатывало: обрезать нечего, пока ширина
   не ограничена. Довод «длинный ник обязан обрезаться, а не выпихивать
   рейтинг за край» был записан — и не действовал.

   Потолок даётся ТОЛЬКО нику и только здесь: числам он ни к чему, а в
   карточке ник виден целиком (правило выше). */
.пр-знач .ур-ник {
  max-width: 8em;
}
/* 🔴 ПОТОЛОК НА ВСЮ КОЛОНКУ ПРОБОВАЛСЯ И ОТКАЧЕН — СНИМОК ПОКАЗАЛ ХУДШЕЕ.
   С `max-width: 52%` подпись слева выпрямилась, зато рейтинг налез на
   шеврон: «2100→» слиплись в одно пятно. Сжимать колонку с числами нельзя,
   и это ровно то, ради чего у неё стоит `flex: none`.
   Подпись лечится не вёрсткой, а словом: «Ваш ник на FACEIT» сокращено до
   «Ник на FACEIT» — на четыре знака короче, и смысл тот же. */
/* Рейтинг — цифрами одной ширины: иначе при обновлении число «дышит». */
.ур-эло {
  flex: none;
  font-size: 13px;
  font-weight: 600;
  color: var(--текст-2);
  font-variant-numeric: tabular-nums;
}
/* 🔴 РОСТ РЕЙТИНГА — ЦВЕТОМ И ЗНАКОМ, а не только цветом (WCAG 1.4.1).
   Плюс и минус несут смысл сами по себе; цвет их лишь усиливает. */
.ур-рост {
  flex: none;
  font-size: 12px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.ур-рост.вверх {
  color: var(--зачтено);
}
.ур-рост.вниз {
  color: var(--отказ);
}
/* 🔴 ПРАВУЮ КОЛОНКУ .пр-знач ЗДЕСЬ НЕ ТРОГАЕМ — И ЭТО РЕШЕНИЕ.
   Первая редакция дописывала ей display: inline-flex, чтобы значок встал
   рядом с ником. Правило поймало бы ВСЕ ряды профиля и кошелька, включая
   те, где справа простой текст, — то есть ради одной строки поменяло бы
   раскладку двух десятков чужих. Вместо этого разметка карточки FACEIT
   несёт свою обёртку .ур-строка, у которой всё нужное уже есть. */
/* ── «ИЗ ЧЕГО СЛОЖИЛОСЬ» (§322) ───────────────────────────────────────────
   Разбивка живёт ВНУТРИ карточки графика, под столбцами, и набрана той же
   палитрой: это продолжение одного разговора о деньгах, а не вторая
   карточка рядом. */
.разб-кнопка {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  margin-top: 12px;
  padding: 11px 2px;
  appearance: none;
  border: 0;
  border-top: 1px solid var(--слой-3);
  /* 🔴 СКРУГЛЕНИЕ ГАСИТСЯ ЯВНО. У кнопок проекта общим правилом стоит
     `border-radius: var(--р-плашки)` (18px), и верхняя граница на таком
     скруглении рисуется ДУГОЙ: на снимке линия загибалась вверх обоими
     концами и читалась как чья-то чужая рамка. Числа этого не показывали —
     ширина, цвет и толщина у неё верные. */
  border-radius: 0;
  background: transparent;
  color: var(--текст-тихо);
  font: inherit;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: pointer;
  /* 🔴 44 ПУНКТА, И ЭТО ЗАМЕР, А НЕ РАСЧЁТ. Комментарий первой редакции
     утверждал «44», а в коде стояло `min-height: 40px` — и браузер намерил
     ровно 40. Отступ сверху (12px) к цели не относится: он снаружи кнопки.
     Порода известная: комментарий утверждает то, чего в коде нет. */
  min-height: 44px;
}
.разб-стрелка {
  font-size: 9px;
  color: var(--текст-тихо);
}
.разб-кнопка[aria-expanded="true"] {
  color: var(--текст-2);
}

.разбивка {
  padding-top: 2px;
}
/* 🔴 СЕТКА ОДНА НА ВЕСЬ СПИСОК, А НЕ СВОЯ У КАЖДОЙ СТРОКИ.
   Первая редакция дала сетку каждой строке отдельно — и ложа полос вышли
   97 · 161 · 179 · 180 пикселей: колонка полосы забирает ОСТАТОК, а он
   зависит от длины имени слева. На снимке это читалось прямой ложью:
   строка «Ролики про CS2 — 100 %» рисовалась ПОЛОСОЙ КОРОЧЕ, чем «TikTok
   — 90 %».
   Полоса существует ровно для того, чтобы сравнивать глазом; полосы на
   разных базах сравнивать нельзя. `display: contents` у строки отдаёт её
   ячейки общей сетке списка — и все четыре колонки становятся общими. */
.разб-список {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: minmax(0, auto) minmax(24px, 1fr) auto auto;
  align-items: center;
  gap: 9px 8px;
  font-size: 13px;
}
.разб-строка {
  display: contents;
}
.разб-имя {
  color: var(--текст-2);
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.разб-полоса {
  height: 4px;
  border-radius: 999px;
  background: var(--слой-2);
  overflow: hidden;
}
.разб-полоса > i {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: var(--деньги);
}
.разб-сумма {
  font-weight: 700;
  /* Цифры одной ширины: иначе «$1 000.00» и «$999.00» встают лесенкой. */
  font-variant-numeric: tabular-nums;
}
.разб-доля {
  min-width: 34px;
  text-align: right;
  color: var(--текст-тихо);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}
/* Признаки пересекаются со слагаемыми, поэтому у них НЕТ ни полосы, ни
   процента — только имя и сумма. Сетка на две колонки говорит это глазом
   раньше, чем подзаголовок словом. То же у единственного слагаемого:
   «100 %» рядом с ним — это то же число, сказанное второй раз. */
.разб-признаки,
.разб-просто {
  grid-template-columns: minmax(0, 1fr) auto;
}
.разб-подзаголовок {
  margin: 14px 0 8px;
  color: var(--текст-тихо);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
}
.разб-итог {
  margin: 12px 0 0;
  color: var(--текст-тихо);
  font-size: 12px;
}
.разбивка-пусто,
.разб-пусто {
  margin: 10px 0 0;
}
/* 🔴 НА УЗКОМ ЭКРАНЕ УБИРАЕТСЯ КОЛОНКА, А НЕ ЯЧЕЙКА.
   Первая редакция прятала `.разб-доля` через `display: none` — и на 320
   разбивка РАЗВАЛИЛАСЬ: сетка у списка общая (иначе полосы врут глазом), а
   строки отдают в неё свои ячейки через `display: contents`. Спрятанная
   ячейка не занимает места в сетке, но колонок остаётся четыре — и весь
   ряд едет: «TikTok ▬ $1 728.00 Reels», а «$60.30» уезжает на третью
   строку. Читалось как сломанная вёрстка, и так оно и было.
   Числа этого не показывали: горизонтальной прокрутки нет, потому что
   ячейки не выходят за край — они ПЕРЕНОСЯТСЯ. Показал снимок.
   Доля при этом не теряется: она есть в `aria-label` строки, то есть
   читатель экрана слышит её и здесь. */
@media (max-width: 359px) {
  .разб-список {
    grid-template-columns: minmax(0, auto) minmax(24px, 1fr) auto;
  }
  .разб-признаки,
  .разб-просто {
    grid-template-columns: minmax(0, 1fr) auto;
  }
  .разб-доля {
    display: none;
  }
}
/* ── СРАВНЕНИЕ С ПРОШЛЫМ ПЕРИОДОМ И ЛУЧШИЙ РОЛИК (§323) ─────────────────── */
.разб-сравнение {
  margin: 10px 0 0;
  color: var(--текст-тихо);
  font-size: 12px;
}
/* Цвет несёт СМЫСЛ, но не несёт его ОДИН: рядом стоят «+» и «−» словами.
   Полагаться на цвет одному нельзя — восьмой процент мужчин его не
   различает, а речь о деньгах. */
.разб-сравнение.вверх {
  color: var(--зачтено);
}
.разб-сравнение.вниз {
  color: var(--текст-2);
}

/* 🔴 ЛУЧШИЙ РОЛИК — ПЛАШКА, А НЕ СТРОКА СПИСКА. Он не слагаемое: его сумма
   уже посчитана внутри «роликов про CS2», и поставь мы его в тот же список,
   человек сложил бы и получил больше, чем заработал. Отдельная плашка на
   другом фоне говорит это глазом раньше, чем подпись словом. */
.разб-лучший {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 2px 8px;
  align-items: baseline;
  margin-top: 14px;
  padding: 10px 12px;
  border-radius: var(--р-плашки);
  background: var(--слой-2);
}
.разб-лучший-подпись {
  color: var(--текст-тихо);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
}
.разб-лучший-сумма {
  font-size: 15px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  text-align: right;
}
.разб-лучший-где {
  grid-column: 1 / -1;
  color: var(--текст-тихо);
  font-size: 12px;
  /* Ссылка на ролик бывает длинной — режем её, а не карточку. */
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.разб-лучший-где a {
  color: var(--текст-2);
  /* Цель нажатия у ссылки внутри строки: подчёркивание говорит, что это
     ссылка, а вертикальный отступ строки даёт палец. */
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* Период в кнопке разбивки: тише самой надписи — он уточнение, а не заголовок. */
.разб-период {
  color: var(--текст-2);
  opacity: 0.75;
}
/* Хвост «Моих заявок» (§343): сколько показано и «Показать ещё» под ним. */
.хвост-списка {
  display: grid;
  justify-items: center;
  gap: 8px;
  margin-block: 12px 4px;
}
