/*
 * SUI — the Strixie UI layer. A thin set of enhancements on top of stock Bootstrap 5.
 *
 * THREE LAYERS, THREE PREFIXES. Keeping them apart is the whole point of the naming:
 *
 *   1. Bootstrap (vendor)   .btn .card .navbar …, --bs-*, data-bs-*
 *      `bs-` is Bootstrap's OWN prefix — it is declared in Bootstrap's scss as
 *      `$prefix: bs-`, and Bootstrap ships classes in it (.bs-tooltip-*, .bs-popover-*),
 *      459 --bs-* custom properties and 10 data-bs-* attributes.
 *      => NEVER author a .bs-* class, and NEVER define a new --bs-* variable.
 *         Overriding the VALUE of an existing --bs-* var (as below) is correct usage
 *         and exactly what Bootstrap intends.
 *
 *   2. SUI (this layer)     .sui-*, --sui-*, data-sui-*, sui.* storage keys
 *      Shared across every project that adopts this shell. Anything a second project
 *      would want lives here. If naming it does not require a domain noun, it is SUI.
 *
 *   3. Application          .strixie-*, .slmv3-*, .sqat-* …
 *      One project only. If you need a domain noun to name it — location-tree,
 *      soil-trends, consortium-map — it belongs to the app, not to SUI.
 *
 * The reference copy of this file lives in strixie_erp; every other project takes it
 * VERBATIM. Do NOT rebrand the prefixes when copying, or `diff` stops working as a sync
 * tool and the copies silently diverge (which is how we got here). Improvements found
 * downstream are ported back to strixie_erp first, then re-copied out.
 *
 * Keep page-specific styling OUT — it goes in the project's own stylesheet.
 * See docs/sui.md.
 */

.sui-shell {
	min-height: 100vh;
}

/* Sidebar width is a variable with the standing default, so a project whose nav is
   short can narrow it from its own layer instead of forking this file — which is the
   only thing that keeps diff working as a sync tool between the projects. Left as a
   length rather than made content-driven on purpose: the collapse below animates
   width, and CSS cannot transition to or from an intrinsic sizing keyword. */
.sui-shell .sui-sidebar {
	--bs-offcanvas-width: var(--sui-sidebar-width, 280px);
	flex: 0 0 var(--sui-sidebar-width, 280px);
	width: var(--sui-sidebar-width, 280px);
	margin-left: 0.5rem;
	transition: flex-basis 0.18s ease, width 0.18s ease;
}

.sui-shell > .d-lg-flex > .flex-grow-1 {
	min-width: 0;
}

.sui-shell .sui-sidebar .offcanvas-header {
	padding: 1rem 1.25rem;
}

.sui-shell .sui-sidebar-content {
	padding: 1.25rem;
	transition: padding 0.18s ease;
}

/* Sidebar brand: a header band sized to match the topbar height, so the logo
   reads as a proper brand instead of a small mark tucked in the corner. The
   bottom border lines up with the topbar's border for one continuous header rule. */
.sui-shell .sui-sidebar-brand {
	min-height: 70px;
	padding-inline: 1rem;
	margin-bottom: 0.5rem;
	font-size: 1.5rem;
	line-height: 1.1;
	border-bottom: 1px solid var(--bs-border-color);
}

.sui-shell .sui-sidebar-brand .bi {
	font-size: 2rem;
}

/* An <img> logo rather than an icon font: sized off the brand's own font-size so
   the two brand treatments stay interchangeable. */
.sui-shell .sui-sidebar-brand-mark {
	height: 1em;
	width: auto;
	flex-shrink: 0;
}

.sui-shell .sui-sidebar-toggle {
	aspect-ratio: 1;
	width: 2.25rem;
	padding: 0;
}

.sui-shell .sui-nav-section-title {
	margin: 1rem 0 0.5rem;
	color: var(--bs-secondary-color);
	font-size: 0.75rem;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
}

.sui-shell .sui-topbar-subtitle {
	color: var(--bs-secondary-color);
}

.sui-shell .summary-stat {
	font-size: 2rem;
	line-height: 1;
}

.sui-shell .amount {
	text-align: right;
	white-space: nowrap;
}

.sui-shell .table td,
.sui-shell .table th {
	vertical-align: top;
}

.sui-shell .work-links a {
	text-decoration: none;
}

@media (min-width: 992px) {
	.sui-shell .sui-sidebar {
		position: sticky;
		top: 0;
		height: 100vh;
		display: flex;
		flex-direction: column;
	}

	/* Sticky at 100vh, so a nav taller than the viewport has to scroll inside the
	   sidebar. Bootstrap's .offcanvas-lg resets .offcanvas-body to overflow-y: visible
	   at this breakpoint, so turn it back on here. min-height: 0 lets the flex child
	   shrink below its content height, which is what makes the overflow happen. */
	.sui-shell .sui-sidebar .offcanvas-body {
		flex: 1 1 auto;
		min-height: 0;
		overflow-y: auto;
		overscroll-behavior: contain;
	}

	html.sui-sidebar-collapsed .sui-shell .sui-sidebar {
		--bs-offcanvas-width: 76px;
		flex-basis: 76px;
		width: 76px;
	}

	html.sui-sidebar-collapsed .sui-shell .sui-sidebar-content {
		padding: 1rem 0.5rem;
	}

	html.sui-sidebar-collapsed .sui-shell .sui-sidebar-brand {
		justify-content: center;
		min-height: 70px;
		padding-left: 0;
		padding-right: 0;
	}

	html.sui-sidebar-collapsed .sui-shell .sui-sidebar-brand .bi {
		font-size: 1.7rem;
	}

	html.sui-sidebar-collapsed .sui-shell .sui-sidebar-brand-mark {
		width: 1.7rem;
		height: 1.7rem;
	}

	html.sui-sidebar-collapsed .sui-shell .sui-sidebar-toggle {
		width: 2.25rem;
	}

	html.sui-sidebar-collapsed .sui-shell .nav-link {
		justify-content: center;
		padding-left: 0;
		padding-right: 0;
	}

	html.sui-sidebar-collapsed .sui-shell .nav-link .bi {
		font-size: 1.1rem;
	}

	/* Collapsed: hide the text visually but keep it for screen readers, so the nav
	   still announces its section structure. `display: none` would drop it entirely. */
	html.sui-sidebar-collapsed .sui-shell .sui-sidebar-label,
	html.sui-sidebar-collapsed .sui-shell .sui-nav-section-title {
		position: absolute !important;
		width: 1px !important;
		height: 1px !important;
		padding: 0 !important;
		margin: -1px !important;
		overflow: hidden !important;
		clip: rect(0, 0, 0, 0) !important;
		white-space: nowrap !important;
		border: 0 !important;
	}
}

/* Placeholder text */
::placeholder {
	color: var(--bs-secondary-color) !important;
	opacity: 0.2 !important;
}

/* User Menu */
.sui-user-menu-toggle {
	width: 38px;
	height: 38px;
	font-weight: 600;
	transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out;
	display: flex;
	align-items: center;
	justify-content: center;
	user-select: none;
}

.sui-user-menu-toggle:hover {
	background-color: var(--bs-gray-200) !important;
	border-color: var(--bs-gray-300) !important;
}

.sui-user-menu .dropdown-menu {
	min-width: 220px;
	margin-top: 0.5rem !important;
}

.sui-user-menu .dropdown-header {
	padding: 0.75rem 1rem;
	border-bottom: 1px solid var(--bs-border-color-light);
	margin-bottom: 0.25rem;
}

/* Notifications */
.sui-notification-toggle {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 0.5rem;
	color: var(--bs-secondary-color);
	background: none;
	border: none;
	font-size: 1.25rem;
	line-height: 1;
	transition: color 0.15s ease-in-out;
}

.sui-notification-toggle:hover {
	color: var(--bs-primary);
}

.sui-notification-badge {
	position: absolute;
	top: 0.35rem;
	right: 0.35rem;
	transform: translate(25%, -25%);
	font-size: 0.65rem;
	padding: 0.25em 0.45em;
	border: 2px solid white; /* Contrast against the bell */
}

/* Background jobs — shared top-bar status menu. */
@keyframes sui-spin {
	from { transform: rotate(0deg); }
	to { transform: rotate(360deg); }
}

.sui-task-toggle {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 0.5rem;
	color: var(--bs-secondary-color);
	background: none;
	border: none;
	font-size: 1.25rem;
	line-height: 1;
	transition: color 0.15s ease-in-out;
}

.sui-task-toggle:hover {
	color: var(--bs-primary);
}

.sui-task-toggle.is-active {
	color: var(--bs-primary);
}

.sui-task-toggle.is-active i {
	display: inline-block;
	animation: sui-spin 2s linear infinite;
}

/* The rotation is how people notice that work is still running, so it continues under reduced motion,
   only slower. The badge carries the count. */
@media (prefers-reduced-motion: reduce) {
	.sui-task-toggle.is-active i {
		animation-duration: 4s;
	}
}

.sui-task-badge {
	position: absolute;
	top: 0.35rem;
	right: 0.35rem;
	transform: translate(25%, -25%);
	font-size: 0.65rem;
	padding: 0.25em 0.45em;
	border: 2px solid white;
}

/* Panel overflow menu — the kebab at the far right of a panel header, holding the
   panel's secondary ACTIONS (verbs). View controls stay inline and visible: a control
   whose state the reader needs to see ("binned by month") must not be hidden in a menu.
   See docs/sui-panel-menu-plan.md. Styled to match the topbar toggles above. */
.sui-panel-menu-toggle {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 2rem;
	height: 2rem;
	padding: 0;
	color: var(--bs-secondary-color);
	font-size: 1.1rem;
	line-height: 1;
	text-decoration: none;
	transition: color 0.15s ease-in-out;
}

.sui-panel-menu-toggle:hover,
.sui-panel-menu-toggle:focus,
.sui-panel-menu-toggle[aria-expanded="true"] {
	color: var(--bs-primary);
}

/* Sortable column header (see sortHeader fragment, background-tasks.js and docs/sui.md §2.5).
 * The control looks like the header text; the arrow after it shows the order. A column that can be
 * sorted but is not sorted on shows a faint two-way arrow, so it reads as clickable. */
.sui-sort {
	display: inline-flex;
	align-items: center;
	gap: 0.25rem;
	padding: 0;
	color: inherit;
	font: inherit;
	text-transform: inherit;
	text-decoration: none;
	background: transparent;
	border: 0;
	white-space: nowrap;
}

.sui-sort:hover,
.sui-sort:focus-visible {
	color: var(--bs-primary);
}

.sui-sort-icon {
	font-size: 0.8em;
	line-height: 1;
}

[aria-sort="none"] .sui-sort-icon {
	opacity: 0.4;
}

.sui-sort:hover .sui-sort-icon,
.sui-sort:focus-visible .sui-sort-icon {
	opacity: 1;
}

/* Inline field-help affordance (see fieldHelp fragment + layout popover script). */
.sui-field-help {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 1rem;
	height: 1rem;
	margin-left: 0.25rem;
	padding: 0;
	color: var(--bs-secondary-color);
	background: transparent;
	border: 0;
	line-height: 1;
	vertical-align: baseline;
}

.form-label + .sui-field-help {
	margin-bottom: 0.5rem;
}

.sui-field-help:hover,
.sui-field-help:focus {
	color: var(--bs-primary);
}

.sui-field-help:focus-visible {
	border-radius: 50%;
	outline: 2px solid rgba(var(--bs-primary-rgb), 0.35);
	outline-offset: 2px;
}

.sui-field-help .bi {
	font-size: 0.875rem;
	line-height: 1;
}

.sui-field-help-popover {
	--bs-popover-max-width: 20rem;
	/* --bs-tertiary-bg rather than --bs-gray-100: it is colour-mode aware, so the popover
	   follows data-bs-theme instead of staying light-grey on a dark ground. Ported up from
	   SQAT_data_governance, which had it right. */
	--bs-popover-bg: var(--bs-tertiary-bg);
	font-size: 0.875rem;
}

/* Print: drop the app chrome and lay records out as a clean, full-width document. */
@media print {
	/* Keep summary columns side by side regardless of the paper's viewport width. */
	.sui-print-columns { flex-wrap: nowrap; break-inside: avoid; }
	.sui-print-columns > * { flex: 1 1 0; width: 0; }
	.no-print { display: none !important; }
	#bootstrapPrimaryNav { display: none !important; }
	.sui-shell { background: #fff !important; }
	.sui-shell, .sui-shell .min-vh-100 { min-height: 0 !important; }
	main#main-content { padding: 0 !important; }
	.card { border: 0 !important; box-shadow: none !important; }
	.card-header { padding-left: 0 !important; padding-right: 0 !important; }
	.card-header .btn { display: none !important; }

	/* Print one panel only. sui-panel-menu.js marks the chosen panel `sui-printing`,
	   marks every ancestor up to <html> `sui-printing-ancestor`, and sets
	   `sui-printing-active` on <body> before calling window.print(); all three are
	   removed on afterprint. Hiding off-path siblings at each level (rather than the
	   usual visibility:hidden trick) leaves the panel in normal flow, so a long panel
	   still paginates instead of being clipped to one page. */
	body.sui-printing-active .sui-printing-ancestor > *:not(.sui-printing-ancestor):not(.sui-printing) {
		display: none !important;
	}
	.table { font-size: 11px; }
	.table a { color: inherit !important; text-decoration: none !important; }
	thead { display: table-header-group; } /* repeat column headers on each printed page */
	tr, img { page-break-inside: avoid; }
	@page { margin: 12mm; }
}
