/* The "Hairline" component set.

   Four rules, applied without exception, and every value below follows from them:

     1. Subtle corners.       --edge (4px), one variable for every control.
     2. 1px hairline borders. Weight is carried by the line, not by a fill.
     3. No shadow on anything inline. Elevation is reserved for things that
        genuinely float - dialogs, toasts, dropdown panels.
     4. One control height.   A field and a button placed side by side line up
                              exactly, with no per-page nudging.

   Hover moves an element's *border*, not its fill. That is the single biggest
   difference from the Metronic set this replaces, along with the removal of the
   1px drop shadow that used to sit under every button and the pastel "-Soft"
   tint fills, which were btn-light-danger and friends wearing a new name.

   Loaded globally by _Layout.cshtml, after site.css and before motion.css. */

:root {
    --control-height: 32px;
    --form-gap: 15px;
    --form-section-gap: 22px;

    /* Primary is a token rather than a hard-coded colour because --nav is
       #060F1B against a #070E17 page in dark mode: a navy button is invisible
       there. Light keeps the brand navy; dark promotes the signal orange, which
       is the only colour in the palette that holds up against both surfaces. */
    --primary: var(--nav);
    --primaryHover: var(--nav3);
    --onPrimary: #fff;

    /* Controls take a subtle 4px corner (was square). One variable, so softening
       or squaring the whole component set is a single edit. Separate from
       --r1/--r2/--r3 in tokens.css, which shape cards, panels and the shell. */
    --edge: 4px;

    /* A switch's "on" colour. Resolved HERE, at :root, so it holds the orange:
       a custom property inherits its computed value, so the blue --signal that
       tabulator-rebrand.css re-points inside every grid never reaches a switch
       rendered in a grid cell. Every switch type below uses this, not --signal. */
    --toggleOn: var(--signal);
}

[data-litheme="dark"] {
    --primary: var(--signal);
    --primaryHover: #FF8A34;
    --onPrimary: #08172A;
}

/* ─────────────────────────── Buttons ─────────────────────────── */

.li-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    height: var(--control-height);
    padding: 0 13px;
    border: 1px solid var(--line);
    border-radius: var(--edge);
    background: var(--surface);
    color: var(--ink);
    font-family: inherit;
    font-size: 11.5px;
    font-weight: 500;
    white-space: nowrap;
    cursor: pointer;
    position: relative;
    box-shadow: none;
    transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease), color var(--dur) var(--ease);
}

.li-button .ms { font-size: 16px; margin-left: -2px; }
/* KeenIcons inside the compact buttons: same optical size as .ms above. (The
   flex gap on .li-button already spaces icon from label - no me-* needed.) */
.li-button > .ki-outline { font-size: 15px; }
.li-button:hover { border-color: var(--ink); background: var(--inset); }
.li-button:active { background: var(--line2); }
.li-button:disabled { background: var(--inset); border-color: var(--line); color: var(--ink3); cursor: not-allowed; }

:where(button, a, input, textarea, select, [tabindex]):focus-visible { outline: 2px solid var(--signal); outline-offset: 1px; }

.li-button-primary { background: var(--primary); border-color: var(--primary); color: var(--onPrimary); font-weight: 600; }
.li-button-primary:hover { background: var(--primaryHover); border-color: var(--primaryHover); }
.li-button-primary:disabled { background: var(--inset); border-color: var(--line); color: var(--ink3); }

.li-button-quiet { border-color: transparent; background: none; color: var(--ink2); }
.li-button-quiet:hover { border-color: transparent; background: var(--inset); color: var(--ink); }
.li-button-quiet:disabled { background: none; border-color: transparent; }

/* Intent buttons are outlines that fill solid on hover, so the weight of a
   destructive or approving action is visible at the moment you commit to it
   rather than shouting from the toolbar the whole time the page is open. */
.li-button-danger { background: none; color: var(--danger); border-color: color-mix(in srgb, var(--danger) 40%, transparent); }
.li-button-danger:hover { background: var(--danger); border-color: var(--danger); color: #fff; }
.li-button-success { background: none; color: var(--ok); border-color: color-mix(in srgb, var(--ok) 40%, transparent); }
.li-button-success:hover { background: var(--ok); border-color: var(--ok); color: #fff; }
.li-button-warning { background: none; color: var(--warn); border-color: color-mix(in srgb, var(--warn) 40%, transparent); }
.li-button-warning:hover { background: var(--warn); border-color: var(--warn); color: #fff; }

/* The solid variants exist for one job: the confirm button in a destructive or
   completing dialog, where that action is the entire point of the screen. They
   are not toolbar buttons - use the outline above there. */
.li-button-danger-solid { background: var(--danger); border-color: var(--danger); color: #fff; font-weight: 600; }
.li-button-danger-solid:hover { background: #A32B3E; border-color: #A32B3E; }
.li-button-success-solid { background: var(--ok); border-color: var(--ok); color: #fff; font-weight: 600; }
.li-button-success-solid:hover { background: #0C6647; border-color: #0C6647; }
.li-button-warning-solid { background: var(--warn); border-color: var(--warn); color: #fff; font-weight: 600; }
.li-button-warning-solid:hover { background: #7A5300; border-color: #7A5300; }

.li-button-small { height: 26px; padding: 0 9px; font-size: 11px; }

/* Square by construction: width tracks --control-height, so the icon button and
   a text button next to it are the same height with no separate sizing. */
.li-button-icon { width: var(--control-height); padding: 0; }
.li-button-icon.li-button-small { width: 26px; }
.li-button-icon .ms { margin: 0; font-size: 17px; }

.li-text-button {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    border: 0;
    background: none;
    padding: 0 2px;
    color: var(--ink2);
    font-family: inherit;
    font-size: 11.5px;
    cursor: pointer;
    text-decoration: underline;
    text-underline-offset: 3px;
    text-decoration-color: var(--line);
}

.li-text-button:hover { color: var(--ink); text-decoration-color: var(--ink3); }
.li-text-button .ms { font-size: 15px; }

.li-button-group { display: inline-flex; }
.li-button-group > .li-button + .li-button { border-left-width: 0; }
/* Only the group's outer corners are rounded; the seams between buttons stay square. */
.li-button-group > .li-button:not(:first-child) { border-top-left-radius: 0; border-bottom-left-radius: 0; }
.li-button-group > .li-button:not(:last-child) { border-top-right-radius: 0; border-bottom-right-radius: 0; }
.li-button-group > .li-button.is-active { background: var(--primary); border-color: var(--primary); color: var(--onPrimary); font-weight: 600; }

/* The label is hidden by colour rather than by removing it, so the button keeps
   its width and the row does not reflow when a save starts. */
.li-button.is-loading { pointer-events: none; color: transparent !important; }
.li-button.is-loading .ms,
.li-button.is-loading .ki-outline { visibility: hidden; }

.li-button.is-loading::after {
    content: "";
    position: absolute;
    width: 13px;
    height: 13px;
    border-radius: 50%;
    border: 1.5px solid var(--ink3);
    border-top-color: transparent;
    animation: liSpin .55s linear infinite;
}

.li-button-primary.is-loading::after,
.li-button-danger-solid.is-loading::after,
.li-button-success-solid.is-loading::after,
.li-button-warning-solid.is-loading::after { border-color: var(--onPrimary); border-top-color: transparent; }

@keyframes liSpin { to { transform: rotate(360deg); } }

/* ─────────────────────────── Form layout ─────────────────────────── */

.li-form { display: grid; gap: var(--form-section-gap); }
.li-form-section { border: 0; padding: 0; margin: 0; min-width: 0; }
.li-form-section + .li-form-section { border-top: 1px solid var(--line); padding-top: 18px; }
.li-form-section legend { padding: 0; margin: 0 0 14px; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .11em; color: var(--ink3); }
.li-form-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--form-gap); }
.li-field { display: block; min-width: 0; }
.li-field-full { grid-column: 1 / -1; }
.li-field-label { display: block; margin-bottom: 5px; font-size: 11.5px; font-weight: 500; color: var(--ink); }
.li-optional { color: var(--ink3); font-weight: 400; }

/* ─────────────────────────── Controls ─────────────────────────── */

.li-control {
    display: block;
    box-sizing: border-box;
    width: 100%;
    min-width: 0;
    height: var(--control-height);
    padding: 0 11px;
    border: 1px solid var(--line);
    border-radius: var(--edge);
    background: var(--surface);
    color: var(--ink);
    font: inherit;
    font-size: 11.5px;
    line-height: 1.4;
    transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}

textarea.li-control { min-height: 80px; height: auto; padding: 8px 11px; resize: vertical; }
.li-control::placeholder { color: var(--ink3); opacity: 1; }
.li-control:hover { border-color: var(--ink3); }

/* A doubled hairline rather than a blurred glow. The old 3px soft ring was the
   other half of what read as "Metronic" on every field - a sharp system cannot
   have a fuzzy focus state. */
.li-control:focus { border-color: var(--signal); outline: none; box-shadow: 0 0 0 1px var(--signal); }
.li-control:disabled, .li-control[readonly] { background: var(--inset); color: var(--ink2); cursor: not-allowed; }
.li-control:disabled:hover, .li-control[readonly]:hover { border-color: var(--line); }
.li-control[aria-invalid='true'], .li-control:user-invalid { border-color: var(--danger); }
.li-control[aria-invalid='true']:focus, .li-control:user-invalid:focus { box-shadow: 0 0 0 1px var(--danger); }

.li-field-help { display: block; margin-top: 5px; font-size: 11px; line-height: 1.5; color: var(--ink2); }
.li-field-error { display: flex; align-items: center; gap: 4px; margin-top: 5px; font-size: 11px; color: var(--danger); }
.li-field-error .ms { font-size: 14px; }
.li-form-note { margin: 0; font-size: 11px; color: var(--ink2); line-height: 1.5; }
.li-form-error { margin: 0; padding: 9px 11px; border: 1px solid var(--danger); border-left-width: 2px; background: var(--dangerSoft); color: var(--danger); border-radius: var(--edge); font-size: 11.5px; }

/* ─────────────────────────── Selects ─────────────────────────── */

/* Native selects inherit the control look. The chevron is drawn rather than left
   to the platform so light and dark stay consistent. */
select, select.li-control, .li-field select {
    -webkit-appearance: none;
    appearance: none;
    display: block;
    box-sizing: border-box;
    width: 100%;
    min-width: 0;
    height: var(--control-height);
    padding: 0 30px 0 11px;
    border: 1px solid var(--line);
    border-radius: var(--edge);
    background-color: var(--surface);
    background-image: linear-gradient(45deg, transparent 50%, var(--ink3) 50%), linear-gradient(135deg, var(--ink3) 50%, transparent 50%);
    background-position: calc(100% - 16px) center, calc(100% - 11px) center;
    background-size: 5px 5px, 5px 5px;
    background-repeat: no-repeat;
    color: var(--ink);
    font: inherit;
    font-size: 11.5px;
    line-height: 1.4;
    cursor: pointer;
    transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}

select:hover { border-color: var(--ink3); }
select:focus { border-color: var(--signal); outline: none; box-shadow: 0 0 0 1px var(--signal); }
select:disabled { background-color: var(--inset); color: var(--ink2); cursor: not-allowed; }

/* Keeps the native option list readable in dark mode. */
[data-litheme="dark"] select { color-scheme: dark; }

/* Toolbar selects sit inline and size to their content. */
select.li-select-inline {
    display: inline-block;
    width: auto;
    height: 26px;
    padding: 0 26px 0 9px;
    font-size: 11px;
    background-position: calc(100% - 13px) center, calc(100% - 8px) center;
}

/* Select2's own container gets an inline width style at init time - 100% only when the caller
   explicitly passes { width: '100%' } (our LISelect2 in site.js does this). Metronic's own
   [data-control="select2"] sweep in scripts.bundle.js does not, so any select2 that sweep grabs
   first (which is most of them - it also sets the "already initialized" flag our own code checks,
   so ours never gets a second try) falls back to Select2's "resolve" mode: a pixel width computed
   once from the original <select> and then frozen, not responsive to its container resizing.
   Forcing it here at the CSS layer fixes every instance regardless of which script initialized
   it, and stays correct across container/viewport size changes that a one-time JS measurement
   can't track. */
.select2-container { width: 100% !important; }

/* The bootstrap5 select2 theme's `.select2-container--bootstrap5 .select2-selection { height:
   auto; }` and our own `.li-control { height: var(--control-height); }` are both two-class-worth
   of specificity by different routes (0,2,0 either way), so which one wins isn't decided by
   source order the way single-class rules are - height:auto happened to win, collapsing the box
   to a content-based ~20px instead of the standard control height every other field uses.
   Select2 carries the original <select>'s classes onto this element, so .li-control is reliably
   present here to hang an equally-specific (also 0,2,0), later-loaded rule on.

   The full select2 restyle lives in components/select2-hairline.css, which loads after this
   file and targets select2's structural classes rather than these two escape hatches. */
.select2-selection.li-control {
    height: var(--control-height);
    display: flex;
    align-items: center;
    border-radius: var(--edge);
}

/* ─────────────────────────── Search ─────────────────────────── */

/* One shared shape for "type to filter this list" inputs - sidebar and toolbar
   search boxes, palette search, grid quick-filters. Distinct from
   .li-combo-search, which only exists inside a combobox's dropdown panel.

   Markup: <span class="li-search"><span class="ms">search</span>
           <input class="li-search-input" placeholder="Search…"></span> */

.li-search { position: relative; display: flex; align-items: center; min-width: 0; }
.li-search > .ms { position: absolute; left: 9px; font-size: 15px; color: var(--ink3); pointer-events: none; }

.li-search-input {
    width: 100%;
    min-width: 0;
    height: var(--control-height);
    padding: 0 10px 0 30px;
    border: 1px solid var(--line);
    border-radius: var(--edge);
    background: var(--surface);
    color: var(--ink);
    font: inherit;
    font-size: 11.5px;
    transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}

.li-search-input::placeholder { color: var(--ink3); opacity: 1; }
.li-search-input:hover { border-color: var(--ink3); }
.li-search-input:focus { border-color: var(--signal); outline: none; box-shadow: 0 0 0 1px var(--signal); }
.li-search:focus-within > .ms { color: var(--ink2); }
.li-search-small .li-search-input { height: 26px; font-size: 11px; padding-left: 27px; }
.li-search-small > .ms { font-size: 14px; left: 7px; }

/* --- Inline field+button group (e.g. a "type name" input glued to its Add button) ----------
   Bootstrap's .input-group expects .form-control/.form-select children (it relies on their own
   flex-basis to share the row); .li-control is width:100%/display:block instead, so it claims the
   entire row on its own and the button wraps onto a new line below - reads as a floating,
   disconnected button rather than one joined control. Generic and reusable: wrap the field + the
   li-button in this instead of .input-group wherever that combination comes up.

   The negative margin is what keeps the shared edge a single hairline rather than two stacked
   borders, which at 1px each read as a visible seam. The z-index on focus lifts the field's
   orange ring above the button's border so the ring is not clipped along that edge. */
.li-input-group { display: flex; align-items: stretch; }
.li-input-group > .li-control { width: auto; flex: 1 1 auto; min-width: 0; }
.li-input-group > .li-button { flex-shrink: 0; margin-left: -1px; }
.li-input-group > .li-control:focus { position: relative; z-index: 1; }

/* Joined controls round only their outer corners. !important because bootstrap-retheme.css
   forces --edge onto every .form-control/.btn, which would otherwise beat Bootstrap's own
   .input-group seam-squaring and put rounded corners in the middle of the group. */
.li-input-group > :not(:first-child),
.input-group > :not(:first-child):not(.dropdown-menu):not(.invalid-feedback):not(.valid-feedback) {
    border-top-left-radius: 0 !important;
    border-bottom-left-radius: 0 !important;
}
.li-input-group > :not(:last-child),
.input-group > :not(:last-child):not(.dropdown-menu):not(.invalid-feedback):not(.valid-feedback) {
    border-top-right-radius: 0 !important;
    border-bottom-right-radius: 0 !important;
}

/* ─────────────────────────── Checkbox and radio ─────────────────────────── */

/* The native input is kept and restyled with appearance:none rather than hidden
   behind a pseudo-element stand-in, so keyboard operation, :checked, :indeterminate
   and form submission all keep working with no JS.

   Radio is the one round thing in the system, deliberately: round versus square is
   how people tell "pick one" from "pick any" without reading the labels, and that
   is worth breaking the shape rule for. */

.li-check, .li-radio { display: inline-flex; align-items: center; gap: 8px; font-size: 11.5px; color: var(--ink); cursor: pointer; }

.li-check input, .li-radio input {
    appearance: none;
    -webkit-appearance: none;
    flex: 0 0 auto;
    margin: 0;
    width: 15px;
    height: 15px;
    border: 1px solid var(--ink3);
    background: var(--surface);
    cursor: pointer;
    transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}

.li-check input { border-radius: var(--edge); }
.li-radio input { border-radius: 50%; }
.li-check input:hover, .li-radio input:hover { border-color: var(--ink); }
.li-check input:checked, .li-radio input:checked { background: var(--primary); border-color: var(--primary); }

/* The tick is inlined as a data URI rather than an icon font so it paints with the
   box instead of waiting on Material Symbols, and so it cannot be knocked out by a
   font-loading failure. Two copies because the stroke has to match --onPrimary,
   which is white on light and near-navy on dark. */
.li-check input:checked {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23fff' stroke-width='2.6' stroke-linecap='square'%3E%3Cpath d='M3.5 8.4l3 3 6-6'/%3E%3C/svg%3E");
    background-size: 100%;
}

[data-litheme="dark"] .li-check input:checked {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%2308172A' stroke-width='2.6' stroke-linecap='square'%3E%3Cpath d='M3.5 8.4l3 3 6-6'/%3E%3C/svg%3E");
}

/* Set via el.indeterminate in JS - the "some rows selected" header checkbox in a grid.
   .is-indeterminate is the class hook for cases where the state is rendered server-side. */
.li-check input:indeterminate, .li-check input.is-indeterminate {
    background: var(--primary);
    border-color: var(--primary);
    background-image: linear-gradient(var(--onPrimary), var(--onPrimary));
    background-size: 7px 2px;
    background-position: center;
    background-repeat: no-repeat;
}

.li-radio input:checked { box-shadow: inset 0 0 0 3px var(--surface); }
.li-check input:disabled, .li-radio input:disabled { background-color: var(--inset); border-color: var(--line); cursor: not-allowed; }
.li-check input:checked:disabled, .li-radio input:checked:disabled { background-color: var(--ink3); border-color: var(--ink3); }
.li-check:has(input:disabled), .li-radio:has(input:disabled) { color: var(--ink3); cursor: not-allowed; }

/* ─────────────────────────── Toggle ─────────────────────────── */

/* Pill track, round knob - the same shape as every other switch in the app.
   Orange (--toggleOn) when on rather than --primary: --primary is the near-black navy
   in light mode, which reads as "off but dark", and green loses against the dark
   surface. The signal orange is the only value that says "live" in both themes.

   Markup: <label class="li-toggle"><input type="checkbox"><i></i><span>Label</span></label>
   The <i> is the track; it must be the input's next sibling for the + selectors. */

.li-toggle { display: inline-flex; align-items: center; gap: 9px; font-size: 11.5px; color: var(--ink); cursor: pointer; }
.li-toggle input { position: absolute; opacity: 0; width: 0; height: 0; }

.li-toggle > i {
    flex: 0 0 auto;
    position: relative;
    width: 32px;
    height: 18px;
    border: 1px solid var(--ink3);
    border-radius: 999px;
    background: var(--inset);
    transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}

.li-toggle > i::after {
    content: "";
    position: absolute;
    top: 2px;
    left: 2px;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background: var(--ink3);
    transition: transform var(--dur) var(--ease), background-color var(--dur) var(--ease);
}

.li-toggle input:checked + i { background: var(--toggleOn); border-color: var(--toggleOn); }
.li-toggle input:checked + i::after { transform: translateX(14px); background: #fff; }
.li-toggle input:focus-visible + i { outline: 2px solid var(--signal); outline-offset: 2px; }
.li-toggle input:disabled + i { opacity: .45; }
.li-toggle:has(input:disabled) { color: var(--ink3); cursor: not-allowed; }
.li-toggle-small > i { width: 26px; height: 15px; }
.li-toggle-small > i::after { width: 9px; height: 9px; }
.li-toggle-small input:checked + i::after { transform: translateX(11px); }

/* ─────────────────────────── Status badges ─────────────────────────── */

/* Hairline box plus coloured text, not a pastel pill. The tinted pill was the most
   Metronic thing left in the grids, and at a dozen per screen the fills competed
   with the data. currentColor drives the border, so a new variant is one line. */

.li-badge {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    height: 19px;
    padding: 0 6px;
    border: 1px solid color-mix(in srgb, currentColor 40%, transparent);
    border-radius: var(--edge);
    background: none;
    color: var(--ink2);
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: .01em;
    white-space: nowrap;
}

.li-badge-ok { color: var(--ok); }
.li-badge-warn { color: var(--warn); }
.li-badge-danger { color: var(--danger); }
.li-badge-info { color: var(--info); }
.li-badge-signal { color: var(--signalInk); }
.li-badge-dot::before { content: ""; width: 5px; height: 5px; background: currentColor; flex: 0 0 auto; }

/* ─────────────────────────── Toasts ─────────────────────────── */

.li-toast-stack {
    position: fixed;
    z-index: 100;
    top: 14px;
    right: 14px;
    display: flex;
    flex-direction: column;
    gap: 9px;
    width: min(360px, calc(100vw - 28px));
}

.li-toast {
    display: flex;
    align-items: flex-start;
    gap: 9px;
    padding: 11px 11px 11px 12px;
    background: var(--surface);
    color: var(--ink);
    border: 1px solid var(--line);
    border-left: 2px solid var(--ink3);
    border-radius: var(--edge);
    box-shadow: var(--shadowUp);
    animation: liToastIn .16s var(--ease) backwards;
}

.li-toast > .ms { flex: 0 0 auto; font-size: 18px; color: var(--ink3); margin-top: -1px; }
.li-toast > div { flex: 1; min-width: 0; }
.li-toast b { display: block; font-size: 11.5px; font-weight: 600; }
.li-toast p { margin: 3px 0 0; font-size: 11px; color: var(--ink2); line-height: 1.5; }

.li-toast-close {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    margin: -1px -2px 0 0;
    padding: 0;
    border: 0;
    border-radius: var(--edge);
    background: none;
    color: var(--ink3);
    cursor: pointer;
}

.li-toast-close:hover { background: var(--inset); color: var(--ink); }
.li-toast-close .ms { font-size: 15px; }
.li-toast-ok { border-left-color: var(--ok); }
.li-toast-ok > .ms { color: var(--ok); }
.li-toast-warn { border-left-color: var(--warn); }
.li-toast-warn > .ms { color: var(--warn); }
.li-toast-danger { border-left-color: var(--danger); }
.li-toast-danger > .ms { color: var(--danger); }
.li-toast-info { border-left-color: var(--info); }
.li-toast-info > .ms { color: var(--info); }

@keyframes liToastIn { from { opacity: 0; transform: translateX(14px); } }

/* ─────────────────────────── Dialogs ─────────────────────────── */

/* Covers the whole viewport, so nothing above it may sit inside a transformed
   ancestor - see the note on the entrance animation in motion.css. */
.li-dialog-backdrop {
    position: fixed;
    inset: 0;
    z-index: 90;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
    background: rgba(8, 23, 42, .62);
}

[data-litheme="dark"] .li-dialog-backdrop { background: rgba(0, 0, 0, .7); }

.li-dialog {
    display: flex;
    flex-direction: column;
    width: 100%;
    max-height: min(90dvh, 900px);
    overflow: hidden;
    background: var(--surface);
    color: var(--ink);
    border: 1px solid var(--line);
    border-radius: var(--edge);
    box-shadow: var(--shadowUp);
    animation: liDialogIn .16s var(--ease) backwards;
}

@keyframes liDialogIn { from { opacity: 0; transform: translateY(6px); } }

.li-dialog-header { display: flex; align-items: flex-start; gap: 12px; padding: 16px 20px; border-bottom: 1px solid var(--line); }
.li-dialog-heading { flex: 1; min-width: 0; }
.li-dialog-header h2 { margin: 0; font-size: 15px; font-weight: 600; letter-spacing: -.25px; }
.li-dialog-header p { margin: 5px 0 0; color: var(--ink2); font-size: 11.5px; line-height: 1.5; }

/* Its own control rather than a button variant: it is an icon in a corner, and
   inheriting button padding put it against the title instead of the edge. */
.li-dialog-close {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    margin: -2px -6px 0 auto;
    padding: 0;
    border: 1px solid transparent;
    border-radius: var(--edge);
    background: transparent;
    color: var(--ink3);
    text-decoration: none;
    cursor: pointer;
    transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease);
}

.li-dialog-close:hover { background: var(--inset); color: var(--ink); }
.li-dialog-close .ms { font-size: 17px; }
.li-dialog-body { flex: 1; overflow: auto; padding: 20px; }
.li-dialog-footer { display: flex; align-items: center; gap: 8px; padding: 12px 20px; border-top: 1px solid var(--line); background: var(--surface2); }
.li-dialog-note { font-size: 11px; color: var(--ink3); }
.li-dialog-actions { display: flex; gap: 7px; margin-left: auto; }
.li-dialog-narrow { max-width: 440px; }
.li-visually-hidden { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }

/* Reuses the dialog shell; only alignment and shape change, so there is one close
   button, one escape handler and one focus trap rather than a second component
   to keep in step. Replaces Metronic's .drawer and .offcanvas. */
.li-drawer-backdrop { padding: 0; justify-content: flex-end; align-items: stretch; }

.li-drawer {
    width: min(400px, 100vw);
    max-height: none;
    height: 100%;
    border-top: 0;
    border-right: 0;
    border-bottom: 0;
    animation: liDrawerIn .18s var(--ease) backwards;
}

@keyframes liDrawerIn { from { opacity: 0; transform: translateX(22px); } }

/* ─────────────────────────── Searchable combobox ─────────────────────────── */

/* For lists long enough that typing beats scanning, where a select2 would be
   overkill - it owns its own markup and needs no plugin. Short lists keep the
   native select, which is cheaper for the browser and for assistive tech. */

.li-combo { position: relative; min-width: 0; }

.li-combo-button {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    min-width: 0;
    height: var(--control-height);
    padding: 0 9px 0 11px;
    border: 1px solid var(--line);
    border-radius: var(--edge);
    background: var(--surface);
    color: var(--ink);
    font-size: 11.5px;
    text-align: left;
    cursor: pointer;
    transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}

.li-combo-button:hover { border-color: var(--ink3); }
.li-combo[data-open='true'] .li-combo-button { border-color: var(--signal); box-shadow: 0 0 0 1px var(--signal); }
.li-combo-value { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.li-combo-button .ms { flex: 0 0 auto; font-size: 17px; color: var(--ink3); transition: transform var(--dur) var(--ease); }
.li-combo[data-open='true'] .li-combo-button .ms { transform: rotate(180deg); }

.li-combo-panel {
    position: absolute;
    z-index: 40;
    top: calc(100% - 1px);
    left: 0;
    right: 0;
    overflow: hidden;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--edge);
    box-shadow: var(--shadowUp);
    animation: liUp .14s var(--ease) both;
}

.li-combo-search { display: flex; align-items: center; gap: 8px; padding: 8px 10px; border-bottom: 1px solid var(--line2); }
.li-combo-search .ms { font-size: 15px; color: var(--ink3); }
.li-combo-search input { flex: 1; min-width: 0; border: 0; background: none; color: var(--ink); font-size: 11.5px; outline: none; }
.li-combo-search input::placeholder { color: var(--ink3); }
.li-combo-count { flex: 0 0 auto; font-family: 'IBM Plex Mono', monospace; font-size: 10.5px; color: var(--ink3); }
.li-combo-list { max-height: 232px; overflow-y: auto; padding: 3px; }

.li-combo-option {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 6px 8px;
    border: 0;
    border-radius: var(--edge);
    background: transparent;
    color: var(--ink);
    font-size: 11.5px;
    text-align: left;
    cursor: pointer;
    transition: background-color var(--dur) var(--ease);
}

.li-combo-option .ms { flex: 0 0 auto; font-size: 16px; color: transparent; }
.li-combo-option[aria-selected='true'] { font-weight: 600; }
.li-combo-option[aria-selected='true'] .ms { color: var(--signal); }
.li-combo-option:hover { background: var(--inset); }
.li-combo-empty { margin: 0; padding: 14px 12px; font-size: 11.5px; color: var(--ink2); text-align: center; }

/* ─────────────────────────── Switches ─────────────────────────── */

/* Toggle switches are always fully round - pill track, circle knob - on every
   screen, including the dashboards whose blanket `* { border-radius: 0 !important }`
   squares everything else. The extra `input` in the selector (0-3-1) is what outranks
   that blanket (0-3-0) and page-level overrides such as subscriptionplans.css. The
   knob is drawn by --bs-form-switch-bg, so it is redrawn here as a circle. */
:root .form-switch input.form-check-input {
    border-radius: 2em !important;
}
:root .form-switch input.form-check-input:checked {
    background-color: var(--toggleOn) !important;
    border-color: var(--toggleOn) !important;
}
/* Some screens (Roles, subscription plans) hide the SVG knob and draw their own with
   ::before - Bootstrap never uses that pseudo on a switch, so this only reaches those. */
:root .form-switch input.form-check-input::before {
    border-radius: 50% !important;
}
.form-switch .form-check-input {
    --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%280, 0, 0, 0.25%29'/%3e%3c/svg%3e");
}
.form-switch .form-check-input:focus {
    --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%280, 0, 0, 0.25%29'/%3e%3c/svg%3e");
}
.form-switch .form-check-input:checked {
    --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23ffffff'/%3e%3c/svg%3e");
}

/* ─────────────────────────── Responsive ─────────────────────────── */

@media (max-width: 600px) {
    .li-form-grid { grid-template-columns: minmax(0, 1fr); }
    .li-dialog-backdrop { padding: 10px; }
    .li-dialog { max-height: calc(100dvh - 20px); }
    .li-dialog-header, .li-dialog-body { padding: 15px; }
    .li-dialog-footer { padding: 11px 15px; }
    .li-toast-stack { top: 10px; right: 10px; }
}

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}
