/*
 * Fenix Chat — виджет в ЛК WooCommerce.
 * Стиль под тему Blogsy / fenix-gsm.com (CSS.txt): акцент #216be9, градиент с #1a5cd8,
 * карточки, скругления 10–16px, тёмная тема через html[scheme="dark"].
 * Цвет бренда переопределяется из опции плагина: inline --fx-brand на .fenix-chat-wrap.
 */

/* ----------------------------------------------------------------------
 * Резервные значения CSS-переменных ДО первого JS-замера:
 *   --fx-site-header-h — высота шапки сайта (sticky header темы)
 *   --fx-site-bottom-h — высота нижней фикс-панели (wp-bottom-menu плагин)
 *
 * На мобильных (≤1024px плагин wp-bottom-menu показывает свою панель)
 * задаём ориентировочные 56px, чтобы чат на ПЕРВОМ ПЕЙНТЕ не уезжал
 * ПОД панель: JS-замер (watchOnlinePanelBounds + ResizeObserver)
 * позже перезапишет значение точным числом. Без этого fallback'а был
 * момент ~50–200мс перед первым замером, когда `var(--fx-site-bottom-h, 0px)`
 * падал в 0 и нижний край чата заходил за фикс-панель навигации —
 * пользователь жаловался: «часто видно, что страница уходит за эту панель».
 * Иначе как DOM-обмера узнать точную высоту панели нельзя, т.к. она
 * настраивается через Customizer темы и зависит от font-size/padding.
 * -------------------------------------------------------------------- */
:root {
	--fx-site-bottom-h: 0px;
	--fx-site-header-h: 56px;
}
@media (max-width: 1024px) {
	:root {
		--fx-site-bottom-h: 56px;
	}
}

.fenix-chat-wrap {
	/* вторичный цвет градиента кнопок — как у кнопок темы */
	--fx-brand-2: #1a5cd8;
	--fx-brand-ink: #fff;
	/* C10 — семантические surface/accent переменные для консолидации
	   повторяющихся dark-override'ов. Новые стили (F19, F20.2, тосты)
	   используют их вместо hard-coded rgba; старые оставлены без ломки
	   ради стабильности. Значения для светлой темы — прозрачные или
	   брендовые тинты; тёмная переопределяет ниже в html[scheme='dark']. */
	--fx-surface-1: rgba(33, 107, 233, 0.04);   /* тихий input/chip */
	--fx-surface-2: rgba(33, 107, 233, 0.08);   /* hover input/chip */
	--fx-surface-border: rgba(33, 107, 233, 0.18);
	--fx-brand-tint-weak: color-mix(in srgb, var(--fx-brand, #216be9) 10%, transparent);
	--fx-brand-tint-strong: color-mix(in srgb, var(--fx-brand, #216be9) 22%, transparent);
	--fx-text-contrast: #14171d;                /* тёмный на светлых пилюлях */
	--fx-bg: var(--wp--preset--color--card-bg, #ffffff);
	--fx-bg-elev: var(--wp--preset--color--card-bg, #f7f8fb);
	/* Единый цвет шапки и футера (панель композера). Задан ТЗ-цвет — чуть
	   голубоватый «бренд-тинт» 3% на белом. В тёмных темах переопределяется. */
	--fx-panel-bg: rgba(33, 107, 233, 0.03);
	/* Контраст «свои vs. чужие» на светлой теме: чуть темнее фон ленты,
	   чтобы пузыри не сливались с --fx-bg / --fx-bg-elev. */
	--fx-bg-bubble: #e4eaf3;
	--fx-bg-bubble-own: color-mix(in srgb, var(--fx-brand) 28%, #f6f9fc);
	--fx-border: var(--wp--preset--color--border-color, #e5e7eb);
	--fx-text: var(--wp--preset--color--heading, #1b2030);
	--fx-text-dim: var(--wp--preset--color--body-color, #697283);
	--fx-online: #22a06b;
	--fx-danger: #d63638;
	/* Цвет ссылок в сообщениях — фикс-бренд-синий на светлой теме.
	   Раньше брали WP-preset accent, и если в теме сайта accent
	   оказывался не синим (например, красный/зелёный из дизайна
	   магазина), ссылки в чате наследовали нечитаемый оттенок.
	   На тёмной теме переопределяется на светло-голубой (#7eb8ff)
	   ниже в html[scheme='dark']. */
	--fx-link: #216be9;
	--fx-shadow: var(--wp--preset--shadow--subtle, 0 4px 20px rgba(0, 0, 0, 0.06));
	--fx-radius: 14px;
	--fx-radius-sm: 10px;

	display: flex;
	flex-direction: column;
	position: relative;
	background: var(--fx-bg);
	color: var(--fx-text);
	border-radius: var(--fx-radius);
	border: 1px solid var(--fx-border);
	box-shadow: var(--fx-shadow);
	min-height: 500px;
	height: calc(100vh - 280px);
	max-height: 740px;
	overflow: hidden;
	font-size: 14px;
	line-height: 1.45;
	box-sizing: border-box;
}

/* Элементы с атрибутом hidden внутри виджета действительно скрыты, даже если у них есть display */
.fenix-chat-wrap [hidden] {
	display: none !important;
}

/* Fallback без color-mix (старые браузеры) */
@supports not (color: color-mix(in srgb, red 50%, blue)) {
	.fenix-chat-wrap {
		--fx-bg-bubble-own: rgba(33, 107, 233, 0.18);
	}
}

/* Тёмная тема сайта (переключатель в шапке — см. CSS.txt html[scheme="dark"]) */
html[scheme='dark'] .fenix-chat-wrap {
	--fx-bg: var(--pt-card-bg, #272c31);
	--fx-bg-elev: #2f353c;
	--fx-bg-bubble: #2b3038;
	--fx-bg-bubble-own: color-mix(in srgb, var(--fx-brand) 34%, #2b3038);
	--fx-border: hsla(0, 0%, 73%, 0.28);
	--fx-text: #e8ecf2;
	--fx-text-dim: #a8b0bc;
	--fx-link: #7eb8ff;
	--fx-shadow: none;
	/* В тёмной теме 3% alpha почти незаметно — берём чуть гуще. */
	--fx-panel-bg: rgba(33, 107, 233, 0.09);
	/* C10 — тёмные значения семантических переменных. */
	--fx-surface-1: rgba(255, 255, 255, 0.04);
	--fx-surface-2: rgba(255, 255, 255, 0.06);
	--fx-surface-border: rgba(255, 255, 255, 0.14);
	--fx-brand-tint-weak: rgba(33, 107, 233, 0.18);
	--fx-brand-tint-strong: rgba(33, 107, 233, 0.32);
	--fx-text-contrast: #e8ecf2;
}

/* Принудительная светлая палитра виджета */
body.fenix-chat-force-light .fenix-chat-wrap {
	--fx-bg: #ffffff;
	--fx-bg-elev: #f7f8fb;
	--fx-bg-bubble: #e2e8f2;
	--fx-bg-bubble-own: rgba(33, 107, 233, 0.26);
	--fx-border: #e2e6ef;
	--fx-text: #1b2030;
	--fx-text-dim: #697283;
	--fx-link: var(--fx-brand, #216be9);
}

/* Принудительная тёмная палитра виджета */
body.fenix-chat-force-dark .fenix-chat-wrap {
	--fx-bg: #1f2328;
	--fx-bg-elev: #272c31;
	--fx-bg-bubble: #262b33;
	--fx-bg-bubble-own: rgba(33, 107, 233, 0.38);
	--fx-border: #3d4654;
	--fx-text: #e8ecf2;
	--fx-text-dim: #99a3b3;
	--fx-link: #7eb8ff;
	--fx-shadow: 0 12px 40px rgba(0, 0, 0, 0.35);
	--fx-panel-bg: rgba(33, 107, 233, 0.11);
}

/* --------------------------------------------------------------------
 * Авто-тёмная тема для ГОСТЯ на публичной /chat-support/.
 * --------------------------------------------------------------------
 * У залогиненных пользователей тема берётся из cookie темы
 * сайта (html[scheme="dark"] — выставляет pt-polite/theme-switcher).
 * У гостя cookie темы часто ещё не выставлен → виджет встаёт в
 * светлой палитре, даже если у юзера ОС в dark-mode. Это заметно на
 * OLED-мобайлах: чат в белом фрейме среди тёмного сайта.
 *
 * Решение: на странице с data-guest="1" И когда на <html> НЕТ явного
 * scheme-атрибута, применяем тёмную палитру по @media prefers-color-
 * scheme:dark. Если юзер позже залогинится — cookie темы переопределит.
 * Залогиненных не трогаем, чтобы не ломать их выбор. */
@media (prefers-color-scheme: dark) {
	html:not([scheme]) body.fenix-chat-shortcode-page .fenix-chat-wrap {
		--fx-bg: #1f2328;
		--fx-bg-elev: #272c31;
		--fx-bg-bubble: #262b33;
		--fx-bg-bubble-own: rgba(33, 107, 233, 0.38);
		--fx-border: #3d4654;
		--fx-text: #e8ecf2;
		--fx-text-dim: #99a3b3;
		--fx-link: #7eb8ff;
		--fx-panel-bg: rgba(33, 107, 233, 0.11);
	}
}

/* Лента личного кабинета: чуть шире на десктопе */
body.woocommerce-account .woocommerce-MyAccount-content .fenix-chat-wrap {
	max-width: 100%;
}

/* Три колонки: TG/презенс/IG слева | статус по центру полосы | translate+search справа.
   Единые отступы: gap:10px между всеми круглыми кнопками, такой же
   как в composer-е (.fx-chat-composer gap:10px). Padding шапки 14×16
   даёт симметричный воздух вокруг линии 48-px кнопок. */
.fx-chat-header {
	position: relative;
	display: grid;
	grid-template-columns: 1fr auto 1fr;
	grid-template-rows: auto auto;
	align-items: center;
	gap: 10px 16px;
	padding: 14px 16px;
	background: var(--fx-panel-bg);
	border-bottom: 1px solid var(--fx-border);
	min-width: 0;
}
/* Нижний акцент-хайлайт — зеркальное отражение .fx-chat-composer-dock::before.
   Раньше пользователь видел «неравную толщину»: снизу у хедера был
   только плоский 1px border-bottom, а у футера сверху border-top
   подсвечен дополнительным 1px бренд-градиентом. Оба края чата
   теперь оформлены одинаково. */
.fx-chat-header::after {
	content: '';
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	height: 1px;
	background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--fx-brand) 30%, transparent), transparent);
	pointer-events: none;
	z-index: 1;
}
.fx-chat-title-wrap {
	grid-column: 1;
	grid-row: 1;
	justify-self: start;
	min-width: 0;
	display: flex;
	align-items: center;
	gap: 10px;
	overflow: visible;
}
.fx-chat-sub-meta {
	grid-column: 2;
	grid-row: 1;
}
.fx-chat-actions {
	grid-column: 3;
	grid-row: 1;
	justify-self: end;
	min-width: 0;
	display: flex;
	align-items: center;
	gap: 10px;
}
/* Строка поиска — во второй строке grid, выезжает плавно из шапки,
   визуально сдвигая ленту сообщений вниз. Поведение одинаково на
   десктопе и мобильных: по умолчанию схлопнута, раскрывается по клику
   на кнопку-лупу (см. .fx-chat-search-toggle). */
/* Поиск по чату ВЫЕЗЖАЕТ ПОВЕРХ ленты, не раздвигая шапку и не смещая
   сообщения. Раньше .fx-chat-search-wrap был строкой грида шапки
   (grid-row 2): при открытии его max-height рос → шапка становилась
   выше → лента «прыгала» вниз во время перехода (дрожание, на которое
   жаловался пользователь). Теперь — абсолютный оверлей, приклеенный к
   нижней кромке шапки (top:100%), с непрозрачным фоном и тенью; грид
   шапки его больше не учитывает, лента стоит на месте. */
.fx-chat-search-wrap {
	position: absolute;
	left: 0;
	right: 0;
	top: 100%; /* сразу под шапкой, поверх первой строки ленты */
	z-index: 45;
	box-sizing: border-box;
	margin: 0;
	padding: 0 14px;
	background: #ffffff;
	border-bottom: 1px solid var(--fx-border);
	box-shadow: 0 8px 18px rgba(0, 0, 0, 0.10);
	max-height: 0;
	opacity: 0;
	transform: translateY(-6px);
	pointer-events: none;
	/* overflow: clip вместо hidden — чтобы фокус-halo от
	   .fx-chat-search:focus (box-shadow 4px) не обрезался верхом/низом
	   враппера. overflow-clip-margin задаёт «запас» вокруг clip-региона. */
	overflow: clip;
	overflow-clip-margin: 6px;
	transition: max-height 0.24s cubic-bezier(0.2, 0.8, 0.2, 1),
		opacity 0.18s ease,
		transform 0.24s cubic-bezier(0.2, 0.8, 0.2, 1),
		padding 0.24s ease;
}
html[scheme='dark'] .fx-chat-search-wrap,
body.fenix-chat-force-dark .fx-chat-search-wrap {
	background: #1f2328;
}
@media (prefers-color-scheme: dark) {
	html:not([scheme]) .fx-chat-search-wrap { background: #1f2328; }
}
.fenix-chat-wrap.is-search-open .fx-chat-search-wrap {
	max-height: 72px;
	opacity: 1;
	transform: translateY(0);
	pointer-events: auto;
	padding: 8px 14px 10px;
}
.fx-chat-search-wrap .fx-chat-search {
	width: 100%;
	max-width: none;
	min-width: 0;
	min-height: 48px;
}

/* =========================================================
   Кнопка "i" (информация о чате) и её popover.
   Круглая кнопка 48x48,
   brand-цвет при ховере/фокусе, синяя при открытом popover.
   Popover — прямоугольник со сглаженными углами, появляется
   в правом верхнем углу чата (через --fx-panel-top), как у
   translate-popover, чтобы не перекрывать шапку.
   ========================================================= */
.fx-chat-info {
	position: relative;
	display: inline-flex;
	align-items: center;
}
.fx-chat-info-toggle {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 48px;
	height: 48px;
	padding: 0;
	background: var(--fx-bg-elev);
	color: var(--fx-text-dim);
	border: 1px solid var(--fx-border);
	border-radius: 50%;
	cursor: pointer;
	flex: none;
	box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
	-webkit-tap-highlight-color: transparent;
	touch-action: manipulation;
	font-family: inherit;
	transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease,
		transform 0.2s ease, box-shadow 0.2s ease;
}
.fx-chat-info-toggle__icon {
	width: 22px;
	height: 22px;
	display: block;
}
.fx-chat-info-toggle:hover,
.fx-chat-info-toggle:focus-visible {
	background: color-mix(in srgb, var(--fx-brand) 10%, var(--fx-bg));
	color: var(--fx-brand);
	border-color: color-mix(in srgb, var(--fx-brand) 30%, var(--fx-border));
	transform: translateY(-1px);
	box-shadow: 0 2px 6px rgba(0, 0, 0, 0.06);
	outline: none;
}
.fx-chat-info-toggle:active {
	transform: scale(0.96);
	background: color-mix(in srgb, var(--fx-brand) 16%, var(--fx-bg));
	border-color: color-mix(in srgb, var(--fx-brand) 40%, var(--fx-border));
	box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}
.fx-chat-info-toggle[aria-expanded='true'] {
	background: linear-gradient(135deg, var(--fx-brand, #216be9) 0%, var(--fx-brand-2, #1a5cd8) 100%);
	color: #fff;
	border-color: transparent;
	box-shadow: 0 4px 12px rgba(33, 107, 233, 0.35);
}
/* F24.2 — hover у «выбранного» info-toggle должен вести себя так же,
   как у всех остальных toggle-кнопок шапки: значок/окантовка получают
   бренд-акцент. Раньше правило [aria-expanded='true'] перекрывало :hover
   из-за одинаковой специфичности и более позднего положения в файле —
   пользователь видел, что «когда i нажата, ховер ничего не меняет».
   Делаем hover+expanded состояние стилистически идентичным обычному
   hover (светлый фон + цвет бренда) и оставляем лёгкий box-shadow,
   чтобы «открытый» статус всё ещё считывался. */
.fx-chat-info-toggle[aria-expanded='true']:hover,
.fx-chat-info-toggle[aria-expanded='true']:focus-visible {
	background: color-mix(in srgb, var(--fx-brand) 12%, var(--fx-bg));
	color: var(--fx-brand);
	border-color: color-mix(in srgb, var(--fx-brand) 35%, var(--fx-border));
	box-shadow: 0 2px 8px rgba(33, 107, 233, 0.18);
	transform: translateY(-1px);
	outline: none;
}
html[scheme='dark'] .fx-chat-info-toggle {
	background: var(--fx-surface-2);
	color: var(--fx-text);
	border-color: var(--fx-surface-border);
}
html[scheme='dark'] .fx-chat-info-toggle:hover,
html[scheme='dark'] .fx-chat-info-toggle:focus-visible {
	background: var(--fx-brand-tint-weak);
	color: #b8d2ff;
	border-color: rgba(33, 107, 233, 0.5);
}
html[scheme='dark'] .fx-chat-info-toggle[aria-expanded='true'] {
	color: #fff;
}
html[scheme='dark'] .fx-chat-info-toggle[aria-expanded='true']:hover,
html[scheme='dark'] .fx-chat-info-toggle[aria-expanded='true']:focus-visible {
	background: var(--fx-brand-tint-weak);
	color: #b8d2ff;
	border-color: rgba(33, 107, 233, 0.5);
}

/* Popover с саммари чата. Позиционируется относительно
   .fenix-chat-wrap (JS переносит его туда при инициализации),
   top считается от верха .fx-chat-feed через --fx-panel-top. */
/* Попап статистики чата. По просьбе пользователя ведёт себя как
   панель участников (`.fx-online-panel`) — «выезжает» боковым
   drawer'ом из правого края окна чата, ограничен сверху шапкой,
   снизу композером (использует --fx-panel-top / --fx-panel-bottom,
   которые JS держит в актуальном состоянии). Благодаря этому
   контейнер статистики НИКОГДА не выходит за границы футера даже
   на коротких экранах, а на ПК ЛК — не наезжает на соседние
   блоки темы. */
.fx-chat-info-popover {
	position: absolute;
	top: var(--fx-panel-top, 0px);
	bottom: var(--fx-panel-bottom, 0px);
	right: 0;
	/* Чуть шире на десктопе: помещаем большие цифры и текст
	   «Активны за 30 дней» без переносов, и снижаем вероятность
	   вертикального скрола (клиент просит его избегать). */
	width: var(--fx-info-panel-w, clamp(280px, 62%, 380px));
	max-width: 85%;
	z-index: 60;
	display: flex;
	flex-direction: column;
	background: var(--fx-bg-elev, #fff);
	border-left: 1px solid var(--fx-border);
	box-shadow: -12px 0 28px rgba(0, 0, 0, 0.18);
	color: var(--fx-text);
	font-size: 13px;
	box-sizing: border-box;
	opacity: 0;
	transform: translateX(102%);
	transition: transform 0.28s cubic-bezier(0.2, 0.8, 0.2, 1), opacity 0.22s ease;
	pointer-events: none;
	overflow: hidden;
	min-height: 0;
}
.fx-chat-info-popover[data-open='1'] {
	opacity: 1;
	transform: translateX(0);
	pointer-events: auto;
}
.fx-chat-info-popover[hidden] { display: none !important; }

.fx-chat-info-popover__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 10px;
	padding: 12px 14px;
	margin: 0;
	border-bottom: 1px solid var(--fx-border);
	background: color-mix(in srgb, var(--fx-brand) 6%, var(--fx-bg-elev));
	flex: 0 0 auto;
}
.fx-chat-info-popover__title {
	font-size: 13px;
	font-weight: 700;
	color: var(--fx-text);
	letter-spacing: 0.01em;
}
.fx-chat-info-popover__refresh {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 26px;
	height: 26px;
	padding: 0;
	background: transparent;
	border: 0;
	color: var(--fx-text-dim);
	border-radius: 8px;
	cursor: pointer;
	transition: background 0.15s ease, color 0.15s ease, transform 0.4s ease;
	-webkit-tap-highlight-color: transparent;
}
.fx-chat-info-popover__refresh:hover,
.fx-chat-info-popover__refresh:focus-visible {
	background: color-mix(in srgb, var(--fx-brand) 14%, transparent);
	color: var(--fx-brand);
	outline: none;
}
.fx-chat-info-popover__refresh[data-spinning='1'] {
	animation: fx-info-spin 0.9s linear infinite;
	color: var(--fx-brand);
}
@keyframes fx-info-spin {
	to { transform: rotate(360deg); }
}

.fx-chat-info-popover__body {
	display: flex;
	flex-direction: column;
	gap: 8px;
	flex: 1 1 0;
	min-height: 0;
	overflow-y: auto;
	overscroll-behavior: contain;
	padding: 10px 12px 10px;
	box-sizing: border-box;
	/* Скроллбар скрыт визуально (Firefox scrollbar-width: none +
	   WebKit ::-webkit-scrollbar), контент по-прежнему прокручивается
	   колесом мыши и касанием. Нужно, чтобы панель «Статистики»
	   не рисовала крупную серую полосу справа — она визуально
	   перекрывала цифры значений. */
	scrollbar-width: none;
	-ms-overflow-style: none;
}
.fx-chat-info-popover__body::-webkit-scrollbar {
	width: 0;
	height: 0;
	display: none;
}
.fx-chat-info-popover__loading,
.fx-chat-info-popover__error {
	padding: 14px 4px;
	text-align: center;
	color: var(--fx-text-dim);
	font-size: 13px;
}
.fx-chat-info-popover__error { color: #c0392b; }

.fx-chat-info-section {
	display: flex;
	flex-direction: column;
	gap: 1px;
	padding: 6px 10px 7px;
	background: color-mix(in srgb, var(--fx-brand) 5%, transparent);
	border: 1px solid color-mix(in srgb, var(--fx-brand) 12%, var(--fx-border));
	border-radius: 10px;
}
.fx-chat-info-section__title {
	display: flex;
	align-items: center;
	gap: 6px;
	font-size: 11px;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	color: var(--fx-brand);
	margin-bottom: 3px;
}
.fx-chat-info-row {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 10px;
	padding: 2px 0;
	font-size: 13px;
	line-height: 1.3;
}
.fx-chat-info-row__label {
	color: var(--fx-text-dim);
	flex: 1 1 auto;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
.fx-chat-info-row__value {
	color: var(--fx-text);
	font-weight: 700;
	font-variant-numeric: tabular-nums;
	flex: 0 0 auto;
	text-align: right;
}
.fx-chat-info-row__value--muted { color: var(--fx-text-dim); font-weight: 600; }

.fx-chat-info-popover__footer {
	margin-top: 2px;
	padding-top: 6px;
	border-top: 1px dashed var(--fx-border);
	text-align: center;
	font-size: 11px;
	color: var(--fx-text-dim);
}

html[scheme='dark'] .fx-chat-info-popover {
	background: var(--fx-bg-elev, #1a1e24);
	border-color: var(--fx-border, rgba(255, 255, 255, 0.12));
}
html[scheme='dark'] .fx-chat-info-section {
	background: color-mix(in srgb, var(--fx-brand) 14%, transparent);
	border-color: color-mix(in srgb, var(--fx-brand) 28%, var(--fx-border));
}
html[scheme='dark'] .fx-chat-info-popover__error {
	color: #ff8a7d;
}

/* На узких мобильных — drawer на всю ширину окна чата, как панель
   участников. Метрики читаются в полный размер, контейнер всё ещё
   ограничен top:--fx-panel-top / bottom:--fx-panel-bottom, поэтому
   не выходит за шапку и композер. */
@media (max-width: 640px) {
	.fx-chat-info-popover {
		width: 100%;
		max-width: 100%;
	}
}

/* ==================== Правила чата (drawer «i») ====================
   Контент панели правил. Сам контейнер/анимация/позиционирование
   наследуются от .fx-chat-info-popover. Здесь — только компактная
   типографика, чтобы все 4 блока поместились без вертикального
   скрола (по просьбе клиента). */
.fx-chat-rules__body {
	gap: 8px;
	padding: 10px 12px 12px;
	font-size: 12.5px;
	line-height: 1.34;
}
.fx-chat-rules__intro {
	margin: 0;
	color: var(--fx-text-dim);
	font-size: 12px;
	line-height: 1.35;
}
.fx-chat-rules-sec {
	display: flex;
	flex-direction: column;
	gap: 3px;
	padding: 7px 10px 8px;
	background: color-mix(in srgb, var(--fx-brand) 5%, transparent);
	border: 1px solid color-mix(in srgb, var(--fx-brand) 12%, var(--fx-border));
	border-radius: 10px;
}
.fx-chat-rules-sec--ban {
	background: color-mix(in srgb, #e5484d 6%, transparent);
	border-color: color-mix(in srgb, #e5484d 22%, var(--fx-border));
}
.fx-chat-rules-sec--punish {
	background: color-mix(in srgb, #d98c00 7%, transparent);
	border-color: color-mix(in srgb, #d98c00 24%, var(--fx-border));
}
.fx-chat-rules-sec__title {
	display: flex;
	align-items: center;
	gap: 6px;
	font-size: 11px;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.05em;
	color: var(--fx-brand);
}
.fx-chat-rules-sec--ban .fx-chat-rules-sec__title { color: #d83a3f; }
.fx-chat-rules-sec--punish .fx-chat-rules-sec__title { color: #b9760a; }
.fx-chat-rules-sec__ico {
	font-size: 13px;
	line-height: 1;
}
.fx-chat-rules-list {
	margin: 0;
	padding: 0;
	list-style: none;
	display: flex;
	flex-direction: column;
	gap: 2px;
}
.fx-chat-rules-list li {
	position: relative;
	padding-left: 13px;
	color: var(--fx-text);
}
.fx-chat-rules-list li::before {
	content: '';
	position: absolute;
	left: 2px;
	top: 0.62em;
	width: 4px;
	height: 4px;
	border-radius: 50%;
	background: currentColor;
	opacity: 0.45;
}
.fx-chat-rules__punish {
	margin: 0;
	color: var(--fx-text);
	font-weight: 600;
}
html[scheme='dark'] .fx-chat-rules-sec {
	background: color-mix(in srgb, var(--fx-brand) 14%, transparent);
	border-color: color-mix(in srgb, var(--fx-brand) 28%, var(--fx-border));
}
html[scheme='dark'] .fx-chat-rules-sec--ban {
	background: color-mix(in srgb, #e5484d 16%, transparent);
	border-color: color-mix(in srgb, #e5484d 34%, var(--fx-border));
}
html[scheme='dark'] .fx-chat-rules-sec--punish {
	background: color-mix(in srgb, #d98c00 16%, transparent);
	border-color: color-mix(in srgb, #d98c00 34%, var(--fx-border));
}
html[scheme='dark'] .fx-chat-rules-sec--ban .fx-chat-rules-sec__title { color: #ff8a8d; }
html[scheme='dark'] .fx-chat-rules-sec--punish .fx-chat-rules-sec__title { color: #f0b24a; }

/* Бейдж перевода: рендерится внутри `.fx-msg__meta` СЛЕВА от времени
   отправки. Визуально — компактный пилл с указанием языка-источника
   («перевод с ru»), по клику возвращает оригинальный текст. Кликабелен,
   поэтому локально переопределяем `pointer-events` родителя (.meta
   задаёт none, чтобы таймстемп не ловил клики). */
/* Круглая кнопка-лупа в единой линейке с .fx-chat-send / .fx-chat-tg-btn. */
.fx-chat-search-toggle {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 48px;
	height: 48px;
	padding: 0;
	background: var(--fx-bg-elev);
	color: var(--fx-text-dim);
	border: 1px solid var(--fx-border);
	border-radius: 50%;
	cursor: pointer;
	flex: none;
	box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
	-webkit-tap-highlight-color: transparent;
	touch-action: manipulation;
	transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease,
		transform 0.2s ease, box-shadow 0.2s ease;
}
.fx-chat-search-toggle svg {
	width: 22px;
	height: 22px;
	display: block;
}
.fx-chat-search-toggle:hover,
.fx-chat-search-toggle:focus-visible {
	background: color-mix(in srgb, var(--fx-brand) 10%, var(--fx-bg));
	color: var(--fx-brand);
	border-color: color-mix(in srgb, var(--fx-brand) 30%, var(--fx-border));
	transform: translateY(-1px);
	box-shadow: 0 2px 6px rgba(0, 0, 0, 0.06);
	outline: none;
}
.fx-chat-search-toggle:active {
	transform: scale(0.96);
	background: color-mix(in srgb, var(--fx-brand) 16%, var(--fx-bg));
	border-color: color-mix(in srgb, var(--fx-brand) 40%, var(--fx-border));
	box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}
.fx-chat-search-toggle[aria-expanded='true'] {
	background: linear-gradient(135deg, var(--fx-brand, #216be9) 0%, var(--fx-brand-2, #1a5cd8) 100%);
	color: #fff;
	border-color: transparent;
	box-shadow: 0 4px 12px rgba(33, 107, 233, 0.35);
}
html[scheme='dark'] .fx-chat-search-toggle {
	background: var(--fx-surface-2);
	color: var(--fx-text);
	border-color: var(--fx-surface-border);
}
html[scheme='dark'] .fx-chat-search-toggle:hover,
html[scheme='dark'] .fx-chat-search-toggle:focus-visible {
	background: var(--fx-brand-tint-weak);
	color: #b8d2ff;
	border-color: rgba(33, 107, 233, 0.5);
}

/* TG-кнопка — круглая иконка в единой линейке с .fx-chat-send и .fx-chat-search-toggle
   (48×48). Только значок, без текста; текст даётся title/aria-label. */
/* Кнопка «Telegram» в шапке чата — стиль единой «инструментальной» кнопки
   чата (.fx-chat-search-toggle / .fx-chat-ig-btn / .fx-chat-send): нейтральный
   фон, серая иконка, бренд-тинт на hover. Раньше была ярким градиентом —
   выпадала из визуального ряда и «перетягивала внимание». */
.fx-chat-tg-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 48px;
	height: 48px;
	padding: 0;
	font: inherit;
	line-height: 0;
	cursor: pointer;
	-webkit-appearance: none;
	appearance: none;
	border-radius: 50%;
	background: var(--fx-bg-elev);
	color: var(--fx-text-dim);
	border: 1px solid var(--fx-border);
	text-decoration: none;
	box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
	flex: none;
	transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease,
		transform 0.2s ease, box-shadow 0.2s ease;
	-webkit-tap-highlight-color: transparent;
}
.fx-chat-tg-btn:hover,
.fx-chat-tg-btn:focus-visible {
	background: color-mix(in srgb, var(--fx-brand) 10%, var(--fx-bg));
	color: var(--fx-brand);
	border-color: color-mix(in srgb, var(--fx-brand) 30%, var(--fx-border));
	transform: translateY(-1px);
	box-shadow: 0 2px 6px rgba(0, 0, 0, 0.06);
	text-decoration: none;
	outline: none;
}
.fx-chat-tg-btn:active {
	transform: scale(0.96);
}
.fx-chat-tg-btn svg {
	width: 22px;
	height: 22px;
	flex: none;
}
html[scheme='dark'] .fx-chat-tg-btn {
	background: var(--fx-surface-2);
	color: var(--fx-text);
	border-color: var(--fx-surface-border);
}
html[scheme='dark'] .fx-chat-tg-btn:hover,
html[scheme='dark'] .fx-chat-tg-btn:focus-visible {
	background: var(--fx-brand-tint-weak);
	color: #b8d2ff;
	border-color: rgba(33, 107, 233, 0.5);
}

/* Instagram-кнопка — ОБЫЧНАЯ иконка-кнопка чата (та же 48×48 круглая
   форма, что и .fx-chat-search-toggle), без специального градиента.
   При наведении перекрашивается в бренд-тинт (как лупа и другие
   инструменты чата). SVG — схематичный логотип IG. */
.fx-chat-ig-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 48px;
	height: 48px;
	padding: 0;
	background: var(--fx-bg-elev);
	color: var(--fx-text-dim);
	border: 1px solid var(--fx-border);
	border-radius: 50%;
	text-decoration: none;
	flex: none;
	box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
	transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease,
		transform 0.2s ease, box-shadow 0.2s ease;
	-webkit-tap-highlight-color: transparent;
}
.fx-chat-ig-btn svg {
	width: 22px;
	height: 22px;
	flex: none;
}
.fx-chat-ig-btn:hover,
.fx-chat-ig-btn:focus-visible {
	background: color-mix(in srgb, var(--fx-brand) 10%, var(--fx-bg));
	color: var(--fx-brand);
	border-color: color-mix(in srgb, var(--fx-brand) 30%, var(--fx-border));
	transform: translateY(-1px);
	box-shadow: 0 2px 6px rgba(0, 0, 0, 0.06);
	outline: none;
	text-decoration: none;
}
.fx-chat-ig-btn:active {
	transform: scale(0.96);
}
html[scheme='dark'] .fx-chat-ig-btn {
	background: var(--fx-surface-2);
	color: var(--fx-text);
	border-color: var(--fx-surface-border);
}
html[scheme='dark'] .fx-chat-ig-btn:hover,
html[scheme='dark'] .fx-chat-ig-btn:focus-visible {
	background: var(--fx-brand-tint-weak);
	color: #b8d2ff;
	border-color: rgba(33, 107, 233, 0.5);
}

/* .fx-chat-sub-meta — зарезервированный «подвал-мета» в шапке.
   Счётчик онлайн теперь живёт внутри .fx-chat-title-wrap (слева,
   справа от .fx-chat-tg-btn), поэтому центральная колонка шапки
   намеренно пустая — резервируем её как грид-распорку. */
.fx-chat-sub-meta {
	justify-self: center;
	min-width: 0;
	display: block;
	font-size: 0;
	line-height: 0;
}
.fx-chat-presence {
	position: relative; /* якорь для dropdown онлайн-юзеров */
	display: inline-flex;
	align-items: center;
	gap: 6px;
	line-height: 1.35;
	color: var(--fx-text-dim);
	font-size: 12px;
	font-weight: 600;
	white-space: nowrap;
}
/* Вспомогательный текст («Подключение…» / «Онлайн сейчас» и т.д.)
   по умолчанию скрываем — счётчик сам по себе информативен. */
.fx-chat-presence-text {
	display: none;
}
/* Счётчик online — компактная круглая «кнопка» в стиле ОБЫЧНЫХ кнопок
   чата (.fx-chat-tg-btn / .fx-chat-search-toggle): нейтральный фон,
   тёмный текст. Зелёной точки-индикатора больше НЕТ — пользователь
   попросил убрать мелкий зелёный маркер сверху счётчика. Вместо неё
   hover/active-анимация полностью совпадает с другими круглыми
   кнопками шапки (translateY на hover, scale на active). */
.fx-chat-presence-count {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	box-sizing: border-box;
	height: 48px;
	min-width: 48px;
	min-height: 48px;
	padding: 0 10px;
	border-radius: 999px;
	background: var(--fx-bg-elev);
	color: var(--fx-text);
	border: 1px solid var(--fx-border);
	box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
	font-weight: 700;
	font-variant-numeric: tabular-nums;
	line-height: 1;
	cursor: pointer;
	-webkit-tap-highlight-color: transparent;
	touch-action: manipulation;
	transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease,
		transform 0.2s ease, box-shadow 0.2s ease;
	flex: none;
}
.fx-chat-presence-count:hover,
.fx-chat-presence-count:focus-visible {
	background: color-mix(in srgb, var(--fx-brand) 10%, var(--fx-bg));
	color: var(--fx-brand);
	border-color: color-mix(in srgb, var(--fx-brand) 30%, var(--fx-border));
	transform: translateY(-1px);
	box-shadow: 0 2px 6px rgba(0, 0, 0, 0.06);
	outline: none;
}
.fx-chat-presence-count:active {
	transform: scale(0.96);
	background: color-mix(in srgb, var(--fx-brand) 16%, var(--fx-bg));
	border-color: color-mix(in srgb, var(--fx-brand) 40%, var(--fx-border));
	box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}
.fx-chat-presence-count__num {
	font-size: 16px;
	font-weight: 800;
	line-height: 1;
}
/* Телеграм-часть счётчика: вторая цифра (члены TG-группы) через
   разделитель-точку. Показываем только когда JS выставляет data-tg > 0. */
.fx-chat-presence-count__tg {
	font-size: 13px;
	font-weight: 700;
	line-height: 1;
	opacity: 0.75;
	display: inline-flex;
	align-items: center;
	gap: 4px;
	margin-left: 6px;
	padding-left: 8px;
	border-left: 1px solid color-mix(in srgb, var(--fx-text) 18%, transparent);
}
.fx-chat-presence-count__tg svg {
	width: 13px;
	height: 13px;
	display: block;
}
/* Лейбл «онлайн» больше не рендерится в шаблоне, но стиль оставляем
   на случай кастомных шорткодов / обратной совместимости. */
.fx-chat-presence-count__label {
	display: none;
}
html[scheme='dark'] .fx-chat-presence-count {
	background: var(--fx-surface-2);
	color: var(--fx-text);
	border-color: var(--fx-surface-border);
}
html[scheme='dark'] .fx-chat-presence-count:hover,
html[scheme='dark'] .fx-chat-presence-count:focus-visible {
	background: var(--fx-brand-tint-weak);
	color: #b8d2ff;
	border-color: rgba(33, 107, 233, 0.5);
}
html[scheme='dark'] .fx-chat-presence-count__tg {
	border-left-color: color-mix(in srgb, var(--fx-text) 25%, transparent);
}

/* Панель выделения: единая линия из трёх зон —
   [Отмена] … [счётчик по центру] … [действия справа (Все свои + Удалить)].
   Такой порядок проще «читается»: отрицательное действие слева, счётчик в центре,
   положительные разрушающие действия — справа у края, как в Telegram/macOS. */
.fx-chat-select-bar {
	display: flex;
	align-items: center;
	gap: 12px;
	padding: 12px 16px;
	border-top: 1px solid var(--fx-border);
	border-bottom: 1px solid var(--fx-border);
	background: color-mix(in srgb, var(--fx-brand) 5%, var(--fx-bg));
	flex-wrap: wrap;
}
.fx-chat-select-bar__actions {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	margin-left: auto;
}
.fx-chat-select-bar--under-header {
	border-top: none;
}
/* Панель как «уведомление» внутри виджета чата (не системный диалог браузера). */
.fx-chat-select-bar--notice {
	position: relative;
	z-index: 5;
	box-shadow: 0 6px 18px rgba(0, 0, 0, 0.08);
	animation: fx-select-bar-in 0.22s ease;
}
@keyframes fx-select-bar-in {
	from {
		opacity: 0;
		transform: translateY(-6px);
	}
	to {
		opacity: 1;
		transform: translateY(0);
	}
}
html[scheme='dark'] .fx-chat-select-bar--notice {
	box-shadow: 0 8px 22px rgba(0, 0, 0, 0.35);
}
/* Кнопка «Отмена» — бренд-стиль сайта (синий outline → заливка на hover).
   Текст всегда контрастен фону: тёмный на светлом, белый на залитом. */
/* Единая база для всех кнопок в select-bar: одинаковая высота
   (height 36px), padding, radius, вес/размер текста, плавная
   hover-анимация. Цвета (border/text/shadow) задаются в каждом
   классе отдельно — каждая кнопка держит свой семантический
   цвет (brand/green/red/gray). */
.fx-chat-select-bar__cancel,
.fx-chat-select-bar__all,
.fx-chat-select-bar__copy,
.fx-chat-select-bar__delete {
	flex: 0 0 auto;
	box-sizing: border-box;
	height: 36px;
	padding: 0 16px;
	border-radius: 10px;
	border: 1.5px solid transparent;
	background: var(--fx-bg);
	font-weight: 700;
	font-size: 14px;
	line-height: 1;
	cursor: pointer;
	font-family: inherit;
	white-space: nowrap;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
	transition: background 0.2s ease, border-color 0.2s ease,
		color 0.2s ease, box-shadow 0.2s ease, transform 0.15s ease;
}
.fx-chat-select-bar__cancel:hover,
.fx-chat-select-bar__cancel:focus-visible,
.fx-chat-select-bar__all:hover,
.fx-chat-select-bar__all:focus-visible,
.fx-chat-select-bar__copy:hover,
.fx-chat-select-bar__copy:focus-visible,
.fx-chat-select-bar__delete:hover,
.fx-chat-select-bar__delete:focus-visible {
	transform: translateY(-1px);
	outline: none;
}
.fx-chat-select-bar__cancel:active,
.fx-chat-select-bar__all:active,
.fx-chat-select-bar__copy:active,
.fx-chat-select-bar__delete:active {
	transform: translateY(0) scale(0.98);
}
.fx-chat-select-bar__cancel {
	border-color: color-mix(in srgb, var(--fx-brand, #216be9) 50%, var(--fx-border));
	color: var(--fx-brand, #216be9);
}
.fx-chat-select-bar__cancel:hover,
.fx-chat-select-bar__cancel:focus-visible {
	background: linear-gradient(135deg, var(--fx-brand, #216be9) 0%, var(--fx-brand-2, #1a5cd8) 100%);
	border-color: transparent;
	color: #fff;
	box-shadow: 0 6px 16px rgba(33, 107, 233, 0.3);
}
/* Счётчик выбранных — сразу справа от «Отмена», не по центру.
   Фиксированный margin-left: 12px, flex-item без растяжки. Справа
   actions всё так же притягиваются к правому краю через
   `margin-left: auto` в `.fx-chat-select-bar__actions`. */
.fx-chat-select-bar__count {
	flex: 0 1 auto;
	text-align: left;
	font-size: 14px;
	font-weight: 600;
	color: var(--fx-text-dim);
	white-space: nowrap;
	min-width: 0;
	margin-left: 4px;
}
/* «Удалить» — красный акцент, единая база подхватывается сверху. */
.fx-chat-select-bar__delete {
	border-color: color-mix(in srgb, #dc2626 45%, var(--fx-border));
	color: #dc2626;
}
.fx-chat-select-bar__delete:hover,
.fx-chat-select-bar__delete:focus-visible {
	background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
	border-color: transparent;
	color: #fff;
	box-shadow: 0 8px 22px rgba(220, 38, 38, 0.4);
}
.fx-chat-select-bar__delete[disabled] {
	opacity: 0.6;
	cursor: not-allowed;
	transform: none;
	box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
	background: var(--fx-bg);
	color: #dc2626;
}
html[scheme='dark'] .fx-chat-select-bar__cancel {
	background: var(--fx-surface-1);
	color: #b8d2ff;
	border-color: rgba(33, 107, 233, 0.45);
}
/* В тёмной теме дефолтный :hover у .fx-chat-select-bar__cancel
   перекрывался более специфичным правилом `html[scheme='dark'] …`.
   Дублируем hover с более высокой специфичностью, чтобы фон/тень/цвет
   действительно менялись при наведении и в тёмной теме. */
html[scheme='dark'] .fx-chat-select-bar__cancel:hover,
html[scheme='dark'] .fx-chat-select-bar__cancel:focus-visible {
	background: linear-gradient(135deg, var(--fx-brand, #216be9) 0%, var(--fx-brand-2, #1a5cd8) 100%);
	border-color: transparent;
	color: #fff;
	box-shadow: 0 8px 22px rgba(33, 107, 233, 0.55);
}
html[scheme='dark'] .fx-chat-select-bar__delete {
	background: var(--fx-surface-1);
	color: #fca5a5;
	border-color: rgba(220, 38, 38, 0.5);
}
html[scheme='dark'] .fx-chat-select-bar__delete:hover,
html[scheme='dark'] .fx-chat-select-bar__delete:focus-visible {
	background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
	border-color: transparent;
	color: #fff;
	box-shadow: 0 10px 26px rgba(220, 38, 38, 0.55);
}
html[scheme='dark'] .fx-chat-select-bar__all:hover,
html[scheme='dark'] .fx-chat-select-bar__all:focus-visible {
	background: color-mix(in srgb, #ffffff 10%, var(--fx-surface-1));
	border-color: color-mix(in srgb, #ffffff 30%, var(--fx-surface-border));
	color: #fff;
	box-shadow: 0 6px 16px rgba(0, 0, 0, 0.35);
}

/* «Выделить все» — нейтрально-серая; единая база — сверху. */
.fx-chat-select-bar__all {
	border-color: color-mix(in srgb, var(--fx-text-dim) 30%, var(--fx-border));
	color: var(--fx-text);
}
.fx-chat-select-bar__all:hover,
.fx-chat-select-bar__all:focus-visible {
	background: color-mix(in srgb, var(--fx-text) 10%, var(--fx-bg));
	border-color: color-mix(in srgb, var(--fx-text-dim) 55%, var(--fx-border));
	color: var(--fx-text);
	box-shadow: 0 6px 16px rgba(0, 0, 0, 0.12);
}
.fx-chat-select-bar__all[disabled] {
	opacity: 0.55;
	cursor: not-allowed;
	transform: none;
}
html[scheme='dark'] .fx-chat-select-bar__all {
	background: var(--fx-surface-1);
	color: var(--fx-text);
	border-color: var(--fx-surface-border);
}

/* «Скопировать» — зелёный; единая база — сверху. */
.fx-chat-select-bar__copy {
	border-color: color-mix(in srgb, #16a34a 50%, var(--fx-border));
	color: #15803d;
}
.fx-chat-select-bar__copy:hover,
.fx-chat-select-bar__copy:focus-visible {
	background: linear-gradient(135deg, #22c55e 0%, #16a34a 100%);
	border-color: transparent;
	color: #fff;
	box-shadow: 0 8px 22px rgba(22, 163, 74, 0.35);
}
.fx-chat-select-bar__copy[disabled] {
	opacity: 0.6;
	cursor: not-allowed;
	transform: none;
	box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
	background: var(--fx-bg);
	color: #15803d;
}
html[scheme='dark'] .fx-chat-select-bar__copy {
	background: var(--fx-surface-1);
	color: #86efac;
	border-color: rgba(34, 197, 94, 0.5);
}
html[scheme='dark'] .fx-chat-select-bar__copy:hover,
html[scheme='dark'] .fx-chat-select-bar__copy:focus-visible {
	background: linear-gradient(135deg, #22c55e 0%, #16a34a 100%);
	border-color: transparent;
	color: #fff;
	box-shadow: 0 10px 26px rgba(22, 163, 74, 0.5);
}

/* Общая оболочка поля сообщения и поля поиска — одни и те же фон,
   рамка, скругление, тень, hover/focus (чтобы оформление не «плыло»
   между правками). Ниже — только отличия: textarea vs search.
   ВАЖНО: все селекторы обёрнуты в `.fenix-chat-wrap`, чтобы
   специфичность была ВЫШЕ, чем у темы Blogsy, которая имеет
   правила типа `input[type=search]` (0,0,1,1) и
   `html[scheme=dark] input[type=search]:focus` (0,0,3,2). Без
   этой обёртки .fx-chat-search получал бы серую рамку и
   «ничего» при focus в тёмной теме (жалоба пользователя:
   «на светлой другое оформление, на тёмной нет синей анимации»). */
.fenix-chat-wrap .fx-chat-input,
.fenix-chat-wrap .fx-chat-search {
	background: var(--fx-bg);
	color: var(--fx-text);
	border: 2px solid var(--fx-border);
	border-radius: 14px;
	outline: none;
	font-family: inherit;
	font-size: 15px;
	font-weight: 500;
	line-height: 1.5;
	box-sizing: border-box;
	box-shadow: 0 1px 2px rgba(0, 0, 0, 0.02);
	-webkit-tap-highlight-color: transparent;
}
.fenix-chat-wrap .fx-chat-input:hover,
.fenix-chat-wrap .fx-chat-search:hover {
	border-color: color-mix(in srgb, var(--fx-brand) 45%, var(--fx-border));
}
.fenix-chat-wrap .fx-chat-input:focus,
.fenix-chat-wrap .fx-chat-search:focus {
	border-color: var(--fx-brand);
	box-shadow: 0 0 0 4px rgba(33, 107, 233, 0.15);
	background: var(--fx-bg);
}
.fenix-chat-wrap .fx-chat-input::placeholder,
.fenix-chat-wrap .fx-chat-search::placeholder {
	color: var(--fx-text-dim);
	opacity: 0.85;
}
/* Поиск: текст, плейсхолдер и каретка по центру строки.
   ВАЖНО: !important нужен потому, что тема Blogsy и нативные стили
   браузеров для input[type=search] перекрывают наше правило при focus
   (специфичность `html[scheme=dark] input[type=search]:focus` выше,
   чем `.fenix-chat-wrap .fx-chat-search`). Без !important пользователь
   видит как при вводе текст «съезжает» влево с первой буквой. */
.fenix-chat-wrap .fx-chat-search,
.fenix-chat-wrap input.fx-chat-search,
.fenix-chat-wrap input#fx-chat-search {
	text-align: center !important;
}
.fenix-chat-wrap .fx-chat-search::placeholder,
.fenix-chat-wrap input#fx-chat-search::placeholder {
	text-align: center !important;
}

/* Подсветка найденных совпадений в ленте.
   После удачного поиска (`onSearch`) совпадения текста внутри
   видимых сообщений оборачиваются в <mark class="fx-search-hit">.
   По просьбе пользователя — БЕЗ фона, только цвет/жирность букв
   (как ссылка). Так сообщение остаётся читаемым, без эффекта
   «маркером прошлись по тексту». */
.fenix-chat-wrap mark.fx-search-hit {
	background: transparent !important;
	color: var(--fx-brand);
	padding: 0;
	border-radius: 0;
	font-weight: 700;
	text-decoration: none;
}
html[scheme='dark'] .fenix-chat-wrap mark.fx-search-hit,
body.fenix-chat-force-dark .fenix-chat-wrap mark.fx-search-hit {
	background: transparent !important;
	color: color-mix(in srgb, var(--fx-brand) 70%, #fff);
}
html[scheme='dark'] .fenix-chat-wrap .fx-chat-input,
html[scheme='dark'] .fenix-chat-wrap .fx-chat-search,
body.fenix-chat-force-dark .fenix-chat-wrap .fx-chat-input,
body.fenix-chat-force-dark .fenix-chat-wrap .fx-chat-search {
	background: var(--fx-surface-1);
	border-color: var(--fx-surface-border);
	color: var(--fx-text);
}
html[scheme='dark'] .fenix-chat-wrap .fx-chat-input:hover,
html[scheme='dark'] .fenix-chat-wrap .fx-chat-search:hover,
body.fenix-chat-force-dark .fenix-chat-wrap .fx-chat-input:hover,
body.fenix-chat-force-dark .fenix-chat-wrap .fx-chat-search:hover {
	border-color: color-mix(in srgb, var(--fx-brand) 55%, var(--fx-surface-border));
}
html[scheme='dark'] .fenix-chat-wrap .fx-chat-input:focus,
html[scheme='dark'] .fenix-chat-wrap .fx-chat-search:focus,
body.fenix-chat-force-dark .fenix-chat-wrap .fx-chat-input:focus,
body.fenix-chat-force-dark .fenix-chat-wrap .fx-chat-search:focus {
	background: rgba(33, 107, 233, 0.08);
	border-color: var(--fx-brand);
	box-shadow: 0 0 0 4px rgba(33, 107, 233, 0.22);
}
/* Guest без html[scheme]: если ОС в dark-режиме — оформление
   тоже должно совпадать с композером. */
@media (prefers-color-scheme: dark) {
	html:not([scheme]) .fenix-chat-wrap .fx-chat-input,
	html:not([scheme]) .fenix-chat-wrap .fx-chat-search {
		background: var(--fx-surface-1);
		border-color: var(--fx-surface-border);
		color: var(--fx-text);
	}
	html:not([scheme]) .fenix-chat-wrap .fx-chat-input:hover,
	html:not([scheme]) .fenix-chat-wrap .fx-chat-search:hover {
		border-color: color-mix(in srgb, var(--fx-brand) 55%, var(--fx-surface-border));
	}
	html:not([scheme]) .fenix-chat-wrap .fx-chat-input:focus,
	html:not([scheme]) .fenix-chat-wrap .fx-chat-search:focus {
		background: rgba(33, 107, 233, 0.08);
		border-color: var(--fx-brand);
		box-shadow: 0 0 0 4px rgba(33, 107, 233, 0.22);
	}
}

/* Поиск: однострочное поле, в точности повторяющее .fx-chat-input по
   оформлению и анимации (padding / min-height / border / focus-halo /
   hover / transition / светлая+тёмная тема). Единственное отличие —
   плейсхолдер выровнен ПО ЦЕНТРУ (через :placeholder-shown), а когда
   пользователь начинает вводить текст — выравнивание возвращается к
   left, как в .fx-chat-input. Лупа внутри поля УБРАНА (см. display:none
   у .fx-chat-search-wrap::before). */
.fenix-chat-wrap .fx-chat-search {
	width: 100%;
	padding: 13px 16px;
	min-height: 48px;
	text-align: left;
	transition: border-color 0.2s ease, box-shadow 0.2s ease, background 0.2s ease;
	appearance: none;
	-webkit-appearance: none;
	-moz-appearance: none;
	background-image: none;
	background-repeat: no-repeat;
	position: relative;
}
.fenix-chat-wrap .fx-chat-search:placeholder-shown {
	text-align: center;
}
.fenix-chat-wrap .fx-chat-search::-webkit-search-decoration,
.fenix-chat-wrap .fx-chat-search::-webkit-search-cancel-button,
.fenix-chat-wrap .fx-chat-search::-webkit-search-results-button,
.fenix-chat-wrap .fx-chat-search::-webkit-search-results-decoration {
	appearance: none;
	-webkit-appearance: none;
	display: none;
}
/* Иконка-лупа перед полем: рисуем ::before у враппера, чтобы цвет
   её линий совпадал с текстом в обеих темах. */
/* Иконка-лупа внутри поля поиска УБРАНА. Ранее это был ::before у
   .fx-chat-search-wrap c маской SVG. Пользователь попросил, чтобы
   поисковая строка визуально не отличалась от строки ввода сообщения. */
.fx-chat-search-wrap::before {
	display: none !important;
	content: none !important;
}

/* ======================================================================
 * ЗАКРЕПЛЁННЫЕ СООБЩЕНИЯ (pinned-bar)
 * ----------------------------------------------------------------------
 * Скрепка убрана — визуальным маркером служит сам плотный бренд-фон
 * бара + накат слева (левая акцент-полоса). Содержимое растягивается
 * на всю ширину; внутри — один или несколько пинов в горизонтальной
 * ленте (overflow-x: auto) с одинаковой фоновой заливкой, без рамок.
 * На нескольких пинах между ними разделители.
 * -------------------------------------------------------------------- */
.fx-chat-pinned {
	display: block;
	padding: 0;
	background: color-mix(in srgb, var(--fx-brand) 14%, var(--fx-bg));
	border-bottom: 1px solid color-mix(in srgb, var(--fx-brand) 35%, var(--fx-border));
	position: relative;
}
html[scheme='dark'] .fx-chat-pinned {
	background: color-mix(in srgb, var(--fx-brand) 22%, var(--fx-bg));
}
.fx-chat-pinned__label {
	display: none; /* текстовая подпись больше не используется */
}
.fx-chat-pinned__icon {
	display: none; /* скрепку убрали */
}
.fx-pinned-item__nick {
	color: var(--fx-brand);
	font-weight: 700;
}
.fx-pinned-item__text {
	color: var(--fx-text);
}
/* Закреплённые: каждый пин — отдельная строка во всю ширину панели
   с превью медиа слева (как в реплаях) и текстом во весь оставшийся
   ряд + многоточие на хвосте. Несколько пинов рендерятся столбиком
   (column), у каждого — собственная полоса. До 0.9.80 здесь была
   строка с marquee-анимацией: пользователь жаловался, что бегущая
   строка плохо читается, и просил тёмное окошко превью медиа как у
   ответов на сообщения. */
.fx-chat-pinned__body {
	width: 100%;
	font-size: 13px;
	display: flex;
	flex-direction: column;
	gap: 4px;
	overflow-y: auto;
	overflow-x: hidden;
	max-height: 132px;
	scrollbar-width: thin;
	padding: 8px 16px;
	box-sizing: border-box;
}
.fx-pinned-item {
	background: transparent;
	padding: 2px 0;
	border-radius: 0;
	border: none;
	max-width: 100%;
	overflow: hidden;
	cursor: pointer;
	display: flex;
	align-items: center;
	gap: 8px;
	min-width: 0;
	width: 100%;
	transition: color 0.15s;
}
.fx-pinned-item + .fx-pinned-item {
	padding-left: 0;
	padding-top: 4px;
	border-left: none;
	border-top: 1px dashed color-mix(in srgb, var(--fx-brand) 25%, var(--fx-border));
}
.fx-pinned-item:hover .fx-pinned-item__text {
	color: var(--fx-brand);
}
/* Пока подгружаем историю до закреплённого сообщения (jumpToMessage),
   меняем курсор на progress, чтобы пользователь видел: клик не
   проигнорирован, идёт загрузка ленты вверх. Атрибут снимается в
   finally-блоке jumpToMessage сразу после прокрутки/таймаута. */
#fx-pinned-bar[data-jump-pending] { cursor: progress; }
#fx-pinned-bar[data-jump-pending] .fx-pinned-item { pointer-events: none; }
.fx-pinned-item__text {
	display: block;
	flex: 1 1 auto;
	min-width: 0;
	overflow: hidden;
	white-space: nowrap;
	text-overflow: ellipsis;
}
/* Превью медиа в пин-строке: переиспользуем компонент
   .fx-msg__reply-thumb (тот же визуал, что у цитат). Для пина чуть
   уменьшаем размер, чтобы строка осталась лаконичной. */
.fx-pinned-item--has-thumb .fx-msg__reply-thumb {
	flex: 0 0 auto;
	width: 28px;
	height: 28px;
	border-radius: 6px;
}

/* Колонка скролла: лента + «печатает…» — один скроллбар на всю высоту.
   v0.9.172: снят scroll-behavior: smooth — он анимировал КАЖДУЮ программную
   правку scrollTop (~300мс) и конкурировал с ручной прокруткой/инерцией тача
   («залипание»); плавность оставлена точечно там, где нужна
   (scrollIntoView({behavior:'smooth'}) в scrollToMessage). Добавлены
   overscroll-behavior: contain (докрутил до края → страница сайта не
   перехватывает скролл) и touch-action: pan-y (тачи между сообщениями /
   по паддингам не проходят полный gesture-арбитраж браузера). */
#fx-chat-scroll.fx-chat-scroll {
	flex: 1 1 auto;
	min-height: 0;
	overflow-y: auto;
	overflow-x: hidden;
	display: flex;
	flex-direction: column;
	scrollbar-gutter: stable;
	scroll-behavior: auto;
	overscroll-behavior: contain;
	touch-action: pan-y;
	-webkit-overflow-scrolling: touch;
}
.fx-chat-scroll__spacer {
	flex: 1 1 0;
	min-height: 0;
}
/* Лента — только поток сообщений; вертикальный скролл у родителя
   #fx-chat-scroll (см. выше). */
.fx-chat-feed {
	flex: 0 0 auto;
	overflow: visible;
	padding: 16px 14px 8px;
	display: flex;
	flex-direction: column;
	gap: 10px;
}
#fx-chat-scroll > .fx-chat-typing {
	flex: 0 0 auto;
	position: sticky;
	bottom: 0;
	z-index: 2;
	background: var(--fx-bg);
	/* Свой композит-слой: sticky репозиционируется на каждом кадре
	   прокрутки — без слоя это перерисовка пересечения с лентой. */
	will-change: transform;
}
/* Бут: первая загрузка истории. Скрываем содержимое до того, как
   JS прижмёт ленту к последнему сообщению (см. bootScrollToBottom()
   в chat.js). Используем visibility, а не display:none — тогда
   layout считается корректно и scrollHeight становится известен
   ещё до показа; scroll-behavior:auto убирает плавную анимацию,
   чтобы мгновенно прыгнуть вниз без видимого «пробега». */
.fx-chat-feed.is-booting {
	visibility: hidden;
	scroll-behavior: auto;
}
/* Скролл-контейнер сейчас — это #fx-chat-scroll (см. рефактор
   typing-indicator). На нём включен `scroll-behavior: smooth`, из-за
   которого scrollTop=scrollHeight анимируется ~300ms; за это время
   is-booting успевает сняться — пользователь видит «пробегание»
   ленты. Пока идёт бут — отключаем плавную прокрутку, чтобы прыжок
   к низу был мгновенным. */
#fx-chat-scroll.fx-chat-scroll.is-booting {
	scroll-behavior: auto;
}
/* Drag-to-select (мышью): пока пользователь тянет по ленте, CSS
   делает две вещи — отключает нативное выделение текста (иначе
   поверх чекбоксов рисуется «синяя простыня») и меняет курсор на
   «крест», чтобы режим был визуально очевиден. Активный draг
   сообщает классом .is-drag-selecting из armDragSelect в chat.js. */
.fx-chat-feed.is-drag-selecting,
.fx-chat-feed.is-drag-selecting * {
	user-select: none;
	-webkit-user-select: none;
	cursor: crosshair;
}
.fx-chat-feed__loader {
	text-align: center;
	color: var(--fx-text-dim);
	font-size: 12px;
	padding: 16px;
}
.fx-chat-feed__loader--error {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 10px;
	padding: 24px 16px;
	color: var(--fx-text);
}
.fx-chat-feed__loader-msg {
	font-size: 13px;
	font-weight: 500;
	color: var(--fx-text);
	max-width: 320px;
}
.fx-chat-feed__loader-retry {
	appearance: none;
	border: 0;
	padding: 8px 16px;
	min-height: 36px;
	border-radius: 999px;
	background: var(--fx-brand);
	color: #fff;
	font: inherit;
	font-size: 13px;
	font-weight: 600;
	cursor: pointer;
	transition: transform 0.12s ease, background 0.15s ease;
}
.fx-chat-feed__loader-retry:hover,
.fx-chat-feed__loader-retry:focus-visible {
	background: color-mix(in srgb, var(--fx-brand) 88%, #000);
	outline: none;
}
.fx-chat-feed__loader-retry:active {
	transform: scale(0.97);
}
html[scheme='dark'] .fx-chat-feed__loader--error .fx-chat-feed__loader-msg {
	color: #eef1f6;
}
.fx-chat-feed__day {
	align-self: center;
	background: var(--fx-bg-elev);
	border: 1px solid var(--fx-border);
	color: var(--fx-text-dim);
	font-size: 11px;
	font-weight: 600;
	padding: 4px 12px;
	border-radius: 999px;
	margin: 6px 0;
}
.fx-chat-feed__empty {
	flex: 1;
	display: flex;
	align-items: center;
	justify-content: center;
	text-align: center;
	padding: 28px 20px;
	color: var(--fx-text-dim);
	font-size: 14px;
	line-height: 1.5;
	max-width: 320px;
	align-self: center;
}

.fx-msg {
	display: flex;
	gap: 10px;
	max-width: 88%;
	align-self: flex-start;
	margin-right: auto;
	align-items: flex-end;
	position: relative;
}
/* Свои сообщения всегда прижаты к правому краю ленты. `margin-left:auto`
   страхует `align-self:flex-end` в случае, если родительский flex-контейнер
   когда-нибудь сменит direction, — пузырь точно останется справа.
   ВАЖНО: `.fx-msg.own` растягиваем на всю ширину ряда, чтобы попап-тулбар
   (`position:absolute; right:10px`) прижимался к правому краю окна чата,
   а не к правому краю узкого собственного бабла (иначе при узком
   сообщении — эмодзи/«ок» — тулбар визуально «свисает» левее бабла и
   выглядит как выход за пределы). Сам бабл при этом остаётся справа за
   счёт `row-reverse`, а `.fx-msg__body` ужимается по контенту ниже. */
.fx-msg.own {
	align-self: stretch;
	width: 100%;
	max-width: 100%;
	margin-left: 0;
	margin-right: 0;
	flex-direction: row-reverse;
	justify-content: flex-start; /* при row-reverse это прижимает к правому краю */
}
/* Бабл собственного сообщения ужимается по содержимому и остаётся справа.
   Верхняя граница ширины — та же 88%, что и у чужих сообщений. */
.fx-msg.own .fx-msg__body {
	flex: 0 1 auto;
	max-width: 88%;
}
/* Свои сообщения идут без аватарки и без подписи: визуальная
   принадлежность считывается за счёт правого края + бренд-фона. */
.fx-msg.own .fx-msg__avatar,
.fx-msg.own .fx-msg__name-head {
	display: none;
}
/* .fx-msg__body в обычном режиме не должен растягиваться по ширине
   у «own»-сообщений, иначе пузырь визуально «плывёт» к левому краю
   контейнера. */
.fx-msg.own .fx-msg__body {
	flex: 0 1 auto;
	display: flex;
	justify-content: flex-end;
}
.fx-msg__avatar {
	width: 34px;
	height: 34px;
	border-radius: 50%;
	background: var(--fx-bg-elev);
	overflow: hidden;
	flex: none;
	display: flex;
	align-items: center;
	justify-content: center;
	font-weight: 700;
	color: var(--fx-text);
	text-transform: uppercase;
	font-size: 13px;
	border: 1px solid var(--fx-border);
	align-self: flex-end;
}
.fx-msg__avatar img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}
/* Плейсхолдер-аватарка без загруженной картинки: компактнее обычной
   аватарки и со скромным силуэтом, чтобы не давить ленту пустыми
   серыми кругами у анонимов/не подтянувшихся Gravatar-ов. */
.fx-msg__avatar--empty {
	width: 24px;
	height: 24px;
	background: var(--fx-bg-elev);
	color: color-mix(in srgb, var(--fx-text-dim) 85%, transparent);
}
.fx-msg__avatar-ph {
	width: 70%;
	height: 70%;
	display: block;
}
html[scheme='dark'] .fx-msg__avatar--empty {
	background: var(--fx-surface-2);
	color: rgba(255, 255, 255, 0.55);
}
.fx-msg__body {
	flex: 1;
	min-width: 0;
}
/* Легаси: .fx-msg__head больше не рендерится в JS — имя и время
   теперь живут внутри самого пузыря (Telegram-style). Скрываем, если
   вдруг всплывёт из кэшированного HTML. */
.fx-msg__head {
	display: none;
}
/* «Шапка» внутри пузыря: имя автора + бейджи — только у чужих сообщений. */
.fx-msg__name-head {
	display: flex;
	align-items: center;
	gap: 8px;
	margin-bottom: 3px;
	flex-wrap: wrap;
	line-height: 1.1;
}
.fx-msg__name {
	font-weight: 700;
	color: var(--fx-brand);
	font-size: 13px;
	letter-spacing: 0.01em;
}
.fx-msg__badge {
	font-size: 10px;
	padding: 2px 7px;
	border-radius: 999px;
	background: rgba(34, 160, 107, 0.15);
	color: var(--fx-online);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.03em;
}
.fx-msg__badge--mod {
	background: rgba(246, 173, 85, 0.22);
	color: #e8952e;
}
.fx-msg__badge--admin {
	background: color-mix(in srgb, var(--fx-brand) 22%, transparent);
	color: var(--fx-brand);
}
.fx-msg__badge--tg {
	background: rgba(33, 107, 233, 0.14);
	color: var(--fx-link);
}

.fx-msg__bubble {
	position: relative;
	background: var(--fx-bg-bubble);
	border: 1px solid color-mix(in srgb, var(--fx-border) 55%, transparent);
	border-radius: 14px;
	/* Симметричные отступы — `.fx-msg__foot` (reactions + meta) живёт в
	   потоке и сам выбирает сторону: у «своих» прижимается вправо (time
	   справа, реакции слева от него), у «чужих» — reverse (time слева,
	   реакции справа от него). Раньше резервировали правое поле 60px
	   под абсолютный таймстемп; теперь это не нужно. */
	padding: 8px 14px;
	word-wrap: break-word;
	overflow-wrap: anywhere;
	box-shadow: 0 2px 6px rgba(15, 23, 42, 0.07);
	min-width: 90px;
}
.fx-msg:not(.own) .fx-msg__bubble {
	border-radius: 14px 14px 14px 0;
}
.fx-msg:not(.own) .fx-msg__bubble::before { content: none; }
.fx-msg__content {
	margin: 0;
}
.fx-msg__content > :last-child {
	margin-bottom: 0;
}
/* Цитаты (blockquote) — как в Telegram: тонкая цветная вертикальная
   полоска слева, слабая заливка, без курсива/кавычек браузера по
   умолчанию. Цитата часто встречается в пересланных сообщениях и
   разделяет блоки внутри одного пузыря. Рендерим плотнее обычного
   параграфа, чтобы список из 10 пунктов (как в инструкциях) не
   выбивался из пропорций бабла. */
.fx-msg__content blockquote,
.fx-chat-reply__text blockquote {
	margin: 4px 0;
	padding: 4px 10px 4px 10px;
	border-left: 3px solid var(--fx-accent, #2b7cff);
	border-radius: 4px;
	background: color-mix(in srgb, var(--fx-accent, #2b7cff) 10%, transparent);
	color: inherit;
	font-style: normal;
	quotes: none;
	/* Блоки внутри не должны «воздушничать» — схлопываем верх-низ
	   вложенных <p>/<strong>/<br>, чтобы цитата визуально читалась
	   единым блоком, а не башней из отступов. */
	line-height: 1.4;
}
.fx-msg__content blockquote::before,
.fx-msg__content blockquote::after,
.fx-chat-reply__text blockquote::before,
.fx-chat-reply__text blockquote::after {
	content: none;
}
.fx-msg__content blockquote > :first-child { margin-top: 0; }
.fx-msg__content blockquote > :last-child  { margin-bottom: 0; }
/* Часто Telegram-entities «дробят» одну логическую цитату на
   несколько последовательных <blockquote>, пересекаясь со
   <strong>/<br> — склеиваем их визуально, убирая зазор между
   соседними блоками. */
.fx-msg__content blockquote + blockquote {
	margin-top: -2px;
	border-top-left-radius: 0;
	border-top-right-radius: 0;
}
.fx-msg__content blockquote:has(+ blockquote) {
	margin-bottom: 0;
	border-bottom-left-radius: 0;
	border-bottom-right-radius: 0;
}
/* Сворачиваемая цитата (expandable_blockquote из TG). По умолчанию свёрнута
   (~5 строк) с «развернуть»; клик по цитате разворачивает/сворачивает
   (делегированный хэндлер). is-short (влезает целиком) отключает свёртку. */
.fx-msg__content blockquote.tg-expandable {
	position: relative;
	max-height: 5.6em;
	overflow: hidden;
	cursor: pointer;
	transition: max-height 0.22s ease;
}
.fx-msg__content blockquote.tg-expandable.is-expanded { max-height: 1600px; }
.fx-msg__content blockquote.tg-expandable.is-short { max-height: none; cursor: auto; }
.fx-msg__content blockquote.tg-expandable:not(.is-expanded):not(.is-short) {
	padding-bottom: 1.7em;
}
.fx-msg__content blockquote.tg-expandable:not(.is-expanded):not(.is-short)::after {
	content: "⌄ развернуть";
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	padding: 0.9em 8px 0.25em;
	text-align: center;
	font-size: 12px;
	font-weight: 600;
	color: var(--fx-accent, #2b7cff);
	background: linear-gradient(to bottom, transparent, var(--fx-bg-bubble, #e4eaf3) 70%);
	pointer-events: none;
}
.fx-msg__content blockquote.tg-expandable.is-expanded::after { content: none; }
/* Тёмная тема — делаем заливку чуть плотнее и убираем слишком
   яркий синий бордер (на тёмном фоне читается лучше мягкий). */
html[scheme="dark"] .fx-msg__content blockquote,
html[scheme="dark"] .fx-chat-reply__text blockquote {
	background: color-mix(in srgb, var(--fx-accent, #4a9bff) 18%, transparent);
	border-left-color: color-mix(in srgb, var(--fx-accent, #4a9bff) 75%, white);
}
/* Подпись (caption) под вложениями: отделяем 6px сверху от
   последней превьюшки, но не даём слипаться с нижней мета-строкой
   (там уже есть свой padding). Сам контент не трогает max-width
   пузыря — пусть оборачивается в естественной ширине. */
.fx-msg__content--caption {
	margin-top: 6px;
	padding-top: 0;
}

/* ----------------------------------------------------------------------
 * Link preview (OG-карточка)
 * По требованию пользователя превью отключены — скрываем любые карточки,
 * которые могли остаться в DOM (старые сообщения, fallback-узлы, и т.п.).
 * Сами стили ниже сохранены — это даёт быстрый откат: достаточно убрать
 * этот display:none и заново включить applyLinkPreview() в chat.js.
 * -------------------------------------------------------------------- */
.fenix-chat-wrap .fx-msg__link-preview,
.fenix-chat-wrap .fx-msg__link-preview--loading,
.fenix-chat-wrap .fx-msg__link-preview--bare,
.fenix-chat-wrap .fx-msg__link-preview--has-img,
.fenix-chat-wrap .fx-msg__link-preview--noimg {
	display: none !important;
}

.fx-msg__link-preview {
	display: grid;
	grid-template-columns: 86px 1fr;
	grid-template-areas: "img body";
	column-gap: 10px;
	align-items: stretch;
	margin-top: 6px;
	padding: 8px 10px 8px 12px;
	border-left: 3px solid var(--fx-link, #216be9);
	background: color-mix(in srgb, var(--fx-link, #216be9) 8%, var(--fx-bubble, transparent));
	border-radius: 8px;
	color: inherit;
	text-decoration: none !important;
	max-width: min(420px, 100%);
	overflow: hidden;
	box-sizing: border-box;
	transition: background 0.15s ease;
}
.fx-msg__link-preview:hover {
	background: color-mix(in srgb, var(--fx-link, #216be9) 14%, var(--fx-bubble, transparent));
}
.fx-msg__link-preview--loading {
	opacity: 0.85;
}
.fx-msg__link-preview--noimg,
.fx-msg__link-preview--bare {
	grid-template-columns: 1fr;
	grid-template-areas: "body";
}
.fx-msg__link-preview__img {
	grid-area: img;
	width: 86px;
	height: 86px;
	object-fit: cover;
	border-radius: 6px;
	background: color-mix(in srgb, currentColor 8%, transparent);
	display: block;
}
.fx-msg__link-preview__body {
	grid-area: body;
	min-width: 0;
	display: flex;
	flex-direction: column;
	gap: 2px;
	justify-content: center;
}
.fx-msg__link-preview__site {
	font-size: 11px;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.02em;
	color: var(--fx-link, #216be9);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
	opacity: 0.9;
}
.fx-msg__link-preview__title {
	font-size: 13px;
	font-weight: 600;
	line-height: 1.3;
	color: var(--fx-text, currentColor);
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
	word-break: break-word;
}
.fx-msg__link-preview__desc {
	font-size: 12px;
	line-height: 1.35;
	color: color-mix(in srgb, var(--fx-text, currentColor) 80%, transparent);
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
	word-break: break-word;
}
/* Внутри собственных пузырей (иначе brand-фон+brand-кант сливались бы
   в одну заливку) делаем фон чуть светлее, кант — белёсым. */
.fx-msg.own .fx-msg__link-preview {
	background: color-mix(in srgb, #ffffff 14%, transparent);
	border-left-color: color-mix(in srgb, #ffffff 60%, transparent);
}
.fx-msg.own .fx-msg__link-preview:hover {
	background: color-mix(in srgb, #ffffff 22%, transparent);
}
.fx-msg.own .fx-msg__link-preview__site,
.fx-msg.own .fx-msg__link-preview__title,
.fx-msg.own .fx-msg__link-preview__desc {
	color: var(--fx-own-text, #fff);
}
@media (max-width: 480px) {
	.fx-msg__link-preview {
		grid-template-columns: 64px 1fr;
		column-gap: 8px;
		padding: 6px 8px 6px 10px;
	}
	.fx-msg__link-preview__img {
		width: 64px;
		height: 64px;
	}
}
/* Attachments-only bubble (фото/видео/голос без подписи): убираем
   «воздух» вокруг картинки. Bubble всё ещё держит место под мету
   (таймстемп в нижнем-правом углу), но сверху и слева от вложения
   лишнего padding'а нет — картинка едет почти до краёв пузыря,
   как это принято в Telegram/WhatsApp/iMessage. */
.fx-msg__bubble.fx-msg__bubble--atts-only {
	padding: 4px 4px 4px 4px;
	min-width: 0;
	overflow: hidden;
	/* Пузырь с вложениями ужимается под контент, а не растягивается
	   на всю ширину .fx-msg__body. Раньше при загрузке файла справа
	   от карточки оставался «воздух» до правого края бабла; теперь
	   бабл строго повторяет размер карточки вложения. */
	width: fit-content;
	max-width: min(360px, 100%);
}
/* Для нескольких картинок/видео/документов в одном сообщении даём
   больше горизонтали (чтобы 2×2 — стандартная сетка мессенджеров —
   помещалась без переноса). has(>…:not(:only-child)) = «более одного
   вложения», работает в Safari 15.4+/Chrome 105+/Firefox 121+.
   Ниже mobile-фоллбэк (без :has) ограничит по %. */
.fx-msg__bubble.fx-msg__bubble--atts-only:has(.fx-atts > .fx-att:nth-child(2)) {
	max-width: min(460px, 100%);
}
/* С подписью (caption) пузырь НЕ атач-only, ширину теперь задаём
   через fit-content + такой же max — иначе пузырь раздувается на
   весь .fx-msg__body шириной. */
.fx-msg__bubble:has(.fx-atts > .fx-att:nth-child(2)):not(.fx-msg__bubble--atts-only) {
	width: fit-content;
	max-width: min(460px, 100%);
}
.fx-msg__bubble:has(.fx-atts > .fx-att:only-child):not(.fx-msg__bubble--atts-only) {
	width: fit-content;
	max-width: min(360px, 100%);
}
.fx-msg__bubble.fx-msg__bubble--atts-only .fx-atts {
	margin: 0;
}
/* Стикер — в TG всегда один на сообщение, без фонового «пузыря».
   Сжимаем бабл до ширины стикера и убираем заливку/рамку/тень,
   чтобы рядом с ним не оставалась пустая «вторая колонка».
   overflow:hidden СНИМАЕМ — у baseline'ного `--atts-only` он стоит, чтобы
   картинка не вылезала за скруглённые углы пузыря; но у стикера пузырь
   прозрачный и без рамки, а ник автора пишется сверху. Пользователь
   жаловался: «при отправке стикеров ник закругляется как углы стикера» —
   это как раз overflow:hidden + border-radius обрезали крайние буквы ника
   по радиусу. Плюс даём паддинг 0 4px, чтобы ник и сам стикер не
   прилипали к левому краю бабла (и визуально не наезжали на
   скруглённый угол соседнего .fx-att). */
.fx-msg__bubble.fx-msg__bubble--atts-only:has(.fx-atts > .fx-att:only-child.fx-att--sticker) {
	width: fit-content !important;
	max-width: 100% !important;
	min-width: 0 !important;
	background: transparent !important;
	border: 0 !important;
	padding: 0 4px !important;
	box-shadow: none !important;
	overflow: visible !important;
	border-radius: 0 !important;
}
.fx-msg__bubble.fx-msg__bubble--atts-only:has(.fx-atts > .fx-att:only-child.fx-att--sticker) .fx-atts {
	width: fit-content;
	max-width: 100%;
	grid-template-columns: max-content !important;
}
/* Ник внутри стикер-бабла: слегка отодвигаем от края, чтобы длинное имя
   не обрезалось скруглённым углом стикера и не «уходило» за его левую
   границу. Даём немного воздуха снизу, чтобы буквы не прижимались к
   самому стикеру, и переносим длинное имя (а не скролл-ellipsis,
   как в общем правиле). */
.fx-msg__bubble.fx-msg__bubble--atts-only:has(.fx-atts > .fx-att:only-child.fx-att--sticker)
	.fx-msg__name-head {
	padding: 2px 4px 4px;
	margin-bottom: 2px;
	max-width: calc(100vw - 80px);
	white-space: normal;
	overflow: visible;
}
/* Для документов / аудио / голосовых фиксируем «ширину сообщения» —
   бабл становится удобной карточкой, не прилипающей к краям ленты.
   min-width не даёт превратиться в узкий столбик при коротких именах,
   max-width держит общий ритм ленты. */
.fx-msg__bubble.fx-msg__bubble--atts-only:has(.fx-att--doc) {
	width: min(320px, 100%);
	max-width: min(320px, 100%);
}
/* Audio / voice — шире, чтобы waveform-дорожка читалась (а не была
   «одной точкой посередине», как писал пользователь). На мобильном
   даём максимум доступной ширины пузыря. */
.fx-msg__bubble.fx-msg__bubble--atts-only:has(.fx-att--audio),
.fx-msg__bubble.fx-msg__bubble--atts-only:has(.fx-att--voice) {
	width: min(400px, 100%);
	max-width: min(400px, 100%);
}
@media (max-width: 640px) {
	.fx-msg__bubble.fx-msg__bubble--atts-only:has(.fx-att--audio),
	.fx-msg__bubble.fx-msg__bubble--atts-only:has(.fx-att--voice) {
		width: 100%;
		max-width: 100%;
	}
}
/* Время/реакции/галочки у сообщений с вложениями — ВСЕГДА в потоке
   ПОД контентом (как у текстовых), а не полупрозрачной пилюлей поверх
   картинки/видео. Так таймстамп не перекрывает контент, стоит в одной
   позиции, и не конфликтует с контролами видео. */
.fx-msg__bubble.fx-msg__bubble--atts-only .fx-msg__foot {
	position: static;
	background: transparent;
	backdrop-filter: none;
	-webkit-backdrop-filter: none;
	color: inherit;
	padding: 4px 8px 2px;
}
.fx-msg__bubble.fx-msg__bubble--atts-only .fx-msg__meta,
.fx-msg__bubble.fx-msg__bubble--atts-only .fx-msg__meta .fx-msg__time,
.fx-msg__bubble.fx-msg__bubble--atts-only .fx-msg__meta .fx-msg__check {
	color: var(--fx-text-dim);
}
.fx-msg__bubble.fx-msg__bubble--atts-only .fx-msg__check svg path {
	stroke: var(--fx-text-dim);
}

/* Футер пузыря: одна flex-строка с реакциями + meta. Telegram-style
   (по просьбе пользователя): реакции ВСЕГДА в левом нижнем углу
   пузыря, а meta (время / бейдж перевода / галочки прочтения) —
   в правом, независимо от того, своё это сообщение или чужое.
   Реализация: DOM-порядок [reactions, meta], meta пушится вправо
   через margin-left:auto (без зависимости от кол-ва реакций).
   flex-wrap остаётся — если эмодзи-чипов много, они просто
   оборачиваются в несколько строк, каждая — тоже слева. */
.fx-msg__foot {
	margin-top: 4px;
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	row-gap: 4px;
	column-gap: 8px;
	min-height: 18px;
	flex-direction: row;
	justify-content: flex-start;
}
.fx-msg__foot .fx-reactions {
	margin: 0;
	display: inline-flex;
	flex-wrap: wrap;
	gap: 4px;
	align-items: center;
	min-height: 18px;
}
/* Реакции в footer-строке должны визуально сидеть на одной линии со
   временем/галочками. Делаем чипы чуть компактнее и одной высоты с
   meta-блоком, чтобы не выбивались вверх. */
.fx-msg__foot .fx-reaction {
	padding: 1px 7px;
	font-size: 11px;
	line-height: 14px;
	min-height: 18px;
}
.fx-msg__foot .fx-reaction__emoji {
	font-size: 12px;
	line-height: 1;
}
/* Meta прижата к правому краю — при пустых реакциях «висит» одна
   справа, при заполненном ряду реакции уезжают влево, meta остаётся
   справа (классика Telegram). */
.fx-msg__foot .fx-msg__meta {
	margin-left: auto;
}

/* Мета (время) — мелкая, приглушённая, выровнена по baseline в футере. */
.fx-msg__meta {
	display: inline-flex;
	align-items: center;
	gap: 5px;
	font-size: 11px;
	line-height: 1;
	min-height: 18px;
	color: var(--fx-text-dim);
	white-space: nowrap;
	pointer-events: none;
	user-select: none;
}
.fx-msg__time {
	font-variant-numeric: tabular-nums;
}
/* Бейдж «изменено» — мелкий текст СЛЕВА от времени в footer-строке
   сообщения. Показывается, если сервер прислал `edited_at` (правки
   в web-чате или синк правки из TG-группы через bot-bridge). */
.fx-msg__edited {
	font-size: 10px;
	line-height: 1;
	opacity: 0.85;
	letter-spacing: 0.01em;
}
.fx-msg.own .fx-msg__meta {
	color: color-mix(in srgb, var(--fx-brand) 55%, var(--fx-text-dim));
}

/* =========================================================================
   F20 — read-receipts: галочки «отправлено / прочитано» в правом углу
   своих пузырей. Одна палочка — сообщение дошло до сервера, но никто
   ещё не открыл (в групповом чате — никто кроме автора). Двойная — >=1
   получатель отметил прочитанным (сработал IntersectionObserver).
   Стиль близок к Telegram: серая/пастельная одинарная, бренд-цвет для
   двойной, опционально число читателей рядом (для группового контекста).
   svg рисуем в currentColor, чтобы тёмная тема наследовала контраст.
   ========================================================================= */
.fx-msg__check {
	display: inline-flex;
	align-items: center;
	gap: 3px;
	margin-left: 2px;
	color: color-mix(in srgb, var(--fx-text-dim) 80%, transparent);
	transition: color 160ms ease-out;
	pointer-events: auto;
}
.fx-msg__check svg {
	width: 14px;
	height: 12px;
	fill: none;
	stroke: currentColor;
	stroke-width: 1.8;
	stroke-linecap: round;
	stroke-linejoin: round;
	display: block;
}
.fx-msg__check--read {
	color: color-mix(in srgb, var(--fx-brand) 80%, #2aa76a);
}
.fx-msg__check-num {
	font-size: 10.5px;
	font-weight: 600;
	line-height: 1;
	font-variant-numeric: tabular-nums;
	color: inherit;
}
html[scheme='dark'] .fx-msg__check {
	color: rgba(235, 240, 250, 0.55);
}
html[scheme='dark'] .fx-msg__check--read {
	color: color-mix(in srgb, var(--fx-brand) 75%, #5cd299);
}
/* Галочка с классом --read — интерактивная: по клику открывается
   popover со списком читателей. Курсор pointer + лёгкая подсветка
   на hover, чтобы давать visual-hint «на меня можно нажать». */
.fx-msg__check--read {
	cursor: pointer;
	padding: 1px 2px;
	border-radius: 4px;
	transition: background-color 160ms ease-out, color 160ms ease-out;
}
.fx-msg__check--read:hover {
	background-color: color-mix(in srgb, currentColor 18%, transparent);
}
/* F26 — read-индикатор на ЧУЖИХ сообщениях: делаем слегка бледнее, чтобы не
   отвлекать от содержимого (как «второстепенная метрика»), но сохраняем
   интерактивность и одинаковый размер с own-индикатором. Кликабельность и
   popover-логика — те же, что и у автора. */
.fx-msg__check--read.fx-msg__check--other {
	color: color-mix(in srgb, var(--fx-text-dim) 75%, transparent);
	opacity: 0.85;
}
.fx-msg__check--read.fx-msg__check--other:hover {
	opacity: 1;
}
html[scheme='dark'] .fx-msg__check--read.fx-msg__check--other {
	color: rgba(235, 240, 250, 0.55);
}

/* =========================================================================
   F20.1 — popover «кто прочитал».
   Один singleton-узел на страницу; position: fixed от viewport'а, потому
   что галочки находятся внутри absolute'но-позиционированного meta, и
   хранить popover локально ломало бы overflow-clip ленты. Позиционирование
   вычисляется в JS. Ширина ограничена 280px — длинные имена усекаем
   через ellipsis, полное имя показывается по title.
   ========================================================================= */
.fx-readers-popover {
	position: fixed;
	z-index: 10010;
	min-width: 220px;
	max-width: 300px;
	max-height: 360px;
	overflow-y: auto;
	/* Унифицируем фон / рамку / тень / радиус со всем семейством
	   контекст-меню чата (.fx-input-ctx / .fx-msg__tools /
	   .fx-react-picker). Раньше тут был var(--fx-bg-surface) и тень
	   послабее — попап выглядел «другой плашкой», пользователь
	   попросил привести всё к единому виду. */
	background: var(--fx-bg, #fff);
	color: var(--fx-text, #14171d);
	border: 1px solid var(--fx-border, rgba(0, 0, 0, 0.12));
	border-radius: 12px;
	box-shadow: 0 14px 40px rgba(0, 0, 0, 0.18), 0 2px 6px rgba(0, 0, 0, 0.08);
	font: 14px/1.3 system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
	padding: 6px;
	animation: fx-readers-pop-in 140ms ease-out;
}
@keyframes fx-readers-pop-in {
	from { opacity: 0; transform: translateY(-4px) scale(0.985); }
	to   { opacity: 1; transform: translateY(0) scale(1); }
}
.fx-readers-popover[data-place="bottom"] {
	animation-name: fx-readers-pop-in-down;
}
@keyframes fx-readers-pop-in-down {
	from { opacity: 0; transform: translateY(4px) scale(0.985); }
	to   { opacity: 1; transform: translateY(0) scale(1); }
}
.fx-readers-popover__head {
	display: flex;
	align-items: center;
	gap: 6px;
	padding: 4px 10px 6px;
	font-size: 11px;
	font-weight: 600;
	letter-spacing: 0.03em;
	text-transform: uppercase;
	color: var(--fx-text-dim, #5a6270);
	border-bottom: 1px solid var(--fx-border, rgba(20, 23, 29, 0.08));
	margin-bottom: 2px;
}
.fx-readers-popover__count {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 18px;
	height: 16px;
	padding: 0 5px;
	font-size: 10.5px;
	font-weight: 700;
	color: #fff;
	background: color-mix(in srgb, var(--fx-brand) 80%, #2aa76a);
	border-radius: 9px;
	text-transform: none;
	letter-spacing: 0;
}
/* Список прочитавших / реакторов — показываем до 5 строк,
   дальше внутренний скролл. Row — 32px min-height + 2x padding,
   пять строк ≈ 5 * 42 = 210px. Ограничиваем явно и прячем
   системный скроллбар (Firefox scrollbar-width: none + WebKit
   ::-webkit-scrollbar), оставляя прокрутку колесом/touch. */
.fx-readers-popover__list {
	padding: 2px 0 4px;
	max-height: 214px;
	overflow-y: auto;
	overscroll-behavior: contain;
	scrollbar-width: none;
	-ms-overflow-style: none;
}
.fx-readers-popover__list::-webkit-scrollbar {
	width: 0;
	height: 0;
	display: none;
}
.fx-readers-popover__more {
	display: block;
	width: calc(100% - 16px);
	margin: 4px 8px 8px;
	padding: 7px 10px;
	font-size: 12px;
	font-weight: 600;
	color: var(--fx-brand);
	background: color-mix(in srgb, var(--fx-brand) 10%, transparent);
	border: 1px solid color-mix(in srgb, var(--fx-brand) 25%, transparent);
	border-radius: 8px;
	cursor: pointer;
	transition: background 0.15s ease, border-color 0.15s ease;
}
.fx-readers-popover__more:hover:not(:disabled) {
	background: color-mix(in srgb, var(--fx-brand) 18%, transparent);
	border-color: color-mix(in srgb, var(--fx-brand) 40%, transparent);
}
.fx-readers-popover__more:disabled {
	opacity: 0.6;
	cursor: default;
}
.fx-readers-popover__row {
	display: flex;
	align-items: flex-start;
	gap: 8px;
	padding: 5px 10px;
	border-radius: 6px;
	min-height: 32px;
}
/* Кликабельная строка (ведёт в DM с участником). data-uid проставляется
   JS только для строк, у которых есть WP-аккаунт и это не сам пользователь. */
.fx-readers-popover__row[data-uid] {
	cursor: pointer;
	transition: background 0.12s ease;
}
.fx-readers-popover__row[data-uid]:hover,
.fx-readers-popover__row[data-uid]:focus-visible {
	background: color-mix(in srgb, var(--fx-brand, #216be9) 12%, transparent);
	color: var(--fx-brand, #216be9);
	outline: none;
}
.fx-readers-popover__mid {
	flex: 1 1 auto;
	min-width: 0;
	display: flex;
	flex-direction: column;
	gap: 2px;
}
.fx-readers-popover__nameline {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	/* gap:6px создавал визуальный «разрыв» между ником и бейджем роли
	   (admin / mod) — пользователь просил, чтобы ярлык стоял вплотную
	   к нику. Уменьшаем до 4px; между бейджем и эмодзи реакции
	   достаточно margin-left ниже. */
	gap: 4px;
	min-width: 0;
}
/* Ник → бейдж «ADMIN/mod» стоят максимально плотно (без лишнего
   воздуха слева), эмодзи реакции при этом отделяется чуть большим
   промежутком — чтобы не сливаться с ярлыком. */
.fx-readers-popover__nameline .fx-readers-popover__name + .fx-readers-popover__badge {
	margin-left: 2px;
}
.fx-readers-popover__nameline .fx-readers-popover__badge + .fx-readers-popover__emoji {
	margin-left: 4px;
}
.fx-readers-popover__row + .fx-readers-popover__row {
	margin-top: 1px;
}
/* Стрелка-хинт «→ написать» в правом углу кликабельной строки
   реактора. Серая по умолчанию, brand-цветом при hover всей строки. */
.fx-readers-popover__dm-hint {
	flex: 0 0 auto;
	align-self: center;
	margin-left: 8px;
	font-size: 14px;
	line-height: 1;
	color: var(--fx-text-dim);
	opacity: 0.55;
	transition: color 0.12s ease, opacity 0.12s ease, transform 0.12s ease;
}
.fx-readers-popover__row[data-uid]:hover .fx-readers-popover__dm-hint,
.fx-readers-popover__row[data-uid]:focus-visible .fx-readers-popover__dm-hint,
.fx-readers-popover__row[data-tg]:hover .fx-readers-popover__dm-hint,
.fx-readers-popover__row[data-tg]:focus-visible .fx-readers-popover__dm-hint {
	color: var(--fx-brand);
	opacity: 1;
	transform: translateX(2px);
}
/* TG-иконка «✈» чуть больше и синего TG-цвета — чтобы визуально
   отличать «написать в сайт-DM» (➤) от «открыть Telegram» (✈). */
.fx-readers-popover__dm-hint--tg {
	color: #2aabee;
	font-size: 15px;
	opacity: 0.75;
}
.fx-readers-popover__row[data-tg]:hover .fx-readers-popover__dm-hint--tg,
.fx-readers-popover__row[data-tg]:focus-visible .fx-readers-popover__dm-hint--tg {
	color: #2aabee;
	opacity: 1;
}
/* Курсор-палец на любой кликабельной строке (WP или TG). */
.fx-readers-popover__row[data-uid],
.fx-readers-popover__row[data-tg] {
	cursor: pointer;
}
.fx-readers-popover__ava {
	flex: 0 0 auto;
	width: 24px;
	height: 24px;
	border-radius: 50%;
	object-fit: cover;
	background: color-mix(in srgb, var(--fx-brand) 20%, transparent);
	display: inline-flex;
	align-items: center;
	justify-content: center;
	font-size: 11px;
	font-weight: 700;
	color: var(--fx-brand, #2aa76a);
}
.fx-readers-popover__name {
	/* flex-grow:0 — имя НЕ растягивается на всю строку, иначе у короткого
	   ника (напр. «Oladushka») бокс заполнял всю ширину и выталкивал
	   эмодзи реакции к правому краю. Теперь имя = ширине текста, эмодзи
	   стоит сразу за ним. Длинные имена всё равно усекаются (flex-shrink:1
	   + min-width:0 + ellipsis). */
	flex: 0 1 auto;
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	font-weight: 500;
}
.fx-readers-popover__badge {
	flex: 0 0 auto;
	font-size: 9.5px;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.04em;
	padding: 1px 5px;
	border-radius: 4px;
	background: color-mix(in srgb, var(--fx-brand) 14%, transparent);
	color: var(--fx-brand, #2aa76a);
}
.fx-readers-popover__badge--admin {
	background: color-mix(in srgb, #e54b4b 18%, transparent);
	color: #c43434;
}
/* F26 — в popover'е «Поставили реакцию» выводим emoji прямо в nameline,
   рядом с ником. Размер подобран так, чтобы не выбивать baseline
   и не рвать перенос при длинном имени. */
.fx-readers-popover__emoji {
	flex: 0 0 auto;
	font-size: 14px;
	line-height: 1;
	margin-left: 2px;
	filter: saturate(1.05);
}
.fx-readers-popover__time {
	font-size: 11px;
	color: var(--fx-text-dim, #5a6270);
	font-variant-numeric: tabular-nums;
	line-height: 1.2;
	align-self: flex-start;
	max-width: 100%;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
.fx-readers-popover__empty,
.fx-readers-popover__loader {
	padding: 12px 14px;
	color: var(--fx-text-dim, #5a6270);
	text-align: center;
	font-size: 12px;
}
html[scheme='dark'] .fx-readers-popover,
body.fenix-chat-force-dark .fx-readers-popover {
	background: #1f232b;
	color: #e6ecf5;
	border-color: rgba(255, 255, 255, 0.12);
	box-shadow: 0 14px 40px rgba(0, 0, 0, 0.6), 0 2px 6px rgba(0, 0, 0, 0.3);
}
html[scheme='dark'] .fx-readers-popover__head {
	color: rgba(230, 235, 245, 0.55);
	border-bottom-color: var(--fx-surface-2);
}
html[scheme='dark'] .fx-readers-popover__time,
html[scheme='dark'] .fx-readers-popover__empty,
html[scheme='dark'] .fx-readers-popover__loader {
	color: rgba(235, 240, 250, 0.55);
}

/* =========================================================================
   Универсальные тосты для UX-событий вне основного потока (доставка upload'а,
   копирование, результат действий). Стекаются снизу, fade-in/out, auto-dismiss
   через ~3.6s. position:fixed относительно viewport'а — не зависят от scroll
   ленты и composer'а.
   ========================================================================= */
.fx-toast-container {
	position: fixed;
	left: 50%;
	bottom: 24px;
	transform: translateX(-50%);
	display: flex;
	flex-direction: column;
	gap: 8px;
	z-index: 10020;
	pointer-events: none;
	max-width: min(92vw, 420px);
	width: max-content;
}
.fx-toast {
	pointer-events: auto;
	padding: 10px 14px;
	border-radius: 10px;
	font-size: 13px;
	font-weight: 500;
	line-height: 1.3;
	color: #fff;
	background: #14171d;
	box-shadow: 0 6px 18px rgba(0, 0, 0, 0.18);
	animation: fx-toast-in 220ms ease-out both;
	max-width: 100%;
	word-wrap: break-word;
	text-align: center;
}
.fx-toast--success {
	background: color-mix(in srgb, var(--fx-brand) 85%, #2aa76a);
}
.fx-toast--error {
	background: #c43434;
}
.fx-toast--leaving {
	animation: fx-toast-out 220ms ease-in forwards;
}
@keyframes fx-toast-in {
	from { opacity: 0; transform: translateY(12px); }
	to   { opacity: 1; transform: translateY(0); }
}
@keyframes fx-toast-out {
	from { opacity: 1; transform: translateY(0); }
	to   { opacity: 0; transform: translateY(6px); }
}
@media (prefers-reduced-motion: reduce) {
	.fx-toast,
	.fx-toast--leaving { animation: none; }
}
html[scheme='dark'] .fx-toast {
	background: #f0f3f8;
	color: #14171d;
	box-shadow: 0 8px 22px rgba(0, 0, 0, 0.6);
}
html[scheme='dark'] .fx-toast--success {
	background: color-mix(in srgb, var(--fx-brand) 75%, #5cd299);
	color: #0a0f16;
}
html[scheme='dark'] .fx-toast--error {
	background: #ff6b6b;
	color: #1a0606;
}
/* Свои сообщения — бренд-фон, зеркальная асимметрия: нижне-правый угол
   ПРЯМОЙ (пузырь «упирается» в край ленты), остальные скруглены.
   Дополнительный контраст: чуть насыщеннее фон, чтобы «свои» и «чужие»
   различались с одного взгляда. */
.fx-msg.own .fx-msg__bubble {
	background: var(--fx-bg-bubble-own);
	border-color: color-mix(in srgb, var(--fx-brand) 38%, var(--fx-border));
	border-radius: 14px 14px 0 14px;
	color: var(--fx-text);
}
.fx-msg.own .fx-msg__bubble::before { content: none; }

/* Тёмная тема: тонкая светлая обводка вместо серой из светлого набора переменных */
html[scheme='dark'] .fx-msg:not(.own) .fx-msg__bubble {
	border-color: hsla(0, 0%, 100%, 0.08);
	box-shadow: 0 1px 4px rgba(0, 0, 0, 0.35);
}
html[scheme='dark'] .fx-msg.own .fx-msg__bubble {
	border-color: color-mix(in srgb, var(--fx-brand) 48%, hsla(0, 0%, 100%, 0.1));
}
body.fenix-chat-force-dark .fx-msg:not(.own) .fx-msg__bubble {
	border-color: hsla(0, 0%, 100%, 0.08);
}
body.fenix-chat-force-dark .fx-msg.own .fx-msg__bubble {
	border-color: color-mix(in srgb, var(--fx-brand) 48%, hsla(0, 0%, 100%, 0.1));
}

.fx-msg__bubble p {
	margin: 0 0 6px;
}
.fx-msg__bubble p:last-child {
	margin-bottom: 0;
}

/* Сообщение только из эмодзи — крупнее, как в мессенджерах */
.fx-msg__bubble--emoji-only {
	padding-top: 10px;
	padding-bottom: 20px;
	min-width: 52px;
}
.fx-msg__content--emoji-only {
	font-size: 2.5rem;
	line-height: 1.25;
	letter-spacing: 0.02em;
}
.fx-msg__bubble--emoji-only .fx-msg__content--emoji-only p {
	font-size: inherit;
	line-height: inherit;
	margin: 0;
}
/* Для emoji-only бабла бейдж перевода остаётся в мете — отдельных
   правил не требуется (см. .fx-msg__tr-badge выше). */
@media (max-width: 600px) {
	.fx-msg__content--emoji-only {
		font-size: 2.1rem;
	}
}

.fx-msg__bubble pre {
	background: rgba(0, 0, 0, 0.06);
	padding: 10px;
	border-radius: 8px;
	overflow-x: auto;
	margin: 8px 0;
	border: 1px solid var(--fx-border);
}
html[scheme='dark'] .fx-msg__bubble pre {
	background: rgba(0, 0, 0, 0.35);
}
.fx-msg__bubble code {
	font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
	font-size: 12.5px;
}
.fx-msg__bubble .fchat-mention {
	/* Используем `--fx-link`, а не `--fx-brand`: на светлой теме они
	   совпадают (бренд-синий), а на тёмной теме `--fx-link: #7eb8ff`
	   (светло-голубой), поэтому `@username` читается одинаково
	   как обычная ссылка. `!important` защищает цвет от возможных
	   переопределений из WP-preset тем. С 0.9.49 mention — это <a> на
	   t.me/<username>, но класс сохраняем и для легаси-span'ов, поэтому
	   cursor: pointer явно, иначе на <span> курсор остаётся текстовым. */
	color: var(--fx-link) !important;
	font-weight: 700;
	text-decoration: none;
	cursor: pointer;
}
.fx-msg__bubble a.fchat-mention:hover,
.fx-msg__bubble a.fchat-mention:focus-visible {
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 2px;
	opacity: 0.9;
}
.fx-msg__bubble a {
	/* Единый бренд-синий цвет ссылок в чате, не зависящий от того,
	   какие WP-preset переменные выставила тема сайта. На светлой
	   теме — `#216be9`, на тёмной — `#7eb8ff` (см. --fx-link). */
	color: var(--fx-link) !important;
	font-weight: 600;
	text-decoration: underline;
	text-underline-offset: 2px;
	text-decoration-thickness: 1px;
	transition: color 0.15s ease, opacity 0.15s ease;
}
.fx-msg__bubble a:hover,
.fx-msg__bubble a:focus-visible {
	opacity: 0.85;
	text-decoration-thickness: 2px;
}
/* «Свои» пузыри на светлой теме имеют светло-голубой тинт
   (`--fx-bg-bubble-own` ≈ 28% brand + #f6f9fc), а не насыщенный бренд-цвет.
   Раньше ссылки принудительно выставлялись белыми «для читаемости на
   синем» — но на светлом тинте белое становилось невидимым, и
   пользователь жаловался: «в наших сообщениях ссылки не выделяются
   цветом». Теперь ссылки в своих сообщениях используют такой же
   бренд-синий (`--fx-link`), как и у чужих — контраст с фоном нормальный
   на обеих темах (фон тёмной темы тоже полупрозрачный brand, но за ним
   есть тёмная панель — синий читается). */
.fx-msg__bubble.own a,
.fx-msg.own .fx-msg__bubble a,
.fx-msg.own .fx-msg__bubble .fchat-mention {
	color: var(--fx-link) !important;
	text-decoration: underline;
	text-underline-offset: 2px;
	text-decoration-thickness: 1px;
}
.fx-msg__bubble.own a:hover,
.fx-msg.own .fx-msg__bubble a:hover,
.fx-msg__bubble.own a:focus-visible,
.fx-msg.own .fx-msg__bubble a:focus-visible {
	text-decoration-thickness: 2px;
	opacity: 0.85;
}
.fx-msg__bubble img,
.fx-msg__bubble video {
	max-width: 100%;
	max-height: 320px;
	border-radius: var(--fx-radius-sm);
	display: block;
	margin-top: 8px;
}

/* Цитата reply-to внутри пузыря — как в Telegram: тонкая «бренд-полоса»
   слева, слабый фон из --fx-brand 10%, ник акцентный, текст цитаты
   обрезан в одну строку многоточием (переносы в цитате не нужны — за
   полным контекстом юзер кликом перейдёт на оригинал). */
.fx-msg__reply {
	display: block;
	position: relative;
	background: color-mix(in srgb, var(--fx-brand) 10%, var(--fx-bg-bubble));
	padding: 6px 10px;
	margin: 0 0 8px;
	border-radius: 8px;
	font-size: 12px;
	line-height: 1.35;
	color: var(--fx-text-dim);
	cursor: pointer;
	overflow: hidden;
	max-width: 100%;
}
.fx-msg__reply strong {
	display: block;
	color: var(--fx-brand);
	font-weight: 700;
	font-size: 12px;
	margin-bottom: 2px;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
	/* Длина имени уже урезана в JS (truncateForQuote, 52 символа),
	   поэтому max-width здесь не ставим — иначе span не растягивался
	   бы до ширины бабла, когда сам бабл шире (длинный ответ). */
	min-width: 0;
	max-width: 100%;
}
.fx-msg__reply:hover {
	background: color-mix(in srgb, var(--fx-brand) 16%, var(--fx-bg-bubble));
}
.fx-msg__reply-text {
	/* Однострочное превью: nowrap + ellipsis как safety net для случаев,
	   когда бабл вдруг уже, чем фактический текст (узкий мобильный
	   viewport, ультра-широкие шрифты).
	   Длину текста режет JS (truncateForQuote → 51 символ + «…»). За счёт
	   этого:
	     • max-content span'а ≈ 52ch, бабл по детям с max-content тоже
	       капается на 52ch — поэтому при коротком ответе («Да») и длинной
	       цитате бабл не растягивается на пол-экрана;
	     • при длинном ответе span (display:block, max-width:100%) сам
	       растягивается до ширины бабла и цитата не оставляет пустой
	       фон справа;
	     • min-width:0 — обязательно для grid-item в --has-thumb. */
	display: block;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
	min-width: 0;
	max-width: 100%;
	color: var(--fx-text);
	opacity: 0.85;
}

/* Reply-thumb: миниатюра первой photo/video/animation сообщения-родителя.
   По умолчанию .fx-msg__reply — блочный (никнейм сверху, текст снизу).
   Когда добавлен класс --has-thumb, раскладываем через grid: слева
   квадратное превью, справа две строки (ник + цитата). */
.fx-msg__reply--has-thumb {
	display: grid;
	grid-template-columns: 40px 1fr;
	grid-template-areas:
		'thumb name'
		'thumb text';
	column-gap: 8px;
	row-gap: 0;
	align-items: center;
}
.fx-msg__reply--has-thumb .fx-msg__reply-thumb { grid-area: thumb; }
.fx-msg__reply--has-thumb > strong,
.fx-msg__reply--has-thumb .fx-msg__reply-name { grid-area: name; margin-bottom: 0; }
.fx-msg__reply--has-thumb .fx-msg__reply-text { grid-area: text; }

.fx-msg__reply-thumb {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 40px;
	height: 40px;
	flex: none;
	border-radius: 6px;
	overflow: hidden;
	background: var(--fx-bg-elev);
	border: 1px solid var(--fx-border);
	user-select: none;
}
.fx-msg__reply-thumb img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}
.fx-msg__reply-thumb-ico {
	position: absolute;
	left: 50%;
	top: 50%;
	transform: translate(-50%, -50%);
	color: #fff;
	font-size: 10px;
	line-height: 1;
	width: 18px;
	height: 18px;
	border-radius: 50%;
	background: rgba(0, 0, 0, 0.55);
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding-left: 1px; /* визуальная центровка треугольника ▶ */
}

/* =========================================================================
   F19 — цепочка реплаев (до 3 уровней).
   Wrap-контейнер содержит стек цитат: самая дальняя сверху, ближайшая
   (immediate parent) снизу. Каждая цитата — обычная .fx-msg__reply, но
   дальние уровни получают уменьшенную непрозрачность, меньший отступ
   сверху и лёгкий compact-вид: это создаёт визуальный «thread» без
   громоздкой вложенности. Под последней цитатой — уже основной текст
   сообщения.
   ========================================================================= */
.fx-msg__reply-chain {
	display: flex;
	flex-direction: column;
	gap: 2px;
	margin-bottom: 8px;
}
.fx-msg__reply-chain .fx-msg__reply {
	margin-bottom: 0;
}
/* Дальние уровни (2, 3) — уменьшенная непрозрачность, чтобы immediate
   parent читался как главный, а предки — как контекст. */
.fx-msg__reply--lvl-2 {
	opacity: 0.85;
	font-size: 11.5px;
	padding: 4px 10px;
}
.fx-msg__reply--lvl-3 {
	opacity: 0.70;
	font-size: 11px;
	padding: 3px 10px;
}
/* Базовый .fx-msg__reply-text теперь сам по себе однострочный
   (white-space: nowrap + text-overflow: ellipsis), поэтому отдельные
   override'ы для уровней 2/3 больше не нужны. */
.fx-msg__reply--deleted {
	opacity: 0.5;
	font-style: italic;
	cursor: default;
}
.fx-msg__reply--deleted:hover {
	/* deleted нельзя открыть — не меняем фон на hover */
	background: color-mix(in srgb, var(--fx-brand) 10%, var(--fx-bg-bubble));
}
.fx-msg__reply-more {
	font-size: 10.5px;
	font-weight: 600;
	letter-spacing: 0.02em;
	color: color-mix(in srgb, var(--fx-brand) 60%, var(--fx-text-dim));
	padding: 2px 0 4px 10px;
	text-transform: uppercase;
	opacity: 0.75;
	user-select: none;
	/* F19-polish: это теперь <button>, а не <div> — сбрасываем
	   дефолтный стиль и добавляем hover-affordance, чтобы пользователь
	   видел, что бейдж кликабелен для догрузки цепочки. */
	background: transparent;
	border: 0;
	cursor: pointer;
	display: inline-block;
	text-align: left;
	font-family: inherit;
	transition: opacity .15s ease, color .15s ease;
}
.fx-msg__reply-more:hover:not(:disabled) {
	opacity: 1;
	color: var(--fx-brand);
}
.fx-msg__reply-more:disabled {
	cursor: progress;
	opacity: 0.5;
}
html[scheme='dark'] .fx-msg__reply--lvl-2 { opacity: 0.78; }
html[scheme='dark'] .fx-msg__reply--lvl-3 { opacity: 0.62; }

.fx-msg__meta {
	font-size: 11px;
	color: var(--fx-text-dim);
	margin-top: 5px;
	display: flex;
	align-items: center;
	gap: 10px;
}

.fx-reactions {
	display: flex;
	flex-wrap: wrap;
	gap: 5px;
	margin-top: 6px;
}
/* Reaction-чип: визуально — пилюля «под кнопку» на фоне страницы.
   Светлая тема — светлый плотный фон, чтобы цифра не сливалась
   с белым пузырём; тёмная — фон под кнопки (var(--fx-surface-1)).
   Размер компактный, число прячем при count===1 (его рисует JS
   только при >1). */
.fx-reaction {
	background: color-mix(in srgb, var(--fx-brand) 8%, var(--fx-bg));
	border: 1px solid color-mix(in srgb, var(--fx-brand) 20%, var(--fx-border));
	color: var(--fx-text);
	border-radius: 999px;
	padding: 2px 8px;
	font-size: 12px;
	line-height: 1.2;
	cursor: pointer;
	transition: background 0.15s ease, border-color 0.15s ease,
		box-shadow 0.15s ease;
	user-select: none;
	display: inline-flex;
	align-items: center;
	gap: 4px;
	font-variant-numeric: tabular-nums;
}
.fx-reaction__count {
	font-weight: 600;
	color: var(--fx-text);
}
.fx-reaction:hover {
	border-color: var(--fx-brand);
	background: color-mix(in srgb, var(--fx-brand) 14%, var(--fx-bg));
	box-shadow: 0 2px 8px rgba(33, 107, 233, 0.15);
}
.fx-reaction.own {
	background: color-mix(in srgb, var(--fx-brand) 22%, var(--fx-bg));
	border-color: color-mix(in srgb, var(--fx-brand) 55%, var(--fx-border));
	color: var(--fx-brand);
	font-weight: 600;
}
.fx-reaction.own .fx-reaction__count {
	color: var(--fx-brand);
}
/* Мини-аватарки реакторов внутри чипа (показываем при count <= 2,
   как в Telegram). Кружки слегка перекрывают друг друга. */
.fx-reaction__avs {
	display: inline-flex;
	align-items: center;
}
.fx-reaction__avs .fx-reaction__av + .fx-reaction__av {
	margin-left: -7px;
}
.fx-reaction__av {
	/* 18px — чуть меньше, чтобы кружок сидел ровно на одной линии с
	   эмодзи (глиф эмодзи компактный), не выпирая по высоте. */
	width: 18px;
	height: 18px;
	border-radius: 50%;
	object-fit: cover;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	box-sizing: border-box;
	border: 2px solid var(--fx-bg);
	background: color-mix(in srgb, var(--fx-brand) 30%, var(--fx-bg));
	flex: 0 0 auto;
	vertical-align: middle;
}
.fx-reaction__av--ph {
	color: #fff;
	font-size: 10px;
	font-weight: 700;
	line-height: 1;
	text-transform: uppercase;
}
.fx-reaction.own .fx-reaction__av { border-color: color-mix(in srgb, var(--fx-brand) 22%, var(--fx-bg)); }
html[scheme='dark'] .fx-reaction__av { border-color: var(--fx-surface-1); }
html[scheme='dark'] .fx-reaction.own .fx-reaction__av { border-color: color-mix(in srgb, var(--fx-brand) 28%, var(--fx-surface-1)); }

html[scheme='dark'] .fx-reaction {
	background: var(--fx-surface-1);
	border-color: var(--fx-surface-border);
	color: var(--fx-text);
}

/* === Единое выравнивание нижней строки сообщения ===
   Время отправки, галочка прочтения, число прочитавших и реакции —
   ВСЕ на одной линии, по центру, одним размером шрифта (раньше были
   разной высоты и разного кегля). Идёт ПОСЛЕ всех прежних определений,
   чтобы гарантированно победить в каскаде. */
.fx-msg__foot {
	align-items: center;
	min-height: 22px;
	column-gap: 8px;
	row-gap: 4px;
}
.fx-msg__foot .fx-reactions,
.fx-msg__foot .fx-msg__meta {
	display: inline-flex;
	align-items: center;
	min-height: 22px;
}
.fx-msg__foot .fx-msg__meta { gap: 5px; font-size: 12px; line-height: 1; }
.fx-msg__foot .fx-msg__time,
.fx-msg__foot .fx-msg__check,
.fx-msg__foot .fx-msg__check-num,
.fx-msg__foot .fx-msg__edited { font-size: 12px; line-height: 1; }
.fx-msg__foot .fx-msg__check { align-items: center; gap: 3px; }
.fx-msg__foot .fx-msg__check svg { width: 15px; height: 13px; display: block; vertical-align: middle; }
/* Каждый элемент меты строго по центру кросс-оси — убирает «что-то выше,
   что-то ниже» между временем, галочкой и числом прочитавших. */
.fx-msg__foot .fx-msg__meta > * { align-self: center; display: inline-flex; align-items: center; }
.fx-msg__foot .fx-reaction {
	display: inline-flex;
	align-items: center;
	min-height: 22px;
	padding: 2px 9px;
	font-size: 12px;
	line-height: 1;
}
.fx-msg__foot .fx-reaction__emoji { font-size: 13px; line-height: 1; }
/* Счётчик просмотров (глаз + число) удалён по запросу. На случай, если
   элемент всё же где-то отрисуется (кэш/старый пузырь) — прячем. */
.fx-msg__views { display: none !important; }
html[scheme='dark'] .fx-reaction:hover {
	background: color-mix(in srgb, var(--fx-brand) 18%, var(--fx-surface-1));
	border-color: color-mix(in srgb, var(--fx-brand) 45%, var(--fx-surface-border));
}
html[scheme='dark'] .fx-reaction.own {
	background: color-mix(in srgb, var(--fx-brand) 28%, var(--fx-surface-1));
	border-color: color-mix(in srgb, var(--fx-brand) 60%, var(--fx-surface-border));
	color: #fff;
}
html[scheme='dark'] .fx-reaction.own .fx-reaction__count {
	color: #fff;
}

/* === Жёсткое выравнивание содержимого чипа реакции по центру ===
   Эмодзи-глиф визуально сидит выше своего бокса, из-за чего 20px-аватарка
   казалась «съехавшей вниз». Принудительно центрируем оба элемента по
   кросс-оси чипа и убираем строчные интервалы у контейнера аватарок. */
.fx-reactions .fx-reaction {
	align-items: center !important;
}
.fx-reactions .fx-reaction > * {
	align-self: center !important;
}
.fx-reaction__emoji {
	display: inline-flex;
	align-items: center;
	line-height: 1;
}
/* Глиф эмодзи (Segoe UI Emoji) рендерится высоко в своём боксе, поэтому
   оптически опускаем сам смайл на 2px — встаёт ровно на одну линию с
   аватаркой реактора (саму аватарку не двигаем). Только для чипов с
   аватарками; чипы с числом (count>2) не трогаем. */
.fx-reaction:has(.fx-reaction__avs) .fx-reaction__emoji {
	position: relative;
	top: 2px;
}
.fx-reaction__avs {
	align-self: center !important;
	line-height: 0;
}
.fx-reaction .fx-reaction__av {
	/* Аватарка — это <img> внутри сообщения, поэтому на неё прилетает
	   общий стиль картинок в сообщении (margin-top + display:block),
	   который ронял кружок вниз и раздувал чип. Гасим его и центрируем
	   аватарку как обычный flex-элемент чипа. */
	margin: 0 !important;
	display: inline-flex !important;
	vertical-align: middle;
}

/* Анимация при постановке своей реакции. JS добавляет класс
   .fx-reaction--pop сразу после ре-рендера сообщения (reaction:updated
   через сокет), затем снимает его через 650ms. Одна короткая pop-
   анимация, чуть подскок и мягкое свечение. prefers-reduced-motion
   — уважается (анимация отключается). */
@keyframes fx-reaction-pop {
	0%   { transform: scale(1); }
	18%  { transform: scale(1.38); }
	36%  { transform: scale(0.92); }
	56%  { transform: scale(1.12); }
	78%  { transform: scale(0.98); }
	100% { transform: scale(1); }
}
@keyframes fx-reaction-glow {
	0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--fx-brand) 60%, transparent); }
	60%  { box-shadow: 0 0 0 10px color-mix(in srgb, var(--fx-brand) 0%, transparent); }
	100% { box-shadow: 0 0 0 0 transparent; }
}
.fx-reaction--pop {
	animation: fx-reaction-pop 0.55s cubic-bezier(0.34, 1.56, 0.64, 1) both,
		fx-reaction-glow 0.6s ease-out both;
	will-change: transform;
}
@media (prefers-reduced-motion: reduce) {
	.fx-reaction--pop { animation: none; }
}
.fx-reaction:active {
	transform: scale(0.94);
	transition: transform 0.08s ease;
}

/* ======================================================================
 * ТУЛБАР ДЕЙСТВИЙ НАД СООБЩЕНИЕМ (Telegram-style)
 * ----------------------------------------------------------------------
 * Открывается:
 *   • desktop — LONG-PRESS (удержание ЛКМ ~400мс) по пузырю,
 *     включая сообщения с файлами/картинками (JS-класс .is-tools-open);
 *   • mobile  — свайпом ВПРАВО по пузырю (JS-класс .is-tools-open);
 *   • desktop double-click по пузырю — сразу Reply, без тулбара.
 *
 * Раскладка тулбара:
 *   • Верхний ряд — одна строка быстрых реакций-смайликов на всю
 *     ширину пузыря. Справа кнопка «⋯» — раскрывает вторичный
 *     ряд с иконками pin/reply/translate/delete.
 *   • Тулбар позиционируется absolutely от .fx-msg, выезжает из-под
 *     пузыря. У своих — правый край тулбара к правому краю пузыря,
 *     у чужих — левый к левому. Ширина: 100% пузыря (ограниченная
 *     max-width 420px, чтобы не переезжать всю ленту).
 *
 * Важно: .fx-msg имеет position: relative (см. родительские стили).
 * -------------------------------------------------------------------- */
/* Tools-row попап: раньше был position:absolute и «висел» над
   соседними сообщениями, перекрывая их. Пользователь попросил, чтобы
   попап выдвигался ИЗ сообщения вниз и СМЕЩАЛ все последующие
   сообщения — для этого делаем его обычным flow-элементом внутри
   `.fx-msg` (через flex-wrap: он занимает следующую строку во flex-контейнере).
   Это автоматически добавляет высоту `.fx-msg` → родительский
   `.fx-chat-feed` (flex-column) раздвигает всё под ним. */
.fx-msg__tools {
	display: none;
	flex-direction: column;
	align-items: stretch;
	gap: 4px;
	/* Унифицированный фон / бордер / тень / радиус со всеми
	   контекст-меню чата (см. .fx-input-ctx, .fx-readers-popover,
	   .fx-react-picker). Это то же визуальное семейство:
	   fixed-панелька, белая/тёмно-серая плашка, крупная мягкая тень,
	   12px радиус, 6px внутренний отступ, шрифт system-ui 14/1.3. */
	padding: 6px;
	background: var(--fx-bg, #fff);
	color: var(--fx-text, #14171d);
	border: 1px solid var(--fx-border, rgba(0, 0, 0, 0.12));
	border-radius: 12px;
	box-shadow: 0 14px 40px rgba(0, 0, 0, 0.18), 0 2px 6px rgba(0, 0, 0, 0.08);
	font: 14px/1.3 system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
	box-sizing: border-box;
	min-width: 200px;
	max-width: min(260px, calc(100vw - 24px));
	width: max-content;
	/* `order:99` гарантирует, что попап оказывается ПОСЛЕ body в
	   flex-wrap-ряду (а не, например, слева от него у row-reverse). */
	order: 99;
	/* Пользователь просил прижать тулбар ближе к сообщению — сократили
	   6px → 2px, теперь действительно выглядит как «выехало из-под
	   пузыря», без воздушной полоски. */
	margin-top: 2px;
}
/* Выравнивание попапа по «говорящей» стороне САМОГО пузыря. Точные
   смещения считаем в JS (openMsgTools → --fx-tools-left /
   --fx-tools-right). У своих правая сторона попапа прилегает к правой
   стороне пузыря, у чужих левая — к левой (под аватаром + gap).
   Fallback в var() — 44px (34 аватар + 10 gap), если JS ещё не успел
   проставить переменную. */
.fx-msg.own .fx-msg__tools {
	margin-left: auto;
	margin-right: var(--fx-tools-right, 0px);
}
.fx-msg:not(.own) .fx-msg__tools {
	margin-left: var(--fx-tools-left, 44px);
	margin-right: auto;
}
/* Раньше `.fx-msg.is-tools-open` безусловно растягивалось до 100%
   ширины ленты — тулбар был в потоке и должен был лежать ПОД баблом
   (flex-basis:100% в flex-wrap-ряду). Сейчас меню ВСЕГДА открывается
   в «плавающем» режиме (position:fixed у курсора, см. .is-tools-floating),
   и этот трюк больше не нужен — а раньше именно он вызывал «прыжок»
   ширины пузыря между состояниями (normal → tools-open → normal).
   Поэтому width:100% применяем ТОЛЬКО к legacy-in-flow режиму
   (is-tools-open без is-tools-floating). При is-tools-floating бабл
   остаётся в своей исходной ширине, а попап выезжает у курсора. */
.fx-msg.is-tools-open:not(.is-tools-floating) {
	flex-wrap: wrap;
	margin-bottom: 4px;
	width: 100%;
	max-width: 100%;
}
.fx-msg:not(.own).is-tools-open:not(.is-tools-floating) .fx-msg__body {
	flex: 0 1 auto;
	max-width: 88%;
}
/* Псевдо-разрыв строки во flex-wrap. Это самый надёжный способ
   заставить следующий flex-item (тулбар) ВСЕГДА оказаться на новой
   строке под баблом: нулевой «элемент» с flex-basis:100% занимает
   полную ширину строки, вынуждая всё с бо́льшим order уйти вниз.
   Предыдущий вариант через flex-basis:100% на самом тулбаре иногда
   не срабатывал, потому что max-width:420px + width:max-content
   давали браузеру основание уместить его рядом с баблом на широкой
   ленте (ПК ЛК, где 88% ширины ~ 900px, а тулбар всего ~320px).
   Теперь ::after безусловно ломает строку. */
.fx-msg.is-tools-open:not(.is-tools-floating)::after {
	/* КРИТИЧНО: сбрасываем все свойства от .fx-msg::after (свайп-стрелка),
	   иначе `position:absolute` оттуда убирает псевдо-элемент из flex-потока —
	   и flex-basis:100% не сработает (на своих сообщениях тулбар уезжал
	   вбок, на row-reverse ряд умещался бабл+тулбар на одной строке).
	   Актуально ТОЛЬКО для legacy in-flow режима — в плавающем режиме
	   тулбар position:fixed и flex-потоку уже ничего не мешает. */
	content: '';
	position: static;
	order: 90;
	flex: 0 0 100%;
	width: 100%;
	min-width: 100%;
	max-width: 100%;
	height: 0;
	margin: 0;
	padding: 0;
	background: transparent;
	border-radius: 0;
	box-shadow: none;
	transform: none;
	opacity: 1;
	pointer-events: none;
	font-size: 0;
	color: transparent;
	top: auto;
	right: auto;
	bottom: auto;
	left: auto;
}
.fx-msg.is-tools-open .fx-msg__tools {
	display: flex;
	animation: fx-tools-slide-down 0.2s ease;
	flex-basis: 100%;
}
/* Плавающий режим — попап всплывает у курсора (ПКМ) или у пальца
   (long-press/single-tap на мобильном). Позиция приходит из JS через
   CSS-переменные --fx-tools-x / --fx-tools-y (clientX/clientY в
   координатах viewport'а). Попап — position:fixed, он ВНЕ flex-потока
   .fx-msg и не требует ломать ширину/wrap пузыря. Поэтому сам .fx-msg
   НИКАК не модифицируем при is-tools-floating — пузырь остаётся
   в точности в том виде, что был до открытия меню (без прыжков текста,
   без переносов на новую строку). Пользователь жаловался: «текст
   внутри сообщения прыгает, что-то переносится на другую строку при
   открытии меню действий» — это был побочный эффект старого
   `width: auto; max-width: initial`, который менял max-width у .fx-msg
   и на долю секунды пересчитывал ширину пузыря. */
.fx-msg.is-tools-floating.is-tools-open::after {
	content: none;
}
.fx-msg.is-tools-floating.is-tools-open > .fx-msg__tools {
	position: fixed;
	z-index: 99999;
	top: var(--fx-tools-y, 0);
	left: var(--fx-tools-x, 0);
	margin: 0;
	flex-basis: auto;
	/* На мобильных минимум подрезаем под экран: `min(260, 92vw)`
	   вместо жёстких 200px — иначе на 320px-экранах (старые iPhone
	   SE / Galaxy Fold в сложенном виде) попап не помещался
	   и вылезал за правый край. */
	min-width: min(220px, calc(100vw - 24px));
	max-width: min(260px, calc(100vw - 24px));
	width: max-content;
	/* JS проставляет --fx-tools-max-h = высота видимой части чата.
	   Fallback на 100vh для не-JS и для обратной совместимости. */
	max-height: var(--fx-tools-max-h, calc(100vh - 24px));
	overflow-y: auto;
	animation: fx-tools-fade-in 0.12s ease-out;
}
.fx-msg.is-tools-floating.is-tools-open > .fx-msg__tools::-webkit-scrollbar {
	width: 0;
	display: none;
}
@keyframes fx-tools-fade-in {
	from { opacity: 0; transform: translateY(4px); }
	to   { opacity: 1; transform: translateY(0); }
}
@keyframes fx-tools-slide-down {
	from { opacity: 0; transform: translateY(-6px); }
	to   { opacity: 1; transform: none; }
}
/* Тёмная тема — такой же контраст, как у .fx-input-ctx: тёмно-серый
   фон, светлый текст, усиленная тень. */
html[scheme='dark'] .fx-msg__tools,
body.fenix-chat-force-dark .fx-msg__tools {
	background: #1f232b;
	color: #e6ecf5;
	border-color: rgba(255, 255, 255, 0.12);
	box-shadow: 0 14px 40px rgba(0, 0, 0, 0.6), 0 2px 6px rgba(0, 0, 0, 0.3);
}
.fx-msg__tools-row {
	display: flex;
	align-items: center;
	gap: 2px;
}
.fx-msg__tools-row--emoji {
	justify-content: space-between;
	padding: 2px;
}
.fx-msg__tools-row--emoji .fx-msg__react {
	flex: 1 1 0;
	background: transparent;
	border: 0;
	cursor: pointer;
	font-size: 20px;
	line-height: 1;
	padding: 6px 2px;
	border-radius: 10px;
	transition: transform 0.12s ease, background 0.12s ease;
}
.fx-msg__tools-row--emoji .fx-msg__react:hover {
	background: color-mix(in srgb, var(--fx-brand) 14%, var(--fx-bg));
	transform: scale(1.15);
}
/* Кнопка «…» в конце ряда быстрых реакций — открывает полный
   emoji-picker (`.fx-react-picker`, position:fixed). Выглядит чуть
   компактнее смайлов: моноспейс-точки, text-dim цвет, тот же
   круглый hover-фон. */
.fx-msg__tools-row--emoji .fx-msg__react--more {
	color: var(--fx-text-dim);
	font-size: 22px;
	font-weight: 700;
	letter-spacing: 1px;
	padding-bottom: 10px;
}
.fx-msg__tools-row--emoji .fx-msg__react--more:hover {
	transform: scale(1.1);
	color: var(--fx-brand);
}

/* ======================================================================
 * Полный emoji-picker реакций — открывается кнопкой «…» в ряде
 * быстрых реакций. Position: fixed поверх всего, grid 8 колонок,
 * компактные клетки, плавное появление. */
.fx-react-picker {
	position: fixed;
	z-index: 99999;
	display: grid;
	grid-template-columns: repeat(8, 1fr);
	gap: 2px;
	/* Унификация с .fx-input-ctx / .fx-msg__tools / .fx-readers-popover —
	   те же бэкграунд / рамка / радиус / тень / шрифт, чтобы все
	   контекст-меню чата читались как одно семейство. */
	padding: 6px;
	background: var(--fx-bg, #fff);
	color: var(--fx-text, #14171d);
	border: 1px solid var(--fx-border, rgba(0, 0, 0, 0.12));
	border-radius: 12px;
	box-shadow: 0 14px 40px rgba(0, 0, 0, 0.18), 0 2px 6px rgba(0, 0, 0, 0.08);
	font: 14px/1.3 system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
	/* Ограничиваем по ширине viewport'а (на узких экранах 320px);
	   по высоте — не более 60vh со скроллом, если EMOJIS-список
	   разросся. */
	max-width: min(360px, calc(100vw - 16px));
	max-height: min(60vh, 320px);
	overflow-y: auto;
	scrollbar-width: none;
	animation: fxReactPickerIn 0.14s ease-out;
}
.fx-react-picker::-webkit-scrollbar {
	width: 0;
	display: none;
}
@keyframes fxReactPickerIn {
	from { opacity: 0; transform: translateY(4px) scale(0.96); }
	to   { opacity: 1; transform: translateY(0) scale(1); }
}
.fx-react-picker__btn {
	background: transparent;
	border: 0;
	cursor: pointer;
	font-size: 22px;
	line-height: 1;
	padding: 6px;
	border-radius: 8px;
	-webkit-tap-highlight-color: transparent;
	touch-action: manipulation;
	transition: background-color 0.12s ease, transform 0.12s ease;
}
.fx-react-picker__btn:hover,
.fx-react-picker__btn:focus-visible {
	background: color-mix(in srgb, var(--fx-brand) 14%, var(--fx-bg));
	transform: scale(1.15);
	outline: none;
}
.fx-react-picker__btn:active {
	transform: scale(0.92);
}
html[scheme='dark'] .fx-react-picker,
body.fenix-chat-force-dark .fx-react-picker {
	background: #1f232b;
	color: #e6ecf5;
	border-color: rgba(255, 255, 255, 0.12);
	box-shadow: 0 14px 40px rgba(0, 0, 0, 0.6), 0 2px 6px rgba(0, 0, 0, 0.3);
}
/* На узких мобильниках сеть 7 колонок вместо 8, чтобы клетки были
   крупнее и удобнее для тапа. */
@media (max-width: 420px) {
	.fx-react-picker {
		grid-template-columns: repeat(7, 1fr);
	}
}
.fx-msg__tools-more {
	flex: 0 0 auto;
	background: transparent;
	border: 0;
	cursor: pointer;
	color: var(--fx-text-dim);
	font-size: 18px;
	padding: 6px 10px;
	border-radius: 10px;
	min-width: 34px;
}
.fx-msg__tools-more:hover {
	color: var(--fx-text);
	background: color-mix(in srgb, var(--fx-brand) 10%, var(--fx-bg));
}
/* Разделитель между эмодзи-реакциями и списком действий —
   визуально такой же, как в .fx-input-ctx. Иконка-ряд сверху,
   список текстовых пунктов снизу как у Telegram / контекстного
   меню системы. */
.fx-msg__tools-sep {
	height: 1px;
	background: var(--fx-border, rgba(0, 0, 0, 0.1));
	margin: 4px 2px;
}
html[scheme='dark'] .fx-msg__tools-sep,
body.fenix-chat-force-dark .fx-msg__tools-sep {
	background: rgba(255, 255, 255, 0.1);
}
.fx-msg__tools-row--actions {
	display: flex;
	flex-direction: column;
	gap: 1px;
	padding: 2px;
}
/* Кнопка-пункт: иконка слева (18×18), текст справа, выровнены
   по левому краю. Hover — мягкая заливка brand-тинтом, как в
   системном контекстном меню (ровно как .fx-input-ctx__item).
   Font/padding/radius подобраны под .fx-input-ctx: 14px/1.3,
   padding 7px 12px, radius 8px, на hover текст тоже становится
   brand-синим (pop-фидбек, а не только фон). */
.fx-msg__tools-row--actions button {
	display: flex;
	align-items: center;
	gap: 10px;
	width: 100%;
	text-align: left;
	background: transparent;
	border: 0;
	cursor: pointer;
	font: inherit;
	line-height: 1.3;
	padding: 7px 12px;
	border-radius: 8px;
	color: inherit;
	transition: background-color 0.12s ease, color 0.12s ease;
}
.fx-msg__tools-row--actions button:hover,
.fx-msg__tools-row--actions button:focus-visible {
	background: color-mix(in srgb, var(--fx-brand, #216be9) 12%, transparent);
	color: var(--fx-brand, #216be9);
	outline: none;
}
.fx-msg__tools-row--actions button[data-act='delete']:hover,
.fx-msg__tools-row--actions button[data-act='delete']:focus-visible {
	background: color-mix(in srgb, #e14b4b 14%, var(--fx-bg));
	color: #e14b4b;
}
.fx-msg__tool-ico {
	flex: 0 0 auto;
	font-size: 15px;
	width: 18px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
}
.fx-msg__tool-ico--danger {
	color: #dc2626;
}
.fx-msg__tool-lbl {
	flex: 1 1 auto;
	font-weight: 500;
}
.fx-msg__tool-lbl--danger {
	color: #dc2626;
}
.fx-msg__tool-txt { display: none; } /* оставлено для совместимости */

/* Колонка чекбоксов для массового удаления — по умолчанию скрыта. */
.fx-msg__pick {
	flex: 0 0 0;
	width: 0;
	opacity: 0;
	overflow: hidden;
	display: flex;
	align-items: flex-start;
	justify-content: center;
	padding-top: 6px;
	transition: width 0.22s ease, opacity 0.18s ease;
	pointer-events: none;
	cursor: pointer;
	box-sizing: border-box;
}
.fenix-chat-wrap.is-select-mode .fx-msg__pick {
	flex: 0 0 auto;
	width: 30px;
	opacity: 1;
	overflow: visible;
	pointer-events: auto;
	margin-right: 2px;
}
.fx-msg__pick input[type='checkbox'] {
	width: 22px;
	height: 22px;
	margin: 0;
	flex-shrink: 0;
	cursor: pointer;
	appearance: none;
	-webkit-appearance: none;
	border: 2px solid color-mix(in srgb, var(--fx-brand) 55%, var(--fx-border));
	border-radius: 50%;
	background: var(--fx-bg);
	box-sizing: border-box;
	position: relative;
	vertical-align: middle;
	transition: border-color 0.15s ease, background 0.15s ease;
}
.fenix-chat-wrap.is-select-mode .fx-msg__pick input[type='checkbox']:checked {
	background: var(--fx-brand);
	border-color: var(--fx-brand);
}
.fenix-chat-wrap.is-select-mode .fx-msg__pick input[type='checkbox']:checked::after {
	content: '';
	position: absolute;
	left: 50%;
	top: 50%;
	width: 8px;
	height: 8px;
	transform: translate(-50%, -50%);
	border-radius: 50%;
	background: #fff;
	box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.06);
}
.fenix-chat-wrap.is-select-mode .fx-msg__pick input[type='checkbox']:focus-visible {
	outline: 2px solid var(--fx-brand);
	outline-offset: 2px;
}
.fx-msg__pick--disabled input[type='checkbox'] {
	cursor: not-allowed;
	opacity: 0.45;
}

.fx-msg--deleted .fx-msg__bubble {
	color: var(--fx-text-dim);
	font-style: italic;
	opacity: 0.85;
}

/* Swipe-to-reply (mobile) -------------------------------------------------
   JS выставляет .fx-msg transform: translateX() и --fx-swipe (0..1).
   Показываем стрелку «ответить» справа, которая становится всё более
   выраженной по мере прогресса жеста. */
.fx-msg {
	--fx-swipe: 0;
	transition: transform .22s cubic-bezier(.22, .61, .36, 1);
	touch-action: pan-y;
}
.fx-msg--swiping {
	transition: none;
}
.fx-msg::after {
	content: "↩";
	position: absolute;
	top: 50%;
	right: -52px;
	left: auto;
	transform: translateY(-50%) scale(calc(0.8 + var(--fx-swipe) * 0.5));
	width: 44px;
	height: 44px;
	display: flex;
	align-items: center;
	justify-content: center;
	border-radius: 0;
	background: transparent;
	box-shadow: none;
	color: var(--fx-brand);
	font-size: 30px;
	font-weight: 700;
	opacity: var(--fx-swipe);
	pointer-events: none;
	transition: opacity .12s ease, transform .12s ease;
}
/* Свайп вправо → выделение для удаления: иконка «корзина» слева.
   Плавающий emoji БЕЗ фоновой плашки и крупнее стандартной стрелки —
   так пользователь сразу видит, что жест означает удаление. Отступ
   влево от пузыря, чтобы корзина не «прилипала» к тексту сообщения. */
.fx-msg[data-swipe-dir="right"]::after {
	content: "🗑";
	right: auto;
	left: -52px;
	width: 44px;
	height: 44px;
	background: transparent;
	border-radius: 0;
	box-shadow: none;
	color: #e53e3e;
	font-size: 30px;
	/* Лёгкое покачивание на подходе к порогу — подсказка, что
	   отпустить сейчас = подтверждение выбора сообщения. */
	transform: translateY(-50%) scale(calc(0.8 + var(--fx-swipe) * 0.5));
}
.fx-msg--swiping::after {
	transition: none;
}
/* Десктоп: стрелка и жест не нужны — скрываем. */
@media (hover: hover) and (pointer: fine) {
	.fx-msg::after { content: none; }
}

.fx-msg--pending {
	opacity: 0.58;
}

.fx-msg--highlight .fx-msg__bubble {
	animation: fx-msg-flash 1.4s ease-out;
}
@keyframes fx-msg-flash {
	0%   { box-shadow: 0 0 0 3px color-mix(in srgb, var(--fx-brand) 45%, transparent); }
	100% { box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04); }
}

/* ======================================================================
 * Удаление сообщения: «Aurora Warp» — современная плавная анимация.
 *
 * Концепция (CSS-only, GPU-accelerated, 820ms):
 *   фаза 1 (0–14%):  микро-«вдох» — scale 1.04 + lift на 1px, вокруг
 *                     пузыря вспыхивает бренд-glow (box-shadow ring).
 *   фаза 2 (14–45%): бабл начинает сжиматься и слегка поворачивается
 *                     против часовой, glow раздувается до bloom-ореола,
 *                     filter: blur ramps up + saturate 1.25 (цвет мягко
 *                     «греется» перед исчезновением).
 *   фаза 3 (45–78%): пузырь уменьшается сильнее, улетает вверх и влево,
 *                     bloom размывается, blur 10px, opacity ~0.3.
 *   фаза 4 (78–100%): доводим scale→0, opacity→0, blur→18px.
 *
 * Отличия от классических fade-out / height-collapse:
 *   • высоту элемент НЕ схлопывает во время анимации — соседи стоят на
 *     месте, нет резкого «прыжка» ленты вверх (только финальный re-flow);
 *   • glow окрашивается под var(--fx-brand), т.е. шпионит за выбранным
 *     брендом и работает на светлой и тёмной теме одинаково;
 *   • anim короче прежней «dust» (820ms vs 1400ms) — по ощущению
 *     энергичнее, но остаётся плавной (cubic-bezier .2 .8 .2 1).
 *
 * Для старых браузеров без filter/mask — остаётся чистый opacity+scale,
 * что всё ещё выглядит как аккуратный pop-out.
 *
 * Класс остался `.fx-msg--dust` (меняется только анимация) — JS
 * использует тот же selector и то же имя keyframe `fx-msg-dust`. */
@keyframes fx-msg-dust {
	0% {
		opacity: 1;
		transform: translate3d(0, 0, 0) scale(1) rotate(0deg);
		filter: blur(0) saturate(1);
		box-shadow: 0 0 0 0 transparent;
	}
	14% {
		opacity: 1;
		transform: translate3d(0, -1px, 0) scale(1.04) rotate(0deg);
		filter: blur(0) saturate(1.1);
		box-shadow: 0 0 0 4px color-mix(in srgb, var(--fx-brand) 26%, transparent),
			0 8px 26px color-mix(in srgb, var(--fx-brand) 18%, transparent);
	}
	45% {
		opacity: 0.88;
		transform: translate3d(-4px, -6px, 0) scale(0.9) rotate(-1.2deg);
		filter: blur(2px) saturate(1.2);
		box-shadow: 0 0 0 2px color-mix(in srgb, var(--fx-brand) 18%, transparent),
			0 16px 42px color-mix(in srgb, var(--fx-brand) 30%, transparent);
	}
	78% {
		opacity: 0.28;
		transform: translate3d(-10px, -14px, 0) scale(0.56) rotate(-3deg);
		filter: blur(10px) saturate(1.3);
		box-shadow: 0 0 0 0 transparent,
			0 26px 60px color-mix(in srgb, var(--fx-brand) 10%, transparent);
	}
	100% {
		opacity: 0;
		transform: translate3d(-16px, -24px, 0) scale(0.1) rotate(-5deg);
		filter: blur(18px) saturate(1.4);
		box-shadow: 0 0 0 0 transparent;
	}
}
.fx-msg--dust {
	pointer-events: none;
	will-change: transform, opacity, filter, box-shadow;
	transform-origin: 50% 80%;
	/* Высоту НЕ схлопываем, чтобы лента не «прыгала» вверх во время
	   анимации. После animationend JS удаляет элемент и лента пере-
	   строится одним кадром (это незаметно). */
	animation: fx-msg-dust 820ms cubic-bezier(0.2, 0.8, 0.2, 1) forwards;
}
/* Строка-родитель бабла, на котором идёт анимация: гасим возможные
   hover-эффекты и отключаем pointer-events, чтобы ошибочные клики
   не попали в уже «распадающийся» бабл. Высоту строки не трогаем —
   её заморозил JS (inline style), чтобы лента не прыгала. */
.fx-msg--dusting-row {
	pointer-events: none;
}
/* У чужих сообщений бабл «улетает» в противоположную сторону — влево
   чужие, вправо свои — чтобы движение читалось естественно под углом
   «прочь от собеседника». Теперь класс .fx-msg--dust висит не на
   строке, а на `.fx-msg__bubble` — поэтому селекторы переделаны
   под новую структуру. */
.fx-msg.own .fx-msg__bubble.fx-msg--dust { transform-origin: 85% 80%; }
.fx-msg.own .fx-msg__bubble.fx-msg--dust {
	animation-name: fx-msg-dust-own;
}
@keyframes fx-msg-dust-own {
	0% {
		opacity: 1;
		transform: translate3d(0, 0, 0) scale(1) rotate(0deg);
		filter: blur(0) saturate(1);
		box-shadow: 0 0 0 0 transparent;
	}
	14% {
		opacity: 1;
		transform: translate3d(0, -1px, 0) scale(1.04) rotate(0deg);
		filter: blur(0) saturate(1.1);
		box-shadow: 0 0 0 4px color-mix(in srgb, var(--fx-brand) 26%, transparent),
			0 8px 26px color-mix(in srgb, var(--fx-brand) 18%, transparent);
	}
	45% {
		opacity: 0.88;
		transform: translate3d(4px, -6px, 0) scale(0.9) rotate(1.2deg);
		filter: blur(2px) saturate(1.2);
		box-shadow: 0 0 0 2px color-mix(in srgb, var(--fx-brand) 18%, transparent),
			0 16px 42px color-mix(in srgb, var(--fx-brand) 30%, transparent);
	}
	78% {
		opacity: 0.28;
		transform: translate3d(10px, -14px, 0) scale(0.56) rotate(3deg);
		filter: blur(10px) saturate(1.3);
		box-shadow: 0 0 0 0 transparent,
			0 26px 60px color-mix(in srgb, var(--fx-brand) 10%, transparent);
	}
	100% {
		opacity: 0;
		transform: translate3d(16px, -24px, 0) scale(0.1) rotate(5deg);
		filter: blur(18px) saturate(1.4);
		box-shadow: 0 0 0 0 transparent;
	}
}
/* Уважаем системное `prefers-reduced-motion`: оставляем лишь лёгкий
   фейд без тяжёлого filter/scale (эпилепсия/укачивание safety). */
@media (prefers-reduced-motion: reduce) {
	.fx-msg--dust,
	.fx-msg.own.fx-msg--dust {
		animation: none !important;
		filter: none !important;
		box-shadow: none !important;
		transform: none !important;
		opacity: 0;
		transition: opacity 260ms ease;
	}
}

/* Typing-индикатор и «присоединился» делят одну строку. Визуально
   различаются фоном: typing — нейтральный voice; joined — лёгкий
   бренд-тинт с левой акцент-полосой, чтобы новое подключение
   не путалось с «печатает». Переходы плавные. */
.fx-chat-typing {
	/* Горизонтальные отступы = у ленты (14px), чтобы текст не уходил
	   под полосу прокрутки колонки #fx-chat-scroll (scrollbar-gutter). */
	padding: 0 14px 1px;
	color: var(--fx-text-dim);
	font-size: 10px;
	/* Узкий min-height — фиксированный слот, лента не прыгает. */
	min-height: 13px;
	line-height: 12px;
	font-style: italic;
	transition: background 0.2s ease, color 0.2s ease,
		border-color 0.2s ease;
}
/* Резерв места ТОЛЬКО для typing-индикатора — чтобы лента не
   дёргалась, когда «печатает…»/«присоединился» появляется/исчезает.
   Баннер уведомлений теперь рисуется поверх ленты (position: absolute,
   см. .fx-chat-banner ниже), поэтому ему никакой слот не нужен. */
.fenix-chat-wrap #fx-chat-typing[hidden] {
	display: block !important;
	visibility: hidden;
	min-height: 13px;
	padding: 0 14px 1px;
}
.fx-chat-typing--active {
	background: transparent;
}
.fx-chat-typing--joined {
	background: color-mix(in srgb, var(--fx-online) 10%, transparent);
	color: color-mix(in srgb, var(--fx-online) 60%, var(--fx-text));
	font-style: normal;
	border-left: 2px solid color-mix(in srgb, var(--fx-online) 65%, transparent);
	padding-left: 10px;
}
html[scheme='dark'] .fx-chat-typing--joined {
	background: color-mix(in srgb, var(--fx-online) 18%, transparent);
	color: #c8f7dc;
}

/* Toast «вам ответили» — кладётся в правый нижний угол чата,
   плавно «влетает» снизу, сам растворяется через ~7 сек, либо
   закрывается крестиком. Клик по телу тоста — scrollToMessage. */
.fx-chat-toasts {
	position: absolute;
	right: 14px;
	bottom: 84px;
	z-index: 50;
	display: flex;
	flex-direction: column;
	gap: 8px;
	pointer-events: none;
}
.fx-chat-toast {
	pointer-events: auto;
	max-width: 320px;
	min-width: 220px;
	background: var(--fx-bg);
	border: 1px solid var(--fx-border);
	border-left: 3px solid var(--fx-brand);
	color: var(--fx-text);
	padding: 10px 34px 10px 14px;
	border-radius: 10px;
	box-shadow: 0 10px 30px rgba(0, 0, 0, 0.18);
	position: relative;
	cursor: pointer;
	transform: translateY(10px);
	opacity: 0;
	animation: fx-chat-toast-in 0.22s ease forwards;
	font-size: 13px;
}
.fx-chat-toast--hide {
	animation: fx-chat-toast-out 0.3s ease forwards;
}
@keyframes fx-chat-toast-in {
	from { transform: translateY(10px); opacity: 0; }
	to   { transform: translateY(0);    opacity: 1; }
}
@keyframes fx-chat-toast-out {
	from { transform: translateY(0);    opacity: 1; }
	to   { transform: translateY(10px); opacity: 0; }
}
.fx-chat-toast__close {
	position: absolute;
	top: 6px;
	right: 6px;
	width: 22px;
	height: 22px;
	background: transparent;
	border: none;
	color: var(--fx-text-dim);
	font-size: 18px;
	line-height: 1;
	cursor: pointer;
	padding: 0;
	border-radius: 8px;
	transition: background 0.14s ease, color 0.14s ease, transform 0.12s ease;
}
.fx-chat-toast__close:hover,
.fx-chat-toast__close:focus-visible {
	color: var(--fx-danger);
	background: rgba(214, 54, 56, 0.08);
	outline: none;
}
.fx-chat-toast__close:active {
	transform: scale(0.92);
	background: rgba(214, 54, 56, 0.16);
}
html[scheme='dark'] .fx-chat-toast__close:hover,
html[scheme='dark'] .fx-chat-toast__close:focus-visible {
	color: #ff8a8c;
	background: rgba(255, 99, 99, 0.14);
}
html[scheme='dark'] .fx-chat-toast__close:active {
	background: rgba(255, 99, 99, 0.22);
}
.fx-chat-toast__head {
	color: var(--fx-text);
	margin-bottom: 4px;
}
.fx-chat-toast__head strong {
	color: var(--fx-brand);
}
.fx-chat-toast__orig {
	font-size: 12px;
	color: var(--fx-text-dim);
	font-style: italic;
	margin-bottom: 4px;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
.fx-chat-toast__body {
	color: var(--fx-text);
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

.fx-chat-reply {
	display: flex;
	align-items: center;
	gap: 8px;
	padding: 8px 12px;
	background: var(--fx-bg-elev);
	border-top: 1px solid var(--fx-border);
	font-size: 12px;
}
/* Иконка-стрелка «↰» (reply) — занимает место бывшей подписи «Ответ на».
   Цвет бренд, чтобы повторять левый цветной бар в цитате TG-style. */
.fx-chat-reply__icon {
	flex: none;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 22px;
	height: 22px;
	color: var(--fx-brand);
}
.fx-chat-reply__icon svg { display: block; }
.fx-chat-reply__inner {
	flex: 1 1 0;
	/* Flex-row: ник (никогда не режем) + текст-цитата, который
	   занимает оставшееся место и режется многоточием. `min-width: 0`
	   ОБЯЗАТЕЛЕН на flex-ребёнке, иначе intrinsic-ширина текста
	   не даёт контейнеру сжиматься. */
	display: flex;
	align-items: baseline;
	gap: 6px;
	min-width: 0;
	overflow: hidden;
	padding-left: 0;
	border-left: 0;
	border-radius: 0;
}
/* .fx-chat-reply__label больше не используется (стрелка заменила
   надпись «Ответ на»), но оставим правило-no-op на случай,
   если старые шаблоны ещё где-то подсунут элемент — просто скрываем. */
.fx-chat-reply__label {
	display: none;
}
.fx-chat-reply__author {
	color: var(--fx-brand);
	font-weight: 700;
	margin: 0;
	flex: none;
	max-width: 40%;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	/* Ник автора, на чьё сообщение отвечаем, — чуть крупнее базового
	   12px reply-bar, чтобы имя читалось сразу. Высоту бара не трогаем
	   (line-height 1.2), текст цитаты ниже остаётся 12px. */
	font-size: 15px;
	line-height: 1.2;
}
.fx-chat-reply__text {
	color: var(--fx-text);
	flex: 1 1 auto;
	min-width: 0;
	overflow: hidden;
	white-space: nowrap;
	text-overflow: ellipsis;
}
.fx-chat-reply__clear {
	background: transparent;
	border: 0;
	color: var(--fx-text-dim);
	cursor: pointer;
	font-size: 18px;
	line-height: 1;
	padding: 4px 8px;
	border-radius: 8px;
	transition: background 0.14s ease, color 0.14s ease, transform 0.12s ease;
}
.fx-chat-reply__clear:hover,
.fx-chat-reply__clear:focus-visible {
	color: var(--fx-danger);
	background: rgba(214, 54, 56, 0.08);
	outline: none;
}
.fx-chat-reply__clear:active {
	transform: scale(0.92);
	background: rgba(214, 54, 56, 0.16);
}
html[scheme='dark'] .fx-chat-reply__clear:hover,
html[scheme='dark'] .fx-chat-reply__clear:focus-visible {
	color: #ff8a8c;
	background: rgba(255, 99, 99, 0.14);
}
html[scheme='dark'] .fx-chat-reply__clear:active {
	background: rgba(255, 99, 99, 0.22);
}

/* ------ Reply-thumb: миниатюра медиа в composer reply-bar ------
   Вставляется JS'ом перед .fx-chat-reply__inner, если цитируем
   сообщение с photo/video/animation. По размеру — квадрат 36x36
   с CSS-object-fit, иконка-плей для видео рисуется поверх. */
.fx-chat-reply__thumb {
	flex: none;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 36px;
	height: 36px;
	border-radius: 6px;
	overflow: hidden;
	background: var(--fx-bg);
	border: 1px solid var(--fx-border);
}
.fx-chat-reply__thumb .fx-msg__reply-thumb {
	width: 100%;
	height: 100%;
	border: 0;
	border-radius: 0;
}

/* ======================================================================
 * Гостевой CTA-блок. Показывается вместо композера, когда виджет
 * рендерится неавторизованному посетителю (data-guest="1"). Задача —
 * визуально заменить строку ввода: та же высота/отступы, что и у dock,
 * чтобы страница не «дёргалась» при входе/выходе. Внутри — мягкая
 * подсказка слева и кнопка с бренд-градиентом справа.
 * ====================================================================== */
.fx-chat-guest-cta {
	flex: none;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	padding: 10px 14px;
	background: var(--fx-panel-bg);
	border-top: 1px solid var(--fx-border);
	box-shadow: 0 -6px 18px rgba(20, 32, 60, 0.04);
	flex-wrap: wrap;
}
.fx-chat-guest-cta__text {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	font-size: 13.5px;
	line-height: 1.35;
	color: var(--fx-ink, #1f2937);
	flex: 1 1 180px;
	min-width: 0;
}
.fx-chat-guest-cta__icon {
	flex: none;
	color: var(--fx-brand);
}
.fx-chat-guest-cta__btn {
	flex: none;
	display: inline-flex;
	align-items: center;
	gap: 8px;
	padding: 9px 16px;
	border-radius: 10px;
	background: linear-gradient(135deg, var(--fx-brand) 0%, var(--fx-brand-2) 100%);
	color: #fff !important;
	font-weight: 600;
	font-size: 13.5px;
	text-decoration: none !important;
	box-shadow: 0 6px 18px rgba(33, 107, 233, 0.28);
	transition: transform 120ms ease, box-shadow 160ms ease, filter 120ms ease;
}
.fx-chat-guest-cta__btn:hover {
	filter: brightness(1.05);
	transform: translateY(-1px);
	box-shadow: 0 10px 22px rgba(33, 107, 233, 0.34);
}
.fx-chat-guest-cta__btn:active {
	transform: translateY(0);
	filter: brightness(0.96);
}
@media (max-width: 560px) {
	.fx-chat-guest-cta {
		padding: 9px 10px;
		gap: 8px;
		flex-wrap: nowrap;
	}
	.fx-chat-guest-cta__text {
		font-size: 12.5px;
		flex: 1 1 auto;
	}
	.fx-chat-guest-cta__btn {
		padding: 9px 14px;
		font-size: 12.5px;
		flex: none;
	}
}
/* Тёмная тема: текст CTA «Чтобы отправить сообщение…», лоадер истории
   и счётчик онлайн (а также презенс-текст «Подключение…») используют
   переменные --fx-text / --fx-text-dim. На тёмной теме --fx-text-dim
   местами давал почти невидимый оттенок — переопределяем явно, чтобы
   гость точно видел CTA и не думал, что чат сломался. */
html[scheme='dark'] .fx-chat-guest-cta {
	background: var(--fx-surface-1);
	border-color: rgba(255, 255, 255, 0.12);
}
html[scheme='dark'] .fx-chat-guest-cta__text {
	color: #e6edf5;
}
html[scheme='dark'] .fx-chat-feed__loader {
	color: #a9b4c2;
}
html[scheme='dark'] .fx-chat-presence,
html[scheme='dark'] .fx-chat-presence-text {
	color: #a9b4c2;
}
html[scheme='dark'] .fx-chat-feed__day {
	color: #a9b4c2;
}

/* Композер + dock (содержит popover эмодзи, который всплывает над формой) */
.fx-chat-composer-dock {
	position: relative;
	flex: none;
	background: var(--fx-panel-bg);
	border-top: 1px solid var(--fx-border);
}
.fx-chat-composer-dock::before {
	content: '';
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	height: 1px;
	background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--fx-brand) 30%, transparent), transparent);
	pointer-events: none;
	z-index: 1;
}

/* Общий контейнер нижнего composer. На ДЕСКТОПЕ выравнивание
   ВСЕГДА по flex-end (ко дну строки) — иначе при разворачивании
   textarea пользователь видит лёгкое «подпрыгивание» эмодзи/
   скрепки: align-items меняется с center на flex-end, и кнопки
   плавно переезжают вверх-вниз. При высоте одной строки (48px)
   flex-end визуально = center, поэтому одностроковый композер
   смотрится как раньше, но уже без скачка при росте. На мобилке
   кнопки absolute-позиционированы (см. media-queries), там
   align-items не влияет. */
.fx-chat-composer {
	display: flex;
	align-items: flex-end;
	gap: 10px;
	padding: 12px 14px;
	position: relative;
	flex-wrap: nowrap;
	background: transparent;
}

/* Скрепка + счётчик вложений. Счётчик теперь встроен В саму
   кнопку-скрепку (она же attach-btn): при 0 файлов — виден SVG-
   паперклип и клик открывает file-picker, при ≥1 — SVG скрыт,
   показывается цифра-бейдж, клик открывает модалку со списком.
   Отдельной счётчик-кнопки больше нет. */
.fx-chat-attach-cluster {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	order: 0;
	flex: 0 0 auto;
	margin: 0;
	padding: 0;
	max-width: 100%;
}

/* Цифра внутри attach-btn (по умолчанию скрыта). Родитель —
   .fx-chat-tool с position:relative (из общего .fx-chat-tool-базиса
   позиционирование может не быть выставлено; для страховки добавим
   через сам селектор). SVG и цифра занимают один и тот же центр
   кнопки; переключаем через data-has-files. */
.fx-chat-attach-btn {
	position: relative;
}
.fx-chat-attach-btn__num {
	position: absolute;
	inset: 0;
	display: none;
	align-items: center;
	justify-content: center;
	font-weight: 800;
	font-size: 16px;
	line-height: 1;
	font-variant-numeric: tabular-nums;
	color: var(--fx-brand);
	pointer-events: none;
}
.fx-chat-attach-btn[data-has-files] .fx-chat-attach-btn__icon {
	display: none;
}
.fx-chat-attach-btn[data-has-files] .fx-chat-attach-btn__num {
	display: inline-flex;
}
/* Когда файлы приложены — кнопка подсвечивается brand-тинтом
   (визуальный «counter-mode»), чтобы цифра читалась как активный
   бейдж, а не как просто темная цифра на нейтральном фоне. */
.fx-chat-attach-btn[data-has-files] {
	background: color-mix(in srgb, var(--fx-brand) 14%, var(--fx-bg)) !important;
	border-color: color-mix(in srgb, var(--fx-brand) 35%, var(--fx-border)) !important;
	color: var(--fx-brand) !important;
}
html[scheme='dark'] .fx-chat-attach-btn[data-has-files],
body.fenix-chat-force-dark .fx-chat-attach-btn[data-has-files] {
	background: rgba(33, 107, 233, 0.18) !important;
	border-color: rgba(33, 107, 233, 0.5) !important;
	color: #b8d2ff !important;
}
html[scheme='dark'] .fx-chat-attach-btn__num,
body.fenix-chat-force-dark .fx-chat-attach-btn__num {
	color: #b8d2ff;
}
/* Единая кнопка-счётчик вложений — теперь в ОДНОМ ряду кнопок чата
   на десктопе: круглая 48×48, как .fx-chat-tool / .fx-chat-send.
   Внутри — цифра; на hover/focus цифра заменяется крестиком, клик =
   сброс всех вложений. Раньше была мелким 26px «пиллом» и визуально
   выбивалась из линейки 48-px кнопок композера. */
.fx-chat-attach-counter {
	position: relative;
	box-sizing: border-box;
	width: 48px;
	height: 48px;
	min-width: 48px;
	padding: 0;
	margin: 0;
	display: inline-grid;
	grid-template-columns: 1fr;
	place-items: center;
	background: color-mix(in srgb, var(--fx-brand) 12%, var(--fx-bg));
	border: 1px solid color-mix(in srgb, var(--fx-brand) 28%, var(--fx-border));
	border-radius: 50%;
	box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
	cursor: pointer;
	color: var(--fx-brand);
	flex: none;
	transition: background 0.2s ease, border-color 0.2s ease, color 0.2s ease,
		transform 0.2s ease, box-shadow 0.2s ease;
	-webkit-tap-highlight-color: transparent;
}
.fx-chat-attach-counter[hidden] {
	display: none !important;
}
.fx-chat-attach-counter__num,
.fx-chat-attach-counter__x {
	grid-area: 1 / 1;
	line-height: 1;
	user-select: none;
	font-variant-numeric: tabular-nums;
	transition: opacity 0.12s ease;
}
.fx-chat-attach-counter__num {
	font-size: 16px;
	font-weight: 800;
	opacity: 1;
}
.fx-chat-attach-counter__x {
	font-size: 22px;
	font-weight: 700;
	opacity: 0;
	pointer-events: none;
}
.fx-chat-attach-counter:focus-visible {
	/* Клик по счётчику теперь открывает модалку со списком файлов
	   (где у каждого отдельная «×» для точечного удаления). Поэтому
	   убираем красный «danger»-hover, превращающий цифру в крестик —
	   это сбивало с толку: ранее клик = «удалить всё», теперь клик =
	   «открыть список». Hover просто немного ярче brand-тинт. */
	background: color-mix(in srgb, var(--fx-brand) 22%, var(--fx-bg));
	border-color: color-mix(in srgb, var(--fx-brand) 45%, var(--fx-border));
	color: var(--fx-brand);
	outline: none;
}
@media (hover: hover) {
	.fx-chat-attach-counter:hover {
		background: color-mix(in srgb, var(--fx-brand) 22%, var(--fx-bg));
		border-color: color-mix(in srgb, var(--fx-brand) 45%, var(--fx-border));
		color: var(--fx-brand);
		outline: none;
	}
}
/* Скрываем старый «×»-spinner — теперь его роль в модалке у каждого
   файла. Счётчик показывает только число. */
.fx-chat-attach-counter__x {
	display: none !important;
}
.fx-chat-attach-counter__num {
	opacity: 1 !important;
}
html[scheme='dark'] .fx-chat-attach-counter {
	background: rgba(33, 107, 233, 0.14);
	border-color: rgba(33, 107, 233, 0.42);
	color: #b8d2ff;
}
html[scheme='dark'] .fx-chat-attach-counter:focus-visible {
	background: rgba(33, 107, 233, 0.28);
	border-color: rgba(33, 107, 233, 0.6);
	color: #fff;
}
@media (hover: hover) {
	html[scheme='dark'] .fx-chat-attach-counter:hover {
		background: rgba(33, 107, 233, 0.28);
		border-color: rgba(33, 107, 233, 0.6);
		color: #fff;
	}
}

/* ======================================================================
 *  Модалка со списком прикреплённых файлов. Вызывается тапом/кликом
 *  по кнопке-счётчику рядом с send. Показывает имя/размер файла
 *  и отдельный крестик для удаления именно этого файла.
 *  ====================================================================== */
.fx-attach-modal {
	position: fixed;
	inset: 0;
	z-index: 99999;
	background: rgba(20, 24, 32, 0.55);
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 16px;
	animation: fxAttachModalIn 0.16s ease-out;
	-webkit-backdrop-filter: blur(2px);
	backdrop-filter: blur(2px);
}
@keyframes fxAttachModalIn {
	from { opacity: 0; }
	to   { opacity: 1; }
}
.fx-attach-modal__box {
	width: min(420px, calc(100vw - 32px));
	max-height: min(72vh, 560px);
	display: flex;
	flex-direction: column;
	background: var(--fx-bg, #fff);
	color: var(--fx-text, #14171d);
	border: 1px solid var(--fx-border, rgba(0, 0, 0, 0.1));
	border-radius: 16px;
	box-shadow: 0 14px 40px rgba(0, 0, 0, 0.18), 0 2px 6px rgba(0, 0, 0, 0.08);
	overflow: hidden;
}
/* Header одного цвета с корпусом (как у .fx-input-ctx): без «другой
   плашки» сверху, чтобы всплывающее окно вложений смотрелось единым
   с меню действий над сообщением. Разделитель — только тонкая
   border-bottom. */
.fx-attach-modal__head {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 12px;
	padding: 14px 16px;
	border-bottom: 1px solid var(--fx-border);
	background: transparent;
}
.fx-attach-modal__title {
	font-size: 15px;
	font-weight: 700;
	color: var(--fx-text);
	text-align: center;
}
.fx-attach-modal__list {
	list-style: none;
	margin: 0;
	padding: 6px 0;
	overflow-y: auto;
	overscroll-behavior: contain;
	scrollbar-width: none;
	flex: 1 1 auto;
}
.fx-attach-modal__list::-webkit-scrollbar {
	width: 0;
	display: none;
}
.fx-attach-modal__item {
	display: grid;
	grid-template-columns: 1fr auto 36px;
	align-items: center;
	gap: 8px;
	padding: 10px 16px;
	border-bottom: 1px solid color-mix(in srgb, var(--fx-border) 55%, transparent);
	font-size: 14px;
}
.fx-attach-modal__item:last-child {
	border-bottom: 0;
}
.fx-attach-modal__name {
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	color: var(--fx-text);
}
.fx-attach-modal__size {
	color: var(--fx-text-dim);
	font-size: 12px;
	font-variant-numeric: tabular-nums;
	white-space: nowrap;
}
.fx-attach-modal__remove {
	width: 32px;
	height: 32px;
	border: 1px solid color-mix(in srgb, #dc2626 35%, var(--fx-border));
	background: var(--fx-bg);
	color: #dc2626;
	border-radius: 50%;
	cursor: pointer;
	font-size: 18px;
	line-height: 1;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	transition: background 0.12s ease, color 0.12s ease,
		border-color 0.12s ease, transform 0.12s ease;
}
.fx-attach-modal__remove:hover,
.fx-attach-modal__remove:focus-visible {
	background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
	border-color: transparent;
	color: #fff;
	outline: none;
	box-shadow: 0 4px 10px rgba(220, 38, 38, 0.25);
}
.fx-attach-modal__remove:active {
	transform: scale(0.94);
}
html[scheme='dark'] .fx-attach-modal__box {
	background: #1f232b;
	color: #e6ecf5;
	border-color: rgba(255, 255, 255, 0.12);
	box-shadow: 0 14px 40px rgba(0, 0, 0, 0.6), 0 2px 6px rgba(0, 0, 0, 0.3);
}
html[scheme='dark'] .fx-attach-modal__head {
	background: transparent;
	border-color: rgba(255, 255, 255, 0.1);
}
html[scheme='dark'] .fx-attach-modal__item {
	border-color: rgba(255, 255, 255, 0.06);
}
/* Тёмная тема: в покое — прозрачный фон (не белый), чтобы кнопка
   визуально не выпадала из тёмной модалки. Красная рамка + красный
   крестик остаются. На hover/active — тот же залитый красный
   градиент, что и на светлой теме. Пользователь жаловался: «уберите
   белый фон круга вокруг крестика на тёмной теме, при наведении/
   нажатии просто красный кружок как на светлой». */
html[scheme='dark'] .fx-attach-modal__remove {
	background: transparent;
	color: #fca5a5;
	border-color: rgba(220, 38, 38, 0.45);
	box-shadow: none;
}
/* Hover/active для тёмной темы — залитый красный градиент, такой же
   как на светлой, белый крестик и красная тень. Одинаковый «кликный»
   отклик в любой теме. */
html[scheme='dark'] .fx-attach-modal__remove:hover,
html[scheme='dark'] .fx-attach-modal__remove:focus-visible {
	background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
	border-color: transparent;
	color: #fff;
	outline: none;
	box-shadow: 0 4px 10px rgba(220, 38, 38, 0.35);
}
html[scheme='dark'] .fx-attach-modal__remove:active {
	transform: scale(0.94);
	box-shadow: 0 2px 6px rgba(220, 38, 38, 0.3);
}

/* «Добавить» — футер модалки со списком вложений. По центру.
   Показывается, пока pendingFiles.length < 10 (ограничение
   MAX_ATTACH_FILES, см. chat.js). При 10 вложениях JS просто не
   рендерит actions-блок. */
.fx-attach-modal__actions {
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 10px 16px 14px;
	border-top: 1px solid color-mix(in srgb, var(--fx-border) 55%, transparent);
}
.fx-attach-modal__add {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 8px;
	min-height: 40px;
	padding: 0 18px;
	border-radius: 12px;
	border: 1px solid color-mix(in srgb, var(--fx-brand) 35%, var(--fx-border));
	background: color-mix(in srgb, var(--fx-brand) 10%, var(--fx-bg));
	color: var(--fx-brand);
	font: inherit;
	font-size: 14px;
	font-weight: 700;
	cursor: pointer;
	transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease,
		transform 0.12s ease, box-shadow 0.15s ease;
	-webkit-tap-highlight-color: transparent;
}
.fx-attach-modal__add-ico {
	display: inline-flex;
	width: 20px;
	height: 20px;
	align-items: center;
	justify-content: center;
	border-radius: 50%;
	background: color-mix(in srgb, var(--fx-brand) 100%, transparent);
	color: #fff;
	font-size: 16px;
	font-weight: 800;
	line-height: 1;
}
.fx-attach-modal__add:focus-visible {
	outline: none;
	background: color-mix(in srgb, var(--fx-brand) 18%, var(--fx-bg));
	border-color: color-mix(in srgb, var(--fx-brand) 55%, var(--fx-border));
	box-shadow: 0 4px 12px rgba(33, 107, 233, 0.18);
}
@media (hover: hover) {
	.fx-attach-modal__add:hover {
		background: color-mix(in srgb, var(--fx-brand) 18%, var(--fx-bg));
		border-color: color-mix(in srgb, var(--fx-brand) 55%, var(--fx-border));
		transform: translateY(-1px);
		box-shadow: 0 4px 12px rgba(33, 107, 233, 0.18);
	}
}
.fx-attach-modal__add:active {
	transform: scale(0.97);
}
html[scheme='dark'] .fx-attach-modal__add,
body.fenix-chat-force-dark .fx-attach-modal__add {
	background: rgba(33, 107, 233, 0.18);
	border-color: rgba(33, 107, 233, 0.5);
	color: #b8d2ff;
}
html[scheme='dark'] .fx-attach-modal__add:focus-visible,
body.fenix-chat-force-dark .fx-attach-modal__add:focus-visible {
	background: rgba(33, 107, 233, 0.3);
	border-color: rgba(33, 107, 233, 0.65);
	color: #fff;
}
@media (hover: hover) {
	html[scheme='dark'] .fx-attach-modal__add:hover,
	body.fenix-chat-force-dark .fx-attach-modal__add:hover {
		background: rgba(33, 107, 233, 0.3);
		border-color: rgba(33, 107, 233, 0.65);
		color: #fff;
	}
}

@media (max-width: 500px) {
	.fx-attach-modal__box {
		width: calc(100vw - 24px);
		max-height: calc(100vh - 32px);
	}
	.fx-attach-modal__item {
		grid-template-columns: 1fr auto 32px;
		padding: 10px 12px;
		font-size: 13.5px;
	}
}

/* Legacy: старый блок превью из кэша — скрываем полностью. */
.fx-chat-upload-preview { display: none !important; }
.fx-chat-upload-preview__name,
.fx-chat-upload-preview__size { display: none; }

/* Раньше при has-files в input'е отводили +28px справа под отдельный
   counter-кружок. Теперь счётчик встроен в саму кнопку-скрепку слева,
   справа только send — дополнительный отступ не нужен. */

/* Голосовая запись (f3): строка-индикатор над composer, пока
   пользователь удерживает Send. Пульсирующая красная точка и таймер.
   Сам Send получает красный «обводной» эффект через .is-recording. */
.fx-voice-ui {
	order: -1;
	flex: 1 1 100%;
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 8px 12px;
	margin: 0 0 4px;
	border-radius: 12px;
	background: color-mix(in srgb, #d33 10%, var(--fx-bg-elev));
	border: 1px solid color-mix(in srgb, #d33 30%, var(--fx-border));
	color: var(--fx-text);
	font-size: 13px;
}
.fx-voice-ui__dot {
	display: inline-block; width: 12px; height: 12px;
	border-radius: 50%; background: #d33;
	animation: fxVoicePulse 1.2s infinite;
}
@keyframes fxVoicePulse {
	0%,100% { opacity: 1; transform: scale(1); }
	50%     { opacity: 0.3; transform: scale(0.75); }
}
.fx-voice-ui__label { font-weight: 600; color: #d33; letter-spacing: 0.06em; }
.fx-voice-ui__time { font-variant-numeric: tabular-nums; color: var(--fx-text-dim); }
.fx-voice-ui__hint { margin-left: auto; color: var(--fx-text-dim); font-size: 12px; }
.fx-chat-send.is-recording {
	background: #d33 !important;
	box-shadow: 0 0 0 0 rgba(221, 51, 51, 0.7);
	animation: fxVoicePulseBtn 1.2s infinite;
}
/* Во время свайпа влево кнопка уходит в режим «отмена»: мы перестаём
   пульсировать и показываем статичную красную обводку без подсветки,
   чтобы пользователь видел — отпустишь здесь → запись отменится. */
.fx-chat-send.is-recording.is-recording-cancel {
	background: #ba1d1d !important;
	animation: none !important;
	transform: translateX(-6px);
	box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.25) inset;
}
@keyframes fxVoicePulseBtn {
	0%   { box-shadow: 0 0 0 0 rgba(221, 51, 51, 0.6); }
	70%  { box-shadow: 0 0 0 14px rgba(221, 51, 51, 0); }
	100% { box-shadow: 0 0 0 0 rgba(221, 51, 51, 0); }
}

/* Унифицированная «инструментальная» кнопка (emoji / attach) —
   круглая, того же диаметра, что и .fx-chat-send (48×48). На всех
   брейкпоинтах — один и тот же размер, чтобы ряд кнопок выглядел
   цельным и симметричным. */
.fx-chat-tool {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 48px;
	height: 48px;
	background: var(--fx-bg-elev);
	color: var(--fx-text-dim);
	border: 1px solid var(--fx-border);
	border-radius: 50%;
	font-size: 22px;
	line-height: 1;
	padding: 0;
	cursor: pointer;
	transition: color 0.15s, background 0.15s, border-color 0.15s, transform 0.1s,
		box-shadow 0.2s ease;
	flex: none;
	box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
	-webkit-tap-highlight-color: transparent;
	touch-action: manipulation;
}
.fx-chat-tool svg {
	width: 22px;
	height: 22px;
}
/* :hover работает ТОЛЬКО на устройствах с настоящим курсором.
   На тач-устройствах :hover «залипает» после тапа и кнопка выглядит
   нажатой до следующего касания. */
@media (hover: hover) {
	.fx-chat-tool:hover {
		color: var(--fx-brand);
		background: color-mix(in srgb, var(--fx-brand) 10%, var(--fx-bg));
		border-color: color-mix(in srgb, var(--fx-brand) 30%, var(--fx-border));
		transform: translateY(-1px);
	}
}
.fx-chat-tool:active,
.fx-chat-tool.is-active {
	transform: scale(0.96);
	color: var(--fx-brand);
	background: color-mix(in srgb, var(--fx-brand) 16%, var(--fx-bg));
	border-color: color-mix(in srgb, var(--fx-brand) 40%, var(--fx-border));
}

.fx-chat-input {
	flex: 1;
	min-width: 0;
	/* Кнопка expand скрыта, поэтому правый внутренний отступ такой же как левый. */
	padding: 13px 16px;
	resize: none;
	min-height: 48px;
	max-height: 200px;
	/* По умолчанию высоту НЕ анимируем — при наборе/удалении текста
	   autoResize() меняет inline-height каждую миллисекунду, и
	   постоянный transition на 200мс давал «желе»-эффект. Анимируем
	   только когда JS включает `.is-resizing` на доке (expand/collapse
	   по двойному тапу — ~240мс). */
	transition: border-color 0.2s ease, box-shadow 0.2s ease, background 0.2s ease;
	word-wrap: break-word;
	overflow-wrap: anywhere;
	overflow-y: auto;
	white-space: pre-wrap;
	/* Скрываем системную полосу прокрутки полностью — колёсико мыши и touch
	   работают без визуального скроллбара (Firefox/WebKit). На мобильных
	   правило дублируется, для старых движков. */
	scrollbar-width: none;
	-ms-overflow-style: none;
}
/* Плавная анимация свёртки/разворота поля ввода. Класс `.is-resizing`
   ставится JS'ом в setExpanded() на 260мс — ровно на время CSS
   transition'а высоты. Snap'ом при двойном клике/тапе больше не
   меняется — пользователь видит плавное «раскрытие» области
   composer'а, без прыжка смежных кнопок (они align-items: flex-end,
   едут вверх синхронно с высотой поля). */
.fx-chat-composer-dock.is-resizing .fx-chat-input {
	transition: height 0.24s cubic-bezier(0.4, 0, 0.2, 1),
		min-height 0.24s cubic-bezier(0.4, 0, 0.2, 1),
		border-color 0.2s ease, box-shadow 0.2s ease, background 0.2s ease;
	will-change: height;
	/* На время анимации свёртки/разворота прячем вертикальный скролл:
	   иначе на границе переполнения скроллбар мелькает то вкл/выкл, и
	   текст «дёргается» по горизонтали при каждом кадре перехода. */
	overflow-y: hidden;
}
/* Уважение OS-настройки «минимум движения»: отключаем height-анимацию
   и смягчаем transform-эффекты — страдают пользователи с vestibular
   disorders и те, кто хочет экономить батарею. */
@media (prefers-reduced-motion: reduce) {
	.fx-chat-composer-dock.is-resizing .fx-chat-input {
		transition: none !important;
	}
}
.fx-chat-input::-webkit-scrollbar,
.fx-chat-input::-webkit-scrollbar-button {
	display: none !important;
	width: 0 !important;
	height: 0 !important;
}
/* contenteditable-композер: плейсхолдер как у textarea (::placeholder). */
.fenix-chat-wrap .fx-chat-input[contenteditable='true'] {
	position: relative;
}
.fenix-chat-wrap .fx-chat-input[contenteditable='true'].fx-chat-input--empty::before {
	content: attr(data-placeholder);
	color: var(--fx-text-dim);
	opacity: 0.85;
	pointer-events: none;
	position: absolute;
	left: 16px;
	right: 16px;
	top: 13px;
	line-height: 1.5;
	white-space: pre-wrap;
}
/* В свёрнутом мобильном режиме input — 1 строка фикс-высоты, и
   placeholder должен стоять ровно по центру вертикали, а не на
   фиксированных 13px сверху (при 44px/40px высоте это выглядело
   чуть ниже центра). На десктопе / в развёрнутом мобильном оставляем
   top:13px — поле многострочное и placeholder должен начинаться с
   первой строки. */
@media (max-width: 600px) {
	.fenix-chat-wrap .fx-chat-composer-dock:not(.is-expanded) .fx-chat-input[contenteditable='true'].fx-chat-input--empty::before {
		top: 50%;
		transform: translateY(-50%);
		line-height: 1.2;
	}
}
.fenix-chat-wrap .fx-chat-input[contenteditable='true'].fx-chat-input--disabled {
	opacity: 0.55;
	pointer-events: none;
}
/* Кнопки emoji/attach в тёмной теме — такой же «пластиковый» фон и
   та же hover-реакция, как у .fx-chat-send, чтобы вся линейка кнопок
   композера выглядела единообразно. */
html[scheme='dark'] .fx-chat-tool {
	background: var(--fx-surface-2);
	color: var(--fx-text);
	border-color: var(--fx-surface-border);
}
@media (hover: hover) {
	html[scheme='dark'] .fx-chat-tool:hover {
		background: color-mix(in srgb, var(--fx-brand) 16%, var(--fx-surface-1));
		color: var(--fx-brand);
		border-color: color-mix(in srgb, var(--fx-brand) 40%, var(--fx-surface-border));
	}
}
html[scheme='dark'] .fx-chat-tool:active,
html[scheme='dark'] .fx-chat-tool.is-active {
	background: color-mix(in srgb, var(--fx-brand) 22%, var(--fx-surface-1));
	border-color: color-mix(in srgb, var(--fx-brand) 50%, var(--fx-surface-border));
}

/* Режим расширения: 3 строки (~120px) — композер растёт вверх, т.к. он внизу колонки */
.fx-chat-composer-dock.is-expanded .fx-chat-input {
	min-height: 120px;
	max-height: min(42vh, 260px);
}
.fx-chat-send {
	/* По умолчанию — нейтральный «пустой» вид, сочетаемый со светлой и тёмной темой.
	   На hover/focus заливается брендовым градиентом. */
	background: var(--fx-bg-elev);
	color: var(--fx-text-dim);
	border: 1px solid var(--fx-border);
	border-radius: 50%;
	width: 48px;
	height: 48px;
	display: flex;
	align-items: center;
	justify-content: center;
	cursor: pointer;
	transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease,
		transform 0.2s ease, box-shadow 0.2s ease;
	flex: none;
	box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
	position: relative;
	-webkit-tap-highlight-color: transparent;
	touch-action: manipulation;
}
.fx-chat-send svg {
	/* Иконка-«бумажный самолётик» в стиле Telegram.
	   Заливная (fill: currentColor), поэтому оставляем нейтральный
	   «круг» вокруг — 26 × 26 внутри кнопки 48 × 48.
	   translateX(1px) визуально компенсирует оптический центр
	   наклонного самолётика. */
	width: 26px !important;
	height: 26px !important;
	display: block;
	overflow: visible;
	transform: translateX(1px);
	fill: currentColor;
	transition: filter 0.2s ease;
}
/* Hover/focus — тот же мягкий brand-тинт, что и у .fx-chat-tool:
   лёгкий голубоватый фон + brand-цвет иконки, без яркого градиента
   и без агрессивной цветной тени. Так три кнопки композера выглядят
   единообразно в обоих состояниях. */
.fx-chat-send:focus-visible:not([disabled]) {
	background: color-mix(in srgb, var(--fx-brand) 10%, var(--fx-bg));
	color: var(--fx-brand);
	border-color: color-mix(in srgb, var(--fx-brand) 30%, var(--fx-border));
	transform: translateY(-1px);
	box-shadow: 0 2px 6px rgba(0, 0, 0, 0.06);
	outline: none;
}
@media (hover: hover) {
	.fx-chat-send:hover:not([disabled]) {
		background: color-mix(in srgb, var(--fx-brand) 10%, var(--fx-bg));
		color: var(--fx-brand);
		border-color: color-mix(in srgb, var(--fx-brand) 30%, var(--fx-border));
		transform: translateY(-1px);
		box-shadow: 0 2px 6px rgba(0, 0, 0, 0.06);
		outline: none;
	}
}
.fx-chat-send:active:not([disabled]) {
	transform: scale(0.96);
	background: color-mix(in srgb, var(--fx-brand) 16%, var(--fx-bg));
	border-color: color-mix(in srgb, var(--fx-brand) 40%, var(--fx-border));
	box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}
.fx-chat-send[disabled] {
	background: var(--fx-bg-elev);
	color: var(--fx-text-dim);
	border-color: var(--fx-border);
	cursor: not-allowed;
	box-shadow: none;
	transform: none;
	opacity: 0.6;
}

/* Тёмная тема: в покое кнопки чуть светлее фона, на hover — тот же
   мягкий бренд-тинт. ОДИНАКОВО для всех трёх кнопок композера
   (emoji / attach / send), чтобы ряд выглядел единым на всех темах. */
html[scheme='dark'] .fx-chat-send,
html[scheme='dark'] .fx-chat-tool {
	background: var(--fx-surface-2);
	color: var(--fx-text);
	border-color: var(--fx-surface-border);
}
html[scheme='dark'] .fx-chat-send:focus-visible:not([disabled]),
html[scheme='dark'] .fx-chat-tool:focus-visible {
	background: color-mix(in srgb, var(--fx-brand) 16%, var(--fx-surface-1));
	color: var(--fx-brand);
	border-color: color-mix(in srgb, var(--fx-brand) 40%, var(--fx-surface-border));
}
@media (hover: hover) {
	html[scheme='dark'] .fx-chat-send:hover:not([disabled]),
	html[scheme='dark'] .fx-chat-tool:hover {
		background: color-mix(in srgb, var(--fx-brand) 16%, var(--fx-surface-1));
		color: var(--fx-brand);
		border-color: color-mix(in srgb, var(--fx-brand) 40%, var(--fx-surface-border));
	}
}

/* ==== Emoji popover — 5 колонок, 3 видимых ряда, всплывает над композером ====
   Фон/рамка унифицированы с .fx-input-ctx (всплывающее меню действий
   над сообщением), чтобы все контекст-меню чата читались как одно
   семейство и не «мигали» другим оттенком фона на светлой/тёмной теме. */
.fx-chat-emoji {
	position: absolute;
	left: 14px;
	bottom: calc(100% + 10px);
	width: min(320px, calc(100% - 28px));
	background: var(--fx-bg, #fff);
	border: 1px solid var(--fx-border);
	border-radius: 14px;
	padding: 10px;
	display: grid;
	grid-template-columns: repeat(5, 1fr);
	gap: 6px;
	max-height: 192px;
	overflow-y: auto;
	overflow-x: hidden;
	-webkit-overflow-scrolling: touch;
	overscroll-behavior: contain;
	z-index: 20;
	box-shadow: 0 14px 40px rgba(0, 0, 0, 0.18), 0 2px 6px rgba(0, 0, 0, 0.08);
	box-sizing: border-box;
	animation: fx-emoji-pop 0.18s ease-out;
}
html[scheme='dark'] .fx-chat-emoji,
body.fenix-chat-force-dark .fx-chat-emoji {
	background: #1f232b;
	border-color: rgba(255, 255, 255, 0.12);
	box-shadow: 0 14px 40px rgba(0, 0, 0, 0.6), 0 2px 6px rgba(0, 0, 0, 0.3);
}
/* Лёгкий «хвостик» у popover, указывающий на кнопку эмодзи */
.fx-chat-emoji::after {
	content: '';
	position: absolute;
	left: 22px;
	bottom: -7px;
	width: 12px;
	height: 12px;
	background: var(--fx-bg, #fff);
	border-right: 1px solid var(--fx-border);
	border-bottom: 1px solid var(--fx-border);
	transform: rotate(45deg);
	box-shadow: 3px 3px 6px rgba(0, 0, 0, 0.05);
}
html[scheme='dark'] .fx-chat-emoji::after,
body.fenix-chat-force-dark .fx-chat-emoji::after {
	background: #1f232b;
	border-right-color: rgba(255, 255, 255, 0.12);
	border-bottom-color: rgba(255, 255, 255, 0.12);
}
@keyframes fx-emoji-pop {
	from { opacity: 0; transform: translateY(6px) scale(0.98); }
	to   { opacity: 1; transform: translateY(0) scale(1); }
}
.fx-chat-emoji button {
	background: transparent;
	border: 0;
	font-size: 24px;
	line-height: 1;
	padding: 0;
	cursor: pointer;
	border-radius: 10px;
	transition: background 0.15s, transform 0.1s;
	aspect-ratio: 1 / 1;
	min-height: 44px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	-webkit-tap-highlight-color: transparent;
	touch-action: manipulation;
}
.fx-chat-emoji button:hover {
	background: color-mix(in srgb, var(--fx-brand) 14%, transparent);
	transform: scale(1.12);
}
.fx-chat-emoji button:active {
	transform: scale(0.92);
}

/* Лёгкая пульсация кнопки эмодзи во время long-press (подсказка,
   что сейчас откроется стикер-панель). Убирается при отпускании
   или при срабатывании таймера. */
#fx-chat-emoji-btn.is-longpress {
	animation: fx-emoji-longpress 0.42s ease-in forwards;
}
@keyframes fx-emoji-longpress {
	from { transform: scale(1); }
	to   { transform: scale(1.18); }
}

/* ==== Sticker picker (открывается по удержанию кнопки эмодзи) ====
   Фон/рамка — как у .fx-input-ctx (см. комментарий выше у .fx-chat-emoji). */
.fx-chat-stickers {
	position: absolute;
	left: 14px;
	right: 14px;
	bottom: calc(100% + 10px);
	max-width: 420px;
	background: var(--fx-bg, #fff);
	border: 1px solid var(--fx-border);
	border-radius: 14px;
	padding: 8px 8px 10px;
	z-index: 22;
	box-shadow: 0 14px 40px rgba(0, 0, 0, 0.18), 0 2px 6px rgba(0, 0, 0, 0.08);
	box-sizing: border-box;
	animation: fx-emoji-pop 0.18s ease-out;
	display: flex;
	flex-direction: column;
	gap: 6px;
	max-height: min(60vh, 420px);
}
html[scheme='dark'] .fx-chat-stickers,
body.fenix-chat-force-dark .fx-chat-stickers {
	background: #1f232b;
	border-color: rgba(255, 255, 255, 0.12);
	box-shadow: 0 14px 40px rgba(0, 0, 0, 0.6), 0 2px 6px rgba(0, 0, 0, 0.3);
}
/* хвостик намеренно скрыт — панель стикеров большая, ей «пузырёк» только мешает */
.fx-chat-stickers::after { content: none; display: none; }
/* Вкладки поверх панели: «Недавние» + персональные стикер-паки.
   Для админа дополнительно справа — sync-кнопка (⟳). */
.fx-chat-stickers__tabs {
	display: flex;
	align-items: center;
	gap: 4px;
	padding: 12px 4px;
	border-bottom: 1px solid var(--fx-border);
	overflow-x: auto;
	overflow-y: hidden;
	scrollbar-width: thin;
	scrollbar-color: var(--fx-border) transparent;
	-webkit-overflow-scrolling: touch;
}
.fx-chat-stickers__tabs::-webkit-scrollbar { height: 4px; }
.fx-chat-stickers__tabs::-webkit-scrollbar-thumb {
	background: var(--fx-border);
	border-radius: 2px;
}
.fx-chat-stickers__tab {
	flex: 0 0 auto;
	appearance: none;
	background: transparent;
	border: 0;
	padding: 4px 6px;
	border-radius: 8px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 4px;
	cursor: pointer;
	color: var(--fx-text-dim, #98a2b3);
	font: inherit;
	font-size: 12px;
	min-width: 36px;
	height: 36px;
	transition: background 0.15s, color 0.15s;
}
.fx-chat-stickers__tab:hover {
	background: color-mix(in srgb, var(--fx-brand) 10%, transparent);
	color: var(--fx-text, inherit);
}
.fx-chat-stickers__tab.is-active {
	background: color-mix(in srgb, var(--fx-brand) 18%, transparent);
	color: var(--fx-text, inherit);
	box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--fx-brand) 35%, transparent);
}
.fx-chat-stickers__tab-ico {
	font-size: 16px;
	line-height: 1;
}
.fx-chat-stickers__tab-ico-media {
	width: 26px;
	height: 26px;
	object-fit: contain;
	display: block;
	background: transparent;
	pointer-events: none;
}
.fx-chat-stickers__tab-label {
	max-width: 90px;
	overflow: hidden;
	white-space: nowrap;
	text-overflow: ellipsis;
}
/* На экране первая вкладка «Недавние» — с иконкой и подписью;
   у паков показываем только иконку (превью первого стикера), подпись
   убираем, чтобы паков помещалось больше. */
.fx-chat-stickers__tab:not([data-tab="recent"]):not(.fx-chat-stickers__tab--sync)
	.fx-chat-stickers__tab-label {
	display: none;
}
.fx-chat-stickers__tab--sync {
	margin-left: auto;
	color: var(--fx-brand);
	/* Делаем кнопку квадратной (а не растянутой по контенту) и с
	   круглым скруглением, чтобы при вращении иконка ⟳ сохраняла
	   геометрию круга, а не вытягивалась в овал. */
	flex: 0 0 auto;
	width: 36px;
	min-width: 36px;
	height: 36px;
	padding: 0;
	border-radius: 50%;
}
/* Сам глиф ⟳ по умолчанию — inline-элемент переменной ширины
   (font-metrics даёт разную advance/ascent), поэтому при `rotate()`
   он визуально «плывёт» в овал. Фиксируем span как квадратный flex-бокс
   и центрируем глиф — теперь вращение происходит вокруг центра круга
   и сам знак читается как симметричный кружок. */
.fx-chat-stickers__tab--sync .fx-chat-stickers__tab-ico {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 22px;
	height: 22px;
	line-height: 1;
	font-size: 18px;
	transform-origin: 50% 50%;
	will-change: transform;
}
.fx-chat-stickers__tab--sync .fx-chat-stickers__tab-ico svg {
	display: block;
	width: 18px;
	height: 18px;
}
.fx-chat-stickers__tab--sync.is-busy .fx-chat-stickers__tab-ico {
	animation: fx-sticker-sync-spin 1s linear infinite;
}
@keyframes fx-sticker-sync-spin {
	from { transform: rotate(0); }
	to   { transform: rotate(360deg); }
}

.fx-chat-stickers__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	padding: 2px 6px 4px;
	border-bottom: 1px solid var(--fx-border);
}
.fx-chat-stickers__title {
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 0.02em;
	text-transform: uppercase;
	color: var(--fx-text-muted, var(--fx-text-dim, #98a2b3));
}
.fx-chat-stickers__body {
	overflow-y: auto;
	overflow-x: hidden;
	-webkit-overflow-scrolling: touch;
	overscroll-behavior: contain;
	padding: 2px;
	min-height: 80px;
}
.fx-chat-stickers__grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(78px, 1fr));
	gap: 6px;
}
/* Стартовый экран «только недавние» — без ограничения высоты в 2 ряда. */
.fx-chat-stickers__grid--recent-only {
	max-height: none;
}

/* «Недавние» — полоса сверху над гридом выбранного пака.
   Показываем ровно 2 строки; при большем кол-ве — вертикальный скролл
   внутри секции, не пролистывая основной грид. */
.fx-chat-stickers__section--recent {
	margin: 0 0 8px;
	padding: 0 0 8px;
	border-bottom: 1px solid var(--fx-border);
}
.fx-chat-stickers__grid--recent {
	/* 2 ряда по ~78px + gap (6px) = 162px; на мобиле пересчитываем ниже. */
	max-height: calc(78px * 2 + 6px + 4px);
	overflow-y: auto;
	overflow-x: hidden;
	overscroll-behavior: contain;
	scrollbar-width: thin;
	padding-right: 2px;
}
.fx-chat-stickers__grid--recent::-webkit-scrollbar { width: 4px; }
.fx-chat-stickers__grid--recent::-webkit-scrollbar-thumb {
	background: var(--fx-border);
	border-radius: 2px;
}
.fx-chat-stickers__item {
	position: relative;
	appearance: none;
	background: transparent;
	border: 0;
	padding: 6px;
	border-radius: 10px;
	cursor: pointer;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	aspect-ratio: 1 / 1;
	transition: background 0.15s, transform 0.1s;
	-webkit-tap-highlight-color: transparent;
	touch-action: manipulation;
}
.fx-chat-stickers__item img,
.fx-chat-stickers__item video {
	width: 100%;
	height: 100%;
	object-fit: contain;
	pointer-events: none; /* клик ловит кнопка целиком */
	background: transparent;
}
.fx-chat-stickers__item:hover {
	background: color-mix(in srgb, var(--fx-brand) 12%, transparent);
	transform: scale(1.05);
}
.fx-chat-stickers__item:active {
	transform: scale(0.94);
}
.fx-chat-stickers__item.is-sending {
	opacity: 0.5;
	pointer-events: none;
}
.fx-chat-stickers__hint {
	padding: 18px 14px;
	font-size: 13px;
	text-align: center;
	color: var(--fx-text-muted, var(--fx-text-dim, #98a2b3));
	line-height: 1.4;
}
.fx-chat-stickers__hint--loading {
	opacity: 0.7;
}
@media (max-width: 560px) {
	.fx-chat-stickers {
		left: 10px;
		right: 10px;
		max-width: none;
		bottom: calc(100% + 8px);
		padding: 8px;
		max-height: 56vh;
	}
	.fx-chat-stickers__grid {
		grid-template-columns: repeat(auto-fill, minmax(72px, 1fr));
		gap: 5px;
	}
	.fx-chat-stickers__grid--recent {
		max-height: calc(72px * 2 + 5px + 4px);
	}
	.fx-chat-stickers::after { display: none; }
}

.fx-chat-banner {
	/* Баннер уведомлений всплывает поверх ленты (а не раздвигает её),
	   чтобы при появлении/скрытии сообщения оставались на месте. JS
	   уже авто-скрывает его через 5 секунд (см. showBanner() в chat.js).
	   Позиционируемся относительно .fenix-chat-wrap (position:relative);
	   top выставляется JS'ом через --fx-banner-top = высота шапки +
	   видимого select-bar/pin-bar. */
	position: absolute;
	top: var(--fx-banner-top, 52px);
	left: 0;
	right: 0;
	width: 100%;
	box-sizing: border-box;
	z-index: 40;
	padding: 8px 16px;
	font-size: 13px;
	text-align: center;
	font-weight: 600;
	border: 0;
	border-bottom: 1px solid var(--fx-border);
	border-radius: 0;
	box-shadow: none;
	pointer-events: auto;
	transition: background 0.2s, color 0.2s, opacity 0.18s ease;
	/* Базовый фон — на случай, если класс-модификатор не успел
	   примениться: непрозрачный, чтобы текст не «просвечивал» ленту. */
	background: var(--fx-bg-elev);
	color: var(--fx-text);
}
.fx-chat-banner--error {
	background: #fde8ea;
	color: #7a1b22;
	border-bottom-color: #f0b8bd;
}
.fx-chat-banner--success {
	background: #e6f7eb;
	color: #14532d;
	border-bottom-color: #b8dcc4;
}
.fx-chat-banner--info {
	background: #e8f0fe;
	color: #0d3d8c;
	border-bottom-color: #b8cff5;
}
html[scheme='dark'] .fx-chat-banner--error {
	background: #3d2226;
	color: #ffc9c9;
	border-bottom-color: #6b3539;
}
html[scheme='dark'] .fx-chat-banner--success {
	background: #1e3325;
	color: #b8f0c8;
	border-bottom-color: #2d5a3d;
}
html[scheme='dark'] .fx-chat-banner--info {
	background: #1a2740;
	color: #c5d9ff;
	border-bottom-color: #2a4570;
}

#fx-chat-scroll.fx-chat-scroll,
.fx-chat-emoji,
.fx-chat-pinned__body {
	scrollbar-width: thin;
	scrollbar-color: color-mix(in srgb, var(--fx-brand) 35%, var(--fx-border)) transparent;
}
#fx-chat-scroll.fx-chat-scroll::-webkit-scrollbar,
.fx-chat-emoji::-webkit-scrollbar,
.fx-chat-pinned__body::-webkit-scrollbar {
	width: 8px;
	height: 8px;
}
#fx-chat-scroll.fx-chat-scroll::-webkit-scrollbar-track,
.fx-chat-emoji::-webkit-scrollbar-track,
.fx-chat-pinned__body::-webkit-scrollbar-track {
	background: transparent;
}
#fx-chat-scroll.fx-chat-scroll::-webkit-scrollbar-thumb,
.fx-chat-emoji::-webkit-scrollbar-thumb,
.fx-chat-pinned__body::-webkit-scrollbar-thumb {
	background: color-mix(in srgb, var(--fx-brand) 25%, var(--fx-border));
	border-radius: 999px;
	border: 2px solid transparent;
	background-clip: padding-box;
}
#fx-chat-scroll.fx-chat-scroll::-webkit-scrollbar-thumb:hover,
.fx-chat-emoji::-webkit-scrollbar-thumb:hover,
.fx-chat-pinned__body::-webkit-scrollbar-thumb:hover {
	background: color-mix(in srgb, var(--fx-brand) 55%, var(--fx-border));
	background-clip: padding-box;
}
/* Скрываем кнопки-стрелки у всех скроллбаров внутри чата (WebKit) */
#fx-chat-scroll.fx-chat-scroll::-webkit-scrollbar-button,
.fx-chat-emoji::-webkit-scrollbar-button,
.fx-chat-pinned__body::-webkit-scrollbar-button {
	display: none !important;
	height: 0;
	width: 0;
}

/* Адаптив */
@media (max-width: 900px) {
	.fenix-chat-wrap {
		height: calc(100vh - 240px);
		min-height: 440px;
		border-radius: 12px;
	}
	.fx-chat-header {
		padding: 14px;
		grid-template-columns: 1fr auto 1fr;
	}
	/* Поисковая строка — на всю ширину шапки (grid-row: 2), никакого
	   узкого «бокса», как в старом варианте. Совпадает по геометрии
	   с .fx-chat-input снизу. */
	.fx-chat-search-wrap .fx-chat-search {
		flex: 1 1 auto;
		width: 100%;
		max-width: none;
		min-width: 0;
	}
}

/* ======================================================================
 * ВАРИАНТ 1: /my-account/account-chat/  → body.fenix-chat-support-page
 * ----------------------------------------------------------------------
 * Чат в колонке My Account — в потоке страницы: видна навигация ЛК,
 * хедер сайта, нижняя панель; страница прокручивается (в т.ч. на
 * мобильном — без fullscreen «только хедер + чат + bottom bar»).
 * Футер на этой странице скрыт (см. правила ниже).
 * -------------------------------------------------------------------- */
body.fenix-chat-support-page .woocommerce-MyAccount-content {
	padding-left: 0 !important;
	padding-right: 0 !important;
	max-width: none !important;
}
body.fenix-chat-support-page .woocommerce-MyAccount-content > .fenix-chat-wrap,
body.fenix-chat-support-page .woocommerce-MyAccount-content .fenix-chat-wrap {
	margin-top: 0;
	margin-left: 0;
	margin-right: 0;
	width: 100%;
	max-width: 100%;
	overflow: hidden; /* страховка — абсолютные child'ы (online-panel) не вылезают */
}
body.fenix-chat-support-page .fenix-chat-wrap #fx-chat-scroll.fx-chat-scroll {
	/* Колонка скролла забирает оставшееся место внутри wrap'а.
	   min-height:0 обязателен в flex-колонке. */
	flex: 1 1 0;
	min-height: 0;
	overflow-y: auto;
}

/* ---- Мобильный ЛК: оборачиваем чат в аккуратный «карточный» контейнер ----
   Раньше на мобильных /my-account/account-chat/ чат растягивался во всю
   ширину колонки WooCommerce без полей и выглядел обрезанным.
   Теперь даём боковые отступы, скруглённые углы, лёгкую тень и убираем
   max-height фида — лента внутри карточки прокручивается нормально, а
   сама страница ЛК продолжает скроллиться. */
@media (max-width: 900px) {
	/* Контейнер чата по ширине совпадает с навигационной панелью ЛК.
	   JS (measureAccountNavSync) пишет --fx-account-nav-w / -left =
	   реальная ширина/отступ от левого края у .woocommerce-MyAccount-navigation.
	   Fallback — 100% ширины колонки (как было до правки).
	   Селектор расширен: не только .fenix-chat-support-page, но и любой
	   .woocommerce-account, где .fenix-chat-wrap лежит в MyAccount-content.
	   Это нужно когда body-class не проставился (кастомный URL rewrite). */
	body.fenix-chat-support-page .woocommerce-MyAccount-content > .fenix-chat-wrap,
	body.fenix-chat-support-page .woocommerce-MyAccount-content .fenix-chat-wrap,
	body.woocommerce-account .woocommerce-MyAccount-content .fenix-chat-wrap {
		box-sizing: border-box;
		/* Левый отступ повторяет отступ nav внутри его колонки
		   (JS пишет --fx-account-nav-left относительно
		   .woocommerce-MyAccount-content). Width — ширина nav, но
		   не больше ширины вьюпорта минус суммарный отступ слева,
		   чтобы на XS-экранах контейнер гарантированно не вылезал
		   за правый край окна. */
		margin: 8px 0 8px var(--fx-account-nav-left, 0);
		width: min(
			var(--fx-account-nav-w, 100%),
			calc(100vw - var(--fx-account-nav-left, 0px) - 16px)
		);
		max-width: 100%;
		border-radius: 16px;
		border: 1px solid var(--fx-border, rgba(0, 0, 0, 0.08));
		background: var(--fx-bg, #fff);
		box-shadow: 0 4px 16px rgba(0, 0, 0, 0.06);
		overflow: hidden;
		/* Мобилка: чат = окно минус сайтовая шапка/низ. Фиксированная
		   высота, лента внутри скроллится. Здесь перекрываем десктоп-
		   правило и задаём «полноэкранный» режим — nav-меню ЛК и сам
		   чат занимают всю оставшуюся высоту.
		   Плюс: вычитаем --fx-kbd-offset (JS кладёт туда высоту
		   мобильной клавиатуры через visualViewport) — иначе при
		   открытии клавиатуры «фикс-высота» не сжимается, композер
		   поднимается браузером, а лента остаётся за клавиатурой. */
		height: calc(100dvh - var(--fx-site-header-h, 56px) - var(--fx-site-bottom-h, 0px) - var(--fx-kbd-offset, 0px) - 20px);
		max-height: none;
		min-height: min(78dvh, calc(100dvh - var(--fx-site-header-h, 56px) - var(--fx-site-bottom-h, 0px) - var(--fx-kbd-offset, 0px) - 20px));
	}
	/* Когда клавиатура открыта — прибиваем контейнер чата фиксированно
	   к экрану, чтобы вся карточка (лента + композер) ехала вместе,
	   а не уезжала за клавиатуру. На <html> вешаем `is-fx-kbd-open`
	   из JS (см. watchVisualViewport в chat.js) — он единственный
	   честный триггер, т.к. CSS не видит visualViewport напрямую. */
html.is-fx-kbd-open body.fenix-chat-support-page .woocommerce-MyAccount-content .fenix-chat-wrap,
html.is-fx-kbd-open body.woocommerce-account .woocommerce-MyAccount-content .fenix-chat-wrap,
html.is-fx-kbd-opening body.fenix-chat-support-page .woocommerce-MyAccount-content .fenix-chat-wrap,
html.is-fx-kbd-opening body.woocommerce-account .woocommerce-MyAccount-content .fenix-chat-wrap {
	position: fixed !important;
	top: calc(var(--fx-site-header-h, 56px) + var(--fx-wp-adminbar-h, 0px) + env(safe-area-inset-top, 0px)) !important;
	left: env(safe-area-inset-left, 0px) !important;
	right: env(safe-area-inset-right, 0px) !important;
	/* Нижняя граница — МАКСИМУМ из двух вариантов:
	     1) над клавиатурой (kbd-offset + 2px зазор от ввода),
	     2) над фикс-панелью `wp-bottom-menu` (site-bottom-h + safe-area).
	   Максимум нужен из-за трёх сценариев:
	     • клавиатура ОТКРЫТА (kbd-offset >> site-bottom-h) → чат
	       сидит над клавой, wp-bottom-menu и так спрятано за ней;
	     • клавиатура ЗАКРЫВАЕТСЯ (is-fx-kbd-opening ещё стоит, но
	       kbd-offset=0) — раньше чат проваливался за wp-bottom-menu на
	       доли секунды, пользователь жаловался: «часто видно, что страница
	       уходит за эту панель». Теперь фолбэк держит чат над панелью;
	     • клавиатура не появилась вовсе (focusout до открытия) →
	       тот же фолбэк на site-bottom-h. */
	bottom: max(
		calc(var(--fx-kbd-offset, 0px) + 2px),
		calc(var(--fx-site-bottom-h, 0px) + env(safe-area-inset-bottom, 0px))
	) !important;
		width: auto !important;
		max-width: none !important;
		height: auto !important;
		min-height: 0 !important;
		max-height: none !important;
		margin: 0 !important;
		border-radius: 0 !important;
		z-index: 40;
	}
	/* .fenix-chat-shortcode-wrap — сам шорткод-враппер иногда создаёт
	   боковые поля > вьюпорта (например через inline-padding темы).
	   На мобилке обнуляем его, чтобы вложенный .fenix-chat-wrap не
	   вылезал за правый край. */
	body.woocommerce-account .woocommerce-MyAccount-content .fenix-chat-shortcode-wrap {
		margin-left: 0;
		margin-right: 0;
		padding-left: 0;
		padding-right: 0;
		max-width: 100%;
		overflow: hidden;
	}
	body.fenix-chat-support-page .fenix-chat-wrap #fx-chat-scroll.fx-chat-scroll,
	body.woocommerce-account .woocommerce-MyAccount-content .fenix-chat-wrap #fx-chat-scroll.fx-chat-scroll {
		flex: 1 1 0;
		min-height: 0;
		max-height: none;
		overflow-y: auto;
	}
	/* Композер внутри карточки — плотнее, без лишнего зазора по краям. */
	body.fenix-chat-support-page .fenix-chat-wrap .fx-chat-composer-dock,
	body.woocommerce-account .woocommerce-MyAccount-content .fenix-chat-wrap .fx-chat-composer-dock {
		border-top: 1px solid var(--fx-border, rgba(0, 0, 0, 0.08));
	}
}
/* ----------------------------------------------------------------------
 * Десктоп ЛК (≥901px): навигация WooCommerce и чат — один flex-ряд,
 * верхние границы колонок на одной линии, высота чата = высота ряда
 * (stretch). Без float, без JS margin/height на #fenix-chat-root.
 * -------------------------------------------------------------------- */
@media (min-width: 901px) {
	body.woocommerce-account.woocommerce-account-chat .woocommerce,
	body.woocommerce-account.fenix-chat-support-page .woocommerce,
	body.fenix-chat-support-page.woocommerce-account .woocommerce {
		display: flex !important;
		flex-flow: row nowrap !important;
		align-items: stretch !important;
		justify-content: flex-start !important;
		gap: clamp(16px, 2vw, 28px) !important;
		width: 100% !important;
		max-width: 100% !important;
		margin: 0 !important;
		float: none !important;
		clear: both !important;
		box-sizing: border-box !important;
	}

	body.woocommerce-account.woocommerce-account-chat .woocommerce-MyAccount-navigation,
	body.woocommerce-account.fenix-chat-support-page .woocommerce-MyAccount-navigation,
	body.fenix-chat-support-page.woocommerce-account .woocommerce-MyAccount-navigation {
		float: none !important;
		width: clamp(200px, 24%, 280px) !important;
		min-width: 200px !important;
		max-width: 280px !important;
		flex: 0 0 clamp(200px, 22%, 280px) !important;
		margin: 0 !important;
		align-self: stretch !important;
		box-sizing: border-box !important;
	}

	body.woocommerce-account.woocommerce-account-chat .woocommerce-MyAccount-content,
	body.woocommerce-account.fenix-chat-support-page .woocommerce-MyAccount-content,
	body.fenix-chat-support-page.woocommerce-account .woocommerce-MyAccount-content {
		float: none !important;
		width: auto !important;
		flex: 1 1 0% !important;
		min-width: 0 !important;
		max-width: none !important;
		margin: 0 !important;
		padding-top: 0 !important;
		padding-left: 0 !important;
		padding-right: 0 !important;
		display: flex !important;
		flex-direction: column !important;
		align-items: stretch !important;
		align-self: stretch !important;
		box-sizing: border-box !important;
	}

	body.woocommerce-account.woocommerce-account-chat .woocommerce-MyAccount-content > .woocommerce-notices-wrapper:empty,
	body.woocommerce-account.fenix-chat-support-page .woocommerce-MyAccount-content > .woocommerce-notices-wrapper:empty,
	body.fenix-chat-support-page.woocommerce-account .woocommerce-MyAccount-content > .woocommerce-notices-wrapper:empty {
		display: none !important;
		margin: 0 !important;
		padding: 0 !important;
		min-height: 0 !important;
		height: 0 !important;
		overflow: hidden !important;
		flex: 0 0 0 !important;
	}

	body.woocommerce-account.woocommerce-account-chat .woocommerce-MyAccount-content > .fenix-chat-shortcode-wrap,
	body.woocommerce-account.fenix-chat-support-page .woocommerce-MyAccount-content > .fenix-chat-shortcode-wrap,
	body.fenix-chat-support-page.woocommerce-account .woocommerce-MyAccount-content > .fenix-chat-shortcode-wrap,
	body.woocommerce-account.woocommerce-account-chat .woocommerce-MyAccount-content .fenix-chat-shortcode-wrap,
	body.woocommerce-account.fenix-chat-support-page .woocommerce-MyAccount-content .fenix-chat-shortcode-wrap,
	body.fenix-chat-support-page.woocommerce-account .woocommerce-MyAccount-content .fenix-chat-shortcode-wrap {
		flex: 1 1 auto !important;
		min-height: 0 !important;
		display: flex !important;
		flex-direction: column !important;
		margin: 0 !important;
		margin-top: 0 !important;
		padding: 0 !important;
		max-width: 100% !important;
		box-sizing: border-box !important;
	}

	body.woocommerce-account.woocommerce-account-chat .woocommerce-MyAccount-content #fenix-chat-root.fenix-chat-wrap,
	body.woocommerce-account.fenix-chat-support-page .woocommerce-MyAccount-content #fenix-chat-root.fenix-chat-wrap,
	body.fenix-chat-support-page.woocommerce-account .woocommerce-MyAccount-content #fenix-chat-root.fenix-chat-wrap,
	body.woocommerce-account.woocommerce-account-chat .woocommerce-MyAccount-content > .fenix-chat-wrap,
	body.woocommerce-account.fenix-chat-support-page .woocommerce-MyAccount-content > .fenix-chat-wrap,
	body.woocommerce-account.woocommerce-account-chat .woocommerce-MyAccount-content .fenix-chat-wrap,
	body.woocommerce-account.fenix-chat-support-page .woocommerce-MyAccount-content .fenix-chat-wrap,
	body.fenix-chat-support-page.woocommerce-account .woocommerce-MyAccount-content .fenix-chat-wrap {
		flex: 1 1 auto !important;
		min-height: 0 !important;
		height: auto !important;
		max-height: none !important;
		margin: 0 !important;
		margin-top: 0 !important;
		width: 100% !important;
		max-width: 100% !important;
		align-self: stretch !important;
		box-sizing: border-box !important;
	}

	body.fenix-chat-support-page .woocommerce-MyAccount-content > .fenix-chat-shortcode-wrap,
	body.fenix-chat-support-page .woocommerce-MyAccount-content .fenix-chat-shortcode-wrap,
	body.woocommerce-account .woocommerce-MyAccount-content > .fenix-chat-shortcode-wrap,
	body.woocommerce-account .woocommerce-MyAccount-content .fenix-chat-shortcode-wrap {
		margin-top: 0 !important;
		margin-bottom: 0 !important;
		padding-top: 0 !important;
		padding-bottom: 0 !important;
	}

	body.fenix-chat-support-page .fenix-chat-wrap #fx-chat-scroll.fx-chat-scroll,
	body.woocommerce-account .woocommerce-MyAccount-content .fenix-chat-wrap #fx-chat-scroll.fx-chat-scroll {
		max-height: none;
		min-height: 0;
	}
}
body.fenix-chat-support-page .fenix-chat-wrap .fx-chat-header,
body.fenix-chat-support-page .fenix-chat-wrap .fx-chat-composer {
	width: 100%;
	max-width: none;
	box-sizing: border-box;
}

/* В ЛК на узкой ширине скрываем футер (как «экран чата»): хедер виден,
   страница скроллится. На десктопе (≥901) футер не трогаем — обычный ЛК,
   в отличие от отдельной страницы со шорткодом (там футер скрыт только
   в мобильном fullscreen-блоке ниже). Селекторы ловят Blogsy/WP подвалы;
   на мобильных при клавиатуре футер иначе мелькал в зазоре под чатом. */
@media (max-width: 900px) {
	body.fenix-chat-support-page footer,
	body.fenix-chat-support-page footer.site-footer,
	body.fenix-chat-support-page #site-footer,
	body.fenix-chat-support-page .blogsy-site-footer,
	body.fenix-chat-support-page #colophon,
	body.fenix-chat-support-page .site-footer,
	body.fenix-chat-support-page .footer-widgets,
	body.fenix-chat-support-page .pt-footer,
	body.fenix-chat-support-page .pt-footer-wrapper,
	body.fenix-chat-support-page .pt-footer-widgets,
	body.fenix-chat-support-page .pt-header {
		display: none !important;
	}
}

body.fenix-chat-support-page .woocommerce-MyAccount-content .woocommerce-message,
body.fenix-chat-support-page .woocommerce-MyAccount-content .woocommerce-info,
body.fenix-chat-support-page .woocommerce-MyAccount-content .woocommerce-error {
	border-radius: 10px;
	border-left-width: 4px;
	font-size: 14px;
	line-height: 1.45;
}

body.fenix-chat-support-page .woocommerce-MyAccount-content .woocommerce-message {
	border-left-color: var(--fx-brand, #216be9);
}

/* ======================================================================
 * Компенсация WordPress admin-bar.
 * ----------------------------------------------------------------------
 * Используется переменная `--fx-wp-adminbar-h` в calc() для `.fenix-chat-wrap`
 * (см. блок ниже). Раньше пробовали и форсить admin-bar в fixed, и двигать
 * pt-header — оба варианта ломали макет на «обычных» страницах у админа.
 *
 * Рабочая конфигурация (подтверждена пользователем на /chat-support/ и
 * /my-account/account-chat/):
 *   • На ДЕСКТОПЕ (≥783px) admin-bar 32px, WP сама подмешивает
 *     `html { margin-top: 32px !important }`, тема Polite/Blogsy сама
 *     двигает свой fixed pt-header — вмешиваться не надо.
 *     Переменная = 32px, чтобы .fenix-chat-wrap учитывал admin-bar
 *     в calc(top).
 *   • На МОБИЛЬНЫХ (≤782px) admin-bar 46px и позиционирован absolute
 *     (WP так решил для узких экранов: он уезжает при прокрутке).
 *     `html { margin-top: 46px }` + position:absolute admin-bar ВМЕСТЕ
 *     уже дают корректный макет — контент сайта и наш pt-header
 *     ложатся ниже admin-bar без нашей помощи.
 *     Поэтому в calc(top) для .fenix-chat-wrap мы НЕ прибавляем 46px
 *     (иначе чат «проваливается» ниже экрана на высоту admin-bar).
 *     Переменная = 0px.
 * -------------------------------------------------------------------- */
body.admin-bar {
	--fx-wp-adminbar-h: 32px;
}
@media screen and (max-width: 782px) {
	body.admin-bar {
		/* 0, а не 46px: на мобильных WP уже компенсирует admin-bar
		   margin-ом на html; дублирующий сдвиг в calc() даёт «дыру»
		   под фиксированным чатом. */
		--fx-wp-adminbar-h: 0px;
	}
}

/* ======================================================================
 * ВАРИАНТ 2: публичная страница с шорткодом [fenix_chat]
 * → body.fenix-chat-shortcode-page (напр. https://fenix-gsm.com/chat-support/)
 * ----------------------------------------------------------------------
 * Десктоп (≥901px): обычная вёрстка темы — контейнер, футер, заголовки
 * страницы не скрываем; виджет наследует базовые правила .fenix-chat-wrap.
 *
 * Мобильные (≤900px): «полноэкранный» режим между шапкой сайта и
 * .wp-bottom-menu + safe-area; блокировка скролла у html включается в JS
 * только на узкой ширине (fenix-chat-page-lock).
 *
 * Переменные измеряет JS (chat.js → siteGeometryLayer):
 *   --fx-site-header-h, --fx-site-bottom-h.
 * -------------------------------------------------------------------- */

/* ---------- Десктоп: страница со шорткодом как обычная страница темы ------- */
@media (min-width: 901px) {
	body.fenix-chat-shortcode-page {
		overflow: visible !important;
	}
	body.fenix-chat-shortcode-page .single-content.card-layout-w {
		border: none !important;
		box-shadow: none !important;
		border-radius: 0 !important;
		background: transparent !important;
	}
	/* Вошедший пользователь на /chat-support: окно чата крупнее и ближе
	   к шапке. Тема даёт большой воздух сверху (.pt-row margin-top:50px +
	   паддинги карточки 20+20 + отступы заголовка) — сокращаем его; высоту
	   виджета поднимаем с базовых 100vh−280/max740 до 100vh−220/max1000. */
	body.fenix-chat-shortcode-page:not(.fenix-chat-shortcode-page--guest) .pt-row.page-content-wrapper {
		margin-top: 14px !important;
	}
	body.fenix-chat-shortcode-page:not(.fenix-chat-shortcode-page--guest) article.single-content.card-layout-w,
	body.fenix-chat-shortcode-page:not(.fenix-chat-shortcode-page--guest) .single-content-inner {
		padding-top: 10px !important;
		padding-bottom: 10px !important;
	}
	body.fenix-chat-shortcode-page:not(.fenix-chat-shortcode-page--guest) .single-page-title {
		margin-top: 0 !important;
		margin-bottom: 12px !important;
		padding-bottom: 0 !important;
	}
	body.fenix-chat-shortcode-page:not(.fenix-chat-shortcode-page--guest) .fenix-chat-wrap {
		height: calc(100vh - 220px) !important;
		max-height: 1000px !important;
		min-height: 600px !important;
	}
}

/* Кнопка перевода чата показывается и на публичной /chat-support/:
   она независимa от выбранного языка сайта (fenix-multilang в шапке).
   RU/EN label = target language; клик переключает направление перевода
   и применяет ко всей ленте. */

/* ---------- Только мобильные: статичная подложка под чат ------------------- */
@media (max-width: 900px) {
	html.fenix-chat-page-lock,
	html.fenix-chat-page-lock body.fenix-chat-shortcode-page {
		overflow: hidden !important;
		/* overflow-x на html+body снимает горизонтальный скролл на iPhone,
		   если внутри что-то вылезает за viewport (safe-area у notch-а,
		   длинный заголовок и т.п.). */
		overflow-x: hidden !important;
		height: 100% !important;
		max-height: 100% !important;
		max-width: 100vw !important;
		/* position: static — не ломаем позиционирование внутренних
		   fixed-элементов темы (их координаты отсчитываются от
		   ближайшего positioned-предка; relative на html сделал бы
		   предком именно html и ломал стейджинг pt-header/admin-bar).
		   Значения подтверждены на проде. */
		position: static;
		overscroll-behavior: none;
	}
	body.fenix-chat-shortcode-page {
		overflow: hidden !important;
		overflow-x: hidden !important;
		max-width: 100vw !important;
		/* Заливаем html/body фоном, совпадающим с композером чата
		   (`--fx-panel-bg` = rgba(33,107,233,0.03) на белом / var в dark),
		   чтобы в момент transition'а клавиатуры (между старой и новой
		   позицией `.fenix-chat-wrap bottom`) в зазоре не мелькал
		   футер/белый фон страницы. Пользователь жаловался: «на долю
		   секунды вижу футер сайта при разворачивании и сворачивании
		   клавиатуры». Теперь за чатом стабильно такой же оттенок,
		   что и в композере — визуально разрыва не видно. */
		background: var(--fx-panel-bg, #f5f8ff) !important;
	}
	html.fenix-chat-page-lock {
		background: var(--fx-panel-bg, #f5f8ff) !important;
	}
	html[scheme='dark'].fenix-chat-page-lock,
	html[scheme='dark'] body.fenix-chat-shortcode-page {
		background: var(--fx-bg, #0f141b) !important;
	}

	/* Узкая ширина — убираем типичный «лишний» край страницы,
	   скрываем элементы ниже основного блока как на отдельном экране чата.
	   Селекторы покрывают темы Blogsy (`#site-footer`, `.blogsy-site-footer`,
	   `.pt-footer*`), стандартный WP (`.site-footer`, `#colophon`), а также
	   виджет-зоны и хлебные крошки. Пользователь жаловался: «на мобильных
	   на долю секунды вижу футер сайта при сворачивании/разворачивании
	   клавиатуры» — раньше Blogsy-футер по `#site-footer`/`.blogsy-site-footer`
	   ни одним селектором не ловился и во время transition'а клавиатуры
	   успевал мелькнуть в зазоре под чатом. */
	body.fenix-chat-shortcode-page footer,
	body.fenix-chat-shortcode-page footer.site-footer,
	body.fenix-chat-shortcode-page .site-footer,
	body.fenix-chat-shortcode-page #site-footer,
	body.fenix-chat-shortcode-page .blogsy-site-footer,
	body.fenix-chat-shortcode-page .footer-widgets,
	body.fenix-chat-shortcode-page #colophon,
	body.fenix-chat-shortcode-page .pt-footer,
	body.fenix-chat-shortcode-page .pt-footer-wrapper,
	body.fenix-chat-shortcode-page .pt-footer-widgets,
	body.fenix-chat-shortcode-page .pt-breadcrumb,
	body.fenix-chat-shortcode-page .pt-page-title,
	body.fenix-chat-shortcode-page .breadcrumb,
	body.fenix-chat-shortcode-page .woocommerce-breadcrumb,
	body.fenix-chat-shortcode-page .entry-header,
	body.fenix-chat-shortcode-page .page-title,
	body.fenix-chat-shortcode-page .post-navigation,
	body.fenix-chat-shortcode-page .comments-area,
	body.fenix-chat-shortcode-page .widget-area,
	body.fenix-chat-shortcode-page .secondary,
	body.fenix-chat-shortcode-page #secondary,
	body.fenix-chat-shortcode-page .site-widget,
	body.fenix-chat-shortcode-page .sidebar,
	body.fenix-chat-shortcode-page .pt-header {
		display: none !important;
	}

	body.fenix-chat-shortcode-page #content,
	body.fenix-chat-shortcode-page .site-main,
	body.fenix-chat-shortcode-page .entry-content,
	body.fenix-chat-shortcode-page .container,
	body.fenix-chat-shortcode-page .pt-page-wrapper,
	body.fenix-chat-shortcode-page .fenix-chat-shortcode-wrap {
		padding: 0 !important;
		margin: 0 !important;
		width: 100% !important;
		max-width: none !important;
		min-height: 0 !important;
	}

	body.fenix-chat-shortcode-page .fenix-chat-wrap {
		position: fixed !important;
		top: calc(var(--fx-wp-adminbar-h, 0px) + env(safe-area-inset-top, 0px)) !important;
		/* Учитываем safe-area-inset слева/справа (landscape iPhone с
		   «ушами» от Dynamic Island / home-indicator), иначе на таких
		   устройствах виджет либо частично за экраном, либо уходит
		   под закругления. На портретном iPhone env() = 0 → ничего
		   не меняется. */
		left: env(safe-area-inset-left, 0px) !important;
		right: env(safe-area-inset-right, 0px) !important;
		/* --fx-kbd-offset выставляет JS на основе window.visualViewport
		   (когда открывается софт-клавиатура на iOS/Android). Без него
		   position:fixed-чат уходит ПОД клавиатуру и между полем ввода
		   и клавой остаётся огромный пустой зазор. */
		bottom: calc(var(--fx-site-bottom-h, 0px) + env(safe-area-inset-bottom, 0px) + var(--fx-kbd-offset, 0px)) !important;
		width: auto !important;
		max-width: none !important;
		height: auto !important;
		min-height: 0 !important;
		max-height: none !important;
		margin: 0 !important;
		border-radius: 0 !important;
		border: none !important;
		box-shadow: none !important;
		z-index: 40;
		display: flex;
		flex-direction: column;
		/* не даём содержимому клипаться об нижнюю границу экрана */
		box-sizing: border-box;
	}
	body.fenix-chat-shortcode-page #fx-chat-scroll.fx-chat-scroll {
		flex: 1 1 auto !important;
		min-height: 0 !important;
		overflow-y: auto;
		overflow-x: hidden;
		-webkit-overflow-scrolling: touch;
	}
	body.fenix-chat-shortcode-page .fx-chat-composer {
		flex: 0 0 auto;
		background: var(--fx-panel-bg);
		/* БЕЗ собственного border-top — composer-dock уже имеет свой.
		   Дубль border-top на тёмной теме создавал тонкую полоску
		   между блоками (пользователь жаловался на «мелкие полосочки
		   в переходе между блоками по центру»). */
		border-top: 0;
		padding-bottom: max(10px, env(safe-area-inset-bottom));
		box-sizing: border-box;
	}
	/* Защита от стыков между composer-dock, reply-bar, typing-indicator,
	   addressed-bar и emoji-panel на тёмной теме: унифицируем их фоны
	   и убираем повторяющиеся border-top'ы (один от composer-dock уже
	   есть — этого достаточно). */
	body.fenix-chat-shortcode-page .fx-chat-reply,
	body.fenix-chat-shortcode-page .fx-chat-typing,
	body.fenix-chat-shortcode-page #fx-chat-addressed,
	body.fenix-chat-shortcode-page .fx-chat-guest-cta {
		border-top: 0;
	}
	body.fenix-chat-shortcode-page .fx-chat-composer-dock::before {
		display: none;
	}
	body.fenix-chat-shortcode-page .fx-chat-header {
		flex: 0 0 auto;
		box-sizing: border-box;
	}
	/* Клавиатура открыта на шорткод-странице: убираем --fx-site-bottom-h
	   из нижнего отступа wrap — иначе между верхним краем клавиатуры и
	   композером остаётся пустая полоса в высоту фикс-меню (КАТЕГОРИИ/
	   ПОИСК/ЧАТ/ЗАКАЗЫ). При закрытой клавиатуре правило выше работает
	   как раньше. Параллельно убираем safe-area-inset-bottom на iOS
	   (он и так уходит в 0 при открытой клавиатуре) и padding-bottom
	   у композера, чтобы ввод прижимался ровно под клавиатуру.
	   Также применяем те же стили для упреждающего `is-fx-kbd-opening` —
	   он ставится на focusin ДО того как viewport реально изменится,
	   чтобы между фокусом и выездом клавиатуры не мелькал футер сайта. */
	html.is-fx-kbd-open body.fenix-chat-shortcode-page .fenix-chat-wrap,
	html.is-fx-kbd-opening body.fenix-chat-shortcode-page .fenix-chat-wrap {
		/* См. комментарий у .woocommerce-MyAccount-content правила:
		   max() между высотой клавиатуры и wp-bottom-menu — чтобы
		   ни клава, ни фикс-панель сайта НЕ перекрывали композер. */
		bottom: max(
			calc(var(--fx-kbd-offset, 0px) + 2px),
			calc(var(--fx-site-bottom-h, 0px) + env(safe-area-inset-bottom, 0px))
		) !important;
	}
	/* Ранее тут было padding-bottom: 0 !important — это сдвигало
	   абсолютно-позиционированные иконки эмодзи/вложения вверх на
	   ~10px относительно текстового поля (они якорятся bottom:16px
	   к композеру, а композер резко уменьшался по высоте). Вернули
	   обычный `max(10px, env(safe-area-inset-bottom))` — иконки
	   остаются ровно по вертикали центра поля ввода, на iOS при
	   открытой клавиатуре env()=0 и отступ деградирует в 10px.
	   Щель между композером и клавиатурой закрывает `+2px` в
	   bottom'е wrap'а выше. */
	/* Жёсткое выравнивание иконок (эмодзи/вложения/мик) и поля ввода
	   по базовой линии внутри композера: во время подъёма клавиатуры
	   переносы между icons и input не должны анимироваться (раньше
	   пользователь видел, как иконки на доли секунды «подпрыгивают»
	   относительно поля ввода, пока CSS-транзишны пересчитывают
	   размеры). Транзишны выключаем именно в переходное состояние,
	   в покое они работают как раньше. */
	html.is-fx-kbd-opening .fx-chat-composer,
	html.is-fx-kbd-opening .fx-chat-composer *,
	html.is-fx-kbd-opening .fx-chat-composer-dock,
	html.is-fx-kbd-opening .fx-chat-composer-dock * {
		transition: none !important;
		animation: none !important;
	}
}

/* ----------------------------------------------------------------------
 * Гость на публичной /chat-support/: чата нет, показываем карточку
 * .fenix-chat-guest → отменяем агрессивные правила «занять весь
 * экран» (они нужны только самому виджету чата), возвращаем
 * обычный поток темы — чтобы карточка уважала хедер/футер сайта
 * и выглядела как полноценная страница-заглушка.
 * -------------------------------------------------------------------- */
body.fenix-chat-shortcode-page--guest,
html.fenix-chat-page-lock body.fenix-chat-shortcode-page--guest {
	overflow: auto !important;
	height: auto !important;
	max-height: none !important;
}
body.fenix-chat-shortcode-page--guest #content,
body.fenix-chat-shortcode-page--guest .site-main,
body.fenix-chat-shortcode-page--guest .entry-content,
body.fenix-chat-shortcode-page--guest .container,
body.fenix-chat-shortcode-page--guest .pt-page-wrapper,
body.fenix-chat-shortcode-page--guest .fenix-chat-shortcode-wrap {
	padding: revert !important;
	margin: revert !important;
	width: auto !important;
	max-width: revert !important;
	min-height: revert !important;
}
body.fenix-chat-shortcode-page--guest footer.site-footer,
body.fenix-chat-shortcode-page--guest .site-footer,
body.fenix-chat-shortcode-page--guest #colophon,
body.fenix-chat-shortcode-page--guest .pt-footer,
body.fenix-chat-shortcode-page--guest .pt-footer-wrapper,
body.fenix-chat-shortcode-page--guest .pt-footer-widgets,
body.fenix-chat-shortcode-page--guest .pt-breadcrumb,
body.fenix-chat-shortcode-page--guest .pt-page-title,
body.fenix-chat-shortcode-page--guest .breadcrumb,
body.fenix-chat-shortcode-page--guest .woocommerce-breadcrumb,
body.fenix-chat-shortcode-page--guest .entry-header,
body.fenix-chat-shortcode-page--guest .page-title,
body.fenix-chat-shortcode-page--guest .post-navigation,
body.fenix-chat-shortcode-page--guest .comments-area,
body.fenix-chat-shortcode-page--guest .widget-area,
body.fenix-chat-shortcode-page--guest .secondary,
body.fenix-chat-shortcode-page--guest #secondary,
body.fenix-chat-shortcode-page--guest .site-widget,
body.fenix-chat-shortcode-page--guest .sidebar {
	display: revert !important;
}
body.fenix-chat-shortcode-page--guest .pt-header {
	display: revert !important;
}
/* У гостя страница выглядит как обычная статическая страница темы —
   отменяем все «full-screen»-правила .fenix-chat-wrap, которые нужны
   только для самого виджета чата (логин). Карточка-заглушка сидит
   внутри обычного потока, не является fixed-обёрткой. */
body.fenix-chat-shortcode-page--guest .fenix-chat-wrap,
body.fenix-chat-shortcode-page--guest .fenix-chat-shortcode-wrap {
	position: static !important;
	top: auto !important;
	left: auto !important;
	right: auto !important;
	bottom: auto !important;
	width: auto !important;
	max-width: none !important;
	height: auto !important;
	max-height: none !important;
	margin: revert !important;
	padding: revert !important;
	z-index: auto !important;
}
/* Гостевая карточка: симметричные боковые отступы (сверху = снизу). */
body.fenix-chat-shortcode-page--guest .fenix-chat-guest,
body.fenix-chat-support-page--guest .fenix-chat-guest {
	padding: 16px;
	box-sizing: border-box;
}
/* Убираем дубль заголовка «Chat • Support» в entry-header темы —
   он совпадает с контентом карточки и создаёт визуальный
   шум на гостевой странице. Лента/меню/breadcrumbs остаются. */
body.fenix-chat-shortcode-page--guest .entry-header,
body.fenix-chat-shortcode-page--guest .page-title,
body.fenix-chat-shortcode-page--guest .pt-page-title,
body.fenix-chat-shortcode-page--guest .single-page-title {
	display: none !important;
}
/* Для гостя на WC-endpoint'е тоже снимаем «full-screen chat» layout. */
body.fenix-chat-support-page--guest .woocommerce-MyAccount-content {
	height: auto !important;
	max-height: none !important;
}

/* Мобильная раскладка message-tools. Ранее попап был жёстко ограничен
   шириной пузыря (через CSS-переменную --fx-tools-w) — но для узких
   «ок/эмодзи-реакция» пузырей ряд из 6 смайлов + кнопка «⋯» туда не
   влезал и переносился/ломался. Новое поведение:
     • минимальная ширина = ширина бабла, НО не меньше ~280px,
       чтобы все эмодзи+многоточие гарантированно поместились;
     • попап может быть ШИРЕ пузыря (разрешаем расширение);
     • у своих сообщений растём ВЛЕВО (right-aligned), у чужих — ВПРАВО
       (left-aligned) — выравнивание задают .fx-msg.own и .fx-msg:not(.own).
   Кнопка «Reply» заменена свайпом-влево — в тулбаре её скрываем. */
@media (max-width: 768px) {
	.fx-msg__tools {
		/* на мобилке попап занимает почти всю строку чата: минимум 280px
		   (чтобы 8 смайлов + «⋯» влезли), максимум = viewport−16. */
		min-width: min(calc(100vw - 16px), max(var(--fx-tools-w, 0px), 280px));
		max-width: calc(100vw - 16px);
		width: auto;
	}
	/* Жёстко прижимаем тулбар к той же крайней стороне строки,
	   что и на десктопе: у своих к правому краю ленты, у чужих —
	   к левому краю (включая колонку аватара). Без margin-*:auto
	   на iOS Safari флекс-item после wrap иногда уезжал к
	   противоположной стороне. */
	.fx-msg.own .fx-msg__tools {
		margin-right: 0;
		margin-left: auto;
	}
	.fx-msg:not(.own) .fx-msg__tools {
		margin-left: 0;
		margin-right: auto;
	}
	/* Ряд реакций подстраивается под узкий бабл — смайлы чуть ужимаем,
	   ряд нельзя разрывать, кнопки gap минимизируем. */
	.fx-msg__tools-row--emoji { gap: 0; }
	.fx-msg__tools-row--emoji .fx-msg__react { padding: 6px 0; font-size: 18px; }
	.fx-msg__tools-more { padding: 6px 6px; min-width: 28px; }
}
/* Раньше на мобильных (<=600px) скрывали кнопку Reply (оправдание —
   «есть свайп влево»). Из-за этого у админа под сообщением виден
   меньший набор действий, чем на десктопе. Пользователь попросил
   паритет: возвращаем Reply на мобильном, чтобы все доступные
   роли-дейcтвия были на виду одним набором. Свайп продолжает
   работать как быстрый шорткат. */

/* ======================================================================
 * Мобильный select-bar: счётчик на отдельной строке сверху,
 * ниже — 3 кнопки в одном ряду равной ширины: [Отмена][Все][Удалить].
 * Ряд на всю ширину, без margin-left:auto. Порядок берём flexbox order.
 * -------------------------------------------------------------------- */
@media (max-width: 600px) {
	.fx-chat-select-bar {
		flex-direction: column;
		align-items: stretch;
		gap: 8px;
		padding: 10px 12px;
	}
	.fx-chat-select-bar__count {
		order: 1;
		text-align: center;
		font-weight: 600;
		padding: 2px 0;
	}
	.fx-chat-select-bar__cancel {
		order: 2;
		flex: 1 1 0;
	}
	.fx-chat-select-bar__actions {
		order: 3;
		margin-left: 0;
		display: flex;
		gap: 8px;
		width: 100%;
	}
	.fx-chat-select-bar__actions > * { flex: 1 1 0; }
	/* Собираем все три кнопки в один ряд через отдельный wrapper —
	   вместо этого «поднимаем» cancel внутрь actions визуально:
	   делаем её grid-sibling через позиционирование. Проще: ставим
	   весь row [cancel | all | delete] flex row на одной строке. */
	.fx-chat-select-bar {
		display: grid;
		grid-template-columns: 1fr 1fr 1fr;
		grid-template-rows: auto auto auto;
		column-gap: 8px;
		row-gap: 8px;
	}
	.fx-chat-select-bar__count {
		grid-column: 1 / -1;
		grid-row: 1;
	}
	.fx-chat-select-bar__cancel {
		grid-column: 1 / -1;
		grid-row: 2;
	}
	/* Actions (Выделить все / Скопировать / Удалить) — отдельной строкой,
	   три равных колонки. На «узких» экранах (<380px) перенос на
	   две строки, чтобы текст не резался. */
	.fx-chat-select-bar__actions {
		grid-column: 1 / -1;
		grid-row: 3;
		width: auto;
		display: grid;
		grid-template-columns: 1fr 1fr 1fr;
		gap: 8px;
	}
	.fx-chat-select-bar__actions > * { flex: none; }
	.fx-chat-select-bar__all,
	.fx-chat-select-bar__copy,
	.fx-chat-select-bar__delete,
	.fx-chat-select-bar__cancel {
		white-space: nowrap;
		min-width: 0;
		padding-left: 10px;
		padding-right: 10px;
	}
}
@media (max-width: 380px) {
	.fx-chat-select-bar__actions {
		grid-template-columns: 1fr 1fr;
	}
	.fx-chat-select-bar__delete {
		grid-column: 1 / -1;
	}
}

@media (max-width: 600px) {
	/* На мобильных убираем «двойной контейнер» — кейс, когда вокруг
	   виджета рисуется рамка/тень/скруглённый угол, а сам он уже
	   находится внутри карточки WooCommerce. Делаем его flush:
	   без своего border/shadow/radius, во всю ширину экрана.
	   ВАЖНО: ширину берём через `width: 100%` + margin-inline без
	   отрицательного значения больше, чем реальный padding родителя
	   (оно могло выходить за viewport и создавать горизонтальный
	   скролл на iPhone). Используем только `max-width: 100vw`, чтобы
	   виджет гарантированно не шире экрана. */
	.fenix-chat-wrap {
		height: calc(100dvh - 180px);
		min-height: 380px;
		max-height: none;
		border-radius: 0;
		border: none;
		box-shadow: none;
		margin-left: calc(-1 * var(--fx-mobile-inset, 16px));
		margin-right: calc(-1 * var(--fx-mobile-inset, 16px));
		width: calc(100% + 2 * var(--fx-mobile-inset, 16px));
		max-width: 100vw;
		box-sizing: border-box;
		overflow-x: hidden;
	}
	/* Единый «шов» между лентой и композером: только 1 border-top на
	   композер-доке. Остальные промежуточные блоки (reply/typing/
	   addressed/guest-cta/banner) свои border-top'ы сбрасывают —
	   на тёмной теме раньше они рисовали несколько очень тонких
	   параллельных полосок у низа экрана. */
	.fenix-chat-wrap .fx-chat-reply,
	.fenix-chat-wrap .fx-chat-typing,
	.fenix-chat-wrap #fx-chat-addressed,
	.fenix-chat-wrap .fx-chat-guest-cta,
	.fenix-chat-wrap .fx-chat-banner {
		border-top: 0;
	}
	.fenix-chat-wrap .fx-chat-composer-dock::before {
		display: none;
	}
	.fx-chat-header {
		grid-template-columns: auto 1fr auto;
		gap: 8px 8px;
		padding: 12px 12px;
	}
	/* Уменьшаем горизонтальный зазор между кнопками справа и
	   между title-wrap слева, чтобы 4 правые кнопки
	   (notif/info/translate/search) + 2 левые (tg/presence)
	   гарантированно помещались в шапке на мобильных (на 360-px
	   устройствах они раньше налезали друг на друга). */
	.fx-chat-title-wrap { gap: 6px; }
	.fx-chat-actions    { gap: 6px; }
	.fx-chat-tg-btn,
	.fx-chat-search-toggle,
	.fx-chat-ig-btn,
	.fenix-chat-wrap .fx-chat-info-toggle,
	.fenix-chat-wrap .fx-chat-notif-toggle {
		width: 40px;
		height: 40px;
	}
	.fx-chat-tg-btn svg,
	.fx-chat-search-toggle svg,
	.fx-chat-ig-btn svg,
	.fx-chat-info-toggle__icon,
	.fx-chat-notif-toggle__icon {
		width: 20px;
		height: 20px;
	}
	/* Поиск — идентичная textarea композера (без иконки-лупы, без
	   левого отступа под неё). */
	.fx-chat-search-wrap .fx-chat-search {
		width: 100%;
		max-width: none;
		min-height: 48px;
		line-height: 1.4;
		border-radius: 14px;
		padding: 13px 16px;
		box-shadow: 0 1px 2px rgba(0, 0, 0, 0.02);
	}
	.fx-chat-sub-meta {
		display: none; /* средняя колонка больше не используется на мобилке */
	}
	.fx-chat-presence-count {
		width: 40px;
		height: 40px;
		min-width: 40px;
		min-height: 40px;
	}
	.fx-chat-presence-count__num {
		font-size: 14px;
	}
	.fx-msg {
		max-width: 94%;
	}
	.fx-chat-emoji {
		left: 10px;
		right: 10px;
		width: calc(100% - 20px);
		max-width: none;
		bottom: calc(100% + 8px);
		padding: 10px;
		max-height: 50vh;
		grid-template-columns: repeat(5, 1fr);
	}
	/* F27 — мобильный fmt-bar: базовые правила см. в override-блоке
	   в конце файла (`@media (max-width: 560px) #fx-chat-composer-dock .fx-chat-fmt-bar`).
	   Там мы размещаем bar поверх attach-cluster (same right/bottom)
	   и прячем саму группу эмодзи+скрепка, пока `.is-fmt-open` активен. */
	.fx-chat-emoji::after {
		left: 18px;
	}
	.fx-chat-emoji button {
		font-size: 22px;
		min-height: 46px;
	}
	/* Мобильный композер v2 (по запросу пользователя):
	   Фикс-сетка из 3 элементов, НИЧЕГО не прыгает при фокусе/
	   выделении/смене режима.
	     [FMT 2×2] [input 2 строки]  [SEND центр]
	     [CL  1×2]
	   Слева колонка из 3-х рядов (2 ряда B/I+U/S формат-кнопок и 1 ряд
	   эмодзи+скрепка). Справа — кнопка отправки, вертикально по центру.
	   В центре — поле ввода фикс-высотой ≈ 2 строки, длинный текст
	   скроллится ВНУТРИ него. Композер не растёт/не сжимается вообще.
	   Всё это — позиционированием absolute относительно dock'а. */
	.fx-chat-composer-dock {
		position: relative;
	}
	.fx-chat-composer {
		position: static;
		display: block;
		padding: 10px 12px;
		/* Высота композера теперь зависит от is-expanded: свёрнутый —
		   одна строка (≈ 64px с паддингами), развёрнутый — две строки
		   + fmt-bar-колонка слева (≈ 120px), как раньше.
		   Дефолт ставим свёрнутый, развёрнутый переопределяется ниже. */
		min-height: 64px;
		gap: 0;
		contain: layout;
		transition: min-height 0.24s cubic-bezier(.2,.8,.2,1);
	}
	.fx-chat-composer-dock.is-expanded .fx-chat-composer {
		min-height: 158px;
	}
	/* ──── Левая колонка.
	   Свёрнутый режим (default, !is-expanded):
	     • fmt-bar ПОЛНОСТЬЮ скрыт — кнопки стилей шрифта недоступны
	       пока поле одной строкой (пользователь просил сделать поле
	       «как телеграм»-компакт пока не редактируешь стили);
	     • cluster — один ряд с 😊/📎, вертикально центрирован на
	       высоте input'а.
	   Развёрнутый режим (is-expanded):
	     • fmt-bar 2×2 в верхнем-левом углу (B/I/U/S);
	     • cluster 2×2 чуть ниже fmt-bar'а (как было раньше). */
	#fx-chat-fmt-bar {
		position: absolute;
		top: 10px;
		left: 12px;
		display: none !important;
		grid-template-columns: 30px 30px;
		/* 6 кнопок (B/I/U/S + моноширный + спойлер) → 2×3. Новые две —
		   верхним рядом (см. order ниже). Композер растёт по высоте. */
		grid-template-rows: 30px 30px 30px;
		gap: 6px;
		z-index: 3;
		margin: 0;
		padding: 0;
		background: transparent;
		border: 0;
		box-shadow: none;
		animation: none;
		opacity: 1;
		pointer-events: auto;
		transform: none;
		transition: none;
	}
	.fx-chat-composer-dock.is-expanded #fx-chat-fmt-bar {
		display: grid !important;
	}
	/* Если JS поставит hidden — в развёрнутом режиме всё равно
	   форсим (layout статичный, прятать нечего); в свёрнутом пусть
	   скрывается. */
	.fx-chat-composer-dock.is-expanded #fx-chat-fmt-bar[hidden] {
		display: grid !important;
	}
	#fx-chat-attach-cluster {
		position: absolute;
		left: 12px;
		z-index: 3;
		pointer-events: auto;
		/* Свёрнутый режим по умолчанию: 😊 и 📎 в один ряд, по центру
		   вертикально относительно input'а (input ≈ 44px, cluster ≈ 30px,
		   зазор = 7px сверху/снизу от композера с padding 10px).
		   Top считаем так: композер min-height 64px, cluster высота 30,
		   центр: (64-30)/2 = 17. */
		top: 17px;
		display: grid;
		grid-template-columns: 30px 30px;
		grid-template-rows: 30px;
		gap: 6px;
		transition: top 0.24s cubic-bezier(.2,.8,.2,1);
	}
	.fx-chat-composer-dock.is-expanded #fx-chat-attach-cluster {
		/* Развёрнутый режим: под fmt-bar'ом (теперь 3 ряда):
		   10 + 30 + 6 + 30 + 6 + 30 + 6 = 118px. */
		top: 118px;
	}
	/* Единый стиль для всех 6 кнопок в левой колонке: круглые 30×30,
	   видимый фон из surface-токенов + тонкая рамка, hover заливается
	   brand-тинтом. Визуальная ритмика повторяет кнопки в шапке чата
	   (языковой переключатель, статистика), чтобы вся UI выглядела
	   как единый set. */
	#fx-chat-fmt-bar .fx-fmt-toolbar__btn,
	.fx-chat-attach-cluster .fx-chat-tool,
	#fx-chat-emoji-btn,
	#fx-chat-attach-btn,
	#fx-chat-attach-counter {
		width: 30px;
		height: 30px;
		min-width: 30px;
		min-height: 30px;
		padding: 0;
		margin: 0;
		border-radius: 50%;
		display: inline-flex;
		align-items: center;
		justify-content: center;
		background: var(--fx-surface-1);
		border: 1px solid var(--fx-surface-border);
		box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
		color: var(--fx-text-dim);
		font-size: 16px;
		line-height: 1;
		cursor: pointer;
		touch-action: manipulation;
		-webkit-user-select: none;
		user-select: none;
		-webkit-tap-highlight-color: transparent;
		transition: background-color 0.12s ease, color 0.12s ease,
			border-color 0.12s ease, transform 0.12s ease;
	}
	/* `@supports (hover: hover)` — hover-эффект применяется ТОЛЬКО
	   на устройствах с настоящим курсором (мышь/трекпад). На
	   тач-устройствах :hover «залипает» после тапа, пока
	   пользователь не коснётся другого элемента — из-за этого
	   кнопки выглядят нажатыми даже после того, как их действие
	   уже завершилось (например, открыт file-picker). :focus-visible
	   без :hover — оставляем: он срабатывает только на клавиатурной
	   навигации (Tab), а не на тапе. */
	@media (hover: hover) {
		#fx-chat-fmt-bar .fx-fmt-toolbar__btn:hover,
		.fx-chat-attach-cluster .fx-chat-tool:hover,
		#fx-chat-emoji-btn:hover,
		#fx-chat-attach-btn:hover {
			background: color-mix(in srgb, var(--fx-brand) 14%, var(--fx-bg)) !important;
			border-color: color-mix(in srgb, var(--fx-brand) 35%, var(--fx-surface-border)) !important;
			color: var(--fx-brand) !important;
			transform: translateY(-1px);
			outline: none;
			box-shadow: 0 4px 10px rgba(33, 107, 233, 0.12) !important;
		}
	}
	#fx-chat-fmt-bar .fx-fmt-toolbar__btn:focus-visible,
	.fx-chat-attach-cluster .fx-chat-tool:focus-visible,
	#fx-chat-emoji-btn:focus-visible,
	#fx-chat-attach-btn:focus-visible {
		background: color-mix(in srgb, var(--fx-brand) 14%, var(--fx-bg)) !important;
		border-color: color-mix(in srgb, var(--fx-brand) 35%, var(--fx-surface-border)) !important;
		color: var(--fx-brand) !important;
		outline: none;
		box-shadow: 0 4px 10px rgba(33, 107, 233, 0.12) !important;
	}
	#fx-chat-fmt-bar .fx-fmt-toolbar__btn:active,
	.fx-chat-attach-cluster .fx-chat-tool:active,
	#fx-chat-emoji-btn:active,
	#fx-chat-attach-btn:active {
		transform: scale(0.94);
	}
	#fx-chat-fmt-bar .fx-fmt-toolbar__btn.is-active {
		background: color-mix(in srgb, var(--fx-brand) 24%, var(--fx-bg)) !important;
		border-color: color-mix(in srgb, var(--fx-brand) 55%, var(--fx-surface-border)) !important;
		color: var(--fx-brand) !important;
	}
	/* Без активного выделения текста кнопки стиля становятся disabled:
	   визуально приглушены, не реагируют на hover/tap. JS выставляет
	   `disabled` на каждую кнопку через syncFmtBarActiveStates. Так
	   пользователь видит, что B/I/U/S — только для выделенного текста. */
	#fx-chat-fmt-bar .fx-fmt-toolbar__btn[disabled],
	#fx-chat-fmt-bar .fx-fmt-toolbar__btn[aria-disabled='true'] {
		opacity: 0.4 !important;
		cursor: not-allowed !important;
		pointer-events: none;
		background: var(--fx-surface-1) !important;
		border-color: var(--fx-surface-border) !important;
		color: var(--fx-text-dim) !important;
		box-shadow: none !important;
		transform: none !important;
	}
	#fx-chat-fmt-bar .fx-fmt-toolbar__btn svg {
		width: 14px;
		height: 14px;
	}
	/* Новые кнопки (моноширный, спойлер) — верхним рядом сетки 2×3,
	   над привычными B/I/U/S. order:-1 ставит их первыми в auto-flow. */
	#fx-chat-fmt-bar .fx-fmt-toolbar__btn[data-cmd='code'],
	#fx-chat-fmt-bar .fx-fmt-toolbar__btn[data-cmd='spoiler'] {
		order: -1;
	}
	#fx-chat-emoji-btn {
		font-size: 18px;
	}
	#fx-chat-attach-btn svg {
		width: 16px;
		height: 16px;
	}
	.fx-chat-attach-counter__num {
		font-size: 12px;
	}
	.fx-chat-attach-counter__x {
		font-size: 14px;
	}

	/* ──── Input.
	   Свёрнутый режим (default): 44px = одна строка. Левый margin 78px —
	   под 😊/📎 в один ряд (cluster left:12 + 30+6+30 = 78). Правый —
	   под кнопку отправки. Высота фиксирована → поле не растёт при
	   вводе, длинный текст скроллится внутри.
	   Развёрнутый режим (is-expanded): 100px ≈ две строки, margin-left
	   74px под 2×2 fmt-bar+cluster колонку. `!important` нужен, чтобы
	   autoResize() (JS, inline-height) не перебил. Плавный переход
	   между режимами — через .is-resizing (transition height/min-height). */
	.fx-chat-input {
		font-size: 15px;
		line-height: 1.4;
		min-height: 44px !important;
		max-height: 44px !important;
		height: 44px !important;
		border-radius: 16px;
		padding: 10px 14px;
		margin-left: 78px;
		margin-right: 50px;
		scrollbar-width: none;
		overflow-y: auto;
	}
	.fx-chat-composer-dock.is-expanded .fx-chat-input {
		/* Высота подогнана под левую колонку 3 ряда fmt + кластер:
		   10(top) + 30+6+30+6+30 (fmt) + 6 + 30 (кластер) = 148 → 138 высота
		   поля (top 10 → низ 148, вровень с низом кластера). */
		min-height: 138px !important;
		max-height: 138px !important;
		height: 138px !important;
		margin-left: 74px;
	}
	/* Плавный transition между режимами — включается из JS через
	   .is-resizing, как и на десктопе. */
	.fx-chat-composer-dock.is-resizing .fx-chat-input,
	.fx-chat-composer-dock.is-resizing .fx-chat-composer {
		transition: height 0.24s cubic-bezier(.2,.8,.2,1),
			min-height 0.24s cubic-bezier(.2,.8,.2,1),
			max-height 0.24s cubic-bezier(.2,.8,.2,1),
			margin-left 0.24s cubic-bezier(.2,.8,.2,1);
	}
	.fx-chat-input::-webkit-scrollbar,
	.fx-chat-input::-webkit-scrollbar-button {
		display: none !important;
		width: 0 !important;
		height: 0 !important;
	}
	/* При загрузке файлов счётчик вложений появляется в кластере как
	   3-й grid-item — cluster вырастает в 2 ряда, fmt-bar остаётся на
	   месте (оверлап между fmt-bar и cluster невозможен, т.к.
	   cluster верх 82px + макс 66px высота = 148 что укладывается в
	   мин-120 dock'а — чуть наезжает на input. Ввод padding'а отжимает
	   от кнопок — не беда, cluster поверх input по z-index). */
	.fx-chat-attach-counter {
		order: 3;
	}

	/* ──── Send: на правом крае, вертикально по центру композера.
	   Центрируем через `top:0; bottom:0; margin:auto` — этот метод
	   НЕ использует transform, поэтому hover/active могут свободно
	   применять scale/translate без риска сорвать центровку.
	   Раньше было `top:50%; transform:translateY(-50%)` — и при тапе
	   по кнопке срабатывало `:active { transform: scale(0.96) }`,
	   которое ПЕРЕПИСЫВАЛО translateY → кнопка теряла центровку и
	   визуально прыгала вниз. Пользователь жаловался: «кнопка
	   отправить смещается из центра вниз при нажатии». */
	.fx-chat-send {
		position: absolute;
		right: 12px;
		top: 0;
		bottom: 0;
		margin: auto 0;
		width: 40px;
		height: 40px;
	}
	/* В мобильной раскладке композера hover-эффект с translateY(-1px)
	   не нужен (нет мыши), а active scale(0.96) работает без
	   transform-override — кнопка остаётся на месте. */
	.fx-chat-send:hover:not([disabled]),
	.fx-chat-send:focus-visible:not([disabled]) {
		transform: none;
	}
	.fx-chat-send svg {
		width: 22px !important;
		height: 22px !important;
	}
	/* Счётчик теперь встроен в attach-btn — отдельной кнопки нет,
	   send остаётся стандартного размера и на своём месте независимо
	   от наличия вложений. Цифра внутри attach-btn на мобильном — с
	   размером под 30×30 кнопку (14px достаточно для «1»–«10»). */
	.fx-chat-attach-btn[data-has-files] .fx-chat-attach-btn__num {
		font-size: 14px;
	}
}

/* Супер-узкие экраны (<= ~420px): на 4 правые кнопки + 2 левые уже
   даже 40×40 с gap 6 могут не влезать при больших title-элементах.
   Дополнительно подрезаем padding шапки и сами кнопки до 36×36,
   уменьшаем gap до 4-5px. Hit-area остаётся приемлемой (>32px), 
   визуал плотнее. */
@media (max-width: 420px) {
	.fx-chat-header {
		padding: 10px 10px;
		gap: 6px 6px;
	}
	.fx-chat-title-wrap { gap: 5px; }
	.fx-chat-actions    { gap: 5px; }
	.fx-chat-tg-btn,
	.fx-chat-search-toggle,
	.fx-chat-ig-btn,
	.fenix-chat-wrap .fx-chat-info-toggle,
	.fenix-chat-wrap .fx-chat-notif-toggle,
	.fx-chat-presence-count {
		width: 36px;
		height: 36px;
		min-width: 36px;
		min-height: 36px;
	}
	.fx-chat-tg-btn svg,
	.fx-chat-search-toggle svg,
	.fx-chat-ig-btn svg,
	.fx-chat-info-toggle__icon,
	.fx-chat-notif-toggle__icon {
		width: 18px;
		height: 18px;
	}
	.fx-chat-presence-count__num {
		font-size: 13px;
	}
	/* Композер на узком экране: уменьшаем размеры левой колонки
	   (26×26 вместо 30×30) и пересчитываем margin input'а.
	   Грид/top'ы кнопок применяем ТОЛЬКО в развёрнутом режиме;
	   в свёрнутом (is-expanded отсутствует) fmt-bar display:none,
	   а cluster — один ряд с центровкой по высоте 1-строчного input'а. */
	#fx-chat-fmt-bar,
	#fx-chat-attach-cluster {
		grid-template-columns: 26px 26px;
		gap: 5px;
		left: 10px;
	}
	.fx-chat-composer-dock.is-expanded #fx-chat-fmt-bar {
		grid-template-rows: 26px 26px 26px;
		top: 8px;
	}
	.fx-chat-composer-dock.is-expanded #fx-chat-attach-cluster {
		top: 101px; /* 8 + 26 + 5 + 26 + 5 + 26 + 5 */
	}
	#fx-chat-attach-cluster {
		/* Свёрнутый режим: центр по высоте 1-строчного композера
		   (56px высота, 26px кнопки, top=(56-26)/2=15). */
		top: 15px;
	}
	#fx-chat-fmt-bar .fx-fmt-toolbar__btn,
	.fx-chat-attach-cluster .fx-chat-tool,
	#fx-chat-emoji-btn,
	#fx-chat-attach-btn,
	#fx-chat-attach-counter {
		width: 26px;
		height: 26px;
		min-width: 26px;
		min-height: 26px;
		font-size: 15px;
	}
	#fx-chat-fmt-bar .fx-fmt-toolbar__btn svg,
	#fx-chat-attach-btn svg {
		width: 12px;
		height: 12px;
	}
	.fx-chat-input {
		/* Свёрнутый режим: высота «одной строки» (≈ 40px) + margin
		   под компактные 😊/📎 (2×26 + 5 gap + 10 left = 67, округлим
		   до 70). */
		margin-left: 70px !important;
		margin-right: 46px !important;
		min-height: 40px !important;
		max-height: 40px !important;
		height: 40px !important;
	}
	.fx-chat-composer-dock.is-expanded .fx-chat-input {
		margin-left: 62px !important;
		margin-right: 46px !important;
		/* 8(top) + 26+5+26+5+26 (fmt 3р) + 5 + 26 (кластер) = 127 → 119 высота. */
		min-height: 119px !important;
		max-height: 119px !important;
		height: 119px !important;
	}
	.fx-chat-composer {
		min-height: 56px;
		padding: 8px 10px;
	}
	.fx-chat-composer-dock.is-expanded .fx-chat-composer {
		min-height: 135px;
	}
	.fx-chat-send {
		right: 10px;
		width: 38px;
		height: 38px;
	}
}
@media (max-width: 360px) {
	.fx-chat-header {
		padding: 8px 8px;
		gap: 5px 5px;
	}
	.fx-chat-title-wrap { gap: 4px; }
	.fx-chat-actions    { gap: 4px; }
	.fx-chat-tg-btn,
	.fx-chat-search-toggle,
	.fx-chat-ig-btn,
	.fenix-chat-wrap .fx-chat-info-toggle,
	.fenix-chat-wrap .fx-chat-notif-toggle,
	.fx-chat-presence-count {
		width: 34px;
		height: 34px;
		min-width: 34px;
		min-height: 34px;
	}
	.fx-chat-tg-btn svg,
	.fx-chat-search-toggle svg,
	.fx-chat-ig-btn svg,
	.fx-chat-info-toggle__icon,
	.fx-chat-notif-toggle__icon {
		width: 17px;
		height: 17px;
	}
}

/* Совсем узкие устройства (<= ~360px) — на 360px при 48×48-кнопках
   (attach + counter + emoji/tool + send) и гапе 8×2 textarea может
   съёжиться до <100px, а клавиатура + placeholder выглядят обрезанно.
   Решение: на <=360 ужимаем круглые кнопки до 40×40 И gap до 4px,
   чтобы textarea оставалось ~140px+. На <=340 дополнительно срезаем
   padding композера. Стиль кнопок и hover-анимация сохранены. */
@media (max-width: 360px) {
	.fx-chat-composer {
		padding: 6px 8px 8px;
		gap: 4px;
	}
	.fx-chat-attach-cluster {
		gap: 4px;
	}
	#fx-chat-attach-btn,
	.fx-chat-attach-counter,
	.fx-chat-tool,
	.fx-chat-send {
		width: 40px !important;
		min-width: 40px !important;
		height: 40px !important;
	}
	#fx-chat-attach-btn svg,
	.fx-chat-tool svg,
	.fx-chat-send svg {
		width: 20px;
		height: 20px;
	}
	/* Переезжаем кластер ближе к send (было 78 → 62), чтобы emoji+скрепка+counter
	   не теснили textarea до нечитаемой ширины.
	   bottom = (40 − 40)/2 + 8 = 8 (кнопки 40×40, textarea min-height 40,
	   composer padding-bottom 8) — идеально по центру поля ввода. */
	#fx-chat-attach-cluster { right: 62px; bottom: 8px; }
	.fx-chat-input {
		min-height: 40px;
		padding: 8px 12px;
		padding-right: 112px;
	}
	.fx-chat-composer--has-files .fx-chat-input {
		padding-right: 156px;
	}
}
@media (max-width: 340px) {
	.fx-chat-composer {
		padding: 4px 6px 6px;
		gap: 3px;
	}
	#fx-chat-attach-btn,
	.fx-chat-attach-counter,
	.fx-chat-tool,
	.fx-chat-send {
		width: 36px !important;
		min-width: 36px !important;
		height: 36px !important;
	}
	.fx-chat-attach-cluster { gap: 3px; }
	/* bottom = (40 − 36)/2 + 6 = 8 (кнопки 36×36, textarea min-height 40,
	   composer padding-bottom 6) — снова ровно посередине поля ввода. */
	#fx-chat-attach-cluster { right: 52px; bottom: 8px; }
	.fx-chat-input {
		padding-right: 100px;
	}
	.fx-chat-composer--has-files .fx-chat-input {
		padding-right: 140px;
	}
}

/* ----------------------------------------------------------------------
 * Гостевой экран чата (невошедший пользователь на /my-account/chat-support/).
 * Заменяет стандартный WooCommerce form-login специально для нашего endpoint'а.
 * Дизайн выдержан в тех же токенах, что и основной виджет.
 * -------------------------------------------------------------------- */
.fenix-chat-guest {
	--fx-brand-2: #1a5cd8;
	--fx-brand-ink: #fff;
	--fx-bg: var(--wp--preset--color--card-bg, #ffffff);
	--fx-bg-elev: #f7f8fb;
	--fx-border: var(--wp--preset--color--border-color, #e5e7eb);
	--fx-text: var(--wp--preset--color--heading, #1b2030);
	--fx-text-dim: var(--wp--preset--color--body-color, #6b7280);
	--fx-shadow: 0 16px 40px rgba(0, 0, 0, 0.06), 0 2px 6px rgba(0, 0, 0, 0.04);
	--fx-radius: 18px;
	--fx-radius-sm: 12px;

	display: flex;
	justify-content: center;
	padding: 16px 0 0;
}

.fenix-chat-guest__card {
	box-sizing: border-box;
	width: 100%;
	max-width: 620px;
	padding: 28px 32px 28px;
	background: var(--fx-bg);
	border: 1px solid var(--fx-border);
	border-radius: var(--fx-radius);
	box-shadow: var(--fx-shadow);
	color: var(--fx-text);
	text-align: center;
	position: relative;
	overflow: hidden;
}
/* Бренд-полоска сверху карточки отключена по запросу. */
.fenix-chat-guest__card::before {
	display: none !important;
	content: none !important;
}
/* Декоративное градиентное пятно отключено по запросу (без градиентов). */
.fenix-chat-guest__card::after {
	display: none !important;
	content: none !important;
}

.fenix-chat-guest__icon {
	width: 64px;
	height: 64px;
	margin: 0 auto 14px;
	display: flex;
	align-items: center;
	justify-content: center;
	border-radius: 50%;
	background: var(--fx-brand);
	color: #fff;
	box-shadow: 0 10px 24px rgba(33, 107, 233, 0.28);
	position: relative;
	z-index: 1;
}

.fenix-chat-guest__title {
	margin: 0 0 10px;
	font-size: 24px;
	font-weight: 700;
	line-height: 1.25;
	color: var(--fx-text);
	letter-spacing: -0.01em;
	position: relative;
	z-index: 1;
}

.fenix-chat-guest__lead {
	margin: 0 auto 18px;
	max-width: 480px;
	color: var(--fx-text-dim);
	font-size: 15px;
	line-height: 1.55;
	position: relative;
	z-index: 1;
}

.fenix-chat-guest__actions {
	display: flex;
	flex-wrap: wrap;
	gap: 10px;
	justify-content: center;
	margin-bottom: 18px;
	position: relative;
	z-index: 1;
}

.fenix-chat-guest__btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 10px;
	padding: 13px 26px;
	border-radius: 12px;
	font-weight: 700;
	font-size: 15px;
	line-height: 1;
	text-decoration: none;
	border: 1.5px solid transparent;
	cursor: pointer;
	font-family: inherit;
	transition: transform 0.18s ease, box-shadow 0.18s ease,
		background 0.18s ease, color 0.18s ease, border-color 0.18s ease,
		filter 0.18s ease;
	-webkit-tap-highlight-color: transparent;
	touch-action: manipulation;
}

.fenix-chat-guest__btn--primary {
	background: var(--fx-brand);
	color: var(--fx-brand-ink);
	box-shadow: 0 10px 24px rgba(33, 107, 233, 0.28);
}

.fenix-chat-guest__btn--primary:hover,
.fenix-chat-guest__btn--primary:focus-visible {
	transform: translateY(-2px);
	box-shadow: 0 16px 32px rgba(33, 107, 233, 0.4);
	color: var(--fx-brand-ink);
	filter: brightness(1.04);
	outline: none;
}
.fenix-chat-guest__btn--primary:active {
	transform: translateY(0) scale(0.98);
	box-shadow: 0 6px 14px rgba(33, 107, 233, 0.3);
}

.fenix-chat-guest__btn--ghost {
	background: var(--fx-bg-elev);
	color: var(--fx-text);
	border-color: var(--fx-border);
}

.fenix-chat-guest__btn--ghost:hover,
.fenix-chat-guest__btn--ghost:focus-visible {
	background: color-mix(in srgb, var(--fx-brand) 6%, var(--fx-bg-elev));
	border-color: color-mix(in srgb, var(--fx-brand) 30%, var(--fx-border));
	color: var(--fx-text);
	transform: translateY(-1px);
	outline: none;
}

.fenix-chat-guest__perks {
	list-style: none;
	margin: 0;
	padding: 0;
	text-align: left;
	display: grid;
	gap: 10px;
	position: relative;
	z-index: 1;
}

.fenix-chat-guest__perks li {
	position: relative;
	padding: 12px 14px 12px 42px;
	background: var(--fx-bg-elev);
	border: 1px solid var(--fx-border);
	border-radius: var(--fx-radius-sm);
	color: var(--fx-text-dim);
	font-size: 13.5px;
	line-height: 1.5;
}

.fenix-chat-guest__perks li::before {
	content: "";
	position: absolute;
	left: 12px;
	top: 50%;
	width: 20px;
	height: 20px;
	border-radius: 50%;
	background: var(--fx-brand);
	transform: translateY(-50%);
	box-shadow: 0 4px 10px rgba(33, 107, 233, 0.2);
}

.fenix-chat-guest__perks li::after {
	content: "";
	position: absolute;
	left: 17px;
	top: 50%;
	width: 8px;
	height: 4px;
	border-left: 2px solid #fff;
	border-bottom: 2px solid #fff;
	transform: translate(0, -70%) rotate(-45deg);
}

.fenix-chat-guest__hint {
	margin: 16px 0 0;
	color: var(--fx-text-dim);
	font-size: 13px;
	position: relative;
	z-index: 1;
}

.fenix-chat-guest__hint a {
	color: var(--fx-brand);
	text-decoration: none;
	font-weight: 600;
}

.fenix-chat-guest__hint a:hover {
	text-decoration: underline;
}

/* Тёмная тема (Blogsy scheme="dark"). */
html[scheme="dark"] .fenix-chat-guest,
[data-theme="dark"] .fenix-chat-guest {
	--fx-bg: #171a24;
	--fx-bg-elev: rgba(255, 255, 255, 0.04);
	--fx-border: rgba(255, 255, 255, 0.08);
	--fx-text: #e6ecf5;
	--fx-text-dim: #a9b4c2;
	--fx-shadow: 0 16px 40px rgba(0, 0, 0, 0.5), 0 2px 6px rgba(0, 0, 0, 0.3);
}

html[scheme="dark"] .fenix-chat-guest__btn--ghost,
[data-theme="dark"] .fenix-chat-guest__btn--ghost {
	background: var(--fx-bg-elev);
	border-color: var(--fx-border);
	color: var(--fx-text);
}

/* Симметрия и защита от старого CSS (padding: var(--fx-site-bottom-h)). */
#fenix-chat-guest.fenix-chat-guest {
	margin: 0 !important;
}
#fenix-chat-guest .fenix-chat-guest__card {
	padding-bottom: 28px !important;
	margin-bottom: 0 !important;
}
/* Тема Blogsy: #site-inner с min-height:100vh давал сотни px пустоты. */
body.fenix-chat-shortcode-page--guest #site-inner,
body.fenix-chat-support-page--guest #site-inner,
body:has(#fenix-chat-guest) #site-inner {
	min-height: 0 !important;
	height: auto !important;
}
/* Зазор между карточкой и футером (не склеивать блоки). */
body.fenix-chat-shortcode-page--guest .main-wrapper,
body.fenix-chat-support-page--guest .main-wrapper,
body:has(#fenix-chat-guest) .main-wrapper {
	min-height: 0 !important;
	height: auto !important;
	padding-bottom: 24px !important;
}
body.fenix-chat-shortcode-page--guest footer.site-footer,
body.fenix-chat-shortcode-page--guest .site-footer,
body.fenix-chat-shortcode-page--guest #colophon,
body.fenix-chat-shortcode-page--guest .pt-footer,
body.fenix-chat-support-page--guest footer.site-footer,
body.fenix-chat-support-page--guest .site-footer,
body:has(#fenix-chat-guest) footer.site-footer,
body:has(#fenix-chat-guest) .site-footer,
body:has(#fenix-chat-guest) #colophon,
body:has(#fenix-chat-guest) .pt-footer {
	margin-top: 20px !important;
}

@media (max-width: 768px) {
	/* Раскрываем обёртки темы / WC: гостевая заглушка на всю ширину
	   article, без «матрёшки» (card-layout-w + fenix-chat-guest__card). */
	body.fenix-chat-support-page--guest .woocommerce,
	body.fenix-chat-support-page--guest .woocommerce-MyAccount-content,
	body.fenix-chat-support-page--guest .u-columns,
	body.fenix-chat-support-page--guest .u-column1,
	body.fenix-chat-support-page--guest .u-column2,
	body.fenix-chat-shortcode-page--guest .content-container,
	body.fenix-chat-shortcode-page--guest .page-content-wrapper,
	body.fenix-chat-shortcode-page--guest #content,
	body.fenix-chat-shortcode-page--guest .site-main,
	body.fenix-chat-shortcode-page--guest .entry-content,
	body.fenix-chat-shortcode-page--guest .container,
	body.fenix-chat-shortcode-page--guest .pt-page-wrapper,
	body.fenix-chat-shortcode-page--guest .fenix-chat-shortcode-wrap,
	body.fenix-chat-shortcode-page--guest article.single-content,
	body.fenix-chat-shortcode-page--guest .single-content-inner {
		width: 100% !important;
		max-width: 100% !important;
		flex: 1 1 100% !important;
		padding-left: 0 !important;
		padding-right: 0 !important;
		margin-left: 0 !important;
		margin-right: 0 !important;
		box-sizing: border-box !important;
	}
	body.fenix-chat-shortcode-page--guest .single-content-inner,
	body.fenix-chat-shortcode-page--guest .fenix-chat-shortcode-wrap {
		padding-top: 0 !important;
		padding-bottom: 0 !important;
	}
	body.fenix-chat-shortcode-page--guest article.single-content.card-layout-w,
	body.fenix-chat-support-page--guest article.single-content.card-layout-w {
		overflow: hidden !important;
		padding-top: 0 !important;
		padding-bottom: 0 !important;
	}
	body.fenix-chat-shortcode-page--guest .single-content-inner,
	body.fenix-chat-support-page--guest .single-content-inner {
		margin-bottom: 0 !important;
	}
	body.fenix-chat-shortcode-page--guest .fenix-chat-guest {
		display: block !important;
		width: 100% !important;
		max-width: 100% !important;
		margin: 0 !important;
		padding: 0 16px 16px !important;
		justify-content: stretch !important;
	}
	body.fenix-chat-support-page--guest .fenix-chat-guest {
		padding: 0 16px 16px !important;
	}
	/* Внутренняя карточка — без второй рамки/тени: оформление только у article. */
	body.fenix-chat-shortcode-page--guest .fenix-chat-guest__card,
	body.fenix-chat-support-page--guest .fenix-chat-guest__card {
		width: 100% !important;
		max-width: 100% !important;
		margin: 0 !important;
		padding: 20px 16px 20px !important;
		border: none !important;
		box-shadow: none !important;
		border-radius: 0 !important;
		background: transparent !important;
	}
	#fenix-chat-guest .fenix-chat-guest__card {
		padding-bottom: 20px !important;
	}
	.fenix-chat-guest {
		padding: 0;
	}
	.fenix-chat-guest__card {
		padding: 20px 16px 20px;
		border-radius: 0;
		max-width: none;
	}
	.fenix-chat-guest__icon {
		width: 60px;
		height: 60px;
		margin-bottom: 14px;
	}
	.fenix-chat-guest__icon svg {
		width: 44px;
		height: 44px;
	}
	.fenix-chat-guest__title {
		font-size: 20px;
	}
	.fenix-chat-guest__lead {
		font-size: 14px;
		margin-bottom: 18px;
	}
	.fenix-chat-guest__btn {
		padding: 12px 22px;
		font-size: 14px;
	}
	.fenix-chat-guest__actions {
		flex-direction: column;
		align-items: stretch;
		margin-bottom: 20px;
	}
	.fenix-chat-guest__btn {
		justify-content: center;
	}
	.fenix-chat-guest__perks li {
		padding: 10px 12px 10px 40px;
		font-size: 13px;
	}
}

/* ==========================================================================
   Attachments (медиа-сетка под сообщением) + Lightbox (галерея просмотра)
   ========================================================================== */

/* Контейнер вложений — сетка карточек. Одной картинке/видео позволяем
   занимать всю доступную ширину, два и более — в гибкой сетке. */
.fx-atts {
	display: grid;
	/* auto-fit (а не auto-fill): пустые «резервные» колонки схлопываются,
	   поэтому при 2 картинках не остаётся пустого места справа. */
	grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
	gap: 6px;
	margin-top: 8px;
}
.fx-atts:has(> .fx-att:only-child.fx-att--image),
.fx-atts:has(> .fx-att:only-child.fx-att--animation) {
	grid-template-columns: minmax(0, min(360px, 100%));
}
.fx-atts:has(> .fx-att:only-child.fx-att--video) {
	grid-template-columns: minmax(0, min(420px, 100%));
	justify-items: center;
}
/* В TG стикер всегда один на сообщение — не даём auto-fill нарезать
   вторую пустую колонку в широком пузыре. */
.fx-atts:has(> .fx-att:only-child.fx-att--sticker) {
	grid-template-columns: max-content !important;
	max-width: 100%;
	width: fit-content;
	justify-items: start;
}
.fx-atts:has(> .fx-att--doc),
.fx-atts:has(> .fx-att--audio),
.fx-atts:has(> .fx-att--voice) {
	/* Одна колонка на всю ширину бабла: размер карточки = размер
	   пузыря. Пузырь сам ограничен width:min(320px,100%) в правилах
	   .fx-msg__bubble--atts-only:has(.fx-att--doc/audio/voice) выше,
	   поэтому карточка не расползается. */
	grid-template-columns: minmax(0, 1fr);
}

.fx-att {
	position: relative;
	display: block;
	border-radius: var(--fx-radius-sm);
	overflow: hidden;
	background: var(--fx-bg-elev);
	border: 1px solid var(--fx-border);
	transition: transform .15s ease, box-shadow .15s ease, border-color .15s ease;
	color: inherit;
	text-decoration: none;
}
.fx-att:hover {
	border-color: color-mix(in srgb, var(--fx-brand) 40%, var(--fx-border));
	box-shadow: 0 4px 16px rgba(33, 107, 233, 0.12);
	transform: translateY(-1px);
}
.fx-att--video:hover {
	transform: none;
	box-shadow: 0 2px 12px rgba(0, 0, 0, 0.35);
}

/* Переопределяем универсальное правило .fx-msg__bubble img/video,
   чтобы media-карточки не получали margin-top и max-height 320px
   вразрез с нашей сеткой. */
.fx-msg__bubble .fx-atts img,
.fx-msg__bubble .fx-atts video {
	margin: 0;
	max-height: none;
	border-radius: 0;
	display: block;
}

/* Image / sticker --------------------------------------------------------- */
.fx-att--image img {
	width: 100%;
	height: 100%;
	aspect-ratio: 4 / 3;
	object-fit: cover;
	display: block;
	/* Telegram-стиль: палец, а не лупа — лайтбокс для просмотра, не «zoom». */
	cursor: pointer;
}
.fx-atts:has(> .fx-att:only-child.fx-att--image) .fx-att--image img {
	aspect-ratio: auto;
	max-height: 420px;
	width: 100%;
	object-fit: contain;
	background: var(--fx-bg);
}

/* Placeholder для сломанных TG-картинок: когда Bot API возвращает
   «wrong file_id» и оба URL-а (thumb + full) упали — window.fxImgFb
   подсовывает inline-SVG и помечает .fx-img--broken. Сжимаем под
   квадрат ~120px и снимаем object-fit: cover, чтобы SVG не растягивался
   на всю плитку альбома и не выглядел баговой картинкой. Курсор-стрелка
   вместо указателя, потому что кликать в лайтбоксе нечего. */
.fx-att--image img.fx-img--broken {
	width: 120px;
	height: 120px;
	aspect-ratio: 1 / 1;
	object-fit: contain;
	background: var(--fx-bg);
	padding: 20px;
	box-sizing: border-box;
	cursor: default;
	opacity: 0.75;
}
.fx-atts:has(> .fx-att:only-child.fx-att--image) .fx-att--image img.fx-img--broken {
	max-height: 160px;
	width: 160px;
	height: 160px;
}

.fx-att--sticker {
	background: transparent;
	border: none;
	padding: 0;
}
.fx-att--sticker img,
.fx-att--sticker video {
	width: 140px;
	height: 140px;
	object-fit: contain;
	background: transparent;
	display: block;
}
.fx-att--sticker:hover {
	transform: none;
	box-shadow: none;
}

/* Animation (gif/mp4-loop) — играем прямо в ленте; лайтбокс не открываем. */
.fx-att--animation {
	cursor: default;
}
.fx-att--animation video {
	width: 100%;
	aspect-ratio: 4 / 3;
	object-fit: cover;
	display: block;
}

/* Video — встроенный плеер в ленте (центрирование, превью = poster) ------- */
.fx-att--video {
	/* Telegram-стиль: палец при наведении на превью — клик открывает
	   лайтбокс / запускает воспроизведение. Нативный video-плеер внутри
	   сам выставит свой cursor на controls. */
	cursor: pointer;
	background: #0a0a0a;
	position: relative;
}
.fx-att--video .fx-att__video-el {
	display: block;
	width: 100%;
	max-height: min(420px, 72vh);
	margin: 0 auto;
	object-fit: contain;
	background: #000;
	border-radius: inherit;
	cursor: pointer;
}
.fx-atts:has(> .fx-att:only-child.fx-att--video) .fx-att--video .fx-att__video-el {
	max-height: min(480px, 75vh);
}
.fx-att--video .fx-att__duration {
	position: absolute;
	right: 8px;
	bottom: 8px;
	background: rgba(0, 0, 0, 0.6);
	color: #fff;
	font-size: 11px;
	font-weight: 600;
	padding: 2px 6px;
	border-radius: 6px;
	pointer-events: none;
	font-variant-numeric: tabular-nums;
}

/* Audio / voice — кастомный плеер с waveform-дорожкой ---------------------
 * Раньше использовался нативный <audio controls>, который на iOS и на
 * части Android превращался в одну кнопку-точку без видимой дорожки.
 * Сейчас — собственная разметка: play-кнопка слева, 48 полосок волны
 * посередине (сид = URL, стабильно между ре-рендерами), время справа;
 * brand-fill рисуется clip-path'ом поверх серой подложки.
 * JS: fxAudioInit / bindAudioPlayers в chat.js. */
.fx-att--audio {
	display: flex;
	align-items: center;
	gap: 12px;
	width: 100%;
	min-width: 0;
	padding: 10px 12px;
	box-sizing: border-box;
	flex-wrap: wrap;
}

/* STT — блок расшифровки под плеером голосового/аудио.
 * flex-basis: 100% заставляет .fx-att__stt переноситься на новую
 * строку под плеером, вне зависимости от ширины бабла. Оформление
 * максимально лаконичное — не конкурирует визуально с плеером. */
.fx-att--audio .fx-att__stt {
	flex: 0 0 100%;
	width: 100%;
	min-width: 0;
	margin-top: 4px;
	padding-top: 8px;
	border-top: 1px dashed color-mix(in srgb, var(--fx-text, #1f2937) 12%, transparent);
	box-sizing: border-box;
}
.fx-att--audio .fx-att__stt-text {
	color: var(--fx-text, #1f2937);
	font-size: 13.5px;
	line-height: 1.45;
	white-space: pre-wrap;
	word-break: break-word;
	opacity: 0.95;
}
.fx-att--audio .fx-att__stt-btn {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 4px 10px;
	border-radius: 10px;
	border: 1px solid color-mix(in srgb, var(--fx-brand, #216be9) 35%, transparent);
	background: color-mix(in srgb, var(--fx-brand, #216be9) 8%, transparent);
	color: var(--fx-brand, #216be9);
	font-size: 12px;
	line-height: 1;
	cursor: pointer;
	transition: background 0.12s ease, border-color 0.12s ease;
}
.fx-att--audio .fx-att__stt-btn:hover {
	background: color-mix(in srgb, var(--fx-brand, #216be9) 14%, transparent);
	border-color: color-mix(in srgb, var(--fx-brand, #216be9) 55%, transparent);
}
.fx-att--audio .fx-att__stt-btn:active { transform: scale(0.97); }
.fx-att--audio .fx-att__stt-icon {
	width: 14px;
	height: 14px;
	flex: 0 0 auto;
}
/* Тумблер «Расшифровка» (status='done'): кнопка + caret + спрятанный
   блок текста, который раскрывается по клику. */
.fx-att--audio .fx-att__stt {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 6px;
	flex-basis: 100%;
}
.fx-att--audio .fx-att__stt-btn--toggle {
	align-self: flex-start;
}
.fx-att--audio .fx-att__stt-caret {
	width: 12px;
	height: 12px;
	flex: 0 0 auto;
	transition: transform 0.18s ease;
}
.fx-att--audio .fx-att__stt-btn--toggle[aria-expanded='true'] .fx-att__stt-caret {
	transform: rotate(180deg);
}
.fx-att--audio .fx-att__stt-btn--toggle[aria-expanded='true'] {
	background: color-mix(in srgb, var(--fx-brand, #216be9) 16%, transparent);
	border-color: color-mix(in srgb, var(--fx-brand, #216be9) 55%, transparent);
}
.fx-att--audio .fx-att__stt-text[hidden] {
	display: none;
}
.fx-att--audio .fx-att__stt-pending {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	color: color-mix(in srgb, var(--fx-text, #1f2937) 65%, transparent);
	font-size: 12.5px;
}
.fx-att--audio .fx-att__stt-spin {
	width: 12px;
	height: 12px;
	border-radius: 50%;
	border: 2px solid color-mix(in srgb, var(--fx-brand, #216be9) 25%, transparent);
	border-top-color: var(--fx-brand, #216be9);
	animation: fx-stt-spin 0.8s linear infinite;
}
@keyframes fx-stt-spin {
	to { transform: rotate(360deg); }
}
.fx-att--audio .fx-att__stt-error {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	font-size: 12.5px;
	color: color-mix(in srgb, #c0392b 80%, var(--fx-text, #1f2937));
}
.fx-att--audio .fx-att__stt-retry {
	padding: 2px 8px;
	font-size: 11.5px;
}
.fx-att--audio .fx-audio__play {
	flex: 0 0 auto;
	width: 44px;
	height: 44px;
	border-radius: 50%;
	border: none;
	background: var(--fx-brand);
	color: #fff;
	cursor: pointer;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 0;
	transition: background 0.15s ease, transform 0.12s ease, box-shadow 0.15s ease;
	box-shadow: 0 2px 8px rgba(33, 107, 233, 0.25);
	-webkit-tap-highlight-color: transparent;
}
.fx-att--audio .fx-audio__play:hover {
	background: color-mix(in srgb, var(--fx-brand) 88%, #000);
	box-shadow: 0 4px 14px rgba(33, 107, 233, 0.35);
}
.fx-att--audio .fx-audio__play:active {
	transform: scale(0.96);
}
.fx-att--audio .fx-audio__play svg {
	width: 22px;
	height: 22px;
	display: block;
}
.fx-att--audio .fx-audio__play .fx-audio__icon-pause { display: none; }
.fx-att--audio.is-playing .fx-audio__play .fx-audio__icon-play { display: none; }
.fx-att--audio.is-playing .fx-audio__play .fx-audio__icon-pause { display: block; }

.fx-att--audio .fx-audio__body {
	flex: 1 1 auto;
	min-width: 0;
	display: flex;
	flex-direction: column;
	gap: 4px;
}
.fx-att--audio .fx-audio__wave {
	position: relative;
	width: 100%;
	height: 28px;
	cursor: pointer;
	touch-action: pan-y;
	/* Небольшой «air» сверху/снизу, чтобы клики мимо полосок тоже
	   попадали в seek-зону. */
	padding: 2px 0;
	box-sizing: border-box;
}
.fx-att--audio .fx-audio__wave:focus {
	outline: 2px solid color-mix(in srgb, var(--fx-brand) 60%, transparent);
	outline-offset: 2px;
	border-radius: 4px;
}
.fx-att--audio .fx-audio__wave-bars {
	position: absolute;
	inset: 2px 0;
	display: flex;
	align-items: center;
	gap: 2px;
	width: 100%;
	height: calc(100% - 4px);
	pointer-events: none;
}
.fx-att--audio .fx-audio__wave-bars > span {
	flex: 1 1 0;
	display: block;
	min-width: 2px;
	height: 30%;
	background: currentColor;
	border-radius: 2px;
}
.fx-att--audio .fx-audio__wave-bars--bg {
	color: color-mix(in srgb, var(--fx-text-dim) 55%, transparent);
}
.fx-att--audio .fx-audio__wave-bars--fg {
	color: var(--fx-brand);
	clip-path: inset(0 100% 0 0);
	transition: clip-path 0.12s linear;
}
.fx-att--audio .fx-audio__time {
	font-size: 12px;
	font-variant-numeric: tabular-nums;
	color: var(--fx-text-dim);
	line-height: 1.3;
}
.fx-att--audio .fx-att__meta {
	flex-basis: 100%;
	margin-top: 2px;
	font-size: 12px;
	color: var(--fx-text-dim);
	/* перенос имени файла на новую строку под waveform (когда
	   аудио — это именно файл, а не голосовое). */
	padding-left: 56px; /* обход play-кнопки */
}
.fx-att--audio.fx-att--voice .fx-att__meta { display: none; }

html[scheme='dark'] .fx-att--audio .fx-audio__wave-bars--bg,
body.fenix-chat-force-dark .fx-att--audio .fx-audio__wave-bars--bg {
	color: rgba(255, 255, 255, 0.22);
}
@media (prefers-color-scheme: dark) {
	html:not([scheme]) .fx-att--audio .fx-audio__wave-bars--bg {
		color: rgba(255, 255, 255, 0.22);
	}
}

/* Document — карточка с цветным бейджем расширения ----------------------- */
/* Увеличенная версия по просьбе пользователя: «показывать большие
   иконки по расширению». Размер thumb-блока ↑ 44×52 → 56×66, карточка
   чуть «пузатее», но всё ещё компактна внутри бабла. */
.fx-att--doc {
	display: flex;
	align-items: center;
	gap: 14px;
	padding: 12px 14px;
	min-height: 80px;
}
.fx-att--doc:hover .fx-att__name {
	color: var(--fx-brand);
}
/* F18 — PDF-карточку немного выделяем, чтобы был явный визуальный
   намёк на возможность предпросмотра. Hover: тонкая рамка brand-цвета. */
.fx-att--pdf {
	transition: background .15s ease, border-color .15s ease;
}
.fx-att--pdf:hover {
	background: color-mix(in srgb, var(--fx-brand) 8%, transparent);
}
@media (min-width: 560px) {
	.fx-att--pdf::after {
		content: '';
		position: absolute;
		right: 12px;
		top: 50%;
		transform: translateY(-50%);
		width: 14px;
		height: 14px;
		background: currentColor;
		opacity: 0;
		transition: opacity .15s ease;
		-webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' d='M15 3h6v6m0-6l-9 9M8 5H5a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-3'/></svg>") center / contain no-repeat;
		        mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' d='M15 3h6v6m0-6l-9 9M8 5H5a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-3'/></svg>") center / contain no-repeat;
		color: var(--fx-brand);
		pointer-events: none;
	}
	.fx-att--pdf { position: relative; }
	.fx-att--pdf:hover::after { opacity: 0.8; }
}
.fx-att__doc-thumb {
	position: relative;
	flex: 0 0 auto;
	width: 56px;
	height: 66px;
	display: flex;
	align-items: center;
	justify-content: center;
	color: color-mix(in srgb, var(--fx-brand) 80%, var(--fx-text));
}
.fx-att__doc-icon {
	width: 56px;
	height: 66px;
	display: block;
}
.fx-att__ext {
	position: absolute;
	left: 50%;
	bottom: 8px;
	transform: translateX(-50%);
	font-size: 11px;
	font-weight: 800;
	letter-spacing: 0.5px;
	padding: 3px 7px;
	border-radius: 5px;
	color: #fff;
	background: #6c7684;
	text-transform: uppercase;
	line-height: 1;
	font-variant-numeric: tabular-nums;
	max-width: 52px;
	overflow: hidden;
	text-overflow: clip;
	white-space: nowrap;
	box-shadow: 0 1px 2px rgba(0, 0, 0, 0.18);
}
.fx-att__ext[data-ext-cat="pdf"]     { background: #d0463b; }
.fx-att__ext[data-ext-cat="doc"]     { background: #2a6fdb; }
.fx-att__ext[data-ext-cat="xls"]     { background: #1f9454; }
.fx-att__ext[data-ext-cat="ppt"]     { background: #e8742c; }
.fx-att__ext[data-ext-cat="archive"] { background: #7a5cc3; }
.fx-att__ext[data-ext-cat="code"]    { background: #28343f; }
.fx-att__ext[data-ext-cat="text"]    { background: #4a5360; }
.fx-att__ext[data-ext-cat="image"]   { background: #29a382; }
.fx-att__ext[data-ext-cat="video"]   { background: #bb2b7a; }
.fx-att__ext[data-ext-cat="audio"]   { background: #0e8fbf; }
.fx-att__ext[data-ext-cat="app"]     { background: #4a8f1f; }

.fx-att__info {
	min-width: 0;
	display: flex;
	flex-direction: column;
	gap: 2px;
}
.fx-att__name {
	font-weight: 600;
	color: var(--fx-text);
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	max-width: 100%;
	font-size: 14px;
	line-height: 1.25;
}
/* Инлайн-размер рядом с именем: «file.ext (12.3 MB)». Гасим цвет
   (dim), чуть уменьшаем шрифт, оставляем tabular-nums, чтобы цифры
   не скакали. */
.fx-att__name-size {
	color: var(--fx-text-dim);
	font-weight: 500;
	font-size: 12px;
	font-variant-numeric: tabular-nums;
	margin-left: 2px;
}
/* Размер файла ОТДЕЛЬНОЙ строкой под именем — чтобы при длинном имени
   (ellipsis) размер не обрезался вместе с ним. */
.fx-att__sub {
	font-size: 12px;
	color: var(--fx-text-dim);
	font-variant-numeric: tabular-nums;
	line-height: 1.2;
}
.fx-att__size {
	font-size: 12px;
	color: var(--fx-text-dim);
}

/* ==========================================================================
   Прогресс-бар загрузки файла в optimistic-вложении.
   Рисуется внутри .fx-att--uploading и показывает, сколько процентов
   от файла уже ушло в chat-server (а оттуда дальше в TG-группу).
   Когда XHR завершился и пришло реальное сообщение, вся карточка
   заменяется swapOptimisticWithReal → прогресс исчезает.
   ========================================================================== */
.fx-att--uploading {
	position: relative;
	cursor: default;
	/* Клики по карточке во время загрузки гасим (нельзя открыть ещё не
	   доставленный файл), НО прогресс-полосу и крестик «отменить» НЕ
	   гасим — им ниже возвращаем pointer-events:auto. */
	pointer-events: none;
	isolation: isolate;
	/* Приглушение «идёт загрузка» применяем ТОЛЬКО к самому превью
	   (см. правило для > img/video/иконки ниже), а НЕ ко всей карточке —
	   иначе тускнели проценты, имя файла и крестик. */
}
/* Лёгкое приглушение только превью-медиа (картинка/видео), чтобы было
   видно «загрузка идёт», но текст прогресса и имя файла оставались
   яркими. Документ-иконку не трогаем — у доков важно имя файла. */
.fx-att--uploading > img,
.fx-att--uploading > video {
	filter: saturate(0.7) brightness(0.9);
	opacity: 0.9;
}
/* Прогресс-полоса и крестик кликабельны и в полной яркости, несмотря на
   pointer-events:none у карточки. */
.fx-att--uploading .fx-att__upload,
.fx-att--uploading .fx-att__upload-cancel { pointer-events: auto; }
/* ------- Batch-upload layout fix -------
 * Пока картинки/видео грузятся, у <img src="blob:"> / <video> ещё
 * нет intrinsic-размеров → внутри `.fx-atts` (display: grid) карточки
 * схлопывались в 0×0 и визуально «накладывались» друг на друга. После
 * загрузки реальный thumb приходит с сервером и уже имеет размеры —
 * поэтому ПОСЛЕ загрузки всё выглядело правильно.
 *   Фикс: карточке-грузящемуся медиа задаём aspect-ratio 4/3 и
 * заставляем <img>/<video> внутри заполнять её на 100%. Так ячейки
 * грида получают стабильный intrinsic height сразу, без ожидания
 * декодирования blob-preview. */
.fx-att--uploading.fx-att--image,
.fx-att--uploading.fx-att--animation,
.fx-att--uploading.fx-att--video {
	aspect-ratio: 4 / 3;
	min-height: 96px;
	width: 100%;
}
.fx-att--uploading.fx-att--image > img,
.fx-att--uploading.fx-att--animation > video,
.fx-att--uploading.fx-att--video > video {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}
/* Бабл с несколькими оптимистик-вложениями — фикс-ширина, чтобы grid
   с `auto-fill, minmax(140px, 1fr)` получил определённую колоночную
   раскладку (а не 1 колонку из-за `width: fit-content` родителя).
   После загрузки реальные размеры файлов дают content-intrinsic, и
   пузырь снова схлопывается до content-width правильным grid-ом. */
.fx-msg__bubble:has(.fx-atts > .fx-att.fx-att--uploading:nth-child(2)) {
	width: min(460px, 100%);
}
/* Тёмный оверлей на превью больше не нужен: загружающиеся карточки
   уже ослаблены фильтром (filter: saturate/brightness + opacity в
   .fx-att--uploading). Это убирает двойное «затемнение» и даёт
   пользователю честный взгляд на то, что файл уже виден в чате —
   нужно только дождаться прогресса. */
.fx-att--uploading::after { display: none; }
/* Прогресс-полоса живёт ВНУТРИ карточки, прилипает к самому низу,
   во всю ширину (вид полосы состояния под файлом). Раньше она
   висела как абсолютный попап с отступом по 8px со всех сторон —
   выглядело «поверх картинки», а не «под файлом» как просил
   пользователь. */
/* === Telegram-style СТРОКА загрузки ===
   Кольцо прогресса слева (прижато к краю пузыря); в центре кольца —
   сколько уже загружено (МБ→ГБ), при наведении вместо размера крестик
   отмены. Справа — имя файла и его ОБЩИЙ вес. */
/* Пока идёт загрузка — список файлов вертикальный (а не grid-галерея). */
.fx-atts:has(.fx-att--up-row) {
	display: flex;
	flex-direction: column;
	gap: 6px;
	width: min(460px, 100%);
}
.fx-att--up-row {
	position: relative;
	display: flex;
	align-items: center;
	gap: 10px;
	width: 100%;
	box-sizing: border-box;
	padding: 8px 12px 8px 4px;
	background: color-mix(in srgb, var(--fx-brand) 6%, var(--fx-bg-elev, #fff));
	border: 1px solid color-mix(in srgb, var(--fx-brand) 14%, var(--fx-border));
	border-radius: 12px;
}
.fx-att__upload-cancel {
	position: relative;
	flex: none;
	pointer-events: auto;
	width: 46px;
	height: 46px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 0;
	margin: 0;
	border: 0;
	background: transparent;
	cursor: pointer;
	-webkit-tap-highlight-color: transparent;
	touch-action: manipulation;
}
.fx-att__ring {
	width: 46px;
	height: 46px;
	display: block;
	transform: rotate(-90deg);
	transform-origin: 50% 50%;
}
.fx-att__ring-bg { fill: none; stroke: color-mix(in srgb, var(--fx-brand) 22%, transparent); stroke-width: 3; }
.fx-att__ring-fg {
	fill: none;
	stroke: var(--fx-brand);
	stroke-width: 3;
	stroke-linecap: round;
	stroke-dasharray: 100;
	stroke-dashoffset: 100;
	transition: stroke-dashoffset 0.18s linear;
}
.fx-att__ring.is-indeterminate { animation: fxRingSpin 0.9s linear infinite; }
.fx-att__ring.is-indeterminate .fx-att__ring-fg { stroke-dasharray: 26 74; transition: none; }
@keyframes fxRingSpin {
	from { transform: rotate(-90deg); }
	to   { transform: rotate(270deg); }
}
/* Центр кольца: по умолчанию «сколько загружено», при наведении — ✕. */
.fx-att__ring-loaded,
.fx-att__ring-x {
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	pointer-events: none;
	line-height: 1;
}
.fx-att__ring-loaded {
	font-size: 10px;
	font-weight: 700;
	color: var(--fx-text);
	font-variant-numeric: tabular-nums;
	white-space: nowrap;
}
.fx-att__ring-x { font-size: 20px; color: var(--fx-danger, #d63638); display: none; }
.fx-att__upload-cancel:hover .fx-att__ring-loaded,
.fx-att__upload-cancel:focus-visible .fx-att__ring-loaded { display: none; }
.fx-att__upload-cancel:hover .fx-att__ring-x,
.fx-att__upload-cancel:focus-visible .fx-att__ring-x { display: block; }
.fx-att__upload-cancel:hover .fx-att__ring-fg,
.fx-att__upload-cancel:focus-visible .fx-att__ring-fg { stroke: var(--fx-danger, #d63638); }
.fx-att__up-meta {
	display: flex;
	flex-direction: column;
	gap: 2px;
	min-width: 0;
	flex: 1 1 auto;
}
.fx-att__up-name {
	font-size: 13px;
	font-weight: 600;
	color: var(--fx-text);
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
.fx-att__up-total {
	font-size: 12px;
	color: var(--fx-text-dim);
	font-variant-numeric: tabular-nums;
}
.fx-att--uploading::after { display: none; }

/* Если загрузка упала — красим карточку в «ошибочный» оттенок.
   .fx-msg--upload-failed навешивается из JS в catch(). Привлекает
   внимание к проблемному сообщению, чтобы юзер попытался отправить
   заново. */
.fx-msg--upload-failed .fx-att--uploading {
	border-color: color-mix(in srgb, var(--fx-danger, #d63638) 40%, var(--fx-border)) !important;
}
.fx-msg--upload-failed .fx-att__upload-bar {
	background: var(--fx-danger, #d63638) !important;
}
.fx-msg--upload-failed .fx-att__upload-label {
	color: #fff !important;
}

/* Панель «Повторить / Отмена» для упавших загрузок. Навешивается JS в
   attachUploadRetry() на .fx-msg (div вне .fx-att, чтобы не ломать
   разметку галереи). Видна только при .fx-msg--upload-failed. */
.fx-msg__upload-retry {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 8px;
	margin: 6px 0 0;
	padding: 8px 10px;
	border-radius: 10px;
	background: color-mix(in srgb, var(--fx-danger, #d63638) 10%, var(--fx-bg));
	border: 1px solid color-mix(in srgb, var(--fx-danger, #d63638) 40%, var(--fx-border));
	font-size: 12px;
	color: var(--fx-text);
}
.fx-msg__upload-retry-reason {
	flex: 1 1 auto;
	min-width: 0;
	line-height: 1.35;
}
.fx-msg__upload-retry-btn,
.fx-msg__upload-retry-drop {
	appearance: none;
	border: 0;
	padding: 6px 12px;
	min-height: 30px;
	border-radius: 999px;
	font: inherit;
	font-size: 12px;
	font-weight: 600;
	cursor: pointer;
	transition: background 0.15s ease, transform 0.12s ease;
}
.fx-msg__upload-retry-btn {
	background: var(--fx-brand);
	color: #fff;
}
.fx-msg__upload-retry-btn:hover,
.fx-msg__upload-retry-btn:focus-visible {
	background: color-mix(in srgb, var(--fx-brand) 85%, #000);
	outline: none;
}
.fx-msg__upload-retry-btn:active {
	transform: scale(0.97);
}
.fx-msg__upload-retry-drop {
	background: transparent;
	color: var(--fx-text-dim);
	border: 1px solid var(--fx-border);
}
.fx-msg__upload-retry-drop:hover,
.fx-msg__upload-retry-drop:focus-visible {
	color: var(--fx-text);
	border-color: var(--fx-brand);
	outline: none;
}
html[scheme='dark'] .fx-msg__upload-retry {
	background: rgba(214, 54, 56, 0.18);
	border-color: rgba(214, 54, 56, 0.45);
	color: #eef1f6;
}
html[scheme='dark'] .fx-msg__upload-retry-drop {
	color: rgba(255, 255, 255, 0.75);
	border-color: rgba(255, 255, 255, 0.2);
}

/* Бейдж «ожидает доставки в Telegram» — показывается на optimistic-
   сообщении при 202 от /api/upload (D13-full). Это не ошибка, просто
   сервер временно не смог достучаться до TG, отложил в spool и docker
   worker докатит через 30с-1мин. Визуально — мягкий нейтральный тон,
   без красного (мы НЕ хотим, чтобы юзер давил retry и дублировал). */
.fx-msg--upload-queued .fx-att--uploading {
	border-color: color-mix(in srgb, var(--fx-brand) 30%, var(--fx-border)) !important;
	opacity: 0.92;
}
.fx-msg--upload-queued .fx-att__upload-bar {
	background: color-mix(in srgb, var(--fx-brand) 45%, var(--fx-border)) !important;
}
.fx-msg__queued-badge {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	margin: 4px 0 0;
	padding: 3px 10px;
	border-radius: 999px;
	background: color-mix(in srgb, var(--fx-brand) 12%, var(--fx-bg));
	border: 1px solid color-mix(in srgb, var(--fx-brand) 35%, var(--fx-border));
	font-size: 11px;
	line-height: 1.4;
	color: var(--fx-text);
	font-weight: 500;
}
.fx-msg__queued-badge::before {
	content: '';
	width: 6px; height: 6px;
	border-radius: 50%;
	background: var(--fx-brand);
	box-shadow: 0 0 0 2px color-mix(in srgb, var(--fx-brand) 25%, transparent);
	animation: fxQueuedPulse 1.4s ease-in-out infinite;
}
@keyframes fxQueuedPulse {
	0%, 100% { opacity: 0.5; transform: scale(0.9); }
	50% { opacity: 1; transform: scale(1.15); }
}
html[scheme='dark'] .fx-msg__queued-badge {
	background: var(--fx-surface-2);
	border-color: var(--fx-surface-border);
	color: #e9edf3;
}

/* Тёмная тема --------------------------------------------------------------- */
html[scheme='dark'] .fx-att {
	background: var(--fx-surface-1);
	border-color: rgba(255, 255, 255, 0.1);
}
html[scheme='dark'] .fx-att:hover {
	border-color: color-mix(in srgb, var(--fx-brand) 55%, var(--fx-surface-border));
	box-shadow: 0 4px 18px rgba(0, 0, 0, 0.4);
}

/* Мобильный вид ------------------------------------------------------------ */
@media (max-width: 600px) {
	.fx-atts {
		grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
	}
	.fx-att--sticker img,
	.fx-att--sticker video {
		width: 108px;
		height: 108px;
	}
}

/* ==========================================================================
   Lightbox (галерея просмотра изображений и видео)
   ========================================================================== */

.fx-lb {
	position: fixed;
	inset: 0;
	background: rgba(0, 0, 0, 0.85);
	backdrop-filter: blur(6px);
	-webkit-backdrop-filter: blur(6px);
	z-index: 2147483000;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 16px;
	opacity: 0;
	visibility: hidden;
	transition: opacity .2s ease, visibility 0s linear .2s;
}

/* =========================================================================
   F18 — PDF preview modal.
   Полноэкранный оверлей с header (title + download + close) и iframe
   внутри. Использует нативный PDF viewer браузера — ничего не нужно
   подгружать. z-index чуть ниже lightbox'а, т.к. они взаимно не
   пересекаются (PDF не попадает в галерею images/video).
   ========================================================================= */
.fx-pdf {
	position: fixed;
	inset: 0;
	background: rgba(15, 18, 24, 0.92);
	backdrop-filter: blur(4px);
	-webkit-backdrop-filter: blur(4px);
	z-index: 2147482900;
	display: flex;
	flex-direction: column;
	opacity: 0;
	visibility: hidden;
	transition: opacity .18s ease, visibility 0s linear .18s;
}
.fx-pdf[aria-hidden='false'] {
	opacity: 1;
	visibility: visible;
	transition: opacity .18s ease;
}
body.fx-pdf-open { overflow: hidden; }
.fx-pdf__header {
	display: flex;
	align-items: center;
	gap: 12px;
	padding: 10px 16px;
	background: rgba(0, 0, 0, 0.35);
	border-bottom: 1px solid rgba(255, 255, 255, 0.08);
	color: #e8ecf2;
	flex: 0 0 auto;
}
.fx-pdf__title {
	flex: 1;
	font-size: 14px;
	font-weight: 600;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
.fx-pdf__download {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 7px 14px;
	border-radius: 8px;
	background: var(--fx-brand, #216be9);
	color: #fff !important;
	text-decoration: none;
	font-size: 13px;
	font-weight: 600;
	transition: filter .15s ease;
}
.fx-pdf__download:hover { filter: brightness(1.1); }
.fx-pdf__close {
	background: transparent;
	border: 0;
	color: #e8ecf2;
	font-size: 28px;
	line-height: 1;
	cursor: pointer;
	padding: 4px 10px;
	border-radius: 8px;
	transition: background 0.14s ease, color 0.14s ease, transform 0.12s ease;
}
.fx-pdf__close:hover,
.fx-pdf__close:focus-visible {
	color: #ff8a8c;
	background: rgba(255, 99, 99, 0.14);
	outline: none;
}
.fx-pdf__close:active {
	transform: scale(0.92);
	background: rgba(255, 99, 99, 0.22);
}
.fx-pdf__stage {
	flex: 1;
	display: flex;
	background: #2a2d33;
	overflow: hidden;
}
.fx-pdf__frame {
	flex: 1;
	border: 0;
	background: #fff;
	width: 100%;
	height: 100%;
}
/* На совсем узких экранах ( <560px ) модал не открывается JS-ом —
   но на случай rotate/resize во время просмотра держим iframe читаемым. */
@media (max-width: 560px) {
	.fx-pdf__header { padding: 8px 10px; gap: 8px; }
	.fx-pdf__download span { display: none; }
	.fx-pdf__download { padding: 7px 10px; }
	.fx-pdf__title { font-size: 12.5px; }
}
.fx-lb[aria-hidden="false"] {
	opacity: 1;
	visibility: visible;
	transition: opacity .2s ease;
}

body.fx-lb-open {
	overflow: hidden !important;
	overscroll-behavior: none !important;
}

.fx-lb__stage {
	position: relative;
	max-width: min(96vw, 1400px);
	max-height: 92vh;
	display: flex;
	align-items: center;
	justify-content: center;
	touch-action: pan-y;
	user-select: none;
	-webkit-user-select: none;
}

.fx-lb__media {
	display: block;
	max-width: 96vw;
	max-height: 92vh;
	border-radius: 10px;
	box-shadow: 0 18px 60px rgba(0, 0, 0, 0.55);
	background: #000;
	transition: transform .28s cubic-bezier(.22, .61, .36, 1);
	will-change: transform;
}
/* display:block на .fx-lb__media перекрывал implicit display:none,
   который браузер добавляет [hidden]-элементам. Из-за этого при
   открытии КАРТИНКИ справа от неё в сцене «висел» пустой чёрный
   прямоугольник с нативными video-контролами. Возвращаем
   hidden-поведение приоритетно. */
.fx-lb__media[hidden] { display: none !important; }
.fx-lb__stage--dragging .fx-lb__media {
	transition: none;
}
.fx-lb__img  { object-fit: contain; cursor: pointer; }
.fx-lb__video { outline: none; cursor: pointer; }

/* Анимация смены слайда */
.fx-lb__slide-next { animation: fxLbSlideNext .35s cubic-bezier(.22,.61,.36,1); }
.fx-lb__slide-prev { animation: fxLbSlidePrev .35s cubic-bezier(.22,.61,.36,1); }
@keyframes fxLbSlideNext { from { opacity: 0; transform: translateX(40px); } to { opacity: 1; transform: translateX(0); } }
@keyframes fxLbSlidePrev { from { opacity: 0; transform: translateX(-40px); } to { opacity: 1; transform: translateX(0); } }

.fx-lb__close {
	position: absolute;
	top: 14px;
	right: 14px;
	background: transparent;
	border: 0;
	color: #e8ecf2;
	font-size: 28px;
	line-height: 1;
	cursor: pointer;
	padding: 4px 10px;
	border-radius: 8px;
	display: flex;
	align-items: center;
	justify-content: center;
	transition: background 0.14s ease, color 0.14s ease, transform 0.12s ease;
	z-index: 2;
}
.fx-lb__close:hover,
.fx-lb__close:focus-visible {
	color: #ff8a8c;
	background: rgba(255, 99, 99, 0.14);
	outline: none;
}
.fx-lb__close:active {
	transform: scale(0.92);
	background: rgba(255, 99, 99, 0.22);
}

.fx-lb__nav {
	position: absolute;
	top: 50%;
	transform: translateY(-50%);
	width: 48px;
	height: 48px;
	border-radius: 50%;
	background: rgba(255, 255, 255, 0.12);
	border: 1px solid rgba(255, 255, 255, 0.18);
	color: #fff;
	display: flex;
	align-items: center;
	justify-content: center;
	cursor: pointer;
	padding: 0;
	transition: background .15s ease, transform .15s ease;
	z-index: 2;
}
.fx-lb__nav:hover {
	background: rgba(255, 255, 255, 0.22);
	transform: translateY(-50%) scale(1.05);
}
.fx-lb__nav svg {
	width: 24px;
	height: 24px;
	display: block;
}
.fx-lb__prev { left: 14px; }
.fx-lb__next { right: 14px; }

.fx-lb__caption {
	position: absolute;
	left: 50%;
	bottom: 16px;
	transform: translateX(-50%);
	max-width: 92vw;
	padding: 6px 12px;
	border-radius: 999px;
	background: rgba(0, 0, 0, 0.55);
	color: #fff;
	font-size: 13px;
	font-weight: 500;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

.fx-lb__counter {
	position: absolute;
	top: 16px;
	left: 16px;
	padding: 4px 10px;
	border-radius: 999px;
	background: rgba(0, 0, 0, 0.5);
	color: rgba(255, 255, 255, 0.85);
	font-size: 12px;
	font-weight: 600;
	font-variant-numeric: tabular-nums;
}

@media (max-width: 600px) {
	.fx-lb__close { top: 10px; right: 10px; font-size: 24px; padding: 2px 8px; }
	.fx-lb__nav { display: none; } /* листаем свайпом */
	.fx-lb__counter { top: 10px; left: 10px; }
}

/* ======================================================================
 * Адресация онлайн-участнику (f5).
 * При тапе по счётчику online открывается dropdown со списком онлайн
 * (из /api/users/online). Выбрал юзера — в composer появляется чип
 * «Для @Name», следующее сообщение уходит с addressed_to_user_id,
 * и в ленте такое сообщение помечается бейджем «→ для @Name»,
 * а у получателя — лёгким акцентом «→ Вам».
 * ---------------------------------------------------------------------- */
.fx-chat-presence.is-open .fx-chat-presence-count {
	box-shadow: 0 0 0 3px color-mix(in srgb, var(--fx-brand) 28%, transparent);
}
.fx-online-dropdown {
	position: absolute;
	top: calc(100% + 6px);
	left: 0;
	min-width: 240px;
	max-width: min(320px, calc(100vw - 24px));
	max-height: min(60vh, 360px);
	overflow: auto;
	background: var(--fx-bg-elev);
	border: 1px solid var(--fx-border);
	border-radius: 14px;
	box-shadow: var(--fx-shadow, 0 8px 28px rgba(0,0,0,0.18));
	padding: 6px;
	z-index: 50;
	font-size: 13px;
	color: var(--fx-text);
}
.fx-online-dropdown[hidden] { display: none !important; }
.fx-online-dropdown__head {
	padding: 6px 10px;
	font-weight: 700;
	font-size: 12px;
	color: var(--fx-text-dim);
	letter-spacing: 0.01em;
	text-transform: uppercase;
}
.fx-online-dropdown__empty,
.fx-online-dropdown__loader {
	padding: 14px 10px;
	color: var(--fx-text-dim);
	text-align: center;
}
.fx-online-dropdown__row {
	display: flex;
	align-items: center;
	gap: 10px;
	width: 100%;
	padding: 8px 10px;
	background: transparent;
	border: 0;
	border-radius: 10px;
	cursor: pointer;
	color: var(--fx-text);
	text-align: left;
}
.fx-online-dropdown__row:hover,
.fx-online-dropdown__row:focus-visible {
	background: color-mix(in srgb, var(--fx-brand) 14%, transparent);
	outline: none;
}
.fx-online-dropdown__ava {
	width: 28px;
	height: 28px;
	border-radius: 50%;
	object-fit: cover;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex: none;
	background: var(--fx-bg);
	font-weight: 700;
	color: var(--fx-text);
	border: 1px solid var(--fx-border);
}
.fx-online-dropdown__ava--ph { font-size: 12px; }
.fx-online-dropdown__name {
	flex: 1 1 auto;
	overflow: hidden;
	white-space: nowrap;
	text-overflow: ellipsis;
	font-weight: 600;
}
.fx-online-dropdown__badge {
	flex: none;
	font-size: 10px;
	padding: 2px 7px;
	border-radius: 999px;
	background: color-mix(in srgb, var(--fx-brand) 20%, transparent);
	color: var(--fx-brand);
	font-weight: 800;
	text-transform: uppercase;
	letter-spacing: 0.04em;
}
.fx-online-dropdown__badge--moderator {
	background: rgba(246, 173, 85, 0.22);
	color: #e8952e;
}
.fx-online-dropdown__badge--admin {
	background: color-mix(in srgb, var(--fx-brand) 24%, transparent);
	color: var(--fx-brand);
}
/* TG-only участник — бейдж в цветах Telegram (28a8ea). Появляется
   справа от ника в панели онлайн-участников у людей, которых нашёл
   userbot в группе, но у которых нет WP-аккаунта. */
.fx-online-dropdown__badge--tg {
	background: rgba(40, 168, 234, 0.18);
	color: #1c86c7;
}
html[scheme='dark'] .fx-online-dropdown__badge--tg {
	background: rgba(40, 168, 234, 0.24);
	color: #6dc2f0;
}
.fx-online-dropdown__tgdot {
	width: 8px;
	height: 8px;
	border-radius: 50%;
	background: #229ed9;
	flex: none;
}

/* Чип «Для @Name» в композере — оформлен один-в-один с reply-bar
   (.fx-chat-reply): та же линейка padding/фон/border-top/font-size,
   чтобы два блока над полем ввода выглядели как одна семейная
   конструкция. Отличие только в содержимом — здесь нет тела
   сообщения, только ник адресата. Так пользователь и просил:
   «оформить как обычный ответ, только без сообщения участника, а
   просто ответ его нику». */
.fx-chat-addressed {
	/* flex:none — чтобы бар в flex-column-родителе (`.fenix-chat-wrap`
	   или `.fx-chat-composer-dock`) занимал ровно высоту контента.
	   Раньше стояло `flex: 1 1 100%` — это делало basis=100% от
	   родителя, и бар растягивался на полную оставшуюся высоту
	   между лентой и композером, откуда и брались «огромные пустоты
	   сверху и снизу ника». `order: -2` тут не нужен — бар вставляется
	   JS'ом прямо перед reply-bar в нужное место DOM-потока. */
	flex: none;
	display: flex;
	align-items: center;
	gap: 6px;
	padding: 10px 14px;
	margin: 0;
	background: var(--fx-bg-elev);
	border-top: 1px solid var(--fx-border);
	border-radius: 0;
	font-size: 12px;
	line-height: 1.2;
	min-height: 0;
}
.fx-chat-addressed[hidden] { display: none !important; }
.fx-chat-addressed__label {
	color: var(--fx-text-dim);
	font-weight: 600;
}
.fx-chat-addressed__name {
	color: var(--fx-brand);
	font-weight: 700;
	/* Ник адресата (кому пишем) — крупнее базового 12px бара, чтобы
	   имя сразу бросалось в глаза. 15px подбирался так, чтобы бар не
	   «распухал» по высоте: line-height остаётся 1.2 и padding бара
	   не трогаем. */
	font-size: 15px;
	line-height: 1.2;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	flex: 1 1 auto;
}
.fx-chat-addressed__clear {
	background: transparent;
	border: 0;
	color: var(--fx-text-dim);
	cursor: pointer;
	font-size: 18px;
	line-height: 1;
	padding: 4px 8px;
	border-radius: 8px;
	transition: background 0.14s ease, color 0.14s ease, transform 0.12s ease;
}
.fx-chat-addressed__clear:hover,
.fx-chat-addressed__clear:focus-visible {
	color: var(--fx-danger);
	background: rgba(214, 54, 56, 0.08);
	outline: none;
}
.fx-chat-addressed__clear:active {
	transform: scale(0.92);
	background: rgba(214, 54, 56, 0.16);
}
html[scheme='dark'] .fx-chat-addressed__clear:hover,
html[scheme='dark'] .fx-chat-addressed__clear:focus-visible {
	color: #ff8a8c;
	background: rgba(255, 99, 99, 0.14);
}
html[scheme='dark'] .fx-chat-addressed__clear:active {
	background: rgba(255, 99, 99, 0.22);
}

/* Бейдж «→ Для @Name» внутри пузыря. */
.fx-msg__addressee {
	display: inline-flex;
	align-items: center;
	gap: 4px;
	margin: 0 0 4px;
	padding: 2px 8px;
	border-radius: 999px;
	font-size: 11.5px;
	font-weight: 700;
	background: color-mix(in srgb, var(--fx-brand) 14%, transparent);
	color: var(--fx-brand);
	line-height: 1.3;
	letter-spacing: 0.01em;
	max-width: 100%;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
.fx-msg__addressee-ico { font-size: 13px; line-height: 1; }
.fx-msg__addressee-label {
	color: var(--fx-text-dim);
	font-weight: 600;
}
.fx-msg__addressee-name {
	color: inherit;
}

/* Адресовано текущему пользователю — усиленный акцент слева бабла. */
.fx-msg--addressed-to-me .fx-msg__bubble {
	box-shadow:
		inset 3px 0 0 var(--fx-brand),
		0 1px 2px rgba(0, 0, 0, 0.06);
}
.fx-msg--addressed-to-me .fx-msg__addressee {
	background: color-mix(in srgb, var(--fx-brand) 22%, transparent);
}

@media (max-width: 768px) {
	.fx-online-dropdown {
		left: auto;
		right: 0;
		min-width: 72vw;
		max-width: 92vw;
	}
}

/* ======================================================================
 * F23 — БОЛЬШАЯ ПАНЕЛЬ ОНЛАЙН-УЧАСТНИКОВ
 * ----------------------------------------------------------------------
 * Полноэкранный оверлей внутри .fenix-chat-wrap (inset:0), слайдится
 * снизу вверх, затемняет feed+composer, закрывается кликом по фону,
 * крестиком в шапке или Escape.
 *
 * Источник палитры — notification-цвета чата (уведомления-баннеры):
 * --fx-bg-elev как основной фон панели, --fx-border как рамка,
 * акценты через color-mix c var(--fx-brand).
 * -------------------------------------------------------------------- */
/* Ширина панели — адаптивная. На узких экранах сужается до 72% ширины
   wrap'а; на широких — фиксированные 320px. */
.fenix-chat-wrap {
	--fx-online-panel-w: clamp(240px, 62%, 320px);
	/* Совпадает с шириной drawer'а статистики (.fx-chat-info-popover). */
	--fx-info-panel-w: clamp(280px, 62%, 380px);
}
.fx-online-panel {
	position: absolute;
	top: var(--fx-panel-top, 0px);
	bottom: var(--fx-panel-bottom, 0px);
	left: 0;
	width: var(--fx-online-panel-w);
	max-width: 85%;
	z-index: 55;
	display: flex;
	flex-direction: column;
	pointer-events: none;
}
/* На мобильных панель занимает всё окно чата — места под «смещённую
   ленту» не остаётся, а компактная drawer меньше 240px читается плохо.
   Соответственно и padding-left на контенте чата в мобильной версии
   не применяем (см. ниже в .is-online-panel-open@mobile). */
@media (max-width: 640px) {
	.fenix-chat-wrap { --fx-online-panel-w: 100%; --fx-info-panel-w: 100%; }
	.fx-online-panel { width: 100%; max-width: 100%; }
}
.fx-online-panel[hidden] { display: none !important; }
/* Сам «лист» панели. Позиционируется внутри .fx-online-panel,
   полная высота доступной области, скругление справа — чтобы
   визуально отделить от смещённой ленты, как боковая drawer. */
.fx-online-panel__sheet {
	position: absolute;
	inset: 0;
	background: var(--fx-bg-elev);
	border-right: 1px solid var(--fx-border);
	/* По просьбе пользователя — прямые углы. Панель прижата
	   к левому краю чата и визуально «отрезает» ленту прямой
	   линией, без скруглений. */
	border-radius: 0;
	box-shadow: 12px 0 28px rgba(0, 0, 0, 0.12);
	display: flex;
	flex-direction: column;
	min-height: 0;
	transform: translateX(-102%);
	opacity: 0;
	transition: transform 0.28s cubic-bezier(0.2, 0.8, 0.2, 1), opacity 0.22s ease;
	pointer-events: auto;
}
.fx-online-panel.is-open .fx-online-panel__sheet {
	transform: translateX(0);
	opacity: 1;
}
/* Панели участников (слева) и статистики (справа) ВЫЕЗЖАЮТ ПОВЕРХ ленты
   как drawer'ы и НЕ смещают сообщения/пузыри (запрос пользователя:
   «должны выезжать не смещая текст сообщений и пузыри, а поверх чата»).
   Раньше при открытии лента получала padding-left/right на ширину
   панели — текст «съезжал» вбок и дёргался во время 0.28s перехода.
   Теперь лента остаётся на месте, а панели (position:absolute,
   z-index 55/60, непрозрачный фон + тень) просто перекрывают её сбоку. */

/* Непрозрачный фон drawer'ов на ВСЕХ экранах — лента под ними не должна
   просвечивать (--fx-bg-elev / card-bg в некоторых темах полупрозрачный,
   из-за чего пузыри «проступали» сквозь панель). До этого фикс был только
   в мобильном media-блоке; теперь панели накрывают ленту и на десктопе. */
.fenix-chat-wrap .fx-online-panel__sheet,
.fenix-chat-wrap .fx-chat-info-popover {
	background: #ffffff;
	background-color: #ffffff;
}
html[scheme='dark'] .fenix-chat-wrap .fx-online-panel__sheet,
body.fenix-chat-force-dark .fenix-chat-wrap .fx-online-panel__sheet,
html[scheme='dark'] .fenix-chat-wrap .fx-chat-info-popover,
body.fenix-chat-force-dark .fenix-chat-wrap .fx-chat-info-popover {
	background: #1f2328;
	background-color: #1f2328;
}
@media (prefers-color-scheme: dark) {
	html:not([scheme]) .fenix-chat-wrap .fx-online-panel__sheet,
	html:not([scheme]) .fenix-chat-wrap .fx-chat-info-popover {
		background: #1f2328;
		background-color: #1f2328;
	}
}
/* На мобильных панель на всё окно → ленте «сместиться вправо» некуда.
   ВАЖНО: не сбрасываем padding в `0`, а возвращаем ДЕФОЛТНЫЕ значения
   (14px), иначе пузыри получают 14 + 14 = 28px лишнего внутреннего
   пространства и визуально становятся ШИРЕ. Пользователь жаловался:
   «при открытии окна участников/статистики сообщения становятся шире
   пузыри». Панели всё равно position:absolute с width:100% на мобилке —
   они полностью перекрывают ленту поверх, независимо от её padding'а. */
@media (max-width: 640px) {
	.fenix-chat-wrap.is-online-panel-open .fx-chat-feed,
	.fenix-chat-wrap.is-online-panel-open .fx-chat-pinned,
	.fenix-chat-wrap.is-online-panel-open .fx-chat-select-bar,
	.fenix-chat-wrap.is-info-panel-open .fx-chat-feed,
	.fenix-chat-wrap.is-info-panel-open .fx-chat-pinned,
	.fenix-chat-wrap.is-info-panel-open .fx-chat-select-bar,
	.fenix-chat-wrap.is-online-panel-open #fx-chat-scroll > .fx-chat-typing,
	.fenix-chat-wrap.is-info-panel-open #fx-chat-scroll > .fx-chat-typing {
		/* Дефолтный padding `.fx-chat-feed` = 16px 14px 8px; для
		   pinned/select-bar — свои дефолты, возвращаем их 14px на
		   боках, чтобы пузыри оставались в той же полосе 100% − 28px. */
		padding-left: 14px !important;
		padding-right: 14px !important;
		transition: none !important;
	}
	.fx-chat-feed,
	.fx-chat-pinned,
	.fx-chat-select-bar {
		/* На мобильном ленту НЕ анимируем по padding — любое изменение
		   в параллельной (пере)раскладке вызывало «прыгающий» текст
		   во время 0.28s перехода. */
		transition: none !important;
	}
}
.fx-chat-feed,
.fx-chat-pinned,
.fx-chat-select-bar {
	transition: padding-left 0.28s cubic-bezier(0.2, 0.8, 0.2, 1),
		padding-right 0.28s cubic-bezier(0.2, 0.8, 0.2, 1);
}

/* --------------------------------------------------------------------
 * МОБИЛЬНЫЙ ОВЕРЛЕЙ ПАНЕЛИ УЧАСТНИКОВ — форсируем непрозрачный фон
 * --------------------------------------------------------------------
 * На мобильных панель занимает всё окно чата (width: 100%), поэтому
 * лента сообщений оказывается прямо под ней. В некоторых темах
 * --fx-bg-elev resolves в rgba() c alpha (WP preset `card-bg` может
 * быть настроен как полупрозрачный) — и лента начинает «просвечивать»
 * сквозь sheet, выглядит как накладка сообщений поверх меню.
 *
 * Правило ниже идёт ПОСЛЕ базового `.fx-online-panel__sheet`, имеет
 * повышенную специфичность через `.fenix-chat-wrap`, и разведено на
 * ВСЕ четыре варианта темы (light / html[scheme=dark] / force-dark /
 * prefers-color-scheme:dark у гостя), чтобы никакой последующий
 * каскад тему уже не перебил. Плюс box-shadow убираем — drawer
 * перекрывает ленту плотно, «краевая подсветка» не нужна.
 *
 * Дополнительно: z-index панели поднят до 60 (сверху feed/pinned/
 * composer), `isolation: isolate` даёт новый контекст наложения —
 * дочерние transform/opacity ленты не могут «всплыть» над панелью.
 * -------------------------------------------------------------------- */
@media (max-width: 640px) {
	.fenix-chat-wrap .fx-online-panel {
		z-index: 60;
		isolation: isolate;
	}
	.fenix-chat-wrap .fx-online-panel__sheet {
		background: #ffffff;
		background-color: #ffffff;
		box-shadow: none;
	}
	html[scheme='dark'] .fenix-chat-wrap .fx-online-panel__sheet,
	body.fenix-chat-force-dark .fenix-chat-wrap .fx-online-panel__sheet {
		background: #1f2328;
		background-color: #1f2328;
	}
}
/* Гостевая авто-тёмная (у юзера ОС в dark, html без scheme): на мобиле
   тоже форсируем тёмный непрозрачный фон панели. */
@media (max-width: 640px) and (prefers-color-scheme: dark) {
	html:not([scheme]) .fenix-chat-wrap .fx-online-panel__sheet {
		background: #1f2328;
		background-color: #1f2328;
	}
}
.fx-online-panel__head {
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 12px 14px;
	border-bottom: 1px solid var(--fx-border);
	background: color-mix(in srgb, var(--fx-brand) 6%, var(--fx-bg-elev));
}
/* Поиск по участникам — занимает всю ширину шапки. И заголовок
   «Участники чата», и кнопка-крестик убраны (закрытие — тапом вне
   панели, Esc или повторным нажатием иконки «Участники»). Иконка-лупа
   внутри поля (абсолютом) + сам input; на фокусе — brand-рамка.
   Используем те же токены, что и у .fx-chat-input/.fx-chat-search
   в композере, чтобы визуально читалось как «поиск» единообразно. */
.fx-online-panel__search-wrap {
	flex: 1 1 auto;
	min-width: 0;
	position: relative;
	display: flex;
	align-items: center;
}
.fx-online-panel__search-icon {
	position: absolute;
	left: 10px;
	top: 50%;
	transform: translateY(-50%);
	color: var(--fx-text-dim);
	pointer-events: none;
	flex: none;
}
.fenix-chat-wrap .fx-online-panel__search {
	width: 100%;
	min-width: 0;
	height: 34px;
	padding: 0 12px 0 30px;
	background: var(--fx-bg);
	color: var(--fx-text);
	border: 1.5px solid var(--fx-border);
	border-radius: 10px;
	font: inherit;
	font-size: 13px;
	font-weight: 500;
	outline: none;
	box-sizing: border-box;
	appearance: none;
	-webkit-appearance: none;
	background-image: none;
	transition: border-color 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
	-webkit-tap-highlight-color: transparent;
}
.fenix-chat-wrap .fx-online-panel__search:hover {
	border-color: color-mix(in srgb, var(--fx-brand) 45%, var(--fx-border));
}
.fenix-chat-wrap .fx-online-panel__search:focus {
	border-color: var(--fx-brand);
	box-shadow: 0 0 0 3px rgba(33, 107, 233, 0.15);
}
.fenix-chat-wrap .fx-online-panel__search::placeholder {
	color: var(--fx-text-dim);
	opacity: 0.85;
}
.fenix-chat-wrap .fx-online-panel__search::-webkit-search-decoration,
.fenix-chat-wrap .fx-online-panel__search::-webkit-search-cancel-button,
.fenix-chat-wrap .fx-online-panel__search::-webkit-search-results-button,
.fenix-chat-wrap .fx-online-panel__search::-webkit-search-results-decoration {
	appearance: none;
	-webkit-appearance: none;
	display: none;
}
html[scheme='dark'] .fenix-chat-wrap .fx-online-panel__search,
body.fenix-chat-force-dark .fenix-chat-wrap .fx-online-panel__search {
	background: var(--fx-surface-1);
	border-color: var(--fx-surface-border);
	color: var(--fx-text);
}
html[scheme='dark'] .fenix-chat-wrap .fx-online-panel__search:hover,
body.fenix-chat-force-dark .fenix-chat-wrap .fx-online-panel__search:hover {
	border-color: color-mix(in srgb, var(--fx-brand) 55%, var(--fx-surface-border));
}
html[scheme='dark'] .fenix-chat-wrap .fx-online-panel__search:focus,
body.fenix-chat-force-dark .fenix-chat-wrap .fx-online-panel__search:focus {
	background: rgba(33, 107, 233, 0.08);
	border-color: var(--fx-brand);
	box-shadow: 0 0 0 3px rgba(33, 107, 233, 0.22);
}
@media (prefers-color-scheme: dark) {
	html:not([scheme]) .fenix-chat-wrap .fx-online-panel__search {
		background: var(--fx-surface-1);
		border-color: var(--fx-surface-border);
		color: var(--fx-text);
	}
	html:not([scheme]) .fenix-chat-wrap .fx-online-panel__search:focus {
		background: rgba(33, 107, 233, 0.08);
		border-color: var(--fx-brand);
		box-shadow: 0 0 0 3px rgba(33, 107, 233, 0.22);
	}
}
.fx-online-panel__close {
	flex: none;
	width: 34px;
	height: 34px;
	border-radius: 50%;
	border: 1px solid var(--fx-border);
	background: var(--fx-bg);
	color: var(--fx-text-dim);
	font-size: 14px;
	line-height: 1;
	cursor: pointer;
	transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
	/* Крестик центрируем flex'ом: без этого символ «✕» сидит со
	   сдвигом из-за baseline-выравнивания кнопки (в Safari/iOS
	   особенно заметно). padding:0 снимает авто-отступ у <button>. */
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 0;
	font-family: inherit;
}
.fx-online-panel__close:hover,
.fx-online-panel__close:focus-visible {
	background: color-mix(in srgb, var(--fx-brand) 14%, var(--fx-bg));
	color: var(--fx-brand);
	border-color: color-mix(in srgb, var(--fx-brand) 30%, var(--fx-border));
	outline: none;
}
.fx-online-panel__body {
	flex: 1 1 auto;
	overflow-y: auto;
	padding: 10px 10px 18px;
	-webkit-overflow-scrolling: touch;
}
.fx-online-panel__loader,
.fx-online-panel__empty {
	padding: 24px 16px;
	color: var(--fx-text-dim);
	text-align: center;
	font-size: 14px;
}
.fx-online-panel__section { margin-top: 6px; }
.fx-online-panel__section + .fx-online-panel__section { margin-top: 16px; }
.fx-online-panel__section-title {
	padding: 6px 12px;
	font-size: 11px;
	font-weight: 800;
	color: var(--fx-text-dim);
	text-transform: uppercase;
	letter-spacing: 0.06em;
}
/* Админ-секция — визуально выделена лёгким brand-тинтом поверх
   panel-body, чтобы «администраторы» сразу бросались в глаза в
   самом верху списка участников. Заголовок окрашен в brand-цвет. */
.fx-online-panel__section--admins {
	background: color-mix(in srgb, var(--fx-brand) 7%, transparent);
	border: 1px solid color-mix(in srgb, var(--fx-brand) 22%, transparent);
	border-radius: 14px;
	padding: 4px 4px 6px;
	margin-top: 0;
}
.fx-online-panel__section--admins .fx-online-panel__section-title {
	color: var(--fx-brand);
}
html[scheme='dark'] .fx-online-panel__section--admins {
	background: color-mix(in srgb, var(--fx-brand) 14%, transparent);
	border-color: color-mix(in srgb, var(--fx-brand) 38%, transparent);
}
.fx-online-panel__list {
	display: flex;
	flex-direction: column;
	gap: 2px;
}
.fx-online-panel__row {
	display: flex;
	align-items: center;
	gap: 12px;
	width: 100%;
	padding: 8px 12px;
	background: transparent;
	border: 0;
	border-radius: 12px;
	font: inherit;
	color: var(--fx-text);
	text-align: left;
	cursor: pointer;
	transition: background 0.14s ease;
}
.fx-online-panel__row:hover,
.fx-online-panel__row:focus-visible {
	background: color-mix(in srgb, var(--fx-brand) 12%, transparent);
	outline: none;
}
.fx-online-panel__row-avaside {
	position: relative;
	flex: none;
	width: 40px;
	height: 40px;
}
.fx-online-panel__ava {
	width: 40px;
	height: 40px;
	border-radius: 50%;
	object-fit: cover;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	background: var(--fx-bg);
	border: 1px solid var(--fx-border);
	font-weight: 800;
	color: var(--fx-text);
	font-size: 14px;
}
.fx-online-panel__ava--ph {
	text-transform: uppercase;
}
.fx-online-panel__dot {
	position: absolute;
	right: -1px;
	bottom: -1px;
	width: 10px;
	height: 10px;
	border-radius: 50%;
	background: var(--fx-online, #22a06b);
	box-shadow: 0 0 0 2px var(--fx-bg-elev);
}
.fx-online-panel__row-main {
	flex: 1 1 auto;
	min-width: 0;
	display: flex;
	flex-direction: column;
	/* Компактная колонка: ник и @username теперь практически
	   «подлеплены» друг к другу, без видимого разрыва. Статус
	   ниже дышит сам за счёт своего font-size/line-height. */
	gap: 0;
}
.fx-online-panel__row-main > .fx-online-panel__username,
.fx-online-panel__row-main > .fx-online-panel__tgline {
	/* чуть поджимаем верхний отступ у @-строки, чтобы визуально шла
	   сразу под ником */
	margin-top: -1px;
}
/* Строка «самолётик TG + @username» — один flex-ряд, у TG-иконки
   фиксированный размер, а @username-спан ужимается/обрезается
   ellipsis'ом. Без этой обёртки иконка переезжала вниз или налезала
   на ник при узкой колонке. */
.fx-online-panel__tgline {
	display: inline-flex;
	align-items: center;
	gap: 3px;
	max-width: 100%;
	min-width: 0;
}
.fx-online-panel__tgline .fx-online-panel__username {
	min-width: 0;
	flex: 0 1 auto;
}
.fx-online-panel__tgline .fx-online-panel__tg {
	flex: 0 0 auto;
	width: 14px;
	height: 14px;
}
.fx-online-panel__tgline .fx-online-panel__tg svg {
	width: 12px;
	height: 12px;
}
.fx-online-panel__row-top {
	display: flex;
	align-items: center;
	gap: 8px;
	min-width: 0;
	width: 100%;
}
.fx-online-panel__name {
	flex: 0 1 auto;
	overflow: hidden;
	white-space: nowrap;
	text-overflow: ellipsis;
	font-weight: 700;
	font-size: 14.5px;
	color: var(--fx-text);
}
/* Самолётик TG рядом с ником — единый «язык» с TG-кнопкой в шапке
   чата. Специально не используем --fx-brand: TG-бирюза
   узнаваема и не конфликтует с синим бренд-цветом остальных
   индикаторов (роль/онлайн-точка). */
.fx-online-panel__tg {
	flex: none;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 18px;
	height: 18px;
	color: #2aabee;
}
.fx-online-panel__tg svg { display: block; }
html[scheme='dark'] .fx-online-panel__tg { color: #5dc1f0; }
/* Hover-хинт «➤ написать» в правом крае строки участника.
   Визуально и поведенчески тождествен такому же в reactors-popover
   (`.fx-readers-popover__dm-hint`): серая стрелка по умолчанию,
   brand-цветом при hover всей строки + плавный сдвиг вправо
   (translateX 2px). Без него строка кажется «статичной», и
   пользователи не пробуют кликнуть, чтобы написать участнику. */
.fx-online-panel__dm-hint {
	flex: 0 0 auto;
	align-self: center;
	margin-left: 8px;
	font-size: 14px;
	line-height: 1;
	color: var(--fx-text-dim);
	opacity: 0.55;
	transition: color 0.12s ease, opacity 0.12s ease, transform 0.12s ease;
}
.fx-online-panel__row:hover .fx-online-panel__dm-hint,
.fx-online-panel__row:focus-visible .fx-online-panel__dm-hint {
	color: var(--fx-brand);
	opacity: 1;
	transform: translateX(2px);
}
/* Быстрые контакты поддержки (WA / TG / Email) — только у строки
   администратора в списке участников. Стиль и анимация синхронизированы
   с toggle-кнопками шапки чата (`.fx-chat-info-toggle` и компанией):
     • круг с фоном --fx-bg-elev и тонким border'ом --fx-border;
     • hover — brand-тинт фона, brand-цвет иконки, translateY(-1px),
       мягкая тень;
     • active — scale(0.96), чуть более насыщенный тинт;
     • focus-visible — тот же hover-стиль + outline:none.
   Размер специально меньше header-кнопок (26×26, иконка 13×13), чтобы
   тройка кнопок помещалась рядом с ником администратора даже на узких
   панелях — ник не обрезается ellipsis'ом. На мобильных размер ещё
   чуть уменьшаем (см. media max-width: 640px). */
.fx-online-panel__adminlinks {
	/* Блок контактов админа — теперь прямой ребёнок row (а не row-top),
	   поэтому выравнивается вертикально по центру строки благодаря
	   `align-items: center` на самом row: аватар, текстовая колонка
	   (ник + @username + статус) и иконки лежат на одной средней оси. */
	flex: none;
	display: inline-flex;
	align-items: center;
	gap: 6px;
	margin-left: auto;
	/* align-self подстраховывает, если кто-нибудь переопределит
	   align-items у row — всё равно встанем по центру по высоте. */
	align-self: center;
}
.fx-online-panel__adminlink {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 32px;
	height: 32px;
	padding: 0;
	border-radius: 50%;
	color: var(--fx-text-dim);
	background: var(--fx-bg-elev);
	border: 1px solid var(--fx-border);
	box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
	-webkit-tap-highlight-color: transparent;
	touch-action: manipulation;
	transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease,
		transform 0.2s ease, box-shadow 0.2s ease;
}
.fx-online-panel__adminlink:hover,
.fx-online-panel__adminlink:focus-visible {
	color: var(--fx-brand);
	background: color-mix(in srgb, var(--fx-brand) 10%, var(--fx-bg));
	border-color: color-mix(in srgb, var(--fx-brand) 30%, var(--fx-border));
	transform: translateY(-1px);
	box-shadow: 0 2px 6px rgba(0, 0, 0, 0.06);
	outline: none;
}
.fx-online-panel__adminlink:active {
	transform: scale(0.96);
	background: color-mix(in srgb, var(--fx-brand) 16%, var(--fx-bg));
	border-color: color-mix(in srgb, var(--fx-brand) 40%, var(--fx-border));
	box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}
.fx-online-panel__adminlink svg {
	display: block;
	width: 16px;
	height: 16px;
}
.fx-online-panel__adminlink--wa:hover,
.fx-online-panel__adminlink--wa:focus-visible {
	color: #25d366;
	background: color-mix(in srgb, #25d366 12%, var(--fx-bg));
	border-color: color-mix(in srgb, #25d366 45%, var(--fx-border));
}
.fx-online-panel__adminlink--tg:hover,
.fx-online-panel__adminlink--tg:focus-visible {
	color: #2aabee;
	background: color-mix(in srgb, #2aabee 12%, var(--fx-bg));
	border-color: color-mix(in srgb, #2aabee 45%, var(--fx-border));
}
html[scheme='dark'] .fx-online-panel__adminlink {
	background: var(--fx-surface-2);
	color: var(--fx-text);
	border-color: var(--fx-surface-border);
}
html[scheme='dark'] .fx-online-panel__adminlink:hover,
html[scheme='dark'] .fx-online-panel__adminlink:focus-visible {
	background: var(--fx-brand-tint-weak);
	color: #b8d2ff;
	border-color: rgba(33, 107, 233, 0.5);
}
html[scheme='dark'] .fx-online-panel__adminlink--wa:hover,
html[scheme='dark'] .fx-online-panel__adminlink--wa:focus-visible {
	color: #4ce08a;
	border-color: rgba(37, 211, 102, 0.55);
}
html[scheme='dark'] .fx-online-panel__adminlink--tg:hover,
html[scheme='dark'] .fx-online-panel__adminlink--tg:focus-visible {
	color: #8dd7f7;
	border-color: rgba(42, 171, 238, 0.55);
}
@media (max-width: 640px) {
	/* На мобильном укрупняем кнопки связи до размера
	   header-toggle'ов (36×36, иконка 18×18), чтобы пальцем
	   попадать было удобно; gap чуть сжимаем — тройка кнопок
	   ~120px, ник админа не обрезается за счёт flex:1 у row-main. */
	.fx-online-panel__adminlinks {
		gap: 6px;
	}
	.fx-online-panel__adminlink {
		width: 36px;
		height: 36px;
	}
	.fx-online-panel__adminlink svg {
		width: 18px;
		height: 18px;
	}
}
/* @username под ником в списке участников (для тех, кто сейчас в TG-группе
   и у кого публичный username задан). Мелкая серая строка-ссылка;
   клик открывает приватную переписку в Telegram (t.me/<username>).
   Ширина ограничивается родителем + ellipsis, чтобы длинные ники не
   ломали сетку. */
.fx-online-panel__username {
	display: inline-block;
	max-width: 100%;
	overflow: hidden;
	white-space: nowrap;
	text-overflow: ellipsis;
	font-size: 11.5px;
	line-height: 1.2;
	color: var(--fx-text-dim);
	text-decoration: none;
	transition: color 0.15s ease;
}
.fx-online-panel__username:hover,
.fx-online-panel__username:focus-visible {
	color: var(--fx-brand);
	text-decoration: underline;
	outline: none;
}
.fx-online-panel__status {
	font-size: 12px;
	color: var(--fx-text-dim);
	line-height: 1.2;
}
.fx-online-panel__status--on {
	color: var(--fx-online, #22a06b);
	font-weight: 700;
}
html[scheme='dark'] .fx-online-panel__backdrop {
	background: rgba(0, 0, 0, 0.55);
}
html[scheme='dark'] .fx-online-panel__sheet {
	background: var(--fx-surface-1);
	border-top-color: var(--fx-surface-border);
}
html[scheme='dark'] .fx-online-panel__head {
	background: color-mix(in srgb, var(--fx-brand) 10%, var(--fx-surface-1));
	border-bottom-color: var(--fx-surface-border);
}
html[scheme='dark'] .fx-online-panel__close {
	background: var(--fx-surface-2);
	border-color: var(--fx-surface-border);
	color: var(--fx-text);
}
html[scheme='dark'] .fx-online-panel__row:hover,
html[scheme='dark'] .fx-online-panel__row:focus-visible {
	background: color-mix(in srgb, var(--fx-brand) 18%, transparent);
}
html[scheme='dark'] .fx-online-panel__ava {
	background: var(--fx-surface-2);
	border-color: var(--fx-surface-border);
}
html[scheme='dark'] .fx-online-panel__dot {
	box-shadow: 0 0 0 2px var(--fx-surface-1);
}

/* ======================================================================
 * Унификация hover у ВСЕХ круглых инструментальных кнопок чата.
 * ----------------------------------------------------------------------
 * Пользователь попросил, чтобы на hover ВСЕ кнопки красились в синий
 * бренд-цвет (как attach/send), а не только они. До этого патча часть
 * кнопок (tg/ig/translate/search/online) в ТЁМНОЙ теме подсвечивались
 * бледно-голубым (#b8d2ff) и слабым фоном — это выглядело «блёкло» по
 * сравнению с attach/send. Ниже — override одним блоком в конце файла
 * (высокая специфичность через `html[scheme='dark']` + cascade-order),
 * чтобы цвет иконки всегда равнялся чистому var(--fx-brand), а фон —
 * одинаковому тинту 16% brand на surface-1.
 * -------------------------------------------------------------------- */
.fx-chat-tg-btn:hover,
.fx-chat-tg-btn:focus-visible,
.fx-chat-ig-btn:hover,
.fx-chat-ig-btn:focus-visible,
.fx-chat-search-toggle:hover:not([aria-expanded='true']),
.fx-chat-search-toggle:focus-visible:not([aria-expanded='true']),
.fx-chat-presence-count:hover,
.fx-chat-presence-count:focus-visible {
	color: var(--fx-brand) !important;
	background: color-mix(in srgb, var(--fx-brand) 12%, var(--fx-bg)) !important;
	border-color: color-mix(in srgb, var(--fx-brand) 34%, var(--fx-border)) !important;
}
html[scheme='dark'] .fx-chat-tg-btn:hover,
html[scheme='dark'] .fx-chat-tg-btn:focus-visible,
html[scheme='dark'] .fx-chat-ig-btn:hover,
html[scheme='dark'] .fx-chat-ig-btn:focus-visible,
html[scheme='dark'] .fx-chat-search-toggle:hover:not([aria-expanded='true']),
html[scheme='dark'] .fx-chat-search-toggle:focus-visible:not([aria-expanded='true']),
html[scheme='dark'] .fx-chat-presence-count:hover,
html[scheme='dark'] .fx-chat-presence-count:focus-visible {
	color: var(--fx-brand) !important;
	background: color-mix(in srgb, var(--fx-brand) 18%, var(--fx-surface-1)) !important;
	border-color: color-mix(in srgb, var(--fx-brand) 45%, var(--fx-surface-border)) !important;
}

/* Addressed-clear и reply-clear ведут себя одинаково — ровно как
   кнопка сброса в reply-bar (красный тинт). Раньше здесь был brand-
   синий, но теперь блок оформлен как reply-bar, и поведение сделали
   консистентным. */
.fx-chat-addressed__clear:hover,
.fx-chat-addressed__clear:focus-visible {
	color: var(--fx-danger) !important;
	background: rgba(214, 54, 56, 0.08) !important;
	outline: none;
}
.fx-online-panel__close:hover,
.fx-online-panel__close:focus-visible {
	color: var(--fx-brand) !important;
	background: color-mix(in srgb, var(--fx-brand) 14%, var(--fx-bg)) !important;
	border-color: color-mix(in srgb, var(--fx-brand) 34%, var(--fx-border)) !important;
}

/* =========================================================
   F24 — Кнопка "колокольчик" (настройки уведомлений) и её popover.
   Визуально повторяет translate-toggle/info-toggle: круглая 48×48,
   brand на hover/focus и active. Popover появляется в ВЕРХНЕМ
   ЛЕВОМ углу области сообщений (зеркало translate-popover), чтобы
   не перекрывать кнопки справа и быть «рядом» с самой кнопкой.
   ========================================================= */
.fx-chat-notif {
	position: relative;
	display: inline-flex;
	align-items: center;
	flex: none;
}
/* Кнопка уведомлений — ЗЕРКАЛО .fx-chat-info-toggle (тот же круг 48×48,
   тот же фон, hover, active, aria-expanded). Держим два отдельных блока
   правил (а не один совмещённый), потому что темы часто перебивают
   селектор по ID/классу, а так мы гарантируем: какой бы CSS-override
   ни прилетел с темы, он одинаково действует на обе кнопки.
   `.fenix-chat-wrap` даёт +10 к specificity — перебиваем любые
   глобальные `button:hover { background: ... }` темы без !important. */
.fenix-chat-wrap .fx-chat-notif-toggle {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 48px;
	height: 48px;
	padding: 0;
	background: var(--fx-bg-elev);
	background-image: none;
	color: var(--fx-text-dim);
	border: 1px solid var(--fx-border);
	border-radius: 50%;
	cursor: pointer;
	flex: none;
	box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
	-webkit-tap-highlight-color: transparent;
	touch-action: manipulation;
	font-family: inherit;
	transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease,
		transform 0.2s ease, box-shadow 0.2s ease;
}
.fx-chat-notif-toggle__icon {
	width: 22px;
	height: 22px;
	display: block;
	color: inherit;
	stroke: currentColor;
	fill: none;
}
.fx-chat-notif-toggle .fx-chat-notif-toggle__icon path,
.fx-chat-notif-toggle .fx-chat-notif-toggle__icon circle,
.fx-chat-notif-toggle .fx-chat-notif-toggle__icon line {
	stroke: currentColor;
}
.fenix-chat-wrap .fx-chat-notif-toggle:hover,
.fenix-chat-wrap .fx-chat-notif-toggle:focus-visible {
	background: color-mix(in srgb, var(--fx-brand) 10%, var(--fx-bg));
	background-image: none;
	color: var(--fx-brand);
	border-color: color-mix(in srgb, var(--fx-brand) 30%, var(--fx-border));
	transform: translateY(-1px);
	box-shadow: 0 2px 6px rgba(0, 0, 0, 0.06);
	outline: none;
}
/* Иконка: форсим currentColor на <svg> и всех его потомках, чтобы
   тема (WooCommerce/storefront шлёт `button:hover svg { stroke: ... }`)
   не перекрашивала нам значок. */
.fenix-chat-wrap .fx-chat-notif-toggle:hover .fx-chat-notif-toggle__icon,
.fenix-chat-wrap .fx-chat-notif-toggle:focus-visible .fx-chat-notif-toggle__icon,
.fenix-chat-wrap .fx-chat-notif-toggle:hover .fx-chat-notif-toggle__icon *,
.fenix-chat-wrap .fx-chat-notif-toggle:focus-visible .fx-chat-notif-toggle__icon * {
	color: var(--fx-brand);
	stroke: var(--fx-brand);
	fill: none;
}
.fenix-chat-wrap .fx-chat-notif-toggle:active {
	transform: scale(0.96);
	background: color-mix(in srgb, var(--fx-brand) 16%, var(--fx-bg));
	background-image: none;
	border-color: color-mix(in srgb, var(--fx-brand) 40%, var(--fx-border));
	box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}
.fenix-chat-wrap .fx-chat-notif-toggle[aria-expanded='true'] {
	background: linear-gradient(135deg, var(--fx-brand, #216be9) 0%, var(--fx-brand-2, #1a5cd8) 100%);
	color: #fff;
	border-color: transparent;
	box-shadow: 0 4px 12px rgba(33, 107, 233, 0.35);
}
.fx-chat-notif-toggle[aria-expanded='true'] .fx-chat-notif-toggle__icon,
.fx-chat-notif-toggle[aria-expanded='true'] .fx-chat-notif-toggle__icon *,
.fx-chat-notif-toggle[aria-expanded='true'] .fx-chat-notif-toggle__icon path {
	color: #fff;
	stroke: #fff;
}
html[scheme='dark'] .fenix-chat-wrap .fx-chat-notif-toggle {
	background: var(--fx-surface-2);
	background-image: none;
	color: var(--fx-text);
	border-color: var(--fx-surface-border);
}
html[scheme='dark'] .fenix-chat-wrap .fx-chat-notif-toggle:hover,
html[scheme='dark'] .fenix-chat-wrap .fx-chat-notif-toggle:focus-visible {
	background: var(--fx-brand-tint-weak);
	background-image: none;
	color: #b8d2ff;
	border-color: rgba(33, 107, 233, 0.5);
}
html[scheme='dark'] .fenix-chat-wrap .fx-chat-notif-toggle[aria-expanded='true'] {
	color: #fff;
}

/* Индикатор «есть включённые уведомления» отключён по просьбе
   пользователя: колокольчик выглядит одинаково вне зависимости от
   состояния настроек. Сам <span> остаётся в разметке (chat.js его
   генерирует), но невидим. */
.fx-chat-notif-toggle__dot {
	display: none !important;
}

/* ============================================================
 *  Mobile overrides — специально ПОСЛЕ базовых правил
 *  .fenix-chat-wrap .fx-chat-notif-toggle, чтобы source-order
 *  выиграл при равной specificity. Ранее уже были mobile-блоки
 *  выше (строки ~4112/4324/4356), но затем в CSS добавился
 *  полный «зеркальный» базовый блок для notif-toggle (48×48) —
 *  он шёл позже в файле и перебивал мобильные 40/36/34.
 *  Итог: на мобильном кнопка notif была больше остальных.
 *  Здесь дублируем размеры в конце файла, чтобы она была
 *  ровно такого же размера, как info/translate/search.
 * ============================================================ */
@media (max-width: 600px) {
	.fenix-chat-wrap .fx-chat-notif-toggle {
		width: 40px;
		height: 40px;
		min-width: 40px;
		min-height: 40px;
	}
	.fenix-chat-wrap .fx-chat-notif-toggle .fx-chat-notif-toggle__icon {
		width: 20px;
		height: 20px;
	}
}
@media (max-width: 420px) {
	.fenix-chat-wrap .fx-chat-notif-toggle {
		width: 36px;
		height: 36px;
		min-width: 36px;
		min-height: 36px;
	}
	.fenix-chat-wrap .fx-chat-notif-toggle .fx-chat-notif-toggle__icon {
		width: 18px;
		height: 18px;
	}
}
@media (max-width: 360px) {
	.fenix-chat-wrap .fx-chat-notif-toggle {
		width: 34px;
		height: 34px;
		min-width: 34px;
		min-height: 34px;
	}
	.fenix-chat-wrap .fx-chat-notif-toggle .fx-chat-notif-toggle__icon {
		width: 17px;
		height: 17px;
	}
}

/* Popover. Позиционируется относительно .fenix-chat-wrap (JS переносит
   его туда при инициализации) и висит в ПРАВОМ верхнем углу окна
   сообщений — зеркало translate-popover (меню выбора языка), чтобы
   визуально быть в одной «зоне» с остальными кнопками шапки. */
.fx-chat-notif-popover {
	position: absolute;
	top: calc(var(--fx-panel-top, 0px) + 10px);
	right: 14px;
	z-index: 60;
	min-width: 320px;
	max-width: min(420px, calc(100% - 28px));
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 0;
	background: var(--fx-bg-elev, #fff);
	border: 1px solid var(--fx-border);
	border-radius: 14px;
	box-shadow: 0 18px 48px rgba(0, 0, 0, 0.22);
	color: var(--fx-text);
	font-size: 13px;
	box-sizing: border-box;
	opacity: 0;
	transform: translateY(-6px) scale(0.96);
	transform-origin: 90% 0%;
	transition: opacity 0.16s ease, transform 0.16s ease;
	pointer-events: none;
	overflow: hidden;
}
.fx-chat-notif-popover[data-open='1'] {
	opacity: 1;
	transform: translateY(0) scale(1);
	pointer-events: auto;
	animation: fx-emoji-pop 0.18s ease-out;
}
.fx-chat-notif-popover[hidden] {
	display: none !important;
}
/* Отдельного заголовка и head-блока больше нет: по запросу пользователя
   слово «Уведомления» теперь — заголовок первого столбца таблицы
   (thead → .fx-chat-notif-table__th-main), а popover закрывается
   кликом вне / ESC. Старый селектор оставляем `display:none`, чтобы
   если где-то в разметке ещё остался узел — он не «торчал». */
.fx-chat-notif-popover__title {
	display: none !important;
}
.fx-chat-notif-popover__body {
	padding: 10px 12px 12px;
	display: flex;
	flex-direction: column;
	gap: 8px;
}
.fx-chat-notif-popover__loading,
.fx-chat-notif-popover__error {
	padding: 14px 4px;
	text-align: center;
	color: var(--fx-text-dim);
	font-size: 13px;
}
.fx-chat-notif-popover__error { color: #c0392b; }

/* Табличка prefs: строка = событие, 3 ячейки-чекбокса = каналы.
   По просьбе пользователя сетка и рамка полностью убраны — ни одной
   линии, ни вокруг таблицы, ни между строками/заголовками. Некоторые
   темы WooCommerce (напр. Blogsy) вешают `border` с высокой спец-ю
   на `table, thead, tbody, th, td` — поэтому используем !important. */
.fx-chat-notif-table {
	width: 100%;
	border-collapse: collapse;
	border-spacing: 0;
	border: 0 !important;
	background: transparent !important;
	font-size: 13px;
	margin: 0;
	table-layout: auto;
	box-shadow: none !important;
}
.fx-chat-notif-table,
.fx-chat-notif-table thead,
.fx-chat-notif-table tbody,
.fx-chat-notif-table tr,
.fx-chat-notif-table th,
.fx-chat-notif-table td {
	border: 0 !important;
	background-color: transparent !important;
	box-shadow: none !important;
}
.fx-chat-notif-table thead th {
	text-align: center;
	font-weight: 700;
	font-size: 11px;
	letter-spacing: 0.03em;
	text-transform: uppercase;
	color: var(--fx-text-dim);
	padding: 4px 4px 8px;
	white-space: nowrap;
}
/* Первая колонка «событие» растягивается, остальные (каналы) — компактные. */
.fx-chat-notif-table thead th:not(:first-child),
.fx-chat-notif-table tbody td.fx-chat-notif-cell {
	width: 1%;
	min-width: 54px;
}
.fx-chat-notif-table thead th:first-child {
	text-align: left;
}
/* По просьбе пользователя первый столбец «Уведомления» визуально
   ничем не отличается от других заголовков-каналов (EMAIL / TELEGRAM /
   САЙТ) — тот же up-case, тот же цвет --fx-text-dim, тот же 11px.
   Раньше здесь был отдельный «главный» стиль (крупнее и ярче), потому
   что надпись играла роль заголовка попапа; теперь это просто ещё
   одна колонка с такой же типографикой. Класс оставляем — тонкая
   разделительная линия ниже всё ещё отделяет thead от tbody. */
.fx-chat-notif-table thead th.fx-chat-notif-table__th-main {
	font-size: 11px;
	font-weight: 700;
	letter-spacing: 0.03em;
	text-transform: uppercase;
	color: var(--fx-text-dim);
	padding-bottom: 8px;
}
.fx-chat-notif-table thead tr {
	border-bottom: 1px solid color-mix(in srgb, var(--fx-border) 55%, transparent) !important;
}
.fx-chat-notif-table tbody td {
	padding: 8px 6px;
}
.fx-chat-notif-table tbody td.fx-chat-notif-cell {
	text-align: center;
}
.fx-chat-notif-table .fx-chat-notif-row__label {
	color: var(--fx-text);
	font-weight: 600;
	line-height: 1.25;
}
.fx-chat-notif-table .fx-chat-notif-row__hint {
	display: block;
	color: var(--fx-text-dim);
	font-size: 11px;
	font-weight: 500;
	margin-top: 2px;
}

/* Кастомный «чекбокс-свитч» — та же форма, что у любимых кнопок-чипов,
   чтобы не светить нативный браузерный стиль (во всех темах он
   разный). Используем hidden-input + ::before-квадрат. */
.fx-chat-notif-check {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 22px;
	height: 22px;
	cursor: pointer;
	user-select: none;
}
.fx-chat-notif-check input[type='checkbox'] {
	position: absolute;
	inset: 0;
	opacity: 0;
	margin: 0;
	cursor: pointer;
}
.fx-chat-notif-check__box {
	width: 20px;
	height: 20px;
	border: 1.5px solid var(--fx-border);
	border-radius: 6px;
	background: var(--fx-bg-elev, #fff);
	transition: background 0.15s ease, border-color 0.15s ease, transform 0.15s ease;
	display: inline-flex;
	align-items: center;
	justify-content: center;
}
.fx-chat-notif-check__box::after {
	content: '';
	width: 10px;
	height: 6px;
	border-left: 2px solid #fff;
	border-bottom: 2px solid #fff;
	transform: rotate(-45deg) translate(1px, -1px) scale(0);
	transition: transform 0.15s ease;
}
.fx-chat-notif-check input[type='checkbox']:checked + .fx-chat-notif-check__box {
	background: var(--fx-brand, #216be9);
	border-color: var(--fx-brand, #216be9);
}
.fx-chat-notif-check input[type='checkbox']:checked + .fx-chat-notif-check__box::after {
	transform: rotate(-45deg) translate(1px, -1px) scale(1);
}
.fx-chat-notif-check input[type='checkbox']:focus-visible + .fx-chat-notif-check__box {
	outline: 2px solid color-mix(in srgb, var(--fx-brand) 60%, transparent);
	outline-offset: 2px;
}
.fx-chat-notif-check input[type='checkbox']:disabled + .fx-chat-notif-check__box {
	opacity: 0.45;
	cursor: not-allowed;
}

/* Подсказка-примечание внизу попапа (напр. «TG не привязан»). */
.fx-chat-notif-popover__note {
	padding: 8px 4px 0;
	font-size: 11px;
	color: var(--fx-text-dim);
	text-align: center;
	line-height: 1.35;
}

html[scheme='dark'] .fx-chat-notif-popover {
	background: var(--fx-bg-elev, #1a1e24);
	border-color: var(--fx-border, rgba(255, 255, 255, 0.12));
}
html[scheme='dark'] .fx-chat-notif-check__box {
	background: var(--fx-surface-2, #23272e);
	border-color: var(--fx-surface-border, rgba(255, 255, 255, 0.16));
}

/* Мобилка: попап растягивается на всю ширину чата, чтобы таблица
   чекбоксов не ужималась. Привязка по правому краю (как меню языка)
   сохраняется. */
@media (max-width: 640px) {
	.fx-chat-notif-popover {
		left: 8px;
		right: 8px;
		min-width: 0;
		max-width: none;
		transform-origin: 90% 0%;
	}
}

/* ---------------------------------------------------------
   Фикс: иконка "i" (статистика) не становилась синей на hover
   в некоторых темах WooCommerce (theme.css перебивал stroke
   у button > svg). Форсим использование currentColor и
   триггерим color на самой иконке, а не только на кнопке.
   --------------------------------------------------------- */
.fx-chat-info-toggle__icon {
	color: inherit;
	stroke: currentColor;
	fill: none;
}
.fx-chat-info-toggle .fx-chat-info-toggle__icon path,
.fx-chat-info-toggle .fx-chat-info-toggle__icon circle,
.fx-chat-info-toggle .fx-chat-info-toggle__icon line {
	stroke: currentColor;
}
/* Маленькая точка "информации" — закрашенный кружок. Он нарисован
   как <circle fill="currentColor" stroke="none"> — темы иногда
   прописывают `button svg * { fill: none }`, что его убивает. */
.fx-chat-info-toggle .fx-chat-info-toggle__icon circle[stroke='none'],
.fx-chat-info-toggle .fx-chat-info-toggle__icon [fill='currentColor'] {
	fill: currentColor !important;
	stroke: none !important;
}
.fx-chat-info-toggle:hover .fx-chat-info-toggle__icon,
.fx-chat-info-toggle:focus-visible .fx-chat-info-toggle__icon {
	color: var(--fx-brand);
}
.fx-chat-info-toggle[aria-expanded='true'] .fx-chat-info-toggle__icon {
	color: #fff;
}
/* F24.2 — hover/focus у «открытой» кнопки (i): значок должен становиться
   синим, как у всех остальных круглых кнопок шапки (translate/search/tg).
   Селектор более специфичный (три класса), чем правило aria-expanded
   выше, поэтому гарантированно перебивает #fff-цвет, который задан
   активному фону-градиенту. */
.fx-chat-info-toggle[aria-expanded='true']:hover .fx-chat-info-toggle__icon,
.fx-chat-info-toggle[aria-expanded='true']:focus-visible .fx-chat-info-toggle__icon {
	color: var(--fx-brand);
}

/* То же самое преемственно применяем к search, tg и ig иконкам. */
.fx-chat-search-toggle svg,
.fx-chat-tg-btn svg,
.fx-chat-ig-btn svg {
	color: inherit;
	stroke: currentColor;
}
.fx-chat-search-toggle svg path,
.fx-chat-search-toggle svg circle,
.fx-chat-search-toggle svg line {
	stroke: currentColor;
}

/* Иконка-глобус кнопки перевода: тема WooCommerce перебивала stroke у
   button > svg, из-за чего на :hover глобус не подсвечивался синим, как
   остальные круглые кнопки шапки. Форсим currentColor и триггерим
   бренд-цвет на самой иконке (а не только на кнопке). */
.fx-chat-translate-toggle__icon {
	color: inherit;
	stroke: currentColor;
	fill: none;
}
.fx-chat-translate-toggle .fx-chat-translate-toggle__icon path,
.fx-chat-translate-toggle .fx-chat-translate-toggle__icon circle,
.fx-chat-translate-toggle .fx-chat-translate-toggle__icon line {
	stroke: currentColor;
}
.fx-chat-translate-toggle:hover:not([data-mode='on']) .fx-chat-translate-toggle__icon,
.fx-chat-translate-toggle:focus-visible:not([data-mode='on']) .fx-chat-translate-toggle__icon {
	color: var(--fx-brand);
}

/* =========================================================
   Заход Б — TG-резилиентность: админ-бейдж состояния моста.
   Показывается только админам/модераторам через JS, когда
   статус !== ok/unknown (см. startTgBridgeStatusPoll в chat.js).
   Цвет зависит от data-status: degraded=amber, down=red,
   off=серый. Пустое hidden-состояние держим через [hidden].
   ========================================================= */
.fx-tg-bridge-badge {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 48px;
	height: 48px;
	padding: 0;
	border-radius: 50%;
	border: 1px solid var(--fx-border);
	background: var(--fx-bg-elev);
	color: var(--fx-text-dim);
	cursor: pointer;
	flex: none;
	margin-left: 4px;
	box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
	-webkit-tap-highlight-color: transparent;
	touch-action: manipulation;
	font-family: inherit;
	transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease,
		transform 0.2s ease, box-shadow 0.2s ease;
}
.fx-tg-bridge-badge[hidden] { display: none !important; }
.fx-tg-bridge-badge svg { width: 22px; height: 22px; display: block; }
.fx-tg-bridge-badge[data-status='degraded'] {
	background: #fff7e6;
	color: #b45309;
	border-color: #fcd34d;
}
.fx-tg-bridge-badge[data-status='down'] {
	background: #fef2f2;
	color: #b91c1c;
	border-color: #fca5a5;
	animation: fx-tg-bridge-pulse 1.8s ease-in-out infinite;
}
.fx-tg-bridge-badge[data-status='off'] {
	background: var(--fx-bg-elev);
	color: var(--fx-text-dim);
	border-color: var(--fx-border);
}
.fx-tg-bridge-badge:hover,
.fx-tg-bridge-badge:focus-visible {
	transform: translateY(-1px);
	box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);
	outline: none;
}
@keyframes fx-tg-bridge-pulse {
	0%, 100% { box-shadow: 0 0 0 0 rgba(220, 38, 38, 0.35); }
	50%      { box-shadow: 0 0 0 6px rgba(220, 38, 38, 0); }
}
html[scheme='dark'] .fx-tg-bridge-badge {
	background: var(--fx-surface-2);
	color: var(--fx-text);
	border-color: var(--fx-surface-border);
}
html[scheme='dark'] .fx-tg-bridge-badge[data-status='degraded'] {
	background: #3b2a0a;
	color: #fbbf24;
	border-color: #a16207;
}
html[scheme='dark'] .fx-tg-bridge-badge[data-status='down'] {
	background: #3b0d0d;
	color: #fca5a5;
	border-color: #991b1b;
}

/* =============================================================
 * F25 — модалка редактирования собственного сообщения.
 * Показывается поверх всего сайта (fixed + высокий z-index),
 * бэкдроп затемняет страницу, клик по нему закрывает окно.
 * Сам box — карточка на 480px (≤ 90% ширины на мобильных),
 * с textarea и горизонтальной лентой вложений. Каждое вложение —
 * чип с превью и крестиком, при «снятии» — визуально перечёркивается
 * (реально удалится только после «Сохранить»).
 * ============================================================= */
.fx-msg-edit {
	position: fixed;
	inset: 0;
	z-index: 100000;
	background: rgba(0, 0, 0, 0.55);
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 16px;
	box-sizing: border-box;
}
.fx-msg-edit__box {
	background: var(--fx-bg-elev, #fff);
	color: var(--fx-text);
	width: min(480px, 92vw);
	max-height: 90vh;
	display: flex;
	flex-direction: column;
	border-radius: 14px;
	box-shadow: 0 20px 48px rgba(0, 0, 0, 0.35);
	overflow: hidden;
	box-sizing: border-box;
}
.fx-msg-edit__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	padding: 12px 14px;
	border-bottom: 1px solid var(--fx-border);
	background: color-mix(in srgb, var(--fx-brand) 6%, var(--fx-bg-elev));
	flex: 0 0 auto;
}
.fx-msg-edit__title {
	font-weight: 700;
	font-size: 14px;
}
.fx-msg-edit__close {
	width: 28px;
	height: 28px;
	border: 0;
	background: transparent;
	color: var(--fx-text-dim);
	font-size: 22px;
	line-height: 1;
	cursor: pointer;
	border-radius: 6px;
	padding: 0;
}
.fx-msg-edit__close:hover {
	background: color-mix(in srgb, var(--fx-brand) 12%, transparent);
	color: var(--fx-brand);
}
/* Обёртка: WYSIWYG-редактор + панель форматирования снизу (выезжает). */
.fx-msg-edit__editor-wrap {
	margin: 12px 14px 0;
	display: flex;
	flex-direction: column;
	gap: 0;
	min-width: 0;
}
.fx-msg-edit__rich {
	padding: 10px 12px;
	min-height: 90px;
	max-height: 40vh;
	overflow-y: auto;
	font: inherit;
	font-size: 14px;
	line-height: 1.45;
	color: var(--fx-text);
	background: var(--fx-bg, #fff);
	border: 1px solid var(--fx-border);
	border-radius: 10px;
	box-sizing: border-box;
	outline: none;
	white-space: pre-wrap;
	word-wrap: break-word;
	position: relative;
}
.fx-msg-edit__rich:focus {
	border-color: var(--fx-brand);
	box-shadow: 0 0 0 3px color-mix(in srgb, var(--fx-brand) 18%, transparent);
}
/* WYSIWYG: форматирование в окне правки должно выглядеть ровно так же,
   как в пузыре чата. Пользователь жаловался, что после правки сообщения
   с цитатами текст в чате «вообще не то что хотелось бы»: в редакторе
   был дефолтный браузерный blockquote (italic + margin), а в бабле —
   телеграм-стиль с вертикальной полоской. Дублируем ключевые правила
   .fx-msg__content здесь — blockquote, списки, code/pre, ссылки,
   упоминания — чтобы то, что пользователь видит в редакторе,
   совпадало с тем, что он увидит в ленте после сохранения. */
.fx-msg-edit__rich blockquote {
	margin: 4px 0;
	padding: 4px 10px;
	border-left: 3px solid var(--fx-accent, #2b7cff);
	border-radius: 4px;
	background: color-mix(in srgb, var(--fx-accent, #2b7cff) 10%, transparent);
	color: inherit;
	font-style: normal;
	quotes: none;
	line-height: 1.4;
}
.fx-msg-edit__rich blockquote::before,
.fx-msg-edit__rich blockquote::after { content: none; }
.fx-msg-edit__rich blockquote > :first-child { margin-top: 0; }
.fx-msg-edit__rich blockquote > :last-child  { margin-bottom: 0; }
.fx-msg-edit__rich blockquote + blockquote {
	margin-top: -2px;
	border-top-left-radius: 0;
	border-top-right-radius: 0;
}
html[scheme="dark"] .fx-msg-edit__rich blockquote {
	background: color-mix(in srgb, var(--fx-accent, #4a9bff) 18%, transparent);
	border-left-color: color-mix(in srgb, var(--fx-accent, #4a9bff) 75%, white);
}
.fx-msg-edit__rich ul,
.fx-msg-edit__rich ol {
	margin: 4px 0;
	padding-left: 1.5em;
}
.fx-msg-edit__rich li { margin: 2px 0; }
.fx-msg-edit__rich strong,
.fx-msg-edit__rich b { font-weight: 700; }
.fx-msg-edit__rich em,
.fx-msg-edit__rich i { font-style: italic; }
.fx-msg-edit__rich u { text-decoration: underline; text-underline-offset: 2px; }
.fx-msg-edit__rich s,
.fx-msg-edit__rich del,
.fx-msg-edit__rich strike { text-decoration: line-through; }
.fx-msg-edit__rich code {
	font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
	font-size: 12.5px;
	background: rgba(0, 0, 0, 0.06);
	padding: 0 4px;
	border-radius: 4px;
}
html[scheme="dark"] .fx-msg-edit__rich code {
	background: rgba(255, 255, 255, 0.08);
}
.fx-msg-edit__rich pre {
	background: rgba(0, 0, 0, 0.06);
	padding: 10px;
	border-radius: 8px;
	overflow-x: auto;
	margin: 8px 0;
	border: 1px solid var(--fx-border);
}
html[scheme="dark"] .fx-msg-edit__rich pre {
	background: rgba(0, 0, 0, 0.35);
}
.fx-msg-edit__rich pre code {
	background: transparent;
	padding: 0;
	border-radius: 0;
}
.fx-msg-edit__rich a {
	color: var(--fx-link) !important;
	font-weight: 600;
	text-decoration: underline;
	text-underline-offset: 2px;
	text-decoration-thickness: 1px;
}
.fx-msg-edit__rich a.fchat-mention {
	font-weight: 700;
	text-decoration: none;
}
.fx-msg-edit__rich p {
	margin: 0 0 6px 0;
}
.fx-msg-edit__rich p:last-child { margin-bottom: 0; }
.fx-msg-edit__rich.fx-msg-edit__rich--empty::before {
	content: attr(data-placeholder);
	position: absolute;
	left: 12px;
	top: 10px;
	right: 12px;
	color: var(--fx-text-dim);
	opacity: 0.75;
	pointer-events: none;
	white-space: pre-wrap;
}
/* Панель форматирования: на всю ширину блока текста, по центру кнопки,
   «выезжает» снизу при выделении (data-open). */
.fx-msg-edit__fmt-bar {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 4px;
	flex-wrap: wrap;
	width: 100%;
	padding: 0 4px;
	margin-top: 0;
	max-height: 0;
	opacity: 0;
	overflow: hidden;
	transform: translateY(6px);
	transition: max-height 0.22s ease, opacity 0.2s ease, transform 0.22s ease,
		margin-top 0.22s ease;
	pointer-events: none;
	box-sizing: border-box;
}
.fx-msg-edit__fmt-bar[data-open='1'] {
	max-height: 52px;
	opacity: 1;
	transform: translateY(0);
	margin-top: 8px;
	pointer-events: auto;
}
/* В модалке редактирования кнопки B/I/U/S выглядят ЗАМЕТНО:
   видимая «пилюля» с бордером и мягкой подложкой + чёткий hover/
   active/focus в brand-палитре. Раньше базовый `.fx-fmt-toolbar__btn`
   имел почти прозрачный hover (`--fx-brand 12%`), и на светлой теме
   пользователь просто не видел обратной связи при клике. */
.fx-msg-edit__fmt-bar .fx-fmt-toolbar__btn {
	width: 34px;
	height: 34px;
	border-radius: 50%;
	background: var(--fx-surface-1);
	border: 1px solid var(--fx-surface-border);
	color: var(--fx-text-dim);
	box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
	transition: background 0.14s ease, border-color 0.14s ease,
		color 0.14s ease, box-shadow 0.14s ease, transform 0.12s ease;
}
.fx-msg-edit__fmt-bar .fx-fmt-toolbar__btn svg {
	width: 15px;
	height: 15px;
}
/* Hover (light) — явно видимый «залитый» кружок: нейтрально-серый фон
   и тёмный текст, чтобы обратная связь отличалась от обычного состояния
   и не сливалась с панелью модалки (она сама светло-серая). */
.fx-msg-edit__fmt-bar .fx-fmt-toolbar__btn:hover,
.fx-msg-edit__fmt-bar .fx-fmt-toolbar__btn:focus-visible {
	background: color-mix(in srgb, var(--fx-text) 10%, var(--fx-bg));
	border-color: color-mix(in srgb, var(--fx-text) 22%, var(--fx-surface-border));
	color: var(--fx-text);
	box-shadow: 0 2px 6px rgba(15, 23, 42, 0.10);
	outline: none;
}
/* Pressed / is-active (light) — бренд-заливка, белая иконка: явный
   «нажатый» отклик, разный с hover. */
.fx-msg-edit__fmt-bar .fx-fmt-toolbar__btn:active,
.fx-msg-edit__fmt-bar .fx-fmt-toolbar__btn.is-active,
.fx-msg-edit__fmt-bar .fx-fmt-toolbar__btn[aria-pressed='true'] {
	background: var(--fx-brand);
	border-color: var(--fx-brand);
	color: #fff;
	box-shadow: 0 4px 10px rgba(33, 107, 233, 0.28);
}
.fx-msg-edit__fmt-bar .fx-fmt-toolbar__btn:active {
	transform: scale(0.94);
}
/* Dark theme — контрастнее, т.к. panel тёмный. */
html[scheme='dark'] .fx-msg-edit__fmt-bar .fx-fmt-toolbar__btn {
	background: var(--fx-surface-2);
	border-color: var(--fx-surface-border);
	color: var(--fx-text-dim);
}
html[scheme='dark'] .fx-msg-edit__fmt-bar .fx-fmt-toolbar__btn:hover,
html[scheme='dark'] .fx-msg-edit__fmt-bar .fx-fmt-toolbar__btn:focus-visible {
	background: rgba(255, 255, 255, 0.10);
	border-color: rgba(255, 255, 255, 0.22);
	color: #fff;
	box-shadow: 0 2px 8px rgba(0, 0, 0, 0.35);
	outline: none;
}
html[scheme='dark'] .fx-msg-edit__fmt-bar .fx-fmt-toolbar__btn:active,
html[scheme='dark'] .fx-msg-edit__fmt-bar .fx-fmt-toolbar__btn.is-active,
html[scheme='dark'] .fx-msg-edit__fmt-bar .fx-fmt-toolbar__btn[aria-pressed='true'] {
	background: var(--fx-brand);
	border-color: var(--fx-brand);
	color: #fff;
	box-shadow: 0 4px 12px rgba(33, 107, 233, 0.45);
}
.fx-msg-edit__atts {
	padding: 10px 14px 0;
	overflow-y: auto;
}
.fx-msg-edit__atts-label {
	font-size: 12px;
	color: var(--fx-text-dim);
	margin-bottom: 6px;
}
.fx-msg-edit__atts-list {
	display: flex;
	flex-direction: column;
	gap: 6px;
}
.fx-msg-edit__att {
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 6px 8px;
	background: color-mix(in srgb, var(--fx-brand) 5%, var(--fx-bg-elev));
	border: 1px solid var(--fx-border);
	border-radius: 10px;
	transition: opacity 0.15s ease, background 0.15s ease;
}
.fx-msg-edit__att.is-removed {
	opacity: 0.5;
	background: color-mix(in srgb, #c0392b 10%, var(--fx-bg-elev));
	text-decoration: line-through;
}
.fx-msg-edit__att-thumb {
	flex: 0 0 auto;
	width: 40px;
	height: 40px;
	border-radius: 8px;
	overflow: hidden;
	background: var(--fx-bg);
	display: inline-flex;
	align-items: center;
	justify-content: center;
}
.fx-msg-edit__att-thumb img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}
.fx-msg-edit__att-ico {
	font-size: 20px;
	line-height: 1;
}
.fx-msg-edit__att-name {
	flex: 1 1 auto;
	font-size: 13px;
	color: var(--fx-text);
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
.fx-msg-edit__att-rm,
.fx-msg-edit__att-replace {
	flex: 0 0 auto;
	width: 28px;
	height: 28px;
	border: 0;
	background: transparent;
	color: var(--fx-text-dim);
	font-size: 20px;
	line-height: 1;
	cursor: pointer;
	border-radius: 6px;
	padding: 0;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	transition: background 0.15s ease, color 0.15s ease;
}
.fx-msg-edit__att-rm:hover {
	background: color-mix(in srgb, #c0392b 14%, transparent);
	color: #c0392b;
}
/* Кнопка «↻ заменить» — акцент синий (brand), чтобы визуально
   отличалась от красного «×». Иконка SVG наследует цвет. */
.fx-msg-edit__att-replace:hover,
.fx-msg-edit__att-replace:focus-visible {
	background: color-mix(in srgb, var(--fx-brand) 14%, transparent);
	color: var(--fx-brand);
	outline: none;
}
.fx-msg-edit__att-replace[disabled],
.fx-msg-edit__att-rm[disabled] {
	opacity: 0.4;
	cursor: default;
}
/* Лёгкий spinner во время заливки. При is-uploading чип
   немного затемняется и replace-кнопка крутит иконку. */
.fx-msg-edit__att.is-uploading {
	opacity: 0.65;
	pointer-events: none;
}
.fx-msg-edit__att.is-uploading .fx-msg-edit__att-replace svg {
	animation: fxEditAttSpin 0.9s linear infinite;
}
@keyframes fxEditAttSpin {
	from { transform: rotate(0deg); }
	to   { transform: rotate(360deg); }
}
.fx-msg-edit__foot {
	display: flex;
	align-items: center;
	/* Кнопки «Отмена» / «Сохранить» должны стоять по противоположным
	   краям футера модалки — пользователь просил, чтобы их нельзя
	   было случайно перепутать по соседству. */
	justify-content: space-between;
	gap: 10px;
	padding: 12px 14px;
	border-top: 1px solid var(--fx-border);
	flex: 0 0 auto;
}
.fx-msg-edit__err {
	flex: 1 1 auto;
	color: #c0392b;
	font-size: 12px;
	/* Ошибка рендерится между кнопками и выравнивается по центру,
	   чтобы не «приклеиваться» к «Отмене» или «Сохранить». */
	text-align: center;
	margin: 0 12px;
}
.fx-msg-edit__cancel,
.fx-msg-edit__save {
	/* Единая база высоты/типографики с кнопками select-bar —
	   пользователь попросил привести все чат-кнопки к одному
	   размеру и ритмике анимаций. */
	box-sizing: border-box;
	height: 36px;
	padding: 0 18px;
	border-radius: 10px;
	border: 1.5px solid transparent;
	font: inherit;
	font-size: 14px;
	font-weight: 700;
	line-height: 1;
	cursor: pointer;
	background: var(--fx-bg, #fff);
	color: var(--fx-text);
	display: inline-flex;
	align-items: center;
	justify-content: center;
	white-space: nowrap;
	box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
	transition: background 0.2s ease, color 0.2s ease,
		border-color 0.2s ease, box-shadow 0.2s ease,
		transform 0.15s ease, filter 0.15s ease;
}
.fx-msg-edit__cancel:hover,
.fx-msg-edit__cancel:focus-visible,
.fx-msg-edit__save:hover,
.fx-msg-edit__save:focus-visible {
	transform: translateY(-1px);
	outline: none;
}
.fx-msg-edit__cancel:active,
.fx-msg-edit__save:active {
	transform: translateY(0) scale(0.98);
}
/* «Отмена»: базовое состояние — поверхность-эвев с тонким бордером,
   hover — выраженный brand-тинт (text-dim→brand), чтобы кнопка НЕ
   сливалась с белым фоном модалки на светлой теме и со светлым
   текстом на тёмной (раньше была плоская и при наведении только
   чуть-чуть серела — пользователь жаловался, что «белый фон
   сливается с текстом»). На тёмной теме hover — мягкий полупрозрачный
   белый поверх базового, чтобы контраст был уверенным. */
/* «Отмена»: outline в brand-палитре, как в select-bar. */
.fx-msg-edit__cancel {
	background: var(--fx-bg);
	color: var(--fx-brand, #216be9);
	border-color: color-mix(in srgb, var(--fx-brand, #216be9) 50%, var(--fx-border));
}
.fx-msg-edit__cancel:hover,
.fx-msg-edit__cancel:focus-visible {
	background: linear-gradient(135deg, var(--fx-brand, #216be9) 0%, var(--fx-brand-2, #1a5cd8) 100%);
	color: #fff;
	border-color: transparent;
	box-shadow: 0 6px 16px rgba(33, 107, 233, 0.3);
}
/* «Сохранить»: outline в зелёной палитре, hover — заливка. */
.fx-msg-edit__save {
	background: var(--fx-bg);
	color: #15803d;
	border-color: color-mix(in srgb, #16a34a 50%, var(--fx-border));
}
.fx-msg-edit__save:hover,
.fx-msg-edit__save:focus-visible {
	background: linear-gradient(135deg, #22c55e 0%, #16a34a 100%);
	color: #fff;
	border-color: transparent;
	box-shadow: 0 8px 22px rgba(22, 163, 74, 0.35);
}
.fx-msg-edit__save:disabled,
.fx-msg-edit__cancel:disabled {
	opacity: 0.6;
	cursor: not-allowed;
}

html[scheme='dark'] .fx-msg-edit__box {
	background: var(--fx-bg-elev, #1a1e24);
}
html[scheme='dark'] .fx-msg-edit__rich {
	background: var(--fx-surface-2, #22272f);
	color: var(--fx-text);
}
html[scheme='dark'] .fx-msg-edit__cancel {
	background: var(--fx-surface-1);
	color: #b8d2ff;
	border-color: rgba(33, 107, 233, 0.45);
}
html[scheme='dark'] .fx-msg-edit__cancel:hover,
html[scheme='dark'] .fx-msg-edit__cancel:focus-visible {
	background: linear-gradient(135deg, var(--fx-brand, #216be9) 0%, var(--fx-brand-2, #1a5cd8) 100%);
	color: #fff;
	border-color: transparent;
}
html[scheme='dark'] .fx-msg-edit__save {
	background: var(--fx-surface-1);
	color: #86efac;
	border-color: rgba(34, 197, 94, 0.5);
}
html[scheme='dark'] .fx-msg-edit__save:hover,
html[scheme='dark'] .fx-msg-edit__save:focus-visible {
	background: linear-gradient(135deg, #22c55e 0%, #16a34a 100%);
	color: #fff;
	border-color: transparent;
}

/* ============================================================
 *  Панель форматирования композера (#fx-chat-fmt-bar)
 *  Стиль повторяет .fx-chat-emoji (тот же bg/border/radius/shadow).
 *  Хвостик-указатель намеренно НЕ рисуем — пользователь попросил
 *  убрать «тот самый хвост» и оставить ровную плашку.
 *  Ширина = fit-content (4 кнопки B/I/U/S не растягивают окно).
 * ============================================================ */
.fx-chat-fmt-bar {
	position: absolute;
	left: 14px;
	bottom: calc(100% + 10px);
	width: auto;
	max-width: calc(100% - 28px);
	z-index: 21;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex-wrap: nowrap;
	gap: 4px;
	padding: 6px 8px;
	background: var(--fx-bg-elev);
	color: var(--fx-text);
	border: 1px solid var(--fx-border);
	border-radius: 14px;
	box-shadow: 0 18px 48px rgba(0, 0, 0, 0.22);
	box-sizing: border-box;
	animation: fx-emoji-pop 0.18s ease-out;
}
html[scheme='dark'] .fx-chat-fmt-bar {
	background: rgba(30, 34, 41, 0.98);
	border-color: rgba(255, 255, 255, 0.1);
	box-shadow: 0 18px 48px rgba(0, 0, 0, 0.45);
}
.fx-fmt-toolbar__btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 30px;
	height: 30px;
	padding: 0;
	background: transparent;
	color: var(--fx-text-dim);
	border: none;
	border-radius: 6px;
	cursor: pointer;
	font: inherit;
	font-size: 14px;
	line-height: 1;
	transition: background 0.12s ease, color 0.12s ease;
}
.fx-fmt-toolbar__btn:hover,
.fx-fmt-toolbar__btn:focus-visible {
	background: color-mix(in srgb, var(--fx-brand) 12%, var(--fx-bg));
	color: var(--fx-brand);
	outline: none;
}
.fx-fmt-toolbar__btn svg {
	width: 16px;
	height: 16px;
}
html[scheme='dark'] .fx-fmt-toolbar__btn:hover,
html[scheme='dark'] .fx-fmt-toolbar__btn:focus-visible {
	background: rgba(255, 255, 255, 0.08);
	color: #fff;
}

/* Legacy «overlay»-раскладка fmt-bar на мобильных (абсолютная панель
   поверх правого края поля ввода, появлявшаяся по is-fmt-open) удалена
   по просьбе пользователя: теперь fmt-bar — статичный 2×2 grid в
   ЛЕВОЙ колонке композера (см. @media (max-width: 600px) выше, там
   задаются top/left и размеры). Никаких overlay/hide/show по выделению
   больше нет — панель всегда видна, композер фикс-высоты, feed не
   дёргается. */

/* =======================================================================
 *  Унификация «нажатого/открытого» состояния toggle-кнопок в шапке чата.
 *  По запросу пользователя все кнопки (notif / info / translate / search)
 *  должны выглядеть одинаково в нажатом состоянии — раньше часть из них
 *  перекрашивалась в сплошной синий градиент (фирменный бренд), а у
 *  info появился «мягкий» hover-override — итогом был разнобой.
 *  Делаем общий «soft-pressed» стиль: светлый бренд-тинт, бренд-иконка,
 *  бренд-окантовка. Работает и на light, и на dark теме, и на мобильных.
 *  Ставим правила в конце файла, чтобы гарантированно перекрыть более
 *  ранние блоки с одинаковой специфичностью. Используем префикс
 *  .fenix-chat-wrap для +1 класса к специфичности — этого достаточно,
 *  чтобы победить базовые и медиа-правила выше. ======================== */
.fenix-chat-wrap .fx-chat-notif-toggle[aria-expanded='true'],
.fenix-chat-wrap .fx-chat-info-toggle[aria-expanded='true'],
.fenix-chat-wrap .fx-chat-search-toggle[aria-expanded='true'] {
	background: color-mix(in srgb, var(--fx-brand) 12%, var(--fx-bg));
	background-image: none;
	color: var(--fx-brand);
	border-color: color-mix(in srgb, var(--fx-brand) 35%, var(--fx-border));
	box-shadow: 0 2px 8px rgba(33, 107, 233, 0.18);
}
.fenix-chat-wrap .fx-chat-notif-toggle[aria-expanded='true']:hover,
.fenix-chat-wrap .fx-chat-notif-toggle[aria-expanded='true']:focus-visible,
.fenix-chat-wrap .fx-chat-info-toggle[aria-expanded='true']:hover,
.fenix-chat-wrap .fx-chat-info-toggle[aria-expanded='true']:focus-visible,
.fenix-chat-wrap .fx-chat-search-toggle[aria-expanded='true']:hover,
.fenix-chat-wrap .fx-chat-search-toggle[aria-expanded='true']:focus-visible {
	background: color-mix(in srgb, var(--fx-brand) 16%, var(--fx-bg));
	background-image: none;
	color: var(--fx-brand);
	border-color: color-mix(in srgb, var(--fx-brand) 45%, var(--fx-border));
	transform: translateY(-1px);
	box-shadow: 0 2px 10px rgba(33, 107, 233, 0.22);
	filter: none;
	outline: none;
}
/* Иконки «открытых» кнопок — тоже цвет бренда, а не белый: перекрываем
   старые `color:#fff; stroke:#fff;` блоки (они у info/notif стояли на
   потомках __icon/__icon *). */
.fenix-chat-wrap .fx-chat-notif-toggle[aria-expanded='true'] .fx-chat-notif-toggle__icon,
.fenix-chat-wrap .fx-chat-notif-toggle[aria-expanded='true'] .fx-chat-notif-toggle__icon *,
.fenix-chat-wrap .fx-chat-info-toggle[aria-expanded='true'] .fx-chat-info-toggle__icon,
.fenix-chat-wrap .fx-chat-info-toggle[aria-expanded='true'] .fx-chat-info-toggle__icon *,
.fenix-chat-wrap .fx-chat-search-toggle[aria-expanded='true'] svg,
.fenix-chat-wrap .fx-chat-search-toggle[aria-expanded='true'] svg * {
	color: var(--fx-brand);
	stroke: var(--fx-brand);
	fill: none;
}
/* Dark-тема: те же «soft-pressed» состояния, но на чуть более ярком
   тинте (светится на тёмном фоне), и текст/иконка — светло-синяя.
   Обязательно дублируем здесь, чтобы перекрыть старые html[scheme='dark']
   блоки с `color:#fff`. */
html[scheme='dark'] .fenix-chat-wrap .fx-chat-notif-toggle[aria-expanded='true'],
html[scheme='dark'] .fenix-chat-wrap .fx-chat-info-toggle[aria-expanded='true'],
html[scheme='dark'] .fenix-chat-wrap .fx-chat-search-toggle[aria-expanded='true'] {
	background: var(--fx-brand-tint-weak);
	background-image: none;
	color: #b8d2ff;
	border-color: rgba(33, 107, 233, 0.5);
	box-shadow: 0 2px 10px rgba(33, 107, 233, 0.2);
}
html[scheme='dark'] .fenix-chat-wrap .fx-chat-notif-toggle[aria-expanded='true']:hover,
html[scheme='dark'] .fenix-chat-wrap .fx-chat-notif-toggle[aria-expanded='true']:focus-visible,
html[scheme='dark'] .fenix-chat-wrap .fx-chat-info-toggle[aria-expanded='true']:hover,
html[scheme='dark'] .fenix-chat-wrap .fx-chat-info-toggle[aria-expanded='true']:focus-visible,
html[scheme='dark'] .fenix-chat-wrap .fx-chat-search-toggle[aria-expanded='true']:hover,
html[scheme='dark'] .fenix-chat-wrap .fx-chat-search-toggle[aria-expanded='true']:focus-visible {
	background: var(--fx-brand-tint-strong, rgba(33, 107, 233, 0.32));
	color: #cfe0ff;
	border-color: rgba(33, 107, 233, 0.7);
	filter: none;
}
html[scheme='dark'] .fenix-chat-wrap .fx-chat-notif-toggle[aria-expanded='true'] .fx-chat-notif-toggle__icon,
html[scheme='dark'] .fenix-chat-wrap .fx-chat-notif-toggle[aria-expanded='true'] .fx-chat-notif-toggle__icon *,
html[scheme='dark'] .fenix-chat-wrap .fx-chat-info-toggle[aria-expanded='true'] .fx-chat-info-toggle__icon,
html[scheme='dark'] .fenix-chat-wrap .fx-chat-info-toggle[aria-expanded='true'] .fx-chat-info-toggle__icon *,
html[scheme='dark'] .fenix-chat-wrap .fx-chat-search-toggle[aria-expanded='true'] svg,
html[scheme='dark'] .fenix-chat-wrap .fx-chat-search-toggle[aria-expanded='true'] svg * {
	color: #b8d2ff;
	stroke: #b8d2ff;
	fill: none;
}

/* F28 — .fx-msg__body containing-block для абсолютных детей
   (кнопка копирования в select-mode и т. п. при необходимости). */
.fx-msg__body { position: relative; }

/* =======================================================================
 *  Selection toolbar — всплывает над/под выделением текста внутри
 *  сообщения. Копировать / Перевести / Ответить на выделение.
 * ======================================================================= */
.fx-sel-toolbar {
	position: fixed;
	z-index: 99998;
	display: flex;
	flex-direction: column;
	min-width: min(180px, calc(100vw - 24px));
	max-width: min(240px, calc(100vw - 24px));
	padding: 6px;
	background: var(--fx-bg, #fff);
	color: var(--fx-text, #14171d);
	border: 1px solid var(--fx-border, rgba(0, 0, 0, 0.12));
	border-radius: 12px;
	box-shadow: 0 14px 40px rgba(0, 0, 0, 0.18), 0 2px 6px rgba(0, 0, 0, 0.08);
	font: 14px/1.3 system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
	user-select: none;
	-webkit-user-select: none;
	animation: fxSelToolbarIn 0.12s ease-out;
}
@keyframes fxSelToolbarIn {
	from { opacity: 0; transform: translateY(4px); }
	to   { opacity: 1; transform: translateY(0); }
}
html[scheme='dark'] .fx-sel-toolbar {
	background: #1f232b;
	color: #e6ecf5;
	border-color: rgba(255, 255, 255, 0.12);
	box-shadow: 0 14px 40px rgba(0, 0, 0, 0.6), 0 2px 6px rgba(0, 0, 0, 0.3);
}
/* Пункт меню выделения: иконка слева + подпись справа, выровнено по
   левому краю — повторяет визуал `.fx-input-ctx__item` в сочетании с
   `.fx-msg__tools-row--actions button`. Единый стиль всех всплывающих
   меню действий в чате. */
.fx-sel-toolbar__item {
	display: flex;
	align-items: center;
	gap: 10px;
	width: 100%;
	padding: 7px 12px;
	background: transparent;
	color: inherit;
	border: 0;
	border-radius: 8px;
	cursor: pointer;
	font: inherit;
	text-align: left;
	transition: background-color .12s ease, color .12s ease;
}
.fx-sel-toolbar__item:hover,
.fx-sel-toolbar__item:focus-visible {
	background: color-mix(in srgb, var(--fx-brand, #216be9) 12%, transparent);
	color: var(--fx-brand, #216be9);
	outline: none;
}
.fx-sel-toolbar__ico {
	flex: 0 0 auto;
	width: 18px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	font-size: 15px;
	line-height: 1;
}
.fx-sel-toolbar__lbl {
	flex: 1 1 auto;
	font-weight: 500;
}
/* Старые стили `.fx-sel-toolbar__btn` оставляем как есть, если где-то
   их ещё используют (обратная совместимость), но новый build создаёт
   пункты .fx-sel-toolbar__item. */
.fx-sel-toolbar__btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 34px;
	height: 34px;
	padding: 0;
	background: transparent;
	color: inherit;
	border: 0;
	border-radius: 50%;
	cursor: pointer;
	font-size: 16px;
	line-height: 1;
}
.fx-sel-toolbar__btn:hover,
.fx-sel-toolbar__btn:focus-visible {
	background: color-mix(in srgb, var(--fx-brand, #216be9) 14%, transparent);
	color: var(--fx-brand, #216be9);
	outline: none;
}

/* =======================================================================
 *  Кастомное контекстное меню для #fx-chat-input (десктоп, ПКМ).
 *  Показывает ряд B/I/U/S + список cut/copy/paste/delete. Монтируется
 *  в <body>, position:fixed. Стили сделаны нейтральными — чтобы тема
 *  сайта не ломала вид (жёстко задаём фон, рамку, тени, радиусы).
 * ======================================================================= */
.fx-input-ctx {
	position: fixed;
	z-index: 99999;
	min-width: 200px;
	padding: 6px;
	background: var(--fx-bg, #fff);
	color: var(--fx-text, #14171d);
	border: 1px solid var(--fx-border, rgba(0, 0, 0, 0.12));
	border-radius: 12px;
	box-shadow: 0 14px 40px rgba(0, 0, 0, 0.18), 0 2px 6px rgba(0, 0, 0, 0.08);
	font: 14px/1.3 system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
	user-select: none;
	-webkit-user-select: none;
}
html[scheme='dark'] .fx-input-ctx {
	background: #1f232b;
	color: #e6ecf5;
	border-color: rgba(255, 255, 255, 0.12);
	box-shadow: 0 14px 40px rgba(0, 0, 0, 0.6), 0 2px 6px rgba(0, 0, 0, 0.3);
}
.fx-input-ctx__row--fmt {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 4px;
	padding: 2px 4px 4px;
}
.fx-input-ctx__fmt {
	flex: 0 0 auto;
	width: 32px;
	height: 32px;
	padding: 0;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	background: transparent;
	color: inherit;
	border: 0;
	border-radius: 50%;
	cursor: pointer;
	transition: background-color .12s ease, color .12s ease;
}
.fx-input-ctx__fmt svg {
	width: 16px;
	height: 16px;
}
.fx-input-ctx__fmt:hover:not([disabled]),
.fx-input-ctx__fmt:focus-visible:not([disabled]) {
	background: color-mix(in srgb, var(--fx-brand, #216be9) 14%, transparent);
	color: var(--fx-brand, #216be9);
	outline: none;
}
.fx-input-ctx__fmt[disabled] {
	opacity: .4;
	cursor: default;
}
.fx-input-ctx__sep {
	height: 1px;
	margin: 4px 2px;
	background: var(--fx-border, rgba(0, 0, 0, 0.1));
}
html[scheme='dark'] .fx-input-ctx__sep {
	background: rgba(255, 255, 255, 0.1);
}
.fx-input-ctx__item {
	display: block;
	width: 100%;
	text-align: left;
	padding: 7px 12px;
	background: transparent;
	color: inherit;
	border: 0;
	border-radius: 8px;
	cursor: pointer;
	font: inherit;
	transition: background-color .12s ease, color .12s ease;
}
.fx-input-ctx__item:hover:not([disabled]),
.fx-input-ctx__item:focus-visible:not([disabled]) {
	background: color-mix(in srgb, var(--fx-brand, #216be9) 12%, transparent);
	color: var(--fx-brand, #216be9);
	outline: none;
}
.fx-input-ctx__item[disabled] {
	opacity: .4;
	cursor: default;
}

/* =======================================================================
 *  Автономный перевод чата — кнопка-«глобус» + popover выбора языка.
 *  Кнопка стоит в ряду .fx-chat-actions рядом с поиском/инфо (48×48,
 *  круглая, brand-тинт на hover; при активном переводе залита брендом
 *  с бейджем кода языка). Popover — прокручиваемый список языков.
 * ======================================================================= */
.fx-chat-translate {
	position: relative;
	display: inline-flex;
	flex: none;
}
.fx-chat-translate-toggle {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 48px;
	height: 48px;
	padding: 0;
	background: var(--fx-bg-elev);
	color: var(--fx-text-dim);
	border: 1px solid var(--fx-border);
	border-radius: 50%;
	cursor: pointer;
	flex: none;
	box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
	-webkit-tap-highlight-color: transparent;
	touch-action: manipulation;
	font-family: inherit;
	transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease,
		transform 0.2s ease, box-shadow 0.2s ease;
}
.fx-chat-translate-toggle__icon {
	width: 22px;
	height: 22px;
	display: block;
}
.fx-chat-translate-toggle:hover:not([data-mode='on']),
.fx-chat-translate-toggle:focus-visible:not([data-mode='on']) {
	background: color-mix(in srgb, var(--fx-brand) 10%, var(--fx-bg));
	color: var(--fx-brand);
	border-color: color-mix(in srgb, var(--fx-brand) 30%, var(--fx-border));
	transform: translateY(-1px);
	box-shadow: 0 2px 6px rgba(0, 0, 0, 0.06);
	outline: none;
}
.fx-chat-translate-toggle:active {
	transform: scale(0.96);
}
/* Активный режим — кнопка залита брендом. */
.fx-chat-translate-toggle[data-mode='on'] {
	background: linear-gradient(135deg, var(--fx-brand, #216be9) 0%, var(--fx-brand-2, #1a5cd8) 100%);
	color: #fff;
	border-color: transparent;
	box-shadow: 0 4px 12px rgba(33, 107, 233, 0.35);
}
.fx-chat-translate-toggle[data-mode='on']:hover,
.fx-chat-translate-toggle[data-mode='on']:focus-visible {
	filter: brightness(1.05);
	transform: translateY(-1px);
	outline: none;
}
.fx-chat-translate-toggle[data-mode='on'] .fx-chat-translate-toggle__icon,
.fx-chat-translate-toggle[data-mode='on'] .fx-chat-translate-toggle__icon * {
	color: #fff;
	stroke: #fff;
}
/* Бейдж кода активного языка в правом нижнем углу глобуса. */
.fx-chat-translate-toggle__badge {
	position: absolute;
	right: -2px;
	bottom: -2px;
	min-width: 20px;
	height: 16px;
	padding: 0 4px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	font-size: 10px;
	font-weight: 800;
	letter-spacing: 0.04em;
	line-height: 1;
	color: #fff;
	background: var(--fx-brand, #216be9);
	border: 2px solid var(--fx-panel-bg, #fff);
	border-radius: 999px;
	pointer-events: none;
	opacity: 0;
	transform: scale(0.7);
	transition: opacity 0.18s ease, transform 0.18s ease;
}
.fx-chat-translate-toggle[data-mode='on'] .fx-chat-translate-toggle__badge {
	opacity: 1;
	transform: scale(1);
}
html[scheme='dark'] .fx-chat-translate-toggle {
	background: var(--fx-surface-2);
	color: var(--fx-text);
	border-color: var(--fx-surface-border);
}
html[scheme='dark'] .fx-chat-translate-toggle:hover:not([data-mode='on']),
html[scheme='dark'] .fx-chat-translate-toggle:focus-visible:not([data-mode='on']) {
	background: var(--fx-brand-tint-weak);
	color: #b8d2ff;
	border-color: rgba(33, 107, 233, 0.5);
}
html[scheme='dark'] .fx-chat-translate-toggle__badge {
	border-color: rgba(26, 30, 36, 0.95);
}

/* Popover выбора языка — абсолютно позиционирован в правом верхнем
   углу .fenix-chat-wrap (привязка к --fx-panel-top, как info-popover). */
.fx-chat-translate-popover {
	position: absolute;
	top: calc(var(--fx-panel-top, 0px) + 10px);
	right: 14px;
	z-index: 60;
	min-width: 220px;
	max-width: min(300px, calc(100% - 28px));
	padding: 8px;
	display: flex;
	flex-direction: column;
	gap: 2px;
	background: var(--fx-bg-elev, #fff);
	border: 1px solid var(--fx-border);
	border-radius: 14px;
	box-shadow: 0 18px 48px rgba(0, 0, 0, 0.22);
	color: var(--fx-text);
	font-size: 13px;
	box-sizing: border-box;
	opacity: 0;
	transform: translateY(-6px) scale(0.96);
	transform-origin: 90% 0%;
	transition: opacity 0.16s ease, transform 0.16s ease;
	pointer-events: none;
}
.fx-chat-translate-popover[data-open='1'] {
	opacity: 1;
	transform: translateY(0) scale(1);
	pointer-events: auto;
	animation: fx-emoji-pop 0.18s ease-out;
}
.fx-chat-translate-popover[hidden] {
	display: none !important;
}
/* Прокручиваемый список языков (заголовок «оригинал» остаётся сверху). */
.fx-chat-translate-popover__list {
	display: flex;
	flex-direction: column;
	gap: 2px;
	max-height: min(46vh, 360px);
	overflow-y: auto;
	overscroll-behavior: contain;
	-webkit-overflow-scrolling: touch;
}
.fx-chat-translate-opt {
	display: inline-flex;
	align-items: center;
	gap: 10px;
	width: 100%;
	padding: 8px 10px;
	background: transparent;
	border: 0;
	border-radius: 10px;
	font: inherit;
	color: var(--fx-text);
	text-align: left;
	cursor: pointer;
	-webkit-tap-highlight-color: transparent;
	transition: background 0.15s ease;
}
.fx-chat-translate-opt:hover,
.fx-chat-translate-opt:focus-visible {
	background: color-mix(in srgb, var(--fx-brand) 14%, transparent);
	outline: none;
}
.fx-chat-translate-opt[aria-checked='true'] {
	background: color-mix(in srgb, var(--fx-brand) 20%, transparent);
	color: var(--fx-brand);
}
/* Строка «Показать оригинал» — отделяем линией снизу. */
.fx-chat-translate-opt--off {
	color: var(--fx-text-dim);
	border-bottom: 1px solid var(--fx-border);
	border-radius: 10px 10px 0 0;
	margin-bottom: 2px;
}
.fx-chat-translate-opt--off[hidden] { display: none; }
.fx-chat-translate-opt--off .fx-chat-translate-opt__code {
	background: color-mix(in srgb, var(--fx-text-dim) 18%, transparent);
	color: var(--fx-text-dim);
}
.fx-chat-translate-opt__code {
	flex: none;
	font-size: 10px;
	padding: 2px 7px;
	border-radius: 999px;
	background: color-mix(in srgb, var(--fx-brand) 20%, transparent);
	color: var(--fx-brand);
	font-weight: 800;
	text-transform: uppercase;
	letter-spacing: 0.04em;
	text-align: center;
	min-width: 32px;
}
.fx-chat-translate-opt[aria-checked='true'] .fx-chat-translate-opt__code {
	background: var(--fx-brand);
	color: #fff;
}
.fx-chat-translate-opt__name {
	flex: 1 1 auto;
	font-size: 14px;
	font-weight: 600;
	overflow: hidden;
	white-space: nowrap;
	text-overflow: ellipsis;
}
html[scheme='dark'] .fx-chat-translate-popover {
	background: var(--fx-bg-elev, #1a1e24);
	border-color: var(--fx-border, rgba(255, 255, 255, 0.12));
}
html[scheme='dark'] .fx-chat-translate-opt:hover,
html[scheme='dark'] .fx-chat-translate-opt:focus-visible {
	background: color-mix(in srgb, var(--fx-brand) 22%, transparent);
}
html[scheme='dark'] .fx-chat-translate-opt[aria-checked='true'] {
	background: color-mix(in srgb, var(--fx-brand) 30%, transparent);
	color: #fff;
}
html[scheme='dark'] .fx-chat-translate-opt[aria-checked='true'] .fx-chat-translate-opt__name {
	color: #fff;
}
/* Мобильные: глобус того же размера, что остальные круглые кнопки. */
@media (max-width: 600px) {
	.fx-chat-translate-toggle {
		width: 40px;
		height: 40px;
	}
	.fx-chat-translate-toggle__icon {
		width: 20px;
		height: 20px;
	}
	.fx-chat-translate-toggle__badge {
		min-width: 18px;
		height: 14px;
		font-size: 9px;
	}
}

/* ======================================================================
 * Унификация всех кнопок-иконок шапки чата на мобильных.
 * ----------------------------------------------------------------------
 * Пользователь: на мобильных все значки (Telegram, онлайн-счётчик,
 * уведомления, инфо, перевод, поиск) должны быть ОДНОГО размера и
 * одинаково подсвечиваться бренд-синим на hover/нажатие — как кнопка
 * языка (планетка) в шапке сайта. Раньше глобус перевода менял размер
 * только на <600px (в диапазоне 601–768px был крупнее остальных), а
 * hover у части кнопок «подпрыгивал» (translateY), у части — нет.
 * Этот блок (в самом конце файла → выигрывает каскад) приводит всё к
 * единому виду и анимации. «Включённые» состояния (открытый popover /
 * включённый перевод) намеренно не трогаем — они остаются залитыми.
 * -------------------------------------------------------------------- */
@media (max-width: 768px) {
	.fenix-chat-wrap .fx-chat-tg-btn,
	.fenix-chat-wrap .fx-chat-presence-count,
	.fenix-chat-wrap .fx-chat-notif-toggle,
	.fenix-chat-wrap .fx-chat-info-toggle,
	.fenix-chat-wrap .fx-chat-translate-toggle,
	.fenix-chat-wrap .fx-chat-search-toggle {
		width: 40px !important;
		height: 40px !important;
		min-width: 40px !important;
		min-height: 40px !important;
		border-radius: 50% !important;
		transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease,
			transform 0.15s ease, box-shadow 0.2s ease !important;
	}
	.fenix-chat-wrap .fx-chat-tg-btn svg,
	.fenix-chat-wrap .fx-chat-search-toggle svg,
	.fenix-chat-wrap .fx-chat-info-toggle__icon,
	.fenix-chat-wrap .fx-chat-notif-toggle__icon,
	.fenix-chat-wrap .fx-chat-translate-toggle__icon {
		width: 20px !important;
		height: 20px !important;
	}

	/* Единый бренд-акцент. Включаем :focus и :active (не только :hover/
	   :focus-visible): на тач-устройствах кнопка должна синеть СРАЗУ по
	   тапу (как кнопка языка), а не «со второго раза». */
	.fenix-chat-wrap .fx-chat-tg-btn:hover,
	.fenix-chat-wrap .fx-chat-tg-btn:focus,
	.fenix-chat-wrap .fx-chat-tg-btn:active,
	.fenix-chat-wrap .fx-chat-presence-count:hover,
	.fenix-chat-wrap .fx-chat-presence-count:focus,
	.fenix-chat-wrap .fx-chat-presence-count:active,
	.fenix-chat-wrap .fx-chat-notif-toggle:not([aria-expanded='true']):hover,
	.fenix-chat-wrap .fx-chat-notif-toggle:not([aria-expanded='true']):focus,
	.fenix-chat-wrap .fx-chat-notif-toggle:not([aria-expanded='true']):active,
	.fenix-chat-wrap .fx-chat-info-toggle:not([aria-expanded='true']):hover,
	.fenix-chat-wrap .fx-chat-info-toggle:not([aria-expanded='true']):focus,
	.fenix-chat-wrap .fx-chat-info-toggle:not([aria-expanded='true']):active,
	.fenix-chat-wrap .fx-chat-translate-toggle:not([data-mode='on']):hover,
	.fenix-chat-wrap .fx-chat-translate-toggle:not([data-mode='on']):focus,
	.fenix-chat-wrap .fx-chat-translate-toggle:not([data-mode='on']):active,
	.fenix-chat-wrap .fx-chat-search-toggle:not([aria-expanded='true']):hover,
	.fenix-chat-wrap .fx-chat-search-toggle:not([aria-expanded='true']):focus,
	.fenix-chat-wrap .fx-chat-search-toggle:not([aria-expanded='true']):active {
		color: var(--fx-brand) !important;
		background: color-mix(in srgb, var(--fx-brand) 12%, var(--fx-bg)) !important;
		border-color: color-mix(in srgb, var(--fx-brand) 34%, var(--fx-border)) !important;
		box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05) !important;
	}
	html[scheme='dark'] .fenix-chat-wrap .fx-chat-tg-btn:hover,
	html[scheme='dark'] .fenix-chat-wrap .fx-chat-tg-btn:focus,
	html[scheme='dark'] .fenix-chat-wrap .fx-chat-tg-btn:active,
	html[scheme='dark'] .fenix-chat-wrap .fx-chat-presence-count:hover,
	html[scheme='dark'] .fenix-chat-wrap .fx-chat-presence-count:focus,
	html[scheme='dark'] .fenix-chat-wrap .fx-chat-presence-count:active,
	html[scheme='dark'] .fenix-chat-wrap .fx-chat-notif-toggle:not([aria-expanded='true']):hover,
	html[scheme='dark'] .fenix-chat-wrap .fx-chat-notif-toggle:not([aria-expanded='true']):focus,
	html[scheme='dark'] .fenix-chat-wrap .fx-chat-notif-toggle:not([aria-expanded='true']):active,
	html[scheme='dark'] .fenix-chat-wrap .fx-chat-info-toggle:not([aria-expanded='true']):hover,
	html[scheme='dark'] .fenix-chat-wrap .fx-chat-info-toggle:not([aria-expanded='true']):focus,
	html[scheme='dark'] .fenix-chat-wrap .fx-chat-info-toggle:not([aria-expanded='true']):active,
	html[scheme='dark'] .fenix-chat-wrap .fx-chat-translate-toggle:not([data-mode='on']):hover,
	html[scheme='dark'] .fenix-chat-wrap .fx-chat-translate-toggle:not([data-mode='on']):focus,
	html[scheme='dark'] .fenix-chat-wrap .fx-chat-translate-toggle:not([data-mode='on']):active,
	html[scheme='dark'] .fenix-chat-wrap .fx-chat-search-toggle:not([aria-expanded='true']):hover,
	html[scheme='dark'] .fenix-chat-wrap .fx-chat-search-toggle:not([aria-expanded='true']):focus,
	html[scheme='dark'] .fenix-chat-wrap .fx-chat-search-toggle:not([aria-expanded='true']):active {
		background: color-mix(in srgb, var(--fx-brand) 18%, var(--fx-surface-1)) !important;
		border-color: color-mix(in srgb, var(--fx-brand) 45%, var(--fx-surface-border)) !important;
	}

	/* Нажатие — одинаковый лёгкий «press» у всех. */
	.fenix-chat-wrap .fx-chat-tg-btn:active,
	.fenix-chat-wrap .fx-chat-presence-count:active,
	.fenix-chat-wrap .fx-chat-notif-toggle:active,
	.fenix-chat-wrap .fx-chat-info-toggle:active,
	.fenix-chat-wrap .fx-chat-translate-toggle:active,
	.fenix-chat-wrap .fx-chat-search-toggle:active {
		transform: scale(0.94) !important;
	}

	/* Сам ЗНАЧОК внутри тоже синеет (как планетка-язык), а не только фон.
	   Раньше у Telegram и лупы значок оставался серым на фокусе/нажатии,
	   а у info/notif/translate синел — отсюда разнобой. Бьём прямо по
	   svg/иконке (stroke и fill через currentColor), чтобы все 6 кнопок
	   подсвечивались единообразно сразу по тапу. */
	.fenix-chat-wrap .fx-chat-tg-btn:hover svg,
	.fenix-chat-wrap .fx-chat-tg-btn:focus svg,
	.fenix-chat-wrap .fx-chat-tg-btn:active svg,
	.fenix-chat-wrap .fx-chat-presence-count:hover .fx-chat-presence-count__num,
	.fenix-chat-wrap .fx-chat-presence-count:focus .fx-chat-presence-count__num,
	.fenix-chat-wrap .fx-chat-presence-count:active .fx-chat-presence-count__num,
	.fenix-chat-wrap .fx-chat-notif-toggle:not([aria-expanded='true']):hover .fx-chat-notif-toggle__icon,
	.fenix-chat-wrap .fx-chat-notif-toggle:not([aria-expanded='true']):focus .fx-chat-notif-toggle__icon,
	.fenix-chat-wrap .fx-chat-notif-toggle:not([aria-expanded='true']):active .fx-chat-notif-toggle__icon,
	.fenix-chat-wrap .fx-chat-info-toggle:not([aria-expanded='true']):hover .fx-chat-info-toggle__icon,
	.fenix-chat-wrap .fx-chat-info-toggle:not([aria-expanded='true']):focus .fx-chat-info-toggle__icon,
	.fenix-chat-wrap .fx-chat-info-toggle:not([aria-expanded='true']):active .fx-chat-info-toggle__icon,
	.fenix-chat-wrap .fx-chat-translate-toggle:not([data-mode='on']):hover .fx-chat-translate-toggle__icon,
	.fenix-chat-wrap .fx-chat-translate-toggle:not([data-mode='on']):focus .fx-chat-translate-toggle__icon,
	.fenix-chat-wrap .fx-chat-translate-toggle:not([data-mode='on']):active .fx-chat-translate-toggle__icon,
	.fenix-chat-wrap .fx-chat-search-toggle:not([aria-expanded='true']):hover svg,
	.fenix-chat-wrap .fx-chat-search-toggle:not([aria-expanded='true']):focus svg,
	.fenix-chat-wrap .fx-chat-search-toggle:not([aria-expanded='true']):active svg {
		color: var(--fx-brand) !important;
		stroke: var(--fx-brand) !important;
	}
	/* Telegram — заливной значок: при 20px он «забивает» кружок плотнее
	   контурных иконок, отчего кнопка кажется крупнее соседних. Слегка
	   уменьшаем до визуального паритета с контурными значками. */
	.fenix-chat-wrap .fx-chat-tg-btn svg {
		width: 18px !important;
		height: 18px !important;
	}
}


/* === Вложения (v0.9.112): без стрелки/крестика — авто-докачка при листании + сохранение по тапу === */
.fx-att--lazy { cursor: pointer; }
.fx-att--lazy .fx-att__doc-thumb { cursor: pointer; }
.fx-att__dl-prog {
	display: block;
	font-size: 11px;
	line-height: 1.3;
	color: color-mix(in srgb, var(--fx-text) 55%, transparent);
	margin-top: 2px;
	font-variant-numeric: tabular-nums;
}
.fx-att__dl-prog:empty { display: none; }
/* Спиннер загрузки поверх иконки — виден только во время докачки/сохранения */
.fx-att__spin {
	position: absolute;
	top: 50%; left: 50%;
	width: 26px; height: 26px;
	margin: -13px 0 0 -13px;
	border-radius: 50%;
	border: 2px solid rgba(255, 255, 255, .28);
	border-top-color: #fff;
	display: none;
	pointer-events: none;
	z-index: 3;
}
.fx-att--loading .fx-att__doc-thumb::after {
	content: '';
	position: absolute; inset: 0;
	background: rgba(20, 24, 33, .42);
	border-radius: 10px;
	pointer-events: none;
	z-index: 2;
}
.fx-att--loading .fx-att__spin {
	display: block;
	animation: fxDlSpin .8s linear infinite;
}
@keyframes fxDlSpin { to { transform: rotate(360deg); } }

/* Маленькая стрелка «скачать» на иконке документа (Telegram-style).
   Видна, пока файл не качается (.fx-att--loading) и не закэширован
   (.fx-att--cached). */
.fx-att__dl-arrow {
	position: absolute;
	right: 0;
	bottom: 2px;
	width: 18px;
	height: 18px;
	border-radius: 50%;
	background: var(--fx-brand);
	color: #fff;
	display: flex;
	align-items: center;
	justify-content: center;
	box-shadow: 0 0 0 2px var(--fx-bg-elev, #fff);
	z-index: 4;
	pointer-events: none;
}
.fx-att__dl-arrow svg { width: 11px; height: 11px; display: block; }
.fx-att--loading .fx-att__dl-arrow,
.fx-att--cached .fx-att__dl-arrow { display: none; }
html[scheme='dark'] .fx-att__dl-arrow { box-shadow: 0 0 0 2px var(--fx-surface-2, #1a1e24); }

/* === v0.9.114: поле поиска — сплошной НЕПРОЗРАЧНЫЙ фон в тёмной теме.
   Двойной id (#fx-chat-search#fx-chat-search) повышает специфичность выше
   конкурирующего !important-правила темы (dark-theme.min.css), иначе фон
   оставался полупрозрачным (rgba(255,255,255,.04)). === */
html[scheme='dark'] #fx-chat-search#fx-chat-search,
body.fenix-chat-force-dark #fx-chat-search#fx-chat-search {
	background: #232a33 !important;
	background-color: #232a33 !important;
}
html[scheme='dark'] #fx-chat-search#fx-chat-search:focus,
body.fenix-chat-force-dark #fx-chat-search#fx-chat-search:focus {
	background: #2a323d !important;
	background-color: #2a323d !important;
}
@media (prefers-color-scheme: dark) {
	html:not([scheme]) #fx-chat-search#fx-chat-search {
		background: #232a33 !important;
		background-color: #232a33 !important;
	}
	html:not([scheme]) #fx-chat-search#fx-chat-search:focus {
		background: #2a323d !important;
		background-color: #2a323d !important;
	}
}


/* === v0.9.128: выпадающий список результатов поиска — FIXED-оверлей,
   позиционируется из JS (fxPositionSearchResults). НЕ трогает вёрстку строки
   поиска и шапки — прежние правила (position:relative обёртки, overflow:visible
   шапки) ломали размер и положение поля поиска. === */
.fx-search-results {
	position: fixed;
	max-height: 60vh;
	overflow-y: auto;
	background: var(--fx-bg-elev, #1b1f25);
	border: 1px solid var(--fx-surface-border, rgba(255, 255, 255, .14));
	border-radius: 12px;
	box-shadow: 0 14px 38px rgba(0, 0, 0, .45);
	z-index: 9999;
	padding: 6px;
	-webkit-overflow-scrolling: touch;
}
.fx-search-results[hidden] { display: none; }
.fx-search-res {
	padding: 9px 11px;
	border-radius: 9px;
	cursor: pointer;
	transition: background .12s ease;
}
.fx-search-res:hover,
.fx-search-res:focus-visible {
	background: color-mix(in srgb, var(--fx-brand, #4a9eff) 16%, transparent);
	outline: none;
}
.fx-search-res__head {
	display: flex; justify-content: space-between; gap: 10px;
	font-size: 12px; margin-bottom: 3px;
}
.fx-search-res__name {
	font-weight: 600;
	color: var(--fx-brand, #4a9eff);
	white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.fx-search-res__date {
	color: var(--fx-text-dim, #8a93a0);
	flex: 0 0 auto;
	font-variant-numeric: tabular-nums;
}
.fx-search-res__snip {
	font-size: 13px; line-height: 1.45;
	color: var(--fx-text, #e8ecf2);
	word-break: break-word;
}
.fx-search-res__note {
	padding: 16px; text-align: center;
	color: var(--fx-text-dim, #8a93a0); font-size: 13px;
}
.fx-search-results .fx-search-hit {
	background: transparent !important;
	color: var(--fx-brand, #4a9eff);
	font-weight: 700;
}

/* v0.9.139 — плавность скролла длинной истории: пропуск отрисовки ТЕЛ
   сообщений за пределами экрана. Применяется ТОЛЬКО к .fx-msg__body —
   меню ПКМ (.fx-msg__tools) и попаповеры (#fx-readers-popover, тулбар
   выделения и пр.) лежат ВНЕ body, поэтому не обрезаются. contain-intrinsic-size
   с ключевым словом auto запоминает реальную высоту после первого рендера. */
.fx-msg__body { content-visibility: auto; contain-intrinsic-size: auto 90px; }

/* ============================================================
   v0.9.174 — TG-паритет: спойлеры, кнопка «вниз», разделитель
   непрочитанных.
   ============================================================ */

/* Спойлер (как в Telegram): текст скрыт размытием, клик раскрывает.
   Приходит из TG как <span class="tg-spoiler"> (сервер сохраняет тег/класс
   в sanitizeHtml). Раньше стилей не было — спойлеры показывались обычным
   текстом. Раскрытие вешает .is-revealed (см. обработчик клика по ленте). */
/* В ЛЕНТЕ: спойлер скрыт размытием, клик раскрывает (.is-revealed). Скоуп
   .fx-msg — чтобы НЕ размывать спойлер в композере/окне правки, где юзер
   должен видеть, что печатает (там — читаемый стиль ниже). */
.fx-msg .tg-spoiler {
	filter: blur(5px);
	background: color-mix(in srgb, currentColor 14%, transparent);
	border-radius: 4px;
	padding: 0 2px;
	cursor: pointer;
	-webkit-user-select: none;
	user-select: none;
	/* НЕ анимируем filter: CSS не интерполирует в `none`, а некоторые движки
	   застревают и на blur(0) — спойлер тогда не раскрывается. Раскрытие
	   мгновенное (как в Telegram). Мягко анимируем только фон. */
	transition: background .18s ease;
	-webkit-tap-highlight-color: transparent;
}
.fx-msg .tg-spoiler::selection { background: transparent; }
.fx-msg .tg-spoiler.is-revealed {
	filter: none; /* transition у filter снят — none применяется мгновенно */
	background: transparent;
	cursor: text;
	-webkit-user-select: text;
	user-select: text;
}
/* В РЕДАКТОРАХ (composer + окно правки): спойлер читаемый, но помечен —
   мягкая подложка + пунктирная подчёркивающая линия, как «скрытый текст». */
.fx-chat-input .tg-spoiler,
.fx-msg-edit__rich .tg-spoiler {
	background: color-mix(in srgb, var(--fx-brand, #216be9) 15%, transparent);
	border-radius: 4px;
	padding: 0 2px;
	box-shadow: inset 0 -2px 0 0 color-mix(in srgb, var(--fx-brand, #216be9) 45%, transparent);
}
@media (prefers-reduced-motion: reduce) {
	.fx-msg .tg-spoiler { transition: none; }
}

/* Плавающая кнопка «вниз» (к последним сообщениям) со счётчиком новых и
   КОЛЬЦОМ ПРОГРЕССА прокрутки — оформление/анимация позаимствованы у
   back-to-top темы blogsy (два SVG-кольца r22.5: трек + прогресс, сплошная
   «таблетка» через ::after, тень акцентом). Sticky в скролл-контейнере;
   темы — через переменные --fx-*. Показ/скрытие/счётчик/прогресс — из JS. */
.fx-chat-scrolldown {
	position: sticky;
	bottom: 12px;
	align-self: flex-end;
	margin-right: 12px;
	margin-top: -48px; /* гасит собственную высоту (48px), не оставляя пустоты у низа ленты */
	z-index: 6;
	width: 48px;
	height: 48px;
	flex: 0 0 auto;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 0;
	/* !important: тема сайта вешает border на button:hover (спецификация
	   0,1,1 бьёт наш одиночный класс) — на светлой теме это давало тонкое
	   чёрное кольцо при наведении. Форсим отсутствие рамки во всех состояниях
	   (см. также :hover/:focus ниже). */
	border: none !important;
	border-radius: 50%;
	/* Оформление 1-в-1 с кнопкой темы #back-to-top: прозрачный фон (подложку
	   даёт ::after), тень акцентом, цвет — body-color темы. Переменные --pt-*
	   определяет тема глобально, поэтому цвета совпадают и переключаются вместе
	   с темой сайта. Фолбэки — на случай отсутствия переменных. */
	background: transparent;
	color: var(--pt-body-color, var(--fx-text, #222));
	box-shadow: 0px 5px 20px 0px var(--pt-accent-80-color, rgba(33, 107, 233, 0.5));
	cursor: pointer;
	opacity: 0;
	transform: translateY(10px) scale(.9);
	pointer-events: none;
	transition: opacity .25s ease, transform .25s ease, box-shadow .25s ease, color .25s ease;
}
/* Тёмная тема чата: базовая тень использует --pt-accent-80-color, но эта
   переменная отражает тему САЙТА — если сайт светлый, значение почти белое
   (#d3e2fb) и на тёмном фоне чата читается как белое свечение. У самой темы
   в тёмном режиме это значение тёмное — берём такое же, тень становится
   незаметной. */
html[scheme='dark'] .fx-chat-scrolldown {
	box-shadow: 0px 5px 20px 0px rgba(16, 16, 16, 0.5);
}
/* Сплошная «таблетка» под кольцами (фон кнопки). z-index -1 — под путями. */
.fx-chat-scrolldown::after {
	content: "";
	position: absolute;
	top: 2px;
	left: 2px;
	z-index: -1;
	width: 45px;
	height: 45px;
	border-radius: 50%;
	background: var(--pt-card-bg, var(--fx-bg, #fff));
	transition: background .25s ease;
}
.fx-chat-scrolldown.is-visible {
	opacity: 1;
	transform: translateY(0) scale(1);
	pointer-events: auto;
}
/* Убираем браузерную фокус/актив-обводку (чёрная рамка при клике):
   кнопка мышевая, состояние и так видно тенью + шевроном. */
.fx-chat-scrolldown:focus,
.fx-chat-scrolldown:focus-visible,
.fx-chat-scrolldown:active {
	outline: none;
}
.fx-chat-scrolldown:focus-visible {
	box-shadow: var(--pt-shadow-soft, 0 6px 24px rgba(33, 107, 233, 0.4));
}
.fx-chat-scrolldown::-moz-focus-inner { border: 0; }
.fx-chat-scrolldown:hover {
	background: inherit;
	color: var(--pt-accent-color, var(--fx-brand, #216be9));
	box-shadow: var(--pt-shadow-soft, 0 6px 24px rgba(33, 107, 233, 0.4));
	border: none !important;
	outline: none !important;
}
.fx-chat-scrolldown:active { transform: translateY(1px) scale(.96); }
/* Шеврон в центре. */
.fx-chat-scrolldown__chevron {
	width: 24px;
	height: 24px;
	display: block;
	transition: opacity .25s ease;
}
.fx-chat-scrolldown:hover .fx-chat-scrolldown__chevron { opacity: .8; }
/* Кольца (трек + прогресс) — SVG 49×49, отцентрованы по кнопке. */
/* Позиция колец 1-в-1 с темой (.scroll-top-border/.scroll-top-progress):
   top:0; left:0; без центрирующего transform. SVG 49×49 на кнопке 48×48
   ложится так же, как в теме (круг path M24.5,2 r22.5 центрируется сам). */
.fx-chat-scrolldown__ring {
	position: absolute;
	top: 0;
	left: 0;
	pointer-events: none;
	line-height: 0;
}
.fx-chat-scrolldown__ring svg { display: block; width: 49px; height: 49px; }
.fx-chat-scrolldown__ring path {
	stroke-width: 2;
	fill: none;
	stroke-dasharray: 141.37px, 141.37px;
	stroke-dashoffset: 0;
	transition: stroke-dashoffset .5s linear;
}
/* Трек = цвет подложки (--pt-card-bg), как в теме, — сам по себе не виден,
   служит фоном под прогрессом. Прогресс — акцент темы. */
.fx-chat-scrolldown__ring--track path {
	stroke: var(--pt-card-bg, var(--fx-bg, #fff));
}
.fx-chat-scrolldown__ring--progress path {
	stroke: var(--pt-accent-color, var(--fx-brand, #216be9));
	/* JS проставляет inline transition для плавного заполнения по скроллу. */
}
@media (prefers-reduced-motion: reduce) {
	.fx-chat-scrolldown, .fx-chat-scrolldown__chevron { transition: opacity .01s; }
}
.fx-chat-scrolldown__badge {
	position: absolute;
	top: -4px;
	right: -2px;
	min-width: 20px;
	height: 20px;
	padding: 0 5px;
	box-sizing: border-box;
	display: flex;
	align-items: center;
	justify-content: center;
	border-radius: 10px;
	background: var(--fx-brand, #216be9);
	color: #fff;
	font-size: 12px;
	font-weight: 700;
	line-height: 1;
	box-shadow: 0 0 0 2px var(--fx-bg, #fff);
}
.fx-chat-scrolldown__badge[hidden] { display: none; }

/* Разделитель «Непрочитанные» — линия с подписью, как в Telegram. */
.fx-chat-unread-divider {
	display: flex;
	align-items: center;
	gap: 10px;
	margin: 6px 8px 2px;
	font-size: 12px;
	font-weight: 600;
	color: var(--fx-text-dim, #7a8290);
	user-select: none;
	position: sticky;
	top: 4px;
	z-index: 1;
}
.fx-chat-unread-divider::before,
.fx-chat-unread-divider::after {
	content: "";
	flex: 1 1 auto;
	height: 1px;
	background: color-mix(in srgb, var(--fx-brand, #216be9) 30%, var(--fx-border, #e2e2e2));
}
.fx-chat-unread-divider__label {
	flex: 0 0 auto;
	padding: 2px 10px;
	border-radius: 10px;
	background: color-mix(in srgb, var(--fx-brand, #216be9) 12%, var(--fx-bg, #fff));
	color: var(--fx-brand, #216be9);
	white-space: nowrap;
}

/* v0.9.176 — заголовок «Переслано от X» в пузыре (как в Telegram). */
.fx-msg__fwd {
	display: flex;
	align-items: center;
	gap: 5px;
	margin: 0 0 3px;
	font-size: 12.5px;
	line-height: 1.3;
	color: var(--fx-brand, #216be9);
}
.fx-msg__fwd-ico { font-size: 13px; opacity: .85; }
.fx-msg__fwd-txt { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fx-msg__fwd-lbl { color: var(--fx-text-dim, #7a8290); font-weight: 500; }
.fx-msg__fwd-name { color: var(--fx-brand, #216be9); font-weight: 600; }
