/* ─────────────────────────────────────────────
   animations.css — Keyframes & transition utilities
   
   Tasteful, minimal motion. Opacity + transform only.
   No flashy stuff — think Dieter Rams, not Disneyland.
   ───────────────────────────────────────────── */


/* ─── Thinking Indicator (three dots) ─── */

@keyframes thinking-pulse {
  0%, 80%, 100% {
    opacity: 0.15;
    transform: scale(0.8);
  }
  40% {
    opacity: 1;
    transform: scale(1);
  }
}

#thinking-indicator {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: var(--space-3) var(--space-4);
}

#thinking-indicator:not([hidden]) {
  display: flex;
}

.thinking-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--color-text-3);
  animation: thinking-pulse 1.4s ease-in-out infinite;
}

.thinking-dot:nth-child(2) {
  animation-delay: 0.16s;
}

.thinking-dot:nth-child(3) {
  animation-delay: 0.32s;
}


/* ─── Fade In (messages, thread items) ─── */

@keyframes fade-in {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.anim-fade-in {
  animation: fade-in var(--duration-normal) var(--ease-out) both;
}


/* ─── Fade In — staggered (for list items loaded in batch) ─── */

.anim-stagger > * {
  animation: fade-in var(--duration-normal) var(--ease-out) both;
}

.anim-stagger > *:nth-child(1)  { animation-delay: 0ms; }
.anim-stagger > *:nth-child(2)  { animation-delay: 30ms; }
.anim-stagger > *:nth-child(3)  { animation-delay: 60ms; }
.anim-stagger > *:nth-child(4)  { animation-delay: 90ms; }
.anim-stagger > *:nth-child(5)  { animation-delay: 120ms; }
.anim-stagger > *:nth-child(6)  { animation-delay: 150ms; }
.anim-stagger > *:nth-child(7)  { animation-delay: 180ms; }
.anim-stagger > *:nth-child(8)  { animation-delay: 210ms; }
.anim-stagger > *:nth-child(9)  { animation-delay: 240ms; }
.anim-stagger > *:nth-child(10) { animation-delay: 270ms; }
.anim-stagger > *:nth-child(n+11) { animation-delay: 300ms; }


/* ─── Slide In — from left (sidebar) ─── */

@keyframes slide-in-left {
  from {
    transform: translateX(-100%);
  }
  to {
    transform: translateX(0);
  }
}

@keyframes slide-out-left {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(-100%);
  }
}


/* ─── Slide In — from bottom (input bar elements, reply indicator) ─── */

@keyframes slide-in-up {
  from {
    opacity: 0;
    transform: translateY(100%);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes slide-out-down {
  from {
    opacity: 1;
    transform: translateY(0);
  }
  to {
    opacity: 0;
    transform: translateY(100%);
  }
}

.anim-slide-up {
  animation: slide-in-up var(--duration-normal) var(--ease-out) both;
}


/* ─── Backdrop fade ─── */

@keyframes backdrop-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@keyframes backdrop-out {
  from { opacity: 1; }
  to   { opacity: 0; }
}


/* ─── Sync Spinner ─── */

@keyframes spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

.anim-spin {
  animation: spin 0.8s linear infinite;
}


/* ─── Pulse — subtle attention draw (token counter warning, etc.) ─── */

@keyframes pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.5; }
}

.anim-pulse {
  animation: pulse 2s ease-in-out infinite;
}


/* ─── Streaming text cursor blink ─── */

@keyframes cursor-blink {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0; }
}

.streaming-cursor::after {
  content: "▌";
  color: var(--color-text-3);
  animation: cursor-blink 0.8s steps(1) infinite;
  margin-inline-start: 1px;
}


/* ─── Scale in — dialogs, dropdowns ─── */

@keyframes scale-in {
  from {
    opacity: 0;
    transform: scale(0.95);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}

.anim-scale-in {
  animation: scale-in var(--duration-fast) var(--ease-out) both;
}


/* ─── Token counter ring fill ─── */

@keyframes ring-fill {
  from {
    stroke-dashoffset: var(--ring-from, 100.53);
  }
  to {
    stroke-dashoffset: var(--ring-to, 100.53);
  }
}

#token-counter-ring {
  transition: stroke-dashoffset var(--duration-slow) var(--ease-out),
              stroke var(--duration-normal) ease;
}


/* ─── Reduced motion — respect user preference ─── */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }

  .streaming-cursor::after {
    animation: none;
    opacity: 1;
  }
}