/* ServerPanel design system — layered on Bootstrap 5.3 (utilities, grid, forms). */

/* ---------- Tokens ---------- */
:root,
[data-bs-theme=light] {
    --sp-bg: #f4f6fa;
    --sp-surface: #ffffff;
    --sp-surface-2: #f8fafc;
    --sp-surface-hover: #f1f5f9;
    --sp-border: #e3e8ef;
    --sp-border-strong: #cbd5e1;
    --sp-text: #0f172a;
    --sp-text-2: #334155;
    --sp-muted: #64748b;
    --sp-primary: #2563eb;
    --sp-primary-hover: #1d4ed8;
    --sp-primary-soft: #eff4ff;
    --sp-success: #16a34a;
    --sp-success-soft: #ecfdf3;
    --sp-warning: #d97706;
    --sp-warning-soft: #fff7ea;
    --sp-danger: #dc2626;
    --sp-danger-soft: #fef1f1;
    --sp-info: #0891b2;
    --sp-info-soft: #ecfbff;
    --sp-neutral-soft: #f1f5f9;
    --sp-shadow-sm: 0 1px 2px rgba(15, 23, 42, .05);
    --sp-shadow: 0 1px 3px rgba(15, 23, 42, .06), 0 1px 2px rgba(15, 23, 42, .04);
    --sp-shadow-lg: 0 20px 40px -12px rgba(15, 23, 42, .25);
    --sp-sidebar: #0f172a;
    --sp-sidebar-2: #1e293b;
    --sp-sidebar-text: #cbd5e1;
    --sp-sidebar-muted: #64748b;
    --sp-sidebar-active: #ffffff;
    --sp-radius: 10px;
    --sp-radius-sm: 7px;
    --sp-code-bg: #0f172a;
    --sp-code-text: #e2e8f0;
}

[data-bs-theme=dark] {
    --sp-bg: #0a0f1c;
    --sp-surface: #111827;
    --sp-surface-2: #0f1626;
    --sp-surface-hover: #182133;
    --sp-border: #1f2a3c;
    --sp-border-strong: #334155;
    --sp-text: #e5e9f0;
    --sp-text-2: #cbd5e1;
    --sp-muted: #8b98ad;
    --sp-primary: #3b82f6;
    --sp-primary-hover: #60a5fa;
    --sp-primary-soft: rgba(59, 130, 246, .14);
    --sp-success: #22c55e;
    --sp-success-soft: rgba(34, 197, 94, .13);
    --sp-warning: #f59e0b;
    --sp-warning-soft: rgba(245, 158, 11, .14);
    --sp-danger: #f87171;
    --sp-danger-soft: rgba(248, 113, 113, .13);
    --sp-info: #22d3ee;
    --sp-info-soft: rgba(34, 211, 238, .12);
    --sp-neutral-soft: rgba(148, 163, 184, .12);
    --sp-shadow-sm: none;
    --sp-shadow: 0 1px 2px rgba(0, 0, 0, .3);
    --sp-shadow-lg: 0 24px 48px -12px rgba(0, 0, 0, .6);
    --sp-sidebar: #070b14;
    --sp-sidebar-2: #131b2c;
    --sp-code-bg: #070b14;
}

/* Map tokens onto Bootstrap so its components follow the theme. */
:root, [data-bs-theme] {
    --bs-body-bg: var(--sp-bg);
    --bs-body-color: var(--sp-text);
    --bs-emphasis-color: var(--sp-text);
    --bs-secondary-color: var(--sp-muted);
    --bs-tertiary-bg: var(--sp-surface-2);
    --bs-border-color: var(--sp-border);
    --bs-border-radius: var(--sp-radius-sm);
    --bs-link-color: var(--sp-primary);
    --bs-link-color-rgb: 37, 99, 235;
    --bs-link-hover-color: var(--sp-primary-hover);
    --bs-font-sans-serif: "Segoe UI Variable Text", "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue", Arial, sans-serif;
    --bs-body-font-size: .9rem;
    --bs-focus-ring-color: rgba(37, 99, 235, .25);
}

html, body { background: var(--sp-bg); color: var(--sp-text); }
body { -webkit-font-smoothing: antialiased; }
h1, .h1 { font-size: 1.45rem; font-weight: 650; letter-spacing: -.01em; }
h2, .h2 { font-size: 1.1rem; font-weight: 600; }
h3, .h3 { font-size: .98rem; font-weight: 600; }
code { color: var(--sp-text-2); background: var(--sp-neutral-soft); padding: .1em .35em; border-radius: 5px; font-size: .85em; }
a { text-decoration: none; }
a:hover { text-decoration: underline; }
.text-muted, .text-secondary { color: var(--sp-muted) !important; }
.small, small { font-size: .82rem; }
.mono { font-family: ui-monospace, "Cascadia Mono", Consolas, monospace; font-size: .85em; }
.min-w-0 { min-width: 0; }

/* ---------- App shell ---------- */
.app-shell { display: grid; grid-template-columns: 252px minmax(0, 1fr); min-height: 100vh; }
.app-main { min-width: 0; display: flex; flex-direction: column; }
.app-content { padding: 28px 32px 48px; max-width: 1440px; width: 100%; margin: 0 auto; }
.app-mobilebar { display: none; }
#nav-toggle { display: none; }

.sidebar {
    position: sticky; top: 0; height: 100vh;
    background: var(--sp-sidebar); color: var(--sp-sidebar-text);
    display: flex; flex-direction: column;
    border-right: 1px solid rgba(255, 255, 255, .04);
}
.sidebar-brand { display: flex; align-items: center; gap: .65rem; padding: 18px 18px 14px; color: #fff; font-weight: 650; font-size: 1.02rem; text-decoration: none !important; }
.sidebar-brand .logo {
    width: 32px; height: 32px; border-radius: 9px; display: grid; place-items: center;
    background: linear-gradient(135deg, #3b82f6, #6366f1); color: #fff; font-size: 1rem;
    box-shadow: 0 4px 12px rgba(59, 130, 246, .35);
}
.sidebar-scroll { flex: 1; overflow-y: auto; padding: 4px 10px 12px; }
.sidebar-section { font-size: .68rem; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--sp-sidebar-muted); padding: 16px 10px 6px; }
.sidebar-link {
    display: flex; align-items: center; gap: .7rem; padding: 7px 10px; margin: 1px 0;
    border-radius: 8px; color: var(--sp-sidebar-text); font-size: .88rem; text-decoration: none !important;
    transition: background .12s, color .12s;
}
.sidebar-link i { font-size: 1.02rem; width: 18px; text-align: center; opacity: .85; }
.sidebar-link:hover { background: var(--sp-sidebar-2); color: #fff; }
.sidebar-link.active { background: var(--sp-sidebar-2); color: var(--sp-sidebar-active); box-shadow: inset 2px 0 0 #3b82f6; }
.sidebar-link .count { margin-left: auto; font-size: .7rem; font-weight: 600; background: #dc2626; color: #fff; border-radius: 999px; padding: 1px 7px; }
.sidebar-link .muted { margin-left: auto; font-size: .72rem; color: var(--sp-sidebar-muted); }
.sidebar-server { font-size: .85rem; }
.sidebar-server .name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sidebar-server .counts { display: block; font-size: .7rem; color: var(--sp-sidebar-muted); line-height: 1.2; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sidebar-footer { border-top: 1px solid rgba(255, 255, 255, .06); padding: 10px; }
.sidebar-user { display: flex; align-items: center; gap: .6rem; padding: 6px 8px; border-radius: 8px; }
.sidebar-user .avatar { width: 30px; height: 30px; border-radius: 50%; background: var(--sp-sidebar-2); display: grid; place-items: center; color: #fff; font-weight: 600; font-size: .8rem; flex: none; }
.sidebar-user .who { min-width: 0; flex: 1; font-size: .8rem; line-height: 1.2; }
.sidebar-user .who .email { color: #fff; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sidebar-user .who .role { color: var(--sp-sidebar-muted); font-size: .72rem; }
.sidebar-icon-btn { background: none; border: 0; color: var(--sp-sidebar-text); width: 30px; height: 30px; border-radius: 7px; display: grid; place-items: center; }
.sidebar-icon-btn:hover { background: var(--sp-sidebar-2); color: #fff; }
.nav-backdrop { display: none; }

@media (max-width: 991.98px) {
    .app-shell { grid-template-columns: minmax(0, 1fr); }
    .sidebar { position: fixed; left: 0; top: 0; bottom: 0; width: 264px; z-index: 1045; transform: translateX(-100%); transition: transform .2s ease; }
    #nav-toggle:checked ~ .sidebar { transform: none; box-shadow: var(--sp-shadow-lg); }
    #nav-toggle:checked ~ .nav-backdrop { display: block; position: fixed; inset: 0; background: rgba(2, 6, 23, .5); z-index: 1040; }
    .app-mobilebar { display: flex; align-items: center; gap: .75rem; height: 54px; padding: 0 16px; background: var(--sp-sidebar); color: #fff; position: sticky; top: 0; z-index: 1030; }
    .app-mobilebar label { cursor: pointer; font-size: 1.4rem; line-height: 1; }
    .app-content { padding: 20px 16px 40px; }
}

/* ---------- Page header ---------- */
.page-header { display: flex; align-items: flex-start; gap: 16px; flex-wrap: wrap; margin-bottom: 22px; }
.page-header .titles { flex: 1; min-width: 220px; }
.page-header h1 { margin: 0; display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; }
.page-header .subtitle { color: var(--sp-muted); margin-top: 4px; }
.page-header .actions { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
/* A muted count next to the page title, e.g. "Alerts  3 open". */
.page-header h1 .meta { font-size: .9rem; font-weight: 400; color: var(--sp-muted); letter-spacing: 0; }
.crumbs { font-size: .8rem; color: var(--sp-muted); margin-bottom: 6px; display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.crumbs a { color: var(--sp-muted); }
.crumbs i { font-size: .7rem; }

/* ---------- Cards ---------- */
.card { --bs-card-bg: var(--sp-surface); --bs-card-border-color: var(--sp-border); --bs-card-border-radius: var(--sp-radius); --bs-card-cap-bg: transparent; box-shadow: var(--sp-shadow-sm); }
.card-header { display: flex; align-items: center; gap: 10px; padding: 14px 18px; border-bottom: 1px solid var(--sp-border); }
.card-header h2, .card-header h3 { margin: 0; font-size: .95rem; font-weight: 600; }
.card-header .actions { margin-left: auto; display: flex; gap: 6px; align-items: center; }
.card-body { padding: 18px; }
.card-footer { background: var(--sp-surface-2); border-top: 1px solid var(--sp-border); padding: 12px 18px; }
.card-table .table { margin: 0; }
.card-table .table > :not(caption) > * > *:first-child { padding-left: 18px; }
.card-table .table > :not(caption) > * > *:last-child { padding-right: 18px; }

/* Stat cards sit in a .stat-grid: as many 150px+ columns as fit, all the same width, so six cards share one row
   from 1366px up (the content area is ~1050px there) and wrap evenly below that. Labels are short ("Online",
   "Changes 24h") and never wrap; the sub line truncates instead of wrapping. */
.stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 16px; }
.stat-card { display: flex; flex-direction: row; gap: 12px; align-items: center; padding: 14px 14px 14px 16px; min-width: 0; }
.stat-card .icon { width: 40px; height: 40px; border-radius: 11px; display: grid; place-items: center; font-size: 1.15rem; flex: none; }
.stat-card .icon + div { min-width: 0; flex: 1; }
.stat-card .label { color: var(--sp-muted); font-size: .8rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.stat-card .value { font-size: 1.4rem; font-weight: 650; line-height: 1.2; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.stat-card .sub { color: var(--sp-muted); font-size: .76rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
a.stat-card { color: inherit; transition: border-color .12s, box-shadow .12s; }
a.stat-card:hover { text-decoration: none; border-color: var(--sp-border-strong); box-shadow: var(--sp-shadow); }

/* Plesk-style "everything for this domain" tiles on the domain dashboard. */
.tool-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 12px; }
a.tool-tile { display: flex; gap: 12px; align-items: flex-start; padding: 13px 14px; border: 1px solid var(--sp-border); border-radius: var(--sp-radius); color: inherit; background: var(--sp-surface); min-width: 0; transition: border-color .12s, box-shadow .12s; }
a.tool-tile:hover { text-decoration: none; border-color: var(--sp-border-strong); box-shadow: var(--sp-shadow); }
.tool-tile > i { font-size: 1.15rem; color: var(--sp-primary); line-height: 1.3; }
.tool-tile .name { font-weight: 600; font-size: .9rem; }
.tool-tile .desc { color: var(--sp-muted); font-size: .78rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tool-tile > div { min-width: 0; }
.table-list tr.row-highlight > td { background: var(--sp-primary-soft); }

.tone-primary { background: var(--sp-primary-soft); color: var(--sp-primary); }
.tone-success { background: var(--sp-success-soft); color: var(--sp-success); }
.tone-warning { background: var(--sp-warning-soft); color: var(--sp-warning); }
.tone-danger { background: var(--sp-danger-soft); color: var(--sp-danger); }
.tone-info { background: var(--sp-info-soft); color: var(--sp-info); }
.tone-neutral { background: var(--sp-neutral-soft); color: var(--sp-muted); }

/* ---------- Tables ----------
   List tables follow docs/superpowers/specs/2026-10-21-ui-standard.md. The classes to use:
   .table-list   on <table>: one-line 44px rows, cells vertically centred, nothing wraps. The name cell is a bold
                 link; secondary facts go into their own column or a title tooltip, never under the name.
   .truncate     on an inline element inside a cell (a link or span): ellipsis instead of wrapping. Give it a
                 width with style="--w: 260px" (default 240px) and the full text in title="…".
   .num          on <th>/<td>: right-aligned, nowrap, tabular digits for counts, sizes and percentages.
   .usage        a percentage next to a narrow inline meter: <span class="usage"><span>26%</span><span class="meter">…</span></span>.
   .row-actions  the last cell: one visible btn-sm btn-light with a label plus an <ActionMenu> (the "⋯" trigger).
   .action-menu  rendered by ActionMenu.razor / MenuItem.razor; the list is position: fixed (placed by spMenu in
                 panel.js) so .table-responsive cannot clip it. Danger items are red with a divider before them.
   Paths, IPs, versions and file names use the normal font in .text-muted, never .mono. */
.table { --bs-table-bg: transparent; --bs-table-color: var(--sp-text); --bs-table-border-color: var(--sp-border); --bs-table-hover-bg: var(--sp-surface-hover); margin-bottom: 0; }
.table > thead th { font-size: .72rem; text-transform: uppercase; letter-spacing: .05em; font-weight: 600; color: var(--sp-muted); background: var(--sp-surface-2); white-space: nowrap; padding-top: 10px; padding-bottom: 10px; }
.table > tbody td { padding-top: 11px; padding-bottom: 11px; vertical-align: middle; }
.table > tbody tr:last-child td { border-bottom: 0; }
.table .row-actions { white-space: nowrap; text-align: right; }
.table .cell-sub { color: var(--sp-muted); font-size: .78rem; margin-top: 2px; }
.table tr.clickable { cursor: pointer; }
.table-list > tbody > tr > td { height: 44px; padding-top: 6px; padding-bottom: 6px; white-space: nowrap; vertical-align: middle; }
.table-list > tbody > tr > td .badge-soft { vertical-align: middle; }
/* Rows that are done with (e.g. acknowledged alerts) are dimmed as a whole. */
.table-list > tbody > tr.dimmed > td { opacity: .55; }
/* A list table inside a card body (account pages): bordered box instead of the card's own edges. */
.bordered-table { border: 1px solid var(--sp-border); border-radius: var(--sp-radius-sm); }
.bordered-table .table > thead th:first-child { border-top-left-radius: var(--sp-radius-sm); }
.bordered-table .table > thead th:last-child { border-top-right-radius: var(--sp-radius-sm); }
.truncate { display: inline-block; max-width: var(--w, 240px); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: bottom; }
.num { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.usage { display: inline-flex; align-items: center; gap: 8px; white-space: nowrap; }
.usage > span:first-child { min-width: 2.6em; font-variant-numeric: tabular-nums; }
.usage .meter { width: 64px; flex: none; }

.action-menu { display: inline-block; vertical-align: middle; }
.action-menu-trigger { color: var(--sp-muted); font-size: 1rem; line-height: 1; }
.action-menu-trigger:hover, .action-menu-trigger[aria-expanded="true"] { color: var(--sp-text); background: var(--sp-surface-hover); }
.action-menu-list { position: fixed; z-index: 1055; min-width: 200px; padding: 6px; background: var(--sp-surface); border: 1px solid var(--sp-border); border-radius: var(--sp-radius-sm); box-shadow: var(--sp-shadow-lg); visibility: hidden; animation: sp-pop .12s ease; }
.menu-item { display: flex; align-items: center; gap: 10px; width: 100%; padding: 7px 10px; border: 0; background: none; border-radius: 6px; color: var(--sp-text-2); font-size: .86rem; text-align: left; white-space: nowrap; text-decoration: none !important; }
.menu-item i { width: 16px; text-align: center; font-size: .95rem; color: var(--sp-muted); }
.menu-item:hover, .menu-item:focus-visible { background: var(--sp-surface-hover); color: var(--sp-text); outline: none; }
.menu-item.danger, .menu-item.danger i { color: var(--sp-danger); }
.menu-item.danger:hover, .menu-item.danger:focus-visible { background: var(--sp-danger-soft); color: var(--sp-danger); }
.menu-item:disabled, .menu-item.disabled { opacity: .5; pointer-events: none; }
.menu-item:not(.danger) + .menu-item.danger { position: relative; margin-top: 9px; }
.menu-item:not(.danger) + .menu-item.danger::before { content: ""; position: absolute; left: -6px; right: -6px; top: -5px; height: 1px; background: var(--sp-border); }

/* ---------- Badges / status ---------- */
.badge-soft { display: inline-flex; align-items: center; gap: 5px; font-weight: 600; font-size: .72rem; padding: 3px 9px; border-radius: 999px; line-height: 1.4; white-space: nowrap; }
.badge-soft.success { background: var(--sp-success-soft); color: var(--sp-success); }
.badge-soft.warning { background: var(--sp-warning-soft); color: var(--sp-warning); }
.badge-soft.danger { background: var(--sp-danger-soft); color: var(--sp-danger); }
.badge-soft.info { background: var(--sp-info-soft); color: var(--sp-info); }
.badge-soft.primary { background: var(--sp-primary-soft); color: var(--sp-primary); }
.badge-soft.neutral { background: var(--sp-neutral-soft); color: var(--sp-muted); }
.dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; flex: none; background: var(--sp-muted); }
.dot.online, .dot.success { background: #22c55e; box-shadow: 0 0 0 3px rgba(34, 197, 94, .18); }
.dot.offline { background: #64748b; }
.dot.warning { background: #f59e0b; }
.dot.danger { background: #ef4444; }

/* ---------- Buttons & forms ---------- */
.btn { --bs-btn-font-size: .86rem; --bs-btn-padding-y: .42rem; --bs-btn-padding-x: .85rem; --bs-btn-border-radius: var(--sp-radius-sm); --bs-btn-font-weight: 500; display: inline-flex; align-items: center; justify-content: center; gap: .4rem; }
.btn-sm { --bs-btn-font-size: .8rem; --bs-btn-padding-y: .28rem; --bs-btn-padding-x: .6rem; }
.btn-lg { --bs-btn-font-size: .95rem; --bs-btn-padding-y: .6rem; }
.btn-primary { --bs-btn-bg: var(--sp-primary); --bs-btn-border-color: var(--sp-primary); --bs-btn-hover-bg: var(--sp-primary-hover); --bs-btn-hover-border-color: var(--sp-primary-hover); --bs-btn-active-bg: var(--sp-primary-hover); --bs-btn-disabled-bg: var(--sp-primary); --bs-btn-disabled-border-color: var(--sp-primary); }
.btn-light, .btn-outline-secondary { --bs-btn-color: var(--sp-text-2); --bs-btn-bg: var(--sp-surface); --bs-btn-border-color: var(--sp-border-strong); --bs-btn-hover-color: var(--sp-text); --bs-btn-hover-bg: var(--sp-surface-hover); --bs-btn-hover-border-color: var(--sp-border-strong); --bs-btn-active-bg: var(--sp-surface-hover); --bs-btn-active-color: var(--sp-text); --bs-btn-active-border-color: var(--sp-border-strong); --bs-btn-disabled-color: var(--sp-muted); --bs-btn-disabled-bg: var(--sp-surface); --bs-btn-disabled-border-color: var(--sp-border); }
.btn-ghost { --bs-btn-color: var(--sp-text-2); --bs-btn-hover-bg: var(--sp-surface-hover); --bs-btn-hover-color: var(--sp-text); --bs-btn-active-bg: var(--sp-surface-hover); border: 0; }
.btn-ghost.danger { --bs-btn-color: var(--sp-danger); --bs-btn-hover-color: var(--sp-danger); --bs-btn-hover-bg: var(--sp-danger-soft); }
.btn-danger { --bs-btn-bg: #dc2626; --bs-btn-border-color: #dc2626; --bs-btn-hover-bg: #b91c1c; --bs-btn-hover-border-color: #b91c1c; }
.btn-outline-danger { --bs-btn-color: var(--sp-danger); --bs-btn-border-color: var(--sp-border-strong); --bs-btn-bg: var(--sp-surface); --bs-btn-hover-bg: var(--sp-danger-soft); --bs-btn-hover-color: var(--sp-danger); --bs-btn-hover-border-color: var(--sp-danger); }
.btn-icon { --bs-btn-padding-x: .45rem; }
.btn .spinner-border { width: .9rem; height: .9rem; border-width: .15em; }

.form-control, .form-select { background-color: var(--sp-surface); border-color: var(--sp-border-strong); color: var(--sp-text); font-size: .88rem; border-radius: var(--sp-radius-sm); padding: .45rem .7rem; }
.form-control:focus, .form-select:focus { border-color: var(--sp-primary); box-shadow: 0 0 0 3px var(--bs-focus-ring-color); background-color: var(--sp-surface); color: var(--sp-text); }
.form-control::placeholder { color: var(--sp-muted); opacity: .7; }
.form-label { font-size: .8rem; font-weight: 600; color: var(--sp-text-2); margin-bottom: 5px; }
.form-text { color: var(--sp-muted); font-size: .78rem; }
.form-check-input { border-color: var(--sp-border-strong); background-color: var(--sp-surface); }
.form-check-input:checked { background-color: var(--sp-primary); border-color: var(--sp-primary); }
.input-group-text { background: var(--sp-surface-2); border-color: var(--sp-border-strong); color: var(--sp-muted); font-size: .85rem; }
.validation-message, .text-danger { color: var(--sp-danger) !important; }
.invalid { border-color: var(--sp-danger) !important; }

/* ---------- Tabs ---------- */
.sp-tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--sp-border); margin-bottom: 22px; overflow-x: auto; scrollbar-width: none; }
.sp-tabs::-webkit-scrollbar { display: none; }
.sp-tab { display: inline-flex; align-items: center; gap: .45rem; padding: 10px 14px; color: var(--sp-muted); font-weight: 500; font-size: .87rem; border: 0; background: none; border-bottom: 2px solid transparent; margin-bottom: -1px; white-space: nowrap; text-decoration: none !important; }
.sp-tab:hover { color: var(--sp-text); }
.sp-tab.active { color: var(--sp-primary); border-bottom-color: var(--sp-primary); }

.segmented { display: inline-flex; background: var(--sp-surface-2); border: 1px solid var(--sp-border); border-radius: 9px; padding: 3px; gap: 2px; }
.segmented button { border: 0; background: none; padding: 5px 12px; border-radius: 7px; font-size: .82rem; color: var(--sp-muted); font-weight: 500; }
.segmented button.active { background: var(--sp-surface); color: var(--sp-text); box-shadow: var(--sp-shadow); }
/* .segmented.sm matches the height of a btn-sm so both can share a card header. */
.segmented.sm { padding: 2px; border-radius: 7px; }
.segmented.sm button { padding: 3px 10px; font-size: .78rem; border-radius: 5px; }

/* ---------- Empty / loading ---------- */
.empty-state { text-align: center; padding: 44px 20px; color: var(--sp-muted); }
.empty-state .icon { width: 52px; height: 52px; border-radius: 14px; display: inline-grid; place-items: center; font-size: 1.5rem; background: var(--sp-neutral-soft); color: var(--sp-muted); margin-bottom: 12px; }
.empty-state h3 { color: var(--sp-text); margin-bottom: 4px; }
.empty-state p { max-width: 420px; margin: 0 auto 14px; }
.loading-block { display: flex; align-items: center; justify-content: center; gap: .6rem; padding: 40px 20px; color: var(--sp-muted); }
.skeleton { background: linear-gradient(90deg, var(--sp-neutral-soft) 25%, var(--sp-surface-hover) 37%, var(--sp-neutral-soft) 63%); background-size: 400% 100%; animation: sp-shimmer 1.3s ease infinite; border-radius: 6px; height: 14px; }
@keyframes sp-shimmer { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }
.top-progress { position: fixed; top: 0; left: 0; right: 0; height: 3px; z-index: 2000; background: linear-gradient(90deg, transparent, var(--sp-primary), transparent); background-size: 50% 100%; animation: sp-progress 1s linear infinite; }
@keyframes sp-progress { 0% { background-position: -50% 0; } 100% { background-position: 150% 0; } }
.skeleton-table { padding: 6px 18px 4px; }
.skeleton-row { display: flex; gap: 24px; align-items: center; padding: 13px 0; border-bottom: 1px solid var(--sp-border); }
.skeleton-row:last-child { border-bottom: 0; }
.skeleton-row .skeleton { flex: 0 1 auto; min-width: 40px; }
/* Static placeholder in App.razor: shown until the first Blazor component renders before it. */
#app-boot { position: fixed; inset: 0; display: grid; place-items: center; color: var(--sp-muted); }
#app-boot:not(:first-child), .app-shell ~ #app-boot, .auth-wrap ~ #app-boot { display: none; }

/* ---------- Callouts ---------- */
.callout { display: flex; gap: 12px; padding: 12px 14px; border-radius: var(--sp-radius); border: 1px solid; font-size: .87rem; }
.callout > i { font-size: 1.05rem; line-height: 1.3; }
.callout.info { background: var(--sp-info-soft); border-color: transparent; color: var(--sp-text-2); }
.callout.info > i { color: var(--sp-info); }
.callout.warning { background: var(--sp-warning-soft); border-color: transparent; color: var(--sp-text-2); }
.callout.warning > i { color: var(--sp-warning); }
.callout.danger { background: var(--sp-danger-soft); border-color: transparent; color: var(--sp-text-2); }
.callout.danger > i { color: var(--sp-danger); }
.callout.success { background: var(--sp-success-soft); border-color: transparent; color: var(--sp-text-2); }
.callout.success > i { color: var(--sp-success); }

/* ---------- Code / secrets ---------- */
.code-block { position: relative; background: var(--sp-code-bg); color: var(--sp-code-text); border-radius: var(--sp-radius-sm); padding: 12px 48px 12px 14px; font-family: ui-monospace, "Cascadia Mono", Consolas, monospace; font-size: .8rem; white-space: pre-wrap; word-break: break-all; }
.code-block .copy { position: absolute; top: 8px; right: 8px; background: rgba(255, 255, 255, .08); border: 0; color: #cbd5e1; border-radius: 6px; width: 30px; height: 28px; display: grid; place-items: center; }
.code-block .copy:hover { background: rgba(255, 255, 255, .16); color: #fff; }

/* ---------- Key/value lists ---------- */
.kv { display: grid; grid-template-columns: minmax(120px, 38%) 1fr; gap: 9px 16px; margin: 0; font-size: .87rem; }
.kv dt { color: var(--sp-muted); font-weight: 500; }
.kv dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }

/* ---------- Meters ---------- */
.meter { height: 7px; border-radius: 999px; background: var(--sp-neutral-soft); overflow: hidden; }
.meter > span { display: block; height: 100%; border-radius: 999px; background: var(--sp-primary); transition: width .4s ease; }
.meter.warning > span { background: var(--sp-warning); }
.meter.danger > span { background: var(--sp-danger); }
.sparkline { width: 100%; height: 56px; display: block; }
.sparkline .line { fill: none; stroke-width: 1.8; vector-effect: non-scaling-stroke; }
.sparkline .area { opacity: .12; }

/* ---------- Modal ---------- */
.sp-modal-backdrop { position: fixed; inset: 0; background: rgba(2, 6, 23, .55); backdrop-filter: blur(2px); z-index: 1060; display: grid; place-items: center; padding: 16px; animation: sp-fade .12s ease; }
/* A modal declared inside a table cell (row actions) must not inherit its right alignment or nowrap. */
.sp-modal-backdrop { text-align: left; white-space: normal; }
.sp-modal { background: var(--sp-surface); color: var(--sp-text); border-radius: 14px; box-shadow: var(--sp-shadow-lg); width: 100%; max-width: 520px; max-height: calc(100vh - 32px); display: flex; flex-direction: column; border: 1px solid var(--sp-border); animation: sp-pop .14s ease; }
.sp-modal.lg { max-width: 760px; }
.sp-modal.xl { max-width: 1100px; }
.sp-modal-header { display: flex; align-items: flex-start; gap: 12px; padding: 18px 20px 6px; }
.sp-modal-header h2 { margin: 0; font-size: 1.05rem; }
.sp-modal-header .close { margin-left: auto; background: none; border: 0; color: var(--sp-muted); font-size: 1.1rem; border-radius: 6px; width: 30px; height: 30px; }
.sp-modal-header .close:hover { background: var(--sp-surface-hover); color: var(--sp-text); }
.sp-modal-body { padding: 10px 20px 18px; overflow-y: auto; }
.sp-modal-footer { display: flex; justify-content: flex-end; gap: 8px; padding: 14px 20px; border-top: 1px solid var(--sp-border); background: var(--sp-surface-2); border-radius: 0 0 14px 14px; }
.sp-modal .confirm-icon { width: 40px; height: 40px; border-radius: 11px; display: grid; place-items: center; font-size: 1.15rem; flex: none; }
@keyframes sp-fade { from { opacity: 0; } }
@keyframes sp-pop { from { opacity: 0; transform: translateY(6px) scale(.98); } }

/* ---------- Toasts ---------- */
.toast-stack { position: fixed; right: 18px; bottom: 18px; z-index: 1080; display: flex; flex-direction: column; gap: 10px; width: min(380px, calc(100vw - 36px)); }
.sp-toast { display: flex; gap: 11px; align-items: flex-start; background: var(--sp-surface); border: 1px solid var(--sp-border); border-radius: 11px; padding: 12px 12px 12px 14px; box-shadow: var(--sp-shadow-lg); animation: sp-pop .16s ease; font-size: .87rem; }
.sp-toast > i { font-size: 1.1rem; line-height: 1.25; }
.sp-toast.success > i { color: var(--sp-success); }
.sp-toast.error > i { color: var(--sp-danger); }
.sp-toast.info > i { color: var(--sp-info); }
.sp-toast .msg { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.sp-toast .msg strong { display: block; margin-bottom: 1px; }
.sp-toast .close { background: none; border: 0; color: var(--sp-muted); padding: 0 4px; }

/* ---------- File manager ---------- */
.file-icon { width: 30px; height: 30px; border-radius: 8px; display: inline-grid; place-items: center; font-size: 1rem; flex: none; }
.file-icon.folder { background: var(--sp-warning-soft); color: var(--sp-warning); }
.file-icon.file { background: var(--sp-neutral-soft); color: var(--sp-muted); }
.file-icon.code { background: var(--sp-primary-soft); color: var(--sp-primary); }
.file-icon.archive { background: var(--sp-info-soft); color: var(--sp-info); }
/* The Files tab: the toolbar holds the root switch and the Site filter; .path-strip is the 44px breadcrumb line under it
   (up button + .path-bar, normal font, slightly smaller); .file-row is icon + name in the one-line table. */
.list-toolbar .segmented { padding: 2px; }
.list-toolbar .segmented button { padding: 5px 11px; }
.path-strip { display: flex; align-items: center; gap: 8px; min-height: 44px; padding: 5px 18px; border-bottom: 1px solid var(--sp-border); }
.path-bar { display: flex; align-items: center; gap: 2px; flex-wrap: wrap; font-size: .85rem; }
.path-bar button { background: none; border: 0; color: var(--sp-primary); padding: 3px 7px; border-radius: 5px; font-weight: 500; }
.path-bar button:hover { background: var(--sp-primary-soft); }
.path-bar .sep { color: var(--sp-muted); font-size: .7rem; }
.file-row { display: inline-flex; align-items: center; gap: 10px; vertical-align: middle; min-width: 0; }
.file-row .file-icon { width: 28px; height: 28px; font-size: .95rem; }
.file-row .truncate { vertical-align: middle; }
/* Modern file manager: selection, cut (dimmed), drop targets, desktop drop overlay and the folder picker. */
.files-card { position: relative; }
.files-surface { outline: none; min-height: 120px; }
.files-table .check-col { width: 42px; padding-right: 0; }
.files-table .check-col .form-check-input { margin: 0; cursor: pointer; }
.files-table > tbody > tr { cursor: default; user-select: none; }
.files-table > tbody > tr.selected > td { background: var(--sp-primary-soft); }
.files-table > tbody > tr.drop-target > td { background: var(--sp-primary-soft); box-shadow: inset 0 1px 0 var(--sp-primary), inset 0 -1px 0 var(--sp-primary); }
.path-bar button.drop-target, .path-strip .btn.drop-target { background: var(--sp-primary-soft); outline: 1px dashed var(--sp-primary); }
.selection-bar { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 12px; padding: 7px 18px; background: var(--sp-primary-soft); border-bottom: 1px solid var(--sp-border); font-size: .87rem; }
.selection-bar .selection-actions { display: flex; flex-wrap: wrap; gap: 6px; margin-left: auto; }
.files-hint { padding: 8px 18px; color: var(--sp-muted); font-size: .76rem; border-top: 1px solid var(--sp-border); }
.drop-overlay { position: absolute; inset: 0; z-index: 20; border: 2px dashed var(--sp-primary); border-radius: var(--sp-radius); background: color-mix(in srgb, var(--sp-surface) 86%, transparent); display: grid; place-items: center; }
.drop-overlay .drop-input { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: copy; }
.drop-overlay .drop-message { text-align: center; pointer-events: none; }
.drop-overlay .drop-message > i { font-size: 2.2rem; color: var(--sp-primary); }
.picker-box { border: 1px solid var(--sp-border); border-radius: var(--sp-radius-sm); overflow: hidden; }
.picker-list { max-height: 320px; overflow-y: auto; }
.picker-list .list-row { padding: 8px 14px; }
.picker-list .list-row:hover:not(:disabled) { background: var(--sp-surface-hover); }
.conflict-list .list-row { padding: 6px 4px; font-size: .87rem; }
/* Backups: the schedule form is one row on ≥992px (switch | at | keep for | include | save) with labels above;
   .control is a 38px box so the switch and the checkboxes line up with the inputs next to them. */
.schedule-form { display: grid; gap: 12px 16px; align-items: end; }
.schedule-form .control { display: flex; align-items: center; gap: 18px; min-height: 38px; }
.schedule-form .control .form-check { margin: 0; min-height: 0; }
@media (min-width: 992px) { .schedule-form { grid-template-columns: auto 150px 130px auto 1fr; } .schedule-form .save { justify-self: end; } }
/* DNS zones and mail domains: a list of buttons, one line each (name left, a muted fact right); the picked one is tinted. */
.pick-list .list-row { font-size: .88rem; }
.pick-list .list-row > i { color: var(--sp-muted); }
.pick-list .list-row.tone-primary > i { color: inherit; }
.card-header h2.text-truncate { min-width: 0; }
/* The zones / mail domains side card: a narrow column, so its header may wrap the buttons onto a second line. */
.pick-card .card-header { flex-wrap: wrap; gap: 8px; }
.pick-card .card-header .actions { gap: 4px; }
.pick-card .card-header h2 { white-space: nowrap; }
.card-header .actions .btn { white-space: nowrap; }
/* The editor modal: full height, the textarea takes all the room between header and footer. */
.editor { font-family: ui-monospace, "Cascadia Mono", Consolas, monospace; font-size: .82rem; min-height: 60vh; tab-size: 4; white-space: pre; background: var(--sp-surface-2) !important; }
.editor-modal .sp-modal { height: calc(100vh - 32px); }
.editor-modal .sp-modal-body { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
.editor-modal .editor { flex: 1 1 auto; min-height: 0; resize: none; line-height: 1.5; }
.log-view { background: var(--sp-code-bg); color: var(--sp-code-text); font-family: ui-monospace, "Cascadia Mono", Consolas, monospace; font-size: .76rem; border-radius: var(--sp-radius-sm); padding: 12px 14px; max-height: 60vh; overflow: auto; white-space: pre; }

/* ---------- Auth pages ---------- */
.auth-wrap { min-height: 100vh; display: grid; place-items: center; padding: 24px 16px; background: radial-gradient(1200px 600px at 10% -10%, rgba(59, 130, 246, .14), transparent 60%), radial-gradient(900px 500px at 110% 110%, rgba(99, 102, 241, .12), transparent 60%), var(--sp-bg); }
.auth-card { width: 100%; max-width: 420px; background: var(--sp-surface); border: 1px solid var(--sp-border); border-radius: 16px; box-shadow: var(--sp-shadow-lg); padding: 30px 30px 26px; }
.auth-card.wide { max-width: 560px; }
.auth-brand { display: flex; align-items: center; gap: .6rem; font-weight: 650; font-size: 1.05rem; margin-bottom: 22px; }
.auth-brand .logo { width: 34px; height: 34px; border-radius: 10px; display: grid; place-items: center; background: linear-gradient(135deg, #3b82f6, #6366f1); color: #fff; }
.auth-card h1 { font-size: 1.3rem; margin-bottom: 4px; }
.auth-card .lead-text { color: var(--sp-muted); margin-bottom: 20px; }
.auth-footer { text-align: center; color: var(--sp-muted); font-size: .78rem; margin-top: 18px; }
.otp-input { font-size: 1.5rem; letter-spacing: .5em; text-align: center; font-family: ui-monospace, Consolas, monospace; }
.auth-icon { width: 52px; height: 52px; border-radius: 14px; display: inline-grid; place-items: center; font-size: 1.4rem; margin-bottom: 12px; }

/* ---------- Account pages ----------
   ManageLayout: a vertical pill nav (.manage-nav) in a narrow card, the page itself in a card body (.manage-body).
   Every page starts with h2.section-title + a muted lead; forms are .form-narrow (one column, labels above);
   h3.section-title + .divider separate sections. Below 992px the nav becomes one horizontal, scrollable row. */
.manage-nav { display: flex; flex-direction: column; gap: 2px; padding: 8px; }
.manage-link { display: flex; align-items: center; gap: .6rem; padding: 8px 12px; border-radius: 8px; color: var(--sp-text-2); font-size: .88rem; font-weight: 500; text-decoration: none !important; white-space: nowrap; }
.manage-link i { width: 18px; text-align: center; font-size: 1rem; color: var(--sp-muted); }
.manage-link:hover { background: var(--sp-surface-hover); color: var(--sp-text); }
.manage-link.active { background: var(--sp-primary-soft); color: var(--sp-primary); }
.manage-link.active i { color: var(--sp-primary); }
@media (max-width: 991.98px) { .manage-nav { flex-direction: row; overflow-x: auto; scrollbar-width: none; } }
.manage-body { padding: 20px 22px 22px; }
.section-title { margin: 0 0 4px; }
h2.section-title { font-size: 1.1rem; }
h3.section-title { font-size: .98rem; }
.form-narrow { max-width: 480px; }
.manage-body .kv.form-narrow { grid-template-columns: minmax(120px, 30%) 1fr; }
/* Set up authenticator: the QR code and the shared key sit in one bordered panel; .step is a step label. */
.qr-panel { border: 1px solid var(--sp-border); border-radius: var(--sp-radius); padding: 16px; text-align: center; }
.step { font-size: .85rem; font-weight: 600; margin-bottom: 10px; }
.code-block.shared-key { padding-right: 14px; font-weight: 600; letter-spacing: .04em; text-align: center; word-break: normal; overflow-wrap: anywhere; }
.code-block.recovery-codes { padding-right: 14px; columns: 2; max-width: 420px; line-height: 1.7; }

/* ---------- Misc ---------- */
.divider { height: 1px; background: var(--sp-border); margin: 18px 0; }
.list-plain { list-style: none; padding: 0; margin: 0; }
.list-row { display: flex; align-items: center; gap: 12px; padding: 11px 18px; border-bottom: 1px solid var(--sp-border); }
.list-row:last-child { border-bottom: 0; }
.list-row:hover { background: var(--sp-surface-hover); }
.alert { border-radius: var(--sp-radius); }
.hstack-wrap { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.text-truncate-2 { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }

/* Blazor defaults kept from the template */
h1:focus { outline: none; }
.valid.modified:not([type=checkbox]) { outline: 1px solid #26b050; }
.blazor-error-boundary { background: var(--sp-danger-soft); padding: 1rem; color: var(--sp-danger); border-radius: var(--sp-radius); }
.blazor-error-boundary::after { content: "Something went wrong on this page. Reload to try again."; }
#blazor-error-ui { color-scheme: light only; background: #fef3c7; bottom: 0; box-shadow: 0 -1px 2px rgba(0, 0, 0, .2); box-sizing: border-box; display: none; left: 0; padding: .6rem 1.25rem .7rem 1.25rem; position: fixed; width: 100%; z-index: 2100; }
#blazor-error-ui .dismiss { cursor: pointer; position: absolute; right: .75rem; top: .5rem; }

/* Authenticator QR code: the generated SVG has a fixed pixel size; make it fit its card. */
.qr-box { background: #fff; border-radius: 10px; padding: 10px; max-width: 220px; margin: 0 auto; }
.qr-box svg { width: 100%; height: auto; display: block; }

/* Long lists (e.g. Windows services) scroll inside their card with the header kept in view. */
.scroll-table { max-height: 560px; overflow: auto; }
.scroll-table thead th { position: sticky; top: 0; z-index: 1; }
/* Security: a hardening check row is status icon | bold title + muted detail | Fix. The detail hides on phones. */
.table .check-status { width: 1%; padding-right: 0; }
.check-icon { width: 26px; height: 26px; border-radius: 7px; display: inline-grid; place-items: center; font-size: .85rem; vertical-align: middle; }
@media (max-width: 767.98px) { .check-detail { display: none; } }

/* ---------- Paged lists ---------- */
/* .list-toolbar is the row under a card header. <ListToolbar> renders it with the three wrappers below; tabs not
   yet migrated still put a .search input and bare selects straight into it. */
.list-toolbar { display: flex; flex-wrap: wrap; gap: 8px 10px; align-items: center; padding: 12px 18px; border-bottom: 1px solid var(--sp-border); }
.list-toolbar .search { flex: 1 1 220px; max-width: 320px; }
.toolbar-search { position: relative; flex: 1 1 180px; min-width: 180px; max-width: 280px; }
.toolbar-search > i { position: absolute; left: 11px; top: 50%; transform: translateY(-50%); color: var(--sp-muted); font-size: .85rem; pointer-events: none; }
.toolbar-search .form-control { padding-left: 32px; height: 36px; }
.toolbar-filters { display: flex; flex-wrap: wrap; gap: 8px 10px; align-items: center; }
.toolbar-actions { margin-left: auto; display: flex; gap: 8px; align-items: center; }
.toolbar-clear { font-size: .82rem; padding: 0 2px; text-decoration: none; }
.toolbar-clear:hover { text-decoration: underline; }
/* A labelled filter: <label class="filter">Status <select class="form-select">…</select></label>. */
label.filter { display: inline-flex; align-items: center; gap: 7px; margin: 0; font-size: .8rem; font-weight: 500; color: var(--sp-muted); white-space: nowrap; }
label.filter .form-select { width: auto; height: 36px; padding: 0 1.7rem 0 .65rem; background-position: right .5rem center; font-size: .85rem; color: var(--sp-text); }
label.filter.active .form-select { border-color: var(--sp-primary); background-color: var(--sp-primary-soft); }
.pager { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }
.pager .pages { margin-left: auto; display: flex; gap: 2px; align-items: center; }
/* The Databases toolbar has five filters: below 1700px they take the toolbar's second line (full width), under the
   search and the buttons, instead of pushing the buttons down. */
@media (max-width: 1700px) { .db-toolbar .toolbar-filters { order: 1; flex: 1 1 100%; } }
/* Databases list: a caret cell expands the row into the users panel (DatabaseUsersPanel), which is itself a
   one-line-per-user .table-list on the surface background with a one-line problem notice above it. */
.table .expander { width: 1%; padding-right: 0; }
.table .expander .btn { color: var(--sp-muted); }
.table tr.db-expand > td { background: var(--sp-surface-2); padding: 12px 18px 14px; height: auto; white-space: normal; }
.table-list > tbody > tr.db-expand > td { height: auto; white-space: normal; }
.db-users .table { --bs-table-bg: transparent; }
.db-users-table { background: var(--sp-surface); border: 1px solid var(--sp-border); border-radius: var(--sp-radius-sm); }
.db-users-table .table > :not(caption) > * > * { padding-left: 12px; padding-right: 12px; }
.db-users-table .table > thead th:first-child { border-top-left-radius: var(--sp-radius-sm); }
.db-users-table .table > thead th:last-child { border-top-right-radius: var(--sp-radius-sm); }
.db-users .form-select.level { width: 150px; height: 38px; padding-top: 0; padding-bottom: 0; }
.db-users .fw-semibold + .badge-soft { margin-left: 6px; }
.db-notice { display: flex; gap: 10px; align-items: center; margin-bottom: 12px; padding: 8px 12px; background: var(--sp-surface); border: 1px solid var(--sp-border); border-radius: var(--sp-radius-sm); font-size: .85rem; color: var(--sp-text-2); }
.db-notice > i { font-size: 1rem; line-height: 1; flex: none; }
.db-notice > .btn { flex: none; }
/* The Fix modal's numbered steps. */
.fix-steps { padding-left: 1.4rem; margin: 0; }
.fix-steps > li { margin-bottom: 16px; padding-left: 4px; }
.fix-steps > li:last-child { margin-bottom: 0; }

/* ---------- Roles ----------
   .changes-off (MainLayout for read-only accounts, ServerDetail around System/Security for operators) hides the
   buttons that start a change. Only for clarity: AgentClient refuses the change on the server anyway. */
.changes-off .page-header .actions .btn-primary,
.changes-off .card-header .btn-primary,
.changes-off .list-toolbar .toolbar-actions .btn-primary,
.changes-off .card-header .btn-danger,
.changes-off .change-only,
/* On the System and Security tabs every inline action is a server-wide change (restart a service, reboot, firewall). */
.admin-only .row-actions > button.btn,
.admin-only .card-header button.btn:not([title]) { display: none !important; }
.readonly-note { max-width: 1440px; }
.server-list-check { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 6px 16px; max-height: 220px; overflow: auto; padding: 10px 12px; border: 1px solid var(--sp-border); border-radius: var(--sp-radius); }
