#classlist-document-object-list {
	$global-elevated-block-background-color: $global-elevated-block-default-background-color;
	$elevated-border-color: $global-border-color;
	$dbqdcldol-button-size: 28px;
	$dbqdcldol-header-height: 48px; // The (minimum) height of a node header, also used to stack the sticky item header below the category header
	$dbqdcldol-overall-progress-height: 44px; // The height of the sticky overall progress at the bottom, also used to stack the sticky form buttons above it
	$dbqdcldol-document-background-color: $render-engine-background-color; // Document nodes (Algemeen and items) use the background of the rendering engine
	$dbqdcldol-category-background-color: $color-layer-0; // Categories (objects) use the base layer (white / black in dark mode) with a border, so their items stand out

	.dbqdcldol-container {
		position: relative;

		&[data-is-loading="true"] {
			min-height: (100 + ($padding-default * 2));

			.dbqdcldol-list,
			.dbqdcldol-footer {
				display: none;
			}
		}

		.dbqdcldol-list {
			display: flex;
			flex-direction: column;
			gap: $margin-default;
		}

		// Refreshing: the existing view is reloaded after a filter change (e.g. another progress bar step).
		// The outdated list is dimmed and a running bar sticks to the top of the list until the new data is shown.
		.dbqdcldol-list,
		.dbqdcldol-footer {
			transition: opacity 150ms ease;
		}

		.dbqdcldol-refreshing-bar {
			display: none;
		}

		&[data-is-refreshing="true"] {
			.dbqdcldol-list,
			.dbqdcldol-footer {
				opacity: 0.45;
				pointer-events: none;
				transition: opacity 200ms ease 150ms; // The delay prevents a flicker when the reload is fast
			}

			.dbqdcldol-refreshing-bar {
				display: block;
				position: sticky;
				top: 0;
				z-index: 5;
				height: 3px;
				margin-bottom: -3px; // Don't push the list down
				overflow: hidden;
				border-radius: 2px;
				background: $color-primary-tone-4;

				&::before {
					content: '';
					position: absolute;
					top: 0;
					bottom: 0;
					left: 0;
					width: 40%;
					border-radius: 2px;
					background: $color-primary;
					animation: dbqdcldol-refreshing-bar 1.1s ease-in-out infinite;
				}
			}
		}

		// Progress indicator (ObtainListInfo.ListHasProgressIndicator).
		// Red as long as a mandatory question is open, green once all mandatory questions are filled.
		.dbqdcldol-progress {
			display: inline-flex;
			align-items: center;
			flex-shrink: 0;
			gap: 6px;

			.dbqdcldol-progress-track {
				width: 80px;
				height: 6px;
				border-radius: 3px;
				background: $color-layer-4;
				overflow: hidden;
			}

			.dbqdcldol-progress-fill {
				height: 100%;
				border-radius: 3px;
				background: color(border-color-error);
				transition: width 0.3s ease-in-out;
			}

			.dbqdcldol-progress-text {
				min-width: 34px;
				font-size: 12px;
				text-align: right;
				color: color(text-color-error);
			}

			&[data-is-mandatory-complete="true"] {
				.dbqdcldol-progress-fill {
					background: color(border-color-success);
				}

				.dbqdcldol-progress-text {
					color: color(text-color-success);
				}
			}

			// The overall progress of the entire list, above the list
			&.dbqdcldol-progress-overall {
				display: flex;
				width: 100%;
				gap: $margin-default;

				.dbqdcldol-progress-track {
					flex: 1 1 auto;
					width: auto;
					height: 8px;
					border-radius: 4px;
				}

				.dbqdcldol-progress-fill {
					border-radius: 4px;
				}

				.dbqdcldol-progress-text {
					font-size: 13px;
					font-weight: 600;
					white-space: nowrap;
				}
			}
		}

		// The overall progress sticks to the bottom while scrolling through the list, so it's always visible.
		// It has a fixed height, because the sticky form buttons are stacked on top of it (see .dbqdcldol-form-buttons).
		// The progress bar is the last element of a header. The items within a category are indented by the padding of the category
		// (.dbqdcldol-node-children) and their own border, so the top level nodes (Algemeen and categories) move their progress bar
		// the same distance to the left. All progress bars (and the buttons in front of them) then end at the same position.
		.dbqdcldol-list > .dbqdcldol-node > .dbqdcldol-node-header > .dbqdcldol-progress {
			margin-right: calc(#{$padding-default} + 1px);
		}

		// The title and functions are on the left, the progress bar is pushed to the right
		.dbqdcldol-node-header > .dbqdcldol-progress {
			margin-left: auto;
		}

		.dbqdcldol-progress-overall-container {
			&:not(:empty) {
				position: sticky;
				bottom: 0;
				z-index: 4;
				display: flex;
				align-items: center;
				height: $dbqdcldol-overall-progress-height;
				margin-top: $margin-default;
				border-top: 1px solid $elevated-border-color;
				background: color(background-color-default);
			}
		}

		&[data-is-loading="true"] .dbqdcldol-progress-overall-container {
			display: none;
		}

		// When the overall progress is shown, the sticky form buttons stick just above it instead of at the bottom
		&:has(> .dbqdcldol-progress-overall-container:not(:empty)) .dbqdcldol-node .dbqdcldol-node-document-container .dbqdb-sidepanel-footer-buttons.dbqdcldol-form-buttons {
			bottom: $dbqdcldol-overall-progress-height;
		}

		%dbqdcldol-card {
			width: 100%;
			background: $global-elevated-block-background-color;
			border: 1px solid $elevated-border-color;
			border-radius: $border-radius-default;
		}

		// Round add button (single add function) and add dropdown toggle (multiple add functions)
		.dbqdcldol-add-button,
		.dbqdcldol-add-dropdown-toggle {
			display: inline-flex;
			align-items: center;
			justify-content: center;
			width: $dbqdcldol-button-size;
			height: $dbqdcldol-button-size;
			padding: 0;
			border: 1px solid $button-border-color;
			border-radius: 50%;
			background: $button-background-color;
			color: $button-text-color;
			outline: none;
			cursor: pointer;

			&::after {
				display: none; // Hide the bootstrap dropdown caret
			}

			svg {
				width: 20px;
				height: 20px;
				fill: $button-text-color;
			}

			&:hover {
				background: $button-hover-background-color;
				border-color: $button-hover-border-color;
				color: $button-hover-text-color;

				svg {
					fill: $button-hover-text-color;
				}
			}

			&.disabled {
				opacity: 0.4;
				cursor: default;
				pointer-events: none;
			}
		}

		// Right align the dropdown menus while they're still in their original position.
		// Please note: the styling of the menus is at the root level (see below), because DbqBootstrapDropdownExtension moves an opened menu
		// to the body. This alignment must stay here: in the body the extension sets an inline left, and right: 0 would stretch the menu.
		.dbqdcldol-add-dropdown-menu,
		.dbqdcldol-group-menu,
		.dbqdcl-dropdown-menu {
			right: 0;
			left: auto;
		}

		.dbqdcldol-node {
			@extend %dbqdcldol-card;

			// Document nodes use the background of the rendering engine, categories override it below
			background: $dbqdcldol-document-background-color;

			// The functions of a document (e.g. delete) are aligned to the right, directly in front of the progress bar.
			// Categories keep their functions (e.g. Formulier toevoegen) next to the title.
			&[data-node-type="document"] > .dbqdcldol-node-header {
				> .dbqdcldol-node-header-actions {
					margin-left: auto;
				}

				> .dbqdcldol-node-header-actions + .dbqdcldol-progress {
					margin-left: $margin-default;
				}
			}

			.dbqdcldol-node-header {
				display: flex;
				align-items: center;
				gap: ($margin-default / 2);
				min-height: $dbqdcldol-header-height;
				padding: ($padding-default / 2) $padding-default;
				cursor: pointer;
				user-select: none;

				.dbqdcldol-node-arrow {
					display: inline-flex;
					flex-shrink: 0;
					transition: transform 0.15s ease-in-out;

					svg {
						width: $svg-icon-size;
						height: $svg-icon-size;
						fill: color(text-color-default);
					}
				}

				.dbqdcldol-node-title-container {
					display: flex;
					flex-direction: column;
					flex: 0 1 auto; // Only as wide as the title, so the functions (e.g. Formulier toevoegen) are placed right next to it
					min-width: 0;

					.dbqdcldol-node-title,
					.dbqdcldol-node-text {
						overflow: hidden;
						text-overflow: ellipsis;
						white-space: nowrap;
					}

					.dbqdcldol-node-title {
						font-weight: 600;
					}

					.dbqdcldol-node-text {
						font-size: 12px;
						color: color(text-color-default);
						opacity: 0.7;
					}
				}

				.dbqdcldol-node-badge {
					display: inline-flex;
					align-items: center;
					justify-content: center;
					flex-shrink: 0;
					min-width: 22px;
					height: 22px;
					padding: 0 6px;
					border-radius: 11px;
					background: $color-primary;
					color: #fff;
					font-size: 12px;
					font-weight: 600;
				}

				.dbqdcldol-node-header-actions {
					display: flex;
					align-items: center;
					flex-shrink: 0;
					gap: ($margin-default / 2);
					margin-left: ($margin-default / 2);
					cursor: default;

					// Without a progress bar the functions are the last element and stay on the right
					&:last-child {
						margin-left: auto;
					}

					// Function group with a query rule (dynamic menu)
					.dbqdcldol-group {
						.dbqdcldol-group-primary-button,
						.dbqdcldol-group-toggle {
							display: inline-flex;
							align-items: center;
							gap: 4px;
							height: $dbqdcldol-button-size;
							padding: 0 10px;
							border: 1px solid $button-border-color;
							border-radius: $border-radius-default;
							background: $button-background-color;
							color: $button-text-color;
							font-size: 13px;
							white-space: nowrap;
							outline: none;
							cursor: pointer;

							&::after {
								display: none; // Hide the bootstrap dropdown caret, the DropdownArrow icon is used instead
							}

							svg {
								width: 18px;
								height: 18px;
								fill: $button-text-color;
							}

							&:hover {
								background: $button-hover-background-color;
								border-color: $button-hover-border-color;
								color: $button-hover-text-color;

								svg {
									fill: $button-hover-text-color;
								}
							}

							&.disabled {
								opacity: 0.4;
								cursor: default;
								pointer-events: none;
							}
						}

						// Split mode: join the primary button and the toggle
						.dbqdcldol-group-primary-button {
							border-top-right-radius: 0;
							border-bottom-right-radius: 0;
						}

						.dbqdcldol-group-primary-button + .dbqdcldol-group-toggle {
							padding: 0 4px;
							border-left-color: rgba(255, 255, 255, 0.4); // Divider between the primary button and the toggle
							border-top-left-radius: 0;
							border-bottom-left-radius: 0;
						}
					}

					.dbqdcl-functions-container {
						display: flex;
						align-items: center;
						gap: 4px;

						.dbqdcl-dropdown-toggle,
						.dbqdcl-elevated-function {
							display: inline-flex;
							align-items: center;
							justify-content: center;
							width: $dbqdcldol-button-size;
							height: $dbqdcldol-button-size;
							padding: 0;
							background: none;
							border: none;
							outline: none;
							cursor: pointer;

							&::after {
								display: none;
							}

							svg {
								width: 20px;
								height: 20px;
								fill: color(text-color-default);
							}

							&:hover svg {
								fill: $color-primary;
							}

							&.disabled {
								opacity: 0.4;
								cursor: default;
								pointer-events: none;
							}
						}
					}
				}
			}

			.dbqdcldol-node-body {
				display: none;
			}

			// Expanded state
			&[data-is-expanded="true"] {

				// Sticky header: while scrolling through an expanded node, its header (title, progress, functions) stays visible at the top.
				// A sticky element only sticks within its own node, so only the header of the node you're scrolling through is shown.
				// The header inherits the background of its node, so the content scrolls underneath it.
				> .dbqdcldol-node-header {
					position: sticky;
					top: 0;
					z-index: 3;
					background: inherit;
					border-radius: $border-radius-default $border-radius-default 0 0;
				}

				> .dbqdcldol-node-header .dbqdcldol-node-arrow {
					transform: rotate(90deg);
				}

				> .dbqdcldol-node-body {
					display: block;
				}
			}

			// Document node: the expanded section contains the rendered document.
			// Please note: this is the container inside the body, not the node itself (the node has the type class .dbqdcldol-node-document).
			.dbqdcldol-node-document-container {
				position: relative;
				border-top: 1px solid $elevated-border-color;
				padding: $padding-default;

				.dbqdcldol-node-loading {
					display: flex;
					align-items: center;
					justify-content: center;
					min-height: 80px;
				}

				.dbqdb-header {
					background: none;
					border-bottom: none;
				}

				.dbqdb-block {
					&.dbqdb-block-elevated-background {
						border: none;
						background: transparent;
					}
				}

				.dbqdb-footer,
				.modal-footer,
				.dbqdb-sidepanel-footer-buttons {
					padding: 0;
				}

				// Our form footer (progress indicator): a status text with the undo link and save button.
				// It sticks to the bottom while scrolling through the form, and is only visible while there is something to save (see data-form-state below).
				.dbqdb-sidepanel-footer-buttons.dbqdcldol-form-buttons {
					position: sticky;
					bottom: 0;
					z-index: 2;
					justify-content: space-between;
					gap: $margin-default;
					padding: ($padding-default / 2) 0;
					background: $dbqdcldol-document-background-color;
					animation: dbqdcldol-form-buttons-in 0.2s ease-out;

					.dbqdcldol-form-status {
						display: inline-flex;
						align-items: center;
						gap: 4px;
						font-size: 13px;
						color: color(text-color-default);
						opacity: 0.8;

						svg {
							width: 18px;
							height: 18px;
							fill: color(text-color-success);
						}
					}

					.dbqdcldol-form-actions {
						display: flex;
						align-items: center;
						gap: ($margin-default / 2);

						// The undo link is an <a> without href, so it doesn't get a pointer cursor by itself
						.dbqdcldol-form-cancel {
							cursor: pointer;
						}
					}
				}
			}

			// Form state (progress indicator): clean = no footer, dirty = status + undo/save, saved = only the saved confirmation.
			// Please note: the selectors repeat the chain of the footer rule above, otherwise they lose on specificity.
			&[data-form-state="clean"] .dbqdcldol-node-document-container .dbqdb-sidepanel-footer-buttons.dbqdcldol-form-buttons {
				display: none;
			}

			&[data-form-state="saved"] .dbqdcldol-node-document-container .dbqdb-sidepanel-footer-buttons.dbqdcldol-form-buttons {
				.dbqdcldol-form-actions {
					display: none;
				}

				.dbqdcldol-form-status {
					color: color(text-color-success);
					opacity: 1;
				}
			}

			// Dirty marker: a dot behind the title, also visible in the sticky header and when the form is collapsed
			&[data-is-dirty="true"] > .dbqdcldol-node-header .dbqdcldol-node-title::after {
				content: "";
				display: inline-block;
				width: 8px;
				height: 8px;
				margin-left: 6px;
				border-radius: 50%;
				background: $color-primary;
				vertical-align: middle;
			}

			// Hide the (partially) rendered document while the document is loading
			&[data-is-loading="true"] > .dbqdcldol-node-body > .dbqdcldol-node-document-container > .dbqdcldol-node-document-render {
				display: none;
			}

			// Category node: the expanded section contains the items
			&.dbqdcldol-node-category {
				background: $dbqdcldol-category-background-color;

				> .dbqdcldol-node-header .dbqdcldol-node-title {
					text-transform: uppercase;
				}

				.dbqdcldol-node-children {
					display: flex;
					flex-direction: column;
					gap: ($margin-default / 2);
					padding: 0 $padding-default $padding-default ($padding-default * 2);

					&:empty {
						display: none;
					}

					.dbqdcldol-node {
						background: $dbqdcldol-document-background-color;

						// The header of an item sticks just below the (sticky) header of its category
						&[data-is-expanded="true"] > .dbqdcldol-node-header {
							top: $dbqdcldol-header-height;
							z-index: 2;
						}

						.dbqdcldol-node-title {
							font-weight: normal;
						}
					}
				}
			}
		}

		.dbqdcldol-footer {
			display: flex;
			justify-content: center;
			padding: $padding-default 0;

			.dbqdcldol-add-button,
			.dbqdcldol-add-dropdown-toggle {
				width: 40px;
				height: 40px;

				svg {
					width: 28px;
					height: 28px;
				}
			}

			// Labeled add button: the add icon followed by the name of the add function, shaped like the other buttons in the system
			.dbqdcldol-add-container-labeled {
				.dbqdcldol-add-button,
				.dbqdcldol-add-dropdown-toggle {
					width: auto;
					gap: 6px;
					padding: 0 18px 0 10px;
					border-radius: $border-radius-default;
					font-size: 14px;
					font-weight: 600;
				}
			}
		}

		.dbqdcldol-empty {
			@extend %dbqdcldol-card;
			display: flex;
			align-items: center;
			justify-content: center;
			gap: 5px;
			min-height: 120px;
			padding: $padding-default;

			.dbqdcldol-empty-icon,
			.dbqdcldol-empty-text {
				color: color(text-color-default);
				opacity: 0.7;
			}

			.dbqdcldol-empty-icon {
				display: flex;

				svg {
					width: $svg-icon-size;
					height: $svg-icon-size;
					fill: currentColor;
				}
			}

			.dbqdcldol-empty-text {
				margin: 0;
				font-size: 14px;
			}
		}

		.dbqdcldol-loading-spinner-container {
			position: absolute;
			top: 50%;
			left: 50%;
			transform: translate(-50%, -50%);
		}
	}
}

// Dropdown menus of the DocumentObjectList.
// These are deliberately not nested under #classlist-document-object-list: DbqBootstrapDropdownExtension moves an opened
// dropdown menu to the body (so it isn't trapped inside the class list window), and nested styles would no longer apply there.

// Add menu (multiple add functions) and the ⋮ menu of a node (.dbqdcldol-dropdown-menu is added by DocumentClassListTreeGridFunctionButtons)
.dbqdcldol-add-dropdown-menu .dropdown-item,
.dbqdcldol-dropdown-menu li a {
	display: flex;
	align-items: center;
	gap: 6px;

	svg {
		width: $classlist-tree-grid-function-button-svg-size;
		height: $classlist-tree-grid-function-button-svg-size;
		flex-shrink: 0;
	}
}

.dbqdcldol-dropdown-menu li {
	&.disabled {
		opacity: 0.5;
		pointer-events: none;
	}

	a {
		padding: 4px 12px;
		color: color(text-color-default);
		text-decoration: none;
	}
}

// Function group menu (dynamic menu loaded by a query rule, e.g. "Formulier toevoegen")
.dbqdcldol-group-menu {
	max-height: 400px;
	overflow-y: auto;

	.dbqdcldol-group-menu-loading {
		display: flex;
		align-items: center;
		gap: 6px;
	}
}

// The window content around a DocumentObjectList is its scroll container. Sticky elements (node headers at the top, form buttons and
// overall progress at the bottom) stop at the padding of the scroll container, which would leave a strip where the scrolling content
// shows through. So the vertical padding is moved from the scroll container to the list itself: same spacing, but it scrolls along.
.classlist-window-content:has(> #classlist-document-object-list) {
	padding-top: 0;
	padding-bottom: 0;

	> #classlist-document-object-list {
		padding-top: $padding-default;
		padding-bottom: $padding-default;
	}
}

// The refreshing bar runs from left to right while the list reloads
@keyframes dbqdcldol-refreshing-bar {
	from {
		transform: translateX(-100%);
	}

	to {
		transform: translateX(250%);
	}
}

// The form footer slides in when there is something to save
@keyframes dbqdcldol-form-buttons-in {
	from {
		opacity: 0;
		transform: translateY(8px);
	}

	to {
		opacity: 1;
		transform: none;
	}
}

// FolderDocumentObjectDisplayMode: colors the header of a node with the same colors as the rows of a regular list (see _classlist-tree-grid.scss).
// Standard (0) keeps the default styling. A transparent background is not applied, because the sticky header needs a solid background.
// Please note: this partial must be imported after _classlist-tree-grid.scss, because it uses its $list-* style maps.
$dbqdcldol-display-mode-styles: (
	1: $list-elevated,
	2: $list-essential,
	3: $list-information,
	4: $list-warning,
	5: $list-error,
	6: $list-diminished,
	7: $list-disabled,
	8: $list-success
);

@each $display-mode, $style in $dbqdcldol-display-mode-styles {
	#classlist-document-object-list .dbqdcldol-container .dbqdcldol-node[data-folder-document-object-display-mode="#{$display-mode}"] {
		> .dbqdcldol-node-header {
			@if map-get($style, background-color) != transparent {
				background-color: map-get($style, background-color);
			}

			.dbqdcldol-node-title,
			.dbqdcldol-node-text {
				color: map-get($style, font-color);
			}

			.dbqdcldol-node-arrow svg {
				fill: map-get($style, font-color);
			}
		}

		// A collapsed node consists of its header only, so the header follows the rounded corners of the node
		&:not([data-is-expanded="true"]) > .dbqdcldol-node-header {
			border-radius: $border-radius-default;
		}
	}
}
