/*
 * Motion.
 *
 * One small kit for the whole site, so that everything moves in the same way:
 * calm, quick, and always arriving gently (a deceleration, never a bounce). The
 * owner asked for an app that feels alive and not a show, so most of this is a
 * fade and a short rise, and nothing is allowed to be loud.
 *
 * What is NOT here, on purpose:
 *
 *   Lifts on hover. A card that jumps up when the mouse passes reads as nervous.
 *   Hover answers with a change of colour; a touch answers with a small press.
 *
 *   Anything that hides words from a search engine, or that is stuck hidden if
 *   the script fails. Content waiting to appear is hidden only while the page's
 *   script is known to be coming (see gks_motion_script in functions.php), and
 *   shown again if it does not.
 *
 *   Anything for a person who has asked their device for less motion. They get
 *   the finished page at once.
 */

:root {
	--gks-dur-fast: 150ms;
	--gks-dur: 250ms;
	--gks-dur-slow: 500ms;
	--gks-ease: cubic-bezier(0.2, 0.7, 0.2, 1);
	--gks-rise: 14px;
}

@keyframes gks-rise {
	from {
		opacity: 0;
		transform: translateY(var(--gks-rise));
	}

	to {
		opacity: 1;
		transform: none;
	}
}

/*
 * Appear once, when scrolled to.
 *
 * Put gks-reveal on a container. Its children rise and fade in one after
 * another the first time it comes into view (motion.js adds is-in), and stay
 * where they are after that. A child that is itself a gks-reveal container does
 * its own children, so nothing is faded twice.
 */
html.gks-js .gks-reveal > :not(.gks-reveal) {
	opacity: 0;
	transform: translateY(var(--gks-rise));
	transition:
		opacity var(--gks-dur-slow) var(--gks-ease),
		transform var(--gks-dur-slow) var(--gks-ease);
}

html.gks-js .gks-reveal.is-in > :not(.gks-reveal) {
	opacity: 1;
	transform: none;
}

html.gks-js .gks-reveal.is-in > :nth-child(2) { transition-delay: 70ms; }
html.gks-js .gks-reveal.is-in > :nth-child(3) { transition-delay: 140ms; }
html.gks-js .gks-reveal.is-in > :nth-child(4) { transition-delay: 210ms; }
html.gks-js .gks-reveal.is-in > :nth-child(5) { transition-delay: 280ms; }
html.gks-js .gks-reveal.is-in > :nth-child(6) { transition-delay: 350ms; }
html.gks-js .gks-reveal.is-in > :nth-child(n + 7) { transition-delay: 420ms; }

/*
 * A page swapped in by the shell arrives with a short fade, so moving about the
 * site feels like moving between screens and not like a flicker. shell.js adds
 * gks-swapped after the first swap, so the page that was loaded the ordinary way
 * does not do it, and every new <main> after that does. Opacity only: what is
 * inside has its own movement and this must not fight it.
 */
.gks-swapped #gks-content { animation: gks-page-in var(--gks-dur) ease-out; }

@keyframes gks-page-in {
	from { opacity: 0; }
	to { opacity: 1; }
}

/*
 * The player bar slides up from the bottom edge when it appears, and again when
 * it comes out of a song page to stay pinned. Not when it is docked into a page
 * (there it sits in the flow and a slide would be a jump).
 */
.gks-bar:not(.is-docked):not([hidden]) { animation: gks-bar-in var(--gks-dur-slow) var(--gks-ease); }

@keyframes gks-bar-in {
	from { transform: translateY(100%); }
	to { transform: none; }
}

/*
 * The play button breathes while a recording that was asked to play is still
 * arriving (player.js adds is-buffering), so a long file on a slow line does not
 * look like a button that did nothing.
 */
.gks-bar.is-buffering [data-gks-bar-play] { animation: gks-breathe 1.1s ease-in-out infinite; }

@keyframes gks-breathe {
	0%, 100% { opacity: 1; }
	50% { opacity: 0.4; }
}

@media (prefers-reduced-motion: reduce) {
	.gks-bar.is-buffering [data-gks-bar-play] { animation: none; opacity: 0.6; }
}

/*
 * A touch answers with a small press. Only on a screen with no hover, since
 * on one that has it the colour already says "this is what you are pointing at".
 */
@media (hover: none) {
	.gks-lang:active,
	.gks-card__link:active,
	.gks-button:active {
		transform: scale(0.985);
	}
}

.gks-button {
	transition: transform var(--gks-dur-fast) var(--gks-ease), filter var(--gks-dur-fast) ease;
}

/* Less motion asked for, and paper: the finished page, now. */
@media (prefers-reduced-motion: reduce), print {
	html.gks-js .gks-reveal > :not(.gks-reveal) {
		opacity: 1;
		transform: none;
		transition: none;
	}
}
