/* ==========================================================================
   Hyaron Skin Booster — motion system
   Loaded only with media="screen and (prefers-reduced-motion: no-preference)"
   and never in the editor, so print, reduced motion and editing are always static.

   Two families on one scale:
   - Liquid (settle curve): headlines rise softly into place, photos are revealed
     by a water level (a section-coloured veil that retracts upward), content
     settles under its rule.
   - Instrument (draw curve): rules are drawn, data reads out in place, the
     Drug Facts label prints.
   No cross-page fade: the browser holds the old page until the new one paints,
   and each page's own arrival carries the transition.

   Gating (set by the inline head script in inc/setup.php):
   - html.hy-motion  motion allowed (reduced motion not requested)
   - html.hy-enter   fresh navigation: plays hero arrivals; lets main.js arm reveals
   Scroll reveals apply only to elements main.js marked [data-hy] while they were
   below the fold; the hidden pre-state is keyed on :not(.is-in) and every reveal
   uses fill-mode backwards, so elements end on their authored styles.
   ========================================================================== */

@media screen and (prefers-reduced-motion: no-preference) {

	:root {
		--hy-ease-settle: cubic-bezier(0.16, 1, 0.3, 1);
		--hy-ease-draw: cubic-bezier(0.65, 0, 0.35, 1);
		--hy-dur-state: 320ms;
		--hy-dur-readout: 600ms;
		--hy-dur-settle: 700ms;
		--hy-dur-draw: 900ms;
		--hy-dur-rise: 900ms;
		--hy-dur-water: 1100ms;
		--hy-dur-print: 1300ms;
		--hy-dur-plunge: 2400ms;
	}

	/* Figure radius, matched to the visible image corners. */
	:is(.hy-hero__img, .hy-cover, .hy-portrait, .hy-plate) { --hy-r: var(--radius-photo); }
	:is(.hy-ghero__img, .hy-apply__img) { --hy-r: 0px; }

	/* Veil colour = the surface the photo sits on, so the "water" reads as the page itself. */
	:is(.hy-section, .hy-hero, .hy-phero, .hy-ghero, .hy-ahero) { --hy-veil: var(--porcelain); }
	.is-style-hy-blossom { --hy-veil: var(--blossom); }
	.is-style-hy-mist { --hy-veil: var(--mist); }
	.is-style-hy-plum { --hy-veil: var(--plum-deep); }

	/* ---------- Vocabulary ---------- */

	/*
	 * Everything that plays while a page is still loading uses compositor-only
	 * properties (opacity, translate, scale), so it stays smooth on a busy main thread.
	 */

	/* Rise: headlines settle softly into place. */
	@keyframes hy-rise {
		from { opacity: var(--hy-rise-from, 0); translate: 0 var(--hy-rise, 0.24em); }
	}
	/* Water: a veil in the surface colour retracts upward, revealing the photo from below. */
	@keyframes hy-veil {
		from { scale: 1 1; }
		to { scale: 1 0; }
	}
	/* Identical keyframes under another name: the no-JS fallback, so a switch restarts cleanly. */
	@keyframes hy-veil-late {
		from { scale: 1 1; }
		to { scale: 1 0; }
	}
	@keyframes hy-water-img {
		from { scale: var(--hy-scale, 1.05); }
		to { scale: 1; }
	}
	@keyframes hy-water-img-late {
		from { scale: var(--hy-scale, 1.05); }
		to { scale: 1; }
	}
	/* Draw: only the top 2px strip (the element's own border) is revealed left to right. */
	@keyframes hy-rule {
		from { clip-path: polygon(0 0, 0 0, 0 2px, 100% 2px, 100% 100%, 0 100%); }
		to { clip-path: polygon(0 0, 100% 0, 100% 2px, 100% 2px, 100% 100%, 0 100%); }
	}
	@keyframes hy-settle {
		from { opacity: 0; translate: 0 var(--hy-rise, 8px); }
	}
	@keyframes hy-fade {
		from { opacity: 0; }
	}
	/* Print: the top edge draws, then the label feeds downward. */
	@keyframes hy-print {
		0% { clip-path: inset(0 100% calc(100% - 2px) 0); animation-timing-function: cubic-bezier(0.65, 0, 0.35, 1); }
		25% { clip-path: inset(0 0 calc(100% - 2px) 0); animation-timing-function: cubic-bezier(0.65, 0, 0.35, 1); }
		100% { clip-path: inset(0 0 0 0); }
	}
	@keyframes hy-draw-x {
		from { scale: 0 1; }
		to { scale: 1 1; }
	}
	@keyframes hy-deposit-in {
		from { opacity: 0; scale: 0.4; }
		to { opacity: 1; scale: 1; }
	}
	@keyframes hy-ripple {
		from { opacity: 0.7; scale: 1; }
		to { opacity: 0; scale: 2.6; }
	}
	@keyframes hy-needle {
		to { opacity: 1; translate: 0 0; }
	}
	@keyframes hy-fill-y {
		from { scale: 1 0; }
		to { scale: 1 1; }
	}
	@keyframes hy-plunge {
		from { scale: 0 1; }
		to { scale: 0.9 1; }
	}

	/* ---------- Arrival: one quiet entrance per page (CSS only, never armed by JS) ---------- */

	.hy-enter :is(.hy-hero__display, .hy-phero h1, .hy-ghero h1, .hy-ahero h1, .hy-chero h1, .hy-404 h1) {
		/* Short travel so a multi-line headline never crosses the line below it; a faint
		   first frame (not 0) so the headline still counts as painted for LCP. */
		--hy-rise: 0.16em;
		--hy-rise-from: 0.08;
		animation: hy-rise var(--hy-dur-rise) var(--hy-ease-settle) backwards;
	}

	/*
	 * Photos revealed by the water veil: hero figures on arrival, and section
	 * figures armed by main.js. The veil is an ::after in the surface colour;
	 * at rest it is scaled to 0 (invisible).
	 */
	.hy-enter :is(.hy-hero__img, .hy-phero .hy-plate, .hy-ghero__img, .hy-ahero .hy-cover),
	.hy-motion [data-hy="water"] {
		position: relative;
		overflow: hidden;
		border-radius: var(--hy-r, 0px);
	}
	.hy-enter :is(.hy-hero__img, .hy-phero .hy-plate, .hy-ghero__img, .hy-ahero .hy-cover)::after,
	.hy-motion [data-hy="water"]::after {
		content: "";
		position: absolute;
		inset: -1px;
		background: linear-gradient(to bottom, var(--hy-veil, var(--porcelain)) calc(100% - 1.5rem), color-mix(in srgb, var(--hy-veil, var(--porcelain)) 0%, transparent));
		transform-origin: 50% 0;
		scale: 1 0;
		pointer-events: none;
	}
	.hy-enter :is(.hy-hero__img, .hy-phero .hy-plate, .hy-ghero__img, .hy-ahero .hy-cover) img,
	.hy-motion [data-hy="water"] img {
		transform-origin: 50% 100%;
	}
	/* These figures clip their overflow, so a linked image draws its focus ring inside. */
	.hy-enter :is(.hy-hero__img, .hy-phero .hy-plate, .hy-ghero__img, .hy-ahero .hy-cover) a:focus-visible,
	.hy-motion [data-hy="water"] a:focus-visible {
		outline-offset: -4px;
	}

	/*
	 * Hero photo: the veil waits for the image to decode (main.js adds .is-ready), so an
	 * empty frame is never revealed. Without JS, the "-late" fallback reveals it at 1.4s.
	 */
	.hy-enter :is(.hy-hero__img, .hy-phero .hy-plate, .hy-ghero__img, .hy-ahero .hy-cover)::after {
		animation: hy-veil-late var(--hy-dur-water) var(--hy-ease-settle) 1400ms backwards;
	}
	.hy-enter :is(.hy-hero__img, .hy-phero .hy-plate, .hy-ghero__img, .hy-ahero .hy-cover) img {
		--hy-scale: 1.04;
		animation: hy-water-img-late var(--hy-dur-water) var(--hy-ease-settle) 1400ms backwards;
	}
	.hy-enter :is(.hy-hero__img, .hy-phero .hy-plate, .hy-ghero__img, .hy-ahero .hy-cover).is-ready::after {
		animation: hy-veil var(--hy-dur-water) var(--hy-ease-settle) backwards;
	}
	.hy-enter :is(.hy-hero__img, .hy-phero .hy-plate, .hy-ghero__img, .hy-ahero .hy-cover).is-ready img {
		animation: hy-water-img var(--hy-dur-water) var(--hy-ease-settle) backwards;
	}
	.hy-enter .hy-ghero .hy-toc {
		animation: hy-rule var(--hy-dur-draw) var(--hy-ease-draw) 300ms backwards;
	}

	/* ---------- Scroll reveals (elements armed by main.js) ---------- */

	/* Surface: in text-only sections, the heading rises, then the line beneath it follows. */
	.hy-motion [data-hy="surface"]:not(.is-in),
	.hy-motion [data-hy="surface"]:not(.is-in) + :is(.hy-subhead, .hy-lede, p) {
		opacity: 0;
		translate: 0 0.24em;
	}
	.hy-motion [data-hy="surface"].is-in {
		animation: hy-rise var(--hy-dur-rise) var(--hy-ease-settle) var(--hy-d, 0ms) backwards;
	}
	.hy-motion [data-hy="surface"].is-in + :is(.hy-subhead, .hy-lede, p) {
		--hy-rise: 0.4em;
		animation: hy-rise var(--hy-dur-rise) var(--hy-ease-settle) calc(var(--hy-d, 0ms) + 120ms) backwards;
	}

	/* Water: section photography (main.js waits for the image before adding .is-in). */
	.hy-motion [data-hy="water"]:not(.is-in)::after {
		scale: 1 1;
	}
	.hy-motion [data-hy="water"].is-in::after {
		animation: hy-veil var(--hy-dur-water) var(--hy-ease-settle) var(--hy-d, 0ms) backwards;
	}
	.hy-motion [data-hy="water"].is-in img {
		animation: hy-water-img var(--hy-dur-water) var(--hy-ease-settle) var(--hy-d, 0ms) backwards;
	}

	/* Draw & settle: ruled items draw their own top border, then content settles beneath it. */
	.hy-motion [data-hy="draw"]:not(.is-in) {
		clip-path: polygon(0 0, 0 0, 0 2px, 100% 2px, 100% 100%, 0 100%);
	}
	.hy-motion [data-hy="draw"]:not(.is-in) > *,
	.hy-motion [data-hy="draw"]:not(.is-in)::before {
		opacity: 0;
	}
	.hy-motion [data-hy="draw"].is-in {
		animation: hy-rule 600ms var(--hy-ease-settle) var(--hy-d, 0ms) backwards;
	}
	.hy-motion [data-hy="draw"].is-in > *,
	.hy-motion [data-hy="draw"].is-in::before {
		animation: hy-settle 600ms var(--hy-ease-settle) calc(var(--hy-d, 0ms) + 220ms) backwards;
	}

	/* Readout: values register in place; dividers and the plum band never move. */
	.hy-motion [data-hy="readout"]:not(.is-in) > * {
		opacity: 0;
	}
	.hy-motion [data-hy="readout"].is-in > * {
		animation: hy-fade var(--hy-dur-readout) var(--hy-ease-settle) var(--hy-d, 0ms) backwards;
	}

	/* Rows: a data table reads out top to bottom as one unit (hairlines stay printed). */
	.hy-motion [data-hy="rows"]:not(.is-in) tr {
		opacity: 0;
	}
	.hy-motion [data-hy="rows"].is-in tr {
		animation: hy-fade 500ms var(--hy-ease-settle) calc(var(--hy-d, 0ms) + min(var(--hy-row, 0) * 30ms, 450ms)) backwards;
	}

	/* Print: the Drug Facts label (Product page signature). */
	.hy-motion [data-hy="print"]:not(.is-in) {
		clip-path: inset(0 100% calc(100% - 2px) 0);
	}
	.hy-motion [data-hy="print"].is-in {
		animation: hy-print var(--hy-dur-print) linear var(--hy-d, 0ms) backwards;
	}

	/* Course: the session timeline (Treatment guide signature). Day labels are never hidden. */
	.hy-motion [data-hy="course"] :is(.hy-timeline__track, .hy-timeline__maintain)::before {
		transform-origin: 0 50%;
	}
	.hy-motion [data-hy="course"]:not(.is-in) :is(.hy-timeline__track, .hy-timeline__maintain)::before {
		scale: 0 1;
	}
	.hy-motion [data-hy="course"]:not(.is-in) .hy-timeline__dot {
		opacity: 0;
		scale: 0.4;
	}
	.hy-motion [data-hy="course"].is-in .hy-timeline__track::before {
		/* Linear: sessions are equally spaced in time. */
		animation: hy-draw-x var(--hy-dur-draw) linear backwards;
	}
	.hy-motion [data-hy="course"].is-in .hy-timeline__session .hy-timeline__dot {
		/* Each dot lands as the line reaches it. */
		animation: hy-deposit-in 600ms var(--hy-ease-settle) calc(var(--hy-n, 0) * var(--hy-dur-draw) / max(var(--sessions, 10) - 1, 1)) backwards;
	}
	.hy-motion [data-hy="course"].is-in .hy-timeline__maintain::before {
		animation: hy-draw-x 350ms var(--hy-ease-draw) var(--hy-dur-draw) backwards;
	}
	.hy-motion [data-hy="course"].is-in .hy-timeline__maintain .hy-timeline__dot {
		animation: hy-deposit-in 600ms var(--hy-ease-settle) 1150ms backwards;
	}
	.hy-motion [data-hy="course"] .hy-timeline__maintain .hy-timeline__dot::after {
		content: "";
		position: absolute;
		inset: -1.5px;
		border-radius: 50%;
		border: 1.5px solid var(--petal);
		opacity: 0;
		pointer-events: none;
	}
	.hy-motion [data-hy="course"].is-in .hy-timeline__maintain .hy-timeline__dot::after {
		/* One ripple, played once. */
		animation: hy-ripple 1400ms var(--hy-ease-settle) 1300ms;
	}

	/* Jumped-to, focused or restored content appears at once, with no animation. */
	.hy-motion .hy-now,
	.hy-motion .hy-now *,
	.hy-motion .hy-now::before,
	.hy-motion .hy-now::after,
	.hy-motion .hy-now *::before,
	.hy-motion .hy-now *::after {
		animation: none !important;
	}

	/* Editor opt-out: a Group with the class hy-no-motion keeps everything inside it still. */
	.hy-motion .hy-no-motion,
	.hy-motion .hy-no-motion *,
	.hy-motion .hy-no-motion::before,
	.hy-motion .hy-no-motion::after,
	.hy-motion .hy-no-motion *::before,
	.hy-motion .hy-no-motion *::after {
		animation: none !important;
	}
	.hy-motion .hy-no-motion .hy-protocol__steps::after { content: none; }

	/* ---------- Depth diagram: the needle enters, then deposits are placed and the bolus swells ---------- */

	@keyframes hy-deposit { to { opacity: 1; transform: scale(1); } }
	@keyframes hy-bolus { to { opacity: 1; transform: scale(1); } }
	.hy-motion .hy-depth--armed :is(.hy-depth__deposit, .hy-depth__bolus) { opacity: 0; }
	.hy-motion .hy-depth--armed .hy-depth__deposit { transform: scale(0.4); }
	.hy-motion .hy-depth--armed .hy-depth__bolus { transform: scale(0.65); }
	.hy-motion .hy-depth--armed.is-visible .hy-depth__deposit {
		animation: hy-deposit 0.9s cubic-bezier(0.2, 0.7, 0.2, 1) calc(0.35s + var(--i) * 0.16s) forwards;
	}
	.hy-motion .hy-depth--armed.is-visible .hy-depth__bolus {
		animation: hy-bolus 1.2s cubic-bezier(0.2, 0.7, 0.2, 1) 0.5s forwards;
	}
	.hy-motion .hy-depth--armed .hy-depth__needle { opacity: 0; }
	.hy-motion .hy-depth--armed .hy-depth__panel--booster .hy-depth__needle { translate: -26px -30px; }
	.hy-motion .hy-depth--armed .hy-depth__panel--filler .hy-depth__needle { translate: -24px -32px; }
	.hy-motion .hy-depth--armed.is-visible .hy-depth__needle {
		animation: hy-needle 600ms var(--hy-ease-settle) forwards;
	}

	/* ---------- Dose line: the protocol connector fills with reading progress ---------- */

	@supports (animation-timeline: view()) {
		.hy-motion .hy-protocol__steps {
			view-timeline: --hy-dose block;
			view-timeline-inset: 45% 45%;
		}
		.hy-motion .hy-protocol__steps::after {
			content: "";
			position: absolute;
			left: 52px;
			top: var(--hy-dose-start, 52px);
			bottom: var(--hy-dose-end, 52px);
			width: 1.5px;
			margin-left: -0.25px;
			background: var(--plum);
			transform-origin: 50% 0;
			pointer-events: none;
			animation: hy-fill-y linear both;
			animation-timeline: --hy-dose;
			animation-range: cover;
		}
		/* Stacking: line, then photos, then the numbered badges. */
		.hy-motion .hy-protocol__img { z-index: 1; }
		.hy-motion .hy-protocol__step::after { z-index: 2; }
		@media (max-width: 520px) {
			.hy-motion .hy-protocol__steps::after { left: 36px; }
		}
	}

	/* ---------- Motion that answers an action ---------- */

	/* FAQ: the answer settles beneath its question while the space opens. */
	.hy-motion .hy-faq .wp-block-details[open] > :not(summary) {
		--hy-rise: -6px;
		animation: hy-settle var(--hy-dur-state) var(--hy-ease-settle) 60ms backwards;
	}

	/* Inquiry: a plunger bar advances while sending; the status settles in after the redirect. */
	.hy-motion .hy-form.is-sending .hy-form__submit {
		position: relative;
		overflow: hidden;
	}
	.hy-motion .hy-form.is-sending .hy-form__submit::after {
		content: "";
		position: absolute;
		left: 0;
		right: 0;
		bottom: 0;
		height: 2px;
		background: var(--petal);
		transform-origin: 0 50%;
		animation: hy-plunge var(--hy-dur-plunge) var(--hy-ease-settle) forwards;
	}
	.hy-motion .hy-form-status {
		--hy-rise: 6px;
		animation: hy-settle var(--hy-dur-state) var(--hy-ease-settle) 120ms backwards;
	}

}
