/* ==========================================================================
   NMS THEME — Glass & Aurora
   The NMS design system (2018) palette — brand blue #1964AA, cyan #009FE3,
   warm amber — rendered as a light, translucent surface language: frosted
   glass panels floating over a slowly drifting aurora, gloss highlights on
   every raised edge, brand-tinted glow instead of grey shadow.
   Typography: Merriweather Sans for headings and UI chrome, Open Sans for
   content at 150% line-height (W3C accessibility minimum).
   Light mode.
   ========================================================================== */

@import url('https://fonts.googleapis.com/css2?family=Merriweather+Sans:wght@300..800&family=Open+Sans:ital,wght@0,300..800;1,300..800&display=swap');


/* ---------- DESIGN TOKENS ---------- */

/* Declared on <html>, not on the themed <body>: the page background and the
   aurora layer are painted on <html>, and custom properties only inherit down. */
html:has(.theme-nms) {
	/* Brand — straight from the NMS design system */
	--nms-blue: #1964AA;
	--nms-blue-deep: #0C3255;
	--nms-blue-mid: #114677;
	--nms-blue-soft: #E8EFF7;
	--nms-cyan: #009FE3;
	--nms-cyan-soft: #E5F5FC;
	--nms-amber: #E8852E;
	--nms-green: #66B536;
	--nms-red: #D00000;

	/* One fill for every saturated control. A cyan-to-blue ramp reads as cyan on a badge
	   and as blue on a button, and the same token looking like two different colours is
	   what made the chrome feel arbitrary — so the ramp stays anchored on the brand blue
	   and only leans towards cyan. */
	--nms-brand: linear-gradient(135deg, #2E8BD0 0%, var(--nms-blue) 70%);
	--nms-brand-hover: linear-gradient(135deg, #2681C7 0%, var(--nms-blue-mid) 75%);

	/* Surfaces — four tiers, and which tier a thing belongs to is decided by what sits
	   behind it, not by what it is.
	   glass   — chrome with nothing but the aurora behind it: the nav rail.
	   frost   — chrome that live content scrolls underneath: the top bar, the chat
	             composer, the filter panel's reset strip. Translucent, but backed by a
	             real backdrop blur so what passes behind is a wash, never readable text.
	   panel   — content cards, grids, chat bubbles. Nothing but the aurora sits behind
	             them, and a blurred smooth gradient is the same gradient, so these take
	             the translucency and the gloss sweep and skip the backdrop filter
	             entirely — which also keeps them from becoming containing blocks.
	   overlay — menus, popovers, tooltips, calendars, modals, offcanvases: every one of
	             them covers arbitrary live content, so every one of them is opaque and
	             takes its gloss from light instead. */
	--nms-bg: #D3E2F3;
	--nms-surface: #FFFFFF;
	--nms-glass: rgba(255, 255, 255, 0.68);
	--nms-glass-strong: rgba(255, 255, 255, 0.88);
	--nms-glass-border: rgba(255, 255, 255, 0.85);
	--nms-panel: rgba(255, 255, 255, 0.70);
	/* Each panel's own top-left highlight. Without it a row of translucent cards reads as
	   randomly tinted rectangles; with it every card is lit from the same direction and
	   the tint underneath becomes the glass, not the accident. */
	--nms-gloss: linear-gradient(158deg, rgba(255, 255, 255, 0.60) 0%, rgba(255, 255, 255, 0.12) 42%, rgba(255, 255, 255, 0) 70%);
	--nms-overlay: #FFFFFF;
	/* The opaque counterpart of --nms-panel, for the surfaces that cover live content:
	   modals, offcanvases, side columns. Faintly blue so they still belong to the field. */
	--nms-sheet: #F6F9FD;
	--nms-hairline: rgba(12, 50, 85, 0.10);
	--nms-hairline-strong: rgba(12, 50, 85, 0.16);
	--nms-blur: blur(18px) saturate(170%);
	--nms-blur-soft: blur(10px) saturate(140%);

	/* Text */
	--nms-text: #253444;
	--nms-text-muted: #606B7A;
	--nms-text-subtle: #8999AF;

	/* Elevation — shadows carry a blue cast so they belong to the palette */
	--nms-shadow-sm: 0 1px 2px rgba(12, 50, 85, 0.05), 0 1px 3px rgba(12, 50, 85, 0.06);
	--nms-shadow: 0 8px 28px rgba(12, 50, 85, 0.08), 0 2px 6px rgba(12, 50, 85, 0.04);
	--nms-shadow-lg: 0 24px 60px rgba(12, 50, 85, 0.18), 0 4px 12px rgba(12, 50, 85, 0.08);
	/* Menus are small. A 60px blur offset 24px down falls clean outside a 24px-tall
	   popup and leaves it floating unanchored, so overlays get their own elevation. */
	--nms-shadow-menu: 0 10px 24px rgba(12, 50, 85, 0.16), 0 2px 6px rgba(12, 50, 85, 0.10);
	--nms-glow: 0 6px 20px rgba(25, 100, 170, 0.28);
	/* Top-edge gloss: the single line that makes a flat panel read as glass */
	--nms-sheen: inset 0 1px 0 rgba(255, 255, 255, 0.75);

	--nms-r-sm: 8px;
	--nms-r: 12px;
	--nms-r-lg: 18px;
	--nms-r-pill: 999px;

	--nms-ease: cubic-bezier(0.22, 0.61, 0.36, 1);
	--nms-ease-out: cubic-bezier(0.16, 1, 0.3, 1);

	--nms-font-head: 'Merriweather Sans', 'Segoe UI', system-ui, sans-serif;
	--nms-font-body: 'Open Sans', 'Segoe UI', system-ui, sans-serif;

	color-scheme: light;
}

.theme-nms {
	font-family: var(--nms-font-body);
	line-height: 1.5;
}


/* =============================================
   BOOTSTRAP OVERRIDES
   The base app palette is already the NMS palette, so only surface-level
   variables are re-pointed here — hues stay as they are.
   ============================================= */

.theme-nms {
	/* --bs-body-bg has to stay an opaque colour. Half the app reaches for it as "the
	   solid surface behind content" — sticky grid heads, the filter panel's reset
	   footer, offcanvas bodies, response cards — and Bootstrap derives
	   --bs-tooltip-color from it, so `transparent` here also turned every tooltip's
	   text invisible. The page background is painted on <html> instead, and <body> is
	   forced transparent below. */
	--bs-body-bg: #F3F8FD;
	--bs-body-bg-rgb: 243, 248, 253;
	--bs-body-color: var(--nms-text);
	--bs-secondary-color: var(--nms-text-muted);
	--bs-border-color: var(--nms-hairline);
	--bs-border-color-translucent: var(--nms-hairline);
	--bs-emphasis-color-rgb: 37, 52, 68;

	--border-color-opacity-10: var(--nms-hairline);
	--input-border-color: var(--nms-hairline-strong);
	--input-focus-box-shadow: 0 0 0 3px rgba(0, 159, 227, 0.22);

	--bs-box-shadow: var(--nms-shadow);
	--bs-box-shadow-sm: var(--nms-shadow-sm);
	--bs-box-shadow-lg: var(--nms-shadow-lg);
	--bs-card-box-shadow: var(--nms-shadow-sm);

	/* The global radius is what small controls inherit — inputs, select2, grid filters,
	   chips. At 12px a 28px-tall select turns into a lozenge next to the .form-control
	   beside it, so the base stays small and panels opt into the larger radii. */
	--bs-border-radius: var(--nms-r-sm);
	--bs-border-radius-sm: 6px;
	--bs-border-radius-lg: var(--nms-r-lg);

	/* The app's --bs-accent is #FD5200, an orange-red that appears nowhere in the NMS
	   palette; the design system's accent is amber. */
	--bs-accent: var(--nms-amber);
	--bs-accent-rgb: 232, 133, 46;

	--bs-tooltip-bg: #143D64;
	--bs-tooltip-color: #FFFFFF;
	--bs-tooltip-opacity: 1;

	--bs-secondary-bg-subtle: var(--nms-blue-soft);
	--bs-secondary-bg-subtle-rgb: 232, 239, 247;
}


/* =============================================
   BODY — aurora field
   Three brand-hued light pools drift behind the whole app. They live on a
   fixed pseudo-element so the animation composites on the GPU instead of
   repainting a `background-attachment: fixed` layer on every scroll.
   ============================================= */

html:has(.theme-nms) {
	background: var(--nms-bg);
}

.theme-nms.theme-nms {
	background: transparent !important;
	color: var(--nms-text);
}

.theme-nms::before {
	content: '';
	position: fixed;
	inset: -25%;
	z-index: -1;
	pointer-events: none;
	/* The pools are placed in this element's own box, which the -25% inset makes 150% of
	   the viewport — so a pool at "10% 4%" of the box lands off-screen above the top-left
	   corner. These positions are the viewport positions remapped into that box:
	   box% = (viewport% + 25) / 1.5.
	   The middle pool is what makes the panels read as glass at all. With the field only
	   coloured at its corners, the content column — the one place every card sits — was
	   the palest part of the page, and a translucent card over near-white is just a white
	   card. */
	background:
		radial-gradient(40% 44% at 23% 22%, rgba(25, 100, 170, 0.47), transparent 68%),
		radial-gradient(36% 40% at 75% 23%, rgba(0, 159, 227, 0.45), transparent 66%),
		radial-gradient(42% 44% at 53% 47%, rgba(0, 159, 227, 0.26), transparent 70%),
		radial-gradient(40% 42% at 33% 75%, rgba(232, 133, 46, 0.20), transparent 70%),
		radial-gradient(34% 38% at 78% 69%, rgba(25, 100, 170, 0.27), transparent 68%);
	animation: nms-aurora-drift 30s var(--nms-ease) infinite alternate;
	will-change: transform;
}

@keyframes nms-aurora-drift {
	0% {
		transform: translate3d(0, 0, 0) scale(1);
	}
	50% {
		transform: translate3d(2.5%, -2%, 0) scale(1.06);
	}
	100% {
		transform: translate3d(-2%, 2.5%, 0) scale(1.03);
	}
}

.theme-nms .body-wrap {
	background: transparent;
}

.theme-nms h1,
.theme-nms h2,
.theme-nms h3,
.theme-nms h4,
.theme-nms h5,
.theme-nms h6,
.theme-nms .card-title {
	font-family: var(--nms-font-head);
	font-weight: 600;
	letter-spacing: -0.01em;
	color: var(--nms-blue-deep);
}

.theme-nms .text-muted {
	color: var(--nms-text-muted) !important;
}

.theme-nms .text-dark,
.theme-nms .text-body {
	color: var(--nms-text) !important;
}

.theme-nms a:not(.btn):not(.nav-link):not(.dropdown-item):not(.navbar-brand) {
	color: var(--nms-blue);
	text-decoration: none;
	transition: color 150ms var(--nms-ease);
}

.theme-nms a:not(.btn):not(.nav-link):not(.dropdown-item):not(.navbar-brand):hover {
	color: var(--nms-cyan);
	text-decoration: underline;
	text-underline-offset: 2px;
}


/* =============================================
   NAVBAR — frosted left rail
   The rail is translucent so the aurora keeps moving behind it; the active
   item is a solid brand pill with a glow, which is the only saturated block
   in the chrome.
   ============================================= */

.theme-nms .navbar {
	background: rgba(255, 255, 255, 0.96) !important;
	box-shadow: var(--nms-sheen), 0 0 0 1px var(--nms-hairline) !important;
	border-right: 0 !important;
}

/* The blur only from md up. Below that the navbar is a fixed top bar that hosts
   the slide-in menu, and a backdrop-filter would make it the containing block
   for that position: fixed panel — collapsing the whole menu to the bar's own
   height. From md up the rail is full height and Bootstrap lays the menu out
   statically inside it, so the glass is safe there. */
@media (min-width: 768px) {
	.theme-nms .navbar {
		background: var(--nms-glass) !important;
		backdrop-filter: var(--nms-blur);
		-webkit-backdrop-filter: var(--nms-blur);
		box-shadow: var(--nms-sheen), 1px 0 0 0 var(--nms-hairline), 8px 0 32px rgba(12, 50, 85, 0.05) !important;
	}
}

.theme-nms .navbar .navbar-brand {
	border-bottom-color: var(--nms-hairline) !important;
}

.theme-nms .navbar .nav-link {
	position: relative;
	color: var(--nms-text-muted);
	border-radius: var(--nms-r);
	transition: color 180ms var(--nms-ease), background-color 180ms var(--nms-ease),
		box-shadow 180ms var(--nms-ease), transform 180ms var(--nms-ease);
}

.theme-nms .navbar .nav-link span {
	font-family: var(--nms-font-head);
	font-weight: 500;
}

.theme-nms .navbar .nav-link:hover {
	color: var(--nms-blue);
	background: linear-gradient(135deg, rgba(0, 159, 227, 0.14), rgba(25, 100, 170, 0.08));
	box-shadow: var(--nms-sheen);
}

.theme-nms .navbar .nav-item.active > .nav-link,
.theme-nms .navbar .nav-link.active {
	color: #fff !important;
	background: var(--nms-brand) !important;
	box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.35), var(--nms-glow) !important;
}

.theme-nms .navbar .nav-item.active > .nav-link .icon,
.theme-nms .navbar .nav-item.active > .nav-link i {
	color: #fff !important;
}

.theme-nms .navbar .nav-divider {
	border-top-color: var(--nms-hairline) !important;
}

/* The rail's own offcanvas must stay a plain wrapper from md up, where
   Bootstrap already makes it transparent. A backdrop-filter here would turn it
   into the containing block for the submenu flyout, and the markup's
   .overflow-auto would then clip the flyout out of existence. */
@media (min-width: 768px) {
	.theme-nms .navbar .offcanvas {
		background: transparent;
		backdrop-filter: none;
		-webkit-backdrop-filter: none;
		border: 0;
		box-shadow: none;
	}
}

/* From md up the submenu is a full-height flyout pinned to the rail: chrome
   rather than a floating menu, so it is square, fully opaque, and cannot let
   the pinned filter panel underneath ghost through it. */
@media (min-width: 768px) {
	.theme-nms .navbar .offcanvas .navbar-nav .nav-item.dropdown .dropdown-menu {
		background: var(--nms-sheet);
		backdrop-filter: none;
		-webkit-backdrop-filter: none;
		border: 0;
		border-right: 1px solid var(--nms-hairline);
		border-radius: 0;
		box-shadow: 8px 0 32px rgba(12, 50, 85, 0.10);
		padding: var(--bs-dropdown-padding-y) var(--bs-dropdown-padding-x);
	}
}

/* Below md the submenu is an inline list inside the rail, not a flyout —
   it has to stay flat instead of turning into a floating sheet. */
@media (max-width: 767.98px) {
	.theme-nms .navbar .dropdown-menu {
		background: transparent;
		backdrop-filter: none;
		-webkit-backdrop-filter: none;
		border: 0;
		border-radius: 0;
		box-shadow: none;
		padding: 0;
	}
}

/* The submenu's rows carry a nine-class block of their own in the base stylesheet, so the
   app-wide dropdown states never reach them and they answered with flat greys — white on
   hover, --bs-light for the current dashboard. These are the filter tree's two fills
   again; the rail's submenu is the same kind of list as the tree and the conversation
   history, so it reads like them. Forced rather than out-specified, as the rest of this
   section already is. */
.theme-nms .navbar .dropdown-menu .dropdown-item.active {
	background: rgba(25, 100, 170, 0.09) !important;
	color: var(--nms-blue-deep) !important;
	font-weight: 600;
}

.theme-nms .navbar .dropdown-menu .dropdown-item:hover,
.theme-nms .navbar .dropdown-menu .dropdown-item:focus,
.theme-nms .navbar .dropdown-menu .dropdown-item.active:hover {
	background: rgba(0, 159, 227, 0.12) !important;
	color: var(--nms-blue) !important;
}


/* =============================================
   TOP BAR
   ============================================= */

/* The page scrolls underneath the fixed chrome, so nothing in it may paint over the
   bar — and a grid filter's calendar (z-index 999) or a select2 menu (1051) otherwise
   does. Isolating the scrolling column puts every such popup in its own stacking
   context; modals and offcanvases are moved to body-level containers outside it and
   still cover everything. */
.theme-nms .content-wrap {
	isolation: isolate;
}

/* Frost, not glass: the page scrolls underneath the top bar, so the backdrop blur is
   doing real work here and the fill has to be opaque enough that what passes behind
   never reads as text. */
.theme-nms .top-bar {
	background: var(--nms-glass-strong) !important;
	backdrop-filter: var(--nms-blur);
	-webkit-backdrop-filter: var(--nms-blur);
	border-bottom: 1px solid var(--nms-hairline) !important;
	box-shadow: var(--nms-sheen), 0 1px 12px rgba(12, 50, 85, 0.05);
}

/* The filters offcanvas is rendered inside the top bar and only moved into
   .offcanvas-container once the JS runs. A backdrop-filter is a containing block for
   position: fixed, so while the panel is still in here it would be laid out against the
   top bar — which starts one nav rail in — and the pinned panel would paint a rail's
   width too far right until the move snapped it back. :has() drops the blur for exactly
   that window and restores it the moment the panel leaves. */
.theme-nms .top-bar:has(.offcanvas) {
	backdrop-filter: none;
	-webkit-backdrop-filter: none;
}


/* =============================================
   SIDEBAR
   ============================================= */

/* The layout reserves the rail's width, so nothing ever passes behind the side column —
   it can take the glass. */
.theme-nms .sidebar,
.theme-nms .tina-sidebar {
	background-color: var(--nms-panel) !important;
	background-image: var(--nms-gloss);
	backdrop-filter: none;
	-webkit-backdrop-filter: none;
	border-right: 0;
	box-shadow: var(--nms-sheen), 1px 0 0 0 var(--nms-hairline) !important;
}

.theme-nms .sidebar .nav-link {
	color: var(--nms-text-muted);
	border-radius: var(--nms-r-sm);
	transition: var(--transition-150);
}

.theme-nms .sidebar .nav-link:hover {
	color: var(--nms-blue);
	background: rgba(0, 159, 227, 0.10);
}

.theme-nms .sidebar .nav-link.active {
	color: var(--nms-blue-deep);
	background: var(--nms-blue-soft);
	font-weight: 600;
	box-shadow: inset 3px 0 0 0 var(--nms-cyan);
}


/* =============================================
   CARDS — floating glass panels
   ============================================= */

.theme-nms .card {
	/* The base stylesheet rounds a card's first and last child with
	   --bs-card-border-radius, so that variable must match the card's own radius —
	   otherwise every child carrying a fill (a .card-body, a grid wrapper, a loading
	   skeleton) pokes square corners out through the parent's rounding. */
	--bs-card-border-radius: var(--nms-r-lg);
	--bs-card-inner-border-radius: var(--nms-r-lg);
	background-color: var(--nms-panel);
	background-image: var(--nms-gloss);
	border: 1px solid var(--nms-glass-border);
	border-radius: var(--nms-r-lg);
	box-shadow: var(--nms-sheen), 0 0 0 1px var(--nms-hairline), var(--nms-shadow);
	transition: box-shadow 260ms var(--nms-ease-out), transform 260ms var(--nms-ease-out);
}

/* The glass makes every card a stacking context, which traps a menu opened
   inside one underneath the cards that follow it in the grid. Lift the card
   for as long as it holds an open overlay. */
.theme-nms .card:has(.dropdown-menu.show) {
	z-index: 3;
}

.theme-nms .card:hover {
	box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.9), 0 0 0 1px rgba(0, 159, 227, 0.35), var(--nms-shadow-lg);
}

/* The lift is a click affordance, so it is left to the cards that are one clickable
   object: the project tiles. A dashboard component is content read under a moving
   pointer, and there the movement is noise rather than an invitation — those answer
   the pointer with the ring above and stay put. */
.theme-nms .page-selectProject .card:hover {
	transform: translateY(-2px);
}

.theme-nms .card-header {
	background: linear-gradient(180deg, rgba(255, 255, 255, 0.85), rgba(255, 255, 255, 0));
	border-bottom: 1px solid var(--nms-hairline);
	font-family: var(--nms-font-head);
	font-weight: 600;
	color: var(--nms-blue-deep);
}

.theme-nms .card-footer {
	background: linear-gradient(0deg, rgba(232, 239, 247, 0.55), rgba(255, 255, 255, 0));
	border-top: 1px solid var(--nms-hairline);
}

.theme-nms .card-title {
	font-family: var(--nms-font-head);
	font-weight: 600;
	color: var(--nms-blue-deep);
}

/* Dashboard section header — a label strip, not a panel */
.theme-nms .card.db-section-header {
	background: transparent;
	border: 0;
	box-shadow: none;
}

.theme-nms .card.db-section-header:hover {
	box-shadow: none;
}

/* A grid is routinely wider than the card holding it, because the app scrolls the page
   rather than the card: the card's box stops at the viewport while the table runs on
   past it. So the table, not the card, is the panel here — it is the only box that spans
   the whole grid. Two translucent surfaces stacked would also read as two: over the card
   the whites multiply and past its right edge only one is left, which drew a seam down
   the rows exactly where the card ended. The card keeps its box for the header and the
   footer and paints nothing of its own. */
.theme-nms .card:has(.datagrid) {
	background: transparent;
	border-color: transparent;
	box-shadow: none;
}

.theme-nms .card:has(.datagrid):hover {
	box-shadow: none;
}

.theme-nms .card:has(.datagrid) > .card-body {
	background: transparent;
}

.theme-nms .card:has(.datagrid) > .card-header {
	background-color: var(--nms-panel);
	background-image: var(--nms-gloss);
	border-radius: var(--nms-r-lg) var(--nms-r-lg) 0 0;
	box-shadow: var(--nms-sheen), 0 0 0 1px var(--nms-hairline);
}

.theme-nms .datagrid table:not(.item-detail-content) {
	background-color: var(--nms-panel);
	background-image: var(--nms-gloss);
	border-radius: var(--nms-r-lg);
	box-shadow: var(--nms-sheen), 0 0 0 1px var(--nms-hairline), var(--nms-shadow);
}

/* With a header above it the table is no longer the top of the panel. */
.theme-nms .card:has(> .card-header) .datagrid table:not(.item-detail-content) {
	border-start-start-radius: 0;
	border-start-end-radius: 0;
}

/* Nothing here can clip — a grid filter opens its calendar inline, inside the table —
   so a tinted header band would square off the panel's rounded top corners. The header
   is carried by weight and a rule instead of a fill. */
.theme-nms .datagrid table thead tr:not(.row-group-actions) th,
.theme-nms .datagrid table thead tr:not(.row-group-actions) td {
	background: transparent !important;
}

.theme-nms .datagrid table thead tr:not(.row-group-actions):last-child > * {
	border-bottom: 2px solid var(--nms-hairline-strong) !important;
}

.theme-nms .bg-white,
.theme-nms .bg-body,
.theme-nms .bg-light {
	background-color: var(--nms-glass-strong) !important;
}

.theme-nms .bg-body-secondary,
.theme-nms .bg-body-tertiary {
	background-color: rgba(232, 239, 247, 0.65) !important;
}


/* =============================================
   BUTTONS — glossy brand, glass secondaries
   ============================================= */

.theme-nms .btn {
	--bs-btn-border-radius: var(--nms-r-sm);
	font-family: var(--nms-font-head);
	font-weight: 500;
	transition: background 200ms var(--nms-ease), color 200ms var(--nms-ease),
		box-shadow 200ms var(--nms-ease), transform 120ms var(--nms-ease);
}

.theme-nms .btn:active:not(:disabled) {
	transform: translateY(1px);
}

/* Primary — the only fully saturated control; gradient + top sheen + glow,
   with a light sweep on hover (same idiom as the app's .animate-shine) */
.theme-nms .btn-primary,
.theme-nms .btn-accent,
.theme-nms .btn-danger,
.theme-nms .btn-success,
.theme-nms .btn-info,
.theme-nms .btn-warning {
	overflow: hidden;
	border-color: transparent;
	box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.28), var(--nms-shadow-sm);
}

.theme-nms .btn-primary::after,
.theme-nms .btn-accent::after,
.theme-nms .btn-danger::after,
.theme-nms .btn-success::after {
	content: '';
	position: absolute;
	top: 0;
	left: -75%;
	width: 50%;
	height: 100%;
	background: linear-gradient(120deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.45) 50%, rgba(255, 255, 255, 0) 100%);
	transform: skewX(-20deg);
	pointer-events: none;
	opacity: 0;
}

.theme-nms .btn-primary:hover:not(:disabled)::after,
.theme-nms .btn-accent:hover:not(:disabled)::after,
.theme-nms .btn-danger:hover:not(:disabled)::after,
.theme-nms .btn-success:hover:not(:disabled)::after {
	animation: nms-btn-shine 800ms var(--nms-ease-out);
}

@keyframes nms-btn-shine {
	0% {
		left: -75%;
		opacity: 1;
	}
	100% {
		left: 125%;
		opacity: 1;
	}
}

.theme-nms .btn-primary {
	--bs-btn-bg: var(--nms-blue);
	--bs-btn-border-color: transparent;
	--bs-btn-hover-bg: var(--nms-blue-mid);
	--bs-btn-hover-border-color: transparent;
	--bs-btn-active-bg: var(--nms-blue-mid);
	background-image: var(--nms-brand);
}

.theme-nms .btn-primary:hover:not(:disabled) {
	background-image: var(--nms-brand-hover);
	box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.28), var(--nms-glow);
}

.theme-nms .btn-accent {
	background-image: linear-gradient(135deg, #F2A24E 0%, var(--nms-amber) 70%);
}

.theme-nms .btn-accent:hover:not(:disabled) {
	box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.28), 0 6px 20px rgba(232, 133, 46, 0.32);
}

.theme-nms .btn-danger {
	background-image: linear-gradient(135deg, #E23B3B 0%, var(--nms-red) 70%);
}

.theme-nms .btn-danger:hover:not(:disabled) {
	box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.28), 0 6px 20px rgba(208, 0, 0, 0.30);
}

.theme-nms .btn-success {
	background-image: linear-gradient(135deg, #85CB56 0%, var(--nms-green) 70%);
}

.theme-nms .btn-success:hover:not(:disabled) {
	box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.28), 0 6px 20px rgba(102, 181, 54, 0.30);
}

.theme-nms .btn-info {
	background-image: linear-gradient(135deg, #46BEED 0%, var(--nms-cyan) 70%);
	--bs-btn-color: #fff;
	--bs-btn-hover-color: #fff;
}

.theme-nms .btn-warning {
	background-image: linear-gradient(135deg, #FECD70 0%, #FDB833 70%);
}

/* Outline — a hairline chip that fills on hover. The theme repaints the resting fill,
   so each variant also has to claim its hover/active colours: Bootstrap's defaults put
   white text on them, which on this near-white fill made the label vanish the moment a
   button went active (the period pill in the top bar). */
/* Only the resting state is repainted — an unqualified `background` here would also win
   over Bootstrap's hover and active fills and leave the button white in every state. */
.theme-nms .btn-outline-primary:not(:hover):not(:active):not(.active):not(.show),
.theme-nms .btn-outline-accent:not(:hover):not(:active):not(.active):not(.show),
.theme-nms .btn-outline-danger:not(:hover):not(:active):not(.active):not(.show),
.theme-nms .btn-outline-success:not(:hover):not(:active):not(.active):not(.show),
.theme-nms .btn-outline-info:not(:hover):not(:active):not(.active):not(.show),
.theme-nms .btn-outline-warning:not(:hover):not(:active):not(.active):not(.show),
.theme-nms .btn-outline-light:not(:hover):not(:active):not(.active):not(.show) {
	background: rgba(255, 255, 255, 0.55);
}

.theme-nms .btn-outline-accent {
	--bs-btn-color: #A85C13;
	--bs-btn-border-color: rgba(232, 133, 46, 0.45);
	--bs-btn-hover-bg: var(--nms-amber);
	--bs-btn-hover-border-color: var(--nms-amber);
	--bs-btn-hover-color: #fff;
	--bs-btn-active-bg: var(--nms-amber);
	--bs-btn-active-border-color: var(--nms-amber);
	--bs-btn-active-color: #fff;
}

.theme-nms .btn-outline-danger {
	--bs-btn-color: var(--nms-red);
	--bs-btn-border-color: rgba(208, 0, 0, 0.40);
	--bs-btn-hover-bg: var(--nms-red);
	--bs-btn-hover-color: #fff;
	--bs-btn-active-bg: var(--nms-red);
	--bs-btn-active-color: #fff;
}

.theme-nms .btn-outline-success {
	--bs-btn-color: #4E8F27;
	--bs-btn-border-color: rgba(102, 181, 54, 0.45);
	--bs-btn-hover-bg: var(--nms-green);
	--bs-btn-hover-color: #fff;
	--bs-btn-active-bg: var(--nms-green);
	--bs-btn-active-color: #fff;
}

.theme-nms .btn-outline-info {
	--bs-btn-color: #006F9F;
	--bs-btn-border-color: rgba(0, 159, 227, 0.40);
	--bs-btn-hover-bg: var(--nms-cyan);
	--bs-btn-hover-color: #fff;
	--bs-btn-active-bg: var(--nms-cyan);
	--bs-btn-active-color: #fff;
}

.theme-nms .btn-outline-warning {
	--bs-btn-color: #8A631B;
	--bs-btn-border-color: rgba(253, 184, 51, 0.55);
	--bs-btn-hover-bg: #FDB833;
	--bs-btn-hover-color: #6B4B10;
	--bs-btn-active-bg: #FDB833;
	--bs-btn-active-color: #6B4B10;
}

.theme-nms .btn-outline-primary {
	--bs-btn-color: var(--nms-blue);
	--bs-btn-border-color: rgba(25, 100, 170, 0.35);
	--bs-btn-hover-bg: var(--nms-blue);
	--bs-btn-hover-border-color: var(--nms-blue);
	--bs-btn-hover-color: #fff;
	--bs-btn-active-bg: var(--nms-blue);
	--bs-btn-active-border-color: var(--nms-blue);
	--bs-btn-active-color: #fff;
}

.theme-nms .btn-outline-primary:hover:not(:disabled) {
	box-shadow: var(--nms-glow);
}

.theme-nms .btn-outline-light {
	--bs-btn-color: var(--nms-text-muted);
	--bs-btn-border-color: var(--nms-hairline-strong);
	--bs-btn-hover-bg: var(--nms-blue-soft);
	--bs-btn-hover-color: var(--nms-blue-deep);
	--bs-btn-hover-border-color: rgba(25, 100, 170, 0.28);
}

/* Flat is the app's quiet default, and it is used mostly for icon chips packed into
   filter trees, grid rows and toolbars. Painting each one as a bordered white tile
   turned those rows into a grid of little boxes, so the affordance is carried entirely
   by the hover fill — which is also what keeps the blue from looking arbitrary: exactly
   one control style is saturated, and this is not it. */
.theme-nms .btn-flat-primary,
.theme-nms .btn-flat-secondary,
.theme-nms .btn-flat-success,
.theme-nms .btn-flat-warning,
.theme-nms .btn-flat-danger,
.theme-nms .btn-flat-info {
	--bs-btn-bg: transparent;
	--bs-btn-border-color: transparent;
	--bs-btn-hover-border-color: transparent;
	--bs-btn-active-border-color: transparent;
	--bs-btn-disabled-bg: transparent;
	--bs-btn-disabled-border-color: transparent;
	box-shadow: none;
}

.theme-nms .btn-flat-primary {
	--bs-btn-color: var(--nms-blue);
	--bs-btn-hover-color: var(--nms-blue-deep);
	--bs-btn-hover-bg: var(--nms-blue-soft);
	--bs-btn-active-color: var(--nms-blue-deep);
	--bs-btn-active-bg: var(--nms-blue-soft);
}

.theme-nms .btn-flat-secondary {
	--bs-btn-color: var(--nms-text-muted);
	--bs-btn-hover-color: var(--nms-blue);
	--bs-btn-hover-bg: rgba(0, 159, 227, 0.10);
}

.theme-nms .btn-flat-success {
	--bs-btn-color: #4E8F27;
	--bs-btn-hover-color: #3E7320;
	--bs-btn-hover-bg: rgba(102, 181, 54, 0.14);
}

.theme-nms .btn-flat-warning {
	--bs-btn-color: #B18124;
	--bs-btn-hover-color: #8A631B;
	--bs-btn-hover-bg: rgba(253, 184, 51, 0.18);
}

.theme-nms .btn-flat-danger {
	--bs-btn-color: var(--nms-red);
	--bs-btn-hover-color: #920000;
	--bs-btn-hover-bg: rgba(208, 0, 0, 0.10);
}

/* Secondary — the base theme paints it solid grey, which reads as a dead
   block next to the glass chrome; make it a quiet glass chip instead */
.theme-nms .btn-secondary {
	--bs-btn-bg: rgba(255, 255, 255, 0.62);
	--bs-btn-border-color: var(--nms-hairline-strong);
	--bs-btn-color: var(--nms-text-muted);
	--bs-btn-hover-bg: var(--nms-blue-soft);
	--bs-btn-hover-border-color: rgba(25, 100, 170, 0.28);
	--bs-btn-hover-color: var(--nms-blue-deep);
	--bs-btn-active-bg: var(--nms-blue-soft);
	--bs-btn-active-border-color: rgba(25, 100, 170, 0.28);
	--bs-btn-active-color: var(--nms-blue-deep);
	--bs-btn-disabled-bg: rgba(255, 255, 255, 0.4);
	--bs-btn-disabled-color: var(--nms-text-subtle);
	--bs-btn-disabled-border-color: var(--nms-hairline);
	box-shadow: var(--nms-sheen), var(--nms-shadow-sm);
}

.theme-nms .btn-outline-secondary {
	--bs-btn-color: var(--nms-text-muted);
	--bs-btn-border-color: var(--nms-hairline-strong);
	--bs-btn-hover-bg: var(--nms-blue);
	--bs-btn-hover-border-color: var(--nms-blue);
	--bs-btn-hover-color: #fff;
}

.theme-nms .btn-link {
	--bs-btn-color: var(--nms-blue);
	--bs-btn-hover-color: var(--nms-cyan);
	text-decoration: none;
}

/* The base sets --bs-btn-disabled-opacity: 0.3. On a saturated gradient that leaves
   white text on a washed-out blue; on a flat button it multiplies with the variant's
   own rgba(0,0,0,.5) label down to roughly 15% alpha — a ghost. Nothing fades out;
   disabled is expressed by a muted colour at full opacity. */
.theme-nms .btn:disabled,
.theme-nms .btn.disabled,
.theme-nms fieldset:disabled .btn {
	--bs-btn-disabled-opacity: 1;
	--bs-btn-disabled-color: var(--nms-text-subtle);
}

.theme-nms .btn-primary:disabled,
.theme-nms .btn-accent:disabled,
.theme-nms .btn-danger:disabled,
.theme-nms .btn-success:disabled,
.theme-nms .btn-info:disabled,
.theme-nms .btn-warning:disabled,
.theme-nms .btn-primary.disabled,
.theme-nms .btn-accent.disabled,
.theme-nms .btn-danger.disabled,
.theme-nms .btn-success.disabled,
.theme-nms .btn-info.disabled,
.theme-nms .btn-warning.disabled {
	--bs-btn-disabled-opacity: 1;
	--bs-btn-disabled-bg: var(--nms-blue-soft);
	--bs-btn-disabled-color: var(--nms-text-subtle);
	--bs-btn-disabled-border-color: transparent;
	background-image: none;
	box-shadow: inset 0 0 0 1px var(--nms-hairline);
}

.theme-nms .btn:disabled,
.theme-nms .btn.disabled {
	box-shadow: none;
	cursor: not-allowed;
}

/* A .btn carrying a background utility instead of a variant class keeps --bs-btn-color,
   i.e. body text — dark navy on solid red for "Delete project". The utility decides the
   fill, so it has to decide the label too. */
.theme-nms .btn.bg-primary,
.theme-nms .btn.bg-danger,
.theme-nms .btn.bg-success,
.theme-nms .btn.bg-info,
.theme-nms .btn.bg-dark,
.theme-nms .btn.bg-secondary {
	--bs-btn-color: #fff;
	--bs-btn-hover-color: #fff;
	--bs-btn-active-color: #fff;
	color: #fff;
}

.theme-nms .btn.bg-warning,
.theme-nms .btn.bg-light {
	--bs-btn-color: var(--nms-text);
	--bs-btn-hover-color: var(--nms-text);
	--bs-btn-active-color: var(--nms-text);
	color: var(--nms-text);
}

.theme-nms .btn:focus-visible {
	box-shadow: 0 0 0 3px rgba(0, 159, 227, 0.30) !important;
	outline: none;
}


/* =============================================
   FORMS — translucent inputs with a cyan focus ring
   ============================================= */

.theme-nms .form-label {
	font-family: var(--nms-font-head);
	font-weight: 600;
	color: var(--nms-text-muted);
}

/* The app leaves every control to its own metrics — a .form-control lands at 27px, a
   native .form-select at 38px, a select2 at 28px — so a form stacks three different
   heights. One height for the default size; the grid's .form-control-sm row keeps its
   own smaller one. */
.theme-nms .form-control:not(.form-control-sm),
.theme-nms .form-select:not(.form-select-sm),
.theme-nms .select2:not(.select2-container--focus),
.theme-nms input[type="search"]:not(.form-control-sm) {
	min-height: 34px;
}

/* A native <select> is intrinsically taller than that, and min-height cannot shrink it,
   so it needs the height stated outright. Multi-line selects keep their own. */
.theme-nms select.form-select:not(.form-select-sm):not([multiple]):not([size]),
.theme-nms select.form-control:not(.form-control-sm):not([multiple]):not([size]) {
	height: 34px;
	padding-block: 0.25rem;
}

.theme-nms .datagrid .form-control:not(.form-control-sm),
.theme-nms .datagrid .form-select:not(.form-select-sm),
.theme-nms .datagrid .select2 {
	min-height: 31px;
}

.theme-nms .datagrid select.form-select:not([multiple]):not([size]),
.theme-nms .datagrid select.form-control:not([multiple]):not([size]) {
	height: 31px;
}

.theme-nms .form-control,
.theme-nms .form-select,
.theme-nms input[type="search"] {
	background-color: rgba(255, 255, 255, 0.72);
	border: 1px solid var(--nms-hairline-strong);
	border-radius: var(--nms-r-sm);
	color: var(--nms-text);
	transition: border-color 180ms var(--nms-ease), box-shadow 180ms var(--nms-ease),
		background-color 180ms var(--nms-ease);
}

.theme-nms .input-group-text {
	background: rgba(232, 239, 247, 0.72);
	border: 1px solid var(--nms-hairline-strong);
	color: var(--nms-text-muted);
	font-family: var(--nms-font-head);
	font-weight: 500;
}

.theme-nms .form-control::placeholder {
	color: var(--nms-text-subtle);
}

.theme-nms .form-control:focus,
.theme-nms .form-select:focus,
.theme-nms input[type="search"]:focus {
	background-color: rgba(255, 255, 255, 0.95);
	border-color: var(--nms-cyan);
	box-shadow: 0 0 0 3px rgba(0, 159, 227, 0.22);
}

.theme-nms .form-control:disabled,
.theme-nms .form-select:disabled {
	background-color: rgba(232, 239, 247, 0.6);
	color: var(--nms-text-subtle);
}

/* The base stylesheet pulls the button flush with the field's border. Here it is a
   chip rather than a flush block, so it sits inside the field's own padding. */
.theme-nms .form-control::file-selector-button,
.theme-nms .form-control::-webkit-file-upload-button {
	margin: 0 0.625rem 0 0;
	padding: 0.25rem 0.625rem;
	background: var(--nms-blue-soft);
	color: var(--nms-blue-deep);
	border: 0;
	border-radius: var(--nms-r-sm);
	font-family: var(--nms-font-head);
	font-weight: 500;
	cursor: pointer;
}

.theme-nms .form-control:hover::file-selector-button {
	background: rgba(25, 100, 170, 0.16);
}

.theme-nms .form-check-input:checked {
	background-color: var(--nms-blue);
	border-color: var(--nms-blue);
	box-shadow: 0 2px 8px rgba(25, 100, 170, 0.28);
}

.theme-nms .form-check-input:focus {
	border-color: var(--nms-cyan);
	box-shadow: 0 0 0 3px rgba(0, 159, 227, 0.22);
}


/* =============================================
   TABLES & DATAGRID
   Rows sit on glass, so row fills are tints rather than opaque greys —
   an opaque row would punch a hole in the panel.
   ============================================= */

.theme-nms .table {
	--bs-table-bg: transparent;
	--bs-table-color: var(--nms-text);
	--bs-table-border-color: var(--nms-hairline);
	--bs-table-hover-bg: rgba(0, 159, 227, 0.1);
	--bs-table-striped-bg: rgba(232, 239, 247, 0.45);
	--bs-table-accent-bg: transparent;
}

/* One header treatment for every table in the app. A tinted band cannot be used: a
   table is routinely flush with its panel's rounded top corners and the band would
   square them off, so the header is carried by weight and a rule. */
.theme-nms .table thead th {
	background: transparent !important;
	border-bottom: 2px solid var(--nms-hairline-strong) !important;
	font-family: var(--nms-font-head);
	font-weight: 600;
	color: var(--nms-blue-deep);
	letter-spacing: 0.01em;
}

.theme-nms .table thead th a,
.theme-nms .table thead th .column-header a:not(:hover) {
	color: var(--nms-blue-deep);
}

.theme-nms .table thead th a:hover {
	color: var(--nms-blue);
}

.theme-nms .table tbody tr td {
	border-bottom-color: var(--nms-hairline);
	background-color: transparent;
	transition: box-shadow 120ms var(--nms-ease);
}

/* Zeroing the row fill above also swallowed the app's row hover. Put it back as a faint
   brand wash — enough to follow a wide row across the screen, not enough to read as a
   selection. The base stylesheet paints row fills as an inset shadow over the cell
   background, so the hover is painted the same way: a background tint would land under
   the stripe and come out weaker on every other row. */
.theme-nms .table tbody tr:hover > td,
.theme-nms .table tbody tr:hover > th {
	box-shadow: inset 0 0 0 9999px var(--bs-table-hover-bg);
}

.theme-nms .table .item-detail-content,
.theme-nms .table .item-detail-content tr td {
	background: rgba(232, 239, 247, 0.5) !important;
}

.theme-nms .datagrid {
	background: transparent !important;
}

.theme-nms .datagrid table th.col-checkbox,
.theme-nms .datagrid .col-checkbox.col-checkbox-first {
	background: transparent !important;
}

.theme-nms .datagrid table thead tr.row-group-actions th {
	background: var(--nms-blue-soft) !important;
	color: var(--nms-blue-deep);
}

.theme-nms .datagrid .datagrid-row-columns-summary td {
	background: rgba(232, 239, 247, 0.7) !important;
	font-weight: 600;
	color: var(--nms-blue-deep);
}

.theme-nms .datagrid tfoot,
.theme-nms .datagrid tfoot .row-grid-bottom,
.theme-nms .datagrid .row-grid-bottom {
	background: transparent !important;
	border-top: 1px solid var(--nms-hairline);
}

/* Pagination */
.theme-nms .page-link {
	background: rgba(255, 255, 255, 0.55);
	border: 1px solid var(--nms-hairline);
	border-radius: var(--nms-r-sm);
	color: var(--nms-blue);
	margin: 0 2px;
	transition: var(--transition-150);
}

.theme-nms .page-link:hover {
	background: var(--nms-blue-soft);
	border-color: rgba(25, 100, 170, 0.28);
	color: var(--nms-blue-deep);
}

.theme-nms .page-item.active .page-link {
	background: var(--nms-brand);
	border-color: transparent;
	color: #fff;
	box-shadow: var(--nms-glow);
}

.theme-nms .page-item.disabled .page-link {
	background: transparent;
	border-color: var(--nms-hairline);
	color: var(--nms-text-subtle);
}


/* =============================================
   DROPDOWNS
   ============================================= */

/* A menu covers arbitrary live content, so it is opaque — the gloss is the light on it,
   not the page showing through it. */
.theme-nms .dropdown-menu {
	background-color: var(--nms-overlay);
	background-image: linear-gradient(180deg, rgba(232, 239, 247, 0.55), rgba(255, 255, 255, 0) 56px);
	border: 1px solid var(--nms-hairline-strong);
	border-radius: var(--nms-r);
	box-shadow: var(--nms-sheen), var(--nms-shadow-menu);
	padding: 0.35rem;
}

.theme-nms .dropdown-item {
	border-radius: var(--nms-r-sm);
	color: var(--nms-text);
	transition: background-color 150ms var(--nms-ease), color 150ms var(--nms-ease);
}

/* Same two state fills as the filter tree and the conversation history — these are all
   the same thing, a column of selectable rows, and the current item was the one place
   that answered with a saturated brand bar instead of a wash. */
.theme-nms .dropdown-item:hover,
.theme-nms .dropdown-item:focus {
	background: rgba(0, 159, 227, 0.12);
	color: var(--nms-blue);
}

.theme-nms .dropdown-item.active {
	background: rgba(25, 100, 170, 0.09);
	color: var(--nms-blue-deep);
	font-weight: 600;
}

.theme-nms .dropdown-item.active:hover,
.theme-nms .dropdown-item.active:focus {
	background: rgba(0, 159, 227, 0.12);
}

/* Pressed, not current: the one state that has to read through the finger. */
.theme-nms .dropdown-item:active {
	background: rgba(0, 159, 227, 0.22);
	color: var(--nms-blue-deep);
}

.theme-nms .dropdown-item-text,
.theme-nms .dropdown-header {
	color: var(--nms-text-muted);
	font-family: var(--nms-font-head);
}

.theme-nms .dropdown-divider {
	border-top-color: var(--nms-hairline);
}


/* =============================================
   MODAL & OFFCANVAS
   ============================================= */

.theme-nms .modal-content {
	background-color: var(--nms-sheet);
	background-image: var(--nms-gloss);
	border: 1px solid var(--nms-glass-border);
	border-radius: var(--nms-r-lg);
	box-shadow: var(--nms-sheen), var(--nms-shadow-lg), 0 0 0 1px var(--nms-hairline);
}

/* An offcanvas is solid in both states, and deliberately so. Floating, the app already
   blurs the whole page behind it, and a translucent panel smears that blur through
   itself instead of revealing the aurora. Pinned, it is a column the page keeps running
   underneath — a wide datagrid scrolls straight behind it — so glass here would mean
   table rows ghosting through the filter labels. */
.theme-nms .offcanvas {
	--bs-offcanvas-bg: var(--nms-sheet);
	--bs-offcanvas-border-color: var(--nms-hairline);
	background-color: var(--nms-sheet);
	background-image: var(--nms-gloss);
	backdrop-filter: none;
	-webkit-backdrop-filter: none;
	border: 0;
	border-radius: 0;
	box-shadow: var(--nms-sheen), var(--nms-shadow-lg);
}

/* Pinned it is chrome beside the content, not a sheet over it, so it drops the drop
   shadow for a hairline. */
@media (min-width: 768px) {
	.theme-nms .offcanvas.offcanvas-pinned {
		box-shadow: var(--nms-sheen), 1px 0 0 0 var(--nms-hairline), 8px 0 32px rgba(12, 50, 85, 0.04);
	}
}

.theme-nms .offcanvas-title {
	font-family: var(--nms-font-head);
	color: var(--nms-blue-deep);
}

.theme-nms .modal-header,
.theme-nms .offcanvas-header {
	border-bottom: 1px solid var(--nms-hairline);
	background: linear-gradient(180deg, rgba(255, 255, 255, 0.85), rgba(255, 255, 255, 0));
}


/* =============================================
   FILTER PANEL
   The one piece of chrome the app is used through all day, so it carries more of the
   theme than the rest: a brand-washed head, tinted group rows, and a reset strip the
   tree runs under rather than stops at.
   ============================================= */

.theme-nms .offcanvas:has(.Filter) .offcanvas-header {
	background: linear-gradient(135deg, rgba(0, 159, 227, 0.14), rgba(25, 100, 170, 0.06) 60%, rgba(255, 255, 255, 0));
	border-bottom: 1px solid var(--nms-hairline);
	box-shadow: var(--nms-sheen);
}

.theme-nms .offcanvas:has(.Filter) .offcanvas-title {
	letter-spacing: -0.01em;
}

/* The search field heads the tree, so it reads as part of the panel's chrome rather
   than as the first of the rows below it. */
.theme-nms .Filter .FilterItem-Search {
	background: linear-gradient(180deg, rgba(232, 239, 247, 0.5), rgba(255, 255, 255, 0));
	border-bottom-color: var(--nms-hairline) !important;
}

.theme-nms .Filter .FilterItem-Search input[type="search"] {
	background-color: var(--nms-surface);
	box-shadow: var(--nms-shadow-sm);
}

/* The tree's own two state fills — the base points them at a flat Bootstrap blue and a
   flat grey, which is the one place in the panel the palette drops out. */
.theme-nms .Filter .FilterItem {
	--filterItem-bg-opened: rgba(25, 100, 170, 0.09);
	--filterItem-bg-hover: rgba(0, 159, 227, 0.12);
}

.theme-nms .Filter .FilterItem > .item {
	border-radius: var(--nms-r-sm);
}

.theme-nms .Filter .FilterItem > .item > .item-label > label {
	font-family: var(--nms-font-head);
}

/* Frost, not fill: the strip floats over the scrolling tree, so the rows keep running
   under it — blurred and dimmed rather than cut off, which is the only way a panel this
   short still reads as having depth. */
.theme-nms .Filter .filter-reset {
	background: linear-gradient(180deg, rgba(246, 249, 253, 0.70), rgba(246, 249, 253, 0.93));
	backdrop-filter: var(--nms-blur);
	-webkit-backdrop-filter: var(--nms-blur);
	border-top: 1px solid var(--nms-hairline);
	box-shadow: 0 -8px 20px rgba(12, 50, 85, 0.05);
}

.theme-nms .modal-footer {
	border-color: var(--nms-hairline);
	background: linear-gradient(0deg, rgba(232, 239, 247, 0.55), rgba(255, 255, 255, 0));
}

.theme-nms .modal-title,
.theme-nms .modal-header h1,
.theme-nms .modal-header h2,
.theme-nms .modal-header h3,
.theme-nms .modal-header h4,
.theme-nms .modal-header h5 {
	font-family: var(--nms-font-head);
	font-weight: 600;
	color: var(--nms-blue-deep);
}

.theme-nms .modal-backdrop.show,
.theme-nms .offcanvas-backdrop.show {
	background: rgba(12, 50, 85, 0.35);
	opacity: 1;
}

/* A full-bleed strip introducing the rows below it. Rounding it, and hanging an inset
   accent off its left edge, detached it from that list and left a stray bar sticking
   out at the modal's edge. */
.theme-nms .modal-body-collapse-header {
	background: rgba(232, 239, 247, 0.55);
	border-radius: 0;
	border-bottom: 1px solid var(--nms-hairline);
	color: var(--nms-blue-deep);
	font-family: var(--nms-font-head);
	transition: background-color 180ms var(--nms-ease);
}

.theme-nms .modal-body-collapse-header:hover,
.theme-nms .modal-body-collapse-header:focus,
.theme-nms .modal-body-collapse-header[aria-expanded="true"] {
	background: var(--nms-blue-soft);
	box-shadow: none;
}


/* =============================================
   BADGES — glass pills
   ============================================= */

.theme-nms .badge {
	border-radius: var(--nms-r-pill);
	font-family: var(--nms-font-head);
	font-weight: 600;
	letter-spacing: 0.01em;
	/* With Bootstrap's line-height: 1 the font's own ascent/descent decide where
	   the baseline lands; Merriweather Sans leaves the cap band ~0.02em above the
	   pill's centre, so the padding is split to put it back. */
	padding-top: 0.37em;
	padding-bottom: 0.33em;
}

/* Saturated pills carry the gloss. The quiet ones must not — a white inner ring
   on a near-white pill only muddies its edge, so they get a hairline instead. */
.theme-nms .badge.bg-primary,
.theme-nms .badge.text-bg-primary,
.theme-nms .badge.bg-success,
.theme-nms .badge.text-bg-success,
.theme-nms .badge.bg-danger,
.theme-nms .badge.text-bg-danger,
.theme-nms .badge.bg-info,
.theme-nms .badge.text-bg-info,
.theme-nms .badge.bg-warning,
.theme-nms .badge.text-bg-warning,
.theme-nms .badge.bg-dark,
.theme-nms .badge.text-bg-dark {
	box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.3);
}

.theme-nms .badge.bg-primary,
.theme-nms .badge.text-bg-primary {
	background: var(--nms-brand) !important;
	color: #fff !important;
}

.theme-nms .badge.bg-success,
.theme-nms .badge.text-bg-success {
	background: linear-gradient(135deg, #85CB56, var(--nms-green)) !important;
	color: #fff !important;
}

.theme-nms .badge.bg-danger,
.theme-nms .badge.text-bg-danger {
	background: linear-gradient(135deg, #E23B3B, var(--nms-red)) !important;
	color: #fff !important;
}

.theme-nms .badge.bg-info,
.theme-nms .badge.text-bg-info {
	background: linear-gradient(135deg, #46BEED, var(--nms-cyan)) !important;
	color: #fff !important;
}

.theme-nms .badge.bg-warning,
.theme-nms .badge.text-bg-warning {
	background: linear-gradient(135deg, #FECD70, #FDB833) !important;
	color: #6B4B10 !important;
}

.theme-nms .badge.bg-dark,
.theme-nms .badge.text-bg-dark {
	background: linear-gradient(135deg, var(--nms-blue-mid), var(--nms-blue-deep)) !important;
	color: #fff !important;
}

/* Secondary is the app's default "no state" pill; the Bootstrap grey reads as a
   dead block against the palette, so it becomes a quiet brand chip. */
.theme-nms .badge.bg-secondary,
.theme-nms .badge.text-bg-secondary {
	background: var(--nms-blue-soft) !important;
	color: var(--nms-blue-deep) !important;
	box-shadow: inset 0 0 0 1px var(--nms-hairline-strong);
}

.theme-nms .badge.bg-light,
.theme-nms .badge.text-bg-light {
	background: rgba(255, 255, 255, 0.9) !important;
	color: var(--nms-text) !important;
	box-shadow: inset 0 0 0 1px var(--nms-hairline-strong);
}

.theme-nms .badge.bg-danger-subtle {
	background: rgba(208, 0, 0, 0.12) !important;
	color: #920000 !important;
}

.theme-nms .bg-primary-subtle {
	background-color: var(--nms-blue-soft) !important;
}

.theme-nms .bg-info-subtle {
	background-color: var(--nms-cyan-soft) !important;
}

.theme-nms .bg-success-subtle {
	background-color: rgba(102, 181, 54, 0.14) !important;
}

.theme-nms .bg-warning-subtle {
	background-color: rgba(253, 184, 51, 0.18) !important;
}

.theme-nms .bg-danger-subtle {
	background-color: rgba(208, 0, 0, 0.10) !important;
}

.theme-nms .bg-secondary-subtle {
	background-color: rgba(232, 239, 247, 0.75) !important;
}


/* =============================================
   ACTIVE FILTERS — period & filter pills
   ============================================= */

.theme-nms .active-filter:not(.active-filter-dummy) {
	background: var(--nms-glass-strong);
	backdrop-filter: blur(8px);
	-webkit-backdrop-filter: blur(8px);
	border: 1px solid rgba(25, 100, 170, 0.22);
	border-radius: var(--nms-r-pill);
	color: var(--nms-blue-deep);
	box-shadow: var(--nms-sheen), var(--nms-shadow-sm);
}

.theme-nms .active-filters-period .bg-secondary-subtle {
	background: linear-gradient(135deg, rgba(0, 159, 227, 0.16), rgba(25, 100, 170, 0.10)) !important;
	color: var(--nms-blue-deep) !important;
	border-radius: var(--nms-r-pill);
}

.theme-nms .filter-item {
	border-radius: var(--nms-r-sm);
	transition: background-color 180ms var(--nms-ease);
}

.theme-nms .filter-item:hover {
	background: rgba(0, 159, 227, 0.08);
}


/* =============================================
   ALERTS & TOASTS
   ============================================= */

/* The tints below are translucent by design, so the alert needs a solid base under them
   — without one the aurora shows straight through and a wide alert washes from its own
   colour on one side to grey on the other, dragging the text with it. */
.theme-nms .alert {
	background-color: var(--nms-sheet);
	border: 1px solid var(--nms-hairline);
	border-radius: var(--nms-r);
	box-shadow: var(--nms-sheen), var(--nms-shadow-sm);
}

.theme-nms .alert-info {
	background-image: linear-gradient(135deg, rgba(0, 159, 227, 0.16), rgba(0, 159, 227, 0.06));
	color: #005B82;
	border-left: 3px solid var(--nms-cyan);
}

.theme-nms .alert-success {
	background-image: linear-gradient(135deg, rgba(102, 181, 54, 0.18), rgba(102, 181, 54, 0.06));
	color: #3E7320;
	border-left: 3px solid var(--nms-green);
}

.theme-nms .alert-warning {
	background-image: linear-gradient(135deg, rgba(253, 184, 51, 0.22), rgba(253, 184, 51, 0.07));
	color: #8A631B;
	border-left: 3px solid #FDB833;
}

.theme-nms .alert-danger {
	background-image: linear-gradient(135deg, rgba(208, 0, 0, 0.14), rgba(208, 0, 0, 0.05));
	color: #920000;
	border-left: 3px solid var(--nms-red);
}


/* =============================================
   TABS & NAV PILLS
   ============================================= */

.theme-nms .nav-tabs {
	border-bottom-color: var(--nms-hairline);
}

.theme-nms .nav-tabs .nav-link {
	border: 0;
	border-radius: var(--nms-r-sm) var(--nms-r-sm) 0 0;
	color: var(--nms-text-muted);
	font-family: var(--nms-font-head);
	font-weight: 500;
	transition: var(--transition-150);
}

.theme-nms .nav-tabs .nav-link:hover {
	color: var(--nms-blue);
	background: rgba(0, 159, 227, 0.08);
}

.theme-nms .nav-tabs .nav-link.active {
	background: var(--nms-glass-strong);
	color: var(--nms-blue-deep);
	box-shadow: inset 0 -2px 0 0 var(--nms-cyan), var(--nms-sheen);
}

.theme-nms .nav-pills .nav-link {
	border-radius: var(--nms-r-pill);
	color: var(--nms-text-muted);
	font-family: var(--nms-font-head);
	transition: var(--transition-150);
}

.theme-nms .nav-pills .nav-link:hover {
	background: rgba(0, 159, 227, 0.10);
	color: var(--nms-blue);
}

.theme-nms .nav-pills .nav-link.active {
	background: var(--nms-brand);
	color: #fff;
	box-shadow: var(--nms-glow);
}


/* =============================================
   LIST GROUP
   ============================================= */

.theme-nms .list-group-item {
	background: transparent;
	border-color: var(--nms-hairline);
	color: var(--nms-text);
	transition: background-color 180ms var(--nms-ease);
}

.theme-nms .list-group-item:hover {
	background: rgba(0, 159, 227, 0.08);
}

.theme-nms .list-group-item.active {
	background: var(--nms-blue-soft);
	border-color: rgba(25, 100, 170, 0.22);
	color: var(--nms-blue-deep);
	box-shadow: inset 3px 0 0 0 var(--nms-cyan);
}


/* =============================================
   ACCORDION
   ============================================= */

.theme-nms .accordion-item {
	background: transparent;
	border-color: var(--nms-hairline);
	border-radius: var(--nms-r);
	overflow: hidden;
}

.theme-nms .accordion-button {
	background: rgba(255, 255, 255, 0.5);
	color: var(--nms-text);
	font-family: var(--nms-font-head);
	font-weight: 500;
	box-shadow: none;
}

.theme-nms .accordion-button:not(.collapsed) {
	background: var(--nms-blue-soft);
	color: var(--nms-blue-deep);
	box-shadow: inset 0 -1px 0 var(--nms-hairline);
}

.theme-nms .accordion-body {
	background: rgba(255, 255, 255, 0.35);
}


/* =============================================
   TOOLTIP & POPOVER
   ============================================= */

/* Set on .tooltip, not on .tooltip-inner: Bootstrap paints the arrow from
   --bs-tooltip-bg, so styling only the bubble left a black arrow on a navy bubble —
   and --bs-tooltip-color has to be stated because Bootstrap defaults it to
   --bs-body-bg. */
.theme-nms .tooltip {
	--bs-tooltip-bg: #143D64;
	--bs-tooltip-color: #FFFFFF;
	--bs-tooltip-opacity: 1;
}

.theme-nms .tooltip-inner {
	background: var(--bs-tooltip-bg);
	color: var(--bs-tooltip-color);
	border-radius: var(--nms-r-sm);
	box-shadow: var(--nms-shadow-menu);
	font-family: var(--nms-font-body);
	text-align: left;
}

.theme-nms .popover {
	background: var(--nms-overlay);
	border: 1px solid var(--nms-hairline-strong);
	border-radius: var(--nms-r);
	box-shadow: var(--nms-sheen), var(--nms-shadow-menu);
}

.theme-nms .popover-header {
	background: var(--nms-blue-soft);
	border-bottom-color: var(--nms-hairline);
	color: var(--nms-blue-deep);
	font-family: var(--nms-font-head);
}

.theme-nms .popover-body {
	color: var(--nms-text);
}


/* =============================================
   BREADCRUMB
   ============================================= */

.theme-nms .breadcrumb-item a {
	color: var(--nms-blue);
}

.theme-nms .breadcrumb-item a:hover {
	color: var(--nms-cyan);
}

.theme-nms .breadcrumb-item.active {
	color: var(--nms-text-muted);
}

.theme-nms .breadcrumb-item + .breadcrumb-item::before {
	color: var(--nms-text-subtle);
}

/* The base hangs a full-height rule off every crumb but the last. Against the frosted
   bar it reads as a stray tick, so it is shortened to a centred hairline. */
.theme-nms .breadcrumb li:not(:last-child) {
	position: relative;
	border-right-color: transparent !important;
}

.theme-nms .breadcrumb li:not(:last-child)::after {
	content: '';
	position: absolute;
	top: 50%;
	right: 0;
	width: 1px;
	height: 1.25rem;
	transform: translateY(-50%);
	background: linear-gradient(180deg, transparent, var(--nms-hairline-strong) 50%, transparent);
}


/* =============================================
   PROJECT SWITCHER
   A select2 living in the breadcrumb. The app-wide select2 chrome turns it into a form
   field parked in the middle of the top bar; here it is the bar's one interactive label,
   so it gets a glass pill instead. The chevron the base paints as a background image has
   to stay, which is why the gloss is carried by shadows rather than a gradient.
   ============================================= */

.theme-nms .projectSwitcher .select2 {
	background-color: rgba(255, 255, 255, 0.45) !important;
	border: 1px solid var(--nms-hairline) !important;
	border-radius: var(--nms-r-pill) !important;
	padding: 0.125rem 0.375rem 0.125rem 0.75rem !important;
	box-shadow: var(--nms-sheen), var(--nms-shadow-sm);
	transition: background-color 180ms var(--nms-ease), border-color 180ms var(--nms-ease),
		box-shadow 180ms var(--nms-ease);
}

.theme-nms .projectSwitcher .select2:hover {
	background-color: rgba(255, 255, 255, 0.85) !important;
	border-color: rgba(25, 100, 170, 0.28) !important;
	box-shadow: var(--nms-sheen), var(--nms-shadow);
}

.theme-nms .projectSwitcher .select2-container--open > .selection > .select2,
.theme-nms .projectSwitcher .select2:focus-within {
	background-color: rgba(255, 255, 255, 0.95) !important;
	border-color: var(--nms-cyan) !important;
	box-shadow: 0 0 0 3px rgba(0, 159, 227, 0.22);
}

.theme-nms .projectSwitcher .select2-selection__rendered,
.theme-nms .projectSwitcher .select2-container--default .select2-selection--single .select2-selection__placeholder {
	font-family: var(--nms-font-head);
	font-weight: 600;
	color: var(--nms-blue-deep);
}

/* select2 sizes the panel to the control, and the control is a pill holding one short
   project name — so a list of real names came out 125px wide with every second one broken
   over four lines. The panel is a menu, not a mirror of the pill. */
.theme-nms .projectSwitcher-dropdown.select2-dropdown {
	padding: 0.35rem;
	min-width: 17rem;
	max-width: min(26rem, calc(100vw - 2rem));
}


/* =============================================
   LOGIN PAGE — glass card on the aurora
   ============================================= */

.theme-nms.sign-in {
	background: transparent !important;
}

.theme-nms.sign-in .container-fluid {
	background: var(--nms-glass-strong) !important;
	backdrop-filter: var(--nms-blur);
	-webkit-backdrop-filter: var(--nms-blur);
	box-shadow: var(--nms-sheen), var(--nms-shadow-lg);
	overflow: hidden;
}

/* A faint brand grid behind the form — reads as texture, not decoration */
.theme-nms.sign-in .container-fluid::before {
	content: '';
	position: absolute;
	inset: 0;
	pointer-events: none;
	background-image:
		linear-gradient(rgba(25, 100, 170, 0.04) 1px, transparent 1px),
		linear-gradient(90deg, rgba(25, 100, 170, 0.04) 1px, transparent 1px);
	background-size: 44px 44px;
	mask-image: radial-gradient(70% 70% at 50% 45%, #000 0%, transparent 100%);
	-webkit-mask-image: radial-gradient(70% 70% at 50% 45%, #000 0%, transparent 100%);
}

/* The side strip is the one saturated surface: a slow brand gradient sweep */
.theme-nms.sign-in .theme-illustration {
	position: relative;
	background: linear-gradient(160deg, var(--nms-cyan) 0%, var(--nms-blue) 55%, var(--nms-blue-deep) 100%);
	background-size: 100% 200%;
	animation: nms-strip-drift 18s ease-in-out infinite alternate;
	overflow: hidden;
}

@keyframes nms-strip-drift {
	from {
		background-position: 0 0;
	}
	to {
		background-position: 0 100%;
	}
}

.theme-nms.sign-in .theme-illustration::before {
	content: '';
	position: absolute;
	inset: 0;
	background: radial-gradient(60% 30% at 50% 0%, rgba(255, 255, 255, 0.35), transparent 70%);
}

.theme-nms.sign-in .theme-illustration::after {
	content: '';
	position: absolute;
	inset: 0;
	background-image: repeating-linear-gradient(115deg, rgba(255, 255, 255, 0.10) 0 1px, transparent 1px 22px);
}

/* The base login styles ask for Barlow Condensed, which the app never loads —
   point the heading at the theme's own display face instead */
.theme-nms.sign-in h1 {
	font-family: var(--nms-font-head);
	font-weight: 300;
	color: var(--nms-blue-deep);
	letter-spacing: -0.02em;
}

.theme-nms.sign-in label {
	font-family: var(--nms-font-head);
	font-weight: 600;
	color: var(--nms-text-muted);
}

.theme-nms.sign-in .form-control {
	background: rgba(255, 255, 255, 0.8);
	border: 1px solid var(--nms-hairline-strong);
	border-radius: var(--nms-r-sm) !important;
}

.theme-nms.sign-in .form-control:focus {
	border-color: var(--nms-cyan);
	box-shadow: 0 0 0 3px rgba(0, 159, 227, 0.22);
}

.theme-nms.sign-in form {
	position: relative;
	z-index: 1;
}

/* The copyright line carries .text-secondary (#ADB5BD) on the markup, which wins over a
   plain colour here and leaves it at roughly 2:1 against the field. */
.theme-nms footer,
.theme-nms footer .text-secondary {
	color: var(--nms-text-muted) !important;
}


/* =============================================
   TINA CHAT / AI ASSISTANT
   ============================================= */

.theme-nms .page-tina {
	background: transparent;
}

/* Conversation history. It is the same thing as the filter tree — a column of selectable
   rows in a side panel — so it takes that tree's two state fills and its row inset
   (.FilterItem > .item is px-2 py-1 rounded) instead of a scheme of its own. The active
   row keeps the weight and the deeper text as its own marker; the accent bar the tree
   has no counterpart for was what made the two columns read as unrelated widgets. */
.theme-nms .tina-sidebar .nav-link {
	border-radius: var(--nms-r-sm);
	padding-inline: 0.5rem;
	color: var(--nms-text-muted);
	transition: var(--transition-150);
}

.theme-nms .tina-sidebar .nav-link:hover,
.theme-nms .tina-sidebar .nav-link:focus-visible,
.theme-nms .tina-sidebar .nav-link.active:hover {
	background: rgba(0, 159, 227, 0.12);
	color: var(--nms-blue);
}

/* The element is .sidebar.tina-sidebar, so the rail's own active row wins the accent bar
   at equal specificity unless it is cleared here. */
.theme-nms .tina-sidebar .nav-link.active {
	background: rgba(25, 100, 170, 0.09);
	color: var(--nms-blue-deep);
	font-weight: 600;
	box-shadow: none;
}

/* Assistant bubble — a glass sheet; user bubble — the brand fill */
.theme-nms .tina-message-container .tina-message {
	background-color: var(--nms-panel);
	background-image: var(--nms-gloss);
	border: 1px solid var(--nms-glass-border);
	border-radius: var(--nms-r-lg);
	box-shadow: var(--nms-sheen), 0 0 0 1px var(--nms-hairline), var(--nms-shadow-sm);
	color: var(--nms-text);
}

.theme-nms .tina-message-container.user .tina-message {
	background: var(--nms-brand);
	border-color: transparent;
	color: #fff;
	box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), var(--nms-glow);
}

/* The user's avatar holds a white icon, so it needs the saturated fill; the assistant's
   holds dark initials and needs the quiet one. The two were the wrong way round, which
   left a white glyph on a white disc. */
.theme-nms .tina-message-container .avatar {
	background: var(--nms-blue-soft);
	color: var(--nms-blue-deep);
	box-shadow: inset 0 0 0 1px var(--nms-hairline-strong);
	font-family: var(--nms-font-head);
	font-weight: 600;
}

.theme-nms .tina-message-container.user .avatar {
	background: var(--nms-brand);
	color: #fff;
	box-shadow: none;
}

/* .tina-input-container is two different components sharing one class: the centred
   intro column (avatar + greeting + suggestions + composer) and the docked composer of
   a running conversation. Panel chrome belongs only to the second — on the intro it
   inflated into a full-height empty slab around the greeting. */
.theme-nms .tina-input-container {
	background: linear-gradient(180deg, rgba(255, 255, 255, 0.55), rgba(255, 255, 255, 0.88));
	backdrop-filter: var(--nms-blur);
	-webkit-backdrop-filter: var(--nms-blur);
	border: 0;
	border-top: 1px solid var(--nms-hairline);
	border-radius: 0;
	box-shadow: 0 -10px 24px rgba(12, 50, 85, 0.06);
}

/* Keep the composer on the message column's measure instead of stretching it to the
   window edges. */
.theme-nms .tina-input-container > .w-100 {
	max-width: var(--tina-wrapper-max-width);
	margin-inline: auto;
}

.theme-nms .tina-input-container:has(.tina-intro-message) {
	background: transparent;
	backdrop-filter: none;
	-webkit-backdrop-filter: none;
	border: 0;
	box-shadow: none;
}

/* The composer is one control, not a field with a button parked beside it: the row that
   holds the textarea and the send button takes the field chrome, and the textarea inside
   it goes bare. Matched on the row's shape rather than on a utility class, because that
   row is the only child of the composer that holds a textarea. */
.theme-nms .tina-input-container textarea.form-control,
.theme-nms .tina-input-container > .w-100 > div:has(> textarea.form-control) {
	background-color: rgba(255, 255, 255, 0.82);
	border: 1px solid var(--nms-hairline-strong);
	border-radius: var(--nms-r-lg);
	color: var(--nms-text);
	box-shadow: var(--nms-sheen), var(--nms-shadow);
	transition: border-color 180ms var(--nms-ease), box-shadow 180ms var(--nms-ease),
		background-color 180ms var(--nms-ease);
}

.theme-nms .tina-input-container > .w-100 > div:has(> textarea.form-control) {
	padding: 0.25rem 0.25rem 0.25rem 0.5rem;
	align-items: flex-end;
}

.theme-nms .tina-input-container > .w-100 > div:has(> textarea.form-control) textarea.form-control {
	background: transparent;
	border: 0;
	box-shadow: none;
	padding-block: 0.5rem;
}

.theme-nms .tina-input-container textarea.form-control:focus,
.theme-nms .tina-input-container > .w-100 > div:has(> textarea.form-control):focus-within {
	background-color: rgba(255, 255, 255, 0.96);
	border-color: var(--nms-cyan);
	box-shadow: var(--nms-sheen), 0 0 0 3px rgba(0, 159, 227, 0.22);
	outline: none;
}

.theme-nms .tina-input-container > .w-100 > div:has(> textarea.form-control) textarea.form-control:focus {
	background: transparent;
	box-shadow: none;
}

/* Send is the page's primary action and was a grey text link under the field. */
.theme-nms .tina-input-container .btn:has(> .bi-send) {
	--bs-btn-color: #fff;
	--bs-btn-hover-color: #fff;
	--bs-btn-active-color: #fff;
	--bs-btn-disabled-color: var(--nms-text-subtle);
	--bs-btn-disabled-opacity: 1;
	background-image: var(--nms-brand);
	border: 0;
	border-radius: var(--nms-r-pill);
	padding: 0.375rem 1rem;
	box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.28), var(--nms-shadow-sm);
}

.theme-nms .tina-input-container .btn:has(> .bi-send):hover:not(:disabled) {
	background-image: var(--nms-brand-hover);
	box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.28), var(--nms-glow);
}

.theme-nms .tina-input-container .btn:has(> .bi-send):disabled {
	background-image: none;
	background-color: var(--nms-blue-soft);
	box-shadow: inset 0 0 0 1px var(--nms-hairline);
}

/* On the intro the textarea is the composer, with no row wrapping it, so it carries the
   chrome itself — and enough height to read as the page's one invitation rather than as
   a search box. */
.theme-nms .tina-input-container:has(.tina-intro-message) > textarea.form-control {
	min-height: 104px;
	padding: 0.75rem 1rem;
}

/* The intro column centres its children, so everything but the textarea shrank to its own
   text: a 600px composer under a 220px stack of suggestions, with the send button floating
   loose under the middle of it. One measure for the column, the suggestions on it, and
   send anchored to the field's own edge. */
.theme-nms .tina-input-container:has(.tina-intro-message) {
	max-width: 680px;
}

.theme-nms .tina-input-container:has(.tina-intro-message) .tina-suggestions {
	width: 100%;
}

/* A 999px radius on a 36px control is a pill at chip width and a lozenge at the column's
   full measure, so on the intro the suggestions take the panel radius instead. */
.theme-nms .tina-input-container:has(.tina-intro-message) .tina-suggestions .btn {
	border-radius: var(--nms-r);
}

/* The disclaimer is page furniture, not part of the greeting. Hanging off the composer it
   pushed the hero off centre and still read as one more thing to do; taken out of the
   flow it sits at the foot of the column, on the column's own measure rather than half of
   it, and the greeting re-centres above it. .text-secondary on the field is about 2:1. */
.theme-nms .tina-input-container:has(.tina-intro-message) {
	position: relative;
}

.theme-nms .tina-input-container:has(.tina-intro-message) > .d-flex.justify-content-center {
	position: absolute;
	inset: auto 0 0;
	margin-top: 0 !important;
}

.theme-nms .tina-input-container:has(.tina-intro-message) > .d-flex.justify-content-center > * {
	width: 100% !important;
	color: var(--nms-text-muted) !important;
}

.theme-nms .tina-input-container:has(.tina-intro-message) > .d-flex.align-items-center {
	width: 100%;
	justify-content: flex-end;
	margin-top: -0.5rem;
}

/* Intro hero — the greeting is the only thing on the page, so it gets the weight and
   the avatar gets a brand ring instead of sitting on the aurora as a bare square. */
.theme-nms .tina-input-container:has(.tina-intro-message) .tina-avatar img {
	border-radius: 50%;
	box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.85), 0 0 0 5px rgba(0, 159, 227, 0.30),
		0 12px 28px rgba(12, 50, 85, 0.18);
}

.theme-nms .tina-intro-message {
	color: var(--nms-blue-deep);
	font-family: var(--nms-font-head);
	font-size: 1.5rem;
	font-weight: 600;
	letter-spacing: -0.02em;
}

.theme-nms .tina-suggestions .btn {
	background-color: rgba(255, 255, 255, 0.72);
	background-image: var(--nms-gloss);
	border: 1px solid var(--nms-glass-border);
	border-radius: var(--nms-r-pill);
	color: var(--nms-blue);
	text-align: left;
	padding: 0.4rem 1rem;
	box-shadow: var(--nms-sheen), 0 0 0 1px var(--nms-hairline), var(--nms-shadow-sm);
	transition: background-color 180ms var(--nms-ease), box-shadow 220ms var(--nms-ease-out),
		transform 220ms var(--nms-ease-out), color 180ms var(--nms-ease);
}

.theme-nms .tina-suggestions .btn:hover {
	background-color: rgba(255, 255, 255, 0.92);
	color: var(--nms-blue-deep);
	box-shadow: var(--nms-sheen), 0 0 0 1px rgba(0, 159, 227, 0.35), var(--nms-shadow);
	transform: translateY(-1px);
}

.theme-nms .tina-suggestions .btn .bi-lightbulb::before {
	color: var(--nms-amber);
}

/* The meta row — timestamp, copy, save-as-image — is the only text on the page that sits
   on the aurora itself rather than on a panel, and .text-secondary (#ADB5BD) over it is
   barely 2:1. It carries the utility class, so the tone has to be taken back by force. */
.theme-nms .tina-message-container .tina-meta,
.theme-nms .tina-message-container .tina-meta .text-secondary,
.theme-nms .tina-message-container .tina-action-btn {
	color: var(--nms-text-muted) !important;
}

.theme-nms .tina-message-container .tina-meta .fs-9 {
	font-size: 0.6875rem !important;
}

/* Copy / save-as-image on a hovered answer: bare icon buttons in the message footer.
   Boxing them in white pills made them louder than the message they belong to. */
.theme-nms .tina-message-container .tina-action-btn {
	background: transparent;
	border: 0;
	border-radius: var(--nms-r-sm);
	padding: 0.125rem 0.25rem !important;
	box-shadow: none;
	transition: var(--transition-150);
}

.theme-nms .tina-message-container .tina-action-btn:hover,
.theme-nms .tina-message-container .tina-action-btn:focus-visible {
	background: rgba(0, 159, 227, 0.10);
	color: var(--nms-blue) !important;
	box-shadow: none;
}

.theme-nms .tina-message-container .markdown-contents code,
.theme-nms .bg-secondary-subtle .markdown-contents code {
	background: rgba(25, 100, 170, 0.08);
	color: var(--nms-blue-deep);
	border-radius: 4px;
}

.theme-nms .tina-message-container .markdown-contents pre,
.theme-nms .bg-secondary-subtle .markdown-contents pre {
	background: rgba(232, 239, 247, 0.8);
	border: 1px solid var(--nms-hairline);
	border-radius: var(--nms-r-sm);
}

.theme-nms .tina-message-container .markdown-contents pre code,
.theme-nms .bg-secondary-subtle .markdown-contents pre code {
	background: transparent;
	color: var(--nms-text);
}

.theme-nms .tina-message-container .markdown-contents blockquote {
	border-left: 3px solid var(--nms-cyan);
	background: var(--nms-cyan-soft);
	color: var(--nms-text-muted);
}

/* Markdown tables never get the .table class, so they miss the app-wide header rule and
   kept a tinted band of their own. The chat's own rules are three classes deep, so the
   Tina-scoped copy is needed to match them rather than lose on specificity. */
.theme-nms .markdown-contents table thead,
.theme-nms .markdown-contents table thead th,
.theme-nms .tina-message-container .markdown-contents table thead,
.theme-nms .tina-message-container .markdown-contents table thead th {
	background: transparent;
	background-color: transparent;
	border-color: var(--nms-hairline);
	border-bottom: 2px solid var(--nms-hairline-strong);
	font-family: var(--nms-font-head);
	font-weight: 600;
	color: var(--nms-blue-deep);
}

.theme-nms .tina-message-container .markdown-contents table tbody td {
	border-color: var(--nms-hairline);
}

.theme-nms .tina-message-container .markdown-contents table tbody tr:hover {
	background: rgba(0, 159, 227, 0.07);
}

.theme-nms .bg-secondary-subtle .markdown-contents h3 {
	color: var(--nms-blue-deep);
	font-family: var(--nms-font-head);
}

.theme-nms .bg-secondary-subtle .markdown-contents hr {
	border-top-color: var(--nms-hairline);
}

.theme-nms .bg-secondary-subtle .markdown-contents strong {
	color: var(--nms-blue-deep);
}

.theme-nms .bg-secondary-subtle .markdown-contents em {
	color: var(--nms-text-muted);
}


/* =============================================
   MISC — select project, detail rows, loader
   ============================================= */

.theme-nms .page-selectProject .card {
	border-radius: var(--nms-r-lg);
}

.theme-nms .page-selectProject .card .card-header,
.theme-nms .page-selectProject .card .card-img-top {
	border-bottom: 1px solid var(--nms-hairline);
}

.theme-nms .page-selectProject .card .card-title {
	font-family: var(--nms-font-head);
	color: var(--nms-blue-deep);
	transition: color 180ms var(--nms-ease);
}

.theme-nms .page-selectProject .card:hover .card-title {
	color: var(--nms-cyan);
}

.theme-nms .page-selectProject .row:hover .card:hover {
	box-shadow: var(--nms-sheen), var(--nms-shadow-lg), 0 0 0 1px rgba(0, 159, 227, 0.25);
}

.theme-nms .page-ratingRequestDetail .response-container,
.theme-nms .ratingRequestDetail-modal .content-row {
	background: rgba(255, 255, 255, 0.55);
	border-radius: var(--nms-r);
}

.theme-nms .ratingRequestDetail-modal .mainheader-row {
	background: var(--nms-blue-soft);
	color: var(--nms-blue-deep);
	border-radius: var(--nms-r-sm);
}

.theme-nms .ratingRequestDetail-modal .subheader-row {
	background: rgba(232, 239, 247, 0.6);
	color: var(--nms-text-muted);
}

.theme-nms .db-compare-table .table thead th[data-field*="previousBlockDiff"],
.theme-nms .db-compare-table .table tbody td[data-table-column*="previousBlockDiff"] {
	background: rgba(0, 159, 227, 0.06) !important;
}

.theme-nms .loader-overlay {
	background: rgba(221, 232, 244, 0.70);
	backdrop-filter: blur(6px);
	-webkit-backdrop-filter: blur(6px);
}


/* =============================================
   QUESTIONNAIRE RESPONSES & SINGLE RESPONSE VIEW
   These views paint their own surfaces from --bs-body-bg, which is opaque again, so
   most of them heal on their own. What is left is matching them to the card they sit
   in rather than to the page.
   ============================================= */

/* Sticky strips sit inside a glass card and their own rows scroll under them, so they
   take the frost treatment: dense enough that nothing passing behind stays readable,
   translucent enough that the strip still belongs to the panel rather than sitting on it
   as a slab of pure white. */
.theme-nms .questionnaire-responses .qr-sticky-head,
.theme-nms .single-response-view .single-response-subheader,
.theme-nms .questionnaire-responses .qr-media-gallery__top {
	background: rgba(255, 255, 255, 0.88);
	backdrop-filter: var(--nms-blur);
	-webkit-backdrop-filter: var(--nms-blur);
}

.theme-nms .questionnaire-responses .qr-sticky-head .media-selection-toolbar {
	background: var(--nms-blue-soft);
	border-color: rgba(25, 100, 170, 0.18);
}

/* The section accent was a 3px --bs-info bar — the loudest cyan on the page, repeated
   down the whole list. Same job, brand hue, a third of the shout. */
.theme-nms .questionnaire-responses .group-node,
.theme-nms .single-response-view .group-node {
	border-left: 2px solid rgba(25, 100, 170, 0.30);
}

.theme-nms .questionnaire-responses .multiple-node,
.theme-nms .single-response-view .multiple-node {
	border-left-width: 2px;
}

.theme-nms .questionnaire-responses .group-node__header,
.theme-nms .single-response-view .group-node__header {
	color: var(--nms-blue-deep);
	font-family: var(--nms-font-head);
}

/* A card inside an offcanvas sits on the same fill as the panel around it, so it needs
   the edge rather than the elevation to separate. */
.theme-nms .offcanvas .card {
	box-shadow: 0 0 0 1px var(--nms-hairline), var(--nms-shadow-sm);
}

.theme-nms .offcanvas .card:hover {
	box-shadow: 0 0 0 1px var(--nms-hairline), var(--nms-shadow);
}


/* =============================================
   SELECT2
   A select2 box sits in the same grid filter row as a .form-control and a flatpickr
   input, so it has to be the same control: same radius, same fill, same border, same
   focus ring. Left to itself it inherited the global radius while the inputs beside it
   took the small one, and it was the only opaque white box in a translucent row.
   ============================================= */

.theme-nms .select2 {
	background-color: rgba(255, 255, 255, 0.72) !important;
	border: 1px solid var(--nms-hairline-strong) !important;
	border-radius: var(--nms-r-sm) !important;
	transition: border-color 180ms var(--nms-ease), box-shadow 180ms var(--nms-ease),
		background-color 180ms var(--nms-ease);
}

.theme-nms .select2:hover {
	border-color: rgba(25, 100, 170, 0.30) !important;
}

.theme-nms .select2:focus-within,
.theme-nms .select2-container--open > .selection > .select2 {
	background-color: rgba(255, 255, 255, 0.95) !important;
	border-color: var(--nms-cyan) !important;
	box-shadow: 0 0 0 3px rgba(0, 159, 227, 0.22);
}

.theme-nms .select2 .select2-selection__placeholder,
.theme-nms .select2 .select2-selection__rendered {
	color: var(--nms-text);
}

.theme-nms .select2-container--default .select2-selection--multiple .select2-selection__choice {
	background: var(--nms-blue-soft);
	border: 1px solid rgba(25, 100, 170, 0.20);
	border-radius: var(--nms-r-pill);
	color: var(--nms-blue-deep);
	padding-inline: 0.25rem;
}

.theme-nms .select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
	color: var(--nms-blue);
}

/* The dropdown is a menu, so it takes the menu elevation. The panel shadow was tuned
   for modals and vanished entirely behind a two-row popup. */
/* The dropdown is a menu over live content, so it takes the menu elevation and stays
   opaque. The panel shadow was tuned for modals and vanished entirely behind a two-row
   popup. */
.theme-nms .select2-container .select2-dropdown {
	background-color: var(--nms-overlay);
	background-image: linear-gradient(180deg, rgba(232, 239, 247, 0.5), rgba(255, 255, 255, 0) 48px);
	border: 1px solid var(--nms-hairline-strong);
	box-shadow: var(--nms-sheen), var(--nms-shadow-menu);
	border-radius: var(--nms-r) !important;
	overflow: hidden;
	padding: 0.25rem;
}

.theme-nms .select2-container .select2-results__options {
	padding-block: 0;
}

/* The base sheet pads the options list from the outside and the option from the right
   only, which left the labels jammed against the sheet's left edge and the hover fill
   running the full width with no inset. Both now sit on the dropdown's own padding. */
.theme-nms .select2-container--default .select2-results__options,
.theme-nms .select2-container--default .select2-dropdown--below .select2-results__options {
	padding-inline: 0;
}

.theme-nms .select2-container .select2-results__option {
	padding: 0.25rem 1.75rem 0.25rem 0.5rem !important;
	border-radius: var(--nms-r-sm);
	color: var(--nms-text);
	transition: background-color 120ms var(--nms-ease), color 120ms var(--nms-ease);
}
.theme-nms .select2-container .select2-results__option--highlighted {
	background: rgba(0, 159, 227, 0.14) !important;
	color: var(--nms-blue-deep) !important;
}
.theme-nms .select2-container .select2-results__option--selected:not(.select2-results__option--highlighted) {
	background: var(--nms-blue-soft) !important;
	color: var(--nms-blue-deep) !important;
}
/* --dropdown only: .select2-search is also worn by the inline search inside a closed
   multi-select, where the separator reads as a stray rule across the control. */
.theme-nms .select2-container--default .select2-search--dropdown {
	padding: 0.125rem 0.125rem 0.375rem !important;
	border-bottom: 1px solid var(--nms-hairline);
	margin-bottom: 0.25rem;
}
.theme-nms .select2-container--default .select2-search--dropdown input {
	min-height: 28px;
	background: var(--nms-surface);
	color: var(--nms-text);
	border: 1px solid var(--nms-hairline-strong);
	border-radius: var(--nms-r-sm);
}
.theme-nms .select2-container--default .select2-search--dropdown input:focus {
	border-color: var(--nms-cyan);
	box-shadow: 0 0 0 3px rgba(0, 159, 227, 0.22);
	outline: none;
}

/* A list longer than the sheet is cut dead at the bottom edge, mid-row, and over a light
   card the menu's own shadow is too weak to say where it stops — so the sliced row reads
   as running under the component behind rather than as "there is more below". Scroll
   shadows: the `local` covers ride with the content and cancel each shadow at its end of
   the scroll, so a list that fits shows nothing at all. */
.theme-nms .select2-container .select2-results__options {
	background:
		linear-gradient(var(--nms-overlay) 30%, rgba(255, 255, 255, 0)) top / 100% 14px no-repeat local,
		linear-gradient(rgba(255, 255, 255, 0), var(--nms-overlay) 70%) bottom / 100% 14px no-repeat local,
		radial-gradient(farthest-side at 50% 0, rgba(12, 50, 85, 0.18), rgba(12, 50, 85, 0)) top / 100% 7px no-repeat,
		radial-gradient(farthest-side at 50% 100%, rgba(12, 50, 85, 0.18), rgba(12, 50, 85, 0)) bottom / 100% 7px no-repeat;
}

/* The results list is the only scroller inside a rounded, clipped sheet, so its
   scrollbar ends up as a bare rule hard against the right edge — the "divider" down the
   open select. Inset it and let it fade in with the pointer. */
.theme-nms .select2-container .select2-results__options::-webkit-scrollbar {
	width: 10px;
}
.theme-nms .select2-container .select2-results__options::-webkit-scrollbar-thumb {
	background: rgba(25, 100, 170, 0.18);
	border: 3px solid transparent;
	background-clip: padding-box;
	border-radius: var(--nms-r-pill);
}
.theme-nms .select2-container .select2-results__options:hover::-webkit-scrollbar-thumb {
	background: rgba(25, 100, 170, 0.38);
	background-clip: padding-box;
}

/* One control height across a grid's filter row. A select2 three pixels shorter than
   the input beside it and a date range twice as tall as both is what made those rows
   look like three different widgets stapled together. */
.theme-nms .datagrid thead .select2 {
	min-height: 31px;
}

/* Two stacked .form-control-sm inputs carry a 25px min-height each, which made the date
   filter twice as tall as every other control in the row. */
.theme-nms .datagrid .datagrid-col-filter-date-range input.flatpickr {
	height: 16px;
	min-height: 16px;
	line-height: 16px;
}


/* =============================================
   FLATPICKR
   ============================================= */

.theme-nms .flatpickr-calendar {
	background: var(--nms-overlay) !important;
	border: 1px solid var(--nms-hairline-strong) !important;
	border-radius: var(--nms-r) !important;
	box-shadow: var(--nms-sheen), var(--nms-shadow-menu) !important;
}

.theme-nms .flatpickr-months .flatpickr-month,
.theme-nms .flatpickr-current-month .flatpickr-monthDropdown-months {
	background: transparent;
	color: var(--nms-text);
}
.theme-nms .flatpickr-current-month .flatpickr-monthDropdown-months option {
	background: var(--nms-surface);
	color: var(--nms-text);
}

.theme-nms .flatpickr-months .flatpickr-prev-month,
.theme-nms .flatpickr-months .flatpickr-next-month {
	color: var(--nms-text-muted);
	fill: var(--nms-text-muted);
}
.theme-nms .flatpickr-months .flatpickr-prev-month:hover,
.theme-nms .flatpickr-months .flatpickr-next-month:hover {
	color: var(--nms-blue);
	fill: var(--nms-blue);
}
.theme-nms .flatpickr-months .flatpickr-prev-month svg,
.theme-nms .flatpickr-months .flatpickr-next-month svg {
	fill: currentColor;
}

.theme-nms span.flatpickr-weekday {
	color: var(--nms-text-muted) !important;
}

.theme-nms .flatpickr-day {
	color: var(--nms-text);
	border-color: transparent;
}
.theme-nms .flatpickr-day:hover {
	background: rgba(0, 159, 227, 0.10);
	border-color: rgba(0, 159, 227, 0.25);
	color: var(--nms-blue);
}
.theme-nms .flatpickr-day.selected,
.theme-nms .flatpickr-day.startRange,
.theme-nms .flatpickr-day.endRange {
	background: var(--nms-blue) !important;
	border-color: var(--nms-blue) !important;
	color: #FFFFFF !important;
	box-shadow: var(--nms-glow);
}
.theme-nms .flatpickr-day.inRange {
	background: rgba(0, 159, 227, 0.10) !important;
	border-color: rgba(0, 159, 227, 0.10) !important;
	box-shadow: none;
}
.theme-nms .flatpickr-day.today {
	border-color: var(--nms-amber) !important;
}
.theme-nms .flatpickr-day.flatpickr-disabled,
.theme-nms .flatpickr-day.prevMonthDay,
.theme-nms .flatpickr-day.nextMonthDay {
	color: var(--nms-text-subtle) !important;
}

.theme-nms .numInputWrapper .cur-year {
	color: var(--nms-text);
}

/* Flatpickr in a grid filter row — the date filter is two stacked inputs inside one
   input-group, and each of them carrying its own border drew a rule straight through the
   middle of what reads as a single control. The group takes the chrome; the inputs go
   bare inside it — and unrounded, so the group needs no overflow clipping to keep its
   corners. It must not have any: both pickers are `static` and render their calendar
   inside this group, so hiding the overflow hides the calendar with it. */
.theme-nms .datagrid .datagrid-col-filter-date-range {
	background: rgba(255, 255, 255, 0.72);
	border: 1px solid var(--nms-hairline-strong);
	border-radius: var(--nms-r-sm);
	transition: border-color 180ms var(--nms-ease), box-shadow 180ms var(--nms-ease),
		background-color 180ms var(--nms-ease);
}

.theme-nms .datagrid .datagrid-col-filter-date-range:hover {
	border-color: rgba(25, 100, 170, 0.30);
}

.theme-nms .datagrid .datagrid-col-filter-date-range:focus-within {
	background: rgba(255, 255, 255, 0.95);
	border-color: var(--nms-cyan);
	box-shadow: 0 0 0 3px rgba(0, 159, 227, 0.22);
}

/* A lone date filter is a control in its own right and keeps the field chrome. */
.theme-nms .datagrid .flatpickr-wrapper input.flatpickr {
	background: rgba(255, 255, 255, 0.72);
	border: 1px solid var(--nms-hairline-strong);
	color: var(--nms-text);
}

.theme-nms .datagrid .datagrid-col-filter-date-range input.flatpickr {
	background: transparent;
	border: 0;
	border-radius: 0;
	box-shadow: none;
	color: var(--nms-text);
}

/* An inline calendar is the modal's content, not a popup floating over it — left with
   the overlay chrome it drew a bordered, shadowed sheet inside an already bordered,
   shadowed sheet. */
.theme-nms .flatpickr-calendar.inline {
	margin-inline: auto;
	background: transparent !important;
	border: 0 !important;
	border-radius: 0 !important;
	box-shadow: none !important;
}

/* The day grid is laid out on flatpickr's own fixed width; stretching it re-flows the
   seven columns, so the modal is widened to fit it instead. */
.theme-nms .modal-calendar {
	--bs-modal-bg: var(--nms-surface);
	--bs-modal-width: 340px;
}

.theme-nms .modal-calendar .modal-body {
	padding: 0 0 0.5rem;
}

/* The range slider's track used to take --nms-bg, which is the page's own field colour —
   a saturated blue rail under a saturated blue fill, with no contrast between the two. */
.theme-nms .noUi-target {
	background: transparent !important;
}
.theme-nms .noUi-base {
	background-color: rgba(12, 50, 85, 0.14) !important;
	border-radius: var(--nms-r-pill);
}
.theme-nms .noUi-connect {
	background: var(--nms-brand) !important;
}
.theme-nms .noUi-handle {
	background: var(--nms-surface) !important;
	border-color: rgba(25, 100, 170, 0.35) !important;
	box-shadow: var(--nms-sheen), 0 2px 6px rgba(12, 50, 85, 0.22);
}
.theme-nms .noUi-handle::before,
.theme-nms .noUi-handle::after {
	background: var(--nms-text-muted) !important;
}


/* =============================================
   DUMMY / SKELETON LOADING PLACEHOLDERS
   ============================================= */

@keyframes nms-shimmer {
	to { background-position: -200% 0; }
}

.theme-nms .dummy-content .dummy-h,
.theme-nms .dummy-content .dummy-line,
.theme-nms .dummy-content .dummy-icon {
	background: linear-gradient(90deg, rgba(25, 100, 170, 0.06) 25%, rgba(0, 159, 227, 0.14) 50%, rgba(25, 100, 170, 0.06) 75%) !important;
	background-size: 200% 100%;
	animation: nms-shimmer 1.4s linear infinite;
}
.theme-nms .dummy-content .dummy-chart {
	opacity: 0.5;
}
.theme-nms .dummy-content .card {
	border-color: var(--nms-hairline) !important;
}

/* Filter loading placeholder */
.theme-nms .loading {
	color: var(--nms-blue);
	opacity: 0.3;
}


/* =============================================
   HIGHCHARTS
   ============================================= */

.theme-nms .highcharts-background {
	fill: transparent !important;
}

.theme-nms .highcharts-plot-background {
	fill: transparent !important;
}

/* Font override */
.theme-nms .highcharts-container,
.theme-nms .highcharts-container text,
.theme-nms .highcharts-container tspan {
	font-family: var(--nms-font-body) !important;
}

/* Axis labels & titles */
.theme-nms .highcharts-axis-labels text,
.theme-nms .highcharts-xaxis-labels text,
.theme-nms .highcharts-yaxis-labels text {
	fill: var(--nms-text-muted) !important;
}
.theme-nms .highcharts-axis-title {
	fill: var(--nms-text-muted) !important;
}

/* Grid lines */
.theme-nms .highcharts-grid-line {
	stroke: var(--nms-hairline) !important;
}
.theme-nms .highcharts-tick {
	stroke: var(--nms-hairline-strong) !important;
}
.theme-nms .highcharts-axis-line {
	stroke: var(--nms-hairline-strong) !important;
}

/* Legend */
.theme-nms .highcharts-legend-item text {
	fill: var(--nms-text-muted) !important;
}
.theme-nms .highcharts-legend-item span {
	color: var(--nms-text-muted) !important;
}
.theme-nms .highcharts-legend-item:hover text {
	fill: var(--nms-text) !important;
}
.theme-nms .highcharts-legend-item:hover span {
	color: var(--nms-text) !important;
}

/* Title */
.theme-nms .highcharts-title {
	fill: var(--nms-text) !important;
	font-family: var(--nms-font-head) !important;
}
.theme-nms .highcharts-subtitle {
	fill: var(--nms-text-muted) !important;
}

/* Tooltip */
.theme-nms .highcharts-tooltip-box {
	fill: var(--nms-glass-strong) !important;
	stroke: var(--nms-glass-border) !important;
}
.theme-nms .highcharts-tooltip text,
.theme-nms .highcharts-tooltip span {
	color: var(--nms-text) !important;
	fill: var(--nms-text) !important;
}

/* Caption */
.theme-nms .highcharts-caption {
	fill: var(--nms-text-muted) !important;
}

/* Credits */
.theme-nms .highcharts-credits {
	fill: var(--nms-text-subtle) !important;
}

/* Data labels */
.theme-nms .highcharts-data-label text {
	fill: var(--nms-text) !important;
}

/* Sankey node labels — remove blurry outline, add subtle readable shadow */
.theme-nms .highcharts-sankey-series .highcharts-text-outline {
	display: none !important;
}
.theme-nms .highcharts-sankey-series .highcharts-data-label text {
	fill: var(--nms-text) !important;
	paint-order: stroke fill;
	stroke: var(--nms-surface) !important;
	stroke-width: 2px !important;
	stroke-opacity: 0.6;
}

/* Crosshair */
.theme-nms .highcharts-crosshair {
	stroke: var(--nms-hairline-strong) !important;
}

/* Pie slice separators — scoped to the pie, because .highcharts-point is every
   point of every series: a white hairline on wordcloud words or line markers
   eats the mark instead of separating it. */
.theme-nms .highcharts-pie-series .highcharts-point {
	stroke: var(--nms-surface) !important;
	stroke-width: 1px !important;
}

/* Pie chart data labels connector */
.theme-nms .highcharts-data-label-connector {
	stroke: var(--nms-text-muted) !important;
}

/* No-data label */
.theme-nms .highcharts-no-data text {
	fill: var(--nms-text-muted) !important;
}

/* Loading indicator */
.theme-nms .highcharts-loading {
	background: var(--nms-surface) !important;
}
.theme-nms .highcharts-loading-inner {
	color: var(--nms-blue) !important;
}

/* Target annotation label */
.theme-nms .highcharts-annotation .highcharts-annotation-label .highcharts-text-outline {
	display: none !important;
}

/* Custom target tooltip */
.theme-nms .highcharts-label rect {
	fill: var(--nms-glass-strong) !important;
}
.theme-nms .highcharts-label text {
	fill: var(--nms-text) !important;
}


/* Bootstrap paints bare <code> in #D63384, a hue that exists nowhere in this palette. */
.theme-nms code,
.theme-nms kbd,
.theme-nms samp {
	color: var(--nms-blue-deep);
	background-color: rgba(25, 100, 170, 0.08);
	border-radius: 4px;
	padding: 0.1em 0.3em;
}

.theme-nms pre {
	background-color: rgba(232, 239, 247, 0.8);
	border: 1px solid var(--nms-hairline);
	border-radius: var(--nms-r-sm);
	color: var(--nms-text);
}

.theme-nms pre code,
.theme-nms .cm-editor code,
.theme-nms a code {
	background-color: transparent;
	padding: 0;
}

.theme-nms a code {
	color: inherit;
}


/* =============================================
   SCROLLBAR
   ============================================= */

.theme-nms ::-webkit-scrollbar { width: 6px; height: 6px; }
.theme-nms ::-webkit-scrollbar-track { background: transparent; }
.theme-nms ::-webkit-scrollbar-thumb {
	background: rgba(25, 100, 170, 0.22);
	border-radius: var(--nms-r-pill);
}
.theme-nms ::-webkit-scrollbar-thumb:hover {
	background: rgba(25, 100, 170, 0.40);
}


/* =============================================
   SELECTION
   ============================================= */

.theme-nms ::selection {
	background: rgba(0, 159, 227, 0.25);
	color: var(--nms-text);
}


/* =============================================
   CODEMIRROR 6
   ============================================= */

.theme-nms .code-editor-container {
	background-color: rgba(255, 255, 255, 0.72);
	border: 1px solid var(--nms-hairline-strong);
	border-radius: var(--nms-r-sm);
	overflow: hidden;
	box-shadow: inset 0 1px 4px rgba(12, 50, 85, 0.06);
}

.theme-nms .cm-editor {
	background-color: transparent;
	color: var(--nms-text);
}

.theme-nms .cm-editor .cm-gutters {
	background-color: rgba(232, 239, 247, 0.7);
	color: var(--nms-text-muted);
	border-right: 1px solid var(--nms-hairline);
}

.theme-nms .cm-editor .cm-activeLineGutter {
	background-color: rgba(0, 159, 227, 0.07);
	color: var(--nms-blue);
}

.theme-nms .cm-editor .cm-activeLine {
	background-color: rgba(0, 159, 227, 0.07);
}

.theme-nms .cm-editor .cm-cursor {
	border-left-color: var(--nms-blue);
}

.theme-nms .cm-editor .cm-selectionBackground,
.theme-nms .cm-editor.cm-focused .cm-selectionBackground {
	background-color: rgba(0, 159, 227, 0.22) !important;
}

.theme-nms .cm-editor .cm-matchingBracket {
	background-color: rgba(232, 133, 46, 0.18);
	color: var(--nms-amber) !important;
}

.theme-nms .cm-editor .cm-searchMatch {
	background-color: rgba(232, 133, 46, 0.2);
	outline: 1px solid rgba(232, 133, 46, 0.4);
}

.theme-nms .cm-editor .cm-searchMatch.cm-searchMatch-selected {
	background-color: rgba(232, 133, 46, 0.35);
}

.theme-nms .cm-editor .cm-tooltip {
	background-color: var(--nms-overlay);
	border: 1px solid var(--nms-hairline);
	color: var(--nms-text);
	box-shadow: var(--nms-sheen), var(--nms-shadow-lg);
	border-radius: var(--nms-r);
}

.theme-nms .cm-editor .cm-tooltip-autocomplete ul li[aria-selected] {
	background-color: var(--nms-blue-soft);
	color: var(--nms-blue-deep);
}

/* Syntax highlighting — NMS brand palette */
.theme-nms .cm-editor .ͼc { color: var(--nms-blue); }        /* keyword */
.theme-nms .cm-editor .ͼd { color: var(--nms-text); }        /* variable */
.theme-nms .cm-editor .ͼe { color: var(--nms-cyan); }        /* definition */
.theme-nms .cm-editor .ͼb { color: var(--nms-text-subtle); font-style: italic; } /* comment */
.theme-nms .cm-editor .ͼi { color: #2E7D32; }                /* string */
.theme-nms .cm-editor .ͼh { color: var(--nms-amber); }       /* number */
.theme-nms .cm-editor .ͼg { color: var(--nms-text-muted); }  /* operator */
.theme-nms .cm-editor .ͼm { color: var(--nms-blue-deep); }   /* typeName */
.theme-nms .cm-editor .ͼl { color: var(--nms-cyan); }        /* function */
.theme-nms .cm-editor .ͼn { color: var(--nms-blue-deep); }   /* tag */
.theme-nms .cm-editor .ͼo { color: var(--nms-amber); }       /* attribute */
.theme-nms .cm-editor .ͼ7 { color: var(--nms-red); }         /* invalid */

/* Panels (search bar, etc.) */
.theme-nms .cm-editor .cm-panels {
	background-color: var(--nms-bg);
	border-color: var(--nms-hairline);
	color: var(--nms-text);
}

.theme-nms .cm-editor .cm-panels input,
.theme-nms .cm-editor .cm-panels button {
	background-color: var(--nms-surface);
	border: 1px solid var(--nms-hairline);
	color: var(--nms-text);
}

.theme-nms .cm-editor .cm-panels button:hover {
	background-color: rgba(0, 159, 227, 0.10);
}

.theme-nms .cm-editor .cm-foldPlaceholder {
	background-color: var(--nms-bg);
	border-color: var(--nms-hairline);
	color: var(--nms-text-muted);
}

/* Formula help panel */
.theme-nms .cm-formula-help {
	background-color: var(--nms-surface) !important;
	border-top-color: var(--nms-hairline) !important;
}

.theme-nms .cm-formula-help-section td {
	color: var(--nms-blue) !important;
}

.theme-nms .cm-formula-help tr:not(.cm-formula-help-section):hover {
	background-color: rgba(0, 159, 227, 0.10) !important;
}

.theme-nms .cm-fh-code code {
	color: var(--nms-amber) !important;
}

.theme-nms .cm-fh-desc {
	color: var(--nms-text-muted) !important;
}

.theme-nms .cm-formula-help-btn {
	background-color: var(--nms-surface) !important;
	border-top-color: var(--nms-hairline) !important;
	color: var(--nms-text-muted) !important;
}

.theme-nms .cm-formula-help-btn:hover {
	color: var(--nms-blue) !important;
}


/* =============================================
   COLLAPSIBLE DOCS PANEL (markdown help)
   ============================================= */

.theme-nms .bg-secondary-subtle .markdown-contents {
	color: var(--nms-text);
}

.theme-nms .bg-secondary-subtle .markdown-contents h1,
.theme-nms .bg-secondary-subtle .markdown-contents h2,
.theme-nms .bg-secondary-subtle .markdown-contents h3 {
	color: var(--nms-blue);
	font-family: var(--nms-font-head);
}

/* =============================================
   MOBILE
   ============================================= */

/* Nothing between a wide grid and <body> scrolls, so below md the page itself slid
   sideways and the content left the fixed chrome behind. The grid takes its own
   scroller; the base gutter spacer only means anything while the page is what scrolls. */
@media (max-width: 767.98px) {
	.theme-nms .datagrid {
		overflow-x: auto;
		overscroll-behavior-x: contain;
	}

	.theme-nms .datagrid table:not(.item-detail-content)::after {
		content: none;
	}
}

/* =============================================
   MOTION SAFETY
   Covers every nms-* keyframe, including the 3rd-party sections below.
   ============================================= */

@media (prefers-reduced-motion: reduce) {
	.theme-nms,
	.theme-nms *,
	.theme-nms *::before,
	.theme-nms *::after {
		animation-duration: 0.001ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.001ms !important;
	}
}


/* =============================================
   PRINT
   The field is a screen device: it is painted on <html> and on a fixed pseudo-element, so
   the app's own `body { background: white }` print rule cannot reach either, and every
   sheet came out with the aurora banded across it. On paper the surface tiers collapse —
   there is nothing to be translucent against — so the glass becomes plain white with the
   hairline it already uses, and the gloss, blur and tinted fills drop out.
   ============================================= */

@media print {
	html:has(.theme-nms),
	.theme-nms.theme-nms {
		background: #fff !important;
	}

	.theme-nms::before {
		display: none !important;
	}

	.theme-nms *,
	.theme-nms *::before,
	.theme-nms *::after {
		backdrop-filter: none !important;
		-webkit-backdrop-filter: none !important;
	}

	.theme-nms .card,
	.theme-nms .offcanvas,
	.theme-nms .modal-content,
	.theme-nms .tina-message-container .tina-message {
		background-color: #fff !important;
		background-image: none !important;
		border: 1px solid var(--nms-hairline) !important;
	}
}
