/* Text animations (see assets/js/text-fx.js). */

/* Blur Text: hidden until the script splits it; shown anyway after 1.5s if the script never runs. */
@media (prefers-reduced-motion: no-preference) {
	[data-fx="blur"]:not(.fx-blur), [data-fx="stroke"]:not(.fx-stroke) { opacity: 0; animation: fx-hold 0s 1.5s forwards; }
}
@keyframes fx-hold { to { opacity: 1; } }
.fx-blur { animation: none !important; opacity: 1; }
.fx-blur .fx-w { display: inline-block; opacity: 0; filter: blur(10px); transform: translateY(-.35em); will-change: transform, filter, opacity; }
.fx-blur.fx-in .fx-w { animation: fx-blur .75s cubic-bezier(.2, .8, .2, 1) both; animation-delay: calc(var(--fx-delay, 0ms) + min(var(--fx-i) * 90ms, 900ms)); }
@keyframes fx-blur {
	0% { opacity: 0; filter: blur(10px); transform: translateY(-.35em); }
	50% { opacity: .5; filter: blur(4px); transform: translateY(.05em); }
	100% { opacity: 1; filter: none; transform: none; }
}

/* Count Up: digits keep the same width while counting. */
.fx-count { display: inline-block; font-variant-numeric: tabular-nums; }

/* Scroll Reveal: words start dim and blurred; the script sets each word's opacity/blur from scroll. */
.fx-reveal .fx-w { display: inline; transition: opacity .12s linear, filter .12s linear; }

/* Shiny Text: a light sheen sweeps across navy text every 5s. */
@media (prefers-reduced-motion: no-preference) {
	[data-fx="shiny"] {
		background: linear-gradient(120deg, var(--iv-navy) 40%, #6FCBF2 50%, var(--iv-navy) 60%) 0 0 / 200% 100%;
		-webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; color: transparent;
		animation: fx-shine 5s linear infinite;
	}
	/* Keep the page's fade-up entrance and add the sheen. */
	html body [data-fx="shiny"] { animation: fx-shine 5s linear infinite; }
	html body [data-fx="shiny"].ivh-r1 { animation: ivh-up .7s var(--iv-ease) both, fx-shine 5s linear infinite; }
}
@keyframes fx-shine { 0% { background-position: 100% 0; } 100% { background-position: -100% 0; } }

/* Masked Heading: words slide up from their slots; an image (lightened so the
   heading stays readable on navy) shows through the letters and drifts slowly. */
@property --fx-pan { syntax: '<length>'; inherits: true; initial-value: 0px; }
.fx-mask { position: relative; }
.fx-mask .fx-mw { display: inline-block; overflow: hidden; vertical-align: bottom; padding: .06em .02em .14em; margin: -.06em -.02em -.14em; }
.fx-mask .fx-w { display: inline-block; transform: translateY(110%); }
.fx-mask.fx-in .fx-w { transform: none; transition: transform .9s cubic-bezier(.2, .8, .2, 1); transition-delay: calc(min(var(--fx-i) * 80ms, 800ms)); }
.fx-mask-on { animation: fx-pan 14s ease-in-out infinite alternate; }
.fx-mask-on .fx-w {
	background-image: linear-gradient(rgba(255, 255, 255, .5), rgba(255, 255, 255, .5)), var(--fx-img);
	background-size: 100% 100%, var(--fx-bs);
	background-position: 0 0, calc(var(--fx-bx) + var(--fx-pan)) var(--fx-by);
	background-repeat: no-repeat;
	-webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; color: transparent;
}
@keyframes fx-pan { from { --fx-pan: 0px; } to { --fx-pan: -80px; } }

/* True Focus: one item sharp inside corner brackets, the others softened. */
.fx-focus { position: relative; }
.fx-focus [data-fx-item] { transition: filter .45s ease, opacity .45s ease; }
.fx-focus [data-fx-item].fx-dim { filter: blur(1.5px); opacity: .5; }
.fx-frame { position: absolute; left: 0; top: 0; width: 0; height: 0; pointer-events: none; opacity: 0; z-index: 2;
	transition: transform .5s cubic-bezier(.2, .8, .2, 1), width .5s cubic-bezier(.2, .8, .2, 1), height .5s cubic-bezier(.2, .8, .2, 1), opacity .3s ease; }
.fx-focus.fx-on .fx-frame { opacity: 1; }
.fx-frame i { position: absolute; width: 14px; height: 14px; border: 3px solid var(--iv-accent); border-radius: 3px; filter: drop-shadow(0 0 4px rgba(37, 173, 227, .6)); }
.fx-frame i:nth-child(1) { left: 0; top: 0; border-right: 0; border-bottom: 0; }
.fx-frame i:nth-child(2) { right: 0; top: 0; border-left: 0; border-bottom: 0; }
.fx-frame i:nth-child(3) { left: 0; bottom: 0; border-right: 0; border-top: 0; }
.fx-frame i:nth-child(4) { right: 0; bottom: 0; border-left: 0; border-top: 0; }

/* Stroke Text: SVG glyphs; outlines draw on (dash offset), then the fill sweeps in from the left. */
.fx-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; }
.fx-stroke-svg { display: block; }
.fx-stroke-svg svg { display: block; max-width: 100%; height: auto; margin: 0 auto; overflow: visible; filter: drop-shadow(0 1px 18px rgba(255, 255, 255, .85)); }
.fx-stroke-line text { fill: none; stroke-width: 1.4; stroke-linejoin: round; transition-property: stroke-dashoffset; transition-timing-function: cubic-bezier(.33, 1, .68, 1); }
.fx-stroke-fill text { fill: currentColor; }

/* Gradient Text: a soft blue gradient flowing through the letters. */
.fx-gradient {
	background: linear-gradient(90deg, #00406E 0%, #0B64A6 25%, #2797D6 50%, #0B64A6 75%, #00406E 100%);
	background-size: 300% 100%; -webkit-background-clip: text; background-clip: text; color: transparent !important;
	-webkit-text-fill-color: transparent; text-shadow: none !important; filter: drop-shadow(0 1px 16px rgba(255, 255, 255, .9));
	animation: fx-gradient 8s linear infinite;
}
@keyframes fx-gradient { from { background-position: 0% 50%; } to { background-position: 300% 50%; } }

/* Variable Proximity: letters thicken near the cursor (weight set per letter in text-fx.js). */
.fx-prox-w { display: inline-block; white-space: nowrap; }
.fx-prox-ch { display: inline-block; }

/* Text Type: the full text holds the space (invisible) while the typed copy sits on top. */
.fx-type { display: grid; }
.fx-type > * { grid-area: 1 / 1; }
.fx-type-ghost { visibility: hidden; }
.fx-type-cursor { display: inline-block; margin-left: 2px; font-weight: 300; color: var(--iv-accent, #25ADE3); animation: fx-type-blink 1s steps(1) infinite; }
@keyframes fx-type-blink { 50% { opacity: 0; } }

/* Fold Text (React Bits "Fold Text", paper style, top hinge): letters unfold down from a crease
   with a fading crease shadow; they tip back a little near the cursor. */
[data-fx="fold"]:not(.fx-fold) { visibility: hidden; }
.fx-fold-w { display: inline-block; white-space: nowrap; }
.fx-fold-seg { display: inline-block; perspective: 700px; vertical-align: baseline; }
.fx-fold-p { position: relative; display: inline-block; backface-visibility: hidden; transform-origin: 50% 0%; opacity: 0; }
.fx-fold-p::after {
	content: attr(data-t); position: absolute; inset: 0; pointer-events: none;
	color: transparent; -webkit-text-fill-color: transparent;
	background-image: linear-gradient(180deg, rgba(0, 0, 0, .58) 0%, rgba(0, 0, 0, .22) 42%, rgba(255, 255, 255, .26) 100%);
	-webkit-background-clip: text; background-clip: text; opacity: var(--fold-crease, 0);
}
.fx-off [data-fx="fold"] { visibility: visible; }
