html, body {
	overflow: hidden;
}

:root {
	--ct-body-bg: #fff;
	--ct-menu-bg: #eaeaea;
	--ct-menu-item-color: #000;
	--ct-menu-item-hover-color: #d8d8d8;
	--ct-menu-item-active-color: #000;
	--df-navtop-border: solid 1px #e4e4e4;
	--df-side-hover: #504f4f;
	--ag-cell-horizontal-padding: .8rem;
	--df-quick-filter-bg: #323130;
}

[data-bs-theme=dark] {
	--ct-body-bg: #252423;
	--ct-menu-bg: #3b3a39;
	--ct-menu-item-color: #fff;
	--ct-menu-item-hover-color: #474644;
	--ct-menu-item-active-color: #ffffff;
	--df-navtop-border: solid 1px #31302f;
	--ct-light: #4b4947;
	--ct-tertiary-bg: #615e5c;
	--ct-input-bg: #201f1e;
	--ct-body-color: #fff;
	--ct-body-color-rgb: 255, 255, 255;
	--df-side-hover: #504f4f;
	--df-quick-filter-bg: #323130;
}

/* The old app loaded Bootstrap's own CSS, which defined --bs-*; Hyper names the same values --ct-*. This file's rules
   still use --bs-* (border colour, tertiary bg, primary…), so they map onto Hyper's — on every themed element, so a
   light/dark subtree gets its own. */
:root,
[data-bs-theme] {
	--bs-body-bg: var(--ct-body-bg);
	--bs-body-color: var(--ct-body-color);
	--bs-secondary-color: var(--ct-secondary-color);
	--bs-tertiary-bg: var(--ct-tertiary-bg);
	--bs-border-color: var(--ct-border-color);
	--bs-border-radius: var(--ct-border-radius);
	--bs-border-radius-sm: var(--ct-border-radius-sm);
	--bs-font-monospace: var(--ct-font-monospace);
	--bs-primary: var(--ct-primary);
	--bs-primary-rgb: var(--ct-primary-rgb);
	--bs-success: var(--ct-success);
	--bs-success-text-emphasis: var(--ct-success-text-emphasis);
	--bs-info: var(--ct-info);
	--bs-warning: var(--ct-warning);
	--bs-warning-text-emphasis: var(--ct-warning-text-emphasis);
	--bs-danger: var(--ct-danger);
	--bs-danger-rgb: var(--ct-danger-rgb);
}

.nav-tabs {
	--ct-nav-tabs-link-active-bg: unset;
}

.no-arrow .dropdown-toggle::after {
	display: none !important;
}

/* The theme draws every badge in white (--ct-badge-color: #fff). On its bright fills — success #0acf97, warning
   #ffc35a, info #39afd1 — that's about 1.6–2.5:1 contrast, unreadable; dark text is 8–12:1. The fills are the same in
   both themes, so the text is dark in both. (bg-light isn't here: it's dark in dark mode.) */
.badge.bg-success,
.badge.bg-warning,
.badge.bg-info,
.badge.text-bg-success,
.badge.text-bg-warning,
.badge.text-bg-info {
	--ct-badge-color: #1c1f23;
	color: #1c1f23 !important;
}

/* Badges at the body's size. The theme's 0.75em is of the parent, so inside .small (status lines, table cells) a badge
   came out at about 0.6rem — too small to read. rem, so a badge in small text or a heading is the same size; a little
   less bold to suit. Badges sized for one place (.layout-palette-nav's counts, .df-workflow) keep their own size. */
.badge {
	--ct-badge-font-size: var(--ct-body-font-size, 0.9rem);
	--ct-badge-font-weight: 600;
}

.logo {
	background-color: var(--ct-topbar-bg);
	border-bottom: var(--df-navtop-border);
	box-shadow: -8px 0px 12px -4px rgba(0, 0, 0, 0.2);
	/*box-shadow: 0 0px 25px -15px rgba(0, 0, 0, 0.2);*/
}

.navbar-custom {
	/*box-shadow: 0 0px 25px -8px rgba(0, 0, 0, 0.2);*/
	box-shadow: 4px 0px 12px -4px rgba(0, 0, 0, 0.2);
	/*-webkit-box-shadow: none;*/
	border-bottom: var(--df-navtop-border);
}

.btn-light.btn:disabled {
	--ct-btn-disabled-bg: #4b4947;
	--ct-btn-disabled-border-color: #4b4947;
	--ct-btn-disabled-color: #807f7d;
}

/* The wordmark (df_wordmark*.svg) in the side menu */
.logo-lg img.df-wordmark {
	height: 22px;
}

/* The site's own logo (Settings > Branding; Views/Shared/Partials/BrandLogo.cshtml): as large as the box allows, kept in
   proportion, with "powered by" Dataflow's wordmark small under it. side-lg: the side menu's 70px logo box; auth: the
   sign-in card's header; sm: the collapsed menu's and the phone-width header's square */
/* around every logo image (BrandLogo.cshtml): the box a theme's decoration is placed on (Data/SiteThemes.cs) — no size of
   its own, the image's */
.df-logo-wrap {
	position: relative;
	display: inline-block;
	line-height: 0;
	vertical-align: middle;
}
/* the user menu's "Seasonal decorations" — shown by /branding/theme.css only while a theme is on */
.df-themes-item {
	display: none !important;
}
html.df-themes-off .df-themes-check {
	display: none;
}
.df-brand {
	display: inline-flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 4px;
	line-height: 1;
	vertical-align: middle;
}
.df-brand-side-lg {
	height: var(--ct-topbar-height, 70px);
}
.logo-lg .df-brand img.df-brand-img,
.df-brand img.df-brand-img {
	height: auto;
	width: auto;
	max-height: 36px;
	max-width: 200px;
	object-fit: contain;
}
.df-brand-auth img.df-brand-img {
	max-height: 56px;
	max-width: 260px;
}
.logo-sm img.df-brand-sm,
.logo-lg img.df-brand-sm {
	height: auto;
	width: auto;
	max-height: 32px;
	max-width: 32px;
	object-fit: contain;
	vertical-align: middle;
}
.logo-topbar img.df-brand-sm.df-brand-wide {
	max-width: 120px;
}
.leftside-menu .logo-sm img.df-brand-sm.df-brand-wide {
	max-width: 56px;
}
.df-powered {
	display: inline-flex;
	align-items: center;
	gap: 4px;
	font-size: 9px;
	letter-spacing: .03em;
	white-space: nowrap;
	color: var(--ct-topbar-item-color, currentColor);
	opacity: .7;
}
.df-powered img,
.logo-lg .df-powered img {
	height: 9px;
	width: auto;
}
.df-brand-auth .df-powered {
	color: #fff;
}

.leftside-menu {
	box-shadow: none;
	-webkit-box-shadow: none;
}

#leftside-menu-container {
	border-right: var(--df-navtop-border);
}

html[data-bs-theme=dark] {
	background-color: #252423;
}

/* the header's user block (Navbar.cshtml): the initials in a circle, then "First L." — one line, so the block is
   narrower than the theme's name-over-role */
.navbar-custom .df-user .df-user-initials {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 32px;
	height: 32px;
	border-radius: 50%;
	/* tinted, not solid: white on the dark theme's light-blue primary is hard to read */
	background-color: var(--ct-primary-bg-subtle);
	color: var(--ct-primary);
	font-size: 13px;
	font-weight: 600;
	letter-spacing: .02em;
	line-height: 1;
}
.navbar-custom .df-user h5 {
	white-space: nowrap;
}

/* the header search's button: the theme's .btn-primary glow hangs below it and makes it look taller than the input */
.app-search .input-group .btn {
	box-shadow: none;
	border-radius: 0 .25rem .25rem 0;      /* the input's corners — square ends read as a bigger block */
}

	/* the same height already, but a bright button beside a dim, borderless input looks taller: an edge on the input
	   (none against the button) evens them up — primary, the button's own colour, focused or not. Unscoped: the theme
	   is per browser */
	.navbar-custom .app-search form .df-search-input {
		border: 1px solid var(--ct-primary);
		border-right: 0;
	}

/* the wide header's search: the box itself while it fits beside the header's icons; when it doesn't
   (.df-search-compact on .navbar-custom, set by dfHeaderSearch.fit — Navbar.cshtml) an icon, and open
   (.df-search-opened, dfHeaderSearch.open) the bar slides out from the icon's left edge (--df-search-left) rightwards over
   the header, covering the icons in its way. Both the bar and the results box hang off .navbar-custom (sticky =
   positioned; .app-search is static) */
.navbar-custom:not(.df-search-compact) .df-search-open,
.navbar-custom:not(.df-search-compact) .df-search-close {
	display: none !important;
}

@media (min-width: 992px) {
	.navbar-custom.df-search-compact .topbar .app-search form.df-search-bar {
		position: absolute;
		top: 0;
		left: var(--df-search-left, 0px);
		z-index: 5;
		width: min(36rem, calc(100% - var(--df-search-left, 0px)));
		max-width: none;
		height: 100%;
		gap: .25rem;
		padding: 0 .5rem 0 0;
		background: var(--ct-topbar-bg);
		clip-path: inset(0 100% 0 0);
		visibility: hidden;
		transition: clip-path .2s ease, visibility 0s linear .2s;
	}

	.navbar-custom.df-search-compact.df-search-opened .topbar .app-search form.df-search-bar {
		clip-path: inset(0 0 0 0);
		visibility: visible;
		transition: clip-path .2s ease, visibility 0s;
	}

	.navbar-custom.df-search-compact .df-search-bar .input-group {
		flex: 1;
	}

	.navbar-custom.df-search-compact .app-search #search-dropdown {
		left: var(--df-search-left, 0px) !important;
		top: 100%;
	}
}

@media (prefers-reduced-motion: reduce) {
	.navbar-custom .topbar .app-search form.df-search-bar,
	.navbar-custom.df-search-opened .topbar .app-search form.df-search-bar {
		transition: none;
	}
}

	html[data-menu-color=dark],
	html[data-bs-theme=dark][data-menu-color=dark] {
		--ct-help-box-bg: rgba(255, 255, 255, 0.07);
	}

	html[data-topbar-color=dark],
	html[data-bs-theme=dark][data-topbar-color=light],
	html[data-bs-theme=dark][data-topbar-color=dark] {
		--ct-topbar-bg: #201f1e;
		--ct-topbar-item-color: #fff;
		--ct-topbar-item-hover-color: var(--ct-primary);
		--ct-topbar-search-bg: #464f5b;
		--ct-topbar-user-bg: #201f1e;
		--ct-topbar-user-border: #414d5d;
	}

	html[data-bs-theme=dark][data-menu-color=light],
	html[data-bs-theme=dark][data-menu-color=dark] {
		--ct-menu-bg: #3b3a39;
		--ct-menu-item-color: #fff;
		--ct-menu-item-hover-color: #fff;
		/*--ct-menu-item-active-color: #ffffff;
	--ct-help-box-bg: rgba(255, 255, 255, 0.07);*/
	}

.side-nav .side-nav-link:hover, .side-nav .side-nav-link:focus, .side-nav .side-nav-link:active {
	background-color: var(--df-side-hover);
}

.nav-tabs.nav-bordered {
	border-bottom: 0;
}

.input-monaco {
	border-radius: 0.25rem;
	padding: 1.5rem 4px 1rem .6rem;
}

	.input-monaco,
	.input-monaco .monaco-editor .margin,
	.input-monaco .monaco-editor, .monaco-editor-background {
		background-color: var(--ct-input-bg) !important;
	}

		.input-monaco .form-floating label {
			color: rgba(var(--ct-body-color-rgb), 0.65);
			padding: .5rem 0 0 0;
			transform: scale(.85) translateY(-2.00rem) translateX(0rem);
		}

monaco-diff-editor .synthetic-focus, .monaco-diff-editor [tabindex="-1"]:focus, .monaco-diff-editor [tabindex="0"]:focus, .monaco-diff-editor button:focus, .monaco-diff-editor input[type=button]:focus, .monaco-diff-editor input[type=checkbox]:focus, .monaco-diff-editor input[type=search]:focus, .monaco-diff-editor input[type=text]:focus, .monaco-diff-editor select:focus, .monaco-diff-editor textarea:focus, .monaco-editor {
	outline-width: 0px !important;
}


.edited-cell {
	font-weight: bold;
	background-color: rgba(255,255,0,.1);
}

/* an edit the server refused — still edited (keeps its tint), ringed in red with a corner mark; the tooltip says why */
.ag-cell.df-error-cell {
	box-shadow: inset 0 0 0 1px var(--bs-danger);
	background-image: linear-gradient(225deg, var(--bs-danger) 7px, transparent 7px);
}

/* its row: a red "!" before the row number (the number's tooltip lists the errors) — unlike deleted-row's right bar */
.df-error-row .ag-cell[col-id="__row"]::before {
	content: "!";
	position: absolute;      /* on the cell's left edge — the number (right-aligned) keeps its place in the narrow column */
	left: 6px;
	top: 50%;
	transform: translateY(-50%);
	width: 14px;
	height: 14px;
	border-radius: 50%;
	background: var(--bs-danger);
	color: #fff;
	font-size: 10px;
	font-weight: 700;
	line-height: 14px;
	text-align: center;
}

/* a cell someone else changed after it loaded (conflictMerge.js) — amber like the form's note; green once decided */
.ag-cell.df-conflict-cell {
	box-shadow: inset 0 0 0 1px var(--bs-warning);
	background-image: linear-gradient(225deg, var(--bs-warning) 7px, transparent 7px);
}
.ag-cell.df-conflict-resolved-cell {
	box-shadow: inset 0 0 0 1px var(--bs-success);
}
.df-conflict-row .ag-cell[col-id="__row"]::before {
	content: "!";
	position: absolute;
	left: 6px;
	top: 50%;
	transform: translateY(-50%);
	width: 14px;
	height: 14px;
	border-radius: 50%;
	background: var(--bs-warning);
	color: #000;
	font-size: 10px;
	font-weight: 700;
	line-height: 14px;
	text-align: center;
}

. /*first-col span {
	text-decoration: underline;
	cursor: pointer;
}

	.first-col span:hover {
		text-decoration: none;
	}*/
.edited-row {
	/*background-color: rgba(224, 247, 250, 0.5);*/ /* Light black overlay for a subtle dark effect */
	/*background-color: black;*/
}
/*.ag-row {    border-left: 4px solid transparent; }
.ag-row-selected {
    border-left: 4px solid #007acc;
}*/
.ag-row-selected:before {
	border-left: 4px solid #007acc;
	background-color: rgba(0, 122, 204, 0.2);
}

.ag-center-cols-container .ag-row-selected:before {
	border-left-color: transparent;
}

/*.ag-row-hover > .ag-cell:first-child
{
	position: relative;
}
.ag-row-hover > .ag-cell:first-child:after {
	content: 'a';
    position: absolute;
	right: 4px;
	color: red;
	top: 4px;
}*/

.df-grid-menu a {
	color: var(--ct-body-color);
}

.ag-body a {
	color: var(--ct-body-color);
}

.df-form.modal-body {
	position: relative;
}

.df-form > .inner-scroll {
	position: relative;
}

.input-max {
	position: absolute !important;
	inset: 0;
	width: auto;
	z-index: 999;
	background: var(--ct-body-bg);
	padding: .5rem;
	margin-bottom: 0;
	overflow: auto;
}

	.input-max,
	.input-max > div,
	.input-max > div > div {
		height: 100% !important;
	}

		.input-max textarea.form-control {
			height: 100% !important;
		}

		.input-max textarea.form-control,
		.input-max .form-control {
			border: 0 !important;
			border-radius: 0 !important;
		}

.search-top {
	padding: 0 calc(var(--ag-cell-horizontal-padding) * 2);
}


/* Your directive wrapper fix (keep this) */
manage {
	display: flex;
	flex-direction: column;
	height: 100%;
	min-height: 0;
}

	manage > .modal-body {
		flex: 1 1 auto;
		overflow: hidden; /* important: let inner-scroll handle the overflow */
		min-height: 0;
	}

/* Fixed header inside modal-body */
.modal-body .inner-header {
	position: sticky;
	top: 0;
	background: var(--ct-modal-bg); /* or your modal background */
	z-index: 20;
}

/* Scrollable content area */
.modal-body .inner-scroll {
	overflow-y: auto;
	min-height: 0;
	max-height: 100%;
}

.dropdown-queries {
	max-width: 250px;
}

.query-favorite {
	min-width: 25px;
}

	.query-favorite .mdi {
		font-size: 1.0rem;
	}

		.query-favorite .mdi:hover {
			opacity: 0.7;
			cursor: pointer;
		}

/*.df-input .input-textarea textarea.form-control { height: 120px; min-height: 120px; }
.df-input .input-textarea.input-max textarea.form-control { height: 60vh; min-height: 60vh; }*/

.input-monaco .form-floating > div[id^="editor_"] {
	transition: opacity .15s ease;
}

.editor-fade {
	opacity: 0;
}

.df-readonly-code {
	max-height: 250px;
	overflow: auto;
	white-space: pre-wrap;
}

.df-input {
	margin-bottom: 1rem;
	display: block;
}

button u, .ribbon-button u, .nav-link u {
	text-decoration: none;
}

html[data-shortcut="true"] button u,
html[data-shortcut="true"] .ribbon-button u,
html[data-shortcut="true"] .nav-link u {
	text-decoration: underline;
}

.df-null .form-control {
	font-style: italic;
}

	.df-null .form-control::placeholder {
		color: #7a7a7a;
	}

.df-null .form-floating > .form-control ~ label {
	transform: scale(0.85) translateY(-0.5rem) translateX(0.15rem);
}

.df-null .form-floating::after {
	content: "NULL";
	position: absolute;
	left: 0.75rem;
	top: 1.625rem;
	line-height: 1.25;
	font-style: italic;
	opacity: 0.55;
	pointer-events: none;
	font-size: 1rem;
}

/*.df-input .input-group { position: relative; }*/

.df-input .input-group .dropdown {
	display: flex;
	align-self: stretch;
}

/* group behaves as the field */
.df-input .input-group:has(.field-menu-btn) {
	border: 1px solid var(--bs-border-color);
	border-radius: var(--bs-border-radius);
	background: var(--bs-body-bg);
	/*overflow: hidden;*/
}

	/* input gives up its own chrome */
	.df-input .input-group:has(.field-menu-btn) .form-control {
		border: 0;
		border-radius: 0;
		background: transparent;
	}

.df-input .field-menu-btn {
	height: 100%;
	border: 0;
	background: transparent;
	padding: 0 0.6rem;
	color: #6d6d6d;
	display: flex;
	align-items: center;
	transition: background-color .12s ease, color .12s ease;
}

.df-input .input-group:hover .field-menu-btn,
.df-input .input-group:focus-within .field-menu-btn {
	color: #b8b8b8;
}

.df-input .field-menu-btn:hover,
.df-input .field-menu-btn:focus-visible,
.df-input .field-menu-btn[aria-expanded="true"] {
	background: rgba(255,255,255,.08);
	color: #fff;
}

.df-input .input-group:has(textarea) .dropdown {
	align-self: stretch;
}

.df-input .input-group:has(textarea) .field-menu-btn {
	align-items: flex-start;
	padding-top: 0.5rem;
}

.df-input .input-group:has(.field-menu-btn) textarea.form-control {
	resize: vertical;
}

.df-input .form-floating > textarea.form-control {
	height: 120px;
	min-height: 120px;
}




.ribbon {
	padding: 0.25rem 0.75rem 0.5rem;
}

.ribbon-tabs {
	gap: 0.25rem;
	margin-bottom: 0.25rem;
}

.ribbon-tab {
	border-radius: 0.25rem 0.25rem 0 0;
	padding: 0.25rem 0.75rem;
	color: var(--bs-secondary-color);
	text-decoration: none;
	border: 1px solid transparent;
	border-bottom: none;
	background: transparent;
}

	.ribbon-tab:hover {
		color: var(--bs-body-color);
	}

	.ribbon-tab.active {
		border-color: var(--bs-border-color);
		color: var(--bs-body-color);
		font-weight: 500;
	}

.ribbon-body {
	display: flex;
	align-items: stretch;
	gap: 1rem;
	padding-top: 0.5rem;
	padding-bottom: 0.25rem;
	border-color: var(--bs-border-color) !important;
	/*overflow: hidden;*/
}

.ribbon-group {
	display: flex;
	flex-direction: column;
	border-right: 1px solid var(--bs-border-color);
	padding-right: 1rem;
	flex: 0 0 auto;
}

	.ribbon-group:last-child {
		border-right: none;
		padding-right: 0;
	}

.ribbon-group-content {
	display: flex;
	gap: 0.25rem;
	align-items: flex-start;
	order: 1;
	flex: 1 1 auto;
}

.ribbon-group-title {
	font-size: 0.7rem;
	text-transform: uppercase;
	color: var(--bs-secondary-color);
	text-align: center;
	order: 2;
	margin-top: 0.35rem;
	flex: 0 0 auto;
}

/* large tier — icon over label */
.ribbon-btn {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 0.15rem;
	white-space: nowrap;
	flex: 0 0 auto;
	min-width: 3.5rem;
	padding: 0.35rem 0.5rem;
	background: transparent;
	border: 1px solid transparent;
	border-radius: 0.25rem;
	color: var(--bs-body-color);
	font-size: 0.75rem;
	line-height: 1.1;
}

	.ribbon-btn:hover:not(:disabled) {
		background: rgba(255,255,255,.08);
		border-color: var(--bs-border-color);
	}

	.ribbon-btn:disabled {
		opacity: .4;
	}

	/* a link-type item (the Related group) — an <a>, so it opens in a new tab too */
	a.ribbon-btn {
		text-decoration: none;
	}

	.ribbon-btn .rb-icon {
		font-size: 2.15rem;
	}

/* stacked column of small buttons */
.ribbon-stack {
	display: flex;
	flex-direction: column;
	gap: 0.15rem;
}

	.ribbon-stack .ribbon-btn {
		flex-direction: row;
		justify-content: flex-start;
		gap: 0.4rem;
		min-width: 0;
		padding: 0.15rem 0.5rem;
	}

		.ribbon-stack .ribbon-btn .rb-icon {
			font-size: 0.9rem;
			width: 1rem;
			text-align: center;
		}

.ribbon-group-content > .ribbon-btn {
	align-self: stretch;
	justify-content: flex-start;
}

/* medium tier — icon beside label */
@media (max-width: 1400px) {
	.ribbon-group[data-tier="flex"] .ribbon-group-content > .ribbon-btn {
		flex-direction: row;
		gap: 0.4rem;
		min-width: 0;
	}

	/* only with the icon-beside-label layout above — the ribbon's buttons sit inside ng-repeat's <any>, so that layout
	   rarely applies, and a small icon over its label looked out of place beside the fixed groups' large ones */
	.ribbon-group[data-tier="flex"] .ribbon-group-content > .ribbon-btn .rb-icon {
		font-size: 0.9rem;
	}
}

/* small tier — icon only, on phones; wider screens keep the label under the large icon, like the fixed groups */
@media (max-width: 575.98px) {
	.ribbon-group[data-tier="flex"] .ribbon-btn .rb-label {
		display: none;
	}
}

.dropdown-menu {
	box-shadow: 0 0.5rem 1.5rem rgba(0, 0, 0, .5);
	border: 1px solid rgba(255, 255, 255, .09);
}


.text-fail {
	--ct-text-opacity: 1;
	color: rgba(var(--ct-danger-rgb), var(--ct-text-opacity)) !important;
}

.bg-fail {
	--ct-bg-opacity: 1;
	background-color: rgba(var(--ct-danger-rgb), var(--ct-bg-opacity)) !important;
}

.notification-list .notify-item .card-body .alert-wrap .noti-item-title,
.notification-list .notify-item .card-body .alert-wrap .noti-item-subtitle {
	white-space: normal !important;
}

/* ---------- palette ---------- */
.layout-palette {
	background: var(--bs-tertiary-bg);
	border: 1px solid var(--bs-border-color);
	border-radius: .375rem;
	padding: .75rem;
}

.layout-palette-title {
	font-size: .7rem;
	text-transform: uppercase;
	color: var(--bs-secondary-color);
	margin-bottom: .5rem;
}

/* ---------- canvas ---------- */
.layout-canvas {
	display: flex;
	flex-wrap: wrap;
	align-items: flex-start;
	min-height: 200px;
}

.layout-section-wrap {
	padding: 0 .25rem .75rem;
	flex: 0 0 auto;
}

.layout-section {
	height: 100%;
	margin-bottom: 0;
}

/* layout-size: a group's / item's width — the label opens a 12-stop slider (layoutEditor.js) */
.layout-size {
	flex: 0 0 auto;
}

.layout-size-btn {
	display: inline-flex;
	align-items: center;
	gap: .1rem;
	background: transparent;
	border: 1px solid transparent;
	border-radius: .2rem;
	color: var(--bs-secondary-color);
	font-size: .7rem;
	line-height: 1.4;
	padding: 0 .15rem 0 .3rem;
	white-space: nowrap;
}

	.layout-size-btn:hover,
	.layout-size-btn[aria-expanded="true"] {
		border-color: var(--bs-border-color);
		color: var(--bs-body-color);
	}

.layout-size-menu {
	width: 15rem;
	padding: .5rem .75rem .6rem;
	cursor: default;
}

.layout-size-head {
	display: flex;
	align-items: baseline;
	gap: .5rem;
	font-size: .75rem;
	margin-bottom: .25rem;
}

	.layout-size-head b {
		margin-left: auto;
	}

.layout-size-menu .form-range {
	display: block;
	cursor: pointer;
}

/* layout-resize: the right edge of a placed item / a group — drag to resize (layoutEditor.js) */
.layout-chip-placed,
.layout-section {
	position: relative;
}

.layout-resize {
	position: absolute;
	top: 0;
	bottom: 0;
	right: -5px;
	width: 9px;
	cursor: ew-resize;
	z-index: 2;
	touch-action: none;
}

	/* a bar on the edge — always there so it can be found; full strength on hover / while dragging */
	.layout-resize::after {
		content: "";
		position: absolute;
		top: 20%;
		bottom: 20%;
		left: 3px;
		width: 3px;
		border-radius: 2px;
		background: var(--bs-primary);
		opacity: .45;
		transition: opacity .1s;
	}

	.layout-resize:hover::after,
	body.layout-resizing .layout-resize:has(.layout-resize-label)::after {
		opacity: 1;
	}

.layout-resize-label {
	position: absolute;
	top: -.6rem;
	right: 6px;
	font-size: .7rem;
	line-height: 1.3;
	padding: 0 .3rem;
	border-radius: .2rem;
	background: var(--bs-primary);
	color: #fff;
	white-space: nowrap;
	pointer-events: none;
}

body.layout-resizing,
body.layout-resizing * {
	cursor: ew-resize !important;
	user-select: none;
}

/* the 12 stops under the track, lined up with the thumb's centre (the thumb is 1rem wide) */
.layout-size-ticks {
	display: flex;
	justify-content: space-between;
	padding: 0 .5rem;
	margin-top: .1rem;
}

	.layout-size-ticks button {
		width: 2px;
		height: .45rem;
		padding: 0;
		border: 0;
		background: var(--bs-border-color);
		position: relative;
	}

		.layout-size-ticks button.on {
			background: var(--bs-primary);
		}

		/* a bigger target than the 2px mark */
		.layout-size-ticks button::after {
			content: "";
			position: absolute;
			inset: -.3rem -.4rem;
		}

.layout-empty {
	border: 1px dashed var(--bs-border-color);
	border-radius: .375rem;
	padding: 2rem;
	text-align: center;
	color: var(--bs-secondary-color);
	font-style: italic;
}

/* ---------- section ---------- */
.layout-section {
	border: 1px solid var(--bs-border-color);
	border-radius: .375rem;
	margin-bottom: .75rem;
	background: var(--bs-body-bg);
}

	.layout-section.active {
		border-color: var(--bs-primary);
		box-shadow: 0 0 0 1px var(--bs-primary);
	}

.layout-section-head {
	display: flex;
	align-items: center;
	gap: .5rem;
	padding: .35rem .5rem;
	background: var(--bs-tertiary-bg);
	border-bottom: 1px solid var(--bs-border-color);
	border-radius: .375rem .375rem 0 0;
}

.layout-section-grip,
.layout-row-grip,
.layout-chip-grip {
	color: var(--bs-secondary-color);
	cursor: grab;
	flex: 0 0 auto;
}

.layout-section-title {
	flex: 1 1 auto;
	background: transparent;
	border: 1px solid transparent;
	border-radius: .25rem;
	color: var(--bs-body-color);
	padding: .1rem .35rem;
	font-weight: 500;
}

	.layout-section-title:hover {
		border-color: var(--bs-border-color);
	}

	.layout-section-title:focus {
		border-color: var(--bs-primary);
		outline: none;
		background: var(--bs-body-bg);
	}

.layout-row-tools {
	flex: 0 0 auto;
	align-self: flex-start;
}

	.layout-row-tools .btn {
		padding: .25rem .4rem;
		line-height: 1;
		color: var(--bs-secondary-color);
		border: 0;
	}

		.layout-row-tools .btn:hover,
		.layout-row-tools .btn[aria-expanded="true"] {
			color: var(--bs-body-color);
			background: rgba(255,255,255,.08);
		}

.layout-section-body {
	padding: .5rem;
}

/* ---------- row ---------- */
.layout-row {
	display: flex;
	align-items: flex-start;
	gap: .5rem;
	padding: .35rem;
	border: 1px dashed transparent;
	border-radius: .25rem;
}

	.layout-row:hover {
		border-color: var(--bs-border-color);
	}

	.layout-row.dragging,
	.layout-section-wrap.dragging {
		opacity: .5;
	}

/* dragging a group: the group under the pointer lights up, not the row or tabs box inside it */
body[data-layout-drag="section"] .drop-target:not(.layout-canvas) {
	border-color: transparent !important;
	background: none !important;
}

body[data-layout-drag="section"] .layout-section:has(.drop-target) {
	border-color: var(--bs-primary);
	box-shadow: 0 0 0 2px var(--bs-primary);
}

/* a row's drag handle, at its left — level with the first line of items */
.layout-row-grip {
	align-self: flex-start;
	padding: .45rem 0;
	line-height: 1;
}

	.layout-row-grip:hover {
		color: var(--bs-body-color);
	}

	.layout-row.drop-target {
		border-color: var(--bs-primary);
		background: rgba(var(--bs-primary-rgb), .08);
	}

.layout-grid {
	flex: 1 1 auto;
	display: flex;
	flex-wrap: wrap;
	align-items: flex-start;
	gap: 0;
	min-height: 2.25rem;
}

.layout-row-empty {
	flex: 1 1 auto;
	display: flex;
	align-items: center;
	justify-content: center;
	border: 1px dashed var(--bs-border-color);
	border-radius: .25rem;
	color: var(--bs-secondary-color);
	font-size: .8rem;
	font-style: italic;
	min-height: 2.25rem;
}

.layout-row-total {
	font-size: .7rem;
	color: var(--bs-secondary-color);
	align-self: center;
	padding: 0 .25rem;
	white-space: nowrap;
}

	.layout-row-total.over {
		color: var(--bs-danger);
		font-weight: 600;
	}

.layout-add-row {
	background: transparent;
	border: 1px dashed var(--bs-border-color);
	border-radius: .25rem;
	color: var(--bs-secondary-color);
	font-size: .8rem;
	padding: .25rem .75rem;
	width: 100%;
	margin-top: .25rem;
}

	.layout-add-row:hover {
		color: var(--bs-body-color);
		border-color: var(--bs-secondary-color);
	}

/* ---------- chips ---------- */
.layout-chip {
	display: flex;
	align-items: center;
	gap: .35rem;
	padding: .3rem .4rem;
	border-radius: .25rem;
	font-size: .8rem;
	cursor: grab;
	border: 1px solid transparent;
	white-space: nowrap;
}

	.layout-chip:active {
		cursor: grabbing;
	}

	.layout-chip.dragging {
		opacity: .4;
	}

.layout-chip-placed {
	background: rgba(var(--bs-primary-rgb), .18);
	border-color: rgba(var(--bs-primary-rgb), .45);
	color: var(--bs-body-color);
	/* width set inline from span */
	flex: 0 0 auto;
	margin-bottom: .25rem;
}

.layout-chip-unassigned {
	background: var(--bs-body-bg);
	border-color: var(--bs-border-color);
	margin-bottom: .25rem;
}

	.layout-chip-unassigned:hover {
		border-color: var(--bs-secondary-color);
	}

.layout-chip-label {
	flex: 1 1 auto;
	overflow: hidden;
	text-overflow: ellipsis;
}

.layout-chip-type {
	font-size: .65rem;
	color: var(--bs-secondary-color);
	flex: 0 0 auto;
}

.layout-chip-menu .btn {
	padding: 0 .2rem;
	line-height: 1;
	border: 0;
	background: transparent;
	color: var(--bs-secondary-color);
	flex: 0 0 auto;
}

	.layout-chip-menu .btn:hover,
	.layout-chip-menu .btn[aria-expanded="true"] {
		color: var(--bs-body-color);
	}

.df-section {
	border: 0;
	padding: 0;
	margin: 0 0 .5rem;
}

/* a tabs element on the record form — one item per tab */
.df-form-tabset {
	margin-bottom: .5rem;
}

.df-form-tabs {
	margin-bottom: 0;
}

.df-form-tab-pane {
	border: 1px solid var(--bs-border-color);
	border-top: 0;
	border-radius: 0 0 .375rem .375rem;
	padding: .5rem;
}

/* layout editor: placed items sit in a slot sized by span; a tabs element holds its tabs left to right */
.layout-chip-slot {
	flex: 0 0 auto;
}

	.layout-chip-slot > .layout-chip-placed {
		width: 100%;
	}

.layout-chip-tabs {
	background: rgba(var(--bs-primary-rgb), .08);
	cursor: default;
}

.layout-tabs-body {
	display: flex;
	flex-wrap: wrap;
	gap: .25rem;
	padding: .35rem;
	border: 1px dashed var(--bs-border-color);
	border-radius: .25rem;
	cursor: default;
}

	.layout-tabs-body.drop-target {
		border-color: var(--bs-primary);
		background: rgba(var(--bs-primary-rgb), .08);
	}

.layout-tab-slot {
	flex: 1 1 10rem;
	min-width: 8rem;
	max-width: 100%;
}

	.layout-tab-slot > .layout-chip-placed {
		margin-bottom: 0;
		border-top-width: 3px;
	}

/* a group tab: a tab holding rows of items — a line of its own in the tabs element */
.layout-tab-slot.layout-tab-slot-group {
	flex: 1 1 100%;
}

.layout-chip-tabgroup {
	background: rgba(var(--bs-primary-rgb), .08);
	cursor: default;
}

	.layout-chip-tabgroup.active {
		border-color: var(--bs-primary);
		box-shadow: 0 0 0 1px var(--bs-primary);
	}

.layout-tabgroup-body {
	border: 1px dashed var(--bs-border-color);
	border-radius: .25rem;
	padding: .25rem;
	cursor: default;
	white-space: normal;
}

	.layout-tabgroup-body .layout-add-row {
		margin-top: 0;
	}

.layout-canvas.drop-target {
	outline: 1px dashed var(--bs-primary);
	outline-offset: 2px;
}

.df-section-title {
	font-size: .75rem;
	text-transform: uppercase;
	color: var(--bs-secondary-color);
	border-bottom: 1px solid var(--bs-border-color);
	padding-bottom: .25rem;
	margin-bottom: .25rem;
	float: none;
	width: 100%;
}

.toast-subject {
	font-size: .7rem;
	text-transform: uppercase;
	letter-spacing: .03em;
	opacity: .75;
	margin-bottom: .1rem;
}

.input-monaco > .form-floating > div[id^="editor_"] {
	height: 250px;
}

.quick-filters {
	border-bottom: 1px solid var(--bs-border-color);
	background-color: var(--df-quick-filter-bg);
}

.quick-filter-btn {
	background-color: var(--bs-body-bg);
	border: 1px solid var(--bs-border-color);
	color: var(--bs-body-color);
	max-width: 14rem;
	white-space: nowrap;
	max-width: 14rem;
	overflow: hidden;
	text-overflow: ellipsis;
}

	.quick-filter-btn:hover {
		background-color: var(--bs-body-bg);
		border-color: var(--bs-secondary-color);
	}

	.quick-filter-btn.active {
		border-color: var(--bs-primary);
		background-color: rgba(var(--bs-primary-rgb), .12);
	}

.layout-req {
	color: var(--bs-danger);
	margin-left: .15rem;
	font-weight: 600;
}

.layout-chip-required {
	border-color: rgba(var(--bs-danger-rgb), .5);
}

.quick-filter-btn .qf-label {
	font-size: .6rem;
	line-height: 1;
	opacity: .6;
	text-transform: uppercase;
}

.quick-filter-btn .qf-value {
	line-height: 1.2;
}

.form-floating > textarea.form-control {
	padding-top: 2.25rem;
}

.form-floating > label.textarea-label {
	padding-top: .3rem;
	padding-bottom: .2rem;
}

/* the strip behind a floated label: the theme's 1.875em reaches ~1px into the value's line once the label is scaled and
   lifted, clipping the tops of capitals in every floating select / lookup / text box — Bootstrap's own 1.5em covers the
   label's line and stops above the value */
.form-floating > .form-control:focus ~ label::after,
.form-floating > .form-control:not(:placeholder-shown) ~ label::after,
.form-floating > .form-control-plaintext ~ label::after,
.form-floating > .form-select ~ label::after {
	height: 1.5em;
}

.df-panel .modal-dialog {
	position: fixed;
	top: 0;
	right: 0;
	margin: 0;
	width: 30rem;
	max-width: 100vw;
	height: 100vh;
	transform: translateX(100%);
	transition: transform .25s ease-out;
}

.df-panel.df-panel-wide .modal-dialog {
	width: min(64rem, 100vw);
}

.df-panel.show .modal-dialog {
	transform: translateX(0);
}

.df-panel .modal-content {
	height: 100vh;
	border-radius: 0;
	border-top: 0;
	border-right: 0;
	border-bottom: 0;
}

@media (max-width: 576px) {
	.df-panel .modal-dialog {
		width: 100vw;
	}
}

/* busy indicators (df-script.js): a bar across the top while any /api/ call runs, and a spinner on the button that
   started one. The button's text and icon go transparent so its size doesn't change. */
#df-progress {
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	height: 3px;
	z-index: 2000;
	pointer-events: none;
	opacity: 0;
	overflow: hidden;
	transition: opacity .2s ease;
}

	#df-progress.on {
		opacity: 1;
	}

	#df-progress::before {
		content: "";
		position: absolute;
		top: 0;
		bottom: 0;
		width: 35%;
		background: var(--ct-primary);
		animation: df-progress 1.1s ease-in-out infinite;
	}

@keyframes df-progress {
	from { left: -35%; }
	to { left: 100%; }
}

.df-busy {
	cursor: progress !important;
}

.df-busy.df-busy-show {
	position: relative;
	color: transparent !important;
}

	.df-busy.df-busy-show > * {
		visibility: hidden;
	}

	.df-busy.df-busy-show::after {
		content: "";
		position: absolute;
		top: 50%;
		left: 50%;
		width: 1rem;
		height: 1rem;
		margin: -.5rem 0 0 -.5rem;
		border: 2px solid currentColor;
		border-color: var(--df-busy-color, var(--ct-body-color));
		border-right-color: transparent;
		border-radius: 50%;
		animation: df-spin .7s linear infinite;
		visibility: visible;
	}

.btn-primary.df-busy-show::after, .btn-danger.df-busy-show::after, .btn-success.df-busy-show::after {
	--df-busy-color: #fff;
}

@keyframes df-spin {
	to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
	#df-progress::before, .df-busy.df-busy-show::after {
		animation-duration: 2.5s;
	}
}

/* maintenance mode (application settings) — a strip across the top of the page, and a dot on the header cog */
.df-maintenance-banner {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: .25rem;
	padding: .5rem 1rem;
	background: rgba(var(--ct-warning-rgb), .15);
	border-bottom: 1px solid rgba(var(--ct-warning-rgb), .5);
	color: var(--ct-body-color);
}

	.df-maintenance-banner .mdi {
		color: var(--ct-warning);
		font-size: 1.1rem;
	}

/*a ~source/ page (Layout_AngularJS): the data source it reads and writes — the warning colour, as maintenance, but
slimmer*/
.df-source-banner {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: .25rem;
	padding: .35rem 1rem;
	background: rgba(var(--ct-warning-rgb), .15);
	border-bottom: 1px solid rgba(var(--ct-warning-rgb), .5);
	color: var(--ct-body-color);
	font-size: .8125rem;
}

	/* the trail above a page's title (dfCrumbs.js) — small and quiet; the title under it stays the heading */
	.df-crumbs {
		font-size: .8rem;
		padding-top: .5rem;
	}

		.df-crumbs a {
			color: var(--bs-secondary-color);
		}

			.df-crumbs a:hover {
				color: var(--bs-link-hover-color);
			}

		.df-crumbs .breadcrumb-item + .breadcrumb-item::before {
			color: var(--bs-secondary-color);
		}

	.df-source-banner .mdi {
		color: var(--ct-warning);
		font-size: 1.1rem;
	}

	/* the page bar (dfPageBar.js): a thin strip under the header, as the maintenance banner, a touch of the primary
	   colour — one line: the page's title on the left, its ⋮ on the right (the trail, a description and buttons stay under
	   it on the page); stays at the top of .content-page (the scroller) — the element itself makes no box, or the strip
	   could only stick inside it */
	df-page-bar {
		display: contents;
	}

	/* what a page hands the bar (dfPageBarPart) stays hidden until it's placed — moved in, or left where it is */
	[df-page-bar-part]:not(.df-placed) {
		display: none !important;
	}

	/* what sticks: the bar and the line a page may hand it under it (a banner — the "below" part) */
	.df-page-bar-stick {
		position: sticky;
		top: 0;
		z-index: 6;
	}

		.df-page-bar-below:empty {
			display: none;
		}

	.df-page-bar {
		display: flex;
		align-items: center;
		gap: .75rem;
		min-height: 2.3rem;
		padding: .2rem .5rem .2rem 1rem;
		background: color-mix(in srgb, var(--bs-primary) 9%, var(--bs-body-bg));
		border-bottom: 1px solid color-mix(in srgb, var(--bs-primary) 25%, var(--bs-border-color));
	}

		/* clipped sideways only (clip, not hidden — hidden would clip both ways): a grid's saved-queries menu drops below it */
		.df-page-bar-title {
			flex: 1 1 auto;
			min-width: 0;
			overflow-x: clip;
			overflow-y: visible;
		}

			/* what's moved in keeps its own markup — made to fit one line (the theme pads every .breadcrumb 12px top and
			   bottom, and a grid's saved-queries menu is a header nav-link) */
			.df-page-bar-title .breadcrumb {
				padding: 0;
				flex-wrap: nowrap;
			}

			.df-page-bar-title h4, .df-page-bar-title .page-title {
				font-size: .95rem;
				font-weight: 600;
				line-height: 1.5;
				margin: 0;
				white-space: nowrap;
				overflow: hidden;
				text-overflow: ellipsis;
			}

			.df-page-bar-title .nav-link {
				padding: 0;
				font-size: .85rem;
				white-space: nowrap;
			}

		/* the page's small buttons (the "actions" part), then the ⋮ — on one line */
		.df-page-bar-end {
			display: flex;
			align-items: center;
			gap: .25rem;
			flex-shrink: 0;
		}

		.df-page-bar-more {
			padding: 0 .35rem;
			line-height: 1.6;
		}

	.df-page-menu {
		min-width: 14rem;
	}

	.df-page-menu {
		min-width: 14rem;
	}

.df-app-dot {
	position: absolute;
	top: 1.4rem;
	right: .55rem;
	width: .5rem;
	height: .5rem;
	border-radius: 50%;
	background: var(--ct-warning);
}

/* page help (helpTour.js) — above modals (1055), under toasts (1090). The spotlight's huge shadow is the dimming; a
   zero-size spotlight in the middle dims everything for a card with no element. */
.df-help-backdrop {
	position: fixed;
	inset: 0;
	z-index: 1085;
}

.df-help-spot {
	position: fixed;
	z-index: 1086;
	border-radius: .375rem;
	box-shadow: 0 0 0 200vmax rgba(0, 0, 0, .55);
	outline: 2px solid var(--ct-primary);
	pointer-events: none;
	transition: top .2s ease, left .2s ease, width .2s ease, height .2s ease;
}

	.df-help-spot.df-help-floating {
		outline: none;
	}

	/* the dark theme is near-black already — dim harder or nothing seems to change */
	[data-bs-theme="dark"] .df-help-spot {
		box-shadow: 0 0 0 200vmax rgba(0, 0, 0, .75);
	}

.df-help-card {
	border: 1px solid var(--ct-border-color);
	position: fixed;
	z-index: 1087;
	width: min(22rem, calc(100vw - 1rem));
	max-height: calc(100vh - 1rem);
	overflow: auto;
	transition: top .2s ease, left .2s ease;
}

.df-help-content img {
	max-width: 100%;
}

.df-help-content > :last-child {
	margin-bottom: 0;
}

/* the Shift+F2 editor. Order: outlines 1081, labels 1082, focus ring 1083, panel 1084 (labels of anything under the
   panel on a narrow screen stay under it), then the tour (a preview dims the panel too). */
.df-help-keybox {
	position: fixed;
	z-index: 1081;
	border: 1px dashed var(--ct-primary);
	border-radius: .25rem;
	pointer-events: none;
}

.df-help-key {
	position: fixed;
	z-index: 1082;
	padding: 0 .3rem;
	border: 0;
	border-radius: .2rem;
	background: var(--ct-primary);
	color: #fff;
	font: 11px/16px var(--bs-font-monospace);
	white-space: nowrap;
	cursor: pointer;
	opacity: .85;
}

	.df-help-key:hover, .df-help-key:focus, .df-help-key.df-help-key-active {
		z-index: 1083;
		opacity: 1;
		outline: 2px solid var(--ct-body-color);
	}

	.df-help-key.df-help-key-active {
		background: var(--ct-warning);
		color: #1c1f23;
	}

.df-help-focus {
	position: fixed;
	z-index: 1083;
	border: 2px solid var(--ct-warning);
	border-radius: .375rem;
	box-shadow: 0 0 0 3px rgba(var(--ct-warning-rgb), .25);
	pointer-events: none;
}

/* the panel: fixed on the right; from 992px the page is pushed over by the same width (html.df-help-editing), so
   nothing sits under it — the sidebar is fixed on the left and the header is sticky inside .wrapper, so a margin on
   .wrapper narrows both, and grids resize themselves. Record modals and toasts move over too. Narrower, it overlays. */
:root {
	--df-help-panel: 26rem;
}

.df-help-panel {
	position: fixed;
	z-index: 1084;
	top: 0;
	right: 0;
	bottom: 0;
	width: min(var(--df-help-panel), 100vw);
	display: flex;
	flex-direction: column;
	background: var(--ct-secondary-bg, var(--bs-body-bg));
	border-left: 1px solid var(--ct-border-color);
	box-shadow: -.25rem 0 1rem rgba(0, 0, 0, .15);
}

.df-help-panel-head {
	min-height: 70px;       /* level with the header */
}

.df-help-panel-body {
	flex: 1;
	overflow: auto;
}

.df-help-chip {
	--bs-btn-padding-y: .05rem;
	--bs-btn-padding-x: .45rem;
	--bs-btn-font-size: .75rem;
}

.df-help-draft {
	max-height: 12rem;
	overflow: auto;
}

@media (min-width: 992px) {
	/* the theme gives .wrapper width: 100% — a margin alone would push it off-screen, not narrow it */
	html.df-help-editing .wrapper {
		width: auto;
		margin-right: var(--df-help-panel);
	}

	html.df-help-editing #model_holder > .modal {
		width: calc(100% - var(--df-help-panel));
	}

	html.df-help-editing .toast-container {
		right: var(--df-help-panel) !important;
	}
}

/* the assistant (dfAssistant.js): the same kind of panel as the help editor's, on the right; from 992px the page moves
   over by its width (html.df-assistant-open), narrower it overlays. One width for both — they aren't open together often,
   and when they are, the help editor (z 1084) sits on top. */
.df-assistant-panel {
	position: fixed;
	z-index: 1083;
	top: 0;
	right: 0;
	bottom: 0;
	width: min(var(--df-help-panel), 100vw);
	display: flex;
	flex-direction: column;
	background: var(--ct-secondary-bg, var(--bs-body-bg));
	border-left: 1px solid var(--ct-border-color);
	box-shadow: -.25rem 0 1rem rgba(0, 0, 0, .15);
}

.df-assistant-head {
	min-height: 70px;
}

.df-assistant-body {
	flex: 1;
	overflow: auto;
}

.df-assistant-me {
	display: flex;
	justify-content: flex-end;
}

.df-assistant-bubble {
	max-width: 85%;
	padding: .4rem .7rem;
	border-radius: .75rem .75rem .2rem .75rem;
	background: rgba(var(--ct-primary-rgb), .15);
	white-space: pre-wrap;
	overflow-wrap: anywhere;
}

.df-assistant-answer {
	overflow-wrap: anywhere;
}

.df-assistant-answer p:last-child,
.df-assistant-answer ul:last-child,
.df-assistant-answer ol:last-child {
	margin-bottom: 0;
}

.df-assistant-answer ul,
.df-assistant-answer ol {
	padding-left: 1.25rem;
}

.df-assistant-tools .badge {
	font-weight: normal;
	white-space: normal;
	text-align: left;
}

.df-assistant-input {
	resize: none;
}

/* History: this user's conversations, above the chat — it scrolls on its own so the chat stays in view */
.df-assistant-history {
	max-height: 45vh;
	overflow: auto;
}

.df-assistant-del {
	padding: .25rem .4rem;
}

/* the conversation open in the panel */
.df-assistant-current {
	background: rgba(var(--ct-primary-rgb), .12);
}

.df-assistant-del:hover {
	color: var(--ct-danger) !important;
}

/* a proposal card: every value as it will be written — spaces and line breaks kept, long ones scroll */
.df-assistant-diff {
	table-layout: fixed;
}
.df-assistant-diff th[scope="row"] {
	width: 30%;
	overflow-wrap: anywhere;
	font-weight: 600;
}
.df-assistant-diff td > span {
	display: block;
	white-space: pre-wrap;
	overflow-wrap: anywhere;
	max-height: 12rem;
	overflow-y: auto;
}
.df-assistant-diff td.df-assistant-from > span:not(.fst-italic) {
	text-decoration: line-through;
	text-decoration-color: var(--ct-danger);
	opacity: .75;
}
.df-assistant-proposal-done .df-assistant-diff {
	opacity: .8;
}
/* the header's apps menu (dfApps.js): an app's tile is an icon font, where the theme's tiles were 24px images */
.df-apps .dropdown-icon-item .df-apps-icon {
	display: block;
	font-size: 1.75rem;
	line-height: 1.2;
	margin-bottom: .25rem;
	color: var(--ct-primary);
}
.df-apps-admin { min-width: 18rem; }
/* wide enough for a package's name and status beside its buttons */
.dropdown-menu.df-apps.dropdown-lg { width: 26rem; max-width: calc(100vw - 1rem); }

/* a build card's XML and SQL: exactly what runs, as text */
.df-assistant-code {
	white-space: pre;
	overflow: auto;
	max-height: 16rem;
	font-size: .75rem;
	background: var(--ct-tertiary-bg);
	border-radius: .25rem;
	padding: .5rem;
}
.df-assistant-code-from {
	opacity: .7;
	max-height: 8rem;
}
/* a picture card (propose_image): the PNG on a checkerboard, so transparent parts show as such */
.df-assistant-image {
	border: 1px solid var(--ct-border-color);
	border-radius: .25rem;
	overflow: hidden;
	background-color: #fff;
	background-image: linear-gradient(45deg, #e6e6e6 25%, transparent 25%, transparent 75%, #e6e6e6 75%), linear-gradient(45deg, #e6e6e6 25%, transparent 25%, transparent 75%, #e6e6e6 75%);
	background-size: 16px 16px;
	background-position: 0 0, 8px 8px;
}
.df-assistant-image img {
	display: block;
	max-width: 100%;
	max-height: 20rem;
	width: auto;
	height: auto;
	margin: 0 auto;
}
/* an icon card (propose_icon): the new icon at 16 / 24 / 48 px as the site draws it (a mask in the text's colour),
   beside the MDI icon it would be drawn instead of */
.df-assistant-icons {
	display: flex;
	flex-wrap: wrap;
	gap: .5rem;
	margin-bottom: .25rem;
}
.df-assistant-icon-set {
	border: 1px solid var(--ct-border-color);
	border-radius: .25rem;
	padding: .375rem .5rem .25rem;
	line-height: 1;
}
.df-assistant-icon-set > .df-assistant-icon,
.df-assistant-icon-set > .mdi {
	margin-right: .5rem;
	vertical-align: bottom;
}
.df-assistant-icon-set > .text-muted {
	margin-top: .25rem;
	font-size: .75rem;
}
.df-assistant-icon {
	display: inline-block;
	background-color: currentColor;
	-webkit-mask-position: center;
	mask-position: center;
	-webkit-mask-size: contain;
	mask-size: contain;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
}

/* chat (dfChat.js): the assistant's kind of panel, on the right, one of the two open at a time (opening chat closes the
   assistant); from 992px the page moves over (html.df-chat-open). Messages are plain text kept as typed (pre-wrap). */
.df-chat-panel {
	position: fixed;
	z-index: 1082;
	top: 0;
	right: 0;
	bottom: 0;
	width: min(var(--df-help-panel), 100vw);
	display: flex;
	flex-direction: column;
	background: var(--ct-secondary-bg, var(--bs-body-bg));
	border-left: 1px solid var(--ct-border-color);
	box-shadow: -.25rem 0 1rem rgba(0, 0, 0, .15);
}

.df-chat-head {
	min-height: 70px;
}

.df-chat-body {
	flex: 1;
	overflow: auto;
}

.df-chat-row {
	background: transparent;
}

.df-chat-msg {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
}

.df-chat-msg.df-chat-mine {
	align-items: flex-end;
}

.df-chat-bubble {
	max-width: 85%;
	padding: .4rem .7rem;
	border-radius: .75rem .75rem .75rem .2rem;
	background: var(--ct-tertiary-bg, rgba(var(--ct-secondary-rgb), .12));
	overflow-wrap: anywhere;
}

/* the message as typed — on the text only, or the template's own line breaks would show too */
.df-chat-text {
	white-space: pre-wrap;
}

.df-chat-mine .df-chat-bubble {
	border-radius: .75rem .75rem .2rem .75rem;
	background: rgba(var(--ct-primary-rgb), .15);
}

.df-chat-bubble.df-chat-removed {
	background: transparent;
	border: 1px dashed var(--ct-border-color);
	color: var(--ct-secondary-color);
}

.df-chat-quote {
	border-left: 2px solid var(--ct-border-color);
	padding-left: .4rem;
	margin-bottom: .2rem;
}

/* Reply / Edit / Remove show on hover or focus (always on touch screens) */
.df-chat-actions {
	visibility: hidden;
}

.df-chat-msg:hover .df-chat-actions,
.df-chat-msg:focus-within .df-chat-actions {
	visibility: visible;
}

@media (hover: none) {
	.df-chat-actions {
		visibility: visible;
	}
}

.df-chat-input {
	resize: none;
}

.df-chat-suggest,
.df-chat-people {
	max-height: 12rem;
	overflow: auto;
}

/* the header button's unread count (Navbar.cshtml: a menu action's badge) */
.df-header-count {
	position: absolute;
	top: 14px;
	right: 2px;
	min-width: 1.1rem;
	padding: 0 .3rem;
	border-radius: 1rem;
	font-size: .65rem;
	line-height: 1.1rem;
	text-align: center;
	color: #fff;
	background: var(--ct-danger);
}

/* phones: the header's icons closer together (gap-3 is 24px), so search, notifications, apps, ⋮, help and the user fit
   beside the logo and menu button at 360px (Navbar.cshtml — Settings and the package icons are in the ⋮ there) */
@media (max-width: 575.98px) {
	.navbar-custom .topbar-menu {
		gap: .625rem !important;
	}
	.navbar-custom .topbar-menu .nav-user {
		gap: 0;
		padding-left: .5rem !important;
		padding-right: .5rem !important;
	}
	/* and the left: the menu button as wide as its icon (the theme does this only at 375px and below), less round the logo */
	.navbar-custom .button-toggle-menu {
		width: auto;
	}
	.navbar-custom .logo-topbar {
		padding-left: .25rem;
		padding-right: .25rem;
	}
}

@media (min-width: 992px) {
	html.df-assistant-open .wrapper,
	html.df-chat-open .wrapper {
		width: auto;
		margin-right: var(--df-help-panel);
	}

	html.df-assistant-open #model_holder > .modal,
	html.df-chat-open #model_holder > .modal {
		width: calc(100% - var(--df-help-panel));
	}

	html.df-assistant-open .toast-container,
	html.df-chat-open .toast-container {
		right: var(--df-help-panel) !important;
	}

	/* side panels (.df-panel: Application settings, column options, the library…) dock beside the assistant, chat or the
	   help editor rather than under it — they slide in from beneath it */
	html.df-assistant-open .df-panel .modal-dialog,
	html.df-chat-open .df-panel .modal-dialog,
	html.df-help-editing .df-panel .modal-dialog {
		right: var(--df-help-panel);
		max-width: calc(100vw - var(--df-help-panel));
	}
}

@media (prefers-reduced-motion: reduce) {
	.df-help-spot, .df-help-card {
		transition: none;
	}
}

.search-top .btn {
	white-space: nowrap;
}

.nav-tabs .nav-link {
	background: transparent;
	border-color: transparent;
}

.df-tabs > .nav-item > .nav-link,
.df-tabs > .nav-item > .dropdown > .nav-link {
	background: transparent;
	border: 0;
	border-bottom: 2px solid transparent;
	border-radius: 0;
	color: var(--bs-secondary-color);
	padding: .5rem .9rem;
}

	.df-tabs > .nav-item > .nav-link:hover,
	.df-tabs > .nav-item > .dropdown > .nav-link:hover {
		color: var(--bs-body-color);
	}

	.df-tabs > .nav-item > .nav-link.active,
	.df-tabs > .nav-item > .dropdown > .nav-link.active {
		background: transparent;
		color: var(--bs-body-color);
		border-bottom-color: var(--df-main-color);
		font-weight: 500;
	}

.df-tabs.nav-tabs {
	border-bottom: 0;
}

.df-tabs .dropdown-menu .dropdown-item {
	border: 0 !important;
	border-radius: 0;
	background: transparent;
	color: var(--bs-body-color);
	padding: .35rem 1rem;
}

	.df-tabs .dropdown-menu .dropdown-item:hover,
	.df-tabs .dropdown-menu .dropdown-item:focus {
		background: rgba(255,255,255,.08);
		color: var(--bs-body-color);
	}

.df-tabs .dropdown-menu li {
	margin-right: 0;
}

.df-fieldrow {
	padding: .5rem 0;
	border-bottom: 1px solid var(--bs-border-color);
}

.df-fieldrow-label {
	font-size: .7rem;
	text-transform: uppercase;
	color: var(--bs-secondary-color);
	margin-bottom: .15rem;
}

.df-fieldrow-type {
	text-transform: none;
	opacity: .6;
	margin-left: .35rem;
}

.df-fieldrow-value {
	word-break: break-word;
}

/*Other Fields: copy a row's value — shown on hover (and while it says copied)*/
.df-fieldrow-copy {
	margin-left: .35rem;
	color: var(--bs-secondary-color);
	opacity: 0;
	text-transform: none;
}

	.df-fieldrow:hover .df-fieldrow-copy, .df-fieldrow-copy:focus, .df-fieldrow-copy:has(.mdi-check) {
		opacity: 1;
	}

	.df-fieldrow-copy:hover {
		color: var(--bs-link-color);
	}

	.df-fieldrow-value.df-null {
		color: var(--bs-secondary-color);
	}

	.df-fieldrow-value.df-empty {
		color: var(--bs-secondary-color);
	}

.layout-section,
.layout-section-body,
.layout-canvas {
	overflow: visible;
}

.record-tags {
	position: relative;
}

.tag-box {
	min-height: 2.4rem;
	height: auto;
	cursor: text;
}

.tag-chip {
	display: inline-flex;
	align-items: center;
	gap: .2rem;
	background: rgba(var(--bs-primary-rgb), .18);
	border: 1px solid rgba(var(--bs-primary-rgb), .45);
	border-radius: .25rem;
	padding: .05rem .35rem;
	font-size: .8rem;
}

.tag-chip-x {
	background: none;
	border: 0;
	padding: 0;
	line-height: 1;
	color: inherit;
	opacity: .6;
}

	.tag-chip-x:hover {
		opacity: 1;
	}

.tag-input {
	border: 0;
	background: transparent;
	outline: none;
	flex: 1 1 6rem;
	min-width: 6rem;
	color: inherit;
}

.tag-suggestions {
	position: absolute;
	z-index: 10;
	left: 0;
	right: 0;
	background: var(--bs-body-bg);
	border: 1px solid var(--bs-border-color);
	border-radius: .25rem;
	list-style: none;
	margin: .15rem 0 0;
	padding: .25rem 0;
	max-height: 12rem;
	overflow-y: auto;
}

	.tag-suggestions li {
		padding: .25rem .6rem;
		cursor: pointer;
	}

		.tag-suggestions li:hover, .tag-suggestions li.active {
			background: rgba(255,255,255,.08);
		}

.df-meta {
	line-height: 1.2;
	white-space: nowrap;
}

.record-tags .form-label {
	display: none;
}
/* label is redundant inline */
.record-tags .tag-box {
	min-height: 2rem;
	padding: .15rem .4rem;
}

.tag-suggestions li.tag-suggest-all,
.tag-suggestions li.text-muted {
	background: none;
	cursor: default;
}

.tag-suggestions li.tag-suggest-all {
	border-top: 1px solid rgba(255,255,255,.1);
}

.df-sort-row {
	position: relative;
}

	.df-sort-row.df-dragging {
		opacity: .4;
	}

	.df-sort-row.df-drop-above::before,
	.df-sort-row.df-drop-below::after {
		content: "";
		position: absolute;
		left: 0;
		right: 0;
		height: 2px;
		background: var(--df-main-color);
		pointer-events: none;
	}

	.df-sort-row.df-drop-above::before {
		top: -2px;
	}

	.df-sort-row.df-drop-below::after {
		bottom: -2px;
	}

.df-lookup-panel {
	position: absolute;
	top: 100%;
	left: 0;
	right: 0;
	max-height: 16rem;
	overflow-y: auto;
	z-index: 5;
}

.df-lookup .form-floating {
	position: relative;
}

.df-lookup-spin {
	position: absolute;
	top: 50%;
	right: .6rem;
	transform: translateY(-50%);
	pointer-events: none;
	z-index: 6;
}

/* the × that empties a lookup / suggest (main-input canClear) — where the spinner sits, which it gives way to */
.df-lookup-clear {
	position: absolute;
	top: 50%;
	right: .35rem;
	transform: translateY(-50%);
	z-index: 6;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 1.6rem;
	height: 1.6rem;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: transparent;
	color: var(--bs-secondary-color);
	font-size: 1rem;
	line-height: 1;
	cursor: pointer;
}

.df-lookup-clear:hover,
.df-lookup-clear:focus-visible {
	color: var(--bs-body-color);
	background: var(--bs-tertiary-bg);
}

.df-lookup .form-floating:has(.df-lookup-clear) > .form-control {
	padding-right: 2.1rem;
}

.layout-palette-toggle {
	cursor: pointer;
	user-select: none;
}

/* a stored value that isn't in the field's option list — shown as-is, marked */
.ag-cell.df-option-unknown {
	font-style: italic;
	opacity: .75;
	text-decoration: underline dotted;
	text-underline-offset: 3px;
}

/* palette chip's options button — faint until hovered, lit when the field has options */
.layout-chip .layout-chip-opts {
	opacity: .35;
	line-height: 1;
}

.layout-chip:hover .layout-chip-opts,
.layout-chip .layout-chip-opts.has-options {
	opacity: 1;
}

.layout-chip .layout-chip-opts.has-options {
	color: var(--bs-info);
}

/* tabbed palette — one list at a time */
/* as many across as fit — four on a wide palette, 2×2 in the usual col-md-3 (~200px) — never overflowing */
.layout-palette-nav {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(5.25rem, 1fr));
	gap: .25rem;
}

.layout-palette-nav .nav-link {
	width: 100%;
	padding: .25rem .35rem;
	font-size: .75rem;
	white-space: nowrap;
}

.layout-palette-nav .badge {
	font-size: .65rem;
}

/* desktop: the palette stays in view beside a long form and scrolls on its own. Stacked (mobile) it just flows. */
@media (min-width: 768px) {
	.layout-palette-tabs {
		position: sticky;
		top: .5rem;
		display: flex;
		flex-direction: column;
		max-height: calc(100vh - 14rem);
	}

	.layout-palette-body {
		min-height: 0;
		overflow-y: auto;
	}

	/* the body scrolls now — a second, inner scroll area is just in the way */
	.layout-palette-body .layout-table-list {
		max-height: none;
	}
}

.layout-table-list {
	max-height: 20rem;
	overflow-y: auto;
}

.layout-chip-dropdown {
	max-height: 24rem;
	overflow-y: auto;
}

.df-form-fill {
	display: flex;
	flex-direction: column;
	flex: 1 1 auto;
	min-height: 0;
}

	.df-form-fill > header.inner-header {
		flex: 0 0 auto;
	}

	.df-form-fill > .inner-scroll {
		flex: 1 1 auto;
		min-height: 0;
		overflow-y: auto;
	}

/* the condensed sidebar (narrower windows, or collapsed) — the theme gives .content-page a min-height of
   --ct-leftbar-condensed-height (2000px) there, with a stronger selector than ours: the page grew to 2000px, the grid
   filled it, and its bottom (the horizontal scrollbar) ended below the window with nothing able to scroll to it */
html[data-sidenav-size="condensed"]:not([data-layout="topnav"]) .wrapper .content-page { min-height: 0; }

.content-page {
	height: calc(100vh - var(--ct-topbar-height) - 2px);
	min-height: 0;
	overflow-y: auto;
	display: flex;
	flex-direction: column;
	/* the theme animates "all" (for the sidebar sliding) — height included, so on a window resize the grid was
	   measured mid-animation and sized for the previous window. Keep the sidebar animation, not the height. */
	transition-property: margin, padding;
}

	.content-page > manage,
	.content-page > search {
		flex: 1 1 auto;
		min-height: 0;
	}

.layout-chip-placed {
	flex-direction: column;
	align-items: stretch;
	gap: .15rem;
	padding: .3rem .4rem;
}

.layout-chip-main {
	display: flex;
	align-items: center;
	gap: .35rem;
	min-width: 0;
}

.layout-chip-meta {
	display: flex;
	flex-wrap: wrap;
	gap: .25rem;
	padding-left: 1.25rem;
}

.layout-meta-tag {
	display: inline-flex;
	align-items: center;
	gap: .15rem;
	font-size: .65rem;
	line-height: 1.4;
	color: var(--bs-secondary-color);
	background: rgba(0,0,0,.15);
	border-radius: .2rem;
	padding: 0 .3rem;
	max-width: 12rem;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

	.layout-meta-tag .mdi {
		font-size: .75rem;
		opacity: .7;
	}

.layout-chip-meta:empty {
	display: none;
}

[data-bs-theme=dark] select,
[data-bs-theme=dark] .form-select {
	color-scheme: dark !important;
}

/* The browser draws a select's list from the select's own colours: where the select is transparent (a field with a ⋮
   menu — the input group draws the box) its white text landed on a white list, and only the hovered option showed.
   The options get the input's colours of their own. */
[data-bs-theme=dark] select option,
[data-bs-theme=dark] select optgroup {
	background-color: var(--ct-input-bg, var(--bs-body-bg));
	color: var(--bs-body-color);
}

.layout-meta-tag {
	max-width: 12rem;
}

.layout-chip-meta .layout-meta-tag:only-child {
	max-width: 100%;
}

.child-search .search-top {
	padding: 0;
}

	.child-search .search-top h4 {
		margin: 0;
	}

.df-tag-chip {
	display: inline-block;
	font-size: .7rem;
	line-height: 1.5;
	padding: 0 .35rem;
	margin-right: .2rem;
	border-radius: .2rem;
	background: var(--bs-tertiary-bg);
	border: 1px solid var(--bs-border-color);
	color: var(--bs-secondary-color);
}

/* a grid cell's "code" renderer (search.render.js) — plain monospace, no pink */
.df-cell-code {
	color: inherit;
	font-size: .8rem;
}

.df-files {
	position: relative;
}

.df-files-drop {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: .5rem;
	padding: 1.25rem;
	border: 2px dashed var(--bs-border-color);
	border-radius: .375rem;
	color: var(--bs-secondary-color);
	margin-bottom: 1rem;
}

	.df-files-drop .mdi {
		font-size: 1.5rem;
	}

.df-files-dragover .df-files-drop {
	border-color: var(--df-main-color);
	background: rgba(0,0,0,.15);
}

.df-files-grid {
	display: flex;
	flex-direction: column;
	gap: .5rem;
}

.df-file-card {
	display: flex;
	align-items: center;
	gap: .75rem;
	padding: .5rem;
	border: 1px solid var(--bs-border-color);
	border-radius: .375rem;
	background: var(--bs-tertiary-bg);
}

.df-file-thumb {
	flex: 0 0 auto;
	width: 3rem;
	height: 3rem;
	border-radius: .25rem;
	overflow: hidden;
	display: flex;
	align-items: center;
	justify-content: center;
	background: rgba(0,0,0,.2);
}

	.df-file-thumb img {
		width: 100%;
		height: 100%;
		object-fit: cover;
	}

.df-file-icon .mdi {
	font-size: 1.75rem;
	color: var(--bs-secondary-color);
}

.df-file-info {
	flex: 1 1 auto;
	min-width: 0;
}

.df-file-name {
	display: block;
	color: var(--bs-body-color);
	text-decoration: none;
}

	.df-file-name:hover {
		text-decoration: underline;
	}

.df-file-meta {
	font-size: .75rem;
	color: var(--bs-secondary-color);
}

.df-file-actions {
	flex: 0 0 auto;
	display: flex;
	gap: .25rem;
}

.df-files-progress {
	margin-bottom: .5rem;
}

/* group behaves as the field */
.df-input .input-group {
	border: 1px solid var(--bs-border-color);
	border-radius: var(--bs-border-radius);
	background: var(--ct-input-bg) !important;
}

	/* input gives up its own chrome */
	.df-input .input-group .form-control {
		border: 0;
		border-radius: 0;
		background: transparent !important;
	}

.toast-body, .toast-subject + * {
	overflow-wrap: anywhere;
}

.toast-body {
	overflow-wrap: anywhere;
	min-width: 0;
}

.toast-container {
	max-width: min(28rem, calc(100vw - 2rem));
}

/* an open merge / history dialog sets --df-toast-bottom (conflictMerge.js dfToastsClear) — toasts sit above its footer
   instead of on its buttons (the container's .bottom-0 is !important too) */
div.toast-container.bottom-0 {
	bottom: var(--df-toast-bottom, 0) !important;
}

.df-status {
	display: inline-flex;
	align-items: center;
	gap: .3rem;
	white-space: nowrap;
}

	.df-status .mdi {
		font-size: .6rem;
	}

.df-workflow .badge {
	font-size: .8rem;
	padding: .4rem .7rem;
	font-weight: 500;
}

.df-files-grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(18rem, 1fr));
	gap: .5rem;
}

@media (max-width: 768px) {
	.df-files-grid {
		grid-template-columns: minmax(0, 1fr);
	}
}


.quick-filter-btn + .dropdown-menu {
	max-height: 60vh;
	overflow-y: auto;
	min-width: 14rem;
}

.qf-menu {
	min-width: 14rem;
	max-width: 22rem;
}

.qf-values {
	max-height: 50vh;
	overflow-y: auto;
}

.ag-pinned-left-cols-container .ag-cell {
	box-shadow: none;
}

.ag-cell[col-id="__row"] {
	border-right: 4px solid transparent !important;
}

.deleted-row .ag-cell[col-id="__row"] {
	color: var(--bs-danger);
	/*text-decoration: line-through;*/
	/*box-shadow: inset -4px 0 0 var(--bs-danger);*/
	border-right: 4px solid var(--bs-danger) !important;
}

.deleted-row .ag-cell {
	color: rgba(var(--ct-body-color-rgb), .6);
}

.record-count {
	display: inline-block;
	min-width: 6rem;
	text-align: right;
}

.df-row-link a {
	color: inherit;
	text-decoration: underline;
	cursor: pointer;
}

	.df-row-link a:hover {
		text-decoration: none;
	}

.df-row-link {
	padding: 0 !important;
}

	.df-row-link a {
		display: block;
		width: 100%;
		height: 100%;
		padding: 0 var(--ag-cell-horizontal-padding);
		line-height: var(--ag-row-height, 2.5rem);
		color: inherit;
		text-decoration: underline;
		cursor: pointer;
	}

		.df-row-link a:hover {
			text-decoration: none;
			background: rgba(255,255,255,.06);
		}

.df-tabs .nav-link.dropdown-toggle::after {
	margin-left: .4rem;
	vertical-align: .15em;
}

/* menu items that are real links — underlined so right-click → new tab is discoverable */
.df-grid-menu a.df-menu-link {
	text-decoration: underline;
	text-underline-offset: 2px;
}

.df-grid-menu-item.active a.df-menu-link {
	text-decoration: none;
}

.df-row-link a:hover {
	text-decoration: none;
	background: rgba(var(--ct-body-color-rgb), .06);
}


/* the grid's row and column menus (gridMenu.js) — the Bootstrap dropdown look, on screen wherever it opened */
.df-grid-menu {
	position: fixed;
	z-index: 1090;
	min-width: 10rem;
	max-height: calc(100vh - 8px);
	overflow-y: auto;
	padding: .25rem 0;
	font-size: .9rem;
	color: var(--bs-body-color);
	background-color: var(--ct-secondary-bg);
	border: 1px solid rgba(var(--ct-body-color-rgb), .09);
	border-radius: var(--bs-border-radius);
	box-shadow: 0 0.5rem 1.5rem rgba(0, 0, 0, .5);
	outline: none;
}

.df-grid-menu-divider {
	margin: .25rem 0;
	border-top: 1px solid rgba(var(--ct-body-color-rgb), .12);
}

.df-grid-menu-item {
	display: flex;
	align-items: center;
	padding: .35rem 0;
	line-height: 1.5;
	cursor: default;
	white-space: nowrap;
}

	.df-grid-menu-item.active {
		background-color: rgba(var(--ct-body-color-rgb), .08);
	}

	.df-grid-menu-item.disabled {
		opacity: .5;
		pointer-events: auto;     /* its tooltip (why it's off) still shows */
	}

.df-grid-menu-icon {
	padding-left: .75rem;
	width: 1.75rem;
	flex: none;
}

	.df-grid-menu-icon a {
		color: inherit;
	}

.df-grid-menu-text {
	flex: 1 1 auto;
	padding-left: .5rem;
	padding-right: 1.5rem;
}

.df-grid-menu-shortcut {
	color: var(--bs-secondary-color);
	padding-right: .75rem;
}

/* the header's column-menu ☰ (search.js headerTemplate) */
.ag-header-cell .df-col-menu {
	cursor: pointer;
	opacity: .45;
	font-size: 1rem;
	line-height: 1;
}

	.ag-header-cell:hover .df-col-menu,
	.ag-header-cell .df-col-menu:hover {
		opacity: 1;
	}

/* the grid's cell range (search.range.js): a tint over whatever the cell already shows (edited, error…), a line round
   the block */
.ag-cell.df-range-cell {
	background-image: linear-gradient(rgba(var(--ct-primary-rgb), .16), rgba(var(--ct-primary-rgb), .16));
}

	.ag-cell.df-range-cell::after {
		content: "";
		position: absolute;
		inset: 0;
		pointer-events: none;
		border: 0 solid var(--ct-primary);
	}

	.ag-cell.df-range-top::after { border-top-width: 1px; }
	.ag-cell.df-range-bottom::after { border-bottom-width: 1px; }
	.ag-cell.df-range-left::after { border-left-width: 1px; }
	.ag-cell.df-range-right::after { border-right-width: 1px; }

/* where Ctrl+V's text lands for a moment (search.range.js catchPaste) — off screen */
.df-paste-catcher {
	position: fixed;
	left: -10000px;
	top: 0;
	width: 1px;
	height: 1px;
	opacity: 0;
}

/* the select-all box over a ticked grid's first column */
.ag-header-cell .df-select-all {
	display: inline-flex;
	margin-right: .5rem;
	cursor: pointer;
}

/* the lookup picker in a cell (gridLookupEditor.js) */
.df-lookup-editor {
	width: 18rem;
	max-width: 90vw;
	padding: .35rem;
	background-color: var(--ct-secondary-bg);
	border: 1px solid rgba(var(--ct-body-color-rgb), .15);
	border-radius: var(--bs-border-radius);
	box-shadow: 0 0.5rem 1.5rem rgba(0, 0, 0, .35);
}

.df-lookup-list {
	max-height: 240px;
	overflow-y: auto;
	margin-top: .35rem;
}

.df-lookup-item,
.df-lookup-note {
	padding: .25rem .5rem;
	border-radius: var(--bs-border-radius-sm);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

.df-lookup-item {
	cursor: pointer;
}

	.df-lookup-item:hover {
		background-color: rgba(var(--ct-body-color-rgb), .06);
	}

	.df-lookup-item.active {
		background-color: rgba(var(--ct-primary-rgb), .15);
	}

.df-lookup-note {
	color: var(--bs-secondary-color);
}

.df-row-menu-cell {
	padding: 0 !important;
	text-align: center;
}

/* the record's own column — the one the "⋮" sits beside — reads as the row's title */
.ag-cell.df-menu-anchor {
	color: var(--ct-primary);
	font-weight: 500;
}

	/* its text is the record's link (search.js, cellRendererSelector) — looks as before, underlined on hover */
	.ag-cell.df-menu-anchor a.df-anchor-link {
		color: inherit;
		text-decoration: none;
	}

		.ag-cell.df-menu-anchor a.df-anchor-link:hover {
			text-decoration: underline;
		}

.df-row-menu {
	background: none;
	border: 0;
	padding: 0;
	line-height: var(--ag-row-height, 2.5rem);
	width: 100%;
	color: var(--bs-secondary-color);
	opacity: 0;
	transition: opacity .1s ease;
}

.ag-row-hover .df-row-menu,
.df-row-menu[aria-expanded="true"] {
	opacity: 1;
}

	.df-row-menu:hover {
		color: var(--bs-body-color);
		background: rgba(var(--ct-body-color-rgb), .08);
	}

.ag-row:has(.df-menu-anchor:hover) .df-row-menu,
.df-row-menu-cell:hover .df-row-menu,
.df-row-menu.df-open {
	opacity: 1;
}

/* open state — the "⋮" stays lit and looks pressed while its menu is showing */
.df-row-menu.df-open {
	opacity: 1;
	color: var(--bs-body-color);
	background: rgba(var(--ct-body-color-rgb), .14);
	box-shadow: inset 0 -2px 0 var(--df-main-color, var(--bs-primary));
}

/* filter builder (Query Editor) — groups of conditions; a nested group is indented and bracketed */
.filter-builder {
	border: 1px solid var(--bs-border-color);
	border-radius: .375rem;
	padding: .5rem .75rem;
	margin-bottom: .5rem;
}

/* inside a panel that's framed already (Compare's filter): no second frame — the Builder | JSON tabs' rule is its top */
.cmp-panel .filter-builder {
	border: 0;
	border-radius: 0;
	padding: 0;
	margin-bottom: 0;
}

/* Query Editor joins — one box per joined table, its field pairs under it */
.query-joins .qj-join {
	border: 1px solid var(--bs-border-color);
	border-radius: .375rem;
	padding: .35rem .5rem;
	margin-bottom: .5rem;
}

.query-joins .qj-join.qj-error {
	border-color: rgba(var(--bs-danger-rgb), .5);
}

.query-joins .qj-table { width: 18rem; }
.query-joins .qj-name { width: 9rem; }
.query-joins .qj-type { width: 14rem; }
.query-joins .qj-field { width: 14rem; }
.query-joins .qj-on { padding-left: 2.25rem; }
.query-joins .qj-on-label { width: 2.5rem; text-align: right; }

@media (max-width: 767.98px) {
	.query-joins .qj-table, .query-joins .qj-type, .query-joins .qj-field { width: 100%; }
	.query-joins .qj-on { padding-left: 0; }
}

/* the layout palette's pills, two fixed columns (auto-fit collapses to one in a shrink-to-fit flex item) */
/* a record's ribbon tabs: one line, never shrinking a tab — on a narrow screen (a table's page has four) the list scrolls
   sideways on its own rather than pushing the ribbon wider */
.df-ribbon-tablist {
	flex: 0 1 auto;
	min-width: 0;
	flex-wrap: nowrap;
	overflow-x: auto;
	overflow-y: hidden;
	scrollbar-width: none;
}
.df-ribbon-tablist::-webkit-scrollbar { display: none; }
.df-ribbon-tablist .nav-item { flex: 0 0 auto; }
.df-ribbon-tablist .nav-link { white-space: nowrap; }

/* Small folder tabs standing on a row's bottom rule — the filter builder's Builder | JSON (.fb-top / .fb-views), a table's
   Schema objects | indexes | result (.df-folder-row / .df-folder-tabs). Other things (a summary, buttons) share the row;
   the open tab's bottom border is the page colour, so it joins what's under it. */
.filter-builder .fb-top,
.df-folder-row {
	border-bottom: 1px solid var(--ct-border-color);
}
.filter-builder .fb-views,
.df-folder-tabs {
	flex: 0 1 auto;
	border-bottom: 0;
	margin-bottom: -1px;
	flex-wrap: nowrap;
}
.df-folder-tabs .nav-link,
.filter-builder .fb-views .nav-link {
	padding: .25rem .85rem;
	font-size: .85rem;
	color: var(--ct-secondary-color);
	background: transparent;
	border: 1px solid transparent;
	border-radius: .375rem .375rem 0 0;
	white-space: nowrap;
}
.df-folder-tabs .nav-link:hover:not(.active),
.filter-builder .fb-views .nav-link:hover:not(.active) {
	color: var(--ct-emphasis-color);
	border-color: var(--ct-border-color) var(--ct-border-color) transparent;
}
.df-folder-tabs .nav-link.active,
.filter-builder .fb-views .nav-link.active {
	color: var(--ct-emphasis-color);
	background: var(--ct-body-bg);
	border-color: var(--ct-border-color) var(--ct-border-color) var(--ct-body-bg);
}
.filter-builder .fb-top > :not(.fb-views),
.df-folder-row > :not(.df-folder-tabs) { margin-bottom: .3rem; }    /* what shares the row, level with the tab text */

/* Compare tab's Record | Structure | Table rows | Text — a segmented switch (btn-group; colours from the .cmp-pane button
   rules below), each segment the same width; on a phone it spans the tab */
.cmp-modes .btn { min-width: 6.5rem; white-space: nowrap; }

@media (max-width: 575.98px) {
	.cmp-modes { display: flex; flex: 1 1 auto; min-width: 0; }
	.cmp-modes .btn { flex: 1 1 auto; min-width: 0; padding-left: .3rem; padding-right: .3rem; font-size: .8rem; }
}

/* Compare's buttons. The toggles are btn-secondary when on, btn-outline-secondary when off — and an outline button's hover
   is that same solid grey, so hovering an off toggle looked like turning it on. And the outline grey (#6c757d) on the dark
   background read as disabled whether it was or not. So: on = a primary tint with its border; hover = a light wash; outline
   text in the body colour; disabled clearly fainter. */
/* (the filter builder's AND / OR switch too — wherever the builder is) */
.cmp-pane .btn-secondary,
.filter-builder .btn-group > .btn-secondary {
	--ct-btn-color: var(--ct-emphasis-color);
	--ct-btn-bg: rgba(var(--ct-primary-rgb), .22);
	--ct-btn-border-color: var(--ct-primary);
	--ct-btn-hover-color: var(--ct-emphasis-color);
	--ct-btn-hover-bg: rgba(var(--ct-primary-rgb), .32);
	--ct-btn-hover-border-color: var(--ct-primary);
	--ct-btn-active-color: var(--ct-emphasis-color);
	--ct-btn-active-bg: rgba(var(--ct-primary-rgb), .4);
	--ct-btn-active-border-color: var(--ct-primary);
	box-shadow: none;     /* the theme's grey glow under btn-secondary */
}

.cmp-pane .btn-outline-secondary,
.filter-builder .btn-group > .btn-outline-secondary {
	--ct-btn-color: var(--ct-body-color);
	--ct-btn-border-color: var(--ct-secondary);
	--ct-btn-hover-color: var(--ct-emphasis-color);
	--ct-btn-hover-bg: rgba(var(--ct-secondary-rgb), .18);
	--ct-btn-hover-border-color: var(--ct-secondary);
	--ct-btn-active-color: var(--ct-emphasis-color);
	--ct-btn-active-bg: rgba(var(--ct-secondary-rgb), .3);
	--ct-btn-active-border-color: var(--ct-secondary);
	--ct-btn-disabled-color: var(--ct-secondary-color);
	--ct-btn-disabled-border-color: var(--ct-border-color);
}

/* in a group, the buttons beside a selected one shouldn't cover its border */
.cmp-pane .btn-group > .btn-secondary,
.filter-builder .btn-group > .btn-secondary { z-index: 1; }

.cmp-pane .btn:disabled,
.cmp-pane .btn.disabled { --ct-btn-disabled-opacity: .4; opacity: .4; }

/* Source ⇄ Target: two cards with the switch between them (stacked, the switch sits between) */
.cmp-sides {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: .5rem;
}

.cmp-sides .cmp-side {
	margin-bottom: 0;
}

.cmp-switch {
	display: flex;
	align-items: center;
	justify-content: center;
}

/* swap and the tables link: small square icon buttons, stacked between the sides on desktop */
.cmp-switch .btn {
	width: 1.75rem;
	height: 1.75rem;
	padding: 0;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	font-size: .9rem;
	line-height: 1;
}

/* Table rows' settings: one sentence ("Rows matched on RID · newer by ModifiedDate · every row") whose bold parts open
   their setting in a panel under it — the defaults need nothing touched */
.cmp-summary { line-height: 1.8; }
.cmp-chip {
	font-weight: 600;
	color: var(--ct-emphasis-color);
	text-decoration: underline dotted;
	text-underline-offset: 3px;
	text-decoration-color: var(--ct-secondary-color);
}
a.cmp-chip:hover, .cmp-chip-host:hover .cmp-chip { color: var(--ct-primary); text-decoration-color: var(--ct-primary); }
a.cmp-chip.text-warning { color: var(--ct-warning) !important; }
.cmp-chip-host { text-decoration: none; }
.cmp-panel {
	position: relative;
	margin-top: .5rem;
	padding: .75rem;
	border: 1px solid var(--ct-border-color);
	border-radius: .375rem;
}
.cmp-panel-close { position: absolute; top: .5rem; right: .5rem; font-size: .65rem; z-index: 3; }
.cmp-panel-scroll { padding-top: 1.75rem; }     /* the × above the scrolling table, not over its header */

/* the Source / Target titles without their rule (the invisible copy in .cmp-switch the same, so it keeps their height) */
.cmp-sides .df-section-title { border-bottom: 0; }

/* the pickers without a form's bottom margin — the notes under them (blank = this page's, the table's rows) sit right
   under; the row's g-2 still spaces pickers stacked on a narrow screen */
.cmp-side > .row .df-input { margin-bottom: 0; }
.cmp-side-note { margin-top: .25rem; }

@media (min-width: 768px) {
	.cmp-sides {
		grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
		column-gap: .35rem;
		row-gap: .75rem;
	}
	/* the buttons under the title's copy, level with the pickers — top and bottom: the stack is the pickers' height
	   (2 × 1.75rem + 4px = 60px) */
	.cmp-switch { justify-content: flex-start; }
}

.cmp-switch-btns { gap: 4px; }

/* Generate script / Update target results */
.cmp-sync-row {
	padding: .35rem 0;
	border-top: 1px solid var(--bs-border-color);
}

.cmp-sql {
	max-height: 40vh;
	overflow: auto;
	margin: .35rem 0 0;
	padding: .5rem;
	font-size: .75rem;
	background: var(--bs-tertiary-bg);
	border-radius: .25rem;
	white-space: pre;
}

/* the Compare tab's diff (dfDiff.js): bordered like before; its change bar only once there's an editor */
.cmp-editor .df-diff-editor { border: 1px solid var(--bs-border-color); }
.cmp-editor .df-diff-bar { margin-bottom: .25rem; }
.cmp-editor.cmp-editor-empty .df-diff-bar { display: none; }

/* the Compare tab's Text mode (dfTextCompare.js): the two editors to paste into — drag the corner for more height */
.df-tc-head { display: flex; align-items: center; gap: .5rem; margin-bottom: .25rem; min-height: 1.5rem; }
.df-tc-editor {
	height: 30vh;
	min-height: 8rem;
	border: 1px solid var(--bs-border-color);
	resize: vertical;
	overflow: hidden;
}

/* Record compare, all matching columns: the column list left of the diff (items styled like the field history's) */
.cmp-record-body.cmp-with-list {
	display: grid;
	grid-template-columns: 18rem minmax(0, 1fr);
	gap: .75rem;
	align-items: start;
}

.cmp-record-diff { min-width: 0; }

.cmp-record-list {
	max-height: calc(60vh + 2.5rem);
	overflow-y: auto;
	border: 1px solid var(--bs-border-color);
}

.cmp-record-list-head {
	position: sticky;
	top: 0;
	z-index: 1;
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: .35rem .75rem;
	padding: .4rem .75rem;
	background: var(--bs-body-bg);
	border-bottom: 1px solid var(--bs-border-color);
}

/* narrow: the list above the diff, shorter */
@media (max-width: 767.98px) {
	.cmp-record-body.cmp-with-list { grid-template-columns: minmax(0, 1fr); }
	.cmp-record-list { max-height: 30vh; }
}

/* Schema tab — an index's SQL preview (tableSchema.html) */
.df-index-sql {
	max-height: 30vh;
	overflow: auto;
	padding: .5rem;
	background: var(--bs-tertiary-bg);
	border-radius: .25rem;
	white-space: pre-wrap;
}

/* Data compare: the two tables' columns (key / compare boxes) — a wide table scrolls inside */
.cmp-data-cols {
	max-height: 40vh;
	overflow: auto;
}

.cmp-data-cols .cmp-allnone { font-size: .75rem; line-height: 1.1; }

/* the header stays put while the columns scroll under it: an opaque page-coloured background (the theme paints cells from
   --ct-table-bg, transparent — so set both) and above the rows' checkboxes and badges */
.cmp-data-cols table.table > thead > tr > th {
	position: sticky;
	top: 0;
	z-index: 2;
	--ct-table-bg: var(--ct-body-bg);
	background-color: var(--ct-body-bg);
	box-shadow: inset 0 -1px 0 var(--ct-border-color);   /* its bottom rule, which a sticky cell's border doesn't keep */
}

.fb-json .df-input {
	margin-bottom: .25rem;
}

.fb-summary {
	font-size: .85rem;
	min-width: 0;
	flex: 1 1 12rem;
}

.fb-group.fb-nested {
	position: relative;
	margin: .25rem 0 .25rem 1rem;
	padding: .35rem .5rem .35rem .75rem;
	border-left: 2px solid var(--bs-primary);
	background: rgba(var(--bs-primary-rgb), .05);
	border-radius: 0 .25rem .25rem 0;
}

.fb-paren {
	font-weight: 600;
	color: var(--bs-primary);
}

.fb-paren-close {
	display: block;
	line-height: 1;
}

.fb-items {
	margin-top: .35rem;
}

.fb-joiner {
	font-size: .7rem;
	text-transform: uppercase;
	color: var(--bs-secondary-color);
	margin: .15rem 0 .15rem .25rem;
}

.fb-cond {
	padding: .15rem 0;
}

/* Edit Data's row icons: + / × at the row's left */
.fb-icon {
	cursor: pointer;
	line-height: 1;
}

.fb-row-tools {
	flex: 0 0 auto;
}

	.fb-cond.fb-incomplete .fb-field,
	.fb-cond.fb-incomplete .fb-values input {
		border-style: dashed;
	}

	.fb-cond .fb-field { width: 14rem; }
	.fb-cond .fb-op { width: 10rem; }
	.fb-cond .fb-text { width: 16rem; }
	.fb-cond .fb-num { width: 8rem; }
	.fb-cond .fb-date { width: 10rem; }
	.fb-cond .fb-time { width: 7rem; }
	.fb-cond .fb-choice { min-width: 14rem; }

	.fb-cond .fb-choice .df-input {
		margin-bottom: 0;
	}

/* a record dialog's title: a link to the record's own page, reading as the heading until hovered; copy-link beside it */
.df-record-link {
	color: inherit;
	text-decoration: none;
}

	.df-record-link:hover {
		text-decoration: underline;
	}

.df-copy-url {
	color: var(--bs-secondary-color);
	flex: 0 0 auto;
	border: 0;
	line-height: 1;
}

	.df-copy-url:hover {
		color: var(--bs-body-color);
	}

/* Script + HTML: two stacked editors for one column */
.input-scripthtml-title {
	font-size: .8rem;
	color: var(--bs-secondary-color);
	margin-bottom: .25rem;
}

.input-scripthtml > main-input > .df-input {
	margin-bottom: .5rem;
}

	.input-scripthtml > main-input:last-child > .df-input {
		margin-bottom: 0;
	}

.input-scripthtml.df-changed .input-scripthtml-title {
	color: var(--bs-warning);
}

/* compact inputs sit inline (Edit Data's value) — no form-spacing margin, or picking a field pushes the rows down */
.df-input.df-compact {
	margin-bottom: 0;
}

.df-input.df-compact .form-floating > .form-control,
.df-input.df-compact .form-floating > .form-select {
    height: calc(1.5em + .75rem + 2px);
    min-height: 0;
    line-height: 1.5;
}
.df-input.df-compact .form-floating > .form-control { padding: .375rem .75rem; }
.df-input.df-compact .form-floating > .form-select { padding: .375rem 2.25rem .375rem .75rem; }
.df-input.df-compact .form-floating > .form-control::placeholder { color: var(--bs-secondary-color); }

.df-edit-value .df-lookup-panel { z-index: 1070; }

/* Edit Data's Paste tab (search.paste.js): the column mapping and the old → new compare */
.df-paste-text { font-size: .8rem; white-space: pre; }
.df-paste-col { width: 13rem; }
.df-paste-compare { max-height: 45vh; overflow: auto; }
.df-paste-compare thead th { position: sticky; top: 0; background: var(--bs-body-bg); z-index: 1; }
.df-paste-compare td { max-width: 20rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.df-paste-compare td.df-paste-changed { background: rgba(var(--bs-success-rgb), .12); }
.df-paste-compare td.df-paste-error { background: rgba(var(--bs-danger-rgb), .15); color: var(--bs-danger-text-emphasis); }


/* ── Concurrency: fields someone else changed after the record was loaded (Manage.js $scope.conflict) ── */
/* an amber bar down the box's left edge while undecided — the same boxes as the green bar of a live update (below);
   was --bs-warning on the controls, which is empty in this theme (gotcha 208), so it never showed */
.input-field.df-conflict :is(.input-group, .input-monaco, .form-floating > .form-control, .form-floating > .form-select):not(.input-group *) {
	box-shadow: inset 3px 0 0 var(--ct-warning);
}
/* the field's note and the grid's live note lead with an amber dot, matching the bar */
.df-amber-dot {
	display: inline-block;
	flex: 0 0 auto;
	width: .5rem;
	height: .5rem;
	border-radius: 50%;
	background: var(--ct-warning);
	vertical-align: middle;
}

/* the banner: icon | text, with the buttons under the text — long lists and names wrap instead of pushing the
   icon and buttons onto rows of their own */
.df-conflict-banner {
    display: flex;
    align-items: flex-start;
    gap: .6rem;
    padding: .6rem .8rem;
}
.df-conflict-icon { font-size: 1.25rem; line-height: 1.2; flex: 0 0 auto; }
.df-conflict-body { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
.df-conflict-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .4rem .6rem;
    margin-top: .45rem;
}
.df-conflict-actions:empty { display: none; }

.df-conflict-note {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .25rem .4rem;
    margin-top: .2rem;
    font-size: .8125rem;
    color: var(--bs-warning-text-emphasis);
}
.df-conflict-note.df-resolved { color: var(--bs-success-text-emphasis); }
/* a field others' saves updated while the record is open (mainInput.html): a green dot with how many, then who / when */
.df-live-field-note {
    display: flex;
    align-items: flex-start;
    gap: .4rem;
    margin-top: .2rem;
    font-size: .8125rem;
    color: var(--ct-secondary-color);
}
/* the text wraps beside the dot (a narrow column), not under it */
.df-live-field-note > span:not(.df-live-count) { flex: 1 1 auto; min-width: 0; }
/* the same dot / count beside the field's label (mainInput.html) — the note under a tall editor is easy to miss */
.df-live-count.df-label-mark { margin: 0 0 0 .35rem; height: 1rem; min-width: 1rem; font-size: .625rem; vertical-align: .1em; }
.df-amber-dot.df-label-mark { margin-left: .35rem; vertical-align: .1em; }
.df-live-count {
    flex: 0 0 auto;
    margin-top: .05rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.1rem;
    height: 1.1rem;
    padding: 0 .3rem;
    border-radius: .55rem;
    background: var(--ct-success);
    color: #fff;
    font-size: .6875rem;
    font-weight: 700;
    line-height: 1;
}
/* the same dot in a grid row's # cell (search.live.js countDot): at the cell's left, the number keeps its place on the
   right. Amber while your edits in the row wait; faded once the row is gone */
.ag-cell .df-live-count-row {
    position: absolute;
    left: 6px;
    top: 50%;
    margin-top: 0;
    transform: translateY(-50%);
    text-decoration: none;
}
.df-live-count.df-live-count-stale { background: var(--ct-warning); color: #313a46; }
.df-live-count.df-live-count-gone { background: var(--ct-secondary-color); }
.df-conflict-note a { font-weight: 600; }

/* above record modals (1055), below the help panel (1084) and tour */
.df-merge {
    position: fixed;
    inset: 0;
    z-index: 1080;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    background: rgba(0, 0, 0, .45);
}
.df-merge-dialog {
    width: min(78rem, 100%);
    max-height: calc(100vh - 2rem);
    display: flex;
    flex-direction: column;
    border-radius: .5rem;
    border: 1px solid var(--ct-border-color, var(--bs-border-color));
    background: var(--ct-secondary-bg, var(--bs-body-bg));
    overflow: hidden;
}
.df-merge-head,
.df-merge-foot {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .75rem 1rem;
}
.df-merge-head { border-bottom: 1px solid var(--ct-border-color, var(--bs-border-color)); }
.df-merge-foot { border-top: 1px solid var(--ct-border-color, var(--bs-border-color)); flex-wrap: wrap; }
.df-merge-body { padding: .75rem 1rem; overflow: auto; }
.df-merge-sides {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: .5rem;
    align-items: end;
    margin-bottom: .4rem;
}
.df-merge-editor { height: min(55vh, 34rem); border: 1px solid var(--ct-border-color, var(--bs-border-color)); }
/* the compare and the Result under it (conflictMerge.html, fieldHistory.html — dfMerge.js): the two share the height */
.df-merge-editor.df-merge-top { height: min(28vh, 18rem); }
.df-merge-editor.df-merge-bottom { height: min(36vh, 24rem); }
.df-merge3 > any { display: contents; }
.df-merge-result-head { margin: .6rem 0 .35rem; }
/* a conflict in the Result: the markers dim, yours blue, theirs amber; the current one with a bar at the left */
.df-mr-editor .df-mr-marker { background: rgba(255, 255, 255, .06); opacity: .75; }
.df-mr-editor .df-mr-mine { background: rgba(53, 120, 229, .16); }
.df-mr-editor .df-mr-theirs { background: rgba(255, 193, 7, .14); }
.df-mr-editor .df-mr-mixed { background: rgba(255, 193, 7, .08); }
/* a conflict's line numbers, markers and all, until its last marker goes */
.df-mr-editor .line-numbers.df-mr-ln { color: var(--ct-warning, #ffbc00) !important; font-weight: 600; }
.df-mr-editor .df-mr-current { box-shadow: inset 3px 0 0 var(--ct-warning, #ffbc00); }
/* their changes that came in by themselves: a cyan bar beside the line numbers */
.df-mr-editor .df-mr-auto { background: var(--ct-info, #39afd1); width: 3px !important; margin-left: 3px; }
.df-mr-editor .df-mr-auto-removed { background: transparent; border-top: 2px solid var(--ct-info, #39afd1); height: 2px !important; }
/* Take Yours · Take Theirs · Take both over each conflict — Monaco's text layer is over its view zones (a click there
   only placed the cursor); raised here, only the zones' own lines are covered */
.df-mr-editor .view-zones { z-index: 1; }
.df-mr-zone { font: .75rem/22px system-ui, sans-serif; padding-left: .5rem; color: var(--bs-secondary-color); white-space: nowrap; }
.df-mr-zone a { color: var(--ct-info, #39afd1); text-decoration: none; cursor: pointer; }
.df-mr-zone a:hover { text-decoration: underline; }
/* the change the toolbar is on (conflictMerge.js _paintCurrent) */
.df-diff-editor .df-merge-current { box-shadow: inset 3px 0 0 var(--bs-warning); background: rgba(255, 193, 7, .08); }
/* the row of actions above a compare (fieldHistory.html) */
.df-merge-tools {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .35rem;
    margin-bottom: .4rem;
}
.df-merge-tools > any { display: contents; }
/* the shared diff (dfDiff.js): its bar and editor sit in the host's layout as if they were its own children */
df-diff,
df-merge-result,
.df-diff-bar > ng-transclude,
.df-diff-bar > ng-transclude > any { display: contents; }
.df-merge-value {
    padding: .5rem .75rem;
    border-radius: .375rem;
    border: 1px solid var(--ct-border-color, var(--bs-border-color));
    word-break: break-word;
    min-height: 3.5rem;
}
.df-merge-value.df-theirs { border-color: var(--bs-warning); }
.df-merge-value.df-mine { border-color: var(--bs-primary); }
@media (max-width: 575.98px) {
    .df-merge { padding: 0; }
    .df-merge-dialog { max-height: 100vh; height: 100vh; border-radius: 0; }
    .df-merge-sides { grid-template-columns: 1fr; }
    /* the conflict dialog (its body is the dialog's own child — the history dialog's sits in .df-history-body): the
       body takes what the header and footer leave and the editor fills it — its 55vh left the footer ~160px up the
       screen with nothing under it */
    .df-merge-dialog > .df-merge-body { flex: 1 1 auto; display: flex; flex-direction: column; min-height: 0; padding: .5rem .6rem; }
    .df-merge-dialog > .df-merge-body > .df-merge-editor,
    .df-merge-dialog > .df-merge-body > df-diff > .df-merge-editor,
    .df-merge-dialog > .df-merge-body > df-merge-result > .df-merge-editor { flex: 1 1 auto; height: auto; min-height: 9rem; }
    .df-merge-result-head .text-muted { display: none; }
}

/* AG Grid sizes the center viewport (the part that scrolls sideways) to its rows — with fewer rows than fit, the
   space below them was the body viewport (overflow hidden) and a sideways wheel / trackpad there did nothing. It
   fills the grid now; with more rows AG Grid's own height is larger and wins. */
.ag-body-viewport > .ag-center-cols-viewport { min-height: 100% !important; }

/* new rows typed into the grid (Add Row, search.js) — pinned at the top, marked in the # cell */
.ag-row.df-new-row { background: color-mix(in srgb, var(--bs-success) 9%, transparent); }
.ag-row.df-new-row .ag-cell { box-shadow: inset 0 -1px 0 color-mix(in srgb, var(--bs-success) 25%, transparent); }
.df-new-badge {
    font-size: .6875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .03em;
    color: var(--bs-success);
}
.df-new-remove {
    border: 0;
    background: transparent;
    color: var(--bs-secondary-color);
    padding: 0 .25rem 0 0;
    line-height: 1;
}
.df-new-remove:hover { color: var(--bs-danger); }
/* the pinned area's edge — new rows above, the table's rows below */
.ag-floating-top:not(:empty) { border-bottom: 2px solid color-mix(in srgb, var(--bs-success) 45%, transparent); }

/* the grid's popup editor for formatted text (gridTextEditor.js) — under the cell, resizable from its corner */
.df-cell-editor {
    display: flex;
    flex-direction: column;
    width: min(46rem, calc(100vw - 2rem));
    height: 22rem;
    min-width: 18rem;
    min-height: 10rem;
    max-width: calc(100vw - 1rem);
    resize: both;
    overflow: hidden;
    border: 1px solid var(--ct-border-color, var(--bs-border-color));
    border-radius: .375rem;
    background: var(--ct-secondary-bg, var(--bs-body-bg));
    box-shadow: 0 .5rem 1.5rem rgba(0, 0, 0, .45);
}
.df-cell-editor-head,
.df-cell-editor-foot { display: flex; align-items: center; gap: .4rem; padding: .35rem .6rem; }
.df-cell-editor-head { border-bottom: 1px solid var(--ct-border-color, var(--bs-border-color)); font-size: .8125rem; }
.df-cell-editor-foot { border-top: 1px solid var(--ct-border-color, var(--bs-border-color)); flex-wrap: wrap; }
.df-cell-editor-body { flex: 1 1 auto; min-height: 0; display: flex; }
.df-cell-editor-body > textarea {
    flex: 1 1 auto;
    border: 0;
    border-radius: 0;
    resize: none;
    font-family: var(--bs-font-monospace);
    font-size: .8125rem;
    white-space: pre;
    tab-size: 4;
}
.df-cell-editor-monaco { flex: 1 1 auto; min-width: 0; }

/* <field-menu> (fieldMenu.html) is only a wrapper — its .dropdown stays the input group's flex item */
field-menu { display: contents; }
/* the field ⋮ on inputs without a box of their own — a checkbox's label, a read-only field's label */
.df-input .df-check:has(.df-inline-menu) { display: flex; align-items: center; gap: .25rem; }
.df-input .df-inline-menu .field-menu-btn { height: auto; padding: .1rem .35rem; border-radius: var(--bs-border-radius-sm); }
.df-input .df-inline-menu:hover .field-menu-btn { color: #b8b8b8; }
.df-input .input-group:has(.field-menu-btn) .form-select { border: 0; border-radius: 0; background-color: transparent; }
/* the theme's disabled item is barely dimmer than an enabled one — make "not now" obvious (the reason is the item's tooltip) */
.df-input .dropdown-menu .dropdown-item.disabled {
    color: var(--bs-secondary-color);
    opacity: .45;
    font-style: italic;
}
.df-input .dropdown-menu li:has(> .dropdown-item.disabled) { cursor: not-allowed; }

/* a field's history (fieldHistory.js): its edits on the left, the compare on the right */
/* list | divider | compare — placed by column, so hiding the list doesn't shift the others; the list's width is
   --df-history-list-w (dragged on the divider, remembered) */
.df-history-body {
    display: grid;
    grid-template-columns: var(--df-history-list-w, 20rem) 10px minmax(0, 1fr);
    min-height: 0;
    flex: 1 1 auto;
    overflow: hidden;
}
.df-history-list {
    grid-column: 1;
    overflow-y: auto;
    max-height: min(62vh, 40rem);
}
.df-history-compare { grid-column: 3; min-width: 0; overflow: auto; }
/* the divider: a line with a round ‹ / › in the middle; the whole strip drags */
.df-history-splitter {
    grid-column: 2;
    position: relative;
    cursor: col-resize;
    touch-action: none;
    outline: none;
}
.df-history-splitter::before {
    content: "";
    position: absolute;
    top: 0; bottom: 0; left: 50%;
    width: 1px;
    background: var(--ct-border-color, var(--bs-border-color));
}
.df-history-splitter:hover::before,
.df-history-splitter:focus-visible::before,
.df-history-splitter.df-dragging::before { width: 3px; margin-left: -1px; background: var(--bs-warning); }
.df-history-splitter-btn {
    position: absolute;
    top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    z-index: 2;
    width: 22px; height: 44px;
    padding: 0;
    display: flex; align-items: center; justify-content: center;
    border-radius: 11px;
    border: 1px solid var(--ct-border-color, var(--bs-border-color));
    background: var(--ct-secondary-bg, var(--bs-body-bg));
    color: var(--bs-secondary-color);
    cursor: pointer;
}
.df-history-splitter-btn:hover { color: #fff; border-color: var(--bs-warning); }
/* while dragging, Monaco and the list don't take the pointer (a text selection would start) */
.df-history-body:has(.df-dragging) { user-select: none; }
.df-history-body:has(.df-dragging) .df-history-compare,
.df-history-body:has(.df-dragging) .df-history-list { pointer-events: none; }
/* the list's keyword box — stays at the top while the list scrolls */
.df-history-search {
    position: sticky;
    top: 0;
    z-index: 1;
    display: flex;
    align-items: center;
    gap: .35rem;
    padding: .5rem .6rem;
    background: var(--ct-secondary-bg, var(--bs-body-bg));
    border-bottom: 1px solid var(--ct-border-color, var(--bs-border-color));
}
.df-history-search > .mdi { color: var(--bs-secondary-color); }
.df-history-filter-btn { white-space: nowrap; }
/* who / from / to — under the search box, sticky with it */
.df-history-filters {
    position: sticky;
    top: 2.9rem;
    z-index: 1;
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
    gap: .35rem .5rem;
    padding: .5rem .6rem;
    background: var(--ct-secondary-bg, var(--bs-body-bg));
    border-bottom: 1px solid var(--ct-border-color, var(--bs-border-color));
}
.df-history-filters > a { grid-column: 2; justify-self: end; }
.df-history-item {
    display: block;
    width: 100%;
    text-align: left;
    padding: .5rem .75rem;
    border: 0;
    border-bottom: 1px solid var(--ct-border-color, var(--bs-border-color));
    border-left: 3px solid transparent;
    background: transparent;
    color: inherit;
}
.df-history-item:hover { background: var(--ct-tertiary-bg, var(--bs-tertiary-bg)); }
.df-history-item.active { border-left-color: var(--bs-warning); background: var(--ct-tertiary-bg, var(--bs-tertiary-bg)); }
.df-history-value {
    font-size: .8125rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.df-history-old { color: var(--bs-secondary-color); }
/* the note saved with the edit (Data/ChangeNotes.cs): up to two lines, the whole of it on hover */
.df-history-note {
    margin: .15rem 0;
    color: var(--bs-info-text-emphasis);
    font-style: italic;
    white-space: pre-line;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.df-history-code { font-family: var(--bs-font-monospace); font-size: .75rem; }
.df-history-pick { cursor: pointer; }
.df-merge-headbtn { line-height: 1; padding: .25rem .45rem; }
/* the two labels start level, whichever wraps (the conflict dialog bottom-aligns them to its toggle) */
.df-history .df-merge-sides { align-items: start; }
.df-history-pos { min-width: 4.5rem; font-variant-numeric: tabular-nums; opacity: 1 !important; }
/* the edit list hidden — the compare takes the width (fieldHistory.js toggleList) */
.df-history.df-history-nolist .df-history-body { grid-template-columns: 0 10px minmax(0, 1fr); }
.df-history.df-history-nolist .df-history-list { display: none; }
/* maximized (toggleMax): the whole window; the list and the compare fill the height, the editor stretches */
.df-merge.df-merge-max { padding: 0; }
.df-merge.df-merge-max .df-merge-dialog { width: 100%; height: 100vh; max-height: 100vh; border-radius: 0; }
.df-history.df-merge-max .df-history-list { max-height: none; }
/* the conflict dialog maximized: the body takes what the header and footer leave, the compare and the Result share it */
.df-merge.df-merge-max:not(.df-history) .df-merge-dialog > .df-merge-body { flex: 1 1 auto; display: flex; flex-direction: column; min-height: 0; }
.df-merge.df-merge-max:not(.df-history) .df-merge-editor { flex: 1 1 0; height: auto; min-height: 10rem; }
.df-merge.df-merge-max:not(.df-history) .df-merge-editor.df-merge-bottom { flex-grow: 1.3; }
.df-history.df-merge-max .df-history-compare { display: flex; flex-direction: column; min-height: 0; }
.df-history.df-merge-max .df-history-compare > .df-merge-body { flex: 1 1 auto; display: flex; flex-direction: column; min-height: 0; }
.df-history.df-merge-max .df-merge-editor { flex: 1 1 auto; height: auto; min-height: 12rem; }
@media (max-width: 767.98px) {
    /* stacked — no divider, so the list is always shown here (a hidden-list setting from a wider screen is ignored) */
    .df-history-body,
    .df-history.df-history-nolist .df-history-body { grid-template-columns: 1fr; overflow: auto; }
    .df-history-splitter { display: none; }
    .df-history.df-history-nolist .df-history-list { display: block; }
    .df-history.df-history-nolist .df-merge-sides .btn-group { display: none; }
    .df-history-list, .df-history-compare { grid-column: 1; }
    .df-history-list { max-height: 30vh; border-bottom: 1px solid var(--ct-border-color, var(--bs-border-color)); }
    .df-history .df-merge-editor { height: min(40vh, 24rem); }
}
/* a phone: the dialog is the whole screen — the list on top, the compare takes what's left and the editor fills it
   (its 55vh would run under the footer); the two labels sit over their halves, without the hints */
@media (max-width: 575.98px) {
    .df-history-body { grid-template-rows: auto minmax(0, 1fr); overflow: hidden; }
    .df-history-list { max-height: 28vh; }
    /* the filter panel takes most of 28vh — give the list room for a couple of edits under it */
    .df-history-list:has(.df-history-filters) { max-height: 46vh; }
    .df-history-compare { display: flex; flex-direction: column; min-height: 0; overflow: auto; }
    .df-history-compare > .df-merge-body { flex: 1 1 auto; display: flex; flex-direction: column; min-height: 0; padding: .5rem .6rem; }
    .df-history .df-merge-editor { flex: 1 1 auto; height: auto; min-height: 9rem; }
    .df-history .df-merge-sides { grid-template-columns: 1fr 1fr; align-items: start; }
    .df-history .df-merge-sides .text-muted { display: none; }
    .df-history .df-merge-foot { padding: .5rem .75rem; }
    /* the boxes stack here — "before" is under yours, so its arrow points up */
    .df-history .df-merge-value .mdi-arrow-left-bold { display: inline-block; transform: rotate(90deg); }
}

/* ---- session ended: sign in again over the page (JsSession, 01-extensions.debug.js) — above every dialog and toast */
.df-session {
	position: fixed;
	inset: 0;
	z-index: 1100;
	display: none;
	align-items: center;
	justify-content: center;
	padding: 1rem;
	background: rgba(0, 0, 0, .55);
	backdrop-filter: blur(2px);
}

.df-session.show { display: flex; }

.df-session-card {
	width: 100%;
	max-width: 24rem;
	max-height: calc(100vh - 2rem);
	overflow-y: auto;
}

html.df-session-open body { overflow: hidden; }

/* ---- the sign-in page (Views/Auth/SignIn.cshtml — Hyper's pages-login) */
.df-signin { min-height: 100vh; overflow-x: hidden; }

/* Compare, table rows: the ␍ after a line whose value had a \r there (search.compare.js paintCr) — a mark, not text */
.df-cr-mark {
	color: var(--ct-secondary-color, #8a8a8a);
	opacity: .7;
	font-size: .85em;
}

/* Dark like the app's logo box / top bar (--ct-topbar-bg in dark), behind the wordmark */
.df-signin-header {
	background-color: #201f1e;
	border-bottom: solid 1px #31302f;
}

.df-signin-eye { cursor: pointer; }
.df-signin-eye:focus-visible { outline: 2px solid var(--ct-primary); outline-offset: -2px; }

/* New table (tableWizard) — the start choices and the columns grid */
.df-tw-choice {
	display: flex;
	flex-direction: column;
	gap: .35rem;
	height: 100%;
	padding: 1.25rem;
	border: 1px solid var(--ct-border-color, var(--bs-border-color));
	border-radius: .5rem;
	background: var(--ct-secondary-bg, var(--bs-tertiary-bg));
	color: inherit;
}
.df-tw-choice:hover, .df-tw-choice:focus-visible { border-color: var(--bs-primary); outline: none; }
.df-tw-choice .mdi { color: var(--bs-primary); }
/* the grid fits an xl dialog; narrower, it scrolls sideways — and a scroll box clips the Links to list, so leave it room */
@media (max-width: 1199.98px) {
	.df-tw-scroll { overflow-x: auto; padding-bottom: 8rem; }
	.df-tw-columns { min-width: 60rem; }
}
.df-tw-columns .df-tw-default td { border-bottom-style: dashed; }
.df-tw-link .df-input { margin: 0; }
.df-tw-dragging { outline: 2px dashed var(--bs-primary); outline-offset: -.5rem; }
/* the file's first rows — both ways scrollable, header kept in view */
.df-tw-preview { max-height: 50vh; overflow: auto; border: 1px solid var(--ct-border-color, var(--bs-border-color)); border-radius: .25rem; }
.df-tw-preview table { white-space: nowrap; }
.df-tw-preview td { max-width: 18rem; overflow: hidden; text-overflow: ellipsis; }
.df-tw-preview thead th { position: sticky; top: 0; background: var(--ct-secondary-bg, var(--bs-tertiary-bg)); z-index: 1; }

/* ---- Push to… (pushRecord.js): the fields list in the dialog, and the receiving record's banner chips */
.df-push-fields {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr));
	column-gap: 1rem;
	max-height: 30vh;
	overflow-y: auto;
	padding: .25rem .5rem;
	border: 1px solid var(--ct-border-color, var(--bs-border-color));
	border-radius: .25rem;
}

.df-push-fields .form-check-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: block; }

.df-push-found { min-height: 1.5rem; padding-left: 1.5rem; }

.df-push-chips { display: flex; flex-wrap: wrap; gap: .25rem; margin-top: .5rem; }

.df-push-chip { padding: .1rem .5rem; font-size: .8rem; }

/* Compare 2 rows (compareRows.html) */
.df-compare-rows-table { max-height: 45vh; overflow-y: auto; }
.df-compare-rows-table table { table-layout: fixed; }
.df-compare-rows-table thead th { position: sticky; top: 0; z-index: 1; background: var(--ct-secondary-bg, var(--bs-body-bg)); }
.df-compare-rows .df-cr-field { width: 22%; }
.df-compare-rows .df-cr-act { width: 2.5rem; }
.df-compare-rows .df-cr-val { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.df-compare-rows tbody tr { cursor: pointer; }
.df-compare-rows tr.df-cr-diff > td { background: rgba(var(--ct-warning-rgb, 255, 193, 7), .08); }
.df-compare-rows tr.df-cr-picked > td { box-shadow: inset 0 1px 0 var(--ct-primary, #3e60d5), inset 0 -1px 0 var(--ct-primary, #3e60d5); }
.df-compare-rows .df-dialog-buttons { display: flex; align-items: center; }

/* a flex child that may shrink below its content, so text-truncate inside it works — the templates used it
   (pushRecord, compareRows, fieldHistory, conflictMerge) but Bootstrap 5 has no such class, so a long subtitle pushed
   the dialog's close button out of view */
.min-w-0 {
	min-width: 0 !important;
}

/* a confirm with a lot to say (Update target's table lists) scrolls inside — the title and the Cancel / OK buttons stay
   on screen */
.df-confirm .modal-body {
	max-height: calc(100vh - 12rem);
	overflow-y: auto;
}

	/* a long list folded after the first few (search.compare.js names()) */
	.df-confirm details.df-more > summary {
		cursor: pointer;
		color: var(--ct-primary);
	}

/* every dialog's header buttons (close, maximize, …) at the right edge — Bootstrap pushes only its own .btn-close over
   (margin-left: auto); ours sat right after the title block (Push to…, Compare rows, Shortcuts, Confirm) */
.modal-header > .df-dialog-buttons {
	display: flex;
	align-items: center;
	margin-left: auto;
	flex-shrink: 0;
}

/* The shared diff's Full screen (dfDiff.js): the bar across the top of the window, the editor under it (its top set from
   the bar's height) — above the dialogs (.df-merge is 1080, Bootstrap modals 1055) */
.df-diff-bar.df-diff-max {
    position: fixed;
    top: 0; left: 0; right: 0;
    z-index: 1090;
    margin: 0;
    padding: .5rem .75rem;
    background: var(--ct-secondary-bg, var(--bs-body-bg));
    border-bottom: 1px solid var(--ct-border-color, var(--bs-border-color));
}
.df-diff-editor.df-diff-max {
    position: fixed;
    left: 0; right: 0; bottom: 0;
    height: auto !important;
    z-index: 1090;
}
body.df-diff-maxed { overflow: hidden; }

/* ---- Live changes (dfLive.js): others' saves while a grid (search.live.js) or a record (Manage.js) is open */
/* the grid's banner (search.html, a .df-conflict-banner above the rows): one line per row you edited that someone
   else saved — the dot, the words, Review */
.df-live-stale-row { display: flex; align-items: baseline; gap: .4rem; margin-top: .3rem; }
.df-live-stale-row .df-amber-dot { align-self: center; }
.df-live-stale-row a { font-weight: 600; white-space: nowrap; }
/* colours: the theme's --ct-* (Hyper) — its --bs-success / warning / danger are empty here */
/* rows: changed by someone (for a few seconds) · saved by someone while you have edits in it · deleted / out of the view */
.ag-row.df-live-updated .ag-cell[col-id="__row"] { box-shadow: inset 3px 0 0 var(--ct-success); }
.ag-row.df-live-stale { background: color-mix(in srgb, var(--ct-warning) 12%, transparent); }
.ag-row.df-live-stale .ag-cell[col-id="__row"] { box-shadow: inset 3px 0 0 var(--ct-warning); }
.ag-row.df-live-gone .ag-cell { opacity: .45; text-decoration: line-through; text-decoration-color: color-mix(in srgb, currentColor 50%, transparent); }
/* the header's indicator (Navbar.cshtml): a dot on the icon like the settings cog's, and its dropdown */
.df-live-dot {
	position: absolute;
	top: 1.4rem;
	right: .4rem;
	width: .5rem;
	height: .5rem;
	border-radius: 50%;
	background: var(--ct-secondary-color);
}
.df-live-dot.df-live-dot-inline { position: static; display: inline-block; margin-right: .4rem; vertical-align: middle; }
.df-live-dot-on { background: var(--ct-success); }
.df-live-dot-connecting,
.df-live-dot-reconnecting { background: var(--ct-warning); animation: df-live-pulse 1.2s ease-in-out infinite; }
.df-live-dot-lost { background: var(--ct-danger); }
@keyframes df-live-pulse { 50% { opacity: .3; } }
.df-live-menu { width: 18rem; padding: .75rem; }
/* a cell's tooltip can be two lines (a refused value, then who else saved the row) */
.ag-tooltip { white-space: pre-line; }
/* the record form: a field someone else just changed — a green bar down the box's left edge, like the grid's in #,
   fading out. The box is whichever draws it — an .input-group (lookups, numbers…), Monaco's .input-monaco, or the
   control itself (long text's textarea) — never the column, which has the gutter */
.df-live-field .df-input :is(.input-group, .input-monaco, .form-floating > .form-control, .form-floating > .form-select):not(.input-group *) {
	animation: df-live-field 5s ease-out;
}
@keyframes df-live-field {
	0%, 50% { box-shadow: inset 3px 0 0 var(--ct-success); }
	100% { box-shadow: inset 3px 0 0 transparent; }
}

/* An integration's secrets (integrationSecrets.html) */
.df-int-secrets .df-int-secret {
	padding: .5rem 0;
	border-bottom: 1px solid var(--ct-border-color);
}
.df-int-secrets .df-int-secret:last-of-type { border-bottom: 0; }
.df-int-secrets .df-int-secret-name { font-size: .875rem; }
.df-int-secrets .df-int-secret-form { padding: .5rem 0 .25rem; }
.df-int-secrets .df-int-test-response {
	max-height: 16rem;
	overflow: auto;
	white-space: pre-wrap;
	word-break: break-word;
	background: var(--ct-tertiary-bg);
	padding: .5rem;
	border-radius: .25rem;
}

/* The in-place page editor (pageEditor.js, dfpageeditor.html) */
.df-pe-start { position: fixed; left: 16px; bottom: 16px; z-index: 1080; }
.df-pe-bar { position: fixed; left: 50%; transform: translateX(-50%); bottom: 16px; z-index: 1080; width: min(46rem, calc(100vw - 32px)); }
.df-pe-draft { width: max-content; max-width: min(28rem, calc(100vw - 32px)); }
/* one row: the format buttons scroll sideways inside the bar on a narrow screen; Save / Publish / Done stay in view */
.df-pe-row { display: flex; align-items: center; gap: .375rem; }
.df-pe-tools { flex: 1 1 auto; min-width: 0; overflow-x: auto; scrollbar-width: thin; }
.df-pe-tools > .btn { flex: none; }
.df-pe-actions { flex: none; display: flex; gap: .25rem; }
.df-pe-actions .mdi + .df-pe-label { margin-left: .25rem; }
@media (max-width: 575.98px) {
	.df-pe-label { display: none; }
	.df-pe-bar { bottom: 8px; }
	.df-pe-bar > .card-body { padding: .375rem !important; }
	.df-pe-note, .df-pe-pkg { font-size: .75rem; }
}
.df-pe-backdrop { position: fixed; inset: 0; z-index: 1084; background: rgba(0, 0, 0, .35); }
.df-pe-dialog { position: fixed; left: 50%; top: 50%; transform: translate(-50%, -50%); z-index: 1085; width: min(30rem, calc(100vw - 32px)); max-height: calc(100vh - 32px); overflow: auto; text-align: left; }
.df-pe-preview { text-align: center; background: var(--ct-tertiary-bg); border-radius: .25rem; min-height: 4rem; }
.df-pe-preview img { max-width: 100%; max-height: 12rem; }
.df-pe-gallery { display: flex; flex-wrap: wrap; gap: .375rem; max-height: 10rem; overflow: auto; }
.df-pe-thumb { width: 4.5rem; height: 4.5rem; padding: 2px; border: 2px solid var(--ct-border-color); border-radius: .25rem; background: var(--ct-tertiary-bg); }
.df-pe-thumb.active { border-color: var(--ct-primary); }
.df-pe-thumb img { width: 100%; height: 100%; object-fit: contain; }
html.df-page-editing .content-page { padding-bottom: 9rem; }
.df-edit-region, .df-edit-zone { outline: 1px dashed var(--ct-primary); outline-offset: 3px; border-radius: 2px; min-height: 1.5em; cursor: text; }
.df-edit-region:hover, .df-edit-zone:hover { outline-style: solid; }
.df-edit-region:focus, .df-edit-zone:focus { outline: 2px solid var(--ct-primary); }
.df-edit-zone { display: block; }
img.df-edit-image { outline: 2px dashed var(--ct-primary); outline-offset: 3px; cursor: pointer; }
img.df-edit-image:hover { outline-style: solid; }
a.df-edit-link { outline: 2px dashed var(--ct-primary); outline-offset: 3px; cursor: pointer; }
a.df-edit-link:hover { outline-style: solid; }
/* the Style menu and a list item's bar (df-page-editor.js) */
.df-pe-menu { position: fixed; z-index: 1086; margin: 0; max-height: calc(100vh - 16px); overflow-y: auto; min-width: 11rem; }
.df-pe-item { position: absolute; z-index: 1081; }
.df-pe-item .btn { padding: .1rem .35rem; }
.df-edit-list > *:hover { outline: 1px dotted var(--ct-primary); outline-offset: 2px; }
.df-edit-off { outline: 1px dashed var(--ct-secondary); outline-offset: 3px; position: relative; }
.df-edit-off:hover::after { content: attr(data-df-edit-why); position: absolute; left: 0; top: 100%; z-index: 1079; margin-top: 6px; padding: .25rem .5rem; font-size: .75rem; font-weight: normal; line-height: 1.3; white-space: normal; width: max-content; max-width: min(24rem, 80vw); color: var(--ct-body-color); background: var(--ct-secondary-bg); border: 1px solid var(--ct-border-color); border-radius: .25rem; }
/* the workflow diagram — a Dataflow.Workflows record's Diagram tab (Content/app/directives/workflowDiagram.js) */
.df-wd { display: flex; flex-direction: column; gap: .375rem; }
.df-wd-toolbar .btn { padding: .15rem .45rem; }
.df-wd-sep { width: 1px; height: 1.25rem; background: var(--ct-border-color); margin: 0 .25rem; }
.df-wd-zoom { min-width: 2.75rem; text-align: center; }
.df-wd-body { display: flex; gap: .5rem; height: calc(100vh - 340px); min-height: 22rem; }
.df-wd-viewport { position: relative; flex: 1 1 auto; overflow: hidden; border: 1px solid var(--ct-border-color); border-radius: .25rem; outline: none; cursor: grab; touch-action: none;
	background-color: var(--ct-tertiary-bg); background-image: radial-gradient(var(--ct-border-color) 1px, transparent 1px); background-size: 20px 20px; }
.df-wd-viewport:active { cursor: grabbing; }
.df-wd-viewport:focus-visible { box-shadow: 0 0 0 2px var(--ct-primary); }
.df-wd-stage { position: absolute; left: 0; top: 0; transform-origin: 0 0; }
.df-wd-svg { position: absolute; left: 0; top: 0; overflow: visible; pointer-events: none; }
.df-wd-nodes { position: absolute; left: 0; top: 0; }
.df-wd-message { position: absolute; left: 50%; top: 45%; transform: translate(-50%, -50%); color: var(--ct-secondary-color); font-size: .875rem; text-align: center; max-width: 80%; pointer-events: none; }
.df-wd-node { position: absolute; width: 168px; height: 58px; padding: .35rem .6rem .35rem .75rem; cursor: move; user-select: none;
	background: var(--ct-secondary-bg); border: 1px solid var(--ct-border-color); border-left: 5px solid var(--df-wd-color, var(--ct-secondary)); border-radius: .375rem; box-shadow: 0 1px 3px rgba(0, 0, 0, .15); }
.df-wd-node.final { border-right-width: 3px; border-right-color: var(--df-wd-color, var(--ct-secondary)); }
.df-wd-node.selected { outline: 2px solid var(--ct-primary); outline-offset: 1px; }
.df-wd-node.has-danger { box-shadow: 0 0 0 2px rgba(var(--ct-danger-rgb), .6); }
.df-wd-node.has-warning { box-shadow: 0 0 0 2px rgba(var(--ct-warning-rgb), .6); }
.df-wd-any { border-style: dashed; border-left-style: dashed; border-left-width: 1px; height: 40px; background: transparent; box-shadow: none; color: var(--ct-secondary-color); font-style: italic; }
.df-wd-title { font-size: .8125rem; font-weight: 600; line-height: 1.25; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.df-wd-value { font-size: .6875rem; font-family: var(--ct-font-monospace, monospace); color: var(--ct-secondary-color); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.df-wd-port { position: absolute; right: -7px; top: 50%; width: 12px; height: 12px; margin-top: -6px; border-radius: 50%; cursor: crosshair;
	background: var(--ct-primary); border: 2px solid var(--ct-secondary-bg); opacity: 0; transition: opacity .1s; }
.df-wd-node:hover .df-wd-port, .df-wd-node.selected .df-wd-port { opacity: 1; }
.df-wd-edge .df-wd-line { fill: none; stroke: currentColor; stroke-width: 1.75; }
.df-wd-edge .df-wd-head { fill: currentColor; stroke: none; }
.df-wd-edge .df-wd-hit { fill: none; stroke: transparent; stroke-width: 14; pointer-events: stroke; cursor: pointer; }
.df-wd-edge.selected .df-wd-line { stroke-width: 3; }
.df-wd-temp { fill: none; stroke: var(--ct-primary); stroke-width: 2; stroke-dasharray: 5 4; }
.df-wd-label { position: absolute; transform: translate(-50%, -50%); padding: .05rem .4rem; font-size: .75rem; white-space: nowrap; cursor: pointer; user-select: none;
	background: var(--ct-secondary-bg); border: 1px solid var(--ct-border-color); border-radius: 1rem; }
.df-wd-label.selected { border-color: var(--ct-primary); box-shadow: 0 0 0 1px var(--ct-primary); }
.df-wd-label .badge { font-size: .625rem; padding: .1rem .3rem; }
.df-wd-panel { flex: 0 0 22rem; max-width: 22rem; margin: 0; overflow-y: auto; }
.df-wd-panel-head { display: flex; align-items: center; padding: .5rem .75rem; border-bottom: 1px solid var(--ct-border-color); position: sticky; top: 0; background: inherit; z-index: 1; }
.df-wd-panel-body { padding: .5rem .75rem; }
.df-wd-from { display: grid; grid-template-columns: 1fr 1fr; column-gap: .5rem; padding-left: .5rem; }
.df-wd-action { background: var(--ct-tertiary-bg); }
.df-wd-issues li { margin-bottom: .2rem; }
.df-wd-link { cursor: pointer; }
.df-wd-link:hover span { text-decoration: underline; }
@media (max-width: 767.98px) {
	.df-wd-body { flex-direction: column; height: auto; }
	.df-wd-viewport { height: 60vh; min-height: 18rem; }
	.df-wd-panel { flex: none; max-width: none; }
}
/* the automation editor's branches (workflowDiagram.js, DfAutomationEditor): a lane's label, its "+" */
.df-wd-label.df-wd-lane { transform: translate(-50%, 0); cursor: default; font-size: .6875rem; padding: 0 .35rem; color: var(--ct-secondary-color); }
.df-wd-add { position: absolute; width: 30px; height: 30px; display: flex; align-items: center; justify-content: center; cursor: pointer; user-select: none;
	border: 1px dashed var(--ct-border-color); border-radius: 50%; color: var(--ct-secondary-color); background: var(--ct-secondary-bg); }
.df-wd-add:hover { color: var(--ct-primary); border-color: var(--ct-primary); }
.df-wd-add.selected { color: var(--ct-primary); border: 2px solid var(--ct-primary); }
