style(assistant): вау-уровень окна Квантика

- стекло-блюр фона окна (backdrop-filter blur+saturate), глубже тень;
- полноширинная градиентная шапка (фиолетово-бирюзовый) со скруглением;
- аватар с зелёным «онлайн»-пульсом;
- анимированный индикатор печати (три прыгающие точки) вместо текста Думаю;
- плавное появление каждого сообщения (slide-in).
Всё уважает prefers-reduced-motion. Только frontend/js/assistant.js, inline SVG.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Maxim Dolgolyov
2026-06-24 22:17:55 +03:00
parent b6c08f1b16
commit 4c9656e8a8
+17 -6
View File
@@ -285,17 +285,28 @@
'.asst-name-face{display:inline-block;transition:transform .2s;}',
reduceMotion ? '' : '.asst-name-face.asst-think{animation:asstThink 1.3s ease-in-out infinite;transform-origin:60% 70%;}',
'@keyframes asstThink{0%,100%{transform:scale(1) rotate(0);}50%{transform:scale(1.08) rotate(-4deg);}}',
'.asst-bubble{position:absolute;left:0;bottom:66px;width:418px;max-width:94vw;background:#fff;border-radius:20px;',
' box-shadow:0 28px 70px -16px rgba(76,29,149,.36),0 6px 20px rgba(15,23,42,.1),0 0 0 1px rgba(155,93,229,.1);padding:14px 16px 16px;border:none;',
'.asst-bubble{position:absolute;left:0;bottom:66px;width:418px;max-width:94vw;background:rgba(255,255,255,.97);backdrop-filter:blur(16px) saturate(1.4);-webkit-backdrop-filter:blur(16px) saturate(1.4);border-radius:20px;overflow:hidden;',
' box-shadow:0 28px 70px -16px rgba(76,29,149,.38),0 6px 20px rgba(15,23,42,.1),0 0 0 1px rgba(155,93,229,.12);padding:14px 16px 16px;border:none;',
' opacity:0;transform:translateY(8px) scale(.98);pointer-events:none;transition:opacity .18s,transform .18s;transform-origin:bottom left;}',
'.asst-name-face{display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;vertical-align:middle;border-radius:50%;background:linear-gradient(135deg,rgba(155,93,229,.18),rgba(6,182,212,.15));margin-right:10px;box-shadow:inset 0 0 0 1px rgba(155,93,229,.22);}',
'.asst-name-face{position:relative;display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;vertical-align:middle;border-radius:50%;background:linear-gradient(135deg,rgba(255,255,255,.9),rgba(255,255,255,.55));margin-right:10px;box-shadow:inset 0 0 0 1px rgba(155,93,229,.28),0 2px 6px rgba(155,93,229,.18);}',
'.asst-name-face svg{width:25px;height:25px;display:block;}',
'.asst-name-face::after{content:"";position:absolute;right:-1px;bottom:0;width:9px;height:9px;border-radius:50%;background:#22c55e;border:2px solid #fff;}',
reduceMotion ? '' : '.asst-name-face::after{animation:asstOnline 2.2s ease-out infinite;}',
'@keyframes asstOnline{0%{box-shadow:0 0 0 0 rgba(34,197,94,.5);}70%,100%{box-shadow:0 0 0 6px rgba(34,197,94,0);}}',
// анимированный индикатор печати
'.asst-typing{display:inline-flex;gap:4px;align-items:center;padding:3px 0;}',
'.asst-typing span{width:7px;height:7px;border-radius:50%;background:#9B5DE5;opacity:.45;}',
reduceMotion ? '' : '.asst-typing span{animation:asstDot 1.1s infinite ease-in-out;}.asst-typing span:nth-child(2){animation-delay:.16s;}.asst-typing span:nth-child(3){animation-delay:.32s;}',
'@keyframes asstDot{0%,80%,100%{transform:translateY(0);opacity:.4;}40%{transform:translateY(-5px);opacity:1;}}',
// плавное появление сообщений
reduceMotion ? '' : '.asst-msg{animation:asstMsgIn .26s cubic-bezier(.4,0,.2,1);}',
'@keyframes asstMsgIn{from{opacity:0;transform:translateY(7px);}to{opacity:1;transform:translateY(0);}}',
'.asst-memnote{font-size:.66rem;color:#9aa5b4;margin-top:9px;line-height:1.45;border-top:1px solid rgba(15,23,42,.05);padding-top:8px;}',
'.asst-bubble.open{opacity:1;transform:translateY(0);pointer-events:auto;}',
'.asst-x{position:absolute;top:12px;right:12px;width:28px;height:28px;border:none;background:transparent;color:#94a3b8;z-index:3;',
' cursor:pointer;border-radius:8px;font-size:19px;line-height:1;transition:all .14s;}',
'.asst-x:hover{background:rgba(15,23,42,.06);color:#0F172A;}',
'.asst-name{font-size:.98rem;font-weight:800;color:#0F172A;text-transform:none;letter-spacing:0;margin:-2px 0 11px;padding:0 28px 11px 0;border-bottom:1px solid rgba(15,23,42,.07);line-height:34px;}',
'.asst-name{font-size:.98rem;font-weight:800;color:#0F172A;text-transform:none;letter-spacing:0;margin:-14px -16px 12px;padding:13px 48px 12px 16px;background:linear-gradient(120deg,rgba(155,93,229,.13),rgba(6,182,212,.10));border-bottom:1px solid rgba(155,93,229,.14);border-radius:20px 20px 0 0;line-height:34px;}',
'.asst-text{font-size:.86rem;line-height:1.5;color:#28324a;margin-bottom:12px;white-space:pre-line;}',
'.asst-actions{display:flex;gap:8px;align-items:center;flex-wrap:wrap;}',
'.asst-btn{display:inline-flex;align-items:center;gap:6px;padding:7px 13px;border-radius:99px;border:none;cursor:pointer;',
@@ -663,7 +674,7 @@
var history = _chat.slice(-6);
_chat.push({ role: 'user', content: q });
var u = msgEl('user'); u.textContent = q; chatEl.appendChild(u);
var ph = msgEl('assistant'); ph.className += ' asst-msg-ph'; ph.textContent = mode === 'check' ? 'Проверяю…' : 'Думаю…'; chatEl.appendChild(ph);
var ph = msgEl('assistant'); ph.className += ' asst-msg-ph'; ph.innerHTML = '<span class="asst-typing"><span></span><span></span><span></span></span>'; chatEl.appendChild(ph);
chatEl.scrollTop = chatEl.scrollHeight;
setNameFace('thinking');
@@ -737,7 +748,7 @@
var history = _chat.slice(-6);
_chat.push({ role: 'user', content: q });
var u = msgEl('user'); u.textContent = q; chatEl.appendChild(u);
var ph = msgEl('assistant'); ph.className += ' asst-msg-ph'; ph.textContent = mode === 'check' ? 'Проверяю…' : 'Думаю…'; chatEl.appendChild(ph);
var ph = msgEl('assistant'); ph.className += ' asst-msg-ph'; ph.innerHTML = '<span class="asst-typing"><span></span><span></span><span></span></span>'; chatEl.appendChild(ph);
chatEl.scrollTop = chatEl.scrollHeight;
setNameFace('thinking');
Promise.all([