/* ═══════════════════════════════════════════════════════════════
   MLAB UI — shadcn-flavored primitive layer
   Consumes the shadcn alias tokens defined in mlab-custom.css.
   Goal: one source of truth per primitive, composable & predictable.
   Namespaced `.mlab-ui-*` so it never collides with Bootstrap.
   Loaded last (via head.html) so token/focus harmonization wins.
═══════════════════════════════════════════════════════════════ */

/* ─── Global focus harmonization ───────────────────────────────
   Give every interactive control the same shadcn-style ring.
   Low specificity via :where() so page CSS can still override. */
:where(.form-control, .form-select, .btn, .form-check-input,
       .mlab-ui-input, .mlab-ui-btn, a.mlab-ui-focus):focus-visible {
    outline: 2px solid transparent;
    outline-offset: 2px;
    box-shadow: var(--ring-shadow);
    border-color: var(--ring);
}
:where(.form-control, .form-select):focus {
    border-color: var(--ring);
    box-shadow: var(--ring-shadow);
}

/* ─── Button ──────────────────────────────────────────────────── */
.mlab-ui-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .5rem;
    font-weight: 500;
    font-size: .875rem;
    line-height: 1;
    white-space: nowrap;
    border-radius: var(--radius);
    border: 1px solid transparent;
    padding: 0 1rem;
    height: 2.5rem;
    cursor: pointer;
    user-select: none;
    transition: background-color var(--mlab-dur-fast) var(--mlab-ease),
                color var(--mlab-dur-fast) var(--mlab-ease),
                border-color var(--mlab-dur-fast) var(--mlab-ease),
                box-shadow var(--mlab-dur-fast) var(--mlab-ease),
                transform .28s cubic-bezier(.34, 1.8, .64, 1); /* release: small overshoot */
}
/* Press: shrinks quickly while held, springs back on release (transition above). */
.mlab-ui-btn:active {
    transform: scale(.96);
    transition-duration: var(--mlab-dur-fast), var(--mlab-dur-fast), var(--mlab-dur-fast), var(--mlab-dur-fast), .08s;
    transition-timing-function: ease;
}
@media (prefers-reduced-motion: reduce) {
    .mlab-ui-btn, .mlab-ui-btn:active { transform: none; transition-property: background-color, color, border-color, box-shadow; }
}
.mlab-ui-btn:disabled { opacity: .5; pointer-events: none; }
.mlab-ui-btn > svg,
.mlab-ui-btn > [data-lucide] { width: 1rem; height: 1rem; }

.mlab-ui-btn--default   { background: var(--primary); color: var(--primary-foreground); }
.mlab-ui-btn--default:hover   { background: var(--primary); box-shadow: 0 4px 12px rgba(var(--mlab-shadow-ink-rgb), .20); }
.mlab-ui-btn--secondary { background: var(--secondary); color: var(--secondary-foreground); border-color: var(--border); }
.mlab-ui-btn--secondary:hover { background: color-mix(in srgb, var(--secondary) 92%, #000); }
.mlab-ui-btn--outline   { background: transparent; color: var(--foreground); border-color: var(--border); }
.mlab-ui-btn--outline:hover   { background: var(--muted); }
.mlab-ui-btn--ghost     { background: transparent; color: var(--foreground); }
.mlab-ui-btn--ghost:hover     { background: var(--muted); }
.mlab-ui-btn--accent    { background: var(--accent); color: var(--accent-foreground); }
.mlab-ui-btn--accent:hover    { background: color-mix(in srgb, var(--accent) 88%, #000); }
/* Solid red rather than --destructive: white on the vivid tone is 3.76:1. */
.mlab-ui-btn--destructive { background: var(--mlab-danger-solid); color: var(--destructive-foreground); }
.mlab-ui-btn--destructive:hover { background: color-mix(in srgb, var(--mlab-danger-solid) 88%, #000); }
.mlab-ui-btn--link      { background: transparent; color: var(--accent); padding: 0; height: auto; }
.mlab-ui-btn--link:hover      { text-decoration: underline; }

.mlab-ui-btn--sm { height: 2rem;   padding: 0 .75rem; font-size: .8125rem; border-radius: calc(var(--radius) - 2px); }
.mlab-ui-btn--lg { height: 2.75rem; padding: 0 1.5rem; font-size: .9375rem; }
.mlab-ui-btn--icon { width: 2.5rem; padding: 0; }

/* Inside a Bootstrap input-group, stretch to the group height and merge the
   left edge with the field instead of floating as a separate pill. */
.input-group > .mlab-ui-btn {
    height: auto;
    align-self: stretch;
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
}

/* mlab-ui inputs/selects inside a Bootstrap .input-group: the primitives are
   display:block;width:100%, which would otherwise force sibling buttons/addons
   onto a new line. Make them behave as flex items and merge the shared edge. */
.input-group > .mlab-ui-input,
.input-group > .mlab-ui-select {
    flex: 1 1 auto;
    width: 1%;
    min-width: 0;
}
.input-group > .mlab-ui-input:not(:last-child),
.input-group > .mlab-ui-select:not(:last-child) {
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
}
.input-group > .mlab-ui-input:not(:first-child),
.input-group > .mlab-ui-select:not(:first-child) {
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
}

/* ─── Card ────────────────────────────────────────────────────── */
.mlab-ui-card {
    background: var(--card);
    color: var(--card-foreground);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--mlab-shadow-sm);
    overflow: hidden; /* clip full-bleed tables/headers to the rounded corners */
}
/* A full-bleed table inside a card should not double its own border on the
   card's bottom edge (card border already closes it). */
.mlab-ui-card > .table-responsive:last-child .mlab-ui-table tbody tr:last-child td { border-bottom: 0; }
.mlab-ui-card__header  { padding: 1.25rem 1.25rem .75rem; }
.mlab-ui-card__title   { font-size: 1rem; font-weight: 600; letter-spacing: -.01em; margin: 0; }
.mlab-ui-card__desc    { font-size: .8125rem; color: var(--muted-foreground); margin: .25rem 0 0; }
/* Full padding by default so header-less cards don't jam content to the top;
   drop the top padding only when a header already sits above the content. */
.mlab-ui-card__content { padding: 1.25rem; }
.mlab-ui-card__header + .mlab-ui-card__content { padding-top: 0; }
.mlab-ui-card__footer  { padding: .75rem 1.25rem 1.25rem; display: flex; gap: .5rem; align-items: center; }

/* ─── Stat / KPI card ─────────────────────────────────────────── */
.mlab-ui-stat { display: flex; flex-direction: column; gap: .3rem; }
.mlab-ui-stat__label {
    font-size: .7rem; font-weight: 500; letter-spacing: .04em;
    text-transform: uppercase; color: var(--muted-foreground);
    display: inline-flex; align-items: center; gap: .375rem;
}
.mlab-ui-stat__value { font-size: 1.5rem; font-weight: 600; letter-spacing: -.02em; line-height: 1.1; }
.mlab-ui-stat__hint  { font-size: .75rem; color: var(--muted-foreground); }

/* ─── Input / Textarea / Label ────────────────────────────────── */
.mlab-ui-input,
.mlab-ui-textarea {
    display: block;
    width: 100%;
    background: var(--background);
    color: var(--foreground);
    border: 1px solid var(--input);
    border-radius: var(--radius);
    padding: 0 .75rem;
    height: 2.5rem;
    font-size: .875rem;
    transition: border-color var(--mlab-dur-fast) var(--mlab-ease),
                box-shadow var(--mlab-dur-fast) var(--mlab-ease);
}
.mlab-ui-textarea { height: auto; min-height: 5rem; padding: .5rem .75rem; }
.mlab-ui-input--sm { height: 2rem; font-size: .8125rem; border-radius: calc(var(--radius) - 2px); }
.mlab-ui-input::placeholder,
.mlab-ui-textarea::placeholder { color: var(--muted-foreground); }
.mlab-ui-input[aria-invalid="true"],
.mlab-ui-textarea[aria-invalid="true"] { border-color: var(--destructive); }
.mlab-ui-label { display: inline-block; font-size: .8125rem; font-weight: 500; margin-bottom: .375rem; }

/* ─── Select ──────────────────────────────────────────────────── */
.mlab-ui-select {
    display: block;
    width: 100%;
    background-color: var(--background);
    color: var(--foreground);
    border: 1px solid var(--input);
    border-radius: var(--radius);
    padding: 0 2.25rem 0 .75rem;
    height: 2.5rem;
    font-size: .875rem;
    cursor: pointer;
    -webkit-appearance: none;
    appearance: none;
    /* chevron-down (slate that reads in both themes) */
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right .625rem center;
    background-size: 1rem;
    transition: border-color var(--mlab-dur-fast) var(--mlab-ease),
                box-shadow var(--mlab-dur-fast) var(--mlab-ease);
}
.mlab-ui-select--sm { height: 2rem; font-size: .8125rem; border-radius: calc(var(--radius) - 2px); }

/* ─── Page header ─────────────────────────────────────────────────
   One standard title block so pages stop hand-rolling h2/h3/h4 +
   pt-4 pb-3. Title + subtitle on the left, optional actions on the right. */
.mlab-page-header {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    justify-content: space-between;
    gap: .5rem 1rem;
    padding-top: 1.5rem;
    padding-bottom: 1rem;
}
.mlab-page-header__title {
    font-size: 1.375rem;
    font-weight: 700;
    letter-spacing: -.02em;
    line-height: 1.2;
    margin: 0;
}
.mlab-page-header__subtitle {
    font-size: .875rem;
    color: var(--muted-foreground);
    margin: .25rem 0 0;
}
.mlab-page-header__actions { display: flex; flex-wrap: wrap; gap: .5rem; align-items: center; }

/* ─── Radio group ─────────────────────────────────────────────
   A row of exclusive choices where the picked one has to be obvious at a
   glance. Unselected options are deliberately uniform: colouring them per
   value makes the colour read as decoration and hides the selection. */
.mlab-ui-radiogroup {
    position: relative;
    display: flex;
    flex-wrap: wrap;
    gap: .5rem;
}
.mlab-ui-radiogroup input[type="radio"] {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}
.mlab-ui-radio {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    height: 2rem;
    padding: 0 .75rem;
    margin: 0;
    font-size: .8125rem;
    font-weight: 500;
    line-height: 1;
    white-space: nowrap;
    color: var(--muted-foreground);
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: calc(var(--radius) - 2px);
    cursor: pointer;
    user-select: none;
    transition: background-color var(--mlab-dur-fast) var(--mlab-ease),
                color var(--mlab-dur-fast) var(--mlab-ease),
                border-color var(--mlab-dur-fast) var(--mlab-ease),
                box-shadow var(--mlab-dur-fast) var(--mlab-ease);
}
.mlab-ui-radio svg,
.mlab-ui-radio [data-lucide] { width: .875rem; height: .875rem; }
.mlab-ui-radio:hover { color: var(--foreground); background: var(--muted); }

/* Selected: filled, not just tinted, and carries a check so the state does
   not rest on colour alone. */
.mlab-ui-radiogroup input[type="radio"]:checked + .mlab-ui-radio {
    color: var(--primary-foreground);
    background: var(--primary);
    border-color: var(--primary);
    box-shadow: var(--mlab-shadow-xs);
}
.mlab-ui-radiogroup input[type="radio"]:focus-visible + .mlab-ui-radio {
    border-color: var(--ring);
    box-shadow: var(--ring-shadow);
}
.mlab-ui-radiogroup input[type="radio"]:disabled + .mlab-ui-radio {
    opacity: .5;
    pointer-events: none;
}
.mlab-ui-radio__check { display: none; }
.mlab-ui-radiogroup input[type="radio"]:checked + .mlab-ui-radio .mlab-ui-radio__check {
    display: inline-flex;
    align-items: center;
}

/* ─── Badge ───────────────────────────────────────────────────── */
.mlab-ui-badge {
    display: inline-flex;
    align-items: center;
    gap: .25rem;
    font-size: .6875rem;
    font-weight: 600;
    line-height: 1;
    padding: .25rem .5rem;
    border-radius: var(--mlab-radius-pill);
    border: 1px solid transparent;
}
.mlab-ui-badge--default     { background: var(--primary); color: var(--primary-foreground); }
.mlab-ui-badge--secondary   { background: var(--muted); color: var(--mlab-muted-fg-strong); }
.mlab-ui-badge--outline     { background: transparent; color: var(--foreground); border-color: var(--border); }
/* Label takes the -fg tone, not the vivid one: at 11px bold on its own tint
   the vivid tone falls under the AA floor in the light theme. */
.mlab-ui-badge--accent      { background: var(--accent-subtle); color: var(--mlab-accent-fg); }
.mlab-ui-badge--success     { background: var(--mlab-success-bg); color: var(--mlab-success-fg); }
.mlab-ui-badge--warning     { background: var(--mlab-warning-bg); color: var(--mlab-warning-fg); }
.mlab-ui-badge--destructive { background: var(--mlab-danger-bg);  color: var(--mlab-danger-fg); }

/* ─── Alert ───────────────────────────────────────────────────── */
.mlab-ui-alert {
    display: flex; gap: .75rem;
    padding: 1rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--card);
    color: var(--foreground);
    font-size: .875rem;
}
.mlab-ui-alert__title { font-weight: 600; margin: 0 0 .25rem; }
.mlab-ui-alert--success     { border-color: rgba(var(--mlab-success-rgb), .35); background: var(--mlab-success-bg); }
.mlab-ui-alert--warning     { border-color: rgba(var(--mlab-warning-rgb), .35); background: var(--mlab-warning-bg); }
.mlab-ui-alert--destructive { border-color: rgba(var(--mlab-danger-rgb), .35);  background: var(--mlab-danger-bg); }
.mlab-ui-alert--info        { border-color: rgba(var(--mlab-info-rgb), .35);    background: var(--mlab-info-bg); }

/* ─── Table ───────────────────────────────────────────────────── */
.mlab-ui-table { width: 100%; border-collapse: collapse; font-size: .875rem; }
.mlab-ui-table thead th {
    text-align: left;
    font-weight: 500;
    color: var(--muted-foreground);
    padding: .625rem .75rem;
    border-bottom: 1px solid var(--border);
    white-space: nowrap;
}
.mlab-ui-table tbody td {
    padding: .75rem;
    border-bottom: 1px solid var(--border);
    vertical-align: middle;
    max-width: 340px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.mlab-ui-table tbody tr:last-child td { border-bottom: 0; }
.mlab-ui-table tbody tr { transition: background-color var(--mlab-dur-fast) var(--mlab-ease); }
.mlab-ui-table tbody tr:hover { background: var(--muted); }
/* Hover: an amber rule on the row's left edge (inset shadow, so nothing moves). */
.mlab-ui-table tbody td:first-child { transition: box-shadow var(--mlab-dur-fast) var(--mlab-ease); }
.mlab-ui-table tbody tr:hover td:first-child { box-shadow: inset 2px 0 0 #d97706; }
.mlab-ui-table tbody tr.mlab-ui-skeleton-row:hover { background: none; }
.mlab-ui-table tbody tr.mlab-ui-skeleton-row:hover td:first-child { box-shadow: none; }
/* Rows that open a page (onclick / data-href on the <tr>) also get a chevron
   sliding in on the right, so "clickable" reads without a word. */
.mlab-ui-table tbody tr:is([onclick], [data-href]) td:last-child { position: relative; padding-right: 2.25rem; }
.mlab-ui-table tbody tr:is([onclick], [data-href]) td:last-child::after {
    content: "";
    position: absolute; right: 1rem; top: 50%;
    width: 7px; height: 7px;
    border-top: 2px solid #d97706; border-right: 2px solid #d97706;
    opacity: 0;
    transform: translate(-4px, -50%) rotate(45deg);
    transition: opacity var(--mlab-dur-fast) var(--mlab-ease), transform .18s var(--mlab-ease);
}
.mlab-ui-table tbody tr:is([onclick], [data-href]):hover td:last-child::after {
    opacity: 1;
    transform: translate(0, -50%) rotate(45deg);
}
@media (prefers-reduced-motion: reduce) {
    .mlab-ui-table tbody td:first-child,
    .mlab-ui-table tbody tr:is([onclick], [data-href]) td:last-child::after { transition: none; }
}
/* Align the outer columns with the card's inner padding so table content
   lines up with the card title/footer instead of sitting tighter. */
.mlab-ui-table th:first-child,
.mlab-ui-table td:first-child { padding-left: 1.25rem; }
.mlab-ui-table th:last-child,
.mlab-ui-table td:last-child  { padding-right: 1.25rem; }
/* Long tables: their own scroll box, so the header can stick. A sticky <th>
   inside .table-responsive (overflow-x: auto) sticks to that box, which never
   scrolls vertically, so it has to be the box that scrolls. Opt-in on the
   wrapper: <div class="table-responsive mlab-ui-table-scroll">. The header
   rule is drawn as a shadow because a collapsed border scrolls away. */
.mlab-ui-table-scroll { max-height: min(70vh, 720px); overflow: auto; overscroll-behavior: contain; }
.mlab-ui-table-scroll .mlab-ui-table thead th {
    position: sticky; top: 0; z-index: 2;
    background: var(--card);
    border-bottom: 0;
    box-shadow: inset 0 -1px 0 var(--border);
}
/* The actions column (last) holds buttons: never truncate or clip it. */
.mlab-ui-table td:last-child,
.mlab-ui-table th:last-child { max-width: none; overflow: visible; }

/* ─── Tabs (segmented) ────────────────────────────────────────── */
.mlab-ui-tabs {
    display: inline-flex;
    flex-wrap: wrap;
    gap: .25rem;
    padding: .25rem;
    background: var(--muted);
    border: 1px solid var(--border);
    border-radius: var(--radius);
}
.mlab-ui-tab {
    border: 0;
    background: transparent;
    color: var(--muted-foreground);
    font-size: .8125rem;
    font-weight: 500;
    padding: .4rem .85rem;
    border-radius: calc(var(--radius) - 2px);
    cursor: pointer;
    transition: background-color var(--mlab-dur-fast) var(--mlab-ease),
                color var(--mlab-dur-fast) var(--mlab-ease);
}
.mlab-ui-tab:hover { color: var(--foreground); }
.mlab-ui-tab.active { background: var(--card); color: var(--foreground); box-shadow: var(--mlab-shadow-xs); }
/* Sliding pill (assets/js/mlab-tabs.js): once the script has taken a bar over,
   the active tab drops its own background and one pill glides between tabs.
   Without JS the static .active style above still applies. */
.mlab-ui-tabs.is-sliding { position: relative; }
.mlab-ui-tabs.is-sliding .mlab-ui-tab { position: relative; z-index: 1; }
.mlab-ui-tabs.is-sliding .mlab-ui-tab.active { background: transparent; box-shadow: none; }
.mlab-ui-tabs-pill {
    position: absolute; z-index: 0; pointer-events: none;
    background: var(--card); box-shadow: var(--mlab-shadow-xs);
    border-radius: calc(var(--radius) - 2px);
    transition: left .28s cubic-bezier(.2, .8, .2, 1), top .28s cubic-bezier(.2, .8, .2, 1),
                width .28s cubic-bezier(.2, .8, .2, 1), height .28s cubic-bezier(.2, .8, .2, 1),
                opacity .15s ease;
}
@media (prefers-reduced-motion: reduce) { .mlab-ui-tabs-pill { transition: none; } }
.mlab-ui-tabpane { display: none; }
.mlab-ui-tabpane.active { display: block; }

/* ─── Pagination ──────────────────────────────────────────────── */
.mlab-ui-pagination { display: inline-flex; flex-wrap: wrap; gap: .25rem; }
.mlab-ui-pagination button {
    min-width: 2rem;
    height: 2rem;
    padding: 0 .5rem;
    border: 1px solid var(--border);
    background: var(--card);
    color: var(--foreground);
    border-radius: calc(var(--radius) - 2px);
    font-size: .8125rem;
    font-weight: 500;
    cursor: pointer;
    transition: background-color var(--mlab-dur-fast) var(--mlab-ease);
}
.mlab-ui-pagination button:hover:not(:disabled):not(.active) { background: var(--muted); }
.mlab-ui-pagination button.active { background: var(--accent-subtle); border-color: var(--accent); color: var(--accent); }
.mlab-ui-pagination button:disabled { opacity: .4; cursor: default; }

/* ─── Separator ───────────────────────────────────────────────── */
.mlab-ui-separator { height: 1px; background: var(--border); border: 0; margin: 1rem 0; }

/* ─── Skeleton ────────────────────────────────────────────────── */
.mlab-ui-skeleton {
    display: block;
    background: var(--muted);
    border-radius: var(--mlab-radius-sm);
    position: relative;
    overflow: hidden;
}
/* Shapes, so a placeholder can mirror the content it stands in for */
.mlab-ui-skeleton--line   { height: .7rem; }
.mlab-ui-skeleton--title  { height: 1.1rem; }
.mlab-ui-skeleton--pill   { height: 1.3rem; border-radius: 999px; }
.mlab-ui-skeleton--circle { border-radius: 50%; }
.mlab-ui-skeleton--btn    { height: 2rem; }
.mlab-ui-skeleton::after {
    content: "";
    position: absolute; inset: 0;
    transform: translateX(-100%);
    background: linear-gradient(90deg, transparent,
                rgba(var(--accent-rgb), .16), transparent);
    animation: mlab-ui-shimmer 1.4s infinite;
}
@keyframes mlab-ui-shimmer { 100% { transform: translateX(100%); } }
@media (prefers-reduced-motion: reduce) {
    .mlab-ui-skeleton::after { animation: none; }
}

/* ─── Empty state ─────────────────────────────────────────────── */
.mlab-ui-empty {
    display: flex; flex-direction: column; align-items: center; text-align: center;
    gap: .5rem; padding: 3rem 1.5rem; color: var(--muted-foreground);
}
.mlab-ui-empty__icon { width: 2.5rem; height: 2.5rem; opacity: .5; }
.mlab-ui-empty__title { font-weight: 600; color: var(--foreground); }

/* ═══════════════════════════════════════════════════════════════
   SURFACES — clean white-card-on-grey-canvas hierarchy (post-login).
   Pre-login pages keep their own look via body.mlab-pub.
═══════════════════════════════════════════════════════════════ */
body:not(.mlab-pub) { background: var(--canvas) !important; }
body:not(.mlab-pub) .content-page { background: transparent; }

/* Cards lift a touch more so white pops on the grey canvas. */
.mlab-ui-card { box-shadow: 0 1px 2px rgba(var(--mlab-shadow-ink-rgb), .04), 0 1px 3px rgba(var(--mlab-shadow-ink-rgb), .06); }
html[data-bs-theme=dark] .mlab-ui-card { box-shadow: 0 1px 2px rgba(0,0,0,.4); }

/* A little amber life on KPI icons. */
.mlab-ui-stat__label i[data-lucide],
.mlab-ui-stat__label svg { color: var(--accent); }

/* ═══════════════════════════════════════════════════════════════
   BOOTSTRAP HARMONIZATION
   The backend injects plain Bootstrap markup (.btn, .card, .badge)
   into templates. Retune Bootstrap's own CSS variables so injected
   controls match the shadcn look without editing the Rust source.
═══════════════════════════════════════════════════════════════ */

/* Cards: one radius everywhere so nested cards stop mismatching. */
.card {
    --bs-card-border-radius: var(--radius);
    --bs-card-inner-border-radius: calc(var(--radius) - 1px);
    --bs-card-border-color: var(--border);
}
/* When a Bootstrap .card was converted to .mlab-ui-card but an inner
   .card-body/.card-header/.card-footer was kept (or comes from injected
   backend HTML), Bootstrap's spacing vars are no longer inherited from a
   .card ancestor, which collapses their left/right padding. Redeclare them
   here so nested Bootstrap card parts keep proper padding. */
.mlab-ui-card {
    --bs-card-spacer-x: 1.25rem;
    --bs-card-spacer-y: 1rem;
    --bs-card-cap-padding-x: 1.25rem;
    --bs-card-cap-padding-y: .75rem;
    --bs-card-border-radius: var(--radius);
    --bs-card-inner-border-radius: calc(var(--radius) - 1px);
}
/* Explicit padding (does NOT rely on Bootstrap's --bs-card-* var inheritance,
   which breaks once the .card ancestor is gone). Covers leftover Bootstrap
   card parts AND backend-injected content placed directly in a card. */
.mlab-ui-card > .card-body   { padding: 1rem 1.25rem; }
.mlab-ui-card > .card-header { padding: .75rem 1.25rem; }
.mlab-ui-card > .card-footer { padding: .75rem 1.25rem; }
/* redkit-result filter bar: match the card's horizontal padding. */
.mlab-ui-card > .filter-bar  { padding-left: 1.25rem; padding-right: 1.25rem; }

/* Buttons: shadcn sizing + radius + neutral outline + brand fill. */
.btn {
    --bs-btn-border-radius: var(--radius);
    --bs-btn-font-weight: 500;
    --bs-btn-padding-x: 1rem;
    --bs-btn-padding-y: .5rem;
    --bs-btn-font-size: .875rem;
    white-space: nowrap;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .4rem;
    /* Konrix sets radius with high specificity — force the shadcn value. */
    border-radius: var(--radius) !important;
}
.btn-sm {
    --bs-btn-padding-x: .75rem;
    --bs-btn-padding-y: .375rem;
    --bs-btn-font-size: .8125rem;
    border-radius: calc(var(--radius) - 2px) !important;
}
.btn-lg { border-radius: var(--radius) !important; }

/* Konrix paints button colors directly (not via --bs-btn-* vars), so we
   override the real properties. Scoped to backend-injected Bootstrap buttons;
   the mlab-ui-btn primitives never need this. */
.btn-primary {
    background-color: var(--primary) !important;
    border-color: var(--primary) !important;
    color: var(--primary-foreground) !important;
}
.btn-primary:hover,
.btn-primary:focus-visible,
.btn-primary:active {
    background-color: var(--primary) !important;
    border-color: var(--primary) !important;
    color: var(--primary-foreground) !important;
    box-shadow: 0 4px 12px rgba(var(--mlab-shadow-ink-rgb), .20) !important;
}
.btn-outline-primary,
.btn-outline-secondary,
.btn-outline-dark {
    background-color: transparent !important;
    border-color: var(--border) !important;
    color: var(--foreground) !important;
}
.btn-outline-primary:hover,
.btn-outline-secondary:hover,
.btn-outline-dark:hover,
.btn-outline-primary:active,
.btn-outline-secondary:active,
.btn-outline-dark:active {
    background-color: var(--muted) !important;
    border-color: var(--border) !important;
    color: var(--foreground) !important;
}
/* Accent-forward Bootstrap button when the backend wants emphasis. */
.btn-accent {
    --bs-btn-bg: var(--accent);
    --bs-btn-border-color: var(--accent);
    --bs-btn-color: var(--accent-foreground);
    --bs-btn-hover-bg: color-mix(in srgb, var(--accent) 88%, #000);
    --bs-btn-hover-border-color: color-mix(in srgb, var(--accent) 88%, #000);
    --bs-btn-hover-color: var(--accent-foreground);
}

/* Native controls (plain checkboxes, radios, ranges, progress) follow the
   accent too; Bootstrap's .form-check-input draws its own and is handled below. */
:root { accent-color: var(--accent); }

/* Checkboxes / switches / radios: use the amber accent when checked, so they
   never fall back to the theme's (sometimes green) primary. */
.form-check-input:checked {
    background-color: var(--accent) !important;
    border-color: var(--accent) !important;
}
.form-check-input:focus { border-color: var(--ring); box-shadow: var(--ring-shadow); }

/* Badges: soft shadcn pills for injected .badge markup. */
.badge { border-radius: var(--mlab-radius-pill); font-weight: 600; }
/* bg-primary badge → neutral primary (theme's primary is green in some dark configs). */
.badge.bg-primary { background-color: var(--primary) !important; color: var(--primary-foreground) !important; }

/* Alerts: align radius/border with the token system. */
.alert { --bs-alert-border-radius: var(--radius); }

/* ═══════════════════════════════════════════════════════════════
   APP SHELL — topbar + sidebar (Konrix classes, shadcn refinement)
═══════════════════════════════════════════════════════════════ */

/* Topbar: drop the glassmorphism for a solid surface + clean hairline.
   Pure white in light, opaque near-black in dark. */
.app-topbar {
    background: #ffffff !important;
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
    border-bottom: 1px solid var(--border) !important;
    box-shadow: none !important;
}
html[data-bs-theme=dark] .app-topbar {
    background: var(--ins-body-bg, #020202) !important;
}

/* Topbar dropdowns (account menu, product menus): clean shadcn popover. */
.app-topbar .dropdown-menu {
    background: #ffffff;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--mlab-shadow-lg);
    padding: .35rem;
    min-width: 220px;
}
html[data-bs-theme=dark] .app-topbar .dropdown-menu {
    background: var(--ins-tertiary-bg, #111);
}
.app-topbar .dropdown-menu .dropdown-item {
    display: flex;
    align-items: center;
    gap: .55rem;
    border-radius: calc(var(--radius) - 2px);
    padding: .5rem .6rem;
    margin: 1px 0;
    font-size: .875rem;
    font-weight: 500;
    color: var(--foreground);
}
.app-topbar .dropdown-menu .dropdown-item:hover,
.app-topbar .dropdown-menu .dropdown-item:focus {
    background: var(--muted);
    color: var(--foreground);
}
.app-topbar .dropdown-menu .dropdown-item > svg,
.app-topbar .dropdown-menu .dropdown-item > [data-lucide] { width: 16px; height: 16px; }
.app-topbar .dropdown-menu .dropdown-divider {
    border-top: 1px solid var(--border);
    margin: .35rem -.05rem;
    opacity: 1;
}
.app-topbar .dropdown-menu .dropdown-header {
    font-size: .68rem;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: var(--muted-foreground);
}

/* ── Topbar mega-menu (Resources) + product menus (Governance/Detection/…) ──
   Align the dense nav dropdowns: one amber accent instead of four product
   colors, muted hovers, token borders. Markup/JS untouched. */
.mlab-mega-menu, .mlab-product-menu { padding: 0 !important; }

.mlab-mega-menu-col + .mlab-mega-menu-col { border-left-color: var(--border) !important; }
.mlab-mega-menu-footer {
    border-top: 1px solid var(--border) !important;
    background: var(--muted) !important;
}
.mlab-mega-menu-footer a { color: var(--muted-foreground) !important; }
.mlab-mega-menu-footer a:hover { color: var(--foreground) !important; }

.mlab-dropdown-eyebrow, .mlab-dropdown-eyebrow-inline {
    color: var(--muted-foreground) !important;
    opacity: 1 !important;
    font-weight: 600;
}

.mlab-dropdown-link {
    color: var(--foreground);
    border-radius: calc(var(--radius) - 2px);
    font-weight: 500;
    padding: .4rem .5rem;
}
.mlab-dropdown-link:hover { background: var(--muted); }
.mlab-dropdown-link i[data-lucide] { opacity: 1; color: var(--muted-foreground); }

.mlab-product-item { border-radius: calc(var(--radius) - 2px); }
.mlab-product-item:hover { background: var(--muted); }

/* One calm amber icon chip everywhere (was 4 product colors). */
.mlab-product-icon {
    background: var(--accent-subtle) !important;
    border-radius: var(--mlab-radius-sm);
}
.mlab-product-icon i[data-lucide] { color: var(--accent) !important; }
.mlab-product-item.is-soon .mlab-product-icon {
    background: var(--muted) !important;
}
.mlab-product-item.is-soon .mlab-product-icon i[data-lucide] { color: var(--muted-foreground) !important; }

.mlab-product-title { color: var(--foreground); }
.mlab-product-subtitle { color: var(--muted-foreground); }
.mlab-product-sublinks a { color: var(--muted-foreground); }
.mlab-product-sublinks a:hover { color: var(--accent); }

.mlab-soon-badge {
    background: var(--muted);
    color: var(--muted-foreground);
    border-radius: var(--mlab-radius-sm);
    font-weight: 600;
}

/* Topbar action links (Resources/Governance/… buttons, theme toggle, search). */
.app-topbar .topbar-menu .topbar-item .topbar-link:hover { background: var(--muted) !important; }

/* Sidebar section labels: quiet uppercase eyebrows. */
.side-nav .side-nav-title {
    text-transform: uppercase;
    letter-spacing: .06em;
    font-size: .68rem;
    font-weight: 600;
    color: var(--muted-foreground);
    padding: .75rem .85rem .35rem;
    margin: 0;
}

/* Sidebar items: rounded, quiet by default, muted hover. */
.side-nav .side-nav-link {
    border-radius: var(--radius);
    margin: 1px .5rem;
    padding: .5rem .6rem;
    color: var(--muted-foreground);
    font-weight: 500;
    transition: background-color var(--mlab-dur-fast) var(--mlab-ease),
                color var(--mlab-dur-fast) var(--mlab-ease);
}
.side-nav .side-nav-link:hover {
    background: var(--muted);
    color: var(--foreground);
}
.side-nav .side-nav-link .menu-icon { color: inherit; }

/* Active item: amber-tinted surface + amber text/icon. */
.side-nav .side-nav-item.active > .side-nav-link,
.side-nav .side-nav-link.active {
    background: var(--accent-subtle);
    color: var(--accent);
}
.side-nav .side-nav-item.active > .side-nav-link .menu-icon,
.side-nav .side-nav-link.active .menu-icon {
    color: var(--accent);
}
/* Submenu: slightly tighter, no double icon column. */
.side-nav .sub-menu .side-nav-link { padding-left: 2.4rem; font-weight: 400; }

/* ═══════════════════════════════════════════════════════════════
   ADMIN TABLES
   The /admin listings share one toolbar (row count + text filter),
   driven by assets/js/admin-tables.js. Kept here so every admin page
   picks it up from the primitive layer instead of inlining its own.
═══════════════════════════════════════════════════════════════ */
.admin-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: .5rem;
    padding: 0 1.25rem .75rem;
}
.admin-toolbar__count {
    font-size: .75rem;
    color: var(--muted-foreground);
}
.admin-toolbar__input { width: 240px; max-width: 100%; }
/* A header sitting right above the toolbar already spaced the block. */
.mlab-ui-card__header + .admin-toolbar { padding-top: .25rem; }
/* Rows that link to a detail page read as clickable. */
.admin-row { cursor: pointer; }

/* A list row that is a link (dashboard recent scans, active jobs). */
.mlab-row-link { border-radius: 6px; transition: background .12s; }
.mlab-row-link:hover { background: color-mix(in srgb, currentColor 6%, transparent); }
/* A bookmark toggle that is on reads as on, not as one more grey icon. */
.mlab-bm.is-on { color: #d97706; }
.mlab-bm.is-on svg { fill: currentColor; }

/* ─── Case picker (assets/js/mlab-case-picker.js) ─── */
.mlab-case-picker .modal-content { border-radius: 12px; }
.mlab-case-picker .mcp-subject { font-size: .8rem; font-family: var(--bs-font-monospace, monospace); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 380px; }
.mlab-case-picker .mcp-search { position: relative; margin-bottom: .75rem; }
.mlab-case-picker .mcp-search svg { position: absolute; left: .7rem; top: 50%; transform: translateY(-50%); width: 15px; height: 15px; opacity: .55; pointer-events: none; }
.mlab-case-picker .mcp-search input { padding-left: 2.1rem; width: 100%; }
.mlab-case-picker .mcp-tabs { margin-bottom: .75rem; }
.mlab-case-picker .mcp-n { opacity: .6; font-weight: 400; margin-left: .15rem; }
.mlab-case-picker .mcp-list { display: flex; flex-direction: column; gap: .35rem; min-height: 220px; max-height: 320px; overflow-y: auto; }
.mlab-case-picker .mcp-item { display: flex; align-items: center; gap: .6rem; width: 100%; text-align: left; padding: .6rem .75rem; border-radius: 8px;
    border: 1px solid var(--ins-border-color, #e5e7eb); background: transparent; color: inherit; cursor: pointer; transition: background .12s, border-color .12s; }
.mlab-case-picker .mcp-item:hover, .mlab-case-picker .mcp-item:focus-visible { background: color-mix(in srgb, currentColor 5%, transparent); border-color: #d97706; outline: none; }
.mlab-case-picker .mcp-item:disabled { opacity: .5; cursor: progress; }
.mlab-case-picker .mcp-item[aria-hidden="true"] { pointer-events: none; } /* loading placeholders */
.mlab-case-picker .mcp-item svg { width: 15px; height: 15px; opacity: .45; flex-shrink: 0; }
.mlab-case-picker .mcp-item-main { flex: 1; min-width: 0; }
.mlab-case-picker .mcp-item-title { font-weight: 600; font-size: .88rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mlab-case-picker .mcp-item-meta { font-size: .75rem; opacity: .65; }
.mlab-case-picker .mcp-empty { font-size: .85rem; opacity: .7; padding: 1.25rem .5rem; text-align: center; }
.mlab-case-picker .mcp-error { font-size: .82rem; margin-top: .6rem; }
.mlab-case-picker .mcp-done { text-align: center; padding: 1rem .5rem .5rem; }
.mlab-case-picker .mcp-done > svg { width: 34px; height: 34px; color: var(--mlab-success-fg, #16a34a); margin-bottom: .6rem; }
.mlab-case-picker .mcp-footer { display: block; }
.mlab-case-picker .mcp-new { display: flex; gap: .5rem; width: 100%; margin: 0; }
.mlab-case-picker .mcp-new input { flex: 1; min-width: 0; }
.mlab-case-picker .mcp-more { font-size: .76rem; opacity: .65; text-align: center; padding: .5rem .25rem .25rem; }

/* Redkit topbar link: the one red exception. On hover the text itself fills
   red, swept left to right (gradient clipped to the glyphs). Lives on the
   inner span so the button's hover background can't reset it. */
.app-topbar .mlab-topbar-redkit > span {
    background-image: linear-gradient(to right, var(--mlab-danger) 50%, currentColor 50%);
    background-size: 200% 100%;
    background-position: 100% 0;
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    transition: background-position .35s ease;
}
.app-topbar .mlab-topbar-redkit:hover > span,
.app-topbar .mlab-topbar-redkit:focus-visible > span {
    background-position: 0 0;
}
@media (prefers-reduced-motion: reduce) {
    .app-topbar .mlab-topbar-redkit > span { transition: none; }
}

/* ─── Dialog (mlabConfirm / mlabPrompt, html/inject/footer.html) ───
   No Bootstrap "fade" on purpose (see bootstrap-modal rules in footer.html);
   the entrance is this CSS animation instead, so show() is never blocked. */
/* The theme hides every .modal-dialog (opacity 0, scale .85) and relies on its
   own zoomInModal animation to reveal it; pin the resting state so the dialog
   stays visible whatever happens to the animation (reduced motion included). */
.mlab-dialog .modal-dialog { max-width: 440px; opacity: 1; transform: none; }
.mlab-dialog .modal-content {
    border: 1px solid var(--border);
    border-radius: 14px;
    background: var(--card);
    color: var(--foreground);
    box-shadow: 0 24px 64px rgba(var(--mlab-shadow-ink-rgb), .22);
    overflow: hidden;
}
.mlab-dialog.show .modal-dialog { animation: mlab-dialog-in .22s cubic-bezier(.2, .8, .2, 1); }
@keyframes mlab-dialog-in { from { opacity: 0; transform: translateY(8px) scale(.97); } }
.mlab-dialog-body { padding: 1.4rem 1.4rem 1.1rem; }
.mlab-dialog-head { display: flex; gap: .9rem; align-items: flex-start; }
.mlab-dialog-icon {
    flex: 0 0 auto;
    width: 40px; height: 40px; border-radius: 50%;
    display: grid; place-items: center;
}
.mlab-dialog-icon svg { width: 20px; height: 20px; }
.mlab-dialog-icon--danger  { background: var(--mlab-danger-bg);  color: var(--mlab-danger); }
.mlab-dialog-icon--warning { background: rgba(var(--accent-rgb), .12); color: var(--accent); }
.mlab-dialog-icon--primary { background: var(--muted); color: var(--foreground); }
.mlab-dialog-icon--success { background: var(--mlab-success-bg); color: var(--mlab-success); }
.mlab-dialog-text { min-width: 0; padding-top: .15rem; }
.mlab-dialog-title { font-size: 1rem; font-weight: 600; line-height: 1.35; margin: 0 0 .3rem; color: var(--foreground); }
.mlab-dialog-desc { font-size: .875rem; line-height: 1.55; color: var(--muted-foreground); margin: 0; overflow-wrap: anywhere; white-space: pre-line; }
.mlab-dialog-fields { display: flex; flex-direction: column; gap: .9rem; margin-top: 1.15rem; }
.mlab-dialog-fields[hidden] { display: none; }
.mlab-dialog-field .mlab-ui-label { display: block; }
.mlab-dialog-input { position: relative; }
.mlab-dialog-input .mlab-ui-input[type="password"],
.mlab-dialog-input .mlab-ui-input:has(+ .mlab-dialog-eye) { padding-right: 2.5rem; }
.mlab-dialog-eye {
    position: absolute; right: .35rem; top: 50%; transform: translateY(-50%);
    width: 2rem; height: 2rem; border: 0; border-radius: calc(var(--radius) - 2px);
    background: transparent; color: var(--muted-foreground);
    display: grid; place-items: center; cursor: pointer;
}
.mlab-dialog-eye:hover { color: var(--foreground); background: var(--muted); }
.mlab-dialog-eye svg { width: 16px; height: 16px; }
.mlab-dialog-hint { font-size: .78rem; color: var(--muted-foreground); margin-top: .35rem; }
.mlab-dialog-error { font-size: .78rem; color: var(--mlab-danger); margin-top: .35rem; }
.mlab-dialog-error:empty { display: none; }
.mlab-dialog-field.is-invalid .mlab-ui-input { border-color: var(--destructive); }
.mlab-dialog-field.is-invalid .mlab-dialog-input { animation: mlab-dialog-shake .3s ease; }
@keyframes mlab-dialog-shake { 25% { transform: translateX(-4px); } 75% { transform: translateX(4px); } }
.mlab-dialog-foot {
    display: flex; justify-content: flex-end; gap: .5rem;
    padding: .85rem 1.4rem;
    background: var(--muted);
    border-top: 1px solid var(--border);
}
@media (max-width: 480px) {
    .mlab-dialog-foot { flex-direction: column-reverse; }
    .mlab-dialog-foot .mlab-ui-btn { width: 100%; }
}
@media (prefers-reduced-motion: reduce) {
    .mlab-dialog.show .modal-dialog, .mlab-dialog-field.is-invalid .mlab-dialog-input { animation: none; }
}

/* ─── Comfort: scrollbars, line breaks, numbers ─────────────────── */
/* Thin, quiet scrollbars in the boxes that scroll inside a page (the page's
   own scrollbar is left to the system). scrollbar-* for Chrome/Firefox, the
   ::-webkit-scrollbar block for Safari; it follows the text colour so it
   stays visible in dark mode. */
:is(.table-responsive, .mlab-ui-table-scroll, .modal, .modal-body, .dropdown-menu,
    .offcanvas-body, pre, textarea, .mcp-list) {
    scrollbar-width: thin;
    scrollbar-color: color-mix(in srgb, var(--foreground) 22%, transparent) transparent;
}
:is(.table-responsive, .mlab-ui-table-scroll, .modal, .modal-body, .dropdown-menu,
    .offcanvas-body, pre, textarea, .mcp-list)::-webkit-scrollbar { width: 8px; height: 8px; }
:is(.table-responsive, .mlab-ui-table-scroll, .modal, .modal-body, .dropdown-menu,
    .offcanvas-body, pre, textarea, .mcp-list)::-webkit-scrollbar-thumb {
    background: color-mix(in srgb, var(--foreground) 22%, transparent);
    border-radius: 999px; border: 2px solid transparent; background-clip: content-box;
}
:is(.table-responsive, .mlab-ui-table-scroll, .modal, .modal-body, .dropdown-menu,
    .offcanvas-body, pre, textarea, .mcp-list)::-webkit-scrollbar-track { background: transparent; }

/* No lone word on the last line of a heading; paragraphs avoid it too where
   the browser supports `pretty` (others keep the normal wrap). */
:is(h1, h2, h3, h4, h5, h6, .mlab-section-title, .mlab-ui-card__title, .mlab-dialog-title) { text-wrap: balance; }
p { text-wrap: pretty; }

/* Same-width digits where numbers change in place or stack in columns, so a
   counter does not jitter and a column lines up digit under digit. */
:is(.mlab-ui-table, .mlab-kv-v, .mlab-scan-live-count, .mlab-scan-pill-count,
    .mlab-score-ring-max, [data-count], [data-countup]) { font-variant-numeric: tabular-nums; }

/* Scroll stays where the pointer is: reaching the end of an inner box no
   longer scrolls the page behind it, and a horizontal swipe at the edge of a
   wide table no longer triggers the browser's back gesture. Only acts on
   boxes that actually scroll in that direction (checked: a horizontal-only
   box still lets the page scroll vertically). Inline max-height boxes are
   matched by their style so the tool pages need no markup change. Modals need
   nothing: Bootstrap locks the page while one is open. */
:is(.table-responsive, .mlab-search-suggest, .doc-nav, .ann-sidebar, .redkit-raw-pre, pre,
    textarea, [style*="max-height"][style*="overflow"]) { overscroll-behavior: contain; }

/* ─── Field errors (assets/js/mlab-validate.js, forms with data-live-validate) ─── */
:is(.mlab-ui-input, .mlab-ui-textarea, .mlab-ui-select, .form-control, .form-select)[aria-invalid="true"] {
    border-color: var(--destructive) !important;
}
:is(.mlab-ui-input, .mlab-ui-textarea, .mlab-ui-select, .form-control, .form-select)[aria-invalid="true"]:focus {
    box-shadow: 0 0 0 3px rgba(var(--mlab-danger-rgb), .18) !important;
}
.mlab-field-error { font-size: .78rem; line-height: 1.4; color: var(--mlab-danger); margin-top: .35rem; }
.mlab-field-error:empty { display: none; }
