/**
 * Motion & interaction layer for The Message International.
 *
 * Follows the "animate" skill (Emil Kowalski): animate only transform/opacity,
 * ease-out for enters + hover lifts, quick presses, a 200ms sweet spot, and a
 * full prefers-reduced-motion opt-out at the bottom. Easing/duration tokens
 * live in colors.css.
 */

/* ------------------------------------------------------------- Post cards */
/* Hover/press use the independent translate + scale properties (not transform)
   so they compose with the transform-based scroll-in entrance instead of
   clobbering it. */
.tmi-card {
	transition: translate var(--tmi-dur-hover) var(--ease-out-quint),
		scale var(--tmi-dur-hover) var(--ease-out-quint),
		box-shadow var(--tmi-dur-hover) var(--ease-out-quint);
}

.tmi-post-card:hover,
.tmi-post-card:focus-within {
	translate: 0 -6px;
	box-shadow: 0 16px 32px rgba(9, 11, 12, 0.16);
}

/* Quick press feedback (skill: button press ~scale 0.97). */
.tmi-post-card:active {
	translate: 0 -2px;
	scale: 0.995;
	transition-duration: var(--tmi-dur-press);
}

.tmi-card.is-dark:hover,
.tmi-card.is-dark:focus-within {
	box-shadow: 0 16px 32px rgba(9, 11, 12, 0.4);
}

.tmi-card-image img {
	transition: transform 0.4s var(--ease-out-quint);
}

.tmi-post-card:hover .tmi-card-image img,
.tmi-post-card:focus-within .tmi-card-image img {
	transform: scale(1.05);
}

.tmi-card-title {
	transition: color 0.15s ease;
}

.tmi-post-card:hover .tmi-card-title {
	color: var(--tmi-green);
}

.tmi-card.is-dark:hover .tmi-card-title {
	color: var(--tmi-amber);
}

/* ---------------------------------------------------------------- Buttons */
.tmi-button {
	transition: transform var(--tmi-dur-hover) var(--ease-out-quint),
		background-color var(--tmi-dur-hover) var(--ease-out-cubic),
		box-shadow var(--tmi-dur-hover) var(--ease-out-quint);
}

.tmi-button:hover {
	background: var(--tmi-dark-800);
	transform: translateY(-2px);
	box-shadow: 0 8px 20px rgba(9, 11, 12, 0.24);
}

.tmi-button:active {
	transform: scale(0.97);
	box-shadow: none;
	transition-duration: var(--tmi-dur-press);
}

.tmi-button img {
	transition: transform var(--tmi-dur-hover) var(--ease-out-quint);
}

.tmi-button:hover img {
	transform: translateX(3px);
}

/* ------------------------------------------------- Header menu / search UI */
.tmi-menu-button,
.tmi-search-button {
	border-radius: 8px;
	transition: background-color 0.15s ease, transform var(--tmi-dur-press) var(--ease-out-cubic);
}

.tmi-menu-button:hover,
.tmi-search-button:hover {
	background: var(--tmi-dark-100);
}

.tmi-menu-button:active,
.tmi-search-button:active {
	transform: scale(0.94);
}

.tmi-header-search {
	position: relative;
	width: min(100%, 560px);
	margin: 0 auto;
	animation: tmi-fade-in 0.2s ease-out;
}

.tmi-header-search__bar {
	display: flex;
	gap: 12px;
	align-items: center;
	padding: 8px 8px 8px 16px;
	background: var(--tmi-white);
	border: 1px solid var(--tmi-dark-200);
	border-radius: 8px;
	box-shadow: var(--tmi-soft-shadow);
}

.tmi-header-search[hidden] {
	display: none;
}

.tmi-header-search input {
	flex: 1;
	min-width: 0;
	border: 0;
	background: transparent;
	color: var(--tmi-dark);
	font: 500 16px/1.35 var(--tmi-font-sans);
	letter-spacing: -0.04em;
}

.tmi-header-search input:focus {
	outline: none;
}

.tmi-header-search__bar > button {
	padding: 10px 20px;
	border: 0;
	border-radius: 6px;
	background: var(--tmi-dark);
	color: var(--tmi-white);
	cursor: pointer;
	transition: background-color 0.2s ease;
}

.tmi-header-search__bar > button:hover {
	background: var(--tmi-green);
}

/* --------------------------------------------------------------- Nav items */
.tmi-nav-item {
	transition: color 0.2s ease, background-color 0.2s ease;
}

.tmi-nav-item:hover {
	color: var(--tmi-dark);
	background: var(--tmi-dark-100);
}

.tmi-nav-dot {
	transition: transform 0.2s ease, background-color 0.2s ease, box-shadow 0.2s ease;
}

.tmi-nav-item:hover .tmi-nav-dot {
	background: var(--tmi-accent-green);
	transform: scale(1.35);
}

/* ---------------------------------------------------------- Live news bar */
.tmi-live-label span {
	animation: tmi-pulse 1.6s ease-in-out infinite;
}

.tmi-live-track {
	display: inline-flex;
	align-items: center;
	gap: 24px;
	white-space: nowrap;
	will-change: transform;
	animation: tmi-marquee 32s linear infinite;
}

.tmi-live-bar:hover .tmi-live-track {
	animation-play-state: paused;
}

@keyframes tmi-marquee {
	from {
		transform: translateX(0);
	}
	to {
		transform: translateX(-50%);
	}
}

@keyframes tmi-pulse {
	0%,
	100% {
		box-shadow: 0 0 0 0 rgba(0, 214, 111, 0.5);
	}
	50% {
		box-shadow: 0 0 0 6px rgba(0, 214, 111, 0);
	}
}

@keyframes tmi-fade-in {
	from {
		opacity: 0;
		transform: translateY(-6px);
	}
	to {
		opacity: 1;
		transform: none;
	}
}

/* -------------------------------------------------------------- Topic cards */
.tmi-topic-card {
	transition: translate var(--tmi-dur-hover) var(--ease-out-quint),
		scale var(--tmi-dur-hover) var(--ease-out-quint),
		box-shadow var(--tmi-dur-hover) var(--ease-out-quint);
}

.tmi-topic-card:hover {
	position: relative;
	z-index: 1;
	translate: 0 -6px;
	box-shadow: 0 16px 30px rgba(9, 11, 12, 0.12);
}

.tmi-topic-card:active {
	translate: 0 -2px;
	scale: 0.99;
	transition-duration: var(--tmi-dur-press);
}

.tmi-topic-icon {
	transition: background-color 0.25s ease, transform 0.25s ease;
}

.tmi-topic-card:hover .tmi-topic-icon {
	background: var(--tmi-green);
	transform: rotate(-4deg) scale(1.05);
}

.tmi-topic-icon img {
	transition: filter 0.25s ease;
}

.tmi-topic-card:hover .tmi-topic-icon img {
	filter: brightness(0) invert(1);
}

/* ---------------------------------------------------------- Topic section */
.tmi-view-all {
	transition: color 0.2s ease;
}

.tmi-view-all:hover {
	color: var(--tmi-dark);
}

.tmi-view-all img {
	transition: transform 0.2s ease;
}

.tmi-view-all:hover img {
	transform: translate(2px, -2px);
}

/* ----------------------------------------------------------- Contributors */
.tmi-contributor {
	transition: translate var(--tmi-dur-hover) var(--ease-out-quint),
		scale var(--tmi-dur-hover) var(--ease-out-quint),
		box-shadow var(--tmi-dur-hover) var(--ease-out-quint);
}

.tmi-contributor:hover {
	position: relative;
	z-index: 1;
	translate: 0 -6px;
	box-shadow: 0 16px 30px rgba(9, 11, 12, 0.12);
}

.tmi-contributor-avatar {
	transition: transform 0.25s ease;
}

.tmi-contributor:hover .tmi-contributor-avatar {
	transform: scale(1.06);
}

.tmi-rating img {
	transition: transform 0.2s ease;
}

.tmi-contributor:hover .tmi-rating img {
	transform: scale(1.1);
}

/* -------------------------------------------------------- Find out more */
/* The card fan owns its own transform transition (see the block stylesheet);
   here we only deepen the shadow on hover. */
.tmi-find-card:hover {
	box-shadow: 0 22px 48px rgba(9, 11, 12, 0.3);
}

/* Arrows keep their translateY(-50%) centring, so hover nudges scale on top of
   it rather than replacing the transform. */
.tmi-find-arrow {
	transition: transform 0.2s ease, opacity 0.2s ease;
	opacity: 0.75;
}

.tmi-find-arrow:hover {
	opacity: 1;
	transform: translateY(-50%) scale(1.12);
}

.tmi-find-arrow.is-left:hover {
	transform: translateY(-50%) scale(1.12) translateX(-3px);
}

.tmi-find-arrow.is-right:hover {
	transform: translateY(-50%) scale(1.12) translateX(3px);
}

.tmi-find-arrow:active {
	transform: translateY(-50%) scale(0.96);
}

/* -------------------------------------------------------------- Subscribe */
.tmi-subscribe-form {
	transition: box-shadow 0.2s ease;
}

.tmi-subscribe-form:focus-within {
	box-shadow: 0 0 0 2px var(--tmi-accent-green);
}

.tmi-subscribe-form button {
	transition: background-color 0.15s ease,
		transform var(--tmi-dur-hover) var(--ease-out-quint);
}

.tmi-subscribe-form button:hover {
	background: var(--tmi-green);
	transform: translateY(-1px);
}

.tmi-subscribe-form button:active {
	transform: scale(0.97);
	transition-duration: var(--tmi-dur-press);
}

/* ----------------------------------------------------------------- Footer */
.tmi-footer a {
	transition: color 0.2s ease;
}

.tmi-footer-links a:hover,
.tmi-footer-bottom a:hover {
	color: var(--tmi-white);
}

.tmi-socials a {
	transition: transform var(--tmi-dur-hover) var(--ease-out-quint), opacity 0.15s ease;
}

.tmi-socials a:hover {
	transform: translateY(-3px) scale(1.1);
}

.tmi-socials a:active {
	transform: translateY(-1px) scale(0.96);
	transition-duration: var(--tmi-dur-press);
}

/* ------------------------------------------------------------------- Logo */
@media (hover: hover) and (min-width: 901px) {
	.tmi-logo {
		transition: transform 0.3s ease;
	}

	.tmi-logo:hover {
		transform: scale(1.02);
	}
}

/* ----------------------------------------- Scroll-in entrance reveals -----
   The skill's "fade in on mount" pattern, done with scroll-driven CSS so it
   works on this server-rendered theme (no JS). Each element eases in as it
   scrolls into view; the timeline is per-element so rows stagger naturally as
   you scroll. Directions vary by element (rise, slide from left/right, pop,
   zoom) to give the page character. Ranges run from the element entering the
   viewport (entry 0%) well up into it (cover 30-38%) so the motion is slow and
   clearly visible rather than finishing off-screen. Progressive enhancement:
   without scroll-driven support the content is simply shown.

   Cards animate `transform` here while their hover-lift uses the independent
   `translate`/`scale` properties, so entrance and hover compose cleanly. */
@keyframes tmi-rise-reveal {
	from {
		opacity: 0;
		transform: translateY(48px);
	}
	to {
		opacity: 1;
		transform: none;
	}
}

@keyframes tmi-slide-in-left {
	from {
		opacity: 0;
		transform: translateX(-72px);
	}
	to {
		opacity: 1;
		transform: none;
	}
}

@keyframes tmi-slide-in-right {
	from {
		opacity: 0;
		transform: translateX(72px);
	}
	to {
		opacity: 1;
		transform: none;
	}
}

@keyframes tmi-pop-reveal {
	from {
		opacity: 0;
		transform: scale(0.8) translateY(24px);
	}
	to {
		opacity: 1;
		transform: none;
	}
}

@keyframes tmi-zoom-fade {
	from {
		opacity: 0;
		transform: scale(1.08);
	}
	to {
		opacity: 1;
		transform: none;
	}
}

@supports (animation-timeline: view()) {
	/* Desktop only. These use scroll-driven timelines, which iOS Safari and
	   older browsers don't support — so the whole page would sit static on those
	   mobiles. Mobile gets an equivalent JS-triggered entrance instead (see
	   .tmi-m-reveal below + initMobileReveal in main.js), which is why these are
	   fenced to the desktop width to avoid both firing on the same element. */
	@media (min-width: 1101px) {
		/* Section headings drop in from above, growing from a slight zoom. */
		.tmi-section-heading {
			animation: tmi-zoom-fade linear both;
			animation-timeline: view();
			animation-range: entry 0% cover 26%;
		}

		/* Topic section header slides in from the left. */
		.tmi-topic-section-head {
			animation: tmi-slide-in-left linear both;
			animation-timeline: view();
			animation-range: entry 0% cover 30%;
		}

		/* Subscribe: copy enters from the left, the form answers from the right. */
		.tmi-subscribe-copy {
			animation: tmi-slide-in-left linear both;
			animation-timeline: view();
			animation-range: entry 0% cover 34%;
		}

		.tmi-subscribe-form {
			animation: tmi-slide-in-right linear both;
			animation-timeline: view();
			animation-range: entry 0% cover 34%;
		}

		/* Footer: brand from the left and each link column rises. */
		.tmi-footer-brand {
			animation: tmi-slide-in-left linear both;
			animation-timeline: view();
			animation-range: entry 0% cover 36%;
		}

		.tmi-footer-links > nav {
			animation: tmi-rise-reveal linear both;
			animation-timeline: view();
			animation-range: entry 0% cover 38%;
		}

		/* Post cards alternate: odd columns swing in from the left, even from
		   the right, so a row assembles from both sides toward the centre. */
		.tmi-post-card:nth-child(odd) {
			animation: tmi-slide-in-left linear both;
			animation-timeline: view();
			animation-range: entry 0% cover 32%;
		}

		.tmi-post-card:nth-child(even) {
			animation: tmi-slide-in-right linear both;
			animation-timeline: view();
			animation-range: entry 0% cover 32%;
		}

		/* Browse-by-topics cards slide in from the right. */
		.tmi-topic-card {
			animation: tmi-slide-in-right linear both;
			animation-timeline: view();
			animation-range: entry 0% cover 34%;
		}

		/* Contributors pop up with a spring-like scale. */
		.tmi-contributor {
			animation: tmi-pop-reveal linear both;
			animation-timeline: view();
			animation-range: entry 0% cover 30%;
		}
	}
}

/* --------------------------------------------------- Mobile menu toggling */
@media (max-width: 900px) {
	.tmi-header-nav {
		display: none;
	}

	.tmi-header.is-menu-open .tmi-header-nav {
		display: grid;
		grid-template-columns: 1fr 1fr;
		gap: 2px 10px;
		width: 100%;
		animation: tmi-fade-in 0.25s ease-out;
	}

	.tmi-header.is-menu-open .tmi-nav-item {
		justify-content: flex-start;
	}

	.tmi-header.is-menu-open .tmi-search-button {
		grid-column: 1 / -1;
		justify-content: flex-start;
	}
}

/* ---------------------------------- Tablet + phone "focus" carousels ------
   On tablets and phones the article-card grids become horizontal, snap-
   scrolling carousels: cards peek at the edges and the one nearest centre
   scales up and brightens (scroll-driven, no JS). Card width steps up as the
   screen narrows. Falls back to a plain snap carousel without scroll-driven
   animation support. */
@media (max-width: 1100px) {
	.tmi-hero-grid,
	.tmi-topic-featured-grid,
	.tmi-topic-small-grid {
		display: flex;
		flex-wrap: nowrap;
		gap: 16px;
		overflow-x: auto;
		overflow-y: hidden;
		scroll-snap-type: x mandatory;
		scroll-snap-stop: always;
		scroll-padding-inline: 9%;
		padding: 12px 0 22px;
		scrollbar-width: none;
		-webkit-overflow-scrolling: touch;
	}

	.tmi-hero-grid::-webkit-scrollbar,
	.tmi-topic-featured-grid::-webkit-scrollbar,
	.tmi-topic-small-grid::-webkit-scrollbar {
		display: none;
	}

	.tmi-hero-grid > .tmi-card,
	.tmi-topic-featured-grid > .tmi-card,
	.tmi-topic-small-grid > .tmi-card {
		flex: 0 0 54%;
		scroll-snap-align: center;
		margin-top: 0;
	}

	/* Uniform card image height so mixed variants line up in the carousel. */
	.tmi-hero-grid .tmi-card-image,
	.tmi-topic-featured-grid .tmi-card-image,
	.tmi-topic-small-grid .tmi-card-image {
		height: 240px;
	}

	/* Left-align the featured card like the rest inside the carousel. */
	.tmi-hero-grid .tmi-card.is-featured .tmi-card-body,
	.tmi-topic-featured-grid .tmi-card.is-featured .tmi-card-body {
		align-items: flex-start;
		text-align: left;
	}

	.tmi-hero-grid .tmi-card.is-featured .tmi-publisher,
	.tmi-topic-featured-grid .tmi-card.is-featured .tmi-publisher {
		justify-content: flex-start;
	}
}

@media (max-width: 700px) {
	.tmi-hero-grid > .tmi-card,
	.tmi-topic-featured-grid > .tmi-card,
	.tmi-topic-small-grid > .tmi-card {
		flex: 0 0 82%;
	}
}

@supports (animation-timeline: view()) {
	@media (max-width: 1100px) {
		.tmi-hero-grid > .tmi-card,
		.tmi-topic-featured-grid > .tmi-card,
		.tmi-topic-small-grid > .tmi-card {
			transform-origin: center;
			animation: tmi-carousel-focus linear both;
			animation-timeline: view(inline);
			animation-range: cover;
		}
	}
}

@keyframes tmi-carousel-focus {
	0%,
	100% {
		transform: scale(0.84);
		opacity: 0.5;
	}
	45%,
	55% {
		transform: scale(1);
		opacity: 1;
	}
}

/* "Browse by topics" shortcut cards: a compact horizontal scroller on tablets
   and phones instead of one tall column. */
@media (max-width: 1100px) {
	.tmi-topic-cards {
		display: flex;
		flex-wrap: nowrap;
		gap: 12px;
		overflow-x: auto;
		overflow-y: hidden;
		scroll-snap-type: x proximity;
		box-shadow: none;
		padding-bottom: 6px;
		scrollbar-width: none;
		-webkit-overflow-scrolling: touch;
	}

	.tmi-topic-cards::-webkit-scrollbar {
		display: none;
	}

	.tmi-topic-card {
		flex: 0 0 210px;
		scroll-snap-align: start;
		box-shadow: var(--tmi-card-shadow);
	}
}

@media (max-width: 560px) {
	.tmi-topic-card {
		flex: 0 0 64%;
	}
}

/* Top contributors: the same focus carousel as the article sections. */
@media (max-width: 1100px) {
	.tmi-contributor-grid {
		display: flex;
		flex-wrap: nowrap;
		gap: 12px;
		overflow-x: auto;
		overflow-y: hidden;
		scroll-snap-type: x mandatory;
		scroll-snap-stop: always;
		scroll-padding-inline: 9%;
		padding: 12px 0 20px;
		scrollbar-width: none;
		-webkit-overflow-scrolling: touch;
	}

	.tmi-contributor-grid::-webkit-scrollbar {
		display: none;
	}

	.tmi-contributor {
		flex: 0 0 46%;
		scroll-snap-align: center;
		transform-origin: center;
	}
}

@media (max-width: 640px) {
	.tmi-contributor {
		flex: 0 0 72%;
	}
}

@supports (animation-timeline: view()) {
	@media (max-width: 1100px) {
		.tmi-contributor {
			animation: tmi-carousel-focus linear both;
			animation-timeline: view(inline);
			animation-range: cover;
		}
	}
}

/* --------------------------- Mobile one-shot entrance (no scroll timeline) ---
   iOS Safari and older browsers don't support scroll-driven timelines, so the
   mobile carousels + reveals above would sit completely static there. This
   JS-triggered entrance works everywhere: main.js adds .tmi-m-reveal on load
   (hiding the block) and .is-inview via IntersectionObserver when the block
   scrolls into view, playing a slow rise + fade. It's applied to headings and
   to the carousel *containers* (not the cards) so it never collides with the
   per-card scroll-focus/coverflow effect on browsers that do support it. The
   entrance uses the independent `translate` property, which composes on top of
   any transform rather than overwriting it. Deliberately unhurried (850ms). */
@media (max-width: 1100px) {
	.tmi-m-reveal {
		opacity: 0;
		translate: 0 46px;
	}

	.tmi-m-reveal.is-inview {
		animation: tmi-mobile-rise 850ms var(--ease-out-quint) both;
	}
}

@keyframes tmi-mobile-rise {
	from {
		opacity: 0;
		translate: 0 46px;
	}
	to {
		opacity: 1;
		translate: 0 0;
	}
}

/* ------------------------------------------------- Reduced-motion opt-out */
@media (prefers-reduced-motion: reduce) {
	*,
	::before,
	::after {
		animation-duration: 0.001ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.001ms !important;
		scroll-behavior: auto !important;
	}

	.tmi-live-track {
		animation: none !important;
	}

	/* Drop carousel focus + scroll-in reveals; show everything statically.
	   (.tmi-find-card is intentionally excluded — the desktop fan needs its
	   transforms; its reduced-motion reset is scoped to mobile in the block CSS.) */
	.tmi-hero-grid > .tmi-card,
	.tmi-topic-featured-grid > .tmi-card,
	.tmi-topic-small-grid > .tmi-card,
	.tmi-post-card,
	.tmi-topic-card,
	.tmi-contributor,
	.tmi-find-stage,
	.tmi-section-heading,
	.tmi-topic-section-head,
	.tmi-subscribe-copy,
	.tmi-subscribe-form,
	.tmi-footer-brand,
	.tmi-footer-links > nav {
		animation: none !important;
		transform: none !important;
		translate: none !important;
		scale: none !important;
		rotate: none !important;
		opacity: 1 !important;
	}
}
