/* Nekto web — оформление в духе Apple HIG.
 *
 * Это осознанный отказ от чёрно-белого правила §C2: смысл теперь несут и
 * системные цвета (синий — вы и активное, красный/оранжевый/зелёный — уровень
 * записи), и материалы с полупрозрачностью. Глифы-префиксы (✕ ! ✓ ●) при этом
 * СОХРАНЕНЫ: цвет добавлен поверх них, а не вместо, — иначе уровень записи
 * пропал бы для дальтоников и в ч/б печати (см. §C3).
 *
 * Прежний вариант остаётся в git: ветка main, метка design-mono.
 *
 * Разметка и скрипты не менялись: все селекторы ниже — те же классы, которые
 * ставят render.js и modals.js.
 */

:root {
  /* Палитра системных цветов Apple (light). Имена --c-bg/--c-fg/--c-inv-*
     сохранены от прежней темы: на них завязаны тесты и привычка глаза. */
  --c-bg: #f2f2f7;        /* фон окна: как сгруппированный список iOS */
  --c-canvas: #ffffff;    /* полотно переписки */
  --c-surface: #ffffff;   /* карточки, поля, всплывающие панели */
  --c-fill: rgba(118, 118, 128, 0.12);   /* заливка неактивных контролов */
  --c-fill-strong: rgba(118, 118, 128, 0.2);
  --c-fg: #1d1d1f;
  --c-muted: #6e6e73;
  --c-faint: #aeaeb2;
  --c-line: rgba(60, 60, 67, 0.16);
  --c-inv-bg: #1d1d1f;    /* редкая инверсия: подсказки поверх контента */
  --c-inv-fg: #ffffff;

  --c-accent: #007aff;
  --c-accent-fg: #ffffff;
  --c-accent-soft: rgba(0, 122, 255, 0.14);
  --c-bubble: #e9e9eb;    /* пузырь собеседника */
  --c-bubble-fg: #1d1d1f;

  --c-red: #d70015;
  --c-orange: #b25000;
  --c-green: #1a7f37;
  --c-warn-bg: rgba(255, 149, 0, 0.16);

  /* Материал: полупрозрачный фон + размытие. Отдельной переменной, потому что
     под ним всегда должен лежать непрозрачный запасной цвет (см. @supports). */
  --c-material: rgba(249, 249, 251, 0.72);
  --c-material-solid: #f7f7f9;

  --sp-1: 4px; --sp-2: 8px; --sp-3: 12px; --sp-4: 16px; --sp-5: 24px; --sp-6: 32px;
  --fs-xs: 0.75rem; --fs-sm: 0.8125rem; --fs-base: 0.9375rem; --fs-lg: 1.375rem;
  /* Размер полей ввода — В ПИКСЕЛЯХ, и это принципиально. Safari на iPhone
     приближает страницу к любому полю мельче 16px и обратно уже не отъезжает.
     `1rem` тут не годится: rem считается от КОРНЕВОГО размера, а он на этой
     же странице сбивался в 15px правилом `html, body { font-size }` — из-за
     чего поля и оказывались 15px при честном на вид `1rem`. */
  --fs-md: 16px;
  --lh-tight: 1.3; --lh-base: 1.5;
  --border: 1px solid var(--c-line);

  /* Скругления: 8 у мелких контролов, 12 у карточек, 20 у пузырей и окон. */
  --radius: 10px;
  --r-sm: 8px; --r-md: 12px; --r-lg: 16px; --r-xl: 20px; --r-pill: 999px;
  --r-bubble: 19px; --r-bubble-tail: 6px;

  --shadow-1: 0 1px 2px rgba(0, 0, 0, 0.06), 0 6px 20px rgba(0, 0, 0, 0.06);
  --shadow-2: 0 12px 48px rgba(0, 0, 0, 0.24);

  /* Высота однострочного поля: строка + вертикальные отступы + рамки.
     Ею же меряется кнопка отправки, иначе она торчит выше композера. */
  --field-h: calc(var(--lh-base) * var(--fs-md) + 2 * var(--sp-2) + 2px);

  /* SF на Apple-устройствах, системный гротеск везде остальном. Моноширинный
     остаётся для технических строк (ключи, адреса капчи). */
  --font: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Helvetica Neue",
    "Segoe UI", Inter, Roboto, system-ui, sans-serif;
  --mono: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, Consolas, monospace;
  --sidebar-w: 272px;

  /* Пружина Apple: быстрый старт, мягкая доводка. */
  --ease: cubic-bezier(0.32, 0.72, 0, 1);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --c-bg: #000000; --c-canvas: #000000; --c-surface: #1c1c1e;
    --c-fill: rgba(118, 118, 128, 0.24); --c-fill-strong: rgba(118, 118, 128, 0.36);
    --c-fg: #f5f5f7; --c-muted: #98989d; --c-faint: #636366;
    --c-line: rgba(84, 84, 88, 0.6);
    --c-inv-bg: #f5f5f7; --c-inv-fg: #1d1d1f;
    --c-accent: #0a84ff; --c-accent-soft: rgba(10, 132, 255, 0.24);
    --c-bubble: #26262a; --c-bubble-fg: #f5f5f7;
    --c-red: #ff6961; --c-orange: #ffb340; --c-green: #30d158;
    --c-warn-bg: rgba(255, 159, 10, 0.2);
    --c-material: rgba(28, 28, 30, 0.72); --c-material-solid: #161618;
    --shadow-1: 0 1px 2px rgba(0, 0, 0, 0.5), 0 6px 20px rgba(0, 0, 0, 0.4);
    --shadow-2: 0 12px 48px rgba(0, 0, 0, 0.6);
  }
}
:root[data-theme="dark"] {
  --c-bg: #000000; --c-canvas: #000000; --c-surface: #1c1c1e;
  --c-fill: rgba(118, 118, 128, 0.24); --c-fill-strong: rgba(118, 118, 128, 0.36);
  --c-fg: #f5f5f7; --c-muted: #98989d; --c-faint: #636366;
  --c-line: rgba(84, 84, 88, 0.6);
  --c-inv-bg: #f5f5f7; --c-inv-fg: #1d1d1f;
  --c-accent: #0a84ff; --c-accent-soft: rgba(10, 132, 255, 0.24);
  --c-bubble: #26262a; --c-bubble-fg: #f5f5f7;
  --c-red: #ff6961; --c-orange: #ffb340; --c-green: #30d158;
  --c-warn-bg: rgba(255, 159, 10, 0.2);
  --c-material: rgba(28, 28, 30, 0.72); --c-material-solid: #161618;
  --shadow-1: 0 1px 2px rgba(0, 0, 0, 0.5), 0 6px 20px rgba(0, 0, 0, 0.4);
  --shadow-2: 0 12px 48px rgba(0, 0, 0, 0.6);
}

* { box-sizing: border-box; }

/* Атрибут hidden должен побеждать любую раскладку.
   Стиль браузера даёт [hidden] { display: none }, но ЛЮБОЕ авторское правило
   с display (.modal-root { display: grid }, .shell { display: flex }, …)
   перебивает его по специфичности — и элемент, помеченный hidden, остаётся на
   экране. Здесь это скрывало кнопку входа скримом модального окна. */
[hidden] { display: none !important; }

/* Корневому элементу размер шрифта НЕ задаём. Он и есть единица rem: сбив его
   в 15px, страница сама себе уменьшала все rem-значения — включая размер полей
   ввода, из-за чего iOS приближался к ним при фокусе. */
html { height: 100%; background: var(--c-bg); }

body {
  margin: 0;
  height: 100%;
  background: var(--c-bg);
  color: var(--c-fg);
  font-family: var(--font);
  font-size: var(--fs-base);
  line-height: var(--lh-base);
  /* Тонкая обводка глифов — то, чем текст на macOS отличается от «жирного» веба. */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

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

:focus-visible { outline: 2px solid var(--c-accent); outline-offset: 2px; }

button, input, textarea {
  font: inherit;
  color: inherit;
  background: transparent;
  border: var(--border);
  border-radius: var(--radius);
}
/* 16px в полях обязателен: иначе iOS зумит страницу при фокусе.
   line-height задаётся явно: сокращение `font: inherit` выше наследует
   ВЫЧИСЛЕННУЮ высоту строки (22.5px от 15px шрифта), а не множитель, —
   и высота поля переставала совпадать с --field-h. */
input, textarea {
  font-size: var(--fs-md); line-height: var(--lh-base);
  padding: var(--sp-2) var(--sp-3); width: 100%;
  background: var(--c-surface);
  transition: border-color 140ms var(--ease), box-shadow 140ms var(--ease);
}
input:focus, textarea:focus { border-color: var(--c-accent); outline: none; }
input:focus-visible, textarea:focus-visible {
  outline: none; box-shadow: 0 0 0 3px var(--c-accent-soft);
}
button {
  cursor: pointer;
  transition: background-color 140ms var(--ease), opacity 140ms var(--ease),
    transform 80ms var(--ease);
}
/* Нажатие «проседает» — тактильный отклик, которым Apple заменяет рамки. */
button:active { transform: scale(0.97); }
code { font-family: var(--mono); font-size: 0.92em; }

/* Тонкие полосы прокрутки: содержимое важнее хрома. */
* { scrollbar-width: thin; scrollbar-color: var(--c-fill-strong) transparent; }
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-thumb { background: var(--c-fill-strong); border-radius: var(--r-pill); }
::-webkit-scrollbar-track { background: transparent; }

/* ─── загрузка / вход ─────────────────────────────────────────────── */
.boot {
  display: grid; place-items: center; height: 100dvh;
  color: var(--c-muted);
}
.login { display: grid; place-items: center; height: 100dvh; padding: var(--sp-4); }
.login-box {
  width: min(360px, 100%);
  background: var(--c-surface); border: var(--border); border-radius: var(--r-xl);
  box-shadow: var(--shadow-1);
  padding: var(--sp-5); display: grid; gap: var(--sp-4);
}
.login-title {
  margin: 0 0 var(--sp-1); text-align: center;
  font-size: var(--fs-lg); font-weight: 700; letter-spacing: -0.02em;
  line-height: var(--lh-tight);
}
.field { display: grid; gap: var(--sp-1); font-size: var(--fs-sm); color: var(--c-muted); }
/* Цвет — усиление, а не единственный носитель: глиф ✕ остаётся. */
.login-error { margin: 0; color: var(--c-red); font-size: var(--fs-sm); }
.login-error::before { content: "✕ "; }
.hint { margin: 0; font-size: var(--fs-sm); color: var(--c-muted); line-height: 1.45; }

.btn {
  padding: var(--sp-2) var(--sp-4); border-radius: var(--radius);
  background: var(--c-fill); border-color: transparent;
  font-size: var(--fs-base); font-weight: 500;
}
.btn:hover { background: var(--c-fill-strong); }
.btn.primary {
  background: var(--c-accent); color: var(--c-accent-fg); border-color: transparent;
  font-weight: 600;
}
.btn.primary:hover { background: var(--c-accent); filter: brightness(1.08); }

/* ─── каркас ──────────────────────────────────────────────────────── */
.shell { display: flex; height: 100dvh; overflow: hidden; }

.sidebar {
  width: var(--sidebar-w); flex: 0 0 var(--sidebar-w);
  border-right: var(--border);
  background: var(--c-material);
  -webkit-backdrop-filter: saturate(180%) blur(24px);
  backdrop-filter: saturate(180%) blur(24px);
  display: flex; flex-direction: column; min-height: 0;
  padding-bottom: env(safe-area-inset-bottom);
}
.sidebar-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--sp-3) var(--sp-4) var(--sp-2);
}
.sidebar-title {
  font-size: var(--fs-xs); font-weight: 600; text-transform: uppercase;
  letter-spacing: 0.06em; color: var(--c-muted);
}
.account-list { flex: 1; overflow-y: auto; padding: var(--sp-1) 0; }

/* Строка списка — не таблица с разделителями, а «капсула» выделения:
   так же выглядит боковик Почты и Сообщений. */
.account {
  display: block; width: calc(100% - 2 * var(--sp-2)); text-align: left;
  margin: 1px var(--sp-2); border: 0; border-radius: var(--r-md);
  padding: var(--sp-2) var(--sp-3);
}
.account:hover { background: var(--c-fill); }
.account[aria-selected="true"] { background: var(--c-accent); color: var(--c-accent-fg); }
.account[aria-selected="true"]:hover { background: var(--c-accent); }
.account-row { display: flex; gap: var(--sp-2); align-items: baseline; }
/* Маркер (● ✎ ⚠ или пробел) — колонка фиксированной ширины: в пропорциональном
   шрифте пробел уже точки, и без явной ширины имена аккаунтов разъезжались. */
.account-row > span:first-child {
  display: inline-block; width: 12px; flex: none; text-align: center;
  color: var(--c-accent); font-size: var(--fs-xs);
}
.account[aria-selected="true"] .account-row > span:first-child { color: var(--c-accent-fg); }
/* Имя со значком связи — по центру строки. Центр честный: маркер слева и
   счётчик справа держат одинаковую ширину, даже когда оба пусты. */
.account-title {
  flex: 1; min-width: 0; display: flex; justify-content: center;
  align-items: baseline; gap: var(--sp-1);
}
.account-name {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-weight: 500;
}
.account-conn { flex: none; }
.account-meta { font-size: var(--fs-sm); color: var(--c-muted); }
.account[aria-selected="true"] .account-meta { color: rgba(255, 255, 255, 0.85); }
/* Счётчик непрочитанных пуст почти всегда: фон рисуем только когда есть число. */
.account-badge {
  font-variant-numeric: tabular-nums;
  flex: none; min-width: 12px; text-align: center;
}
.account-badge:not(:empty) {
  background: var(--c-accent); color: var(--c-accent-fg);
  border-radius: var(--r-pill); padding: 1px 7px;
  font-size: var(--fs-xs); font-weight: 600; line-height: 1.5;
}
.account[aria-selected="true"] .account-badge:not(:empty) {
  background: var(--c-accent-fg); color: var(--c-accent);
}

.add-account {
  border: 0; background: transparent; color: var(--c-accent);
  margin: var(--sp-1) var(--sp-2); width: calc(100% - 2 * var(--sp-2));
  border-radius: var(--r-md); padding: var(--sp-2) var(--sp-3);
  text-align: left; font-weight: 500;
}
.add-account:hover { background: var(--c-fill); }
.sidebar-foot {
  display: flex; gap: var(--sp-4); padding: var(--sp-3) var(--sp-4);
  flex-wrap: wrap; border-top: var(--border);
}
.link-btn {
  border: 0; padding: 0; background: transparent;
  color: var(--c-accent); font-size: var(--fs-sm);
}
.link-btn:hover { background: transparent; opacity: 0.7; }

/* position: relative — общий контекст наложения для шапки и плашки «↓ новые»:
   размытая шапка обязана лежать над журналом, а плашка — над обеими. */
.main {
  flex: 1; display: flex; flex-direction: column; min-width: 0; min-height: 0;
  position: relative; background: var(--c-canvas);
}

.header {
  display: flex; gap: var(--sp-2); align-items: center;
  padding: var(--sp-2) var(--sp-3); border-bottom: var(--border);
  background: var(--c-material);
  -webkit-backdrop-filter: saturate(180%) blur(24px);
  backdrop-filter: saturate(180%) blur(24px);
  z-index: 2;
}
.header-text { flex: 1; min-width: 0; }
.header-line {
  font-size: var(--fs-sm); color: var(--c-muted); overflow-wrap: anywhere;
  line-height: 1.4;
}
.header-line:first-child { color: var(--c-fg); font-weight: 500; }
/* Разделитель между кусками шапки рисует CSS, а не текст: скрытый на телефоне
   кусок уносит с собой и свою точку. Первый кусок (имя аккаунта, состояние
   связи) виден всегда, поэтому :first-child здесь надёжен. */
.header-line > span:not(:first-child)::before { content: " · "; color: var(--c-faint); }
.ai-status:empty { display: none; }
.header-actions { display: flex; gap: var(--sp-1); }
.icon-btn {
  min-width: 44px; min-height: 44px; display: grid; place-items: center;
  border: 0; background: transparent; border-radius: var(--r-md);
  color: var(--c-accent);
}
.icon-btn:hover { background: var(--c-fill); }

/* Единый размер для всех глифов-кнопок: поиск, ИИ, справка, отправка.
   Рисуем их одним классом, чтобы 44×44 коробка была одинаково заполнена. */
.icon { width: 20px; height: 20px; display: block; flex: none; }

/* Потеря связи — предупреждение, а не авария: мягкая янтарная плашка. */
.banner {
  padding: var(--sp-2) var(--sp-4);
  background: var(--c-warn-bg); color: var(--c-orange);
  font-size: var(--fs-sm); font-weight: 500; text-align: center;
}

/* ─── журнал ──────────────────────────────────────────────────────── */
.chat {
  flex: 1; overflow-y: auto; padding: var(--sp-4) var(--sp-5);
  display: flex; flex-direction: column; gap: 2px;
  scroll-behavior: smooth;
  overscroll-behavior: contain;
}
.chat:empty::before {
  content: "Журнал пуст";
  margin: auto; color: var(--c-muted);
}

/* Пузырь. position: relative — якорь для точки непрочитанного слева. */
.entry {
  position: relative;
  max-width: min(60ch, 74%);
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--r-bubble);
  line-height: 1.35;
  overflow-wrap: anywhere; white-space: pre-wrap;
}
.entry.mine {
  align-self: flex-end;
  background: var(--c-accent); color: var(--c-accent-fg);
}
.entry.peer {
  align-self: flex-start;
  background: var(--c-bubble); color: var(--c-bubble-fg);
}
/* «Хвост» — только у последнего пузыря в серии: подряд идущие реплики одной
   стороны читаются как один блок, как в Сообщениях. */
.entry.mine:not(:has(+ .entry.mine)) { border-bottom-right-radius: var(--r-bubble-tail); }
.entry.peer:not(:has(+ .entry.peer)) { border-bottom-left-radius: var(--r-bubble-tail); }
/* Смена стороны — воздух; внутри серии хватает 2px из gap. */
.entry.mine + .entry.peer, .entry.peer + .entry.mine { margin-top: var(--sp-2); }

.entry.system {
  align-self: center; text-align: center; max-width: 100%;
  background: transparent; padding: 0;
  font-size: var(--fs-xs); color: var(--c-muted);
  margin-block: var(--sp-3);
}
.entry + .entry.system, .entry.system + .entry { margin-top: var(--sp-3); }

/* Появление новой строки: короткий выезд со своей стороны.
   Только для действительно новых записей — перерисовка из-за смены квитанции
   (… → ✓ → ✓✓) анимацию не повторяет, иначе журнал мигал бы на каждом
   подтверждении. Под prefers-reduced-motion длительность гасится общим
   правилом внизу файла. */
@keyframes entry-appear { from { opacity: 0; transform: translateY(8px); } }
@keyframes entry-appear-mine { from { opacity: 0; transform: translateY(8px) scale(0.94); } }
@keyframes entry-appear-peer { from { opacity: 0; transform: translateY(8px) scale(0.94); } }

.entry.appear { animation: entry-appear 220ms var(--ease); }
.entry.mine.appear { animation-name: entry-appear-mine; transform-origin: bottom right; }
.entry.peer.appear { animation-name: entry-appear-peer; transform-origin: bottom left; }

/* Квитанция живёт в том же пузыре — приглушаем её до сноски. */
.receipt {
  color: rgba(255, 255, 255, 0.75); font-size: var(--fs-xs);
  white-space: nowrap;
}
/* Метку «собеседник» рисует сторона и цвет пузыря — текст был бы шумом. */
.peer-label { display: none; }
/* Непрочитанное — точка на поле слева от пузыря, как значок в списке чатов. */
.entry.peer.unread::before {
  content: ""; position: absolute; left: -14px; top: 50%;
  width: 8px; height: 8px; margin-top: -4px;
  border-radius: 50%; background: var(--c-accent);
}

/* Уровень несут глиф И цвет: ни один из них не единственный носитель. */
.entry.level-error { color: var(--c-red); font-weight: 500; }
.entry.level-error .glyph::before { content: "✕ "; }
.entry.level-warning { color: var(--c-orange); }
.entry.level-warning .glyph::before { content: "! "; }
.entry.level-success { color: var(--c-green); }
.entry.level-success .glyph::before { content: "✓ "; }

/* Плашка висит над последней строкой журнала, а не на фиксированной высоте:
   раньше её держали `bottom: 150px`, и на узком экране, где кнопки композера
   переносятся во вторую строку, она уезжала под них. Здесь она — обычный
   элемент потока между журналом и композером, поднятый отрицательным полем.
   Высота задана явно, поэтому -40 + 32 + 8 = 0: показ и скрытие плашки не
   сдвигают журнал ни на пиксель. */
.jump {
  position: relative; z-index: 3;
  align-self: center; height: 32px;
  margin: -40px auto var(--sp-2);
  padding: var(--sp-1) var(--sp-4); border-radius: var(--r-pill);
  background: var(--c-surface); color: var(--c-accent); border: var(--border);
  box-shadow: var(--shadow-1);
  font-size: var(--fs-sm); font-weight: 500;
  z-index: 3;
}
.jump:hover { background: var(--c-surface); filter: brightness(0.98); }

/* ─── капча ───────────────────────────────────────────────────────── */
.captcha {
  margin: 0 var(--sp-4) var(--sp-2); padding: var(--sp-3);
  background: var(--c-surface); border: var(--border); border-radius: var(--r-lg);
  box-shadow: var(--shadow-1);
  display: grid; gap: var(--sp-2);
}
.captcha-head { display: flex; gap: var(--sp-2); align-items: baseline; }
.captcha-image { max-width: 100%; height: auto; border-radius: var(--r-sm); }
.captcha-url {
  margin: 0; font-size: var(--fs-sm); font-family: var(--mono);
  color: var(--c-muted); overflow-wrap: anywhere;
}
.selectable { user-select: all; }
.captcha-row { display: flex; gap: var(--sp-2); flex-wrap: wrap; }
.captcha-row input { flex: 1; min-width: 160px; }
.muted { color: var(--c-muted); }

/* ─── композер ────────────────────────────────────────────────────── */
.composer {
  border-top: var(--border); display: grid; gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3) calc(var(--sp-2) + env(safe-area-inset-bottom));
  background: var(--c-material);
  -webkit-backdrop-filter: saturate(180%) blur(24px);
  backdrop-filter: saturate(180%) blur(24px);
}
/* Строка «печатает» никогда не схлопывается — иначе прыгает вёрстка. */
.typing {
  min-height: 1.5em; font-size: var(--fs-sm); color: var(--c-muted);
  padding-left: var(--sp-2);
}
.composer-row { display: flex; gap: var(--sp-2); align-items: flex-end; }
.composer-row textarea {
  resize: none; min-height: var(--field-h); max-height: 7.5em; overflow-y: auto;
  border-radius: var(--r-bubble);
  padding-inline: var(--sp-4);
}
/* Круг ровно в высоту однострочного поля; при росте textarea кнопка остаётся
   прижатой к его нижнему краю (align-items: flex-end у строки). */
.send {
  width: var(--field-h); height: var(--field-h); flex: none;
  display: grid; place-items: center;
  border: 0; border-radius: 50%;
  background: var(--c-accent); color: var(--c-accent-fg);
}
.send:hover { filter: brightness(1.08); }
.send:disabled {
  background: var(--c-fill); color: var(--c-faint);
  cursor: not-allowed; filter: none; transform: none;
}
.composer-tools { display: flex; gap: var(--sp-2); flex-wrap: wrap; }
.chip, .choice {
  padding: var(--sp-1) var(--sp-3); border-radius: var(--r-pill);
  border: 0; background: var(--c-fill);
  font-size: var(--fs-sm); font-weight: 500; color: var(--c-fg);
}
.chip:hover, .choice:hover { background: var(--c-fill-strong); }
.chip[aria-pressed="true"], .choice[aria-pressed="true"] {
  background: var(--c-accent); color: var(--c-accent-fg);
}
.chip[aria-pressed="true"]:hover, .choice[aria-pressed="true"]:hover {
  background: var(--c-accent); filter: brightness(1.08);
}
/* Не --c-faint: строка несёт числа, а не украшает (§C3 — блёклый только декор). */
.online { font-size: var(--fs-xs); color: var(--c-muted); padding-left: var(--sp-2); }

/* ─── модальные окна ──────────────────────────────────────────────── */
.modal-root { position: fixed; inset: 0; display: grid; place-items: center; z-index: 10; }
.modal-scrim {
  position: absolute; inset: 0; background: rgba(0, 0, 0, 0.32);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
}
.modal {
  position: relative; width: min(480px, calc(100% - 2 * var(--sp-4)));
  max-height: 86dvh; overflow-y: auto;
  background: var(--c-surface); border: var(--border); border-radius: var(--r-xl);
  box-shadow: var(--shadow-2);
  padding: var(--sp-5) var(--sp-4) var(--sp-4);
  display: grid; gap: var(--sp-4);
  animation: sheet-in 260ms var(--ease);
}
/* Окно «прилетает» подросшим — движение Apple, а не мгновенная подмена. */
@keyframes sheet-in { from { opacity: 0; transform: scale(0.94) translateY(8px); } }
.modal-title {
  margin: 0; text-align: center;
  font-size: 1.0625rem; font-weight: 600; letter-spacing: -0.01em;
}
.modal-body { display: grid; gap: var(--sp-4); }
.modal-actions { display: flex; gap: var(--sp-2); justify-content: flex-end; flex-wrap: wrap; }
.choices { display: flex; gap: var(--sp-2); flex-wrap: wrap; }
.group-title {
  font-size: var(--fs-sm); font-weight: 600; color: var(--c-muted);
  margin-bottom: var(--sp-2);
}
/* Сгруппированный список настроек: одна карточка, строки через волосяную линию. */
.rows {
  display: grid; background: var(--c-bg); border-radius: var(--r-md);
  overflow: hidden;
}
.row {
  display: flex; gap: var(--sp-3); justify-content: space-between; align-items: center;
  padding: var(--sp-2) var(--sp-3);
}
.row + .row { border-top: var(--border); }
.kbd-table { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
.kbd-table td { border-bottom: var(--border); padding: var(--sp-2) 0; }
.kbd-table tr:last-child td { border-bottom: 0; }
.kbd-table td:last-child {
  text-align: right; color: var(--c-muted); font-family: var(--mono);
  font-size: var(--fs-xs); white-space: nowrap;
}
.scroll-x { overflow-x: auto; }

/* ─── адаптив ─────────────────────────────────────────────────────── */
.only-mobile { display: none; }
.scrim {
  position: fixed; inset: 0; background: rgba(0, 0, 0, 0.32); z-index: 4;
  -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
}

@media (max-width: 899px) {
  .only-mobile { display: grid; }
  /* Шапка на телефоне занимала треть экрана. Оставляем то, что меняется и
     влияет на решения: имя аккаунта, состояние связи, кого ищем. Остальное —
     режим автоответа, тема поиска, ID пользователя — видно в своих окнах. */
  .h-ai, .h-theme, .h-id { display: none; }
  /* Шпаргалка по клавишам на телефоне бессмысленна: клавиш нет. */
  .only-desktop { display: none; }
  .sidebar {
    position: fixed; inset: 0 auto 0 0; z-index: 5;
    width: min(320px, 86vw); flex-basis: auto;
    background: var(--c-material-solid);
    box-shadow: var(--shadow-2);
    transform: translateX(-100%);
    transition: transform 320ms var(--ease);
  }
  .shell.drawer-open .sidebar { transform: translateX(0); }
  .chat { padding: var(--sp-3) var(--sp-4); }
  .entry { max-width: 84%; }
  .icon-btn { min-width: 38px; }
}

/* Без поддержки backdrop-filter материалы становятся непрозрачными: полу-
   прозрачный фон поверх текста без размытия читался бы грязным. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .sidebar, .header, .composer { background: var(--c-material-solid); }
}

@media (prefers-reduced-motion: reduce) {
  *, ::before, ::after {
    animation-duration: .01ms !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  button:active { transform: none; }
}
