/**
 * Marquee
 *
 * The scrolling-row mechanism shared by every block that has one — currently
 * Image Slider and Card slider. Registered as its own style handle in
 * inc/enqueue.php and named in each block's block.json, so it stays a single
 * source of truth without loading on pages that have no marquee.
 *
 * Blocks bring their own cell contents; this file owns the track, the drift,
 * the pause states and how wide a cell is.
 *
 * @package Norwegian_Flagstone
 */

.nf-marquee {
	--nf-marquee-gap: clamp(0.5rem, 1.5vw, 1.25rem); /* 8 → 20px */

	/* Width the "cells in view" count is measured against. */
	--nf-marquee-viewport: 100vw;

	/* Defaults mirror the Large size below. */
	--nf-marquee-in-view: 3.75;
	--nf-marquee-min-width: 17rem;
	--nf-marquee-max-width: 30rem;

	/*
	 * Cell width is driven by how many should be in view, because on a
	 * full-bleed row that is what decides how big they look. 3.75 means three
	 * whole cells and three quarters of the next, which is the cue that the row
	 * keeps going. The clamp floor is what stops a phone showing four slivers,
	 * so no media query is needed for it.
	 */
	--nf-marquee-cell-width: clamp(
		var(--nf-marquee-min-width),
		calc(var(--nf-marquee-viewport) / var(--nf-marquee-in-view) - var(--nf-marquee-gap)),
		var(--nf-marquee-max-width)
	);
}

/* Size --------------------------------------------------------------------- */

.nf-marquee--size-l {
	--nf-marquee-in-view: 3.75;
	--nf-marquee-min-width: 17rem;
	--nf-marquee-max-width: 30rem;
}

.nf-marquee--size-m {
	--nf-marquee-in-view: 4.75;
	--nf-marquee-min-width: 15rem;
	--nf-marquee-max-width: 24rem;
}

.nf-marquee--size-s {
	--nf-marquee-in-view: 6.75;
	--nf-marquee-min-width: 12rem;
	--nf-marquee-max-width: 18rem;
}

/* Track width -------------------------------------------------------------- */

.nf-marquee--w-full {
	--nf-marquee-viewport: 100vw;
}

.nf-marquee--w-container {
	--nf-marquee-viewport: min(100vw - (var(--nf-gutter) * 2), var(--nf-container));
}

.nf-marquee--w-content {
	--nf-marquee-viewport: min(100vw - (var(--nf-gutter) * 2), var(--nf-content));
}

/* Track -------------------------------------------------------------------- */

.nf-marquee__track {
	display: flex;

	/* Keeps a sideways flick from turning into a browser back gesture. */
	overscroll-behavior-x: contain;
	overflow-x: auto;
	overflow-y: hidden;

	/* Our own scrollLeft writes must never be smooth-animated. */
	scroll-behavior: auto;

	/* The scrollbar would sit under the row and jitter as it auto-scrolls. */
	scrollbar-width: none;
}

.nf-marquee__track::-webkit-scrollbar {
	display: none;
}

.nf-marquee__track:focus-visible {
	outline: 2px solid var(--nf-color-accent);
	outline-offset: 4px;
}

/* Only offer the grab cursor where dragging actually applies. */
@media (hover: hover) and (pointer: fine) {

	.nf-marquee__track {
		cursor: grab;
	}

	.nf-marquee.is-dragging .nf-marquee__track {
		cursor: grabbing;
	}
}

/*
 * While dragging, stop the contents from being selected or dragged off as
 * files.
 */
.nf-marquee.is-dragging .nf-marquee__track {
	user-select: none;
}

.nf-marquee.is-dragging img {
	pointer-events: none;
}

.nf-marquee__list {
	display: flex;
	flex: 0 0 auto;
	gap: var(--nf-marquee-gap);
	list-style: none;
	margin: 0;
	padding: 0;
}

.nf-marquee__cell {
	flex: 0 0 auto;
	margin: 0;
	width: var(--nf-marquee-cell-width);
}

/* Static ------------------------------------------------------------------- */

/*
 * A row with auto-scroll off, inside a container rather than bled to the edge,
 * is not a marquee any more — it is a row of cards. The fixed cell width exists
 * to leave part of the next cell showing, which is the cue that the row keeps
 * going; with nothing moving and a visible right-hand edge that cue is just a
 * gap, so the cells take the space instead.
 *
 * `flex-grow: 1` with the designed width as the basis, and no shrink: few
 * enough cells and they spread to fill the container; too many and they hold
 * their size and overflow, leaving the track to scroll as before. Added by the
 * block template — see cards.php.
 */
.nf-marquee--static .nf-marquee__strip,
.nf-marquee--static .nf-marquee__list {
	flex: 1 1 auto;

	/* Floor, not a cap: the list still grows past it when the cells overflow. */
	min-width: 100%;
}

.nf-marquee--static .nf-marquee__cell {
	flex: 1 0 var(--nf-marquee-cell-width);
	width: auto;
}

/*
 * Nothing to grab. Beats the grab cursor inside the hover media query on
 * specificity, so it holds wherever that rule applies.
 */
.nf-marquee--static .nf-marquee__track {
	cursor: auto;
}

/* Auto-scroll -------------------------------------------------------------- */

/*
 * The drift is a composited CSS animation on the strip, not a per-frame
 * scrollLeft write.
 *
 * Scroll offsets are quantised, so at a slow 30px/s — half a pixel per frame —
 * scrolling advances in visible 1px steps and reads as stutter. A transform is
 * subpixel and runs on the compositor, so it stays smooth at any speed and
 * survives main-thread work such as image decoding.
 *
 * The track is still a real scroll container: user interaction moves
 * scrollLeft, and marquee.js hands the animation's offset over to it when a
 * drag starts, so the two never fight.
 */
.nf-marquee__strip {
	display: flex;
	flex: 0 0 auto;
	gap: var(--nf-marquee-gap);
}

.nf-marquee.is-animating .nf-marquee__strip {
	animation: nf-marquee var(--nf-marquee-duration, 40s) linear infinite;
	will-change: transform;
}

.nf-marquee.is-animating.is-reverse .nf-marquee__strip {
	animation-direction: reverse;
}

.nf-marquee.is-paused .nf-marquee__strip {
	animation-play-state: paused;
}

@keyframes nf-marquee {

	from {
		transform: translate3d(0, 0, 0);
	}

	to {
		transform: translate3d(calc(var(--nf-marquee-distance, 0px) * -1), 0, 0);
	}
}

@media (prefers-reduced-motion: reduce) {

	.nf-marquee.is-animating .nf-marquee__strip {
		animation: none;
		will-change: auto;
	}
}
