Files
SHiNE-server/shine-UI/styles/features/chat.css
T
qandClaude Opus 5.5 2e62616b46 UI v4: новый стиль по макету V3/V4 и доводка экранов
Палитра «Сияние» по умолчанию, новые роли цветов. Лента канала: плоские записи, ряд действий
с равным шагом иконок, дата у записи. Обсуждение со строкой ввода, личный чат, шторки.
Вход и регистрация: стартовый экран (надпись «СИЯНИЕ», сияние мандалы), настройки входа
со статусами серверов, статус логина в одну строку, вход с другого устройства (код, таймер, шаги),
сохранение ключей с переключателями. Корневые разделы – заголовок по центру; фильтр чатов –
переключатель; уведомления – список как в чатах; фото – просмотр на весь экран.
Общее: один зазор под шапкой (--page-top-gap), переключатели высотой с поле ввода,
второстепенные кнопки по одной роли (в том числе на экранах устройств и серверов),
иконки только из ui-icon.js, полоса прокрутки скрыта, среднее тире в текстах интерфейса.

Что нужно от сервера и разработчика – docs/UI-Design/UI-v4-for-dev.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 01:36:52 +03:00

1358 lines
29 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* Direct chat screen and composer/message styles. */
.chat-header-icon-btn {
min-width: 44px;
width: 44px;
min-height: 44px;
height: 44px;
padding: 0;
display: inline-flex;
align-items: center;
justify-content: center;
font-size: 20px;
line-height: 1;
}
.chat-header-call-btn {
border-radius: 12px;
}
.chat-header-menu-btn {
border-radius: 12px;
font-size: 24px;
}
.chat-unread-separator {
display: flex;
align-items: center;
gap: 10px;
margin: 8px 0;
color: var(--accent);
font-size: 12px;
}
.chat-unread-separator::before,
.chat-unread-separator::after {
content: "";
flex: 1 1 auto;
height: 1px;
background: linear-gradient(90deg, color-mix(in srgb, var(--accent) 12%, transparent), color-mix(in srgb, var(--accent) 45%, transparent), color-mix(in srgb, var(--accent) 12%, transparent));
}
.chat-unread-separator > span {
white-space: nowrap;
}
.bubble {
max-width: 76%;
padding: 10px 12px;
border-radius: 14px;
font-size: 14px;
line-height: 1.35;
}
.bubble-text {
white-space: pre-wrap;
word-break: break-word;
}
.bubble-reply-preview {
display: block;
width: 100%;
margin: 0 0 8px;
padding: 8px 10px;
border-radius: 10px;
text-align: left;
cursor: pointer;
}
.bubble-reply-preview-author {
font-size: 12px;
font-weight: 700;
color: var(--warning);
}
.bubble-reply-preview-text {
margin-top: 3px;
font-size: 12px;
line-height: 1.3;
color: var(--text-primary);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.bubble-meta {
margin-top: 4px;
display: flex;
justify-content: flex-end;
align-items: center;
gap: 5px;
font-size: 11px;
line-height: 1.1;
color: var(--text-primary);
}
.bubble-meta-edited {
margin-top: 3px;
justify-content: flex-end;
color: var(--warning);
}
.bubble-time {
letter-spacing: 0.01em;
}
.bubble-status {
min-width: 14px;
text-align: right;
color: var(--text-primary);
}
.bubble-status--delivered,
.bubble-status--read {
color: var(--text-primary);
text-shadow: 0 0 6px color-mix(in srgb, var(--accent) 36%, transparent);
}
.bubble-status--failed {
color: var(--danger);
}
.bubble-delivery-note {
max-width: 280px;
margin-top: 6px;
font-size: 11px;
line-height: 1.3;
color: var(--warning);
}
.bubble-delivery-note--failed {
color: var(--danger);
}
.bubble.in {
justify-self: start;
background: var(--surface);
border-top-left-radius: 6px;
}
.bubble.out {
justify-self: end;
background: var(--surface);
border-top-right-radius: 6px;
}
.bubble.call-tech {
max-width: 90%;
justify-self: center;
border-radius: 16px;
border: 1px solid color-mix(in srgb, var(--accent) 28%, transparent);
background: var(--surface);
color: var(--text-primary);
font-size: 12px;
padding: 12px 14px;
}
.bubble-call-card {
display: grid;
min-width: min(280px, 72vw);
}
.bubble-call-head {
display: inline-flex;
align-items: center;
gap: 8px;
flex-wrap: wrap;
}
.bubble-call-icon {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
width: 28px;
height: 28px;
color: var(--text-primary);
flex: 0 0 auto;
}
.bubble-call-icon-phone {
font-size: 28px;
line-height: 1;
transform: translateY(-1px);
}
.bubble-call-icon-arrow {
position: absolute;
right: 4px;
bottom: 3px;
font-size: 11px;
line-height: 1;
font-weight: 700;
}
.bubble-call-icon--incoming .bubble-call-icon-arrow {
color: var(--text-primary);
}
.bubble-call-icon--outgoing .bubble-call-icon-arrow {
color: var(--warning);
}
.bubble-call-title {
font-size: 14px;
font-weight: 700;
color: var(--text-primary);
line-height: 1.2;
}
.bubble-call-line {
font-size: 12px;
line-height: 1.2;
margin-left: 2px;
}
.bubble-call-line--success {
color: var(--success);
}
.bubble-call-line--plain {
color: var(--text-primary);
}
.dm-chat-wrap {
gap: 12px;
}
.dm-chat-screen {
display: flex;
flex-direction: column;
min-height: 0;
gap: 12px;
}
.dm-chat-screen > .dm-chat-wrap {
flex: 1 1 auto;
min-height: 0;
overflow-y: auto;
}
.dm-chat-composer {
position: sticky;
bottom: 0;
z-index: 12;
flex: 0 0 auto;
}
.screen-content:has(> .dm-chat-screen) > .dm-chat-screen {
flex: 1 1 auto;
min-height: 0;
}
.screen-content:has(> .dm-chat-screen) {
display: flex;
flex-direction: column;
overflow: hidden;
padding-top: 0;
padding-bottom: 0;
scrollbar-width: none;
-ms-overflow-style: none;
}
.screen-content:has(> .dm-chat-screen)::-webkit-scrollbar {
width: 0;
height: 0;
display: none;
}
.dm-messages-log {
gap: 10px;
}
.dm-screen .bubble {
max-width: 78%;
padding: 11px 14px;
line-height: 1.42;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.32);
}
.dm-screen .bubble.in {
justify-self: start;
border-radius: 18px 18px 18px 4px;
border: 1px solid var(--border-subtle);
background: var(--surface);
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
}
.dm-screen .bubble.out {
justify-self: end;
border-radius: 18px 18px 4px 18px;
border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
background: color-mix(in srgb, var(--accent) 16%, transparent);
color: var(--text-primary);
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
}
.dm-edit-banner {
grid-column: 1 / -1;
display: grid;
grid-template-columns: 1fr auto;
align-items: start;
gap: 10px;
padding: 10px 12px;
border-radius: 14px;
border: 1px solid transparent;
background: color-mix(in srgb, var(--warning) 12%, transparent);
color: var(--text-primary);
box-shadow: 0 10px 22px rgba(0, 0, 0, 0.22);
}
.dm-edit-banner[hidden] {
display: none;
}
.dm-edit-banner__text {
min-width: 0;
font-size: 12px;
line-height: 1.35;
white-space: pre-line;
overflow: hidden;
}
.dm-edit-banner__close {
min-width: 30px;
width: 30px;
height: 30px;
padding: 0;
border-radius: 10px;
}
.dm-chat-input--multiline .dm-actions-col {
grid-template-columns: 46px;
grid-template-rows: repeat(2, 46px);
grid-template-areas:
"emoji"
"send";
}
.dm-emoji-btn {
grid-area: emoji;
min-width: 46px;
width: 46px;
padding: 0;
line-height: 1;
}
.dm-emoji-btn__glyph {
display: inline-grid;
place-items: center;
width: 100%;
height: 100%;
font-size: 27px;
line-height: 1;
}
.bubble.bubble--emoji-only,
.dm-screen .bubble.bubble--emoji-only {
padding: 0;
border: 0;
background: transparent;
box-shadow: none;
backdrop-filter: none;
-webkit-backdrop-filter: none;
color: inherit;
}
.bubble.bubble--emoji-only.in,
.dm-screen .bubble.bubble--emoji-only.in,
.bubble.bubble--emoji-only.out,
.dm-screen .bubble.bubble--emoji-only.out {
border: 0;
background: transparent;
}
.bubble.bubble--emoji-only .bubble-meta {
margin-top: 2px;
padding: 0 4px;
color: var(--text-secondary);
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
}
.bubble-text--twemoji-only {
font-size: 56px;
line-height: 1;
}
.bubble-text--twemoji-only .chat-twemoji {
width: 1em;
height: 1em;
}
.dm-chat-input .dm-input {
min-height: 42px;
max-height: 180px;
width: 100%;
min-width: 0;
resize: none;
overflow-y: auto;
scrollbar-width: none;
-ms-overflow-style: none;
line-height: 1.35;
padding: 10px 12px;
}
.dm-chat-input--multiline .dm-input {
padding-right: 14px;
}
.dm-chat-input .dm-input::-webkit-scrollbar {
width: 0;
height: 0;
}
.dm-input {
background: color-mix(in srgb, var(--text-primary) 4%, transparent);
border: 1px solid transparent;
border-radius: 14px;
color: var(--text-primary);
}
.dm-input::placeholder {
color: var(--text-secondary);
}
.dm-send-btn {
background: color-mix(in srgb, var(--warning) 20%, transparent);
border: 1px solid transparent;
color: var(--warning);
border-radius: 14px;
font-weight: 700;
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.3);
}
.dm-send-icon-btn {
grid-area: send;
min-width: 46px;
width: 46px;
padding: 0;
font-size: 15px;
line-height: 1;
}
.dm-message-actions-popover {
position: fixed;
left: 12px;
top: 12px;
margin: 0;
pointer-events: auto;
opacity: 0;
transform: translateY(8px) scale(0.98);
transition: opacity 120ms ease, transform 120ms ease;
box-shadow: 0 18px 34px rgba(0, 0, 0, 0.42);
}
.dm-message-actions-popover.is-visible {
opacity: 1;
transform: translateY(0) scale(1);
}
.dm-message-action-btn {
width: 100%;
min-height: 42px;
justify-content: flex-start;
padding: 0 14px;
border-radius: 12px;
}
.dm-message-action-btn--danger {
color: var(--text-primary);
border-color: color-mix(in srgb, var(--danger) 30%, transparent);
background: color-mix(in srgb, var(--surface) 22%, transparent);
}
/* Чат: в центре только компактная идентичность собеседника. */
.chat-header-identity {
min-width: 0;
max-width: 132px;
display: inline-flex;
align-items: center;
justify-content: center;
gap: 7px;
}
.chat-header-avatar-slot {
width: 40px;
height: 40px;
min-width: 40px;
min-height: 40px;
display: inline-flex;
align-items: center;
justify-content: center;
}
.chat-header-avatar.avatar,
.chat-header-avatar.avatar-image {
width: 40px;
height: 40px;
min-width: 40px;
min-height: 40px;
font-size: 14px;
border: 0;
box-shadow: none;
}
/* Фиксированная высота, а не только min-height: при смене основных вкладок
* верхняя граница контента больше не меняется из-за локальной шапки страницы. */
/* Один и тот же текстовый ритм на Контактах / Каналах / Связях /
* Уведомлениях / Профиле и вложенных экранах. */
/* В списке контактов логин слева также остаётся в общей палитре шапки. */
/* Все интерактивные элементы верхней шапки имеют одинаковую рабочую высоту. */
/* Личный чат: аватар остаётся компактным, логин теперь равен общему 18px. */
.chat-header-identity {
max-width: 176px;
gap: 8px;
}
/* Личный чат: логин остаётся строго в центральной колонке,
* аватар живёт отдельно в левой колонке рядом со стрелкой назад. */
.chat-header-login {
min-width: 0;
font-family: var(--font-main);
font-size: 18px;
line-height: 22px;
font-weight: 700;
color: var(--app-topbar-gold);
text-shadow: 0 0 5px var(--app-topbar-blue-glow),
0 0 14px var(--app-topbar-blue-glow-soft);
display: block;
max-width: min(42vw, 180px);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
text-align: center;
}
.chat-header-avatar-slot--left {
flex: 0 0 28px;
margin-left: 0;
}
.chat-header-connections-btn,
.chat-header-avatar-btn {
padding: 0;
min-width: 0;
min-height: 0;
border: 0;
background: transparent;
box-shadow: none;
transform: none;
}
.chat-header-connections-btn:hover,
.chat-header-connections-btn:active,
.chat-header-connections-btn:focus,
.chat-header-connections-btn:focus-visible,
.chat-header-avatar-btn:hover,
.chat-header-avatar-btn:active,
.chat-header-avatar-btn:focus,
.chat-header-avatar-btn:focus-visible {
border: 0;
background: transparent;
box-shadow: none;
transform: none;
}
.chat-header-connections-btn {
width: 38px;
height: 38px;
border-radius: 999px;
display: inline-flex;
align-items: center;
justify-content: center;
background: var(--surface);
border: 1px solid color-mix(in srgb, var(--accent) 26%, transparent);
box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 8%, transparent), 0 0 12px color-mix(in srgb, var(--accent) 18%, transparent);
}
.chat-header-connections-btn:hover,
.chat-header-connections-btn:focus-visible {
border-color: color-mix(in srgb, var(--accent) 38%, transparent);
box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 16%, transparent), 0 0 16px color-mix(in srgb, var(--accent) 28%, transparent);
}
.chat-header-connections-logo {
width: 24px;
height: 24px;
object-fit: contain;
display: block;
}
.chat-header-avatar-btn {
display: inline-flex;
align-items: center;
justify-content: center;
}
.chat-header-avatar-btn .chat-header-avatar-slot {
display: inline-flex;
}
/* Пузырям сообщений не нужна отдельная обводка: направление читается по фону и геометрии. */
.dm-chat-screen .bubble,
.dm-chat-screen .bubble.in,
.dm-chat-screen .bubble.out,
.dm-chat-screen .bubble.call-tech {
border: 0;
}
.dm-chat-screen .bubble-reply-preview {
border: 0;
}
/* Нижняя панель чата повторяет бело-голубую цветовую роль верхнего toolbar вместо золота. */
.dm-chat-input .dm-input {
border-color: var(--border-subtle);
color: var(--app-topbar-gold);
text-shadow:
0 0 4px color-mix(in srgb, var(--accent) 34%, transparent),
0 0 10px color-mix(in srgb, var(--accent) 16%, transparent);
caret-color: var(--app-topbar-gold);
}
.dm-chat-input .dm-input:focus {
border-color: color-mix(in srgb, var(--accent) 28%, transparent);
box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 8%, transparent);
}
.dm-chat-input .dm-input::placeholder {
color: var(--text-secondary);
text-shadow: none;
}
.dm-chat-input .dm-emoji-btn,
.dm-chat-input .dm-send-btn,
.dm-chat-input .dm-edit-banner__close {
color: var(--app-topbar-gold);
text-shadow:
0 0 5px var(--app-topbar-blue-glow),
0 0 12px var(--app-topbar-blue-glow-soft);
filter: drop-shadow(0 0 4px color-mix(in srgb, var(--accent) 42%, transparent));
}
.dm-chat-input .dm-send-btn {
border-color: var(--border-subtle);
background: color-mix(in srgb, var(--accent) 8%, transparent);
box-shadow: none;
}
.dm-chat-input .dm-edit-banner {
border-color: color-mix(in srgb, var(--accent) 18%, transparent);
background: color-mix(in srgb, var(--accent) 8%, transparent);
color: var(--app-topbar-gold);
}
.dm-chat-input .emoji-picker-tab.is-active {
background: color-mix(in srgb, var(--accent) 12%, transparent);
}
/* Composer должен быть продолжением основного фона: без верхнего разделителя
* и без отдельной затемнённой/стеклянной подложки. */
/* ===== Feature geometry around the centralized App Shell ===== */
/* DM: shell рисует global fade, а внутренний scroll-container только резервирует
* место под TopBar/Composer, не реализуя собственное глобальное затухание. */
.app-shell--scroll-nested .dm-chat-screen > .dm-chat-wrap {
box-sizing: border-box;
padding-top: calc(var(--topbar-height, 64px) + 12px);
padding-bottom: calc(var(--composer-height, 0px) + 52px);
}
/* Один визуальный язык для меню профиля, чатов и каналов. */
.dm-message-action-btn {
width: 100%;
min-height: 42px;
padding: 0 11px;
display: flex;
align-items: center;
justify-content: flex-start;
gap: 10px;
border: 0;
border-radius: 10px;
background: transparent;
color: var(--text-primary);
font: inherit;
font-size: 14px;
font-weight: 600;
line-height: 1.2;
text-align: left;
white-space: nowrap;
}
.dm-message-action-btn:hover,
.dm-message-action-btn:focus-visible {
outline: none;
background: color-mix(in srgb, var(--accent) 12%, transparent);
}
.dm-message-action-btn--danger {
color: var(--text-primary);
background: transparent;
}
.dm-message-actions-menu {
min-width: 196px;
padding: 6px;
gap: 2px;
border: 1px solid color-mix(in srgb, var(--accent) 22%, transparent);
border-radius: 16px;
background: linear-gradient(155deg, var(--surface), var(--surface));
box-shadow: 0 18px 42px rgba(0, 0, 0, 0.48),
0 0 24px color-mix(in srgb, var(--accent) 10%, transparent),
inset 0 1px 0 color-mix(in srgb, var(--text-primary) 6%, transparent);
backdrop-filter: blur(20px) saturate(125%);
-webkit-backdrop-filter: blur(20px) saturate(125%);
width: min(78vw, 240px);
}
.chat-header-login-btn {
padding: 4px 7px;
min-height: 34px;
border: 0;
border-radius: 10px;
background: transparent;
cursor: pointer;
}
/* Поле сообщения занимает почти всю ширину; действия прижаты к правому краю. */
/* Нижняя панель чата — поверхность с линией сверху, как у канала и обсуждения */
.dm-chat-input {
grid-template-columns: minmax(0, 1fr) auto;
align-items: end;
position: relative;
z-index: 10;
margin-inline: calc(-1 * var(--page-gutter));
padding: 9px var(--page-gutter) calc(11px + env(safe-area-inset-bottom));
border-top: 1px solid var(--border-subtle);
background: var(--surface);
gap: 6px;
}
.dm-chat-input--multiline .dm-actions-col {
grid-template-columns: 43px;
}
.dm-emoji-btn,
.dm-send-icon-btn {
min-width: 43px;
width: 43px;
}
/* DM peer identity: one large invisible button fills the area between Back and Call. */
/* Шапка чата — общая «визитка» (topbar.css .topbar-identity). У аватара стеклянный ободок на 119%,
* поэтому ни кнопка, ни слот аватара не обрезают содержимое; текст обрезается сам. */
.chat-header-peer-btn { width: 100%; overflow: visible; }
.chat-header-peer-btn .chat-header-avatar-slot { width: 36px; height: 36px; min-width: 36px; flex: 0 0 36px; overflow: visible; }
.chat-header-peer-btn .chat-header-avatar-slot .avatar.chat-header-avatar { width: 36px; height: 36px; min-width: 36px; min-height: 36px; overflow: visible; }
.chat-header-peer-text { flex: 1 1 auto; overflow: hidden; }
/* Shell state + Chat-owned composer adjustment (moved out of app-shell.css). */
.app-shell--scroll-nested.keyboard-open .composer-slot .dm-chat-input {
padding-bottom: 9px;
}
/* Composer icon actions own their white/blue interaction surface. */
.dm-chat-input :is(.dm-emoji-btn, .dm-send-btn, .dm-edit-banner__close),
.dm-chat-input :is(.dm-emoji-btn, .dm-send-btn, .dm-edit-banner__close):hover,
.dm-chat-input :is(.dm-emoji-btn, .dm-send-btn, .dm-edit-banner__close):focus {
color: var(--text-primary);
text-shadow: 0 0 5px color-mix(in srgb, var(--accent) 72%, transparent), 0 0 12px color-mix(in srgb, var(--accent) 34%, transparent);
filter: drop-shadow(0 0 4px color-mix(in srgb, var(--accent) 46%, transparent));
}
/* ===== Зашифрованные вложения в личных сообщениях ===== */
.dm-file-btn {
position: absolute;
right: 45px;
bottom: 52px;
z-index: 6;
min-width: 43px;
width: 43px;
height: 43px;
padding: 0;
border-radius: 14px;
font-size: 21px;
line-height: 1;
background: var(--surface);
border: 1px solid color-mix(in srgb, var(--accent) 28%, transparent);
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.3), inset 0 1px 0 color-mix(in srgb, var(--text-primary) 8%, transparent);
backdrop-filter: blur(16px);
-webkit-backdrop-filter: blur(16px);
}
.dm-file-btn[hidden] {
display: none;
}
.dm-file-btn:disabled {
opacity: 0.7;
cursor: progress;
}
.dm-file-card {
min-width: min(285px, 72vw);
max-width: min(330px, 76vw);
display: grid;
grid-template-columns: 36px minmax(0, 1fr) auto;
align-items: center;
gap: 9px;
}
.dm-file-card__icon {
width: 36px;
height: 36px;
display: grid;
place-items: center;
border-radius: 12px;
background: color-mix(in srgb, var(--text-primary) 8%, transparent);
font-size: 19px;
}
.dm-file-card__copy {
min-width: 0;
display: grid;
gap: 3px;
}
.dm-file-card__name {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 13px;
font-weight: 680;
}
.dm-file-card__meta {
font-size: 11px;
color: var(--text-secondary);
}
.dm-file-card__download {
min-height: 34px;
padding: 0 10px;
border-radius: 11px;
font-size: 12px;
font-weight: 650;
white-space: nowrap;
}
.dm-file-card__download:disabled {
opacity: 0.65;
cursor: progress;
}
@media (max-width: 390px) {
.dm-screen .dm-file-card {
min-width: min(264px, 76vw);
grid-template-columns: 32px minmax(0, 1fr);
}
.dm-screen .dm-file-card__download {
grid-column: 2;
justify-self: start;
}
}
.dm-chat-input--multiline .dm-file-btn {
right: 0;
bottom: 104px;
}
/* ===== DM file transfer v2 + voice notes ===== */
.dm-attachment-stack {
display: grid;
gap: 8px;
min-width: 0;
}
.dm-send-icon-btn svg {
width: 22px;
height: 22px;
display: block;
margin: auto;
}
.dm-send-icon-btn.is-recording {
transform: scale(1.04);
box-shadow: 0 0 0 5px color-mix(in srgb, var(--danger) 8%, transparent), 0 0 24px color-mix(in srgb, var(--danger) 18%, transparent);
}
.dm-send-icon-btn.is-recording:not(.is-locked) {
color: var(--text-primary);
}
.dm-send-icon-btn.is-locked {
color: var(--text-primary);
background: color-mix(in srgb, var(--danger) 28%, transparent);
border-color: color-mix(in srgb, var(--danger) 32%, transparent);
}
.dm-send-busy-dot {
display: inline-grid;
place-items: center;
width: 100%;
height: 100%;
font-size: 20px;
line-height: 1;
}
.dm-voice-recording-status {
grid-column: 1;
min-height: 42px;
display: grid;
grid-template-columns: auto auto minmax(0, 1fr);
align-items: center;
gap: 8px;
padding: 0 12px;
border: 1px solid var(--border-subtle);
border-radius: 14px;
background: color-mix(in srgb, var(--text-primary) 4%, transparent);
overflow: hidden;
}
.dm-voice-recording-status[hidden] {
display: none;
}
.dm-voice-recording-dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: color-mix(in srgb, var(--danger) 96%, transparent);
box-shadow: 0 0 12px color-mix(in srgb, var(--danger) 55%, transparent);
animation: dmVoicePulse 1s ease-in-out infinite;
}
@keyframes dmVoicePulse {
0%, 100% { opacity: 0.55; transform: scale(0.82); }
50% { opacity: 1; transform: scale(1); }
}
.dm-voice-recording-time {
font-variant-numeric: tabular-nums;
font-size: 13px;
font-weight: 720;
color: var(--text-primary);
}
.dm-voice-recording-hint {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
text-align: right;
font-size: 11px;
color: var(--text-secondary);
}
.dm-chat-input--recording .dm-actions-col {
align-self: center;
}
.dm-voice-card {
min-width: min(280px, 72vw);
max-width: min(330px, 76vw);
display: grid;
grid-template-columns: 42px minmax(0, 1fr);
align-items: center;
gap: 10px;
}
.dm-voice-card__play {
width: 42px;
height: 42px;
min-width: 42px;
padding: 0;
border-radius: 50%;
display: grid;
place-items: center;
font-size: 15px;
line-height: 1;
background: color-mix(in srgb, var(--accent) 12%, transparent);
border: 1px solid color-mix(in srgb, var(--accent) 22%, transparent);
}
.dm-voice-card__play:disabled {
opacity: 0.65;
cursor: progress;
}
.dm-voice-card__body {
min-width: 0;
display: grid;
gap: 6px;
}
.dm-voice-card__track {
position: relative;
width: 100%;
height: 18px;
min-height: 18px;
padding: 0;
border: 0;
background: transparent;
overflow: hidden;
}
.dm-voice-card__track::before {
content: '';
position: absolute;
left: 0;
right: 0;
top: 8px;
height: 2px;
border-radius: 999px;
background: color-mix(in srgb, var(--text-primary) 20%, transparent);
}
.dm-voice-card__fill {
position: absolute;
left: 0;
top: 7px;
width: 0;
height: 4px;
border-radius: 999px;
background: currentColor;
box-shadow: 0 0 8px color-mix(in srgb, var(--accent) 35%, transparent);
pointer-events: none;
}
.dm-voice-card__meta {
display: flex;
justify-content: space-between;
gap: 10px;
font-size: 11px;
color: var(--text-secondary);
font-variant-numeric: tabular-nums;
}
@media (max-width: 390px) {
.dm-voice-card {
min-width: min(252px, 76vw);
}
.dm-voice-recording-hint {
max-width: 150px;
}
}
/* Пересылка DM: выбор чата и подтверждение остаются внутри одного feature-owned modal. */
.dm-forward-modal {
align-items: center;
padding: 18px;
}
.dm-forward-card {
width: min(92vw, 430px);
max-height: min(78vh, 680px);
overflow: hidden;
gap: 12px;
border: 1px solid color-mix(in srgb, var(--accent) 25%, transparent);
border-radius: 24px;
background: linear-gradient(155deg, var(--surface), var(--surface));
box-shadow: 0 30px 80px rgba(0, 0, 0, 0.52), 0 0 34px color-mix(in srgb, var(--accent) 12%, transparent);
backdrop-filter: blur(24px) saturate(130%);
-webkit-backdrop-filter: blur(24px) saturate(130%);
}
.dm-forward-head,
.dm-forward-confirm-peer {
display: flex;
align-items: center;
gap: 12px;
}
.dm-forward-head {
justify-content: space-between;
}
.dm-forward-close {
width: 36px;
height: 36px;
border-radius: 50%;
font-size: 25px;
line-height: 1;
color: var(--text-primary);
background: color-mix(in srgb, var(--text-primary) 5%, transparent);
}
.dm-forward-preview {
padding: 11px 13px;
border: 1px solid var(--border-subtle);
border-radius: 14px;
color: var(--text-primary);
background: color-mix(in srgb, var(--text-primary) 4%, transparent);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.dm-forward-preview--confirm {
white-space: normal;
max-height: 128px;
overflow: auto;
}
.dm-forward-list {
display: flex;
flex-direction: column;
gap: 4px;
min-height: 120px;
max-height: min(54vh, 460px);
overflow-y: auto;
padding-right: 2px;
}
.dm-forward-chat-row {
width: 100%;
display: grid;
grid-template-columns: auto 1fr auto;
align-items: center;
gap: 11px;
min-height: 62px;
padding: 8px 10px;
border: 0;
border-radius: 15px;
text-align: left;
color: var(--text);
background: transparent;
}
.dm-forward-chat-row:hover,
.dm-forward-chat-row:focus-visible {
outline: none;
background: color-mix(in srgb, var(--accent) 11%, transparent);
}
.dm-forward-chat-copy {
min-width: 0;
display: flex;
flex-direction: column;
gap: 2px;
}
.dm-forward-chat-copy strong,
.dm-forward-chat-copy span {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.dm-forward-chat-arrow {
font-size: 28px;
color: var(--accent);
}
.dm-forward-loading {
padding: 20px 8px;
text-align: center;
}
.dm-forward-confirm-peer {
padding: 12px;
border-radius: 16px;
background: color-mix(in srgb, var(--accent) 8%, transparent);
}
.dm-forward-confirm-actions {
margin-top: 2px;
}
.dm-chat-screen .bubble {
max-width: min(85%, 34rem);
padding: 10px 12px 7px;
border-radius: 17px;
color: var(--text-primary);
font-size: .9375rem;
line-height: 1.375rem;
box-shadow: none;
overflow-wrap: anywhere;
}
.dm-chat-screen .bubble.in { background: var(--surface); border-bottom-left-radius: 5px; }
.dm-chat-screen .bubble.out { background: var(--bubble-out); border-bottom-right-radius: 5px; }
/* Время и статус — в конце последней строки (эксперимент V4, принят); не влезают — переносятся */
.dm-chat-screen .bubble-text { display: inline; }
.dm-chat-screen .bubble-meta { float: right; margin: 5px 0 0 10px; display: inline-flex; align-items: center; gap: 4px; font-size: .6875rem; line-height: 1rem; color: color-mix(in srgb, var(--text-secondary) 70%, var(--text-primary)); }
.dm-chat-screen .bubble::after { content: ''; display: table; clear: both; }
.dm-chat-screen .bubble-status { display: inline-flex; min-width: 0; color: inherit; text-shadow: none; }
.dm-chat-screen .bubble-status svg { width: 16px; height: 16px; }
.dm-chat-screen .bubble-status--read { color: var(--action); }
.dm-chat-screen .bubble-status--failed { color: var(--danger); }
.dm-chat-screen .bubble-delivery-note { clear: both; }
.dm-day-separator { display: flex; justify-content: center; margin: 8px 0; }
.dm-day-separator span { padding: 3px 10px; border-radius: var(--radius-pill); color: var(--text-secondary); background: var(--surface); border: 1px solid var(--border-subtle); font-size: var(--text-xs); line-height: var(--leading-xs); }
.dm-chat-input .dm-input {
min-height: var(--control-height);
border: 1px solid var(--border-control);
border-radius: 22px;
color: var(--text-primary);
background: var(--surface-raised);
text-shadow: none;
caret-color: var(--accent);
font-size: 1rem;
}
.dm-chat-input .dm-input:focus { border-color: var(--accent); box-shadow: none; }
.dm-chat-input .dm-input::placeholder { color: color-mix(in srgb, var(--text-secondary) 62%, var(--surface)); }
.dm-chat-input .dm-emoji-btn,
.dm-chat-input .dm-edit-banner__close { color: var(--text-secondary); text-shadow: none; filter: none; }
.dm-chat-input .dm-send-btn {
color: var(--on-accent);
background: var(--accent);
border: 0;
text-shadow: none;
filter: none;
}
.dm-chat-input .dm-edit-banner { color: var(--text-primary); }
.composer-slot:has(> .dm-chat-input) { padding-inline: var(--page-gutter); }
.dm-chat-input .dm-send-btn { width: 44px; min-width: 44px; height: 44px; min-height: 44px; padding: 0; border-radius: 50%; }