/*
 * Northside: motion (front end only).
 *
 * Every rule is scoped to html.ns-motion, which a tiny inline script adds only
 * when animations are enabled in Site Settings AND the visitor hasn't asked
 * for reduced motion. Without it (no JS, reduced motion, editor) everything
 * renders in its final state. The final state of every animation is exactly
 * the design; motion only affects how elements arrive.
 *
 * Scroll reveals: assets/js/motion.js adds .is-in to an element when it
 * enters the viewport, with --ns-i as its stagger position.
 */

:root {
	--ns-ease: cubic-bezier(0.16, 1, 0.3, 1);
	--ns-dur: 0.8s;
	--ns-rise: 32px;
	--ns-step: 90ms;
}

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

	/* Section links (#why, #contact…) glide instead of jumping. */
	html.ns-motion {
		scroll-behavior: smooth;
	}

	/* ---------------------------------------------------------------------
	 * On load: hero, page intro, product intro
	 * ------------------------------------------------------------------ */
	@keyframes ns-rise {
		from {
			opacity: 0;
			transform: translate3d(0, var(--ns-rise), 0);
		}
		to {
			opacity: 1;
			transform: none;
		}
	}

	@keyframes ns-fade {
		from {
			opacity: 0;
		}
		to {
			opacity: 1;
		}
	}

	@keyframes ns-bar {
		from {
			transform: scaleX(0);
		}
		to {
			transform: scaleX(1);
		}
	}

	@keyframes ns-settle {
		from {
			transform: scale(1.08);
		}
		to {
			transform: scale(1);
		}
	}

	@keyframes ns-slide-in {
		from {
			opacity: 0;
			transform: translate3d(48px, 0, 0);
		}
		to {
			opacity: 1;
			transform: none;
		}
	}

	.ns-motion .ns-hero .wp-block-cover__image-background {
		animation: ns-settle 2.2s var(--ns-ease) both;
	}

	.ns-motion .ns-hero .wp-block-cover__inner-container > *,
	.ns-motion .ns-page-hero__inner > *,
	.ns-motion .ns-product__text > * {
		animation: ns-rise var(--ns-dur) var(--ns-ease) both;
	}

	.ns-motion :is(.ns-hero .wp-block-cover__inner-container, .ns-page-hero__inner, .ns-product__text) > :nth-child(1) { animation-delay: 0.15s; }
	.ns-motion :is(.ns-hero .wp-block-cover__inner-container, .ns-page-hero__inner, .ns-product__text) > :nth-child(2) { animation-delay: 0.3s; }
	.ns-motion :is(.ns-hero .wp-block-cover__inner-container, .ns-page-hero__inner, .ns-product__text) > :nth-child(3) { animation-delay: 0.45s; }
	.ns-motion :is(.ns-hero .wp-block-cover__inner-container, .ns-page-hero__inner, .ns-product__text) > :nth-child(4) { animation-delay: 0.6s; }

	/* Hero + page intro: everything arrives from the right, moving left. */
	@keyframes ns-from-right {
		from {
			opacity: 0;
			transform: translate3d(64px, 0, 0);
		}
		to {
			opacity: 1;
			transform: none;
		}
	}

	.ns-motion :is(.ns-hero .wp-block-cover__inner-container, .ns-page-hero__inner) > * {
		animation-name: ns-from-right;
	}

	.ns-motion :is(.ns-hero .wp-block-cover__inner-container, .ns-page-hero__inner) > :is(.ns-hero__actions, .ns-page-hero__actions) {
		animation-delay: 1.05s;
	}

	/* Headline + paragraph: word by word (motion.js wraps each word in .ns-word). */
	.ns-motion :is(.ns-hero__title, .ns-hero__lead, .ns-page-hero__title, .ns-page-hero__lead):not(.ns-split) {
		opacity: 0;
	}

	.ns-motion :is(.ns-hero__title, .ns-hero__lead, .ns-page-hero__title, .ns-page-hero__lead).ns-split {
		animation: none;
	}

	.ns-motion .ns-word {
		display: inline-block;
		animation: ns-from-right 0.75s var(--ns-ease) both;
		animation-delay: calc(var(--ns-base, 0s) + var(--ns-w, 0) * var(--ns-wstep, 70ms));
	}

	/* The yellow eyebrow bar draws in from the left. */
	.ns-motion :is(.ns-hero, .ns-page-hero, .ns-product) .ns-eyebrow::before {
		transform-origin: left center;
		animation: ns-bar 0.7s var(--ns-ease) 0.35s both;
	}

	.ns-motion .ns-product__media {
		animation: ns-slide-in 1s var(--ns-ease) 0.35s both;
	}

	/* ---------------------------------------------------------------------
	 * On scroll: hidden until .is-in
	 * ------------------------------------------------------------------ */

	/* Rise */
	.ns-motion :is(
		.ns-section-head__title > *,
		.ns-section-head__intro,
		.ns-about__text > *,
		.ns-why__text > .ns-eyebrow,
		.ns-why__text > .ns-section__title,
		.ns-order-early__text > *,
		.ns-order-early__actions,
		.ns-quote__head > *,
		.ns-quote__card,
		.ns-card,
		.ns-stat,
		.ns-footer__col,
		.ns-product-details__main,
		.ns-product-details__aside,
		.ns-photo-grid__item
	) {
		transition:
			opacity var(--ns-dur) var(--ns-ease),
			transform var(--ns-dur) var(--ns-ease);
		transition-delay: calc(var(--ns-i, 0) * var(--ns-step));
	}

	.ns-motion :is(
		.ns-section-head__title > *,
		.ns-section-head__intro,
		.ns-about__text > *,
		.ns-why__text > .ns-eyebrow,
		.ns-why__text > .ns-section__title,
		.ns-order-early__text > *,
		.ns-order-early__actions,
		.ns-quote__head > *,
		.ns-quote__card,
		.ns-card,
		.ns-stat,
		.ns-footer__col,
		.ns-product-details__main,
		.ns-product-details__aside,
		.ns-photo-grid__item
	):not(.is-in) {
		opacity: 0;
		transform: translate3d(0, var(--ns-rise), 0);
	}

	/* The 50+ box rises from a little lower, like it's being set down. */
	.ns-motion .ns-stat:not(.is-in) {
		transform: translate3d(0, 56px, 0);
	}

	/* About photo slides in from the right. */
	.ns-motion .ns-about__image {
		transition: opacity 1s var(--ns-ease), transform 1.1s var(--ns-ease);
	}

	.ns-motion .ns-about__image:not(.is-in) {
		opacity: 0;
		transform: translate3d(56px, 0, 0);
	}

	/* Checklist items come in from the left; the yellow box pops. */
	.ns-motion .is-style-checklist > li {
		transition: opacity 0.7s var(--ns-ease), transform 0.7s var(--ns-ease);
		transition-delay: calc(var(--ns-i, 0) * 110ms);
	}

	.ns-motion .is-style-checklist > li::before {
		transition: transform 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
		transition-delay: calc(var(--ns-i, 0) * 110ms + 0.2s);
	}

	.ns-motion .is-style-checklist > li:not(.is-in) {
		opacity: 0;
		transform: translate3d(-28px, 0, 0);
	}

	.ns-motion .is-style-checklist > li:not(.is-in)::before {
		transform: scale(0.4);
	}

	/* "Why Northside" photo: the yellow frame slides into its offset. */
	.ns-motion :is(.ns-why__media, .ns-product__media)::before,
	.ns-motion .ns-why__image {
		transition: opacity 1s var(--ns-ease), transform 1.1s var(--ns-ease);
	}

	.ns-motion .ns-why__image {
		transition-delay: 0.1s;
	}

	.ns-motion .ns-why__media:not(.is-in)::before {
		opacity: 0;
		transform: translate3d(40px, 40px, 0);
	}

	.ns-motion .ns-why__media:not(.is-in) .ns-why__image {
		opacity: 0;
		transform: translate3d(-24px, -24px, 0);
	}

	/* Gallery tiles */
	.ns-motion .wp-block-gallery.is-style-mosaic > figure {
		transition: opacity 0.9s var(--ns-ease), transform 0.9s var(--ns-ease);
		transition-delay: calc(var(--ns-i, 0) * 100ms);
	}

	.ns-motion .wp-block-gallery.is-style-mosaic > figure:not(.is-in) {
		opacity: 0;
		transform: scale(0.94);
	}

	/* Hazard stripes draw from left to right. (A mask, not clip-path:
	   IntersectionObserver treats a fully clipped element as not visible.) */
	.ns-motion .wp-block-separator.is-style-hazard {
		-webkit-mask: linear-gradient(#000, #000) no-repeat left top / 100% 100%;
		mask: linear-gradient(#000, #000) no-repeat left top / 100% 100%;
		transition: -webkit-mask-size 1.1s var(--ns-ease), mask-size 1.1s var(--ns-ease);
	}

	.ns-motion .wp-block-separator.is-style-hazard:not(.is-in) {
		-webkit-mask-size: 0% 100%;
		mask-size: 0% 100%;
	}

	/* Equipment callout: slides in from the right, then its accent arrives:
	   dark plate: the stripe edge drops down (+ a faint shine now and then)
	   highlighter: the marker sweeps across the question
	   tag: the stripe band draws across the top */
	@keyframes ns-shine {
		0% {
			transform: translateX(-120%) skewX(-20deg);
		}
		22%,
		100% {
			transform: translateX(420%) skewX(-20deg);
		}
	}

	.ns-motion .ns-callout {
		transition: opacity 0.8s var(--ns-ease), transform 0.9s var(--ns-ease);
		transition-delay: 0.2s;
	}

	.ns-motion .ns-callout:not(.is-in) {
		opacity: 0;
		transform: translate3d(80px, 0, 0);
	}

	.ns-motion .ns-callout::before {
		transition: transform 0.8s var(--ns-ease) 0.7s;
	}

	.ns-motion .ns-callout:not(.is-in)::before {
		transform: scaleY(0);
	}

	.ns-motion .ns-callout--tag:not(.is-in)::before {
		transform: scaleX(0);
	}

	.ns-motion .ns-callout:not(.ns-callout--marker):not(.ns-callout--tag).is-in::after {
		content: "";
		position: absolute;
		top: 0;
		bottom: 0;
		left: 0;
		width: 35%;
		background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.12), transparent);
		pointer-events: none;
		animation: ns-shine 6s ease-in-out 1.6s infinite;
	}

	.ns-motion .ns-callout--marker strong {
		transition: background-size 0.9s var(--ns-ease) 0.75s;
	}

	.ns-motion .ns-callout--marker:not(.is-in) strong {
		background-size: 0% 100%;
	}

	/* About page: story text rises, photo slides in, quote pops, timeline
	   years slide from the left, contact cards rise. */
	.ns-motion :is(.ns-story__text > *, .ns-info-card, .ns-about__actions) {
		transition: opacity var(--ns-dur) var(--ns-ease), transform var(--ns-dur) var(--ns-ease);
		transition-delay: calc(var(--ns-i, 0) * var(--ns-step));
	}

	.ns-motion :is(.ns-story__text > *, .ns-info-card, .ns-about__actions):not(.is-in) {
		opacity: 0;
		transform: translate3d(0, var(--ns-rise), 0);
	}

	.ns-motion .ns-story__media {
		transition: opacity 1s var(--ns-ease), transform 1.1s var(--ns-ease);
	}

	.ns-motion .ns-story__media:not(.is-in) {
		opacity: 0;
		transform: translate3d(56px, 0, 0);
	}

	.ns-motion .ns-philosophy__inner > * {
		transition: opacity 0.9s var(--ns-ease), transform 0.9s cubic-bezier(0.34, 1.4, 0.64, 1);
		transition-delay: calc(var(--ns-i, 0) * 180ms);
	}

	.ns-motion .ns-philosophy__inner > :not(.is-in) {
		opacity: 0;
		transform: scale(0.92);
	}

	.ns-motion .is-style-timeline > li {
		transition: opacity 0.7s var(--ns-ease), transform 0.7s var(--ns-ease);
		transition-delay: calc(var(--ns-i, 0) * 110ms);
	}

	.ns-motion .is-style-timeline > li:not(.is-in) {
		opacity: 0;
		transform: translate3d(-36px, 0, 0);
	}

	/* Badge: pops in, then the ring text turns slowly. */
	@keyframes ns-spin {
		to {
			transform: rotate(360deg);
		}
	}

	.ns-motion .ns-badge__ring {
		animation: ns-spin 14s linear infinite;
	}

	.ns-motion .ns-badge .wp-block-button__link:hover .ns-badge__ring {
		animation-duration: 5s;
	}

	.ns-motion .ns-badge-wrap {
		transition: opacity 0.7s var(--ns-ease), transform 0.8s cubic-bezier(0.34, 1.56, 0.64, 1);
		transition-delay: 0.3s;
	}

	.ns-motion .ns-badge-wrap:not(.is-in) {
		opacity: 0;
		transform: scale(0.4) rotate(-90deg);
	}

	/* Homepage About photo: a calm, never-ending drift (slow zoom + pan). */
	@keyframes ns-drift {
		from {
			transform: scale(1.03) translate3d(0, 0, 0);
		}
		to {
			transform: scale(1.14) translate3d(-2.5%, -1.5%, 0);
		}
	}

	.ns-motion .ns-about .ns-about__image img {
		transform-origin: 60% 55%;
		animation: ns-drift 22s ease-in-out infinite alternate;
		will-change: transform;
	}

	/* ---------------------------------------------------------------------
	 * Hover (subtle; final layout unchanged)
	 * ------------------------------------------------------------------ */
	.ns-card__media img,
	.wp-block-gallery.is-style-mosaic > figure img,
	.ns-photo-grid__item img {
		transition: transform 0.6s var(--ns-ease);
	}

	.ns-card:hover .ns-card__media img,
	.wp-block-gallery.is-style-mosaic > figure:hover img,
	.ns-photo-grid__item:hover img {
		transform: scale(1.04);
	}

	.ns-card__cta::after,
	.ns-btn--arrow .wp-block-button__link::after,
	.ns-quote .ff-btn-submit::after {
		transition: transform 0.3s var(--ns-ease);
	}

	.ns-card:hover .ns-card__cta::after,
	.ns-btn--arrow .wp-block-button__link:hover::after,
	.ns-btn--arrow .wp-block-button__link:focus-visible::after,
	.ns-quote .ff-btn-submit:hover::after {
		transform: translateX(5px);
	}
}
