/* Дополнительные эффекты активности Stream и готовности ответа.

   Отдельная таблица, а не врезка в общий styles.css: набор эффектов растёт
   независимо от оболочки, и держать их рядом дешевле для правок. Все состояния
   строятся на --accent, поэтому работают в любой теме. */

/* ============================================================== Дыхание ===
   Ни полосы, ни точки: карточка едва заметно светлеет и гаснет. Замечается
   боковым зрением и не мешает читать соседние строки. */
:root[data-stream-status-effect="breath"] .task-workspace-item[data-running]::after,
:root[data-stream-status-effect="breath"] .stream-tab[data-running] .stream-tab-status-layer::after,
:root[data-stream-status-effect="breath"]
  .task-workspace-item[data-unread]:not([data-running])::after,
:root[data-stream-status-effect="breath"] .stream-tab[data-answer-ready] .stream-tab-status-layer::after {
  background: var(--accent);
  border-radius: inherit;
  content: "";
  inset: 0;
  opacity: 0;
  pointer-events: none;
  position: absolute;
}

:root[data-stream-status-effect="breath"] .task-workspace-item[data-running]::after,
:root[data-stream-status-effect="breath"] .stream-tab[data-running] .stream-tab-status-layer::after {
  animation: stream-breath 3.5s ease-in-out infinite;
}

/* Готовность — один глубокий вдох и остановка на светлом. */
:root[data-stream-status-effect="breath"]
  .task-workspace-item[data-unread][data-answer-arrived]:not([data-running])::after,
:root[data-stream-status-effect="breath"]
  .stream-tab[data-answer-ready][data-answer-arrived] .stream-tab-status-layer::after {
  animation: stream-breath-ready 1.1s ease-out forwards;
}

:root[data-stream-status-effect="breath"]
  .task-workspace-item[data-unread]:not([data-running], [data-answer-arrived])::after,
:root[data-stream-status-effect="breath"]
  .stream-tab[data-answer-ready]:not([data-answer-arrived]) .stream-tab-status-layer::after {
  opacity: 0.28;
}

@keyframes stream-breath {
  0%, 100% { opacity: 0.05; }
  50% { opacity: 0.24; }
}

@keyframes stream-breath-ready {
  0% { opacity: 0.06; }
  55% { opacity: 0.46; }
  100% { opacity: 0.28; }
}

/* ================================================================= Нить ===
   По левой кромке наматывается тонкая нить, а готовность сматывает её в узел:
   начало и конец работы связаны одной формой. */
:root[data-stream-status-effect="thread"] .task-workspace-item[data-running]::after,
:root[data-stream-status-effect="thread"] .stream-tab[data-running] .stream-tab-status-layer::after,
:root[data-stream-status-effect="thread"]
  .task-workspace-item[data-unread]:not([data-running])::after,
:root[data-stream-status-effect="thread"] .stream-tab[data-answer-ready] .stream-tab-status-layer::after {
  background: linear-gradient(180deg, transparent, var(--accent) 24%, var(--accent) 76%, transparent);
  box-shadow: 0 0 14px color-mix(in srgb, var(--accent) 62%, transparent),
    18px 0 26px -12px color-mix(in srgb, var(--accent) 52%, transparent);
  content: "";
  inset: 0 auto 0 0;
  pointer-events: none;
  position: absolute;
  width: 7px;
}

:root[data-stream-status-effect="thread"] .task-workspace-item[data-running]::after,
:root[data-stream-status-effect="thread"] .stream-tab[data-running] .stream-tab-status-layer::after {
  animation: stream-thread-wind 2.9s ease-in-out infinite;
  transform-origin: top center;
}

:root[data-stream-status-effect="thread"]
  .task-workspace-item[data-unread]:not([data-running])::after,
:root[data-stream-status-effect="thread"] .stream-tab[data-answer-ready] .stream-tab-status-layer::after {
  background: var(--accent);
  border-radius: 0 4px 4px 0;
  inset: 18% auto 18% 0;
  width: 8px;
}

@keyframes stream-thread-wind {
  0% { transform: scaleY(0.05); }
  55% { transform: scaleY(1); }
  100% { transform: scaleY(0.05); }
}

/* ============================================================== Осадок ===
   Заливка растёт снизу вверх, пока идёт ход, и остаётся полной у готового
   ответа: карточка сама показывает, что работа была длинной. */
:root[data-stream-status-effect="sediment"] .task-workspace-item[data-running]::after,
:root[data-stream-status-effect="sediment"] .stream-tab[data-running] .stream-tab-status-layer::after,
:root[data-stream-status-effect="sediment"]
  .task-workspace-item[data-unread]:not([data-running])::after,
:root[data-stream-status-effect="sediment"] .stream-tab[data-answer-ready] .stream-tab-status-layer::after {
  background:
    linear-gradient(0deg, color-mix(in srgb, var(--accent) 92%, transparent) 0 62%, var(--accent) 82%, transparent);
  border-radius: inherit;
  content: "";
  inset: 0;
  opacity: 0.34;
  pointer-events: none;
  position: absolute;
  transform-origin: bottom center;
}

:root[data-stream-status-effect="sediment"] .task-workspace-item[data-running]::after,
:root[data-stream-status-effect="sediment"] .stream-tab[data-running] .stream-tab-status-layer::after {
  animation: stream-sediment-rise 4.2s ease-in-out infinite;
}

:root[data-stream-status-effect="sediment"]
  .task-workspace-item[data-unread]:not([data-running])::after,
:root[data-stream-status-effect="sediment"] .stream-tab[data-answer-ready] .stream-tab-status-layer::after {
  opacity: 0.5;
  transform: scaleY(1);
}

@keyframes stream-sediment-rise {
  0% { transform: scaleY(0.08); }
  70% { transform: scaleY(0.9); }
  100% { transform: scaleY(0.08); }
}

/* ================================================================ Эхо ===
   Во время хода не движется ничего, только точка. Кольцо расходится ровно
   тогда, когда появился ответ: движение означает новость, а не занятость. */
:root[data-stream-status-effect="echo"] .task-workspace-item[data-running]::after,
:root[data-stream-status-effect="echo"] .stream-tab[data-running] .stream-tab-status-layer::after {
  animation: stream-echo-dot 2.6s ease-in-out infinite;
  background: var(--accent);
  border-radius: 50%;
  box-shadow: 0 0 0 6px color-mix(in srgb, var(--accent) 24%, transparent),
    0 0 20px 4px color-mix(in srgb, var(--accent) 62%, transparent);
  content: "";
  height: 12px;
  inset: auto 0.6rem 0.6rem auto;
  pointer-events: none;
  position: absolute;
  width: 12px;
}

@keyframes stream-echo-dot {
  0%, 100% { opacity: 0.55; transform: scale(0.86); }
  50% { opacity: 1; transform: scale(1.06); }
}

:root[data-stream-status-effect="echo"]
  .task-workspace-item[data-unread]:not([data-running])::after,
:root[data-stream-status-effect="echo"] .stream-tab[data-answer-ready] .stream-tab-status-layer::after {
  border: 2px solid var(--accent);
  border-radius: inherit;
  box-shadow: 0 0 12px color-mix(in srgb, var(--accent) 40%, transparent);
  content: "";
  inset: 0;
  pointer-events: none;
  position: absolute;
}

:root[data-stream-status-effect="echo"]
  .task-workspace-item[data-unread][data-answer-arrived]:not([data-running])::after,
:root[data-stream-status-effect="echo"]
  .stream-tab[data-answer-ready][data-answer-arrived] .stream-tab-status-layer::after {
  animation: stream-echo-ring 1.15s ease-out 3;
}

@keyframes stream-echo-ring {
  0% { opacity: 1; transform: scale(0.94); }
  100% { opacity: 0; transform: scale(1.13); }
}

/* Карточки вне окна не анимируются: при двух десятках идущих потоков это
   снимает всю фоновую отрисовку, не меняя вида видимой части списка. */
.task-workspace-item[data-stream-offscreen]::before,
.task-workspace-item[data-stream-offscreen]::after,
.stream-tab[data-stream-offscreen] .stream-tab-status-layer::before,
.stream-tab[data-stream-offscreen] .stream-tab-status-layer::after {
  animation-play-state: paused;
}

@media (prefers-reduced-motion: reduce) {
  :root[data-stream-status-effect="breath"] .task-workspace-item[data-running]::after,
  :root[data-stream-status-effect="breath"] .stream-tab[data-running] .stream-tab-status-layer::after,
  :root[data-stream-status-effect="thread"] .task-workspace-item[data-running]::after,
  :root[data-stream-status-effect="thread"] .stream-tab[data-running] .stream-tab-status-layer::after,
  :root[data-stream-status-effect="sediment"] .task-workspace-item[data-running]::after,
  :root[data-stream-status-effect="sediment"] .stream-tab[data-running] .stream-tab-status-layer::after,
  :root[data-stream-status-effect="echo"]
    .task-workspace-item[data-unread]:not([data-running])::after,
  :root[data-stream-status-effect="echo"] .stream-tab[data-answer-ready] .stream-tab-status-layer::after {
    animation: none;
  }

  :root[data-stream-status-effect="breath"] .task-workspace-item[data-running]::after,
  :root[data-stream-status-effect="breath"] .stream-tab[data-running] .stream-tab-status-layer::after {
    opacity: 0.2;
  }

  :root[data-stream-status-effect="thread"] .task-workspace-item[data-running]::after,
  :root[data-stream-status-effect="thread"] .stream-tab[data-running] .stream-tab-status-layer::after {
    transform: scaleY(1);
  }

  :root[data-stream-status-effect="sediment"] .task-workspace-item[data-running]::after,
  :root[data-stream-status-effect="sediment"] .stream-tab[data-running] .stream-tab-status-layer::after {
    transform: scaleY(0.55);
  }
}

/* ============================== Свёртка и ротация контекста на карточке ===
   Оба состояния статичные: ни одной анимации, только контур. Это надёжно
   читается при любом выбранном эффекте, потому что эффекты занимают
   псевдоэлементы, а контур — свойство самой карточки. */
.task-workspace-item[data-maintenance],
.stream-tab[data-maintenance] .stream-tab-status-layer {
  outline-offset: -3px;
}

.task-workspace-item[data-maintenance="compaction"],
.stream-tab[data-maintenance="compaction"] .stream-tab-status-layer {
  outline: 1px dashed color-mix(in srgb, var(--accent) 52%, transparent);
}

/* Ротация заметнее: она меняет тред, а не только сжимает историю. */
.task-workspace-item[data-maintenance="rotation"],
.stream-tab[data-maintenance="rotation"] .stream-tab-status-layer {
  outline: 2px double color-mix(in srgb, var(--accent) 78%, transparent);
}

/* ========================= «Подсвечивать панели Stream целиком» для новых ===
   Переключатель заливки меняет носитель эффекта: вместо кромки или точки тот
   же эффект занимает всю поверхность карточки. Формулы движения не меняются —
   меняются только геометрия слоя и его плотность. */

/* Дыхание и осадок уже занимают всю поверхность: в заливке они просто плотнее. */
:root[data-stream-status-style="fill"][data-stream-status-effect="breath"]
  .task-workspace-item[data-running]::after,
:root[data-stream-status-style="fill"][data-stream-status-effect="breath"]
  .stream-tab[data-running] .stream-tab-status-layer::after {
  animation-name: stream-breath-fill;
}

:root[data-stream-status-style="fill"][data-stream-status-effect="breath"]
  .task-workspace-item[data-unread][data-answer-arrived]:not([data-running])::after,
:root[data-stream-status-style="fill"][data-stream-status-effect="breath"]
  .stream-tab[data-answer-ready][data-answer-arrived] .stream-tab-status-layer::after {
  animation-name: stream-breath-ready-fill;
}

:root[data-stream-status-style="fill"][data-stream-status-effect="breath"]
  .task-workspace-item[data-unread]:not([data-running], [data-answer-arrived])::after,
:root[data-stream-status-style="fill"][data-stream-status-effect="breath"]
  .stream-tab[data-answer-ready]:not([data-answer-arrived]) .stream-tab-status-layer::after {
  opacity: 0.38;
}

@keyframes stream-breath-fill {
  0%, 100% { opacity: 0.09; }
  50% { opacity: 0.36; }
}

@keyframes stream-breath-ready-fill {
  0% { opacity: 0.12; }
  55% { opacity: 0.58; }
  100% { opacity: 0.38; }
}

:root[data-stream-status-style="fill"][data-stream-status-effect="sediment"]
  .task-workspace-item[data-running]::after,
:root[data-stream-status-style="fill"][data-stream-status-effect="sediment"]
  .stream-tab[data-running] .stream-tab-status-layer::after {
  opacity: 0.48;
}

:root[data-stream-status-style="fill"][data-stream-status-effect="sediment"]
  .task-workspace-item[data-unread]:not([data-running])::after,
:root[data-stream-status-style="fill"][data-stream-status-effect="sediment"]
  .stream-tab[data-answer-ready] .stream-tab-status-layer::after {
  opacity: 0.6;
}

/* Нить в заливке разворачивается в занавес: та же анимация по вертикали, но
   уже на всю ширину карточки. */
:root[data-stream-status-style="fill"][data-stream-status-effect="thread"]
  .task-workspace-item[data-running]::after,
:root[data-stream-status-style="fill"][data-stream-status-effect="thread"]
  .stream-tab[data-running] .stream-tab-status-layer::after,
:root[data-stream-status-style="fill"][data-stream-status-effect="thread"]
  .task-workspace-item[data-unread]:not([data-running])::after,
:root[data-stream-status-style="fill"][data-stream-status-effect="thread"]
  .stream-tab[data-answer-ready] .stream-tab-status-layer::after {
  background: linear-gradient(180deg, transparent, var(--accent) 34%, var(--accent) 66%, transparent);
  border-radius: inherit;
  box-shadow: none;
  inset: 0;
  opacity: 0.32;
  width: auto;
}

:root[data-stream-status-style="fill"][data-stream-status-effect="thread"]
  .task-workspace-item[data-unread]:not([data-running])::after,
:root[data-stream-status-style="fill"][data-stream-status-effect="thread"]
  .stream-tab[data-answer-ready] .stream-tab-status-layer::after {
  background: var(--accent);
  opacity: 0.38;
}

/* Эхо в заливке: во время хода панель едва подсвечена ровным светом вместо
   точки, а готовность даёт вспышку по всей поверхности вместо кольца. */
:root[data-stream-status-style="fill"][data-stream-status-effect="echo"]
  .task-workspace-item[data-running]::after,
:root[data-stream-status-style="fill"][data-stream-status-effect="echo"]
  .stream-tab[data-running] .stream-tab-status-layer::after {
  animation-name: stream-echo-dot-fill;
  background: var(--accent);
  border-radius: inherit;
  box-shadow: none;
  height: auto;
  inset: 0;
  width: auto;
}

@keyframes stream-echo-dot-fill {
  0%, 100% { opacity: 0.1; }
  50% { opacity: 0.26; }
}

:root[data-stream-status-style="fill"][data-stream-status-effect="echo"]
  .task-workspace-item[data-unread]:not([data-running])::after,
:root[data-stream-status-style="fill"][data-stream-status-effect="echo"]
  .stream-tab[data-answer-ready] .stream-tab-status-layer::after {
  background: var(--accent);
  border: 0;
  border-radius: inherit;
  inset: 0;
}

:root[data-stream-status-style="fill"][data-stream-status-effect="echo"]
  .task-workspace-item[data-unread][data-answer-arrived]:not([data-running])::after,
:root[data-stream-status-style="fill"][data-stream-status-effect="echo"]
  .stream-tab[data-answer-ready][data-answer-arrived] .stream-tab-status-layer::after {
  animation: stream-echo-fill 1.15s ease-out 2;
}

@keyframes stream-echo-fill {
  0% { opacity: 0.55; }
  100% { opacity: 0.14; }
}

@media (prefers-reduced-motion: reduce) {
  :root[data-stream-status-style="fill"][data-stream-status-effect="echo"]
    .task-workspace-item[data-unread]:not([data-running])::after,
  :root[data-stream-status-style="fill"][data-stream-status-effect="echo"]
    .stream-tab[data-answer-ready] .stream-tab-status-layer::after {
    animation: none;
    opacity: 0.3;
  }
}
