/*!
 * @be-partner-labs/ds v1.8.0 — components/carousel
 * © 2026 Be Partner Labs. MIT License.
 *
 * CDN:  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@be-partner-labs/ds@1.8.0/dist/components/carousel.min.css">
 * npm:  @import "@be-partner-labs/ds/components/carousel";
 * Docs: https://ds.bepartnerlabs.com/components/carousel/
 */
@layer bp-tokens, bp-reset, bp-grid, bp-components, bp-utilities;

@layer bp-components {
	/**
	 * .bp-carousel
	 * CSS scroll-snap carousel — no JS required for basic behavior.
	 * Public API:
	 *   --carousel-gap        Gap between slides
	 *   --carousel-slide-min  Minimum slide width (default: 100%)
	 *   --carousel-radius     Slide border radius
	 *   --carousel-slide-background   Slide background (default: transparent)
	 */
	.bp-carousel {
		--_gap: var(--carousel-gap, var(--bp-space-4));
		--_slide-min: var(--carousel-slide-min, 100%);
		--_radius: var(--carousel-radius, var(--bp-radius-lg));
		--_background: var(--carousel-slide-background, transparent);
		--_padding: var(--carousel-slide-padding, 0px);
		--_height: var(--carousel-slide-min-height, auto);

		display: flex;
		flex-direction: column;
		gap: var(--bp-space-4);
	}

	.bp-carousel__track {
		display: flex;
		gap: var(--_gap);
		overflow-x: auto;
		scroll-snap-type: x mandatory;
		scrollbar-width: none;
		-webkit-overflow-scrolling: touch;
		scroll-behavior: smooth;
		padding-bottom: var(--bp-space-1); /* prevent clip of box-shadow on focused slide */
	}

	.bp-carousel__track::-webkit-scrollbar {
		display: none;
	}

	.bp-carousel__slide {
		flex: 0 0 var(--_slide-min);
		min-height: var(--_height);
		padding: var(--_padding);
		scroll-snap-align: start;
		scroll-snap-stop: always;
		border-radius: var(--_radius);
		background-color: var(--_background);
		overflow: hidden;
		position: relative;
	}

	.bp-carousel__slide:focus-visible {
		outline: none;
		box-shadow: var(--bp-focus-ring);
	}

	/* ─── Manual dots (fallback) ────────────────────────────────
     Shown when ::scroll-marker is not supported.
     JS toggles .is-active based on IntersectionObserver.       */
	.bp-carousel__dots {
		display: flex;
		justify-content: center;
		gap: var(--bp-space-2);
		list-style: none;
		padding: 0;
	}

	.bp-carousel__dot {
		width: 0.5rem;
		height: 0.5rem;
		border-radius: var(--bp-radius-full);
		background-color: var(--bp-color-border);
		border: none;
		padding: 0;
		cursor: pointer;
		transition:
			width var(--bp-duration-normal) var(--bp-ease),
			background-color var(--bp-duration-fast) var(--bp-ease);
	}

	.bp-carousel__dot.is-active,
	.bp-carousel__dot[aria-current='true'] {
		background-color: var(--bp-primary);
		width: 1.5rem;
	}

	.bp-carousel__dot:focus-visible {
		outline: none;
		box-shadow: var(--bp-focus-ring);
	}

	/* Prev/Next buttons (manual fallback) */
	.bp-carousel__controls {
		display: flex;
		justify-content: center;
		gap: var(--bp-space-3);
	}

	/* ─── Native ::scroll-marker + ::scroll-button ───────────────
     Progressive enhancement — no JS needed for dots or arrows.
     Hides the manual .bp-carousel__dots when supported.        */
	@supports selector(::scroll-marker) {
		/* Hide manual dots — native markers take over */
		.bp-carousel__dots {
			display: none;
		}
		.bp-carousel__controls {
			display: none;
		}

		.bp-carousel__track {
			/* Required to activate the marker group */
			scroll-marker-group: after;
		}

		/* Each slide gets a native dot marker */
		.bp-carousel__slide::scroll-marker {
			content: '';
			display: block;
			width: 0.5rem;
			height: 0.5rem;
			border-radius: var(--bp-radius-full);
			background-color: var(--bp-color-border);
			border: 2px solid transparent;
			transition:
				width var(--bp-duration-normal) var(--bp-ease),
				background-color var(--bp-duration-fast) var(--bp-ease);
		}

		.bp-carousel__slide::scroll-marker:target-current {
			background-color: var(--bp-primary);
			width: 1.5rem;
			border-radius: var(--bp-radius-full);
		}

		.bp-carousel__slide::scroll-marker:focus-visible {
			outline: none;
			border-color: var(--bp-primary);
			box-shadow: var(--bp-focus-ring);
		}

		/* The marker group row — centered below the track */
		.bp-carousel__track::scroll-marker-group {
			display: flex;
			justify-content: center;
			align-items: center;
			gap: var(--bp-space-2);
			padding-block: var(--bp-space-2);
		}

		/* Anchor positioning — each carousel scopes its own anchor name
       so multiple carousels on the same page don't interfere.        */
		.bp-carousel {
			anchor-scope: --bp-carousel-track;
			position: relative;
			isolation: isolate;
		}

		.bp-carousel__track {
			anchor-name: --bp-carousel-track;
		}

		/* Native prev/next scroll buttons — anchored to the track,
       floating over the slides at vertical center.               */
		/* Shared scroll button styles via wildcard */
		.bp-carousel__track::scroll-button(*) {
			display: flex;
			align-items: center;
			justify-content: center;
			width: 2rem;
			height: 2rem;
			border-radius: var(--bp-radius-full);
			background: var(--bp-color-bg-elevated);
			border: 1px solid var(--bp-color-border);
			color: var(--bp-color-text);
			cursor: pointer;
			font-size: 1rem;
			z-index: 1;
			transition:
				background-color var(--bp-duration-fast) var(--bp-ease),
				border-color var(--bp-duration-fast) var(--bp-ease),
				opacity var(--bp-duration-fast) var(--bp-ease);

			/* Anchor to the track, float at the left/right edges */
			position: absolute;
			position-anchor: --bp-carousel-track;
		}

		/* content: "icon" / "accessible label" — screen readers get the label */
		.bp-carousel__track::scroll-button(inline-start) {
			content: '←' / 'Previous slide';
			position-area: inline-start center;
			translate: -50% 0;
		}

		.bp-carousel__track::scroll-button(inline-end) {
			content: '→' / 'Next slide';
			position-area: inline-end center;
			translate: 50% 0;
		}

		.bp-carousel__track::scroll-button(*):hover {
			background-color: var(--bp-color-bg-subtle);
			border-color: var(--bp-color-border);
		}

		.bp-carousel__track::scroll-button(*):focus-visible {
			outline: none;
			box-shadow: var(--bp-focus-ring);
		}

		.bp-carousel__track::scroll-button(*):disabled {
			opacity: 0.3;
			cursor: default;
		}
	}

	/* Multi-slide variant: show partial next slide as affordance */
	.bp-carousel--multi .bp-carousel__track {
		padding-inline: var(--bp-space-4);
	}

	.bp-carousel--multi .bp-carousel__slide {
		flex: 0 0 calc(var(--_slide-min) - var(--bp-space-8));
	}

	/* Carousel is its own container for slide content scaling */
	.bp-carousel {
		container-type: inline-size;
	}

	/* Slide content inside a narrow carousel gets smaller type */
	@container (inline-size > 0) {
		.bp-carousel__slide {
			font-size: clamp(var(--bp-text-sm), 3cqi, var(--bp-text-base));
		}
	}

	/* ─── Responsive peek — bp-carousel--peek variant ───────────
     Automatically adjusts how many slides are visible based on
     the carousel's container width. No JS, no media queries.

     < 30rem  → 1.2 slides (peek of 20% of next slide)
     < 50rem  → 1.8 slides
     ≥ 50rem  → 2.2 slides (peek of 20% of third slide)

     Formula: slide-min = calc(100% / N - var(--_gap) * (N-1) / N)
     Simplified to: (100% - gap) / N using approximate gap amortization. */
	.bp-carousel--peek {
		.bp-carousel__track {
			padding-inline: var(--bp-space-4);
		}
	}

	@container (inline-size < 30rem) {
		.bp-carousel--peek .bp-carousel__slide {
			--carousel-slide-min: calc(100% / 1.2 - var(--bp-space-4));
		}
	}

	@container (30rem <= inline-size < 50rem) {
		.bp-carousel--peek .bp-carousel__slide {
			--carousel-slide-min: calc(100% / 1.8 - var(--bp-space-4));
		}
	}

	@container (inline-size >= 50rem) {
		.bp-carousel--peek .bp-carousel__slide {
			--carousel-slide-min: calc(100% / 2.2 - var(--bp-space-4));
		}
	}
}
