<script lang="ts">
	// Renders streamed model output token-by-token with a fade-in, the way the
	// Claude web UI does: each arriving token materialises instead of snapping
	// in. Every token is its own keyed span, so Svelte mounts only the newest
	// one per update and its fade plays exactly once — re-rendering the whole
	// Markdown string on each token (what {@html} does) would replay every
	// element's animation and flicker.
	//
	// This is plain text on purpose: it is the transient streaming view. The
	// caller swaps to the sanitizing <Markdown> renderer once the turn settles,
	// so formatting still arrives — just at the end, without mid-stream reflow.
	let { tokens }: { tokens: string[] } = $props();
</script>

<div class="streaming-text text-sm break-words whitespace-pre-wrap">
	{#each tokens as token, i (i)}<span class="tok">{token}</span>{/each}
</div>

<style>
	@keyframes pb-token-in {
		from {
			opacity: 0;
			filter: blur(3px);
		}
		to {
			opacity: 1;
			filter: blur(0);
		}
	}
	.tok {
		animation: pb-token-in 0.55s ease-out both;
	}
	/* Motion is decorative; the settled text is the same either way. */
	@media (prefers-reduced-motion: reduce) {
		.tok {
			animation: none;
		}
	}
</style>
