/* HyperKit — Scrolling Text Reveal
 *
 * The text element has class `.hk-str` and (until JS runs) shows its plain
 * content fully visible. As soon as JS finishes the split + initial state
 * pass, it adds `.hk-str--ready` and the units start in their hidden state.
 *
 * The `[data-hk-str]:not(.hk-str--ready)` rule below hides the text in
 * that brief pre-mount window, so users don't see a flash of fully-visible
 * text before the animation initial state takes over. (We err on the side
 * of hiding rather than flashing — a moment of nothing is less jarring
 * than a flash of FOUC.)
 */

.hk-str-wrap {
	width: 100%;
}

.hk-str-wrap--sticky {
	position: sticky;
	/* `top` comes from the widget's sticky_top control via Elementor selector. */
	z-index: 1;
}

.hk-str {
	margin: 0;
}

/* Pre-mount: keep text invisible to avoid a flash before the animation
 * initial state can take over. The .hk-str--ready class is added by JS
 * after split/measure/initial-apply complete. */
.hk-str[data-hk-str]:not(.hk-str--ready) {
	visibility: hidden;
}

/* Each word is a span — display:inline-block lets it transform without
 * breaking word-level line wrapping. We DON'T inline-block the
 * character-level units because that breaks justified text and can change
 * line breaks. The JS sets display:inline-block lazily on the actual
 * units it animates with translate. */
.hk-str-w {
	display: inline-block;
}

/* Whitespace handling — the wrapper preserves spaces between words via
 * plain text nodes, but we want to make sure word-spans don't
 * accidentally collapse their internal whitespace. */
.hk-str-w,
.hk-str-u {
	white-space: pre;
}

/* Reduced motion: snap to final state, no transitions. */
@media (prefers-reduced-motion: reduce) {
	.hk-str-w,
	.hk-str-u {
		filter: none !important;
		transform: none !important;
		opacity: 1 !important;
	}
}
