/* ─────────────────────────────────────────────────────────────────────────
   Панель управления VPN-бота (на базе оболочки WoT Rent).

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

     фон (шум + свечение)
       └ поверхность экрана        --s-0   почти прозрачная
           └ карточка              --s-1
               └ вложенный блок    --s-2
                   └ плавающее     --s-3   таб-бар, шапка
                       └ диалог    --s-4   самое плотное, под ним затемнение

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

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

:root {
  /* ─── подложка ─── */
  --bg: #070b14;
  --bg-2: #0c1220;

  /* Цвета, которые раньше стояли числами прямо в правилах — из-за них при
     смене темы часть экрана оставалась в прежних тонах. */
  --hover-veil: rgba(var(--glass-rgb), 0.1);
  --spinner-track: rgba(var(--glass-rgb), 0.28);
  --spinner-head: #fff;
  --knob: #fff;
  --scrim: rgba(3, 6, 14, 0.66);
  --bad-line: rgba(255, 95, 109, 0.28);
  --sunken: rgba(0, 0, 0, 0.22);
  --warn-line: rgba(255, 194, 75, 0.24);
  --pick-ring: rgba(255, 255, 255, 0.55);
  --overlay-dim: rgba(6, 7, 11, 0.5);
  /* Плотные тона для панели ввода. Полупрозрачность держится на
     `backdrop-filter`, а он есть не везде: в оболочке Telegram на Windows его
     нет, и «стекло» превращается в мутную плёнку, сквозь которую читается
     переписка. Панель, поверх которой печатают, обязана быть непрозрачной. */
  --composer-bg: #0e1526;
  --composer-field: #080d18;

  /* Тон стекла и линий. Здесь запасное тёплое значение — рабочее ставит
     `theme.applyAccent` из выбранного цвета, поэтому синий интерфейс выходит
     синим целиком, а не синими кнопками на янтарном стекле. */
  --glass-rgb: 196, 220, 255;

  /* ─── стекло по слоям ─── */
  --s-0: rgba(var(--glass-rgb), 0.024);
  --s-1: rgba(var(--glass-rgb), 0.045);
  --s-2: rgba(var(--glass-rgb), 0.068);
  --s-3: rgba(12, 20, 36, 0.74);
  --s-4: rgba(14, 22, 40, 0.88);

  --line: rgba(var(--glass-rgb), 0.075);
  --line-strong: rgba(var(--glass-rgb), 0.14);
  --line-soft: rgba(var(--glass-rgb), 0.045);

  /* Блик по верхней кромке — то, что делает стекло стеклом, а не серым прямоугольником */
  --sheen: linear-gradient(180deg, rgba(var(--glass-rgb), 0.11), rgba(var(--glass-rgb), 0) 42%);

  /* ─── текст ─── */
  --fg: #eef3fb;
  --fg-1: #dbe5f5;   /* чуть тусклее основного: заголовок непрочитанной строки */
  --fg-2: #a9b8d0;
  --fg-3: #6f809c;
  --fg-4: #4a5670;

  /* ─── смысловые цвета ─── */
  --accent: #3b82f6;
  --accent-2: #7cb8ff;
  --accent-soft: rgba(59, 130, 246, 0.16);
  --ok: #5cd98a;
  --ok-soft: rgba(92, 217, 138, 0.15);
  --warn: #ffc24b;
  --warn-soft: rgba(255, 194, 75, 0.15);
  --bad: #ff5f6d;
  --bad-soft: rgba(255, 95, 109, 0.15);
  --info: #8fb8e0;
  --info-soft: rgba(143, 184, 224, 0.15);

  /* ─── тени ─── */
  --sh-1: 0 1px 2px rgba(0, 0, 0, 0.35);
  --sh-2: 0 8px 24px -8px rgba(0, 0, 0, 0.6);
  --sh-3: 0 20px 50px -12px rgba(0, 0, 0, 0.75);
  --glow: 0 0 0 1px rgba(59, 130, 246, 0.35), 0 8px 32px -8px rgba(59, 130, 246, 0.45);

  /* ─── форма и ритм ─── */
  --r-xs: 8px;
  --r-sm: 12px;
  --r-md: 16px;
  --r-lg: 20px;
  --r-xl: 28px;
  --r-pill: 999px;

  --blur-1: 18px;
  --blur-2: 28px;
  --blur-3: 40px;

  --gap: 12px;
  --pad: 16px;

  /* Безопасные зоны Telegram: шапка сверху, «домой» снизу */
  --safe-t: env(safe-area-inset-top, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);
  /* Запасная высота системной строки — на случай, если телефон про неё
     промолчал. У приложения, добавленного на экран «Домой», своей шапки нет:
     страница рисует себя во весь экран, включая полосу с часами. Обычно место
     под них сообщает `env(safe-area-inset-top)`, но он приходит не всегда и не
     везде, и тогда время с батареей ложатся прямо на заголовок.

     Занизить хуже, чем завысить: в первом случае шапка перечёркнута, во
     втором — лишняя полоска фона. 26px — типичная строка без выреза; там, где
     вырез есть, настоящий инсет больше и выигрывает он. */
  --status-h: 26px;
  /* И такой же запас снизу. У айфона там полоска «домой», и подписи вкладок
     упираются в неё вплотную: нажимаешь «Баланс» — телефон понимает это как
     жест «свернуть приложение». Восьми точек хватает, чтобы промаха не было,
     а на телефонах без полоски это просто чуть больше воздуха. */
  --tabbar-lift: 8px;
  /* Сколько панель занимает на самом деле. Всё, что должно лежать над ней —
     кнопки, всплывающие подсказки, отступ содержимого, — считается отсюда, а
     не складывается заново в каждом месте: иначе стоит поменять одно число,
     и половина экрана уезжает под панель. */
  --tabbar-total: calc(var(--tabbar-h) + var(--safe-b) + var(--tabbar-lift));
  --tabbar-h: 64px;
  --header-h: 52px;

  --font: "Manrope", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono: "JetBrains Mono", ui-monospace, "SF Mono", "Cascadia Code", Menlo, monospace;

  /* ─── то, что меняется вместе с темой ───
     Всё остальное (размеры, скругления, смысловые зелёный и красный) общее:
     тема — это освещение, а не другой интерфейс. */
  --aurora-1: rgba(59, 130, 246, 0.24);
  --aurora-2: rgba(124, 184, 255, 0.17);
  --aurora-3: rgba(30, 80, 200, 0.10);
  --noise-opacity: 0.5;
  --noise-blend: overlay;
  --media-bg: radial-gradient(120% 90% at 50% 0%, rgba(255, 138, 43, 0.22), transparent 65%),
              linear-gradient(160deg, #1e1409, #100a05);
  --btn-grad: linear-gradient(180deg, #3b82f6, #2563eb);
  --btn-grad-hover: linear-gradient(180deg, #5b95f8, #3574f0);
  --btn-shadow: 0 6px 20px -8px rgba(59, 130, 246, 0.9);
  --btn-primary-line: rgba(255, 255, 255, 0.18);
  --chip-on-fg: #cfe3ff;
  --accent-line: rgba(59, 130, 246, 0.4);
  --option-bg: #0f172a;
  --badge-fg: #06101f;
  --overlay-chip: rgba(6, 10, 20, 0.68);
  /* Поле ввода — плотное, а не полупрозрачное.
     Сквозь прозрачное просвечивает то, что лежит под шторкой, и граница поля
     теряется: строка выглядит кривой и грязной, хотя вёрстка ровная. */
  --input-bg: #0f1626;
  --input-bg-focus: #141d30;
  --hero-fade: linear-gradient(180deg, transparent 40%, rgba(7, 8, 12, 0.92));
  --hero-top-fade: linear-gradient(180deg, rgba(7, 8, 12, 0.55), transparent);
  --composer-fade: linear-gradient(180deg, transparent, var(--bg) 30%);

  --ease: cubic-bezier(0.32, 0.72, 0, 1);
  --fast: 140ms var(--ease);
  --mid: 260ms var(--ease);
  --slow: 420ms var(--ease);
}

/* Установленное приложение рисует себя во весь экран, включая полосу часов.
   Берём то, что больше: настоящий инсет, если система его сообщила, или нашу
   оценку высоты строки. `max` здесь важнее вида: занизить — значит перечеркнуть
   шапку часами, завысить — всего лишь оставить лишнюю полоску фона. */
@media (display-mode: standalone), (display-mode: fullscreen), (display-mode: minimal-ui) {
  :root {
    --safe-t: max(env(safe-area-inset-top, 0px), var(--status-h));
  }
}


/* Светлая тема. Акцент тот же янтарный — меняется освещение, а не бренд.

   Ключевое отличие от тёмной: слои идут не «светлее фона», а «белее и плотнее».
   Полупрозрачный белый на светлом почти не виден, поэтому непрозрачность выше,
   а границы заметнее — на солнце их всё равно едва хватает. */
:root[data-theme="light"] {
  /* Свой тон стекла: у тёмной темы он холодный и светлый, на белом фоне он давал синеву. */
  --glass-rgb: 24, 38, 66;
  --status-h: 0px;
  --bg: #f3f7fc;
  --bg-2: #ffffff;

  --hover-veil: rgba(20, 50, 100, 0.07);
  --spinner-track: rgba(20, 50, 100, 0.18);
  --spinner-head: #1d4ed8;
  --knob: #fff;
  --scrim: rgba(20, 35, 60, 0.38);
  --bad-line: rgba(200, 50, 62, 0.3);
  /* «Утопленный» фон в светлой теме не чёрный, а тёплый серый: чёрная плашка
     на бежевом листе выглядит дырой, а не углублением. */
  --sunken: rgba(20, 50, 100, 0.06);
  --warn-line: rgba(190, 130, 20, 0.3);
  --pick-ring: rgba(255, 255, 255, 0.85);
  --overlay-dim: rgba(255, 255, 255, 0.55);

  --s-0: rgba(255, 255, 255, 0.5);
  --s-1: rgba(255, 255, 255, 0.72);
  --s-2: rgba(255, 255, 255, 0.9);
  --s-3: rgba(244, 248, 253, 0.86);
  --s-4: rgba(252, 253, 255, 0.96);

  --line: rgba(20, 50, 100, 0.12);
  --line-strong: rgba(20, 50, 100, 0.2);
  --line-soft: rgba(20, 50, 100, 0.07);
  --sheen: linear-gradient(180deg, rgba(255, 255, 255, 0.6), rgba(255, 255, 255, 0) 46%);

  --fg: #0b1f3a;
  --fg-1: #1b3050;
  --fg-2: #45566f;
  --fg-3: #6b7c96;
  --fg-4: #9aa8bb;

  --accent: #1d6ff2;
  --accent-2: #63a6ff;
  --accent-soft: rgba(29, 111, 242, 0.12);
  --ok: #14915a;
  --ok-soft: rgba(20, 145, 90, 0.12);
  --warn: #b97400;
  --warn-soft: rgba(185, 116, 0, 0.13);
  --bad: #d33141;
  --bad-soft: rgba(211, 49, 65, 0.11);
  --info: #3a6a9a;
  --info-soft: rgba(58, 106, 154, 0.12);

  --sh-1: 0 1px 2px rgba(30, 50, 80, 0.08);
  --sh-2: 0 8px 24px -10px rgba(30, 50, 80, 0.22);
  --sh-3: 0 20px 50px -14px rgba(30, 50, 80, 0.3);
  --glow: 0 0 0 1px rgba(29, 111, 242, 0.3), 0 8px 32px -8px rgba(29, 111, 242, 0.3);

  --aurora-1: rgba(120, 170, 255, 0.34);
  --aurora-2: rgba(170, 210, 255, 0.3);
  --aurora-3: rgba(140, 190, 255, 0.22);
  /* На светлом зерно не «шумит», а грязнит: оставляем еле заметное. */
  --noise-opacity: 0.16;
  --noise-blend: multiply;

  --media-bg: radial-gradient(120% 90% at 50% 0%, rgba(29, 111, 242, 0.16), transparent 65%),
              linear-gradient(160deg, #e6eef9, #d6e2f3);
  --btn-grad: linear-gradient(180deg, #2f7ff5, #1d6ff2);
  --btn-grad-hover: linear-gradient(180deg, #4a8ff7, #2a78f0);
  --btn-shadow: 0 6px 18px -8px rgba(29, 111, 242, 0.7);
  --btn-primary-line: rgba(0, 40, 120, 0.2);
  --chip-on-fg: #0b3f9a;
  --accent-line: rgba(29, 111, 242, 0.42);
  --option-bg: #fbfdff;
  --badge-fg: #ffffff;
  --overlay-chip: rgba(250, 253, 255, 0.86);
  --composer-bg: #eef3fa;
  --composer-field: #ffffff;
  --input-bg: #ffffff;
  --input-bg-focus: #ffffff;
  --hero-fade: linear-gradient(180deg, transparent 38%, rgba(243, 247, 252, 0.94));
  --hero-top-fade: linear-gradient(180deg, rgba(243, 247, 252, 0.6), transparent);
  --composer-fade: linear-gradient(180deg, transparent, var(--bg) 30%);
}

/* Тёмный фон подложки таб-бара у бейджа берётся из --bg, поэтому отдельного
   правила для светлой темы не нужно — он подстроится сам. */

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  /* Страница не ездит вбок и не оттягивается по краям.

     Стоит одному блоку оказаться шире экрана — таблице, длинному номеру
     заказа, ленте вкладок, — как весь документ становится прокручиваемым по
     горизонтали. Тогда нижняя панель, прибитая к экрану, остаётся на месте, а
     всё вокруг едет под пальцем, и выглядит это как будто листаются сами
     кнопки. Ширину ограничиваем здесь, а широкое содержимое прокручивается
     внутри своих контейнеров. */
  max-width: 100%;
  overflow-x: hidden;
  overscroll-behavior: none;
}
/* Фон задаётся и на html тоже.

   Телефон растягивает страницу за её пределы — при оттягивании вниз или при
   смене темы видно то, что лежит под `body`. Если у html фона нет, там
   оказывается цвет по умолчанию, и экран выглядит как наполовину
   переключившийся. */
/* Масштабирование пальцами выключено: панель — интерфейс, а не документ.
   Случайный «зум» здесь только ломает вёрстку и пугает. Прокрутка при этом
   остаётся: запрещаем именно щипок и двойной тап. */
html, body { touch-action: pan-x pan-y; }

html { background: var(--bg); }

/* Пока идёт переключение темы, цветовые переходы выключены целиком.

   Каждый элемент со своим `transition` доезжает до нового цвета за своё время,
   и полсекунды экран выглядит собранным из двух разных тем. Мгновенная смена
   честнее: тема меняется вся сразу. */
:root.theme-switching *,
:root.theme-switching *::before,
:root.theme-switching *::after {
  transition: none !important;
}

body {
  font-family: var(--font);
  font-size: 15px;
  line-height: 1.45;
  color: var(--fg);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Свечение и зерно живут на псевдоэлементах: так они не мешают прокрутке
   и не перерисовываются при каждом обновлении содержимого. */
body::before {
  content: "";
  position: fixed;
  inset: -20% -10% auto -10%;
  height: 90vh;
  pointer-events: none;
  z-index: 0;
  background:
    radial-gradient(70% 55% at 16% 0%, var(--aurora-1), transparent 70%),
    radial-gradient(62% 50% at 90% 6%, var(--aurora-2), transparent 70%),
    radial-gradient(90% 60% at 50% 100%, var(--aurora-3), transparent 72%);
  filter: blur(28px);
}

body::after {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  opacity: var(--noise-opacity);
  mix-blend-mode: var(--noise-blend);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='.32'/%3E%3C/svg%3E");
}

::selection { background: var(--accent-soft); color: var(--fg); }

/* Полоса прокрутки: тонкая, появляется только при наведении — на телефоне её нет вовсе */
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--line-strong); border-radius: var(--r-pill); }

/* Ссылки внутри панели не подчёркиваются: подчёркивание нужно в тексте, где
   ссылку надо отличить от слов вокруг. Здесь она и так стоит отдельной строкой
   или кнопкой — линия только зашумляет. */
a { color: inherit; text-decoration: none; }
a.link { color: var(--accent); font-weight: 650; }
a.link:hover { opacity: 0.85; }

/* ─────────────────────────── каркас ─────────────────────────── */
#root {
  position: relative;
  z-index: 1;
  min-height: 100%;
  display: flex;
  flex-direction: column;
}

.shell {
  display: flex;
  flex: 1;
  min-height: 0;
}

.main {
  flex: 1;
  min-width: 0;
  padding: calc(var(--header-h) + var(--safe-t) + 8px) var(--pad)
           calc(var(--tabbar-total) + 24px);
  max-width: 780px;
  margin: 0 auto;
  width: 100%;
}

/* ─────────────────────────── шапка ─────────────────────────── */
.header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 40;
  height: calc(var(--header-h) + var(--safe-t));
  padding: var(--safe-t) var(--pad) 0;
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--s-3);
  backdrop-filter: blur(var(--blur-2)) saturate(160%);
  -webkit-backdrop-filter: blur(var(--blur-2)) saturate(160%);
  border-bottom: 1px solid var(--line-soft);
}

.header__back {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  flex: 0 0 34px;
  margin-left: -6px;
  border-radius: var(--r-pill);
  color: var(--fg-2);
  background: transparent;
  border: 0;
  cursor: pointer;
  transition: background var(--fast), color var(--fast), transform var(--fast);
}
.header__back:hover { background: var(--s-2); color: var(--fg); }
.header__back:active { transform: scale(0.92); }

.header__titles { min-width: 0; flex: 1; }
.header__title {
  margin: 0;
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -0.02em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.header__sub {
  font-size: 11.5px;
  color: var(--fg-3);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.header__actions { display: flex; gap: 6px; align-items: center; }

/* Колокольчик со счётчиком непрочитанного.

   Счётчик, а не точка: «есть что-то новое» и «пока вас не было, случилось
   восемь вещей» — разные новости, и вторая говорит, стоит ли открывать сейчас
   или можно потом. */
.header__bell { position: relative; }
.header__badge {
  position: absolute;
  top: 2px;
  right: 2px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: var(--r-pill);
  background: var(--bad);
  color: var(--badge-fg);
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 700;
  line-height: 16px;
  text-align: center;
  box-shadow: 0 0 0 2px var(--s-3);
  pointer-events: none;
}

/* Шапка на телефоне и на большом экране разная не по красоте, а по смыслу.

   На большом экране настройки стоят в боковом меню, и шестерёнка в шапке была
   бы вторым входом в ту же дверь. На телефоне бокового меню нет, а шестая
   вкладка внизу сделала бы все шесть уже пальца — поэтому настройки уезжают
   в шапку, рядом с поиском.

   Место под шестерёнку освобождает «обновить»: данные и так приезжают сами,
   сервер держит запрос открытым и отпускает, когда что-то произошло. На
   большом экране кнопка остаётся — там места хватает, и мышью её жмут охотнее,
   чем тянут страницу пальцем. */
.header__narrow { display: inline-flex; }
.header__wide { display: none; }
@media (min-width: 900px) {
  .header__narrow { display: none; }
  .header__wide { display: inline-flex; }
}

/* ─────────────────────────── нижняя навигация ─────────────────────────── */
.tabbar {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 45;
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  padding-bottom: calc(var(--safe-b) + var(--tabbar-lift));
  height: var(--tabbar-total);
  background: var(--s-3);
  backdrop-filter: blur(var(--blur-3)) saturate(180%);
  -webkit-backdrop-filter: blur(var(--blur-3)) saturate(180%);
  border-top: 1px solid var(--line-soft);
}

.tab {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  border: 0;
  background: none;
  color: var(--fg-3);
  font-family: inherit;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: -0.01em;
  cursor: pointer;
  transition: color var(--fast);
}
.tab svg { transition: transform var(--mid); }
.tab:active svg { transform: scale(0.86); }
.tab[aria-current="page"] { color: var(--fg); }
.tab[aria-current="page"] svg { color: var(--accent); }
/* Точка вместо подчёркивания: на 5 колонках полоска выглядит как ошибка вёрстки */
.tab[aria-current="page"]::after {
  content: "";
  position: absolute;
  top: 6px;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 10px var(--accent);
}

.tab__badge {
  position: absolute;
  top: 8px;
  right: calc(50% - 22px);
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  display: grid;
  place-items: center;
  font-size: 10px;
  font-weight: 700;
  color: var(--badge-fg);
  background: var(--bad);
  border-radius: var(--r-pill);
  box-shadow: 0 0 0 2px var(--bg-2);
}

/* Боковое меню на широком экране: телефонный таб-бар там выглядит инородно */
.sidebar { display: none; }

@media (min-width: 900px) {
  .tabbar { display: none; }
  .sidebar {
    display: flex;
    flex-direction: column;
    gap: 4px;
    position: sticky;
    top: calc(var(--header-h) + var(--safe-t));
    align-self: flex-start;
    width: 224px;
    flex: 0 0 224px;
    padding: 16px 12px;
    height: calc(100vh - var(--header-h) - var(--safe-t));
    border-right: 1px solid var(--line-soft);
    overflow-y: auto;
  }
  .side-link {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 12px;
    /* Прозрачная рамка в обычном состоянии: без неё выбранный пункт
       подпрыгивал бы на пиксель, когда рамка появляется. */
    border: 1px solid transparent;
    border-radius: var(--r-sm);
    background: none;
    color: var(--fg-2);
    font: inherit;
    font-size: 14px;
    font-weight: 600;
    text-align: left;
    cursor: pointer;
    transition: background var(--fast), color var(--fast),
                border-color var(--fast), box-shadow var(--fast);
  }
  .side-link:hover { background: var(--s-1); color: var(--fg); }
  .main { padding-bottom: 48px; max-width: 900px; }
}

/* Выбранный пункт: свечение обводит кнопку целиком, а не полоской сбоку.
   Полоска слева работает в длинных списках, где важно «где я в дереве»;
   здесь пунктов шесть, и подсветить нужно саму кнопку. */
.side-link[aria-current="page"],
.menu-item[aria-current="page"] {
  background: var(--accent-soft);
  color: var(--fg);
  border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent-soft), 0 6px 22px -10px var(--accent);
}
.side-link[aria-current="page"] svg,
.menu-item[aria-current="page"] svg { color: var(--accent); }

/* Подсветка активного пункта меню едет, а не перепрыгивает: так видно, что
   выбор сместился на соседний раздел, а не сменился целиком. */
.side-glow {
  position: absolute;
  top: 0;
  left: 12px;
  right: 12px;
  z-index: 0;
  border-radius: var(--r-sm);
  background: var(--accent-soft);
  border: 1px solid var(--accent);
  box-shadow: 0 0 0 1px var(--accent-soft), 0 6px 22px -10px var(--accent);
  transition: transform var(--mid), height var(--mid), opacity var(--fast);
  pointer-events: none;
  opacity: 0;
}
.sidebar { position: relative; }
.side-link { position: relative; z-index: 1; }
/* Сам пункт фона больше не рисует — за него это делает едущая подсветка. */
.side-link[aria-current="page"] {
  background: transparent;
  border-color: transparent;
  box-shadow: none;
}

/* Значки садятся на базовую линию текста, а не болтаются по вертикали.
   `flex: none` обязателен: иначе длинная подпись сжимает значок в овал. */
.btn svg,
.row > svg,
.kv svg,
.tile__label svg,
.menu-item svg,
.seg__opt svg,
.notice svg,
.chip svg {
  flex: none;
  display: block;
}
/* Колонка под значок в начале строки. Аватар сюда не попадает: он не значок,
   у него свой размер, и раньше это правило (оно специфичнее) ужимало его до
   22px по ширине при высоте 38px — получался вертикальный овал вместо круга. */
.row > span:first-child:not(.row__body):not(.row__side):not(.avatar) {
  display: grid;
  place-items: center;
  width: 22px;
  flex: none;
}
.tile__label svg { position: relative; top: 0.5px; }

/* ─────────────────────────── стекло ─────────────────────────── */
.glass {
  position: relative;
  background: var(--s-1);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  backdrop-filter: blur(var(--blur-1)) saturate(150%);
  -webkit-backdrop-filter: blur(var(--blur-1)) saturate(150%);
  box-shadow: var(--sh-2);
  overflow: hidden;
}
/* Блик рисуем псевдоэлементом, чтобы он не перекрывал содержимое карточки */
.glass::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 56%;
  background: var(--sheen);
  pointer-events: none;
}
.glass > * { position: relative; }

.section { margin-bottom: 18px; }
.section__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin: 0 2px 10px;
}
.section__title {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--fg-3);
}
/* Значок в заголовке — часть строки, а не отдельный ярус.

   Заголовки набраны прописными в 12px, а значок рисовался в 16px по своей
   базовой линии: он выпирал вверх и казался приклеенным сбоку. Здесь и всюду
   дальше действует одно правило — значок центрируется по строке, не сжимается
   и наследует размер от текста, к которому относится. */
.section__title svg {
  flex: none;
  width: 1.25em;
  height: 1.25em;
  color: var(--fg-4);
}
.section__link {
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--accent);
  cursor: pointer;
}
.section__link:active { opacity: 0.6; }

/* ─────────────────────────── плитки-метрики ─────────────────────────── */
.tiles {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--gap);
}
/* Три плитки в ряд помещаются не на всяком телефоне: «30.55 ₽» на узком
   экране ломается пополам, и рубль уезжает на вторую строку. Поэтому три
   колонки включаются только начиная с ширины, где число заведомо влезает. */
.tiles--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (min-width: 400px) {
  .tiles--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
/* На широком экране колонок столько, сколько плиток, а не всегда четыре.
   Четыре жёстких колонки означали, что две плитки занимают половину экрана, а
   вторая половина стоит пустой — выглядит как недогруженная страница.
   `auto-fit` схлопывает пустые колонки, и оставшиеся плитки растягиваются на
   всю ширину. */
@media (min-width: 620px) {
  .tiles { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }
}

/* Плитка, оставшаяся в последнем ряду одна, занимает его целиком. Половина
   ряда с пустотой рядом читается как недогруженный экран — будто что-то не
   загрузилось, — а не как последняя цифра отчёта. Условие «последний и
   нечётный» и есть «один в ряду»: при чётном числе плиток ряд полный. */
.tiles > *:last-child:nth-child(odd) { grid-column: 1 / -1; }
@media (min-width: 400px) {
  .tiles--3 > *:last-child:nth-child(odd) { grid-column: auto; }
  .tiles--3 > *:last-child:nth-child(3n + 1) { grid-column: 1 / -1; }
}
@media (min-width: 620px) {
  .tiles > *:last-child:nth-child(odd),
  .tiles--3 > *:last-child:nth-child(3n + 1) { grid-column: auto; }
  .tiles > *:last-child:nth-child(4n + 1) { grid-column: 1 / -1; }
}

.tile {
  position: relative;
  padding: 13px 14px 14px;
  background: var(--s-1);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  backdrop-filter: blur(var(--blur-1));
  -webkit-backdrop-filter: blur(var(--blur-1));
  overflow: hidden;
  text-align: left;
  font: inherit;
  color: inherit;
  cursor: default;
  transition: transform var(--fast), border-color var(--fast);
}
.tile::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 60%;
  background: var(--sheen);
  pointer-events: none;
}
button.tile { cursor: pointer; }
button.tile:hover { border-color: var(--line-strong); }
button.tile:active { transform: scale(0.985); }

.tile__label {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 11px;
  font-weight: 600;
  color: var(--fg-3);
  letter-spacing: 0.02em;
  margin-bottom: 6px;
}
.tile__value {
  font-family: var(--mono);
  /* Число подстраивается под ширину плитки: на узком экране 21px не хватает
     места, и сумма разрывается посередине. */
  font-size: clamp(17px, 5.2vw, 21px);
  font-weight: 700;
  letter-spacing: -0.035em;
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
  white-space: nowrap;
}
.tile__value small { font-size: 13px; font-weight: 600; color: var(--fg-3); margin-left: 2px; }
.tile__foot { margin-top: 5px; font-size: 11.5px; color: var(--fg-3); }

.delta { font-weight: 700; font-family: var(--mono); font-size: 11.5px; }
.delta--up { color: var(--ok); }
.delta--down { color: var(--bad); }
.delta--flat { color: var(--fg-3); }

/* ─────────────────────────── бейджи ─────────────────────────── */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 9px;
  border-radius: var(--r-pill);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: -0.005em;
  white-space: nowrap;
  border: 1px solid transparent;
}
.badge::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  box-shadow: 0 0 8px currentColor;
  flex: none;
}
.badge--plain::before { display: none; }
.badge--ok { color: var(--ok); background: var(--ok-soft); border-color: rgba(92, 217, 138, 0.22); }
.badge--warn { color: var(--warn); background: var(--warn-soft); border-color: rgba(255, 194, 75, 0.22); }
.badge--bad { color: var(--bad); background: var(--bad-soft); border-color: rgba(255, 95, 109, 0.22); }
.badge--info { color: var(--info); background: var(--info-soft); border-color: rgba(224, 194, 143, 0.22); }
.badge--accent { color: var(--accent); background: var(--accent-soft);
                 border-color: var(--accent-line); }
.badge--mute { color: var(--fg-3); background: var(--s-2); border-color: var(--line); }

/* ─────────────────────────── кнопки ─────────────────────────── */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  min-height: 42px;
  padding: 0 16px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--s-2);
  color: var(--fg);
  font: inherit;
  font-size: 14px;
  font-weight: 650;
  letter-spacing: -0.01em;
  cursor: pointer;
  white-space: nowrap;
  transition: transform var(--fast), background var(--fast),
              border-color var(--fast), opacity var(--fast);
}
.btn:hover { background: var(--hover-veil); }
.btn:active { transform: scale(0.97); }
.btn:disabled { opacity: 0.42; cursor: not-allowed; transform: none; }
.btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.btn--primary {
  background: var(--btn-grad);
  border-color: var(--btn-primary-line);
  color: #fff;
  box-shadow: var(--btn-shadow);
}
.btn--primary:hover { background: var(--btn-grad-hover); }

.btn--ok { color: var(--ok); background: var(--ok-soft); border-color: rgba(92, 217, 138, 0.28); }
.btn--ok:hover { background: rgba(92, 217, 138, 0.22); }
.btn--danger { color: var(--bad); background: var(--bad-soft); border-color: rgba(255, 95, 109, 0.28); }
.btn--danger:hover { background: rgba(255, 95, 109, 0.22); }
.btn--ghost { background: transparent; border-color: var(--line); }
.btn--ghost:hover { background: var(--s-1); }

.btn--sm { min-height: 34px; padding: 0 11px; font-size: 13px; border-radius: var(--r-xs); }
.btn--icon { min-height: 36px; width: 36px; padding: 0; border-radius: var(--r-pill); }
.btn--block { width: 100%; }
.btn--loading { pointer-events: none; color: transparent !important; position: relative; }
.btn--loading::after {
  content: "";
  position: absolute;
  width: 15px;
  height: 15px;
  border: 2px solid var(--spinner-track);
  border-top-color: var(--spinner-head);
  border-radius: 50%;
  animation: spin 640ms linear infinite;
}

@keyframes spin { to { transform: rotate(360deg); } }

/* Кнопки в ряду переносятся, а не сжимаются.

   По умолчанию flex ужимает элементы ниже их содержимого, а надпись на кнопке
   переносить нельзя — она набрана в одну строку. Получалось наложение: три
   кнопки в ряду печатались одна поверх другой. Запрет на сжатие ниже текста
   отправляет лишнюю кнопку на следующую строку — там она и должна быть. */
.btn-row { display: flex; gap: 8px; flex-wrap: wrap; }
.btn-row > .btn { flex-shrink: 0; }
/* `min-width: max-content` держал кнопку шире экрана, если подпись длинная:
   строка вылезала за край, и страницу можно было таскать вбок. Пусть лучше
   сожмётся — подпись всё равно в одну строку. */
.btn-row > .btn.grow { flex: 1 1 auto; min-width: 0; }
.btn-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.btn-grid > .btn { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
@media (min-width: 700px) { .btn-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

/* ─────────────────────────── чипсы-фильтры ─────────────────────────── */
.chips {
  display: flex;
  gap: 7px;
  overflow-x: auto;
  padding: 2px 2px 6px;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.chips::-webkit-scrollbar { display: none; }
.chips--tight { gap: 5px; padding: 0; overflow: visible; }
/* Фишки в две строки вместо прокрутки вбок.

   Прокрутка хороша для длинного списка, где заранее ясно, что он длинный:
   фильтры аккаунтов, например. Шесть шагов таймера — не список, а полный
   набор, и «+1 ч», уехавший за край экрана, читается как отсутствующий. */
.chips--wrap { flex-wrap: wrap; overflow: visible; }

/* Выбор периода — не список, а переключатель: вариантов мало, они равнозначны
   и никогда не прокручиваются. Поэтому они делят строку поровну, а не жмутся
   к левому краю, оставляя справа пустоту. */
.chips--fill { overflow: visible; }
.chips--fill > .chip {
  flex: 1 1 0;
  min-width: 0;
  padding: 0 8px;
  justify-content: center;
}

/* Подсветка едет под чипами, поэтому собственный фон выбранного чипа больше
   не нужен — иначе на экране два одинаковых прямоугольника вместо одного. */
.chips { position: relative; }
.chips > .chip[aria-pressed="true"] { background: transparent; border-color: transparent; }
.chips > .chip { position: relative; z-index: 1; }
.chips > [data-glow] { border-radius: var(--r-pill); }

.chip {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 32px;
  padding: 0 13px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--s-1);
  color: var(--fg-2);
  font: inherit;
  font-size: 13px;
  font-weight: 650;
  cursor: pointer;
  transition: all var(--fast);
}
.chip:active { transform: scale(0.95); }
.chip[aria-pressed="true"] {
  background: var(--accent-soft);
  border-color: var(--accent-line);
  color: var(--chip-on-fg);
}
.chip__n {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--fg-3);
  font-variant-numeric: tabular-nums;
}
.chip[aria-pressed="true"] .chip__n { color: var(--accent); }

/* ─────────────────────────── поля ввода ─────────────────────────── */
.field { margin-bottom: 14px; }
.field__label {
  display: block;
  font-size: 12px;
  font-weight: 650;
  color: var(--fg-2);
  margin: 0 0 6px 2px;
}
.field__hint {
  font-size: 11.5px;
  line-height: 1.45;
  color: var(--fg-3);
  margin: 6px 0 0 2px;
}
/* Пояснение перед кнопкой — не подпись к ней, а отдельная мысль. Вплотную
   они читаются как одно целое, и кнопка теряется в тексте. */
.field__hint + .btn,
.field__hint + .btn-row,
.field__hint + .btn-grid { margin-top: 12px; }
p + .btn--block { margin-top: 12px; }
.field__error { font-size: 11.5px; color: var(--bad); margin: 6px 0 0 2px; font-weight: 600; }

.input,
.textarea,
.select {
  width: 100%;
  /* Ширину считаем вместе с рамкой и отступами: иначе поле в шторке шире
     самой шторки ровно на них, и правый край текста уезжает за экран. */
  box-sizing: border-box;
  max-width: 100%;
  min-height: 44px;
  padding: 11px 13px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--input-bg);
  color: var(--fg);
  font: inherit;
  font-size: 15px;   /* меньше 16px iOS зумит поле при фокусе */
  transition: border-color var(--fast), box-shadow var(--fast), background var(--fast);
}
.input::placeholder, .textarea::placeholder { color: var(--fg-4); }
.input:focus, .textarea:focus, .select:focus {
  outline: none;
  border-color: var(--accent-line);
  box-shadow: 0 0 0 3px var(--accent-soft);
  background: var(--input-bg-focus);
}
.input[aria-invalid="true"], .textarea[aria-invalid="true"] {
  border-color: rgba(255, 95, 109, 0.6);
  box-shadow: 0 0 0 3px var(--bad-soft);
}
.textarea { min-height: 96px; resize: vertical; line-height: 1.5; }
.select { appearance: none; padding-right: 34px; cursor: pointer; }
.select option { background: var(--option-bg); color: var(--fg); }

.search {
  position: relative;
  display: flex;
  align-items: center;
}
.search svg { position: absolute; left: 12px; color: var(--fg-3); pointer-events: none; }
.search .input { padding-left: 38px; }
.search__clear {
  position: absolute;
  right: 8px;
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border: 0;
  border-radius: 50%;
  background: var(--s-2);
  color: var(--fg-2);
  cursor: pointer;
}

/* Переключатель */
.switch {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  padding: 12px 14px;
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}
.switch__track {
  flex: none;
  width: 44px;
  height: 26px;
  border-radius: var(--r-pill);
  background: var(--s-2);
  border: 1px solid var(--line);
  position: relative;
  transition: background var(--mid), border-color var(--mid);
}
.switch__track::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--fg-3);
  transition: transform var(--mid), background var(--mid);
}
.switch[aria-checked="true"] .switch__track {
  background: var(--btn-grad);
  border-color: transparent;
}
.switch[aria-checked="true"] .switch__track::after {
  transform: translateX(18px);
  background: var(--knob);
}

/* ─────────────────────────── списки-строки ─────────────────────────── */
.rows { display: flex; flex-direction: column; }
.row {
  display: flex;
  align-items: center;
  gap: 11px;
  width: 100%;
  padding: 12px 14px;
  border: 0;
  border-bottom: 1px solid var(--line-soft);
  background: none;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
  transition: background var(--fast);
}
.row:last-child { border-bottom: 0; }
.row:hover { background: var(--s-1); }
.row:active { background: var(--s-2); }
.row--static { cursor: default; }
.row--static:hover { background: none; }
/* Строки собраны из span, а не div: кнопке нельзя вкладывать блочные
   элементы по HTML. Поэтому раскладку задаём здесь — иначе заголовок
   и подпись слипаются в одну строку. */
.row__body { display: block; flex: 1; min-width: 0; }
.row__title {
  display: block;
  font-size: 14.5px;
  font-weight: 650;
  letter-spacing: -0.01em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.row__sub {
  display: block;
  font-size: 12.5px;
  color: var(--fg-3);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-top: 1px;
}
/* В шторке выбора строка — это не пункт списка, а объяснение выбора.

   В списке обрезка уместна: строк много, и они однотипные. В шторке строк
   три, каждая объясняет, что именно случится, — и обрывок «поменяет сам ·
   около …» не объясняет ничего. Здесь текст переносится, а строка растёт. */
.sheet .row__sub,
.picker .row__sub {
  white-space: normal;
  overflow: visible;
  text-overflow: clip;
  line-height: 1.35;
}
.sheet .row__title,
.picker .row__title { white-space: normal; }
.sheet .row,
.picker .row { align-items: flex-start; }
.sheet .row > span:first-child:not(.row__body):not(.row__side):not(.avatar),
.picker .row > span:first-child:not(.row__body):not(.row__side):not(.avatar) {
  margin-top: 2px;
}

.row__side { flex: none; text-align: right; display: flex; flex-direction: column; gap: 3px; align-items: flex-end; }
/* Кнопки в правой части строки стоят в ряд, а не столбиком: столбик растягивает
   строку вдвое и превращает список в лестницу. */
.row__side--actions { flex-direction: row; align-items: center; gap: 4px; }
.row__chev { flex: none; color: var(--fg-4); }

/* Пара «подпись — значение», основа всех карточек данных */
.kv {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--line-soft);
  font-size: 14px;
}
.kv:last-child { border-bottom: 0; }
/* Подпись со значком — одна строка. Значок здесь часть подписи, а не отдельный
   ярус: «конверт» над словом «Почта» читается как два разных элемента. */
.kv__k {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  color: var(--fg-3);
  font-size: 13px;
  flex: none;
}
.kv__k svg { flex: none; color: var(--fg-4); }
.kv__v {
  font-weight: 650;
  text-align: right;
  min-width: 0;
  overflow-wrap: anywhere;
}
.kv__v--mono { font-family: var(--mono); font-variant-numeric: tabular-nums; letter-spacing: -0.02em; }

/* Длинный текст (описание лота из заказа) не помещается в правую половину
   строки: прижатый к правому краю, он превращается в узкий столбик рваных
   строк, а переносы исходника при этом теряются. Такому значению нужна вся
   ширина, обычная левая выключка и сохранённые переносы — тогда описание
   читается так же, как его видит покупатель на витрине. */
.kv--stack {
  display: block;
  padding-top: 12px;
  padding-bottom: 13px;
}
.kv--stack .kv__k { display: flex; margin-bottom: 6px; }
.kv__text {
  display: block;
  margin: 0;
  color: var(--fg);
  font-size: 13px;
  font-weight: 500;
  line-height: 1.5;
  text-align: left;
  white-space: pre-line;
  overflow-wrap: anywhere;
}

/* Секрет: точками, пока не открыт. Открывается по PIN и копируется тапом. */
.secret {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 4px 9px;
  border: 1px dashed var(--line-strong);
  border-radius: var(--r-xs);
  background: var(--input-bg);
  font-family: var(--mono);
  font-size: 13px;
  letter-spacing: 0.02em;
  color: var(--fg);
  cursor: pointer;
  transition: border-color var(--fast), background var(--fast);
}
.secret:hover { border-color: var(--accent); }
.secret--masked { color: var(--fg-3); letter-spacing: 0.16em; }
.secret svg { color: var(--fg-3); flex: none; }
.secret--copied { border-style: solid; border-color: var(--ok); color: var(--ok); }

/* ─────────────────────────── карточка аккаунта ─────────────────────────── */
.acc-grid {
  display: grid;
  /* Две колонки на телефоне, крупная сетка на экране: карточка здесь —
     это витрина, а на витрине смотрят на картинку, а не на подпись. */
  grid-template-columns: repeat(auto-fill, minmax(154px, 1fr));
  gap: 14px;
  gap: var(--gap);
}

.acc-card {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--s-1);
  backdrop-filter: blur(var(--blur-1));
  -webkit-backdrop-filter: blur(var(--blur-1));
  overflow: hidden;
  cursor: pointer;
  text-align: left;
  font: inherit;
  color: inherit;
  padding: 0;
  transition: transform var(--fast), border-color var(--fast), box-shadow var(--fast);
}
.acc-card:hover { border-color: var(--line-strong); box-shadow: var(--sh-2); }
.acc-card:active { transform: scale(0.985); }

.acc-card__media {
  display: grid;
  position: relative;
  aspect-ratio: 16 / 11;
  background: var(--media-bg);
  display: grid;
  place-items: center;
  overflow: hidden;
}
@media (min-width: 560px) {
  .acc-grid { grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); }
}
@media (min-width: 900px) {
  .acc-grid { grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }
}

.acc-card__media img {
  width: 100%;
  height: 100%;
  /* cover, а не contain: скриншот ангара всегда шире карточки, и `contain`
     оставлял бы поля по бокам. Центрируем — интересное в ангаре по центру. */
  object-fit: cover;
  object-position: center;
  display: block;
}
/* Без фото плитка не держит пустой прямоугольник 16:11.

   Фото ангара есть далеко не у всех аккаунтов, и до сих пор каждая такая
   плитка отдавала половину своей высоты серому пятну: на экран помещалось
   четыре аккаунта вместо восьми, а листать приходилось ради строки текста.
   Значки состояния и номера при этом никуда не деваются — они переезжают в
   узкую полосу сверху, где и читаются лучше, чем поверх картинки. */
.acc-card__media--empty {
  aspect-ratio: auto;
  min-height: 34px;
  background: transparent;
}
.acc-card__media--empty .acc-card__stub { display: none; }
.acc-card__media--empty .acc-card__badge,
.acc-card__media--empty .acc-card__num { top: 10px; }
.acc-card__media--empty .acc-card__timer { bottom: auto; top: 10px; left: auto; right: 62px; }
.acc-card__stub {
  display: grid;
  place-items: center;
  width: 54px;
  height: 54px;
  border-radius: 50%;
  background: var(--s-2);
  border: 1px solid var(--line);
  color: var(--fg-4);
}
.acc-card__badge { position: absolute; top: 8px; left: 8px; backdrop-filter: blur(10px); }
.acc-card__num {
  position: absolute;
  top: 8px;
  right: 8px;
  padding: 2px 8px;
  border-radius: var(--r-pill);
  background: var(--overlay-chip);
  backdrop-filter: blur(10px);
  font-family: var(--mono);
  font-size: 11.5px;
  font-weight: 700;
}
/* Таймер поверх фото: у занятого аккаунта это самое важное число на карточке */
.acc-card__timer {
  position: absolute;
  left: 8px;
  bottom: 8px;
  padding: 3px 9px;
  border-radius: var(--r-pill);
  background: var(--overlay-chip);
  backdrop-filter: blur(10px);
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--warn);
}
.acc-card__body { display: block; padding: 10px 12px 12px; }
.acc-card__title {
  display: block;
  font-size: 14.5px;
  font-weight: 700;
  letter-spacing: -0.015em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.acc-card__meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-top: 3px;
  font-size: 12px;
  color: var(--fg-3);
}
.acc-card__price { font-family: var(--mono); font-weight: 700; color: var(--fg-2); }

/* Лестница сроков под ценой: четыре коротких пары «срок — цена».

   Числа те, что видит покупатель, и округлены до рубля: в плитке важно, ровно
   ли растёт лестница, а не копейка на конце. Срок, для которого лота ещё нет,
   показан бледным — иначе непонятно, почему выручка идёт только с двух. */
.acc-card__ladder {
  display: flex;
  flex-wrap: wrap;
  gap: 3px 5px;
  margin-top: 6px;
  font-family: var(--mono);
  font-size: 10.5px;
  font-variant-numeric: tabular-nums;
  color: var(--fg-3);
}
.acc-card__step {
  display: inline-flex;
  gap: 3px;
  padding: 1px 5px;
  border-radius: 6px;
  background: var(--sunken);
  white-space: nowrap;
}
.acc-card__step b { color: var(--fg-4); font-weight: 700; }
.acc-card__step--gone { opacity: 0.42; }

/* Строка о том, чего пока нет: срок без лота. Бледная, но читаемая — это не
   ошибка и не запрет, а незанятое место, которое можно занять. */
.row--dim { opacity: 0.55; }

/* Полоска заполнения: окупаемость аккаунта. Число рядом отвечает «сколько»,
   полоска — «много это или мало», и второе читается быстрее. */
.meter {
  height: 6px;
  border-radius: var(--r-pill);
  background: var(--sunken);
  overflow: hidden;
}
.meter__fill {
  display: block;
  height: 100%;
  border-radius: var(--r-pill);
  background: var(--accent);
  transition: width var(--mid);
}
.meter__fill.ok { background: var(--ok); }

/* Герой детального экрана */
/* Фото ангара — главное, что отличает один аккаунт от другого, поэтому оно
   занимает всю ширину и настолько высоко, насколько позволяет экран. Раньше
   потолок в 260px резал скриншот пополам: техника оказывалась за кадром, а
   видно было небо и надпись «ангар». */
.hero {
  position: relative;
  margin: 0 calc(var(--pad) * -1) 16px;
  aspect-ratio: 16 / 9;
  max-height: 46vh;
  overflow: hidden;
  background: var(--media-bg);
  display: grid;
  place-items: center;
  cursor: zoom-in;
  /* Скругление снизу: сверху кадр упирается в шапку, а снизу должен закончиться
     мягко, а не обрывом поперёк экрана. */
  border-radius: 0 0 var(--r-lg) var(--r-lg);
}
/* `cover`: кадр заполняет рамку целиком. `contain` оставлял поля, закрытые
   размытой копией того же кадра, и выглядело это так, будто фото вставили
   криво. Обрезается при этом немного — скриншот ангара и рамка почти одного
   отношения сторон, — а целиком кадр открывается по нажатию. */
.hero img {
  position: relative;
  z-index: 1;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.hero__blur {
  position: absolute;
  inset: -12px;
  z-index: 0;
  background-size: cover;
  background-position: center;
  filter: blur(26px) saturate(1.2);
  opacity: 0.55;
}
@media (min-width: 900px) {
  .hero { max-height: 480px; }
}

/* Широкий экран — широкая колонка.
   Девятьсот точек посреди двух с половиной тысяч выглядят как страница,
   зажатая с боков: половина окна пустая, а фото ангара и плитки ужаты в
   середину. Растём вместе с окном, но не бесконечно — строка длиннее ста
   знаков читается хуже, а не лучше. */
@media (min-width: 1280px) {
  .main { max-width: 1120px; }
}
@media (min-width: 1600px) {
  .main { max-width: 1320px; }
  .hero { max-height: 560px; }
}
/* Затемнение снизу — под подпись, чтобы белый текст читался на любом кадре. */
.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--hero-fade);
  pointer-events: none;
}

/* И сверху: там проходит шапка экрана, и на светлом небе её название
   сливалось с ангаром. Полоса размывает сам кадр, а не кладёт на него плашку —
   так остаётся видно, что под ней. */
.hero::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 34%;
  z-index: 2;
  background: var(--hero-top-fade);
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
  -webkit-mask-image: linear-gradient(180deg, #000 35%, transparent);
  mask-image: linear-gradient(180deg, #000 35%, transparent);
  pointer-events: none;
}
/* Затемнение под подписью.

   Ник и номер лежат прямо на скриншоте ангара, а ангар — это яркая пёстрая
   картинка: белые буквы на светлом танке не читаются вовсе. Раньше их
   спасала только тень от шрифта, и на половине аккаунтов её не хватало.
   Мягкая тень снизу вверх решает это, не пряча сам кадр. */
.hero::after {
  content: "";
  position: absolute;
  inset: auto 0 0;
  height: 52%;
  z-index: 1;
  background: linear-gradient(180deg, transparent, rgba(0, 0, 0, 0.78));
  pointer-events: none;
}
.hero__name, .hero__sub { text-shadow: 0 1px 3px rgba(0, 0, 0, 0.65); }
.hero__name { color: #fff; }
.hero__sub { color: rgba(255, 255, 255, 0.86) !important; }

.hero__overlay { z-index: 3; }
.hero__overlay {
  position: absolute;
  left: var(--pad);
  right: var(--pad);
  bottom: 12px;
  z-index: 2;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 12px;
}
.hero__overlay > .grow { min-width: 0; }
.hero__overlay .inline { flex: none; }
/* Длинное имя ужимается, а не выталкивает кнопки вниз: две строки максимум,
   дальше многоточие. Ник целиком всегда виден в шапке экрана. */
.hero__name {
  font-size: 24px;
  font-weight: 800;
  letter-spacing: -0.035em;
  line-height: 1.1;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.hero__sub { font-size: 12.5px; color: var(--fg-2); margin-top: 3px; }

/* ─────────────────────────── чат ─────────────────────────── */

/* Композер: заготовки ответов сверху, поле ввода снизу.

   Раньше здесь стоял `flex-direction: row`, и лента заготовок вставала в один
   ряд с полем ввода — она наезжала на него и на кнопку отправки, а на узком
   экране кнопку было просто не нажать. Это два разных яруса, а не два соседа. */
.composer {
  position: sticky;
  bottom: var(--tabbar-total);
  /* Панель поверх переписки, а не вровень с ней.

     Без своего слоя сообщения, идущие в разметке ниже, рисовались поверх
     поля: разделитель дня и аватар наезжали на строку ввода, и она выглядела
     живущей отдельной жизнью. Липкое положение само по себе слоя не создаёт —
     нужен явный. */
  z-index: 4;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 10px 0;
  /* Плотная плашка, а не полупрозрачный градиент.

     Градиент оставлял просвечивать то, что проезжает под композером: заголовок
     «ОТЗЫВ» читался сквозь заготовки ответов, и низ экрана выглядел смазанным.
     Композер — это панель поверх переписки, и вести себя должен как панель. */
  background: var(--composer-bg);
  border-top: 1px solid var(--line);
  margin: 0 calc(var(--pad) * -1);
  padding: 10px var(--pad);
}
/* Верхний край композера смягчаем узкой растяжкой — иначе панель обрубает
   ленту сообщений линейкой поперёк экрана. */
.composer::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 100%;
  height: 18px;
  background: var(--composer-fade);
  pointer-events: none;
}
.composer > .inline { width: 100%; }
.composer .textarea {
  min-height: 44px;
  max-height: 140px;
  resize: none;
  border-radius: var(--r-lg);
  padding: 11px 15px;
  /* Поле тоже плотное: полупрозрачное поверх полупрозрачной панели давало
     два слоя дымки, сквозь которые просвечивал разговор. */
  background: var(--composer-field);
  border-color: var(--line-strong);
}
.composer .textarea:focus { background: var(--composer-field); }
/* Кнопка отправки ровно по нижнему краю поля, а не по его середине: поле
   растёт вверх по мере набора, и привязка к середине уводила кнопку вбок. */
.composer .btn--icon { flex: none; align-self: flex-end; }
/* Поле и кнопка — всегда в одну строку.

   `.inline` умеет переносить, и это правильно для панелей с кнопками. Но не
   здесь: стоит полю запросить чуть больше ширины, чем осталось, и кнопка
   «отправить» уезжает на строку ниже, а поле растягивается во всю панель.
   Выглядит это как поломка, и ею и является: композер — одна строка.

   `flex: 1 1 0` вместо `auto` — чтобы ширину поля задавал остаток места,
   а не длина набранного текста. */
.composer .inline { flex-wrap: nowrap; min-width: 0; }
.composer .textarea.grow { flex: 1 1 0; min-width: 0; }

/* Переписка списком, как на самой площадке: аватар, ник, время, текст.

   Пузыри хороши в мессенджере, где два собеседника обмениваются короткими
   репликами. Здесь другое: сообщения бота длинные и шаблонные, и в пузырях
   они занимали пол-экрана каждое, а найти среди них живой вопрос покупателя
   становилось трудно. */
.talk { display: flex; flex-direction: column; padding-bottom: 6px; }
.talk__day {
  align-self: center;
  margin: 14px 0 10px;
  padding: 3px 12px;
  border-radius: var(--r-pill);
  background: var(--s-1);
  border: 1px solid var(--line-soft);
  font-size: 11.5px;
  font-weight: 650;
  color: var(--fg-3);
}
.msg {
  display: flex;
  gap: 10px;
  padding: 8px 2px;
}
/* Подряд идущие сообщения одного автора: без повтора шапки и аватара —
   так лента читается как разговор, а не как таблица. */
.msg--same { padding-top: 0; }
.msg--same .msg__head { display: none; }
.msg__side { flex: none; width: 34px; }
.msg__body { flex: 1; min-width: 0; }
.msg__head {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-bottom: 2px;
}
.msg__author { font-size: 13.5px; font-weight: 700; letter-spacing: -0.01em; }
.msg__author--mine { color: var(--accent); }
.msg__time {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--fg-4);
  font-variant-numeric: tabular-nums;
}
.msg__tag {
  font-size: 10px;
  font-weight: 700;
  color: var(--fg-3);
  padding: 1px 6px;
  border-radius: var(--r-pill);
  background: var(--s-2);
}
.msg__text {
  font-size: 14.5px;
  line-height: 1.45;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.msg__text img { max-width: min(100%, 320px); border-radius: var(--r-sm); margin-top: 6px; }

/* Системные сообщения FunPay — плашкой, как на площадке */
.msg--system {
  padding: 10px 12px;
  margin: 8px 0;
  border-radius: var(--r-sm);
  background: var(--s-1);
  border: 1px solid var(--line-soft);
  font-size: 13px;
  color: var(--fg-2);
  line-height: 1.45;
}

/* ─────────────────────────── графики ─────────────────────────── */
.chart { position: relative; width: 100%; }
.chart svg { display: block; width: 100%; overflow: visible; }
.chart__grid line { stroke: var(--line-soft); stroke-width: 1; }
/* Точки и подписи лежат поверх графика обычной вёрсткой.

   Сам SVG растянут неравномерно (`preserveAspectRatio="none"`), иначе линия
   не займёт всю ширину. Но вместе с линией растягивалось и всё остальное:
   кружок превращался в овал, а цифры оси — в сплющенные. Поэтому они здесь,
   снаружи, и позиционируются в процентах: круг остаётся кругом при любой
   ширине экрана. */
.chart__dots, .chart__axes {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.chart__dot {
  position: absolute;
  width: 9px;
  height: 9px;
  margin: -4.5px 0 0 -4.5px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 2.5px var(--bg);
  opacity: 0;
  transition: opacity var(--fast);
}
.chart__dot.is-on { opacity: 1; }

.chart__axis {
  position: absolute;
  bottom: 2px;
  transform: translateX(-50%);
  color: var(--fg-4);
  font-size: 10px;
  font-family: var(--mono);
  white-space: nowrap;
}
/* Столбики остались только как невидимые области попадания: по ним удобно
   целиться пальцем, но рисовать их незачем — форму задаёт линия. */
.chart__hit { fill: transparent; cursor: pointer; }
.chart__hit:hover + .chart__mark, .chart__hit:hover { opacity: 1; }
.chart__area { fill: url(#areaGrad); }
.chart__line {
  fill: none;
  stroke: var(--accent);
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  filter: drop-shadow(0 2px 8px color-mix(in srgb, var(--accent) 45%, transparent));
}
.chart__mark { opacity: 0; transition: opacity var(--fast); }
.chart__cursor { stroke: var(--line-strong); stroke-width: 1; stroke-dasharray: 3 3; }

.chart__tip {
  position: absolute;
  z-index: 5;
  pointer-events: none;
  transform: translate(-50%, -100%);
  padding: 7px 10px;
  border-radius: var(--r-xs);
  background: var(--s-4);
  border: 1px solid var(--line-strong);
  backdrop-filter: blur(var(--blur-2));
  -webkit-backdrop-filter: blur(var(--blur-2));
  box-shadow: var(--sh-3);
  font-size: 12px;
  white-space: nowrap;
  opacity: 0;
  transition: opacity var(--fast);
}
.chart__tip[data-show="1"] { opacity: 1; }
/* Перевёрнутая подсказка растёт вниз от точки, а не вверх. */
.chart__tip--below { transform: translate(-50%, 0); }
.chart__tip b { font-family: var(--mono); font-variant-numeric: tabular-nums; }

/* Гистограмма распределения оценок */
.stars-spread { display: flex; flex-direction: column; gap: 5px; flex: 1; }
.stars-row { display: flex; align-items: center; gap: 8px; font-size: 11.5px; }
.stars-row__n { width: 30px; color: var(--fg-3); font-family: var(--mono); }
/* display:block обязателен: span внутри span остаётся строчным и высоту
   не принимает — полоска рисуется нулевой и распределение выглядит пустым. */
.stars-row__bar { display: block; flex: 1; height: 6px; border-radius: var(--r-pill);
                  background: var(--s-2); overflow: hidden; }
.stars-row__fill { display: block; height: 100%; min-width: 2px; border-radius: var(--r-pill);
                   background: linear-gradient(90deg, var(--warn), #ffd88a);
                   transition: width var(--slow); }
.stars-row__c { width: 26px; text-align: right; color: var(--fg-3); font-family: var(--mono); }

.star-on svg { fill: currentColor; }

.rating-big {
  font-family: var(--mono);
  font-size: 40px;
  font-weight: 800;
  letter-spacing: -0.05em;
  line-height: 1;
}

/* Ввод своего значения рядом с быстрыми кнопками: набрать «90» быстрее,
   чем нажать «+1 ч» и потом «+30 м». */
.custom-row { display: flex; gap: 8px; align-items: stretch; }
.custom-row .input { flex: 1; min-height: 38px; padding: 8px 12px; }
.custom-row .btn { min-height: 38px; }

/* Заголовок блока со значком. Значок здесь не украшение: блоки в разделе
   «Ещё» идут подряд и различаются одним словом, а по значку глаз находит
   нужный, не читая. */
.hold__head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 4px;
  font-weight: 650;
}
.hold__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 9px;
  background: var(--accent-soft);
  color: var(--accent);
}

/* Непрочитанный диалог. Не переставляем его в списке — помечаем: место в
   списке говорит «когда написали», а точка — «вы это не читали». Смешивать
   два разных вопроса в одном признаке значит потерять оба. */
.row--unread .row__title { font-weight: 750; color: var(--fg-1); }
.row--unread .row__sub { color: var(--fg-2); }
.dot-new {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);
  flex: none;
}

/* Образцы цвета: кружок с самим цветом и обводка у выбранного. Подпись здесь
   лишняя — цвет и есть подпись. */
.swatches {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(44px, 1fr));
  gap: 10px;
  margin: 12px 0 6px;
}
.swatch {
  height: 44px;
  border-radius: var(--r-sm);
  border: 1px solid var(--line);
  background: var(--s-1);
  display: grid;
  place-items: center;
  cursor: pointer;
  transition: all var(--fast);
}
.swatch span {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--swatch);
  box-shadow: 0 2px 8px color-mix(in srgb, var(--swatch) 55%, transparent);
}
.swatch:active { transform: scale(0.94); }

/* Свой цвет. Системное поле выбора цвета рисуется как прямоугольник, и в
   ряду с круглыми образцами читалось как овал — будто девятый цвет чем-то
   отличается от остальных. Приводим к тому же кругу. */
.swatch-own {
  width: 34px;
  height: 34px;
  padding: 0;
  border: 2px solid var(--line-strong);
  border-radius: 50%;
  background: none;
  cursor: pointer;
  overflow: hidden;
  appearance: none;
  -webkit-appearance: none;
}
.swatch-own::-webkit-color-swatch-wrapper { padding: 0; }
.swatch-own::-webkit-color-swatch { border: 0; border-radius: 50%; }
.swatch-own::-moz-color-swatch { border: 0; border-radius: 50%; }
.swatch--on {
  border-color: var(--swatch);
  background: color-mix(in srgb, var(--swatch) 14%, transparent);
}

/* ─────────────────────────── состояния ─────────────────────────── */
.skeleton {
  border-radius: var(--r-sm);
  background: linear-gradient(90deg, var(--s-1) 25%, var(--s-2) 50%, var(--s-1) 75%);
  background-size: 220% 100%;
  animation: shimmer 1.35s infinite linear;
}
@keyframes shimmer { to { background-position: -220% 0; } }


/* Лента событий: что происходило с человеком — цветная точка, текст, «3 часа назад». */
.tl { padding: 6px 0; }
.tl__row {
  display: grid;
  grid-template-columns: 8px minmax(0, 1fr) auto;
  gap: 12px;
  align-items: baseline;
  padding: 8px 16px;
  font-size: 13px;
  line-height: 1.4;
}
.tl__dot { width: 7px; height: 7px; border-radius: 50%; background: var(--fg-4); align-self: start; margin-top: 6px; }
.tl__row--ok .tl__dot { background: var(--ok); }
.tl__row--warn .tl__dot { background: var(--warn); }
.tl__row--bad .tl__dot { background: var(--bad); }
.tl__text { overflow-wrap: anywhere; }
.tl__time { font-size: 11px; color: var(--fg-4); white-space: nowrap; }

/* Раскрывающийся блок карточки: значок в цветной плитке, подпись последнего события, счётчик. */
.drawer__icon {
  flex: none;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 11px;
  background: var(--info-soft);
  color: var(--info);
}
.drawer__icon--ok { background: var(--ok-soft); color: var(--ok); }
.drawer__icon--warn { background: var(--warn-soft); color: var(--warn); }
.drawer__icon--bad { background: var(--bad-soft); color: var(--bad); }
.drawer__sub {
  display: block;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.drawer__badge {
  flex: none;
  padding: 3px 9px;
  border-radius: 999px;
  font-size: 11.5px;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
  background: var(--s-2);
  color: var(--fg-3);
  white-space: nowrap;
}
.drawer__badge--ok { background: var(--ok-soft); color: var(--ok); }
.drawer__badge--warn { background: var(--warn-soft); color: var(--warn); }
.drawer__badge--bad { background: var(--bad-soft); color: var(--bad); }

/* Опасное действие — отдельной карточкой с красной рамкой, чтобы его нельзя было нажать «заодно». */
.danger-card {
  margin-top: 14px;
  padding: 0;
  overflow: hidden;
  border-color: color-mix(in srgb, var(--bad) 45%, transparent);
}

/* Список вариантов: значок в плитке, заголовок, пояснение, стрелка. */
.opt-list { padding: 0; overflow: hidden; }
.opt-list .rows > .opt + .opt { border-top: 1px solid var(--line-soft); }
.opt { padding: 13px 14px; }
.opt[disabled] { opacity: 0.55; cursor: not-allowed; }
.opt .opt__icon {
  flex: none;
  width: 36px;
  height: 36px;
  display: grid;
  place-items: center;
  margin-top: 0;
  border-radius: var(--r-sm);
  background: var(--accent-soft);
  color: var(--accent);
}
.opt--danger .opt__icon { background: var(--bad-soft); color: var(--bad); }
.sheet .opt { align-items: center; }
/* Подпись варианта объясняет, что случится, — обрезать её нельзя. */
.opt-list .row__sub, .opt-list .row__title {
  white-space: normal;
  overflow: visible;
  text-overflow: clip;
  line-height: 1.35;
}
.empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 44px 24px;
  text-align: center;
}
.empty__icon {
  display: grid;
  place-items: center;
  width: 56px;
  height: 56px;
  border-radius: var(--r-lg);
  background: var(--s-2);
  border: 1px solid var(--line);
  color: var(--fg-3);
}
.empty__title { font-size: 15.5px; font-weight: 700; }
.empty__text { font-size: 13px; color: var(--fg-3); max-width: 300px; line-height: 1.5; }

.error-box {
  display: flex;
  gap: 11px;
  padding: 14px;
  border-radius: var(--r-md);
  background: var(--bad-soft);
  border: 1px solid var(--bad-line);
}
.error-box svg { color: var(--bad); flex: none; margin-top: 1px; }
.error-box__title { font-weight: 700; font-size: 14px; margin-bottom: 2px; }
.error-box__text { font-size: 13px; color: var(--fg-2); overflow-wrap: anywhere; }

.notice {
  display: flex;
  gap: 10px;
  margin-top: 10px;
  padding: 12px 14px;
  border-radius: var(--r-md);
  background: var(--s-1);
  border: 1px solid var(--line);
  font-size: 13px;
  color: var(--fg-2);
  line-height: 1.45;
}
.notice svg { flex: none; margin-top: 1px; color: var(--fg-3); }
.notice--warn { background: var(--warn-soft); border-color: rgba(255, 194, 75, 0.24); }
.notice--warn svg { color: var(--warn); }

/* ─────────────────────────── шторка и диалог ─────────────────────────── */
.scrim {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: var(--scrim);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  animation: fade var(--mid) both;
}
@keyframes fade { from { opacity: 0; } }

.sheet {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 61;
  max-height: 86vh;
  display: flex;
  flex-direction: column;
  padding-bottom: var(--safe-b);
  background: var(--s-4);
  backdrop-filter: blur(var(--blur-3)) saturate(180%);
  -webkit-backdrop-filter: blur(var(--blur-3)) saturate(180%);
  border-top: 1px solid var(--line-strong);
  border-radius: var(--r-xl) var(--r-xl) 0 0;
  box-shadow: var(--sh-3);
  animation: rise var(--slow) both;
}
@keyframes rise { from { transform: translateY(102%); } }

.sheet__grip {
  width: 38px;
  height: 4px;
  border-radius: var(--r-pill);
  background: var(--line-strong);
  margin: 9px auto 4px;
  flex: none;
}
.sheet__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 6px 18px 12px;
  flex: none;
}
.sheet__title { font-size: 17px; font-weight: 750; letter-spacing: -0.02em; }
.sheet__body { padding: 0 18px 18px; overflow-y: auto; -webkit-overflow-scrolling: touch; }

@media (min-width: 620px) {
  .sheet {
    left: 50%;
    right: auto;
    bottom: auto;
    top: 50%;
    width: min(520px, calc(100vw - 40px));
    transform: translate(-50%, -50%);
    border-radius: var(--r-xl);
    border: 1px solid var(--line-strong);
    animation: pop var(--mid) both;
  }
  @keyframes pop {
    from { opacity: 0; transform: translate(-50%, -46%) scale(0.97); }
  }
}

/* Сетка разделов в «Ещё» — как ящик приложений */
.menu-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 9px;
}
.menu-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--s-1);
  color: var(--fg);
  font: inherit;
  font-size: 14px;
  font-weight: 650;
  text-align: left;
  cursor: pointer;
  transition: background var(--fast), transform var(--fast);
}
.menu-item:hover { background: var(--s-2); }
.menu-item:active { transform: scale(0.97); }
.menu-item svg { color: var(--accent); flex: none; }
.menu-item small { display: block; font-size: 11px; font-weight: 500; color: var(--fg-3); }

/* ─────────────────────────── тосты ─────────────────────────── */
.toasts {
  position: fixed;
  left: 50%;
  transform: translateX(-50%);
  bottom: calc(var(--tabbar-total) + 14px);
  z-index: 80;
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: min(440px, calc(100vw - 28px));
  pointer-events: none;
}
.toast {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 11px 14px;
  border-radius: var(--r-md);
  background: var(--s-4);
  border: 1px solid var(--line-strong);
  backdrop-filter: blur(var(--blur-2)) saturate(170%);
  -webkit-backdrop-filter: blur(var(--blur-2)) saturate(170%);
  box-shadow: var(--sh-3);
  font-size: 13.5px;
  font-weight: 600;
  animation: toast-in var(--mid) both;
  pointer-events: auto;
}
.toast svg { flex: none; }
.toast--ok svg { color: var(--ok); }
.toast--bad svg { color: var(--bad); }
.toast--info svg { color: var(--accent); }
.toast[data-leaving="1"] { animation: toast-out var(--fast) both; }
@keyframes toast-in { from { opacity: 0; transform: translateY(14px) scale(0.96); } }
@keyframes toast-out { to { opacity: 0; transform: translateY(8px) scale(0.97); } }

/* ─────────────────────────── переход между экранами ───────────────────────────
   Экран появляется сразу, без въезда.

   Анимация была задумана как мягкость, а читалась как задержка: между нажатием
   и готовой страницей полкадра пустоты, и на возврате к уже загруженному
   экрану она проигрывалась заново — это и есть то самое «моргание при
   перезаходе». Мгновенная отрисовка честнее: страница готова — значит,
   показана. */
.view { animation: none; }

/* Переключатель темы. Значок показывает, что получишь после нажатия
   (луна в светлой теме, солнце в тёмной), — так понятнее, чем показывать
   текущее состояние: кнопку нажимают, чтобы что-то изменить. */
.theme-toggle svg { transition: transform var(--mid); }
.theme-toggle:active svg { transform: rotate(-35deg) scale(0.86); }

/* Сегментированный переключатель: два-четыре варианта, все видны сразу.

   Список из трёх пунктов, который надо открыть, чтобы увидеть три пункта, —
   лишний шаг ради ничего. Выбор виден и меняется одним касанием. */
.seg {
  position: relative;
  display: inline-flex;
  padding: 3px;
  gap: 2px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--sunken);
  width: 100%;
}
.seg__opt {
  flex: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 34px;
  padding: 0 10px;
  border: 0;
  border-radius: 9px;
  background: none;
  color: var(--fg-3);
  font: inherit;
  font-size: 13.5px;
  font-weight: 650;
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--fast), color var(--fast);
}
.seg__opt:hover { color: var(--fg-2); }
.seg__opt[aria-pressed="true"] { color: var(--fg); }
.seg__opt[aria-pressed="true"] span { position: relative; z-index: 1; }

/* Подсветка — отдельный слой, который переезжает под выбранный пункт.
   Перекрашивать фон у двух кнопок сразу дёшево, но выглядит как мигание;
   едущий прямоугольник показывает, что выбор сместился, а не сменился. */
/* Отступ сверху не задаём: положение целиком считает `attachGlow` и кладёт
   в transform. Пока здесь стояло `top: 3px`, к посчитанной координате
   прибавлялись ещё три пикселя набивки — подсветка садилась ниже кнопки, и это
   было видно как неровную рамку. */
.seg__glow {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 0;
  border-radius: 9px;
  background: var(--accent-soft);
  box-shadow: inset 0 0 0 1px var(--accent-line);
  transition: transform var(--mid), width var(--mid), height var(--mid),
              opacity var(--fast);
  pointer-events: none;
}
.seg__opt[aria-pressed="true"] svg { color: var(--accent); }

/* Данные из кеша: показывать вчерашние цифры молча нельзя */
.stale {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 12px;
  padding: 9px 12px;
  border-radius: var(--r-sm);
  background: var(--warn-soft);
  border: 1px solid var(--warn-line);
  color: var(--warn);
  font-size: 12.5px;
  font-weight: 600;
}

/* Выбор нескольких аккаунтов: галочка поверх плитки */
.acc-card__pick {
  position: absolute;
  top: 8px;
  left: 8px;
  z-index: 2;
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  border: 2px solid var(--pick-ring);
  background: var(--overlay-dim);
  backdrop-filter: blur(8px);
  color: transparent;
}
.acc-card[aria-selected="true"] { border-color: var(--accent); box-shadow: var(--glow); }
.acc-card[aria-selected="true"] .acc-card__pick {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

/* Панель массовых действий: появляется, когда есть что выбрать */
.bulkbar {
  position: fixed;
  left: 50%;
  transform: translateX(-50%);
  bottom: calc(var(--tabbar-total) + 12px);
  z-index: 50;
  display: flex;
  align-items: center;
  gap: 8px;
  width: min(520px, calc(100vw - 24px));
  padding: 10px 12px;
  border-radius: var(--r-lg);
  background: var(--s-4);
  border: 1px solid var(--line-strong);
  backdrop-filter: blur(var(--blur-3)) saturate(180%);
  -webkit-backdrop-filter: blur(var(--blur-3)) saturate(180%);
  box-shadow: var(--sh-3);
  animation: rise var(--mid) both;
}

/* Заготовки ответов над полем ввода */
/* Заготовки ответов переносятся строками, а не уезжают вбок.

   Горизонтальная лента прятала половину заготовок за краем экрана: чтобы
   узнать, что там, надо было её листать — а ради этого проще напечатать
   ответ руками. Две строки видно целиком и сразу. */

/* Аватар собеседника: буква вместо картинки — FunPay их не отдаёт списком */
.avatar {
  display: grid;
  place-items: center;
  flex: none;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: var(--media-bg);
  border: 1px solid var(--line);
  font-weight: 700;
  font-size: 15px;
  color: var(--fg-2);
  text-transform: uppercase;
}
.avatar--sm { width: 30px; height: 30px; font-size: 12.5px; }
.avatar--unread { border-color: var(--accent); color: var(--accent); }

/* ─────────────────────────── мелочи ─────────────────────────── */
.mono { font-family: var(--mono); font-variant-numeric: tabular-nums; letter-spacing: -0.02em; }
.muted { color: var(--fg-3); }
.dim { color: var(--fg-4); }
.ok { color: var(--ok); }
.warn { color: var(--warn); }
.bad { color: var(--bad); }
.center { text-align: center; }
.stack { display: flex; flex-direction: column; gap: var(--gap); }
.inline { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.spread { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.pad { padding: 14px; }
.grow { flex: 1; min-width: 0; }
.nowrap { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hidden { display: none !important; }
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.timer { font-family: var(--mono); font-variant-numeric: tabular-nums; font-weight: 700; letter-spacing: -0.03em; }
.timer--soon { color: var(--warn); }
.timer--over { color: var(--bad); }

.divider { height: 1px; background: var(--line-soft); margin: 14px 0; }

/* Уважение к системной настройке: анимация — украшение, а не смысл */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ─────────────────────────── сворачиваемый блок ───────────────────────────
   Содержимое остаётся в разметке и прячется стилем: раскрытие происходит
   мгновенно, без запроса и без перерисовки экрана. Высота анимируется через
   grid-template-rows — единственный способ доехать до «сколько получится»,
   не зная высоты заранее. */
.fold__wrap {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--mid);
}
.fold--open > .fold__wrap { grid-template-rows: 1fr; }
.fold__body {
  overflow: hidden;
  min-height: 0;
}
.fold > .row[aria-expanded] .row__chev { transition: transform var(--mid); }
.fold--open > .row[aria-expanded] .row__chev { transform: rotate(180deg); }
/* Заголовок раскрытого блока отделяем от содержимого — иначе первая строка
   настроек читается как часть заголовка. */
.fold--open > .row[aria-expanded] { border-bottom: 1px solid var(--line); }
.fold__rows > .row + .row,
.fold__rows > .switch + .switch,
.fold__rows > .row + .switch,
.fold__rows > .switch + .row { border-top: 1px solid var(--line); }

@media (prefers-reduced-motion: reduce) {
  .fold__wrap { transition: none; }
}


/* Ссылка со значком — одна строка. «Открыть ↗» с переносом читается как две
   разные вещи: слово и непонятный символ под ним. */
.link {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  white-space: nowrap;
  color: var(--accent);
  font-weight: 650;
}
.link svg { flex: none; }

/* Вложенный блок внутри группы настроек: действие лежит там же, где настройки,
   которыми оно управляется. Отделяем линией и подписью, чтобы не путать
   действие («выгрузить») со значением («хранить копий: 7»). */
.subblock {
  padding: 12px 14px 14px;
  border-top: 1px solid var(--line);
}
.subblock__head {
  display: flex;
  align-items: center;
  gap: 7px;
  margin-bottom: 10px;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--fg-3);
}
.subblock__head svg { color: var(--fg-4); }

/* Аватар с настоящим фото. Буква остаётся под картинкой: если та не
   загрузилась (а чужой хост может отдать что угодно), кружок не станет пустым. */
.avatar, .avatar--sm {
  flex: none;
  align-self: center;
  aspect-ratio: 1;
}
/* Размер задан жёстко и не должен переопределяться контекстом. */
.avatar { width: 38px; height: 38px; }
.avatar--sm { width: 30px; height: 30px; }
/* Кружок с фотографией.

   Рамка здесь не `border`, а внутренняя тень. Обычная рамка рисуется снаружи
   содержимого: картинка занимает только внутреннюю область, и между ней и
   рамкой остаётся кольцо фона — та самая кривая обводка. Внутренняя тень лежит
   поверх картинки и обходится без зазора.

   Буква под фотографией остаётся как запасной слой — на случай, если чужая
   картинка не загрузится. Пока картинка есть, буква спрятана: просвечивая по
   краям, она превращала кружок в грязное пятно. */
.avatar--photo {
  position: relative;
  overflow: hidden;
  padding: 0;
  border: 0;
  box-shadow: inset 0 0 0 1px var(--line);
}
.avatar--photo::before {
  content: attr(data-letter);
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
}
.avatar--photo:has(img)::before { content: none; }
.avatar--photo img {
  position: absolute;
  inset: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 50%;
  /* Заглушки площадки нарисованы с полями и в круге смотрятся мелко —
     небольшое увеличение убирает пустую кайму по краям. */
  transform: scale(1.02);
}
.avatar--photo.avatar--unread { box-shadow: inset 0 0 0 1.5px var(--accent); }

/* Прокрутка внутри шторки не должна «протекать» на страницу под ней: дотянув
   список до конца, палец начинал тащить фон. */
.sheet, .sheet__body {
  overscroll-behavior: contain;
}
.sheet__body { -webkit-overflow-scrolling: touch; }

/* Поля ввода не меняют размер от содержимого и не увеличивают шрифт при
   фокусе: 16px — та граница, ниже которой мобильный Safari сам приближает
   страницу, и после этого «всё едет». */
.input, .textarea, .select {
  font-size: max(16px, 1em);
  max-width: 100%;
}

/* Широкая плитка: слева главное число, справа — то, что из него следует. */
.tile--wide { display: block; }
.tile__main {
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
  flex: none;
}
.tile__facts {
  display: flex;
  gap: 18px;
  flex-wrap: wrap;
  justify-content: flex-end;
}
.fact { text-align: right; min-width: 0; }
.fact__label {
  font-size: 11px;
  font-weight: 650;
  color: var(--fg-3);
  letter-spacing: 0.02em;
}
.fact__value {
  font-family: var(--mono);
  font-size: 15px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  margin-top: 2px;
  white-space: nowrap;
}
.fact__foot { font-size: 10.5px; color: var(--fg-4); margin-top: 1px; }

/* На узком экране факты уходят под число, а не жмутся в столбик по одному. */
@media (max-width: 420px) {
  .tile--wide .spread { flex-direction: column; gap: 12px; }
  .tile__facts { justify-content: flex-start; width: 100%; gap: 14px; }
  .fact { text-align: left; }
}


/* ─────────────── значки в строке: общее правило ───────────────
   Везде, где значок стоит рядом с текстом, он выравнивается по центру строки
   и не сжимается. Раньше это чинилось по месту — и каждый новый заголовок
   приходилось чинить заново. */
.section__title,
.subblock__head,
.tile__label,
.kv__k,
.row__title,
.fact__label,
.field__label {
  display: flex;
  align-items: center;
  gap: 7px;
}
.section__title > svg,
.subblock__head > svg,
.tile__label > svg,
.kv__k > svg,
.row__title > svg,
.field__label > svg {
  flex: none;
  vertical-align: middle;
}
/* Подписи в плитках мельче заголовков — значок подстраивается под них. */
.tile__label svg { width: 1.15em; height: 1.15em; }

/* ─────────────────────────── жесты ───────────────────────────
   Подсказка выезжает из-под строки: пока палец тянет, видно, что произойдёт. */
.swipe-active { position: relative; z-index: 1; will-change: transform; }
.swipe-hint {
  position: absolute;
  top: 0;
  bottom: 0;
  z-index: -1;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 18px;
  font-size: 13px;
  font-weight: 700;
  color: var(--fg);
  background: var(--s-2);
}
.swipe-hint--left { right: 0; flex-direction: row-reverse; }
.swipe-hint--right { left: 0; }
.swipe-hint--ok { background: var(--ok-soft); color: var(--ok); }
.swipe-hint--danger { background: var(--bad-soft); color: var(--bad); }
.swipe-hint--accent { background: var(--accent-soft); color: var(--accent); }
.swipe-hint svg { flex: none; }

/* Полоса отмены: висит поверх всего, но ниже шторок — она их не перекрывает. */
.undo {
  position: fixed;
  left: var(--pad);
  right: var(--pad);
  bottom: calc(var(--tabbar-total) + 12px);
  z-index: 55;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 14px;
  border-radius: var(--r-md);
  background: var(--s-4);
  border: 1px solid var(--line-strong);
  box-shadow: var(--sh-2);
  -webkit-backdrop-filter: blur(var(--blur-2)) saturate(160%);
  backdrop-filter: blur(var(--blur-2)) saturate(160%);
  animation: rise var(--mid) both;
}
.undo--out { animation: fade var(--fast) both reverse; }
.undo__text { font-size: 13.5px; font-weight: 600; min-width: 0; }
.undo__btn {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: 1px solid var(--accent-line);
  background: var(--accent-soft);
  color: var(--accent);
  border-radius: var(--r-pill);
  padding: 7px 13px;
  font: inherit;
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
}
.undo__count { font-family: var(--mono); opacity: 0.75; }
.menu-item--danger { color: var(--bad); }
.menu-item--danger svg { color: var(--bad); }

/* Скелеты той же формы, что и содержимое под ними. */
.skel--card {
  aspect-ratio: 16 / 11;
  height: auto;
  border-radius: var(--r-lg);
}
.skel--msg {
  height: 44px;
  margin-bottom: 10px;
  border-radius: var(--r-md);
}

/* Прилипающий заголовок: в длинном списке видно, к какой группе относится
   то, что сейчас на экране. Раньше заголовок уезжал вверх, и после третьего
   экрана прокрутки становилось непонятно, что именно перед глазами. */
.section__head--sticky {
  position: sticky;
  top: calc(var(--header-h) + var(--safe-t));
  z-index: 5;
  margin: 0 calc(var(--pad) * -1);
  padding: 8px var(--pad);
  background: var(--s-3);
  -webkit-backdrop-filter: blur(var(--blur-2)) saturate(160%);
  backdrop-filter: blur(var(--blur-2)) saturate(160%);
}
.talk__day {
  position: sticky;
  top: calc(var(--header-h) + var(--safe-t) + 6px);
  z-index: 4;
}

/* Панель массовых действий: наборы сверху, действия снизу. */
.bulkbar__sets {
  display: flex;
  gap: 6px;
  overflow-x: auto;
  padding-bottom: 8px;
  scrollbar-width: none;
}
.bulkbar__sets::-webkit-scrollbar { display: none; }
.bulkbar__row {
  display: flex;
  align-items: center;
  gap: 7px;
}

/* Строка-дело: кнопка действия внутри строки не должна выглядеть приклеенной
   к краю — ей нужен воздух и своя область нажатия. */
.row--task { align-items: center; gap: 10px; }
.row--task .btn { flex: none; white-space: nowrap; }

/* ─────────────────────────── полоса занятости ─────────────────────────── */
.tl__scale {
  position: relative;
  height: 16px;
  margin: 0 0 6px 96px;
  font-size: 10.5px;
  color: var(--fg-4);
}
.tl__mark {
  position: absolute;
  top: 0;
  transform: translateX(-50%);
  white-space: nowrap;
}
.tl__mark--now { transform: none; color: var(--accent); font-weight: 700; }

.tl__lane {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 5px 0;
  cursor: pointer;
  border-radius: var(--r-xs);
}
.tl__lane:hover { background: var(--s-0); }
.tl__lane--off { opacity: 0.5; }
.tl__name {
  flex: none;
  width: 86px;
  font-size: 12.5px;
  font-weight: 650;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tl__name small {
  display: block;
  font-size: 10.5px;
  font-weight: 500;
  color: var(--fg-4);
}
.tl__track {
  position: relative;
  flex: 1;
  height: 18px;
  border-radius: var(--r-pill);
  background: var(--sunken);
  overflow: hidden;
}
.tl__free { display: block; height: 100%; }
.tl__bar {
  position: absolute;
  top: 0;
  bottom: 0;
  border-radius: var(--r-pill);
  background: var(--btn-grad);
  box-shadow: 0 0 12px -4px var(--accent);
}
/* Ручное занятие отличается штриховкой: это не продажа, и в статистику оно
   не идёт — путать их на одной полосе нельзя. */
.tl__bar--manual {
  background: repeating-linear-gradient(
    45deg, var(--accent-soft), var(--accent-soft) 5px,
    transparent 5px, transparent 10px);
  box-shadow: inset 0 0 0 1px var(--accent-line);
}


/* Вкладки раздела переносятся на вторую строку, а не уезжают за край:
   четвёртая вкладка, которую не видно, — это вкладка, которой нет. */
.seg--wrap { flex-wrap: wrap; }
.seg--wrap .seg__opt { flex: 1 1 auto; min-width: 32%; }

/* Четыре фильтра со счётчиками в одну строку на телефон не помещаются:
   последний уезжает за край, и «Возвраты» не видно вовсе — фильтр, о котором
   не знаешь, всё равно что выключенный. Раскладываем сеткой два на два, а на
   широком экране возвращаем один ряд. */
.seg--grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
.seg--grid .seg__opt { min-width: 0; }
@media (min-width: 480px) {
  .seg--grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* Подмена содержимого вкладки. Старое гаснет, новое проявляется — полсекунды
   пустоты читаются как сбой, полсекунды бледного текста не читаются никак. */
[data-inner] { transition: none; }
[data-inner].swap { opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  [data-inner] { transition: none; }
  [data-inner].swap { opacity: 1; }
}


/* ─────────────────────────── лента событий ───────────────────────────
   Список строк, а не карточек: событий за день десятки, и каждое в своей
   рамке превращает ленту в простыню, по которой невозможно вести глазом.
   Значок слева отвечает на «что это», время справа — на «когда», и оба
   стоят на одном месте в каждой строке. */
.feed { display: flex; flex-direction: column; }
.feed__day {
  padding: 10px 14px 6px;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--fg-4);
}
.feed__row {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--line-soft);
}
.feed__row:last-child { border-bottom: 0; }
/* Непрочитанное помечено полосой у края, а не цветом текста: цветной текст
   в списке читается как «важнее», хотя новость может быть любой. */
.feed__row--new { box-shadow: inset 2px 0 0 var(--accent); }
.feed__icon {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 9px;
  background: var(--sunken);
  color: var(--fg-3);
}
.feed__icon.ok { color: var(--ok); }
.feed__icon.warn { color: var(--warn); }
.feed__icon.bad { color: var(--bad); }
.feed__body { min-width: 0; flex: 1; }
.feed__title {
  display: block;
  font-size: 13.5px;
  font-weight: 650;
  line-height: 1.35;
  overflow-wrap: anywhere;
}
.feed__text {
  display: block;
  margin-top: 2px;
  font-size: 12px;
  line-height: 1.45;
  color: var(--fg-3);
  white-space: pre-line;
  overflow-wrap: anywhere;
}
.feed__time { flex: none; font-size: 11px; color: var(--fg-4); padding-top: 2px; }

/* Карта спроса ------------------------------------------------------------
   Семь строк по дням недели, 24 клетки в каждой. Клетки квадратные и мелкие
   намеренно: это не график, который читают по значениям, а пятно, по которому
   видно форму недели за один взгляд. Подписи часов идут снизу отдельной
   строкой и попадают в ту же сетку, поэтому «12» стоит ровно над своим
   столбцом, а не примерно рядом. */
.heat {
  display: flex;
  gap: 8px;
  align-items: stretch;
}
.heat__days {
  display: grid;
  grid-template-rows: repeat(7, minmax(0, 1fr));
  gap: 3px;
  flex: none;
  font-size: 10px;
  font-weight: 650;
  color: var(--fg-4);
}
.heat__days span { display: flex; align-items: center; }
.heat { --heat-days: 26px; }
.heat__days { width: var(--heat-days); }
.heat__grid {
  display: grid;
  grid-template-columns: repeat(24, minmax(0, 1fr));
  /* Высоту ряда задаёт сама клетка, а не доля от высоты блока.
     С `1fr` ряд получал высоту от колонки с днями недели — а она считается по
     тексту, — и выходил выше квадратной клетки. Клетка вставала к верху ряда,
     между рядами появлялся неровный зазор, и заполненные клетки выглядели
     разъехавшимися: пустые на тёмном фоне этого не показывали. */
  grid-template-rows: repeat(7, auto);
  gap: 3px;
  flex: 1;
  min-width: 0;
}
.heat__cell {
  display: block;
  aspect-ratio: 1;
  border-radius: 3px;
  background: rgba(var(--accent-rgb, 255, 138, 43), calc(0.08 + var(--v) * 0.92));
  transition: transform .12s ease;
}
.heat__cell--void { background: var(--sunken); }
.heat__cell:hover { transform: scale(1.35); }
.heat__hours {
  display: grid;
  grid-template-columns: repeat(24, minmax(0, 1fr));
  /* Отступ слева ровно такой же, какой занимает колонка дней плюс зазор —
     иначе «00» стоит не над своим столбцом. */
  margin: 6px 0 0 calc(var(--heat-days, 26px) + 8px);
  font-size: 10px;
  color: var(--fg-4);
}
.heat__hours span { grid-row: 1; }

/* Подсказка по горячим клавишам --------------------------------------------
   Показывается по «?» и закрывается чем угодно. Это справка, а не диалог: ни
   кнопок, ни выбора — поэтому и закрывать её должно любое движение. */
.hk {
  position: fixed;
  inset: 0;
  z-index: 1200;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.55);
  backdrop-filter: blur(6px);
  padding: 20px;
}
.hk__card {
  width: min(360px, 100%);
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: 18px 20px 16px;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.5);
}
.hk__title {
  font-size: 15px;
  font-weight: 700;
  margin-bottom: 12px;
}
.hk__row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 5px 0;
  font-size: 13px;
  color: var(--fg-2);
}
.hk__row kbd {
  flex: none;
  min-width: 30px;
  text-align: center;
  font-family: var(--mono);
  font-size: 11.5px;
  padding: 3px 6px;
  border-radius: 6px;
  border: 1px solid var(--line);
  background: var(--sunken);
  color: var(--fg);
}
.hk__foot {
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid var(--line);
  font-size: 11.5px;
  color: var(--fg-4);
}

/* ─────────────────────────── аккаунты столбиками ───────────────────────────
   Список с числами справа читается строка за строкой; столбики отвечают на
   вопрос «кто тащит, а кто лежит» одним взглядом. */
.bars { display: grid; gap: 8px; }
.bars__row {
  display: grid;
  grid-template-columns: 42px 1fr auto;
  align-items: center;
  gap: 10px;
  padding: 4px 0;
  background: none;
  border: 0;
  width: 100%;
  text-align: left;
  cursor: pointer;
}
.bars__name {
  font-size: 13px;
  font-weight: 700;
  color: var(--fg-2);
  font-variant-numeric: tabular-nums;
  min-width: 96px;
  max-width: 40%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.bars__track {
  position: relative;
  display: block;
  height: 26px;
  border-radius: 7px;
  background: var(--s-1);
  overflow: hidden;
  min-width: 0;
}
.bars__fill {
  position: absolute;
  inset: 0 auto 0 0;
  border-radius: 7px;
  background: linear-gradient(90deg,
    color-mix(in srgb, var(--accent) 55%, transparent), var(--accent));
  transition: width var(--slow, .5s) ease;
}
.bars__sub {
  position: absolute;
  top: 0;
  padding: 0 9px;
  line-height: 26px;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--fg-3);
  white-space: nowrap;
}
/* Внутри заливки — тёмными по светлому; снаружи — обычным приглушённым. */
.bars__sub--in { color: var(--accent-ink, #221304); }
.bars__value {
  font-size: 13px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.bars__row:active .bars__track { transform: scale(0.99); }

/* ─────────────────────────── профиль магазина ───────────────────────────
   Верх настроек: как магазин выглядит покупателю и кто к нему возвращается. */
.prof { display: flex; align-items: center; gap: 12px; }
.prof__face {
  width: 52px;
  height: 52px;
  border-radius: 50%;
  object-fit: cover;
  border: 1px solid var(--line-strong);
  flex: none;
}
.prof__face--stub {
  display: grid;
  place-items: center;
  background: var(--s-2);
  color: var(--fg-4);
}
.prof__id { min-width: 0; }
.prof__name { font-size: 18px; font-weight: 800; letter-spacing: -0.02em; }
.prof__stars {
  font-size: 13px;
  color: var(--warn, #ffc24b);
  letter-spacing: 1px;
  margin-top: 2px;
}
.prof__stars .muted { letter-spacing: 0; margin-left: 6px; font-size: 12px; }

.prof__people { display: grid; gap: 6px; margin-top: 10px; }
.prof__person {
  display: grid;
  grid-template-columns: 1fr auto auto;
  align-items: center;
  gap: 10px;
  padding: 9px 11px;
  border-radius: var(--r-sm);
  background: var(--s-1);
  border: 1px solid var(--line);
  width: 100%;
  text-align: left;
  cursor: pointer;
}
.prof__who { font-size: 13.5px; font-weight: 650; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.prof__times { font-size: 11.5px; color: var(--fg-4); white-space: nowrap; }
.prof__sum { font-size: 13px; font-weight: 700; font-variant-numeric: tabular-nums; }

/* promo editor: plan checklist and paired fields */
.checks { display: flex; flex-direction: column; gap: 6px; }
.check { display: flex; align-items: center; gap: 10px; font-size: 14px; padding: 6px 2px; }
.check input { width: 18px; height: 18px; accent-color: var(--accent, #6b8afd); }
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
@media (max-width: 420px) { .grid-2 { grid-template-columns: 1fr; } }


/* ── Simpler panel (2026-09-16): larger type, calmer surfaces, inline editing ───────────────────────── */
.row { padding: 14px 14px; min-height: 60px; }
.row__title { font-size: 16px; }
.row__sub { font-size: 13.5px; white-space: normal; line-height: 1.35; }
.tile__label { font-size: 12.5px; }
.tile__value { font-size: clamp(22px, 6.4vw, 28px); }
.tile__foot { font-size: 12.5px; }
.tile--link { text-align: left; font: inherit; color: inherit; cursor: pointer; }
.tile--link:active { transform: scale(0.985); }
.section__title { font-size: 14px; letter-spacing: 0.02em; }
.btn { font-size: 15px; min-height: 46px; }
.badge { font-size: 11px; }
.glass { backdrop-filter: blur(8px) saturate(120%); -webkit-backdrop-filter: blur(8px) saturate(120%); }
.glass::before { opacity: 0.6; }
.tab span { font-size: 11.5px; }

/* plans: price / markup right in the row */
.plan .row__body { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.plan__name { display: inline-flex; align-items: center; gap: 6px; padding: 0; border: 0; background: none; color: inherit; font: inherit; font-weight: 650; font-size: 16px; text-align: left; cursor: pointer; }
.plan__edit { display: flex; gap: 10px; margin-top: 2px; flex-wrap: nowrap; align-items: center; }
.plan__field { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; color: var(--fg-3); }
.input--inline { width: 84px; min-height: 40px; padding: 0 10px; font-size: 16px; font-weight: 700; text-align: right; }
.input--inline:focus { border-color: var(--accent); }
