/* ============================================================================
   Сцена первого экрана. Три акта в одном кадре:
     1) тренер шлёт голосовое в личку Сетке,
     2) приходит карточка на подтверждение — курсор колеблется и жмёт «Ок»,
     3) сообщения уходят клиентам.

   Акты 1–2 живут внутри окна чата: рамка, шапка, аватар — это переписка
   ТЕБЯ с ботом. Акт 3 рамки не имеет вовсе: пузыри лежат прямо на фоне
   страницы, у каждого свой получатель и пометка, как сообщение ушло. Разная
   плоскость — единственный способ показать, что бот пишет НЕ тебе.

   Всё в пространстве `d-`. Состояния — короткие классы (`on`, `lit`, `press`,
   `d-noanim`, `d-fade`), их вешает site/js/scene.js.
   ========================================================================= */

.d-demo{width:100%;max-width:520px}
@media(min-width:940px){.d-demo{max-width:none;justify-self:end}}

/* Блоки лежат в обычном потоке, без абсолютного позиционирования: нижний
   край окна чата — это как раз подтверждённая карточка, накрывать её вторым
   слоем нельзя. Глубину даёт не нахлёст, а ступенчатая ширина, тени и
   размытый силуэт под пачкой сообщений. Высоту сцены держит reserve(). */
.d-stage{position:relative}
/* Окно во всю колонку; ступенчатость даёт пачка сообщений под ним. */

/* ============================ Окно чата ================================== */
.d-win{background:var(--surface);border:1px solid var(--border);
  border-radius:var(--radius);overflow:hidden;box-shadow:var(--shadow-2);
  opacity:0;transform:translateY(14px) scale(.985);
  transition:opacity 340ms var(--ease-enter),transform 340ms var(--ease-enter)}
.d-win.on{opacity:1;transform:none}

.d-head{display:flex;align-items:center;gap:var(--s2);padding:10px var(--s4);
  border-bottom:1px solid var(--border);background:var(--surface)}
.d-head-t{font-size:15px;font-weight:600}
.d-head-s{margin-left:auto;font-size:13px;color:var(--fg-muted);white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis}

/* Поток сообщений: высота окна фиксирована, трек прижат к низу, старое
   уходит под верхний край — как в настоящем чате. */
.d-chat{position:relative;height:208px;background:var(--sand);overflow:hidden}
.d-chat::after{content:"";position:absolute;top:0;left:0;right:0;height:28px;z-index:2;
  pointer-events:none;
  background:linear-gradient(var(--sand) 25%,rgba(243,237,228,0))}
.d-track{position:absolute;left:0;right:0;bottom:0;z-index:1;
  padding:0 var(--s4) var(--s3);transition:transform 340ms var(--ease-out)}
.d-m{display:none}
.d-m.on{display:block}
/* Индикатор набора не исчезает в один кадр: `leaving` даёт ему 160 мс на
   уход, и только потом снимается `on` (display нельзя анимировать). Иначе
   стык «печатает… → ответ» читается как склейка, а не как замена. */
.d-m.leaving{opacity:0;filter:blur(3px);
  transition:opacity 160ms var(--ease-in-out),filter 160ms var(--ease-in-out)}
.d-row{display:flex;align-items:flex-end;gap:10px;margin-top:var(--s2)}
.d-row-out{justify-content:flex-end}

.d-av{width:28px;height:28px;border-radius:50%;flex:none;margin-bottom:1px;
  display:flex;align-items:center;justify-content:center;
  font-size:12px;font-weight:700;user-select:none}
.d-av-bot{background:var(--accent);color:#fff}
.d-av-cl{background:var(--sand);color:var(--fg-muted);border:1px solid var(--border)}
.d-head .d-av{margin:0}

/* Входящее — белое слева; исходящее тренера — тёплая плашка справа */
.d-b{position:relative;flex:0 1 auto;min-width:0;
  background:var(--surface);border:1px solid var(--border);
  border-radius:var(--radius-lg);border-bottom-left-radius:6px;padding:8px 12px}
.d-b p{margin:0;font-size:14px;line-height:1.45;color:var(--fg)}
.d-b p + p{margin-top:2px}
.d-b-out{background:var(--accent-soft);border-color:var(--accent-line);
  border-bottom-left-radius:var(--radius-lg);border-bottom-right-radius:6px}

/* --------------------------- голосовое ---------------------------------- */
.d-b-voice{padding:8px 12px 9px}
.d-voice{display:flex;align-items:center;gap:10px}
.d-vplay{width:26px;height:26px;flex:none;border-radius:50%;
  background:var(--accent);color:#fff;display:flex;align-items:center;justify-content:center}
.d-vplay svg{width:11px;height:11px;margin-left:1px}
.d-wave{display:flex;align-items:center;gap:2px;height:22px;flex:1 1 auto;min-width:0}
/* Столбик волны: высота задана инлайновой --h, чтобы рисунок был неровным,
   как настоящая дорожка, и не требовал двадцати четырёх классов. */
.d-wave i{display:block;width:2px;flex:1 1 2px;max-width:3px;border-radius:2px;
  background:var(--accent-dark);opacity:.55;
  height:calc(4px + var(--h) * 18px)}
.d-vtime{flex:none;font-size:12px;font-weight:600;color:var(--accent-dark);
  font-variant-numeric:tabular-nums}

/* Расшифровка раскрывается под дорожкой: сначала слышно, потом разобрано */
.d-vwrap{display:grid;grid-template-rows:0fr;
  transition:grid-template-rows 400ms var(--e-grow)}
.d-vwrap.on{grid-template-rows:1fr}
.d-vclip{overflow:hidden;min-height:0}
.d-vtext{display:block;margin-top:7px;padding-top:7px;
  border-top:1px solid var(--accent-line);
  font-size:13px;line-height:1.42;color:var(--fg-muted);
  opacity:0;transform:translateY(3px);
  transition:opacity 240ms 60ms var(--ease-out),transform 240ms 60ms var(--ease-out)}
.d-vwrap.on .d-vtext{opacity:1;transform:none}
.d-vtext b{display:block;font-size:11px;font-weight:700;text-transform:uppercase;
  letter-spacing:.06em;color:var(--fg-muted);margin-bottom:2px}

/* ------------------------- индикатор разбора ---------------------------- */
.d-b-typing{display:flex;align-items:center;gap:5px;padding:12px}
.d-dot{width:6px;height:6px;border-radius:50%;background:var(--fg-faint);
  animation:d-dot 1200ms var(--ease-in-out) infinite}
.d-dot:nth-child(2){animation-delay:160ms}
.d-dot:nth-child(3){animation-delay:320ms}
@keyframes d-dot{
  0%,60%,100%{opacity:.35;transform:translateY(0)}
  30%{opacity:1;transform:translateY(-3px)}
}

/* --------------------- карточка на подтверждение ------------------------ */
/* Бот правит своё же сообщение — так это и работает в Telegram. Оба текста
   лежат в одной ячейке грида: подмена идёт на месте, высота держится по
   длинному из них, окно не дёргается. */
.d-card{max-width:100%}
.d-swapmsg{display:grid}
.d-swapmsg>div{grid-area:1/1;
  transition:opacity 200ms var(--ease-out),transform 200ms var(--ease-out),
             filter 200ms var(--ease-out)}
.d-msg-a{opacity:0;transform:translateY(4px);filter:blur(3px)}
.d-card.confirmed .d-msg-q{opacity:0;transform:translateY(-4px);filter:blur(3px)}
.d-card.confirmed .d-msg-a{opacity:1;transform:none;filter:blur(0);transition-delay:60ms}

/* Кнопки уходят вместе со строкой — карточка становится записью в истории */
.d-swapwrap{display:grid;grid-template-rows:1fr;
  transition:grid-template-rows 400ms 40ms var(--e-grow)}
.d-swapclip{overflow:hidden;min-height:0}
.d-swap{display:flex;align-items:center;gap:6px;padding-top:9px;
  transition:opacity 160ms var(--ease-out),transform 160ms var(--ease-out),
             filter 160ms var(--ease-out)}
.d-card.confirmed .d-swapwrap{grid-template-rows:0fr}
.d-card.confirmed .d-swap{opacity:0;transform:translateY(3px);filter:blur(3px)}

.d-btn{display:inline-flex;align-items:center;gap:5px;padding:5px 13px;
  border-radius:var(--radius-sm);background:var(--surface);
  border:1px solid var(--border-strong);font-size:13px;font-weight:600;color:var(--fg);
  transition:background-color 140ms var(--ease-out),border-color 140ms var(--ease-out),
             color 140ms var(--ease-out),transform 418ms var(--e-press)}
.d-btn.hover{background:var(--sand);border-color:var(--fg-faint)}
.d-btn.press{background:var(--accent-dark);border-color:var(--accent-dark);color:#fff;
  transform:scale(.94)}

/* ===================== Акт 3: сообщения клиентам ========================= */
/* Ни окна, ни рамки: другая плоскость — другой разговор. */
.d-out{margin-top:var(--s5)}
.d-outcap{display:flex;align-items:center;gap:var(--s2);
  font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;
  color:var(--fg-muted);margin-bottom:var(--s3);
  opacity:0;transition:opacity 640ms var(--ease-enter)}
.d-outcap.on{opacity:1}
.d-outcap svg{width:14px;height:14px;flex:none;color:var(--accent);opacity:.9}

.d-outstack{position:relative}
/* Силуэт: та же вёрстка, статичное размытие, меняется только прозрачность.
   Перехода filter в сцене нет — он даёт артефакты по краям. */
/* До акта 3 силуэта НЕТ. Раньше он лежал под окном с opacity:.32 все первые
   8.5 с и читался как незагрузившийся блок: контента поверх него в это время
   не было вовсе. Теперь он проявляется вместе с подписью «Дальше он пишет за
   тебя» (класс `pre`) и служит пред-тенью приходящих пузырей, а `lit` его
   гасит. Виден ~1.5 с — ровно там, где осмыслен. */
.d-oghost{position:absolute;inset:0;z-index:-1;pointer-events:none;
  filter:blur(9px);opacity:0;transition:opacity 320ms var(--ease-out)}
.d-outstack.pre .d-oghost{opacity:.32}
.d-outstack.lit .d-oghost{opacity:0;transition-duration:520ms}
.d-oghost .d-obb{box-shadow:none}

.d-ob{position:relative;opacity:0;transform:translateY(10px) scale(.985);
  transition:opacity 420ms var(--ease-enter),transform 420ms var(--ease-enter)}
.d-ob.on{opacity:1;transform:none}
.d-ob + .d-ob{margin-top:9px}
/* Ближний пузырь крупнее и висит выше — перспектива держится на тени */
.d-ob-1{z-index:1;width:86%;margin-left:0}
.d-ob-2{z-index:3;width:92%;margin-left:8%}
.d-ob-3{z-index:2;width:100%;margin-left:0}

.d-obhead{display:flex;align-items:center;gap:var(--s2);margin-bottom:5px;padding-left:2px}
.d-obto{font-size:13px;font-weight:700;color:var(--fg)}
.d-tag{margin-left:auto;display:inline-flex;align-items:center;gap:4px;
  padding:2px 9px;border-radius:var(--radius-pill);
  background:var(--sand);border:1px solid var(--border);
  font-size:11.5px;font-weight:600;color:var(--fg-muted);white-space:nowrap}
.d-tag svg{width:11px;height:11px;flex:none}
/* Зелёным помечено только то, что действительно уходит без тебя */
.d-tag-auto{background:var(--ok-soft);border-color:var(--ok-soft);color:var(--ok)}
.d-tag-wait{background:var(--accent-soft);border-color:var(--accent-line);
  color:var(--accent-dark)}

.d-obb{background:var(--surface);border:1px solid var(--border);
  border-radius:var(--radius-lg);padding:10px 13px;box-shadow:var(--shadow-2)}
.d-obb p{margin:0;font-size:14.5px;line-height:1.45;color:var(--fg)}
.d-obb p + p{margin-top:6px}
.d-ob-2 .d-obb{box-shadow:var(--shadow-3)}
.d-ob-1 .d-obb p{font-size:14px}
/* Строка «почему» — это то, что бот говорит ТЕБЕ, а не клиенту */
.d-obwhy{font-size:12.5px;color:var(--fg-muted);padding-bottom:6px;
  border-bottom:1px solid var(--border)}
.d-obb .d-obwhy + p{margin-top:7px}
/* Черновик ждёт нажатия: пунктир и кнопки на месте */
.d-ob-3 .d-obb{border-style:dashed;border-color:var(--border-strong)}
.d-obact{display:flex;gap:6px;margin-top:9px;padding-top:8px;
  border-top:1px solid var(--border)}
.d-btn-send{background:var(--sand)}

/* ============================== Курсор =================================== */
/* Курсор подводится к кнопке и жмёт, чтобы смена состояния читалась как
   чей-то ответ. Сперва он идёт к «Изменить» и там задерживается: бот
   спрашивает, и у человека есть настоящий выбор — это часть продукта. */
.d-cursor{position:absolute;left:0;top:0;z-index:6;width:22px;height:22px;
  pointer-events:none;opacity:0;
  transition:opacity 700ms var(--ease-in-out),transform 640ms var(--ease-enter)}
.d-cursor svg{width:22px;height:22px;display:block;overflow:visible}
.d-cursor.on{opacity:1}
.d-cursor.tap{transition:opacity 700ms var(--ease-in-out),transform 220ms var(--ease-out)}
.d-cursor::after{content:"";position:absolute;left:-4px;top:-4px;width:26px;height:26px;
  border-radius:50%;border:2px solid var(--accent-bright);opacity:0;transform:scale(.4)}
.d-cursor.ring::after{animation:d-ring 420ms var(--ease-out) forwards}
@keyframes d-ring{
  0%{opacity:.85;transform:scale(.4)}
  100%{opacity:0;transform:scale(1.5)}
}

/* =========================== Кнопка повтора ============================== */
.d-replay{display:inline-flex;align-items:center;gap:var(--s2);min-height:44px;
  padding:0 var(--s4);margin-top:var(--s5);
  background:transparent;border:1px solid var(--border);border-radius:10px;
  font-family:inherit;font-size:14px;font-weight:600;color:var(--fg-muted);cursor:pointer;
  opacity:0;visibility:hidden;transform:translateY(8px);
  transition:opacity 560ms var(--ease-in-out),transform 560ms var(--ease-in-out),
             visibility 560ms,border-color 180ms var(--ease-out),color 180ms var(--ease-out)}
.d-replay.on{opacity:1;visibility:visible;transform:none;
  transition:opacity 620ms var(--ease-enter),transform 620ms var(--ease-enter),
             visibility 620ms,border-color 180ms var(--ease-out),color 180ms var(--ease-out)}
.d-replay svg{width:16px;height:16px;flex:none}
@media(hover:hover) and (pointer:fine){
  .d-replay:hover{border-color:var(--border-strong);color:var(--fg)}
}

/* ====================== Служебные состояния сцены ======================== */
/* Замер высоты идёт с выключенными переходами: иначе меряется полпути. */
.d-noanim *{transition:none!important;animation:none!important}
/* Когда всё показано, фильтры снимаются полностью: иначе браузер держит
   растеризованный слой и по краям остаются светлые прямоугольники. */
.d-clear .d-oghost{filter:none}
.d-fade .d-win,.d-fade .d-ob,.d-fade .d-outcap,.d-fade .d-replay,.d-fade .d-cursor,
.d-fade .d-oghost{opacity:0;transition:opacity 400ms var(--ease-in-out)}

/* ============================ Адаптив ==================================== */
@media(min-width:940px) and (max-width:1059px){
  .d-chat{height:200px}
}
@media(max-width:520px){
  .d-chat{height:236px}
  .d-head{padding:9px var(--s3)}
  .d-track{padding:0 var(--s3) 10px}
  .d-av{width:26px;height:26px;font-size:11.5px}
  .d-b p{font-size:13.5px}
  .d-swap{flex-wrap:wrap}
  .d-ob-1,.d-ob-2,.d-ob-3{width:100%;margin-left:0}
  .d-obb p{font-size:14px}
  .d-tag{font-size:11px;padding:2px 7px}
  .d-obhead{flex-wrap:wrap;gap:6px}
  .d-tag{margin-left:0}
}

/* Пометка на уже применённой карточке: строки «✅ проведено…» бот отдаёт
   ПОСЛЕ нажатия «Ок» (extraction.apply_actions), а не в ответ на реплику.
   Без этой подписи первый обмен сцены обещал бы разбор без подтверждения. */
.d-conf{margin-top:5px;font-size:11.5px;color:var(--fg-muted);opacity:.85}

/* Сноска под стопкой исходящих: без Business и без подключённого клиента
   автоотправки нет — Сетка приносит текст, отправляет тренер. */
.d-outnote{margin:var(--s4) 0 0;font-size:14px;line-height:1.5;
  color:var(--fg-muted);max-width:46ch;
  opacity:0;transition:opacity 560ms var(--ease-enter)}
.d-outstack.lit ~ .d-outnote,
.d-noanim .d-outnote{opacity:1}
