/* generated by Generator Studio — standard theme (DevExtreme-derived)
   UI Framework: Native · mode: dark
   Edit colours in Generator Studio, not here: this file is regenerated. */

:root {
    color-scheme: light dark;

    /* brand */
    --app-primary: #e02e96;
    --app-secondary: #6c757d;
    --app-accent: #49bc65;
    --ui-primary-hover: #e343a0;
    --ui-primary-active: #e654a9;
    --ui-secondary-hover: #7b838a;
    --ui-focus-ring: rgba(224,46,150,0.25);

    /* typography — DevExtreme Generic stack */
    --ui-font: 'Helvetica Neue', 'Segoe UI', Helvetica, Verdana, sans-serif;
    --ui-font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    --ui-font-size: 14px;
    --ui-font-size-sm: 12px;
    --ui-line-height: 1.5;
    --ui-font-weight-bold: 700;

    /* metrics */
    --ui-control-height: 32px;
    --ui-radius: 6px;
    --ui-radius-sm: 4px;
    --ui-pad-x: 8px;
    --ui-pad-y: 5px;
    --ui-row-gap: 10px;
    --ui-topbar-h: 62px;
    --ui-sidebar-w: 258px;
    --ui-subbar-h: 46px;
    --ui-gap: 6px;
    --ui-transition: 150ms ease;

    /* surfaces — light is always the base. The AdminLTE shell this
       template ships is not dark-aware, so emitting dark values at
       :root produced dark inputs and grids inside a white page. Dark
       is applied below, scoped to a body class, together with the
       page containers so the whole thing flips at once. */
    --ui-bg: #fff;
    --ui-bg-subtle: #f9f9f9;
    --ui-bg-hover: #f5f5f5;
    --ui-bg-active: #ebebeb;
    --ui-bg-disabled: #f5f5f5;
    --ui-bg-overlay: #fff;
    --ui-text: #333;
    --ui-text-muted: #626b75;
    --ui-text-disabled: #bbb;
    --ui-border: #ddd;
    --ui-border-strong: #c9c9c9;
    --ui-card-border: #e7e9ec;
    --ui-shadow: 0 4px 6px rgba(0,0,0,.16);
    --ui-shadow-lg: 0 10px 40px rgba(0,0,0,.25);
    --ui-text-inverse: #fff;

    /* status — DevExtreme Generic palette */
    --ui-danger: #d9534f;
    --ui-success: #5cb85c;
    --ui-warning: #f0ad4e;
    --ui-info: #5bc0de;
}

/* ==========================================================================
   1b. ONE TYPEFACE
   The shell loads Montserrat and Open Sans and applies them element by
   element, so a form came out with its labels in one face and its inputs
   in another, and the brand in a third. Rather than chase every shell
   selector, the family is stated on the document and restated on the
   elements the shell names directly.

   Deliberately no descendant or universal selectors here: icon fonts set
   their own family on the icon element, and a rule like ".btn *" would
   override it and turn every glyph into letters.
   ========================================================================== */

html,
body {
    font-family: var(--ui-font);
    font-size: var(--ui-font-size);
    line-height: var(--ui-line-height);
}

button,
input,
select,
textarea,
optgroup { font-family: var(--ui-font); }

h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 { font-family: var(--ui-font); }

label,
legend,
.form-label,
.col-form-label,
.card-title,
.card-header,
.breadcrumb,
.navbar-brand,
.brand-text,
.content-header-title,
.nav,
.btn,
.table,
table,
.modal,
.dropdown-menu,
.badge,
.alert { font-family: var(--ui-font); }

/* Widget frameworks keep their own class chains, so name them too. */
.dx-widget,
.dx-widget input,
.dx-widget textarea,
.tabulator,
.select2-container { font-family: var(--ui-font); }

/* Anything genuinely monospaced stays that way. */
code, kbd, pre, samp { font-family: var(--ui-font-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace); }

/* ==========================================================================
   2. NATIVE ADAPTER SKIN (.ua-*)
   Every rule below resolves to a token, never to a raw value, so the whole
   surface re-themes from :root alone.
   ========================================================================== */

.ua-input,
.ua-button,
.ua-dd-input,
.ua-grid,
.ua-dialog,
.ua-popup {
    font-family: var(--ui-font);
    font-size: var(--ui-font-size);
    line-height: var(--ui-line-height);
}

/* ---- text inputs ---- */
.ua-input {
    width: 100%;
    min-height: var(--ui-control-height);
    padding: var(--ui-pad-y) var(--ui-pad-x);
    color: var(--ui-text);
    background: var(--ui-bg);
    border: 1px solid var(--ui-border);
    border-radius: var(--ui-radius);
    box-sizing: border-box;
    transition: border-color var(--ui-transition), box-shadow var(--ui-transition);
}
.ua-input::placeholder { color: var(--ui-text-muted); }
.ua-input:hover { border-color: var(--ui-border-strong); }
/* A ring rather than the browser outline: outline sits outside the border
   box and clips inside table cells and the grid filter row. */
.ua-input:focus,
.ua-input:focus-visible {
    outline: none;
    border-color: var(--app-primary);
    box-shadow: 0 0 0 3px var(--ui-focus-ring);
}
.ua-input:disabled,
.ua-input[readonly] {
    background: var(--ui-bg-disabled);
    color: var(--ui-text-disabled);
    cursor: not-allowed;
}
textarea.ua-input { min-height: calc(var(--ui-control-height) * 2); resize: vertical; }

.ua-radio-label,
.ua-switch-label {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    color: var(--ui-text);
    font-family: var(--ui-font);
    font-size: var(--ui-font-size);
}
.ua-radio-label { margin-right: 14px; }

/* ---- buttons ---- */
.ua-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    min-height: var(--ui-control-height);
    /* was a fixed 16px, which left density and theme family changing the
       button's height but never its width */
    padding: 0 calc(var(--ui-pad-x) * 2);
    color: var(--ui-text);
    background: var(--ui-bg);
    border: 1px solid var(--ui-border);
    border-radius: var(--ui-radius);
    cursor: pointer;
    white-space: nowrap;
    transition: background var(--ui-transition), border-color var(--ui-transition);
}
.ua-button:hover { background: var(--ui-bg-hover); }
.ua-button:active { background: var(--ui-bg-active); }
.ua-button:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--ui-focus-ring); }
.ua-button:disabled { color: var(--ui-text-disabled); background: var(--ui-bg-disabled); cursor: not-allowed; }
/* Inline SVG icons: sized in em so they track the control's font-size,
   and stroke inherits currentColor so one path set serves every variant. */
.ua-icon { width: 1.05em; height: 1.05em; flex: 0 0 auto; vertical-align: -0.15em; }
.ua-button > .ua-icon { margin: 0; }
.ua-grid-btn .ua-icon { width: 1.1em; height: 1.1em; }
.ua-dd-btn .ua-icon,
.ua-dd-toggle .ua-icon { width: 1em; height: 1em; }

.ua-button-default {
    color: var(--ui-text-inverse);
    background: var(--app-primary);
    border-color: var(--app-primary);
}
.ua-button-default:hover { background: var(--ui-primary-hover); border-color: var(--ui-primary-hover); }
.ua-button-default:active { background: var(--ui-primary-active); border-color: var(--ui-primary-active); }
.ua-button-normal { color: var(--ui-text-inverse); background: var(--app-secondary); border-color: var(--app-secondary); }
.ua-button-normal:hover { background: var(--ui-secondary-hover); border-color: var(--ui-secondary-hover); }
.ua-button-success { color: var(--ui-text-inverse); background: var(--ui-success); border-color: var(--ui-success); }
.ua-button-danger  { color: var(--ui-text-inverse); background: var(--ui-danger);  border-color: var(--ui-danger); }

/* ---- lookup dropdown (SelectBox / Autocomplete / TagBox) ---- */
.ua-dd { position: relative; }
.ua-dd-input { padding-right: 30px; }

.ua-dd-clear,
.ua-dd-toggle,
.ua-dd-btn {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    background: none;
    border: none;
    cursor: pointer;
    color: var(--ui-text-muted);
    line-height: 1;
    transition: color var(--ui-transition);
}
.ua-dd-clear { right: 26px; font-size: 18px; padding: 0 4px; }
.ua-dd-toggle { right: 4px; padding: 4px 6px; }
.ua-dd-clear:hover,
.ua-dd-toggle:hover,
.ua-dd-btn:hover { color: var(--app-primary); }

.ua-dd-caret {
    display: inline-block;
    width: 0; height: 0;
    border-left: 5px solid transparent;
    border-right: 5px solid transparent;
    border-top: 6px solid currentColor;
    transition: transform var(--ui-transition);
}
.ua-dd-open .ua-dd-caret { transform: rotate(180deg); }

.ua-dd-extras { position: absolute; right: 22px; top: 50%; transform: translateY(-50%); display: inline-flex; align-items: center; }
.ua-dd-btn { position: static; transform: none; padding: 4px 5px; }

/* Room reserved inside the field per visible button, so the icons never
   sit on top of the text. */
.ua-dd-btns-1 .ua-dd-input { padding-right: 30px; }
.ua-dd-btns-2 .ua-dd-input { padding-right: 74px; }
.ua-dd-btns-3 .ua-dd-input { padding-right: 98px; }
.ua-dd-btns-2 .ua-dd-clear { right: 48px; }
.ua-dd-btns-3 .ua-dd-clear { right: 72px; }

.ua-dd-list {
    /* Fixed, and placed by the adapter: absolute positioning left the
       list inside .card, which clips its overflow. Left, top, width
       and max-height are all set inline when it opens. */
    position: fixed;
    z-index: 1080;
    max-height: 260px;
    overflow-y: auto;
    background: var(--ui-bg-overlay);
    color: var(--ui-text);
    border: 1px solid var(--ui-border);
    border-radius: var(--ui-radius);
    box-shadow: var(--ui-shadow);
}
.ua-dd-option {
    padding: var(--ui-pad-y) var(--ui-pad-x);
    cursor: pointer;
    transition: background var(--ui-transition);
}
.ua-dd-option:hover { background: var(--ui-bg-hover); }
/* Keyboard focus is the strong state; hover stays subtle so the two are
   distinguishable when both apply. */
.ua-dd-active { background: var(--app-primary); color: var(--ui-text-inverse); }
.ua-dd-empty,
.ua-dd-more { padding: var(--ui-pad-y) var(--ui-pad-x); color: var(--ui-text-muted); font-size: var(--ui-font-size-sm); }
.ua-dd-more { border-top: 1px solid var(--ui-border); }
.ua-dd-action .ui-link { color: var(--app-primary); }
.ua-dd-active.ua-dd-action .ui-link { color: var(--ui-text-inverse); }

.ua-dd-tags { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 4px; }
.ua-dd-tag {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 8px;
    background: var(--app-primary);
    color: var(--ui-text-inverse);
    border-radius: 12px;
    font-size: var(--ui-font-size-sm);
}
.ua-dd-tag-x { background: none; border: none; color: inherit; cursor: pointer; font-size: 14px; line-height: 1; padding: 0; }

/* ---- validation ---- */
.ua-invalid .ua-input,
.ua-invalid .ua-dd-input,
.ua-invalid input,
.ua-invalid textarea,
.ua-invalid select { border-color: var(--ui-danger); }
.ua-invalid .ua-input:focus { box-shadow: 0 0 0 3px rgba(217,83,79,.25); }
.ua-invalid-badge {
    position: absolute;
    right: 6px; top: 50%;
    transform: translateY(-50%);
    width: 16px; height: 16px;
    border-radius: 50%;
    background: var(--ui-danger);
    color: var(--ui-text-inverse);
    font-size: 11px;
    font-weight: var(--ui-font-weight-bold);
    line-height: 16px;
    text-align: center;
    cursor: help;
    z-index: 2;
}
.ua-invalid-message { color: var(--ui-danger); font-size: var(--ui-font-size-sm); margin-top: 4px; }
.ua-validation-summary { color: var(--ui-danger); font-size: var(--ui-font-size-sm); }

/* ---- overlays ---- */
.ua-dialog-backdrop,
.ua-popup-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,.45); z-index: 1050; }
.ua-dialog,
.ua-popup {
    position: fixed;
    z-index: 1060;
    top: 50%; left: 50%;
    transform: translate(-50%,-50%);
    min-width: 320px;
    max-width: 95vw;
    max-height: 90vh;
    overflow: auto;
    background: var(--ui-bg-overlay);
    color: var(--ui-text);
    border-radius: var(--ui-radius);
    box-shadow: var(--ui-shadow-lg);
}
.ua-dialog { padding: 20px; }
.ua-dialog-title { font-weight: 600; margin-bottom: 10px; }
.ua-dialog-buttons { display: flex; justify-content: flex-end; gap: var(--ui-gap); margin-top: 18px; }
.ua-popup-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 16px;
    border-bottom: 1px solid var(--ui-border);
    font-weight: 600;
}
.ua-popup-close { background: none; border: none; font-size: 22px; line-height: 1; cursor: pointer; color: var(--ui-text-muted); }
.ua-popup-close:hover { color: var(--ui-text); }
.ua-popup-content { padding: 16px; }
.ua-popup-toolbar {
    display: flex;
    justify-content: flex-end;
    gap: var(--ui-gap);
    padding: 12px 16px;
    border-top: 1px solid var(--ui-border);
}

.ua-toast-host { position: fixed; z-index: 1070; top: 16px; right: 16px; display: flex; flex-direction: column; gap: var(--ui-gap); }
.ua-toast {
    padding: 10px 16px;
    border-radius: var(--ui-radius);
    color: var(--ui-text-inverse);
    background: var(--app-secondary);
    box-shadow: var(--ui-shadow);
    font-family: var(--ui-font);
    font-size: var(--ui-font-size);
}
.ua-toast-success { background: var(--ui-success); }
.ua-toast-error   { background: var(--ui-danger); }
.ua-toast-warning { background: var(--ui-warning); }
.ua-toast-info    { background: var(--ui-info); }

.ua-toolbar { display: flex; align-items: center; justify-content: space-between; gap: var(--ui-gap); padding: 6px 0; }
.ua-toolbar-before, .ua-toolbar-center, .ua-toolbar-after { display: flex; align-items: center; gap: var(--ui-gap); }

.ua-drawer {
    position: fixed;
    z-index: 1040;
    top: 0; bottom: 0;
    width: 280px;
    background: var(--ui-bg);
    box-shadow: var(--ui-shadow-lg);
    transition: transform .2s ease;
}
.ua-drawer-left { left: 0; transform: translateX(-100%); }
.ua-drawer-right { right: 0; transform: translateX(100%); }
.ua-drawer-open { transform: translateX(0); }

.ua-map { width: 100%; min-height: 320px; }
.ua-map-unavailable,
.ua-grid-unavailable {
    padding: 16px;
    border: 1px dashed var(--ui-border);
    border-radius: var(--ui-radius);
    color: var(--ui-text-muted);
}

/* ---- unified surfaces ----
   Framework cards previously used a darker outline and a different
   corner radius than dialogs, grids and builder panels. A quiet
   hairline keeps groups readable without boxing every section in. */
.card,
.modal-content,
.dropdown-menu,
.popover,
.tabulator,
.dx-overlay-content {
    border-radius: var(--ui-radius);
}
.card {
    border: 1px solid var(--ui-card-border);
    box-shadow: 0 1px 2px rgba(0, 0, 0, .04);
    overflow: hidden;
}
.card-header,
.card-footer {
    border-color: var(--ui-card-border);
}
.card-header:first-child,
.card-footer:last-child {
    border-radius: 0;
}
body.app-dark .card {
    box-shadow: 0 1px 2px rgba(0, 0, 0, .18);
}

/* ---- form density ----
   The generated create/edit views lay fields out in Bootstrap rows. The
   template's default gutters were tuned for a handful of fields, not the
   ~20 these entities produce, so rows are tightened here rather than in
   each generated view. */
.ua-form-row,
.card-body .row > [class^='col-'] > .form-group,
.card-body .row > [class*=' col-'] > .form-group { margin-bottom: var(--ui-row-gap); }
.card-body .form-group > label { margin-bottom: 2px; font-size: var(--ui-font-size); color: var(--ui-text); }

/* Client-supplied logos arrive at arbitrary sizes; every slot that
   shows one gets a hard cap so a 2000px upload cannot cover the
   screen. width:auto preserves aspect ratio within the cap. */
.header-navbar .brand-logo,
.navbar-header img,
.main-menu img,
.navbar-brand img {
    max-height: 34px;
    width: auto;
    max-width: 160px;
    object-fit: contain;
}
.preloader img, .loader img { max-height: 72px; width: auto; }

/* ---- topbar (white, DevExtreme-demos style) ----
   The header partial keeps its Bootstrap/AdminLTE skeleton; only the
   surface is defined here. High-specificity shell rules for
   .header-navbar are out-specified by the class chain, and this file
   loads last. */
.header-navbar.ua-topbar {
    background: var(--ui-bg-overlay);
    border-bottom: 1px solid var(--ui-border);
    box-shadow: none;
    /* Above the sidebar rail (1020). The theme never stated this, so
       the shell's own value applied; with the rail pinned to left 0 it
       covered the navbar's left corner — which is where the menu
       toggle lives, so the button could not be clicked at all. */
    z-index: 1030;
}
.header-navbar.ua-topbar .nav-link,
.header-navbar.ua-topbar .navbar-brand,
.header-navbar.ua-topbar .brand-text,
.header-navbar.ua-topbar .user-name,
.header-navbar.ua-topbar i {
    color: var(--ui-text) !important;
}
.header-navbar.ua-topbar .nav-link:hover,
.header-navbar.ua-topbar .nav-link:hover i { color: var(--app-primary) !important; }
.header-navbar.ua-topbar .brand-text { font-weight: var(--ui-font-weight-bold); }
/* the shell paints these with the primary colour; on a white bar that
   left a stray blue block beside the toggles */
.header-navbar.ua-topbar .navbar-header,
.header-navbar.ua-topbar .navbar-container,
.header-navbar.ua-topbar .navbar-wrapper { background: transparent; }
.header-navbar.ua-topbar .dropdown-menu {
    background: var(--ui-bg-overlay);
    border: 1px solid var(--ui-border);
    border-radius: var(--ui-radius);
    box-shadow: var(--ui-shadow);
}
.header-navbar.ua-topbar .dropdown-item { color: var(--ui-text); }
.header-navbar.ua-topbar .dropdown-item:hover { background: var(--ui-bg-hover); color: var(--app-primary); }
.header-navbar.ua-topbar .search-input .input {
    background: var(--ui-bg);
    color: var(--ui-text);
    border: 1px solid var(--ui-border);
    border-radius: var(--ui-radius);
}
/* the secondary horizontal menu strip under the topbar */
.header-navbar.navbar-horizontal {
    background: var(--ui-bg-overlay);
    border-bottom: 1px solid var(--ui-border);
}

/* ---- auth (login/register) pages ----
   blank-page shells: subtle page background, the existing card
   markup inside gets elevated and centred. */
body.ua-auth-page,
body.ua-error-page { background: var(--ui-bg-subtle); }
/* Block flow with a margin-centred card, NOT flex on the wrapper:
   the login views nest the card in Bootstrap .row/.col chains whose
   widths are percentages, and a shrink-to-fit flex container
   collapsed that whole chain to intrinsic width - a 140px card with
   the title wrapping letter by letter. */
/* Grid with align-content:center gives true vertical centring while
   justify-items:stretch keeps children full-width - unlike flex or
   place-items:center, which shrink-wrap the child and re-collapse
   the view's percentage-based column chain. */
body.ua-auth-page .content-wrapper,
body.ua-error-page .content-wrapper {
    display: grid;
    align-content: center;
    justify-items: stretch;
    min-height: calc(100vh - 40px);
    padding: 24px 16px;
}
body.ua-auth-page .content-wrapper .row { margin: 0; }
/* The login view wraps its card in section.flexbox-container >
   .col-12.d-flex > .col-lg-4. Every layer of that chain is flattened
   to a full-width block so the card's own margin:auto is the single
   centring mechanism - mixing the shell's flex chain with forced
   widths is what previously parked the card at the left edge. */
body.ua-auth-page .content-wrapper section,
body.ua-auth-page .content-wrapper .flexbox-container,
body.ua-auth-page .content-wrapper .d-flex,
body.ua-auth-page .content-wrapper [class^='col-'],
body.ua-auth-page .content-wrapper [class*=' col-'] {
    display: block !important;
    width: 100% !important;
    max-width: none;
    flex: none;
    padding: 0;
    height: auto !important;
}
body.ua-auth-page .card,
body.ua-error-page .card {
    background: var(--ui-bg-overlay);
    color: var(--ui-text);
    border: 1px solid var(--ui-card-border);
    border-radius: var(--ui-radius);
    box-shadow: var(--ui-shadow-lg);
    width: 100%;
    max-width: 430px;
    /* the login view puts .m-0 on this card, which is margin:0
       !important in Bootstrap and silently beat a plain margin:auto */
    margin-left: auto !important;
    margin-right: auto !important;
    float: none !important;
}
/* keep the remember-me / forgot-password row on one line each side */
body.ua-auth-page .card label { white-space: nowrap; }
body.ua-auth-page .card .card-header,
body.ua-auth-page .card .card-title { border: none; background: transparent; text-align: center; }
body.ua-auth-page .card img { max-height: 64px; width: auto; max-width: 80%; object-fit: contain; }
body.ua-error-page .card { max-width: 560px; text-align: center; }
/* the generated error views title with h2.error-code, not h1 */
body.ua-error-page .error-code,
body.ua-error-page h1 {
    font-size: 72px;
    font-weight: var(--ui-font-weight-bold);
    color: var(--app-primary);
    margin-bottom: 4px;
}
body.ua-error-page .content-wrapper { padding-top: 16vh; }
body.ua-error-page .content-wrapper > * { max-width: 640px; margin-left: auto; margin-right: auto; }
body.ua-auth-page .btn-primary,
body.ua-error-page .btn-primary,
body.ua-auth-page .btn-danger,
body.ua-auth-page .input-group .btn {
    background: var(--app-primary);
    border-color: var(--app-primary);
    color: var(--ui-text-inverse);
}
body.ua-auth-page .btn-primary:hover,
body.ua-error-page .btn-primary:hover {
    background: var(--ui-primary-hover);
    border-color: var(--ui-primary-hover);
}

/* ---- tree menu (DevExtreme-demos style sidebar) ----
   The shell markup keeps its menu-dark class because the template's
   own JS keys on it; the surface is restyled here instead. Light
   sidebar on light mode, token-driven so dark mode flips it too. */
/* Docked to the left edge, full height under the topbar, flush - no
   float, no rounding, no drop shadow. The shell shipped it as a
   detached floating panel and nothing reserved space for it, so
   content ran underneath. */
.main-menu,
.main-menu.menu-dark,
.main-menu.menu-light {
    position: fixed;
    top: var(--ui-topbar-h);
    left: 0;
    bottom: 0;
    width: var(--ui-sidebar-w);
    /* strictly under Bootstrap's .fixed-top (1030) so the navbar and
       its dropdowns always win; the sidebar previously covered them */
    z-index: 1020;
    overflow-x: hidden;
    overflow-y: auto;
    background: var(--ui-bg-overlay);
    border-right: 1px solid var(--ui-border);
    border-radius: 0;
    box-shadow: none;
    transition: width var(--ui-transition);
}
/* The inner column keeps its full width while the outer element
   animates to zero, so nothing rewraps mid-slide. */
.main-menu .main-menu-content,
.main-menu .ua-nav,
.main-menu .ua-nav-search { width: var(--ui-sidebar-w); }
.main-menu .main-menu-content { padding-top: 0; }

/* Content reserves the sidebar's width. Scoped away from blank-page,
   which is what the login and error layouts use - they have no menu
   and must not be indented by it. */
body:not(.blank-page) .app-content {
    margin-left: var(--ui-sidebar-w);
    /* The shell indents .app-content for its own rail as well. Left in
       place that stacks with the margin above and the content starts at
       roughly twice the sidebar width, so the reservation is expressed
       once, here. */
    padding-left: 0;
    transition: margin-left var(--ui-transition);
}

/* Collapsed: the menu is text-only below the dashboard row, so an
   icon rail would show nothing useful - it closes fully instead,
   which is also what the reference sidebar's toggle does. */
/* The shell's own rail geometry, overridden.
   vertical-overlay-menu positions .main-menu through selectors more
   specific than anything above (body.vertical-overlay-menu.menu-open
   .main-menu and friends), so the plain .main-menu rules lost and the
   rail rendered one sidebar-width to the right of where the content
   margin had reserved space for it. Matching that specificity would
   mean guessing at the shell's exact selector chain; these six
   properties are geometry we own outright, so they are pinned. Nothing
   cosmetic is forced — colour, borders and shadow still come from the
   rules above and stay themeable. */
body:not(.app-menu-collapsed) .main-menu {
    position: fixed !important;
    /* Starts below the navbar. --ui-topbar-h is measured from
       .header-navbar at runtime and falls back to 62px, so the rail
       never overlaps the toggle even before the measurement lands. */
    top: var(--ui-topbar-h) !important;
    left: 0 !important;
    right: auto !important;
    bottom: 0 !important;
    width: var(--ui-sidebar-w) !important;
    margin: 0 !important;
    padding-left: 0 !important;
    /* a width rule cannot undo a transform, which is what kept the rail
       parked off-canvas before */
    transform: none !important;
    visibility: visible;
    opacity: 1;
}
body.app-menu-collapsed .main-menu {
    left: 0 !important;
    /* Pinned as well: a collapsed rail left at full width would keep
       covering whatever sits beneath it, including the toggle. */
    width: 0 !important;
    min-width: 0 !important;
    padding: 0 !important;
    transform: none !important;
    margin: 0 !important;
    overflow: hidden !important;
}
body.app-menu-collapsed .main-menu { width: 0; border-right-color: transparent; }
body.app-menu-collapsed:not(.blank-page) .app-content { margin-left: 0; }

@media (max-width: 991.98px) {
    /* On a small screen the rail overlays the page rather than
       displacing it — there is not enough width to give away. Pinned,
       because the base indent is pinned and the shell adds its own. */
    body:not(.blank-page) .app-content {
        margin-left: 0 !important;
        padding-left: 0 !important;
    }

    body:not(.app-menu-collapsed) .main-menu {
        /* never the full screen: the page stays visible behind it, so
           it reads as a panel over the page rather than a new one */
        width: min(86vw, var(--ui-sidebar-w)) !important;
        box-shadow: var(--ui-shadow-lg);
        z-index: 1025;
    }

    .main-menu .main-menu-content,
    .main-menu .ua-nav,
    .main-menu .ua-nav-search { width: 100%; }

    /* Dimmed page behind the open rail. Tapping it closes the menu,
       wired in the switcher, which is the gesture anyone expects from
       an overlay. */
    body:not(.app-menu-collapsed)::after {
        content: '';
        position: fixed;
        top: var(--ui-topbar-h);
        left: 0;
        right: 0;
        bottom: 0;
        background: rgba(0, 0, 0, .45);
        z-index: 1024;
    }

    /* Touch targets. 32px is fine for a mouse and not for a thumb. */
    .ua-nav .ua-nav-link,
    .ua-nav .ua-nav-parent > a { min-height: 44px; }
}

@media (max-width: 575.98px) {
    /* The header carries a brand, a toggle and a user menu; below this
       width they need to stop competing for the same row. */
    .header-navbar.ua-topbar .navbar-container { padding-left: 8px; padding-right: 8px; }
    .header-navbar.ua-topbar .brand-text { display: none; }
    body:not(.blank-page) .content-header {
        flex-wrap: wrap;
        row-gap: 6px;
        padding-left: 12px;
        padding-right: 12px;
    }
    .app-content { padding-left: 10px; padding-right: 10px; }
}

.ua-nav {
    list-style: none;
    margin: 0;
    padding: 0 0 24px;
    font-family: var(--ui-font);
    font-size: var(--ui-font-size);
}
.ua-nav ul { list-style: none; margin: 0; padding: 0; }

/* Shown when the menu service returns nothing, so an empty rail always
   says why rather than looking like a dead toggle. */
.ua-nav-note {
    padding: 12px 16px;
    font-size: var(--ui-font-size-sm);
    line-height: 1.5;
    color: var(--ui-text-muted);
}

/* section header: bold row with a rotating chevron, like the demo
   sidebar's category headings */
.ua-nav-head {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 9px 14px;
    background: none;
    border: none;
    cursor: pointer;
    text-align: left;
    color: var(--ui-text);
    font-family: inherit;
    font-size: inherit;
    font-weight: var(--ui-font-weight-bold);
    transition: background var(--ui-transition), color var(--ui-transition);
}
.ua-nav-head:hover { background: var(--ui-bg-hover); }
.ua-nav-title { flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ua-nav-chev { width: 14px; height: 14px; color: var(--ui-text-muted); transition: transform var(--ui-transition); }
.open > .ua-nav-head > .ua-nav-chev { transform: rotate(180deg); }

/* second level: normal-weight rows with the small solid caret the
   demo list items use, rotating when expanded */
.ua-nav-subhead { font-weight: 400; padding: 7px 14px 7px 22px; }
.ua-nav-caret { width: 12px; height: 12px; color: var(--ui-text-muted); transition: transform var(--ui-transition); flex: 0 0 auto; }
.open > .ua-nav-subhead > .ua-nav-caret { transform: rotate(90deg); color: var(--app-primary); }

/* collapse/expand */
.ua-nav-children { display: none; }
.open > .ua-nav-children { display: block; }

/* leaves */
.ua-nav-link {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 7px 14px 7px 38px;
    color: var(--ui-text);
    text-decoration: none;
    border-left: 3px solid transparent;
    transition: background var(--ui-transition), color var(--ui-transition);
}
.ua-nav-top > .ua-nav-link { padding-left: 14px; font-weight: var(--ui-font-weight-bold); }
.ua-nav-link:hover { background: var(--ui-bg-hover); color: var(--app-primary); }
.ua-nav-link .ua-icon { width: 15px; height: 15px; flex: 0 0 auto; }

/* active leaf: accent bar + tinted row, active trail stays open via
   the server-rendered 'open'/'active' classes from Html.IsSelected */
.ua-nav-leaf.active > .ua-nav-link,
.ua-nav-leaf.open > .ua-nav-link {
    border-left-color: var(--app-primary);
    background: var(--ui-focus-ring);
    color: var(--app-primary);
    font-weight: var(--ui-font-weight-bold);
}

/* ---- secondary bar: breadcrumb + menu toggle ----
   Fixed under the topbar and starting at the sidebar's right edge,
   exactly as the reference does: it stays put while the page
   scrolls, and slides to the viewport edge when the menu collapses.
   _PageHeading renders .content-header.row, so that IS the bar
   rather than something wrapped around it. */
body:not(.blank-page) .content-header {
    position: fixed;
    top: var(--ui-topbar-h);
    left: var(--ui-sidebar-w);
    right: 0;
    z-index: 900;
    display: flex;
    align-items: center;
    flex-wrap: nowrap;
    gap: 12px;
    min-height: var(--ui-subbar-h);
    margin: 0;
    padding: 0 16px;
    background: var(--ui-bg-subtle);
    border-bottom: 1px solid var(--ui-border);
    transition: left var(--ui-transition);
}
body.app-menu-collapsed:not(.blank-page) .content-header { left: 0; }
@media (max-width: 991.98px) {
    /* menu overlays rather than displaces, so the bar spans fully */
    body:not(.blank-page) .content-header { left: 0; }
}

/* the partial lays the bar out as a Bootstrap .row of columns; those
   columns become flex children of the bar instead */
body:not(.blank-page) .content-header > [class^='col-'],
body:not(.blank-page) .content-header > [class*=' col-'] {
    flex: 0 0 auto;
    width: auto;
    max-width: none;
    padding: 0;
}
/* whatever the partial puts second is pushed to the right edge */
body:not(.blank-page) .content-header > [class^='col-']:last-child,
body:not(.blank-page) .content-header > [class*=' col-']:last-child {
    margin-left: auto;
    text-align: right;
}
body:not(.blank-page) .content-header .breadcrumb {
    display: flex;
    flex-wrap: nowrap;
    margin: 0;
    padding: 0;
    background: transparent;
    font-size: var(--ui-font-size);
    white-space: nowrap;
}
body:not(.blank-page) .content-header .breadcrumb-item.active { color: var(--ui-text-muted); }
body:not(.blank-page) .content-header .breadcrumb a { color: var(--app-primary); }

/* content clears the fixed bar */
body:not(.blank-page) .content-wrapper { padding-top: calc(var(--ui-subbar-h) + 18px); }

/* Security access pages render their own heading followed by a page
   shell. Keep that shell below the fixed breadcrumb bar so the title,
   actions and tabs remain visible in every theme. */
body:not(.blank-page) .access-management-content {
    margin-top: var(--ui-subbar-h);
}

/* sidebar search, pinned above the tree like the reference */
.ua-nav-search {
    position: sticky;
    top: 0;
    z-index: 2;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 12px;
    background: var(--ui-bg-overlay);
    border-bottom: 1px solid var(--ui-border);
    box-sizing: border-box;
}
.ua-nav-search svg { width: 15px; height: 15px; color: var(--ui-text-muted); flex: 0 0 auto; }
.ua-nav-search input {
    flex: 1 1 auto;
    min-width: 0;
    border: none;
    outline: none;
    background: transparent;
    color: var(--ui-text);
    font-family: var(--ui-font);
    font-size: var(--ui-font-size);
}
.ua-nav-search input::placeholder { color: var(--ui-text-muted); }
/* while filtering, every surviving branch is shown open */
.ua-nav-filtered .ua-nav-children { display: block; }

/* always-visible collapse toggle at the left of the content header */
.ua-menu-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px; height: 32px;
    margin-right: 10px;
    padding: 0;
    border: 1px solid transparent;
    border-radius: var(--ui-radius);
    background: transparent;
    color: var(--ui-text-muted);
    cursor: pointer;
    vertical-align: middle;
}
.ua-menu-btn:hover { background: var(--ui-bg-hover); color: var(--app-primary); }
.ua-menu-btn svg { width: 18px; height: 18px; }

/* ---- theme switcher ---- */
.ua-theme-gear {
    position: fixed;
    right: 18px; bottom: 18px;
    z-index: 1090;
    width: 42px; height: 42px;
    display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid var(--ui-border);
    border-radius: 50%;
    background: var(--ui-bg-overlay);
    color: var(--ui-text-muted);
    cursor: pointer;
    box-shadow: var(--ui-shadow);
    transition: color var(--ui-transition), transform var(--ui-transition);
}
.ua-theme-gear:hover { color: var(--app-primary); transform: rotate(20deg); }
.ua-theme-gear svg { width: 20px; height: 20px; }
.ua-theme-panel {
    position: fixed;
    right: 18px; bottom: 68px;
    z-index: 1090;
    width: 230px;
    padding: 14px;
    background: var(--ui-bg-overlay);
    color: var(--ui-text);
    border: 1px solid var(--ui-border);
    border-radius: var(--ui-radius);
    box-shadow: var(--ui-shadow-lg);
    font-family: var(--ui-font);
    font-size: var(--ui-font-size);
}
.ua-theme-group { margin-bottom: 12px; }
.ua-theme-label { font-size: var(--ui-font-size-sm); color: var(--ui-text-muted); margin-bottom: 5px; text-transform: uppercase; letter-spacing: .04em; }
.ua-theme-seg { display: flex; border: 1px solid var(--ui-border); border-radius: var(--ui-radius); overflow: hidden; }
.ua-theme-opt {
    flex: 1;
    padding: 5px 0;
    border: none;
    background: var(--ui-bg);
    color: var(--ui-text);
    cursor: pointer;
    font-size: var(--ui-font-size-sm);
}
.ua-theme-opt + .ua-theme-opt { border-left: 1px solid var(--ui-border); }
.ua-theme-opt.ua-theme-on { background: var(--app-primary); color: var(--ui-text-inverse); }
.ua-theme-swatches { display: flex; gap: 8px; flex-wrap: wrap; }
.ua-theme-swatch {
    width: 22px; height: 22px;
    border-radius: 50%;
    border: 2px solid var(--ui-border);
    cursor: pointer;
    padding: 0;
}
.ua-theme-swatch.ua-theme-on { border-color: var(--ui-text); box-shadow: 0 0 0 2px var(--ui-focus-ring); }
.ua-theme-reset {
    width: 100%;
    padding: 6px 0;
    border: 1px solid var(--ui-border);
    border-radius: var(--ui-radius);
    background: var(--ui-bg);
    color: var(--ui-text-muted);
    cursor: pointer;
    font-size: var(--ui-font-size-sm);
}
.ua-theme-reset:hover { color: var(--ui-text); background: var(--ui-bg-hover); }

/* ---- grid chrome ---- */
:root { --ui-bg-surface: var(--ui-bg); }
body.app-dark { --ui-bg-surface: var(--ui-bg); }
.ua-grid { width: 100%; min-width: 0; }
.ua-grid-card-details { display: grid; grid-template-columns: minmax(100px, 1fr) minmax(0, 2fr); gap: 8px 16px; margin: 0; padding: 12px; white-space: normal; }
.ua-grid-card-details dt { color: var(--ui-text-muted); font-weight: 500; overflow-wrap: anywhere; }
.ua-grid-card-details dd { color: var(--ui-text); margin: 0; overflow-wrap: anywhere; }
.app-content, .content-wrapper, .content-body, .card-body { min-width: 0; }
.app-content .btn-primary { background: var(--app-primary); border-color: var(--app-primary); color: var(--ui-text-inverse); }
.app-content .text-muted { color: var(--ui-text-muted) !important; }
body.app-dark .app-content .text-body { color: var(--ui-text) !important; }
.form-body .row { row-gap: var(--ui-row-gap); }
.form-body .col-form-label { overflow-wrap: anywhere; }
.form-body > .mg-l-auto { display: flex; flex-wrap: wrap; gap: 8px; padding-bottom: 12px; }
@media (max-width: 767.98px) {
    body:not(.blank-page) .content-header > [class*='col-']:last-child { display: none; }
    body:not(.blank-page) .content-header > [class*='col-'] { flex: 1 1 auto; min-width: 0; overflow: hidden; }
    body:not(.blank-page) .content-header .breadcrumb { overflow: auto; }
    .app-content .content-wrapper { padding: 12px; }
    .app-content .card-body { padding: 12px; }
    .ua-grid-toolbar-before, .ua-grid-toolbar-after { flex-wrap: wrap; max-width: 100%; }
    .ua-grid-toolbar-after { width: 100%; }
    .ua-grid-search { flex: 1; min-width: 0; max-width: 100%; }
    .tabulator .tabulator-footer .tabulator-footer-contents { display: flex; flex-wrap: wrap; gap: 12px; }
    .tabulator .tabulator-footer .tabulator-paginator { display: flex; flex-wrap: wrap; gap: 8px; margin: 0; }
    .tabulator .tabulator-footer .tabulator-pages { margin: 0; }
    .ua-input, .ua-button { min-height: 44px; }
    .ua-form-field { grid-column: 1 / -1 !important; width: 100% !important; }
    .form-body .col-form-label { padding-bottom: 4px; }
}
.ua-grid-toolbar { display: flex; align-items: center; justify-content: space-between; gap: var(--ui-gap); margin-bottom: var(--ui-gap); flex-wrap: wrap; }
.ua-grid-toolbar-before, .ua-grid-toolbar-after { display: flex; align-items: center; gap: 6px; }
.ua-grid-search { width: 220px; }
.ua-grid-buttons { display: flex; gap: var(--ui-gap); justify-content: center; }
.ua-grid-btn { color: var(--app-primary); text-decoration: none; }
.ua-grid-btn:hover { opacity: .7; }
.ua-grid-loading { position: relative; opacity: .6; pointer-events: none; }
.ua-colchooser-row { display: flex; align-items: center; gap: var(--ui-gap); padding: 3px 0; }

/* ==========================================================================
   3. TABULATOR SKIN
   Tabulator ships a Bootstrap stylesheet; these rules pull it onto the same
   tokens so the grid matches the forms instead of looking like a different
   product bolted on.
   ========================================================================== */

.tabulator {
    background: transparent;
    border: 1px solid var(--ui-border);
    border-radius: var(--ui-radius);
    font-family: var(--ui-font);
    font-size: var(--ui-font-size);
    color: var(--ui-text);
}
.tabulator .tabulator-header {
    background: var(--ui-bg);
    color: var(--ui-text);
    border-bottom: 1px solid var(--ui-border);
    font-weight: var(--ui-font-weight-bold);
}
.tabulator .tabulator-header .tabulator-col {
    background: transparent;
    border-right: 1px solid var(--ui-border);
}
.tabulator .tabulator-header .tabulator-col .tabulator-col-content {
    padding: var(--ui-pad-y) var(--ui-pad-x);
}
/* Headers must stay readable: with ~18 columns fitColumns squeezed each
   to about 90px and every caption ellipsised to 'Org...'. A min width
   plus horizontal scroll is better than a table of unreadable stubs. */
.tabulator .tabulator-header .tabulator-col .tabulator-col-title {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.tabulator .tabulator-header .tabulator-col.tabulator-sortable:hover {
    background: var(--ui-bg-hover);
}
.tabulator .tabulator-header .tabulator-col .tabulator-header-filter input {
    width: 100%;
    min-height: 28px;
    padding: 4px 6px;
    color: var(--ui-text);
    background: var(--ui-bg);
    border: 1px solid var(--ui-border);
    border-radius: var(--ui-radius-sm);
    font-family: var(--ui-font);
    font-size: var(--ui-font-size-sm);
    box-sizing: border-box;
}
.tabulator .tabulator-header .tabulator-col .tabulator-header-filter input:focus {
    outline: none;
    border-color: var(--app-primary);
    box-shadow: 0 0 0 2px var(--ui-focus-ring);
}
.tabulator .tabulator-tableholder { background: var(--ui-bg); }
.tabulator .tabulator-tableholder .tabulator-placeholder span {
    color: var(--ui-text-muted);
    font-size: var(--ui-font-size);
    font-weight: 400;
}
.tabulator .tabulator-row { background: var(--ui-bg); border-bottom: 1px solid var(--ui-border); }
.tabulator .tabulator-row.tabulator-row-even { background: var(--ui-bg-subtle); }
.tabulator .tabulator-row:hover { background: var(--ui-bg-hover); }
.tabulator .tabulator-row.tabulator-selected { background: var(--ui-focus-ring); }
.tabulator .tabulator-row .tabulator-cell {
    padding: var(--ui-pad-y) var(--ui-pad-x);
    border-right: 1px solid var(--ui-border);
}
.tabulator .tabulator-row .tabulator-cell.tabulator-editing input { font-family: var(--ui-font); font-size: var(--ui-font-size); }
.tabulator .tabulator-footer {
    background: var(--ui-bg);
    border-top: 1px solid var(--ui-border);
    color: var(--ui-text);
}
.tabulator .tabulator-footer .tabulator-page {
    min-height: 30px;
    padding: 4px 10px;
    margin: 0 2px;
    color: var(--ui-text);
    background: var(--ui-bg);
    border: 1px solid var(--ui-border);
    border-radius: var(--ui-radius);
}
.tabulator .tabulator-footer .tabulator-page:not(.disabled):hover {
    background: var(--ui-bg-hover);
    color: var(--ui-text);
}
.tabulator .tabulator-footer .tabulator-page.active {
    color: var(--ui-text-inverse);
    background: var(--app-primary);
    border-color: var(--app-primary);
}
.tabulator .tabulator-footer .tabulator-page.disabled { color: var(--ui-text-disabled); }
.tabulator .tabulator-col-resize-handle { border-color: var(--ui-border); }
.tabulator-menu {
    background: var(--ui-bg-overlay);
    border: 1px solid var(--ui-border);
    border-radius: var(--ui-radius);
    box-shadow: var(--ui-shadow);
}
.tabulator-menu .tabulator-menu-item:hover { background: var(--ui-bg-hover); }

/* ==========================================================================
   4. DEVEXTREME OVERRIDES
   So DevExtreme mode uses the project's palette instead of the stock theme
   accent, and the two frameworks agree on brand colour and font.
   ========================================================================== */

.dx-widget { font-family: var(--ui-font); }
.dx-texteditor { border-radius: var(--ui-radius); }

/* Sizing, not just colour. The bridge previously restated the palette
   and left DevExtreme's own metrics in place, so changing density or
   theme family moved the buttons and the shell while every data entry
   control kept its stock height — the two halves of a form visibly
   disagreed. These resolve to the same tokens everything else uses. */
.dx-widget { font-size: var(--ui-font-size); }
.dx-texteditor-container,
.dx-texteditor-input-container { min-height: var(--ui-control-height); }
.dx-texteditor-input {
    height: auto;
    min-height: var(--ui-control-height);
    padding: var(--ui-pad-y) var(--ui-pad-x);
    font-family: var(--ui-font);
    font-size: var(--ui-font-size);
    line-height: var(--ui-line-height);
}
.dx-placeholder { font-size: var(--ui-font-size); }
.dx-placeholder::before { padding: var(--ui-pad-y) var(--ui-pad-x); }
.dx-button {
    min-height: var(--ui-control-height);
    border-radius: var(--ui-radius);
}
.dx-button-content { padding: var(--ui-pad-y) var(--ui-pad-x); }
.dx-button-text { font-size: var(--ui-font-size); line-height: var(--ui-line-height); }
.dx-datagrid, .dx-treelist { font-size: var(--ui-font-size); }
.dx-checkbox-icon { border-radius: var(--ui-radius-sm); }

/* ---- command bars ----
   Every generated form emits its commands as block-level divs in a
   plain container, so they stacked vertically and each button sized to
   its own label: Edit above Create, Save above Cancel, all different
   widths. One row, one gap, one width floor. */
#CommandContainter,
#RestoreCommandContainter,
.col-md-offset {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--ui-gap);
}
.col-md-offset > .ui-button,
.col-md-offset .ua-button,
.col-md-offset .dx-button {
    min-width: 104px;
}
/* The label sits centred rather than left, so a short command and a
   long one read as the same control at different lengths. */
.col-md-offset .ua-button { justify-content: center; }
.col-md-offset .dx-button-content { justify-content: center; }

.dx-texteditor.dx-state-focused,
.dx-texteditor.dx-state-active { border-color: var(--app-primary); }
.dx-texteditor.dx-invalid .dx-texteditor-container { border-color: var(--ui-danger); }
.dx-button-mode-contained.dx-button-default {
    background-color: var(--app-primary);
    border-color: var(--app-primary);
}
.dx-button-mode-contained.dx-button-default.dx-state-hover { background-color: var(--ui-primary-hover); }
.dx-button-mode-contained.dx-button-default.dx-state-active { background-color: var(--ui-primary-active); }
.dx-button-mode-contained.dx-button-success { background-color: var(--ui-success); border-color: var(--ui-success); }
.dx-button-mode-contained.dx-button-danger { background-color: var(--ui-danger); border-color: var(--ui-danger); }
.dx-list-item.dx-state-focused,
.dx-list-item.dx-list-item-selected { background-color: var(--app-primary); color: var(--ui-text-inverse); }
.dx-datagrid .dx-row-alt > td { background-color: var(--ui-bg-subtle); }
.dx-datagrid-rowsview .dx-selection > td { background-color: var(--ui-focus-ring); }
.dx-pager .dx-page.dx-selection { background-color: var(--app-primary); color: var(--ui-text-inverse); }
.dx-checkbox-checked .dx-checkbox-icon { background-color: var(--app-primary); border-color: var(--app-primary); }
/* ---- dark mode (body.app-dark) ---- */
body.app-dark {
    --ui-bg: #2a2a2a;
    --ui-bg-subtle: #313131;
    --ui-bg-hover: #383838;
    --ui-bg-active: #404040;
    --ui-bg-disabled: #333;
    --ui-bg-overlay: #2f2f2f;
    --ui-text: #dedede;
    --ui-text-muted: #b4bcc6;
    --ui-text-disabled: #6b6b6b;
    --ui-border: #515151;
    --ui-border-strong: #6a6a6a;
    --ui-card-border: #454545;
    --ui-shadow: 0 4px 12px rgba(0,0,0,.45);
    --ui-shadow-lg: 0 10px 40px rgba(0,0,0,.6);
    --ui-primary-hover: #e343a0;
    --ui-primary-active: #e654a9;
    background: #222;
    color: var(--ui-text);
}
body.app-dark .card,
body.app-dark .content-wrapper,
body.app-dark .content-body,
body.app-dark .app-content { background: var(--ui-bg-overlay); color: var(--ui-text); }
body.app-dark .card { border-color: var(--ui-card-border); }
body.app-dark .card-header,
body.app-dark .card-footer,
body.app-dark .card-body,
body.app-dark .content-header,
body.app-dark .modal-content,
body.app-dark .dropdown-menu {
    background: var(--ui-bg-overlay);
    color: var(--ui-text);
    border-color: var(--ui-border);
}
body.app-dark .card-header .card-title,
body.app-dark .content-header-title,
body.app-dark h1, body.app-dark h2, body.app-dark h3,
body.app-dark h4, body.app-dark h5 { color: var(--ui-text); }
body.app-dark .dropdown-item { color: var(--ui-text); }
body.app-dark .dropdown-item:hover { background: var(--ui-bg-hover); }
body.app-dark .breadcrumb { background: transparent; }
body.app-dark label,
body.app-dark .card-title,
body.app-dark .breadcrumb a { color: var(--ui-text); }
body.app-dark.ua-auth-page, body.app-dark.ua-error-page { background: #222; }

/* ---- theme families (body[data-app-theme]) ---- */
body[data-app-theme="fluent"] {
    --app-primary: #0f6cbd;
    --ui-primary-hover: #115ea3;
    --ui-primary-active: #0c3b5e;
    --ui-focus-ring: rgba(15, 108, 189, .30);
    --ui-font: 'Segoe UI Variable Text', 'Segoe UI', system-ui, -apple-system, sans-serif;
    --ui-font-size: 14px;
    --ui-font-size-sm: 12px;
    --ui-line-height: 1.43;
    --ui-font-weight-bold: 600;
    --ui-control-height: 32px;
    --ui-radius: 6px;
    --ui-radius-sm: 4px;
    --ui-pad-x: 10px;
    --ui-pad-y: 5px;
    --ui-row-gap: 12px;
    --ui-gap: 8px;
    --ui-border: #d1d1d1;
    --ui-border-strong: #a19f9d;
    --ui-card-border: #e3e1df;
    --ui-bg-subtle: #faf9f8;
    --ui-bg-hover: #f3f2f1;
    --ui-bg-active: #ededeb;
    --ui-shadow: 0 1px 2px rgba(0,0,0,.14), 0 0 2px rgba(0,0,0,.12);
    --ui-shadow-lg: 0 8px 16px rgba(0,0,0,.14), 0 0 2px rgba(0,0,0,.12);
    --ui-transition: 100ms cubic-bezier(.33,0,.67,1);
}
body.app-dark[data-app-theme="fluent"] {
    --app-primary: #479ef5;
    --ui-primary-hover: #62abf5;
    --ui-primary-active: #77b7f7;
    --ui-border: #3d3d3d;
    --ui-border-strong: #565656;
    --ui-card-border: #353535;
    --ui-bg-subtle: #1f1f1f;
    --ui-bg-hover: #2b2b2b;
    --ui-bg-active: #333;
}
body[data-app-theme="material"] {
    --app-primary: #6750a4;
    --ui-primary-hover: #56438d;
    --ui-primary-active: #4a3880;
    --ui-focus-ring: rgba(103, 80, 164, .28);
    --ui-font: Roboto, 'Segoe UI', system-ui, -apple-system, sans-serif;
    --ui-font-size: 14px;
    --ui-font-size-sm: 12px;
    --ui-line-height: 1.5;
    --ui-font-weight-bold: 500;
    --ui-control-height: 40px;
    --ui-radius: 8px;
    --ui-radius-sm: 4px;
    --ui-pad-x: 14px;
    --ui-pad-y: 8px;
    --ui-row-gap: 16px;
    --ui-gap: 8px;
    --ui-border: #cac4d0;
    --ui-border-strong: #79747e;
    --ui-card-border: #e4dfe7;
    --ui-bg-subtle: #f7f2fa;
    --ui-bg-hover: #f3edf7;
    --ui-bg-active: #ece6f0;
    --ui-shadow: 0 1px 3px rgba(0,0,0,.20), 0 1px 2px rgba(0,0,0,.12);
    --ui-shadow-lg: 0 6px 12px rgba(0,0,0,.22), 0 2px 4px rgba(0,0,0,.14);
    --ui-transition: 200ms cubic-bezier(.2,0,0,1);
}
body.app-dark[data-app-theme="material"] {
    --app-primary: #d0bcff;
    --ui-primary-hover: #c0a9f8;
    --ui-primary-active: #b195f0;
    --ui-text-inverse: #381e72;
    --ui-border: #49454f;
    --ui-border-strong: #635b70;
    --ui-card-border: #403c43;
    --ui-bg-subtle: #1d1b20;
    --ui-bg-hover: #262329;
    --ui-bg-active: #2f2b34;
}
body[data-app-theme="material"] .ua-button,
body[data-app-theme="material"] .btn { border-radius: 20px; }
body[data-app-theme="material"] .ua-textbox,
body[data-app-theme="material"] .ua-select { border-radius: var(--ui-radius) var(--ui-radius) 0 0; }

/* ---- compact density (body.app-compact) ---- */
body.app-compact {
    --ui-control-height: 26px;
    --ui-font-size: 12px;
    --ui-font-size-sm: 11px;
    --ui-pad-x: 6px;
    --ui-pad-y: 3px;
    --ui-row-gap: 6px;
    --ui-gap: 4px;
}

/* ---- accent presets (body[data-app-accent]) ---- */
body[data-app-accent="blue"] {
    --app-primary: #2d6cdf;
    --ui-primary-hover: #2963cd;
    --ui-primary-active: #265bbb;
    --ui-focus-ring: rgba(45,108,223,0.25);
}
body.app-dark[data-app-accent="blue"] {
    --ui-primary-hover: #427be2;
    --ui-primary-active: #5386e5;
}
body[data-app-accent="teal"] {
    --app-primary: #0f9d8f;
    --ui-primary-hover: #0e9084;
    --ui-primary-active: #0d8478;
    --ui-focus-ring: rgba(15,157,143,0.25);
}
body.app-dark[data-app-accent="teal"] {
    --ui-primary-hover: #27a79a;
    --ui-primary-active: #3aafa3;
}
body[data-app-accent="green"] {
    --app-primary: #3f9c35;
    --ui-primary-hover: #3a9031;
    --ui-primary-active: #35832d;
    --ui-focus-ring: rgba(63,156,53,0.25);
}
body.app-dark[data-app-accent="green"] {
    --ui-primary-hover: #52a649;
    --ui-primary-active: #62ae59;
}
body[data-app-accent="purple"] {
    --app-primary: #7c4dbe;
    --ui-primary-hover: #7247af;
    --ui-primary-active: #6841a0;
    --ui-focus-ring: rgba(124,77,190,0.25);
}
body.app-dark[data-app-accent="purple"] {
    --ui-primary-hover: #895fc4;
    --ui-primary-active: #946dca;
}
body[data-app-accent="orange"] {
    --app-primary: #e07b39;
    --ui-primary-hover: #ce7134;
    --ui-primary-active: #bc6730;
    --ui-focus-ring: rgba(224,123,57,0.25);
}
body.app-dark[data-app-accent="orange"] {
    --ui-primary-hover: #e3884d;
    --ui-primary-active: #e6935d;
}
body[data-app-accent="red"] {
    --app-primary: #cf4b3f;
    --ui-primary-hover: #be453a;
    --ui-primary-active: #ae3f35;
    --ui-focus-ring: rgba(207,75,63,0.25);
}
body.app-dark[data-app-accent="red"] {
    --ui-primary-hover: #d45d52;
    --ui-primary-active: #d86b62;
}
