:root {
  --bg: var(--tg-theme-bg-color, #0f1115);
  --secondary-bg: var(--tg-theme-secondary-bg-color, #171a21);
  --text: var(--tg-theme-text-color, #e9ebf0);
  --hint: var(--tg-theme-hint-color, #8b92a3);
  --link: var(--tg-theme-link-color, #6ab2ff);
  --button: var(--tg-theme-button-color, #3b82f6);
  --button-text: var(--tg-theme-button-text-color, #ffffff);
  --danger: #f87171;
  --ok: #4ade80;
  --radius: 16px;
  --header-bg: #000;
}

/* Пробный фон (владелец, 2026-09-04: "давай попробуем новый цвет фона
   17212b"), пока включается только модераторами в Профиле. Перекрывает
   --bg/--secondary-bg целиком, а не подменяет --tg-theme-*: тема Telegram
   приходит инлайном на <html> (см. applyThemeColors в app.js), и переопределять
   надо именно конечные переменные. Селектор с классом специфичнее :root,
   поэтому побеждает без !important. --secondary-bg — парный к нему тон
   (карточки/панели), иначе на синеватом фоне они смотрелись бы грязными.
   --header-bg — отдельный, чуть более тёмный тон для шапки и плашек
   поверх фото в Ленте (владелец, 2026-09-10: жалоба, что шапка и фон Ленты
   не поменялись — они были на хардкод-чёрном в обход переменных темы,
   и жалоба же "сделать шапку темнее, отделить" — просто --bg дал бы
   тот же тон, что у самого фона, и разделение бы пропало). */
html.theme-blue {
  --bg: #17212b;
  --secondary-bg: #232e3c;
  --header-bg: #0e141a;
}

/* Экран загрузки — заменяет голый чёрный кадр между открытием Mini App и
   готовностью данных: эмблема мягко "дышит", вокруг вращается тонкое
   кольцо (тот же язык, что у логотипов Apple/Microsoft/крупных финтех-
   приложений на старте — статичный знак + лёгкая анимация, не спиннер
   отдельно от бренда). */
.splash-screen {
  position: fixed;
  inset: 0;
  z-index: 3000;
  background: #000;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: opacity 0.35s ease;
}

.splash-screen.fade-out {
  opacity: 0;
  pointer-events: none;
}

.splash-ring {
  position: absolute;
  width: 96px;
  height: 96px;
  border-radius: 50%;
  border: 2px solid transparent;
  border-top-color: #e2791f;
  border-right-color: color-mix(in srgb, #e2791f 35%, transparent);
  animation: splash-spin 1.1s linear infinite;
}

.splash-logo {
  width: 56px;
  height: auto;
  animation: splash-pulse 1.8s ease-in-out infinite;
}

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

@keyframes splash-pulse {
  0%, 100% {
    transform: scale(1);
    opacity: 1;
  }
  50% {
    transform: scale(1.08);
    opacity: 0.82;
  }
}

[hidden] {
  display: none !important;
}

* {
  box-sizing: border-box;
}

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: "Manrope", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  -webkit-tap-highlight-color: transparent;
  /* Рикошет прокрутки (pull-to-refresh) на мобильных WebView визуально
     дёргает зафиксированную нижнюю навигацию при переходе на более
     короткий экран — убираем сам рикошет по вертикали. Горизонталь
     (overscroll-behavior-x) добавлена отдельно (2026-08-20) — Лента стала
     главным экраном и растягивается на всю ширину без боковых отступов
     .app (полноэкранный Reels-стиль), поэтому свайпы теперь чаще стартуют
     у самого края экрана, где WebView интерпретирует горизонтальный
     оверскролл как системный жест "назад"/выход из приложения.
     overscroll-behavior-x: none отдаёт этот жест целиком странице, не
     системе. */
  overscroll-behavior: none;
}

button, input, select, textarea {
  font-family: inherit;
}

.app {
  max-width: 560px;
  margin: 0 auto;
  padding: 20px 16px calc(110px + env(safe-area-inset-bottom, 0px));
}

.app-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin: -20px -16px 16px;
  padding: 12px 16px;
  background: var(--header-bg);
}

.header-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  border: none;
  background: none;
  padding: 0;
  margin: 0;
  font-family: inherit;
  cursor: pointer;
}

.header-mark {
  display: block;
  height: 30px;
  width: auto;
}

.header-title {
  font-size: 17px;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: #f2f2f2;
}

.header-title-accent {
  color: #e2791f;
}

/* Слегка "фирменная" кнопка — в цвет оранжевого акцента эмблемы и с лёгким
   свечением, чтобы не терялась рядом с чёрным фоном шапки. */
.header-profile-btn {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: none;
  border: 1px solid rgba(226, 121, 31, 0.55);
  background: rgba(226, 121, 31, 0.14);
  color: #f0a765;
  border-radius: 999px;
  padding: 7px 13px 7px 10px;
  font-size: 12px;
  font-weight: 700;
  cursor: pointer;
  font-family: inherit;
  box-shadow: 0 0 10px rgba(226, 121, 31, 0.35);
}

.header-profile-btn svg {
  width: 17px;
  height: 17px;
  flex: none;
}

.header-right {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: none;
}

.header-icon-btn {
  position: relative;
  flex: none;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  border: 1px solid rgba(127, 127, 127, 0.3);
  background: none;
  color: #f2f2f2;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.header-icon-btn svg {
  width: 18px;
  height: 18px;
}

/* Просто точка, без числа (2026-08-20, владелец: "как в популярных
   сервисах") — тонкая обводка цветом фона шапки отделяет её от иконки
   позади, иначе на плотных пикселях точка сливалась бы с контуром
   колокольчика. */
.notifications-badge {
  position: absolute;
  top: 1px;
  right: 1px;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--danger);
  border: 2px solid #000;
}

.screen-title {
  font-size: 19px;
  font-weight: 650;
  margin: 4px 4px 12px;
}

/* Общий заголовок главных вкладок нижней навигации (Осмотр/Лента/Избранное)
   — по центру и с одной и той же высотой блока (те же отступы, что у
   обычного .screen-title), чтобы при переключении вкладок заголовок не
   "прыгал". */
.tab-screen-title {
  text-align: center;
}

.screen-title-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin: 4px 4px 12px;
}

/* Экран "Описание осмотра" — уже не корневая вкладка, а подэкран со своей
   кнопкой "Назад" (открывается из "Осмотр"/"Мои осмотры"), поэтому заголовок
   слева, как на остальных подэкранах, а не по центру. */
.screen-title-row-left {
  justify-content: flex-start;
}

.screen-title-row .screen-title {
  margin: 0;
}

.profile-header-row {
  justify-content: space-between;
}

.profile-header-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

/* Аккуратный "+" слева от шестерёнки — тот же стиль кружка, что у неё, вместо
   прежней жирной кнопки "+ Добавить публикацию" через всю ширину экрана
   (владелец, 2026-08-20: "убери эту жирную... добавь аккуратный плюс, как
   в Ленте"). */
.profile-add-post-btn {
  flex: none;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: none;
  background: color-mix(in srgb, var(--secondary-bg) 80%, white 6%);
  color: var(--text);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.profile-add-post-btn svg {
  width: 20px;
  height: 20px;
}

/* Крупная кнопка настроек в кружке — тот же визуальный приём, что у
   сердечка "в избранное" на карточках (.tile-favorite): круглая подложка,
   контурная иконка внутри, только без абсолютного позиционирования — тут
   кнопка стоит в строке заголовка, а не поверх фото. */
.profile-settings-btn {
  flex: none;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: none;
  background: color-mix(in srgb, var(--secondary-bg) 80%, white 6%);
  color: var(--text);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.profile-settings-btn svg {
  width: 22px;
  height: 22px;
}

.help-btn {
  flex: none;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: 1px solid rgba(127, 127, 127, 0.3);
  background: none;
  color: var(--hint);
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: inherit;
}

.option-card {
  display: flex;
  align-items: center;
  gap: 14px;
  width: 100%;
  background: var(--secondary-bg);
  border: 1px solid rgba(127, 127, 127, 0.14);
  border-radius: var(--radius);
  padding: 18px;
  margin-bottom: 12px;
  text-align: left;
  cursor: pointer;
  color: inherit;
  font: inherit;
  transition: transform 0.12s ease, background 0.12s ease;
}

.option-card:active {
  transform: scale(0.98);
  background: color-mix(in srgb, var(--secondary-bg) 85%, var(--button));
}

.option-icon {
  flex: none;
  width: 44px;
  height: 44px;
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: color-mix(in srgb, var(--button) 18%, transparent);
  color: var(--button);
}

.option-icon svg {
  width: 22px;
  height: 22px;
}

.option-body {
  display: flex;
  flex: 1;
  min-width: 0;
  flex-direction: column;
  gap: 3px;
}

/* Переключатель "Закрытый аккаунт" в настройках — тот же .option-card, но
   div, а не button (внутри свой интерактивный элемент — сам тумблер). */
.setting-toggle-row {
  cursor: default;
}

.toggle-switch {
  flex: none;
  position: relative;
  width: 44px;
  height: 26px;
}

.toggle-switch input {
  position: absolute;
  opacity: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  cursor: pointer;
}

.toggle-slider {
  position: absolute;
  inset: 0;
  background: color-mix(in srgb, var(--hint) 30%, transparent);
  border-radius: 999px;
  transition: background 0.15s ease;
}

.toggle-slider::before {
  content: "";
  position: absolute;
  top: 3px;
  left: 3px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: #fff;
  transition: transform 0.15s ease;
}

.toggle-switch input:checked + .toggle-slider {
  background: var(--button);
}

.toggle-switch input:checked + .toggle-slider::before {
  transform: translateX(18px);
}

.option-title {
  font-size: 16px;
  font-weight: 600;
}

.option-hint {
  font-size: 13px;
  color: var(--hint);
}

/* Профиль (свой и чужой) — сводка в стиле Instagram: аватар слева,
   публикации/подписчики/подписки справа в ряд. */
.profile-summary {
  display: flex;
  align-items: center;
  gap: 20px;
  margin: 8px 0 16px;
}

.profile-avatar-btn {
  flex: none;
  width: 76px;
  height: 76px;
  border-radius: 50%;
  border: none;
  padding: 0;
  cursor: pointer;
  background: color-mix(in srgb, var(--button) 16%, var(--secondary-bg));
  color: var(--button);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  font-family: inherit;
}

.profile-avatar-btn-static {
  cursor: default;
}

.profile-avatar-wrap {
  position: relative;
  flex: none;
}

/* Кружок-плюс поверх своего аватара — появляется только если аватар уже
   загружен (тогда тап по самому аватару открывает его, а не сразу загрузку
   нового фото, см. app.js). Пока аватара нет, кнопка скрыта — тап по
   плейсхолдеру и так открывает выбор файла. */
.profile-avatar-add-btn {
  position: absolute;
  top: -4px;
  right: -4px;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: 2px solid var(--bg);
  background: var(--button);
  color: var(--button-text);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 0;
}

.profile-avatar-add-btn svg {
  width: 14px;
  height: 14px;
}

.profile-avatar-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.profile-avatar-placeholder {
  font-size: 28px;
  font-weight: 700;
}

/* Чужой профиль (2026-08-20, владелец): имя — выше блока со счётчиками, но
   не выше аватарки, справа от неё, по её верхней границе — не в общем
   центрированном .profile-summary (тот используется и в своём профиле, там
   макет не менялся), а в отдельной колонке рядом с аватаркой. */
.profile-summary-align-top {
  align-items: flex-start;
}

.profile-summary-info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.profile-name-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

/* Кнопка подписки — компактная пилюля в строке с именем, а не через весь
   экран (владелец, 2026-08-20: "сейчас она слишком громоздкая"). */
.profile-follow-btn {
  flex: none;
  border: none;
  border-radius: 999px;
  padding: 7px 16px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  font-family: inherit;
}

.profile-follow-btn-primary {
  background: var(--button);
  color: var(--button-text);
}

.profile-follow-btn-ghost {
  background: color-mix(in srgb, var(--hint) 20%, transparent);
  color: var(--text);
}

.profile-follow-btn:disabled {
  opacity: 0.6;
  cursor: default;
}

.profile-stats {
  flex: 1;
  display: flex;
  justify-content: space-around;
}

.profile-stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
}

.profile-stat strong {
  font-size: 17px;
  font-weight: 700;
}

.profile-stat span {
  font-size: 12px;
  color: var(--hint);
}

.follow-list-row {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 10px 4px;
  border-bottom: 1px solid rgba(127, 127, 127, 0.12);
}

/* Аватар+имя — сама кликабельная зона (открывает профиль), row вокруг —
   просто контейнер (position:relative для .follow-list-unfollow-btn ниже). */
.follow-list-main {
  display: flex;
  align-items: center;
  gap: 12px;
  flex: 1;
  min-width: 0;
  border: none;
  background: none;
  color: var(--text);
  padding: 0;
  cursor: pointer;
  font-family: inherit;
  text-align: left;
}

/* "Отписаться" — раскрывается долгим нажатием на строку (owner, 2026-08-21),
   тот же приём и тот же вид пилюли, что у "Удалить" на комментариях/
   уведомлениях (wireLongPressReveal). Только на вкладке "Подписки". */
.follow-list-unfollow-btn {
  position: absolute;
  top: 50%;
  right: 4px;
  transform: translateY(-50%);
  z-index: 5;
  border: none;
  border-radius: 999px;
  padding: 8px 16px;
  background: var(--danger);
  color: #fff;
  font-size: 12px;
  font-weight: 700;
  cursor: pointer;
  font-family: inherit;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.35);
}

.follow-list-avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  object-fit: cover;
  background: color-mix(in srgb, var(--button) 55%, #444);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 15px;
  font-weight: 700;
  color: #fff;
  flex: none;
}

.follow-list-name {
  font-size: 14px;
  font-weight: 600;
}

/* «Мои комментарии» в Настройках (владелец, 2026-08-24) — превью поста
   (первое фото) слева, текст комментария и дата справа, вся строка —
   кнопка на саму публикацию. */
.my-comment-row {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 10px 4px;
  border-bottom: 1px solid rgba(127, 127, 127, 0.12);
  border-left: none;
  border-right: none;
  border-top: none;
  background: none;
  color: var(--text);
  cursor: pointer;
  font-family: inherit;
  text-align: left;
}

.my-comment-thumb {
  width: 48px;
  height: 48px;
  border-radius: 10px;
  object-fit: cover;
  flex: none;
  background: var(--secondary-bg);
}

.my-comment-thumb-placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--hint);
}

.my-comment-thumb-placeholder svg {
  width: 22px;
  height: 22px;
}

.my-comment-body {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
  flex: 1;
}

.my-comment-text {
  font-size: 13.5px;
  line-height: 1.4;
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

.my-comment-meta {
  font-size: 12px;
  color: var(--hint);
}

.muted-author-row {
  cursor: default;
  justify-content: space-between;
}

.muted-author-row .follow-list-name {
  flex: 1;
}

.profile-stat-btn {
  border: none;
  background: none;
  color: var(--text);
  cursor: pointer;
  font-family: inherit;
  padding: 0;
}

/* Чужой закрытый профиль — списки подписчиков/подписок недоступны, кнопка
   выглядит как обычный нередактируемый счётчик (владелец, 2026-08-23: до
   этого счётчики на чужом профиле были и вовсе некликабельны всегда). */
.profile-stat-btn-static {
  cursor: default;
}

.profile-name {
  font-size: 15px;
  font-weight: 700;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.notice {
  color: var(--hint);
  font-size: 13px;
  line-height: 1.5;
  padding: 0 0 0 12px;
  margin: 0 0 18px;
  border-left: 3px solid color-mix(in srgb, var(--button) 45%, transparent);
}

.notice-list {
  color: var(--hint);
  font-size: 13px;
  line-height: 1.5;
  padding: 0 0 0 28px;
  margin: -8px 0 18px;
  border-left: 3px solid color-mix(in srgb, var(--button) 45%, transparent);
  margin-left: 0;
}

.notice-list li {
  margin-bottom: 4px;
}

.notice-list strong {
  color: var(--text);
}

.field {
  display: block;
  margin-bottom: 16px;
}

.field-label {
  display: block;
  font-size: 13px;
  color: var(--hint);
  margin-bottom: 6px;
}

.field-input {
  width: 100%;
  background: var(--secondary-bg);
  border: 1px solid rgba(127, 127, 127, 0.18);
  border-radius: 12px;
  padding: 12px 14px;
  font-size: 15px;
  color: var(--text);
  font-family: inherit;
  resize: vertical;
}

.field-input:focus {
  outline: none;
  border-color: var(--button);
}

.field-input.mono,
.search-input.mono {
  font-family: "SF Mono", "Cascadia Mono", Consolas, monospace;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}

/* В моноширинном шрифте пробел — такой же по ширине символ, как буква или
   цифра, поэтому автоматические пробелы между группами госномера выглядят
   непропорционально широкими зазорами; word-spacing сужает только их. */
.gosnomer-input {
  word-spacing: -0.35em;
}

.form-message {
  border-radius: 12px;
  padding: 10px 14px;
  font-size: 13px;
  margin-bottom: 16px;
}

.form-message.error {
  background: color-mix(in srgb, var(--danger) 16%, transparent);
  color: var(--danger);
}

.form-message.ok {
  background: color-mix(in srgb, var(--ok) 16%, transparent);
  color: var(--ok);
}

.results {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.result-card {
  background: var(--secondary-bg);
  border-radius: 12px;
  padding: 14px;
  border: 1px solid rgba(127, 127, 127, 0.14);
}

/* Уведомления — плоский список строк, как в Инстаграме (2026-08-20: раньше
   были карточками .result-card с обычным .result-text — тот же цвет текста,
   что и везде в приложении, без аватара и разделения "кто/что", выглядело
   как список технических сообщений, а не соцсети). #notifications-list
   переопределяет gap у общего .results — строки идут вплотную, разделяются
   заголовками дат, а не промежутками между карточками. */
#notifications-list {
  gap: 0;
}

.notification-date-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 14px;
  font-weight: 700;
  padding: 16px 2px 8px;
}

.notification-date-header:first-child {
  padding-top: 2px;
}

/* Стрелка группы старше позавчера — сама группа свёрнута по умолчанию
   (владелец, 2026-08-20: "как история в браузере"), поворот на 180° при
   разворачивании — плавный transform-transition, не мгновенный скачок. */
.notification-group-toggle {
  border: none;
  background: none;
  color: var(--hint);
  padding: 4px;
  cursor: pointer;
  display: flex;
}

.notification-group-toggle svg {
  width: 18px;
  height: 18px;
  transition: transform 0.2s ease;
}

.notification-group-toggle.expanded svg {
  transform: rotate(180deg);
}

.notification-row {
  position: relative;
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 8px 2px;
  border-radius: 10px;
}

/* Аватар+текст — отдельная кликабельная зона (профиль автора действия), не
   вся строка целиком: превьюшка публикации справа (.notification-thumb-btn)
   ведёт в другое место (владелец, 2026-08-21). */
.notification-main {
  display: flex;
  align-items: center;
  gap: 12px;
  flex: 1;
  min-width: 0;
  border: none;
  background: none;
  text-align: left;
  font-family: inherit;
  cursor: pointer;
  padding: 0;
}

/* Уведомления от модератора — тот же ряд аватар+текст, но не кнопка: некуда
   вести клик (не настоящий профиль пользователя). */
.notification-main-static {
  cursor: default;
}

.notification-thumb-btn {
  flex: none;
  border: none;
  background: none;
  padding: 0;
  line-height: 0;
  cursor: pointer;
}

/* "Удалить" — скрыта по умолчанию, раскрывается долгим нажатием на строку
   (wireLongPressReveal), тот же приём, что и у комментариев (владелец,
   2026-08-20). Оверлеем поверх правого края строки, а не в общем потоке —
   иначе раскрытие сдвигало бы остальную разметку строки. */
.notification-delete-btn {
  position: absolute;
  top: 50%;
  right: 4px;
  transform: translateY(-50%);
  z-index: 5;
  border: none;
  border-radius: 999px;
  padding: 8px 16px;
  background: var(--danger);
  color: #fff;
  font-size: 12px;
  font-weight: 700;
  cursor: pointer;
  font-family: inherit;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.35);
}

.notification-row-unread {
  background: color-mix(in srgb, var(--button) 9%, transparent);
}

.notification-avatar {
  width: 46px;
  height: 46px;
  border-radius: 50%;
  object-fit: cover;
  flex: none;
  background: color-mix(in srgb, var(--button) 55%, #444);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 17px;
  font-weight: 700;
  color: #fff;
}

.notification-body {
  flex: 1;
  min-width: 0;
}

.notification-text {
  font-size: 13.5px;
  line-height: 1.4;
  color: var(--text);
}

.notification-author-name {
  font-weight: 700;
}

.notification-time {
  font-size: 12px;
  color: var(--hint);
  margin-top: 3px;
}

/* Снимок содержимого под текстом уведомления (владелец, 2026-08-24) — тише
   основного текста, в один ряд с многоточием, если не влезает. */
.notification-preview {
  font-size: 12.5px;
  color: var(--hint);
  margin-top: 2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* "Одобрить"/"Отклонить" прямо в уведомлении о заявке на подписку
   (владелец, 2026-08-24). */
.notification-follow-actions {
  display: flex;
  gap: 8px;
  margin-top: 8px;
}

.notification-approve-btn,
.notification-reject-btn {
  border: none;
  border-radius: 999px;
  padding: 7px 14px;
  font-size: 12px;
  font-weight: 700;
  cursor: pointer;
  font-family: inherit;
}

.notification-approve-btn {
  background: var(--button);
  color: var(--button-text);
}

.notification-reject-btn {
  background: color-mix(in srgb, var(--hint) 16%, transparent);
  color: var(--text);
}

.notification-thumb {
  width: 44px;
  height: 44px;
  border-radius: 6px;
  object-fit: cover;
  flex: none;
}

/* Осмотры в карточке авто — более заметное разделение между записями
   (2026-08-20: раньше отличались от списка чужих постов только тонкой
   границей и было трудно понять, где кончается один осмотр и начинается
   следующий) и место под фото, если оно приложено к записи. */
.inspection-reviews {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.inspection-review-card {
  padding: 16px;
  border: 1px solid rgba(127, 127, 127, 0.24);
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
}

/* Комментарии к осмотру (владелец, 2026-08-23) — раскрываются под записью
   по клику на "Комментарии", как редко используемая деталь, не всегда
   видная всем сразу. */
.inspection-comments-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: none;
  background: none;
  color: var(--hint);
  font-size: 13px;
  font-weight: 600;
  padding: 8px 0 0;
  cursor: pointer;
  font-family: inherit;
  text-align: left;
}

.inspection-comments-toggle svg {
  width: 19px;
  height: 19px;
  flex-shrink: 0;
}

.inspection-comments {
  margin-top: 8px;
}

.inspection-comments-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 10px;
}

.inspection-comment-row {
  font-size: 13px;
  line-height: 1.4;
}

.inspection-comment-author {
  font-weight: 700;
  margin-right: 6px;
}

.inspection-comment-form {
  display: flex;
  gap: 8px;
}

.inspection-comment-form .field-input {
  flex: 1;
}

.result-meta {
  display: flex;
  justify-content: space-between;
  color: var(--hint);
  font-size: 12px;
  margin-bottom: 6px;
}

.result-text {
  font-size: 14px;
  line-height: 1.5;
  white-space: pre-wrap;
}

.empty-state {
  color: var(--hint);
  font-size: 14px;
  text-align: center;
  padding: 24px 8px;
}

/* Внутри grid-раскладки плиток (Лента/профиль) пустое состояние —
   единственный элемент, без этого он занимал бы только первую колонку
   из двух и текст казался бы прижатым влево, а не по центру. */
.tile-grid .empty-state {
  grid-column: 1 / -1;
}

.empty-state p {
  margin: 0 0 10px;
}

.empty-state .btn {
  margin-top: 6px;
}

.field-hint {
  display: block;
  font-size: 12px;
  color: var(--hint);
  margin-top: 6px;
}

.section-title {
  font-size: 15px;
  font-weight: 650;
  margin: 22px 4px 10px;
}

.section-title:first-of-type {
  margin-top: 4px;
}

/* Групповой заголовок над несколькими .section-title — крупнее подзаголовков,
   но чуть скромнее заголовка всего экрана (.screen-title), чтобы визуально
   было три уровня, а не два. */
.section-title-group {
  font-size: 17px;
  font-weight: 700;
  margin: 28px 4px 4px;
  padding-top: 14px;
  border-top: 1px solid rgba(127, 127, 127, 0.18);
}

.photo-grid {
  display: flex;
  gap: 8px;
  margin-top: 10px;
  flex-wrap: wrap;
}

.photo-grid img {
  width: 84px;
  height: 84px;
  object-fit: cover;
  border-radius: 10px;
  border: 1px solid rgba(127, 127, 127, 0.18);
}

.photo-thumbs {
  display: flex;
  gap: 10px;
  margin-top: 10px;
  flex-wrap: wrap;
}

.photo-thumb {
  position: relative;
  width: 84px;
  height: 84px;
}

.photo-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 10px;
  border: 1px solid rgba(127, 127, 127, 0.18);
}

.photo-thumb-remove {
  position: absolute;
  top: -6px;
  right: -6px;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: none;
  background: var(--danger);
  color: #fff;
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.35);
}

/* Маленькое превью уже выбранных фото на шаге 2 формы публикации (владелец,
   2026-08-20: "фото уже чуть меньше"). Собирается через innerHTML-копию
   живых миниатюр шага 1 (app.js) — обработчики клика при этом не
   переносятся, поэтому кнопку "×" и кольцо прогресса здесь прячем: удалить
   фото можно только вернувшись на шаг 1 через "Изменить фото". */
.photo-thumbs-compact {
  margin-bottom: 4px;
}

.photo-thumbs-compact .photo-thumb {
  width: 56px;
  height: 56px;
}

.photo-thumbs-compact .photo-thumb-remove,
.photo-thumbs-compact .photo-thumb-overlay {
  display: none;
}

.post-edit-photos-link {
  display: block;
  border: none;
  background: none;
  color: var(--link);
  font-size: 13px;
  font-weight: 600;
  padding: 0;
  margin: 0 0 18px;
  cursor: pointer;
  font-family: inherit;
}

/* Кольцо прогресса загрузки поверх миниатюры фото */
.photo-thumb-overlay {
  position: absolute;
  inset: 0;
  border-radius: 10px;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
}

.progress-ring {
  width: 36px;
  height: 36px;
  transform: rotate(-90deg);
}

.progress-ring-bg {
  fill: none;
  stroke: rgba(255, 255, 255, 0.25);
  stroke-width: 3;
}

.progress-ring-fg {
  fill: none;
  stroke: #fff;
  stroke-width: 3;
  stroke-linecap: round;
  transition: stroke-dashoffset 0.15s ease;
}

.result-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-top: 10px;
  flex-wrap: wrap;
}

/* "⋮" -> "Удалить описание" — только у модераторов, справа в той же строке,
   что и "Пожаловаться" (владелец, 2026-08-20). */
.inspection-menu-wrap {
  position: relative;
  display: flex;
}

.inspection-menu-btn {
  flex: none;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: none;
  background: color-mix(in srgb, var(--secondary-bg) 80%, white 6%);
  color: var(--text);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.inspection-menu-btn svg {
  width: 17px;
  height: 17px;
}

.inspection-delete-btn {
  position: absolute;
  top: 40px;
  right: 0;
  z-index: 5;
  white-space: nowrap;
  border: none;
  border-radius: 999px;
  padding: 9px 16px;
  background: var(--danger);
  color: #fff;
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
  font-family: inherit;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.35);
}

.btn {
  border: none;
  border-radius: 10px;
  padding: 8px 14px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  font-family: inherit;
}

.btn:disabled {
  opacity: 0.55;
  cursor: default;
}

/* Крутящийся кружок вместо текста, пока идёт запрос (setBusy в app.js) —
   раньше кнопка просто становилась disabled без какой-либо другой видимой
   разницы, из-за чего казалось, что нажатие не сработало (владелец,
   2026-08-20, про "Сохранить" в редакторе аватара). Общий класс — работает
   на любой кнопке, использующей setBusy, не только на этой. */
button.is-busy {
  position: relative;
  color: transparent !important;
}

button.is-busy::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 16px;
  height: 16px;
  margin: -8px 0 0 -8px;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.35);
  border-top-color: #fff;
  animation: btn-spin 0.6s linear infinite;
}

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

.btn-primary {
  background: var(--button);
  color: var(--button-text);
}

.btn-danger {
  background: color-mix(in srgb, var(--danger) 20%, transparent);
  color: var(--danger);
}

.btn-ghost {
  background: color-mix(in srgb, var(--hint) 16%, transparent);
  color: var(--text);
}

.status-badge {
  display: inline-block;
  font-size: 11px;
  font-weight: 650;
  padding: 2px 8px;
  border-radius: 999px;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.status-badge.pending {
  background: color-mix(in srgb, #fbbf24 20%, transparent);
  color: #fbbf24;
}

.status-badge.published {
  background: color-mix(in srgb, var(--ok) 20%, transparent);
  color: var(--ok);
}

.status-badge.rejected {
  background: color-mix(in srgb, var(--danger) 20%, transparent);
  color: var(--danger);
}

/* Кнопка-скрепка вместо системного вида <input type=file> */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

.attach-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: var(--secondary-bg);
  border: 1px solid rgba(127, 127, 127, 0.18);
  border-radius: 12px;
  padding: 10px 16px;
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
  cursor: pointer;
  font-family: inherit;
}

.attach-btn svg {
  width: 18px;
  height: 18px;
  color: var(--button);
}

.attach-btn:active {
  background: color-mix(in srgb, var(--secondary-bg) 85%, var(--button));
}

/* Полноэкранный просмотр фото */
/* Редактор аватара — перед сохранением фото просят расположить в круге
   (перетащить/зажать пальцами), как в Instagram, а не просто присваивают
   аватаром центр исходника. */
.avatar-editor-overlay {
  position: fixed;
  inset: 0;
  z-index: 2000;
  background: rgba(0, 0, 0, 0.94);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 18px;
  padding: 24px;
  /* На невысоких экранах (маленький телефон + разложенная клавиатура/шапка
     Telegram) круг + подсказка + кнопки могли не помещаться по высоте —
     без прокрутки контент просто обрезался бы сверху и снизу поровну
     (justify-content: center), из-за чего кнопки внизу могли уехать за
     край экрана. */
  overflow-y: auto;
}

.avatar-editor-stage {
  position: relative;
  width: min(78vw, 300px);
  height: min(78vw, 300px);
  border-radius: 50%;
  overflow: hidden;
  background: #111;
  touch-action: none;
  box-shadow: 0 0 0 2000px rgba(0, 0, 0, 0.6);
}

.avatar-editor-stage img {
  position: absolute;
  top: 0;
  left: 0;
  transform-origin: 0 0;
  user-select: none;
  -webkit-user-drag: none;
  max-width: none;
}

.avatar-editor-hint {
  color: var(--hint);
  font-size: 13px;
  text-align: center;
  max-width: 280px;
  margin: 0;
}

.avatar-editor-actions {
  display: flex;
  gap: 12px;
}

/* Обе кнопки на фоне редактора — фон там всегда одинаковый (почти чёрный,
   rgba(0,0,0,0.94)) независимо от темы приложения, поэтому и кнопки здесь
   зафиксированы: сплошные, непрозрачные, не завязаны на тему Telegram
   (--button у части пользователей тёмный — на этом фоне выглядел
   выключенным). Первая попытка (2026-08-20) сделала только "Отмена"
   полупрозрачной белой и добавила тень — владелец повторно сообщил, что обе
   кнопки всё ещё выглядят тёмными/невзрачными (2026-08-24), поэтому здесь
   обе теперь сплошного цвета, без какой-либо прозрачности вообще. */
.avatar-editor-actions .btn {
  min-width: 120px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.45);
}

.avatar-editor-actions .btn-ghost {
  background: #e5e7eb;
  border: none;
  color: #111;
}

.avatar-editor-actions .btn-primary {
  background: #fff;
  color: #111;
}

.lightbox {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.92);
  z-index: 1000;
  cursor: zoom-out;
}

/* Полоса фото на весь экран — один src (карточка осмотра, товар apipoint)
   или несколько (галерея аватаров, см. openLightbox в app.js), между
   которыми можно листать горизонтальным свайпом, тот же нативный
   scroll-snap, что и в фото одного поста Ленты. */
.lightbox-strip {
  display: flex;
  width: 100%;
  height: 100%;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
}

.lightbox-strip::-webkit-scrollbar {
  display: none;
}

/* Обёртка вокруг каждого фото — раньше <img> были прямыми детьми полосы;
   нужна обёртка с position:relative, чтобы разместить "⋮"/"Удалить" поверх
   конкретного фото в галерее своих аватаров (2026-08-20), не поверх всей
   полосы сразу. */
.lightbox-slide {
  position: relative;
  flex: none;
  width: 100%;
  height: 100%;
  scroll-snap-align: start;
  padding: 24px;
  box-sizing: border-box;
}

.lightbox-strip img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/* "⋮" на конкретном фото в галерее своих аватаров — тот же стиль, что у
   .feed-reel-menu-btn (белые точки на чёрном полупрозрачном кружке).
   "Удалить" рядом — скрыта по умолчанию, раскрывается по тапу на "⋮", тот
   же приём, что и у долгого нажатия на комментарий, только по обычному
   тапу — здесь это не случайное срабатывание, лайтбокс и так открыт
   намеренно. top ниже .lightbox-close (top:16, высота 40px, до 56px) — на
   той же высоте кружки налезали друг на друга (владелец, 2026-08-20). */
.lightbox-menu-btn {
  position: absolute;
  top: 72px;
  right: 32px;
  z-index: 5;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: none;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.lightbox-menu-btn svg {
  width: 19px;
  height: 19px;
}

.lightbox-delete-btn {
  position: absolute;
  top: 72px;
  right: 78px;
  z-index: 5;
  border: none;
  border-radius: 999px;
  padding: 9px 16px;
  background: var(--danger);
  color: #fff;
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
  font-family: inherit;
}

/* z-index обязателен: .lightbox-slide (внутри .lightbox-strip, идёт в
   разметке после этой кнопки) тоже position:relative — без z-index два
   позиционированных элемента красятся в порядке DOM, и фото оказывалось
   поверх крестика закрытия (владелец, 2026-08-20: "крестик находится за
   фотографией"). */
.lightbox-close {
  position: absolute;
  top: 16px;
  right: 16px;
  z-index: 10;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: none;
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
}

.photo-grid img,
.photo-thumb img {
  cursor: zoom-in;
}

/* Экран-заглушка "откройте в Telegram" */
.tg-gate {
  position: fixed;
  inset: 0;
  z-index: 2000;
  background: var(--bg);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 32px;
  gap: 14px;
}

.tg-gate-icon {
  color: var(--button);
  margin-bottom: 6px;
}

.tg-gate-icon svg {
  width: 52px;
  height: 52px;
}

.tg-gate-title {
  font-size: 20px;
  font-weight: 700;
}

.tg-gate-text {
  color: var(--hint);
  font-size: 14px;
  line-height: 1.5;
  max-width: 320px;
  margin: 0;
}

.tg-gate-btn {
  margin-top: 8px;
  padding: 12px 28px;
  font-size: 15px;
  text-decoration: none;
  display: inline-block;
}

/* Вкладки в админ-панели — переносятся строкой, чтобы не нужно было
   листать в сторону в поисках не поместившейся кнопки */
.tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 14px;
  margin-bottom: 16px;
}

.tab-btn {
  flex: none;
  border: none;
  background: var(--secondary-bg);
  color: var(--hint);
  border-radius: 10px;
  padding: 9px 14px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  font-family: inherit;
  white-space: nowrap;
}

.tab-btn.active {
  background: var(--button);
  color: var(--button-text);
}

/* Вкладки "Избранного" — сегментированный переключатель в стиле модалки
   подписчиков/подписок в Instagram: во всю ширину, подсветка активной
   вкладки подчёркиванием, а не заливкой пилюли (в отличие от общего
   .tab-btn, который используется в админке/поддержке и там уместнее). */
.fav-tabs {
  position: relative;
  display: flex;
  border-bottom: 1px solid rgba(127, 127, 127, 0.2);
  margin: 14px 0 16px;
}

.fav-tab {
  flex: 1;
  text-align: center;
  border: none;
  background: none;
  color: var(--hint);
  font-size: 14px;
  font-weight: 700;
  padding: 10px 0;
  cursor: pointer;
  font-family: inherit;
}

.fav-tab.active {
  color: var(--text);
}

/* Плавно скользящая полоска вместо мгновенной подсветки активной вкладки
   (владелец, 2026-08-20: "перезод ползунка сделай красивой плавной
   анимацией") — один общий элемент, а не подчёркивание на каждой кнопке
   отдельно, translateX анимируется через transition. Ровно 2 вкладки
   (FAVORITES_TABS в app.js), поэтому ширина/сдвиг — фиксированные 50%. */
.fav-tab-indicator {
  position: absolute;
  left: 0;
  bottom: -1px;
  width: 50%;
  height: 2px;
  background: var(--text);
  border-radius: 2px;
  transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);
}

.fav-tab-indicator.fav-tab-indicator-1 {
  transform: translateX(100%);
}

/* pan-y — явно говорим браузеру, что вертикальный скролл нативный, а
   горизонтальный жест наш (свайп между вкладками, wireSwipeTabs) — без
   этого браузер иногда не сразу решает, кому отдать жест, и свайп
   ощущается как не срабатывающий с первого раза. */
.fav-tab-panels {
  touch-action: pan-y;
  flex: 1;
  min-height: 0;
}

/* Свайп между вкладками (wireSwipeTabs) слушает касания на самом элементе —
   а его высота по умолчанию равна высоте контента. Когда контента мало
   (пустой поиск на "Осмотре", пара карточек в "Избранном"), под ним
   остаётся пустой хвост экрана, который уже не принадлежит этому элементу —
   жест там не долетает до обработчика (владелец, 2026-08-23: "свайп
   работает только в верхней части экрана"). min-height растягивает элемент
   на весь видимый экран независимо от количества контента; 110px + safe-area
   — тот же запас под плавающую нижнюю навигацию, что и в .app. Строка с
   100vh — запасной вариант для движков без поддержки dvh, следующая строка
   её переопределяет там, где dvh понимают. */
.screen[data-screen="home"],
.screen[data-screen="favorites"] {
  min-height: calc(100vh - var(--header-h, 60px) - 110px - env(safe-area-inset-bottom, 0px));
  min-height: calc(100dvh - var(--header-h, 60px) - 110px - env(safe-area-inset-bottom, 0px));
}

/* Только "Избранное": свайп-слушатель здесь висит не на самом экране, а на
   .fav-tab-panels (соседе заголовка и вкладок внутри экрана) — ей нужно
   расти вместо экрана, поэтому именно здесь нужен flex-контейнер. На
   "Осмотре" слушатель висит на самом экране, обычного min-height достаточно
   без flex. */
.screen[data-screen="favorites"] {
  display: flex;
  flex-direction: column;
}

.tab-count {
  opacity: 0.75;
  font-size: 12px;
}

/* Тап-зона больше самого текста (padding + компенсирующий отрицательный
   margin) — иначе рядом с "← Ко всем объявлениям" легко промахнуться мимо
   маленькой строки текста и попасть по соседним элементам. */
/* Строка "Назад" на карточке публикации (Лента) — вместо большой красной
   "Удалить публикацию" через всю ширину, теперь "⋮" в той же строке, справа
   (владелец, 2026-08-20: "раздражает большая кнопка удалить"). */
.post-detail-top-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 4px;
}

/* .back-link несёт отрицательный margin для случая, когда он один/первый
   на экране — в общей строке с "⋮" он из-за этого съезжал по вертикали
   (тот же баг и та же правка, что у .car-card-top-row .back-link). */
.post-detail-top-row .back-link {
  margin: 0;
}

.post-detail-menu-wrap {
  position: relative;
}

.post-detail-menu-btn {
  flex: none;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: none;
  background: color-mix(in srgb, var(--secondary-bg) 80%, white 6%);
  color: var(--text);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.post-detail-menu-btn svg {
  width: 19px;
  height: 19px;
}

.back-link {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  border: none;
  background: none;
  color: var(--link);
  font-size: 15px;
  font-weight: 600;
  padding: 12px 12px 12px 0;
  margin: -10px 0 2px -2px;
  cursor: pointer;
  font-family: inherit;
}

/* SVG-шеврон вместо символа "←" — у стрелки как текстового символа своя,
   не всегда предсказуемая базовая линия в разных шрифтах/рендерерах, из-за
   этого она выглядела "криво" относительно надписи. Иконка с flex-выравниванием
   всегда ровно по центру строки. */
.back-link-icon {
  width: 20px;
  height: 20px;
  flex: none;
}

/* Групповая карточка авто по VIN в админке */
.vin-card {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  width: 100%;
  text-align: left;
  background: var(--secondary-bg);
  border: 1px solid rgba(127, 127, 127, 0.14);
  border-radius: 12px;
  padding: 14px;
  cursor: pointer;
  color: inherit;
  font: inherit;
}

.vin-card-vin {
  font-family: "SF Mono", "Cascadia Mono", Consolas, monospace;
  font-weight: 700;
  font-size: 14px;
}

.vin-card-meta {
  color: var(--hint);
  font-size: 12px;
  margin-top: 3px;
}

.vin-card-count {
  flex: none;
  background: color-mix(in srgb, var(--button) 18%, transparent);
  color: var(--button);
  border-radius: 999px;
  padding: 3px 10px;
  font-size: 12px;
  font-weight: 700;
}

/* Массовые действия */
.bulk-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  background: color-mix(in srgb, var(--button) 14%, transparent);
  border-radius: 12px;
  padding: 10px 12px;
  margin-bottom: 12px;
  font-size: 13px;
  flex-wrap: wrap;
}

.result-card.selectable {
  display: flex;
  align-items: flex-start;
  gap: 10px;
}

.result-card-select {
  flex: none;
  width: 20px;
  height: 20px;
  margin-top: 2px;
  accent-color: var(--button);
}

.result-card-body {
  flex: 1;
  min-width: 0;
}

/* Лог сервера */
.log-box {
  background: var(--secondary-bg);
  border-radius: 12px;
  padding: 12px 14px;
  font-size: 11px;
  line-height: 1.5;
  font-family: "SF Mono", "Cascadia Mono", Consolas, monospace;
  white-space: pre-wrap;
  word-break: break-word;
  max-height: 60vh;
  overflow-y: auto;
}

.option-card-compact {
  padding: 14px 16px;
  margin-bottom: 22px;
}

/* Настройки — сгруппированы по категориям (владелец, 2026-08-24: "Мои
   действия" / "Приватность"), заголовок группы — как обычно у таких
   списков, мелкий и приглушённый. Инструкция/Техподдержка/Админ-панель
   остались без группы, вне этих двух заголовков. */
.settings-section-title {
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--hint);
  margin: 22px 4px 10px;
}

.settings-section-title:first-child {
  margin-top: 4px;
}

/* Шрифт этого экрана чуть мельче остальных (владелец, 2026-08-24) —
   .option-title/.option-hint используются и на других экранах
   (Инструкция, Техподдержка), поэтому правим только здесь, не глобально. */
.screen[data-screen="settings"] .option-title {
  font-size: 15px;
}

.screen[data-screen="settings"] .option-hint {
  font-size: 12px;
}

/* Поиск на объединённом экране "Найти" */
.search-bar {
  display: flex;
  gap: 8px;
  margin-bottom: 12px;
}

/* Пара полей "VIN или госномер" — на главном экране поиска и в форме
   осмотра: одна и та же вёрстка, второе поле только помогает найти/заполнить
   VIN (через number2vin), а не заменяет его как идентификатор записи. */
.dual-input-group {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 8px;
}

.dual-input-or {
  align-self: center;
  font-size: 12px;
  font-weight: 600;
  color: var(--button);
  animation: dual-input-or-glow 2.4s ease-in-out infinite;
}

@keyframes dual-input-or-glow {
  0%, 100% {
    opacity: 0.6;
    text-shadow: 0 0 2px color-mix(in srgb, var(--button) 40%, transparent);
  }
  50% {
    opacity: 1;
    text-shadow: 0 0 8px color-mix(in srgb, var(--button) 85%, transparent);
  }
}

.search-input {
  flex: 1;
  min-width: 0;
  background: var(--secondary-bg);
  border: 1px solid rgba(127, 127, 127, 0.18);
  border-radius: 12px;
  padding: 12px 14px;
  font-size: 15px;
  color: var(--text);
}

.search-input:focus {
  outline: none;
  border-color: var(--button);
}

.search-btn {
  flex: none;
  width: 46px;
  border: none;
  border-radius: 12px;
  background: var(--button);
  color: var(--button-text);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.search-btn svg {
  width: 20px;
  height: 20px;
}

/* Фильтры — узкие кнопки, открывающие модалку выбора (.picker-overlay).
   justify-content: center действует, только пока чипы помещаются в строку —
   если они шире экрана, ряд просто скроллится влево-вправо как обычно. */
.filter-bar {
  display: flex;
  justify-content: center;
  gap: 8px;
  margin-top: 14px;
  margin-bottom: 16px;
  overflow-x: auto;
  padding-bottom: 2px;
}

.filter-trigger {
  flex: none;
  max-width: 150px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  background: var(--secondary-bg);
  border: 1px solid rgba(127, 127, 127, 0.18);
  border-radius: 10px;
  padding: 9px 12px;
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  cursor: pointer;
  text-align: left;
}

.filter-trigger-block {
  display: block;
  width: 100%;
  max-width: none;
  padding: 12px 14px;
  font-size: 15px;
  font-weight: 400;
}

.filter-trigger:disabled {
  opacity: 0.5;
  cursor: default;
}

.filter-trigger.active {
  border-color: var(--button);
  color: var(--button);
  background: color-mix(in srgb, var(--button) 12%, var(--secondary-bg));
}

/* Поля формы публикации — вместо подписи над полем текст-подсказка внутри
   самой кнопки ("Марка (необязательно)"), пропадает при выборе значения
   (владелец, 2026-08-20). Пока не выбрано — приглушённый цвет, как у
   настоящего placeholder, а не обычный текст кнопки. */
.post-field-trigger:not(.active) {
  color: var(--hint);
}

.filter-trigger-x {
  display: inline-flex;
  margin-left: 4px;
  opacity: 0.8;
}

.filter-reset-all {
  flex: none;
  border: none;
  background: none;
  color: var(--link);
  font-size: 13px;
  font-weight: 600;
  padding: 9px 4px;
  cursor: pointer;
  font-family: inherit;
}

.field-static {
  background: var(--secondary-bg);
  border: 1px solid rgba(127, 127, 127, 0.18);
  border-radius: 12px;
  padding: 12px 14px;
  font-size: 15px;
  color: var(--hint);
}

.btn-block {
  display: block;
  width: 100%;
  text-align: center;
  padding: 14px;
  font-size: 15px;
  margin-top: 4px;
}

/* "Найти" + "Добавить осмотр" рядом (владелец, 2026-08-23) — раньше кнопка
   добавления жила только внутри карточки результата, после поиска; эта
   пара кнопок — быстрый путь для тех, кто и так знает, что будет добавлять
   осмотр, без промежуточного экрана. */
.home-search-actions {
  display: flex;
  gap: 8px;
  margin-top: 4px;
}

.home-search-actions .btn {
  flex: 1;
}

/* Подсказки для новых пользователей (владелец, 2026-08-25) — плавающая
   карточка со стрелкой-указателем на реальный элемент управления, один раз
   на человека (localStorage). Цвет — акцентный (--button), чтобы сразу
   отличаться от обычных карточек интерфейса, не теряться на фоне. */
.onboarding-hint {
  position: fixed;
  z-index: 3000;
  max-width: 230px;
  background: var(--button);
  color: var(--button-text);
  border-radius: 14px;
  padding: 12px 14px 10px;
  font-size: 13px;
  line-height: 1.4;
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.4);
  opacity: 0;
  transform: translateY(4px);
  transition: opacity 0.15s ease, transform 0.15s ease;
}

.onboarding-hint.onboarding-hint-visible {
  opacity: 1;
  transform: translateY(0);
}

.onboarding-hint-arrow {
  position: absolute;
  width: 14px;
  height: 14px;
  background: inherit;
  transform: translateX(-50%) rotate(45deg);
}

.onboarding-hint-below .onboarding-hint-arrow {
  top: -6px;
}

.onboarding-hint-above .onboarding-hint-arrow {
  bottom: -6px;
}

.onboarding-hint-text {
  margin-bottom: 8px;
}

.onboarding-hint-close {
  display: block;
  margin-left: auto;
  border: none;
  background: rgba(255, 255, 255, 0.25);
  color: inherit;
  border-radius: 999px;
  padding: 5px 12px;
  font-size: 12px;
  font-weight: 700;
  cursor: pointer;
  font-family: inherit;
}

/* Вкладка "Статистика" в админке (владелец, 2026-08-23) — сводные числа по
   всему приложению, тот же принцип плиток, что и у .tile-grid, но без фото. */
.stats-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}

.stat-tile {
  display: flex;
  flex-direction: column;
  gap: 4px;
  background: var(--secondary-bg);
  border: 1px solid rgba(127, 127, 127, 0.14);
  border-radius: 14px;
  padding: 14px;
}

.stat-tile strong {
  font-size: 22px;
  font-weight: 700;
}

.stat-tile span {
  font-size: 12px;
  color: var(--hint);
}

/* Плитки в ленте / избранном — как карточки объявлений */
.tile-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}

.tile-card {
  display: block;
  width: 100%;
  text-align: left;
  background: var(--secondary-bg);
  border: 1px solid rgba(127, 127, 127, 0.14);
  border-radius: 14px;
  overflow: hidden;
  color: inherit;
  font: inherit;
  cursor: pointer;
  position: relative;
}

.tile-photo {
  width: 100%;
  aspect-ratio: 1 / 1;
  display: flex;
  align-items: center;
  justify-content: center;
  background: color-mix(in srgb, var(--button) 10%, var(--secondary-bg));
  color: color-mix(in srgb, var(--button) 55%, var(--hint));
}

.tile-photo svg {
  width: 40%;
  height: 40%;
}

.tile-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.tile-favorite {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: none;
  background: rgba(0, 0, 0, 0.45);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.tile-favorite svg {
  width: 21px;
  height: 21px;
}

.tile-favorite.active {
  color: #fbbf24;
}

.tile-favorite.active svg {
  fill: #fbbf24;
}

/* Звёздочка на плитке публикации (владелец, 2026-08-25) — верх-правый угол
   там уже занят счётчиком лайков/статусом, поэтому эта — в левом. */
.tile-favorite-post {
  left: 8px;
  right: auto;
}

.tile-status {
  position: absolute;
  top: 8px;
  right: 8px;
}

.tile-body {
  padding: 8px 10px 10px;
}

.tile-title {
  font-size: 13px;
  font-weight: 700;
  line-height: 1.3;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.tile-city {
  color: var(--hint);
  font-size: 12px;
  margin-top: 4px;
}

/* Плитка публикации в "Ленте" — счётчик лайков вместо кнопки "В избранное"
   (у публикаций своё избранное не заведено, только лайк). */
.tile-like-count {
  position: absolute;
  top: 8px;
  right: 8px;
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 5px 9px;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.45);
  color: #fff;
  font-size: 12px;
  font-weight: 700;
}

.tile-like-count svg {
  width: 14px;
  height: 14px;
}

/* Лента — полноэкранная вертикальная карусель постов, в стиле Reels:
   один пост на экран, вертикальный свайп/скролл к следующему, внутри
   поста — горизонтальный свайп между его фото (если их несколько). Экран
   зафиксирован под шапкой (её высоту меряет JS в --header-h), поэтому не
   участвует в обычной прокрутке страницы, как остальные вкладки. */
.screen-feed {
  position: fixed;
  left: 0;
  right: 0;
  top: var(--header-h, 60px);
  bottom: 0;
  margin: 0;
  padding: 0;
  overflow: hidden;
  background: var(--bg);
  /* Ещё один, независимый от JS, слой защиты от свайпа-закрытия с левого
     края (владелец, 2026-08-26: JS-обход в app.js всё ещё не всегда
     успевал). touch-action читается движком до всякого JS — если он
     распознаёт горизонтальный жест как «не браузерный», у системного
     edge-back жеста меньше шансов начаться вообще, а не просто быть
     отменённым postfactum через preventDefault. Вложенные горизонтальные
     скроллеры (.feed-reel-photos — свайп между фото поста) не страдают:
     они сами себе scroll-контейнер и определяют свой touch-action
     независимо от предка — тот же принцип уже применён у .fav-tab-panels. */
  touch-action: pan-y;
}

.feed-create-btn {
  position: absolute;
  top: 12px;
  right: 12px;
  z-index: 20;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: none;
  background: rgba(0, 0, 0, 0.45);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.feed-create-btn svg {
  width: 20px;
  height: 20px;
}

.feed-filter-btn {
  position: absolute;
  top: 12px;
  right: 60px;
  z-index: 20;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: none;
  background: rgba(0, 0, 0, 0.45);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

/* Кнопка "⋮" — в верхнем правом углу самого блока с фото (.feed-reel-photo-
   area), не в общей строке с "+"/фильтром Ленты (владелец, 2026-08-20: "в
   этом блоке расположи эти три точки... в верхнем правом углу"). Белые
   точки на чёрном полупрозрачном кружке — тот же приём, что у сердечка "в
   избранное" (.tile-favorite), только правее не 8px, а 16px — Лента
   полноэкранная без боковых отступов, вплотную к физическому краю экрана
   кружок визуально подрезался скруглением корпуса телефона (владелец,
   2026-08-20: "как будто обрезается об рамку"). Шапка публикации
   (.feed-reel-header) больше не резервирует под неё место слева. */
.feed-reel-menu-btn {
  position: absolute;
  top: 12px;
  right: 16px;
  z-index: 10;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: none;
  background: rgba(0, 0, 0, 0.45);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.feed-reel-menu-btn svg {
  width: 19px;
  height: 19px;
}

/* Звёздочка "в избранное" рядом с "⋮" (владелец, 2026-08-25) — тот же
   кружок, что у меню, левее на свою ширину + отступ, чтобы не перекрывались. */
.feed-reel-favorite-btn {
  position: absolute;
  top: 12px;
  right: 62px;
  z-index: 10;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: none;
  background: rgba(0, 0, 0, 0.45);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.feed-reel-favorite-btn svg {
  width: 19px;
  height: 19px;
}

.feed-reel-favorite-btn.active {
  color: #fbbf24;
}

.feed-reel-favorite-btn.active svg {
  fill: #fbbf24;
}

/* Меню "⋮" — та же шторка снизу, что у фильтров Ленты (.feed-filter-*),
   только без пикеров, просто список пунктов. */
.post-menu-overlay {
  position: fixed;
  inset: 0;
  z-index: 1500;
  background: rgba(0, 0, 0, 0.75);
  display: flex;
  align-items: flex-end;
}

.post-menu-sheet {
  width: 100%;
  background: var(--bg);
  border-radius: 20px 20px 0 0;
  padding: 10px 0 calc(20px + env(safe-area-inset-bottom, 0px));
}

.post-menu-item {
  display: block;
  width: 100%;
  border: none;
  background: none;
  color: var(--text);
  font-size: 15px;
  font-family: inherit;
  text-align: center;
  padding: 14px 16px;
  cursor: pointer;
  border-top: 1px solid rgba(127, 127, 127, 0.14);
}

.post-menu-item:first-child {
  border-top: none;
}

.post-menu-cancel {
  color: var(--hint);
  font-weight: 700;
}

.post-menu-danger {
  color: var(--danger);
}

.feed-filter-btn svg {
  width: 19px;
  height: 19px;
}

.feed-filter-overlay {
  position: fixed;
  inset: 0;
  z-index: 1500;
  background: rgba(0, 0, 0, 0.75);
  display: flex;
  align-items: flex-end;
}

.feed-filter-modal {
  width: 100%;
  background: var(--bg);
  border-radius: 20px 20px 0 0;
  padding: 18px 16px calc(20px + env(safe-area-inset-bottom, 0px));
}

.feed-filter-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
}

.feed-filter-title {
  font-size: 16px;
  font-weight: 700;
}

/* "Все пользователи" / "Только подписки" — сегментированный переключатель,
   тот же приём, что у .tab-btn в других шторках (владелец, 2026-08-20). */
.feed-filter-audience {
  display: flex;
  gap: 8px;
  margin-bottom: 16px;
}

.feed-filter-audience-btn {
  flex: 1;
  border: none;
  border-radius: 10px;
  padding: 10px 8px;
  background: var(--secondary-bg);
  color: var(--hint);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  font-family: inherit;
}

.feed-filter-audience-btn.active {
  background: var(--button);
  color: var(--button-text);
}

.feed-filter-close {
  position: static;
}

.feed-filter-actions {
  display: flex;
  gap: 10px;
  margin-top: 8px;
}

.feed-filter-actions .btn {
  flex: 1;
}

/* Долгое нажатие на фото — прячет "хром" (шапку и подвал поста, "+"/фильтр
   Ленты), остаётся только само изображение (не масштабируется). Раньше это
   была единственная защита фото от текста поверх него — теперь, когда
   шапка/подвал и так не наезжают на фото (2026-08-20, стиль Instagram-карточки
   вместо оверлея Reels), это просто более "чистый" полноэкранный режим
   просмотра. pointer-events:none на скрытых элементах — чтобы палец, всё ещё
   лежащий на экране, не мог случайно задеть спрятанную кнопку. */
.screen-feed-chromeless .feed-create-btn,
.screen-feed-chromeless .feed-filter-btn,
.screen-feed-chromeless .feed-reel-menu-btn,
.screen-feed-chromeless .feed-reel-header,
.screen-feed-chromeless .feed-reel-footer {
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s ease;
}

.feed-reels {
  height: 100%;
  overflow-y: auto;
  scroll-snap-type: y mandatory;
  scrollbar-width: none;
  /* overscroll-behavior на body (см. выше) гасит только его собственный
     рикошет — вложенные скролл-контейнеры вроде этого имеют свой, его нужно
     глушить отдельно на них же самих, иначе на границе прокрутки WebView
     всё равно может принять рикошет за системный жест. */
  overscroll-behavior: none;
}

.feed-reels::-webkit-scrollbar {
  display: none;
}

.feed-reels .empty-state {
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 32px;
}

/* Instagram-карточка, а не оверлей Reels (2026-08-20, решение владельца —
   раньше ник/подпись/лайки лежали поверх фото полупрозрачными слоями и
   "сливались" с ним; теперь шапка и подвал — непрозрачные блоки в потоке,
   каждый со своей высотой, а фото — flex:1 занимает всё, что осталось между
   ними, и никогда не перекрывается текстом). */
.feed-reel {
  position: relative;
  height: 100%;
  scroll-snap-align: start;
  scroll-snap-stop: always;
  background: var(--bg);
  display: flex;
  flex-direction: column;
}

.feed-reel-photo-area {
  position: relative;
  flex: 1 1 0%;
  min-height: 0;
}

.feed-reel-photos {
  display: flex;
  height: 100%;
  width: 100%;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  /* Тот же принцип, что у .feed-reels — этот контейнер начинается у самого
     левого края экрана (Лента на всю ширину), его собственный горизонтальный
     рикошет нужно глушить отдельно, не полагаясь только на body. */
  overscroll-behavior-x: none;
}

.feed-reel-photos::-webkit-scrollbar {
  display: none;
}

.feed-reel-photo-slide {
  flex: none;
  width: 100%;
  height: 100%;
  scroll-snap-align: start;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.feed-reel-photo-slide img {
  width: 100%;
  height: 100%;
  /* contain, не cover — фото показывается целиком (как публиковал автор),
     а не обрезается под экран; чёрные поля по бокам/сверху-снизу делают
     ленту единообразной независимо от исходных пропорций фото, как в
     Instagram (2026-08-20, было cover — обрезало и "не влезало"). */
  object-fit: contain;
  user-select: none;
  -webkit-user-drag: none;
  -webkit-touch-callout: none;
}

.feed-reel-empty-photo {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--hint);
}

.feed-reel-empty-photo svg {
  width: 64px;
  height: 64px;
  opacity: 0.4;
}

/* Точки-индикатор количества/текущего фото поста — только если фото
   больше одного (владелец, 2026-08-20). transform+background-color на
   transition — переход активной точки плавный, не мгновенный скачок. */
.feed-reel-dots {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 12px;
  z-index: 5;
  display: flex;
  justify-content: center;
  gap: 6px;
  pointer-events: none;
}

.feed-reel-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.45);
  transition: transform 0.2s ease, background-color 0.2s ease;
}

.feed-reel-dot.active {
  background: #fff;
  transform: scale(1.35);
}

/* Всплывающее сердце по двойному тапу (владелец, 2026-08-20) — тот же
   принцип, что в Instagram: показывается по центру фото и само гаснет. */
.feed-reel-heart-pop {
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: 6;
  color: #fff;
  pointer-events: none;
  animation: feed-reel-heart-pop 0.65s ease forwards;
}

.feed-reel-heart-pop svg {
  width: 92px;
  height: 92px;
  filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.45));
}

@keyframes feed-reel-heart-pop {
  0% {
    opacity: 0;
    transform: translate(-50%, -50%) scale(0.5);
  }
  25% {
    opacity: 1;
    transform: translate(-50%, -50%) scale(1.15);
  }
  40% {
    transform: translate(-50%, -50%) scale(1);
  }
  70% {
    opacity: 1;
    transform: translate(-50%, -50%) scale(1);
  }
  100% {
    opacity: 0;
    transform: translate(-50%, -50%) scale(1);
  }
}

/* Шапка публикации — аватар/ник/регион, непрозрачный блок над фото (не
   поверх него). "⋮" теперь внутри .feed-reel-photo-area, а не в этой
   строке (2026-08-20) — слева обычный отступ, без резерва под кнопку.
   padding-right по-прежнему оставляет место под "+"/фильтр Ленты — те
   плавают поверх верхней части шапки (position:absolute от .screen-feed). */
.feed-reel-header {
  flex: none;
  display: flex;
  align-items: center;
  padding: 10px 108px 10px 12px;
  background: var(--header-bg);
  min-height: 54px;
}

.feed-reel-author-btn {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  border: none;
  background: none;
  padding: 0;
  color: #fff;
  cursor: pointer;
  font-family: inherit;
}

.feed-reel-avatar {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  object-fit: cover;
  background: color-mix(in srgb, var(--button) 55%, #444);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  font-weight: 700;
  color: #fff;
  flex: none;
}

.feed-reel-header-text {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  min-width: 0;
}

/* line-height задан явно (а не унаследован) — ник+регион вместе должны
   уместиться в 34px высоты аватарки (владелец, 2026-08-20: "регион не ниже
   нижней границы аватарки"), а не растягивать шапку по центру за её пределы. */
.feed-reel-username {
  font-size: 13.5px;
  line-height: 16px;
  font-weight: 700;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.feed-reel-region {
  font-size: 11px;
  line-height: 13px;
  color: var(--hint);
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Подвал публикации — лайк/комментарии и подпись, непрозрачный блок под
   фото (не поверх него), как в настоящем Instagram (2026-08-20: раньше это
   был полупрозрачный оверлей в стиле Reels прямо на фото — владелец попросил
   классическую карточку, чтобы фото оставалось "чистым"). padding-bottom
   отступает от плавающей нижней навигации (она поверх Ленты, z-index 500):
   bottom 14px + safe-area, высота ~77px — итого верхний край панели на
   ~91px от низа экрана, берём 96px с небольшим запасом. */
.feed-reel-footer {
  flex: none;
  background: var(--header-bg);
  padding: 10px 12px calc(96px + env(safe-area-inset-bottom, 0px));
}

.feed-reel-actions {
  display: flex;
  align-items: center;
  gap: 18px;
  margin-bottom: 8px;
}

/* Дата публикации — справа в той же строке, что лайк/комментарии
   (владелец, 2026-08-20), относительное время ("5 мин назад") тем же
   форматтером, что и у уведомлений (formatRelativeTime в app.js). */
.feed-reel-time {
  margin-left: auto;
  font-size: 12px;
  color: var(--hint);
}

.feed-reel-action-btn {
  display: flex;
  align-items: center;
  gap: 6px;
  background: none;
  border: none;
  color: #fff;
  cursor: pointer;
  font-family: inherit;
  padding: 0;
}

.feed-reel-action-btn svg {
  width: 23px;
  height: 23px;
}

.feed-reel-action-btn.active {
  color: #f87171;
}

.feed-reel-action-btn.active svg {
  fill: #f87171;
}

.feed-reel-action-count {
  font-size: 13px;
  font-weight: 600;
}

/* Подпись — жирный ник + текст одной "строкой", тот же приём, что и у
   компактных комментариев (.comment-author-name). */
.feed-reel-caption {
  color: #fff;
  font-size: 13.5px;
  line-height: 1.4;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.feed-reel-caption-name {
  font-weight: 700;
  margin-right: 5px;
}

/* Хэштег в подписи — кликабельный, ведёт на экран со всеми публикациями с
   этим же хэштегом (владелец, 2026-08-20). Тот же голубой, что у ссылок в
   приложении (var(--link)), а не обычный цвет текста — иначе не читался бы
   как интерактивный элемент. */
.hashtag {
  color: var(--link);
  font-weight: 600;
  cursor: pointer;
}

/* Карточка публикации (Лента → одна запись) */
.post-detail-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 14px 0 10px;
}

.post-author-link {
  border: none;
  background: none;
  color: var(--link);
  font-size: 14px;
  font-weight: 700;
  padding: 0;
  cursor: pointer;
  font-family: inherit;
}

/* Анонимная публикация (владелец, 2026-08-31) — нечего открывать, поэтому и
   выглядеть как ссылка не должно. */
.post-author-link.is-static {
  color: var(--text);
  cursor: default;
}

/* Пилюля лайка на карточке публикации — раньше счётчик был <span> внутри
   самой кнопки лайка (клик по числу переключал бы лайк, не открывал список
   оценивших). Разделено на две кнопки-соседа внутри общей пилюли: свой клик
   у иконки (переключает лайк) и свой у числа (владелец, 2026-08-23: "кто
   поставил лайк"). */
.post-like-pill {
  display: flex;
  align-items: center;
  gap: 6px;
  background: color-mix(in srgb, var(--hint) 14%, transparent);
  color: var(--text);
  border-radius: 999px;
  padding: 7px 12px;
  font-size: 13px;
  font-weight: 700;
}

.post-like-toggle-btn,
.post-like-count-btn {
  border: none;
  background: none;
  color: inherit;
  font: inherit;
  padding: 0;
  cursor: pointer;
  display: flex;
  align-items: center;
}

.post-like-toggle-btn svg {
  width: 18px;
  height: 18px;
}

.post-like-toggle-btn.active {
  color: #f87171;
}

.post-like-toggle-btn.active svg {
  fill: #f87171;
}

.post-detail-caption {
  font-size: 14px;
  line-height: 1.5;
  margin: 0 0 16px;
}

.comment-edit-form {
  margin-top: 8px;
}

.post-detail-caption-edit-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 8px;
}

.comment-input-row {
  display: flex;
  gap: 8px;
  margin-top: 12px;
  position: sticky;
  /* Обычно поле висит над нижней навигацией (84px). При открытой клавиатуре
     навигация скрыта (см. .keyboard-open ниже), а поле должно стоять прямо
     над клавиатурой — --keyboard-h выставляет app.js по visualViewport
     (владелец, 2026-09-04). */
  bottom: calc(84px + env(safe-area-inset-bottom, 0px));
  transition: bottom 0.15s ease;
}

/* Клавиатура открыта: нижняя навигация уезжает совсем (иначе торчит поверх
   клавиатуры), а поле ввода с кнопкой «Отправить» поднимается ровно на её
   высоту. Владелец, 2026-09-04. */
.keyboard-open .bottom-nav,
.keyboard-open .bottom-nav-scrim {
  display: none;
}

/* Селектор намеренно с обоими классами (.comment-input-row.mention-field-wrap
   — так поле размечено в index.html): ниже по файлу лежит правило с той же
   специфичностью, которое уже один раз перебивало настройки этого поля (см.
   комментарий там же), и полагаться на порядок правил здесь не хочется. */
.keyboard-open .comment-input-row,
.keyboard-open .comment-input-row.mention-field-wrap {
  bottom: calc(var(--keyboard-h, 0px) + 12px);
}

/* Выпадающий список отметок (@ник) — общая точка привязки для подписи
   публикации и поля комментария, оба оборачивают своё поле этим классом. */
.mention-field-wrap {
  position: relative;
}

/* .comment-input-row держится над нижней навигацией через position: sticky
   (см. выше) — то же свойство "position" в .mention-field-wrap иначе
   перебивало бы его на "relative" (тот же порядок правил, та же
   специфичность класса), а смещение bottom при этом никуда не девалось бы:
   элемент оставался бы в потоке ПОСЛЕ комментариев, но визуально уезжал бы
   вверх на те же 84px+, наезжая на последние комментарии. */
.comment-input-row.mention-field-wrap {
  position: sticky;
}

.mention-suggestions {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(100% + 4px);
  z-index: 20;
  background: var(--secondary-bg);
  border-radius: 12px;
  box-shadow: 0 4px 18px rgba(0, 0, 0, 0.28);
  overflow: hidden;
  max-height: 220px;
  overflow-y: auto;
}

/* Поле комментария прижато к низу экрана (position: sticky, у самой
   клавиатуры) — список подсказок открывается вверх, а не вниз, иначе ушёл
   бы под клавиатуру. */
.comment-input-row.mention-field-wrap .mention-suggestions {
  top: auto;
  bottom: calc(100% + 4px);
}

.mention-suggestion {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  border: none;
  background: none;
  padding: 9px 12px;
  cursor: pointer;
  font-family: inherit;
  text-align: left;
}

.mention-suggestion:hover,
.mention-suggestion:active {
  background: color-mix(in srgb, var(--button) 12%, transparent);
}

.mention-suggestion-avatar {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  object-fit: cover;
  flex: none;
  background: color-mix(in srgb, var(--button) 55%, #444);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: 700;
  color: #fff;
}

.mention-suggestion-name {
  font-size: 13.5px;
  color: var(--text);
}

.comment-input-row .field-input {
  flex: 1;
}

.comment-reply-context {
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: color-mix(in srgb, var(--button) 12%, var(--secondary-bg));
  border-radius: 10px;
  padding: 8px 12px;
  margin-top: 10px;
  font-size: 12px;
  color: var(--hint);
}

.comment-reply-context button {
  border: none;
  background: none;
  color: var(--hint);
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
}

/* Комментарии — компактно, в стиле Instagram: маленький аватар, имя+текст
   одной строкой (переносится как абзац), лайк отдельной колонкой справа.
   Раньше каждый комментарий был отдельной карточкой с рамкой и занимал
   заметно больше места (2026-08-20). */
.comments-list {
  display: flex;
  flex-direction: column;
}

.comment-row {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 9px 0;
  border-bottom: 1px solid rgba(127, 127, 127, 0.1);
}

.comment-row-reply {
  margin-left: 42px;
}

.comment-avatar {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  object-fit: cover;
  flex: none;
  background: color-mix(in srgb, var(--button) 55%, #444);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: 700;
  color: #fff;
}

.comment-body {
  flex: 1;
  min-width: 0;
}

/* Имя автора отдельной строкой над текстом (владелец, 2026-08-21: "сам
   коммент должен быть под ником, иначе выглядит как обращение") — раньше имя
   и текст шли в одном потоке ("@имя текст"), из-за чего было легко прочитать
   это как адресацию кому-то, а не как подпись автора. */
.comment-text-line {
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: 13px;
  line-height: 1.45;
  word-break: break-word;
}

.comment-author-name {
  font-weight: 700;
  cursor: pointer;
}

.comment-text-body {
  word-break: break-word;
}

/* Ссылка на адресата ответа — перед текстом самого ответа, тот же приём,
   что у Instagram: "@адресат текст ответа". Отдельная строка от имени
   автора выше, чтобы не путать "кто писал" с "кому писал". */
.comment-reply-to-link {
  border: none;
  background: none;
  padding: 0;
  margin: 0;
  font: inherit;
  font-weight: 700;
  color: var(--link);
  cursor: pointer;
}

.comment-meta-row {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-top: 4px;
  color: var(--hint);
  font-size: 11px;
}

.comment-meta-row button {
  border: none;
  background: none;
  color: var(--hint);
  font-size: 11px;
  font-weight: 700;
  cursor: pointer;
  padding: 0;
  font-family: inherit;
}

/* Кнопка "Удалить" — тот же вид, что и у уведомлений (.notification-delete-
   btn, 2026-08-20: "сделать такую же"): красная пилюля поверх правого края
   строки, а не текстовая ссылка в общем ряду "Ответить"/"Изменить".
   Раскрывается долгим нажатием на строку (wireLongPressReveal в app.js),
   прячется по тапу мимо (revealedLongPressButtons). position:absolute —
   опирается на .comment-row (position:relative), а не .comment-meta-row.
   Селектор с родителем ".comment-meta-row", а не просто ".comment-delete-
   btn" — иначе проигрывает по специфичности ".comment-meta-row button"
   выше (тот же элемент + класс против одного класса) и остаётся серым,
   прозрачным, без внутренних отступов — этот баг уже чинили один раз для
   этого же класса, наступили на те же грабли при переписывании стиля. */
.comment-meta-row .comment-delete-btn {
  position: absolute;
  top: 50%;
  right: 4px;
  transform: translateY(-50%);
  z-index: 5;
  border: none;
  border-radius: 999px;
  padding: 8px 16px;
  background: var(--danger);
  color: #fff;
  font-size: 12px;
  font-weight: 700;
  cursor: pointer;
  font-family: inherit;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.35);
}

/* Тот же принцип, что у .post-like-pill выше — иконка и число раньше были
   одной кнопкой, теперь два соседа в общей колонке, число кликабельно само
   по себе (владелец, 2026-08-23: список тех, кто оценил комментарий). */
.comment-like-group {
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
}

.comment-like-toggle-btn,
.comment-like-count-btn {
  border: none;
  background: none;
  color: var(--hint);
  cursor: pointer;
  padding: 0;
  font-family: inherit;
  display: flex;
  align-items: center;
  justify-content: center;
}

.comment-like-toggle-btn svg {
  width: 13px;
  height: 13px;
}

.comment-like-toggle-btn.active {
  color: #f87171;
}

.comment-like-toggle-btn.active svg {
  fill: #f87171;
}

.comment-like-count-btn {
  font-size: 10px;
  font-weight: 700;
  min-height: 12px;
}

/* Модалка выбора (регион/город, марка, модель) — уже полноэкранного фильтра,
   с полем поиска и недавними значениями. Открывается и из формы (поверх
   обычного фона), и из шторки фильтров Ленты (.feed-filter-overlay,
   z-index 1500) — z-index выше, иначе при равных значениях эта модалка
   рисовалась под шторкой, а не поверх (баг, 2026-08-20: "окно ввода
   региона... появляется на заднем плане"). */
.picker-overlay {
  position: fixed;
  inset: 0;
  z-index: 1600;
  background: rgba(0, 0, 0, 0.55);
  display: flex;
  align-items: flex-end;
  justify-content: center;
}

.picker-modal {
  width: 100%;
  max-width: 380px;
  max-height: 72vh;
  background: var(--bg);
  border: 1px solid rgba(127, 127, 127, 0.18);
  border-radius: 18px 18px 0 0;
  padding: 14px 16px calc(16px + env(safe-area-inset-bottom, 0px));
  display: flex;
  flex-direction: column;
  gap: 10px;
}

@media (min-width: 460px) {
  .picker-overlay {
    align-items: center;
  }
  .picker-modal {
    border-radius: 18px;
    max-height: 70vh;
  }
}

.picker-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.picker-title {
  font-size: 16px;
  font-weight: 700;
}

.picker-close {
  border: none;
  background: color-mix(in srgb, var(--hint) 16%, transparent);
  color: var(--text);
  width: 28px;
  height: 28px;
  border-radius: 50%;
  font-size: 16px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}

.picker-input {
  background: var(--secondary-bg);
  border: 1px solid rgba(127, 127, 127, 0.18);
  border-radius: 12px;
  padding: 12px 14px;
  font-size: 15px;
  color: var(--text);
}

.picker-input:focus {
  outline: none;
  border-color: var(--button);
}

.picker-list {
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.picker-option {
  display: block;
  width: 100%;
  text-align: left;
  border: none;
  background: none;
  color: var(--text);
  padding: 11px 8px;
  font-size: 14px;
  border-radius: 10px;
  cursor: pointer;
  font-family: inherit;
}

.picker-option:active {
  background: var(--secondary-bg);
}

.picker-option-hint {
  color: var(--hint);
  font-size: 12px;
  margin-left: 6px;
}

.picker-section-label {
  color: var(--hint);
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 8px 8px 2px;
}

.picker-empty {
  color: var(--hint);
  font-size: 13px;
  text-align: center;
  padding: 16px 8px;
}

/* Поделиться */
.share-overlay {
  position: fixed;
  inset: 0;
  z-index: 1500;
  background: rgba(0, 0, 0, 0.55);
  display: flex;
  align-items: flex-end;
  justify-content: center;
}

@media (min-width: 460px) {
  .share-overlay {
    align-items: center;
  }
}

.share-sheet {
  width: 100%;
  max-width: 360px;
  background: var(--bg);
  border: 1px solid rgba(127, 127, 127, 0.18);
  border-radius: 18px 18px 0 0;
  padding: 14px 16px calc(16px + env(safe-area-inset-bottom, 0px));
}

@media (min-width: 460px) {
  .share-sheet {
    border-radius: 18px;
  }
}

.share-options {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-top: 8px;
}

.share-option {
  display: flex;
  align-items: center;
  gap: 12px;
  border: none;
  background: none;
  color: var(--text);
  padding: 11px 8px;
  font-size: 14px;
  font-weight: 600;
  border-radius: 10px;
  cursor: pointer;
  font-family: inherit;
}

.share-option:active {
  background: var(--secondary-bg);
}

.share-option-icon {
  flex: none;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--button) 16%, transparent);
  color: var(--button);
  display: flex;
  align-items: center;
  justify-content: center;
}

.share-option-icon svg {
  width: 18px;
  height: 18px;
}

/* Окно "дневной лимит исчерпан" — та же база, что у .share-overlay, только
   центрируется сразу (это не список опций, тянуть его к низу незачем). */
.limit-overlay {
  position: fixed;
  inset: 0;
  z-index: 1600;
  background: rgba(0, 0, 0, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
}

.limit-sheet {
  width: 100%;
  max-width: 340px;
  background: var(--bg);
  border: 1px solid rgba(127, 127, 127, 0.18);
  border-radius: 18px;
  padding: 24px 20px 20px;
  text-align: center;
}

.limit-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--danger) 16%, transparent);
  color: var(--danger);
  margin-bottom: 14px;
}

.limit-icon svg {
  width: 26px;
  height: 26px;
}

.limit-title {
  font-size: 16px;
  font-weight: 700;
  margin-bottom: 8px;
}

.limit-text {
  color: var(--hint);
  font-size: 13px;
  line-height: 1.5;
  margin-bottom: 18px;
}

/* Плавающая нижняя навигация */
/* Затемнение-скрим под плавающей панелью — эффект "экран уходит за панель",
   а не просто обрывается краем: контент, доскроленный до низа, тонет в
   градиент вместо того, чтобы упираться в панель на ровном фоне. */
.bottom-nav-scrim {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  height: calc(120px + env(safe-area-inset-bottom, 0px));
  background: linear-gradient(to bottom, transparent, color-mix(in srgb, var(--bg) 55%, black 45%) 75%);
  pointer-events: none;
  z-index: 400;
}

.bottom-nav {
  position: fixed;
  left: 50%;
  bottom: calc(14px + env(safe-area-inset-bottom, 0px));
  transform: translateX(-50%);
  display: flex;
  gap: 2px;
  background: color-mix(in srgb, var(--secondary-bg) 92%, black 4%);
  border: 1px solid rgba(127, 127, 127, 0.16);
  border-radius: 26px;
  padding: 9px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
  z-index: 500;
  max-width: calc(100vw - 24px);
}

.bottom-nav-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  border: none;
  background: none;
  color: var(--hint);
  border-radius: 20px;
  /* Уже 4 вкладки (была "Генерации", 2026-08-27) — горизонтальный отступ
     чуть меньше, чем раньше при трёх, иначе на узких экранах не помещается. */
  padding: 10px 11px;
  font-size: 10px;
  font-weight: 600;
  cursor: pointer;
  font-family: inherit;
}

.bottom-nav-btn svg {
  width: 23px;
  height: 23px;
}

/* Контур на неактивной вкладке, заливка на активной — как в Telegram. */
.bottom-nav-btn .icon-filled {
  display: none;
}

.bottom-nav-btn.active .icon-outline {
  display: none;
}

.bottom-nav-btn.active .icon-filled {
  display: block;
}

.bottom-nav-btn.active {
  background: color-mix(in srgb, var(--button) 20%, transparent);
  color: var(--button);
}

/* Лёгкая подсветка в момент нажатия на иконку — работает поверх .active */
.bottom-nav-btn.tap-glow {
  animation: nav-tap-glow 0.35s ease-out;
}

@keyframes nav-tap-glow {
  0% {
    background: color-mix(in srgb, var(--button) 38%, transparent);
  }
  100% {
    background: transparent;
  }
}

/* Карточка авто: карусель фото + шапка + характеристики по VIN */
.car-carousel {
  display: flex;
  gap: 6px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  border-radius: 14px;
  margin-bottom: 14px;
  -webkit-overflow-scrolling: touch;
}

.car-carousel img {
  flex: none;
  width: 100%;
  scroll-snap-align: start;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: 14px;
}

.car-carousel-placeholder {
  width: 100%;
  aspect-ratio: 4 / 3;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 16px;
  text-align: center;
  background: color-mix(in srgb, var(--button) 10%, var(--secondary-bg));
  color: color-mix(in srgb, var(--button) 55%, var(--hint));
}

.car-carousel-placeholder svg {
  width: 22%;
  height: 22%;
}

.car-carousel-placeholder-text {
  font-size: 13px;
  max-width: 230px;
  line-height: 1.4;
}

/* Шапка карточки авто — "Назад" вместо "Ко всем объявлениям" (тот же вид,
   что и везде в приложении), сердечко "в избранное" переехало сюда же,
   справа (владелец, 2026-08-20). У модераторов правее сердечка есть ещё
   "⋮" -> "Удалить карточку" (все осмотры по VIN разом). */
.car-card-top-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 4px;
}

/* .back-link несёт отрицательный margin, рассчитанный на то, что это
   единственный/первый элемент экрана (подтягивает его к самому верху) —
   в общей строке с сердечком/меню он из-за этого съезжал по вертикали
   относительно них (проверено структурно: разница ~10px). Сбрасываем. */
.car-card-top-row .back-link {
  margin: 0;
}

.car-card-top-actions {
  position: relative;
  display: flex;
  align-items: center;
  gap: 8px;
}

.car-card-menu-btn {
  flex: none;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: none;
  background: color-mix(in srgb, var(--secondary-bg) 80%, white 6%);
  color: var(--text);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.car-card-menu-btn svg {
  width: 19px;
  height: 19px;
}

.car-card-delete-card-btn {
  position: absolute;
  top: 46px;
  right: 0;
  z-index: 5;
  white-space: nowrap;
  border: none;
  border-radius: 999px;
  padding: 10px 18px;
  background: var(--danger);
  color: #fff;
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
  font-family: inherit;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.35);
}

.car-card-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 12px;
}

.car-card-title {
  font-size: 19px;
  font-weight: 700;
}

.car-card-vin {
  color: var(--hint);
  font-size: 13px;
  font-family: "SF Mono", "Cascadia Mono", Consolas, monospace;
  margin-top: 2px;
}

.car-card-header-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: none;
}

/* Сердечко «в избранное» переехало сюда, на карточку авто целиком (по
   VIN), с отдельных осмотров внутри неё (2026-08-20) — переиспользует вид
   .tile-favorite (тот же кружок с сердечком), но не поверх фото, а в ряд
   рядом с «Поделиться», поэтому абсолютное позиционирование сбрасываем. */
.car-card-favorite {
  position: static;
  width: 38px;
  height: 38px;
}

.car-specs {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  background: var(--secondary-bg);
  border-radius: 12px;
  padding: 12px 14px;
  margin-bottom: 6px;
}

.car-spec {
  display: flex;
  flex-direction: column;
  font-size: 13px;
}

.car-spec span:first-child {
  color: var(--hint);
  font-size: 11px;
  margin-bottom: 2px;
}

.car-spec span:last-child {
  font-weight: 600;
}

/* Карточка платного источника (apipoint.ru) — видна только модераторам,
   пока в приложении нет биллинга с конечных пользователей */
.product-card {
  background: var(--secondary-bg);
  border: 1px solid color-mix(in srgb, var(--button) 35%, transparent);
  border-radius: 14px;
  padding: 16px;
  margin-bottom: 18px;
}

.product-card-header {
  margin-bottom: 8px;
}

.product-card-badge {
  display: inline-block;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--button);
  background: color-mix(in srgb, var(--button) 16%, transparent);
  border-radius: 999px;
  padding: 3px 10px;
}

.product-card-title {
  font-size: 15px;
  font-weight: 700;
  margin-bottom: 8px;
}

.product-card-text {
  color: var(--hint);
  font-size: 13px;
  line-height: 1.5;
  margin: 0 0 14px;
}

.product-card-result {
  margin-top: 14px;
}

.product-card-image {
  display: block;
  width: 100%;
  max-height: 220px;
  object-fit: cover;
  border-radius: 12px;
  margin-bottom: 10px;
  cursor: zoom-in;
}

/* Генерация фото авто в стиле шаблона — админ-панель, 2026-08-26. Сетка
   шаблонов — тот же приём, что у .tile-grid (плитки Ленты/Избранного), но
   своя, а не общая: карточка шаблона показывает фото+название+удаление, а
   не VIN/лайки. */
.imagegen-template-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin-bottom: 18px;
}

.imagegen-template-card {
  position: relative;
  border-radius: 14px;
  overflow: hidden;
  border: 1px solid rgba(127, 127, 127, 0.14);
  background: var(--secondary-bg);
  cursor: pointer;
  text-align: left;
}

.imagegen-template-card img {
  display: block;
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
}

.imagegen-template-name {
  display: block;
  padding: 8px 10px;
  font-size: 13px;
  font-weight: 600;
}

.imagegen-template-delete {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  border: none;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Лупа поверх карточки шаблона — открывает фото на весь экран, не выбирая
   шаблон (владелец, 2026-08-30). Слева, чтобы не пересекаться с кнопками
   редактирования/удаления админа справа. */
.imagegen-template-zoom {
  position: absolute;
  top: 8px;
  left: 8px;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: none;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}

.imagegen-template-zoom svg {
  width: 15px;
  height: 15px;
}

/* Шаблон закреплён сверху в шаге "добавьте своё фото" — владелец,
   2026-08-26: "так же не убирать картинку шаблона, пусть видит её там же". */
.imagegen-chosen-template {
  display: flex;
  align-items: center;
  gap: 12px;
  background: var(--secondary-bg);
  border: 1px solid rgba(127, 127, 127, 0.14);
  border-radius: 14px;
  padding: 10px;
  margin-bottom: 16px;
}

.imagegen-chosen-template img {
  width: 64px;
  height: 64px;
  border-radius: 10px;
  object-fit: cover;
  flex: none;
  cursor: zoom-in;
}

.imagegen-chosen-template span {
  font-size: 14px;
  font-weight: 600;
}

/* Круглый пунктирный индикатор с волшебной палочкой в центре (владелец,
   2026-08-27: "перенести на середину экрана в кружочке горизонтального
   пунктира") — честного прогресса в процентах у нас нет (OpenAI его не
   отдаёт), поэтому вместо заполнения кольца — вращение всего пунктира
   целиком, как у обычного спиннера: понятно, что идёт работа, без
   притворства, что мы знаем, сколько осталось. */
.gen-loading {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
  padding: 32px 16px;
  text-align: center;
  color: var(--hint);
  font-size: 13px;
}

.gen-loading-ring {
  position: relative;
  width: 96px;
  height: 96px;
  flex: none;
}

.gen-loading-ring-svg {
  width: 100%;
  height: 100%;
  animation: gen-loading-spin 2.4s linear infinite;
}

.gen-loading-ring-svg circle {
  fill: none;
  stroke: var(--button);
  stroke-width: 5;
  stroke-linecap: round;
  stroke-dasharray: 3 11;
  opacity: 0.85;
}

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

.gen-loading-wand {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 34px;
  height: 34px;
  transform: translate(-50%, -50%);
  color: var(--button);
  animation: gen-wand-cast 1.6s ease-in-out infinite;
}

@keyframes gen-wand-cast {
  0%, 100% {
    transform: translate(-50%, -50%) rotate(-8deg) scale(1);
    opacity: 0.75;
  }
  50% {
    transform: translate(-50%, -50%) rotate(8deg) scale(1.12);
    opacity: 1;
  }
}

.imagegen-result {
  margin-top: 16px;
}

.imagegen-result img {
  display: block;
  width: 100%;
  border-radius: 14px;
  cursor: zoom-in;
}

/* Карусель "генерация - оригинал" (владелец, 2026-08-29: "исходник можно
   посмотреть, листнув вправо") — та же .car-carousel, что и у фото машины в
   Ленте/карточке, просто с двумя картинками вместо N. */
.imagegen-result .car-carousel {
  margin-bottom: 0;
}

.imagegen-swipe-hint {
  margin-top: -2px;
  margin-bottom: 12px;
  opacity: 0.75;
}

/* Скачать результат генерации — "стрелка вниз в горизонтальную скобку"
   (владелец, 2026-08-27), тот же смысл, что у стандартной иконки download. */
.gen-download-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  border: 1px solid rgba(127, 127, 127, 0.2);
  background: var(--secondary-bg);
  color: var(--text);
  border-radius: 12px;
  padding: 11px;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  font-family: inherit;
  margin-bottom: 8px;
}

.gen-download-btn svg {
  width: 19px;
  height: 19px;
  flex: none;
}

/* Скачать и Опубликовать — рядом, в одну строку (владелец, 2026-08-27:
   без нажатия "Опубликовать" в Ленту фото не уходит — раньше публикация
   была автоматической, теперь это отдельное явное действие). */
.gen-btn-row {
  display: flex;
  gap: 8px;
  margin-bottom: 8px;
}

.gen-btn-row .gen-download-btn {
  margin-bottom: 0;
}

.gen-publish-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  flex: 1;
  border: none;
  background: var(--button);
  color: var(--button-text);
  border-radius: 12px;
  padding: 11px;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  font-family: inherit;
}

.gen-publish-btn svg {
  width: 18px;
  height: 18px;
  flex: none;
}

.gen-publish-btn:disabled {
  background: var(--secondary-bg);
  color: var(--hint);
  cursor: default;
}

/* "Сгенерировано ИИ" на карточке в Ленте — не должно читаться как обычное
   фото машины (владелец, 2026-08-27: пометка обязательна при авто-публикации,
   чтобы не подрывать доверие к Ленте). Кликабельна, только если известен
   шаблон (режим "По шаблону") — см. ai_template_id в api.py. */
.feed-reel-ai-badge {
  position: absolute;
  top: 12px;
  left: 12px;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 5px;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  border: none;
  border-radius: 999px;
  padding: 6px 11px 6px 8px;
  font-size: 12px;
  font-weight: 600;
  font-family: inherit;
}

.feed-reel-ai-badge svg {
  width: 14px;
  height: 14px;
}

button.feed-reel-ai-badge {
  cursor: pointer;
}

span.feed-reel-ai-badge {
  cursor: default;
}

/* "Платные логи" — сгруппировано по категории, внутри по дате (владелец,
   2026-08-27), см. renderCharges. */
.charge-kind-group {
  margin-bottom: 26px;
}

.charge-kind-group .section-title {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
}

.charge-kind-total {
  font-size: 13px;
  font-weight: 600;
  color: var(--hint);
}

.charge-date-group {
  margin-bottom: 14px;
}

.charge-date-title {
  font-size: 12px;
  font-weight: 600;
  color: var(--hint);
  margin: 0 4px 6px;
}

.charge-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  background: var(--secondary-bg);
  border: 1px solid rgba(127, 127, 127, 0.14);
  border-radius: 10px;
  padding: 9px 12px;
  margin-bottom: 6px;
  font-size: 13px;
}

.charge-row span:first-child {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.charge-row span:last-child {
  flex: none;
  color: var(--hint);
}
