/**
 * GSAP Text Effects — frontend styles.
 *
 * Heading Segments block: keep CSS minimal so per-segment inline styles
 * are the source of truth. We only ship structural rules (display, reset
 * margins) and alignment helpers.
 */

.gte-heading-segments {
	/* Inherit margins/sizes from the theme by default — don't impose
	   a strong opinion. Inline styles set by users will override. */
}

.gte-heading-segments__segment {
	/* Inline span — should sit inline with adjacent segments. */
	display: inline;
}

/* When a segment has a background highlight, the inline-block makes
   padding render correctly across line breaks (otherwise padding can
   wrap awkwardly between lines). The PHP renderer adds padding/radius
   inline only when a backgroundColor is set, so this rule scopes the
   display change to those cases via the [style*="background"] attribute. */
.gte-heading-segments__segment[style*="background-color"],
.gte-heading-segments__segment[style*="background:"] {
	box-decoration-break: clone;
	-webkit-box-decoration-break: clone;
}

/* Text alignment helpers — mirror WordPress's standard class names so
   the AlignmentToolbar's output works out of the box. */
.gte-heading-segments.has-text-align-left    { text-align: left; }
.gte-heading-segments.has-text-align-center  { text-align: center; }
.gte-heading-segments.has-text-align-right   { text-align: right; }
.gte-heading-segments.has-text-align-justify { text-align: justify; }

/* ============================================================
 * Animated Heading
 * Most styles inherit from .gte-heading-segments via the segment
 * class. Below: animation-specific bits.
 * ============================================================ */

.gte-animated-heading {
	/* Set up for transforms — must be display:block (default for h1-h6)
	   so transforms render correctly. */
}

.gte-animated-heading__segment {
	display: inline;
}

.gte-animated-heading__segment[style*="background-color"],
.gte-animated-heading__segment[style*="background:"] {
	box-decoration-break: clone;
	-webkit-box-decoration-break: clone;
}

/* Unit elements created by the JS splitter. Must be inline-block so
   transforms (translate/scale/rotation) apply correctly — inline spans
   don't honour transform. */
.gte-unit {
	display: inline-block;
	/* Preserve baseline alignment so split letters don't drift. */
	vertical-align: baseline;
	/* Ensure transforms are GPU-accelerated for smooth animation. */
	will-change: transform, opacity, filter;
}

/* Line mode keeps the segment as its own unit — already display:inline
   from the segment rule above, override to inline-block for transforms. */
.gte-animated-heading__segment.gte-unit--line {
	display: inline-block;
}

/* Alignment classes — reuse the same naming as Heading Segments. */
.gte-animated-heading.has-text-align-left    { text-align: left; }
.gte-animated-heading.has-text-align-center  { text-align: center; }
.gte-animated-heading.has-text-align-right   { text-align: right; }
.gte-animated-heading.has-text-align-justify { text-align: justify; }

/* ============================================================
 * Rising Text
 * Heading wraps an inner span (the rising text) and a line span
 * (the horizon line). The heading clips the inner span vertically
 * via overflow: clip; the line is absolutely positioned at the
 * bottom edge. JS translates the inner span up from below.
 *
 * Note on `overflow: clip` vs `overflow: hidden`: `clip` doesn't
 * create a new scroll container the way `hidden` does, which is
 * important when this heading is inside a scrollable parent or
 * a sticky layout. Falls back to `hidden` for browsers without
 * `clip` support (very old Safari < 16, Firefox < 81).
 * ============================================================ */

.gte-rising-text {
	position: relative;
	overflow: hidden;
	/* Modern browsers prefer clip — same visual effect, doesn't
	   establish a scroll container or a new stacking context. */
	overflow: clip;
	/* Allow descenders (g, y, p) to sit below the baseline by adding
	   a small padding-bottom; the line itself is anchored just above
	   this padding so the visible text rests ON the line. */
	padding-bottom: 0.15em;
}

.gte-rising-text__inner {
	display: inline-block;
	/* `inline-block` lets the heading remain inline-flow-wise but
	   gives us a transformable container for the translate. */
}

/* JS adds this class to opt-in to the clipping behaviour. Until
   the class is present, text renders normally (no FOUC where
   text would be hidden during the brief window before JS runs). */
.gte-rising-text:not(.gte-rising-text--ready) .gte-rising-text__inner {
	transform: none !important;
}
.gte-rising-text:not(.gte-rising-text--ready) .gte-rising-text__line {
	opacity: 0;
}

.gte-rising-text__line {
	position: absolute;
	bottom: 0;
	/* `height` and `background` (colour) come from inline styles set by PHP */
	display: block;
	pointer-events: none;
	will-change: transform;
}

.gte-rising-text__segment {
	display: inline;
}

.gte-rising-text__segment[style*="background-color"],
.gte-rising-text__segment[style*="background:"] {
	box-decoration-break: clone;
	-webkit-box-decoration-break: clone;
}

.gte-rising-text.has-text-align-left    { text-align: left; }
.gte-rising-text.has-text-align-center  { text-align: center; }
.gte-rising-text.has-text-align-right   { text-align: right; }

/* Reduced motion: show final state, no animation. */
@media ( prefers-reduced-motion: reduce ) {
	.gte-rising-text__inner {
		transform: none !important;
	}
	.gte-rising-text__line {
		transform: scaleX(1) !important;
	}
}

/* ============================================================
 * Wipe Text
 * Heading: position: relative. The line is absolutely positioned
 * on the LEFT, full height, z-index above the text. The text has
 * padding-left equal to (line thickness + gap) so visible
 * characters appear past the line's right edge.
 *
 * Reveal mechanic: clip-path on the inner span sweeps from
 * inset(0 100% 0 0) → inset(0 0 0 0). The reveal edge starts at
 * x=0 (behind the line, invisible due to z-index), then crosses
 * past the line's right edge — that's when text becomes visible.
 * The visual effect is "text emerging from behind the line."
 * ============================================================ */

.gte-wipe-text {
	position: relative;
	margin: 0;
}

.gte-wipe-text__line {
	position: absolute;
	left: 0;
	/* `top` and `bottom` come from inline styles; default 0 unless
	   the user sets linePadding which negative-offsets these. */
	/* `width` and `background` come from inline styles. */
	z-index: 2;
	display: block;
	pointer-events: none;
	will-change: transform;
}

.gte-wipe-text__inner {
	display: block;
	/* `padding-left` comes from inline style — pushes visible text
	   past the line's right edge. */
	position: relative;
	z-index: 1;
}

/* JS adds this class right before setting the initial clip state,
   so the text doesn't flash visible during the brief window before
   the animation kicks in (FOUC protection). */
.gte-wipe-text:not(.gte-wipe-text--ready) .gte-wipe-text__inner {
	clip-path: none !important;
}
.gte-wipe-text:not(.gte-wipe-text--ready) .gte-wipe-text__line {
	transform: scaleY(1) !important;
}

.gte-wipe-text__segment {
	display: inline;
}

.gte-wipe-text__segment[style*="background-color"],
.gte-wipe-text__segment[style*="background:"] {
	box-decoration-break: clone;
	-webkit-box-decoration-break: clone;
}

/* Reduced motion: no animation, show final state. */
@media ( prefers-reduced-motion: reduce ) {
	.gte-wipe-text__inner {
		clip-path: none !important;
	}
	.gte-wipe-text__line {
		transform: scaleY(1) !important;
	}
}

/* ============================================================
 * Scramble Text
 * Simple — the JS just swaps textContent. No structural needs
 * beyond layout. We rely on the heading's natural rendering.
 * ============================================================ */
.gte-scramble-text {
	/* Use a monospaced fallback to keep character widths stable
	   while scrambling, so the heading width doesn't bounce around.
	   The user-set font-family still wins if they specify one. */
}
.gte-scramble-text__segment {
	display: inline;
	/* font-variant-numeric tabular-nums helps slightly for fixed-width
	   digits if numbers are part of the text. */
	font-variant-numeric: tabular-nums;
}
.gte-scramble-text.has-text-align-left    { text-align: left; }
.gte-scramble-text.has-text-align-center  { text-align: center; }
.gte-scramble-text.has-text-align-right   { text-align: right; }

/* ============================================================
 * Marquee Text
 * Container clips its overflow so the off-screen items are hidden.
 * Track is a flex row so cloned items sit side-by-side.
 * ============================================================ */
.gte-marquee-text {
	overflow: hidden;
	width: 100%;
	margin: 0;
}
.gte-marquee-text__track {
	display: flex;
	flex-wrap: nowrap;
	align-items: center;
	width: max-content;
	will-change: transform;
}
.gte-marquee-text__item {
	display: inline-flex;
	flex: 0 0 auto;
	align-items: center;
	white-space: nowrap;
}
.gte-marquee-text__segment,
.gte-marquee-text__sep {
	display: inline;
}

/* Until ready class, hide the track to avoid FOUC of a still
   track before JS measures and starts the loop. */
.gte-marquee-text:not(.gte-marquee-text--ready) .gte-marquee-text__track {
	visibility: hidden;
}

/* Reduced motion: show one static item, no loop. */
@media ( prefers-reduced-motion: reduce ) {
	.gte-marquee-text__track {
		transform: none !important;
	}
}

/* ============================================================
 * Gradient Sweep Text
 * Gradient styles are inline on each segment (the trick needs
 * background-image + background-clip:text on the text element).
 * This class scope handles ready-state and alignment.
 * ============================================================ */
.gte-gradient-sweep-text {
	/* Layout — same as a normal heading. */
}
.gte-gradient-sweep-text__segment {
	/* All gradient styles live inline. Keep this class as a CSS hook
	   for future overrides. */
}
.gte-gradient-sweep-text.has-text-align-left    { text-align: left; }
.gte-gradient-sweep-text.has-text-align-center  { text-align: center; }
.gte-gradient-sweep-text.has-text-align-right   { text-align: right; }

/* Reduced motion: no sweep. Initial inline style holds the position
   at 100% center which shows the base colour uniformly. */
@media ( prefers-reduced-motion: reduce ) {
	.gte-gradient-sweep-text__segment {
		background-position: 100% center !important;
	}
}

/* ============================================================
 * Sliding Text
 * Horizontal analog of Rising Text. Heading clips horizontally;
 * the inner span starts translated off to one side (depending on
 * direction setting) and slides into its natural position.
 *
 * Vertical line on the left, on top via z-index — stays visible
 * throughout, or animates separately via scaleY when line-draw-in
 * is enabled.
 * ============================================================ */

.gte-sliding-text {
	position: relative;
	overflow: hidden;
	overflow: clip;
	margin: 0;
}

.gte-sliding-text__line {
	position: absolute;
	left: 0;
	/* width, top, bottom, background come from inline styles */
	z-index: 2;
	display: block;
	pointer-events: none;
	will-change: transform;
}

.gte-sliding-text__inner {
	display: inline-block;
	position: relative;
	z-index: 1;
	/* padding-left set inline = lineThickness + lineGap */
	will-change: transform;
}

/* JS adds this class before setting initial transform — until then,
   text shows normally (FOUC protection). */
.gte-sliding-text:not(.gte-sliding-text--ready) .gte-sliding-text__inner {
	transform: none !important;
}
.gte-sliding-text:not(.gte-sliding-text--ready) .gte-sliding-text__line {
	transform: scaleY(1) !important;
}

.gte-sliding-text__segment {
	display: inline;
}

.gte-sliding-text__segment[style*="background-color"],
.gte-sliding-text__segment[style*="background:"] {
	box-decoration-break: clone;
	-webkit-box-decoration-break: clone;
}

.gte-sliding-text.has-text-align-left    { text-align: left; }
.gte-sliding-text.has-text-align-center  { text-align: center; }
.gte-sliding-text.has-text-align-right   { text-align: right; }

/* Reduced motion: show final state, no animation. */
@media ( prefers-reduced-motion: reduce ) {
	.gte-sliding-text__inner {
		transform: none !important;
	}
	.gte-sliding-text__line {
		transform: scaleY(1) !important;
	}
}
