/* ==========================================================================
 * QynTro AI - Hero heading
 *
 * Line one rises word by word out of a blur, with a light passing across it.
 * Line two cycles the full model roster, each name arriving on a WIPE: a blade
 * of light crosses the line, takes the old name with it and leaves the new one
 * behind.
 *
 * The Animated Headlines plugin keeps running and keeps its timing. This file
 * and its JS only change how the switch LOOKS - the plugin still decides when.
 * If the JS never runs, the headline is exactly what it is today.
 *
 * ADDITIVE. Everything is .qhh- prefixed except where it has to reach the
 * theme's own `.ah-` classes, and those are only ever decorated.
 *
 * DEPLOY ORDER MATTERS: upload FIRST, then bump ?v=. 7-day cache.
 * ========================================================================== */

/* ==========================================================================
 * LINE ONE
 * ========================================================================== */

/* AOS already fades the whole h1 in. Its animation is neutralised here so the
   per-word rise below is the only thing moving - running both at once reads as
   mush, and AOS wins on the parent while the words move inside it.

   Deliberately NOT scoped to #main: this page has two elements sharing that id,
   and while a CSS id selector happens to match both, depending on that is a
   trap waiting for whoever reads this next. The .qhh- class is only ever added
   to the real headline, so it is scope enough. */
.frontend-body h1.qhh-h1 {
	opacity: 1 !important;
	transform: none !important;
	position: relative;
}

.qhh-h1 .qhh-w {
	display: inline-block;
	opacity: 0;
	filter: blur(9px);
	transform: translateY(26px) scale(.97);
	animation: qhh-word .8s cubic-bezier(.2, .9, .3, 1) forwards;
	animation-delay: var(--d, 0ms);
}
@keyframes qhh-word {
	to { opacity: 1; filter: blur(0); transform: none; }
}

/* A light crossing the line every 7s. Sits above the type but takes no clicks. */
.qhh-h1::after {
	content: "";
	position: absolute;
	top: -6%;
	bottom: -6%;
	left: -25%;
	width: 22%;
	background: linear-gradient(100deg, transparent, rgba(209, 254, 23, .20), transparent);
	filter: blur(14px);
	pointer-events: none;
	animation: qhh-shine 7s ease-in-out 2.2s infinite;
}
@keyframes qhh-shine {
	0%        { left: -25%; opacity: 0; }
	8%        { opacity: 1; }
	38%, 100% { left: 110%; opacity: 0; }
}

/* ==========================================================================
 * LINE TWO - the roster
 * ========================================================================== */

/* `width: auto` with !important, and it has to be !important.
 *
 * The plugin sizes this wrapper to fit the category words that ship in the
 * markup - 299px, the width of "AVATAR" - and writes that as an INLINE style it
 * re-animates on every switch. The line now shows model names instead, up to
 * "Luma Dream Machine" at 759px, so that inline width would crop most of them.
 * A stylesheet !important is the one thing that outranks an inline style, and
 * it lets the wrapper size itself to whatever is actually in it. */
.qhh-rot .ah-words-wrapper {
	position: relative;
	width: auto !important;
	white-space: nowrap;
}

/* Brackets are pseudo-elements on the plugin's own wrapper, so no element is
   inserted into markup the plugin walks with .next() to pick the next word. */
.qhh-rot .ah-words-wrapper::before,
.qhh-rot .ah-words-wrapper::after {
	position: absolute;
	top: 50%;
	transform: translateY(-50%);
	color: var(--qp-lime, #d1fe17);
	font-weight: 400;
	opacity: .42;
	pointer-events: none;
}
.qhh-rot .ah-words-wrapper::before { content: "["; left: -.42em;  animation: qhh-brl 2.8s ease-in-out infinite; }
.qhh-rot .ah-words-wrapper::after  { content: "]"; right: -.42em; animation: qhh-brr 2.8s ease-in-out infinite; }
@keyframes qhh-brl {
	0%, 100% { transform: translateY(-50%) translateX(0);    opacity: .42; }
	50%      { transform: translateY(-50%) translateX(-7px); opacity: .85; }
}
@keyframes qhh-brr {
	0%, 100% { transform: translateY(-50%) translateX(0);    opacity: .42; }
	50%      { transform: translateY(-50%) translateX(7px);  opacity: .85; }
}

/* The plugin's own `slide` transition is neutralised. It exists to move a word
   in from the side, and with the wipe doing that job the two read as one
   fighting the other - and worse, the outgoing word stays on screen through its
   slide, so both names are briefly visible at once. The plugin keeps switching
   these classes; they just no longer animate anything. */
.qhh-rot b.is-hidden  { opacity: 0 !important; transform: none !important; }
.qhh-rot b.is-visible {
	opacity: 1 !important;
	transform: none !important;
	position: relative !important;
	display: inline-block;
	text-align: center;
	text-shadow: 0 0 38px rgba(209, 254, 23, .5);
}

/* ---- the wipe ----
 *
 * The name is clipped rather than faded, so it is revealed by an edge travelling
 * across it. clip-path is the right tool: it costs nothing to animate and it
 * leaves the type completely crisp, where a mask or a gradient would soften it.
 */
.qhh-txt {
	display: inline-block;
	clip-path: inset(0 0 0 0);
}
.qhh-txt.qhh-out { animation: qhh-wipe-out .3s cubic-bezier(.5, 0, .7, .5) forwards; }
.qhh-txt.qhh-in  { animation: qhh-wipe-in .55s cubic-bezier(.3, .9, .3, 1) forwards; }
@keyframes qhh-wipe-out {
	from { clip-path: inset(0 0 0 0); }
	to   { clip-path: inset(0 0 0 100%); }
}
@keyframes qhh-wipe-in {
	from { clip-path: inset(0 100% 0 0); }
	to   { clip-path: inset(0 0 0 0); }
}

/* The blade itself. Runs out and back: out on the clear, back on the reveal,
   so one pass of light accounts for both halves of the change. */
.qhh-edge {
	position: absolute;
	top: -8%;
	bottom: -8%;
	left: 0;
	width: 4px;
	border-radius: 3px;
	opacity: 0;
	pointer-events: none;
	background: var(--qp-lime, #d1fe17);
	box-shadow: 0 0 22px 5px rgba(209, 254, 23, .8);
}
.qhh-edge.qhh-run { animation: qhh-blade .85s cubic-bezier(.3, .9, .3, 1) forwards; }
@keyframes qhh-blade {
	0%   { left: 0;    opacity: 0; }
	8%   { opacity: 1; }
	35%  { left: 100%; }
	65%  { left: 0;    opacity: 1; }
	100% { left: 0;    opacity: 0; }
}

/* Category line under the name. "Veo 3.1" on its own tells a visitor nothing
   about what it does; this is what keeps the rotation legible. */
.qhh-cat {
	margin: 11px auto 0;
	font-size: 11px;
	font-weight: 700;
	letter-spacing: .18em;
	text-transform: uppercase;
	color: var(--qp-text-muted, #9b9ea6);
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 9px;
	min-height: 1.2em;   /* reserved, so the line below never shifts */
}
.qhh-new {
	padding: 2px 7px;
	border-radius: 5px;
	font-size: 9px;
	letter-spacing: .1em;
	background: rgba(255, 61, 154, .16);
	border: 1px solid rgba(255, 61, 154, .45);
	color: #ff7ab8;
}

/* Underline, sized to each name by the JS. */
.qhh-bar {
	height: 3px;
	width: 0;
	margin: 14px auto 0;
	border-radius: 3px;
	background: linear-gradient(90deg, transparent, var(--qp-lime, #d1fe17), transparent);
	box-shadow: 0 0 16px rgba(209, 254, 23, .75);
	transition: width .55s cubic-bezier(.2, .9, .3, 1);
	pointer-events: none;
}

/* ==========================================================================
 * CHIP - same pulse as the section heads, so the page has one language
 * ========================================================================== */
.frontend-body h6.qhh-chip {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	padding: 7px 16px 7px 13px;
	border-radius: 999px;
	background: rgba(255, 255, 255, .04);
	border: 1px solid rgba(255, 255, 255, .12);
}
.qhh-chip i {
	width: 6px;
	height: 6px;
	border-radius: 50%;
	flex: none;
	background: var(--qp-lime, #d1fe17);
	box-shadow: 0 0 10px var(--qp-lime, #d1fe17);
	animation: qhh-pulse 1.7s ease-in-out infinite;
}
@keyframes qhh-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .3; } }

@media (prefers-reduced-motion: reduce) {
	.qhh-h1 .qhh-w { opacity: 1; filter: none; transform: none; animation: none; }
	.qhh-h1::after,
	.qhh-rot .ah-words-wrapper::before,
	.qhh-rot .ah-words-wrapper::after,
	.qhh-chip i { animation: none; }
	.qhh-txt.qhh-out, .qhh-txt.qhh-in { animation: none; clip-path: none; }
	.qhh-edge { display: none; }
	.qhh-bar { transition: none; }
}
