/**
 * variables.css
 *
 * Design tokens for browJS — the "Graphite Chartreuse" identity.
 *
 * Architecture:
 *   1. Primitive scales (--color-*)            — raw values, kept as aliases.
 *   2. Semantic token layer (--surface-*, --text-*, --accent-*, ...) — single
 *      source of truth. Dark is the only theme.
 *   3. Legacy/consumer vars (--bg-color-*, --button-*, --input-*, --bs-*)
 *      are rewired to reference the semantic layer so the whole app + Bootstrap
 *      + UIKit re-skin from one place.
 *
 * This file is part of browJS
 */

:root {
    /* ===== 1. Primitive scales (aliases; repoint the ramp, keep the names) ===== */
    --color-white: #fff;
    --color-black: #000;

    /* Neutral-ink ramp (light -> dark). Near-achromatic on purpose: the accent
       is a high-chroma yellow-green, and any hue in the chrome fights it. */
    --color-gray-50: #f7f7f7;
    --color-gray-100: #eeefef;
    --color-gray-200: #e4e5e5;
    --color-gray-300: #d9dada;
    --color-gray-400: #c4c5c6;
    --color-gray-500: #8d9092;
    --color-gray-600: #6f7375;
    --color-gray-700: #33363a;
    --color-gray-800: #26282b;
    --color-gray-900: #17181a;

    /* Chartreuse (accent) ramp. Keeps the --color-blue-* names so no call site
       has to change; the hues are green now. */
    --color-blue-50: #f4f9e2;
    --color-blue-100: #e8f3c2;
    --color-blue-200: #d7ea95;
    --color-blue-300: #c9e372;
    --color-blue-400: #c6e765;
    --color-blue-500: #b6d94a;
    --color-blue-600: #9dbe38;
    --color-blue-700: #7f9c2b;
    --color-blue-800: #5e7420;
    --color-blue-900: #3f4f16;

    /* Orange (signal) + status primitives */
    --color-amber-500: #e88a3c;
    --color-amber-400: #f59b4f;
    --color-red-500: #ee6a5f;
    --color-red-600: #d9534a;
    /* Success is deep teal, not green — a yellow-green accent and a green
       "succeeded" state are indistinguishable at 10px. */
    --color-green-500: #29a08d;
    --color-green-600: #1f8375;
    --color-yellow-500: #e8c93f;
    --color-yellow-600: #cfae26;
    --color-cyan-600: #b6d94a;
    --color-cyan-700: #9dbe38;

    /* ===== Spacing ===== */
    --spacing-1: 0.25rem;
    --spacing-2: 0.5rem;
    --spacing-3: 0.75rem;
    --spacing-4: 1rem;
    --spacing-5: 1.25rem;
    --spacing-6: 1.5rem;
    --spacing-8: 2rem;
    --spacing-10: 2.5rem;
    --spacing-12: 3rem;
    --spacing-16: 4rem;
    --spacing-20: 5rem;

    /* ===== Typography ===== */
    /* Font families / sizes / weights are defined in fonts.css */

    /* ===== Border Radius (sharp / CAD) ===== */
    --radius-xs: 2px;
    --radius-sm: 3px;
    --radius-base: 4px;
    --radius-md: 6px;
    --radius-lg: 8px;
    --radius-full: 9999px;
    /* Legacy names -> new sharp scale */
    --border-radius-sm: var(--radius-xs);
    --border-radius-base: var(--radius-sm);
    --border-radius-md: var(--radius-base);
    --border-radius-lg: var(--radius-md);
    --border-radius-xl: var(--radius-lg);
    --border-radius-full: var(--radius-full);

    /* ===== Shadows (tuned for dark chrome) ===== */
    --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.25);
    --shadow-base: 0 1px 3px 0 rgba(0, 0, 0, 0.35), 0 1px 2px 0 rgba(0, 0, 0, 0.25);
    --shadow-md: 0 4px 10px -2px rgba(0, 0, 0, 0.45), 0 2px 4px -1px rgba(0, 0, 0, 0.3);
    --shadow-lg: 0 10px 24px -4px rgba(0, 0, 0, 0.5), 0 4px 8px -2px rgba(0, 0, 0, 0.35);
    --shadow-xl: 0 20px 40px -8px rgba(0, 0, 0, 0.55), 0 8px 16px -6px rgba(0, 0, 0, 0.4);

    /* ===== Z-index ===== */
    --z-index-dropdown: 1000;
    --z-index-sticky: 1020;
    --z-index-fixed: 1030;
    --z-index-modal-backdrop: 1040;
    --z-index-modal: 1050;
    --z-index-popover: 1060;
    --z-index-tooltip: 1070;

    /* ===== Motion ===== */
    --ease-standard: cubic-bezier(0.2, 0, 0, 1);
    --ease-emphasized: cubic-bezier(0.2, 0, 0, 1);
    --dur-fast: 120ms;
    --dur: 160ms;
    --dur-slow: 240ms;
    /* Legacy names */
    --transition-fast: var(--dur-fast);
    --transition-base: var(--dur);
    --transition-slow: var(--dur-slow);

    /* ============================================================= */
    /* ===== 2. Semantic token layer — DARK (the only theme) ======== */
    /* ============================================================= */

    /* Surfaces (elevation ramp) */
    --surface-sunken: #0c0d0e;
    --surface-0: #111213;   /* app root chrome */
    --surface-1: #17181a;   /* panels, sidebars */
    --surface-2: #1e2022;   /* headers, inputs, raised */
    --surface-3: #26282b;   /* hover / selected */
    --surface-4: #2e3134;   /* menus, popovers, tooltips */

    /* Borders + machined keyline */
    --border-subtle: #212325;
    --border-base: #33363a;
    --border-strong: #43474b;
    --keyline: rgba(255, 255, 255, 0.05);

    /* Text */
    --text-1: #e9eaea;
    --text-2: #a5a8a9;
    --text-3: #6f7375;
    --text-disabled: #4d5052;
    /* Chartreuse is a LIGHT accent — anything sitting on it takes dark ink.
       This single token flips every primary button, armed tool and active mode
       tile; leaving it light gives white-on-lime across the app. */
    --text-on-accent: #111213;

    /* Accent (chartreuse) — interactive & selection */
    --accent: #b6d94a;
    --accent-hover: #c6e765;
    --accent-active: #9dbe38;
    --accent-muted: rgba(182, 217, 74, 0.14);
    --accent-border: rgba(182, 217, 74, 0.5);

    /* Signal (orange) — armed tool / unsaved / attention */
    --signal: #e88a3c;
    --signal-hover: #f59b4f;
    --signal-muted: rgba(232, 138, 60, 0.16);

    /* Status */
    --status-success: #29a08d;
    --status-danger: #ee6a5f;
    /* Pulled toward true yellow: at #e0a63a it read as a dimmer twin of the
       #e88a3c signal wherever the two sat side by side (GRF explorer badges). */
    --status-warning: #e8c93f;
    --status-info: var(--accent);
    /* Hover pairs, semantic like --accent-hover/--signal-hover. */
    --status-danger-hover: var(--color-red-600);
    --status-warning-hover: var(--color-yellow-600);

    /* Focus ring */
    --focus-ring: 0 0 0 2px rgba(182, 217, 74, 0.45);

    /* ---- Glass / instrument panels ---------------------------------
       Translucent surfaces over a backdrop blur, hairline keyline dividers,
       soft depth shadow. Built with color-mix() over the semantic
       --surface-* ramp so one definition tracks any future surface change. */
    --glass-panel:   color-mix(in srgb, var(--surface-1) 82%, transparent);
    --glass-raised:  color-mix(in srgb, var(--surface-2) 86%, transparent);
    --glass-sunken:  color-mix(in srgb, var(--surface-sunken) 55%, transparent);
    --glass-blur:    10px;
    --glass-border:  var(--keyline);
    --glass-divider: var(--keyline);
    --glass-shadow:  var(--shadow-md);

    /* Tinted "pill" chips — translucent semantic fills + matching text. */
    --tint-accent-bg:  var(--accent-muted);
    --tint-accent-fg:  var(--accent);
    --tint-accent-bd:  var(--accent-border);
    --tint-signal-bg:  var(--signal-muted);
    --tint-signal-fg:  var(--signal-hover);
    --tint-signal-bd:  color-mix(in srgb, var(--signal) 45%, transparent);
    --tint-success-bg: color-mix(in srgb, var(--status-success) 18%, transparent);
    --tint-success-fg: var(--status-success);
    --tint-success-bd: color-mix(in srgb, var(--status-success) 45%, transparent);
    --tint-danger-bg:  color-mix(in srgb, var(--status-danger) 18%, transparent);
    --tint-danger-fg:  var(--status-danger);
    --tint-danger-bd:  color-mix(in srgb, var(--status-danger) 45%, transparent);

    /* ============================================================= */
    /* ===== 3. Legacy / consumer vars — rewired to semantic ======= */
    /* ============================================================= */

    /* Background Colors */
    --bg-color-primary: var(--surface-1);
    --bg-color-secondary: var(--surface-2);
    --bg-color-tertiary: var(--surface-3);
    --bg-color-inverse: var(--text-1);

    /* Text Colors */
    --text-color-primary: var(--text-1);
    --text-color-secondary: var(--text-2);
    --text-color-tertiary: var(--text-3);
    --text-color-inverse: var(--surface-0);

    /* Border Colors */
    --border-color-light: var(--border-subtle);
    --border-color-base: var(--border-base);
    --border-color-dark: var(--border-strong);

    /* Element Colors */
    --focus-color: var(--accent);
    --link-color: var(--accent);
    --link-hover-color: var(--accent-hover);
    --selection-color: var(--accent-muted);

    /* Button Colors */
    --button-primary-bg: var(--accent);
    --button-primary-text: var(--text-on-accent);
    --button-primary-hover-bg: var(--accent-hover);
    --button-secondary-bg: var(--surface-3);
    --button-secondary-text: var(--text-1);
    --button-secondary-hover-bg: var(--surface-4);

    /* Form Controls */
    --input-bg: var(--surface-2);
    --input-text: var(--text-1);
    --input-border: var(--border-base);
    --input-focus-border: var(--accent);
    --input-placeholder: var(--text-3);

    /* Scrollbar Colors */
    --scrollbar-track-color: transparent;
    --scrollbar-thumb-color: var(--border-strong);
    --scrollbar-thumb-hover-color: var(--text-3);

    /* Icon Filter (icons are authored light; keep visible on dark chrome) */
    --icon-filter: none;

    /* Status Colors (legacy names) */
    --color-success: var(--status-success);
    --color-error: var(--status-danger);
    --color-danger: var(--status-danger);
    --color-danger-dark: var(--color-red-600);
    --color-warning: var(--status-warning);
    --color-info: var(--status-info);

    /* Dialog specific */
    --dialog-shadow: var(--shadow-lg);

    /* Legacy aliases — some sidebars reference these via var(--x, hardcoded)
       fallbacks (e.g. #4caf50 green, #151515). Define them so those call sites
       adopt the identity without touching each file. */
    --primary-color: var(--accent);
    --sidebar-bg: var(--surface-1);
}

/* ============================================================= */
/* ===== Bootstrap retheme — point --bs-* at the tokens ======== */
/* Scoped to [data-bs-theme] (set on <html>+<body> by the app) so */
/* these override Bootstrap's own [data-bs-theme] block, which    */
/* the app loads before this file. Light is intentionally still   */
/* mapped: if any stray call site sets data-bs-theme="light" it   */
/* now resolves to the same dark tokens rather than to            */
/* Bootstrap's untouched light defaults.                          */
/* ============================================================= */
[data-bs-theme="dark"],
[data-bs-theme="light"] {
    --bs-body-bg: var(--surface-0);
    --bs-body-color: var(--text-1);
    --bs-emphasis-color: var(--text-1);
    --bs-secondary-color: var(--text-2);
    --bs-tertiary-color: var(--text-3);
    --bs-border-color: var(--border-base);
    --bs-border-radius: var(--radius-base);
    --bs-border-radius-sm: var(--radius-xs);
    --bs-link-color: var(--accent);
    --bs-link-hover-color: var(--accent-hover);
    --bs-primary: var(--accent);
    --bs-secondary-bg: var(--surface-2);
    --bs-tertiary-bg: var(--surface-1);
    --bs-body-font-family: var(--font-family-base);
    --bs-primary-rgb: 182, 217, 74;
}

/* Light theme removed. `.theme-light` is no longer defined anywhere, so the
   selector in app.css (`:root:not(.theme-light) #copy-toolbar…`) now always
   matches — which is the intended dark styling. Follow-ups outside this file:
     - SettingsDialog.js: drop the theme toggle and its persisted pref.
     - index.html: keep `<body class="theme-dark" data-bs-theme="dark">`.
     - app.css: the paired `[data-bs-theme="dark"] / .theme-dark` blocks
       (lines ~1864-1896) are now unconditional and can be flattened. */

/* app.css — consolidated app chrome (was main.css + others.css). */

/* ===== (former others.css: Bootstrap form overrides + component styles) ===== */
:root {
	/* override Bootstrap variables */
	color-scheme: light dark;
}

[hidden] {
	display: none !important;
}

/* a, span, small, p, label, button, h1, h2, h3, h4, h5, h6 { */
label, button, h1, h2, h3, h4, h5, h6 {
	user-select: none;
	-webkit-user-select: none;
	-moz-user-select: none;
	-ms-user-select: none;
	-o-user-select: none;
}

code {
	user-select: text;
	-webkit-user-select: text;
	-moz-user-select: text;
	-ms-user-select: text;
	-o-user-select: text;
	cursor: auto;
}

input, select {
	vertical-align: middle;
	outline: none;
    border: 1px solid var(--bs-border-color-translucent);
    padding: 0.05rem 0.2rem;
	transition: all 0.2s ease;
}

input:hover, select:hover {
	border-color: var(--bs-border-color);
}

input {
	padding: 0.08rem 0.2rem;
}

textarea {
	outline: none;
	border: 1px solid var(--bs-border-color-translucent);
	padding: 0.15rem 0.4rem;
	tab-size: 4;
	white-space: pre;
	word-wrap: normal;
	transition: all 0.2s ease;
}

textarea:hover {
	border-color: var(--bs-border-color);
}

textarea.success {
	border-color: var(--color-success) !important;
}

textarea.fail {
	border-color: var(--color-error) !important;
	background-color: rgba(239, 68, 68, 0.05);
}

/* --- Bootstrap form overrides (match AIModelCreate look) --- */
.form-label,
.col-form-label,
.col-form-label-sm {
	font-size: unset;
}

.form-control,
.form-select {
	vertical-align: middle;
	outline: none;
	border: 1px solid var(--bs-border-color-translucent);
	background-color: var(--bs-body-bg, transparent);
	color: var(--bs-body-color);
	padding: 0.25rem 0.5rem;
	font-size: inherit;
	line-height: 1.4;
	border-radius: var(--bs-border-radius, 0.25rem);
	transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.form-control:hover,
.form-select:hover {
	border-color: var(--bs-border-color);
}

.form-control:focus,
.form-select:focus {
	outline: none;
	border-color: var(--bs-border-color);
	box-shadow: 0 0 0 2px rgba(var(--bs-primary-rgb, 66, 153, 225), 0.2);
}

.form-control::placeholder {
	color: var(--bs-secondary-color);
	opacity: 0.8;
}

.form-control-sm,
.form-select-sm {
	padding: 0.08rem 0.35rem;
	font-size: var(--font-size-sm);
	border-radius: var(--bs-border-radius-sm, 0.2rem);
}

.form-control-lg,
.form-select-lg {
	padding: 0.35rem 0.6rem;
	font-size: 1rem;
	border-radius: var(--bs-border-radius-lg, 0.3rem);
}

.form-control.success,
.form-select.success {
	border-color: var(--color-success) !important;
}

.form-control:invalid:not(:placeholder-shown),
.form-control.fail,
.form-select.fail {
	border-color: var(--color-error) !important;
	background-color: rgba(239, 68, 68, 0.05);
}

/* textarea with form-control */
.form-control[multiple],
textarea.form-control {
	padding: 0.15rem 0.4rem;
	tab-size: 4;
	white-space: pre;
	word-wrap: normal;
}

/* form-check: match amc-checkbox (flex, align, gap) */
.form-check {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	min-height: 1.25rem;
	/* padding-left: 0; */
}

.form-check-input {
	width: 1em;
	height: 1em;
	margin: 0;
	outline: none;
	border: 1px solid var(--bs-border-color-translucent);
	background-color: var(--bs-body-bg);
	transition: border-color 0.2s ease, background-color 0.2s ease;
	flex-shrink: 0;
}

.form-check-input:hover {
	border-color: var(--bs-border-color);
}

.form-check-input:focus {
	border-color: var(--bs-border-color);
	box-shadow: 0 0 0 2px rgba(var(--bs-primary-rgb, 66, 153, 225), 0.2);
}

.form-check-input:checked {
	background-color: var(--bs-primary, #4299e1);
	border-color: var(--bs-primary, #4299e1);
}

.form-check-label {
	font-size: var(--font-size-xs, 0.8125rem);
	user-select: none;
	cursor: pointer;
}

/* form-switch (toggle) */
.form-check.form-switch .form-check-input {
	width: 2rem;
	height: 1rem;
	border-radius: 999px;
}

.form-check.form-switch .form-check-input:checked {
	background-color: var(--bs-primary, #4299e1);
	border-color: var(--bs-primary, #4299e1);
}

.form-text {
	margin-top: 0.25rem;
	font-size: var(--font-size-xs, 0.8125rem);
	color: var(--bs-secondary-color);
}

.input-group .form-control,
.input-group .form-select {
	border-radius: 0;
}

.input-group .form-control:first-child,
.input-group .form-select:first-child {
	border-radius: var(--bs-border-radius, 0.25rem) 0 0 var(--bs-border-radius, 0.25rem);
}

.input-group .form-control:last-child,
.input-group .form-select:last-child {
	border-radius: 0 var(--bs-border-radius, 0.25rem) var(--bs-border-radius, 0.25rem) 0;
}

.btn-xs {
	padding: 4px 6px !important;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    max-height: 20px;
}

.form-range {
	height: 4px !important;
	background-color: rgba(100, 116, 139, 0.3) !important;
	border-radius: 0 !important;
	cursor: pointer;
	transition: all 0.2s ease;
}

.form-range::-webkit-slider-thumb {
	width: 14px !important;
	height: 14px !important;
	background-color: var(--bs-primary, #4299e1) !important;
	border: 2px solid rgba(45, 55, 72, 0.8) !important;
	border-radius: 2px !important;
	cursor: pointer;
	appearance: none !important;
	-webkit-appearance: none !important;
	transition: all 0.2s ease;
	box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
}

.form-range::-moz-range-thumb {
	width: 14px !important;
	height: 14px !important;
	background-color: var(--bs-primary, #4299e1) !important;
	border: 2px solid rgba(45, 55, 72, 0.8) !important;
	border-radius: 2px !important;
	cursor: pointer;
	transition: all 0.2s ease;
	box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
}

.form-range::-ms-thumb {
	width: 14px !important;
	height: 14px !important;
	background-color: var(--bs-primary, #4299e1) !important;
	border: 2px solid rgba(45, 55, 72, 0.8) !important;
	border-radius: 2px !important;
	cursor: pointer;
	transition: all 0.2s ease;
	box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
}

.form-range:hover {
	background-color: rgba(100, 116, 139, 0.4) !important;
}

.form-range:hover::-webkit-slider-thumb {
	transform: scale(1.15);
	box-shadow: 0 3px 6px rgba(0, 0, 0, 0.3);
}

.form-range:hover::-moz-range-thumb {
	transform: scale(1.15);
	box-shadow: 0 3px 6px rgba(0, 0, 0, 0.3);
}

.form-range:hover::-ms-thumb {
	transform: scale(1.15);
	box-shadow: 0 3px 6px rgba(0, 0, 0, 0.3);
}

.form-range:active::-webkit-slider-thumb {
	transform: scale(1.1);
}

.form-range:active::-moz-range-thumb {
	transform: scale(1.1);
}

.form-range:active::-ms-thumb {
	transform: scale(1.1);
}

.form-range::-webkit-slider-runnable-track {
	height: 4px !important;
	background-color: rgba(100, 116, 139, 0.3) !important;
}

.form-range::-moz-range-track {
	height: 4px !important;
	background-color: rgba(100, 116, 139, 0.3) !important;
}

.form-range::-ms-track {
	height: 4px !important;
	background-color: rgba(100, 116, 139, 0.3) !important;
}

/* utils */
.w-0 {
	width: unset;
}

/* Sidebar Widget quick fix*/
.SidebarWidget {
	display: flex !important;
}

#map-dataset-export-dialog {
	max-width: 98vw !important;
	max-height: 98vh !important;
	overflow: hidden;
}

#map-dataset-export-dialog .modal-footer {
	position: absolute;
    bottom: 0px;
    left: 0;
    right: 0;
    background: var(--bg-color-primary);
}

/* Map Dialog Layout Improvements */
.map-dataset-export-container {
	overflow: hidden;
}

.map-dataset-export-container .card {
	overflow: hidden;
}

.map-dataset-export-container .card-body {
	overflow: auto;
}

.map-item {
	border: 1px solid transparent;
	border-radius: var(--bs-border-radius-sm);
	padding: 16px;
	transition: all 0.2s ease;
	margin-bottom: 12px;
}

.map-item:hover {
	border-color: var(--accent);
	background-color: var(--accent-muted);
	transform: translateY(-2px);
	box-shadow: 0 8px 25px color-mix(in srgb, var(--accent) 20%, transparent);
}

.map-item .minimap-preview {
	transition: transform 0.2s ease;
}

.map-item:hover .minimap-preview {
	transform: scale(1.1);
}

.minimap-placeholder {
	background: linear-gradient(45deg, #4a5568 25%, transparent 25%), 
	            linear-gradient(-45deg, #4a5568 25%, transparent 25%), 
	            linear-gradient(45deg, transparent 75%, #4a5568 75%), 
	            linear-gradient(-45deg, transparent 75%, #4a5568 75%);
	background-size: 8px 8px;
	background-position: 0 0, 0 4px, 4px -4px, -4px 0px;
}

/* Map List Dialog Improvements */
.list-group-item {
	transition: all 0.2s ease;
	margin-bottom: 8px;
	border-radius: var(--bs-border-radius-sm) !important;
}

.list-group-item:hover {
	background-color: var(--accent-muted);
	transform: translateX(4px);
	box-shadow: 0 4px 12px color-mix(in srgb, var(--accent) 20%, transparent);
}

.list-group-item img {
	transition: transform 0.2s ease;
}

.list-group-item:hover img {
	transform: scale(1.05);
}

/* Custom Scrollbars */
.overflow-auto::-webkit-scrollbar {
	width: 6px;
}

.overflow-auto::-webkit-scrollbar-track {
	background: rgba(45, 55, 72, 0.3);
	border-radius: var(--bs-border-radius-sm);
}

.overflow-auto::-webkit-scrollbar-thumb {
	background: linear-gradient(135deg, #4a5568 0%, #2d3748 100%);
	border-radius: var(--bs-border-radius-sm);
}

.overflow-auto::-webkit-scrollbar-thumb:hover {
	background: linear-gradient(135deg, var(--accent) 0%, var(--accent-hover) 100%);
}

/* Modern Cards */
.card {
	transition: all 0.2s ease;
}

.card:hover {
	transform: translateY(-2px);
	box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
}

/* Draggable Window Improvements */
.draggable-window {
	animation: windowFadeIn 0.3s ease-out;
}

@keyframes windowFadeIn {
	from {
		opacity: 0;
		transform: translate(-50%, -50%) scale(0.9);
	}
	to {
		opacity: 1;
		transform: translate(-50%, -50%) scale(1);
	}
}

/* Progress Bar Improvements */
.progress {
	background: rgba(45, 55, 72, 0.8);
	border-radius: var(--bs-border-radius-sm);
	overflow: hidden;
}

.progress-bar {
	background: linear-gradient(135deg, var(--accent) 0%, var(--accent-active) 100%);
	border-radius: var(--bs-border-radius-sm);
	transition: width 0.3s ease;
}

/* Loading States */
.spinner-border {
	color: var(--accent);
}

/* Tab Transition Animations */
.tab-transition {
	transition: all 0.2s ease-in-out;
}

.tab-hidden {
	opacity: 0.3;
	transform: translateX(-10px);
}

.tab-visible {
	opacity: 1;
	transform: translateX(0);
}

/* Mode Transitioning Effect */
.mode-transitioning {
	position: relative;
}

.mode-transitioning::before {
	content: '';
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	bottom: 0;
	background: linear-gradient(45deg, transparent 30%, rgba(255, 255, 255, 0.1) 50%, transparent 70%);
	animation: mode-transition-sweep 0.4s ease-out;
	pointer-events: none;
	z-index: 999;
}

@keyframes mode-transition-sweep {
	0% {
		transform: translateX(-100%);
	}
	100% {
		transform: translateX(100%);
	}
}

/* Settings Dialog Styles */
#settings-dialog .Panels {
	padding: var(--spacing-2);
}

/* Shortcuts Settings Styles */
.shortcuts-settings .shortcut-input {
	text-align: center;
	background: var(--bg-color-secondary);
	border: 1px solid var(--border-color-base);
}

.shortcuts-settings .shortcut-input:focus {
	background: var(--bg-color-primary);
	border-color: var(--color-blue-500);
	box-shadow: 0 0 0 0.2rem rgba(13, 110, 253, 0.25);
}

.shortcuts-settings .shortcut-row {
	background: var(--bg-color-primary);
	border: 1px solid var(--border-color-base);
	transition: all 0.2s ease;
}

.shortcuts-settings .shortcut-row:hover {
	background: var(--bg-color-secondary);
	border-color: var(--color-blue-500);
}

/* Body Mode Classes for Global Styling */

body.edit-mode-terrain .brush-cursor {
	border-color: #8b4513;
}

body.edit-mode-texture .brush-cursor {
	border-color: #ff6b35;
}

body.edit-mode-altitude .brush-cursor {
	border-color: #007bff;
}

body.edit-mode-wall .brush-cursor {
	border-color: #dc3545;
}

/* osx */

.Panel {
	-moz-user-select: none;
	-webkit-user-select: none;
	-ms-user-select: none;

	/* No support for these yet */
	-o-user-select: none;
	user-select: none;
}

/* Ensure sidebar panels can handle dynamic content - flat dark theme */
#sidebar .Panel {
	color: var(--bs-body-color);
	border-top: 1px solid var(--border-base);
	background: var(--surface-1);
	display: flex;
	flex-direction: column;
	min-height: 0;
	height: 100%;
	overflow-y: auto;
	overflow-x: hidden;
}

/* Parent containers handle ALL scrolling */
.sidebar-content,
.Panels,
#sidebar .Panels,
#OutlinerSidebar .Panels {
	overflow-y: auto;
	overflow-x: hidden;
	flex: 1;
	min-height: 0;
}

.TabbedPanel {
	display: flex;
	-moz-user-select: none;
    -webkit-user-select: none;
    -ms-user-select: none;
    -o-user-select: none;
    user-select: none;
    position: relative;
    width: 100%;
    height: 100%;
}

.TabbedPanel .Tabs {
	position: relative;
    z-index: 1;
    display: block;
    width: 100%;
    white-space: pre;
    overflow: hidden;
    border-bottom: 1px solid var(--border-base);
    height: 1.6rem;
    flex-shrink: 0;
    background: var(--surface-2);
}

.TabbedPanel-vertical .Tabs {
	display: flex;
	flex-direction: column;
	width: unset;
	border-bottom: none;
	height: unset;
	overflow: auto; /* Independent scrolling for vertical tabs */
	flex-shrink: 0; /* Prevent vertical tabs from shrinking */

}
/* Vertical tab borders based on side */
.TabbedPanel-left .Tabs {
	border-right: 1px solid var(--border-color-base);
}

.TabbedPanel-right .Tabs {
	border-left: 1px solid var(--border-color-base);
}

.TabbedPanel-top .Tabs {
	border-bottom: 1px solid var(--border-color-base);
}

.TabbedPanel-bottom .Tabs {
	border-top: 1px solid var(--border-color-base);
}

.TabbedPanel .Tabs::-webkit-scrollbar {
	height: 5px;
	background: var(--bg-color-secondary);
}

.TabbedPanel .Tabs::-webkit-scrollbar-thumb {
	background: var(--color-blue-500, #08f3);
}

.TabbedPanel .Tabs:hover::-webkit-scrollbar-thumb {
	background: var(--color-blue-600, #08f);
	cursor: ew-resize;
}

.TabbedPanel .Tabs .Tab {
	padding: 0.2rem 0.750rem;
    text-transform: uppercase;
    border-bottom: 1px solid var(--border-subtle);
    border-right: 1px solid var(--border-base);
    cursor: pointer;
    transition: all var(--uk-dur-fast) var(--uk-ease);
    font-size: 0.75rem;
    font-weight: 500;
    color: var(--text-2);
    background: var(--surface-1);
}

.TabbedPanel .Tabs .Tab:hover {
	background-color: var(--surface-2);
	color: var(--text-1);
}

.TabbedPanel .Tabs .Tab.selected {
	background-color: var(--accent);
	color: var(--text-on-accent);
	border-bottom-color: var(--accent);
}

.TabbedPanel .Panels {
    width: 100%;
    overflow: auto; /* Independent scrolling for panels */
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0; /* Allow flex to shrink */
}

/* Listbox */
.Listbox {
	color: var(--text-color-primary);
	background-color: var(--bg-color-primary);
	padding: 0;
	width: 100%;
	min-height: 180px;
	font-size: var(--bs-body-font-size);
	cursor: default;
	overflow: auto;
}

.Listbox .ListboxItem {
	padding: var(--spacing-2);
	color: var(--text-color-secondary);
	white-space: nowrap;
}

.Listbox .ListboxItem.active {
	background-color: var(--color-blue-50, rgba(0, 0, 0, 0.04));
}

/* CodeMirror */

.CodeMirror {
	position: absolute !important;
	width: 100% !important;
	background: none !important;
}

.CodeMirror.cm-s-monokai {
	height: calc(100% - 37px) !important;
}

.CodeMirror pre.CodeMirror-line, .CodeMirror pre.CodeMirror-line-like {
	padding-right: 50px !important;
}

.CodeMirror-foldgutter-open, .CodeMirror-foldgutter-folded {
	margin-left: 5px !important;
}

.CodeMirror-line span {
	font-family: var(--bs-font-monospace) !important;
	font-size: var(--font-size-base) !important;
}

button {
	border: 0px;
}

button:hover {
	cursor: pointer;
	transition: all 0.2s ease;
	background: rgba(255, 255, 255, 0.1);
	transform: translateY(-1px);
}

button:active {
	transform: translateY(0);
	background: rgba(255, 255, 255, 0.15);
}


/* Modern History Panel Styles */
.history-header-section {
	display: flex;
	align-items: center;
	gap: 4px;
	padding: 4px 2px;
	font-size: 10px;
	font-weight: 600;
	color: var(--text-color-primary);
	text-transform: uppercase;
	letter-spacing: 0.3px;
	border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

.history-header-section i {
	font-size: 10px;
	opacity: 0.7;
}

.history-controls-section {
	padding: 4px 2px;
	border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

.history-clear-section {
	padding: 4px 2px;
}

.history-clear-btn {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 4px;
	width: 100%;
	height: 22px;
	background: rgba(239, 68, 68, 0.15);
	border: 1px solid rgba(239, 68, 68, 0.3);
	color: rgba(252, 165, 165, 0.9);
	font-size: 9px;
	font-weight: 500;
	border-radius: 3px;
	transition: all 0.2s ease;
}

.history-clear-btn i {
	font-size: 9px;
}

.history-clear-btn:hover {
	background: rgba(239, 68, 68, 0.25);
	border-color: rgba(239, 68, 68, 0.5);
	color: rgba(252, 165, 165, 1);
	transform: translateY(-1px);
}

.history-clear-btn:active {
	transform: translateY(0);
	background: rgba(239, 68, 68, 0.3);
}


/* UI */

#resizer {
	position: absolute;
	z-index: 2;
	top: 32px;
	right: 350px;
	width: 5px;
	bottom: 0px;
	transform: translatex(2.5px);
	cursor: col-resize;
	transition: opacity 0.2s ease;
}

#resizer:hover {
	background-color: var(--color-blue-400);
	opacity: 0.5;
	transition-property: background-color;
	transition-delay: 0.1s;
	transition-duration: var(--transition-base);
}

#resizer:active {
	background-color: var(--color-blue-500);
}

/* Label+input rows (sidebar, dialogs, etc.) – shared with UIInputRows */
.Row {
	display: flex;
	align-items: center;
	overflow-y: hidden !important;
	flex-direction: row !important;
	margin-bottom: var(--spacing-2);
}

.Row .Label {
	width: 120px;
	font-size: var(--bs-body-font-size);
	user-select: none;
}

/* Sidebar Data Components Styling */
.sidebar-content {
	height: calc(100vh - 62px);
	overflow-y: auto;
}

.rsw-section, .gnd-section, .gat-section, .terrain-section {
	margin-bottom: var(--spacing-1);
	padding: var(--spacing-2);
	border: 1px solid var(--border-base);
	border-radius: 0;
	background: var(--surface-1);
}

.section-title {
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.5px;
	margin-bottom: var(--spacing-2);
	font-size: 0.7rem;
	color: var(--text-2);
	border-bottom: 1px solid var(--border-base);
	padding-bottom: var(--spacing-1);
}

.data-row {
	display: flex;
    justify-content: space-between;
    padding: 2px 4px;
    border-bottom: 1px solid var(--border-color-base);
    font-size: var(--font-size-xs) !important; /* Always XS */
    flex-direction: row !important;
	transition: background-color 0.2s ease;
	line-height: 1.6;
	min-height: 16px;
}
.data-row:hover {
	background-color: var(--bg-color-secondary);
}
.data-row.last {
	border-bottom: none;
}
.data-row .data-key {
	/* font-weight: 600; */
	flex: 1 0 45%;
	font-size: var(--font-size-xs) !important;
}
.data-row .data-value {
	flex: 0 0 50%;
	text-align: right;
	word-break: break-all;
	font-size: var(--font-size-xs) !important;
}
.widget-container {
	background: var(--bg-color-tertiary);
	border: 1px solid var(--border-color-base);
	border-radius: var(--bs-border-radius-sm);
	padding: 4px 6px; /* Minimal padding */
	margin: 2px 0;
}
.widget-title {
	font-size: var(--font-size-xs) !important; /* Always XS */
	font-weight: 600;
	color: var(--text-color-primary);
	text-transform: uppercase;
	letter-spacing: 0.3px;
	margin-bottom: 2px;
	display: block;
	line-height: 1.2;
}

.texture-item {
	font-family: var(--bs-font-monospace);
	font-size: calc(var(--bs-body-font-size) - 1px);
	color: var(--text-color-secondary);
}

/* GAT specific styling */
.data-row.walkable {
	color: var(--color-success);
}

.data-row.non-walkable {
	color: var(--color-danger);
}

.data-row.water {
	color: var(--color-info);
}

.data-row.snipable {
	color: var(--color-warning);
}


.Panels #textures,
.Panels #terrain {
	height: 100%;
}

#sidebar .d-flex.justify-content-between {
	flex-direction: row !important;
}

/* --- Sidebar UI/UX Fine-tuning --- */
.sidebar-content {
    height: 100%;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    padding: var(--spacing-2) 0;
    gap: var(--spacing-2);
}

.sidebar-section {
    margin-bottom: 2px;
    padding: 4px 6px; /* Minimal padding */
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius-sm);
}
.sidebar-section:focus-within,
.sidebar-section:hover {
    box-shadow: 0 2px 8px rgba(0,0,0,0.08);
    border-color: var(--color-blue-400);
}

.section-title {
    font-weight: 600;
    font-size: var(--font-size-xs) !important; /* XS size */
    margin-bottom: 4px;
    letter-spacing: 0.3px;
    border-bottom: 1px solid var(--border-color-base);
    padding-bottom: 2px;
    text-transform: uppercase;
    line-height: 1.2;
}

.accordion-item {
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius-sm);
    margin-bottom: 2px;
}
.accordion-item:focus-within,
.accordion-item:hover {
    border-color: var(--color-blue-400);
}

.accordion-header {
    cursor: pointer;
    padding: 3px 6px !important; /* Minimal padding */
    border-bottom: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius-sm) var(--bs-border-radius-sm) 0 0;
    display: flex;
    align-items: center;
    gap: 4px;
    font-weight: 600;
    font-size: var(--font-size-xs) !important; /* XS size */
    transition: background-color 0.2s;
    outline: none;
    min-height: 20px;
    overflow: hidden;
    white-space: nowrap;
    line-height: 1.2;
}
.accordion-header:hover,
.accordion-header:focus {
    background: var(--bg-color-tertiary);
}

.accordion-body {
    padding: 4px 6px; /* Minimal padding */
    border-radius: 0 0 var(--bs-border-radius-sm) var(--bs-border-radius-sm);
    overflow: visible;
    min-height: fit-content;
    font-size: var(--font-size-xs) !important; /* XS size */
}

/* Custom scrollbar improvements */
.overflow-y-auto::-webkit-scrollbar {
    width: 6px;
}

.overflow-y-auto::-webkit-scrollbar-track {
    background: var(--bg-color-secondary);
    border-radius: var(--bs-border-radius-sm);
}

.overflow-y-auto::-webkit-scrollbar-thumb {
    background: var(--text-color-secondary);
    border-radius: var(--bs-border-radius-sm);
}

.overflow-y-auto::-webkit-scrollbar-thumb:hover {
    background: var(--text-color-primary);
}

/* Screen reader only text */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* Animation improvements */
.accordion-header {
    transition: background-color 0.2s ease-in-out;
}

.accordion-header:hover {
    background-color: var(--bg-color-quaternary);
}

/* SidebarRSW specific refinements */
#sidebar-rsw {
	font-size: var(--font-size-xs);
}

#sidebar-rsw .accordion-header {
	flex-direction: row !important;
	align-items: center;
	transition: all 0.2s ease;
	border: 1px solid var(--bs-border-color);
}

#sidebar-rsw .accordion-header:hover {
	background-color: var(--bs-secondary-bg-subtle);
	border-color: var(--bs-primary);
}

#sidebar-rsw .accordion-title {
	flex-direction: row !important;
	gap: var(--spacing-1);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
	min-width: 0;
}

#sidebar-rsw .accordion-body {
	overflow: visible;
	min-height: fit-content;
	font-size: var(--font-size-xs);
}

#sidebar-rsw .rsw-kv {
	gap: 8px;
}

#sidebar-rsw .rsw-kv .rsw-value {
	max-width: 70%;
	text-align: right;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

#sidebar-rsw .table thead th {
	position: sticky;
	top: 0;
	background: var(--bs-secondary-bg);
	z-index: 10;
	font-size: var(--font-size-xs);
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.5px;
}

#sidebar-rsw .table tbody td {
	vertical-align: middle;
	font-size: var(--font-size-xs);
}

#sidebar-rsw .rsw-card {
	user-select: none;
}

#sidebar-rsw .form-control[type="color"] {
	padding: 0;
	min-height: 28px;
	height: 28px;
	border-radius: var(--bs-border-radius-sm);
}

#sidebar-rsw .form-range {
	padding: 0;
	margin: 0;
	height: 20px;
}

#sidebar-rsw .small div {
	flex-direction: row !important;
}

/* Professional card styling */
#sidebar-rsw .card {
	border: 1px solid var(--bs-border-color);
	transition: all 0.2s ease;
}

#sidebar-rsw .card:hover {
	transform: translateY(-1px);
	box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

/* Badge improvements */
#sidebar-rsw .badge {
	font-size: var(--font-size-xs);
	padding: 0.25rem 0.5rem;
}

/* List group improvements */
#sidebar-rsw .list-group-item {
	font-size: var(--font-size-xs);
	padding: 0.5rem;
}

/* Form improvements */
#sidebar-rsw .form-label {
	font-size: var(--font-size-xs);
	font-weight: 600;
	margin-bottom: 0.25rem;
}

#sidebar-rsw .form-control,
#sidebar-rsw .form-select {
	font-size: var(--font-size-xs);
}

/* Cursor pointer for interactive elements */
#sidebar-rsw .cursor-pointer {
	cursor: pointer;
}

/* Responsive improvements */
@media (max-width: 768px) {
	#sidebar-rsw .accordion-body {
		overflow: visible;
		min-height: fit-content;
	}
}

/* Focus improvements for accessibility (form focus in Bootstrap form overrides above) */
.btn:focus {
    outline: 0;
}

/* Table improvements */
.table-responsive {
    border-radius: var(--bs-border-radius-sm);
    overflow: hidden;
}

.table-sm th,
.table-sm td {
    padding: 0.25rem;
    font-size: var(--font-size-xs);
}

/* Card improvements */
.card {
    transition: transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
}

.card:hover {
    transform: translateY(-1px);
}

/* Grid improvements */
.row {
    margin-left: -0.25rem;
    margin-right: -0.25rem;
	flex-direction: row !important;
}

.row > * {
    padding-left: 0.25rem;
    padding-right: 0.25rem;
}

/* Texture gallery improvements */
.texture-gallery {
    max-height: 300px;
    overflow-y: auto;
    border-radius: var(--bs-border-radius-sm);
}

.texture-gallery .card {
    transition: transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
}

.texture-gallery .card:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}

/* Model Information Section Styles */
.model-info-section {
    border: 1px solid var(--border-color-base);
    border-radius: 4px;
    padding: 10px;
    margin: 10px 0;
}

.model-info-section .Label {
    font-weight: 600;
    color: var(--text-color-primary);
    min-width: 80px;
}

.model-info-section .type {
    font-family: monospace;
    font-size: 10px;
    padding: 2px 4px;
    border-radius: 2px;
    background: var(--bg-color-secondary);
    color: var(--text-color-secondary);
}

/* RSM Animation Info Styles */
.rsm-animation-info {
    background: var(--bg-color-tertiary);
    border: 1px solid var(--border-color-accent);
    border-radius: 4px;
    margin-top: 10px;
    padding: 10px;
}

.rsm-animation-info .Label {
    font-weight: 600;
    color: var(--text-color-primary);
    min-width: 100px;
}

/* Animated node indicator in outliner */
.type.Animated {
    background: #ff6b6b !important;
    color: white !important;
    font-weight: bold !important;
}

/* Sidebar.TextureEditor */
.texture-list {
	overflow-x: hidden;
}
.texture-entry {
	margin-bottom: var(--spacing-1);
    padding: var(--spacing-1);
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius-sm);
    background-color: var(--bg-color-secondary);
    display: flex;
    gap: var(--spacing-2);
    align-items: flex-start;
}
.image-column {
	flex: 0 0 128px;
    display: flex;
    flex-direction: column;
    align-items: center;
}
.canvas-container {
	text-align: center;
    width: 128px;
    height: 128px;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: var(--bg-color-secondary);
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius-sm);
    overflow: hidden;
}
.action-btn-sm {
	width: 24px;
    height: 24px;
    padding: 0px;
    border: 1px solid transparent;
    border-radius: var(--bs-border-radius-sm);
    background-color: var(--bg-color-secondary);
    cursor: pointer;
}
.action-btn-sm:hover {
	background-color: var(--bg-color-primary);
	transition: background-color 0.2s ease-in-out;
}
.action-btn-sm:active {
	background-color: var(--bg-color-primary);
	border-color: var(--color-blue-400);
	transition: background-color 0.2s ease-in-out;
}

.map-heightmap-wrap {
	display: flex;
	position: absolute;
	top: 40px;
	right: 10px;
}
.map-heightmap-meta {
	color: rgb(153, 170, 187);
	position: absolute;
	bottom: 3px;
	right: 3px;
	background: black;
}
/* ===== (former main.css: app-shell layout + overlays) ===== */

:root {
    --top-toolbar-height: 2.5rem;
}

/* New Layout Structure - Header, Body, Footer */
body {
    margin: 0;
    padding: 0;
    height: 100vh;
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    overflow: hidden;
}

div, textarea {
    scrollbar-width: thin;
    scrollbar-color: rgba(255, 255, 255, 0.2) transparent;
    scroll-behavior: smooth;
    scroll-snap-type: y mandatory;
}

textarea {
    user-select: text;
    -webkit-user-select: text;
    -moz-user-select: text;
    -ms-user-select: text;
    -o-user-select: text;
    text-wrap: wrap;
}

option {
    background: var(--bg-color-primary);
    color: var(--bs-body-color);
	user-select: none;
	-webkit-user-select: none;
	-moz-user-select: none;
	-ms-user-select: none;
	-o-user-select: none;
}

#app {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
    overflow: hidden;
}

/* Header Section — in-flow row (toolbar / menubar). Not position:fixed:
   the body no longer needs padding-top to reserve space under it. */
   .app-header {
    position: relative;
    display: flex;
    align-items: stretch;
    flex: 0 0 auto;
    z-index: calc(var(--z-index-fixed) + 100);
    min-height: var(--top-toolbar-height);
    height: var(--top-toolbar-height);
    background: var(--surface-2);
    border-bottom: none;
    box-shadow: none;
}
.app-header button:hover,
.app-header button:active {
    transform: none;
}

/* Body Section — fills the space between header and footer. */
.app-body {
    flex: 1 1 auto;
    min-height: 0;
    position: relative;
    display: flex;
    overflow: hidden;
}

/* Footer Section — in-flow status bar host. Shrink-wraps content so
   .viewport-container's getBoundingClientRect excludes the chrome. */
.app-footer {
    position: relative;
    flex: 0 0 auto;
    z-index: calc(var(--z-index-fixed) + 100);
    background: linear-gradient(135deg, var(--bg-color-secondary) 0%, var(--bg-color-tertiary) 100%);
    border-top: 2px solid var(--border-color-base);
    box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.1);
}

/* Viewport Container */
.viewport-container {
    flex: 1;
    min-height: 0;
    min-width: 0;
    position: relative;
    background: var(--bg-color-primary);
    overflow: hidden;
    z-index: 1;
}

/* Enhanced Viewport */
#viewport {
    background: var(--bg-color-primary);
    border: none !important;
    width: 100% !important;
    height: 100% !important;
    position: relative;
    z-index: 1;
    pointer-events: auto;
}

#viewport .Text {
    text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.25);
    pointer-events: none;
}

#viewport canvas {
    border: none !important;
    box-shadow: inset 0 0 20px rgba(0, 0, 0, 0.1);
    width: 100% !important;
    height: 100% !important;
    position: relative;
    z-index: 1;
    pointer-events: auto;
}

.viewport-container:has(.ui-overlay.interactive:not(.collapsed)) #viewport canvas {
    pointer-events: auto;
}

#script {
    position: absolute;
    background-color: rgba(39, 40, 34, 0.9) !important;
    height: 80vh;
    width: 80vw;
    z-index: 1000;
    border-radius: 5px;
    border: 1px solid rgba(255, 255, 255, 0.1);
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
    justify-self: center;
    align-self: anchor-center;
}

/* Layered UI Elements - Semi-transparent overlays */
.ui-overlay {
    position: absolute;
    pointer-events: none;
    z-index: 999;
    transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

.ui-overlay.interactive {
    pointer-events: auto;
}

/* Ensure UI overlays capture all pointer events and prevent bubbling */
.ui-overlay.interactive * {
    pointer-events: auto;
}

/* Prevent text selection on UI elements to avoid interference */
.ui-overlay.interactive,
.ui-overlay.interactive * {
    user-select: none;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
}

/* Drag-to-resize handle for the shell side panels */
.panel-resize {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 7px;
    cursor: ew-resize;
    z-index: 1000;
    pointer-events: auto;
    transition: background 0.15s ease;
}
.panel-resize--right { right: -3px; }
.panel-resize--left { left: -3px; }
.panel-resize:hover { background: var(--accent-muted); }

/* Outliner Sidebar Overlay */
.outliner-overlay {
	top: 0;
	left: 0;
    width: 220px;
    /* Full height of the viewport container — the toolbar lives in .app-header
       above this host, so no toolbar offset is needed here. */
    height: 100%;
    background: var(--glass-panel);
    backdrop-filter: blur(var(--glass-blur));
    -webkit-backdrop-filter: blur(var(--glass-blur));
    border-right: 1px solid var(--glass-border);
    box-shadow: var(--glass-shadow);
    transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
    pointer-events: auto;
}

.outliner-overlay.collapsed {
		transform: translateX(-100%);
}

.outliner-overlay.collapsed .outliner-toggle {
    right: -20px;
}

.outliner-overlay.collapsed #OutlinerSidebar {
    opacity: 0;
    pointer-events: none;
    visibility: hidden;
}

.outliner-overlay .outliner-toggle {
    position: absolute;
    top: 10px;
    right: -20px;
    width: 20px;
    height: 40px;
    background: var(--glass-raised);
    backdrop-filter: blur(var(--glass-blur));
    -webkit-backdrop-filter: blur(var(--glass-blur));
    border: 1px solid var(--glass-border);
    border-left: none;
    border-radius: 0 var(--radius-md) var(--radius-md) 0;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-color-primary);
    font-size: 12px;
	transition: all 0.2s ease;
    pointer-events: auto;
    z-index: 999;
    user-select: none;
    -webkit-user-select: none;
}

.outliner-overlay .outliner-toggle:hover {
    background: var(--surface-3);
    border-color: var(--accent-border);
    color: var(--accent);
    transform: scale(1.05);
}

/* Dynamic Toolbar Overlay - for dat.GUI and other floating panels */
.dynamic-toolbar-overlay {
    /* Absolute inside .viewport-container, which already starts below the
       toolbar — so this is a plain margin, not a toolbar offset. */
    top: 10px;
    left: 300px; /* Keep distance from outliner (280px width + 20px margin) */
    width: auto;
    height: auto;
    max-width: 400px;
    max-height: calc(100% - 20px);
    pointer-events: none; /* Allow viewport interaction when no content */
    z-index: 998; /* Below outliner/sidebar but above viewport */
    overflow: visible;
}

/* When outliner is collapsed, move dynamic toolbar closer to left edge */
.outliner-overlay.collapsed ~ .dynamic-toolbar-overlay {
    left: 20px; /* Small margin from left edge */
    transition: left 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

/* Dynamic toolbar children (dat.GUI, dialogs, etc.) should capture events */
.dynamic-toolbar-overlay > * {
    pointer-events: auto;
}

/* dat.GUI styling within dynamic toolbar */
.dynamic-toolbar-overlay .dg.ac {
    position: relative !important;
    float: none !important;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border-radius: 8px;
    overflow: hidden;
    animation: slideInFromLeft 0.3s ease-out;
}

@keyframes slideInFromLeft {
    from {
        opacity: 0;
        transform: translateX(-20px);
    }
    to {
        opacity: 1;
        transform: translateX(0);
    }
}

/* FIX to do not show the close button (which is actually a toggle minimize button) */
.dynamic-toolbar-overlay .dg .close-button {
    display: none !important;
}

/* Smooth Transitions */
* {
    transition: background-color 0.2s ease, border-color 0.2s ease, transform 0.2s ease;
}

/* Loading States */
.loading-overlay {
	position: absolute;
    top: 0;
	left: 0;
    right: 0;
	bottom: 0;
    background: rgba(33, 37, 41, 0.8);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 999;
}

.loading-spinner {
    width: 40px;
    height: 40px;
    border: 3px solid rgba(255, 255, 255, 0.3);
    border-top: 3px solid var(--color-blue-500);
    border-radius: 50%;
    animation: spin 1s linear infinite;
}

@keyframes spin {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
}

/* Sidebar and Outliner Components */
#sidebar, #OutlinerSidebar {
    flex-direction: column;
}

/* Enhance the outliner options with better visual feedback */
#outliner .option {
	padding: 3px 6px;
	margin: 1px 0;
	transition: all 0.15s ease;
	border-radius: 3px;
	font-size: 10px;
	line-height: 1.4;
	position: relative;
}

#outliner .option:hover {
	background-color: rgba(255, 255, 255, 0.08) !important;
	padding-left: 8px;
}

#outliner .option.active {
	background: linear-gradient(90deg, color-mix(in srgb, var(--accent) 20%, transparent) 0%, color-mix(in srgb, var(--accent) 5%, transparent) 100%) !important;
	border-color: var(--accent-border);
	padding-left: 8px;
}

/* Better hierarchy visualization */
#outliner .opener {
	font-size: 9px;
	font-weight: bold;
	transition: transform 0.2s ease;
	width: 12px;
	height: 12px;
}

#outliner .opener:hover {
	transform: scale(1.1);
	color: var(--color-blue-400);
}

/* Ensure the outliner takes remaining space */
#OutlinerSidebar #outliner,
#OutlinerSidebar #history {
	min-height: 0; /* Important for flexbox scrolling */
	overflow-y: auto;
	overflow-x: hidden;
}

#OutlinerSidebar .outliner-filter-container {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
	align-items: center;
}

#OutlinerSidebar .outliner-type-filter {
	padding: 1px 2px;
    border: 1px solid rgba(255, 255, 255, 0.2);
	border-radius: 3px;
    background: rgba(255, 255, 255, 0.1);
	color: var(--text-color-primary);
	min-width: 80px;
}

#OutlinerSidebar .outliner-toggle-filter {
	display: flex;
	align-items: center;
	gap: 6px;
	color: var(--text-color-secondary);
	cursor: pointer;
	user-select: none;
	padding: 4px 6px;
	border-radius: 3px;
	transition: all 0.2s ease;
}

#OutlinerSidebar .outliner-toggle-filter:hover {
	background: rgba(255, 255, 255, 0.1);
	color: var(--text-color-primary);
}

#OutlinerSidebar .outliner-checkbox {
	margin: 0;
	accent-color: var(--color-blue-500);
}

/* #OutlinerSidebar .outliner-clear-filters {
	padding: 1px 2px;
    border: 1px solid rgba(255, 255, 255, 0.2);
	border-radius: 3px;
    background: rgba(255, 255, 255, 0.1);
	color: var(--text-color-secondary);
	cursor: pointer;
	transition: all 0.2s ease;
} */

#OutlinerSidebar .outliner-clear-filters:hover {
    background: rgba(255, 255, 255, 0.2);
	color: var(--text-color-primary);
	border-color: var(--color-blue-500);
}

/* Search highlight */
#outliner .search-highlight {
	background: #ffd700;
	color: #000;
	padding: 1px 2px;
	border-radius: 2px;
	font-weight: bold;
}

/* Scroll highlight effect */
#outliner .option.highlight-scroll {
    background: linear-gradient(90deg, rgba(255, 255, 0, 0.3) 0%, rgba(255, 255, 0, 0.1) 100%);
    border: 2px solid #ffd700;
    border-radius: 4px;
    box-shadow: 0 0 10px rgba(255, 215, 0, 0.5);
    animation: highlight-pulse 2s ease-out;
}

@keyframes highlight-pulse {
    0% {
        background: linear-gradient(90deg, rgba(255, 255, 0, 0.5) 0%, rgba(255, 255, 0, 0.3) 100%);
        box-shadow: 0 0 15px rgba(255, 215, 0, 0.8);
    }
    100% {
        background: linear-gradient(90deg, rgba(255, 255, 0, 0.3) 0%, rgba(255, 255, 0, 0.1) 100%);
        box-shadow: 0 0 10px rgba(255, 215, 0, 0.5);
    }
}

/* Texture atlas container in toolbar */
#texture-atlas-container {
	position: absolute;
	top: 100%;
	left: 0;
	right: 0;
    background: rgba(255, 255, 255, 0.1);
    border: 1px solid rgba(255, 255, 255, 0.2);
	border-top: none;
	padding: var(--spacing-2);
	max-height: 300px;
	overflow-y: auto;
	z-index: 999;
	box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}

#texture-atlas-container .texture-atlas-widget {
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid rgba(255, 255, 255, 0.2);
}

#texture-atlas-container .atlas-canvas {
    border: 1px solid rgba(255, 255, 255, 0.2) !important;
	max-height: 250px !important;
}

#texture-atlas-container .atlas-info {
    background: rgba(255, 255, 255, 0.1) !important;
	color: var(--text-color-primary) !important;
    border-color: rgba(255, 255, 255, 0.2) !important;
}

/* Dark chrome — unconditional (the app is dark-only, so this no longer hides
   behind prefers-color-scheme or :not(.theme-light)). */
#copy-toolbar.floating-toolbar {
	background: rgba(39, 43, 48, 0.9);
	border: 1px solid rgba(122, 130, 136, 0.8);
}

#copy-toolbar.floating-toolbar:hover {
	background: rgba(39, 43, 48, 0.95);
}

.texture-atlas-section {
    background: rgba(255, 255, 255, 0.1);
    border-color: rgba(255, 255, 255, 0.2);
}

.texture-atlas-widget {
    background: rgba(255, 255, 255, 0.05);
    border-color: rgba(255, 255, 255, 0.2);
}

.tile-info {
    background: rgba(255, 255, 255, 0.05);
    border-color: rgba(255, 255, 255, 0.2);
}

#copy-toolbar {
    background: rgba(255, 255, 255, 0.1);
    border-color: rgba(255, 255, 255, 0.2);
}

#copy-toolbar .toolbar-title {
	color: var(--color-blue-400);
}

#copy-toolbar .prefab-section {
    background: rgba(255, 255, 255, 0.15);
    border-color: rgba(255, 255, 255, 0.2);
}



/**
 * UIKit.css
 *
 * Centralised component design system for browJS.
 * Builds on top of variables.css tokens. Import once; use `ui-*` classes everywhere.
 * Inline styles are the intentional exception for instance-level overrides.
 *
 * Sections
 *  1. UIKit tokens
 *  2. Scrollbars
 *  3. Buttons
 *  4. Inputs – text / number / textarea
 *  5. Range slider
 *  6. Toggle switch
 *  7. Checkbox & radio
 *  8. Select
 *  9. Form fields
 * 10. Color swatch
 * 11. File drop zone
 * 12. Cards & panels
 * 13. Window
 * 14. Overlay / backdrop
 * 15. Dialogs (message, confirm, prompt)
 * 16. Toast
 * 17. Alert
 * 18. Badge
 * 19. Progress & spinner
 * 20. Tooltip
 * 21. Divider / separator
 * 22. Accordion
 * 23. Tabs
 * 24. Table
 * 25. List
 * 26. Tree
 * 27. Image preview & visualiser
 * 28. Context menu
 * 29. Utilities
 */

/* ============================================================
   1. UIKit tokens – extend variables.css without modifying it
   ============================================================ */

:root {
    /* surface layers — mapped onto the global semantic ramp (variables.css) */
    --uk-surface-0:         var(--surface-1);   /* panel base */
    --uk-surface-1:         var(--surface-2);   /* raised / input */
    --uk-surface-2:         var(--surface-3);   /* hover / selected */
    --uk-surface-raised:    var(--surface-2);
    --uk-overlay:           var(--surface-4);   /* menus / popovers / tooltips */
    --uk-keyline:           var(--keyline);     /* machined top-edge highlight */

    /* text */
    --uk-text-1:            var(--text-1);
    --uk-text-2:            var(--text-2);
    --uk-text-3:            var(--text-3);
    --uk-text-placeholder:  var(--text-3);

    /* borders */
    --uk-border:            var(--border-base);
    --uk-border-light:      var(--border-subtle);
    --uk-border-dark:       var(--border-strong);

    /* accent / signal / semantic */
    --uk-accent:            var(--accent);
    --uk-accent-hover:      var(--accent-hover);
    --uk-accent-active:     var(--accent-active);
    --uk-accent-muted:      var(--accent-muted);
    --uk-accent-text:       var(--text-on-accent);
    --uk-accent-border:     var(--accent-border);
    --uk-signal:            var(--signal);        /* armed tool / unsaved / attention */
    --uk-signal-hover:      var(--signal-hover);
    --uk-signal-muted:      var(--signal-muted);
    --uk-danger:            var(--status-danger);
    /* Semantic, not a raw palette step: the scale only has 500/600, and light's danger
       base is already darker than dark's -600 — so -600 hovered LIGHTER there. */
    --uk-danger-hover:      var(--status-danger-hover);
    --uk-success:           var(--status-success);
    --uk-warning:           var(--status-warning);
    /* Same reason: light's warning base IS -600, so this hover was a no-op there. */
    --uk-warning-hover:     var(--status-warning-hover);
    --uk-info:              var(--status-info);

    /* inputs — compact, flat (SettingsDialog / others.css) */
    --uk-input-bg:          var(--input-bg);
    --uk-input-text:        var(--input-text);
    --uk-input-border:      var(--input-border);
    --uk-input-focus:       var(--focus-color);
    --uk-input-radius:      var(--radius-xs);
    --uk-input-height:      24px;
    --uk-input-height-sm:   20px;
    --uk-input-height-xs:   18px;
    --uk-font-size:         0.75rem;
    --uk-font-size-lg:      0.9375rem;
    --uk-font-size-md:      0.8125rem;
    --uk-font-size-sm:      0.6875rem;
    --uk-font-size-xs:      0.625rem;
    --uk-focus-ring:        var(--focus-ring);
    --uk-track-bg:          var(--surface-3);
    --uk-switch-w:          28px;
    --uk-switch-h:          14px;
    --uk-switch-thumb:      10px;

    /* sizing — sharp, small radii */
    --uk-radius-sm:         var(--radius-xs);
    --uk-radius:            var(--radius-sm);
    --uk-radius-md:         var(--radius-base);
    --uk-radius-lg:         var(--radius-md);
    --uk-radius-xl:         var(--radius-lg);
    --uk-radius-full:       var(--radius-full);

    /* spacing shortcuts — tighter */
    --uk-gap-xs:            0.125rem;
    --uk-gap-sm:            var(--spacing-1);
    --uk-gap:               var(--spacing-2);
    --uk-gap-md:            var(--spacing-3);
    --uk-gap-lg:            var(--spacing-4);

    /* window / dialog chrome */
    --uk-chrome-bg:         var(--surface-1);
    --uk-chrome-header-bg:  var(--surface-2);
    --uk-chrome-shadow:     var(--shadow-lg);

    /* glass / instrument panels — the "DataExplorer" look (variables.css) */
    --uk-glass:            var(--glass-panel);
    --uk-glass-raised:     var(--glass-raised);
    --uk-glass-sunken:     var(--glass-sunken);
    --uk-glass-blur:       var(--glass-blur);
    --uk-glass-border:     var(--glass-border);
    --uk-glass-divider:    var(--glass-divider);
    --uk-glass-shadow:     var(--glass-shadow);

    /* motion */
    --uk-dur-fast:          var(--dur-fast);
    --uk-dur:               var(--dur);
    --uk-ease:              var(--ease-standard);
}


/* ============================================================
   2. Scrollbars
   ============================================================ */

.ui-scrollable,
.ui-scrollable-x,
.ui-scrollable-y {
    scrollbar-width: thin;
    scrollbar-color: var(--scrollbar-thumb-color) var(--scrollbar-track-color);
}

.ui-scrollable,
.ui-scrollable-y { overflow-y: auto; }
.ui-scrollable-x { overflow-x: auto; }
.ui-scrollable   { overflow: auto; }

.ui-scrollable::-webkit-scrollbar,
.ui-scrollable-x::-webkit-scrollbar,
.ui-scrollable-y::-webkit-scrollbar { width: 6px; height: 6px; }
.ui-scrollable::-webkit-scrollbar-track,
.ui-scrollable-x::-webkit-scrollbar-track,
.ui-scrollable-y::-webkit-scrollbar-track { background: var(--scrollbar-track-color); }
.ui-scrollable::-webkit-scrollbar-thumb,
.ui-scrollable-x::-webkit-scrollbar-thumb,
.ui-scrollable-y::-webkit-scrollbar-thumb {
    background: var(--scrollbar-thumb-color);
    border-radius: var(--border-radius-sm);
}
.ui-scrollable::-webkit-scrollbar-thumb:hover,
.ui-scrollable-x::-webkit-scrollbar-thumb:hover,
.ui-scrollable-y::-webkit-scrollbar-thumb:hover {
    background: var(--scrollbar-thumb-hover-color);
}


/* ============================================================
   3. Buttons
   ============================================================ */

.ui-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--uk-gap-sm);
    padding: 0 var(--uk-gap-sm);
    height: var(--uk-input-height);
    font-size: var(--uk-font-size);
    font-weight: 500;
    line-height: 1;
    white-space: nowrap;
    border: 1px solid transparent;
    border-radius: var(--uk-input-radius);
    cursor: pointer;
    user-select: none;
    transition:
        background-color var(--uk-dur-fast) var(--uk-ease),
        border-color     var(--uk-dur-fast) var(--uk-ease),
        color            var(--uk-dur-fast) var(--uk-ease);
    outline: none;
    box-shadow: none;
}

.ui-btn:focus-visible {
    box-shadow: var(--uk-focus-ring);
}

.ui-btn:disabled,
.ui-btn[aria-disabled="true"] {
    opacity: 0.45;
    cursor: not-allowed;
    pointer-events: none;
}

/* variants */
.ui-btn--primary {
    background: var(--uk-accent);
    color: var(--uk-accent-text);
    border-color: var(--uk-accent-border);
}
.ui-btn--primary:hover  { background: var(--uk-accent-hover); border-color: var(--uk-accent-hover); }
.ui-btn--primary:active { background: var(--uk-accent-active); border-color: var(--uk-accent-active); }

.ui-btn--secondary {
    background: var(--uk-surface-1);
    color: var(--uk-text-1);
    border-color: var(--uk-border);
}
.ui-btn--secondary:hover  { background: var(--uk-surface-2); }
.ui-btn--secondary:active { background: var(--uk-border); }

.ui-btn--ghost {
    background: transparent;
    color: var(--uk-text-2);
    border-color: transparent;
}
.ui-btn--ghost:hover  { background: rgba(255,255,255,0.07); color: var(--uk-text-1); }
.ui-btn--ghost:active { background: rgba(255,255,255,0.12); }

.ui-btn--danger {
    background: var(--uk-danger);
    color: #fff;
    border-color: var(--uk-danger);
}
.ui-btn--danger:hover  { background: var(--uk-danger-hover); border-color: var(--uk-danger-hover); }

.ui-btn--success {
    background: var(--uk-success);
    color: #fff;
    border-color: var(--uk-success);
}

.ui-btn--warning {
    background: var(--uk-warning);
    color: #1a1205;
    border-color: var(--uk-warning);
}
.ui-btn--warning:hover  { background: var(--uk-warning-hover); border-color: var(--uk-warning-hover); }

.ui-btn--link {
    background: transparent;
    color: var(--uk-accent);
    border-color: transparent;
    padding: 0 var(--uk-gap-sm);
}
.ui-btn--link:hover { color: var(--uk-accent-hover); text-decoration: underline; }

/* sizes */
.ui-btn--sm  { height: 20px; padding: 0 var(--uk-gap); font-size: var(--uk-font-size-sm); }
.ui-btn--lg  { height: 28px; padding: 0 var(--uk-gap-md); font-size: var(--uk-font-size); }
.ui-btn--xl  { height: 32px; padding: 0 var(--uk-gap-lg); font-size: 0.8125rem; }

/* icon-only */
.ui-btn--icon {
    padding: 0;
    width: var(--uk-input-height);
    border-radius: var(--uk-input-radius);
}
.ui-btn--icon.ui-btn--sm { width: 20px; }
.ui-btn--icon.ui-btn--lg { width: 28px; }

/* button group */
.ui-btn-wrapper {
    display: inline-flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--uk-gap);
}

/* A segmented control: one continuous strip, square joints, rounded end caps.

   `gap` and the joined borders below are mutually exclusive — with a gap, every button
   but the last renders visibly missing its right edge. The border rules are the ones
   that carry the segmented look (and the `--active` fill assumes it), so the gap goes.
   Use `.ui-flex.ui-gap-sm` for a row of buttons that should read as separate. */
.ui-btn-group {
    display: inline-flex;
    align-items: stretch;
    max-width: 100%;
}
.ui-btn-group > .ui-btn { border-radius: 0; border-right-width: 0; min-width: 0; }
.ui-btn-group > .ui-btn:first-child { border-radius: var(--uk-input-radius) 0 0 var(--uk-input-radius); }
.ui-btn-group > .ui-btn:last-child  { border-radius: 0 var(--uk-input-radius) var(--uk-input-radius) 0; border-right-width: 1px; }
.ui-btn-group > .ui-btn:only-child  { border-radius: var(--uk-input-radius); border-right-width: 1px; }

.ui-btn-group__item--active,
.ui-btn-group > .ui-btn.ui-btn-group__item--active {
    background: var(--uk-accent);
    /* border-color: var(--uk-accent); */
    color: var(--uk-accent-text);
}


/* ============================================================
   4. Inputs – text / number / textarea
   ============================================================ */

.ui-input,
.ui-textarea {
    display: block;
    width: 100%;
    height: var(--uk-input-height-sm);
    padding: 0.08rem 0.4rem;
    background: var(--uk-input-bg);
    color: var(--uk-input-text);
    border: 1px solid var(--uk-input-border);
    border-radius: var(--uk-input-radius);
    font-size: var(--uk-font-size-xs);
    font-family: inherit;
    outline: none;
    -webkit-appearance: none;
    appearance: none;
    transition: all var(--uk-dur-fast) var(--uk-ease);
    box-sizing: border-box;
}

.ui-input::placeholder,
.ui-textarea::placeholder { color: var(--uk-text-placeholder); }

.ui-input:focus,
.ui-textarea:focus {
    border-color: var(--uk-accent);
    box-shadow: 0 0 0 2px rgba(var(--uk-accent-rgb), 0.2);
}

.ui-input:disabled,
.ui-textarea:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.ui-input--error { border-color: var(--uk-danger) !important; }
.ui-input--error:focus { box-shadow: 0 0 0 2px rgba(238,95,91,0.25) !important; }

/* A textarea holds authored PROSE, not a field value, so it is set a step up from the
   shared input size above — deliberately here and not in the `.ui-input, .ui-textarea`
   block, which would rescale every text and number input in the app. */
.ui-textarea {
    height: auto;
    min-height: 44px;
    max-height: 200px;
    padding: 0.25rem 0.4rem;
    resize: vertical;
    font-size: var(--uk-font-size);
    line-height: 1.5;
}

/* inline variant – auto-width */
.ui-input--inline { width: auto; display: inline-block; }

/* number drag-scrub input */
.ui-input--number {
    /* width: 72px; */
    cursor: ns-resize;
    /* text-align: right; */
    padding: 0.08rem 0 0.08rem 0.35rem;
}


/* ── UKAIPrompt — textarea + corner "enhance with AI" button ──────────────
   The action cluster floats over the textarea's top-right corner, so it costs no
   layout. `--enhanceable` (set only while a provider is available) is what reserves
   the room for it, so a plain textarea keeps its full width. Both the constructor
   path and `UKAIPrompt.attach()` produce this markup, and `.ui-aiprompt__area` is
   added to the raw <textarea> in the attach case so a host dialog's own textarea
   styling (a descendant selector) still applies. */

.ui-aiprompt {
    position: relative;
    display: block;
    width: 100%;
}

/* A prompt is the primary thing the user AUTHORS in the AI flows, and ✨ rewrites it in
   place — so it has to be comfortable to read back, not just to fill in. One step above
   the textarea default, which is itself one above a field value. Call sites must not set
   an inline font-size: inline wins, and the `sm` ones read as a rendering bug next to
   this. */
.ui-aiprompt__area {
    font-size: var(--uk-font-size-md);
    line-height: 1.55;
}

/* Reserve the corner so typed text never runs under the buttons — one button's
   worth normally, two once ↩ Undo joins ✨ after an enhancement is applied. */
/* Deliberately 3 classes deep: `attach()` puts this over a host dialog's own
   textarea, whose styling is typically a `.host textarea` rule — this has to
   out-specify it or the reserved corner is lost and text runs under the buttons. */
.ui-aiprompt.ui-aiprompt--enhanceable > .ui-aiprompt__area { padding-right: 2.1rem; }
.ui-aiprompt.ui-aiprompt--enhanceable.ui-aiprompt--undoable > .ui-aiprompt__area { padding-right: 3.6rem; }

.ui-aiprompt__actions {
    position: absolute;
    top: 3px;
    right: 3px;
    display: flex;
    align-items: center;
    gap: 2px;
    /* The textarea's own resize grip lives bottom-right, so nothing collides. */
    z-index: 1;
}

.ui-aiprompt__btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    padding: 0;
    border: 1px solid transparent;
    border-radius: var(--uk-input-radius);
    background: transparent;
    color: var(--uk-text-3);
    font-size: 0.7rem;
    line-height: 1;
    cursor: pointer;
    opacity: 0.65;
    transition: opacity var(--uk-dur-fast), color var(--uk-dur-fast),
                background var(--uk-dur-fast), border-color var(--uk-dur-fast);
}

.ui-aiprompt__btn:hover:not(:disabled) {
    opacity: 1;
    color: var(--uk-accent);
    background: var(--tint-accent-bg, transparent);
    border-color: var(--tint-accent-bd, transparent);
}

.ui-aiprompt__btn:focus-visible {
    outline: none;
    opacity: 1;
    box-shadow: var(--uk-focus-ring);
}

.ui-aiprompt__btn:disabled { cursor: default; }

/* Enhancing: the wand keeps the accent colour and spins, so the wait is visible
   without adding a second element. */
.ui-aiprompt__btn--busy {
    opacity: 1;
    color: var(--uk-accent);
}
.ui-aiprompt__btn--busy > i { animation: ui-aiprompt-spin 1.1s linear infinite; }

/* The textarea stays editable while enhancing — only the buttons lock — but the
   pending replacement is signalled on the box itself. */
.ui-aiprompt--busy > .ui-aiprompt__area { border-color: var(--uk-accent); }

@keyframes ui-aiprompt-spin {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
    .ui-aiprompt__btn--busy > i { animation: none; }
}


/* ============================================================
   5. Range slider
   ============================================================ */

.ui-range {
    display: flex;
    align-items: center;
    gap: var(--uk-gap-sm);
    width: 100%;
}

.ui-range__track {
    -webkit-appearance: none;
    appearance: none;
    flex: 1;
    height: 4px;
    background: var(--uk-track-bg);
    border-radius: 0;
    outline: none;
    cursor: pointer;
}

.ui-range__track::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 14px;
    height: 14px;
    border-radius: 2px;
    background: var(--uk-accent);
    cursor: pointer;
    border: 2px solid rgba(45, 55, 72, 0.8);
    box-shadow: none;
    transition: transform var(--uk-dur-fast);
}
.ui-range__track::-webkit-slider-thumb:hover  { transform: scale(1.1); }
.ui-range__track::-moz-range-thumb {
    width: 14px;
    height: 14px;
    border-radius: 2px;
    background: var(--uk-accent);
    cursor: pointer;
    border: 2px solid rgba(45, 55, 72, 0.8);
    box-shadow: none;
}

.ui-range__value {
    min-width: 32px;
    text-align: right;
    font-size: var(--uk-font-size-sm);
    color: var(--uk-text-2);
    flex-shrink: 0;
}


/* ============================================================
   6. Toggle switch
   ============================================================ */

.ui-toggle {
    display: inline-flex;
    align-items: center;
    gap: var(--uk-gap-sm);
    cursor: pointer;
    user-select: none;
}

.ui-toggle__input { position: absolute; opacity: 0; width: 0; height: 0; }

.ui-toggle__track {
    position: relative;
    width: var(--uk-switch-w);
    height: var(--uk-switch-h);
    background: var(--uk-input-bg);
    border: 1px solid var(--uk-border-dark);
    border-radius: var(--uk-input-radius);
    transition: background var(--uk-dur-fast), border-color var(--uk-dur-fast);
    flex-shrink: 0;
}

.ui-toggle__track::after {
    content: '';
    position: absolute;
    top: 1px;
    left: 1px;
    width: var(--uk-switch-thumb);
    height: var(--uk-switch-thumb);
    border-radius: 1px;
    background: var(--uk-text-2);
    transition: transform var(--uk-dur-fast), background var(--uk-dur-fast);
}

.ui-toggle__input:checked + .ui-toggle__track {
    background: var(--uk-accent);
    border-color: var(--uk-accent);
}
.ui-toggle__input:checked + .ui-toggle__track::after {
    transform: translateX(calc(var(--uk-switch-w) - var(--uk-switch-thumb) - 3px));
    background: #fff;
}

.ui-toggle__input:focus-visible + .ui-toggle__track {
    box-shadow: var(--uk-focus-ring);
}

.ui-toggle__label { font-size: var(--uk-font-size); color: var(--uk-text-1); }

.ui-toggle--disabled { opacity: 0.45; cursor: not-allowed; }
.ui-toggle--disabled .ui-toggle__input { pointer-events: none; }


/* ============================================================
   7. Checkbox & radio
   ============================================================ */

.ui-check,
.ui-radio {
    display: inline-flex;
    align-items: center;
    gap: var(--uk-gap-sm);
    cursor: pointer;
    user-select: none;
    font-size: var(--uk-font-size);
    color: var(--uk-text-1);
    min-height: 1.25rem;
}

.ui-check input[type="checkbox"],
.ui-radio  input[type="radio"] {
    -webkit-appearance: none;
    appearance: none;
    margin: 0;
    border: 1px solid var(--uk-border-dark);
    background: var(--uk-input-bg);
    outline: none;
    cursor: pointer;
    position: relative;
    flex-shrink: 0;
    transition: background var(--uk-dur-fast), border-color var(--uk-dur-fast);
}

/* checkbox → compact squared switch */
.ui-check input[type="checkbox"] {
    width: var(--uk-switch-w);
    height: var(--uk-switch-h);
    border-radius: var(--uk-input-radius);
}

.ui-check input[type="checkbox"]::before {
    content: '';
    position: absolute;
    top: 1px;
    left: 1px;
    width: var(--uk-switch-thumb);
    height: var(--uk-switch-thumb);
    border-radius: 1px;
    background: var(--uk-text-2);
    transition: transform var(--uk-dur-fast), background var(--uk-dur-fast);
}

.ui-check input[type="checkbox"]:checked {
    background: var(--uk-accent);
    border-color: var(--uk-accent);
}

.ui-check input[type="checkbox"]:checked::before {
    transform: translateX(calc(var(--uk-switch-w) - var(--uk-switch-thumb) - 3px));
    background: #fff;
}

/* radio → square indicator */
.ui-radio input[type="radio"] {
    width: 14px;
    height: 14px;
    border-radius: var(--uk-input-radius);
}

.ui-radio input[type="radio"]:checked {
    border-color: var(--uk-accent);
    background: var(--uk-accent);
}

.ui-radio input[type="radio"]:checked::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 6px;
    height: 6px;
    border-radius: 1px;
    background: #fff;
}

.ui-check input:focus-visible,
.ui-radio input:focus-visible { box-shadow: var(--uk-focus-ring); }

.ui-radio-group {
    display: flex;
    flex-direction: column;
    gap: var(--uk-gap-xs);
}
.ui-radio-group--horizontal { flex-direction: row; flex-wrap: wrap; gap: var(--uk-gap-sm); }


/* ============================================================
   8. Select
   ============================================================ */

.ui-select {
    display: block;
    width: 100%;
    height: var(--uk-input-height-xs);
    padding: 0.08rem 1.5rem 0.08rem 0.35rem;
    background: var(--uk-input-bg);
    color: var(--uk-input-text);
    border: 1px solid var(--uk-input-border);
    border-radius: var(--uk-input-radius);
    font-size: var(--uk-font-size-xs);
    font-family: inherit;
    outline: none;
    cursor: pointer;
    -webkit-appearance: none;
    appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%2710%27 height=%276%27 viewBox=%270 0 10 6%27%3E%3Cpath fill=%27%23999%27 d=%27M0 0l5 6 5-6z%27/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 6px center;
    transition: all var(--uk-dur-fast) var(--uk-ease);
    box-sizing: border-box;
}

.ui-select:focus {
    border-color: var(--uk-input-focus);
    box-shadow: var(--uk-focus-ring);
}

.ui-select:disabled { opacity: 0.5; cursor: not-allowed; }

.ui-select option {
    background: var(--uk-surface-1);
    color: var(--uk-text-1);
}

.ui-select--inline { width: auto; display: inline-block; }


/* ============================================================
   9. Form fields (label + input + helper)
   ============================================================ */

.ui-field {
    display: flex;
    flex-direction: column;
    gap: var(--uk-gap-sm);
    width: 100%;
    margin-bottom: var(--uk-gap);
}
.ui-field:last-child { margin-bottom: 0; }

.ui-field--row {
    flex-direction: row;
    align-items: center;
    gap: var(--uk-gap-sm);
}

.ui-field__label {
    font-size: var(--uk-font-size-sm);
    font-weight: 500;
    color: var(--uk-text-2);
    white-space: nowrap;
}

.ui-field--row > .ui-field__label {
    flex: 0 0 auto;
    min-width: 90px;
}

/* label + inline (i) info badge, kept together as one column in row layout */
.ui-field__labelwrap {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}
.ui-field--row > .ui-field__labelwrap {
    flex: 0 0 auto;
    min-width: 90px;
}
.ui-field__labelwrap > .ui-field__label { min-width: 0; }

.ui-field--row > .ui-input,
.ui-field--row > .ui-select,
.ui-field--row > .ui-range,
.ui-field--row > .ui-textarea { flex: 1; }

/* toggle/checkbox rows: control takes the lead, badge trails it */
.ui-field--row > .ui-toggle,
.ui-field--row > .ui-checkbox { flex: 0 1 auto; }

.ui-field__helper {
    font-size: var(--uk-font-size-xs);
    color: var(--uk-text-3);
}

.ui-field__error {
    font-size: var(--uk-font-size-xs);
    color: var(--uk-danger);
}

/* grouped form rows */
.ui-form {
    display: flex;
    flex-direction: column;
    gap: var(--uk-gap-sm);
}

.ui-form--row { flex-direction: row; }

.ui-form--compact { gap: var(--uk-gap-xs); }

.ui-fieldset {
    border: 1px solid var(--uk-border-light);
    border-radius: var(--uk-input-radius);
    padding: var(--uk-gap-sm) var(--uk-gap);
    margin: 0;
}

.ui-fieldset > legend {
    font-size: var(--uk-font-size-sm);
    font-weight: 600;
    color: var(--uk-text-2);
    padding: 0 var(--uk-gap-xs);
}


/* ============================================================
   10. Color swatch
   ============================================================ */

.ui-swatch {
    display: inline-flex;
    align-items: center;
    gap: var(--uk-gap-sm);
    cursor: pointer;
}

.ui-swatch__chip {
    width: 18px;
    height: 18px;
    border-radius: var(--uk-input-radius);
    border: 1px solid rgba(255,255,255,0.15);
    flex-shrink: 0;
    box-shadow: none;
}

.ui-swatch__chip--checkerboard {
    background-image:
        linear-gradient(45deg, #888 25%, transparent 25%),
        linear-gradient(-45deg, #888 25%, transparent 25%),
        linear-gradient(45deg, transparent 75%, #888 75%),
        linear-gradient(-45deg, transparent 75%, #888 75%);
    background-size: 8px 8px;
    background-position: 0 0, 0 4px, 4px -4px, -4px 0;
}

.ui-swatch__value {
    font-size: var(--uk-font-size-sm);
    font-family: monospace;
    color: var(--uk-text-2);
}

.ui-swatch:hover .ui-swatch__chip { border-color: rgba(255,255,255,0.35); }


/* ============================================================
   11. File drop zone
   ============================================================ */

.ui-dropzone {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--uk-gap-xs);
    min-height: 64px;
    padding: var(--uk-gap-sm);
    border: 1px dashed var(--uk-border);
    border-radius: var(--uk-input-radius);
    background: var(--uk-surface-0);
    color: var(--uk-text-3);
    font-size: var(--uk-font-size);
    text-align: center;
    cursor: pointer;
    transition: border-color var(--uk-dur-fast), background var(--uk-dur-fast);
}

.ui-dropzone:hover,
.ui-dropzone--over {
    border-color: var(--uk-accent);
    background: rgba(0,123,255,0.05);
    color: var(--uk-text-2);
}

.ui-dropzone__icon { font-size: 1.5rem; opacity: 0.5; }


/* ============================================================
   12. Cards & panels
   ============================================================ */

.ui-panel {
    background: var(--uk-surface-1);
    border: 1px solid var(--uk-border-light);
    border-radius: var(--uk-input-radius);
    overflow: hidden;
}

.ui-panel__header {
    display: flex;
    align-items: center;
    gap: var(--uk-gap-xs);
    padding: 3px 6px;
    background: var(--uk-chrome-header-bg);
    border-bottom: 1px solid var(--uk-border-light);
    font-size: var(--uk-font-size);
    font-weight: 600;
    color: var(--uk-text-1);
    user-select: none;
    min-height: 20px;
    line-height: 1.2;
}

.ui-panel__header-actions {
    display: flex;
    align-items: center;
    gap: var(--uk-gap-xs);
    margin-left: auto;
}

.ui-panel__body {
    padding: 4px 6px;
}

.ui-panel__footer {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--uk-gap-xs);
    padding: 3px 6px;
    border-top: 1px solid var(--uk-border-light);
    background: var(--uk-surface-0);
}

/* card (flat panel) */
.ui-card {
    background: var(--uk-surface-1);
    border: 1px solid var(--uk-border-light);
    border-radius: var(--uk-input-radius);
    box-shadow: none;
    overflow: hidden;
}

.ui-card__header { padding: 3px 6px; border-bottom: 1px solid var(--uk-border-light); font-weight: 600; font-size: var(--uk-font-size); min-height: 20px; line-height: 1.2; }
.ui-card__body   { padding: 4px 6px; }
.ui-card__footer { padding: 3px 6px; border-top: 1px solid var(--uk-border-light); display: flex; gap: var(--uk-gap-xs); justify-content: flex-end; }

.ui-card--compact .ui-card__body { padding: 3px 4px; }
.ui-card--compact .ui-card__header { padding: 2px 4px; font-size: var(--uk-font-size-sm); }


/* ============================================================
   13. Window
   ============================================================ */

.ui-window {
    position: fixed;
    display: flex;
    flex-direction: column;
    background: var(--uk-chrome-bg);
    border: 1px solid var(--uk-border);
    border-radius: var(--uk-input-radius);
    box-shadow: var(--uk-chrome-shadow);
    overflow: hidden;
    box-sizing: border-box; /* so maximised width/height include the border */
    min-width: 200px;
    min-height: 80px;
    z-index: var(--z-index-fixed);
}

/* Maximised: drop the radius so the frame sits flush on the viewport edges. */
.ui-window--maximized {
    border-radius: 0;
}

.ui-window--focused {
    box-shadow: var(--uk-chrome-shadow);
    outline: 1px solid var(--uk-accent);
    z-index: calc(var(--z-index-fixed) + 1);
}

.ui-window__titlebar {
    display: flex;
    align-items: center;
    gap: var(--uk-gap-xs);
    padding: 0 var(--uk-gap-sm);
    height: 24px;
    background: var(--surface-3);
    border-bottom: 1px solid var(--uk-border-light);
    cursor: move;
    user-select: none;
    flex-shrink: 0;
}

.ui-window__title {
    flex: 1;
    font-size: var(--uk-font-size);
    font-weight: 600;
    color: var(--uk-text-1);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ui-window__controls {
    display: flex;
    align-items: center;
    gap: 4px;
    flex-shrink: 0;
}

/* Host-supplied titlebar adornments (counters, chips) — sit between the title and
   the window controls. See UKWindow.appendToTitlebar(). */
.ui-window__titlebar-slot {
    display: flex;
    align-items: center;
    gap: var(--uk-gap-sm);
    flex-shrink: 0;
    margin-right: var(--uk-gap-sm);
}

/* Backdrop for a modal UKWindow. NOT `.ui-overlay` — that one has its position/inset
   deliberately commented out (it would pile the sidebars up against the canvas), so it
   does not cover the viewport.

   A modal pair gets its own stacking level ABOVE ordinary windows: the backdrop on
   `--z-index-modal-backdrop` and the window it belongs to on `--z-index-modal`. Sitting
   the backdrop just below `--z-index-fixed` instead would leave every other window on top
   of the dimmer and still clickable — i.e. not modal at all. */
.ui-window__backdrop {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.55);
    backdrop-filter: blur(2px);
    z-index: var(--z-index-modal-backdrop);
    animation: uk-fade-in var(--uk-dur-fast) var(--uk-ease);
}

/* Compound selector so this beats `.ui-window--focused`'s z-index whichever order the
   two rules end up in. */
.ui-window.ui-window--modal,
.ui-window.ui-window--modal.ui-window--focused {
    z-index: var(--z-index-modal);
}

.ui-window__btn {
    width: 14px;
    height: 14px;
    border-radius: var(--uk-input-radius);
    border: 1px solid rgba(0, 0, 0, 0.15);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.5rem;
    transition: filter var(--uk-dur-fast);
    padding: 0;
    color: rgba(0,0,0,0.7);
    font-weight: 700;
}
.ui-window__btn:hover { filter: brightness(1.1); }

.ui-window__btn--close    { background: #ed6a5e; }
.ui-window__btn--minimize { background: #f5c451; }
.ui-window__btn--maximize { background: #61c355; }

/* The default is a plain BLOCK box that scrolls: right for a dialog whose content is a
   document (a form, a report), and deliberately left alone because most windows want it.

   A window whose content is a SHELL that must fill the frame — a wizard, a split view, an
   embedded browser — has to opt out in its own `className`-scoped block, and both halves
   are needed:

     .my-window .ui-window__content { padding: 0; display: flex; min-height: 0;
                                      overflow: hidden; }
     .my-shell                      { flex: 1; min-width: 0; }

   Without the second line the shell is `flex: 0 1 auto` in a ROW container, so it sizes to
   max-content and leaves dead space beside itself; without `overflow: hidden` above, the
   shell's own scrolling pane ends up nested inside a second scroll container. Any flex
   child further down that must scroll needs `min-height: 0` — the automatic minimum size
   otherwise refuses to let it shrink. */
.ui-window__content {
    flex: 1;
    overflow: auto;
    scrollbar-width: thin;
    scrollbar-color: var(--scrollbar-thumb-color) transparent;
}

.ui-window__content::-webkit-scrollbar         { width: 6px; height: 6px; }
.ui-window__content::-webkit-scrollbar-thumb   { background: var(--scrollbar-thumb-color); border-radius: 3px; }

.ui-window__footer {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--uk-gap-xs);
    padding: 3px 6px;
    border-top: 1px solid var(--uk-border-light);
    background: var(--uk-surface-0);
    flex-shrink: 0;
}

/* resize handles */
.ui-window__resize {
    position: absolute;
    bottom: 0;
    right: 0;
    width: 12px;
    height: 12px;
    cursor: se-resize;
}
.ui-window__resize::before {
    content: '';
    position: absolute;
    bottom: 3px; right: 3px;
    width: 0; height: 0;
    border-style: solid;
    border-width: 0 0 6px 6px;
    border-color: transparent transparent var(--uk-text-2) transparent;
}

/* minimised */
.ui-window--minimized .ui-window__content,
.ui-window--minimized .ui-window__footer { display: none; }


/* ============================================================
   14. Overlay / backdrop
   ============================================================ */

.ui-overlay {
    background: rgba(0,0,0,0.55);
    backdrop-filter: blur(2px);
    z-index: var(--z-index-modal-backdrop);
    /* animation: uk-fade-in var(--uk-dur-fast) var(--uk-ease); BIALI TODO: uncomment this if we want to add a fade in effect*/
}

.ui-overlay--transparent { background: transparent; backdrop-filter: none; }


/* ============================================================
   15. Dialogs
   ============================================================ */

.ui-dialog {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    display: flex;
    flex-direction: column;
    background: var(--uk-chrome-bg);
    border: 1px solid var(--uk-border);
    border-radius: var(--uk-input-radius);
    box-shadow: var(--uk-chrome-shadow);
    z-index: var(--z-index-modal);
    min-width: 280px;
    max-width: min(90vw, 560px);
    max-height: 90vh;
    overflow: hidden;
    animation: uk-dialog-in var(--uk-dur-fast) var(--uk-ease);
}

@keyframes uk-dialog-in {
    from { opacity: 0; transform: translate(-50%, calc(-50% - 6px)); }
    to   { opacity: 1; transform: translate(-50%, -50%); }
}

@keyframes uk-fade-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}

.ui-dialog__header {
    display: flex;
    align-items: center;
    gap: var(--uk-gap-xs);
    padding: 4px 6px;
    border-bottom: 1px solid var(--uk-border-light);
    font-weight: 600;
    font-size: var(--uk-font-size);
    color: var(--uk-text-1);
    flex-shrink: 0;
    min-height: 20px;
    line-height: 1.2;
}

.ui-dialog__close {
    margin-left: auto;
    background: none;
    border: none;
    color: var(--uk-text-3);
    cursor: pointer;
    font-size: 0.875rem;
    line-height: 1;
    padding: 0 2px;
    border-radius: var(--uk-input-radius);
    transition: color var(--uk-dur-fast), background var(--uk-dur-fast);
}
.ui-dialog__close:hover { color: var(--uk-text-1); background: rgba(255,255,255,0.06); }

.ui-dialog__icon {
    font-size: 0.875rem;
    flex-shrink: 0;
}

.ui-dialog__body {
    padding: 4px 6px;
    overflow-y: auto;
    font-size: var(--uk-font-size);
    color: var(--uk-text-2);
    line-height: 1.4;
    flex: 1;
}

.ui-dialog__footer {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--uk-gap-xs);
    padding: 3px 6px;
    border-top: 1px solid var(--uk-border-light);
    background: var(--uk-surface-0);
    flex-shrink: 0;
}

/* type icons */
.ui-dialog--info    .ui-dialog__icon { color: var(--uk-info); }
.ui-dialog--success .ui-dialog__icon { color: var(--uk-success); }
.ui-dialog--warning .ui-dialog__icon { color: var(--uk-warning); }
.ui-dialog--error   .ui-dialog__icon { color: var(--uk-danger); }

/* draggable dialog — positioned by JS, not centered */
.ui-dialog--draggable {
    top: 10%;
    left: 50%;
    transform: translateX(-50%);
    cursor: move;
}
.ui-dialog--draggable .ui-dialog__header {
    cursor: move;
}

/* prompt input */
.ui-dialog--prompt .ui-dialog__body { display: flex; flex-direction: column; gap: var(--uk-gap-sm); }
.ui-dialog--prompt .ui-dialog__prompt-input { margin-top: var(--uk-gap-xs); }


/* ============================================================
   16. Toast
   ============================================================ */

.ui-toast-container {
    position: fixed;
    display: flex;
    flex-direction: column;
    gap: var(--uk-gap-sm);
    z-index: var(--z-index-tooltip);
    pointer-events: none;
    padding: var(--uk-gap-md);
}

.ui-toast-container--top-right    { top: 0; right: 0; align-items: flex-end; }
.ui-toast-container--top-left     { top: 0; left: 0;  align-items: flex-start; }
.ui-toast-container--top-center   { top: 0; left: 50%; transform: translateX(-50%); align-items: center; }
.ui-toast-container--bottom-right { bottom: 0; right: 0; align-items: flex-end; flex-direction: column-reverse; }
.ui-toast-container--bottom-left  { bottom: 0; left: 0;  align-items: flex-start; flex-direction: column-reverse; }
.ui-toast-container--bottom-center{ bottom: 0; left: 50%; transform: translateX(-50%); align-items: center; flex-direction: column-reverse; }

/* Glass-morphism toast with enhanced readability */
.ui-toast {
    display: flex;
    align-items: flex-start;
    gap: var(--uk-gap-xs);
    padding: 12px 14px;
    /* Glass effect */
    background: var(--glass-panel, rgba(30, 30, 35, 0.85));
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border: 1px solid var(--glass-border, rgba(255, 255, 255, 0.1));
    border-left: 3px solid;
    border-radius: 12px;
    box-shadow:
        0 8px 32px rgba(0, 0, 0, 0.4),
        0 2px 8px rgba(0, 0, 0, 0.3),
        inset 0 1px 0 rgba(255, 255, 255, 0.1);
    min-width: 280px;
    max-width: 400px;
    pointer-events: all;
    animation: uk-toast-in var(--uk-dur-fast) var(--uk-ease);
    /* Improved text rendering */
    text-rendering: optimizeLegibility;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

/* Slide up from bottom for bottom-right position */
.ui-toast-container--bottom-right .ui-toast,
.ui-toast-container--bottom-left .ui-toast,
.ui-toast-container--bottom-center .ui-toast {
    animation: uk-toast-in-bottom var(--uk-dur-fast) var(--uk-ease);
}

@keyframes uk-toast-in {
    from { opacity: 0; transform: translateX(12px); }
    to   { opacity: 1; transform: translateX(0); }
}

@keyframes uk-toast-in-bottom {
    from { opacity: 0; transform: translateY(12px); }
    to   { opacity: 1; transform: translateY(0); }
}

.ui-toast--out {
    animation: uk-toast-out var(--uk-dur-fast) var(--uk-ease) forwards;
}

@keyframes uk-toast-out {
    to { opacity: 0; transform: scale(0.95); max-height: 0; margin: 0; padding: 0; overflow: hidden; }
}

/* Type-specific border colors with glow */
.ui-toast--info    { border-left-color: var(--uk-info, #17a2b8); box-shadow: 0 8px 32px rgba(23, 162, 184, 0.15), 0 2px 8px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.1); }
.ui-toast--success { border-left-color: var(--uk-success, #62c462); box-shadow: 0 8px 32px rgba(98, 196, 98, 0.15), 0 2px 8px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.1); }
.ui-toast--warning { border-left-color: var(--uk-warning, #f39c12); box-shadow: 0 8px 32px rgba(243, 156, 18, 0.15), 0 2px 8px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.1); }
.ui-toast--error   { border-left-color: var(--uk-danger, #e74c3c); box-shadow: 0 8px 32px rgba(231, 76, 60, 0.15), 0 2px 8px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.1); }

.ui-toast__icon  { font-size: 1rem; padding-top: 1px; flex-shrink: 0; filter: drop-shadow(0 1px 2px rgba(0,0,0,0.3)); }
.ui-toast--info    .ui-toast__icon { color: var(--uk-info, #17a2b8); }
.ui-toast--success .ui-toast__icon { color: var(--uk-success, #62c462); }
.ui-toast--warning .ui-toast__icon { color: var(--uk-warning, #f39c12); }
.ui-toast--error   .ui-toast__icon { color: var(--uk-danger, #e74c3c); }

.ui-toast__body   { flex: 1; min-width: 0; }
.ui-toast__title  { font-size: var(--uk-font-size-sm); font-weight: 600; color: var(--uk-text-1); margin-bottom: 2px; letter-spacing: 0.01em; }
.ui-toast__text   { font-size: 13px; color: var(--uk-text-2); line-height: 1.5; }

.ui-toast__close {
    background: rgba(255, 255, 255, 0.05);
    border: none;
    color: var(--uk-text-2);
    cursor: pointer;
    font-size: 0.875rem;
    padding: 4px 6px;
    line-height: 1;
    flex-shrink: 0;
    border-radius: 6px;
    transition: all var(--uk-dur-fast) ease;
}
.ui-toast__close:hover {
    color: var(--uk-text-1);
    background: rgba(255, 255, 255, 0.1);
}


/* ============================================================
   17. Alert
   ============================================================ */

.ui-alert {
    display: flex;
    align-items: flex-start;
    gap: var(--uk-gap-xs);
    padding: 4px 6px;
    border-radius: var(--uk-input-radius);
    border: 1px solid;
    font-size: var(--uk-font-size);
    line-height: 1.4;
}

.ui-alert--info {
    background: rgba(23,162,184,0.10);
    border-color: rgba(23,162,184,0.30);
    color: var(--uk-text-1);
}
.ui-alert--success {
    background: rgba(98,196,98,0.10);
    border-color: rgba(98,196,98,0.30);
    color: var(--uk-text-1);
}
.ui-alert--warning {
    background: rgba(248,148,6,0.12);
    border-color: rgba(248,148,6,0.35);
    color: var(--uk-text-1);
}
.ui-alert--error,
.ui-alert--danger {
    background: rgba(238,95,91,0.10);
    border-color: rgba(238,95,91,0.30);
    color: var(--uk-text-1);
}

.ui-alert__icon { flex-shrink: 0; padding-top: 1px; }
.ui-alert--info    .ui-alert__icon { color: var(--uk-info); }
.ui-alert--success .ui-alert__icon { color: var(--uk-success); }
.ui-alert--warning .ui-alert__icon { color: var(--uk-warning); }
.ui-alert--error   .ui-alert__icon,
.ui-alert--danger  .ui-alert__icon { color: var(--uk-danger); }

.ui-alert__body { flex: 1; }
.ui-alert__title { font-weight: 600; margin-bottom: 2px; }


/* ============================================================
   18. Badge
   ============================================================ */

.ui-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 16px;
    padding: 0 4px;
    font-size: var(--uk-font-size-xs);
    font-weight: 600;
    line-height: 1;
    border-radius: var(--uk-input-radius);
    white-space: nowrap;
}

.ui-badge--primary { background: var(--uk-accent);   color: #fff; }
.ui-badge--success { background: var(--uk-success);  color: #fff; }
.ui-badge--warning { background: var(--uk-warning);  color: #fff; }
.ui-badge--danger  { background: var(--uk-danger);   color: #fff; }
.ui-badge--info    { background: var(--uk-info);     color: #fff; }
.ui-badge--neutral { background: var(--uk-surface-2); color: var(--uk-text-2); }

.ui-badge--dot {
    width: 6px;
    height: 6px;
    padding: 0;
    border-radius: var(--uk-input-radius);
}

/* Pill + soft tinted chips — generalized from the GrfExplorer badges
   (translucent semantic fill + matching text + hairline border). */
.ui-badge--pill { border-radius: var(--uk-radius-full); padding: 0 8px; }

.ui-badge--soft {
    border: 1px solid transparent;
    font-weight: 600;
    letter-spacing: 0.02em;
}
.ui-badge--soft.ui-badge--primary,
.ui-badge--soft.ui-badge--info {
    background: var(--tint-accent-bg);  color: var(--tint-accent-fg);  border-color: var(--tint-accent-bd);
}
.ui-badge--soft.ui-badge--signal {
    background: var(--tint-signal-bg);  color: var(--tint-signal-fg);  border-color: var(--tint-signal-bd);
}
.ui-badge--soft.ui-badge--success {
    background: var(--tint-success-bg); color: var(--tint-success-fg); border-color: var(--tint-success-bd);
}
.ui-badge--soft.ui-badge--warning {
    background: var(--tint-signal-bg);  color: var(--tint-signal-fg);  border-color: var(--tint-signal-bd);
}
.ui-badge--soft.ui-badge--danger {
    background: var(--tint-danger-bg);  color: var(--tint-danger-fg);  border-color: var(--tint-danger-bd);
}
.ui-badge--soft.ui-badge--neutral {
    background: color-mix(in srgb, var(--uk-text-3) 14%, transparent);
    color: var(--uk-text-2);
    border-color: var(--uk-glass-border);
}

/* ---- Reusable glass panel utility ----------------------------------
   Apply .ui-glass to any container to get the translucent instrument
   surface + blur + hairline used across the shell overlays. */
.ui-glass {
    background: var(--uk-glass);
    -webkit-backdrop-filter: blur(var(--uk-glass-blur));
    backdrop-filter: blur(var(--uk-glass-blur));
    border: 1px solid var(--uk-glass-border);
    box-shadow: var(--uk-glass-shadow);
}
.ui-glass--raised { background: var(--uk-glass-raised); }
.ui-glass--sunken { background: var(--uk-glass-sunken); box-shadow: none; }
/* hairline divider between glass regions */
.ui-glass-divide-r { border-right: 1px solid var(--uk-glass-divider); }
.ui-glass-divide-l { border-left: 1px solid var(--uk-glass-divider); }
.ui-glass-divide-b { border-bottom: 1px solid var(--uk-glass-divider); }
.ui-glass-divide-t { border-top: 1px solid var(--uk-glass-divider); }


/* ============================================================
   19. Progress & spinner
   ============================================================ */

.ui-progress {
    width: 100%;
    height: 4px;
    background: var(--uk-track-bg);
    border-radius: 0;
    overflow: hidden;
}

.ui-progress__bar {
    height: 100%;
    background: var(--uk-accent);
    border-radius: 0;
    transition: width var(--uk-dur) var(--uk-ease);
}

/* A secondary bar under a primary one — used for the per-job gauge beneath the
   whole-task gauge on the busy overlay. */
.ui-progress--sm { height: 2px; }

.ui-progress--success .ui-progress__bar { background: var(--uk-success); }
.ui-progress--warning .ui-progress__bar { background: var(--uk-warning); }
.ui-progress--danger  .ui-progress__bar { background: var(--uk-danger); }

.ui-progress--indeterminate .ui-progress__bar {
    width: 40% !important;
    animation: uk-progress-indeterminate 1.4s ease infinite;
}

@keyframes uk-progress-indeterminate {
    0%   { transform: translateX(-100%); }
    100% { transform: translateX(350%); }
}

/* spinner */
.ui-spinner {
    display: inline-block;
    width: 20px;
    height: 20px;
    border: 2px solid var(--uk-border);
    border-top-color: var(--uk-accent);
    border-radius: 50%;
    animation: uk-spin 0.7s linear infinite;
    flex-shrink: 0;
}

.ui-spinner--sm { width: 14px; height: 14px; border-width: 2px; }
.ui-spinner--lg { width: 32px; height: 32px; border-width: 3px; }

@keyframes uk-spin {
    to { transform: rotate(360deg); }
}


/* ============================================================
   20. Tooltip
   ============================================================ */

[data-uk-tooltip] { position: relative; }

[data-uk-tooltip]::after {
    content: attr(data-uk-tooltip);
    position: absolute;
    bottom: calc(100% + 4px);
    left: 50%;
    transform: translateX(-50%);
    background: var(--bg-color-inverse);
    color: var(--text-color-inverse);
    font-size: var(--uk-font-size-xs);
    white-space: nowrap;
    padding: 2px 6px;
    border-radius: var(--uk-input-radius);
    pointer-events: none;
    opacity: 0;
    transition: opacity var(--uk-dur-fast);
    z-index: var(--z-index-tooltip);
    box-shadow: none;
}

[data-uk-tooltip]:hover::after { opacity: 1; }

/* manual tooltip element */
.ui-tooltip {
    position: absolute;
    background: var(--bg-color-inverse);
    color: var(--text-color-inverse);
    font-size: var(--uk-font-size-xs);
    padding: 2px 6px;
    border-radius: var(--uk-input-radius);
    pointer-events: none;
    z-index: var(--z-index-tooltip);
    white-space: nowrap;
    box-shadow: none;
}

/* ---- Info badge (i) + rich popover --------------------------------
   A small "(i)" affordance next to a feature that opens a titled
   explanation with an optional "Learn more" documentation link. */
.ui-info-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 14px;
    height: 14px;
    padding: 0;
    margin: 0 0 0 4px;
    font-size: 9px;
    font-weight: 700;
    line-height: 1;
    color: var(--uk-text-3);
    background: transparent;
    border: 1px solid var(--uk-border);
    border-radius: var(--uk-radius-full);
    cursor: help;
    flex: 0 0 auto;
    vertical-align: middle;
    transition: color var(--uk-dur-fast) var(--uk-ease),
                border-color var(--uk-dur-fast) var(--uk-ease),
                background var(--uk-dur-fast) var(--uk-ease);
}
.ui-info-badge:hover,
.ui-info-badge:focus-visible,
.ui-info-badge.is-open {
    color: var(--uk-accent);
    border-color: var(--uk-accent-border, var(--uk-accent));
    background: var(--uk-accent-muted);
    outline: none;
}
.ui-info-badge--sm { width: 12px; height: 12px; font-size: 8px; }
.ui-info-badge--lg { width: 16px; height: 16px; font-size: 10px; }
.ui-info-badge[hidden] { display: none; }

.ui-popover {
    position: fixed;
    z-index: var(--z-index-popover);
    max-width: 280px;
    padding: 10px 12px;
    background: var(--uk-overlay);
    color: var(--uk-text-1);
    border: 1px solid var(--uk-glass-border);
    border-radius: var(--uk-radius-md);
    box-shadow: var(--shadow-lg);
    font-size: var(--uk-font-size-md);
    line-height: 1.45;
    opacity: 0;
    transform: translateY(2px);
    pointer-events: none;
    transition: opacity var(--uk-dur-fast) var(--uk-ease),
                transform var(--uk-dur-fast) var(--uk-ease);
}
.ui-popover.is-open { opacity: 1; transform: translateY(0); pointer-events: auto; }
.ui-popover__title {
    display: block;
    margin-bottom: 4px;
    font-size: var(--uk-font-size-md);
    font-weight: 700;
    color: var(--uk-text-1);
}
.ui-popover__body { color: var(--uk-text-2); }
.ui-popover__body p { margin: 0 0 6px; }
.ui-popover__body p:last-child { margin-bottom: 0; }
.ui-popover__link {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-top: 8px;
    font-size: var(--uk-font-size-sm);
    font-weight: 600;
    color: var(--uk-accent);
    text-decoration: none;
}
.ui-popover__link:hover { color: var(--uk-accent-hover); text-decoration: underline; }
.ui-popover__link i { font-size: 0.85em; }
/* The three parts are built up front and hidden when empty (UKInfoBadge can be
   re-pointed at a new subject), and an explicit `display` above beats `[hidden]`'s
   UA rule — so state it. */
.ui-popover__title[hidden],
.ui-popover__body[hidden],
.ui-popover__link[hidden] { display: none; }


/* ============================================================
   21. Divider / separator
   ============================================================ */

.ui-divider {
    border: none;
    border-top: 1px solid var(--uk-border-light);
    margin: var(--uk-gap-sm) 0;
}

.ui-separator {
    display: flex;
    align-items: center;
    gap: var(--uk-gap-xs);
    color: var(--uk-text-3);
    font-size: var(--uk-font-size-xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    margin: var(--uk-gap-xs) 0;
}

.ui-separator::before,
.ui-separator::after {
    content: '';
    flex: 1;
    height: 1px;
    background: var(--uk-border-light);
}

.ui-separator--left::before  { display: none; }
.ui-separator--right::after  { display: none; }


/* ============================================================
   22. Accordion
   ============================================================ */

.ui-accordion {
    border: 1px solid var(--uk-border-light);
    border-radius: var(--uk-input-radius);
    overflow: hidden;
}

.ui-accordion__item {
    border-bottom: 1px solid var(--uk-border-light);
}
.ui-accordion__item:last-child { border-bottom: none; }

.ui-accordion__header {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 3px 6px;
    background: var(--uk-surface-1);
    cursor: pointer;
    user-select: none;
    font-size: var(--uk-font-size);
    font-weight: 600;
    color: var(--uk-text-1);
    transition: background var(--uk-dur-fast);
    min-height: 20px;
    line-height: 1.2;
    border-bottom: 1px solid var(--uk-border);
}

.ui-accordion__header:hover { background: var(--uk-surface-2); }

.ui-accordion__arrow {
    margin-left: auto;
    font-size: 0.5rem;
    color: var(--uk-text-3);
    transition: transform var(--uk-dur-fast);
    flex-shrink: 0;
}

.ui-accordion__item--open .ui-accordion__arrow { transform: rotate(180deg); }

.ui-accordion__body {
    display: none;
    padding: 4px 6px;
    background: var(--uk-surface-1);
    font-size: var(--uk-font-size);
    color: var(--uk-text-2);
}

.ui-accordion__item--open .ui-accordion__body { display: block; }

.ui-accordion__toolbar {
    display: flex;
    justify-content: flex-end;
    padding: 2px 4px;
    border-bottom: 1px solid var(--uk-border-light);
    background: var(--uk-surface-1);
}

.ui-accordion__title { flex: 1; min-width: 0; }

/* Full-height bodies: parent scrolls, no max-height clip (UIAccordion always-open pattern) */
.ui-accordion--full-height {
    overflow: visible;
}

.ui-accordion--full-height .ui-accordion__body {
    display: none;
    overflow: visible;
    max-height: none;
}

.ui-accordion--full-height .ui-accordion__item--open .ui-accordion__body {
    display: block;
    max-height: none;
    padding-top: 4px;
    padding-bottom: 4px;
}

/* animated variant */
.ui-accordion--animated .ui-accordion__body {
    display: block;
    overflow: hidden;
    max-height: 0;
    padding-top: 0;
    padding-bottom: 0;
    transition: max-height var(--uk-dur) var(--uk-ease), padding var(--uk-dur-fast) var(--uk-ease);
}

.ui-accordion--animated .ui-accordion__item--open .ui-accordion__body {
    max-height: 2000px;
    padding-top: 4px;
    padding-bottom: 4px;
}


/* ============================================================
   23. Tabs
   ============================================================ */

.ui-tabs {
    display: flex;
    flex-direction: column;
    min-height: 0;
    min-width: 0;
}

.ui-tabs__list {
    display: flex;
    align-items: stretch;
    border-bottom: 1px solid var(--uk-border-light);
    background: var(--uk-surface-1);
    overflow-x: auto;
    scrollbar-width: none;
    flex-shrink: 0;
}

.ui-tabs__list::-webkit-scrollbar { display: none; }

.ui-tabs__tab {
    display: inline-flex;
    align-items: center;
    gap: var(--uk-gap-sm);
    padding: 4px 10px;
    font-weight: 500;
    color: var(--uk-text-3);
    cursor: pointer;
    border-bottom: 2px solid transparent;
    white-space: nowrap;
    user-select: none;
    transition: all var(--uk-dur-fast) var(--uk-ease);
    position: relative;
    top: 1px;
    background: transparent;
    border-left: none;
    border-right: none;
    border-top: none;
    outline: none;
    min-height: 20px;
    font-size: var(--uk-font-size-sm);
}

.ui-tabs__tab:hover { color: var(--uk-text-1); background: rgba(255,255,255,0.03); }

.ui-tabs__tab--active {
    color: var(--uk-accent);
    border-bottom-color: var(--uk-accent);
    background: rgba(var(--uk-accent-rgb), 0.08);
}

.ui-tabs__tab:focus-visible {
    background: rgba(255,255,255,0.05);
    border-radius: var(--uk-input-radius) var(--uk-input-radius) 0 0;
}

/* UKTabs always builds this wrapper (UIKit.js), but it had no rule of its own, so it
   defaulted to `display: block` — which made the `flex: 1` below inert in every tabbed
   dialog in the app, and left each surface to rebuild the chain in its own section.
   Owning it here is what lets a tab panel fill the window.

   `display: flex` is safe for every consumer BY CONSTRUCTION: UKTabs only ever appends
   `.ui-tabs__panel` elements here (`addTab` and `_addGroup` both do), and all but the
   active one are `display: none` — so there is only ever one flex item, and a panel's own
   children keep normal block flow. Host content is never a direct child. */
.ui-tabs__panels {
    display: flex;
    flex: 1;
    min-height: 0;
    min-width: 0;
}

.ui-tabs__panel {
    display: none;
    flex: 1;
    min-height: 0;
    min-width: 0;
    overflow: auto;
}

/* Deliberately still `block`: the panel is now a flex ITEM of `__panels` (so it fills),
   but its own children keep normal block flow. A surface that wants a flex column inside
   opts in — see `.tst-root .ui-tabs__panel--active` (§55). */
.ui-tabs__panel--active { display: block; }

/* vertical tabs */
.ui-tabs--vertical {
    flex-direction: row;
}

.ui-tabs--vertical .ui-tabs__list {
    flex-direction: column;
    border-bottom: none;
    border-right: 1px solid var(--uk-border-light);
    overflow-y: auto;
    overflow-x: visible;
    min-width: 120px;
    margin-top: 1em;
    padding: 0.5em;
}

.ui-tabs--vertical .ui-tabs__tab {
    border-bottom: none;
    border-right: 2px solid transparent;
    border-left: none;
    top: 0;
    right: -1px;
    padding: 3px 6px;
}

.ui-tabs--vertical .ui-tabs__tab--active {
    border-right-color: var(--uk-accent);
    color: var(--uk-accent);
}

/* grouped/collapsible tabs (vertical only) */
.ui-tabs__group { display: flex; flex-direction: column; }
.ui-tabs__group-header {
    display: flex; align-items: center; gap: var(--uk-gap-sm); justify-content: space-between;
    padding: 3px 6px; font-weight: 500; color: var(--uk-text-2);
    background: transparent; border: none; cursor: pointer; text-align: left;
    font-size: var(--uk-font-size-sm);
}
.ui-tabs__group-header:hover { color: var(--uk-text-1); }
.ui-tabs__group-chev { font-size: 9px; opacity: .7; transition: transform var(--uk-dur-fast); }
.ui-tabs__group--open .ui-tabs__group-chev { transform: rotate(180deg); }
.ui-tabs__group-children { display: none; flex-direction: column; padding-left: 14px; }
.ui-tabs__group--open .ui-tabs__group-children { display: flex; }
.ui-tabs__tab--child { padding: 3px 6px; font-size: 11.5px; }

/* pill tabs */
.ui-tabs--pills .ui-tabs__list {
    border-bottom: none;
    background: transparent;
    gap: var(--uk-gap-xs);
    padding: var(--uk-gap-xs) 0;
}

.ui-tabs--pills .ui-tabs__tab {
    border: 1px solid transparent;
    border-radius: var(--uk-input-radius);
    top: 0;
    padding: 2px 6px;
}

.ui-tabs--pills .ui-tabs__tab--active {
    background: var(--uk-accent);
    color: #fff;
    border-color: var(--uk-accent);
}


/* ============================================================
   24. Table
   ============================================================ */

.ui-table-wrap {
    width: 100%;
    overflow-x: auto;
    border: 1px solid var(--uk-border-light);
    border-radius: var(--uk-input-radius);
}

.ui-table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--uk-font-size);
    color: var(--uk-text-1);
}

.ui-table thead th {
    padding: 3px 6px;
    text-align: left;
    font-size: var(--uk-font-size-sm);
    font-weight: 600;
    color: var(--uk-text-3);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    border-bottom: 1px solid var(--uk-border-light);
    background: var(--uk-surface-1);
    white-space: nowrap;
    user-select: none;
}

.ui-table thead th.sortable { cursor: pointer; }
.ui-table thead th.sortable:hover { color: var(--uk-text-1); }

.ui-table tbody td {
    padding: 2px 6px;
    border-bottom: 1px solid var(--uk-border-light);
    color: var(--uk-text-1);
    vertical-align: middle;
}

.ui-table tbody tr:last-child td { border-bottom: none; }

.ui-table tbody tr:hover td { background: rgba(255,255,255,0.03); }

.ui-table tbody tr.selected td { background: rgba(0,123,255,0.10); }

.ui-table--striped tbody tr:nth-child(even) td { background: rgba(255,255,255,0.02); }

.ui-table--compact thead th,
.ui-table--compact tbody td { padding: 1px 4px; }

.ui-table tfoot td {
    padding: 3px 6px;
    border-top: 1px solid var(--uk-border-light);
    font-size: var(--uk-font-size-sm);
    color: var(--uk-text-3);
    background: var(--uk-surface-1);
}


/* ============================================================
   25. List
   ============================================================ */

.ui-list {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--uk-border-light);
    border-radius: var(--uk-input-radius);
    overflow: hidden;
    font-size: var(--uk-font-size);
}

.ui-list--borderless { border: none; border-radius: 0; }

.ui-list__item {
    display: flex;
    align-items: center;
    gap: var(--uk-gap-xs);
    padding: 3px 6px;
    border-bottom: 1px solid var(--uk-border-light);
    color: var(--uk-text-1);
    cursor: default;
    transition: background var(--uk-dur-fast);
    min-height: 20px;
}

.ui-list__item:last-child { border-bottom: none; }

.ui-list__item--interactive { cursor: pointer; }
.ui-list__item--interactive:hover { background: rgba(255,255,255,0.04); }
.ui-list__item--interactive:active { background: rgba(255,255,255,0.08); }

.ui-list__item--selected { background: var(--uk-accent-muted) !important; color: var(--uk-accent); }

.ui-list__item-icon {
    flex-shrink: 0;
    width: 18px;
    text-align: center;
    color: var(--uk-text-3);
}

.ui-list__item-label { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ui-list__item-meta  { color: var(--uk-text-3); font-size: var(--uk-font-size-sm); flex-shrink: 0; }
.ui-list__item-actions { display: flex; gap: var(--uk-gap-xs); flex-shrink: 0; }


/* ============================================================
   26. Tree
   ============================================================ */

.ui-tree {
    font-size: var(--uk-font-size);
    color: var(--uk-text-1);
    user-select: none;
}

.ui-tree__node { display: flex; flex-direction: column; }

.ui-tree__node-row {
    display: flex;
    align-items: center;
    gap: 2px;
    padding: 1px 4px;
    cursor: default;
    border-radius: var(--uk-input-radius);
    transition: background var(--uk-dur-fast);
    min-height: 18px;
}

.ui-tree__node-row:hover { background: rgba(255,255,255,0.05); }
.ui-tree__node-row--selected { background: var(--uk-accent-muted) !important; }

.ui-tree__toggle {
    width: 14px;
    height: 14px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    color: var(--uk-text-3);
    font-size: 0.5rem;
    flex-shrink: 0;
    transition: transform var(--uk-dur-fast);
}

.ui-tree__node--open > .ui-tree__node-row .ui-tree__toggle { transform: rotate(90deg); }

.ui-tree__node-icon {
    flex-shrink: 0;
    width: 14px;
    text-align: center;
    color: var(--uk-text-3);
    font-size: 0.75rem;
}

.ui-tree__node-label { flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.ui-tree__children {
    display: none;
    padding-left: 18px;
}

.ui-tree__node--open > .ui-tree__children { display: flex; flex-direction: column; }

/* Tree inside asset-browser panels — slightly roomier rows */
.ui-asset-tree-panel .ui-tree__node-row {
    padding: 4px 8px;
    margin: 1px 0;
    min-height: 22px;
}

.ui-asset-tree-panel .ui-tree__node-row:hover {
    background: var(--uk-accent-muted);
}

.ui-asset-tree-panel .ui-tree__node-row--selected {
    background: var(--uk-accent-muted) !important;
    color: var(--uk-text-1);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
}

.ui-asset-tree-panel .ui-tree__node-label {
    font-weight: 500;
    font-size: var(--uk-font-size-sm, 0.8125rem);
}


/* ============================================================
   32. Asset browser (shared picker / catalog grid)
   ============================================================ */

.ui-asset-browser {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
    overflow: hidden;
    color: var(--uk-text-1);
    background: var(--uk-surface-0);
}

.ui-asset-toolbar {
    flex: 0 0 auto;
    padding: var(--uk-gap-sm) var(--uk-gap);
    border-bottom: 1px solid var(--uk-border-light);
    background: var(--uk-surface-1);
}

.ui-asset-toolbar .ui-input {
    flex: 1 1 200px;
    min-width: 160px;
}

.ui-asset-toolbar__actions {
    margin-left: auto;
}

.ui-asset-tree-panel {
    flex: 1;
    min-height: 0;
    overflow: hidden;
    padding: var(--uk-gap-sm);
    background: var(--uk-surface-2);
    border: 1px solid var(--uk-border-light);
    border-radius: var(--uk-input-radius);
}

.ui-asset-gridwrap {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
    overflow: hidden;
    position: relative;
    background: var(--uk-surface-2);
    border: 1px solid var(--uk-border-light);
    border-radius: var(--uk-input-radius);
}

.ui-asset-grid {
    flex: 1;
    overflow: auto;
    scroll-behavior: smooth;
}

.ui-asset-grid .UIInfiniteScroll_List {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
    gap: var(--uk-gap);
    padding: var(--uk-gap);
    align-content: start;
}

.ui-asset-grid .UIInfiniteScroll_Item {
    padding: 0;
}

.ui-asset-tile {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: var(--uk-gap-sm);
    border: 1px solid var(--uk-border-light);
    border-radius: var(--uk-input-radius);
    cursor: pointer;
    transition: border-color var(--uk-dur-fast), background var(--uk-dur-fast),
        transform var(--uk-dur-fast), box-shadow var(--uk-dur-fast);
    min-height: 160px;
    background: var(--uk-surface-1);
    position: relative;
}

.ui-asset-tile:hover:not(.is-selected) {
    border-color: var(--uk-accent);
    background: var(--uk-accent-muted);
    transform: translateY(-2px);
    box-shadow: 0 8px 20px rgba(0, 0, 0, 0.25);
}

.ui-asset-tile.is-selected {
    border-color: var(--uk-signal);
    background: var(--uk-signal-muted);
    box-shadow: 0 0 16px var(--uk-signal-muted);
    transform: translateY(-1px) scale(1.01);
}

.ui-asset-thumb {
    position: relative;
    margin-bottom: var(--uk-gap-xs);
    width: 128px;
    height: 128px;
    background: var(--uk-surface-0);
    border-radius: var(--uk-input-radius);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    border: 1px solid var(--uk-border-light);
    font-size: 2.5rem;
    opacity: 0.7;
}

.ui-asset-thumb video,
.ui-asset-thumb img {
    display: block;
    width: 128px;
    height: 128px;
    border-radius: calc(var(--uk-input-radius) - 2px);
    object-fit: contain;
}

.ui-asset-label {
    text-align: center;
    word-break: break-word;
    max-height: 2.8em;
    overflow: hidden;
    display: -webkit-box;
    line-clamp: 2;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    width: 100%;
    color: var(--uk-text-1);
    font-weight: 500;
    font-size: var(--uk-font-size-sm, 0.8125rem);
    line-height: 1.4;
}

.ui-split__side.ui-asset-preview-column {
    min-height: 0;
    overflow: hidden;
}

.ui-asset-preview-panel {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

.ui-asset-preview-panel .ui-panel__body {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    padding: 6px;
    overflow: hidden;
    gap: 6px;
    background-color: var(--uk-surface-0);
}

.ui-asset-preview-panel .ui-panel__body [data-uk-metadata] {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow: auto;
    gap: var(--uk-gap);
    scrollbar-width: none;
    -ms-overflow-style: none;
}

.ui-asset-preview-panel .ui-panel__body [data-uk-metadata]::-webkit-scrollbar {
    display: none;
}

.ui-asset-preview-mount {
    display: flex;
    flex-direction: column;
    flex: 0 0 auto;
    height: 30vh;
    min-height: 140px;
}

.ui-asset-preview-mount > * {
    flex: 1 1 auto;
    min-height: 0;
    width: 100%;
}

.ui-asset-preview-mount.ui-asset-model-preview {
    gap: 4px;
}

.ui-asset-preview-mount > .ui-asset-model-preview__controls {
    display: flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: flex-end;
    gap: 4px;
}

.ui-asset-preview-mount > .ui-asset-model-preview__canvas {
    flex: 1 1 auto;
    min-height: 0;
    width: 100%;
    position: relative;
    overflow: hidden;
    border-radius: var(--uk-radius, 4px);
    background: #274472;
}

.ui-asset-model-preview__canvas canvas {
    display: block;
    width: 100% !important;
    height: 100% !important;
}

.ui-asset-model-preview__btn {
    min-width: 24px;
}

.ui-asset-model-preview__btn.is-active {
    background: rgba(100, 150, 255, 0.25);
    color: var(--uk-text-1, #fff);
}

.ui-asset-model-preview__speed {
    min-width: 32px;
}

.ui-asset-grid-empty {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--uk-surface-2);
    z-index: 2;
}

.ui-asset-footer {
    flex: 0 0 auto;
    padding: var(--uk-gap-sm) var(--uk-gap);
    border-top: 1px solid var(--uk-border-light);
    background: var(--uk-surface-1);
}

/* The asset pickers (assetSources.js) hand this shell to a UKWindow classed
   `ui-asset-picker-window`, which had no block of its own — so the shell sat in the
   default padded, scrolling content box instead of filling it. See the contract note
   above `.ui-window__content` (§13). */
.ui-asset-picker-window .ui-window__content {
    padding: 0;
    overflow: hidden;
    display: flex;
    min-height: 0;
}

.ui-asset-dialog {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-width: 0;
    height: 100%;
    min-height: 0;
}

.ui-asset-dialog .ui-asset-browser {
    flex: 1 1 auto;
    min-height: 0;
}

/* RSM metadata panel (Model Catalog info sidebar) */
.ui-rsm-meta {
    gap: var(--uk-gap-sm);
}

.ui-rsm-meta__block {
    padding: var(--uk-gap-sm);
    border-radius: var(--uk-radius-sm);
    background: var(--uk-surface-2);
    border: 1px solid var(--uk-border-light);
}

.ui-rsm-meta__title {
    font-weight: 600;
    margin-bottom: var(--uk-gap-xs);
    color: var(--uk-accent);
}

/* UKKeyValue / UKKeyValueGrid — reusable label:value rows */
.ui-kv {
    display: flex;
    gap: var(--uk-gap-sm);
    align-items: baseline;
}
.ui-kv--grid { display: contents; }
.ui-kv__key { color: var(--uk-text-3); }
.ui-kv__val { color: var(--uk-text-1); word-break: break-word; }
.ui-kv__val--mono {
    font-family: var(--uk-font-mono, ui-monospace, monospace);
    font-size: 0.75rem;
}
.ui-kv-grid {
    display: grid;
    grid-template-columns: minmax(72px, auto) 1fr;
    gap: 2px var(--uk-gap-sm);
    align-items: baseline;
}

.ui-rsm-meta__nodes {
    max-height: 240px;
    display: flex;
    flex-direction: column;
    gap: var(--uk-gap-xs);
}

.ui-rsm-meta__node {
    padding: var(--uk-gap-xs) var(--uk-gap-sm);
    border-radius: var(--uk-radius-sm);
    background: var(--uk-surface-2);
    border: 1px solid var(--uk-border-light);
    border-left: 3px solid var(--uk-text-3);
}

.ui-rsm-meta__node.is-animated {
    border-left-color: var(--uk-success);
}

.ui-rsm-meta__node-head {
    display: flex;
    align-items: center;
    gap: var(--uk-gap-xs);
    flex-wrap: wrap;
}

.ui-rsm-meta__node-name {
    font-family: var(--uk-font-mono, monospace);
    font-size: var(--uk-text-sm, 0.8125rem);
    font-weight: 600;
    color: var(--uk-accent);
}

.ui-rsm-meta__node-stats {
    margin-top: 4px;
}

.ui-rsm-meta__node-textures {
    margin-top: 4px;
    color: var(--uk-text-3);
}

.ui-rsm-meta__textures {
    max-height: 280px;
}

.ui-rsm-meta__texture-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
    gap: var(--uk-gap-sm);
}

.ui-rsm-meta__texture-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    padding: var(--uk-gap-xs);
    border-radius: var(--uk-radius-sm);
    background: var(--uk-surface-2);
    border: 1px solid var(--uk-border-light);
}

.ui-rsm-meta__texture-thumb {
    width: 64px;
    height: 64px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--uk-surface-1);
    border-radius: var(--uk-radius-sm);
    border: 1px solid var(--uk-border-light);
    color: var(--uk-text-3);
    font-size: 0.75rem;
    overflow: hidden;
}

.ui-rsm-meta__texture-thumb.is-missing {
    color: var(--uk-text-3);
}

.ui-rsm-meta__texture-img {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

.ui-rsm-meta__texture-name,
.ui-rsm-meta__texture-path,
.ui-rsm-meta__texture-used {
    width: 100%;
    text-align: center;
    word-break: break-all;
    line-height: 1.3;
}

.ui-rsm-meta__texture-path {
    font-family: var(--uk-font-mono, monospace);
    font-size: 0.6875rem;
}

.ui-rsm-meta__texture-used {
    color: var(--uk-success);
}

/* History picker compact grid */
.ui-asset-history-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
    gap: var(--uk-gap-sm);
    padding: var(--uk-gap-sm);
    align-content: start;
    overflow: auto;
    flex: 1;
    min-height: 0;
}

.ui-asset-history-tile {
    display: flex;
    flex-direction: column;
    gap: var(--uk-gap-xs);
    padding: var(--uk-gap-xs);
    border: 2px solid transparent;
    border-radius: var(--uk-input-radius);
    cursor: pointer;
    background: var(--uk-surface-1);
    transition: border-color var(--uk-dur-fast), background var(--uk-dur-fast);
}

.ui-asset-history-tile:hover {
    border-color: var(--uk-accent);
    background: var(--uk-accent-muted);
}

.ui-asset-history-tile .ui-preview {
    aspect-ratio: 1;
    width: 100%;
}


/* ============================================================
   27. Image preview & visualiser
   ============================================================ */

.ui-preview {
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--uk-surface-0);
    border: 1px solid var(--uk-border-light);
    border-radius: var(--uk-input-radius);
    overflow: hidden;
    position: relative;
}

.ui-preview--checker {
    background-image:
        linear-gradient(45deg, #2a2a2a 25%, transparent 25%),
        linear-gradient(-45deg, #2a2a2a 25%, transparent 25%),
        linear-gradient(45deg, transparent 75%, #2a2a2a 75%),
        linear-gradient(-45deg, transparent 75%, #2a2a2a 75%);
    background-size: 16px 16px;
    background-position: 0 0, 0 8px, 8px -8px, -8px 0;
}

.ui-preview img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    display: block;
}

.ui-preview__label {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    padding: 2px 4px;
    background: rgba(0,0,0,0.55);
    font-size: var(--uk-font-size-xs);
    color: #fff;
    text-align: center;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* color visualiser strip */
.ui-color-strip {
    display: flex;
    height: 10px;
    border-radius: var(--uk-input-radius);
    overflow: hidden;
}

.ui-color-strip__segment { flex: 1; }

/* gradient visualiser */
.ui-gradient-preview {
    height: 18px;
    border-radius: var(--uk-input-radius);
    border: 1px solid rgba(255,255,255,0.1);
}


/* ============================================================
   28. Context menu
   ============================================================ */

.ui-context-menu {
    position: fixed;
    background: var(--uk-chrome-bg);
    border: 1px solid var(--uk-border);
    border-radius: var(--uk-input-radius);
    box-shadow: var(--uk-chrome-shadow);
    z-index: var(--z-index-popover);
    min-width: 140px;
    max-width: 260px;
    padding: 2px 0;
    animation: uk-fade-in var(--uk-dur-fast) var(--uk-ease);
    font-size: var(--uk-font-size);
}

.ui-context-menu__item {
    display: flex;
    align-items: center;
    gap: var(--uk-gap-xs);
    padding: 2px 6px;
    color: var(--uk-text-1);
    cursor: pointer;
    transition: background var(--uk-dur-fast);
    user-select: none;
    white-space: nowrap;
    min-height: 20px;
}

.ui-context-menu__item:hover    { background: rgba(255,255,255,0.06); }
.ui-context-menu__item:active   { background: rgba(255,255,255,0.10); }
.ui-context-menu__item--danger  { color: var(--uk-danger); }
.ui-context-menu__item--danger:hover { background: rgba(238,95,91,0.08); }

/* `:disabled` too — a menu built out of real <button>s (GrfExplorer's) marks its
   inert entries that way rather than with the modifier class. */
.ui-context-menu__item:disabled,
.ui-context-menu__item--disabled {
    opacity: 0.4;
    cursor: not-allowed;
    pointer-events: none;
}

.ui-context-menu__icon   { width: 14px; text-align: center; flex-shrink: 0; }
.ui-context-menu__label  { flex: 1; }
.ui-context-menu__shortcut { color: var(--uk-text-3); font-size: var(--uk-font-size-xs); margin-left: var(--uk-gap-xs); }

.ui-context-menu__separator {
    border: none;
    border-top: 1px solid var(--uk-border-light);
    margin: var(--uk-gap-xs) 0;
}

.ui-context-menu__submenu-arrow {
    color: var(--uk-text-3);
    font-size: 0.5rem;
}


/* ============================================================
   28b. Dropdowns (UKDropdown / UKDropdownPanel / UKToolbarDropdown)
   ============================================================ */

.uk-dropdown {
    position: relative;
    display: inline-flex;
    align-items: center;
    vertical-align: middle;
}

/*
 * Split dropdown — Bootstrap `.btn-group` + `.dropdown-toggle-split`.
 * DOM: primary button, caret button, then `.uk-dropdown__menu` (positioned;
 * must not participate in the join/radius rules the way `.ui-btn-group` does).
 */
.uk-dropdown--split {
    align-items: stretch;
    gap: 0;
}

.uk-dropdown--toolbar {
    /* Matches ViewportToolbar subgroup clustering */
    display: inline-flex;
}

/* Screen-reader-only label for split caret buttons. */
.uk-sr-only {
    position: absolute !important;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.uk-dropdown__toggle {
    position: relative;
}

/* Corner fold on single-face toggles only — never on split carets. */
.uk-dropdown__toggle:not(.uk-dropdown__toggle--split)::after {
    content: "";
    position: absolute;
    right: 2px;
    bottom: 2px;
    width: 0;
    height: 0;
    border-style: solid;
    border-width: 0 0 5px 5px;
    border-color: transparent transparent var(--uk-text-3) transparent;
    pointer-events: none;
    opacity: 0.85;
}

/*
 * Bootstrap `.dropdown-toggle::after` caret-down used to live here for split
 * faces. Split carets now use FA `fa-caret-down` on the button so the glyph
 * inherits the face's text color across variants. Corner-fold below stays
 * for single-face toggles only.
 */

/* Bootstrap `.btn-group > .btn`: stacking context for joined borders */
.uk-dropdown--split > .ui-btn,
.uk-dropdown--split > .ui-tbtn {
    position: relative;
}
.uk-dropdown--split > .ui-btn:hover,
.uk-dropdown--split > .ui-btn:focus-visible,
.uk-dropdown--split > .ui-btn:active,
.uk-dropdown--split > .ui-tbtn:hover,
.uk-dropdown--split > .ui-tbtn:focus-visible,
.uk-dropdown--split > .ui-tbtn:active {
    z-index: 1;
}

/* Bootstrap: collapse the shared edge between primary and caret */
.uk-dropdown--split > .ui-btn + .ui-btn,
.uk-dropdown--split > .ui-tbtn + .ui-tbtn {
    margin-left: -1px;
}

/*
 * Radii — Bootstrap `btn-group` rules that ignore the trailing menu sibling:
 *   primary  = first button → square the end that meets the caret
 *   caret    = second button → square the start; keep the outer end radius
 */
.uk-dropdown--split > .ui-btn:first-child,
.uk-dropdown--split.uk-dropdown--toolbar > .ui-tbtn:first-child {
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
}
.uk-dropdown--split > .ui-btn.uk-dropdown__toggle--split,
.uk-dropdown--split > .ui-tbtn.uk-dropdown__toggle--split {
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
}

.uk-dropdown--split > .ui-btn.ui-btn--sm.uk-dropdown__toggle--split {
    padding-left: 0.375rem;
    padding-right: 0.375rem;
}

/* Toolbar split: tighter caret hit target next to icon buttons */
.uk-dropdown--split > .ui-tbtn.uk-dropdown__toggle--split {
    min-width: 1.25rem;
    padding-left: 0.25rem;
    padding-right: 0.25rem;
}

/* FA caret inherits the button face color (warning dark text, danger white, …). */
.uk-dropdown__toggle--split > i,
.uk-dropdown__caret > i {
    color: inherit;
    line-height: 1;
    pointer-events: none;
}

.uk-dropdown__menu {
    display: none;
    position: absolute;
    top: calc(100% + 2px);
    left: 0;
    z-index: var(--z-index-popover);
    min-width: 10rem;
    max-width: min(320px, 90vw);
    max-height: min(70vh, 480px);
    overflow-y: auto;
    padding: 2px 0;
    margin: 0;
    list-style: none;
    background: var(--uk-chrome-bg);
    border: 1px solid var(--uk-border);
    border-radius: var(--uk-input-radius);
    box-shadow: var(--uk-chrome-shadow);
    font-size: var(--uk-font-size);
    color: var(--uk-text-1);
    animation: uk-fade-in var(--uk-dur-fast) var(--uk-ease);
}

.uk-dropdown__menu.is-open { display: block; }

.uk-dropdown__menu--end {
    left: auto;
    right: 0;
}

.uk-dropdown__menu--up {
    top: auto;
    bottom: calc(100% + 2px);
}

.uk-dropdown__menu--panel {
    min-width: 0;
    max-width: none;
    padding: 0;
    overflow: visible;
}

/* Multi-select checkbox dropdown (UKMultiSelect / UKToolbarMultiSelect) */
.uk-multiselect {
    display: inline-flex;
    vertical-align: middle;
}

.uk-multiselect__trigger {
    min-width: 4rem;
    justify-content: space-between;
    font-size: var(--uk-font-size-xs);
    font-weight: 200;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.uk-multiselect__menu {
    min-width: 8rem;
    max-width: 22rem;
    max-height: none;
    flex-direction: column;
    padding: 0;
    overflow: hidden;
}

/* Must stay AFTER `.uk-dropdown__menu.is-open` (same specificity, later wins) and
   must NOT set `display` on the closed rule above — an unconditional `display: flex`
   there beats `.uk-dropdown__menu`'s `display: none` on source order, which left the
   menu permanently open. */
.uk-multiselect__menu.is-open { display: flex; }

.uk-multiselect__toolbar {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px 8px;
    border-bottom: 1px solid var(--uk-border, rgba(255, 255, 255, 0.08));
    flex-shrink: 0;
}

.uk-multiselect__search-wrap {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    flex: 1 1 auto;
    min-width: 0;
    position: relative;
}

.uk-multiselect__search {
    flex: 1 1 auto;
    min-width: 0;
    width: 100%;
    height: 24px;
    padding: 0.08rem 0.35rem 0.08rem 0.35rem;
    padding-right: 22px;
    font-size: var(--uk-font-size-sm, 0.75rem);
}

.uk-multiselect__search-clear {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    padding: 0;
    border-radius: var(--uk-radius);
    border: 1px solid transparent;
    background: transparent;
    color: var(--uk-danger);
    font-size: 10px;
    line-height: 1;
    cursor: pointer;
    flex: 0 0 auto;
    position: absolute;
    right: 4px;
    top: 50%;
    transform: translateY(-50%);
}
.uk-multiselect__search-clear:hover {
    background: color-mix(in srgb, var(--uk-danger) 16%, transparent);
    border-color: var(--uk-danger);
}

.uk-multiselect__actions {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    flex: 0 0 auto;
    margin-left: auto;
}

.uk-multiselect__actions .ui-btn {
    min-width: 1.75rem;
    padding-left: 0.35rem;
    padding-right: 0.35rem;
}

.uk-multiselect__list-host {
    position: relative;
    display: flex;
    flex-direction: column;
    min-height: 0;
    flex: 1 1 auto;
}

.uk-multiselect__list {
    flex: 1 1 auto;
    overflow: auto;
    padding: 4px 0;
    max-height: 14rem;
    scroll-behavior: smooth;
    scrollbar-width: thin;
    scrollbar-color: var(--scrollbar-thumb-color, rgba(255,255,255,0.25))
        var(--scrollbar-track-color, transparent);
    margin-bottom: 10px;
}

.uk-multiselect__list::-webkit-scrollbar {
    width: 8px;
}
.uk-multiselect__list::-webkit-scrollbar-thumb {
    background: var(--scrollbar-thumb-color, rgba(255,255,255,0.25));
    border-radius: 4px;
}

/* Window-style corner caret; drag adjusts height only (`ns-resize`). */
.uk-multiselect__resize {
    position: absolute;
    bottom: 0;
    right: 0;
    width: 12px;
    height: 12px;
    cursor: ns-resize;
    opacity: 0.35;
    z-index: 1;
}
.uk-multiselect__resize::before {
    content: '';
    position: absolute;
    bottom: 3px;
    right: 3px;
    width: 0;
    height: 0;
    border-style: solid;
    border-width: 0 0 6px 6px;
    border-color: transparent transparent var(--uk-text-2) transparent;
}
.uk-multiselect__resize:hover { opacity: 0.7; }

.uk-multiselect__option {
    display: flex;
    align-items: center;
    gap: 6px;
    margin: 0;
    padding: 2px 6px;
    font-weight: normal;
    line-height: 1.2;
    color: var(--uk-text-1);
    white-space: nowrap;
    cursor: pointer;
    user-select: none;
    font-size: var(--uk-font-size-sm);
}

.uk-multiselect__option:hover {
    background: rgba(255, 255, 255, 0.06);
}

.uk-multiselect__option--disabled {
    opacity: 0.45;
    cursor: not-allowed;
    pointer-events: none;
}

.uk-multiselect__option input[type="checkbox"] {
    position: relative;
    top: 0;
    margin: 0;
    flex: 0 0 auto;
    width: 12px;
    height: 12px;
    accent-color: var(--uk-accent, #6ea8fe);
    cursor: pointer;
}

.uk-multiselect__option-label {
    overflow: hidden;
    text-overflow: ellipsis;
}

.uk-dropdown__item {
    display: flex;
    align-items: center;
    gap: var(--uk-gap-xs);
    width: 100%;
    padding: 4px 10px;
    border: 0;
    background: transparent;
    color: var(--uk-text-1);
    font: inherit;
    text-align: left;
    cursor: pointer;
    user-select: none;
    white-space: nowrap;
    min-height: 28px;
    transition: background var(--uk-dur-fast);
}

.uk-dropdown__item:hover  { background: rgba(255,255,255,0.06); }
.uk-dropdown__item:active { background: rgba(255,255,255,0.10); }

.uk-dropdown__item--danger { color: var(--uk-danger); }
.uk-dropdown__item--danger:hover { background: rgba(238,95,91,0.08); }

.uk-dropdown__item:disabled,
.uk-dropdown__item--disabled {
    opacity: 0.4;
    cursor: not-allowed;
    pointer-events: none;
}

.uk-dropdown__icon {
    width: 14px;
    text-align: center;
    flex-shrink: 0;
    color: var(--uk-text-2);
}

.uk-dropdown__label { flex: 1 1 auto; min-width: 0; }

.uk-dropdown__header {
    padding: 6px 10px 2px;
    font-size: var(--uk-font-size-xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--uk-text-3);
    user-select: none;
}

.uk-dropdown__divider {
    border: none;
    border-top: 1px solid var(--uk-border-light);
    margin: var(--uk-gap-xs) 0;
}

.uk-dropdown__item-text {
    padding: 6px 10px;
    color: var(--uk-text-3);
    font-size: var(--uk-font-size-xs);
    user-select: none;
}

/* (toolbar split caret sizing lives with `.uk-dropdown__toggle--split` above) */


/* ============================================================
   29. Utilities
   ============================================================ */

/* flex helpers */
.ui-flex      { display: flex; }
.ui-flex-col  { display: flex; flex-direction: column; }
.ui-flex-row  { display: flex; flex-direction: row; }
.ui-items-center { align-items: center; }
.ui-justify-end  { justify-content: flex-end; }
.ui-justify-between { justify-content: space-between; }
.ui-gap-xs    { gap: var(--uk-gap-xs); }
.ui-gap-sm    { gap: var(--uk-gap-sm); }
.ui-gap       { gap: var(--uk-gap); }
.ui-gap-md    { gap: var(--uk-gap-md); }
.ui-flex-1    { flex: 1; }
.ui-min-h-0   { min-height: 0; }
.ui-shrink-0  { flex-shrink: 0; }
.ui-flex-wrap { flex-wrap: wrap; }

/* text */
.ui-text-1    { color: var(--uk-text-1); }
.ui-text-2    { color: var(--uk-text-2); }
.ui-text-3    { color: var(--uk-text-3); }
.ui-text-xs   { font-size: var(--uk-font-size-xs); }
.ui-text-sm   { font-size: var(--uk-font-size-sm); }
.ui-text-base { font-size: var(--uk-font-size); }
.ui-text-mono { font-family: monospace; }
.ui-bold      { font-weight: 600; }
.ui-truncate  { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* spacing */
.ui-p-sm  { padding: var(--uk-gap-sm); }
.ui-p-md  { padding: var(--uk-gap-md); }
.ui-p-lg  { padding: var(--uk-gap-lg); }
.ui-m-0   { margin: 0; }

/* display */
.ui-hidden   { display: none !important; }
.ui-visible  { visibility: visible; }
.ui-invisible { visibility: hidden; }

.ui-self-start { align-self: flex-start; }
.ui-self-end   { align-self: flex-end; }

/* full-width helpers */
.ui-w-full   { width: 100%; }
.ui-h-full   { height: 100%; }
.ui-fill     { width: 100%; height: 100%; }


/* ============================================================
   30. Stepper + busy overlay (multi-step flows)
   ============================================================ */

/* ── Stepper rail ── */

.ui-stepper {
    width: 170px;
    flex: 0 0 170px;
    background: var(--uk-surface-0);
    border-right: 1px solid var(--uk-border-light);
    padding: var(--uk-gap-xs);
    display: flex;
    flex-direction: column;
    gap: 2px;
    overflow: hidden;
    transition: width var(--uk-dur) var(--uk-ease), flex-basis var(--uk-dur) var(--uk-ease);
}

.ui-stepper--collapsed {
    width: 54px;
    flex-basis: 54px;
}

.ui-stepper--dimmed {
    opacity: 0.45;
    pointer-events: none;
}

.ui-stepper__toggle {
    align-self: flex-end;
    margin-bottom: 2px;
}

.ui-stepper--collapsed .ui-stepper__toggle {
    align-self: center;
}

.ui-stepper__list {
    display: flex;
    flex-direction: column;
    gap: var(--uk-gap-xs);
}

.ui-stepper__step {
    display: flex;
    align-items: center;
    gap: var(--uk-gap-xs);
    padding: 3px 4px;
    border: 1px solid transparent;
    border-radius: var(--uk-input-radius);
    background: rgba(127, 127, 127, 0.05);
    cursor: pointer;
    text-align: left;
    color: var(--uk-text-1);
    opacity: 0.5;
    width: 100%;
    font: inherit;
    font-size: var(--uk-font-size);
}

.ui-stepper__step--reachable { opacity: 1; }
.ui-stepper__step:disabled { cursor: default; }

.ui-stepper__step--active {
    background: rgba(0, 123, 255, 0.14);
    border-color: var(--uk-accent);
    opacity: 1;
}

.ui-stepper__step--busy .ui-stepper__ic {
    animation: uk-step-pulse 1.1s ease-in-out infinite;
}

.ui-stepper__ic {
    flex: 0 0 18px;
    width: 18px;
    height: 18px;
    border-radius: var(--uk-input-radius);
    background: var(--uk-surface-2);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: var(--uk-font-size-xs);
    font-weight: 600;
}

.ui-stepper__step--done .ui-stepper__ic { background: var(--uk-success); color: #fff; }
.ui-stepper__step--active .ui-stepper__ic { background: var(--uk-accent); color: #fff; }

.ui-stepper__text {
    display: flex;
    flex-direction: column;
    min-width: 0;
    line-height: 1.25;
}

.ui-stepper__label {
    font-size: var(--uk-font-size-sm);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.ui-stepper__sub {
    font-size: var(--uk-font-size-xs);
    color: var(--uk-text-3);
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

.ui-stepper--collapsed .ui-stepper__step {
    justify-content: center;
    padding: 3px 0;
}

.ui-stepper--collapsed .ui-stepper__text { display: none; }

@keyframes uk-step-pulse {
    0%, 100% { outline: 0 solid rgba(0, 123, 255, 0.5); }
    50% { outline: 2px solid rgba(0, 123, 255, 0); }
}

/* ── Busy overlay ── */

.ui-busy-overlay {
    position: absolute;
    inset: 0;
    z-index: 20;
    display: none;
    align-items: center;
    justify-content: center;
    background: rgba(0, 0, 0, 0.72);
    backdrop-filter: blur(2px);
}

.ui-busy-overlay--active { display: flex; }

.ui-busy-overlay__card {
    /* Wider than the original 360px: six labelled readings and a preview
       thumbnail do not fit at that width, and they do at this one. */
    width: min(460px, 94%);
    background: var(--uk-chrome-bg);
    border: 1px solid var(--uk-border);
    border-radius: var(--uk-input-radius);
    box-shadow: var(--uk-chrome-shadow);
    padding: var(--uk-gap-md);
    display: flex;
    flex-direction: column;
    gap: var(--uk-gap-sm);
}

.ui-busy-overlay__head {
    display: flex;
    align-items: center;
    gap: var(--uk-gap);
}

.ui-busy-overlay__titles { flex: 1; min-width: 0; }

.ui-busy-overlay__stage {
    font-size: var(--uk-font-size);
    font-weight: 600;
    color: var(--uk-text-1);
}

.ui-busy-overlay__sub {
    font-size: var(--uk-font-size-xs);
    color: var(--uk-text-3);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.ui-busy-overlay__pct {
    font-size: var(--uk-font-size-sm);
    color: var(--uk-text-2);
    font-variant-numeric: tabular-nums;
    flex-shrink: 0;
}

.ui-busy-overlay__gauge-label {
    font-size: var(--uk-font-size-xs);
    color: var(--uk-text-3);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    margin-top: -2px;
}

.ui-busy-overlay__job-bar { opacity: 0.75; }

/* Preview + log share one row, so the thumbnail costs no extra card height. */
.ui-busy-overlay__body {
    display: flex;
    gap: var(--uk-gap-sm);
    align-items: stretch;
    min-width: 0;
}

.ui-busy-overlay__preview {
    width: var(--uk-busy-preview, 96px);
    height: var(--uk-busy-preview, 96px);
    flex: 0 0 auto;
    object-fit: contain;
    background: var(--uk-surface-0);
    border: 1px solid var(--uk-border-light);
    border-radius: var(--uk-input-radius);
    image-rendering: auto;
}

.ui-busy-overlay__log {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: var(--uk-font-size-xs);
    line-height: 1.45;
    color: var(--uk-text-2);
    background: var(--uk-surface-0);
    border: 1px solid var(--uk-border-light);
    border-radius: var(--uk-input-radius);
    padding: 4px 6px;
    height: 96px;
    user-select: text;
    /* min-width: 0 lets a long log line ellipsise inside the flex row instead
       of pushing the preview out of the card. */
    flex: 1;
    min-width: 0;
}

/* ── Machine readout (job SSE `event: resources`) ── */

.ui-busy-overlay__res {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 2px var(--uk-gap-sm);
    font-size: var(--uk-font-size-xs);
    color: var(--uk-text-3);
    border-top: 1px solid var(--uk-border-light);
    padding-top: var(--uk-gap-sm);
    margin-bottom: var(--uk-gap);
}

.ui-busy-overlay__res-cell {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: baseline;
    gap: 4px;
    min-width: 0;
    user-select: none;
    -webkit-user-select: none;
    -moz-user-select: none;
}

.ui-busy-overlay__res-label {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ui-busy-overlay__res-value {
    color: var(--uk-text-2);
    /* Tabular figures so the row does not jitter as values change width. */
    font-variant-numeric: tabular-nums;
}

.ui-busy-overlay__res-cell--warn .ui-busy-overlay__res-value { color: var(--uk-signal); }

.ui-busy-overlay__res-bar {
    grid-column: 1 / -1;
    height: 2px;
    background: var(--uk-track-bg);
    border-radius: 1px;
    overflow: hidden;
}

.ui-busy-overlay__res-bar-fill {
    display: block;
    height: 100%;
    width: 0;
    background: var(--uk-accent);
    transition: width var(--uk-motion, 120ms) linear;
}

.ui-busy-overlay__log-time {
    color: var(--uk-text-3);
    margin-right: 6px;
}

.ui-busy-overlay__log-line--err { color: var(--uk-danger); }

.ui-busy-overlay__cancel { align-self: center; }

/* ── Preview extras ── */

.ui-preview__img { max-width: 100%; max-height: 100%; object-fit: contain; }

.ui-preview__hint {
    position: absolute;
    bottom: 4px;
    left: 6px;
    font-size: var(--uk-font-size-xs);
    background: rgba(0, 0, 0, 0.55);
    color: #fff;
    padding: 0 4px;
    border-radius: var(--uk-input-radius);
    pointer-events: none;
}

.ui-preview__badge {
    position: absolute;
    top: 4px;
    right: 4px;
    background: rgba(0, 0, 0, 0.55);
    color: #fff;
    font-size: var(--uk-font-size-xs);
    padding: 0 4px;
    border-radius: var(--uk-input-radius);
    pointer-events: none;
}

/* ── Split layout (sidebar + main) ── */

.ui-split {
    display: flex;
    gap: var(--uk-gap);
    height: 100%;
    min-height: 0;
}

/* A rail is fixed-width and usually taller than the split (settings forms, tool stacks),
   so it scrolls itself rather than spilling past the panel. A consumer that must clip
   instead overrides with a compound selector — see `.ui-split__side.ui-asset-preview-column`.

   Whoever decorates a UKSplit column must use `classList.add`, not `className =`:
   assigning drops this class and with it the column layout AND `flex-shrink: 0`, which
   leaves the rail free to squeeze to min-content while keeping the inline width UKSplit
   set — a rail that looks almost right and is not. */
.ui-split__side {
    display: flex;
    flex-direction: column;
    gap: var(--uk-gap-sm);
    min-height: 0;
    min-width: 0;
    flex-shrink: 0;
    /* Both axes stated on purpose: a lone `overflow-y` would leave `overflow-x: visible`,
       which CSS then computes to `auto` — and Chrome reports a <button>'s min-content
       width as scrollable overflow even when nothing visibly sticks out, so the rail grew
       a phantom horizontal scrollbar. A rail is fixed-width; there is nothing to scroll to
       sideways. */
    overflow-x: hidden;
    overflow-y: auto;
}

.ui-split__main {
    flex: 1;
    min-width: 0;
    min-height: 0;
    display: flex;
    flex-direction: column;
    gap: var(--uk-gap-xs);
}


/* ============================================================
   31. Empty state
   ============================================================ */

.ui-empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--uk-gap-xs);
    padding: var(--uk-gap-md);
    color: var(--uk-text-3);
    font-size: var(--uk-font-size);
    text-align: center;
}

.ui-empty-state__icon {
    font-size: 1rem;
    opacity: 0.45;
}

.ui-empty-state__text {
    max-width: 28rem;
    line-height: 1.4;
}

/* ============================================================
   "Graphite Instrument" signature layer
   - machined keyline on raised chrome
   - amber "armed" state (active tool / live / unsaved)
   - mono numeric readouts
   - reduced-motion floor
   ============================================================ */

/* Machined keyline: a 1px top-inset highlight that reads as brushed metal.
   Applied to raised chrome; box-shadow so it never affects layout. */
.ui-panel__header,
.ui-card__header,
.ui-window__header,
.ui-context-menu,
.ui-dialog {
    box-shadow: inset 0 1px 0 0 var(--uk-keyline);
}
.ui-btn--primary,
.ui-btn--secondary {
    box-shadow: inset 0 1px 0 0 var(--uk-keyline);
}
.ui-btn--primary:active,
.ui-btn--secondary:active { box-shadow: none; }

/* Menus / popovers sit on the highest surface. */
.ui-context-menu { background: var(--uk-overlay); }

/* Amber "armed" state — the currently-live tool / gizmo / unsaved marker.
   Reserved as the app's second accent; never used for plain interactivity. */
.ui-btn--armed,
.is-armed,
[data-armed="true"] {
    background: var(--uk-signal-muted);
    border-color: var(--uk-signal);
    color: var(--uk-signal);
}
.ui-btn--armed:hover,
.is-armed:hover { background: var(--uk-signal-muted); border-color: var(--uk-signal-hover); color: var(--uk-signal-hover); }

/* Unsaved / attention dot */
.ui-dot--signal {
    display: inline-block;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--uk-signal);
    box-shadow: 0 0 0 2px var(--uk-signal-muted);
}

/* Numeric / data readouts inside UIKit (coords, tile #, elevation). */
.ui-range__value,
.ui-num {
    font-family: var(--font-family-data);
    font-variant-numeric: tabular-nums;
    font-feature-settings: 'tnum' 1;
}

@media (prefers-reduced-motion: reduce) {
    * {
        animation-duration: 0.001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.001ms !important;
        scroll-behavior: auto !important;
    }
}


/* ============================================================
   Utilities
   ============================================================ */
.uk-is-hidden { display: none !important; }


/* ============================================================
   UIMenuBar — application menu bar (dropdowns / submenus)
   ============================================================ */

.uk-menubar {
    position: absolute;
    top: 100%;
    left: var(--uk-gap-sm);
    z-index: 1001;
    display: none;
    margin-top: var(--uk-gap-xs);
    font-family: var(--font-family-base);
    font-size: var(--uk-font-size-md);
    color: var(--uk-text-1);
}
.uk-menubar.is-open { display: block; }

/* Persistent desktop menu bar: always-visible inline row (File / Edit / View …),
   compact enough to sit in the thin viewport toolbar. Dropdowns still open below
   each top item (absolute, so they escape the toolbar). */
   .uk-menubar--persistent {
    position: static;
    display: flex;
    align-items: stretch;
    align-self: stretch;
    margin-top: 0;
    z-index: auto;
    height: 100%;
}
.uk-menubar--persistent .uk-menubar__bar {
    gap: 0;
    height: 100%;
    align-items: stretch;
    background: transparent;
    border: 0;
    box-shadow: none;
}
.uk-menubar--persistent .uk-menubar__menu {
    height: 100%;
    align-self: stretch;
    align-items: stretch;
}
.uk-menubar--persistent .uk-menubar__top {
    display: flex;
    align-items: center;
    align-self: stretch;
    height: auto;
    padding: 0 0.6rem;
    font-size: 0.75rem;
    border-radius: 0;
    border-right: 1px solid var(--border-base);
}
.uk-menubar--persistent .uk-menubar__top:first-child { border-left: 0; }

/* Horizontal ribbon of top-level menus — flat, matte, industrial look */
.uk-menubar__bar {
    display: inline-flex;
    align-items: stretch;
    gap: 0;
    padding: 0;
    background: var(--surface-2);
    border: 1px solid var(--border-base);
    border-radius: 0;
    box-shadow: none;
    backdrop-filter: none;
}

.uk-menubar__menu { position: relative; display: flex; align-items: stretch; }

.uk-menubar__top {
    appearance: none;
    border: 0;
    border-right: 1px solid var(--border-base);
    background: transparent;
    color: var(--uk-text-2);
    font: inherit;
    font-size: 0.75rem;
    line-height: 1;
    padding: 0.4rem 0.75rem;
    border-radius: 0;
    cursor: pointer;
    white-space: nowrap;
    transform: none;
    transition: background var(--uk-dur-fast) var(--uk-ease),
                color var(--uk-dur-fast) var(--uk-ease);
}
.uk-menubar__top:first-child { border-left: 0; }
.uk-menubar__top:hover,
.uk-menubar__top:active {
    background: var(--uk-accent);
    color: var(--uk-accent-text);
    transform: none;
}
.uk-menubar__top.is-active:hover {
    background: var(--uk-accent-hover);
}

/* Dropdown panels (top-level + nested) — flat, matte style */
.uk-menu {
    position: absolute;
    top: 100%;
    left: 0;
    z-index: 2;
    display: none;
    min-width: 14rem;
    overflow: visible;
    margin-top: 0;
    padding: 0;
    background: var(--surface-3);
    border: 1px solid var(--border-base);
    border-radius: 0;
    box-shadow: var(--shadow-md);
    backdrop-filter: none;
}
.uk-menubar__menu.is-open > .uk-menu { display: block; }

.uk-menu--sub {
    top: 0;
    left: 100%;
    margin: 0;
    border-left: 1px solid var(--border-base);
}
.uk-menu__item--sub:hover > .uk-menu--sub,
.uk-menu__item--sub.is-open > .uk-menu--sub { display: block; }

/* Rows — flat menu items with lime accent on hover */
.uk-menu__item {
    position: relative;
    display: flex;
    align-items: center;
    gap: var(--uk-gap-sm);
    width: 100%;
    box-sizing: border-box;
    appearance: none;
    border: 0;
    border-bottom: 1px solid var(--border-subtle);
    background: transparent;
    color: var(--uk-text-1);
    font: inherit;
    text-align: left;
    line-height: 1.2;
    padding: 0.5rem 0.75rem;
    border-radius: 0;
    cursor: pointer;
    white-space: nowrap;
    transition: all var(--uk-dur-fast) var(--uk-ease);
}
.uk-menu__item:last-child { border-bottom: 0; }
.uk-menu__item:hover,
.uk-menu__item--sub:hover {
    background: var(--uk-accent);
    color: var(--uk-accent-text);
}
.uk-menu__item.is-active {
    background: var(--uk-accent);
    color: var(--uk-accent-text);
}
.uk-menu__item.is-disabled {
    color: var(--uk-text-3);
    font-style: italic;
    cursor: default;
    pointer-events: none;
}

.uk-menu__icon {
    flex: 0 0 auto;
    width: 1.15em;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 0.95em;
    color: var(--uk-text-2);
}
.uk-menu__item:hover > .uk-menu__icon { color: inherit; }
.uk-menu__label { flex: 1 1 auto; }
.uk-menu__shortcut {
    flex: 0 0 auto;
    margin-left: var(--uk-gap-md);
    font-family: var(--font-family-mono);
    font-size: 0.85em;
    color: var(--uk-text-3);
}
.uk-menu__item:hover > .uk-menu__shortcut { color: inherit; opacity: 0.85; }
.uk-menu__arrow {
    flex: 0 0 auto;
    margin-left: auto;
    width: 1em;
    text-align: right;
    color: var(--uk-text-3);
}
.uk-menu__arrow::after { content: '\203A'; }   /* › */
.uk-menu__item--sub:hover > .uk-menu__arrow { color: inherit; }

/* Checkable items — check glyph occupies the icon slot */
.uk-menu__item--check.is-checked > .uk-menu__icon::after { content: '\2713'; }  /* ✓ */
.uk-menu__item--check.is-checked > .uk-menu__icon { color: var(--uk-accent); }
.uk-menu__item--check.is-checked:hover > .uk-menu__icon { color: inherit; }

.uk-menu__sep {
    height: 1px;
    margin: 0;
    background: var(--border-base);
}

.uk-menu__info {
    padding: 0.2rem 0.6rem;
    font-size: var(--uk-font-size-xs);
    font-style: italic;
    color: var(--uk-text-3);
    white-space: normal;
}


/* ============================================================
   UIToolButton — tool buttons & palettes
   ============================================================ */

.uk-toolbtn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--uk-gap-xs);
    box-sizing: border-box;
    appearance: none;
    border: 1px solid transparent;
    border-radius: var(--uk-radius);
    background: transparent;
    color: var(--uk-text-2);
    font-family: var(--font-family-base);
    font-size: var(--uk-font-size);
    line-height: 1;
    cursor: pointer;
    transition: background var(--uk-dur-fast) var(--uk-ease),
                color var(--uk-dur-fast) var(--uk-ease),
                border-color var(--uk-dur-fast) var(--uk-ease);
}
.uk-toolbtn--sm { height: 1.25rem; min-width: 1.25rem; padding: 0 0.25rem; }
.uk-toolbtn--md { height: 1.55rem; min-width: 1.55rem; padding: 0 0.4rem; }
.uk-toolbtn--lg { height: 1.9rem;  min-width: 1.9rem;  padding: 0 0.55rem; font-size: var(--uk-font-size-md); }
.uk-toolbtn--labelled { padding-inline: 0.55rem; }

.uk-toolbtn:hover { background: var(--uk-surface-2); color: var(--uk-text-1); }
.uk-toolbtn:focus-visible { outline: none; box-shadow: var(--uk-focus-ring); }
.uk-toolbtn.is-active {
    background: var(--uk-accent-muted);
    border-color: var(--uk-accent-border, var(--uk-accent));
    color: var(--uk-accent-hover);
}
.uk-toolbtn.is-active:hover { background: var(--uk-accent-muted); color: var(--uk-accent-hover); }
.uk-toolbtn.is-disabled,
.uk-toolbtn:disabled { opacity: 0.4; cursor: default; pointer-events: none; }

.uk-toolbtn__icon { display: inline-flex; align-items: center; justify-content: center; }
.uk-toolbtn__label { white-space: nowrap; }
.uk-toolbtn__badge {
    min-width: 1rem;
    padding: 0 0.2rem;
    border-radius: var(--uk-radius-full);
    background: var(--uk-signal);
    color: var(--surface-0);
    font-family: var(--font-family-data);
    font-size: var(--uk-font-size-xs);
    line-height: 1rem;
    text-align: center;
}

.uk-toolbtn-group {
    display: inline-flex;
    align-items: center;
    gap: var(--uk-gap-xs);
}
.uk-toolbtn-group--column { flex-direction: column; align-items: stretch; }
.uk-toolbtn-group__sep {
    align-self: stretch;
    width: 1px;
    margin: 0.15rem var(--uk-gap-xs);
    background: var(--uk-border-light);
}
.uk-toolbtn-group--column > .uk-toolbtn-group__sep {
    width: auto;
    height: 1px;
    margin: var(--uk-gap-xs) 0.15rem;
}


/* ============================================================
   StatusBar chrome (footer bar + console drawer + docking)
   ============================================================ */

/* In-flow inside .app-footer — not position:fixed. Fixed bottom placement
   collapsed the footer and let .viewport-container extend under the chrome,
   so maximized UKWindows had no correct host rect to clamp to. */
.status-bar {
    position: relative;
    width: 100%;
    display: flex;
    flex-direction: column;
    z-index: 10000;
    pointer-events: auto;
}

/* Console debugger drawer — hosts the log window */
.status-bar-debugger {
    display: flex;
    flex-direction: column;
    height: 0;
    max-height: 60vh;
    overflow: hidden;
    opacity: 0;
    transform: translateY(6px);
    pointer-events: none;
    background: var(--surface-sunken);
    border-top: 1px solid transparent;
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    contain: layout paint;
    overscroll-behavior: contain;
    transition: height var(--dur) var(--ease-standard),
                opacity var(--dur-fast) var(--ease-standard),
                transform var(--dur) var(--ease-standard);
}
.status-bar-debugger.is-expanded {
    height: var(--sb-debugger-height, 8rem);
    min-height: var(--sb-debugger-height, 8rem);
    flex-shrink: 0;
    opacity: 0.8;
    transform: translateY(0);
    pointer-events: auto;
    border-top-color: var(--keyline);
}
/* No transition while the user is dragging the resize handle */
.status-bar.is-resizing .status-bar-debugger { transition: none; }

/* Resize handle at the top edge of the drawer */
.status-bar-resize-handle {
    height: 4px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: ns-resize;
    opacity: 0;
    pointer-events: none;
    touch-action: none;
    background: linear-gradient(to right, transparent, var(--border-strong), transparent);
    border-bottom: 1px solid var(--keyline);
    transition: opacity var(--dur-fast) var(--ease-standard),
                background var(--dur) var(--ease-standard);
}
.status-bar-debugger.is-expanded .status-bar-resize-handle {
    opacity: 1;
    pointer-events: auto;
}
.status-bar-resize-handle:hover {
    background: linear-gradient(to right, transparent, var(--accent), transparent);
}

/* Raise the whole footer (drawer included) above dialogs when pinned */
.status-bar.is-pinned-top { z-index: 2147483000; }

/* ============================================================
   Log panel (console drawer contents): toolbar + scrollable list
   ============================================================ */
.log-panel {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
    background: var(--surface-sunken);
    color: var(--text-2);
    font-family: var(--font-family-mono, monospace);
    font-size: var(--font-size-xs, 0.625rem);
    line-height: 1.35;
}

/* Toolbar */
.log-panel__toolbar {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 0 0 auto;
    flex-wrap: wrap;
    padding: 4px 8px;
    background: var(--surface-2);
    border-bottom: 1px solid var(--keyline);
}

.log-panel__filters { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }

.log-panel__chip {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 2px 7px;
    height: 20px;
    border-radius: 999px;
    border: 1px solid var(--border-base);
    background: var(--surface-3);
    color: var(--text-3);
    font-family: var(--font-family-data, monospace);
    font-size: var(--font-size-xs, 0.625rem);
    line-height: 1;
    cursor: pointer;
    opacity: 0.55;
    transition: background var(--dur-fast) var(--ease-standard),
                border-color var(--dur-fast) var(--ease-standard),
                opacity var(--dur-fast) var(--ease-standard);
}
.log-panel__chip:hover { background: var(--surface-4); }
.log-panel__chip.is-active { opacity: 1; }
.log-panel__chip-count {
    min-width: 14px;
    padding: 0 3px;
    text-align: center;
    border-radius: 999px;
    background: var(--surface-1, rgba(0,0,0,0.25));
    color: var(--text-2);
    font-size: 9px;
}
/* Per-type accent when active (dot + count tint) */
.log-panel__chip::before {
    content: "";
    width: 7px; height: 7px;
    border-radius: 50%;
    background: currentColor;
    flex: 0 0 auto;
}
.log-panel__chip--log.is-active    { color: var(--text-1); border-color: var(--border-strong); }
.log-panel__chip--info.is-active   { color: var(--accent-hover, #57adff); border-color: var(--accent-border, rgba(58,160,255,0.5)); }
.log-panel__chip--debug.is-active  { color: var(--text-3, #6e7880); border-color: var(--border-strong); }
.log-panel__chip--warn.is-active   { color: var(--status-warning, #e0a63a); border-color: var(--status-warning, #e0a63a); }
.log-panel__chip--error.is-active  { color: var(--status-danger, #ee6a5f); border-color: var(--status-danger, #ee6a5f); }
.log-panel__chip.is-active .log-panel__chip-label { color: var(--text-1); }

/* Search */
.log-panel__search {
    position: relative;
    display: flex;
    align-items: center;
    flex: 1 1 160px;
    min-width: 120px;
}
.log-panel__search-icon {
    position: absolute;
    left: 8px;
    font-size: 10px;
    color: var(--text-3);
    pointer-events: none;
}
.log-panel__search-input {
    width: 100%;
    height: 22px;
    padding: 0 8px 0 24px;
    border-radius: var(--radius-md, 6px);
    border: 1px solid var(--border-base);
    background: var(--surface-3);
    color: var(--text-1);
    font-family: var(--font-family-mono, monospace);
    font-size: var(--font-size-xs, 0.625rem);
}
.log-panel__search-input:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: var(--focus-ring);
}
.log-panel__search-input::placeholder { color: var(--text-3); }

/* Action buttons */
.log-panel__actions { display: flex; align-items: center; gap: 4px; }
.log-panel__btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 22px;
    border-radius: var(--radius-sm, 5px);
    border: 1px solid var(--border-base);
    background: var(--surface-3);
    color: var(--text-2);
    font-size: 11px;
    cursor: pointer;
    transition: background var(--dur-fast) var(--ease-standard),
                color var(--dur-fast) var(--ease-standard),
                border-color var(--dur-fast) var(--ease-standard);
}
.log-panel__btn:hover { background: var(--surface-4); color: var(--text-1); }
.log-panel__btn.is-active {
    background: var(--accent-muted, rgba(58,160,255,0.14));
    border-color: var(--accent-border, rgba(58,160,255,0.5));
    color: var(--accent-hover, #57adff);
}
.log-panel__btn--danger:hover {
    background: var(--status-danger, #ee6a5f);
    border-color: var(--status-danger, #ee6a5f);
    color: var(--surface-0, #fff);
}

/* Scrollable log list */
.log-panel__body {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
    overscroll-behavior: contain;
    padding: 4px 8px 6px;
    user-select: text;
    -webkit-user-select: text;
}
.log-panel__body:focus { outline: none; }

.log-row {
    display: flex;
    align-items: baseline;
    gap: 8px;
    padding: 1px 0;
    border-bottom: 1px solid transparent;
    white-space: nowrap;
}
.log-row__time {
    flex: 0 0 auto;
    color: var(--text-3);
    font-variant-numeric: tabular-nums;
    opacity: 0.8;
}
.log-row__tag {
    flex: 0 0 44px;
    text-align: right;
    font-weight: 600;
    letter-spacing: 0.3px;
    color: var(--text-3);
}
.log-row__msg {
    flex: 1 1 auto;
    min-width: 0;
    white-space: pre-wrap;
    word-break: break-word;
    color: var(--text-2);
}
.log-row--log   .log-row__tag { color: var(--text-2); }
.log-row--info  .log-row__tag { color: var(--accent-hover, #57adff); }
.log-row--info  .log-row__msg { color: var(--text-1); }
.log-row--debug .log-row__tag { color: var(--text-3, #6e7880); }
.log-row--debug .log-row__msg { color: var(--text-3, #6e7880); }
.log-row--warn  .log-row__tag,
.log-row--warn  .log-row__msg { color: var(--status-warning, #e0a63a); }
.log-row--error .log-row__tag,
.log-row--error .log-row__msg { color: var(--status-danger, #ee6a5f); }
.log-row--error { background: color-mix(in srgb, var(--status-danger, #ee6a5f) 8%, transparent); }

/* Left cluster: loaded-map name chip, then the docking area for minimized dialogs */
.status-bar-left-cluster {
    display: flex;
    align-items: center;
    gap: var(--uk-gap-sm);
    height: 100%;
    min-width: 0;
    flex: 1;
    overflow: hidden;
}

/* Loaded-map name chip: bold editable name + red close (×) button */
.status-bar-map-session {
    display: flex;
    align-items: center;
    gap: var(--uk-gap-xs);
    flex: 0 0 auto;
    padding-right: var(--uk-gap-sm);
    border-right: 1px solid var(--border-base);
}
.status-bar-map-session[hidden] { display: none; }

.status-bar-map-name {
    font-weight: 700;
    font-size: 10px;
    font-family: var(--font-family-data, monospace);
    color: var(--text-1);
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--uk-radius);
    padding: 1px 4px;
    height: 18px;
    max-width: 160px;
    box-sizing: border-box;
}
.status-bar-map-name:hover {
    border-color: var(--border-base);
}
.status-bar-map-name:focus {
    outline: none;
    border-color: var(--accent, #3aa0ff);
    background: var(--surface-3, #2c3237);
}

.status-bar-map-close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    padding: 0;
    border-radius: var(--uk-radius);
    border: 1px solid transparent;
    background: transparent;
    color: var(--uk-danger);
    font-size: 10px;
    line-height: 1;
    cursor: pointer;
}
.status-bar-map-close:hover {
    background: color-mix(in srgb, var(--uk-danger) 16%, transparent);
    border-color: var(--uk-danger);
}

/* Docking area for minimized windows (display toggled by UKWindow) */
.dialog-docking-container {
    align-items: center;
    justify-content: flex-start;
    gap: var(--uk-gap-sm);
    height: 100%;
    min-height: 18px;
    flex: 1;
    min-width: 0;
    overflow: hidden;
    padding: 0 var(--uk-gap-sm);
    box-sizing: border-box;
}

/* Default readout sections — stable widths so values don't jitter */
.status-bar .UIStatusBar_Section { font-variant-numeric: tabular-nums; }
.status-bar-sec--mouse   { min-width: 120px; }
.status-bar-sec--tile    { min-width: 120px; }
.status-bar-sec--height  { min-width: 90px; }
.status-bar-sec--mode    { min-width: 110px; }
.status-bar-sec--camera  { min-width: 260px; }
.status-bar-sec--version { min-width: 140px; }

/* Dev-mode window cue. Applied at BOOT by `applyDevChrome`, which ships (inert)
   in the main bundle, so this one rule stays here rather than in src/dev/dev.css —
   a lazily-loaded chunk would make the outline flash in late. ~100 bytes. */
body.browjs-dev {
    outline: 3px solid #c0392b;
    outline-offset: -3px;
}

.status-bar-dev-chip {
    display: inline-flex;
    align-items: center;
    margin-right: 6px;
    padding: 1px 6px;
    border: none;
    border-radius: var(--uk-radius, 3px);
    background: #c0392b;
    color: #fff;
    font-family: inherit;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.04em;
    line-height: 1.4;
    user-select: none;
    cursor: pointer;
}
.status-bar-dev-chip.is-auto-reload {
    background: #e67e22;
    box-shadow: inset 0 0 0 1px #fff;
}
.status-bar-reload-btn {
    margin-right: 6px;
}

/* Clickable status-bar sections (e.g. version -> changelog dialog) */
.status-bar-sec--clickable {
    cursor: pointer;
    border-radius: var(--radius-sm, 3px);
}
.status-bar-sec--clickable:hover,
.status-bar-sec--clickable:focus-visible {
    background: var(--surface-3, #2c3237);
}
.status-bar-sec--clickable:focus-visible {
    outline: 1px solid var(--accent, #3aa0ff);
    outline-offset: -1px;
}

/* Worker activity indicator */
.worker-activity-indicator {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 18px;
    padding: 1px 6px;
    border-radius: var(--uk-radius);
    background: var(--surface-2);
    border: 1px solid var(--border-base);
    opacity: 0.85;
}
.worker-activity-indicator:hover { background: var(--surface-3); }
.worker-activity-dot {
    width: 9px;
    height: 9px;
    border-radius: var(--radius-full);
    background: var(--text-3);
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.35);
}
.worker-activity-indicator.is-active .worker-activity-dot {
    background: var(--status-success);
    box-shadow: 0 0 8px var(--status-success), inset 0 0 0 1px rgba(255, 255, 255, 0.22);
}

/* The log panel's floating host (ConsoleDebuggerDialog with no container): the panel
   owns its own scrolling, so the window body must not add padding or a second
   scrollbar around it. */
.log-panel-window .ui-window__content {
    padding: 0;
    display: flex;
    flex-direction: column;
    min-height: 0;
    overflow: hidden;
}


/* ============================================================
   ViewportToolbar (top chrome) — migrated from ViewportToolbar.css
   ============================================================ */

#viewport-toolbar {
    /* position: fixed; */
    top: 0;
    left: 0;
    right: 0;
    min-height: var(--top-toolbar-height, 2.5rem);
    padding: 0.2rem 0.4rem;
    gap: 0.35rem;
    z-index: 1000;
    flex-wrap: wrap;
    align-items: center;
    background: var(--surface-0);
    border-bottom: 1px solid var(--border-base);
}

/* Compact the shared toolbar-button sizing for the dense top chrome, while keeping
   the icon-over-corner-shortcut layout from the UKToolbarButton component. */
#viewport-toolbar .ui-tbtn {
    min-width: 2.5rem;
    min-height: 2rem;
    padding: 0.2rem 0.35rem;
    gap: 0;
}
#viewport-toolbar .ui-tbtn__icon { font-size: 0.9rem; }
#viewport-toolbar .ui-tbtn__label { font-size: 0.6rem; }
#viewport-toolbar .ui-tbtn__sc {
    right: 1px; bottom: 0;
    font-size: 0.5rem; padding: 0 2px;
}

/* Split-button dropdown carets sit tight against their primary button. */
#viewport-toolbar .ui-tbtn--caret,
#viewport-toolbar .uk-dropdown__caret {
    min-width: 1.1rem;
    padding-left: 0.1rem;
    padding-right: 0.1rem;
}

/* Inline sub-cluster wrapper (split buttons + their UK dropdown menu). */
#viewport-toolbar .ui-toolbar__subgroup,
#viewport-toolbar .uk-dropdown--toolbar {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 1px;
}

#viewport-toolbar .uk-dropdown__menu--panel {
    max-height: calc(100vh - 60px);
    overflow-y: auto;
}

#viewport-toolbar .uk-dropdown__recent {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 14rem;
    max-width: 18rem;
}
#viewport-toolbar .uk-dropdown__recent-title {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 0.5rem;
}
#viewport-toolbar .uk-dropdown__recent-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
#viewport-toolbar .uk-dropdown__recent-badge {
    flex-shrink: 0;
    font-size: 0.55rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding: 1px 6px;
    border-radius: 999px;
    background: var(--uk-surface-2);
    color: var(--uk-text-2);
}
#viewport-toolbar .uk-dropdown__recent-badge--data {
    background: rgba(80, 200, 120, 0.2);
    color: #8ee4a8;
}
#viewport-toolbar .uk-dropdown__recent-badge--grf {
    background: rgba(80, 160, 220, 0.2);
    color: #9ec8f0;
}
#viewport-toolbar .uk-dropdown__recent-path {
    font-size: var(--uk-font-size-xs);
    color: var(--uk-text-3);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Inline label + select inside the light-mode cluster. */
#viewport-toolbar .ui-toolbar__text {
    font-size: 0.68rem;
    color: var(--text-2);
    padding: 0 0.25rem;
    white-space: nowrap;
}
#viewport-toolbar .ui-toolbar__select {
    height: 1.5rem;
    /* font-size: 0.68rem; */
    margin-right: 0.5rem;
    min-width: 5.5rem;
}

#viewport-toolbar .hamburger-button {
    min-width: 1.6rem;
    justify-content: center;
}

/* Render options dropdown */
#viewport-toolbar .render-options-panel {
    min-width: 260px;
    max-width: 300px;
    padding: 0.6rem 0.7rem;
    display: flex;
    flex-direction: column;
    gap: 0.55rem;
}
#viewport-toolbar .render-options-header {
    font-size: 0.75rem;
    font-weight: 600;
    padding-bottom: 0.35rem;
    border-bottom: 1px solid var(--keyline);
}
#viewport-toolbar .render-options-section {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
}
#viewport-toolbar .render-options-section-header {
    font-size: 0.62rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-3);
}
#viewport-toolbar .render-options-section-body {
    display: flex;
    flex-direction: column;
    gap: 0.45rem;
}
#viewport-toolbar .render-options-row {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    margin: 0;
    padding: 0.15rem 0;
    cursor: pointer;
    user-select: none;
}
#viewport-toolbar .render-options-row input { margin: 0; flex-shrink: 0; }
#viewport-toolbar .render-options-row-label { font-size: 0.72rem; flex: 1; min-width: 0; }
#viewport-toolbar .render-options-inline {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    border-radius: var(--radius-lg);
    padding: 8px;
    background: var(--surface-2);
}
#viewport-toolbar .render-options-inline-label { font-size: 0.72rem; margin: 0; flex-shrink: 0; }
#viewport-toolbar .render-options-inline-value {
    font-size: 0.68rem;
    font-variant-numeric: tabular-nums;
    color: var(--text-2);
}
#viewport-toolbar .render-options-inline-control { flex: 1; max-width: 9rem; font-size: 0.72rem; }
#viewport-toolbar .render-options-block {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    border-radius: var(--radius-lg);
    padding: 8px;
    background: var(--surface-2);
}
#viewport-toolbar .render-options-block.is-disabled { opacity: 0.45; pointer-events: none; }
#viewport-toolbar .render-options-block-label { font-size: 0.72rem; font-weight: 600; }
#viewport-toolbar .render-options-block .form-range { margin: 0; height: 0.35rem; }
#viewport-toolbar .render-options-hint { font-size: 0.62rem; color: var(--text-3); }
#viewport-toolbar .render-options-grid-group {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    border-radius: var(--radius-lg);
    padding: 8px;
    background: var(--surface-2);
}
#viewport-toolbar .render-options-grid-settings {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    padding-left: 1.35rem;
    transition: opacity 0.15s;
}
#viewport-toolbar .render-options-grid-settings.is-disabled { opacity: 0.4; pointer-events: none; }
#viewport-toolbar .render-options-grid-settings-row { display: flex; align-items: center; gap: 0.5rem; }
#viewport-toolbar .render-options-grid-settings-label { font-size: 0.72rem; min-width: 4.5rem; flex-shrink: 0; }
#viewport-toolbar .render-options-grid-settings-value {
    font-size: 0.68rem;
    font-variant-numeric: tabular-nums;
    color: var(--text-2);
    min-width: 1.75rem;
    text-align: right;
    flex-shrink: 0;
}
#viewport-toolbar .render-options-grid-settings-color {
    width: 2rem;
    height: 1.25rem;
    padding: 0;
    border: 1px solid var(--border-base);
    border-radius: 0.2rem;
    background: transparent;
    flex-shrink: 0;
}
#viewport-toolbar .render-options-grid-settings-row .form-range { flex: 1; margin: 0; height: 0.35rem; }


/* ============================================================
   33. Packaged templates — tabbed dialog & staged wizard window
   ============================================================ */

/* Tabbed dialog: UKWindow hosting a UKTabs panel that fills the body.

   The content box is a ROW flex container, so `.ui-tabs` needs a grow factor to fill it
   and `min-width: 0` (not `min-height: 0`, which was the axis this had wrong) to be
   allowed to shrink — `.ui-tabs__list` scrolls horizontally, so without it the tab strip
   can push the whole panel wider than its share. `height: 100%` applied to the vertical
   layout only; both layouts need it, and stretch alone does not survive a tall panel.
   `.ui-tabs__panels` gets its fill/shrink from §23 now. */
.ui-tabbed-dialog .ui-window__content { padding: 0; display: flex; min-height: 0; overflow: hidden; }
.ui-tabbed-dialog .ui-tabs { flex: 1; min-width: 0; height: 100%; }
.ui-tabbed-dialog .ui-tabs__panels { width: 100%; }
.ui-tabbed-dialog .ui-tabs__panel { padding: var(--uk-gap-md); }

/* Staged wizard window: stepper rail on the left, scrollable step host right. */
.ui-staged-window__content { padding: 0; }
.ui-staged-window__body {
    display: flex;
    height: 100%;
    min-height: 0;
}
.ui-staged-window__body .ui-stepper {
    flex: 0 0 auto;
    border-right: 1px solid var(--uk-glass-divider);
    background: var(--uk-glass-sunken);
}
.ui-staged-window__host {
    flex: 1;
    min-width: 0;
    min-height: 0;
    overflow: auto;
    padding: var(--uk-gap-md);
}
.ui-staged-window__pane { display: flex; flex-direction: column; gap: var(--uk-gap); }


/* ============================================================
   34. Markdown / prose content (Changelog, Help, …)
   ============================================================ */

.ui-markdown {
    line-height: 1.6;
    color: var(--uk-text-2);
    user-select: text;
    padding: var(--uk-gap-lg) calc(var(--uk-gap-lg) + 6px) calc(var(--uk-gap-lg) * 2);
}
.ui-markdown > :first-child { margin-top: 0; }
.ui-markdown h1, .ui-markdown h2, .ui-markdown h3 { color: var(--uk-text-1); line-height: 1.25; }
.ui-markdown h1 { margin: 0 0 18px; font-size: 1.5rem; }
.ui-markdown h2 { margin-top: 24px; font-size: 1.125rem; }
.ui-markdown h3 { margin-top: 18px; margin-bottom: 4px; font-size: 0.875rem; color: var(--uk-accent); }
.ui-markdown p, .ui-markdown li { color: var(--uk-text-2); font-size: var(--uk-font-size-md); }
.ui-markdown code {
    padding: 2px 4px;
    color: var(--uk-text-1);
    background: var(--uk-surface-1);
    border-radius: var(--uk-radius);
    font-family: var(--font-family-mono, monospace);
    font-size: 0.92em;
}
.ui-markdown a { color: var(--uk-accent); text-decoration: none; }
.ui-markdown a:hover { color: var(--uk-accent-hover); text-decoration: underline; }
.ui-markdown ul, .ui-markdown ol { padding-left: 1.4em; }
.ui-markdown blockquote {
    margin: 0 0 12px;
    padding: 4px 12px;
    border-left: 3px solid var(--uk-accent-border, var(--uk-accent));
    background: var(--uk-glass-sunken);
    color: var(--uk-text-2);
}
.ui-markdown pre {
    overflow: auto;
    padding: 12px;
    background: var(--surface-sunken);
    border: 1px solid var(--uk-border);
    border-radius: var(--uk-radius-md);
}
.ui-markdown pre code { padding: 0; background: transparent; }
.ui-markdown table { border-collapse: collapse; margin: 0 0 12px; }
.ui-markdown th, .ui-markdown td {
    padding: 4px 10px;
    border: 1px solid var(--uk-border);
    color: var(--uk-text-2);
    font-size: var(--uk-font-size-md);
    text-align: left;
}
.ui-markdown th { background: var(--uk-surface-1); color: var(--uk-text-1); font-weight: 600; }
.ui-markdown__status { color: var(--uk-text-3); }


/* 35. (vacant) — the Texture Studio's own block moved to §55 when the Studio and
   the Texture Sandbox merged into one window. This section number sat in the
   §1-37 design-system range, which was a misfiling for a per-surface block.
   Sections are never renumbered; see §51/§52 for the same convention. */


/* ============================================================
   36. Thumbnail grid + lightbox (asset previews)
   ============================================================ */

.ui-thumb-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, 64px);
    gap: 8px;
    align-content: start;
}

.ui-thumb {
    position: relative;
    width: 64px;
    height: 64px;
    border-radius: var(--uk-radius-md);
    border: 1px solid var(--uk-glass-border);
    background-color: var(--uk-surface-1);
    background-image:
        linear-gradient(45deg, color-mix(in srgb, var(--uk-text-3) 18%, transparent) 25%, transparent 25%),
        linear-gradient(-45deg, color-mix(in srgb, var(--uk-text-3) 18%, transparent) 25%, transparent 25%),
        linear-gradient(45deg, transparent 75%, color-mix(in srgb, var(--uk-text-3) 18%, transparent) 75%),
        linear-gradient(-45deg, transparent 75%, color-mix(in srgb, var(--uk-text-3) 18%, transparent) 75%);
    background-size: 12px 12px;
    background-position: 0 0, 0 6px, 6px -6px, -6px 0;
    overflow: hidden;
    cursor: zoom-in;
    flex: 0 0 auto;
}
.ui-thumb img { width: 100%; height: 100%; object-fit: contain; display: block; }
.ui-thumb__mag {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: color-mix(in srgb, var(--surface-sunken) 60%, transparent);
    color: #fff;
    font-size: 15px;
    opacity: 0;
    transition: opacity var(--uk-dur-fast) var(--uk-ease);
    pointer-events: none;
}
.ui-thumb:hover .ui-thumb__mag { opacity: 1; }
.ui-thumb:hover { border-color: var(--uk-accent-border, var(--uk-accent)); }
.ui-thumb__badge {
    position: absolute;
    right: 2px;
    bottom: 2px;
    min-width: 14px;
    height: 14px;
    padding: 0 3px;
    font-size: 9px;
    font-weight: 700;
    line-height: 14px;
    text-align: center;
    color: var(--uk-accent-text, #fff);
    background: var(--uk-accent);
    border-radius: var(--uk-radius-full);
    pointer-events: none;
}
.ui-thumb--placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--uk-text-3);
    font-size: 18px;
    cursor: default;
}
.ui-thumb--placeholder .ui-thumb__mag { display: none; }

/* Click-to-zoom lightbox */
.ui-lightbox {
    position: fixed;
    inset: 0;
    z-index: var(--z-index-modal);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 40px;
    background: color-mix(in srgb, var(--surface-sunken) 82%, transparent);
    -webkit-backdrop-filter: blur(4px);
    backdrop-filter: blur(4px);
    cursor: zoom-out;
}
.ui-lightbox__img {
    max-width: 90vw;
    max-height: 82vh;
    image-rendering: pixelated;
    border: 1px solid var(--uk-glass-border);
    border-radius: var(--uk-radius-md);
    box-shadow: var(--shadow-xl);
    background: var(--uk-surface-1);
}
.ui-lightbox__cap {
    position: absolute;
    bottom: 24px;
    left: 50%;
    transform: translateX(-50%);
    max-width: 80vw;
    padding: 4px 10px;
    font-size: var(--uk-font-size-sm);
    color: var(--uk-text-1);
    background: var(--uk-overlay);
    border: 1px solid var(--uk-glass-border);
    border-radius: var(--uk-radius);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}


/* ============================================================
   37. Sidebar info header (title + "(i)" affordance)
   ============================================================ */

.sidebar-info-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--uk-gap-sm);
    padding: 0 0 4px;
    margin-bottom: 4px;
    border-bottom: 1px solid var(--uk-glass-divider);
}
.sidebar-info-header .sidebar-header { margin: 0; }


/* ============================================================
   38. Stats overlay (draggable FPS/mem HUD — customUI/UIStats)
   ============================================================ */

.ui-stats {
    position: fixed;
    top: 12px;
    right: 12px;
    z-index: 10050;
    display: flex;
    flex-direction: column;
    background: var(--uk-glass-raised);
    -webkit-backdrop-filter: blur(var(--uk-glass-blur));
    backdrop-filter: blur(var(--uk-glass-blur));
    border: 1px solid var(--uk-glass-border);
    border-radius: var(--uk-radius-md);
    box-shadow: var(--uk-glass-shadow);
    overflow: hidden;
    user-select: none;
}
.ui-stats__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 6px;
    padding: 4px 6px 4px 8px;
    font-size: 11px;
    font-weight: 600;
    color: var(--uk-text-1);
    background: var(--uk-glass-sunken);
    cursor: move;
    border-bottom: 1px solid var(--uk-glass-divider);
}
.ui-stats__header:active { cursor: grabbing; }
.ui-stats__title { flex: 1; min-width: 0; }
.ui-stats__close {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    padding: 0;
    font-size: 16px;
    line-height: 1;
    color: var(--uk-text-2);
    background: transparent;
    border: none;
    border-radius: var(--uk-radius);
    cursor: pointer;
    transition: color 0.15s, background 0.15s;
}
.ui-stats__close:hover { color: var(--uk-text-1); background: var(--surface-3); }
.ui-stats__close:active { background: var(--surface-4); }
.ui-stats__body { display: flex; align-items: center; padding: 2px 4px; }
.ui-stats__body canvas { display: block; }


/* ============================================================
   39. Map loading progress overlay (customUI/MapLoadingProgressDialog)
   Self-managed centered overlay (deliberately not a UKWindow), tokenized.
   ============================================================ */

.mlp-overlay {
    position: fixed; inset: 0; z-index: 2600;
    display: flex; align-items: center; justify-content: center;
    pointer-events: none; /* forced, non-dismissable — card takes pointer events */
}
.mlp-card {
    pointer-events: auto;
    min-width: 400px; max-width: 90vw; padding: 20px;
    display: flex; flex-direction: column;
    background: var(--uk-glass-raised, var(--surface-1));
    border: 1px solid var(--uk-glass-border, var(--uk-border));
    border-radius: var(--uk-radius-lg);
    box-shadow: var(--uk-glass-shadow, var(--shadow-xl));
    backdrop-filter: var(--uk-glass-blur, none);
}
.mlp-info { text-align: center; margin-bottom: 20px; }
.mlp-info__icon { color: var(--uk-accent); font-size: 2.5rem; margin-bottom: 12px; }
.mlp-title { color: var(--uk-text-1); font-size: 16px; font-weight: 600; margin: 0 0 6px; }
.mlp-sub { color: var(--uk-text-3); font-size: 12px; margin: 0; }
.mlp-progress { margin-bottom: 16px; }
.mlp-bar {
    height: 24px; background: var(--surface-sunken);
    border: 1px solid var(--uk-glass-border, var(--uk-border)); border-radius: var(--uk-radius-full); overflow: hidden;
}
.mlp-bar__fill {
    height: 100%; width: 0; background: var(--uk-accent); color: #fff;
    display: flex; align-items: center; justify-content: center;
    font-size: 12px; font-weight: 600; white-space: nowrap; transition: width 0.3s ease;
}
.mlp-status { text-align: center; color: var(--uk-text-1); font-weight: 500; font-size: 14px; margin-bottom: 4px; }
.mlp-detail { text-align: center; color: var(--uk-text-2); font-size: 12px; min-height: 16px; }
.mlp-status.success, .mlp-detail.success { color: var(--status-success); }
.mlp-bar__fill.success { background: var(--status-success); }
.mlp-success-icon { text-align: center; color: var(--status-success); font-size: 2rem; margin-bottom: 12px; }


/* ============================================================
   40. Tile info popover (customUI/TileInfo)
   ============================================================ */

#tile-info {
    pointer-events: none;
    background: var(--uk-glass);
    border: 1px solid var(--uk-glass-border);
    border-radius: var(--uk-radius-lg);
    padding: 12px;
    box-shadow: var(--uk-glass-shadow);
    -webkit-backdrop-filter: blur(var(--uk-glass-blur));
    backdrop-filter: blur(var(--uk-glass-blur));
    max-width: 300px;
    font-size: 12px;
    color: var(--uk-text-1);
    font-family: var(--font-family-base, system-ui, sans-serif);
}
.tile-info-content { display: flex; flex-direction: column; gap: 8px; }
.tile-info-header {
    font-weight: bold;
    font-size: 14px;
    margin-bottom: 4px;
    border-bottom: 1px solid var(--uk-glass-divider);
    padding-bottom: 4px;
}
.tile-info-texture-section,
.tile-info-colors-section,
.tile-info-colors-visualization,
.tile-info-stats-section,
.tile-info-surface-tiles-section { display: flex; flex-direction: column; }
.tile-info-texture-section { gap: 6px; }
.tile-info-colors-section { gap: 6px; }
.tile-info-colors-visualization { gap: 4px; }
.tile-info-stats-section { gap: 4px; font-size: 10px; }
.tile-info-surface-tiles-section { gap: 4px; }
.tile-info-texture-label,
.tile-info-colors-label,
.tile-info-surface-tiles-label,
.tile-info-stat-label,
.tile-info-face-label { font-size: 10px; color: var(--uk-text-2); }
.tile-info-face-label { font-size: 9px; color: var(--uk-text-3); }
.tile-info-texture-name {
    font-size: 10px;
    font-family: var(--font-family-mono, monospace);
    color: var(--uk-text-1);
    word-break: break-all;
    margin-bottom: 4px;
}
.tile-info-texture-container {
    position: relative;
    width: 124px;
    height: 124px;
    border: 1px solid var(--uk-glass-border);
    border-radius: var(--uk-radius);
    overflow: hidden;
    background-color: var(--surface-sunken);
}
.tile-info-texture-img { width: 100%; height: 100%; object-fit: cover; }
.tile-info-uv-canvas { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; }
.tile-info-color-row { display: flex; align-items: center; gap: 6px; }
.tile-info-color-swatch {
    width: 8px;
    height: 8px;
    border: 1px solid var(--uk-border-dark);
    border-radius: 2px;
    background-color: var(--surface-3);
}
.tile-info-color-label { font-size: 10px; color: var(--uk-text-2); min-width: 25px; }
.tile-info-color-value,
.tile-info-face-value,
.tile-info-surface-type-value { font-size: 10px; color: var(--uk-text-1); }
.tile-info-color-value { font-family: var(--font-family-mono, monospace); }
.tile-info-stat-row,
.tile-info-gat-info { display: flex; justify-content: space-between; }
.tile-info-stat-value,
.tile-info-face-value { font-weight: 500; }
.tile-info-surface-tiles-row { display: flex; gap: 8px; font-size: 10px; font-family: var(--font-family-mono, monospace); }
.tile-info-face-container { display: flex; flex-direction: column; align-items: center; gap: 2px; }
.tile-info-surface-type-value.cliff { color: var(--status-danger); }
.tile-info-surface-type-value.ground { color: var(--status-success); }


/* ============================================================
   41. Database Manager dialog (customUI/DatabaseManagerDialog)
   Hosted in a UKWindow; chrome uses UIKit primitives (including UKDropdown
   for Clear Store). The virtual-scroll table layout still uses Bootstrap
   grid/table utilities scoped here — a partial migration.
   ============================================================ */

.database-manager { display: flex; flex-direction: column; height: 100%; max-height: 100vh; overflow: hidden; padding: 1rem; gap: 1rem; }
.database-header, .maintenance-section { flex-shrink: 0; }
.data-section { flex: 1 1 auto; display: flex; flex-direction: column; min-height: 0; overflow: hidden; max-height: 100%; }
.data-section > .flex-grow-1,
.data-tab-content { flex: 1 1 auto; display: flex; flex-direction: column; min-height: 0; max-height: 100%; overflow: hidden; }
.data-tab-content > .d-flex.flex-column { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; overflow: hidden; max-height: 100%; }
.d-flex.flex-wrap.align-items-center.justify-content-between.gap-2.p-2.border-bottom { flex-shrink: 0; padding: 0.75rem 1rem !important; }
.table-responsive.flex-grow-1 { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; overflow: auto; max-height: 100%; }
.table-responsive.flex-grow-1 table { width: 100%; table-layout: auto; margin-bottom: 0; }
.table-responsive.flex-grow-1 table td.text-truncate { max-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.table-responsive.flex-grow-1 thead.sticky-top { position: sticky; top: 0; z-index: 10; background-color: var(--surface-2); box-shadow: var(--shadow-sm); }
.table-responsive.flex-grow-1 table tbody tr.virtual-spacer { pointer-events: none; user-select: none; }
.table-responsive.flex-grow-1 table tbody tr.virtual-spacer td { padding: 0; border: none; height: auto; }
.table-responsive.flex-grow-1 table tbody tr { height: auto; }
.table-responsive.flex-grow-1 table tbody td { padding: 0.5rem 0.75rem; vertical-align: middle; }
.database-header .row { margin-bottom: 0.75rem !important; }
.database-header .h5, .database-header .h6 { margin-bottom: 0.25rem !important; font-size: 1.1rem; }
.database-header small { font-size: 0.75rem; }
.maintenance-section .bg-dark { padding: 0.75rem 1rem !important; }
.maintenance-section .btn-sm { padding: 0.25rem 0.5rem; font-size: 0.875rem; }
.database-manager .gap-3 { gap: 1rem !important; }
.database-manager .gap-2 { gap: 0.5rem !important; }
.text-center.text-muted.py-4 { flex-shrink: 0; }
/* Search box (UIKit input with a leading icon) */
.dbm-search { position: relative; display: inline-flex; align-items: center; }
.dbm-search__icon { position: absolute; left: 8px; color: var(--uk-text-3); font-size: 12px; pointer-events: none; }
.dbm-search__input { padding-left: 26px; min-width: 200px; }


/* ============================================================
   42. JSON viewer (customUI/JSONViewer — CodeMirror)
   ============================================================ */

.json-viewer-panel {
    width: min(1200px, 90vw);
    height: min(700px, 85vh);
    background: var(--surface-1);
    display: flex;
    flex-direction: column;
    border-radius: var(--uk-radius-xl);
    border: 1px solid var(--uk-border);
    overflow: hidden;
    box-shadow: var(--shadow-xl);
    font-family: var(--font-family-base, 'Segoe UI', Roboto, sans-serif);
}
.json-viewer-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 16px;
    background: var(--surface-2);
    border-bottom: 1px solid var(--uk-border);
}
.json-viewer-title { font-size: var(--uk-font-size-lg); font-weight: 600; color: var(--uk-text-1); }
.json-viewer-size { font-size: var(--uk-font-size-sm); opacity: 0.7; color: var(--uk-text-2); }
.json-viewer-warning { color: var(--status-warning); font-size: 16px; }
.json-viewer-buttons { display: flex; gap: 6px; }
.json-viewer-button {
    background: transparent;
    color: var(--uk-text-1);
    border: 1px solid var(--uk-border);
    border-radius: var(--uk-radius-md);
    padding: 6px 10px;
    cursor: pointer;
    transition: all 0.2s ease;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: var(--uk-font-size-md);
}
.json-viewer-button:hover { background: var(--accent); color: var(--text-on-accent); border-color: var(--accent); transform: translateY(-1px); }
.json-viewer-button:active { transform: translateY(0); }
.json-viewer-button:disabled { opacity: 0.5; cursor: not-allowed; transform: none; }
.json-viewer-content { flex: 1; position: relative; background: var(--surface-sunken); }
.json-viewer-textarea {
    width: 100%; height: 100%; border: none; outline: none; resize: none; padding: 12px;
    font-family: var(--font-family-mono, 'Fira Code', 'Consolas', monospace);
    font-size: var(--uk-font-size-md);
    background: var(--surface-sunken);
    color: var(--uk-text-1);
}
#JsonViewerPanel .CodeMirror {
    height: 100% !important;
    background-color: var(--surface-sunken);
    color: var(--uk-text-1);
    font-family: var(--font-family-mono, 'Fira Code', 'Consolas', monospace);
    font-size: var(--uk-font-size-md);
}
#JsonViewerPanel .CodeMirror-gutters { background: var(--surface-1); border-right: 1px solid var(--uk-border); }
#JsonViewerPanel .CodeMirror-linenumber { color: var(--uk-text-3); padding: 0 3px 0 5px; min-width: 20px; }
#JsonViewerPanel .CodeMirror-foldgutter { width: 20px; }
#JsonViewerPanel .CodeMirror-foldgutter-open::after { content: '▼'; color: var(--accent); font-size: 12px; cursor: pointer; transition: transform 0.2s ease; }
#JsonViewerPanel .CodeMirror-foldgutter-open:hover::after { transform: scale(1.2); }
#JsonViewerPanel .CodeMirror-foldgutter-folded::after { content: '▶'; color: var(--accent); font-size: 12px; cursor: pointer; transition: transform 0.2s ease; }
#JsonViewerPanel .CodeMirror-foldgutter-folded:hover::after { transform: scale(1.2) translateX(2px); }
#JsonViewerPanel .cm-folded {
    opacity: 0.8;
    background-color: var(--accent-muted);
    border-left: 2px solid var(--accent);
    padding-left: 8px;
    font-style: italic;
    transition: all 0.2s ease;
}
.cm-folded:hover { background-color: var(--accent-muted); }
.search-highlight { background: var(--accent) !important; color: var(--text-on-accent) !important; font-weight: 600; border-radius: 3px; padding: 1px 2px; }
.json-viewer-panel .cm-matchhighlight { background: var(--accent-muted) !important; }
#JsonViewerPanel .CodeMirror-foldmarker { color: var(--accent) !important; text-shadow: none !important; font-family: var(--font-family-mono, monospace) !important; }
#JsonViewerPanel .cm-fold-widget-value {
    color: var(--accent) !important;
    opacity: 0.8 !important;
    font-style: italic !important;
    font-family: var(--font-family-mono, monospace) !important;
    font-size: var(--uk-font-size-md) !important;
    cursor: pointer !important;
    max-width: 400px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    display: inline-block; vertical-align: middle;
}
#JsonViewerPanel .cm-fold-widget-value:hover { opacity: 1 !important; color: var(--accent-hover) !important; }
#JsonViewerPanel .CodeMirror-cursor { border-left: 2px solid var(--uk-text-1) !important; }
#JsonViewerPanel .CodeMirror-selected { background: var(--accent-muted) !important; }
#JsonViewerPanel ::-webkit-scrollbar { width: 12px; height: 12px; }
#JsonViewerPanel ::-webkit-scrollbar-track { background: var(--surface-sunken); }
#JsonViewerPanel ::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 6px; }
#JsonViewerPanel ::-webkit-scrollbar-thumb:hover { background: var(--text-3); }


/* ============================================================
   43. Help dialog (customUI/Help)
   ============================================================ */

.help-dialog-root {
    display: grid;
    grid-template-columns: 280px minmax(0, 1fr);
    height: 100%;
    min-height: 0;
    background: var(--surface-0);
    color: var(--text-1);
}
.help-dialog-sidebar { display: flex; flex-direction: column; min-height: 0; border-right: 1px solid var(--border-base); background: var(--surface-sunken); }
.help-dialog-search { padding: 10px; border-bottom: 1px solid var(--border-base); }
.help-dialog-search input {
    width: 100%; box-sizing: border-box; padding: 8px 10px;
    color: var(--text-1); background: var(--surface-2);
    border: 1px solid var(--border-strong); border-radius: var(--uk-radius-md); outline: none;
}
.help-dialog-search input:focus { border-color: var(--accent); box-shadow: var(--focus-ring); }
.help-dialog-nav { flex: 1; min-height: 0; overflow: auto; padding: 8px; }
.help-dialog-category-group { margin-bottom: 4px; }
.help-dialog-category-toggle {
    display: flex; align-items: center; gap: 6px; width: 100%; margin: 8px 0 2px; padding: 6px 8px;
    color: var(--text-2); font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em;
    text-align: left; background: transparent; border: 0; border-radius: var(--uk-radius-md); cursor: pointer;
}
.help-dialog-category-toggle:hover { color: var(--text-1); background: var(--surface-2); }
.help-dialog-category-chevron { flex: 0 0 auto; width: 0; height: 0; border-top: 4px solid transparent; border-bottom: 4px solid transparent; border-left: 5px solid currentColor; transition: transform 0.15s ease; }
.help-dialog-category-group:not(.collapsed) .help-dialog-category-chevron { transform: rotate(90deg); }
.help-dialog-category-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.help-dialog-category-items { display: block; }
.help-dialog-category-group.collapsed .help-dialog-category-items { display: none; }
.help-dialog-nav button.help-dialog-topic {
    display: block; width: 100%; margin: 1px 0; padding: 7px 8px; overflow: hidden;
    color: var(--text-1); text-align: left; text-overflow: ellipsis; white-space: nowrap;
    background: transparent; border: 0; border-radius: var(--uk-radius-md); cursor: pointer;
}
.help-dialog-nav button.help-dialog-topic:hover { background: var(--surface-2); }
.help-dialog-nav button.help-dialog-topic.active { color: var(--text-on-accent); background: var(--accent); }
.help-dialog-empty { padding: 12px 8px; color: var(--text-3); font-size: 13px; }
.help-dialog-main { display: flex; flex-direction: column; min-width: 0; min-height: 0; }
.help-dialog-toolbar {
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    min-height: 42px; padding: 8px 14px; border-bottom: 1px solid var(--border-base); background: var(--surface-1);
}
.help-dialog-breadcrumbs { min-width: 0; overflow: hidden; color: var(--text-2); font-size: 12px; text-overflow: ellipsis; white-space: nowrap; }
.help-dialog-actions { display: flex; align-items: center; gap: 8px; }
.help-dialog-action-btn {
    flex: 0 0 auto; width: 32px; height: 32px;
    display: inline-flex; align-items: center; justify-content: center;
    color: var(--text-2); background: transparent;
    border: 1px solid var(--border-strong); border-radius: var(--uk-radius-md);
    cursor: pointer;
}
.help-dialog-action-btn:hover { color: var(--text-1); border-color: var(--accent); background: var(--surface-2); }
.help-dialog-action-btn i { font-size: 14px; }
.help-dialog-content { flex: 1; min-height: 0; overflow: auto; padding: 22px 28px 40px; }
.help-dialog-markdown { max-width: 900px; line-height: 1.6; user-select: text; }
.help-dialog-markdown h1, .help-dialog-markdown h2, .help-dialog-markdown h3 { color: var(--text-1); line-height: 1.25; }
.help-dialog-markdown h1 { margin: 0 0 18px; font-size: 28px; }
.help-dialog-markdown h2 { margin-top: 28px; font-size: 21px; }
.help-dialog-markdown h3 { margin-top: 22px; font-size: 17px; }
.help-dialog-markdown p, .help-dialog-markdown li, .help-dialog-markdown th, .help-dialog-markdown td { color: var(--text-2); font-size: var(--uk-font-size-md); }
.help-dialog-markdown a { color: var(--accent); }
.help-dialog-markdown code { padding: 2px 4px; color: var(--text-1); background: var(--surface-1); border-radius: var(--uk-radius); }
.help-dialog-markdown pre { overflow: auto; padding: 12px; background: var(--surface-sunken); border: 1px solid var(--border-base); border-radius: var(--uk-radius-md); }
.help-dialog-markdown pre code { padding: 0; background: transparent; }
.help-dialog-status { color: var(--text-3); }
@media (max-width: 760px) {
    .help-dialog-root { grid-template-columns: 1fr; grid-template-rows: 220px minmax(0, 1fr); }
    .help-dialog-sidebar { border-right: 0; border-bottom: 1px solid var(--border-base); }
    .help-dialog-content { padding: 18px; }
}

/* ============================================================
   43. Help dialog print overlay
   ============================================================ */

.help-print-overlay {
    position: fixed;
    inset: 0;
    z-index: 10000;
    background: rgba(0, 0, 0, 0.6);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
}

.help-print-overlay[hidden] { display: none; }

.help-print-view {
    background: var(--surface-1);
    border: 1px solid var(--border-base);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    width: 100%;
    max-width: 900px;
    max-height: 90vh;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.help-print-toolbar {
    display: flex;
    justify-content: flex-end;
    align-items: center;
    padding: 8px 12px;
    border-bottom: 1px solid var(--border-base);
    background: var(--surface-2);
}

.help-print-close {
    background: transparent;
    border: none;
    color: var(--text-2);
    font-size: 24px;
    line-height: 1;
    cursor: pointer;
    padding: 0;
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-base);
}

.help-print-close:hover {
    color: var(--text-1);
    background: var(--surface-3);
}

.help-print-content {
    flex: 1;
    overflow: auto;
    padding: 24px 32px;
}

.help-print-article {
    max-width: 800px;
    margin: 0 auto;
    line-height: 1.6;
    color: var(--text-2);
}

.help-print-article h1,
.help-print-article h2,
.help-print-article h3 {
    color: var(--text-1);
    line-height: 1.25;
}

.help-print-article h1 {
    font-size: 28px;
    margin: 0 0 18px;
    border-bottom: 2px solid var(--border-base);
    padding-bottom: 0.5em;
}

.help-print-article h2,
.help-print-article h3 {
    margin-top: 1.5em;
}

.help-print-article h2 { font-size: 21px; }
.help-print-article h3 { font-size: 17px; }

.help-print-article p,
.help-print-article li,
.help-print-article th,
.help-print-article td {
    color: var(--text-2);
    font-size: var(--uk-font-size-md);
}

.help-print-article a { color: var(--accent); }
.help-print-article code {
    padding: 2px 4px;
    color: var(--text-1);
    background: var(--surface-1);
    border-radius: var(--uk-radius);
}

.help-print-article pre {
    overflow: auto;
    padding: 12px;
    background: var(--surface-sunken);
    border: 1px solid var(--border-base);
    border-radius: var(--uk-radius-md);
}

.help-print-article pre code {
    padding: 0;
    background: transparent;
}

.help-print-article blockquote {
    border-left: 4px solid var(--border-base);
    margin: 0;
    padding-left: 1em;
}

.help-print-article table {
    border-collapse: collapse;
    width: 100%;
}

.help-print-article th,
.help-print-article td {
    border: 1px solid var(--border-base);
    padding: 8px 12px;
}

.help-print-article th { background: var(--surface-2); }

.help-print-header { margin-bottom: 1.5em; }
.help-print-meta { color: var(--text-3); margin-top: 8px; }

.help-print-link-url {
    color: var(--text-3);
    font-size: 0.85em;
    word-break: break-all;
}

@media print {
    .help-print-overlay {
        position: static;
        background: transparent;
        padding: 0;
    }

    .help-print-view {
        box-shadow: none;
        border: none;
        max-width: none;
        max-height: none;
    }

    .help-print-toolbar,
    .help-print-close {
        display: none !important;
    }

    .help-print-content {
        padding: 0;
    }

    .help-print-article {
        max-width: 100%;
    }

    body * {
        visibility: hidden;
    }

    .help-print-overlay,
    .help-print-overlay * {
        visibility: visible;
    }

    .help-print-overlay {
        position: absolute;
        left: 0;
        top: 0;
    }
}


/* ============================================================
   44. Biome-set browser dialog (customUI/BiomeSetBrowserDialog)
   ============================================================ */

.biome-dialog-root { display: flex; flex-direction: column; height: 100%; overflow: hidden; }
.biome-dialog-header { display: flex; justify-content: space-between; align-items: center; padding: 8px 12px; background: var(--glass-sunken); border-bottom: 1px solid var(--glass-divider); }
.biome-dialog-stats { display: flex; gap: 12px; align-items: center; }
.biome-dialog-header-actions { display: flex; gap: 8px; align-items: center; }
.biome-dialog-toolbar { display: flex; gap: 12px; align-items: center; padding: 12px; background: var(--glass-sunken); border-bottom: 1px solid var(--glass-divider); }
.biome-select-wrapper { display: flex; gap: 8px; align-items: center; }
.biome-select-label { color: var(--text-2); }
.biome-select { padding: 6px 10px; background: var(--surface-2); border: 1px solid var(--border-base); border-radius: var(--radius-base); color: var(--text-1); }
.biome-search-wrapper { position: relative; width: 240px; }
.biome-search-icon { position: absolute; left: 10px; top: 50%; transform: translateY(-50%); color: var(--text-3); }
.biome-search-input { width: 100%; padding: 6px 10px 6px 30px; background: var(--surface-2); border: 1px solid var(--border-base); border-radius: var(--radius-full); color: var(--text-1); outline: none; }
.biome-search-input:focus { border-color: var(--accent-border); }
.biome-pagination-wrapper { display: flex; gap: 8px; align-items: center; margin-left: auto; }
.biome-pagination-label { color: var(--text-2); font-size: 12px; }
.biome-page-size-select { padding: 4px 8px; background: var(--surface-2); border: 1px solid var(--border-base); border-radius: var(--radius-base); color: var(--text-1); }
.biome-page-info { color: var(--text-2); font-size: 12px; min-width: 120px; text-align: center; }
.biome-dialog-body { flex: 1; min-height: 0; padding: 12px; }
.biome-dialog-grid { height: 100%; overflow: auto; }
.biome-dialog-table { width: 100%; border-collapse: collapse; background: var(--glass-sunken); }
.biome-table-header-row { background: var(--glass-sunken); border-bottom: 2px solid var(--border-base); }
.biome-table-header { padding: 12px; text-align: left; color: var(--text-1); font-weight: 600; }
.biome-table-header-name { width: 200px; }
.biome-table-header-actions { text-align: center; width: 120px; }
.biome-table-row { border-bottom: 1px solid var(--glass-divider); transition: background-color 0.2s; }
.biome-table-row:hover { background-color: var(--accent-muted); }
.biome-table-cell { padding: 12px; vertical-align: top; }
.biome-table-cell-name { width: 200px; }
.biome-table-cell-actions { text-align: center; width: 120px; }
.biome-dialog-footer { padding: 10px 12px; background: var(--glass-sunken); border-top: 1px solid var(--glass-divider); font-size: 11px; color: var(--text-2); }
.biome-hover-preview { position: fixed; display: none; z-index: 10000; pointer-events: none; background: var(--surface-sunken); border: 1px solid var(--glass-border); border-radius: var(--radius-lg); padding: 8px; box-shadow: var(--shadow-lg); }
.biome-context-menu { position: fixed; display: none; z-index: 10001; background: var(--surface-4); border: 1px solid var(--glass-border); border-radius: var(--radius-base); padding: 4px; min-width: 200px; box-shadow: var(--shadow-lg); }
.context-menu-item { padding: 8px 12px; color: var(--text-1); cursor: pointer; font-size: 13px; border-bottom: 1px solid var(--glass-divider); }
.context-menu-item:last-child { border-bottom: none; }
.context-menu-item:hover { background: var(--surface-3); }
/* Texture type badges (semantic; cliff keeps a distinct hue) */
.texture-badge-ground,
.texture-badge-wall,
.texture-badge-cliff { color: #fff; padding: 1px 4px; border-radius: 6px; font-size: 6px; font-weight: bold; line-height: 1.4em; position: absolute; top: -4px; right: -4px; }
.texture-badge-ground { background: var(--status-success); }
.texture-badge-wall { background: var(--status-danger); }
.texture-badge-cliff { background: #6f42c1; }
.texture-container, .model-container { display: flex; flex-wrap: wrap; gap: 6px; align-items: flex-start; }
.texture-item { position: relative; background: var(--surface-2); border: 1px solid var(--border-base); border-radius: var(--radius-base); box-sizing: content-box; display: flex; flex-direction: column; align-items: center; justify-content: center; cursor: pointer; }
.model-item { border: 1px solid var(--border-base); border-radius: var(--radius-base); box-sizing: border-box; display: flex; flex-direction: column; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; }
.name-cell-content { display: flex; flex-direction: column; gap: 4px; }
.name-title { font-weight: 600; color: var(--text-1); font-size: 14px; }
.name-count { font-size: 11px; color: var(--text-2); }
.loading-text { color: var(--text-3); font-size: 8px; margin-top: 2px; }
/* Texture magnifier lens — intentionally a light lens for viewing textures */
#biome-magnifier {
    position: fixed; left: 0; top: 0; transform: translate(-9999px,-9999px) translateZ(0); z-index: 999999;
    background: rgba(255,255,255,0.96);
    backdrop-filter: saturate(120%) blur(4px); -webkit-backdrop-filter: saturate(120%) blur(4px);
    border: 1px solid rgba(0,0,0,0.08); border-radius: 10px;
    box-shadow: 0 10px 30px rgba(0,0,0,0.18), 0 2px 8px rgba(0,0,0,0.12);
    padding: 8px; opacity: 0; transition: opacity 80ms ease-out;
}


/* ============================================================
   45. GRF Explorer (customUI/GrfExplorer) — already tokenized
   ============================================================ */

/* GrfExplorer Styles — tokenized (Graphite Instrument / glass) */

/* Its floating host. The explorer fills the window and scrolls its own list
   viewport, so the window body must not add padding or a second scrollbar. */
.grf-explorer-window .ui-window__content {
    padding: 0;
    overflow: hidden;
    display: flex;
    min-height: 0;
}

/* Root Container */
/* `flex: 1; min-width: 0` for the same reason as `.sw-shell` / `.smw-shell`: the content
   box above is a ROW flex container, so without a grow factor this sizes to max-content
   and leaves dead space beside itself. */
.grf-explorer {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-width: 0;
    height: 100%;
    overflow: hidden;
}

/* Toolbar */
.grf-explorer__toolbar {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 12px;
    background: var(--glass-sunken);
    border-bottom: 1px solid var(--glass-divider);
    backdrop-filter: blur(var(--glass-blur));
    -webkit-backdrop-filter: blur(var(--glass-blur));
}

.grf-explorer__breadcrumbs {
    flex: 1;
    min-width: 0;
    font-size: 13px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.grf-explorer__search {
    position: relative;
    width: 200px;
}

.grf-explorer__search .fas {
    position: absolute;
    left: 10px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--text-3);
    pointer-events: none;
    font-size: 12px;
}

.grf-explorer__search-input {
    width: 100%;
    padding: 6px 10px 6px 32px;
    background: var(--surface-2);
    border: 1px solid var(--border-base);
    border-radius: var(--radius-full);
    color: var(--text-1);
    font-size: 12px;
    outline: none;
    transition: all 0.2s;
}

.grf-explorer__search-input:focus {
    background: var(--surface-3);
    border-color: var(--accent-border);
}

.grf-explorer__view-mode {
    display: inline-flex;
    align-items: center;
    background: var(--surface-sunken);
    border-radius: 6px;
    padding: 2px;
    gap: 2px;
}

.grf-explorer__view-mode-btn {
    padding: 5px 12px;
    background: transparent;
    border: none;
    color: var(--text-2);
    cursor: pointer;
    font-size: 12px;
    border-radius: 4px;
    transition: all 0.2s;
}

.grf-explorer__view-mode-btn--active {
    background: var(--accent-muted);
    color: var(--accent);
}

/* Body Layout */
.grf-explorer__body {
    display: flex;
    gap: 0;
    width: 100%;
    flex: 1;
    min-height: 0;
    flex-direction: row;
}

.grf-explorer__body-left {
    flex: 0 0 30%;
    min-width: 0;
    position: relative;
    border-right: 1px solid var(--glass-divider);
    overflow: hidden;
    display: flex;
    flex-direction: column;
    background: var(--glass-sunken);
}

.grf-explorer__body-left--full {
    flex: 0 0 100%;
}

.grf-explorer__body-middle {
    flex: 1 1 45%;
    min-width: 0;
    position: relative;
    border-right: 1px solid var(--glass-divider);
    overflow: hidden;
    display: flex;
    flex-direction: column;
    background: var(--glass-sunken);
}

.grf-explorer__body-middle--hidden {
    display: none;
}

.grf-explorer__body-middle--zero {
    flex: 1 1 0%;
}

.grf-explorer__body-right {
    flex: 0 0 25%;
    min-width: 0;
    position: relative;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    background: var(--glass-sunken);
}

.grf-explorer__body-right--hidden {
    display: none;
}

/* Tree View */
.grf-explorer__tree {
    flex: 1;
    overflow: auto;
    padding: 8px;
}

/* Preview */
.grf-explorer__preview-container {
    position: relative;
    width: 100%;
    height: 100%;
    background: var(--surface-sunken);
    border: 1px solid var(--glass-border);
    border-radius: 8px;
    overflow: hidden;
    align-content: center;
    justify-items: center;
}

.grf-explorer__preview-header {
    position: absolute;
    top: 8px;
    left: 12px;
    right: 12px;
    height: 20px;
    font: 11px/20px system-ui, sans-serif;
    font-weight: 600;
    color: var(--text-2);
    z-index: 2;
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.8);
    letter-spacing: 0.02em;
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.grf-explorer__preview-title {
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.grf-explorer__preview-controls {
    display: none;
    gap: 6px;
    align-items: center;
}

.grf-explorer__rotate-btn,
.grf-explorer__reset-btn,
.grf-explorer__speed-btn {
    padding: 2px 6px;
    background: var(--surface-3);
    border: 1px solid var(--border-strong);
    border-radius: 3px;
    color: var(--text-1);
    cursor: pointer;
    font-size: 10px;
    transition: all 0.2s;
}

.grf-explorer__rotate-btn:hover,
.grf-explorer__reset-btn:hover,
.grf-explorer__speed-btn:hover {
    background: var(--surface-4);
}

.grf-explorer__rotate-btn--active {
    background: var(--accent-muted);
}

.grf-explorer__speed-btn {
    min-width: 24px;
}

/* File Info */
.grf-explorer__file-info {
    flex: 1;
    min-height: 0;
    overflow: auto;
    padding: 16px;
    background: var(--glass-sunken);
    backdrop-filter: blur(5px);
    -webkit-backdrop-filter: blur(5px);
}

/* Canvas Elements */
.grf-explorer__canvas-2d,
.grf-explorer__canvas-3d {
    position: relative;
    inset: 0;
    display: none;
}

.grf-explorer__canvas-3d {
    width: 100%;
    height: 100%;
}

/* Zoom functionality */
.grf-explorer__preview-container {
    overflow: hidden; /* Prevent scrollbars during zoom */
}

.grf-explorer-preview-img {
    transition: transform 0.1s ease-out;
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
}

.grf-explorer__canvas-2d {
    transition: transform 0.1s ease-out;
}

/* List Viewport */
.grf-explorer__list-viewport {
    position: absolute;
    inset: 0;
    overflow: auto;
    padding: 4px 0;
}

/* Footer */
.grf-explorer__footer {
    position: sticky;
    bottom: 0;
    z-index: 100;
    background: var(--glass-panel);
    border-top: 1px solid var(--glass-border);
    padding: 12px 20px;
    box-shadow: var(--glass-shadow);
    backdrop-filter: blur(var(--glass-blur));
    -webkit-backdrop-filter: blur(var(--glass-blur));
    display: flex;
    gap: 10px;
    align-items: center;
}

.grf-explorer__selection-counter {
    margin-right: auto;
    padding: 4px 12px;
    background: var(--tint-accent-bg);
    border: 1px solid var(--tint-accent-bd);
    color: var(--tint-accent-fg);
    border-radius: 16px;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.02em;
    transition: all 0.2s;
}

.grf-explorer__selection-counter--hidden {
    display: none;
}

/* The confirm button is a UKButton now — `.grf-explorer__confirm-btn` and the
   `--disabled` modifier it never used are gone, as is the `--dialog` counter
   variant that positioned a second counter in the old dialog's title bar. */

.grf-explorer__translate-wrap {
    display: flex;
    align-items: center;
    gap: 6px;
    font: 12px system-ui, sans-serif;
    color: var(--text-2);
    cursor: pointer;
    user-select: none;
}

.grf-explorer__translate-checkbox {
    margin: 0;
    cursor: pointer;
}

.grf-explorer__translate-label {
    font-size: 11px;
}


/* Tree Rows */
.grf-explorer__tree-row {
    display: flex;
    align-items: center;
    padding: 4px 10px;
    cursor: pointer;
    transition: all 0.15s;
    border-radius: 4px;
    margin: 0 4px;
}

.grf-explorer__tree-row:hover {
    background: var(--accent-muted);
}

.grf-explorer__tree-row--selected {
    background: var(--accent-muted);
}

.grf-explorer__tree-row--multi-selected {
    background: var(--accent-muted);
    border-left: 3px solid var(--accent);
}

.grf-explorer__tree-checkbox {
    margin-right: 8px;
    cursor: pointer;
    accent-color: var(--accent);
}

.grf-explorer__tree-icon {
    margin-right: 8px;
    font-size: 16px;
    flex-shrink: 0;
}

.grf-explorer__tree-name {
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 13px;
    color: var(--text-1);
}

.grf-explorer__tree-source-badge {
    margin-left: 6px;
    font-size: 9px;
    padding: 2px 5px;
    border-radius: 8px;
    background: var(--tint-success-bg);
    border: 1px solid var(--tint-success-bd);
    color: var(--tint-success-fg);
    font-weight: 600;
    flex-shrink: 0;
}

.grf-explorer__tree-source-badge--external {
    background: var(--tint-accent-bg);
    border: 1px solid var(--tint-accent-bd);
    color: var(--tint-accent-fg);
}

.grf-explorer__tree-type-badge {
    margin-left: 8px;
    font-size: 10px;
    padding: 2px 6px;
    border-radius: 10px;
    opacity: 0.9;
    flex-shrink: 0;
}

.grf-explorer__tree-type-badge--model {
    background: var(--tint-signal-bg);
    border: 1px solid var(--tint-signal-bd);
    color: var(--tint-signal-fg);
}

.grf-explorer__tree-type-badge--texture {
    background: var(--tint-success-bg);
    border: 1px solid var(--tint-success-bd);
    color: var(--tint-success-fg);
}

.grf-explorer__tree-meta {
    margin-left: auto;
    font-size: 11px;
    color: var(--text-3);
    flex-shrink: 0;
    padding-left: 10px;
}

.grf-explorer__tree-cache-indicator {
    margin-left: 8px;
    font-size: 11px;
    opacity: 0;
    transition: opacity 0.2s;
    flex-shrink: 0;
}

.grf-explorer__tree-cache-indicator--visible {
    opacity: 0.8;
    color: var(--status-success);
}

.grf-explorer__tree-status {
    margin-left: 6px;
    opacity: 0.5;
    font-size: 10px;
    flex-shrink: 0;
}

/* Directory Rows */
.grf-explorer__dir-row {
    display: flex;
    align-items: center;
    padding: 4px 10px;
    cursor: pointer;
    transition: all 0.15s;
    border-radius: 4px;
    margin: 0 4px;
}

.grf-explorer__dir-row:hover {
    background: var(--accent-muted);
}

.grf-explorer__dir-expand-icon {
    display: inline-block;
    width: 16px;
    cursor: pointer;
    user-select: none;
}

.grf-explorer__dir-folder-icon {
    margin-left: 4px;
}

.grf-explorer__dir-name {
    margin-left: 6px;
}

/* File Rows */
.grf-explorer__file-row {
    display: flex;
    align-items: center;
    padding: 4px 10px;
    cursor: pointer;
    transition: all 0.15s;
    border-radius: 4px;
    margin: 0 4px;
}

.grf-explorer__file-row:hover {
    background: var(--accent-muted);
}

.grf-explorer__file-checkbox {
    margin-left: 4px;
    margin-right: 4px;
    cursor: pointer;
}

.grf-explorer__file-icon {
    margin-left: 4px;
}

.grf-explorer__file-name {
    margin-left: 6px;
}

.grf-explorer__file-source-badge {
    margin-left: 6px;
    font-size: 9px;
    padding: 2px 5px;
    border-radius: 8px;
    background: var(--tint-success-bg);
    border: 1px solid var(--tint-success-bd);
    color: var(--tint-success-fg);
    font-weight: 600;
}

.grf-explorer__file-source-badge--external {
    background: var(--tint-accent-bg);
    border: 1px solid var(--tint-accent-bd);
    color: var(--tint-accent-fg);
}

.grf-explorer__file-type-badge {
    margin-left: 8px;
    font-size: 10px;
    padding: 2px 6px;
    border-radius: 10px;
    opacity: 0.9;
}

.grf-explorer__file-type-badge--model {
    background: var(--tint-signal-bg);
    border: 1px solid var(--tint-signal-bd);
    color: var(--tint-signal-fg);
}

.grf-explorer__file-type-badge--texture {
    background: var(--tint-success-bg);
    border: 1px solid var(--tint-success-bd);
    color: var(--tint-success-fg);
}

.grf-explorer__file-size {
    margin-left: auto;
    opacity: 0.6;
    font-size: 11px;
}

/* Loading indicator — a centred glass pill over the virtualized list. Was built inline
   in JS (with its own injected @keyframes) against a class name the stylesheet never
   knew about; the rules that lived here matched nothing. */
.grf-explorer__loading {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 24px;
    border-radius: var(--radius-md);
    background: var(--glass-raised);
    border: 1px solid var(--glass-border);
    box-shadow: var(--glass-shadow);
    backdrop-filter: blur(var(--glass-blur));
    -webkit-backdrop-filter: blur(var(--glass-blur));
    color: var(--text-1);
    font-size: 13px;
    font-weight: 500;
    z-index: 10;
    animation: uk-fade-in var(--dur-fast) var(--ease-standard);
}

.grf-explorer__loading--fade-out {
    animation: grf-fade-out 0.2s var(--ease-standard) forwards;
}

@keyframes grf-fade-out {
    to { opacity: 0; }
}


/* Tree rows. These came from a second, older copy of this stylesheet that lived in
   app.css; the rest of that copy was either superseded by the rules above or named
   classes the explorer no longer emits. */
.grf-tree-node {
    display: flex;
    align-items: center;
    min-height: 24px;
    padding: 2px 8px;
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: background-color var(--dur-fast) var(--ease-standard);
}
.grf-tree-node:hover              { background: var(--surface-3); }
.grf-tree-node--selected          { background: var(--selection-color); }
.grf-tree-node--multi-selected {
    background: var(--accent-muted);
    border-left: 3px solid var(--accent);
}
.grf-tree-node--dir .grf-tree-node__name { font-weight: 500; }
.grf-tree-node__size              { margin-left: auto; }

.grf-row__checkbox:hover,
.grf-tree-node__checkbox:hover    { transform: scale(1.1); }

.grf-explorer__placeholder {
    padding: 40px 20px;
    text-align: center;
    font-size: 14px;
    color: var(--text-3);
}

/* Preview Image */
.grf-explorer__preview-image {
    object-fit: contain;
    display: block;
}

/* ── Breadcrumbs ──────────────────────────────────────────── */
.grf-explorer__crumb {
    color: var(--text-2);
    text-decoration: none;
    padding: 4px 6px;
    border-radius: var(--radius-sm);
    font-weight: 500;
    transition: background var(--dur-fast) var(--ease-standard), color var(--dur-fast) var(--ease-standard);
}
.grf-explorer__crumb:hover { background: var(--surface-3); color: var(--text-1); }
.grf-explorer__crumb--current { color: var(--accent); font-weight: 600; }
.grf-explorer__crumb-sep { color: var(--text-3); margin: 0 2px; font-size: 12px; }

/* ── Context menu (UIKit chrome, explorer sizing) ─────────── */
.grf-explorer__context-menu {
    z-index: var(--z-index-tooltip);
    max-height: 50vh;
    overflow-y: auto;
}

/* ── List rows ────────────────────────────────────────────── */
/* Hover/selected were painted from JS with four hard-coded colours; they are
   states here so they follow the theme. */
.grf-explorer__tree-row:hover                        { background: var(--surface-3); }
.grf-row--multi-selected                             { background: var(--accent-muted); }
.grf-row--multi-selected:hover                       { background: var(--selection-color); }
.grf-explorer__tree-row.grf-row--sel,
.grf-explorer__tree-row.grf-row--sel:hover {
    background: var(--selection-color);
    border-left: 3px solid var(--accent);
}

.grf-row__checkbox { margin-right: 8px; cursor: pointer; accent-color: var(--accent); }
.grf-row__icon     { margin-right: 8px; font-size: 16px; flex-shrink: 0; }
.grf-row__name {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 13px;
    color: var(--text-1);
}
.grf-row__meta {
    margin-left: auto;
    padding-left: 10px;
    font-size: 11px;
    color: var(--text-3);
    flex-shrink: 0;
}
.grf-row__status { margin-left: 6px; opacity: 0.5; font-size: 10px; flex-shrink: 0; }

.grf-row__source-badge {
    margin-left: 6px;
    font-size: 9px;
    padding: 2px 5px;
    border-radius: var(--radius-full);
    font-weight: 600;
    flex-shrink: 0;
}
.grf-row__source-badge--data {
    background: var(--tint-success-bg);
    border: 1px solid var(--tint-success-bd);
    color: var(--tint-success-fg);
}
.grf-row__source-badge--grf {
    background: var(--tint-accent-bg);
    border: 1px solid var(--tint-accent-bd);
    color: var(--tint-accent-fg);
}

.grf-row__badge {
    margin-left: 8px;
    font-size: 10px;
    padding: 2px 6px;
    border-radius: var(--radius-full);
    opacity: 0.9;
    flex-shrink: 0;
}
.grf-row__badge--overridden {
    background: var(--tint-signal-bg);
    border: 1px solid var(--tint-signal-bd);
    color: var(--tint-signal-fg);
}
.grf-row__badge--override {
    background: var(--tint-success-bg);
    border: 1px solid var(--tint-success-bd);
    color: var(--tint-success-fg);
}

/* ── Tree rows ────────────────────────────────────────────── */
/* Depth is data, so it rides in on a custom property rather than a style rule. */
.grf-tree-node--dir  { padding-left: calc(var(--grf-tree-depth, 0) * 16px); }
.grf-tree-node--file { padding-left: calc(var(--grf-tree-depth, 0) * 16px + 16px); }
.grf-tree-node__expand   { display: inline-block; width: 16px; cursor: pointer; user-select: none; }
.grf-tree-node__checkbox { margin: 0 4px; cursor: pointer; accent-color: var(--accent); }
.grf-tree-node__icon     { margin-left: 4px; }
.grf-tree-node__name     { margin-left: 6px; }

/* ── Sprite/animation preview controls ────────────────────── */
.grf-preview__controls {
    position: absolute;
    bottom: 8px;
    left: 8px;
    right: 8px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 10px;
    border-radius: var(--radius-md);
    background: var(--glass-raised);
    border: 1px solid var(--glass-border);
    box-shadow: var(--glass-shadow);
    backdrop-filter: blur(var(--glass-blur));
    -webkit-backdrop-filter: blur(var(--glass-blur));
    color: var(--text-1);
    font-size: 11px;
}
.grf-preview__controls--compact { flex-direction: row; align-items: center; padding: 8px; }

.grf-preview__row           { display: flex; align-items: center; gap: 8px; }
.grf-preview__row--between  { justify-content: space-between; }
.grf-preview__row--tight    { gap: 6px; }

.grf-preview__label            { color: var(--text-2); flex-shrink: 0; }
.grf-preview__label--action    { min-width: 50px; }
.grf-preview__label--dir       { min-width: 30px; }
.grf-preview__label--speed     { min-width: 45px; }
.grf-preview__label--loop      { min-width: 35px; margin-left: 8px; }

.grf-preview__readout          { min-width: 70px; text-align: center; color: var(--text-2); }
.grf-preview__readout--sm      { min-width: 35px; }
.grf-preview__readout--frame   { min-width: 60px; }

.grf-preview__select           { min-width: 80px; }
.grf-preview__slider           { flex: 1; min-width: 120px; }
.grf-preview__slider--speed    { flex: 0 0 auto; width: 80px; min-width: 0; }
.grf-preview__check            { margin-left: 4px; cursor: pointer; accent-color: var(--accent); }

.grf-preview__play             { min-width: 35px; }
.grf-preview__play.is-playing  { background: var(--surface-4); }
.grf-preview__step--back       { margin-left: 8px; }
.grf-preview__step--fwd        { margin-right: 8px; }

.grf-preview__3d-toggle {
    position: absolute;
    top: 8px;
    right: 8px;
    font-weight: 700;
    backdrop-filter: blur(var(--glass-blur));
    -webkit-backdrop-filter: blur(var(--glass-blur));
}
.grf-preview__3d-toggle.is-active {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--text-on-accent);
}

/* ── File-info panel ──────────────────────────────────────────
   The right-hand metadata report. It used to be ~150 inline style
   attributes of hard-coded hex, so it read the same in light theme as in
   dark. Everything here is tokenized; only genuinely data-driven values
   (a frame's pixel size, a node's indent depth) still ride on the element
   style property. */
.grf-info {
    font-size: 13px;
    line-height: 1.5;
    color: var(--text-1);
}

.grf-info__head {
    font-weight: 600;
    font-size: 14px;
    margin-bottom: 12px;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--keyline);
}
.grf-info__head-row { display: flex; align-items: center; gap: 8px; }
.grf-info__name     { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }

.grf-info__block { margin-bottom: 12px; }
.grf-info__row   { margin-bottom: 6px; }
.grf-info__group { margin: 10px 0; }

.grf-info__grid          { display: grid; grid-template-columns: 80px 1fr; gap: 6px; }
.grf-info__grid--tight   { gap: 4px; }
.grf-info__grid--wide    { grid-template-columns: 100px 1fr; gap: 4px; font-size: 11px; }

.grf-info__k          { color: var(--text-3); }
.grf-info__k--block   { display: block; margin-bottom: 4px; }
.grf-info__count      { font-size: 10px; color: var(--text-3); font-weight: normal; }
.grf-info__mono       { font-family: var(--font-family-mono, monospace); font-size: 11px; word-break: break-all; }
.grf-info__mono--xs   { font-size: 10px; }
.grf-info__mono--2xs  { font-size: 9px; }

.grf-info__v--ok    { color: var(--status-success); }
.grf-info__v--warn  { color: var(--status-warning); }
.grf-info__v--bad   { color: var(--status-danger); }
.grf-info__v--info  { color: var(--accent); }
.grf-info__v--muted { color: var(--text-3); }
.grf-info__v--sm    { font-size: 11px; }
.grf-info__v--xs    { font-size: 10px; }

.grf-info__empty {
    color: var(--text-3);
    text-align: center;
    padding: 20px;
    font-size: 13px;
}
.grf-info__empty--left { text-align: left; padding: 12px; }

.grf-info__note {
    margin: 8px 0;
    padding: 8px;
    background: var(--surface-sunken);
    border-radius: var(--radius-sm);
    font-size: 11px;
    line-height: 1.5;
}
.grf-info__pill {
    padding: 2px 8px;
    background: var(--tint-accent-bg);
    border-radius: var(--radius-sm);
    font-size: 11px;
}
.grf-info__badge {
    padding: 1px 4px;
    background: var(--tint-success-bg);
    color: var(--tint-success-fg);
    border-radius: 2px;
    font-size: 9px;
}
.grf-info__chips {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 8px;
    font-size: 10px;
    color: var(--text-3);
}
.grf-info__chip {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 2px 6px;
    border-radius: var(--radius-sm);
    background: var(--surface-3);
}

/* One tinted panel per metadata kind; the title inherits the panel's hue. */
.grf-info__panel {
    --grf-panel-fg: var(--accent);
    --grf-panel-bg: var(--tint-accent-bg);
    --grf-panel-bd: var(--tint-accent-bd);
    margin-bottom: 12px;
    padding: 10px;
    border-radius: var(--radius-md);
    background: var(--grf-panel-bg);
    border: 1px solid var(--grf-panel-bd);
}
.grf-info__panel--signal { --grf-panel-fg: var(--tint-signal-fg); --grf-panel-bg: var(--tint-signal-bg); --grf-panel-bd: var(--tint-signal-bd); }
.grf-info__panel--danger { --grf-panel-fg: var(--tint-danger-fg); --grf-panel-bg: var(--tint-danger-bg); --grf-panel-bd: var(--tint-danger-bd); }
.grf-info__panel--flat   { padding: 8px; border: none; border-radius: var(--radius-sm); }

.grf-info__panel-title {
    display: flex;
    align-items: center;
    gap: 6px;
    font-weight: 600;
    font-size: 13px;
    margin-bottom: 8px;
    color: var(--grf-panel-fg, var(--accent));
}
.grf-info__panel-title--sm { font-size: 12px; margin-bottom: 6px; display: block; }

.grf-info__cards {
    display: grid;
    grid-template-rows: 1fr 1fr;
    gap: 12px;
    margin-bottom: 10px;
}
.grf-info__card {
    padding: 8px;
    border-radius: var(--radius-sm);
    background: var(--surface-2);
}
.grf-info__card--signal  { background: var(--tint-signal-bg); }
.grf-info__card--success { background: var(--tint-success-bg); }
.grf-info__card-title {
    font-weight: 600;
    font-size: 11px;
    margin-bottom: 6px;
    color: var(--text-2);
}
.grf-info__card-title--accent  { color: var(--accent); }
.grf-info__card-title--signal  { color: var(--tint-signal-fg); }
.grf-info__card-title--danger  { color: var(--tint-danger-fg); }
.grf-info__card-title--success { color: var(--tint-success-fg); }

.grf-info__group-title {
    display: flex;
    align-items: center;
    gap: 6px;
    font-weight: 600;
    font-size: 12px;
    margin-bottom: 8px;
    color: var(--text-2);
}
.grf-info__group-title--accent { color: var(--accent); }
.grf-info__group-title--signal { color: var(--tint-signal-fg); }
.grf-info__group-title--danger { color: var(--tint-danger-fg); }

.grf-info__scroll {
    max-height: 300px;
    overflow-y: auto;
    padding: 10px;
    border: 1px solid var(--keyline);
    border-radius: var(--radius-md);
    background: var(--surface-sunken);
}
.grf-info__scroll--tall { max-height: 400px; }

.grf-info__item {
    margin-bottom: 8px;
    padding: 6px;
    border-radius: var(--radius-sm);
    background: var(--surface-2);
}

/* STR layer texture rows */
.grf-info__tex-row {
    margin: 2px 0;
    padding: 2px 4px;
    border-radius: 2px;
    background: var(--surface-3);
    font-family: var(--font-family-mono, monospace);
    font-size: 9px;
}
.grf-info__tex-path { color: var(--text-3); font-size: 8px; }

/* RSM node hierarchy */
.grf-info__node {
    margin: 4px 0;
    padding: 6px;
    border-radius: var(--radius-sm);
    background: var(--surface-2);
    border-left: 3px solid var(--text-3);
}
.grf-info__node.is-animated { border-left-color: var(--status-success); }
.grf-info__node-head {
    display: flex;
    align-items: center;
    gap: 6px;
    padding-left: var(--grf-node-indent, 0);
}
.grf-info__node-name {
    font-weight: 600;
    font-size: 11px;
    color: var(--accent);
    font-family: var(--font-family-mono, monospace);
}
.grf-info__node-body {
    margin-top: 4px;
    font-size: 10px;
    color: var(--text-2);
    padding-left: calc(var(--grf-node-indent, 0px) + 20px);
}
.grf-info__node-tex { margin-top: 4px; color: var(--text-3); font-size: 9px; }
.grf-info__bullet        { color: var(--text-3); font-size: 10px; }
.grf-info__bullet--leaf  { color: var(--text-3); }

/* SPR frame previews, grouped by action. The hue cycle only exists so adjacent
   action groups read apart. */
.grf-info__action {
    margin-bottom: 20px;
    padding: 12px;
    border-radius: var(--radius-md);
    border: 1px solid var(--keyline);
    background: color-mix(in srgb, var(--grf-action-hue, var(--text-3)) 10%, transparent);
}
.grf-info__action[data-hue="0"]        { --grf-action-hue: #ff64c8; }
.grf-info__action[data-hue="1"]        { --grf-action-hue: #64c8ff; }
.grf-info__action[data-hue="2"]        { --grf-action-hue: #64ff64; }
.grf-info__action[data-hue="3"]        { --grf-action-hue: #ffc864; }
.grf-info__action[data-hue="4"]        { --grf-action-hue: #c864ff; }
.grf-info__action[data-hue="5"]        { --grf-action-hue: #ffff64; }
.grf-info__action[data-hue="6"]        { --grf-action-hue: #64ffff; }
.grf-info__action[data-hue="7"]        { --grf-action-hue: #ff9696; }
.grf-info__action[data-hue="static"]   { --grf-action-hue: var(--text-3); }

.grf-info__action-head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 10px;
    padding-bottom: 6px;
    border-bottom: 1px solid var(--keyline);
}
.grf-info__action-title {
    display: flex;
    align-items: center;
    gap: 6px;
    font-weight: 600;
    font-size: 12px;
    color: var(--tint-danger-fg);
}
.grf-info__action-meta { display: flex; flex-direction: column; gap: 4px; align-items: flex-end; }

.grf-info__frames {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(40px, 1fr));
    gap: 6px;
    max-width: 100%;
}
.grf-info__frame { position: relative; display: flex; flex-direction: column; align-items: center; }
.grf-info__frame-img {
    border: 1px solid var(--keyline);
    border-radius: var(--radius-sm);
    image-rendering: pixelated;
    margin-bottom: 2px;
}
.grf-info__frame-missing {
    width: 40px;
    height: 40px;
    margin-bottom: 2px;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    border: 1px solid var(--keyline);
    border-radius: var(--radius-sm);
    background: var(--surface-3);
    color: var(--text-3);
    font-size: 7px;
}
.grf-info__frame-no {
    min-width: 16px;
    padding: 1px 4px;
    border-radius: var(--radius-sm);
    background: var(--surface-sunken);
    color: var(--text-1);
    font-size: 8px;
    font-weight: 700;
    text-align: center;
}

/* RSM texture gallery */
.grf-info__tex-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
    gap: 8px;
}
.grf-info__tex-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    padding: 6px;
    border: 1px solid var(--keyline);
    border-radius: var(--radius-sm);
    background: var(--surface-2);
}
.grf-info__tex-thumb {
    width: 64px;
    height: 64px;
    object-fit: contain;
    border-radius: var(--radius-sm);
    border: 1px solid var(--keyline);
}
.grf-info__tex-thumb--empty {
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--surface-sunken);
    color: var(--text-3);
    font-size: 9px;
}
.grf-info__tex-label { font-size: 9px; color: var(--text-2); text-align: center; word-break: break-all; max-width: 100%; }
.grf-info__tex-sub   { font-size: 8px; color: var(--text-3); text-align: center; font-family: var(--font-family-mono, monospace); word-break: break-all; }
.grf-info__tex-used  { font-size: 8px; color: var(--status-success); }


/* ============================================================
   46. Model preview dialog (customUI/ModelPreviewDialog)
   ============================================================ */

/* The dialog's floating host: the preview fills it and manages its own scrolling. */
.mpd-window .ui-window__content {
    padding: 0;
    overflow: hidden;
    display: flex;
    min-height: 0;
}

.mpd-root {
    /* `--mpd-text-muted` was referenced by a dozen rules in this section but never
       defined, so each of them fell through to the inherited colour. */
    --mpd-text-muted: var(--text-3);
    display: flex;
    flex-direction: column;
    height: 100%;
    width: 100%;
    overflow: hidden;
    background: var(--surface-sunken);
}

.mpd-topbar {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 14px;
    border-bottom: 1px solid var(--keyline);
    background: linear-gradient(180deg, var(--surface-1) 0%, var(--surface-0) 100%);
}

.mpd-topbar-main {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.mpd-topbar-title {
    font-size: 14px;
    font-weight: 700;
    letter-spacing: 0.03em;
    color: var(--text-1);
}

.mpd-topbar-subtitle {
    font-size: 11px;
    color: var(--text-3);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.mpd-topbar-actions {
    display: flex;
    gap: 8px;
    align-items: center;
}

.mpd-spacer {
    flex: 1;
}

.mpd-hint {
    font-size: 12px;
    opacity: 0.75;
}

.mpd-export-hint {
    font-size: 11px;
    font-weight: 600;
    color: var(--accent-hover);
    border: 1px solid var(--accent-border);
    border-radius: 999px;
    padding: 5px 10px;
    background: var(--accent-muted);
    white-space: nowrap;
}

.mpd-main {
    display: flex;
    flex: 1;
    min-height: 0;
}

.mpd-viewports {
    display: flex;
    flex: 1;
    gap: 10px;
    padding: 10px;
    min-width: 0;
}

/* Single viewport layout (replaces dual left/right split) */
.mpd-viewports-single {
    display: flex;
    flex: 1;
}

.mpd-viewport {
    position: relative;
    flex: 1;
    min-width: 0;
    border: 2px solid var(--text-2);
    border-radius: 8px;
    overflow: hidden;
    background: var(--surface-sunken);
}

.mpd-viewport-full {
    flex: 1;
}

.mpd-viewport-title {
    position: absolute;
    top: 8px;
    left: 8px;
    z-index: 5;
    font-size: 12px;
    padding: 3px 8px;
    border-radius: 999px;
    background: rgba(0, 0, 0, 0.5);
    border: 1px solid var(--surface-3);
    color: var(--text-1);
    pointer-events: none;
}

.mpd-canvas {
    width: 100%;
    height: 100%;
    display: block;
}

.mpd-viewport-toolbar {
    position: absolute;
    top: 8px;
    right: 8px;
    z-index: 6;
    display: flex;
    align-items: center;
    gap: 8px;
    background: rgba(0, 0, 0, 0.55);
    border: 1px solid var(--keyline);
    padding: 6px 8px;
    border-radius: 10px;
    backdrop-filter: blur(8px);
}

.mpd-chip {
    font-size: 11px;
    padding: 4px 8px;
    border-radius: 999px;
    background: var(--keyline);
    color: var(--text-1);
    border: 1px solid var(--surface-3);
}

.mpd-viewport-modes {
    display: inline-flex;
    align-items: center;
    gap: 4px;
}

.mpd-mode-btn {
    width: 28px;
    height: 28px;
    padding: 0;
    border-radius: 6px;
    background: var(--keyline);
    border: 1px solid var(--surface-4);
    color: var(--text-2);
    transition: all 0.15s ease;
}

.mpd-mode-btn:hover {
    background: var(--surface-4);
}

.mpd-mode-btn.active {
    color: var(--accent);
    border-color: var(--accent);
    box-shadow: 0 0 0 1px var(--accent-border);
    background: var(--accent-muted);
}

.mpd-panel {
    width: 340px;
    border-left: 1px solid var(--keyline);
    background: var(--surface-0);
    padding: 12px;
    overflow: auto;
    position: relative;
}

.mpd-section-title {
    margin-top: 10px;
    margin-bottom: 6px;
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    opacity: 0.75;
}

.mpd-row {
    display: grid;
    grid-template-columns: 90px 1fr;
    gap: 8px;
    align-items: center;
    margin-bottom: 8px;
}

.mpd-row-tight {
    align-items: flex-start;
}

.mpd-row-two-col {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 8px;
    margin-bottom: 8px;
}

.mpd-select-group {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.mpd-geometry-controls {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 8px;
}

.mpd-preset-wrap {
    flex: 1;
    min-width: 0;
}

.mpd-preset-select-container {
    position: relative;
    display: flex;
    align-items: center;
}

.mpd-preset-icon {
    position: absolute;
    left: 10px;
    z-index: 1;
    pointer-events: none;
    font-size: 12px;
    color: var(--text-2);
}

.mpd-preset-select-container select {
    padding-left: 32px;
}

.mpd-checkboxes-wrap {
    display: flex;
    align-items: center;
    gap: 8px;
}

.mpd-checkboxes-wrap .form-check {
    margin: 0;
    display: flex;
    align-items: center;
}

.mpd-checkboxes-wrap .form-check-label {
    padding: 0;
    margin-left: 4px;
    display: flex;
    align-items: center;
    font-size: 14px;
}

.mpd-checkboxes-wrap .form-check-input {
    margin: 0;
    margin-top: 0;
}

.mpd-label {
    font-size: 12px;
    opacity: 0.85;
}

.mpd-range-wrap {
    display: flex;
    align-items: center;
    gap: 8px;
}

.mpd-range-value {
    width: 54px;
    text-align: right;
    font-size: 12px;
    opacity: 0.85;
}

.mpd-stats-container {
    border: 1px solid var(--keyline);
    border-radius: 10px;
    padding: 10px;
    background: linear-gradient(180deg, var(--surface-sunken) 0%, var(--surface-sunken) 100%);
    margin-bottom: 10px;
}

.mpd-stats {
    margin-top: 6px;
}

.mpd-info-texture-row {
    margin-top: 8px;
}

.mpd-info-texture-thumb {
    width: 64px;
    height: 64px;
    object-fit: contain;
    background: var(--surface-sunken);
    border: 1px solid var(--keyline);
    border-radius: 6px;
    cursor: pointer;
}

.mpd-texture-tooltip {
    position: fixed;
    z-index: 10000;
    padding: 6px;
    background: var(--surface-2);
    border: 1px solid var(--surface-4);
    border-radius: 8px;
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5);
}

.mpd-texture-tooltip img {
    max-width: 320px;
    max-height: 320px;
    width: auto;
    height: auto;
    display: block;
    border-radius: 4px;
}

.mpd-stats-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 6px;
}

.mpd-stats-col {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.mpd-stat {
    display: flex;
    justify-content: space-between;
    font-size: 11px;
    padding: 5px 7px;
    border: 1px solid var(--keyline);
    border-radius: 5px;
    background: var(--surface-sunken);
}

.mpd-stat span {
    opacity: 0.75;
}

.mpd-stat b {
    font-weight: 600;
    color: var(--text-1);
}

.mpd-tint-controls {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 8px;
    align-items: center;
}


.mpd-collapsible-section {
    margin-bottom: 10px;
    border: 1px solid var(--keyline);
    border-radius: 10px;
    padding: 0 10px 10px;
    background: var(--surface-sunken);
}

.mpd-collapsible-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 10px 0;
    cursor: pointer;
    user-select: none;
    transition: opacity 0.2s ease;
}

.mpd-collapsible-header:hover {
    opacity: 0.9;
}

.mpd-collapsible-title {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    opacity: 0.85;
}

.mpd-collapsible-icon {
    font-size: 10px;
    transition: transform 0.2s ease;
    opacity: 0.6;
}

.mpd-collapsible-content {
    margin-top: 6px;
}

/* Fine-tune geometry (vertex editor) */
.mpd-finetune-wrap {
    flex-shrink: 0;
    margin-top: 8px;
    border: 1px solid var(--surface-3);
    border-radius: 8px;
    background: rgba(0, 0, 0, 0.25);
    overflow: hidden;
}
.mpd-finetune-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 8px 12px;
    font-size: 11px;
    font-weight: 600;
    color: var(--mpd-text, var(--text-1));
    background: rgba(0, 0, 0, 0.2);
    cursor: pointer;
    user-select: none;
}
.mpd-finetune-header:hover {
    background: rgba(0, 0, 0, 0.35);
}
.mpd-finetune-body {
    padding: 10px 12px;
    display: flex;
    flex-direction: column;
    gap: 10px;
    font-size: 11px;
    color: var(--mpd-text, var(--text-1));
}
.mpd-finetune-row {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}
.mpd-finetune-label {
    min-width: 52px;
    color: var(--mpd-text-muted);
}
.mpd-finetune-row select,
.mpd-finetune-row input[type="number"] {
    min-width: 72px;
    padding: 4px 8px;
    border-radius: 6px;
    border: 1px solid var(--surface-4);
    background: rgba(0, 0, 0, 0.3);
    color: var(--mpd-text);
    font-size: 11px;
}
.mpd-finetune-nudge {
    display: flex;
    align-items: center;
    gap: 4px;
}
.mpd-finetune-nudge button {
    width: 26px;
    height: 26px;
    padding: 0;
    border: 1px solid var(--surface-4);
    border-radius: 6px;
    background: var(--keyline);
    color: var(--mpd-text);
    font-size: 12px;
    cursor: pointer;
    line-height: 1;
}
.mpd-finetune-nudge button:hover {
    background: var(--accent-muted);
    border-color: var(--accent-border);
}
.mpd-finetune-coord {
    font-family: monospace;
    min-width: 56px;
    font-size: 10px;
    color: var(--mpd-text);
}
.mpd-finetune-undo-row {
    display: flex;
    gap: 6px;
    margin-top: 4px;
    padding-top: 8px;
    border-top: 1px solid var(--keyline);
}
.mpd-finetune-undo-row button {
    padding: 4px 10px;
    font-size: 11px;
    border-radius: 6px;
    border: 1px solid var(--surface-4);
    background: var(--keyline);
    color: var(--mpd-text);
    cursor: pointer;
}
.mpd-finetune-undo-row button:hover:not(:disabled) {
    background: var(--accent-muted);
    border-color: var(--accent-border);
}
.mpd-finetune-undo-row button:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}
.mpd-finetune-hint {
    font-size: 10px;
    color: var(--mpd-text-muted);
    margin-top: 4px;
}

/* Mesh edit panel (Vertex/Face/Edge tool) */
.mpd-meshedit-mode-row {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}
.mpd-meshedit-mode-btns {
    display: flex;
    gap: 4px;
    flex-wrap: wrap;
}
.mpd-meshedit-mode-btn {
    padding: 4px 10px;
    font-size: 11px;
    border-radius: 6px;
    border: 1px solid var(--surface-4);
    background: var(--keyline);
    color: var(--mpd-text, var(--text-1));
    cursor: pointer;
}
.mpd-meshedit-mode-btn:hover {
    background: var(--surface-3);
}
.mpd-meshedit-mode-btn.active {
    background: var(--accent-border);
    border-color: var(--accent);
    color: var(--text-1);
}
.mpd-meshedit-snap-row {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}
.mpd-meshedit-snap-row .form-check-label {
    font-size: 11px;
    color: var(--mpd-text-muted);
}
.mpd-meshedit-selection-info {
    font-size: 11px;
    color: var(--mpd-text-muted);
    min-height: 1.2em;
}
.mpd-meshedit-hint {
    font-size: 10px;
    color: var(--mpd-text-muted);
    margin-top: 4px;
}

/* Chrome that used to be inline in ModelPreviewDialog.js, or Bootstrap form/button
   classes. The controls themselves are UIKit (`ui-btn`, `ui-input`, `ui-select`,
   `ui-toggle`); what is left here is only the placement each one needs. */
.mpd-inline-btn        { margin-left: 4px; }
.mpd-switch            { font-size: 11px; color: var(--mpd-text-muted); }
.mpd-snap-grid-size    { width: 4rem; }

.mpd-finetune-placeholder {
    padding: 8px 12px;
    font-size: 11px;
    color: var(--mpd-text-muted);
}

.mpd-wirelines {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-left: 8px;
}
.mpd-wirelines__label {
    font-size: 11px;
    color: var(--text-2);
    cursor: pointer;
    user-select: none;
}

.mpd-segment-hint {
    margin-left: auto;
    font-size: 10px;
    color: var(--mpd-text-muted);
    white-space: nowrap;
}


/* ============================================================
   47. Data import dialog (customUI/DataImportDialog)
   ============================================================ */

.data-import-dialog-content {
	padding: 0.5rem;
	color: var(--bs-body-color);
	height: 100%;
	min-height: 0; /* Allow flex shrinking */
}

.data-import-main {
	display: flex;
	flex-direction: column;
	gap: 0.5rem;
	height: 100%;
	min-height: 0;
}

.data-import-top {
	display: grid;
	grid-template-columns: 3fr 2fr;
	gap: 0.5rem;
	height: 338px;
	flex: 0 0 auto;
}

@media (max-width: 900px) {
	.data-import-top {
		grid-template-columns: 1fr;
	}
}

.data-import-panel {
	display: flex;
	flex-direction: column;
	min-height: 0;
	border: 1px solid var(--surface-3);
	border-radius: 0.6rem;
}

.data-import-panel-header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 0.5rem;
	padding: 0.6rem 0.75rem;
	border-bottom: 1px solid var(--keyline);
	background: linear-gradient(180deg, var(--surface-2), var(--surface-1));
	backdrop-filter: blur(6px);
}

.data-import-panel-heading {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	min-width: 0;
}

.data-import-panel-heading i {
	color: var(--text-2);
}

.data-import-panel-heading-text {
	display: flex;
	flex-direction: column;
	gap: 0.1rem;
	min-width: 0;
}

.data-import-panel-title {
	font-size: 0.85rem;
	font-weight: 600;
	letter-spacing: 0.2px;
	line-height: 1.1;
}

.data-import-panel-subtitle {
	color: var(--bs-secondary-color);
	line-height: 1.1;
}

.data-import-panel-actions {
	display: flex;
	align-items: center;
	gap: 0.35rem;
	flex-shrink: 0;
}

.data-import-panel-body {
	flex: 1;
	min-height: 0;
	overflow: hidden;
	padding: 0.5rem;
	display: flex;
	flex-direction: column;
}

.data-import-panel-body .data-import-task-list.uia-container {
	flex: 1;
	min-height: 0;
	overflow-y: hidden;
	display: flex;
	flex-direction: column;
}

.data-import-summary {
	display: flex;
	align-items: center;
	gap: 0.35rem;
	margin-left: 0.5rem;
	flex-shrink: 0;
}

.data-import-summary .badge {
	font-size: 0.7rem;
	font-weight: 600;
	letter-spacing: 0.2px;
}

.data-import-empty {
	padding: 0.6rem 0.75rem;
	border: 1px dashed var(--surface-3);
	border-radius: 0.5rem;
	color: var(--bs-secondary-color);
	background: rgba(0, 0, 0, 0.15);
}

.data-import-note {
	display: flex;
	align-items: flex-start;
	gap: 0.5rem;
	padding: 0.6rem 0.75rem;
	margin-bottom: 0.75rem;
	border: 1px solid var(--accent-muted);
	border-radius: 0.5rem;
	background: var(--accent-muted);
	color: var(--text-1);
	font-size: 0.75rem;
	line-height: 1.3;
}

.data-import-note i {
	margin-top: 0.05rem;
	color: var(--accent);
}

.data-import-log-search {
	width: 220px;
}

.data-import-log-filter {
	width: 140px;
}

@media (max-width: 900px) {
	.data-import-log-search {
		width: 100%;
	}
	.data-import-panel-actions {
		flex-wrap: wrap;
		justify-content: flex-end;
	}
}

.data-import-log-autoscroll {
	margin: 0;
	padding: 0;
	display: inline-flex;
	align-items: center;
	gap: 0.35rem;
}

.data-import-log-autoscroll .form-check-input {
	margin: 0;
}

.data-import-status {
	font-size: 0.85rem;
	color: var(--bs-secondary-color);
}

.data-import-progress {
	height: 6px;
	background-color: var(--surface-3);
}

.data-import-progress .progress-bar {
	background-color: var(--bs-primary);
}

.store-item {
	border-bottom: 1px solid var(--keyline);
}

.store-item:last-child {
	border-bottom: none;
}

.store-name {
	font-weight: 500;
	color: var(--bs-body-color);
}

.store-count {
	font-size: var(--font-size-xs);
    min-width: 2.0rem;
    text-align: center;
    line-height: 0.65em;
}

.btn-clear-store {
	/* padding: 0.125rem 0.375rem; */
	font-size: var(--font-size-xs);
	/* line-height: 1; */
	width: 1.5rem;
	height: 1.5rem;
	/* display: flex; */
	/* align-items: center; */
	/* justify-content: center; */
}

.btn-clear-store:disabled {
	opacity: 0.5;
	cursor: not-allowed;
}

/* Footer Styles */
.data-import-footer {
	padding: 0.5rem;
}

.data-import-log-section {
	display: flex;
	flex-direction: column;
	gap: 0.25rem;
	flex: 1;
	min-height: 0;
}

.data-import-log-toolbar {
	padding: 0.25rem 0;
	flex-shrink: 0;
}

.data-import-log-toolbar .form-select-sm,
.data-import-log-toolbar .btn-xs {
	font-size: 0.75rem;
}

.data-import-body-logger {
	flex: 1;
    min-height: 95px;
    max-height: none;
    overflow-y: auto;
    background: rgba(0, 0, 0, 0.3);
    border: 1px solid var(--surface-3);
    border-radius: 0.4rem;
    padding: 0.5rem;
    font-family: 'Courier New', monospace;
    font-size: var(--font-size-xs);
    line-height: 1.2;
    color: var(--bs-body-color);
    scrollbar-width: thin;
    scrollbar-color: var(--surface-4) transparent;
    user-select: text;
}

.data-import-body-logger::-webkit-scrollbar {
	width: 6px;
}

.data-import-body-logger::-webkit-scrollbar-track {
	background: transparent;
}

.data-import-body-logger::-webkit-scrollbar-thumb {
	background: var(--surface-4);
	border-radius: 3px;
}

.data-import-body-logger::-webkit-scrollbar-thumb:hover {
	background: var(--text-3);
}

.data-import-body-logger .log-entry {
	margin-bottom: 0.25rem;
	padding: 0.125rem 0;
	border-bottom: 1px solid var(--surface-2);
}

.data-import-body-logger .log-entry:last-child {
	border-bottom: none;
	margin-bottom: 0;
}

.data-import-body-logger .log-icon-wrap {
	display: inline-flex;
	margin-right: 0.35rem;
	flex-shrink: 0;
}

.data-import-body-logger .log-icon {
	font-size: 0.7em;
}

.data-import-body-logger .log-icon-info { color: var(--bs-info); }
.data-import-body-logger .log-icon-success { color: var(--status-success); }
.data-import-body-logger .log-icon-warning { color: var(--status-warning); }
.data-import-body-logger .log-icon-error { color: var(--status-danger); }

.data-import-body-logger .log-timestamp {
	color: var(--bs-secondary-color);
	margin-right: 0.5rem;
	font-weight: normal;
}

.data-import-body-logger .log-stage {
	color: var(--bs-primary);
	font-weight: bold;
	margin-right: 0.5rem;
}

.data-import-body-logger .log-message {
	white-space: pre-wrap;
	word-break: break-word;
}

.data-import-body-logger .log-success {
	color: var(--status-success);
}

.data-import-body-logger .log-error {
	color: var(--status-danger);
}

.data-import-body-logger .log-warning {
	color: var(--status-warning);
}

.data-import-body-logger .log-info {
	color: var(--bs-info);
}

.data-import-footer-status {
	display: flex;
	align-items: center;
	gap: 0.75rem;
	flex-shrink: 0; /* Don't shrink the status row */
}

.data-import-footer-status .data-import-status {
	font-size: 0.8rem;
	flex: 1;
	min-width: 0;
}

.data-import-footer-status .data-import-progress {
	flex: 0 0 120px;
	height: 6px;
	margin: 0;
}

.data-import-footer-logger {
	flex: 1;
	min-height: 0;
	max-height: none;
	overflow-y: auto;
	background: rgba(0, 0, 0, 0.3);
	border: 1px solid var(--surface-3);
	border-radius: 0.4rem;
	padding: 0.5rem;
	font-family: 'Courier New', monospace;
	font-size: 0.75rem;
	line-height: 1.3;
	color: var(--bs-body-color);
	scrollbar-width: thin;
	scrollbar-color: var(--surface-4) transparent;
}

.data-import-footer-logger::-webkit-scrollbar {
	width: 6px;
}

.data-import-footer-logger::-webkit-scrollbar-track {
	background: transparent;
}

.data-import-footer-logger::-webkit-scrollbar-thumb {
	background: var(--surface-4);
	border-radius: 3px;
}

.data-import-footer-logger::-webkit-scrollbar-thumb:hover {
	background: var(--text-3);
}

.data-import-footer-logger .log-entry {
	margin-bottom: 0.25rem;
	padding: 0.125rem 0;
	border-bottom: 1px solid var(--surface-2);
}

.data-import-footer-logger .log-entry:last-child {
	border-bottom: none;
	margin-bottom: 0;
}

.data-import-footer-logger .log-timestamp {
	color: var(--bs-secondary-color);
	margin-right: 0.5rem;
	font-weight: normal;
}

.data-import-footer-logger .log-stage {
	color: var(--bs-primary);
	font-weight: bold;
	margin-right: 0.5rem;
}

.data-import-footer-logger .log-message {
	white-space: pre-wrap;
	word-break: break-word;
}

.data-import-footer-logger .log-success {
	color: var(--status-success);
}

.data-import-footer-logger .log-error {
	color: var(--status-danger);
}

.data-import-footer-logger .log-warning {
	color: var(--status-warning);
}

.data-import-footer-logger .log-info {
	color: var(--bs-info);
}

/* Worker Pool Card Styles */
.worker-pool-card {
	max-height: 180px;
	display: flex;
	flex-direction: column;
	overflow: hidden;
	padding: 0.25rem;
	border: 1px solid var(--surface-3);
	border-radius: 0.25rem;
	background: rgba(0, 0, 0, 0.2);
	margin-bottom: 0.25rem;
}

.worker-pool-header-row {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	flex-shrink: 0;
	padding: 0.125rem 0;
	font-size: 0.7rem;
	line-height: 1;
}

.worker-pool-title {
	font-weight: 600;
	font-size: 0.7rem;
	white-space: nowrap;
	flex-shrink: 0;
}

.worker-pool-controls {
	display: flex;
	align-items: center;
	gap: 0.2rem;
	flex-shrink: 0;
	font-size: 0.65rem;
}

.worker-pool-controls .worker-pool-input {
	height: 18px !important;
	padding: 0.1rem 0.2rem !important;
	font-size: 0.65rem !important;
	line-height: 1 !important;
	width: 40px !important;
}

.worker-pool-controls .btn-xs {
	padding: 2px 4px !important;
	min-width: 20px;
	height: 18px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
}

.worker-pool-controls .btn-xs i {
	font-size: 0.7rem;
}

.worker-pool-summary {
	font-size: 0.65rem;
	white-space: nowrap;
	margin-left: auto;
	color: var(--bs-secondary-color);
}

.worker-pool-table-wrapper {
	flex: 1;
	min-height: 0;
	overflow-y: auto;
	margin-top: 0.125rem;
}

.worker-pool-table {
	width: 100%;
	font-size: 0.65rem;
	border-collapse: collapse;
	background: transparent;
}

.worker-pool-table thead th {
	padding: 0.1rem 0.2rem;
	font-size: 0.6rem;
	font-weight: 600;
	border-bottom: 1px solid var(--keyline);
	text-align: left;
	background: transparent;
}

.worker-pool-table tbody td {
	padding: 0.1rem 0.2rem;
	font-size: 0.65rem;
	line-height: 1.1;
	vertical-align: middle;
	background: transparent;
}

.worker-pool-table tbody td:last-child {
	padding: 0.1rem;
}

.worker-pool-table tbody td .btn-xs {
	padding: 2px 4px !important;
	min-width: 18px;
	height: 16px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
}

.worker-pool-table tbody td .btn-xs i {
	font-size: 0.65rem;
}

.worker-pool-table tbody tr {
	border-bottom: 1px solid var(--surface-1);
}

.worker-pool-table tbody tr:last-child {
	border-bottom: none;
}

.worker-pool-empty {
	font-size: 0.65rem;
	color: var(--bs-secondary-color);
	text-align: center;
	padding: 0.25rem !important;
}

.badge-xs {
	font-size: 0.6rem;
	padding: 0.1rem 0.2rem;
	line-height: 1;
}

/* Task running state (accordion) */
.uia-widget.task-running {
	border-left: 3px solid var(--bs-primary);
}

/* Task file item states */
.task-file-item {
	transition: color 0.3s ease, opacity 0.5s ease-out;
	padding: 0.25rem 0.5rem;
}

.task-file-item.task-file-processing,
.task-file-item.task-file-item-processing {
	color: var(--bs-primary);
	background: var(--accent-muted);
	border-radius: 4px;
	padding: 2px 4px;
	font-weight: 500;
}

.task-file-item.task-file-completed {
	color: var(--bs-body-color);
	opacity: 0.7;
	transition: text-decoration 0s, opacity 0.5s ease-out, color 0.3s ease;
}


/* ============================================================

/* Chrome introduced by the UKWindow migration: the window body must not double up
   on padding/scrolling, the status bar shares the footer with the two buttons, and
   the Bootstrap text utilities that used to carry the notices are now real classes. */
.data-import-window .ui-window__content {
    padding: 0;
    overflow: hidden;
    display: flex;
    min-height: 0;
}

.data-import-statusbar { flex: 1 1 auto; min-width: 0; }

.data-import-notice {
    padding: 8px 12px;
    font-size: 11px;
}
.data-import-notice--warn  { color: var(--status-warning); }
.data-import-notice--error { color: var(--status-danger); }

.data-import-file-list          { font-size: 11px; }
.data-import-note__text         { font-size: 11px; }
.data-import-log-autoscroll__label { font-size: 11px; }

/* ============================================================
   48. GENESYS call-history dialog (customUI/GenesysHistoryDialog)
   ============================================================ */

.genesys-history { display: flex; flex-direction: column; gap: 10px; height: 100%; min-height: 0; color: var(--uk-text-1); }
.genesys-history__toolbar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.genesys-history__count { font-size: 12px; color: var(--uk-text-2); margin-right: auto; }
.genesys-history__list { display: flex; flex-direction: column; gap: 10px; flex: 1; min-height: 0; overflow-y: auto; padding-right: 4px; }
.genesys-history__empty { color: var(--uk-text-3); padding: 20px; text-align: center; line-height: 1.5; }
.genesys-history__head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.genesys-history__op { font-size: 13px; }
.genesys-history__time { font-size: 11px; color: var(--uk-text-3); margin-left: auto; }
.genesys-history__meta { display: flex; gap: 14px; flex-wrap: wrap; font-size: 11px; color: var(--uk-text-2); margin-top: 8px; }
.genesys-history__meta .is-error { color: var(--uk-danger); }
.genesys-history__params { margin-top: 8px; }
.genesys-history__params summary { cursor: pointer; font-size: 12px; color: var(--uk-text-2); }
.genesys-history__params pre {
    margin: 6px 0 0; padding: 8px;
    background: var(--surface-sunken); border: 1px solid var(--uk-border); border-radius: var(--uk-radius);
    font-size: 11px; max-height: 220px; overflow: auto; white-space: pre-wrap; word-break: break-word;
    font-family: var(--font-family-mono, monospace);
}
.genesys-history__gallery { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 8px; }
.genesys-history__tile { display: flex; flex-direction: column; gap: 3px; align-items: center; }
.genesys-history__thumb {
    width: 96px; height: 96px; object-fit: cover;
    border: 1px solid var(--uk-border); border-radius: var(--uk-radius);
    background: var(--surface-sunken); cursor: pointer;
}
.genesys-history__ph {
    width: 96px; height: 96px; display: flex; align-items: center; justify-content: center; text-align: center;
    border: 1px dashed var(--uk-border); border-radius: var(--uk-radius); font-size: 10px; color: var(--uk-text-3); padding: 4px;
}
.genesys-history__tile-size { font-size: 10px; color: var(--uk-text-3); }
.genesys-history__actions { display: flex; gap: 8px; justify-content: flex-end; margin-top: 8px; }


/* ============================================================
   49. Map analysis dialog (customUI/MapAnalysisDialog)
   ============================================================ */

.mad-root { display: flex; flex-direction: column; height: 100%; min-height: 0; }
.mad-stats { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 8px 12px; border-bottom: 1px solid var(--uk-glass-divider); flex-wrap: wrap; flex: 0 0 auto; }
.mad-stats__group { display: flex; gap: 16px; align-items: center; flex-wrap: wrap; font-size: 12px; color: var(--uk-text-2); }
.mad-stats__group b { color: var(--uk-text-1); }
.mad-root .ui-tabs { flex: 1; min-height: 0; }
.mad-root .ui-tabs__panels { overflow: auto; min-height: 0; flex: 1; }
.mad-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 8px; }
.mad-card { border: 1px solid var(--uk-glass-border); border-radius: var(--uk-radius-md); padding: 10px; background: var(--uk-glass-sunken); }
.mad-card h6 { margin: 0 0 8px; font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--uk-text-3); }
.mad-kv { display: flex; justify-content: space-between; gap: 8px; font-size: 12px; margin-bottom: 3px; }
.mad-kv .k { color: var(--uk-text-3); }
.mad-kv .v { color: var(--uk-text-1); font-weight: 600; word-break: break-word; text-align: right; }
.mad-thumb { background: var(--surface-sunken); border: 1px solid var(--uk-glass-border); border-radius: var(--uk-radius); min-height: 200px; display: flex; align-items: center; justify-content: center; color: var(--uk-text-3); }
.mad-toolbar { display: flex; gap: 8px; margin-bottom: 10px; }
.mad-hint { color: var(--uk-text-3); font-size: 12px; }


/* ============================================================
   50. Texture analysis dialog (customUI/TextureAnalysisDialog)
   ============================================================ */

.ta-root { display: flex; flex-direction: column; height: 100%; min-height: 0; }

.ta-header {
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    padding: 8px 12px; border-bottom: 1px solid var(--uk-glass-divider); flex: 0 0 auto;
}
.ta-stats { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.ta-stats .ui-badge b { font-weight: 700; }
.ta-progress { display: flex; align-items: center; gap: 8px; min-width: 220px; }
.ta-progress .bar { flex: 1 1 auto; height: 10px; background: var(--surface-sunken); border: 1px solid var(--uk-glass-border); border-radius: var(--uk-radius-full); overflow: hidden; }
.ta-progress .fill { height: 100%; width: 0%; background: var(--uk-success); transition: width .2s ease; }
.ta-progress .label { min-width: 92px; text-align: right; font-size: 11px; color: var(--uk-text-3); font-variant-numeric: tabular-nums; }

.ta-controls {
    display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
    padding: 8px 12px; border-bottom: 1px solid var(--uk-glass-divider); flex: 0 0 auto;
}
.ta-controls .ta-search { width: 260px; max-width: 100%; }
.ta-controls .ta-filter { width: 150px; }
.ta-controls .ta-status { width: 160px; }
.ta-pager { display: flex; align-items: center; gap: 8px; margin-left: auto; }
.ta-pager .ta-pagesize { width: 80px; }
.ta-pager .ta-page-info { font-size: 11px; color: var(--uk-text-3); font-variant-numeric: tabular-nums; }

.ta-grid-wrap { flex: 1 1 auto; min-height: 0; overflow: auto; border-top: 1px solid var(--uk-glass-divider); }
.ta-grid { display: grid; gap: 1px; background: var(--uk-glass-divider); min-height: 100%; }

.ta-head-cell {
    position: sticky; top: 0; z-index: 1;
    background: var(--uk-surface-2); color: var(--uk-text-2);
    padding: 8px; font-weight: 600; text-align: center; font-size: 12px;
}
.ta-cell { background: var(--uk-surface-1); color: var(--uk-text-1); padding: 8px; font-size: 12px; min-width: 0; }
.ta-cell--center { text-align: center; }
.ta-cell code { color: var(--uk-text-1); word-break: break-all; font-family: var(--font-family-mono, monospace); font-size: 11px; }
.ta-cell .ui-select { width: 100%; }
.ta-thumb { display: flex; align-items: center; justify-content: center; padding: 4px; background: var(--uk-surface-1); }
.ta-thumb img { max-width: 44px; max-height: 44px; object-fit: contain; border-radius: var(--uk-radius-sm); }
.ta-usage { display: flex; justify-content: center; gap: 4px; }
.ta-muted { color: var(--uk-text-3); }
.ta-maps { font-size: 11px; color: var(--uk-text-2); display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.ta-footer {
    display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
    padding: 10px 12px; border-top: 1px solid var(--uk-glass-divider); flex: 0 0 auto;
}
.ta-footer .ta-selinfo { margin-left: auto; font-size: 12px; color: var(--uk-text-3); }


/* 51. (vacant) — the standalone AI Terrain Populate dialog was removed: its
   element table and TRELLIS-creation flow now live in the AI Map wizard's Props
   step (see section 79's `.sw-props-review`). The number is left unreused so
   52-79 keep the identities they are referenced by elsewhere. */


/* 52. (vacant) — the AI Image Generator dialog was removed 2026-08-06.
   The number is left unreused so 53-79 keep the identities they are
   referenced by elsewhere. */


/* ============================================================
   53. Translation Dictionary (customUI/TranslationDictionaryDialog)
   ============================================================ */

.tdd-body { display: flex; flex-direction: column; gap: 12px; padding: 12px; height: 100%; box-sizing: border-box; }
.tdd-card { border: 1px solid var(--uk-glass-border); border-radius: var(--uk-radius-md); background: var(--uk-glass-sunken); overflow: hidden; }
.tdd-card__head {
    display: flex; align-items: center; justify-content: space-between; gap: 8px;
    padding: 8px 12px; border-bottom: 1px solid var(--uk-glass-divider); background: var(--uk-glass-panel);
}
.tdd-card__head h6 { margin: 0; font-size: 12px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--uk-text-2); font-weight: 600; }
.tdd-card__body { padding: 12px; }
.tdd-card__body--flush { padding: 0; }

.tdd-cats { display: flex; flex-direction: column; gap: 8px; }
.tdd-cat { justify-content: flex-start; text-align: left; }
.tdd-cat.active { background: var(--uk-accent); border-color: var(--uk-accent); color: #fff; }

.tdd-controls { display: flex; gap: 6px; }
.tdd-head-actions { display: flex; gap: 8px; align-items: center; }
.tdd-search { width: 200px; max-width: 40vw; }

.tdd-progress {
    height: 30px; border-radius: var(--uk-radius); background: var(--surface-sunken);
    border: 1px solid var(--uk-glass-border); overflow: hidden; margin-bottom: 12px;
}
.tdd-progress__bar {
    height: 100%; width: 0; display: flex; align-items: center; justify-content: center;
    background: linear-gradient(90deg, var(--uk-accent), color-mix(in srgb, var(--uk-accent) 70%, #fff));
    color: #fff; font-size: 12px; font-weight: 600; transition: width .2s ease; white-space: nowrap;
}

.tdd-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 8px; margin-bottom: 12px; }
.tdd-stat { display: flex; flex-direction: column; gap: 2px; }
.tdd-stat__label { font-size: 11px; color: var(--uk-text-3); }
.tdd-stat__value { font-size: 20px; font-weight: 700; color: var(--uk-text-1); font-variant-numeric: tabular-nums; }
.tdd-stat__value.is-success { color: var(--uk-success); }
.tdd-stat__value.is-warning { color: var(--uk-warning); }
.tdd-stat__value.is-danger { color: var(--uk-danger); }
.tdd-catstats { font-size: 11px; color: var(--uk-text-3); }

.tdd-table-wrap { max-height: 400px; overflow: auto; }
.tdd-table thead th { position: sticky; top: 0; z-index: 1; background: var(--uk-surface-2); }
.tdd-table tbody tr:hover td { background: color-mix(in srgb, var(--uk-accent) 8%, transparent); }
.tdd-table code { font-family: var(--font-family-mono, monospace); font-size: 11px; }
.tdd-empty { text-align: center; color: var(--uk-text-3); padding: 16px; }

.tdd-log {
    max-height: 200px; overflow-y: auto; font-family: var(--font-family-mono, monospace);
    font-size: 11px; line-height: 1.35; user-select: text;
    background: var(--surface-sunken); border: 1px solid var(--uk-glass-border); border-radius: var(--uk-radius); padding: 6px 8px;
}
.tdd-log__line { margin-bottom: 2px; }
.tdd-log__t { color: var(--uk-text-3); margin-right: 5px; }
.tdd-log__msg { color: var(--uk-text-2); }
.tdd-log__msg.is-success { color: var(--uk-success); }
.tdd-log__msg.is-warning { color: var(--uk-warning); }
.tdd-log__msg.is-danger { color: var(--uk-danger); }
.tdd-log__msg.is-info { color: var(--uk-info); }


/* ============================================================
   54. Staged Model Wizard (customUI/AIModelCreate/staged)
   Was an injected <style> (StagedModelWizardStyles.js); tokenized here.
   ============================================================ */

/* The wizard's floating host. Without this the shell lives in the default
   `.ui-window__content`, which is `overflow: auto` (plus `.ui-scrollable`) — a second
   scroll container wrapped around `.smw-panel`'s own. Same block every other dialog
   carries; see `.sw-window` (§61), `.grf-explorer-window`, `.nm-window`. */
.smw-window .ui-window__content {
    padding: 0;
    overflow: hidden;
    display: flex;
    min-height: 0;
}

/* `flex: 1; min-width: 0` because the content box above is a ROW flex container: without
   a grow factor the shell sizes to max-content and leaves dead space beside itself. */
.smw-shell {
    display: flex; flex-direction: column; flex: 1; min-width: 0;
    height: 100%; min-height: 0;
    color: var(--uk-text-1, #e7e7e7);
}
.smw-main { position: relative; display: flex; flex-direction: column; flex: 1; min-height: 0; }
.smw-panel { flex: 1; min-height: 0; overflow: auto; padding: var(--uk-gap, 12px); }
.smw-foot {
    flex: 0 0 auto;
    border-top: 1px solid var(--uk-keyline, rgba(255,255,255,0.12));
    padding: 8px var(--uk-gap, 12px);
    display: flex; flex-direction: column; gap: 8px;
    background: var(--uk-surface-2, rgba(0,0,0,0.15));
}
/* Lay the shared (vertical) stepper out horizontally in the footer.

   Every one of these declarations is load-bearing, because UKStepper's default IS a
   vertical left rail (§30: `width: 170px; flex: 0 0 170px` + its own surface, right
   keyline and padding). Overriding `width` alone is not enough: `.smw-foot` is a COLUMN
   flex container, so a surviving `flex-basis: 170px` is read as a HEIGHT — which is
   exactly how the footer came to be a 170px band with three step buttons stretched down
   it. Keep this list in step with `.sw-foot .ui-stepper` (§61), which had it right. */
.smw-foot .ui-stepper {
    width: auto;
    flex: 0 0 auto;
    flex-direction: row;
    align-items: center;
    background: transparent;
    border-right: none;
    padding: 0;
    overflow: visible;
}
.smw-foot .ui-stepper__list { flex-direction: row; flex: 1; gap: 6px; }
.smw-foot .ui-stepper__step { flex: 1; width: auto; }
.smw-foot .ui-stepper__toggle { display: none; }
.smw-foot-row { display: flex; align-items: center; gap: 8px; }
.smw-status {
    flex: 1; font-size: 12px; color: var(--uk-text-2, #9aa0a6);
    min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Stage layout: three columns (setup | main | inspect). */
.smw-stage { display: flex; flex-direction: column; gap: var(--uk-gap, 12px); height: 100%; min-height: 0; }
.smw-cols { display: flex; gap: var(--uk-gap, 12px); flex: 1; min-height: 0; }
.smw-col-side { flex: 0 0 300px; display: flex; flex-direction: column; gap: 10px; overflow: auto; }
.smw-col-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 8px; min-height: 0; }
.smw-col-end { flex: 0 0 288px; display: flex; flex-direction: column; gap: 10px; overflow: auto; }
/* These columns space their children with `gap`, so `.ui-field`'s own bottom margin
   (§9) stacks on top of it and doubles the rhythm — ~9 fields per column. Drop the
   margin here rather than changing the shared component. */
.smw-col-side > .ui-field,
.smw-col-main > .ui-field,
.smw-col-end  > .ui-field { margin-bottom: 0; }

/* Two stage panels lay themselves out from JS (`style.cssText`) because they had no
   class: ConceptStage's retouch panel and ExportStage's action stack. */
.smw-stack { display: flex; flex-direction: column; gap: 8px; }
.smw-stack--actions { gap: 6px; margin-top: 6px; }

/* Concept / preview surfaces. */
.smw-canvas {
    position: relative; flex: 1; min-height: 0;
    /* ConceptStage mounts an InpaintCanvas in here, whose <img> is capped by
       `--inpaint-max-height` with a 60vh fallback. That fallback is taller than this
       box, which clips (`overflow: hidden` below); the map wizard sets the property on
       its own stage (§61 `.sw-inpaint-stage`), so set it here too. `100%` keeps the
       image inside whatever height the flex chain hands down. */
    --inpaint-max-height: 100%;
    /* A sunken canvas the concept/mesh sits on. Was `var(--uk-surface-3, #151515)` — a
       token that is defined nowhere, so it always fell through to the hardcoded value
       and ignored the theme. `--surface-sunken` is the ramp's darkest step. */
    background: var(--surface-sunken);
    border: 1px solid var(--uk-keyline, rgba(255,255,255,0.12));
    border-radius: var(--uk-radius-md, 6px);
    overflow: hidden; display: flex; align-items: center; justify-content: center;
}
.smw-canvas img { max-width: 100%; max-height: 100%; object-fit: contain; }
.smw-dropzone {
    position: absolute; inset: 0;
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px;
    color: var(--uk-text-2, #9aa0a6); font-size: 12px; cursor: pointer; text-align: center; padding: 16px;
}
.smw-dropzone--drag { outline: 2px dashed var(--uk-accent, #4c9aff); outline-offset: -8px; }

/* Small info grid (mesh stats / rsm details). */
.smw-info-grid { display: grid; grid-template-columns: auto 1fr; gap: 2px 10px; font-size: 12px; }
.smw-info-grid > span { color: var(--uk-text-2, #9aa0a6); }
.smw-info-grid > b { text-align: right; font-variant-numeric: tabular-nums; }

.smw-row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.smw-hint { font-size: 11px; color: var(--uk-text-2, #9aa0a6); line-height: 1.4; }


/* ============================================================
   55. Texture Studio (customUI/TextureStudioDialog — .tst-*)
   Successor to the old three-column ".txs" Texture Sandbox block, which had a
   hard `min-width: 860px` and so scrolled sideways inside its own tab.
   ============================================================ */

.tst-window .ui-window__content {
    /* Both halves of the window↔shell contract. Miss the shell's `flex` and it
       sizes to max-content in a row container; miss `overflow: hidden` and the
       shell's own scrolling panes sit inside a second scroll container. */
    padding: 0;
    display: flex;
    min-height: 0;
    overflow: hidden;
}

.tst-root {
    /* Alias the design tokens once so every rule below is theme-agnostic. */
    --tst-gap: 12px;
    --tst-rail: 288px;
    --tst-surface: var(--uk-glass-sunken, var(--surface-1));
    --tst-border: var(--keyline);
    --tst-text-2: var(--text-2);

    /* Pin the text colour rather than inheriting it, the same as `.mbd-root`:
       the components inside (UKCard headers especially) declare none of their
       own, so they otherwise ride on whatever Bootstrap's reboot left on body. */
    color: var(--text-1);

    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    min-height: 0;
    /* This is what anchors the absolutely-positioned UKBusyOverlay. */
    position: relative;
    /* …and what the Studio tab's @container queries measure. */
    container-type: inline-size;
    container-name: tst;
}

.tst-root > .ui-tabs {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
}
.tst-root > .ui-tabs > .ui-tabs__panels { flex: 1 1 auto; min-height: 0; }
.tst-root .ui-tabs__panel { padding: 0; }
.tst-root .ui-tabs__panel--active {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
}

.tst-status {
    flex: 0 0 auto;
    padding: 4px 10px;
    font-size: 0.78rem;
    color: var(--tst-text-2);
    border-top: 1px solid var(--tst-border);
    min-height: 22px;
}

/* Anything hidden by the current operation, or disabled while a job runs. */
.tst-root .is-hidden { display: none !important; }
.tst-root .is-disabled { opacity: 0.45; pointer-events: none; }

/* ── Browse tab ──────────────────────────────────────────────────────────── */
/* The tab is the shared AssetBrowser (§32) scoped to data\texture — the toolbar,
   folder rail, grid and preview are all `ui-asset-*`. All that belongs here is the
   flex contract between the tab panel and that shell, plus the armed-slot badge. */

.tst-browse {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
    width: 100%;
}
/* `.ui-asset-browser` is `height: 100%` — give it a flex item that can shrink,
   or its own scrolling panes end up inside a second scroll container. */
.tst-browse > .ui-asset-browser {
    flex: 1 1 auto;
    min-height: 0;
}
/* Which Studio slot the next pick fills. It sits with the Send buttons in the
   toolbar's right-aligned action group, so it must not wrap away from them. */
.tst-browse__armed {
    white-space: nowrap;
}

/* ── Studio tab ──────────────────────────────────────────────────────────── */

.tst-studio {
    display: grid;
    grid-template-columns: var(--tst-rail) minmax(0, 1fr) var(--tst-rail);
    gap: var(--tst-gap);
    padding: var(--tst-gap);
    flex: 1 1 auto;
    min-height: 0;
    overflow: auto;
}
/* Generate reads neither source slot, so the rail is hidden — and the template
   has to lose a column with it. `display: none` alone does not leave a hole: the
   remaining items shift up a track, which put the stage in the 288px rail column. */
.tst-studio--no-sources { grid-template-columns: minmax(0, 1fr) var(--tst-rail); }

/* Three columns, then two, then one — instead of the old fixed 860px minimum and
   a sideways scrollbar. These are CONTAINER queries, not viewport ones: this is a
   window inside the page, so its own width is what the layout has to answer to. */
@container tst (max-width: 1180px) {
    .tst-studio { grid-template-columns: var(--tst-rail) minmax(0, 1fr); }
    .tst-studio--no-sources { grid-template-columns: minmax(0, 1fr); }
    .tst-rail--operation { grid-column: 1 / -1; }
}
@container tst (max-width: 820px) {
    .tst-studio,
    .tst-studio--no-sources { grid-template-columns: 1fr; }
    .tst-rail--operation { grid-column: auto; }
}

.tst-rail {
    display: flex;
    flex-direction: column;
    gap: 8px;
    min-width: 0;
    min-height: 0;
}
.tst-centre {
    display: flex;
    flex-direction: column;
    gap: 8px;
    min-width: 0;
    min-height: 0;
}
.tst-row { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
.tst-hint {
    font-size: var(--uk-font-size-sm);
    color: var(--tst-text-2);
    line-height: 1.4;
}
.tst-hint--apply { color: var(--uk-signal, var(--signal)); }

/* Source slots */
.tst-slot { display: flex; flex-direction: column; gap: 6px; }
.tst-thumb {
    width: 100%;
    aspect-ratio: 1;
    max-height: 168px;
    border: 1px dashed var(--tst-border);
    border-radius: 6px;
    background-color: var(--tst-surface);
    background-size: cover;
    background-position: center;
    image-rendering: pixelated;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: border-color var(--motion-fast, 120ms) ease;
}
.tst-thumb:hover,
.tst-thumb:focus-visible { border-color: var(--uk-accent-border, var(--accent-border)); }
.tst-thumb--over {
    border-color: var(--uk-accent, var(--accent));
    border-style: solid;
}
.tst-thumb:not(.tst-thumb--empty) { border-style: solid; }
.tst-slot__btns { display: flex; gap: 4px; flex-wrap: wrap; }
.tst-slot__btns .ui-btn { flex: 1 1 auto; }

/* Mask toolbar — every mask control in ONE place. These used to be split
   between the left column and a strip under the stage. */
.tst-tools {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    padding: 6px 8px;
    background: var(--tst-surface);
    border: 1px solid var(--tst-border);
    border-radius: 6px;
}
.tst-tools__group { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.tst-tools__group:last-child { margin-left: auto; }
.tst-tools__brush { min-width: 168px; margin: 0; }
.tst-tools__brush .ui-field__label { font-size: var(--uk-font-size-sm); }
.tst-tools__coverage { margin-left: 4px; white-space: nowrap; }
.tst-tools .ui-btn.is-active {
    background: var(--tint-accent-bg, var(--surface-3));
    color: var(--tint-accent-fg, var(--text-1));
    border-color: var(--tint-accent-bd, var(--accent-border));
}

/* The stage. The BOX is fluid; the backing store is fixed — MaskStage converts
   pointer events through getBoundingClientRect(), so painting stays exact at any
   on-screen size. Do not put a pixel width back on `.tst-stage`. */
.tst-stage-wrap {
    display: flex;
    justify-content: center;
    align-items: flex-start;
    flex: 1 1 auto;
    min-height: 0;
}
.tst-stage {
    position: relative;
    width: 100%;
    max-width: 560px;
    aspect-ratio: 1;
    line-height: 0;
    touch-action: none;
    border: 1px solid var(--uk-border);
    border-radius: 4px;
    overflow: hidden;
}
.tst-stage:focus-visible { outline: 2px solid var(--uk-accent, var(--accent)); outline-offset: 2px; }
.tst-layer { position: absolute; inset: 0; width: 100%; height: 100%; }
.tst-base { image-rendering: pixelated; }
.tst-paint { cursor: crosshair; }
.tst-grid { pointer-events: none; }

/* Result strip */
.tst-results { display: flex; flex-direction: column; gap: 6px; min-height: 0; flex: 0 0 auto; }
.tst-results__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 0.78rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--tst-text-2);
}
.tst-results__strip {
    display: flex;
    gap: 8px;
    overflow-x: auto;
    padding-bottom: 4px;
    min-height: 96px;
}
.tst-results__empty { flex: 1; align-self: center; }
.tst-result {
    margin: 0;
    flex: 0 0 auto;
    width: 108px;
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 4px;
    border: 1px solid var(--tst-border);
    border-radius: 6px;
    background: var(--tst-surface);
}
.tst-result--active { border-color: var(--uk-accent, var(--accent)); }
.tst-result img {
    width: 100%;
    aspect-ratio: 1;
    object-fit: cover;
    image-rendering: pixelated;
    border-radius: 4px;
    background: var(--surface-sunken, var(--surface-1));
}
.tst-result figcaption {
    font-size: 10px;
    color: var(--tst-text-2);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.tst-result__actions { display: flex; gap: 2px; }
.tst-result__actions .ui-btn { flex: 1 1 auto; padding-inline: 4px; }

/* Apply is the one primary action on the panel. */
.tst-apply { width: 100%; }

/* Saved-mask library (inside a UKDialog) */
.tst-mask-library {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(104px, 1fr));
    gap: 8px;
    max-height: 60vh;
    overflow: auto;
}
.tst-mask-cell {
    display: flex;
    flex-direction: column;
    gap: 4px;
    align-items: center;
    padding: 6px;
    border: 1px solid var(--tst-border);
    border-radius: 6px;
}
.tst-mask-cell:hover { border-color: var(--uk-accent, var(--accent)); }
.tst-mask-cell img {
    width: 88px;
    height: 88px;
    image-rendering: pixelated;
    background: var(--surface-sunken, var(--surface-1));
    border-radius: 4px;
    cursor: pointer;
}
.tst-mask-cell--unreadable img { opacity: 0.3; }
.tst-mask-cell__name {
    max-width: 88px;
    font-size: var(--uk-font-size-sm);
    color: var(--tst-text-2);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}


/* ============================================================
   56. Map Browser dialog (customUI/MapBrowserDialog)
   Was an inline <style> in the dialog template; relocated here.
   ============================================================ */

.mbd-root { display: flex; flex-direction: column; height: 100%; min-height: 0; color: var(--text-1); }
.mbd-header { display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid var(--glass-divider); padding: 6px 10px; gap: 8px; flex: 0 0 auto; }
.mbd-header__title { display: flex; gap: 8px; align-items: center; font-weight: 600; }
.mbd-header__count { color: var(--text-3); font-size: 12px; }
.mbd-wrap { display: grid; grid-template-columns: 300px 1fr; flex: 1; min-height: 0; }
.mbd-side { border-right: 1px solid var(--glass-divider); display: flex; flex-direction: column; min-height: 0; background: var(--glass-sunken); }
.mbd-main { display: flex; flex-direction: column; min-height: 0; overflow: hidden; }
.mbd-root .side-top { padding: 8px; border-bottom: 1px solid var(--glass-divider); display: flex; flex-direction: column; gap: 8px; flex: 0 0 auto; }
.mbd-filters { display: flex; gap: 6px; flex-wrap: wrap; }
.mbd-root .tags { display: flex; flex-wrap: wrap; gap: 6px; max-height: 80px; overflow: auto; }
.mbd-root .tag { border: 1px solid var(--border-base); border-radius: var(--radius-full); padding: 2px 8px; font-size: 11px; color: var(--text-2); cursor: pointer; user-select: none; }
.mbd-root .tag.active { background: var(--accent-muted); color: var(--accent); border-color: var(--accent-border); }
.mbd-root .side-toolbar { padding: 6px 8px; border-bottom: 1px solid var(--glass-divider); display: flex; justify-content: space-between; align-items: center; gap: 6px; color: var(--text-3); font-size: 11px; flex: 0 0 auto; }
.mbd-root .side-list { position: relative; overflow: auto; flex: 1; min-height: 0; }
.mbd-root .vl-spacer { position: relative; width: 100%; }
.mbd-row { position: absolute; left: 4px; right: 4px; height: 28px; line-height: 28px; padding: 0 8px; border-radius: var(--radius-base); cursor: pointer; display: flex; justify-content: space-between; align-items: center; gap: 6px; }
.mbd-row:hover { background: var(--accent-muted); }
.mbd-row.active { background: var(--accent-muted); box-shadow: inset 2px 0 0 var(--accent); }
.mbd-row > span:first-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mbd-root .text-mono { font-family: var(--font-family-mono, ui-monospace, monospace); font-size: 12px; }
.mbd-badge { font-size: 10px; border: 1px solid var(--glass-border); border-radius: var(--radius-full); padding: 0 6px; color: var(--text-3); flex: 0 0 auto; }
.mbd-insp { position: relative; display: flex; flex-direction: column; min-height: 0; height: 100%; }
.mbd-insp__head { display: flex; align-items: center; gap: 8px; padding: 8px 12px; border-bottom: 1px solid var(--glass-divider); flex: 0 0 auto; }
.mbd-insp__name { font-weight: 600; font-size: 0.95rem; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mbd-insp__actions { display: flex; gap: 6px; flex: 0 0 auto; }
.mbd-insp .ui-tabs { flex: 1; min-height: 0; }
.mbd-insp .ui-tabs__panels { overflow: auto; min-height: 0; flex: 1; }
.mbd-loader {
    position: absolute; inset: 0; z-index: 10; display: none;
    background: var(--glass-raised); backdrop-filter: blur(2px);
    align-items: center; justify-content: center;
}
.mbd-loader__box {
    display: flex; flex-direction: column; align-items: center; gap: 12px;
    background: var(--surface-raised); padding: 20px; border-radius: var(--radius-lg);
    border: 1px solid var(--glass-border); box-shadow: var(--glass-shadow);
    text-align: center; min-width: 200px;
}
.mbd-loader__msg { font-weight: 600; font-size: 13px; }
.mbd-loader__files {
    display: flex; flex-direction: column; gap: 4px; width: 100%;
    font-family: var(--font-family-mono); font-size: 11px; color: var(--text-3);
}
.mbd-loader__file {
    padding: 2px 8px; background: var(--surface-sunken); border-radius: 4px;
    border: 1px solid var(--glass-border);
}
.mbd-minimap { width: 240px; height: 240px; max-width: 100%; border: 1px solid var(--glass-border); border-radius: var(--radius-md); background: var(--surface-sunken); display: flex; align-items: center; justify-content: center; overflow: hidden; color: var(--text-3); font-size: 12px; }
.mbd-minimap img, .mbd-minimap canvas { max-width: 100%; max-height: 100%; }
.mbd-kv { display: grid; grid-template-columns: max-content 1fr; gap: 5px 16px; align-items: baseline; margin: 0 0 4px; }
.mbd-kv dt { color: var(--text-3); font-size: 12px; }
.mbd-kv dd { margin: 0; font-size: 12px; font-variant-numeric: tabular-nums; word-break: break-word; }
.mbd-sec { margin-top: 14px; }
.mbd-sec__title { display: flex; align-items: center; gap: 8px; font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-3); margin: 0 0 8px; }
.mbd-counts { display: flex; gap: 6px; margin-bottom: 10px; flex-wrap: wrap; }
.mbd-empty { color: var(--text-3); font-size: 12px; padding: 8px 0; }


/* ============================================================
   57. Toolbar (UKToolbar / UKToolbarGroup / UKToolbarButton)
   ============================================================ */

.ui-toolbar { display: flex; align-items: center; gap: 6px; }
.ui-toolbar--vertical { flex-direction: column; align-items: stretch; }
.ui-toolbar__group {
    display: inline-flex; align-items: center; gap: 2px;
    padding: 2px; border-radius: var(--uk-radius-md, 8px);
    background: color-mix(in srgb, var(--uk-surface-2) 60%, transparent);
    border: 1px solid var(--uk-glass-border, var(--uk-border));
}
.ui-toolbar--vertical .ui-toolbar__group { flex-direction: column; align-items: stretch; }
.ui-toolbar__group-label {
    font-size: 9px; text-transform: uppercase; letter-spacing: 0.05em;
    color: var(--uk-text-3); padding: 0 4px; align-self: center;
}
.ui-toolbar__spacer { flex: 1 1 auto; }
.ui-toolbar__sep { flex: 0 0 auto; align-self: stretch; background: var(--uk-glass-border, var(--uk-border)); }
.ui-toolbar--horizontal .ui-toolbar__sep { width: 1px; margin: 4px 4px; }
.ui-toolbar--vertical .ui-toolbar__sep { height: 1px; margin: 4px 4px; }

/* Floating glass rail (over-canvas, dynamic per edit mode) */
.ui-toolbar--glass {
    padding: 4px 1px; 
    border-radius: var(--uk-radius-lg, 12px);
    background: var(--uk-glass-raised, var(--surface-1));
    border: 1px solid var(--uk-glass-border, var(--uk-border));
    box-shadow: var(--uk-glass-shadow, var(--shadow-lg));
    backdrop-filter: var(--uk-glass-blur, none);
    gap: 4px;
}
.ui-toolbar--glass .ui-toolbar__group { background: transparent; border: none; padding: 0; }

/* Toolbar button — larger, icon over optional label, corner shortcut badge */
.ui-tbtn {
    position: relative;
    display: inline-flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 2px; box-sizing: border-box;
    min-width: 40px; min-height: 40px;
    /* padding: 6px 8px; */
    border: 1px solid transparent; border-radius: var(--uk-radius-md, 8px);
    background: transparent; color: var(--uk-text-1);
    cursor: pointer; font: inherit; line-height: 1;
    transition: background .12s ease, border-color .12s ease, color .12s ease;
}
.ui-tbtn--sm { min-width: 32px; min-height: 32px; padding: 4px 6px; }
.ui-tbtn--lg { min-width: 52px; min-height: 52px; padding: 8px 10px; }
.ui-tbtn:hover { background: color-mix(in srgb, var(--uk-accent) 12%, transparent); }
.ui-tbtn:active { background: color-mix(in srgb, var(--uk-accent) 20%, transparent); }
.ui-tbtn:focus-visible { outline: 2px solid var(--uk-accent); outline-offset: 1px; }
.ui-tbtn.is-active {
    background: var(--uk-accent);
    color: var(--uk-accent-text);
    border-color: var(--uk-accent-border);
}
.ui-tbtn:disabled { opacity: 0.4; cursor: not-allowed; }
.ui-tbtn__icon { font-size: 16px; line-height: 1; pointer-events: none; }
.ui-tbtn--lg .ui-tbtn__icon { font-size: 20px; }
.ui-tbtn--sm .ui-tbtn__icon { font-size: 14px; }
.ui-tbtn__label { font-size: 10px; color: inherit; opacity: 0.9; pointer-events: none; white-space: nowrap; }
.ui-tbtn__sc {
    position: absolute; right: 3px; bottom: 2px;
    font-size: 8px; font-weight: 700; line-height: 1;
    padding: 1px 3px; border-radius: 3px;
    /* Same dangling token as above: color-mix() over an undefined custom property is
       invalid, so the shortcut badge was drawing with no backing at all. */
    background: color-mix(in srgb, var(--uk-surface-2) 80%, transparent);
    color: var(--uk-text-3); pointer-events: none;
    font-variant-numeric: tabular-nums;
}
.ui-tbtn.is-active .ui-tbtn__sc { background: rgba(0,0,0,0.28); color: rgba(255,255,255,0.85); }

.viewport-toolbar {
    box-sizing: border-box;
    width: 100%;
    height: 100%;
    min-height: 0;
    align-items: stretch;
    gap: 0;
    padding: 0;
    background: var(--surface-2);
    border-bottom: 1px solid var(--border-base);
}
.viewport-toolbar .ui-toolbar__group,
.viewport-toolbar .uk-dropdown,
.viewport-toolbar .ui-toolbar__subgroup {
    /* align-items: stretch; */
    align-self: stretch;
    padding: 0;
    /* gap: 0; */
    border-radius: 0;
    background: transparent;
    border: none;
}
.viewport-toolbar .ui-tbtn,
.viewport-toolbar .ui-tbtn--sm,
.viewport-toolbar .ui-tbtn--lg {
    align-self: stretch;
    height: auto;
    min-height: 0;
    min-width: 2.5rem;
    border-radius: 0;
    transform: none;
}
.viewport-toolbar .ui-tbtn:hover,
.viewport-toolbar .ui-tbtn:active {
    background: var(--uk-accent);
    color: var(--uk-accent-text);
    transform: none;
}
.viewport-toolbar .ui-tbtn.is-active:hover {
    background: var(--uk-accent-hover);
}

/* Grouped/flyout tool button (Photoshop-style tool groups) */
.ui-tbtn-flyout { position: relative; }
.ui-tbtn-flyout__caret {
    position: absolute; right: 1px; bottom: 1px; width: 0; height: 0;
    border-left: 5px solid transparent; border-bottom: 5px solid var(--uk-text-3);
    pointer-events: none; opacity: 0.85;
}
.ui-tbtn-flyout__pop {
    position: absolute; left: calc(100% + 6px); top: 0; z-index: 20;
    display: flex; gap: 4px; padding: 6px;
    background: var(--uk-glass-raised, var(--surface-1));
    border: 1px solid var(--uk-glass-border, var(--uk-border));
    border-radius: var(--uk-radius-lg, 12px);
    box-shadow: var(--uk-glass-shadow, var(--shadow-lg));
}
.ui-toolbar--vertical .ui-tbtn-flyout__pop { flex-direction: row; }

/* ============================================================
   58. ModeActionRail (floating per-mode rail over the canvas)
   ============================================================ */

.mode-rail {
    position: absolute;
    /* Sits clear of the outliner: its live width comes from ModeActionRail via
       --mode-rail-anchor, and the collapsed rule below drops the offset to 0.
       The extra 28px clears the outliner's protruding toggle tab. */
    --mode-rail-anchor: 220px;
    left: calc(var(--mode-rail-anchor) + 28px);
    /* Anchored near the top of the canvas (below the viewport toolbar), growing
       downward — NOT vertically centered. */
    top: 16px;
    z-index: 900;
    pointer-events: none;               /* only the rail itself is interactive */
    max-height: calc(100% - 32px);
    display: flex;
    transition: left 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

/* Outliner collapsed → only its toggle tab remains on screen. */
.outliner-overlay.collapsed ~ .mode-rail {
    left: 28px;
}
.mode-rail > .ui-toolbar { pointer-events: auto; overflow-x: visible; }

/* The mode-identity header reads as a caption, not a pressable button. */
.mode-rail__title { cursor: default; opacity: 1; }
.mode-rail__title:hover { background: transparent; }
.mode-rail__title:disabled { opacity: 1; cursor: default; }
.mode-rail__title .ui-tbtn__icon { color: var(--uk-accent); font-size: 18px; }
.mode-rail__title .ui-tbtn__label { font-weight: 600; opacity: 1; }
.mode-rail__title .ui-tbtn__sc {
    background: transparent; color: var(--uk-text-3);
    right: 2px; bottom: 1px;
}

/* ============================================================
   59. Concept Art Studio (.cas-*)
   ============================================================ */

.cas-root {
    /* Alias the design tokens once so every rule below is theme-agnostic. */
    --cas-gap: 12px;
    --cas-card: 168px;
    --cas-surface: var(--uk-glass-sunken, var(--surface-1));
    --cas-border: var(--keyline);
    --cas-text-2: var(--text-2);

    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
    position: relative;
}

.cas-root > .ui-tabs {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
}
.cas-root > .ui-tabs > .ui-tabs__panels { flex: 1 1 auto; min-height: 0; }
.cas-root .ui-tabs__panel--active { height: 100%; min-height: 0; }

.cas-status {
    flex: 0 0 auto;
    padding: 4px 10px;
    font-size: 0.78rem;
    color: var(--cas-text-2);
    border-top: 1px solid var(--cas-border);
    min-height: 22px;
}

/* Two-column panel: a fixed settings rail plus a scrolling gallery. */
.cas-panel {
    display: grid;
    grid-template-columns: minmax(220px, 300px) 1fr;
    gap: var(--cas-gap);
    height: 100%;
    min-height: 0;
    padding: var(--cas-gap);
}
@media (max-width: 900px) {
    .cas-panel { grid-template-columns: 1fr; }
}

.cas-side {
    display: flex;
    flex-direction: column;
    gap: 8px;
    min-height: 0;
    overflow-y: auto;
    padding-right: 4px;
    border-right: 1px solid var(--cas-border);
}
.cas-side-head {
    margin-top: 10px;
    padding-top: 8px;
    border-top: 1px solid var(--cas-border);
    font-size: 0.78rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--cas-text-2);
}

.cas-main {
    display: flex;
    flex-direction: column;
    gap: var(--cas-gap);
    min-height: 0;
    overflow-y: auto;
}

.cas-row { display: flex; gap: 8px; align-items: flex-end; flex-wrap: wrap; }

.cas-section-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    flex-wrap: wrap;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--text-1);
    border-bottom: 1px solid var(--cas-border);
    padding-bottom: 6px;
}

.cas-rows { display: flex; flex-direction: column; gap: var(--cas-gap); }
.cas-item-row { display: flex; flex-direction: column; gap: 6px; }
.cas-item-head {
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--cas-text-2);
    text-transform: capitalize;
}

.cas-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(var(--cas-card), 1fr));
    gap: var(--cas-gap);
}
.cas-grid--single { grid-template-columns: minmax(var(--cas-card), 320px); }

.cas-empty {
    grid-column: 1 / -1;
    padding: 18px;
    text-align: center;
    font-size: 0.82rem;
    color: var(--cas-text-2);
    border: 1px dashed var(--cas-border);
    border-radius: var(--radius-md, 6px);
}

/* ── card ─────────────────────────────────────────────────── */

.cas-card {
    display: flex;
    flex-direction: column;
    background: var(--cas-surface);
    border: 1px solid var(--cas-border);
    border-radius: var(--radius-md, 6px);
    overflow: hidden;
    transition: border-color var(--motion-fast, 120ms) ease;
}
.cas-card:hover { border-color: var(--accent); }
.cas-card--busy { opacity: 0.6; }

.cas-card__figure {
    position: relative;
    aspect-ratio: 1 / 1;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--surface-0, #111);
}
.cas-card__figure--clickable { cursor: zoom-in; }
.cas-card__img { width: 100%; height: 100%; object-fit: contain; display: block; }
.cas-card__empty { color: var(--text-3); font-size: 1.4rem; }
.cas-card__spinner {
    position: absolute;
    inset: auto 0 0 0;
    padding: 3px 6px;
    font-size: 0.7rem;
    text-align: center;
    background: var(--tint-accent-bg, rgba(0, 0, 0, 0.5));
    color: var(--tint-accent-fg, #fff);
    display: none;
}
.cas-card--busy .cas-card__spinner { display: block; }

.cas-card__badge {
    position: absolute;
    top: 6px;
    right: 6px;
    padding: 1px 7px;
    border-radius: 999px;
    font-size: 0.68rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    background: var(--tint-accent-bg);
    color: var(--tint-accent-fg);
    border: 1px solid var(--tint-accent-bd);
}
.cas-card__badge[data-tone="ok"] {
    background: var(--tint-success-bg); color: var(--tint-success-fg); border-color: var(--tint-success-bd);
}
.cas-card__badge[data-tone="warn"] {
    background: var(--tint-signal-bg); color: var(--tint-signal-fg); border-color: var(--tint-signal-bd);
}
.cas-card__badge[data-tone="error"] {
    background: var(--tint-danger-bg); color: var(--tint-danger-fg); border-color: var(--tint-danger-bd);
}

.cas-card__body {
    display: flex;
    align-items: flex-start;
    gap: 6px;
    padding: 6px 8px 2px;
    min-width: 0;
}
.cas-card__check { flex: 0 0 auto; margin: 2px 0 0; }
.cas-card__text { min-width: 0; display: flex; flex-direction: column; }
.cas-card__title {
    font-size: 0.8rem;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.cas-card__sub {
    font-size: 0.72rem;
    color: var(--cas-text-2);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.cas-card__actions {
    display: flex;
    gap: 4px;
    padding: 2px 8px 8px;
    flex-wrap: wrap;
}
.cas-card__actions:empty { display: none; }


/* ============================================================
   60. Settings > Shortcuts (per-category grouped grid)
   ============================================================ */

.sc-settings { padding: var(--uk-gap-md); }
.sc-settings__empty { padding: var(--uk-gap-lg) 0; text-align: center; color: var(--uk-text-3); }
.sc-settings__footer { margin-top: var(--uk-gap-md); padding-top: var(--uk-gap-sm); border-top: 1px solid var(--uk-border-light); }

.sc-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0 var(--uk-gap-lg); }
.sc-group-hdr {
    grid-column: 1 / -1;
    font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em;
    color: var(--uk-text-3); margin: var(--uk-gap-md) 0 var(--uk-gap-xs);
}
.sc-group-hdr:first-child { margin-top: 0; }

.sc-row {
    display: flex; align-items: center; justify-content: space-between; gap: var(--uk-gap-sm);
    padding: 6px 2px; border-bottom: 1px solid var(--uk-border-light); overflow-x: auto;
}
.sc-row__name { font-size: 11.5px; color: var(--uk-text-1); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sc-row__name small { display: block; font-size: 9.5px; font-weight: 400; color: var(--uk-text-3); }
.sc-row__ctrl { display: flex; align-items: center; gap: var(--uk-gap-xs); flex-shrink: 0; }

.sc-key {
    font-family: var(--uk-font-mono, monospace); font-size: 10.5px; color: var(--uk-text-1);
    background: var(--uk-surface-2); border: 1px solid var(--uk-border-light);
    border-radius: var(--uk-input-radius); padding: 2px 8px; cursor: pointer;
}
.sc-key:hover { border-color: var(--uk-accent); }
.sc-key--armed { border-color: var(--uk-accent); color: var(--uk-accent); animation: sc-key-pulse 1s ease-in-out infinite; }
@keyframes sc-key-pulse { 50% { opacity: 0.5; } }

.sc-reset { background: transparent; border: none; color: var(--uk-text-3); cursor: pointer; padding: 2px 4px; }
.sc-reset:hover { color: var(--uk-text-1); }

@media (max-width: 560px) {
    .sc-grid { grid-template-columns: 1fr; }
}

/* ============================================================
   61. AI Map Wizard (customUI/AIMapCreate) — .sw-*
   Was StagedMapWizardStyles.js, injected at runtime from a template
   literal (which is why that file could not contain a backtick).
   ============================================================ */

/* The wizard's floating host: the shell fills it and scrolls its own panes. */
.sw-window .ui-window__content {
    padding: 0;
    overflow: hidden;
    display: flex;
    min-height: 0;
}

/* `flex: 1; min-width: 0` because the content box above is a ROW flex container: without
   a grow factor the shell is `flex: 0 1 auto` and sizes to max-content, which left ~58px
   of dead space beside it at 1600x900 (and clipped, since the content box hides overflow). */
.sw-shell {
  display: flex;
  flex: 1;
  min-width: 0;
  height: 100%;
  position: relative;
  color: var(--uk-text-1);
  font-size: 0.8125rem;
}
.sw-main {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
  position: relative;
  padding: var(--uk-gap-md);
  gap: var(--uk-gap);
}
.sw-panel {
  flex: 1;
  min-height: 0;
  overflow: hidden;
}
.sw-foot {
  display: flex;
  flex-direction: column;
  gap: var(--uk-gap-sm);
  border-top: 1px solid var(--uk-border-light);
  padding-top: var(--uk-gap-sm);
}
.sw-foot-row {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: var(--uk-gap-sm);
}
/* The rail row: steps take the space, run-wide tools sit at the end behind a hairline. */
.sw-foot-rail {
  display: flex;
  align-items: stretch;
  gap: var(--uk-gap);
  min-width: 0;
}
/* Tools that belong to the WHOLE run, not to the current step — they live outside
   `.sw-panel`, so a step swap never takes them away. */
.sw-foot-tools {
  display: flex;
  align-items: center;
  gap: var(--uk-gap-xs);
  flex: 0 0 auto;
  padding-left: var(--uk-gap);
  border-left: 1px solid var(--uk-border-light);
}
/* An outdated report is still worth reading, so this is a caution, not an error: amber is
   this app's "armed / does not match what is saved" signal. `--signal-hover` rather than
   `--tint-signal-fg` so it tracks the light theme — see the note in the shaping-rail block. */
.sw-foot-tools .ui-btn.is-stale:not(:disabled) {
  color: var(--signal-hover);
}
/* The shared UKStepper is a vertical left rail by default; lay it out as a
   horizontal strip when it lives in the footer. */
.sw-foot .ui-stepper {
  width: auto;
  /* `flex: 1` here, not a utility class in JS: this rule out-specifies a single class,
     so the utility would silently lose and the steps would size to content. */
  flex: 1;
  min-width: 0;
  flex-direction: row;
  align-items: center;
  background: transparent;
  border-right: none;
  padding: 0;
  overflow: visible;
}
.sw-foot .ui-stepper__toggle { display: none; }
.sw-foot .ui-stepper__list {
  flex-direction: row;
  flex: 1;
  flex-wrap: wrap;
}
.sw-foot .ui-stepper__step { width: auto; flex: 1; }
.sw-status {
  flex: 1;
  font-size: 0.75rem;
  color: var(--uk-text-2);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  user-select: text;
}
.sw-magnifier-lens {
  position: fixed;
  z-index: 4000;
  width: 170px;
  height: 170px;
  border-radius: var(--uk-radius-sm);
  border: 2px solid rgba(255, 255, 255, 0.75);
  box-shadow: 0 6px 22px rgba(0, 0, 0, 0.55);
  pointer-events: none;
  background-repeat: no-repeat;
  display: none;
}
.sw-magnifier-lens--tex {
  border-radius: var(--uk-radius);
  image-rendering: pixelated;
}
.sw-magnifier-lens--tilegrid {
  border-radius: var(--uk-radius);
  image-rendering: pixelated;
}.sw-canvas {
  width: 100%;
  flex: 1;
  min-height: 200px;
  display: block;
  background: var(--uk-surface-0);
  border: 1px solid var(--uk-border-light);
  border-radius: var(--uk-radius-md);
}
.sw-canvas--tall { min-height: 38vh; flex: 1; }
/* Zones step: preview fills the main column; concept art floats top-right as reference */
.sw-zones-preview-wrap {
  position: relative;
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}/* ── Terrain step · DEAD height-correction chrome ───────────────────────────────
   Unreachable since the Topography view became the relief editor: nothing builds
   .sw-hm-frame / .sw-hm-img / .sw-hm-handle-layer any more. Kept with the rest of the
   Height Correction subsystem, which comes out in one piece.
   Fills the main column: a centred heightmap that scales to the space, drag handles
   pinned to it, and the height-correction panel underneath. The FRAME shrink-wraps the
   image rather than stretching to the column, because .sw-hm-handle-layer covers the
   frame edge-to-edge (inset 0) — any letterboxing inside the frame would offset every
   drag handle from the pixels it edits. */
.sw-topo-edit-wrap {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: var(--uk-gap-sm);
}
.sw-hm-stage {
  flex: 1;
  min-height: 120px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: auto;
  padding: var(--uk-gap-xs);
  border: 1px solid var(--uk-border-light);
  border-radius: var(--uk-radius-md);
  background: var(--uk-surface-0);
}
/* inline-block + a max-constrained image => the frame is exactly the image's box,
   which is what makes the absolutely-positioned handle layer line up with it. */
.sw-hm-frame {
  position: relative;
  display: inline-block;
  flex: 0 1 auto;
  max-width: 100%;
  line-height: 0;
}
/* The correction panel moved to the reference rail, so the stage owns the whole main
   column and the image can use it. `width/height: auto` under the two maxes keeps the
   aspect ratio, which is what lets `.sw-hm-frame` shrink-wrap it — and the shrink-wrap is
   what keeps the drag handles on the pixels they edit, so neither may become a definite
   size.

   `--hm-max-height` is measured from the stage by `_syncHeightmapStageHeight` (with a
   ResizeObserver keeping it current). The `60vh` fallback is what this used to be on its
   own, and it is why the drag handles disappeared when the window got SHORTER: vh tracks
   the window, but the toolbar above the stage is a fixed height, so the stage's share of
   the window shrinks faster than 60vh does. The image outgrew the stage, the stage
   scrolled, and the bottom handles scrolled out of sight. The measurement makes the cap
   the room that actually exists; `overflow: auto` stays as the safety net. */
.sw-hm-img {
  display: block;
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: var(--hm-max-height, 60vh);
  border-radius: var(--uk-radius-sm);
}
.sw-hm-empty {
  display: none;
  padding: 0 var(--uk-gap);
  text-align: center;
  font-size: var(--uk-font-size-sm);
  color: var(--uk-text-3);
}

/* ── Terrain step · Relief editor ───────────────────────────────────────────────
   The Topography view's workspace (reliefEditor.js): the relief on a canvas, its point
   prompts pinned over it, an adjustment list in the rail.

   The CANVAS is the image's own pixel size and is scaled down by CSS — the same reason
   .sw-hm-frame shrink-wraps its image. Click coordinates are read from
   getBoundingClientRect and normalised, so the scale is never assumed anywhere; but the
   point MARKERS are positioned in %, so the frame must be exactly the canvas's box or
   they would sit off the pixels they mark. `--topo-max-height` is measured from the stage
   by _syncTopographyStageHeight. */
.sw-re-stage {
  flex: 1;
  min-height: 120px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: auto;
  padding: var(--uk-gap-xs);
  border: 1px solid var(--uk-border-light);
  border-radius: var(--uk-radius-md);
  background: var(--uk-surface-0);
}
.sw-re-frame {
  position: relative;
  display: inline-block;
  flex: 0 1 auto;
  max-width: 100%;
  line-height: 0;
}
.sw-re-canvas {
  display: block;
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: var(--topo-max-height, 60vh);
  border-radius: var(--uk-radius-sm);
  /* A relief is a height field, not a photograph: smoothing it on the way to the screen
     hides exactly the single-pixel noise the Denoise op exists to remove. */
  image-rendering: pixelated;
}
.sw-re-frame.is-picking .sw-re-canvas { cursor: crosshair; }
.sw-re-points {
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.sw-re-point {
  position: absolute;
  width: 10px;
  height: 10px;
  margin: -5px 0 0 -5px;
  border-radius: 50%;
  background: var(--uk-accent);
  border: 2px solid var(--uk-surface-0);
  box-shadow: 0 0 0 1px var(--uk-accent);
}
.sw-re-point.is-exclude {
  background: var(--uk-danger);
  box-shadow: 0 0 0 1px var(--uk-danger);
}
.sw-re-empty {
  display: none;
  padding: 0 var(--uk-gap);
  text-align: center;
  font-size: var(--uk-font-size-sm);
  color: var(--uk-text-3);
}
.sw-re-stage.is-empty .sw-re-frame { display: none; }
.sw-re-stage.is-empty .sw-re-empty { display: block; }

.sw-re-actions {
  display: flex;
  align-items: center;
  gap: var(--uk-gap-sm);
  flex-wrap: wrap;
}
.sw-re-list { display: flex; flex-direction: column; gap: 2px; }
.sw-re-list:empty { display: none; }
.sw-re-row {
  display: flex;
  align-items: center;
  gap: var(--uk-gap-xs);
  padding: 2px var(--uk-gap-xs);
  border: 1px solid transparent;
  border-radius: var(--uk-radius-sm);
  cursor: pointer;
  font-size: var(--uk-font-size-sm);
}
.sw-re-row:hover { background: var(--uk-surface-2); }
.sw-re-row.is-selected {
  border-color: var(--uk-accent);
  background: var(--uk-surface-2);
}
.sw-re-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sw-re-badge {
  flex: none;
  font-size: var(--uk-font-size-xs);
  color: var(--uk-text-3);
}
.sw-re-eye,
.sw-re-del {
  flex: none;
  border: 0;
  background: none;
  padding: 0 2px;
  cursor: pointer;
  color: var(--uk-text-2);
  font-size: var(--uk-font-size-sm);
  line-height: 1;
}
.sw-re-eye:hover,
.sw-re-del:hover { color: var(--uk-text-1); }
.sw-re-controls:empty { display: none; }
/* The flat-area census, under the adjustment list: how much of the relief a ceiling, a
   posterise or a clipped Brightness has pinned flat, plus the sheer-riser warning. */
.sw-re-readout {
  margin: 0;
  font-size: var(--uk-font-size-xs);
  color: var(--uk-text-3);
}
.sw-re-segrow { display: flex; gap: var(--uk-gap-sm); flex-wrap: wrap; }
/* Terrain-step main preview host: a bar + a body holding the main slot and a
   reference panel (reused .sw-concept-thumb-overlay chrome) that swaps contents by
   view ('relief' shows the concept there; 'topography'/'image' park the live 3D canvas
   there so it stays visible as a reference while editing in the main slot). */
.sw-terrain-preview-host {
  position: relative;
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}
.sw-terrain-preview-body {
  position: relative;
  flex: 1;
  min-height: 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
}
.sw-terrain-preview-main {
  flex: 1;
  min-height: 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
}
.sw-terrain-overlay-body {
  width: 100%;
  height: 100%;
}
/* Editor views (Heightmap / Concept Edit): the main slot is a form, not a scene, so
   the floating chrome is DOCKED — the view switch becomes a real toolbar row and the
   reference thumb a right-hand rail. Floating them covered the paint tools and the
   art being painted, and ate the clicks aimed at them. */
.sw-terrain-preview-host--edit { gap: var(--uk-gap-sm); }
.sw-terrain-preview-host--edit > .sw-preview-overlay-bar {
  position: static;
  align-self: stretch;
  flex-wrap: wrap;
  gap: var(--uk-gap);
  background: var(--uk-surface-2);
  box-shadow: none;
}
.sw-terrain-preview-host--edit > .sw-terrain-preview-body {
  flex-direction: row;
  align-items: stretch;
  gap: var(--uk-gap-sm);
}
/* Slot for the active view's own tools, right of the view switch and behind a hairline
   so "which view" and "what it can do" stay legibly separate. Empty in Relief. */
.sw-view-tools {
  display: flex;
  align-items: center;
  gap: var(--uk-gap);
  min-width: 0;
  flex-wrap: wrap;
  /* Takes the rest of the bar when at least ~320px of it is free — otherwise wraps to a
     line of its own rather than being squeezed. Without a grow factor the brush settings
     stacked three-high against a shrink-to-fit width; without the 320px basis they were
     crushed into the leftovers of a narrow window and spilled over the shaping rail. */
  flex: 1 1 320px;
}
.sw-view-tools:empty { display: none; }
/* Any overlay bar, not just the Terrain step's docked one: the hairline is what keeps
   "what you're looking at" and "what you can do to it" legibly separate. */
.sw-preview-overlay-bar > .sw-view-tools:not(:empty) {
  padding-left: var(--uk-gap);
  border-left: 1px solid var(--uk-border-light);
}
/* A toggle in the bar is a compact control, not a form row: its label wrapping under the
   switch made a 20px control 36px tall and pushed the bar out of line. */
.sw-preview-overlay-bar .ui-toggle__label { white-space: nowrap; }
/* The reference column. `display: contents` in Relief so the thumbnail keeps floating
   over the scene — it is absolutely positioned against `.sw-terrain-preview-body`, which
   stays its containing block whether or not this wrapper generates a box. */
.sw-terrain-side { display: contents; }
.sw-terrain-preview-host--edit .sw-terrain-side {
  display: flex;
  flex-direction: column;
  gap: var(--uk-gap-sm);
  flex: 0 0 216px;
  width: 216px;
  min-height: 0;
}
/* "relative", not "static": .sw-concept-thumb-label is absolutely positioned inside
   this box, and unpositioning it would let the label escape to the body wrapper. */
/* `top: auto` is load-bearing: this box is `position: relative` here, so the offset the
   floating case uses to clear the bar would push it down inside the rail instead. */
.sw-terrain-preview-host--edit .sw-concept-thumb-overlay {
  position: relative;
  top: auto;
  flex: 0 0 162px;
  width: 100%;
  height: 162px;
  box-shadow: none;
}
/* In the EDITOR views this box holds the live 3D terrain, and it is the only place the
   terrain is visible while you work — so it takes the pointer and OrbitControls (already
   bound to that canvas) gives it orbit, pan and zoom. Scoped to `--edit` on purpose: in
   Relief this same overlay floats OVER the scene as a reference thumbnail, where taking
   the pointer would swallow the drags aimed at the terrain behind it. That is what the
   base rule's `pointer-events: none` is for, and it stays. */
.sw-terrain-preview-host--edit .sw-concept-thumb-overlay { pointer-events: auto; }
/* The caption is a label, not a handle — it sits over the top of the canvas and would
   otherwise eat every drag that started on it. */
.sw-terrain-preview-host--edit .sw-concept-thumb-label { pointer-events: none; }
/* The active view's tools, under the terrain they shape. Never scrolls: a tool that
   scrolls out of a 216px rail is a tool you cannot find. */
.sw-terrain-tools {
  flex: 0 0 auto;
  min-width: 0;
}
.sw-terrain-tools:empty { display: none; }
/* The active view's context (the heightmap's correction layers). Takes the rest of the
   rail and scrolls itself — layers accumulate without bound. */
.sw-terrain-ctx {
  flex: 1;
  min-height: 0;
  overflow-x: hidden;
  overflow-y: auto;
}
.sw-terrain-ctx:empty { display: none; }
/* When the 3D canvas is parked in the reference panel (Heightmap/Concept-Edit views)
   it must fill that box instead of the tall min-height it uses as the main preview. */
.sw-concept-thumb-overlay .sw-canvas {
  width: 100%;
  height: 100%;
  min-height: 0;
  flex: none;
  display: block;
}
/* ── Terrain step · Concept Edit (inpaint) view ────────────────────────────────
   Stage on top, action bar under it. The tools dock in the view toolbar and the history
   sits in the reference rail — both mounted there by `_setTerrainView`, not here. The
   230px scrolling paint rail this replaced took a quarter of the panel and still could
   not show its own contents without scrolling. */
.sw-inpaint-wrap {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: var(--uk-gap-sm);
}
/* The paint stage takes the free vertical space and centres the (aspect-preserved)
   concept; InpaintCanvas stretches its layers over the image box, so they stay aligned.
   `--inpaint-max-height` is the ONLY safe size lever here — the <img> is the layout
   element, and giving this box an explicit height is what desynced the mask from the art.
   The value below is just a first-paint fallback: `_syncInpaintStageHeight()` measures the
   free space and writes the real px cap, because a viewport-relative guess cannot know how
   many lines the docked toolbar took, and when it guessed high the art overflowed a
   `visible` box and painted straight over the action bar. */
.sw-inpaint-stage {
  flex: 1;
  min-height: 0;
  justify-content: center;
  --inpaint-max-height: 40vh;
}
/* The inpaint canvas' stage wrapper: img + paint canvas + cursor overlay share one box.
   No transform — the concept is north-up and so is the terrain it builds. */
.sw-inpaint-stage-inner {
  position: relative;
}
/* Action bar — the stage's one verb, directly under what it acts on. */
.sw-inpaint-act {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: var(--uk-gap-xs);
  padding: var(--uk-gap-sm);
  border: 1px solid var(--uk-border-light);
  border-radius: var(--uk-radius-md);
  background: var(--uk-surface-1);
}
.sw-inpaint-act__label {
  display: flex;
  align-items: center;
  gap: var(--uk-gap-xs);
  font-size: var(--uk-font-size-sm);
  font-weight: 600;
  color: var(--uk-text-2);
}
.sw-inpaint-act__row {
  display: flex;
  align-items: center;
  gap: var(--uk-gap);
  flex-wrap: wrap;
}
/* `1 1 190px`: shares the row with the button when there is room, wraps to its own line
   when there is not — rather than collapsing to an invisible slider. The track needs
   `min-width: 0` for the same reason as the brush settings: a range input will not shrink
   past its UA intrinsic width while `min-width: auto` applies. */
.sw-inpaint-act__strength {
  flex: 1 1 190px;
  min-width: 0;
  margin-bottom: 0;
}
.sw-inpaint-act__strength .ui-range__track { min-width: 0; }
/* ── Paint tools, docked in the view toolbar ──
   Two stacked rows, always: tools, then the brush settings that modify them. Letting the
   two share a line when they happen to fit squeezed the settings until their labels
   collided with their own readouts. */
.sw-paint-tools {
  display: flex;
  flex-direction: column;
  /* `stretch`, not `flex-start`: shrink-to-fit rows would take their max-content width
     and then wrap internally against THAT, stacking three settings that fit side by side. */
  align-items: stretch;
  gap: var(--uk-gap-xs);
  min-width: 0;
  flex: 1;
}
/* Every row in the bar wraps: a toolbar that cannot wrap overflows its column, and this
   one sits beside the shaping rail with nothing to clip it. */
.sw-paint-tools__row { display: flex; align-items: center; gap: var(--uk-gap-sm); flex-wrap: wrap; }
.sw-paint-tools__hist { display: flex; align-items: center; gap: 2px; }
/* Glyph-only tool buttons: square, so the five read as one instrument strip. */
.sw-paint-tools .ui-btn-group__item {
  min-width: 26px;
  padding-left: 4px;
  padding-right: 4px;
}
/* Brush settings, shown only for the freehand tools. Each is a label + a short slider;
   they are secondary to the tool choice, so they are set smaller and quieter. */
.sw-paint-tools__brush { display: flex; align-items: center; gap: var(--uk-gap); flex-wrap: wrap; }
.sw-paint-tools__brush[hidden] { display: none; }
/* `width: auto` because `.ui-field` is `width: 100%` for stacked forms — left alone, each
   setting takes the whole row and the three stack instead of sitting side by side.
   `flex: 0 0 auto` then wraps them at a narrow window rather than compressing a slider
   until its label runs into its own readout. */
.sw-paint-tools__field {
  width: auto;
  flex: 0 0 auto;
  margin-bottom: 0;
  gap: var(--uk-gap-xs);
  align-items: center;
}
/* `.ui-field--row` reserves a 90px label column so stacked form rows line up. Nothing
   lines up in a toolbar strip, and here that column is just a gap between each label and
   the slider it names — so the label shrinks to its text. */
.sw-paint-tools__field > .ui-field__label {
  min-width: 0;
  font-size: var(--uk-font-size-xs);
  color: var(--uk-text-3);
  white-space: nowrap;
}
.sw-paint-tools__field > .ui-range { width: 104px; flex: 0 0 104px; }
/* In the 216px reference rail the tools are a COLUMN, not a bar: each brush setting takes
   the full width so its slider gets the whole rail instead of the 104px it takes when it
   is sharing a toolbar line with two others. The tool glyphs still wrap on their own. */
.sw-terrain-tools .sw-paint-tools { flex: none; }
.sw-terrain-tools .sw-paint-tools__brush {
  flex-direction: column;
  align-items: stretch;
  gap: var(--uk-gap-xs);
}
.sw-terrain-tools .sw-paint-tools__field { width: 100%; }
.sw-terrain-tools .sw-paint-tools__field > .ui-range { width: auto; flex: 1 1 auto; }
/* An <input type=range> has a UA intrinsic width around 130px, and a flex item's default
   `min-width: auto` will not shrink below that — so the track ignored the box above,
   overflowed it, and painted its own readout across the NEXT setting's label. */
.sw-paint-tools__field .ui-range__track { min-width: 0; }
/* ── Concept versions, between the art and the prompt ──
   A horizontal filmstrip directly under the stage: these are alternatives to the picture
   above them, so they read left-to-right against it.

   This block used to describe a vertical column in the 216px reference rail. The column
   had the room, but it cropped every thumbnail to a 100×84 box with `object-fit: cover` —
   and telling two edits of one image apart is the ONLY thing a version thumbnail is for,
   so cropping 40% away made the whole strip useless. Now the thumb is smaller and shows
   the WHOLE image, with a hover lens (`_attachLens`, `single`) carrying the detail a 56px
   square never could. */
.sw-concept-hist-row {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: var(--uk-gap-sm);
  min-width: 0;
}
/* Nothing to caption until there is a version to click. */
.sw-concept-hist-row:has(> .sw-concept-history:empty) { display: none; }
.sw-concept-hist-row__label {
  flex: 0 0 auto;
  font-size: var(--uk-font-size-xs);
  color: var(--uk-text-3);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
/* `nowrap` + its own horizontal scroll. The strip is capped at 12 entries; letting it
   wrap to a second line would silently eat height that `_syncInpaintStageHeight` has
   already handed to the art above. */
.sw-concept-history {
  flex: 1 1 auto;
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  gap: var(--uk-gap-sm);
  min-width: 0;
  overflow-x: auto;
  overflow-y: hidden;
  padding: 2px;
}
.sw-concept-history:empty { display: none; }
.sw-concept-hist {
  position: relative;
  flex: 0 0 auto;
  width: 56px;
  height: 56px;
  padding: 0;
  border: 2px solid var(--uk-border-light);
  border-radius: var(--uk-radius-sm);
  background: var(--uk-surface-0);
  cursor: pointer;
  overflow: hidden;
}
.sw-concept-hist:hover { border-color: var(--uk-accent, #4c9aff); }
.sw-concept-hist.is-active { border-color: var(--uk-accent, #4c9aff); box-shadow: 0 0 0 1px var(--uk-accent, #4c9aff); }
/* `contain`, never `cover`: a cropped version thumbnail cannot be compared with the one
   beside it, which is the entire point of the strip. */
.sw-concept-hist img { width: 100%; height: 100%; object-fit: contain; display: block; }
.sw-concept-hist__n {
  position: absolute;
  left: 0;
  bottom: 0;
  padding: 1px 4px;
  font-size: 0.625rem;
  font-weight: 600;
  color: #fff;
  background: rgba(0, 0, 0, 0.6);
  border-top-right-radius: var(--uk-radius-sm);
}
.sw-tex-preview-wrap {
  position: relative;
  flex: 1;
  min-height: 0;
  display: flex;
}
/* width MUST be 100% (never auto): the preview renderer writes the canvas's
   layout size back into its width/height attributes every frame, and with
   width:auto the attribute (intrinsic size) feeds back into flex layout —
   the canvas oversizes past the wrap and, at fractional devicePixelRatio,
   grows ~1px/frame forever (terrain off-center + constant rightward drift). */
.sw-tex-preview-wrap .sw-canvas {
  flex: 1;
  width: 100%;
  min-width: 0;
  min-height: 0;
}
.sw-concept-thumb-overlay {
  position: absolute;
  /* Clear the floating overlay bar rather than sharing its band. Both are absolutely
     positioned over the same scene — bar top-left, thumb top-right — so on a narrow enough
     preview they collide; measured at 1280 wide, the Terrain bar ran 12px under the thumb
     once it gained a second toggle. The bar is z-index 3 to the thumb's 2, so the controls
     stayed usable and it was the thumbnail that got clipped, but two independent floating
     boxes that can overlap at all is a latent bug. Starting below the bar's band (its height
     plus a gap) removes it at every width. */
  top: calc(var(--uk-gap-sm) + 38px);
  right: var(--uk-gap-sm);
  width: auto;
  height: 180px;
  z-index: 2;
  pointer-events: none;
  border: 2px solid var(--uk-border-light);
  border-radius: var(--uk-radius-md);
  overflow: hidden;
  box-shadow: 0 4px 18px rgba(0, 0, 0, 0.5);
  background: var(--uk-surface-0);
}
.sw-concept-thumb-overlay--hidden { display: none; }
.sw-concept-thumb-overlay img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.sw-concept-thumb-label {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 2px var(--uk-gap-xs);
  font-size: 0.625rem;
  font-weight: 600;
  text-align: center;
  color: #fff;
  background: linear-gradient(transparent, rgba(0, 0, 0, 0.72));
  letter-spacing: 0.02em;
}
.sw-scroll-list {
  display: flex;
  flex-direction: column;
  gap: var(--uk-gap-sm);
  flex: 1;
  min-height: 80px;
  overflow: auto;
  overflow-x: hidden;
  padding: 2px 4px 2px 0;
}
/* Every stage group built by `stageSections.js::section()` — despite the Props-flavoured
   name, which is what this bug came out of.

   The base used to be `min-height: 0`, needed by the ONE group that holds a scrolling list.
   But on a flex child `min-height: 0` removes the min-content floor, so EVERY other group
   became shrinkable by its siblings: at any height where the rail did not fit, groups were
   squashed below their content and their text overflowed onto the group beneath. The
   Textures and Props rails each restored the floor with their own `flex: 0 0 auto`; Water
   and Lights build their rail from a plain `.ui-form` and never did — both panels rendered
   with headings and notes overlapping.

   So the safe value is the base, and the one growing exception opts in (see
   `.sw-props-form > .sw-props-widget:has(...)`). */
.sw-props-widget { flex: 0 0 auto; }
/* Water step: the clickable pond grid — one cell per water zone, mirroring the map layout.
   It is the wizard's stand-in for clicking the terrain (which the editor's water mode does). */
/* Split: `[w] × [h]` on one line. A UKNumberInput takes the full width it is offered, so
   two of them plus the `×` overflowed the space left by `.ui-field--row`'s 90px label
   column and wrapped one per line. Fixed basis, not a width — `.ui-field--row > .ui-input`
   sets `flex: 1`, which grows past any width (the same trap the Props seed field hit). */
.sw-water-split { min-width: 0; }
.sw-water-split .ui-input,
.sw-water-split .ui-number-input { flex: 0 0 64px; width: 64px; min-width: 0; }
.sw-water-zone-grid {
  display: grid;
  gap: 2px;
  max-height: 180px;
  overflow: auto;
}
.sw-water-zone-cell {
  aspect-ratio: 1 / 1;
  min-width: 18px;
  min-height: 18px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.5625rem;
  font-family: var(--uk-font-mono, monospace);
  color: var(--uk-text-3);
  border: 1px solid var(--uk-border-light);
  border-radius: var(--uk-radius-sm);
  background: var(--uk-surface-2);
  cursor: pointer;
  overflow: hidden;
}
.sw-water-zone-cell:hover { border-color: var(--uk-accent); }
.sw-water-zone-cell.is-active {
  border-color: var(--uk-signal);
  background: var(--uk-tint-signal-bg, rgba(233, 161, 59, 0.18));
  color: var(--uk-text-1);
}
/* Lights step: native colour swatch, sized to sit on a UKField row like the other controls. */
.sw-color-input {
  width: 48px;
  height: 22px;
  padding: 0;
  border: 1px solid var(--uk-border-light);
  border-radius: var(--uk-radius-sm);
  background: transparent;
  cursor: pointer;
  flex: 0 0 auto;
}
.sw-geo-left { min-width: 0; overflow-x: hidden; overflow-y: auto;}
/* The Terrain step's rail: a scrolling body (settings, brief, the collapsed adjustment
   accordion) above a footer pinned to the bottom (view switch + draw/create actions), so
   the actions stay reachable regardless of which accordion groups are open. `.ui-split__side`
   already sets flex-column + min-height:0; this only overrides ITS OWN scrolling — the body
   and footer below scroll (or not) independently instead. `.sw-geo-left` alone (every other
   step's rail) keeps `.ui-split__side`'s scrolling untouched, since it has no footer to pin. */
.sw-terrain-rail { overflow-y: hidden; }
.sw-terrain-rail__body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
}
.sw-terrain-rail__footer {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: var(--uk-gap-sm);
  padding-top: var(--uk-gap-sm);
  border-top: 1px solid var(--keyline);
}
.sw-terrain-view-switch { align-self: stretch; }
.sw-terrain-view-switch .ui-btn { flex: 1; }
.sw-terrain-settings { padding-bottom: var(--uk-gap-md); }
.sw-terrain-settings__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: end;
  gap: var(--uk-gap-sm);
}
.sw-terrain-settings__lock[aria-pressed="true"] { color: var(--accent); }
.sw-terrain-settings__grid .ui-field { margin-bottom: 0; min-width: 0; }
.sw-terrain-brief-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--uk-gap-sm);
}
.sw-terrain-brief-grid .ui-field {
  margin-bottom: 0;
  min-width: 0;
  gap: var(--uk-gap-xs);
}
.sw-terrain-brief-grid .ui-field__label {
  font-size: var(--uk-font-size-xs);
}
.sw-brief-hint {
  font-size: 11px;
  color: var(--uk-text-2, #9aa0a6);
  line-height: 1.4;
  margin-top: calc(-1 * var(--uk-gap-xs));
  margin-bottom: var(--uk-gap-sm);
}
.sw-brief-hint:empty { display: none; }
.sw-terrain-actions {
    display: flex;
    flex-direction: column;
    gap: var(--uk-gap);
    margin-bottom: 1em;
}
.sw-terrain-actions__row {
  display: grid;
  gap: var(--uk-gap-xs);
  align-items: stretch;
}
.sw-terrain-actions__row--draw {
  grid-template-columns: 1fr auto;
}
.sw-terrain-actions__row--draw .ui-btn { min-height: 34px; }
.sw-terrain-actions__draw { font-weight: 600; }
.sw-terrain-actions__row--draw > .ui-btn:not(.sw-terrain-actions__draw) {
  aspect-ratio: 1 / 1;
  padding-left: 0.5rem;
  padding-right: 0.5rem;
}
.sw-terrain-actions__row--secondary {
  grid-template-columns: 1fr;
}
.sw-terrain-actions__row--secondary .ui-btn { font-size: var(--uk-font-size-sm); min-height: 34px; }
@media (max-width: 360px) {
  .sw-terrain-brief-grid { grid-template-columns: 1fr; }
}
/* ── Terrain step · shaping rail ────────────────────────────────────────────────
   Four titled groups, each reading its own state back. `display: grid` is stated here
   rather than via a `ui-form` class in JS so one element carries one layout declaration;
   `.ui-split__side` (§30) sets column-flex, and this overrides it on source order.

   There used to be a `margin-top: 22px` here "to clear the floating view-switch bar".
   That bar is `position: absolute` inside `.sw-terrain-preview-host`, i.e. inside
   `.ui-split__main`, so it can never reach this column — the margin cleared nothing and
   was simply why the rail started 22px below the preview it sits beside. */
.sw-geo-right {
  width: 300px;
  flex: 0 0 300px;
  display: grid;
  grid-auto-rows: max-content;
  align-content: start;
  background-color: var(--uk-surface-0);
  padding: var(--uk-gap);
  border: 1px solid var(--uk-border-light);
  border-radius: var(--uk-radius-md);
  gap: var(--uk-gap-md);
}
.sw-shape-group { display: flex; flex-direction: column; gap: var(--uk-gap-sm); }
/* Eyebrow: name, live summary, and a reset that only exists once it has work to do. */
.sw-shape-group__head {
  display: flex;
  align-items: baseline;
  gap: var(--uk-gap-sm);
  padding-bottom: 3px;
  border-bottom: 1px solid var(--uk-border-light);
}
.sw-shape-group__name {
  font-size: var(--uk-font-size-xs);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--uk-text-2);
  flex: 0 0 auto;
}
.sw-shape-group__summary {
  flex: 1;
  min-width: 0;
  text-align: right;
  font-family: var(--font-family-data, monospace);
  font-size: var(--uk-font-size-xs);
  color: var(--uk-text-3);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Amber = this app's "armed / differs from what is saved" signal. A group that shapes
   the terrain is exactly that: a departure from the generated heightmap.

   `--signal*` directly, NOT the `--tint-signal-*` aliases: those are declared once on
   `:root`, so they resolve against the DARK palette and stay there, while `--signal` and
   `--signal-hover` are redeclared under `body.theme-light`. Mixing the two would have the
   dot follow the theme while the summary beside it did not. */
.sw-shape-group.is-active .sw-shape-group__name { color: var(--signal-hover); }
.sw-shape-group.is-active .sw-shape-group__summary { color: var(--signal-hover); }
.sw-shape-group.is-active .sw-shape-group__head {
  border-bottom-color: color-mix(in srgb, var(--signal) 45%, transparent);
}
/* The reset button IS the state dot: an amber pip when the group is off neutral, nothing
   at all when it is neutral, so the rail stays quiet until it has news. The button itself
   is the dot — an inner pseudo-element stretched to the button's content box instead of
   holding its own 7px square. */
.sw-shape-group__reset.ui-btn {
  flex: 0 0 auto;
  width: 8px;
  min-width: 8px;
  height: 8px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: var(--signal);
  align-self: center;
  visibility: hidden;
  transition: transform var(--uk-dur-fast), box-shadow var(--uk-dur-fast);
}
.sw-shape-group.is-active .sw-shape-group__reset.ui-btn { visibility: visible; }
.sw-shape-group__reset.ui-btn:hover {
  background: var(--signal-hover);
  transform: scale(1.35);
  box-shadow: 0 0 0 3px var(--signal-muted);
}
.sw-shape-group__reset.ui-btn:focus-visible { box-shadow: var(--uk-focus-ring); }
/* Two columns: selects pair up, ranges take the full width. A half-column range is
   unusable — `.ui-range__value` reserves 32px for its readout, leaving barely any track. */
.sw-shape-group__body {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--uk-gap-sm) var(--uk-gap-sm);
}
.sw-shape-cell,
.sw-shape-cell--wide { margin-bottom: 0; min-width: 0; }
.sw-shape-cell--wide { grid-column: 1 / -1; }
/* Rail footer: how far this terrain has been pushed from what the model generated. */
.sw-shape-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--uk-gap-sm);
  padding-top: var(--uk-gap-sm);
  border-top: 1px solid var(--uk-border-light);
}
.sw-shape-foot__count {
  font-size: var(--uk-font-size-xs);
  color: var(--uk-text-3);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}.sw-hm-variant {
  flex: 1 1 0;
  min-width: 0;
  aspect-ratio: 1 / 1;
  padding: 0;
  cursor: pointer;
  overflow: hidden;
  border-radius: var(--uk-radius-md);
  border: 2px solid var(--uk-border-light);
  background: var(--uk-surface-0);
}
.sw-hm-variant img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.sw-hm-variant.is-selected {
  border-color: var(--uk-accent, #5b8def);
  box-shadow: 0 0 0 1px var(--uk-accent, #5b8def);
}
/* Height-correction stack (Terrain step; DEAD — see above). It lives in the reference rail
   now; its +Linear/+Radial/Bake/Clear row docks in the view toolbar instead. It used to
   be a COLLAPSED <details> under the image, which hid the whole feature behind a
   disclosure triangle most users never opened. */
.sw-hm-correct {
  border: 1px solid var(--uk-border-light);
  border-radius: var(--uk-radius-md);
  background: var(--uk-surface-1);
}
.sw-hm-correct.is-disabled { opacity: 0.5; pointer-events: none; }
.sw-hm-correct__actions { display: flex; align-items: center; gap: var(--uk-gap-sm); flex-wrap: wrap; }
.sw-hm-correct__actions.is-disabled { opacity: 0.5; pointer-events: none; }
.sw-hm-correct__body { padding: var(--uk-gap-sm); }
/* Shared eyebrow for the two rail panels (correction layers, concept versions). */
.sw-rail-title {
  font-size: var(--uk-font-size-xs);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--uk-text-2);
}
/* An always-visible list has to say something when it is empty. */
.sw-rail-empty {
  margin: 0;
  font-size: var(--uk-font-size-xs);
  line-height: 1.45;
  color: var(--uk-text-3);
}
.sw-rail-empty[hidden] { display: none; }
.sw-hm-correct__list { display: flex; flex-direction: column; gap: 2px; }
.sw-hm-correct__list:empty { display: none; }
.sw-hm-correct__row {
  display: flex;
  gap: 0.25rem;
  align-items: center;
  padding: 2px 4px;
  border: 1px solid transparent;
  border-radius: var(--uk-radius-sm);
  background: var(--uk-surface-0);
}
.sw-hm-correct__row.is-selected { border-color: var(--uk-accent); }
.sw-hm-correct__row > button {
  padding: 0;
  border: none;
  border-radius: var(--uk-radius-sm);
  background: transparent;
  color: var(--uk-text-3);
  cursor: pointer;
  line-height: 1;
}
.sw-hm-correct__row > button:not(.sw-hm-correct__label) {
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
}
.sw-hm-correct__row > button:hover { color: var(--uk-text-1); background: var(--uk-surface-2); }
.sw-hm-correct__label {
  flex: 1;
  min-width: 0;
  text-align: left;
  padding: 2px 4px;
  font-size: var(--uk-font-size-sm);
  color: var(--uk-text-2);
}
.sw-hm-correct__row.is-selected .sw-hm-correct__label { color: var(--uk-text-1); font-weight: 600; }
.sw-hm-correct__controls {
  margin-top: var(--uk-gap-sm);
  padding-top: var(--uk-gap-sm);
  border-top: 1px solid var(--uk-border-light);
}
.sw-hm-correct__controls[hidden] { display: none; }
.sw-hm-correct__controls .ui-field { margin-bottom: 0; }
.sw-hm-handle-layer { position: absolute; inset: 0; pointer-events: none; }
.sw-hm-handle-layer.is-active { pointer-events: auto; }
/* box-sizing matters: the -6px margins only centre the handle on its (u,v) point when
   the 2px border is INSIDE the 12px box — content-box put every handle 2px off. */
.sw-hm-handle {
  position: absolute; box-sizing: border-box;
  width: 14px; height: 14px; margin: -7px 0 0 -7px;
  border-radius: 50%; background: #fff; border: 2px solid #222; cursor: grab;
  pointer-events: auto;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.6);
}
.sw-hm-handle:hover { border-color: var(--uk-accent); }
.sw-hm-handle:active { cursor: grabbing; }
.sw-legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--uk-gap-xs);
  font-size: 0.6875rem;
  color: var(--uk-text-3);
}
.sw-legend-item {
  display: flex;
  align-items: center;
  gap: 4px;
}
/* ── Textures stage: tab system ──────────────────────────────────── */
.sw-tex-side {
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: 0;
  overflow: hidden;
  padding: var(--uk-gap-sm);
  border-right: 1px solid var(--uk-border-light);
}.sw-tex-main {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
  padding: var(--uk-gap-sm);
  gap: var(--uk-gap-sm);
}/* ── "Load ▾" source menu (Terrain / Textures / Props) ───────────── */
.sw-load-menu { position: relative; display: inline-block; }
.sw-load-menu-items {
  position: absolute;
  z-index: 50;
  top: calc(100% + 2px);
  left: 0;
  min-width: 150px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 4px;
  border-radius: var(--uk-radius, 6px);
  background: var(--uk-surface-2, #1b1f27);
  border: 1px solid var(--uk-border-light);
  box-shadow: 0 6px 18px rgba(0,0,0,0.45);
}
/* Preview canvas in the unified Textures step — the track now lives in the left panel,
   so the preview gets the whole right column. */
.sw-canvas--preview { min-height: 46vh; flex: 1; }
/* Floating interactive toolbar over a 3D preview (Textures: Zones/Grid/Build), distinct
   from the reference-only .sw-concept-thumb-overlay which stays pointer-events: none. */
.sw-preview-overlay-bar {
  position: absolute;
  top: var(--uk-gap-sm);
  left: var(--uk-gap-sm);
  z-index: 3;
  display: flex;
  align-items: center;
  gap: var(--uk-gap-lg);
  padding: 4px 6px;
  border-radius: var(--uk-radius-md);
  background: rgba(0, 0, 0, 0.55);
  border: 1px solid var(--uk-border-light);
  box-shadow: 0 4px 18px rgba(0, 0, 0, 0.45);
  pointer-events: auto;
}
/* ── Compact segmentation row (left panel top) ── */
.sw-seg-row {
  display: flex;
  align-items: center;
  gap: var(--uk-gap-sm);
  flex-wrap: wrap;
}
/* `width: auto` on the fields because `.ui-field` is `width: 100%` — left alone, each
   control takes the whole row and Max / Method / Segment stack three-high. */
.sw-seg-row .ui-field { margin: 0; width: auto; }
.sw-seg-row .ui-field--row > .ui-field__label { min-width: 0; }
.sw-seg-row .ui-input[type="number"] { width: 52px; }
.sw-seg-row .ui-select { min-width: 0; }

/* ── Textures step · the numbered Generate sequence ──────────────────────────────
   Steps 2 and 3 blend the tiles step 1 makes, so this is an ORDER, not three peer
   buttons — which is what it used to be drawn as. Numbering earns its place here
   (contrast the Terrain shaping rail, where the groups are not a sequence and are
   deliberately unnumbered). */
/* The rail's groups state their own height; only the track absorbs the slack. That is now
   the base `.sw-props-widget` rule for every stage — this used to be one of the two local
   restatements of it, which is exactly why Water and Lights (which have no such rail block)
   went without and overlapped. */
.sw-gen-steps {
  display: flex;
  flex-direction: column;
  flex: 0 0 auto;
  border: 1px solid var(--uk-border-light);
  border-radius: var(--uk-radius-md);
  overflow: hidden;
}
.sw-gen-step {
  display: flex;
  align-items: center;
  gap: var(--uk-gap-sm);
  padding: var(--uk-gap-sm);
  background: var(--uk-surface-1);
}
.sw-gen-step + .sw-gen-step { border-top: 1px solid var(--uk-border-light); }
/* The step index — a numeral, so it reads as position in a sequence. It becomes a tick
   once that step has produced something. */
.sw-gen-step__n {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 1px solid var(--uk-border-light);
  background: var(--uk-surface-0);
  color: var(--uk-text-3);
  font-size: var(--uk-font-size-xs);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.sw-gen-step.is-done .sw-gen-step__n {
  background: var(--status-success, var(--uk-success));
  border-color: transparent;
  color: #fff;
  font-size: 0;
}
.sw-gen-step.is-done .sw-gen-step__n::after { content: '✓'; font-size: 0.6875rem; }
.sw-gen-step__body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.sw-gen-step__title {
  font-size: var(--uk-font-size);
  font-weight: 600;
  color: var(--uk-text-1);
}
/* What the step makes, and then what it has actually made — the second answers
   "did that work?" without opening the track. */
.sw-gen-step__what,
.sw-gen-step__state {
  font-size: var(--uk-font-size-xs);
  color: var(--uk-text-3);
  line-height: 1.35;
}
.sw-gen-step__state:empty { display: none; }
.sw-gen-step.is-done .sw-gen-step__state { color: var(--status-success, var(--uk-success)); }
/* Blocked = its input does not exist yet. Stated on the step, rather than left for a
   failed run to explain. */
.sw-gen-step.is-blocked { opacity: 0.6; }
.sw-gen-step.is-blocked .sw-gen-step__state { color: var(--uk-text-3); font-style: italic; }
.sw-gen-step > .ui-btn { flex: 0 0 auto; }
/* ── Texture track (unified Textures step — VERTICAL, per-zone rows, left panel) ── */
.sw-track {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  gap: 4px;
  overflow-y: auto;
  overflow-x: hidden;
  padding: var(--uk-gap-sm) 2px;
  border-top: 1px solid var(--uk-border-light);
  min-height: 0;
}
/* One zone = one CARD: a header line [colour dot][name][actions] over a wrapping tile row.
   Two lines rather than one because the actions and the tiles are both fixed-width: on one
   line the zone NAME was the only thing that could give, so it collapsed to its 40px minimum
   and wrapped while the tiles ran off the right edge into the track's `overflow-x: hidden`. */
.sw-track-zone {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 4px 2px 6px;
  border-bottom: 1px solid var(--uk-border-light);
}
.sw-track-zonehead {
  display: flex; align-items: center; gap: 6px; min-width: 0;
}
.sw-track-actions { display: flex; gap: 3px; flex: 0 0 auto; margin-left: auto; }
.sw-track-icon-btn {
  width: 32px; height: 32px;
  flex: 0 0 32px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--uk-radius-sm);
  border: 1px solid var(--uk-border-light);
  background: var(--uk-surface-1);
  color: var(--uk-text-2);
  cursor: pointer;
  transition: color var(--uk-motion-fast, 120ms) ease, border-color var(--uk-motion-fast, 120ms) ease;
}
.sw-track-icon-btn:hover:not(:disabled) { color: var(--uk-accent); border-color: var(--uk-accent); }
.sw-track-icon-btn:disabled { opacity: 0.4; cursor: default; }
.sw-track-zonename {
	flex: 1 1 auto; min-width: 0; display: flex; align-items: baseline; gap: 6px;
	font-size: 0.75rem; color: var(--uk-text-1);
	overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
.sw-track-zonename > .sw-track-hint { overflow: hidden; text-overflow: ellipsis; }
/* The zone's colour in the Zones overlay, so a row and the terrain it names read as the same
   thing. `--swatch` is set from `zoneColorHex`, which is what the 3D overlay uses too. */
.sw-track-swatch {
	flex: 0 0 auto; width: 10px; height: 10px; border-radius: 2px;
	background: var(--swatch, var(--uk-text-3));
	box-shadow: 0 0 0 1px var(--uk-glass-border, rgba(0, 0, 0, 0.35)) inset;
}
/* Add-track row (always last of the zone rows). */
.sw-track-add {
  display: flex; align-items: center; gap: 6px;
  padding: 3px 2px;
}
.sw-track-add-label { font-size: 0.6875rem; color: var(--uk-text-2); }
/* Transitions section (below the zone rows). */
.sw-track-trans { display: flex; flex-direction: column; gap: 4px; padding-top: 4px; }
.sw-track-head { display: flex; align-items: center; gap: 4px; }
.sw-track-title {
  font-size: 0.6875rem; font-weight: 600; color: var(--uk-text-2);
  white-space: nowrap; max-width: 168px; overflow: hidden; text-overflow: ellipsis;
}
.sw-track-row { display: flex; flex-direction: row; gap: 6px; }
.sw-track-row--wrap { flex-wrap: wrap; }
.sw-track-cell { display: flex; flex-direction: column; align-items: center; gap: 2px; }
.sw-track-thumb {
  width: 32px; height: 32px;
  border-radius: var(--uk-radius-sm);
  background-size: cover; background-position: center; background-repeat: no-repeat;
  background-color: var(--uk-surface-0);
  border: 1px solid var(--uk-border-light);
}
.sw-track-thumb--menu { cursor: context-menu; }
.sw-track-thumb--menu:hover { border-color: var(--uk-accent); }
.sw-track-thumb--empty {
  background-image: repeating-linear-gradient(45deg, var(--uk-surface-2) 0 4px, transparent 4px 8px);
  opacity: 0.6;
}
/* An empty base slot invites a left-click to set its prompt + generate. */
.sw-track-thumb--clickable { cursor: pointer; }
.sw-track-thumb--clickable:hover { border-color: var(--uk-accent); opacity: 0.9; }
.sw-track-cap {
  font-size: 0.5625rem; color: var(--uk-text-3);
  max-width: 44px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.sw-track-hint { font-size: 0.625rem; color: var(--uk-text-3); align-self: flex-start; white-space: nowrap; }
/* Single-region track keeps the old grouped layout (one block, wrapping thumbs). */
.sw-track-group { display: flex; flex-direction: column; gap: 4px; }
/* Active state for the "🖌 Paint zones" toggle. */
.sw-track .is-active,
.ui-btn.is-active { outline: 2px solid var(--uk-accent); outline-offset: 1px; }
/* Floating zone-paint toolbar over the Textures preview. */
.sw-zonepaint-bar {
  position: absolute;
  top: var(--uk-gap-sm);
  left: var(--uk-gap-sm);
  z-index: 3;
  display: flex;
  align-items: center;
  gap: var(--uk-gap-sm);
  padding: 6px 8px;
  border-radius: var(--uk-radius-md);
  background: var(--uk-surface-0);
  border: 1px solid var(--uk-border-light);
  box-shadow: 0 6px 22px rgba(0, 0, 0, 0.5);
}
.sw-zonepaint-bar .ui-field { margin: 0; }
.sw-zonepaint-bar .ui-range { width: 90px; }
/* ── Right-click context menu (per-tile actions) ── */
.sw-context-menu {
  position: fixed; z-index: 9999;
  min-width: 172px;
  padding: 4px;
  border-radius: var(--uk-radius-md);
  background: var(--uk-surface-0);
  border: 1px solid var(--uk-border-light);
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.5);
  display: flex; flex-direction: column;
}
.sw-context-menu__item {
  display: block; width: 100%; text-align: left;
  background: none; border: none;
  padding: 6px 10px; border-radius: var(--uk-radius-sm);
  font-size: 0.75rem; color: var(--uk-text-1); cursor: pointer;
}
.sw-context-menu__item:hover:not(:disabled) { background: var(--uk-surface-2); }
.sw-context-menu__item:disabled { color: var(--uk-text-3); cursor: default; }
/* ── Texture-set picker (save/load dialog) ── */
.sw-set-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
  gap: var(--uk-gap-sm);
  max-height: 52vh;
  overflow-y: auto;
}
.sw-set-card {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  padding: 6px; border-radius: var(--uk-radius-md);
  border: 1px solid var(--uk-border-light); background: var(--uk-surface-1);
  cursor: pointer;
}
.sw-set-card:hover { border-color: var(--uk-accent); }
.sw-set-thumb {
  width: 72px; height: 72px; border-radius: var(--uk-radius-sm);
  background-size: cover; background-position: center; background-color: var(--uk-surface-0);
  border: 1px solid var(--uk-border-light);
}
.sw-set-name {
  font-size: 0.6875rem; color: var(--uk-text-1);
  max-width: 84px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Props step: the rail's scrolling list (`data-props-groups`, set by propsPlanStage.js).
   Its rows are ordinary flex stacks; what a row contains is decided in the stage, not
   recovered from DOM order here. */
.sw-props-widget .sw-scroll-list[data-props-groups] {
  gap: var(--uk-gap-xs);
  min-height: 120px;
}
.sw-props-widget .sw-scroll-list[data-props-groups] > .ui-card {
  border-radius: var(--uk-radius-sm);
  background: var(--uk-surface-1);
  border-color: var(--uk-border-light);
  overflow: visible;
}
.sw-props-widget .sw-scroll-list[data-props-groups] > .ui-card:hover {
  border-color: var(--uk-border-strong, var(--uk-border-light));
}
.sw-props-widget .sw-scroll-list[data-props-groups] > .ui-card > .ui-card__body {
  display: flex;
  flex-direction: column;
  gap: var(--uk-gap-xs);
  padding: var(--uk-gap-sm);
}
.sw-props-widget .sw-scroll-list[data-props-groups] .ui-card .ui-input {
  min-width: 0;
  width: 5em;
  flex: 0 0 auto;
}
/* Groups hold their own height by default (base rule); the group LIST is the one that
   absorbs the rail's slack, and the only place `min-height: 0` is wanted — it scrolls. */
.sw-props-form > .sw-props-widget:has(> .sw-scroll-list[data-props-groups]) { flex: 1 1 auto; min-height: 0; }

/* The Props main column: preview above, element review below. Both halves need
   `min-height: 0` or the table's own scroll container never engages and the
   preview is pushed off the panel instead. */
.sw-props-main {
  display: flex; flex-direction: column; gap: var(--uk-gap-sm);
  flex: 1; min-height: 0; min-width: 0;
  /* The canvas carries a 200px floor and the review a max-height; without this the
     two together can exceed a short window and spill past the panel instead of the
     review giving up its share. */
  overflow: hidden;
}
.sw-props-main > .sw-zones-preview-wrap { flex: 1 1 auto; min-height: 0; }

.sw-props-review {
  /* `0 1 auto`, not `0 0 auto`: the review is the half that yields when the window
     is short — the preview is what the user is judging placement in. */
  flex: 0 1 auto;
  display: flex;
  flex-direction: column;
  gap: var(--uk-gap-xs);
  max-height: 42%;
  min-height: 0;
  overflow: hidden;
}
.sw-props-review__head { display: flex; align-items: baseline; gap: var(--uk-gap-sm); }
.sw-props-table-wrap {
  min-height: 0;
  border: 1px solid var(--uk-border-light);
  border-radius: var(--uk-radius-sm);
}
.sw-props-table { width: 100%; border-collapse: collapse; font-size: 0.7188rem; }
.sw-props-table th,
.sw-props-table td {
  text-align: left; padding: 4px 8px;
  border-bottom: 1px solid var(--uk-border-light);
  white-space: nowrap;
}
.sw-props-table th {
  position: sticky; top: 0; z-index: 1;
  background: var(--uk-surface-2); color: var(--uk-text-3); font-weight: 500;
}
.sw-props-table td.wrap { white-space: normal; max-width: 240px; }
.sw-props-seed { margin-bottom: 0; width: auto; }
.sw-props-seed > .ui-field__label { min-width: 0; }
.sw-props-seed > .ui-input { flex: 0 0 88px; width: 88px; }

/* ============================================================
   62. New Map dialog (customUI/NewMap) — .nm-*
   Five sources merged here: NEWMAP_CSS (injected via a singleton <style>)
   plus four <style> blocks that shipped inside the sub-modules' HTML
   template strings.
   ============================================================ */

/* Its floating host. */
.nm-window .ui-window__content {
    padding: 0;
    overflow: hidden;
    display: flex;
    min-height: 0;
}

/* `flex: 1; min-width: 0` — see the contract note above `.ui-window__content` (§13). */
.nm-window .nm-newmap-root {
    height: 100%;
    min-height: 0;
    display: flex;
    flex-direction: column;
    flex: 1;
    min-width: 0;
    gap: 10px;
    overflow: hidden;
    padding: 10px;
}
.nm-window .nm-grid {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
}
.nm-window .nm-main-row {
    flex: 1 1 auto;
    min-height: 0;
    display: grid;
    grid-template-columns: minmax(420px, 0.94fr) minmax(360px, 0.5fr);
    gap: 12px;
}
.nm-window .nm-left-col,
.nm-window .nm-right-col,
.nm-window .nm-preview-col,
.nm-window .nm-surface-card,
.nm-window .nm-panel-card,
.nm-window .nm-tabbed-panel,
.nm-window .nm-tab-content,
.nm-window .nm-tab-pane {
    min-height: 0;
}
.nm-window .nm-left-col,
.nm-window .nm-right-col {
    display: flex;
    flex-direction: column;
    gap: 12px;
}
.nm-window .nm-top-row {
    display: grid;
    grid-template-columns: minmax(280px, 0.9fr) minmax(320px, 1.1fr);
    gap: 12px;
}
.nm-window .nm-bottom-row,
.nm-window .nm-preview-col {
    flex: 1 1 auto;
    display: flex;
}
.nm-window .nm-surface-card,
.nm-window .nm-panel-card,
.nm-window .nm-tabbed-panel {
    border: 1px solid var(--keyline);
    border-radius: 12px;
    background:
        linear-gradient(180deg, var(--surface-2), var(--surface-1)),
        var(--surface-sunken);
    box-shadow: inset 0 1px 0 var(--surface-2);
}
.nm-window .nm-surface-card {
    padding: 10px;
}
.nm-window .nm-surface-title {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--text-2);
    margin-bottom: 8px;
}
.nm-window .nm-tabbed-panel {
    padding: 8px;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    height: 100%;
}
.nm-window .nm-tab-list {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
    margin-bottom: 8px;
}
.nm-window .nm-tab-btn {
    border: 1px solid var(--keyline);
    background: var(--surface-1);
    color: var(--text-2);
    border-radius: 999px;
    padding: 6px 11px;
    font-size: 11px;
    font-weight: 700;
    line-height: 1;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    cursor: pointer;
    transition: background-color .16s ease, border-color .16s ease, color .16s ease, transform .16s ease;
}
.nm-window .nm-tab-btn:hover {
    color: var(--text-1);
    border-color: var(--surface-4);
    background: var(--keyline);
}
.nm-window .nm-tab-btn.active {
    color: var(--text-1);
    border-color: var(--accent-border);
    background: linear-gradient(180deg, var(--accent-border), var(--accent-muted));
    box-shadow: inset 0 1px 0 var(--keyline);
}
.nm-window .nm-tab-content {
    flex: 1 1 auto;
    overflow: hidden;
}
.nm-window .nm-tab-pane {
    height: 100%;
    overflow: hidden;
}
.nm-window .nm-tab-pane.show.active {
    display: flex;
    flex-direction: column;
}
.nm-window #pane-worldmap,
.nm-window .nm-worldmap-widget {
    flex: 1 1 auto;
}
.nm-window .nm-muted {
    color: var(--text-3);
}
.nm-window .nm-basic-grid {
    display: grid;
    gap: 10px;
}
.nm-window .nm-field-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 8px;
}
.nm-window .nm-field {
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.nm-window .nm-field > label {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-2);
}
.nm-window .nm-check-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 10px;
    border: 1px solid var(--keyline);
    border-radius: 10px;
    background: var(--surface-1);
}
.nm-window .nm-preview-card {
    display: flex;
    flex-direction: column;
    min-height: 0;
    height: 100%;
    width: 100%;
    margin-bottom: 0 !important;
}
.nm-window .nm-preview-body {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 170px;
    gap: 10px;
    min-height: 0;
    flex: 1 1 auto;
}
.nm-window .nm-preview-canvas {
    min-height: 320px;
    height: 100%;
    width: 100%;
}
.nm-window .nm-preview-info {
    font-size: 10px;
    line-height: 1.45;
    color: var(--text-1);
}
@media (max-width: 1240px) {
    .nm-window .nm-main-row,
    .nm-window .nm-top-row,
    .nm-window .nm-preview-body {
        grid-template-columns: 1fr;
    }
    .nm-window .nm-preview-canvas {
        min-height: 280px;
    }
}
@media (max-width: 992px) {
    .nm-window .nm-newmap-root {
        overflow: auto;
    }
}

/* ── Texture ingest (NewMap.TextureIngest.js) ─────────────────────── */
          .nmti-drop { border:2px dashed var(--tint-success-bd); border-radius:10px; padding:14px; text-align:center; color:var(--tint-success-fg); cursor:pointer; font-size:12px; }
          .nmti-drop.drag { background:var(--tint-success-bg); border-color:var(--status-success); }
          .nmti-list { display:flex; flex-direction:column; gap:6px; margin-top:10px; }
          .nmti-row { display:flex; align-items:center; gap:8px; font-size:11px; background:var(--surface-1); border-radius:8px; padding:6px; }
          .nmti-thumb { width:40px; height:40px; border-radius:6px; object-fit:cover; background:var(--surface-sunken); flex:0 0 auto; }
          .nmti-row select { background:var(--surface-sunken); color:var(--text-1); border:1px solid var(--surface-3); border-radius:6px; font-size:11px; padding:2px 4px; }
          .nmti-name { flex:1 1 auto; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:var(--text-2); }
          .nmti-coverage { margin-top:10px; font-size:11px; color:var(--text-2); background:var(--accent-muted); border-left:3px solid var(--accent); border-radius:4px; padding:6px 8px; }
          .nmti-del { background:none; border:none; color:var(--status-danger); cursor:pointer; font-size:12px; }
        

/* ── Topography picker (NewMap.Topography.js) ─────────────────────── */
                    .nm-topo-widget .nm-terrain-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(120px,1fr));gap:8px}
                    .nm-topo-widget .nm-tcard{border:1px solid var(--keyline);border-radius:10px;overflow:hidden;cursor:pointer}
                    .nm-topo-widget .nm-tcard.selected{outline:2px solid var(--accent)}
                    .nm-topo-widget .nm-tcard svg{width:100%;height:56px;display:block;background:var(--surface-sunken)}
                    .nm-topo-widget .nm-tcard-label{font-size:11px;padding:4px 6px}
                    .nm-topo-widget .nm-essentials,.nm-topo-widget .nm-advanced label{display:flex;gap:8px;align-items:center;margin-top:8px}
                

/* ── Water widget (NewMap.Water.js) ─────────────────────── */
                    .nm-water-widget .nm-water-stack { display:flex; flex-direction:column; gap:10px; }
                    .nm-water-widget .nm-water-field { display:flex; flex-direction:column; gap:4px; }
                    .nm-water-widget .nm-water-field label { font-size:11px; text-transform:uppercase; letter-spacing:0.08em; color:var(--text-2); }
                    .nm-water-widget .nm-water-toggle { display:flex; align-items:center; gap:8px; padding:8px 10px; border:1px solid var(--keyline); border-radius:10px; background:var(--surface-1); }
                    .nm-water-widget .nm-water-preview-button { border:1px solid var(--keyline); border-radius:12px; background:var(--surface-1); padding:8px; display:flex; align-items:center; justify-content:space-between; gap:12px; width:100%; color:inherit; }
                    .nm-water-widget .nm-water-preview-media { width:108px; height:108px; border:1px solid var(--surface-3); border-radius:10px; overflow:hidden; background:var(--surface-sunken); display:flex; align-items:center; justify-content:center; flex-shrink:0; }
                    .nm-water-widget .nm-water-type-options { display:grid; grid-template-columns:repeat(2, minmax(0,1fr)); gap:8px; }
                    .nm-water-widget .nm-water-type-card { border:1px solid var(--keyline); border-radius:10px; background:var(--surface-1); padding:8px; display:flex; align-items:center; gap:10px; cursor:pointer; }
                    .nm-water-widget .nm-water-type-card.active { border-color:var(--accent-border); background:var(--accent-muted); }
                    .nm-water-widget .nm-water-type-card canvas { border-radius:8px; overflow:hidden; }
                    .nm-water-widget .nm-water-range-meta { display:flex; justify-content:space-between; font-size:10px; color:var(--text-3); }
                

/* ── Worldmap pipeline (NewMap.Worldmap.js) ─────────────────────── */
                    .nm-worldmap-widget {
                        display:flex;
                        flex-direction:column;
                        gap:10px;
                    }
                    .nm-worldmap-widget .wm-header {
                        display: grid;
                        grid-template-columns: minmax(0, 1fr) auto;
                        gap: 8px;
                        align-items: end;
                    }
                    .nm-worldmap-widget .wm-header-actions {
                        display: flex;
                        gap: 6px;
                    }
                    .nm-worldmap-widget .wm-progress-wrap {
                        margin-top: 8px;
                    }
                    .nm-worldmap-widget .wm-main-grid {
                        display: grid;
                        grid-template-columns: minmax(320px, 44%) minmax(0, 1fr);
                        gap: 10px;
                        min-height: 0;
                    }
                    .nm-worldmap-widget .wm-left,
                    .nm-worldmap-widget .wm-right {
                        min-height: 0;
                        display: flex;
                        flex-direction: column;
                        gap: 8px;
                    }
                    .nm-worldmap-widget .wm-source-canvas,
                    .nm-worldmap-widget .wm-tile-canvas {
                        width: 100%;
                        border: 1px solid var(--keyline);
                        background: radial-gradient(circle at top, var(--accent-muted), var(--surface-sunken));
                        border-radius: 12px;
                        display: block;
                    }
                    .nm-worldmap-widget .wm-source-canvas {
                        height: 320px;
                    }
                    .nm-worldmap-widget .wm-tile-canvas {
                        height: 340px;
                    }
                    .nm-worldmap-widget .wm-accordion-host {
                        min-height: 0;
                    }
                    .nm-worldmap-widget .wm-actions {
                        display: flex;
                        gap: 6px;
                        flex-wrap: wrap;
                    }
                    .nm-worldmap-widget .wm-actions .btn {
                        flex: 1 1 auto;
                    }
                    .nm-worldmap-widget .wm-panel-label {
                        font-size: 11px;
                        text-transform: uppercase;
                        letter-spacing: 0.08em;
                        color: var(--text-2);
                    }
                    @media (max-width: 1200px) {
                        .nm-worldmap-widget .wm-main-grid {
                            grid-template-columns: 1fr;
                        }
                        .nm-worldmap-widget .wm-source-canvas {
                            height: 260px;
                        }
                    }
                    @media (max-width: 720px) {
                        .nm-worldmap-widget .wm-header {
                            grid-template-columns: 1fr;
                        }
                        .nm-worldmap-widget .wm-header-actions {
                            justify-content: stretch;
                        }
                        .nm-worldmap-widget .wm-header-actions .btn {
                            flex: 1 1 auto;
                        }
                        .nm-worldmap-widget .wm-tile-canvas {
                            height: 260px;
                        }
                    }
                

/* The widget roots used to lean on Bootstrap's `.small` for their type scale. */
.nm-widget { font-size: 0.8125rem; }

/* ============================================================
   62b. Create New Map Dialog (CreateNewMapDialog.js)
   Simplified "Create a new map" dialog — flat GND, black texture.
   ============================================================ */
.cnm-window .cnm-root {
    padding: 16px;
    display: flex;
    flex-direction: column;
    height: 100%;
    gap: 16px;
    overflow: auto;
}

.cnm-window .cnm-grid {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.cnm-window .cnm-dims-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
}

.cnm-window .cnm-classifier-grid {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    gap: 12px;
}

@media (max-width: 768px) {
    .cnm-window .cnm-dims-grid {
        grid-template-columns: 1fr;
    }
    .cnm-window .cnm-classifier-grid {
        grid-template-columns: 1fr;
    }
}

/* ============================================================
   63. Viewport surface (UIViewPort)
   Was injected at runtime from UIViewPort.js.
   ============================================================ */
			.UIViewPort { position: relative; width: 100%; height: 100%; overflow: hidden; }
			.UIViewPort_Content { position: absolute; inset: 0; }
			.UIViewPort_Overlay { position: absolute; inset: 0; pointer-events: none; }
			.UIViewPort_Overlay > * { pointer-events: auto; }
		


/* ============================================================
   64. Media viewer (UIMediaViewer)
   Was injected at runtime from UIMediaViewer.js.
   ============================================================ */
			.UIMediaViewer { width: 100%; height: 100%; overflow: hidden; }
			.UIMediaViewer_Media { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; }
			.UIMediaViewer_Media img, .UIMediaViewer_Media video { max-width: 100%; max-height: 100%; }
			.UIMediaViewer_Media audio { width: 100%; }
		


/* ============================================================
   65. Search bar (UISearchBar)
   Was injected at runtime from UISearchBar.js.
   ============================================================ */
			.UISearchBar { display: flex; align-items: center; gap: 6px; padding: 4px 6px;
				border-radius: 6px; border: 1px solid var(--surface-3);
				background: var(--surface-sunken);
			}
			.UISearchBar_Icon { font-size: 12px; opacity: 0.7; }
			.UISearchBar_Input { flex: 1; min-width: 120px; background: transparent; border: 0;
				color: inherit; font-size: 12px; outline: none;
			}
			.UISearchBar_Button { padding: 4px 8px; border-radius: 4px; font-size: 12px;
				background: var(--keyline); border: 1px solid var(--surface-3);
				color: inherit;
			}
			.UISearchBar_Button:hover { background: var(--surface-3); }
			.UISearchBar.is-disabled { opacity: 0.6; pointer-events: none; }
		


/* ============================================================
   66. Toast stack (UIToast / UIToastManager)
   Was injected at runtime from UIToast.js.
   ============================================================ */
            .UIToastContainer {
                position: fixed;
                left: var(--uk-gap-lg);
                bottom: var(--uk-gap-lg);
                z-index: calc(var(--z-index-fixed) + 100);
                display: flex;
                flex-direction: column;
                gap: var(--uk-gap);
                align-items: flex-start;
                pointer-events: none;
            }
            .UIToast {
                width: min(360px, 92vw);
                pointer-events: auto;
                border-radius: var(--uk-radius-lg, 10px);
                overflow: hidden;
                background: rgba(30, 30, 35, 0.85);
                backdrop-filter: blur(12px) saturate(180%);
                -webkit-backdrop-filter: blur(12px) saturate(180%);
                border: 1px solid rgba(255, 255, 255, 0.12);
                border-left: 4px solid var(--status-info);
                box-shadow:
                    0 8px 32px rgba(0, 0, 0, 0.4),
                    0 2px 8px rgba(0, 0, 0, 0.2),
                    inset 0 1px 0 rgba(255, 255, 255, 0.1);
                transition: transform var(--dur-slow) var(--ease-standard), opacity var(--dur-slow);
                animation: toast-in-up var(--dur-slow) var(--ease-standard);
            }
            .UIToast--info { border-left-color: var(--status-info); }
            .UIToast--success { border-left-color: var(--status-success); }
            .UIToast--warn { border-left-color: var(--status-warning); }
            .UIToast--error { border-left-color: var(--status-danger); }
            @keyframes toast-in-left {
                from { transform: translateX(-20px) scale(0.98); opacity: 0; }
                to { transform: translateX(0) scale(1); opacity: 1; }
            }
            .UIToast {
                animation: toast-in-left var(--dur-slow) var(--ease-standard);
            }
            .UIToast--dismissing {
                transform: translateX(-20px) scale(0.98) !important;
                opacity: 0 !important;
                transition: transform var(--dur-fast), opacity var(--dur-fast);
            }
            .UIToast_Header {
                display: flex;
                align-items: center;
                justify-content: space-between;
                gap: var(--uk-gap-sm, 8px);
                padding: 8px 12px 0;
            }
            .UIToast_ButtonGroup {
                display: flex;
                align-items: center;
                gap: var(--uk-gap-xs, 4px);
            }
            .UIToast_Title {
                font-family: var(--font-family-mono);
                font-size: 0.7rem;
                font-weight: 600;
                text-transform: uppercase;
                letter-spacing: 0.06em;
                color: var(--text-2);
                line-height: 1;
            }
            .UIToast_Close, .UIToast_Copy {
                width: 24px;
                height: 24px;
                border-radius: 4px;
                background: rgba(255, 255, 255, 0.05);
                border: 1px solid rgba(255, 255, 255, 0.08);
                font-size: 0.75rem;
                color: var(--text-2);
                flex: 0 0 auto;
                cursor: pointer;
                transition: all var(--dur-fast);
                display: flex;
                align-items: center;
                justify-content: center;
            }
            .UIToast_Close:hover, .UIToast_Copy:hover {
                background: rgba(255, 255, 255, 0.12);
                border-color: rgba(255, 255, 255, 0.2);
                color: var(--text-1);
            }
            .UIToast_Body {
                padding: 10px 14px 12px;
                font-size: 0.85rem;
                color: var(--text-1);
                line-height: 1.5;
                text-rendering: optimizeLegibility;
                -webkit-font-smoothing: antialiased;
                -moz-osx-font-smoothing: grayscale;
            }



/* ============================================================   
    67. Infinite scroll sentinel (UIInfiniteScroll)
    Was injected at runtime from UIInfiniteScroll.js.
   ============================================================ */
            .UIInfiniteScroll_List { display: block; }
            .UIInfiniteScroll_Item { padding: 6px; border-radius: 3px; }
            .UIInfiniteScroll_Item:hover { background: var(--keyline); }
		


/* ============================================================
   68. Image loader / drop zone (UIImageLoader)
   Was injected at runtime from UIImageLoader.js.
   ============================================================ */
		.UIImageLoader { display: block; }
		.UIImageLoader__input { display: none; }
		.UIImageLoader__drop {
			position: relative;
			display: flex;
			align-items: center;
			justify-content: center;
			min-height: 140px;
			border: 1px dashed var(--surface-4);
			border-radius: 10px;
			background: rgba(0,0,0,0.18);
			cursor: pointer;
			overflow: hidden;
			transition: border-color 0.15s ease, background 0.15s ease;
		}
		.UIImageLoader__drop:hover { border-color: var(--text-3); background: rgba(0,0,0,0.22); }
		.UIImageLoader__drop.dragover {
			border-color: var(--accent);
			background: var(--accent-muted);
		}
		.UIImageLoader__drop.has-image {
			background-repeat: no-repeat;
			background-position: center;
			border-style: solid;
			border-color: var(--surface-3);
		}
		.UIImageLoader__drop.has-image:hover { border-color: var(--surface-4); }
		.UIImageLoader__placeholder {
			pointer-events: none;
			text-align: center;
			padding: 12px;
			font-size: 12px;
			color: var(--text-2);
		}
		.UIImageLoader__placeholder strong { display: block; margin-bottom: 4px; }
		.UIImageLoader__placeholder span { font-size: 11px; opacity: 0.72; }
		.UIImageLoader__drop.has-image .UIImageLoader__placeholder { display: none; }
		.UIImageLoader__clear {
			position: absolute;
			top: 8px;
			right: 8px;
			width: 28px;
			height: 28px;
			display: none;
			align-items: center;
			justify-content: center;
			border: none;
			border-radius: 6px;
			background: rgba(0,0,0,0.55);
			color: var(--text-1);
			cursor: pointer;
			font-size: 12px;
			transition: background 0.15s ease, color 0.15s ease;
		}
		.UIImageLoader__drop.has-image .UIImageLoader__clear { display: flex; }
		.UIImageLoader__clear:hover {
			background: var(--status-danger);
			color: var(--text-1);
		}
		.UIImageLoader__picker-wrap {
			display: inline-flex;
			align-items: center;
		}
		.UIImageLoader__picker-wrap .UIImageLoader__input { display: none; }
		.UIImageLoader__picker-btn {
			padding: 8px 14px;
			font-size: 12px;
			border: 1px solid var(--surface-4);
			border-radius: 8px;
			background: rgba(0,0,0,0.2);
			color: var(--text-1);
			cursor: pointer;
			transition: border-color 0.15s ease, background 0.15s ease;
		}
		.UIImageLoader__picker-btn:hover { border-color: var(--text-3); background: rgba(0,0,0,0.3); }
		.UIImageLoader.is-disabled .UIImageLoader__drop,
		.UIImageLoader.is-disabled .UIImageLoader__picker-btn { opacity: 0.6; cursor: not-allowed; pointer-events: none; }
	


/* ============================================================
   69. Legacy toolbar (UIToolbar)
   Was injected at runtime from UIToolbar.js.
   ============================================================ */
			.UIToolbar { display: flex; align-items: center; gap: 6px; padding: 6px;
				border-bottom: 1px solid var(--border-base, #333); background: var(--surface-1, #1b1f22);
				color: var(--text-1, #e7ecef);
			}
			.UIToolbar_Section { display: inline-flex; align-items: center; gap: 6px; background: var(--surface-2, #23282c); padding: 0 4px; }
			.UIToolbar_Section.dropdown { gap: 0; }
			.UIToolbar_Spacer { flex: 1 1 auto; }
			.UIToolbar_Separator { width: 1px; height: 18px; background: var(--border-base, #333); margin: 0 4px; }
			.UIToolbar_Btn { display: inline-flex; align-items: center; gap: 6px;
				padding: 4px 8px; border-radius: var(--radius-base, 4px);
				background: var(--surface-2, #23282c); border: 1px solid var(--border-base, #333);
				color: inherit; font-size: 12px;
			}
			.UIToolbar_Btn:hover { background: var(--surface-3, #2c3237); }
			.UIToolbar_Btn.is-on { background: var(--accent-muted, rgba(58,160,255,0.14)); border-color: var(--accent-border, rgba(58,160,255,0.5)); color: var(--accent-hover, #57adff); }
			.UIToolbar_Text { font-size: 12px; color: var(--text-2, #a7b0b7); }
			.UIToolbar_Input { font-size: 12px; padding: 3px 6px; border-radius: var(--radius-base, 4px);
				background: var(--surface-2, #23282c); border: 1px solid var(--border-base, #333); color: inherit;
			}
			.UIToolbar_Input[type="range"] { padding: 0; }
			.UIToolbar_Progress { width: 120px; height: 8px; }
		


/* ============================================================
   70. Menu / navbar (UIMenu)
   Was injected at runtime from UIMenu.js.
   ============================================================ */
			.UIMenu { display: block; width: 100%;
				background: var(--surface-sunken); border-bottom: 1px solid var(--keyline);
				color: var(--text-1); font-size: 12px;
			}
			.UIMenu_Inner { display: flex; align-items: center; gap: 10px; padding: 6px 10px; }
			.UIMenu_Brand { font-weight: 600; text-decoration: none; color: inherit; white-space: nowrap; }
			.UIMenu_Brand:hover { color: var(--text-1); }

			.UIMenu_Toggler { display: none; align-items: center; justify-content: center;
				width: 34px; height: 28px; border-radius: 4px;
				background: var(--surface-2); border: 1px solid var(--surface-3);
				color: inherit;
			}
			.UIMenu_Toggler:hover { background: var(--keyline); }
			.UIMenu_TogglerIcon { position: relative; display: block; width: 16px; height: 2px; background: currentColor; }
			.UIMenu_TogglerIcon::before, .UIMenu_TogglerIcon::after {
				content: ''; position: absolute; left: 0; width: 100%; height: 2px; background: currentColor;
			}
			.UIMenu_TogglerIcon::before { top: -5px; }
			.UIMenu_TogglerIcon::after { top: 5px; }

			.UIMenu_Collapse { flex: 1; display: flex; align-items: center; }
			.UIMenu_Nav { display: flex; align-items: center; gap: 8px; flex: 1; }
			.UIMenu_NavList { display: flex; align-items: center; gap: 6px; }
			.UIMenu_NavList--right { margin-left: auto; }

			.UIMenu_Item { display: inline-flex; align-items: center; gap: 6px;
				padding: 4px 8px; border-radius: 4px; border: 1px solid transparent;
				background: transparent; color: inherit; text-decoration: none; font-size: 12px; cursor: pointer;
			}
			.UIMenu_Item:hover { background: var(--keyline); }
			.UIMenu_Item.is-active { background: var(--accent-muted); border-color: var(--accent-border); }
			.UIMenu_Item.is-disabled { opacity: 0.5; pointer-events: none; }

			.UIMenu_Text { opacity: 0.8; padding: 4px 6px; }

			.UIMenu--expand .UIMenu_Toggler { display: none; }

			.UIMenu--collapse .UIMenu_Toggler { display: inline-flex; }
			.UIMenu--collapse .UIMenu_Collapse { display: none; width: 100%; }
			.UIMenu--collapse.is-open .UIMenu_Collapse { display: flex; }
			.UIMenu--collapse .UIMenu_Inner { flex-wrap: wrap; }
			.UIMenu--collapse .UIMenu_Nav,
			.UIMenu--collapse .UIMenu_NavList {
				flex-direction: column; align-items: stretch; width: 100%;
			}
			.UIMenu--collapse .UIMenu_NavList--right { margin-left: 0; }
			.UIMenu--collapse .UIMenu_Item { width: 100%; justify-content: flex-start; }

			.UIMenu--expand-sm .UIMenu_Toggler,
			.UIMenu--expand-md .UIMenu_Toggler,
			.UIMenu--expand-lg .UIMenu_Toggler,
			.UIMenu--expand-xl .UIMenu_Toggler,
			.UIMenu--expand-xxl .UIMenu_Toggler {
				display: none;
			}

			@media (max-width: 575.98px) {
				.UIMenu--expand-sm .UIMenu_Toggler { display: inline-flex; }
				.UIMenu--expand-sm .UIMenu_Collapse { display: none; width: 100%; }
				.UIMenu--expand-sm.is-open .UIMenu_Collapse { display: flex; }
				.UIMenu--expand-sm .UIMenu_Inner { flex-wrap: wrap; }
				.UIMenu--expand-sm .UIMenu_Nav,
				.UIMenu--expand-sm .UIMenu_NavList {
					flex-direction: column; align-items: stretch; width: 100%;
				}
				.UIMenu--expand-sm .UIMenu_NavList--right { margin-left: 0; }
				.UIMenu--expand-sm .UIMenu_Item { width: 100%; justify-content: flex-start; }
			}

			@media (max-width: 767.98px) {
				.UIMenu--expand-md .UIMenu_Toggler { display: inline-flex; }
				.UIMenu--expand-md .UIMenu_Collapse { display: none; width: 100%; }
				.UIMenu--expand-md.is-open .UIMenu_Collapse { display: flex; }
				.UIMenu--expand-md .UIMenu_Inner { flex-wrap: wrap; }
				.UIMenu--expand-md .UIMenu_Nav,
				.UIMenu--expand-md .UIMenu_NavList {
					flex-direction: column; align-items: stretch; width: 100%;
				}
				.UIMenu--expand-md .UIMenu_NavList--right { margin-left: 0; }
				.UIMenu--expand-md .UIMenu_Item { width: 100%; justify-content: flex-start; }
			}

			@media (max-width: 991.98px) {
				.UIMenu--expand-lg .UIMenu_Toggler { display: inline-flex; }
				.UIMenu--expand-lg .UIMenu_Collapse { display: none; width: 100%; }
				.UIMenu--expand-lg.is-open .UIMenu_Collapse { display: flex; }
				.UIMenu--expand-lg .UIMenu_Inner { flex-wrap: wrap; }
				.UIMenu--expand-lg .UIMenu_Nav,
				.UIMenu--expand-lg .UIMenu_NavList {
					flex-direction: column; align-items: stretch; width: 100%;
				}
				.UIMenu--expand-lg .UIMenu_NavList--right { margin-left: 0; }
				.UIMenu--expand-lg .UIMenu_Item { width: 100%; justify-content: flex-start; }
			}

			@media (max-width: 1199.98px) {
				.UIMenu--expand-xl .UIMenu_Toggler { display: inline-flex; }
				.UIMenu--expand-xl .UIMenu_Collapse { display: none; width: 100%; }
				.UIMenu--expand-xl.is-open .UIMenu_Collapse { display: flex; }
				.UIMenu--expand-xl .UIMenu_Inner { flex-wrap: wrap; }
				.UIMenu--expand-xl .UIMenu_Nav,
				.UIMenu--expand-xl .UIMenu_NavList {
					flex-direction: column; align-items: stretch; width: 100%;
				}
				.UIMenu--expand-xl .UIMenu_NavList--right { margin-left: 0; }
				.UIMenu--expand-xl .UIMenu_Item { width: 100%; justify-content: flex-start; }
			}

			@media (max-width: 1399.98px) {
				.UIMenu--expand-xxl .UIMenu_Toggler { display: inline-flex; }
				.UIMenu--expand-xxl .UIMenu_Collapse { display: none; width: 100%; }
				.UIMenu--expand-xxl.is-open .UIMenu_Collapse { display: flex; }
				.UIMenu--expand-xxl .UIMenu_Inner { flex-wrap: wrap; }
				.UIMenu--expand-xxl .UIMenu_Nav,
				.UIMenu--expand-xxl .UIMenu_NavList {
					flex-direction: column; align-items: stretch; width: 100%;
				}
				.UIMenu--expand-xxl .UIMenu_NavList--right { margin-left: 0; }
				.UIMenu--expand-xxl .UIMenu_Item { width: 100%; justify-content: flex-start; }
			}
		


/* ============================================================
   71. Status bar widget (UIStatusBar)
   Was injected at runtime from UIStatusBar.js.
   ============================================================ */
			.UIStatusBar { display: flex; align-items: center; gap: 6px; padding: 3px 6px;
				border-top: 1px solid var(--border-base, #333); background: var(--surface-2, #23282c);
				color: var(--text-1, #e7ecef);
				font-size: 10px; font-family: var(--font-family-data, monospace);
			}
			.UIStatusBar_Left, .UIStatusBar_Right { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: flex; align-items: center; gap: 4px; font-family: var(--font-family-data, monospace); }
			.UIStatusBar_Left { flex: 1; }
			.UIStatusBar_Right { flex: 0 0 auto; }
			.UIStatusBar_ProgressWrap { flex: 0 0 160px; height: 4px; border-radius: 999px; overflow: hidden;
				background: var(--surface-3, #2c3237); border: 1px solid var(--border-base, #333);
			}
			.UIStatusBar_ProgressWrap.is-hidden { display: none; }
			.UIStatusBar_ProgressBar { height: 100%; width: 0%; background: var(--accent, #3aa0ff); }
			.UIStatusBar_Section { display: inline-flex; align-items: center; gap: 3px; padding: 1px 4px; min-height: 16px; font-size: 10px; font-family: var(--font-family-data, monospace); color: var(--text-1, #e7ecef); }
			.UIStatusBar_Section_Label { color: var(--text-3, #6e7880); font-size: 9px; font-family: var(--font-family-data, monospace); text-transform: uppercase; letter-spacing: 0.3px; }
			.UIStatusBar_Section_Value { font-size: 10px; font-family: var(--font-family-data, monospace); }
			.UIStatusBar_Spacer { flex: 1 1 auto; }
			.UIStatusBar_Separator { width: 1px; height: 14px; background: var(--border-base, #333); margin: 0 3px; }
			.UIStatusBar_Btn { display: inline-flex; align-items: center; justify-content: center; gap: 3px;
				padding: 1px 6px; border-radius: var(--radius-sm, 3px); min-width: 22px; height: 18px;
				background: var(--surface-3, #2c3237); border: 1px solid var(--border-base, #333);
				color: inherit; font-size: 9px; font-family: var(--font-family-data, monospace); line-height: 1; cursor: pointer;
			}
			.UIStatusBar_Btn:hover { background: var(--surface-4, #333a40); }
			.UIStatusBar_Btn.is-on { background: var(--accent-muted, rgba(58,160,255,0.14)); border-color: var(--accent-border, rgba(58,160,255,0.5)); color: var(--accent-hover, #57adff); }
			.UIStatusBar_Btn .UIStatusBar_Icon { font-size: 9px; line-height: 1; display: inline-flex; align-items: center; }
			.UIStatusBar_Btn .UIStatusBar_Label { font-size: 9px; line-height: 1; }
			.UIStatusBar_Text { font-size: 10px; font-family: var(--font-family-data, monospace); color: var(--text-2, #a7b0b7); }
			.UIStatusBar_Input { font-size: 10px; font-family: var(--font-family-data, monospace); }
		


/* ============================================================
   72. File tree (UIFileTree)
   Was injected at runtime from UIFileTree.js.
   ============================================================ */
			.UIFileTree { overflow: auto; user-select: none; outline: none; }
			.UIFileTree_Tree { padding: 4px; }
			.UIFileTree_Row { display: flex; align-items: center; gap: 6px; padding: 2px 6px; border-radius: 3px; cursor: default; border: 1px solid transparent; }
			.UIFileTree_Row:hover { background: var(--keyline); }
			.UIFileTree_Row.is-selected { background: var(--surface-3); }
			.UIFileTree_Row.UIFileTree_Row--drop-before { border-top: 2px dashed var(--text-3); }
			.UIFileTree_Row.UIFileTree_Row--drop-after { border-bottom: 2px dashed var(--text-3); }
			.UIFileTree_Row.UIFileTree_Row--drop-inside { background: var(--keyline); }
			.UIFileTree_Toggle { width: 14px; height: 14px; display: inline-flex; align-items: center; justify-content: center; opacity: 0.8; }
			.UIFileTree_Toggle::before { content: "▸"; font-size: 12px; line-height: 12px; }
			.UIFileTree_Toggle.is-expanded::before { content: "▾"; }
			.UIFileTree_Indent { width: 14px; flex: 0 0 14px; }
			.UIFileTree_Icon { width: 14px; height: 14px; opacity: 0.8; display: inline-flex; align-items: center; justify-content: center; }
			.UIFileTree_Label { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; flex: 1; }
			.UIFileTree_Actions { display: flex; align-items: center; gap: 2px; margin-left: auto; }
			.UIFileTree_Action { width: 16px; height: 16px; display: inline-flex; align-items: center; justify-content: center; opacity: 0; cursor: pointer; border-radius: var(--radius-sm, 3px); font-size: 11px; line-height: 1; color: var(--text-2, #a7b0b7); }
			.UIFileTree_Row:hover .UIFileTree_Action, .UIFileTree_Action.is-active { opacity: 0.75; }
			.UIFileTree_Action:hover { opacity: 1; background: var(--surface-3); color: var(--text-1, #e7ecef); }
			.UIFileTree_Row.is-hidden .UIFileTree_Icon, .UIFileTree_Row.is-hidden .UIFileTree_Label { opacity: 0.4; font-style: italic; }
		


/* ============================================================
   73. Accordion (UIAccordion*)
   Was injected at runtime from UIAccordion.js.
   ============================================================ */
            .uia-container {
                display: flex;
                flex-direction: column;
                gap: 0;
            }

            .uia-widget {
                display: flex;
                flex-direction: column;
            }

            .uia-widget:last-child {
                border-bottom: none;
            }

            .uia-header {
                background: var(--bg-color-secondary);
                border: 1px solid var(--bs-border-color);
                border-bottom: none;
                cursor: pointer;
                transition: background-color 0.2s ease;
                user-select: none;
                display: flex;
                flex-direction: row;
                align-items: center;
                gap: 4px;
                overflow: hidden !important;
                white-space: nowrap;
            }

            /* Keep existing "UIText renders span" padding behavior */
            .uia-header span {
                padding: 3px 6px;
            }

            .uia-header:hover {
                background: var(--bg-color-tertiary);
            }

            .uia-toggle {
                min-width: 16px;
                text-align: center;
                transition: transform 0.2s ease;
            }

            .uia-header.collapsed .uia-toggle {
                transform: rotate(-90deg);
            }

            .uia-icon {
                min-width: 16px;
                text-align: center;
            }

            .uia-title {
                flex: 1;
                font-size: var(--font-size-xs);
                font-weight: bold;
                text-transform: uppercase;
                letter-spacing: 0.3px;
                line-height: 1.2;
                min-width: 0;
                overflow: hidden;
                text-overflow: ellipsis;
            }

            .uia-title-suffix {
                display: inline-flex;
                align-items: center;
                margin-left: 4px;
                flex-shrink: 0;
            }

            /* Header badge (section count) */
            .uia-header-badge {
                display: inline-flex;
                align-items: center;
                justify-content: center;
                min-width: 18px;
                height: 16px;
                padding: 0 6px;
                border-radius: 999px;
                border: 1px solid var(--bs-border-color);
                background: var(--bg-color-tertiary);
                font-size: var(--font-size-xxs, 10px);
                line-height: 1;
                opacity: 0.9;
                margin-right: 2px;
            }

            /* Header buttons slot (right-aligned due to title flex:1) */
            .uia-header-buttons {
                display: flex;
                flex-direction: row;
                align-items: center;
                gap: 4px;
                padding: 3px;
                padding-left: 0;
            }

            .uia-header-buttons Button {
                align-items: center;
                justify-content: center;
                border: none;
                box-sizing: border-box;
                font-size: var(--font-size-xs);
                line-height: 1rem;
            }

            /* Prevent header-buttons area from inheriting the span padding rule */
            .uia-header-buttons span {
                padding: 0;
            }

            .uia-body {
                display: block;
                transition: max-height 0.3s ease, opacity 0.3s ease;
                opacity: 1;
                padding: 0.5rem;
                height: auto;
                border: 1px solid var(--bs-border-color);
                border-top: none;
            }

            .uia-body.collapsed {
                display: none;
                max-height: none;
                opacity: 0;
                padding: 0;
            }

            /* Body header row for a section-level badge */
            .uia-body-header {
                display: flex;
                justify-content: flex-end;
                align-items: center;
                padding: 0 0 6px 0;
            }

            .uia-body-header-badge {
                display: inline-flex;
                align-items: center;
                justify-content: center;
                min-width: 18px;
                height: 16px;
                padding: 0 6px;
                border-radius: 999px;
                border: 1px solid var(--bs-border-color);
                background: var(--bg-color-secondary);
                font-size: var(--font-size-xxs, 10px);
                line-height: 1;
                opacity: 0.85;
            }

            /* Standardized BodyItem layout */
            .uia-body-item {
                display: flex;
                flex-direction: row;
                align-items: center;
                gap: 6px;
                padding: 4px 2px;
                border-bottom: 1px solid var(--surface-2);
            }

            .uia-body-item:last-child {
                border-bottom: none;
            }

            .uia-body-icon {
                min-width: 16px;
                text-align: center;
                opacity: 0.85;
            }

            .uia-body-content {
                flex: 1;
                min-width: 0;
                overflow: hidden;
                white-space: nowrap;
                text-overflow: ellipsis;
            }

            .uia-body-label {
                font-size: var(--font-size-xs);
            }

            /* Per-row badge */
            .uia-body-badge {
                display: inline-flex;
                align-items: center;
                justify-content: center;
                min-width: 18px;
                height: 16px;
                padding: 0 6px;
                border-radius: 999px;
                border: 1px solid var(--bs-border-color);
                background: var(--bg-color-secondary);
                font-size: var(--font-size-xxs, 10px);
                line-height: 1;
                opacity: 0.85;
            }

            .uia-body-buttons {
                display: flex;
                flex-direction: row;
                align-items: center;
                gap: 4px;
            }
        


/* ============================================================
   74. HUD / collapsible panels (UIHud)
   Was injected at runtime from UIHud.js.
   ============================================================ */
            .UIHud {
                pointer-events: none;
                max-width: 400px;
                max-height: calc(100% - 24px);
                overflow: visible;
            }
            
            .UIHud > * {
                pointer-events: auto;
            }
            
            .CollapsiblePanel {
                background: var(--surface-1);
                backdrop-filter: blur(8px);
                -webkit-backdrop-filter: blur(8px);
                border: 1px solid var(--surface-3);
                border-radius: 6px;
                box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);
                margin-bottom: 8px;
                overflow: hidden;
            }
            
            .CollapsibleHeader {
                user-select: none;
                transition: background-color 0.2s ease;
            }
            
            .CollapsibleHeader:hover {
                background-color: var(--surface-3) !important;
            }
            
            .CollapsibleContent {
                padding: 8px 12px;
                overflow-y: auto;
                overflow-x: hidden;
            }
            
            .CollapsibleContent::-webkit-scrollbar {
                width: 6px;
            }
            
            .CollapsibleContent::-webkit-scrollbar-track {
                background: var(--surface-sunken);
            }
            
            .CollapsibleContent::-webkit-scrollbar-thumb {
                background: var(--surface-4);
                border-radius: 3px;
            }
            
            .CollapsibleContent::-webkit-scrollbar-thumb:hover {
                background: var(--text-3);
            }
/* ============================================================
   75. Sidebar.ColorEditor
   ============================================================ */
    .sidebar-section { padding: 10px; border: 1px solid var(--bs-border-color); border-radius: 4px; }
    .sidebar-section + .sidebar-section { margin-top: 8px; }
    .sidebar-section .section-title { font-weight: 600; font-size: 0.85rem; opacity: 0.85; margin-bottom: 6px; }
    .slider-label { display: flex; justify-content: space-between; align-items: center; }
    .slider-value { font-weight: bold; margin-left: auto; padding-left: 8px; }
    .slider-input { height: 0.5rem; }
    .color-btn-row { display: flex; gap: 6px; margin-top: 6px; }
    .color-btn-row .Button { flex: 1; }
    .color-ai-status { font-size: 0.78rem; opacity: 0.8; margin-top: 6px; min-height: 1.1em; }
    .color-inline { display: flex; align-items: center; gap: 8px; }
    .color-field-row { display: flex; align-items: center; gap: 8px; margin-top: 6px; }
    .color-field-row > label { width: 96px; font-size: 0.82rem; flex: 0 0 auto; }
    .color-field-row select, .color-field-row input[type=number] { flex: 1; min-width: 0; }
    .color-incl { display: none; }
    .color-incl.show { display: flex; gap: 8px; }
    .color-incl input[type=number] { width: 100%; }
    .color-grad { margin-top: 8px; }
    .color-grad-bar { height: 16px; border-radius: 3px; border: 1px solid var(--bs-border-color); margin: 6px 0;
        background-color: var(--text-3);
        background-image:
            linear-gradient(90deg, #000, #000),
            linear-gradient(45deg, var(--text-3) 25%, transparent 25%, transparent 75%, var(--text-3) 75%),
            linear-gradient(45deg, var(--text-3) 25%, var(--text-3) 25%, var(--text-3) 75%, var(--text-3) 75%);
        background-size: 100% 100%, 10px 10px, 10px 10px;
        background-position: 0 0, 0 0, 5px 5px; }
    .color-grad-stops { display: flex; flex-direction: column; gap: 5px; margin-top: 4px; }
    .color-grad-stop { display: flex; align-items: center; gap: 8px; }
    .color-grad-stop .stop-lbl { width: 46px; font-size: 0.74rem; opacity: 0.8; flex: 0 0 auto; }
    .color-grad-stop input[type=color] { width: 30px; height: 20px; padding: 0; border: none; background: transparent; flex: 0 0 auto; }
    .color-grad-stop input[type=range] { flex: 1; min-width: 0; height: 0.5rem; }
    .color-grad-stop .stop-a { width: 30px; font-size: 0.72rem; opacity: 0.7; text-align: right; flex: 0 0 auto; }


/* ============================================================
   76. Sidebar.LightEditor
   ============================================================ */
    #sidebar-light-editor .sidebar-section { padding: 10px; border: 1px solid var(--bs-border-color); border-radius: 4px; }
    #sidebar-light-editor .sidebar-section + .sidebar-section { margin-top: 8px; }
    #sidebar-light-editor .section-title { font-weight: 600; font-size: 0.85rem; opacity: 0.85; margin-bottom: 6px; }
    #sidebar-light-editor .slider-label { display: flex; justify-content: space-between; align-items: center; }
    #sidebar-light-editor .slider-value { font-weight: bold; margin-left: auto; padding-left: 8px; }
    #sidebar-light-editor .slider-input { height: 0.5rem; }
    #sidebar-light-editor .light-inline { display: flex; align-items: center; gap: 8px; }
    #sidebar-light-editor .light-note { font-size: 0.72rem; opacity: 0.7; line-height: 1.35; margin-top: 4px; }
    #sidebar-light-editor .light-status { font-size: 0.78rem; opacity: 0.85; min-height: 1.2em; margin-top: 6px; }
    #sidebar-light-editor .light-btn-row { display: flex; gap: 6px; margin-top: 8px; }
    #sidebar-light-editor .light-btn-row .Button { flex: 1; }
    #sidebar-light-editor .light-bar { height: 6px; border-radius: 3px; background: var(--bs-border-color); overflow: hidden; margin-top: 6px; }
    #sidebar-light-editor .light-bar > i { display: block; height: 100%; width: 0%; background: var(--accent, #3d8bff); transition: width 80ms linear; }


/* ============================================================
   77. Sidebar.WaterEditor
   ============================================================ */
    #sidebar-water-editor .sidebar-section { padding: 10px; border: 1px solid var(--bs-border-color); border-radius: 4px; }
    #sidebar-water-editor .sidebar-section + .sidebar-section { margin-top: 8px; }
    #sidebar-water-editor .section-title { font-weight: 600; font-size: 0.85rem; opacity: 0.85; margin-bottom: 6px; }
    #sidebar-water-editor .slider-label { display: flex; justify-content: space-between; align-items: center; }
    #sidebar-water-editor .slider-value { font-weight: bold; margin-left: auto; padding-left: 8px; }
    #sidebar-water-editor .slider-input { height: 0.5rem; }
    #sidebar-water-editor .water-inline { display: flex; align-items: center; gap: 8px; }
    #sidebar-water-editor .water-note { font-size: 0.72rem; opacity: 0.7; line-height: 1.35; margin-top: 4px; }
    #sidebar-water-editor .water-warn { font-size: 0.72rem; line-height: 1.35; margin-top: 4px; color: var(--signal, #e9a13b); }
    #sidebar-water-editor .water-status { font-size: 0.78rem; opacity: 0.85; min-height: 1.2em; margin-top: 6px; }
    #sidebar-water-editor .water-btn-row { display: flex; gap: 6px; margin-top: 8px; }
    #sidebar-water-editor .water-btn-row .Button { flex: 1; }


/* ============================================================
   78. Sidebar.Outliner
   ============================================================ */
/* Sidebar.Outliner Styles */

/* Type identity for RSM model roots in the tree — a deliberate hue, declared once
   rather than repeated as a literal at each use. */
#outliner {
    --outliner-model-root: #a76ef5;
    --outliner-model-root-dim: #9061c2;
}

/* Shared sidebar styles (copied from main.css for Outliner) */
#OutlinerSidebar {
    background: var(--surface-1) !important;
    border: none !important;
    box-shadow: none !important;
    position: relative;
    z-index: 999; /* Ensure content is above viewport */
    height: 100%; /* Ensure full height */
    display: flex;
    flex-direction: column;
}

/* Sidebar tab bar — dark header with lime accent on selected */
#OutlinerSidebar .TabbedPanel .Tabs {
    background: var(--surface-2) !important;
    border-bottom: 1px solid var(--border-base) !important;
    display: flex;
}

/* History & Info sidebar headers — flat dark header bar */
.history-header-section,
.sidebar-header-section {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.75rem 0.5rem;
    background: var(--surface-2);
    border-bottom: 1px solid var(--border-base);
    color: var(--text-1);
    font-size: 0.75rem;
    font-weight: 600;
}
.history-header-section i,
.sidebar-header-section i {
    color: var(--uk-accent);
}

/* Sidebar controls sections */
.history-controls-section,
.sidebar-controls-section {
    padding: 0.5rem;
    background: var(--surface-1);
    border-bottom: 1px solid var(--border-subtle);
}

/* Outliner container */
#OutlinerSidebar .outliner-container {
	height: 100%;
	overflow: hidden;
	display: flex;
	flex-direction: column;
	flex: 1;
}

/* Search / filter toolbar */
#OutlinerSidebar .outliner-toolbar {
	display: flex;
	align-items: center;
	gap: var(--spacing-1, 4px);
	padding: 4px;
	flex: 0 0 auto;
	border-bottom: 1px solid var(--keyline, rgba(255, 255, 255, 0.05));
}

#OutlinerSidebar .outliner-toolbar .outliner-search {
	flex: 1 1 auto;
	min-width: 0;
}


/* ============================================================
   79. Sidebar.GND
   ============================================================ */
/* Sidebar GND Styles */
.data-row { display: flex; justify-content: space-between; }

.gnd-texture-magnifier {
	position: fixed;
	z-index: 10000;
	padding: 6px;
	background: var(--bg-color-tertiary, #1e293b);
	border: 1px solid var(--border-color-base, rgba(255, 255, 255, 0.15));
	border-radius: 8px;
	box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5);
	pointer-events: none;
}

.gnd-texture-magnifier canvas {
	width: 256px;
	height: 256px;
	display: block;
	border-radius: 4px;
	image-rendering: pixelated;
	image-rendering: crisp-edges;
}

.texture-list-item {
	cursor: default;
}

/* ============================================================
   80. Water type picker (customUI/WaterTypePicker)
   ============================================================ */
/* Shared by the AI Map Wizard's Water step; NewMap keeps its own `.nm-water-*` chrome
   (§62) and uses only the picker's frame engine. A water type is a number with no meaning
   outside the client's texture folder, so the control is a picture first and a label
   second — everything here exists to make the frames readable at 44–56px. */
.wtp {
	display: flex;
	flex-direction: column;
	gap: var(--uk-gap-sm);
	min-width: 0;
}
.wtp-current {
	display: flex;
	align-items: center;
	gap: var(--uk-gap-sm);
	width: 100%;
	padding: 4px 8px 4px 4px;
	color: inherit;
	background: var(--uk-surface-1);
	border: 1px solid var(--uk-border-light);
	border-radius: var(--uk-radius-md);
	cursor: pointer;
	text-align: left;
}
.wtp-current:hover { border-color: var(--uk-accent-border, var(--accent-border)); }
.wtp-current-label {
	flex: 1;
	min-width: 0;
	font-size: 12px;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
.wtp-chevron {
	color: var(--uk-text-3);
	transition: transform var(--uk-motion-fast, 120ms) ease;
}
.wtp.is-open .wtp-chevron { transform: rotate(180deg); }
/* The thumbnail box, not the canvas: the canvas is sized in device pixels by the engine
   and stretched to fit here, so a card and the button can show the same frames at
   different sizes without two loaders. */
.wtp-thumb {
	display: flex;
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
	overflow: hidden;
	background: var(--uk-surface-sunken, var(--surface-sunken));
	border: 1px solid var(--uk-border-light);
	border-radius: var(--uk-radius-sm);
}
.wtp-current .wtp-thumb { width: 44px; height: 44px; }
.wtp-card .wtp-thumb { width: 56px; height: 56px; }
.wtp-thumb canvas { display: block; width: 100%; height: 100%; }
.wtp-grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
	gap: var(--uk-gap-sm);
	max-height: 300px;
	overflow-y: auto;
	padding: var(--uk-gap-sm);
	background: var(--uk-surface-sunken, var(--surface-sunken));
	border: 1px solid var(--uk-border-light);
	border-radius: var(--uk-radius-md);
}
.wtp-card {
	display: flex;
	align-items: center;
	gap: var(--uk-gap-sm);
	padding: 4px;
	color: inherit;
	background: var(--uk-surface-1);
	border: 1px solid var(--uk-border-light);
	border-radius: var(--uk-radius-sm);
	cursor: pointer;
	text-align: left;
}
.wtp-card:hover { border-color: var(--uk-accent-border, var(--accent-border)); }
.wtp-card.is-active {
	border-color: var(--uk-accent-border, var(--accent-border));
	background: var(--uk-accent-muted, var(--accent-muted));
}
.wtp-card-label {
	min-width: 0;
	font-size: 11px;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}


/* ============================================================
   81. Tool rail (customUI/ToolRail) — the vertical edit toolbar
   ============================================================ */

/* The rail is an IN-FLOW column in `.app-body`, after `.viewport-container`.
   Everything that measures the canvas — the renderer's ResizeObserver, UKWindow's
   maximize, every right-edge overlay — reads `.viewport-container`'s box, so being
   in flow is what keeps the canvas out from under the rail with no offset maths.
   `.mode-rail` (§58) is a different thing: the floating per-mode rail on the LEFT. */
.tool-rail-host {
	flex: 0 0 auto;
	display: flex;
	align-items: stretch;
	/* Above `.viewport-container` (z-index: 1) so the rail's own shadow and any
	   button flyout draw over the canvas edge. */
	z-index: 2;
}

.tool-rail {
	display: flex;
	align-items: stretch;
	padding: 6px 5px;
	background: var(--glass-panel);
	-webkit-backdrop-filter: blur(var(--glass-blur));
	backdrop-filter: blur(var(--glass-blur));
	border-left: 1px solid var(--glass-border);
	box-shadow: var(--glass-shadow);
}

/* The toolbar fills the rail's height so the spacer can push the session group to
   the bottom; `min-height: 0` lets a long mode list scroll instead of overflowing. */
.tool-rail > .ui-toolbar {
	flex: 1 1 auto;
	min-height: 0;
	overflow-y: auto;
	overflow-x: visible;
	gap: 4px;
}

/* Groups here are structure, not visible clusters — the rail itself is the chrome. */
.tool-rail .ui-toolbar__group {
	background: transparent;
	border: none;
	padding: 0;
	gap: 3px;
}

.tool-rail .ui-tbtn {
	min-width: 38px;
	min-height: 38px;
	padding: 4px;
}

.tool-rail__session {
	/* Reads as a separate cluster from the modes above it. */
	border-top: 1px solid var(--glass-border);
	padding-top: 6px !important;
}


/* ============================================================
   82. Mode panel (customUI/ToolRail) — the sliding glass editor panel
   ============================================================ */

/* Floats over the canvas at the right edge, flush against the tool rail, and slides
   out from under it when a mode is picked. Absolute (not in flow) on purpose: opening
   a panel must not resize the 3D view.

   Two things this shape is protecting:
   - `display: none` would kill the transition, so the closed state uses `visibility`
     with a delayed 0s step — which also keeps a closed panel out of the tab order.
   - Nothing here animates `opacity` or sets `filter` on the panel: `backdrop-filter`
     inside an element that is itself being faded blurs that element's rendered output
     instead of the page behind it, which is exactly how a glass surface comes out
     looking flat. Fade a non-blurred child if a fade is ever wanted. */
.mode-panel {
	position: absolute;
	top: 0;
	right: 0;
	height: 100%;
	width: 320px;
	z-index: 999;
	display: flex;
	flex-direction: column;
	min-height: 0;
	background: var(--glass-panel);
	-webkit-backdrop-filter: blur(var(--glass-blur));
	backdrop-filter: blur(var(--glass-blur));
	border-left: 1px solid var(--glass-border);
	box-shadow: var(--glass-shadow);
	transform: translateX(100%);
	visibility: hidden;
	pointer-events: none;
	/* More specific than app.css's global `* { transition: … transform 0.2s ease }`,
	   which is why the duration is stated here rather than inherited from it. */
	transition: transform 320ms cubic-bezier(0.2, 0.8, 0.2, 1), visibility 0s linear 320ms;
}

.mode-panel.is-open {
	transform: translateX(0);
	visibility: visible;
	pointer-events: auto;
	transition: transform 320ms cubic-bezier(0.2, 0.8, 0.2, 1), visibility 0s;
}

@media (prefers-reduced-motion: reduce) {
	.mode-panel,
	.mode-panel.is-open { transition: none; }
}

.mode-panel__header {
	flex: 0 0 auto;
	display: flex;
	align-items: center;
	gap: 8px;
	padding: 8px 10px;
	border-bottom: 1px solid var(--glass-border);
	background: var(--glass-raised);
}

.mode-panel__icon { font-size: 18px; line-height: 1; }

.mode-panel__titles { flex: 1 1 auto; min-width: 0; }

.mode-panel__title {
	font-size: 12px;
	font-weight: 600;
	color: var(--uk-text-1, var(--text-color-primary));
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

.mode-panel__desc {
	font-size: 10px;
	color: var(--uk-text-3, var(--text-color-muted));
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

/* The tool's (i) sits beside the close button. It is the ONE help affordance for a
   mode whose own sidebar no longer builds a header row of its own. */
.mode-panel__info { flex: 0 0 auto; }

.mode-panel__close {
	flex: 0 0 auto;
	width: 24px;
	height: 24px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	border: 1px solid transparent;
	border-radius: var(--uk-radius-sm, 6px);
	background: transparent;
	color: var(--uk-text-3, var(--text-color-muted));
	cursor: pointer;
	font-size: 12px;
}

.mode-panel__close:hover {
	background: color-mix(in srgb, var(--uk-accent) 14%, transparent);
	color: var(--uk-text-1, var(--text-color-primary));
}

.mode-panel__close:focus-visible {
	outline: 2px solid var(--uk-accent);
	outline-offset: 1px;
}

.mode-panel__body {
	flex: 1 1 auto;
	min-height: 0;
	overflow-y: auto;
	overflow-x: hidden;
}

/* One page per mode; the leaving page keeps `is-current` until the next mode claims
   it, so the panel is never empty mid-slide. */
.mode-panel__pane { display: none; height: 100%; }
.mode-panel__pane.is-current { display: block; }


/* ============================================================
   83. Minimap (customUI/Minimap) — the top-down map thumbnail
   ============================================================ */

/* Floats over the top-right of the canvas, under the mode panel (z 999) so a mode
   that slides out is never obscured by it. `App._updateRightInsets()` writes the
   `right` offset, the same way it keeps the selection HUD and the view helper clear
   of the mode panel — the panel is user-resizable, so no CSS constant can be right.

   Hidden with `display: none` rather than a transform: the two canvases inside are
   painted on demand, and a hidden panel that still occupies a box would keep taking
   pointer events over the canvas. */
.minimap-panel {
	position: absolute;
	top: 12px;
	right: 12px;
	z-index: 900;
	display: none;
	flex-direction: column;
	border: 1px solid var(--uk-glass-border, var(--glass-border));
	border-radius: var(--uk-radius-md);
	box-shadow: var(--glass-shadow);
	overflow: hidden;
	user-select: none;
	-webkit-user-select: none;
}

.minimap-panel.is-visible { display: flex; }

.minimap-panel__head {
	display: flex;
	align-items: center;
	gap: 6px;
	padding: 4px 4px 4px 8px;
	border-bottom: 1px solid var(--uk-glass-border, var(--glass-border));
}

.minimap-panel__title {
	flex: 1 1 auto;
	min-width: 0;
	font-size: 11px;
	font-weight: 600;
	letter-spacing: 0.03em;
	text-transform: uppercase;
	color: var(--text-2);
}

.minimap-panel__action {
	flex: 0 0 auto;
	width: 20px;
	height: 20px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 0;
	font-size: 10px;
	color: var(--text-2);
	background: transparent;
	border: 0;
	border-radius: var(--uk-radius-sm);
	cursor: pointer;
}

.minimap-panel__action:hover {
	color: var(--text-0);
	background: var(--uk-glass-sunken, var(--glass-sunken));
}

/* The two canvases are stacked: the photograph underneath, the camera-coverage
   lines on top. Both are sized in JS from the same `--minimap-size`, so nothing
   here may scale one without the other. */
.minimap-panel__body {
	position: relative;
	width: var(--minimap-size, 196px);
	height: var(--minimap-size, 196px);
	background: var(--surface-0);
}

.minimap-panel__image,
.minimap-panel__overlay {
	position: absolute;
	inset: 0;
	display: block;
	width: 100%;
	height: 100%;
}

.minimap-panel__overlay { pointer-events: none; }

.minimap-panel__foot {
	padding: 3px 8px 4px;
	font-size: 10px;
	font-family: var(--font-family-mono);
	color: var(--text-2);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
	border-top: 1px solid var(--uk-glass-border, var(--glass-border));
}

/* The Client Preview's copy of the panel. It sits over the preview's own canvas
   (`.minimap-panel` is absolute, the preview stage is the positioned ancestor) and
   is always out — the preview has no toolbar to toggle it from. */
.minimap-panel--play { top: 12px; right: 12px; }

/* Only the preview's marker layer takes clicks; the editor's coverage overlay stays
   inert so it can never swallow a drag meant for the canvas underneath.

   The cursor stays neutral here on purpose: `PlayMinimap` writes `pointer` or
   `not-allowed` inline from the walkmap on every hovered cell, and a `pointer` default
   would promise "you can go here" over water for the moment before the first
   pointermove corrects it. */
.minimap-panel__overlay--interactive {
	pointer-events: auto;
	cursor: default;
}


/* ============================================================
   84. Ghost scrollbar (UIKit/ghostScrollbar.js)
   ============================================================ */

/* Global Thin Transparent Scrollbars with Fade Effect */
::-webkit-scrollbar {
    width: 6px;
    height: 6px;
}
::-webkit-scrollbar-track {
    background: transparent;
}
::-webkit-scrollbar-thumb {
    background: rgba(var(--uk-accent-rgb), 0.2);
    border-radius: 3px;
    transition: background var(--uk-dur-fast) var(--uk-ease);
}
::-webkit-scrollbar-thumb:hover {
    background: rgba(var(--uk-accent-rgb), 0.5);
}
/* For Firefox */
* {
    scrollbar-width: thin;
    scrollbar-color: rgba(var(--uk-accent-rgb), 0.3) transparent;
}
.uk-ghost-scroll-host { position: relative; }

.uk-ghost-scroll__view {
	scrollbar-width: none;          /* Firefox */
	-ms-overflow-style: none;
}

.uk-ghost-scroll__view::-webkit-scrollbar { width: 0; height: 0; display: none; }

/* Rectangular on purpose: a 3px bar with a radius reads as a dash, not a scrollbar.
   The thumb is positioned with `transform` so scrolling never lays out the panel. */
.uk-ghost-scroll {
	position: absolute;
	top: 0;
	right: 2px;
	width: 3px;
	background: var(--uk-ghost-scroll, color-mix(in srgb, var(--uk-accent) 60%, #7dd3fc));
	border-radius: 0;
	opacity: 0;
	pointer-events: none;
	will-change: transform;
	transition: opacity 420ms ease;
}

.uk-ghost-scroll.is-active {
	opacity: 1;
	pointer-events: auto;
	transition: opacity 110ms ease;
}

@media (prefers-reduced-motion: reduce) {
	.uk-ghost-scroll,
	.uk-ghost-scroll.is-active { transition: none; }
}


/* ============================================================
   85. Sidebar.TextureEditor — the map's ground-texture list
   ============================================================ */

/* The whole panel body is the list: the transform / add-texture / generate widgets
   this sidebar used to carry now live on the mode action rail, and the tool's own
   header moved to `.mode-panel__header`'s (i) badge. What is left is a two-up grid
   of tiles, each with its actions stacked beside it and everything else — name,
   path, slot id, pixel size — behind that tile's (i). */
#sidebar-texture-editor {
	display: flex;
	flex-direction: column;
	height: 100%;
	min-height: 0;
	overflow: hidden;                /* the inner view scrolls; the host must not */
	/* app.css's `.sidebar-content` puts vertical padding here. An absolutely
	   positioned child is laid out against the PADDING box, so the ghost thumb would
	   start a few pixels above the pane it is measuring. The grid carries its own
	   padding anyway. */
	padding: 0;
	gap: 0;
}

.texture-editor__view {
	flex: 1 1 auto;
	min-height: 0;
	overflow-y: auto;
	overflow-x: hidden;
}

.texture-grid {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 8px;
	padding: 8px;
	align-content: start;
}

.texture-grid .sidebar-info {
	grid-column: 1 / -1;
	padding: 12px 4px;
	font-size: 12px;
	color: var(--uk-text-3, var(--text-color-muted));
	text-align: center;
}

.texture-entry {
	display: flex;
	gap: 4px;
	min-width: 0;
	padding: 4px;
	border: 1px solid var(--uk-glass-border, var(--glass-border));
	border-radius: var(--uk-radius-sm, 6px);
	background: var(--uk-glass-sunken, var(--glass-sunken));
}

.texture-entry:hover { border-color: color-mix(in srgb, var(--uk-accent) 55%, transparent); }

/* Square, so a row of tiles lines up whatever the panel is resized to. The canvas
   inside carries its own intrinsic size (the texture's pixels), and the two max-*
   rules scale it down to fit while keeping its aspect ratio. */
.texture-entry__thumb {
	flex: 1 1 auto;
	min-width: 0;
	aspect-ratio: 1 / 1;
	display: flex;
	align-items: center;
	justify-content: center;
	background: var(--uk-surface-0, #000);
	border-radius: 3px;
	overflow: hidden;
}

.texture-entry__thumb canvas {
	max-width: 100%;
	max-height: 100%;
	image-rendering: pixelated;
	cursor: crosshair;
	touch-action: none;
}

.texture-entry__actions {
	flex: 0 0 auto;
	display: flex;
	flex-direction: column;
	gap: 2px;
}

.texture-entry__act {
	width: 20px;
	height: 20px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 0;
	font-size: 10px;
	line-height: 1;
	border: 1px solid transparent;
	border-radius: var(--uk-radius-sm, 6px);
	background: transparent;
	color: var(--uk-text-3, var(--text-color-muted));
	cursor: pointer;
}

.texture-entry__act:hover {
	background: color-mix(in srgb, var(--uk-accent) 16%, transparent);
	color: var(--uk-text-1, var(--text-color-primary));
}

.texture-entry__act--danger:hover {
	background: color-mix(in srgb, var(--uk-danger, #e5484d) 18%, transparent);
	color: var(--uk-danger, #e5484d);
}

.texture-entry__act:focus-visible {
	outline: 2px solid var(--uk-accent);
	outline-offset: 1px;
}

/* ── the (i) tooltip ─────────────────────────────────────────────────────────
   One shared element parked on <body>, opened to the LEFT of the badge that asked
   for it (the panel is flush with the right edge of the viewport). It takes pointer
   events because it carries the copy / reveal buttons — which is also why it hides
   on a short grace timer instead of on `mouseleave`. */
.tex-tip {
	position: fixed;
	z-index: 10050;
	min-width: 180px;
	max-width: 320px;
	padding: 8px 10px;
	display: none;
	flex-direction: column;
	gap: 4px;
	border: 1px solid var(--uk-glass-border, var(--glass-border));
	border-radius: var(--uk-radius-sm, 6px);
	background: var(--uk-glass-raised, var(--glass-raised));
	-webkit-backdrop-filter: blur(var(--glass-blur));
	backdrop-filter: blur(var(--glass-blur));
	box-shadow: var(--uk-glass-shadow, var(--glass-shadow));
	color: var(--uk-text-1, var(--text-color-primary));
	font-size: 11px;
	opacity: 0;
	transition: opacity 140ms ease;
}

.tex-tip.is-mounted { display: flex; }
.tex-tip.is-open { opacity: 1; }

.tex-tip__row {
	display: flex;
	align-items: center;
	gap: 4px;
	min-width: 0;
}

.tex-tip__label {
	flex: 0 0 auto;
	width: 34px;
	color: var(--uk-text-3, var(--text-color-muted));
	text-transform: uppercase;
	letter-spacing: 0.04em;
	font-size: 9px;
}

.tex-tip__val {
	flex: 1 1 auto;
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.tex-tip__val--mono {
	font-family: var(--uk-font-mono, 'IBM Plex Mono', monospace);
	color: var(--uk-text-2, var(--text-color-secondary));
}

.tex-tip__mini {
	flex: 0 0 auto;
	width: 18px;
	height: 18px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 0;
	font-size: 9px;
	border: 1px solid transparent;
	border-radius: 4px;
	background: transparent;
	color: var(--uk-text-3, var(--text-color-muted));
	cursor: pointer;
}

.tex-tip__mini:hover {
	background: color-mix(in srgb, var(--uk-accent) 18%, transparent);
	color: var(--uk-text-1, var(--text-color-primary));
}

.tex-tip__mini:focus-visible {
	outline: 2px solid var(--uk-accent);
	outline-offset: 1px;
}

@media (prefers-reduced-motion: reduce) {
	.tex-tip { transition: none; }
}

/* ── AI Terrain from Prompt (.ai-terrain-create) ─────────────────────────────
   Chat-driven terrain creation dialog. Left column: chat transcript + prompt +
   compile params + texture picks. Right column: TerrainPreview3D canvas.
   Window↔shell flex contract: the content box opts out of the scrolling
   document default; the shell fills the frame. */
.ai-terrain-create .ui-window__content {
	padding: 0;
	display: flex;
	min-height: 0;
	overflow: hidden;
}
.atc-shell {
	flex: 1;
	min-width: 0;
	display: flex;
	gap: 0;
	min-height: 0;
}
.atc-left {
	flex: 0 0 340px;
	min-width: 280px;
	display: flex;
	flex-direction: column;
	min-height: 0;
	padding: 10px;
	gap: 10px;
	border-right: 1px solid var(--keyline, var(--bs-border-color));
}
.atc-right {
	flex: 1;
	min-width: 0;
	display: flex;
	flex-direction: column;
	min-height: 0;
}
.atc-chat {
	flex: 1;
	min-height: 0;
	overflow-y: auto;
	display: flex;
	flex-direction: column;
	gap: 6px;
	padding: 4px;
}
.atc-msg {
	max-width: 92%;
	padding: 6px 9px;
	border-radius: var(--radius-md, 6px);
	font-size: 0.85rem;
	line-height: 1.35;
	white-space: pre-wrap;
}
.atc-msg--user {
	align-self: flex-end;
	background: color-mix(in srgb, var(--uk-accent) 20%, transparent);
	color: var(--uk-text-1, var(--text-color-primary));
}
.atc-msg--assistant {
	align-self: flex-start;
	background: var(--glass-raised, var(--surface-raised, rgba(128,128,128,.12)));
}
.atc-msg--system {
	align-self: center;
	opacity: 0.75;
	font-style: italic;
	font-size: 0.8rem;
}
.atc-prompt-row {
	display: flex;
	gap: 8px;
	align-items: stretch;
}
.atc-prompt-row .ui-field { flex: 1; min-width: 0; }
.atc-prompt-btns {
	display: flex;
	flex-direction: column;
	gap: 6px;
	justify-content: flex-end;
}
.atc-params {
	display: flex;
	flex-direction: column;
	gap: 6px;
}
.atc-seed-row {
	display: flex;
	gap: 6px;
	align-items: center;
}
.atc-seed-row .ui-field { flex: 1; min-width: 0; }
.atc-textures {
	display: flex;
	flex-direction: column;
	gap: 6px;
}
.atc-textures__title {
	font-weight: 600;
	font-size: 0.85rem;
	opacity: 0.85;
}
.atc-tex-row {
	display: flex;
	align-items: center;
	gap: 8px;
}
.atc-tex-row__label {
	flex: 0 0 56px;
	text-transform: capitalize;
	font-size: 0.85rem;
}
.atc-tex-row__status {
	flex: 1;
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	opacity: 0.7;
	font-size: 0.8rem;
}
.atc-canvas {
	flex: 1;
	min-height: 0;
	width: 100%;
	display: block;
}
.atc-actions {
	display: flex;
	gap: 8px;
	justify-content: flex-end;
	padding: 8px 10px;
	border-top: 1px solid var(--keyline, var(--bs-border-color));
}

