/* Block: Slider (acf/slider)
   ---------------------------------------------------------------------------
   Figma "RDV Updates", home frames 1:5 (desktop) and 2:1090 (iPhone, 440px).

   GEOMETRY. Every size lives in the custom properties at the top. slider.js
   only measures the result (the .slider--frame ruler and a card's width), so
   a size change here needs no JS change.
     desktop  cards 427 x 616, the active one 697 wide; the active card and
              the one after it are centred as a pair, which leaves a card
              peeking in at each edge (Figma: 274px / 277px at 1728).
              The sizes scale with the viewport below 1728 (the vw values
              are the Figma's px / 1728) and stop growing above it.
     mobile   one card, centred, neighbours peeking (Figma: 327 x 616 at 440)

   TWO MODES. Before slider.js runs (no JS, and always in the editor canvas)
   the track is a native horizontal scroller with scroll-snap, so every slide
   is still reachable. slider.js adds .is-ready and the track is moved by
   transform instead, with clones on both sides for the endless loop.

   THE MOTION is the site's reveal move (see "Scroll reveal" in style.css).
     - entrance: the cards start spread apart and close up on the active one
       (slider-assemble below)
     - navigation: the cards just slide, on the reveal curve (--slider-ease)
   Until 2026-10-07 the gaps between the cards opened while the track crept
   on an ease-in quart, then slammed shut with a small recoil. Dapper found
   that "a little too playful — can we just have them slide", so the gaps and
   the recoil are gone. The quart went with them: without the gaps filling
   its ~400ms creep, a click looked unanswered.
--------------------------------------------------------------------------- */

.slider--block {
	--slider-gap: 18px;
	--slider-cut: 10px;          /* card + arrow chamfer, as in the Figma */
	--slider-accent: #8a303a;    /* progress bar + arrows (Figma "RDV Updates") */
	--slider-ms: 800ms;          /* one move; the track lands at 86% of it */
	--slider-ease: var(--rdv-snap-ease, cubic-bezier(0.2, 0.1, 0.75, 0.35)); /* moves from the first frame */
	--slider-seam: 24px;         /* how far apart the cards start on the entrance */
	--slider-w: min(calc(100vw - 113px), 420px); /* 327 at 440 */
	--slider-w-active: var(--slider-w);
	--slider-h: min(calc(var(--slider-w) * 1.884), 616px); /* the Figma's 327 x 616 */
	--slider-frame: var(--slider-w-active); /* what gets centred */

	position: relative;
	/* Full-bleed track: the cards must never widen the page. clip, not just
	   hidden: a hidden box can still be scrolled (a mouse drag's autoscroll
	   moved this one 295px sideways in testing), which shifts every card off
	   the position slider.js computed. hidden stays as the fallback. */
	overflow: hidden;
	overflow: clip;
	padding-block: var(--wp--preset--spacing--large);
	color: var(--wp--preset--color--cream, #efede6);
}

@media (min-width: 992px) {
	.slider--block {
		--slider-seam: 48px;
		--slider-w: clamp(260px, 24.71vw, 427px);
		--slider-w-active: clamp(420px, 40.34vw, 697px);
		--slider-h: clamp(440px, 35.65vw, 616px);
		--slider-frame: calc(var(--slider-w-active) + var(--slider-gap) + var(--slider-w));
	}

	.slider--block.slider--single {
		--slider-frame: var(--slider-w-active);
	}

	/* "All the same" widths (the article gallery, Frame 7): every card at the
	   narrow width, the front one centred on its own. slider.js measures a
	   card for its step, so it needs no change. */
	.slider--block.slider--equal {
		--slider-w-active: var(--slider-w);
		--slider-frame: var(--slider-w);
	}
}

/* Caption below the image: a shorter picture, so the card with its caption
   stands about as tall as an overlay card. */
.slider--text-below {
	--slider-media-h: calc(var(--slider-h) * 0.75);
}

/* ------------------------------------------------------------- the track */

.slider--viewport {
	position: relative;
}

/* Invisible ruler: its left edge is where the active card sits. */
.slider--frame {
	position: absolute;
	top: 0;
	left: 50%;
	width: var(--slider-frame);
	height: 0;
	margin-left: calc(var(--slider-frame) / -2);
	visibility: hidden;
	pointer-events: none;
}

/* Without JS: a scroller whose first card starts at the ruler. */
.slider--track {
	display: flex;
	align-items: flex-start;
	gap: var(--slider-gap);
	padding-inline: calc((100% - var(--slider-frame)) / 2);
	overflow-x: auto;
	overscroll-behavior-x: contain;
	scroll-snap-type: x mandatory;
	scroll-padding-inline: calc((100% - var(--slider-frame)) / 2);
	scrollbar-width: thin;
}

.slider--slide {
	position: relative;
	flex: 0 0 var(--slider-w);
	min-width: 0;
	scroll-snap-align: start;
}

.slider--slide.is-active {
	flex-basis: var(--slider-w-active);
}

/* With JS: the track is moved, not scrolled. pan-y hands vertical swipes to
   the page and horizontal ones to slider.js. */
.slider--block.is-ready .slider--track {
	padding-inline: 0;
	overflow: visible;
	scroll-snap-type: none;
	touch-action: pan-y;
	user-select: none;
	-webkit-user-select: none;
	transition: transform calc(var(--slider-ms) * 0.86) var(--slider-ease);
}

.slider--block.is-ready .slider--slide {
	transition: flex-basis calc(var(--slider-ms) * 0.86) var(--slider-ease);
}

.slider--block.is-ready .slider--slide:not(.is-active) {
	cursor: pointer; /* a click on a peeking card brings it in */
}

.slider--block.is-dragging .slider--track {
	cursor: grabbing;
}

/* Loop wrap and resize: re-seat the track with no motion at all. */
.slider--block.is-dragging .slider--track,
.slider--block.is-jumping .slider--track,
.slider--block.is-jumping .slider--slide,
.slider--block.is-jumping .slider--thumb {
	transition: none;
}

/* ------------------------------------------------------------- the cards */

.slider--media {
	position: relative;
	height: var(--slider-media-h, var(--slider-h));
	overflow: hidden;
	background-color: #0d0d14; /* holds the card's shape while the image loads */
	clip-path: polygon(
		var(--slider-cut) 0, calc(100% - var(--slider-cut)) 0,
		100% var(--slider-cut), 100% calc(100% - var(--slider-cut)),
		calc(100% - var(--slider-cut)) 100%, var(--slider-cut) 100%,
		0 calc(100% - var(--slider-cut)), 0 var(--slider-cut)
	);
}

.slider--image {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	-webkit-user-drag: none;
}

/* A slide's video (Chris Yates, 2026-10-26) lies over its image. slider.js
   plays only the front card's and tags it .is-playing while it plays; until
   then the image is the still, so the cards to the sides, the editor and
   reduced motion all show the picture. A video with no image shows its first
   frame. Under the overlay's scrim, which comes later in the box. */
.slider--video {
	position: absolute;
	inset: 0;
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	pointer-events: none;
}

.slider--image ~ .slider--video {
	opacity: 0;
	transition: opacity 0.4s ease;
}

.slider--image ~ .slider--video.is-playing {
	opacity: 1;
}

.slider--title {
	margin: 0;
	font-family: var(--wp--preset--font-family--oxanium, "Oxanium", sans-serif);
	font-size: 43px;
	font-weight: 600;
	line-height: 1;
	letter-spacing: 0.0065em;
	color: inherit;
}

.slider--text {
	max-width: 360px;
	margin: 0;
	font-family: var(--wp--preset--font-family--roboto, "Roboto", sans-serif);
	font-size: 21px;
	line-height: 1.24;
	letter-spacing: 0.03em;
}

/* Desktop type scales with the cards (the Figma's 43px at 1728), so a
   title like "Direct-To-Device" stays on one line on a 1440 laptop. */
@media (min-width: 992px) {
	.slider--title {
		font-size: clamp(34px, 2.49vw, 43px);
	}

	.slider--text {
		font-size: clamp(21px, 1.505vw, 26px);
		line-height: max(1.08em, 26px); /* the Figma's 26/28 at full size, never tighter than mobile's 26px */
		letter-spacing: 0.024em;
	}
}

/* Over the image: title at the top, text at the bottom, and the image
   darkened behind both. The Figma's images sit under a near-even 35% black
   (measured against the Defense source, band by band); the ends are a little
   deeper here so light photos still carry cream text. A slide with no title
   or text (a photo gallery) has nothing to carry, so it keeps its colors. */
.slider--text-overlay .slider--media:has(+ .slider--copy)::after {
	content: "";
	position: absolute;
	inset: 0;
	background: linear-gradient(180deg,
		rgba(0, 0, 0, 0.5) 0%,
		rgba(0, 0, 0, 0.35) 25%,
		rgba(0, 0, 0, 0.35) 65%,
		rgba(0, 0, 0, 0.55) 100%);
	pointer-events: none;
}

.slider--text-overlay .slider--copy {
	position: absolute;
	inset: 0;
	display: flex;
	flex-direction: column;
	justify-content: space-between;
	gap: 24px;
	padding: 38px 16px 46px 37px; /* the iPhone frame runs the text to the card's edge */
	pointer-events: none;
}

@media (min-width: 992px) {
	.slider--text-overlay .slider--copy {
		padding-right: 37px;
	}
}

/* With the lightbox on, the overlay text is raised to clear the + tile in
   the image's corner: 21px inset + 47px tile + 18px of air. */
.slider--has-lightbox.slider--text-overlay .slider--copy {
	padding-bottom: calc(21px + 47px + 18px);
}

/* Caption below: the same type, moved under the picture. Here the copy sits
   on the block's own background, so it takes the ink the buttons use: cream
   on dark, black on a light palette color (css/buttons.css sets it). */
.slider--text-below .slider--copy {
	color: var(--rdv-button-ink, var(--wp--preset--color--cream, #efede6));
	display: flex;
	flex-direction: column;
	gap: 14px;
	padding: 26px 8px 0 0;
}

/* ---------------------------------------------------------- the controls */

/* Under .slider--block so it outranks .theme-container's own padding and
   max-width whichever stylesheet prints first. */
.slider--block .slider--controls {
	display: flex;
	align-items: center;
	gap: 32px;
	margin-top: 48px;
	padding-inline: 28px;
}

/* Desktop: a 1246px row, centred (Figma: 241 to 1487 at 1728), so it sits
   inside the card pair rather than flush with the copy above. */
@media (min-width: 992px) {
	.slider--block .slider--controls {
		max-width: calc(1246px + 2 * var(--theme-content-padding));
		margin-top: 38px;
		padding-inline: var(--theme-content-padding);
	}
}

/* Arrows that cannot work are worse than none; the scroller needs none. The
   editor canvas keeps them, so the block looks like itself there. */
.slider--block:not(.is-ready) .slider--controls {
	display: none;
}

.acf-block-preview .slider--block .slider--controls {
	display: flex;
}

/* A 2px line with a 10px thumb, one slide's share of it long. */
.slider--progress {
	position: relative;
	flex: 1;
	height: 10px;
}

.slider--progress::before {
	content: "";
	position: absolute;
	top: 4px;
	left: 0;
	right: 0;
	height: 2px;
	background-color: var(--slider-accent);
}

.slider--thumb {
	position: absolute;
	inset: 0 auto 0 0;
	width: calc(100% / var(--slider-count, 1));
	background-color: var(--slider-accent);
	transform: translateX(calc(var(--slider-index, 0) * 100%));
	transition: transform calc(var(--slider-ms) * 0.86) var(--slider-ease);
}

.slider--arrows {
	display: flex;
	flex: none;
	gap: 21px;
}

/* 47px tiles with one corner cut: top-right on next, bottom-left on prev. */
.slider--arrow {
	display: grid;
	place-items: center;
	width: 47px;
	height: 47px;
	padding: 0;
	border: 0;
	border-radius: 0;
	background-color: var(--slider-accent);
	color: var(--wp--preset--color--cream, #efede6);
	cursor: pointer;
	clip-path: polygon(0 0, calc(100% - var(--slider-cut)) 0, 100% var(--slider-cut), 100% 100%, 0 100%);
	transition: background-color 0.3s;
}

.slider--prev {
	clip-path: polygon(0 0, 100% 0, 100% 100%, var(--slider-cut) 100%, 0 calc(100% - var(--slider-cut)));
}

.slider--arrow svg {
	display: block;
	fill: currentColor;
}

.slider--prev svg {
	transform: rotate(180deg);
}

.slider--arrow:hover,
.slider--arrow:focus-visible {
	background-color: var(--rdv-red, #bf4042);
}

/* The clip would cut a ring drawn outside the tile, so it is drawn inside. */
.slider--arrow:focus-visible {
	outline: 2px solid currentColor;
	outline-offset: -6px;
}

/* Auto-advance's pause/play tile, before the arrows. Not in the Figma (there
   is no auto-advance there): the arrows' tile, uncut, so it doesn't read as
   a third arrow. slider.js toggles .is-stopped. */
.slider--pause {
	clip-path: none;
}

.slider--pause .slider--play-icon,
.slider--pause.is-stopped .slider--pause-icon {
	display: none;
}

.slider--pause.is-stopped .slider--play-icon {
	display: block;
}

/* -------------------------------------------------------------- lightbox */

/* The + tile (Figma "RDV Updates" Frame 7): 47px, cream, a 1px red outline,
   a 17px red plus, the lower-right corner cut 10px, set 22px in from the
   image's right edge and 21px up from its bottom. It is an SVG, so the cut
   corner keeps its outline. Hover and focus invert it. */
.slider--zoom {
	position: absolute;
	right: 22px;
	bottom: 21px;
	z-index: 1; /* over the overlay's scrim */
	display: block;
	width: 47px;
	height: 47px;
	color: var(--rdv-red, #bf4042);
	clip-path: polygon(0 0, 100% 0, 100% calc(100% - var(--slider-cut)), calc(100% - var(--slider-cut)) 100%, 0 100%);
	-webkit-user-drag: none;
	/* Shown only on the front card, and only once it has landed. */
	transition:
		opacity 0.3s ease-out calc(var(--slider-ms) * 0.86),
		visibility 0s calc(var(--slider-ms) * 0.86);
}

.slider--slide:not(.is-active) .slider--zoom {
	opacity: 0;
	visibility: hidden; /* also takes the hidden tiles out of the tab order */
	transition: opacity 0.2s, visibility 0s 0.2s;
}

.slider--block.is-jumping .slider--zoom {
	transition: none;
}

.slider--zoom svg {
	display: block;
}

.slider--zoom-tile {
	fill: var(--wp--preset--color--cream, #efede6);
	stroke: var(--rdv-red, #bf4042);
	stroke-width: 1;
	transition: fill 0.3s;
}

.slider--zoom-plus {
	fill: none;
	stroke: currentColor;
	stroke-width: 2;
}

.slider--zoom:hover,
.slider--zoom:focus-visible {
	color: var(--wp--preset--color--cream, #efede6);
}

.slider--zoom:hover .slider--zoom-tile,
.slider--zoom:focus-visible .slider--zoom-tile {
	fill: var(--rdv-red, #bf4042);
}

/* Inside the tile, because the clip would cut a ring drawn outside it. */
.slider--zoom:focus-visible {
	outline: 2px solid currentColor;
	outline-offset: -6px;
}

/* A click anywhere on the front image opens it too (slider.js). A video
   card has no tile, so nothing to open. */
.slider--has-lightbox.is-ready .slider--slide.is-active .slider--media:has(.slider--zoom) {
	cursor: zoom-in;
}

/* The pop-up (GLightbox; slider.js tags its container). The picture keeps
   its own shape and takes the cards' chamfer; the shadow would be clipped. */
.slider--lightbox .gslide-media {
	box-shadow: none;
}

/* One picture per opening: GLightbox still draws its prev/next arrows (as
   disabled) unless something hides them. media.css does, but only on pages
   that carry a Media block. */
.slider--lightbox .gprev,
.slider--lightbox .gnext {
	display: none;
}

.slider--lightbox .gslide-image img {
	clip-path: polygon(
		var(--slider-cut, 10px) 0, calc(100% - var(--slider-cut, 10px)) 0,
		100% var(--slider-cut, 10px), 100% calc(100% - var(--slider-cut, 10px)),
		calc(100% - var(--slider-cut, 10px)) 100%, var(--slider-cut, 10px) 100%,
		0 calc(100% - var(--slider-cut, 10px)), 0 var(--slider-cut, 10px)
	);
}

/* ---------------------------------------------------------------- motion */

/* Entrance (slider.js arms it only when the row starts below the fold, the
   rule js/reveal.js follows). --snap-i is a card's place from the active one.
   The cards close up on the site's reveal move (style.css), so they land on
   the frame the type around them does, and stop dead. */
.slider--block.is-assemble-armed .slider--slide {
	opacity: 0;
	transform: translateX(calc(var(--snap-i, 0) * var(--slider-seam)));
}

.slider--block.is-assembling .slider--slide {
	animation:
		slider-assemble var(--rdv-snap-ms, 500ms) var(--rdv-snap-ease, ease-in) both,
		rdv-rise-fade calc(var(--rdv-snap-ms, 500ms) * 0.85) linear both;
}

@keyframes slider-assemble {
	from { transform: translateX(calc(var(--snap-i, 0) * var(--slider-seam))); }
}

@media (prefers-reduced-motion: reduce) {
	.slider--block.is-ready .slider--track,
	.slider--block.is-ready .slider--slide,
	.slider--thumb,
	.slider--arrow,
	.slider--zoom,
	.slider--slide:not(.is-active) .slider--zoom,
	.slider--zoom-tile,
	.slider--image ~ .slider--video {
		transition: none;
	}

	.slider--block.is-assemble-armed .slider--slide {
		opacity: 1;
		transform: none;
	}

	.slider--block.is-assembling .slider--slide {
		animation: none;
	}
}

/* ----------------------------------------------------------- editor only */

.slider--empty {
	margin: 0;
	opacity: 0.7;
	font-style: italic;
}
