@layer components {
  /* Under the latest message; collapsed rather than removed, so screen readers keep the live region. */
  .typing-line {
    display: flex; align-items: center; gap: 9px; padding: 6px var(--gutter) 9px;
    font-size: var(--text-meta); line-height: 1.4; color: var(--muted-foreground);
  }
  .typing-line:not(.is-active) { height: 0; padding-block: 0; overflow: hidden; }
  .typing-dots { display: inline-flex; align-items: center; gap: 3px; }
  .typing-dots > span {
    width: 4px; height: 4px; border-radius: 999px; background: currentColor;
    animation: typing-dot 1.2s ease-in-out infinite;
  }
  .typing-dots > span:nth-child(2) { animation-delay: 0.2s; }
  .typing-dots > span:nth-child(3) { animation-delay: 0.4s; }
  /* A clipped animation still runs: collapsed, the dots stand still. */
  .typing-line:not(.is-active) .typing-dots > span { animation: none; }
  @keyframes typing-dot { 0%, 60%, 100% { opacity: 0.3; } 30% { opacity: 1; } }
  @media (prefers-reduced-motion: reduce) { .typing-dots > span { animation: none; opacity: 0.6; } }
}
