/* =============================================================================
   TEN DIGITALS - MOTION SYSTEM
   Scroll-triggered reveals and hover behaviour for cards and text.
   Timing bands follow spec 3:
     micro     150-250ms  buttons, hover, focus, icons
     standard  300-500ms  cards, navigation, section reveals
     signature 600-1200ms hero geometry, major system transitions
   Everything degrades to a static end-state under prefers-reduced-motion.
   ========================================================================== */

/* -----------------------------------------------------------------------------
   1. SCROLL REVEAL
   Elements carry [data-reveal]; an IntersectionObserver adds .is-revealed.
   Without JS the :not(.js-motion) guard leaves everything visible.
   -------------------------------------------------------------------------- */

.js-motion [data-reveal] {
	opacity: 0;
	transition:
		opacity var(--td-t-signature) var(--td-ease-out),
		transform var(--td-t-signature) var(--td-ease-out),
		clip-path var(--td-t-signature) var(--td-ease-out),
		filter var(--td-t-signature) var(--td-ease-out);
	transition-delay: var(--td-reveal-delay, 0ms);
	will-change: opacity, transform;
}

.js-motion [data-reveal="up"]    { transform: translate3d(0, 34px, 0); }
.js-motion [data-reveal="down"]  { transform: translate3d(0, -28px, 0); }
.js-motion [data-reveal="left"]  { transform: translate3d(38px, 0, 0); }
.js-motion [data-reveal="right"] { transform: translate3d(-38px, 0, 0); }
.js-motion [data-reveal="fade"]  { transform: none; }

.js-motion [data-reveal="scale"] {
	transform: scale(0.94) translate3d(0, 18px, 0);
}

/* Mask wipe - the signature reveal for headlines and feature imagery. */
.js-motion [data-reveal="wipe"] {
	clip-path: inset(0 0 100% 0);
	opacity: 1;
	transform: translate3d(0, 14px, 0);
}

/* Blur-in for hero geometry. */
.js-motion [data-reveal="emerge"] {
	filter: blur(14px);
	transform: scale(1.04);
}

.js-motion [data-reveal].is-revealed {
	clip-path: inset(0 0 0 0);
	filter: none;
	opacity: 1;
	transform: none;
}

/* Stagger: parent sets --i on each child via CSS counter or inline style. */
.js-motion [data-reveal-stagger] > * {
	--td-reveal-delay: calc(var(--i, 0) * 85ms);
}

.js-motion [data-reveal-stagger="fast"] > * {
	--td-reveal-delay: calc(var(--i, 0) * 55ms);
}

.js-motion [data-reveal-stagger="slow"] > * {
	--td-reveal-delay: calc(var(--i, 0) * 130ms);
}

/* -----------------------------------------------------------------------------
   2. TEXT REVEAL
   Lines are wrapped in .td-line > .td-line__inner by reveal.js, then the
   inner element rises out of an overflow-hidden mask. Falls back to a plain
   fade if the splitter cannot run.
   -------------------------------------------------------------------------- */

.td-line {
	display: block;
	overflow: hidden;
	padding-block: 0.06em;          /* room for descenders inside the mask */
	margin-block: -0.06em;
}

.js-motion .td-line__inner {
	display: block;
	transform: translate3d(0, 105%, 0);
	transition:
		transform var(--td-t-signature) var(--td-ease-out),
		opacity var(--td-t-standard) var(--td-ease-out);
	transition-delay: var(--td-line-delay, 0ms);
	will-change: transform;
}

.js-motion .is-revealed .td-line__inner,
.js-motion .td-line__inner.is-revealed {
	transform: translate3d(0, 0, 0);
}

/* Word-level shimmer used once, on the hero H1. */
.td-shimmer-once {
	background-image: linear-gradient(
		96deg,
		currentColor 0%,
		currentColor 38%,
		var(--td-orange-300) 50%,
		currentColor 62%,
		currentColor 100%
	);
	background-size: 260% 100%;
	background-position: 140% 0;
	-webkit-background-clip: text;
	background-clip: text;
}

.js-motion .td-shimmer-once.is-revealed {
	animation: td-shimmer-sweep 1500ms var(--td-ease-out) 600ms 1 both;
}

@keyframes td-shimmer-sweep {
	from { background-position: 140% 0; }
	to   { background-position: -40% 0; }
}

/* -----------------------------------------------------------------------------
   3. HOVER - CARDS
   One shared behaviour so every card in the system responds identically:
   lift, deepen the surface, sweep a light across it, advance the arrow.
   -------------------------------------------------------------------------- */

.td-hover-card {
	--td-lift: -6px;
	isolation: isolate;
	position: relative;
	transition:
		transform var(--td-t-standard) var(--td-ease-spring),
		box-shadow var(--td-t-standard) var(--td-ease),
		border-color var(--td-t-standard) var(--td-ease),
		background-color var(--td-t-standard) var(--td-ease);
	will-change: transform;
}

.td-hover-card::after {
	background: linear-gradient(
		115deg,
		transparent 32%,
		var(--td-shimmer) 48%,
		transparent 64%
	);
	border-radius: inherit;
	content: "";
	inset: 0;
	opacity: 0;
	pointer-events: none;
	position: absolute;
	transform: translateX(-24%);
	transition:
		opacity var(--td-t-standard) var(--td-ease),
		transform var(--td-t-signature) var(--td-ease-out);
	z-index: 2;
}

.td-hover-card:hover,
.td-hover-card:focus-within {
	box-shadow: var(--td-card-shadow-hover);
	transform: translate3d(0, var(--td-lift), 0);
}

.td-hover-card:hover::after,
.td-hover-card:focus-within::after {
	opacity: 0.75;
	transform: translateX(24%);
}

/* Accent rule that grows along the card edge on hover. */
.td-hover-card__rule {
	background: var(--td-grad-brand);
	border-radius: 2px;
	bottom: 0;
	content: "";
	height: 2px;
	left: 0;
	position: absolute;
	transform: scaleX(0);
	transform-origin: left center;
	transition: transform var(--td-t-standard) var(--td-ease-out);
	width: 100%;
	z-index: 3;
}

.td-hover-card:hover .td-hover-card__rule,
.td-hover-card:focus-within .td-hover-card__rule { transform: scaleX(1); }

/* Directional arrow used across capability, insight and work cards. */
.td-arrow {
	align-items: center;
	display: inline-flex;
	flex: none;
	height: 1em;
	justify-content: center;
	transition: transform var(--td-t-standard) var(--td-ease-spring);
	width: 1em;
}

.td-hover-card:hover .td-arrow,
.td-hover-card:focus-within .td-arrow,
a:hover > .td-arrow,
.td-btn:hover .td-arrow { transform: translate3d(0.28em, -0.28em, 0); }

.td-arrow--right { transform: none; }

.td-hover-card:hover .td-arrow--right,
.td-hover-card:focus-within .td-arrow--right,
.td-btn:hover .td-arrow--right { transform: translate3d(0.3em, 0, 0); }

/* Media inside a card zooms fractionally - never a jarring scale. */
.td-hover-media {
	overflow: hidden;
	position: relative;
}

.td-hover-media img,
.td-hover-media .td-hover-media__inner {
	transition: transform var(--td-t-signature) var(--td-ease-out);
	will-change: transform;
}

.td-hover-card:hover .td-hover-media img,
.td-hover-card:focus-within .td-hover-media img,
.td-hover-card:hover .td-hover-media__inner { transform: scale(1.045); }

/* -----------------------------------------------------------------------------
   4. HOVER - TEXT AND LINKS
   -------------------------------------------------------------------------- */

/* Underline that wipes in from the left. */
.td-link {
	background-image: linear-gradient(var(--td-accent), var(--td-accent));
	background-position: 0 100%;
	background-repeat: no-repeat;
	background-size: 0% 1px;
	padding-bottom: 2px;
	text-decoration: none;
	transition:
		background-size var(--td-t-standard) var(--td-ease-out),
		color var(--td-t-micro) var(--td-ease);
}

.td-link:hover,
.td-link:focus-visible { background-size: 100% 1px; }

/* Two-layer swap: the label slides up and a duplicate rises to replace it. */
.td-swap {
	display: inline-grid;
	overflow: hidden;
	vertical-align: bottom;
}

.td-swap__a,
.td-swap__b {
	grid-area: 1 / 1;
	transition: transform var(--td-t-standard) var(--td-ease-out);
}

.td-swap__b {
	color: var(--td-accent);
	transform: translate3d(0, 100%, 0);
}

.td-swap:hover .td-swap__a,
a:hover .td-swap .td-swap__a,
.td-hover-card:hover .td-swap__a { transform: translate3d(0, -100%, 0); }

.td-swap:hover .td-swap__b,
a:hover .td-swap .td-swap__b,
.td-hover-card:hover .td-swap__b { transform: translate3d(0, 0, 0); }

/* -----------------------------------------------------------------------------
   5. SCROLL-LINKED PROGRESS
   Used by the lifecycle rail. JS writes --td-progress (0-1); browsers with
   scroll-driven animation support get it natively and skip the listener.
   -------------------------------------------------------------------------- */

.td-progress-rail { position: relative; }

.td-progress-rail__fill {
	background: var(--td-grad-brand);
	transform-origin: left center;
	transform: scaleX(var(--td-progress, 0));
	transition: transform 120ms linear;
}

.td-progress-rail--vertical .td-progress-rail__fill {
	transform: scaleY(var(--td-progress, 0));
	transform-origin: center top;
}

/* -----------------------------------------------------------------------------
   6. AMBIENT
   -------------------------------------------------------------------------- */

@keyframes td-float {
	0%, 100% { transform: translate3d(0, 0, 0) rotate(0deg); }
	50%      { transform: translate3d(0, -14px, 0) rotate(1.2deg); }
}

@keyframes td-drift {
	0%, 100% { transform: translate3d(0, 0, 0) scale(1); opacity: 0.55; }
	50%      { transform: translate3d(2%, -3%, 0) scale(1.06); opacity: 0.8; }
}

@keyframes td-pulse-ring {
	0%   { opacity: 0.5; transform: scale(0.94); }
	70%  { opacity: 0; transform: scale(1.18); }
	100% { opacity: 0; transform: scale(1.18); }
}

@keyframes td-marquee {
	from { transform: translate3d(0, 0, 0); }
	to   { transform: translate3d(-50%, 0, 0); }
}

@keyframes td-spin-slow {
	to { transform: rotate(360deg); }
}

@keyframes td-fade-up {
	from { opacity: 0; transform: translate3d(0, 12px, 0); }
	to   { opacity: 1; transform: none; }
}

.td-float { animation: td-float 7s ease-in-out infinite; }
.td-drift { animation: td-drift 16s ease-in-out infinite; }

/* -----------------------------------------------------------------------------
   7. REDUCED MOTION
   Spec 3 / 22: disable parallax, continuous rotation and large transforms.
   Content must arrive at its final state immediately - never stay hidden.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
	.js-motion [data-reveal],
	.js-motion [data-reveal].is-revealed {
		clip-path: none !important;
		filter: none !important;
		opacity: 1 !important;
		transform: none !important;
		transition: opacity 1ms linear !important;
	}

	.js-motion .td-line__inner {
		transform: none !important;
		transition: none !important;
	}

	.td-line { overflow: visible; }

	.td-hover-card,
	.td-hover-card:hover,
	.td-hover-card:focus-within {
		transform: none !important;
	}

	.td-hover-card::after { display: none; }

	.td-hover-card:hover .td-hover-media img,
	.td-hover-card:focus-within .td-hover-media img { transform: none; }

	.td-arrow,
	.td-swap__a,
	.td-swap__b { transition-duration: 1ms !important; }

	.td-float,
	.td-drift,
	.td-shimmer-once.is-revealed,
	[class*="td-marquee"] > * {
		animation: none !important;
	}

	*,
	*::before,
	*::after {
		animation-duration: 1ms !important;
		animation-iteration-count: 1 !important;
		scroll-behavior: auto !important;
		transition-duration: 120ms !important;
	}
}
