/**
 * Rajgir Parent Theme
 *
 * Component CSS — Loaders
 *
 * Canonical path:
 * assets/css/components/loaders.css
 *
 * Loading Architecture:
 *
 * REQUEST
 *    ↓
 * LOADING
 *    ↓
 * ┌──────────────┬──────────────┬──────────────┐
 * │ Spinner      │ Skeleton     │ Progress     │
 * │ Action       │ Content      │ Process      │
 * └──────────────┴──────────────┴──────────────┘
 *    ↓
 * SUCCESS / EMPTY / ERROR
 *
 * Responsibilities:
 * - Loading indicator presentation.
 * - Spinner presentation.
 * - Skeleton presentation.
 * - Progress presentation.
 * - Loading overlay presentation where required.
 * - Disabled/loading visual state.
 *
 * This file does NOT:
 * - make API requests;
 * - determine request state;
 * - determine success;
 * - determine failure;
 * - perform retry logic;
 * - perform business logic;
 * - perform authorization;
 * - access the database.
 *
 * @package Rajgir
 */


/* ==========================================================================
   1. LOADER FOUNDATION
   ========================================================================== */

.rg-loader {
	display: inline-flex;

	align-items: center;
	justify-content: center;

	flex:
		0 0 auto;

	color:
		var(--rajgir-color-primary);

	vertical-align: middle;
}


/* ==========================================================================
   2. SPINNER
   ========================================================================== */

.rg-spinner {
	display: inline-block;

	width:
		var(--rajgir-size-loader);

	height:
		var(--rajgir-size-loader);

	border:
		var(--rajgir-loader-border-width)
		solid
		var(--rajgir-color-border);

	border-top-color:
		var(--rajgir-color-primary);

	border-radius:
		50%;

	animation:
		rajgir-spinner-rotate
		var(--rajgir-motion-duration-spinner)
		linear
		infinite;
}


/* ==========================================================================
   3. SPINNER ROTATION
   ========================================================================== */

@keyframes rajgir-spinner-rotate {

	to {
		transform:
			rotate(360deg);
	}

}


/* ==========================================================================
   4. SMALL SPINNER
   ========================================================================== */

.rg-spinner--small {
	width:
		var(--rajgir-size-loader-sm);

	height:
		var(--rajgir-size-loader-sm);

	border-width:
		var(--rajgir-loader-border-width-sm);
}


/* ==========================================================================
   5. LARGE SPINNER
   ========================================================================== */

.rg-spinner--large {
	width:
		var(--rajgir-size-loader-lg);

	height:
		var(--rajgir-size-loader-lg);

	border-width:
		var(--rajgir-loader-border-width-lg);
}


/* ==========================================================================
   6. BUTTON LOADING
   ========================================================================== */

.rg-button.is-loading,
.rg-action-btn.is-loading,
.rg-button[aria-busy="true"],
.rg-action-btn[aria-busy="true"] {
	position: relative;

	cursor:
		wait;
}


/* ==========================================================================
   7. BUTTON LOADING SPINNER
   ========================================================================== */

.rg-button.is-loading::after,
.rg-action-btn.is-loading::after,
.rg-button[aria-busy="true"]::after,
.rg-action-btn[aria-busy="true"]::after {
	content: "";

	display: inline-block;

	width:
		var(--rajgir-size-loader-sm);

	height:
		var(--rajgir-size-loader-sm);

	margin-left:
		var(--rajgir-space-icon-gap);

	border:
		var(--rajgir-loader-border-width-sm)
		solid
		currentColor;

	border-right-color:
		transparent;

	border-radius:
		50%;

	animation:
		rajgir-spinner-rotate
		var(--rajgir-motion-duration-spinner)
		linear
		infinite;
}


/* ==========================================================================
   8. INLINE LOADER
   ========================================================================== */

.rg-inline-loader {
	display: inline-flex;

	align-items: center;

	gap:
		var(--rajgir-space-icon-gap);

	color:
		var(--rajgir-color-text-muted);

	font-size:
		var(--rajgir-font-size-small);

	line-height:
		var(--rajgir-line-height-small);
}


/* ==========================================================================
   9. INLINE LOADER TEXT
   ========================================================================== */

.rg-inline-loader__text {
	display: inline-block;
}


/* ==========================================================================
   10. CONTENT LOADER
   ========================================================================== */

.rg-content-loader {
	display: flex;

	align-items: center;
	justify-content: center;

	width: 100%;

	min-height:
		var(--rajgir-loader-content-min-height);

	padding:
		var(--rajgir-space-loader-content);

	color:
		var(--rajgir-color-text-muted);
}


/* ==========================================================================
   11. CONTENT LOADER MESSAGE
   ========================================================================== */

.rg-content-loader__message {
	margin: 0;

	font-size:
		var(--rajgir-font-size-small);

	line-height:
		var(--rajgir-line-height-small);
}


/* ==========================================================================
   12. SKELETON FOUNDATION
   ========================================================================== */

.rg-skeleton {
	display: block;

	background:
		var(--rajgir-color-skeleton);

	border-radius:
		var(--rajgir-radius-skeleton);

	color:
		transparent;

	user-select: none;

	pointer-events: none;

	overflow: hidden;
}


/* ==========================================================================
   13. SKELETON TEXT
   ========================================================================== */

.rg-skeleton--text,
.rg-skeleton-text {
	width: 100%;

	height:
		var(--rajgir-skeleton-text-height);

	margin-bottom:
		var(--rajgir-space-skeleton-line-gap);
}


/* ==========================================================================
   14. SKELETON TEXT SHORT
   ========================================================================== */

.rg-skeleton--text-short {
	width:
		var(--rajgir-skeleton-text-short-width);
}


/* ==========================================================================
   15. SKELETON TEXT MEDIUM
   ========================================================================== */

.rg-skeleton--text-medium {
	width:
		var(--rajgir-skeleton-text-medium-width);
}


/* ==========================================================================
   16. SKELETON TITLE
   ========================================================================== */

.rg-skeleton--title {
	width:
		var(--rajgir-skeleton-title-width);

	height:
		var(--rajgir-skeleton-title-height);

	margin-bottom:
		var(--rajgir-space-skeleton-title-gap);
}


/* ==========================================================================
   17. SKELETON IMAGE
   ========================================================================== */

.rg-skeleton--image {
	width: 100%;

	aspect-ratio:
		var(--rajgir-skeleton-image-ratio);
}


/* ==========================================================================
   18. SKELETON AVATAR
   ========================================================================== */

.rg-skeleton--avatar {
	width:
		var(--rajgir-skeleton-avatar-size);

	height:
		var(--rajgir-skeleton-avatar-size);

	border-radius:
		50%;
}


/* ==========================================================================
   19. SKELETON CARD
   ========================================================================== */

.rg-skeleton-card {
	display: flex;

	flex-direction: column;

	gap:
		var(--rajgir-space-skeleton-card-gap);

	width: 100%;
}


/* ==========================================================================
   20. SKELETON CARD MEDIA
   ========================================================================== */

.rg-skeleton-card__media {
	width: 100%;

	aspect-ratio:
		var(--rajgir-skeleton-card-media-ratio);
}


/* ==========================================================================
   21. SKELETON CARD BODY
   ========================================================================== */

.rg-skeleton-card__body {
	display: flex;

	flex-direction: column;

	gap:
		var(--rajgir-space-skeleton-card-gap);
}


/* ==========================================================================
   22. SKELETON CARD TITLE
   ========================================================================== */

.rg-skeleton-card__title {
	width:
		var(--rajgir-skeleton-title-width);

	height:
		var(--rajgir-skeleton-title-height);
}


/* ==========================================================================
   23. SKELETON CARD TEXT
   ========================================================================== */

.rg-skeleton-card__text {
	width: 100%;

	height:
		var(--rajgir-skeleton-text-height);
}


/* ==========================================================================
   24. SKELETON CARD TEXT LAST LINE
   ========================================================================== */

.rg-skeleton-card__text:last-child {
	width:
		var(--rajgir-skeleton-text-medium-width);
}


/* ==========================================================================
   25. SKELETON SHIMMER
   ========================================================================== */

/*
 * Shimmer is optional visual enhancement.
 *
 * Loading state itself remains meaningful without animation.
 */

.rg-skeleton--animated {
	background-image:
		linear-gradient(
			90deg,
			transparent 0%,
			var(--rajgir-color-skeleton-highlight) 50%,
			transparent 100%
		);

	background-size:
		var(--rajgir-skeleton-shimmer-size) 100%;

	animation:
		rajgir-skeleton-shimmer
		var(--rajgir-motion-duration-skeleton)
		linear
		infinite;
}


/* ==========================================================================
   26. SKELETON SHIMMER ANIMATION
   ========================================================================== */

@keyframes rajgir-skeleton-shimmer {

	from {
		background-position:
			calc(
				var(--rajgir-skeleton-shimmer-size) * -1
			)
			0;
	}

	to {
		background-position:
			var(--rajgir-skeleton-shimmer-size)
			0;
	}

}


/* ==========================================================================
   27. SKELETON CONTAINER
   ========================================================================== */

.rg-skeleton-group {
	display: flex;

	flex-direction: column;

	gap:
		var(--rajgir-space-skeleton-group-gap);

	width: 100%;
}


/* ==========================================================================
   28. FEED SKELETON
   ========================================================================== */

.rg-feed-skeleton {
	display: flex;

	flex-direction: column;

	gap:
		var(--rajgir-space-skeleton-card-gap);

	width: 100%;
}


/* ==========================================================================
   29. FEED SKELETON ITEM
   ========================================================================== */

.rg-feed-skeleton__item {
	width: 100%;
}


/* ==========================================================================
   30. PROFILE SKELETON
   ========================================================================== */

.rg-profile-skeleton {
	display: flex;

	align-items: flex-start;

	gap:
		var(--rajgir-space-component-gap);

	width: 100%;
}


/* ==========================================================================
   31. PROFILE SKELETON CONTENT
   ========================================================================== */

.rg-profile-skeleton__content {
	flex:
		1 1 auto;

	min-width: 0;
}


/* ==========================================================================
   32. SEARCH RESULTS SKELETON
   ========================================================================== */

.rg-search-skeleton {
	display: flex;

	flex-direction: column;

	gap:
		var(--rajgir-space-skeleton-card-gap);

	width: 100%;
}


/* ==========================================================================
   33. BUSINESS LISTING SKELETON
   ========================================================================== */

.rg-business-skeleton {
	display: flex;

	flex-direction: column;

	gap:
		var(--rajgir-space-skeleton-card-gap);

	width: 100%;
}


/* ==========================================================================
   34. PROGRESS FOUNDATION
   ========================================================================== */

.rg-progress {
	display: block;

	width: 100%;

	min-height:
		var(--rajgir-progress-height);

	overflow: hidden;

	border-radius:
		var(--rajgir-radius-pill);

	background:
		var(--rajgir-color-progress-track);
}


/* ==========================================================================
   35. PROGRESS VALUE
   ========================================================================== */

.rg-progress__value {
	display: block;

	width:
		var(--rajgir-progress-value);

	height: 100%;

	border-radius:
		inherit;

	background:
		var(--rajgir-color-progress);
}


/*
 * The value is expected to be supplied by the authoritative state/
 * application layer.
 */


/* ==========================================================================
   36. INDETERMINATE PROGRESS
   ========================================================================== */

.rg-progress--indeterminate
.rg-progress__value {
	width:
		var(--rajgir-progress-indeterminate-width);

	animation:
		rajgir-progress-indeterminate
		var(--rajgir-motion-duration-progress)
		linear
		infinite;
}


/* ==========================================================================
   37. INDETERMINATE PROGRESS ANIMATION
   ========================================================================== */

@keyframes rajgir-progress-indeterminate {

	from {
		transform:
			translateX(
				var(--rajgir-progress-start)
			);
	}

	to {
		transform:
			translateX(
				var(--rajgir-progress-end)
			);
	}

}


/* ==========================================================================
   38. FULL AREA LOADER
   ========================================================================== */

.rg-loading-overlay {
	position: absolute;

	inset: 0;

	display: flex;

	align-items: center;
	justify-content: center;

	padding:
		var(--rajgir-space-loader-overlay);

	background:
		var(--rajgir-color-loading-overlay);

	z-index:
		var(--rajgir-layer-sticky);
}


/* ==========================================================================
   39. FULL AREA LOADER CONTENT
   ========================================================================== */

.rg-loading-overlay__content {
	display: flex;

	flex-direction: column;

	align-items: center;

	justify-content: center;

	gap:
		var(--rajgir-space-component-gap);

	text-align: center;
}


/* ==========================================================================
   40. FULL AREA LOADER MESSAGE
   ========================================================================== */

.rg-loading-overlay__message {
	margin: 0;

	color:
		var(--rajgir-color-text);

	font-size:
		var(--rajgir-font-size-small);

	line-height:
		var(--rajgir-line-height-small);
}


/* ==========================================================================
   41. LOADING STATE
   ========================================================================== */

[data-loading="true"],
.is-loading {
}


/*
 * Loading state is represented by application/component state.
 *
 * CSS only presents it.
 */


/* ==========================================================================
   42. ARIA BUSY
   ========================================================================== */

[aria-busy="true"] {
	cursor:
		wait;
}


/* ==========================================================================
   43. ARIA BUSY CONTENT
   ========================================================================== */

[aria-busy="true"] .rg-loading-target {
	opacity:
		var(--rajgir-state-loading-opacity);
}


/* ==========================================================================
   44. DISABLED DURING LOADING
   ========================================================================== */

.rg-loading-disabled,
[aria-busy="true"] button,
[aria-busy="true"] .rg-button {
	cursor:
		wait;
}


/* ==========================================================================
   45. LOADING + CONTENT PRESERVATION
   ========================================================================== */

/*
 * Loading does not automatically mean:
 *
 *     hide all existing content
 *
 * Cached or already-rendered content may remain visible while a refresh
 * is occurring when the feature contract allows it.
 */


/* ==========================================================================
   46. REFRESHING STATE
   ========================================================================== */

.rg-refreshing {
	position: relative;
}


/* ==========================================================================
   47. REFRESHING INDICATOR
   ========================================================================== */

.rg-refreshing__indicator {
	display: inline-flex;

	align-items: center;

	gap:
		var(--rajgir-space-icon-gap);

	color:
		var(--rajgir-color-text-muted);

	font-size:
		var(--rajgir-font-size-small);
}


/* ==========================================================================
   48. OFFLINE LOADING BOUNDARY
   ========================================================================== */

/*
 * Offline is not an endless loading state.
 *
 * If network availability is known to be unavailable, the UI should
 * transition to an appropriate Offline / Recovery state.
 */


/* ==========================================================================
   49. ERROR TRANSITION BOUNDARY
   ========================================================================== */

/*
 * Loading must not continue forever after failure.
 *
 * Canonical transition:
 *
 * LOADING
 *    ↓
 * ERROR
 *    ↓
 * RECOVERY
 */


/* ==========================================================================
   50. EMPTY TRANSITION BOUNDARY
   ========================================================================== */

/*
 * Successful request with zero data:
 *
 * LOADING
 *    ↓
 * SUCCESS
 *    ↓
 * EMPTY
 *
 * Skeleton must not be used as an empty state.
 */


/* ==========================================================================
   51. LOADING VS SKELETON
   ========================================================================== */

/*
 * Spinner:
 *
 * Short-duration action
 *
 * Skeleton:
 *
 * Content-driven loading
 *
 * Progress:
 *
 * Known / meaningful process progression
 *
 * Placeholder:
 *
 * Appropriate temporary visual replacement
 */


/* ==========================================================================
   52. NO SPINNER EVERYWHERE
   ========================================================================== */

/*
 * Large content areas should not automatically be blocked by a spinner.
 *
 * Content shape should determine the loading pattern.
 */


/* ==========================================================================
   53. NO SKELETON FOREVER
   ========================================================================== */

/*
 * Skeleton must transition to:
 *
 * SUCCESS
 * EMPTY
 * ERROR
 *
 * It must never remain indefinitely after the request has failed.
 */


/* ==========================================================================
   54. NO SPINNER FOREVER
   ========================================================================== */

/*
 * Indefinite:
 *
 * Loading...
 * Loading...
 * Loading...
 *
 * without a recovery path is not acceptable once failure is known.
 */


/* ==========================================================================
   55. NO DECORATIVE LOADING
   ========================================================================== */

/*
 * Loading animation exists to communicate processing.
 *
 * It is not entertainment.
 *
 * Avoid heavy or unnecessary animation.
 */


/* ==========================================================================
   56. ACCESSIBLE LOADING
   ========================================================================== */

/*
 * Where applicable:
 *
 * aria-busy="true"
 *
 * may communicate that a region is being updated.
 *
 * Visible status text may be required depending on context.
 *
 * Animation alone must not be the only feedback.
 */


/* ==========================================================================
   57. SCREEN READER LOADING MESSAGE
   ========================================================================== */

.rg-loading-status {
	position: absolute;

	width: 1px;
	height: 1px;

	padding: 0;
	margin: -1px;

	overflow: hidden;

	clip: rect(0, 0, 0, 0);

	white-space: nowrap;

	border: 0;
}


/* ==========================================================================
   58. LOADING TARGET
   ========================================================================== */

.rg-loading-target {
	min-width: 0;
}


/* ==========================================================================
   59. PERFORMANCE
   ========================================================================== */

/*
 * Loading components must remain lightweight.
 *
 * Avoid:
 *
 * - unnecessary DOM generation;
 * - continuous heavy animation;
 * - unnecessary JavaScript;
 * - unnecessary layout work.
 */


/* ==========================================================================
   60. REDUCED MOTION
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {

	.rg-spinner,
	.rg-button.is-loading::after,
	.rg-action-btn.is-loading::after,
	.rg-button[aria-busy="true"]::after,
	.rg-action-btn[aria-busy="true"]::after,
	.rg-skeleton--animated,
	.rg-progress--indeterminate .rg-progress__value {
		animation: none;
	}

}


/* ==========================================================================
   61. MOBILE
   ========================================================================== */

@media (max-width: 767px) {

	.rg-content-loader {
		min-height:
			var(--rajgir-loader-content-mobile-min-height);
	}

	.rg-loading-overlay {
		padding:
			var(--rajgir-space-loader-overlay-mobile);
	}

}


/* ==========================================================================
   62. LOADER COMPONENT BOUNDARY
   ========================================================================== */

/*
 * loaders.css
 *     ↓
 * presentation
 *
 * Component JS
 *     ↓
 * interaction/state
 *
 * API
 *     ↓
 * request
 *
 * Backend
 *     ↓
 * authority
 */


/* ==========================================================================
   63. STATE OWNERSHIP
   ========================================================================== */

/*
 * Frontend may own:
 *
 * Loading
 * Selected UI state
 * Refreshing
 *
 * Backend remains authoritative for:
 *
 * Business result
 * Booking confirmation
 * Payment result
 * Complaint state
 * Persistent business state
 */


/* ==========================================================================
   64. NO FALSE SUCCESS
   ========================================================================== */

/*
 * Loading completion must not be interpreted as success.
 *
 * Correct:
 *
 * REQUEST
 *    ↓
 * LOADING
 *    ↓
 * RESPONSE
 *    ↓
 * SUCCESS / ERROR
 */


/* ==========================================================================
   65. NO DUPLICATE ACTION
   ========================================================================== */

/*
 * During processing, the associated action may be disabled where
 * appropriate to prevent duplicate submission.
 *
 * Backend idempotency remains the authoritative protection.
 */


/* ==========================================================================
   66. COMPONENT COMPOSITION
   ========================================================================== */

/*
 * Loader may compose with:
 *
 * Button
 * Card
 * Feed
 * Search
 * Profile
 * Business Listing
 * Modal
 * Form
 *
 * without creating separate loading design systems for each feature.
 */


/* ==========================================================================
   67. FINAL LOADING RULE
   ========================================================================== */

/*
 * LOADING
 *     ≠
 * ANIMATION
 *
 * Loading is a state.
 *
 * Spinner / Skeleton / Progress are presentation patterns selected
 * according to context.
 *
 * Purpose before decoration.
 */