/* Loading state for tool forms ("Dot verse"). See inc/form-loader.php.
 *
 * assets/js/form-loader.js sets these classes on .mwai-form-output-container:
 *   ws-generating  waiting, nothing to read yet: a shimmering label over six lines of dots
 *   ws-handoff     the first words just arrived: the loader fades out
 *   ws-streaming   words are arriving: the box keeps the loader's height, so nothing jumps
 * The label is the reply box's ::before. The dots are a canvas (.ws-dot-verse) that the
 * script adds to the reply box and draws while it waits, then removes; the two colors below
 * are its only settings here. Image tools (body.ws-dark) have a loader of their own, so the
 * loader rules here skip them; see the note at the end. */

body .mwai-form-output-container {
	--ws-loader-h: 207px;  /* 24 padding + 20 label + 16 gap + 123 dot lines + 24 padding */
	--ws-loader-label: "Writing…";
	--ws-loader-text: var(--ws-gray-500);
	--ws-loader-text-hi: var(--ws-gray-900);
	--ws-loader-dot: color-mix(in srgb, var(--ws-gray-200) 80%, var(--ws-gray-300));  /* at rest */
	--ws-loader-dot-hi: var(--ws-gray-700);  /* the ink at the crest of the wave */
}

@keyframes ws-shimmer {
	from { background-position: 100% 0; }
	to   { background-position: 0 0; }
}
@keyframes ws-loader-in {
	from { opacity: 0; transform: translateY(6px); }
	to   { opacity: 1; transform: none; }
}
@keyframes ws-loader-out {
	from { opacity: 1; filter: none; }
	to   { opacity: 0; filter: blur(4px); }
}

/* The box opens to the loader's height at once and holds it until the reply is done, then
 * eases to the reply's own height. */
body:not(.ws-dark) .mwai-form-output-container .mwai-form-output {
	transition: min-height 320ms var(--ws-ease-out);
}
body:not(.ws-dark) .mwai-form-output-container:is(.ws-generating, .ws-handoff, .ws-streaming) .mwai-form-output {
	position: relative;
	min-height: var(--ws-loader-h);
}
/* Nothing to read yet, so AI Engine's blinking cursor steps aside for the loader. */
body:not(.ws-dark) .mwai-form-output-container.ws-generating .mwai-form-output > :not(.ws-dot-verse) { visibility: hidden; }

/* Label: the words shimmer, a light band passing through them. */
body:not(.ws-dark) .mwai-form-output-container:is(.ws-generating, .ws-handoff) .mwai-form-output::before {
	content: var(--ws-loader-label);
	position: absolute;
	top: var(--ws-space-5);
	left: var(--ws-space-5);
	pointer-events: none;
	font: 600 var(--ws-text-small)/20px var(--ws-font-sans);
	color: transparent;
	background-image: linear-gradient(90deg, var(--ws-loader-text) 0 40%, var(--ws-loader-text-hi) 50%, var(--ws-loader-text) 60% 100%);
	background-size: 300% 100%;
	-webkit-background-clip: text;
	background-clip: text;
	animation: ws-loader-in 400ms var(--ws-ease-out) both, ws-shimmer 2s linear infinite;
}
/* Dots: six lines like a short verse, a wave of ink rippling through them. The canvas is
 * 2px taller than the lines on each side, so it starts 2px above the 16px gap. The script
 * reads its two colors from `color` (at rest) and `border-color` (the ink); there's no
 * border to see. */
body:not(.ws-dark) .mwai-form-output-container .mwai-form-output > .ws-dot-verse {
	position: absolute;
	top: calc(var(--ws-space-5) + 20px + var(--ws-space-4) - 2px);
	left: var(--ws-space-5);
	width: calc(100% - 2 * var(--ws-space-5));
	height: 128px;
	margin: 0;
	pointer-events: none;
	color: var(--ws-loader-dot);
	border: 0 solid var(--ws-loader-dot-hi);
	animation: ws-loader-in 400ms var(--ws-ease-out) both;
}
/* The first words arrived: the loader dissolves over them. */
body:not(.ws-dark) .mwai-form-output-container.ws-handoff .mwai-form-output::before {
	animation: ws-loader-out 450ms ease-out forwards, ws-shimmer 2s linear infinite;
}
body:not(.ws-dark) .mwai-form-output-container.ws-handoff .mwai-form-output > .ws-dot-verse {
	animation: ws-loader-out 450ms ease-out forwards;
}

/* Streaming cursor: a slim caret that fades in and out, instead of AI Engine's 8px block
 * that blinks on and off. AI Engine sets the block's look inline; an animation's values
 * beat inline styles, so the keyframes carry the 2px width as well as the fade. */
@keyframes ws-caret {
	0%, 100% { opacity: 1; border-left-width: 2px; }
	50%      { opacity: 0.15; border-left-width: 2px; }
}
@keyframes ws-caret-still {
	from, to { opacity: 1; border-left-width: 2px; }
}
body .mwai-form-output-container .mwai-form-output span[style*="border-left"] {
	animation: ws-caret 1s ease-in-out infinite;
}

/* Submit button while the form runs: AI Engine puts a spinner and a timer in the button and
 * hides the label, but ai-engine.css keeps disabled labels visible (for the waiting state),
 * so the spinner sat on top of the words. The label hides again while it runs. Only forms on
 * AI Engine's ChatGPT theme draw the spinner: four old tools (Image Generator, Photo Roast,
 * Product Review Writer, Video Ad Writer) have no theme, so they keep the label and timer. */
body .mwai-form-container.mwai-chatgpt-theme :is(.mwai-form-submit, .mwai-form-reset).mwai-loading button[disabled] span { opacity: 0; }

@media (prefers-reduced-motion: reduce) {
	body:not(.ws-dark) .mwai-form-output-container .mwai-form-output { transition: none; }
	/* The label and dots hold still (the script draws one still frame of dots). */
	body:not(.ws-dark) .mwai-form-output-container:is(.ws-generating, .ws-handoff) .mwai-form-output::before,
	body:not(.ws-dark) .mwai-form-output-container .mwai-form-output > .ws-dot-verse { animation: none; }
	body .mwai-form-output-container .mwai-form-output span[style*="border-left"] { animation: ws-caret-still 1s infinite; }
}

/* ── Image tools (body.ws-dark, see inc/dark-theme.php) ──
 * Image tools have their own loader ("Moonlight": inc/image-loader.php,
 * assets/css/image-loader.css, assets/js/image-loader.js). Every loader rule above starts
 * with body:not(.ws-dark), so this file draws nothing on those pages: no label, no
 * height on the output box, no hidden children, no fade. form-loader.js still sets its
 * classes there, and nothing uses them, and it never adds the dot canvas there. The caret
 * and the submit-label rules still apply. */
