/* =========================================================================
   zfedora — custom theme layered on Bootstrap 5.3
   ========================================================================= */

:root {
    --z-primary:        #4f46e5;
    --z-primary-rgb:    79, 70, 229;
    --z-primary-hover:  #4338ca;
    --z-radius:         14px;
    --z-radius-sm:      10px;
    --z-sidebar-w:      248px;

    --bs-primary:       var(--z-primary);
    --bs-primary-rgb:   var(--z-primary-rgb);
    --bs-link-color:    var(--z-primary);
    --bs-link-hover-color: var(--z-primary-hover);
    --bs-border-radius: var(--z-radius-sm);
    --bs-body-font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}

/* ---- Light palette ------------------------------------------------------ */
[data-bs-theme="light"] {
    --z-bg:        #f4f5fb;
    --z-surface:   #ffffff;
    --z-surface-2: #f8f9fd;
    --z-border:    #e7e8f0;
    --z-text:      #1c1d29;
    --z-muted:     #6b6d7e;
    --z-sidebar:   #14152b;
    --z-sidebar-text:  #b9bcd6;
    --z-shadow:    0 1px 2px rgba(20, 21, 43, .05), 0 8px 24px rgba(20, 21, 43, .06);
}

/* ---- Dark palette ------------------------------------------------------- */
[data-bs-theme="dark"] {
    --z-bg:        #0e0f1a;
    --z-surface:   #181a2a;
    --z-surface-2: #1f2136;
    --z-border:    #2a2d45;
    --z-text:      #e8e9f3;
    --z-muted:     #9698b4;
    --z-sidebar:   #0a0b16;
    --z-sidebar-text:  #a3a6c9;
    --z-shadow:    0 1px 2px rgba(0, 0, 0, .3), 0 12px 30px rgba(0, 0, 0, .35);

    --bs-body-bg: var(--z-bg);
    --bs-body-color: var(--z-text);
}

* { -webkit-tap-highlight-color: transparent; }

body {
    background: var(--z-bg);
    color: var(--z-text);
    transition: background-color .25s ease, color .25s ease;
}

/* ---- Brand mark --------------------------------------------------------- */
.app-brand-mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px; height: 34px;
    border-radius: 10px;
    font-weight: 800;
    color: #fff;
    background: linear-gradient(135deg, #6366f1, #8b5cf6);
    box-shadow: 0 4px 12px rgba(99, 102, 241, .4);
}
.app-brand-mark--lg { width: 48px; height: 48px; border-radius: 14px; font-size: 1.5rem; }

/* =========================================================================
   Auth (login) page
   ========================================================================= */
.auth-body {
    min-height: 100dvh;
    display: grid;
    place-items: center;
    padding: 1.5rem;
    background:
        radial-gradient(1200px 600px at 15% -10%, rgba(99, 102, 241, .28), transparent 60%),
        radial-gradient(1000px 500px at 110% 110%, rgba(139, 92, 246, .25), transparent 55%),
        #0e0f1a;
    color: #e8e9f3;
}
.auth-wrap { width: 100%; max-width: 400px; }
.auth-card {
    background: rgba(24, 26, 42, .72);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    border: 1px solid rgba(255, 255, 255, .08);
    border-radius: 20px;
    padding: 2rem;
    box-shadow: 0 24px 60px rgba(0, 0, 0, .45);
}
.auth-brand { display: flex; align-items: center; gap: .85rem; margin-bottom: 1.75rem; }
.auth-brand-name { font-size: 1.4rem; font-weight: 800; letter-spacing: -.01em; }
.auth-brand-sub { font-size: .8rem; color: #9698b4; }
.auth-card .form-control {
    background: rgba(255, 255, 255, .04);
    border-color: rgba(255, 255, 255, .12);
    color: #fff;
}
.auth-card .form-control:focus {
    background: rgba(255, 255, 255, .06);
    border-color: var(--z-primary);
    box-shadow: 0 0 0 .2rem rgba(var(--z-primary-rgb), .25);
}
.auth-card .form-floating > label { color: #9698b4; }
.auth-password { position: relative; }
.auth-reveal {
    position: absolute; top: 50%; right: .5rem; transform: translateY(-50%);
    border: 0; background: transparent; color: #9698b4; padding: .35rem .5rem; cursor: pointer;
}
.auth-reveal:hover { color: #fff; }
.auth-submit { display: inline-flex; align-items: center; justify-content: center; gap: .5rem; margin-top: .25rem; }
.auth-submit .spinner-border { display: none; width: 1rem; height: 1rem; }
.auth-submit.loading .label { opacity: .6; }
.auth-submit.loading .spinner-border { display: inline-block; }
.auth-note { margin: 1.25rem 0 0; font-size: .8rem; color: #9698b4; text-align: center; }
.auth-copy { text-align: center; color: rgba(255,255,255,.4); font-size: .75rem; margin: 1rem 0 0; }

/* =========================================================================
   App shell
   ========================================================================= */
.app-shell { min-height: 100dvh; }

.app-sidebar {
    position: fixed; inset: 0 auto 0 0;
    width: var(--z-sidebar-w);
    background: var(--z-sidebar);
    color: var(--z-sidebar-text);
    display: flex; flex-direction: column;
    padding: 1.1rem .85rem;
    z-index: 1040;
    transition: transform .25s ease;
}
.app-brand { display: flex; align-items: center; gap: .7rem; padding: .35rem .5rem 1.1rem; }
.app-brand-name { font-weight: 800; font-size: 1.25rem; color: #fff; letter-spacing: -.01em; }

.app-nav { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; flex: 1; overflow-y: auto; }
.app-nav-heading {
    font-size: .68rem; text-transform: uppercase; letter-spacing: .08em;
    color: rgba(255,255,255,.35); padding: 1rem .75rem .35rem;
}
.app-nav-link {
    display: flex; align-items: center; gap: .75rem;
    padding: .62rem .75rem; border-radius: 10px;
    color: var(--z-sidebar-text); text-decoration: none;
    font-weight: 500; font-size: .93rem;
    border: 0; width: 100%; background: transparent; text-align: left;
    transition: background-color .15s ease, color .15s ease;
}
.app-nav-link i:first-child { font-size: 1.1rem; width: 1.2rem; text-align: center; }
.app-nav-link:hover { background: rgba(255,255,255,.06); color: #fff; }
.app-nav-link.active { background: linear-gradient(135deg, var(--z-primary), #7c3aed); color: #fff; box-shadow: 0 6px 16px rgba(var(--z-primary-rgb), .35); }
.app-nav-link.disabled { opacity: .4; cursor: not-allowed; }
.app-nav-lock { margin-left: auto; font-size: .8rem; }
.app-sidebar-foot { margin-top: auto; padding-top: .5rem; border-top: 1px solid rgba(255,255,255,.08); }
.app-logout:hover { background: rgba(239, 68, 68, .18); color: #fecaca; }

.app-main { margin-left: var(--z-sidebar-w); min-height: 100dvh; display: flex; flex-direction: column; }

.app-topbar {
    position: sticky; top: 0; z-index: 1030;
    display: flex; align-items: center; gap: 1rem;
    padding: .85rem 1.5rem;
    background: color-mix(in srgb, var(--z-bg) 82%, transparent);
    backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
    border-bottom: 1px solid var(--z-border);
}
.app-topbar-title { font-size: 1.15rem; font-weight: 700; margin: 0; letter-spacing: -.01em; }
.app-topbar-actions { margin-left: auto; display: flex; align-items: center; gap: .6rem; }
.app-menu-toggle { display: none; border: 0; background: transparent; color: var(--z-text); font-size: 1.4rem; padding: .1rem .3rem; }

.app-theme-toggle {
    width: 40px; height: 40px; border-radius: 10px;
    border: 1px solid var(--z-border); background: var(--z-surface);
    color: var(--z-text); cursor: pointer; display: grid; place-items: center;
    transition: background-color .15s, transform .15s;
}
.app-theme-toggle:hover { transform: translateY(-1px); }
.app-theme-toggle .theme-icon-dark { display: none; }
[data-bs-theme="dark"] .app-theme-toggle .theme-icon-light { display: none; }
[data-bs-theme="dark"] .app-theme-toggle .theme-icon-dark { display: block; }

.app-user-chip { display: flex; align-items: center; gap: .55rem; text-decoration: none; color: var(--z-text); padding: .25rem .5rem .25rem .25rem; border-radius: 999px; border: 1px solid var(--z-border); background: var(--z-surface); }
.app-user-chip:hover { color: var(--z-text); border-color: var(--z-primary); }
.app-user-avatar { border-radius: 50%; object-fit: cover; }
.app-user-name { font-weight: 600; font-size: .9rem; max-width: 160px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.app-content { padding: 1.5rem; max-width: 1180px; width: 100%; }

.app-sidebar-backdrop { display: none; position: fixed; inset: 0; background: rgba(0,0,0,.5); z-index: 1035; }
.app-shell.sidebar-open .app-sidebar-backdrop { display: block; }

/* =========================================================================
   Cards, panels, stats
   ========================================================================= */
.panel {
    background: var(--z-surface);
    border: 1px solid var(--z-border);
    border-radius: var(--z-radius);
    padding: 1.35rem;
    box-shadow: var(--z-shadow);
}
.panel-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 1rem; }
.panel-title { font-size: 1rem; font-weight: 700; margin: 0; }

.welcome-hero { margin-bottom: 1.5rem; }
.welcome-title { font-weight: 800; letter-spacing: -.02em; margin: 0; font-size: 1.6rem; }
.welcome-sub { color: var(--z-muted); margin: .25rem 0 0; }

.stat-card {
    display: block; background: var(--z-surface);
    border: 1px solid var(--z-border); border-radius: var(--z-radius);
    padding: 1.25rem; color: var(--z-text); box-shadow: var(--z-shadow);
    transition: transform .18s ease, box-shadow .18s ease, border-color .18s;
    height: 100%;
}
a.stat-card:hover { transform: translateY(-3px); border-color: color-mix(in srgb, var(--z-primary) 40%, var(--z-border)); }
.stat-icon { width: 46px; height: 46px; border-radius: 12px; display: grid; place-items: center; font-size: 1.35rem; margin-bottom: .85rem; }
.stat-value { font-size: 1.6rem; font-weight: 800; letter-spacing: -.02em; line-height: 1.1; }
.stat-label { color: var(--z-muted); font-size: .85rem; margin-top: .15rem; }

.bg-tint-blue   { background: rgba(59, 130, 246, .14);  color: #3b82f6; }
.bg-tint-violet { background: rgba(139, 92, 246, .14);  color: #8b5cf6; }
.bg-tint-green  { background: rgba(16, 185, 129, .14);  color: #10b981; }
.bg-tint-amber  { background: rgba(245, 158, 11, .16);  color: #f59e0b; }

.quick-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: .75rem; }
.quick-tile {
    display: flex; flex-direction: column; align-items: flex-start; gap: .5rem;
    padding: 1rem; border-radius: 12px; text-decoration: none;
    background: var(--z-surface-2); border: 1px solid var(--z-border);
    color: var(--z-text); font-weight: 600; transition: transform .15s, border-color .15s;
}
.quick-tile i { font-size: 1.4rem; color: var(--z-primary); }
a.quick-tile:hover { transform: translateY(-2px); border-color: var(--z-primary); }
.quick-tile.disabled { opacity: .55; }
.quick-tile small { font-size: .65rem; text-transform: uppercase; letter-spacing: .05em; color: var(--z-muted); font-weight: 700; }

.feature-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .6rem; }
.feature-list li { display: flex; align-items: center; gap: .65rem; color: var(--z-text); }
.feature-list i { color: var(--z-primary); font-size: 1.1rem; }

/* Storage analytics */
.storage-headline { display: flex; align-items: baseline; gap: .5rem; margin-bottom: .6rem; }
.storage-used { font-size: 1.8rem; font-weight: 800; letter-spacing: -.02em; }
.storage-of { color: var(--z-muted); font-size: .9rem; }
.storage-progress { height: 10px; border-radius: 6px; }
.storage-breakdown { display: grid; grid-template-columns: 1fr 1fr; gap: .5rem .75rem; margin-top: 1rem; }
.storage-breakdown > div { display: flex; align-items: center; gap: .5rem; color: var(--z-muted); font-size: .88rem; }
.storage-breakdown strong { margin-left: auto; color: var(--z-text); }
.storage-breakdown .dot { width: 10px; height: 10px; border-radius: 50%; }

/* Shared-links manager (borderless table) */
.shares-table th { color: var(--z-muted); font-weight: 600; font-size: .74rem; text-transform: uppercase; letter-spacing: .04em; border: 0; padding: .4rem .6rem; }
.shares-table td { border: 0; padding: .55rem .6rem; }
.shares-table tbody tr { border-bottom: 1px solid var(--z-border); }
.shares-table tbody tr:last-child { border-bottom: 0; }
.share-manage-row.expired { opacity: .6; }
.share-name-link { border: 0; background: transparent; color: var(--z-text); font-weight: 600; cursor: pointer; display: inline-flex; align-items: center; max-width: 240px; padding: 0; }
.share-name-link span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.share-name-link:hover { color: var(--z-primary); }
.shares-table .share-manage-url { min-width: 170px; max-width: 230px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .72rem; }
.share-manage-actions { display: flex; gap: .35rem; justify-content: flex-end; }

/* Storage donut */
.storage-chart { display: flex; align-items: center; gap: 1.25rem; flex-wrap: wrap; }
.donut { width: 150px; height: 150px; flex-shrink: 0; }
.donut-track { fill: none; stroke: var(--z-border); stroke-width: 14; }
.donut-seg { fill: none; stroke-width: 14; transform: rotate(-90deg); transform-origin: 60px 60px; transition: stroke-dasharray .4s ease; }
.donut-num { fill: var(--z-text); font-size: 22px; font-weight: 800; text-anchor: middle; }
.donut-sub { fill: var(--z-muted); font-size: 9px; text-anchor: middle; letter-spacing: .1em; text-transform: uppercase; }
.storage-legend { display: flex; flex-direction: column; gap: .5rem; flex: 1; min-width: 160px; }
.storage-legend > div { display: flex; align-items: center; gap: .5rem; color: var(--z-muted); font-size: .9rem; }
.storage-legend strong { margin-left: auto; color: var(--z-text); }
.storage-legend .dot { width: 11px; height: 11px; border-radius: 50%; flex-shrink: 0; }
.storage-legend-total { margin-top: .35rem; padding-top: .55rem; border-top: 1px solid var(--z-border); color: var(--z-text) !important; font-weight: 600; }

@media (max-width: 575.98px) {
    .shares-table .share-manage-url { display: none; }
}

.page-head { margin-bottom: 1.25rem; }
.page-head-sub { color: var(--z-muted); margin: 0; }

/* =========================================================================
   Gallery + uploader
   ========================================================================= */
.uploader { margin-bottom: 1.5rem; }
.dropzone {
    display: block; text-align: center; cursor: pointer;
    border: 2px dashed var(--z-border); border-radius: var(--z-radius);
    padding: 2rem 1rem; background: var(--z-surface);
    transition: border-color .15s, background-color .15s;
}
.dropzone:hover, .dropzone.dragover { border-color: var(--z-primary); background: color-mix(in srgb, var(--z-primary) 6%, var(--z-surface)); }
.dropzone-icon { font-size: 2.2rem; color: var(--z-primary); }
.dropzone-title { font-weight: 700; margin-top: .5rem; }
.dropzone-title span { color: var(--z-primary); text-decoration: underline; }
.dropzone-sub { color: var(--z-muted); font-size: .85rem; margin-top: .2rem; }

.upload-queue { margin-top: 1rem; display: flex; flex-direction: column; gap: .5rem; }
.upload-row { display: flex; align-items: center; gap: .75rem; font-size: .85rem; }
.upload-row .name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.upload-progress { flex: 0 0 120px; height: 6px; border-radius: 3px; background: var(--z-border); overflow: hidden; }
.upload-progress > span { display: block; height: 100%; width: 0; background: var(--z-primary); transition: width .2s ease; }
.upload-row .status i { font-size: 1rem; }
.upload-row.done .status { color: #10b981; }
.upload-row.error .status { color: #ef4444; }

.gallery-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 1rem; }
.gallery-item {
    margin: 0; background: var(--z-surface); border: 1px solid var(--z-border);
    border-radius: var(--z-radius-sm); overflow: hidden; box-shadow: var(--z-shadow);
    transition: transform .18s ease, box-shadow .7s ease, border-color .7s ease;
}
.gallery-item:hover { transform: translateY(-3px); }
/* Just-uploaded items land highlighted, then fade out (see Sync → View Gallery). */
.gallery-item.gallery-highlight {
    border-color: var(--z-primary);
    box-shadow: 0 0 0 3px var(--z-primary), 0 10px 30px rgba(var(--z-primary-rgb), .55);
}
.gallery-thumb { display: block; aspect-ratio: 1; overflow: hidden; width: 100%; padding: 0; border: 0; background: var(--z-surface-2); cursor: pointer; position: relative; }
.gallery-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform .3s ease; }
.gallery-thumb:hover img { transform: scale(1.05); }
.gallery-vid {
    position: absolute; top: .5rem; left: .5rem; z-index: 1;
    width: 26px; height: 26px; border-radius: 8px; display: grid; place-items: center;
    background: rgba(0,0,0,.55); color: #fff; font-size: .8rem; pointer-events: none;
}
.gallery-cap { display: flex; align-items: center; gap: .35rem; padding: .5rem .6rem; }
.gallery-name { flex: 1; font-size: .78rem; color: var(--z-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gallery-del { border: 0; background: transparent; color: var(--z-muted); padding: .2rem; cursor: pointer; border-radius: 6px; }
.gallery-del:hover { color: #ef4444; background: rgba(239, 68, 68, .12); }

.gallery-empty { text-align: center; padding: 3rem 1rem; color: var(--z-muted); }
.gallery-empty i { font-size: 2.5rem; opacity: .4; }
.gallery-empty p { margin: .75rem 0 0; }

.lightbox {
    position: fixed; inset: 0; z-index: 2000;
    background: rgba(0, 0, 0, .9);
    display: grid; place-items: center; padding: 2rem;
    touch-action: none; overscroll-behavior: contain; overflow: hidden;
}
/* Freeze the page behind the viewer so gestures never scroll it. */
body.lb-scroll-lock { position: fixed; left: 0; right: 0; width: 100%; overflow: hidden; }
.lightbox-stage { display: grid; place-items: center; }
.lightbox-media {
    max-width: 92vw; max-height: 82vh; border-radius: 8px;
    box-shadow: 0 20px 60px rgba(0,0,0,.6); display: block;
    transform-origin: center center; will-change: transform;
}
img.lightbox-media { -webkit-user-select: none; user-select: none; -webkit-user-drag: none; }
img.lightbox-media.is-zoomed { cursor: grab; border-radius: 0; }
img.lightbox-media.is-zoomed:active { cursor: grabbing; }
/* Zoom controls: desktop only — mobile pinches the image instead. */
.lightbox-zoom { display: flex; gap: .5rem; }
@media (hover: none) and (pointer: coarse) { .lightbox-zoom { display: none !important; } }
video.lightbox-media { background: #000; }
.lightbox-close { position: absolute; top: 1.25rem; right: 1.5rem; border: 0; background: rgba(255,255,255,.1); color: #fff; width: 44px; height: 44px; border-radius: 50%; font-size: 1.2rem; cursor: pointer; }
.lightbox-close:hover { background: rgba(255,255,255,.2); }
.lightbox-caption { position: absolute; bottom: 1.5rem; left: 0; right: 0; text-align: center; color: rgba(255,255,255,.85); font-size: .9rem; }

/* Viewer chrome: top-right menu/close + side nav arrows */
.lightbox-bar { position: absolute; top: 1rem; right: 1.25rem; z-index: 3; display: flex; gap: .5rem; }
.lightbox-icon-btn {
    border: 0; background: rgba(255,255,255,.14); color: #fff;
    width: 44px; height: 44px; border-radius: 50%; font-size: 1.2rem;
    cursor: pointer; display: grid; place-items: center;
}
.lightbox-icon-btn:hover { background: rgba(255,255,255,.26); }
.lightbox-arrow {
    position: absolute; top: 50%; transform: translateY(-50%); z-index: 3; border: 0;
    background: rgba(255,255,255,.14); color: #fff; width: 44px; height: 44px;
    border-radius: 50%; font-size: 1.2rem; cursor: pointer; display: grid; place-items: center;
}
.lightbox-arrow:hover { background: rgba(255,255,255,.26); }
.lightbox-prev { left: 1.25rem; }
.lightbox-next { right: 1.25rem; }
.viewer-video { position: relative; display: grid; place-items: center; }
.viewer-play {
    position: absolute; inset: 0; margin: auto; width: 96px; height: 96px;
    border: 0; background: transparent; color: rgba(255,255,255,.9); font-size: 5rem;
    cursor: pointer; display: grid; place-items: center;
}
.viewer-play:hover { color: #fff; }

/* =========================================================================
   Profile + admin
   ========================================================================= */
.avatar-wrap { display: inline-block; position: relative; }
.avatar-lg { width: 128px; height: 128px; border-radius: 50%; object-fit: cover; border: 4px solid var(--z-surface); box-shadow: var(--z-shadow); background: var(--z-surface-2); }
.profile-name { font-weight: 800; letter-spacing: -.01em; }

.theme-choice { display: flex; gap: .75rem; }
.theme-opt { flex: 1; }
.theme-opt input { position: absolute; opacity: 0; pointer-events: none; }
.theme-opt-box {
    display: flex; align-items: center; justify-content: center; gap: .5rem;
    padding: .7rem; border-radius: 10px; border: 1.5px solid var(--z-border);
    background: var(--z-surface-2); cursor: pointer; font-weight: 600;
    transition: border-color .15s, background-color .15s;
}
.theme-opt input:checked + .theme-opt-box { border-color: var(--z-primary); background: color-mix(in srgb, var(--z-primary) 10%, var(--z-surface)); color: var(--z-primary); }

.admin-avatar { border-radius: 50%; object-fit: cover; }
.storage-mini { height: 5px; border-radius: 3px; background: var(--z-border); overflow: hidden; max-width: 120px; margin: .2rem 0; }
.storage-mini > span { display: block; height: 100%; background: var(--z-primary); }
.storage-mini > span.over { background: #ef4444; }
.backup-log { background: var(--z-surface-2); border: 1px solid var(--z-border); border-radius: 8px; padding: .6rem .8rem; font-size: .78rem; max-height: 220px; overflow: auto; white-space: pre-wrap; word-break: break-word; color: var(--z-text); }
.admin-table > :not(caption) > * > * { padding: .85rem 1rem; }

/* Admin center tabs + pager */
.admin-tabs { display: flex; gap: .4rem; flex-wrap: nowrap; margin-bottom: 1.25rem; border-bottom: 1px solid var(--z-border); padding-bottom: .5rem; overflow-x: auto; }
.admin-tab { display: inline-flex; align-items: center; gap: .4rem; white-space: nowrap; text-decoration: none; color: var(--z-muted); font-weight: 600; font-size: .9rem; padding: .5rem .9rem; border-radius: 10px; }
.admin-tab:hover { color: var(--z-text); background: var(--z-surface-2); }
.admin-tab.active { color: #fff; background: var(--z-primary); }
.admin-tab .badge { font-size: .65rem; }
.admin-pager { display: flex; align-items: center; gap: .3rem; margin-top: 1rem; flex-wrap: wrap; }
.admin-page { display: inline-grid; place-items: center; min-width: 34px; height: 34px; padding: 0 .4rem; border-radius: 8px; border: 1px solid var(--z-border); color: var(--z-text); text-decoration: none; font-size: .85rem; }
.admin-page:hover { border-color: var(--z-primary); color: var(--z-primary); }
.admin-page.active { background: var(--z-primary); border-color: var(--z-primary); color: #fff; }

/* Maintenance banner */
.maint-banner { display: flex; align-items: center; gap: .5rem; background: #f59e0b; color: #1c1d29; font-weight: 600; border-radius: 10px; padding: .6rem 1rem; margin-bottom: 1rem; }
.maint-banner .badge { margin-left: auto; }
.shares-table code { font-size: .78rem; color: var(--z-text); }
.text-bg-success-subtle { background: rgba(16,185,129,.14) !important; }

/* Generic Bootstrap tweaks */
.btn-primary { --bs-btn-bg: var(--z-primary); --bs-btn-border-color: var(--z-primary); --bs-btn-hover-bg: var(--z-primary-hover); --bs-btn-hover-border-color: var(--z-primary-hover); --bs-btn-active-bg: var(--z-primary-hover); }
.btn-outline-primary { --bs-btn-color: var(--z-primary); --bs-btn-border-color: var(--z-primary); --bs-btn-hover-bg: var(--z-primary); --bs-btn-hover-border-color: var(--z-primary); }
.form-control, .form-select { background: var(--z-surface); border-color: var(--z-border); color: var(--z-text); }
.form-control:focus, .form-select:focus { border-color: var(--z-primary); box-shadow: 0 0 0 .2rem rgba(var(--z-primary-rgb), .18); }
.modal-content { background: var(--z-surface); border: 1px solid var(--z-border); border-radius: var(--z-radius); }
.table { --bs-table-bg: transparent; color: var(--z-text); }

/* =========================================================================
   Responsive
   ========================================================================= */
@media (max-width: 991.98px) {
    .app-sidebar { transform: translateX(-100%); }
    .app-shell.sidebar-open .app-sidebar { transform: translateX(0); }
    .app-main { margin-left: 0; }
    .app-menu-toggle { display: block; }
}
@media (min-width: 992px) {
    .app-sidebar-backdrop { display: none !important; }
}
@media (max-width: 575.98px) {
    .app-content { padding: 1rem; }
    .app-topbar { padding: .75rem 1rem; }
    .app-user-name { max-width: 40vw; }
    .quick-grid { grid-template-columns: 1fr; }
}

/* =========================================================================
   Gallery actions + sharing
   ========================================================================= */
.gallery-cap { justify-content: center; }
.gallery-actions { display: flex; align-items: center; gap: .35rem; }
.gallery-btn { font-size: 1.05rem; }

/* Tags modal can be opened from inside the fullscreen viewer (z-index 2000). */
#tagsModal { z-index: 2100; }

/* Tag editor inside the tags modal (theme-aware chips) */
.tags-editor { display: flex; flex-wrap: wrap; gap: .35rem; min-height: 1.6rem; align-items: center; }
.tags-editor .lb-tag { background: var(--z-surface-2); border: 1px solid var(--z-border); color: var(--z-text); }
.tags-editor .lb-tag button { color: var(--z-muted); }
.tags-editor .lb-tag button:hover { color: var(--z-text); }
/* Read-only auto (AI) tags — accented, no remove control. */
.tags-editor .lb-tag-ai {
    background: color-mix(in srgb, var(--z-primary) 14%, transparent);
    border-color: color-mix(in srgb, var(--z-primary) 40%, transparent);
    color: var(--z-text); padding: .1rem .65rem;
}
.gallery-btn { border: 0; background: transparent; color: var(--z-muted); padding: .25rem; cursor: pointer; border-radius: 6px; line-height: 1; }
.gallery-btn:hover { color: var(--z-primary); background: color-mix(in srgb, var(--z-primary) 12%, transparent); }
.gallery-del:hover { color: #ef4444; background: rgba(239, 68, 68, .12); }

.gallery-thumb { position: relative; }
.gallery-share-badge {
    position: absolute; top: .5rem; right: .5rem;
    width: 26px; height: 26px; border-radius: 50%;
    display: grid; place-items: center;
    background: var(--z-primary); color: #fff; font-size: .85rem;
    box-shadow: 0 2px 8px rgba(var(--z-primary-rgb), .5);
}

/* Share modal */
.share-mode { display: flex; flex-direction: column; gap: .5rem; }
.share-mode-opt input { position: absolute; opacity: 0; pointer-events: none; }
.share-mode-box {
    display: flex; align-items: center; gap: .55rem;
    padding: .7rem .85rem; border-radius: 10px; cursor: pointer;
    border: 1.5px solid var(--z-border); background: var(--z-surface-2);
    font-weight: 600; transition: border-color .15s, background-color .15s;
}
.share-mode-box i { font-size: 1.1rem; }
.share-mode-opt input:checked + .share-mode-box { border-color: var(--z-primary); background: color-mix(in srgb, var(--z-primary) 10%, var(--z-surface)); color: var(--z-primary); }

.share-list { display: flex; flex-direction: column; gap: .6rem; max-height: 260px; overflow-y: auto; }
.share-row { border: 1px solid var(--z-border); border-radius: 10px; padding: .6rem .7rem; background: var(--z-surface-2); }
.share-row.expired { opacity: .6; }
.share-row-top { display: flex; flex-wrap: wrap; gap: .4rem; margin-bottom: .5rem; }
.share-tag {
    display: inline-flex; align-items: center; gap: .3rem;
    font-size: .72rem; font-weight: 600; color: var(--z-muted);
    background: var(--z-surface); border: 1px solid var(--z-border);
    padding: .15rem .5rem; border-radius: 999px;
}
.share-tag.expired { color: #ef4444; border-color: rgba(239,68,68,.3); }
.share-row-url { display: flex; gap: .35rem; }
.share-row-url input { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .78rem; }
[data-copy].copied { background: #10b981; border-color: #10b981; color: #fff; }

/* =========================================================================
   Public share page (share.php) — standalone, no sidebar
   ========================================================================= */
.share-body {
    min-height: 100dvh; margin: 0; color: #e8e9f3;
    background:
        radial-gradient(1200px 600px at 15% -10%, rgba(99,102,241,.28), transparent 60%),
        radial-gradient(1000px 500px at 110% 110%, rgba(139,92,246,.25), transparent 55%),
        #0e0f1a;
}
.share-wrap { min-height: 100dvh; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1.25rem; padding: 1.5rem; }
.share-brand { display: inline-flex; align-items: center; gap: .6rem; text-decoration: none; color: #fff; font-weight: 800; font-size: 1.2rem; }
.share-brand:hover { color: #fff; opacity: .9; }

.share-card {
    width: 100%; max-width: 400px; text-align: center;
    background: rgba(24,26,42,.72); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);
    border: 1px solid rgba(255,255,255,.08); border-radius: 20px; padding: 2rem;
    box-shadow: 0 24px 60px rgba(0,0,0,.45);
}
.share-lock, .share-state-icon { font-size: 2.4rem; color: #a5b4fc; }
.share-lock { width: 64px; height: 64px; margin: 0 auto 1rem; border-radius: 50%; display: grid; place-items: center; background: rgba(99,102,241,.18); }
.share-title, .share-state-title { font-size: 1.35rem; font-weight: 800; margin: 0 0 .35rem; }
.share-sub, .share-state-msg { color: #9698b4; font-size: .9rem; margin-bottom: 1.25rem; }
.share-state-msg { margin-bottom: 0; }
.share-card .form-control { background: rgba(255,255,255,.04); border-color: rgba(255,255,255,.12); color: #fff; }
.share-card .form-control:focus { background: rgba(255,255,255,.06); border-color: var(--z-primary); box-shadow: 0 0 0 .2rem rgba(var(--z-primary-rgb), .25); }
.share-card .form-floating > label { color: #9698b4; }
.share-state-icon { display: block; margin-bottom: .75rem; }

/* Viewer */
.share-viewer { min-height: 100dvh; display: flex; flex-direction: column; }
.share-viewer-bar { display: flex; align-items: center; justify-content: space-between; padding: 1rem 1.5rem; }
.share-stage { flex: 1; display: grid; place-items: center; padding: 0 1.5rem; min-height: 0; }
.share-image { max-width: min(100%, 1100px); max-height: 78vh; border-radius: 12px; box-shadow: 0 20px 60px rgba(0,0,0,.5); }
.share-viewer-foot { display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: 1rem 1.5rem; color: #9698b4; font-size: .85rem; flex-wrap: wrap; }
.share-filename { font-weight: 600; color: #e8e9f3; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

@media (max-width: 575.98px) {
    .share-image { max-height: 68vh; }
}

/* =========================================================================
   Album bar + gallery toolbar + mass uploader
   ========================================================================= */
.album-bar { display: flex; align-items: center; gap: .75rem; margin-bottom: 1rem; }
.album-chips { display: flex; align-items: center; gap: .5rem; overflow-x: auto; padding-bottom: .25rem; flex: 1; scrollbar-width: thin; }
.album-chip {
    display: inline-flex; align-items: center; gap: .4rem; white-space: nowrap;
    border: 1px solid var(--z-border); background: var(--z-surface);
    color: var(--z-text); border-radius: 999px; padding: .4rem .85rem;
    font-size: .85rem; font-weight: 600; cursor: pointer;
    transition: border-color .15s, background-color .15s, color .15s;
}
.album-chip:hover { border-color: var(--z-primary); }
.album-chip.active { background: var(--z-primary); border-color: var(--z-primary); color: #fff; }
.album-count { font-size: .72rem; background: color-mix(in srgb, var(--z-muted) 22%, transparent); border-radius: 999px; padding: .05rem .45rem; font-weight: 700; }
.album-chip.active .album-count { background: rgba(255,255,255,.25); }
.album-del { margin-left: .1rem; opacity: .55; display: inline-flex; border-radius: 50%; width: 18px; height: 18px; align-items: center; justify-content: center; }
.album-del:hover { opacity: 1; background: rgba(239,68,68,.25); color: #fecaca; }
.album-new-btn { white-space: nowrap; flex-shrink: 0; }

.gallery-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 1rem; margin-bottom: 1.25rem; flex-wrap: wrap; }
.gallery-toolbar-left { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; }
.gallery-toolbar-right { display: flex; align-items: center; gap: .5rem; }
.upload-target { color: var(--z-muted); font-size: .82rem; }
.sort-label { color: var(--z-muted); font-size: 1.1rem; }
.sort-select { min-width: 160px; }

.gallery-loader { text-align: center; color: var(--z-muted); padding: 1.25rem; font-size: .9rem; }
.gallery-sentinel { height: 1px; }

/* Drag overlay */
.dropzone-overlay {
    position: fixed; inset: 0; z-index: 1900;
    background: color-mix(in srgb, var(--z-primary) 30%, rgba(0,0,0,.6));
    display: grid; place-items: center; backdrop-filter: blur(3px);
}
.dropzone-overlay-inner {
    border: 3px dashed rgba(255,255,255,.7); border-radius: 20px;
    padding: 3rem 4rem; text-align: center; color: #fff; font-size: 1.3rem; font-weight: 700;
    display: flex; flex-direction: column; align-items: center; gap: .75rem;
}
.dropzone-overlay-inner i { font-size: 3rem; }

/* Upload progress panel */
.upload-panel {
    position: fixed; right: 1.25rem; bottom: 84px; z-index: 1500; width: 340px; max-width: calc(100vw - 2.5rem);
    background: var(--z-surface); border: 1px solid var(--z-border); border-radius: 14px;
    box-shadow: var(--z-shadow); padding: .9rem 1rem; overflow: hidden;
}
.upload-panel-head { display: flex; align-items: center; justify-content: space-between; font-weight: 600; font-size: .9rem; margin-bottom: .6rem; gap: .5rem; }
.upload-bar { height: 6px; border-radius: 3px; background: var(--z-border); overflow: hidden; }
.upload-bar > span { display: block; height: 100%; width: 0; background: var(--z-primary); transition: width .25s ease; }
.upload-recent { margin-top: .6rem; display: flex; flex-direction: column; gap: .25rem; max-height: 160px; overflow-y: auto; }
.upload-recent-row { display: flex; align-items: center; gap: .45rem; font-size: .78rem; color: var(--z-muted); }
.upload-recent-row.ok i { color: #10b981; }
.upload-recent-row.err i { color: #ef4444; }
.upload-recent-row span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Top image viewer (fade / swipe) — auto-collapses on scroll */
.hero { position: relative; width: 100%; margin-bottom: 1.25rem; }
.hero-viewport {
    position: relative; width: 100%; aspect-ratio: 3 / 2; max-height: 78vh;
    border-radius: 16px; overflow: hidden; background: var(--z-surface-2);
    border: 1px solid var(--z-border); touch-action: pan-y; cursor: zoom-in;
}
/* Desktop: a shorter, wider hero (~32% less tall than the mobile 3:2). */
@media (min-width: 992px) {
    .hero-viewport { aspect-ratio: 11 / 5; max-height: 58vh; }
}
/* Taller than the viewport so it can pan vertically (Ken Burns). */
.hero-img {
    position: absolute; left: 0; top: 0; width: 100%; height: 130%; object-fit: cover;
    opacity: 0; will-change: transform, opacity; user-select: none; -webkit-user-drag: none;
}
.hero-nav {
    position: absolute; top: 50%; transform: translateY(-50%);
    width: 42px; height: 42px; border-radius: 50%; border: 0;
    background: rgba(0,0,0,.4); color: #fff; display: grid; place-items: center;
    cursor: pointer; opacity: 0; transition: opacity .2s, background-color .2s; font-size: 1.2rem;
}
.hero:hover .hero-nav { opacity: 1; }
.hero-prev { left: .75rem; }
.hero-next { right: .75rem; }
.hero-nav:hover { background: rgba(0,0,0,.6); }

/* Transparent caption pinned to the bottom of the viewer */
.hero-caption {
    position: absolute; left: 0; right: 0; bottom: 0; z-index: 2;
    display: flex; align-items: center; justify-content: space-between; gap: 1rem;
    padding: 3rem 1.5rem 1.25rem;
    background: linear-gradient(to top, rgba(0,0,0,.55), rgba(0,0,0,0));
    color: #fff; pointer-events: none;
}
.hero-caption-title { font-size: 1.45rem; font-weight: 800; letter-spacing: -.01em; text-shadow: 0 2px 14px rgba(0,0,0,.55); }
.hero-see-more {
    pointer-events: auto; display: inline-flex; align-items: center; gap: .4rem; white-space: nowrap;
    background: rgba(255,255,255,.16); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
    color: #fff; text-decoration: none; font-weight: 600; font-size: .9rem;
    padding: .45rem .95rem; border-radius: 999px; border: 1px solid rgba(255,255,255,.28);
    transition: background-color .15s;
}
.hero-see-more:hover { background: rgba(255,255,255,.3); color: #fff; }

/* "Memories from …" month view banner */
.month-banner {
    display: flex; align-items: center; justify-content: space-between; gap: 1rem;
    background: var(--z-surface); border: 1px solid var(--z-border); border-radius: 12px;
    padding: .6rem 1rem; margin-bottom: 1rem; box-shadow: var(--z-shadow);
}

/* Month / year group headers inside the grid */
.gallery-group-head {
    grid-column: 1 / -1; font-weight: 800; letter-spacing: -.01em; font-size: 1.05rem;
    color: var(--z-text); padding: .35rem .1rem .55rem; margin-top: .5rem;
    border-bottom: 1px solid var(--z-border);
}
.gallery-group-head:first-child { margin-top: 0; }

/* Icon-only "new album" button */
.album-new-btn { padding: .35rem .55rem; line-height: 1; }

/* Fixed-bottom, collapsible tools dock */
.upload-dock {
    position: fixed; left: var(--z-sidebar-w); right: 0; bottom: 0; z-index: 1200;
    display: flex; align-items: center; gap: .6rem; padding: .6rem 1.25rem;
    background: color-mix(in srgb, var(--z-surface) 94%, transparent);
    backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
    border-top: 1px solid var(--z-border);
}
.upload-dock-body { display: flex; flex: 1; align-items: stretch; gap: .6rem; }
.dock-btn { flex: 1 1 0; min-width: 0; }
.upload-dock-toggle {
    border: 1px solid var(--z-border); background: var(--z-surface); color: var(--z-text);
    width: 34px; height: 34px; border-radius: 9px; cursor: pointer; display: grid; place-items: center;
    flex-shrink: 0; font-size: 1.05rem;
}
/* Collapsed → a floating round "+" button, bottom-right */
.upload-dock.collapsed {
    left: auto; right: 1.25rem; bottom: 1.25rem; padding: 0;
    background: transparent; border: 0; backdrop-filter: none; -webkit-backdrop-filter: none;
}
.upload-dock.collapsed .upload-dock-body { display: none; }
.upload-dock.collapsed .upload-dock-toggle {
    width: 54px; height: 54px; border-radius: 50%; border: 0;
    background: var(--z-primary); color: #fff; font-size: 1.5rem;
    box-shadow: 0 8px 22px rgba(var(--z-primary-rgb), .5);
}
.upload-dock-spacer { height: 12px; }

/* Search: FAB mirroring the "+" on the left, transparent bottom bar */
.search-fab {
    position: fixed; left: calc(var(--z-sidebar-w) + 1.25rem); bottom: 1.25rem; z-index: 1200;
    width: 54px; height: 54px; border-radius: 50%; border: 0;
    background: var(--z-primary); color: #fff; font-size: 1.4rem;
    box-shadow: 0 8px 22px rgba(var(--z-primary-rgb), .5);
    display: grid; place-items: center; cursor: pointer; transition: background-color .15s;
}
.search-fab.active, .search-fab:hover { background: var(--z-primary-hover); }
.search-bar {
    position: fixed; left: calc(var(--z-sidebar-w) + 1.25rem); bottom: 1.25rem; z-index: 1300;
    width: min(520px, calc(100vw - var(--z-sidebar-w) - 3rem)); height: 54px;
    display: flex; align-items: center; gap: .5rem; padding: 0 1.1rem; border-radius: 999px;
    background: color-mix(in srgb, var(--z-surface) 55%, transparent);
    backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
    border: 1px solid var(--z-border); box-shadow: var(--z-shadow);
    transition: transform .18s ease;
}
.search-bar-icon { color: var(--z-muted); }
.search-bar-input { flex: 1; border: 0; background: transparent; color: var(--z-text); outline: none; font-size: 1rem; }
.search-bar-close { border: 0; background: transparent; color: var(--z-muted); cursor: pointer; padding: .25rem .4rem; }
.search-bar-close:hover { color: var(--z-text); }

/* Viewer tag editor */
.lightbox-tags {
    position: absolute; bottom: 3.4rem; left: 50%; transform: translateX(-50%); z-index: 3;
    display: flex; align-items: center; gap: .45rem; flex-wrap: wrap; justify-content: center;
    max-width: min(90vw, 720px); color: #fff;
}
.lightbox-tags > i { color: rgba(255,255,255,.7); }
.lb-tags { display: inline-flex; flex-wrap: wrap; gap: .35rem; }
.lb-tag { display: inline-flex; align-items: center; gap: .25rem; background: rgba(255,255,255,.16); border: 1px solid rgba(255,255,255,.25); border-radius: 999px; padding: .1rem .25rem .1rem .65rem; font-size: .8rem; }
.lb-tag button { border: 0; background: transparent; color: rgba(255,255,255,.8); cursor: pointer; font-size: 1rem; line-height: 1; padding: 0 .2rem; }
.lb-tag button:hover { color: #fff; }
.lb-tag-input { border: 0; background: rgba(255,255,255,.12); border-radius: 999px; color: #fff; padding: .22rem .8rem; outline: none; font-size: .8rem; min-width: 120px; }
.lb-tag-input::placeholder { color: rgba(255,255,255,.6); }

@media (max-width: 991.98px) {
    .upload-dock:not(.collapsed) { left: 0; }
    .search-fab { left: 1.25rem; }
    .search-bar { left: 1.25rem; width: calc(100vw - 2.5rem); }
}
@media (max-width: 575.98px) {
    .upload-target { width: 100%; }
}

@media (prefers-reduced-motion: reduce) {
    * { transition: none !important; }
}

/* ==== Admin overview: server gauges + console ========================== */
.stat-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(178px, 1fr)); gap: 1rem; }
.stat-card { background: var(--z-surface); border: 1px solid var(--z-border); border-radius: 16px; padding: 1rem .75rem; text-align: center; }
.stat-card-head { font-size: .85rem; font-weight: 600; color: var(--z-muted); margin-bottom: .5rem; }
.gauge-wrap { position: relative; width: 128px; height: 128px; margin: 0 auto; }
.gauge { width: 100%; height: 100%; transform: rotate(-90deg); }
.gauge-track { fill: none; stroke: var(--z-surface-2); stroke-width: 10; }
.gauge-fill { fill: none; stroke: var(--z-primary); stroke-width: 10; stroke-linecap: round; transition: stroke-dasharray .6s ease; }
.gauge-center { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; gap: 2px; padding: 0 10px; }
.gauge-val { font-size: 1.4rem; font-weight: 800; letter-spacing: -.02em; line-height: 1; white-space: nowrap; }
.gauge-unit { font-size: .72rem; font-weight: 600; color: var(--z-muted); }
.stat-card-foot { margin-top: .55rem; font-size: .74rem; color: var(--z-muted); min-height: 1.1em; }

.sv-console {
    background: #0b0e14; color: #cbd5e1; border: 1px solid var(--z-border); border-radius: 12px;
    padding: .75rem 1rem; height: 260px; overflow-y: auto;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .82rem; line-height: 1.5;
}
.sv-console:empty::before { content: "Output appears here…"; color: #475569; }
.sv-console-line { white-space: pre-wrap; word-break: break-word; }
.sv-cmd { color: #7dd3fc; margin-top: .35rem; }
.sv-out { color: #cbd5e1; }
.sv-err { color: #fca5a5; }
.sv-console-form {
    display: flex; align-items: center; gap: .5rem; margin-top: .5rem;
    background: #0b0e14; border: 1px solid var(--z-border); border-radius: 10px; padding: .4rem .8rem;
}
.sv-console-prompt { color: #7dd3fc; font-family: ui-monospace, monospace; }
.sv-console-input {
    flex: 1; background: transparent; border: 0; outline: none; color: #e2e8f0;
    font-family: ui-monospace, monospace; font-size: .85rem;
}

/* ==== Admin storage nodes: distribution doughnut ====================== */
.dist-ring { width: 130px; height: 130px; border-radius: 50%; position: relative; flex: 0 0 auto; }
.dist-hole { position: absolute; inset: 18px; border-radius: 50%; background: var(--z-surface); display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; }
.dist-hole span { font-weight: 800; font-size: 1rem; line-height: 1.1; }
.dist-hole small { color: var(--z-muted); font-size: .68rem; }
.dist-legend { list-style: none; margin: 0; padding: 0; font-size: .85rem; display: flex; flex-direction: column; gap: .3rem; }
.dist-dot { display: inline-block; width: 10px; height: 10px; border-radius: 3px; margin-right: .4rem; vertical-align: middle; }

/* ==== Admin overview: server pager (head-end + nodes) ================= */
.server-pager { display: flex; flex-wrap: wrap; gap: .4rem; }
.server-tab {
    display: inline-flex; align-items: center; gap: .1rem; padding: .4rem .85rem;
    border-radius: 999px; border: 1px solid var(--z-border); background: var(--z-surface);
    color: var(--z-text); text-decoration: none; font-size: .88rem; font-weight: 600;
}
.server-tab:hover { border-color: var(--z-primary); color: var(--z-text); }
.server-tab.active { background: var(--z-primary); border-color: var(--z-primary); color: #fff; }
.server-dot { width: 7px; height: 7px; border-radius: 50%; margin-left: .4rem; display: inline-block; }
.server-dot-ok { background: #22c55e; }
.server-dot-warn { background: #f59e0b; }
.server-dot-err { background: #ef4444; }
tr.node-row { cursor: pointer; transition: background-color .12s ease; }
tr.node-row:hover { background: color-mix(in srgb, var(--z-primary) 7%, transparent); }

/* ==== Camera-roll sync page =========================================== */
.sync-wrap { max-width: 560px; margin: 0 auto; padding: 1rem 0 3rem; }
.sync-hero { text-align: center; padding: 1.5rem 1rem; }
.sync-icon {
    width: 76px; height: 76px; margin: 0 auto 1rem; border-radius: 22px;
    display: grid; place-items: center; font-size: 2.2rem; color: #fff;
    background: linear-gradient(135deg, #6366f1, #8b5cf6); box-shadow: 0 10px 26px rgba(99,102,241,.45);
}
.sync-title { font-size: 1.6rem; font-weight: 800; letter-spacing: -.01em; margin-bottom: .5rem; }
.sync-lead { color: var(--z-muted); font-size: .95rem; margin-bottom: 1.5rem; }
.sync-pick {
    display: inline-flex; align-items: center; justify-content: center;
    padding: .95rem 1.6rem; border-radius: 14px; cursor: pointer; user-select: none;
    background: var(--z-primary); color: #fff; font-weight: 700; font-size: 1.05rem;
    box-shadow: 0 8px 22px rgba(var(--z-primary-rgb), .45); transition: transform .12s, background-color .15s;
}
.sync-pick:hover { background: var(--z-primary-hover); transform: translateY(-1px); }
.sync-pick:active { transform: translateY(0); }
.sync-tip { margin-top: .9rem; font-size: .82rem; color: var(--z-muted); }

.sync-share-tip {
    text-align: left; background: color-mix(in srgb, var(--z-primary) 8%, var(--z-surface));
    border: 1px solid color-mix(in srgb, var(--z-primary) 30%, var(--z-border));
    border-radius: 18px; padding: 1.15rem 1.35rem; margin-top: .5rem;
}
.sync-share-head { font-weight: 800; font-size: 1.05rem; margin-bottom: .6rem; display: flex; align-items: center; }
.sync-share-steps { margin: 0; padding-left: 1.2rem; display: flex; flex-direction: column; gap: .5rem; }
.sync-share-steps li { color: var(--z-muted); font-size: .92rem; line-height: 1.4; }
.sync-share-steps strong { color: var(--z-text); font-weight: 700; }

.sync-or {
    display: flex; align-items: center; gap: .75rem; margin: 1.1rem .25rem .1rem; color: var(--z-muted); font-size: .82rem;
}
.sync-or::before, .sync-or::after { content: ""; flex: 1; height: 1px; background: var(--z-border); }

.sync-recipe { border: 1px solid var(--z-border); border-radius: 12px; overflow: hidden; }
.sync-recipe > summary {
    cursor: pointer; padding: .7rem .9rem; font-weight: 700; font-size: .9rem;
    list-style: none; background: color-mix(in srgb, var(--z-primary) 6%, var(--z-surface));
}
.sync-recipe > summary::-webkit-details-marker { display: none; }
.sync-recipe[open] > summary { border-bottom: 1px solid var(--z-border); }
.sync-recipe-body { padding: .9rem; font-size: .88rem; color: var(--z-muted); }
.sync-recipe-body ol, .sync-recipe-body ul { padding-left: 1.15rem; }
.sync-recipe-body li { margin-bottom: .35rem; line-height: 1.45; }
.sync-recipe-body strong { color: var(--z-text); }
.sync-recipe-body code { font-size: .82rem; word-break: break-all; }

.sync-drop {
    margin-top: .5rem; padding: 2.75rem 1.5rem; border-radius: 20px; cursor: pointer;
    border: 2px dashed var(--z-border); background: var(--z-surface);
    display: flex; flex-direction: column; align-items: center; gap: 1.1rem;
    transition: border-color .15s ease, background-color .15s ease;
}
.sync-drop:hover { border-color: var(--z-primary); }
.sync-drop.dragover { border-color: var(--z-primary); background: color-mix(in srgb, var(--z-primary) 12%, var(--z-surface)); }
.sync-drop-icon { font-size: 3rem; color: var(--z-primary); line-height: 1; }
.sync-drop-label { margin: 0; color: var(--z-muted); font-size: .95rem; }

.sync-panel { background: var(--z-surface); border: 1px solid var(--z-border); border-radius: 16px; padding: 1.25rem; }
.sync-progress-head { display: flex; justify-content: space-between; font-weight: 600; margin-bottom: .5rem; }
.sync-stats { display: flex; gap: .75rem; }
.sync-stat { flex: 1; text-align: center; background: var(--z-surface-2); border-radius: 12px; padding: .75rem .25rem; }
.sync-stat-num { display: block; font-size: 1.5rem; font-weight: 800; line-height: 1; }
.sync-stat-num.sync-fail { color: #ef4444; }
.sync-stat-lbl { font-size: .72rem; color: var(--z-muted); }
.sync-actions { display: flex; gap: .5rem; margin-top: 1rem; justify-content: center; align-items: center; flex-wrap: wrap; }
.sync-keep { margin: 1rem 0 0; font-size: .82rem; color: var(--z-muted); }
.sync-done { margin: 1rem 0 0; font-weight: 600; }
.sync-install { margin-top: 1.5rem; text-align: center; font-size: .82rem; color: var(--z-muted); }

/* ---- NOC world map (admin → Map) ---- */
.noc-map-panel { background: #0a0e1a; border: 1px solid #1e2740; border-radius: 16px; padding: .75rem; }
.noc-legend { display: flex; flex-wrap: wrap; gap: .9rem; align-items: center; padding: .25rem .5rem .6rem; color: #9fb0d0; font-size: .8rem; }
.noc-leg { display: inline-flex; align-items: center; gap: .35rem; }
.noc-leg-count { margin-left: auto; color: #6b7ba0; font-variant-numeric: tabular-nums; }
.noc-dot { width: .6rem; height: .6rem; border-radius: 50%; display: inline-block; }
.noc-dot.noc-ok   { background: #22c55e; box-shadow: 0 0 6px #22c55e; }
.noc-dot.noc-warn { background: #f59e0b; box-shadow: 0 0 6px #f59e0b; }
.noc-dot.noc-err  { background: #ef4444; box-shadow: 0 0 6px #ef4444; }
.noc-dot.noc-head { background: #818cf8; box-shadow: 0 0 6px #818cf8; }
.noc-map { position: relative; width: 100%; border-radius: 12px; overflow: hidden;
    background: radial-gradient(ellipse at 50% 40%, #0f1730 0%, #080b16 82%); }
#nocSvg { display: block; width: 100%; height: auto; touch-action: none; cursor: grab; --noc-k: 1; }
.noc-map.noc-grabbing #nocSvg { cursor: grabbing; }
#nocViewport { transform-origin: 0 0; }
.noc-zoom { position: absolute; right: .55rem; bottom: .55rem; display: flex; flex-direction: column; gap: .3rem; }
.noc-zbtn { width: 2rem; height: 2rem; border-radius: 8px; border: 1px solid #24304f;
    background: rgba(10, 14, 26, .82); color: #c9d6f0; display: grid; place-items: center; cursor: pointer; font-size: .85rem; }
.noc-zbtn:hover { background: #16203a; color: #fff; }
.noc-landdot { fill: #24304f; }
.noc-arc { stroke-width: 1.4; fill: none; opacity: .55; vector-effect: non-scaling-stroke; }
.noc-arc-ok   { stroke: #22c55e; stroke-dasharray: 5 7; animation: nocflow 1s linear infinite; }
.noc-arc-warn { stroke: #f59e0b; opacity: .7; }
.noc-arc-err  { stroke: #ef4444; opacity: .7; stroke-dasharray: 2 5; }
@keyframes nocflow { to { stroke-dashoffset: -12; } }
.noc-packet { fill: #7dffb0; filter: drop-shadow(0 0 4px #22c55e); r: calc(3 / var(--noc-k, 1)); }
.noc-pin .noc-core { fill: #818cf8; }
.noc-pin-ok   .noc-core { fill: #22c55e; }
.noc-pin-warn .noc-core { fill: #f59e0b; }
.noc-pin-err  .noc-core { fill: #ef4444; }
.noc-pin-head .noc-core { fill: #a5b4fc; }
.noc-ring { fill: none; stroke: #818cf8; stroke-width: 1.2; opacity: .6; animation: nocpulse 2.4s ease-out infinite; }
@keyframes nocpulse { 0% { r: 7; opacity: .7; } 100% { r: 15; opacity: 0; } }
.noc-label { fill: #c9d6f0; font-size: 14px; font-weight: 600; paint-order: stroke; stroke: #080b16; stroke-width: 3px; }
.noc-pin-err .noc-label { fill: #fca5a5; }
.noc-empty { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; color: #6b7ba0; font-size: .9rem; text-align: center; padding: 1rem; }
.noc-type { display: inline-block; width: .55rem; height: .55rem; border-radius: 2px; margin-right: .45rem; vertical-align: middle; }
.noc-type-head { background: #818cf8; } .noc-type-storage { background: #22c55e; } .noc-type-backup { background: #38bdf8; }
/* Collapsible Locations panel */
.noc-locpanel > summary { list-style: none; cursor: pointer; display: flex; align-items: center; justify-content: space-between; gap: .5rem; }
.noc-locpanel > summary::-webkit-details-marker { display: none; }
.noc-locpanel > summary .noc-chev { transition: transform .2s ease; color: var(--z-muted); }
.noc-locpanel[open] > summary .noc-chev { transform: rotate(180deg); }
.noc-locpanel[open] > summary { border-bottom: 1px solid var(--z-border); }

/* ---- Recently Deleted (trash) ------------------------------------------ */
.album-chip-trash { margin-left: auto; }         /* push the trash chip to the end */
.trash-bar {
    display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap;
    gap: .5rem; margin: 0 0 1rem; padding: .6rem .85rem;
    background: var(--z-surface); border: 1px solid var(--z-border);
    border-radius: var(--z-radius-sm); box-shadow: var(--z-shadow);
}
.trash-bar-info { font-size: .82rem; color: var(--z-muted); }
.trash-bar-actions { display: flex; gap: .4rem; flex-wrap: wrap; }

/* Selection check (top-right; video badge already sits top-left). */
.trash-check {
    position: absolute; top: .5rem; right: .5rem; z-index: 2;
    width: 24px; height: 24px; border-radius: 50%;
    display: grid; place-items: center; cursor: pointer;
    background: rgba(0,0,0,.45); color: transparent;
    border: 2px solid rgba(255,255,255,.85); font-size: .8rem; line-height: 1;
    transition: background .12s ease, color .12s ease;
}
.gallery-item:hover .trash-check { color: rgba(255,255,255,.9); }
.trash-item.selected { outline: 3px solid var(--z-primary); outline-offset: -3px; }
.trash-item.selected .trash-check { background: var(--z-primary); border-color: var(--z-primary); color: #fff; }

/* Days-remaining pill (bottom-left of the thumb). */
.trash-daysleft {
    position: absolute; left: .5rem; bottom: .5rem; z-index: 1; pointer-events: none;
    padding: .1rem .4rem; border-radius: 6px; font-size: .68rem; font-weight: 600;
    background: rgba(0,0,0,.6); color: #fff;
}

/* ================= Feature pack: people / map / dupes / bulk / albums ===== */
.page-title { font-size: 1.4rem; font-weight: 700; margin: 0 0 .15rem; }
.page-sub   { color: var(--z-muted); margin: 0 0 1rem; font-size: .9rem; }

/* --- Map (#5) --- */
.photo-map { height: calc(100vh - 190px); min-height: 380px; border-radius: var(--z-radius);
    overflow: hidden; border: 1px solid var(--z-border); box-shadow: var(--z-shadow); }
.photo-map-empty { text-align: center; color: var(--z-muted); padding: 3rem 1rem; }
.photo-map-empty i { font-size: 2.4rem; display: block; margin-bottom: .5rem; }
.leaflet-popup-content { margin: .6rem; }

/* --- Duplicates (#9) --- */
.dup-toolbar { display: flex; align-items: center; justify-content: space-between; gap: .5rem;
    margin-bottom: 1rem; padding: .6rem .85rem; background: var(--z-surface);
    border: 1px solid var(--z-border); border-radius: var(--z-radius-sm); box-shadow: var(--z-shadow);
    position: sticky; top: .5rem; z-index: 5; }
.dup-group { display: flex; flex-wrap: wrap; gap: .6rem; padding: .75rem; margin-bottom: .75rem;
    background: var(--z-surface); border: 1px solid var(--z-border); border-radius: var(--z-radius-sm); }
.dup-item { margin: 0; width: 150px; }
.dup-item.marked { outline: 3px solid #e11d48; outline-offset: 2px; border-radius: 8px; }
.dup-item.dup-keep { outline: 3px solid var(--z-primary); outline-offset: 2px; border-radius: 8px; }
.dup-thumb img { width: 150px; height: 130px; object-fit: cover; border-radius: 8px; display: block; }
.dup-pick { display: flex; align-items: center; gap: .35rem; font-size: .8rem; margin-top: .3rem; cursor: pointer; }
.dup-meta { font-size: .72rem; color: var(--z-muted); }

/* --- People (#4) --- */
.people-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 1rem; }
.person-card { display: flex; flex-direction: column; align-items: center; text-align: center;
    text-decoration: none; color: var(--z-text); gap: .3rem; }
.person-avatar { width: 96px; height: 96px; border-radius: 50%; overflow: hidden; background: var(--z-surface-2);
    display: grid; place-items: center; border: 1px solid var(--z-border); box-shadow: var(--z-shadow); }
.person-avatar img { width: 100%; height: 100%; object-fit: cover; }
.person-avatar i { font-size: 2rem; color: var(--z-muted); }
.person-card:hover .person-avatar { border-color: var(--z-primary); }
.person-name { font-weight: 600; font-size: .9rem; }
.person-count { font-size: .75rem; color: var(--z-muted); }
.person-name-input { max-width: 320px; }
.people-person-head .gallery-vid { pointer-events: none; }

/* --- Album cover + share chip (#3/#10) --- */
.album-cover { width: 22px; height: 22px; border-radius: 5px; object-fit: cover; margin-right: .1rem; vertical-align: middle; }
.album-share { margin-left: .3rem; opacity: .55; cursor: pointer; }
.album-share:hover { opacity: 1; }
.album-chip.dragging { opacity: .5; }

/* --- Bulk select (#2) --- */
.bulk-bar { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: .5rem;
    margin-bottom: 1rem; padding: .6rem .85rem; background: var(--z-surface);
    border: 1px solid var(--z-border); border-radius: var(--z-radius-sm); box-shadow: var(--z-shadow);
    position: sticky; top: .5rem; z-index: 6; }
.bulk-count { font-weight: 600; font-size: .9rem; }
.bulk-actions { display: flex; gap: .4rem; flex-wrap: wrap; }
#selectToggle.active { background: var(--z-primary); color: #fff; border-color: var(--z-primary); }
.gallery-grid.select-mode .gallery-item { cursor: pointer; }
.gallery-grid.select-mode .gallery-item .gallery-cap { pointer-events: none; }
.gallery-item.bulk-selected { outline: 3px solid var(--z-primary); outline-offset: -3px; }
.gallery-item.bulk-selected::after { content: "\2713"; position: absolute;
    top: .4rem; right: .4rem; z-index: 3; width: 24px; height: 24px; border-radius: 50%;
    background: var(--z-primary); color: #fff; display: grid; place-items: center; font-size: .9rem; font-weight: 700; }

/* --- Public album share page (#3) --- */
.share-album-wrap { max-width: 1100px; }
.share-album-head { text-align: center; margin: 1rem 0 1.5rem; }
.share-album-title { font-size: 1.5rem; font-weight: 700; }
.share-album-sub { color: var(--z-muted); font-size: .9rem; }
.share-album-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: .5rem; }
.share-album-item { position: relative; display: block; border-radius: 10px; overflow: hidden; aspect-ratio: 1; }
.share-album-item img { width: 100%; height: 100%; object-fit: cover; }
.share-album-vid { position: absolute; inset: 0; display: grid; place-items: center; color: #fff; font-size: 2rem;
    background: rgba(0,0,0,.25); pointer-events: none; }

/* ================= Admin/user feature pack #2 ============================ */
/* Smart album chip (#5) */
.album-chip-smart .bi-funnel-fill { color: #8b5cf6; }
.album-chip-smart.active { border-color: #8b5cf6; }

/* Photo editor (#10) */
.photo-editor { position: fixed; inset: 0; z-index: 2100; display: flex; flex-direction: column;
    background: rgba(10,11,22,.96); }
.pe-bar { display: flex; align-items: center; justify-content: space-between; gap: 1rem;
    padding: .6rem .9rem; border-bottom: 1px solid rgba(255,255,255,.08); }
.pe-tools { display: flex; gap: .4rem; }
.pe-tools button { background: rgba(255,255,255,.08); color: #fff; border: 0; border-radius: 8px;
    width: 40px; height: 36px; display: grid; place-items: center; cursor: pointer; font-size: 1rem; }
.pe-tools button.active, .pe-tools button:hover { background: var(--z-primary); }
.pe-tools button[hidden] { display: none; }
.pe-actions { display: flex; gap: .4rem; }
.pe-stage { flex: 1; position: relative; display: grid; place-items: center; overflow: hidden; touch-action: none; }
#peCanvas { max-width: 96%; max-height: 100%; box-shadow: 0 8px 40px rgba(0,0,0,.5); }
.pe-crop { position: absolute; border: 2px dashed #fff; background: rgba(255,255,255,.12); pointer-events: none; }
.pe-sliders { display: flex; flex-wrap: wrap; align-items: center; gap: 1rem; justify-content: center;
    padding: .7rem 1rem; border-top: 1px solid rgba(255,255,255,.08); color: #cfd0e0; font-size: .8rem; }
.pe-sliders label { display: flex; align-items: center; gap: .5rem; }
.pe-sliders input[type=range] { width: 120px; }
.pe-reset { background: rgba(255,255,255,.08); color: #fff; border: 0; border-radius: 8px; padding: .25rem .7rem; cursor: pointer; }

/* ================= Overview: alerts & fleet-health panel ================= */
.alerts-panel .panel-head { margin-bottom: .75rem; }

/* Alert rows */
.alert-list { display: flex; flex-direction: column; gap: .45rem; }
.alert-row { display: flex; gap: .55rem; align-items: flex-start; padding: .5rem .65rem;
    border: 1px solid var(--z-border); border-left-width: 3px; border-radius: var(--z-radius-sm);
    background: var(--z-surface-2); }
.alert-row-danger    { border-left-color: #ef4444; }
.alert-row-warning   { border-left-color: #f59e0b; }
.alert-row-secondary { border-left-color: var(--z-muted); }
.alert-row-ico { font-size: 1rem; margin-top: .05rem; flex: 0 0 auto; }
.alert-row-body { flex: 1 1 auto; min-width: 0; }
.alert-row-msg { font-weight: 600; font-size: .85rem; line-height: 1.25; overflow-wrap: anywhere; }
.alert-row-meta { font-size: .72rem; color: var(--z-muted); margin-top: .1rem; }
.alert-row-action { flex: 0 0 auto; margin-left: auto; }

/* Metric cards */
.metric-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
    gap: .6rem; margin-top: .85rem; }
.metric-card { background: var(--z-surface-2); border: 1px solid var(--z-border);
    border-left: 3px solid var(--mc, var(--z-primary)); border-radius: var(--z-radius-sm);
    padding: .55rem .7rem; overflow: hidden; }
.metric-card-top { display: flex; align-items: center; gap: .35rem; }
.metric-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--mc, var(--z-primary)); flex: 0 0 auto; }
.metric-label { font-size: .72rem; color: var(--z-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.metric-value { font-size: 1.45rem; font-weight: 700; line-height: 1.1; color: var(--z-text); }
.metric-unit { font-size: .8rem; font-weight: 600; color: var(--z-muted); margin-left: 1px; }
.metric-spark { margin-top: .3rem; }
.metric-spark svg { width: 100%; height: 32px; display: block; }

/* Suppress / silence controls — wrap, never overflow */
.alert-controls-wrap { margin-top: 1rem; padding-top: 1rem; border-top: 1px solid var(--z-border); }
.alert-controls { display: grid; grid-template-columns: 1fr; gap: .75rem; }
@media (min-width: 992px) { .alert-controls { grid-template-columns: 3fr 2fr; } }
.alert-control { display: flex; flex-wrap: wrap; gap: .4rem; align-items: center;
    padding: .6rem .7rem; background: var(--z-surface-2); border: 1px solid var(--z-border);
    border-radius: var(--z-radius-sm); }
.alert-control-title { flex: 1 0 100%; font-size: .76rem; font-weight: 600; color: var(--z-muted); }
.alert-control input { min-width: 0; }              /* the key: let inputs shrink */
.ac-subject { flex: 2 1 90px; }
.ac-num     { flex: 1 1 60px; }
.ac-reason  { flex: 3 1 110px; }
.ac-btn     { flex: 0 0 auto; white-space: nowrap; }

/* Active window / silence pills */
.alert-pills { display: flex; flex-wrap: wrap; gap: .4rem; margin-top: .7rem; }
.alert-pill { display: inline-flex; align-items: center; gap: .3rem; font-size: .72rem;
    padding: .2rem .55rem; border-radius: 999px; border: 1px solid var(--z-border); }
.alert-pill-warn  { background: rgba(245, 158, 11, .14); border-color: rgba(245, 158, 11, .35); color: #b45309; }
.alert-pill-muted { background: var(--z-surface-2); color: var(--z-muted); }
.alert-pill-x { background: none; border: 0; color: inherit; cursor: pointer; font-size: 1rem; line-height: 1; padding: 0; opacity: .7; }
.alert-pill-x:hover { opacity: 1; }
@media (prefers-color-scheme: dark) { .alert-pill-warn { color: #fbbf24; } }
:root[data-theme="dark"] .alert-pill-warn { color: #fbbf24; }
:root[data-theme="light"] .alert-pill-warn { color: #b45309; }

/* ================= Consolidated admin: pagers + stacked sections ========= */
.admin-page-gap { color: var(--z-muted); padding: 0 .15rem; }
/* On merged pages, successive page-heads read as section dividers */
.admin-tabs { flex-wrap: wrap; }
@media (min-width: 640px) { .admin-tab { font-size: .95rem; padding: .55rem 1.1rem; } }
/* Live pulse indicator */
.live-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: #22c55e;
    box-shadow: 0 0 0 0 rgba(34,197,94,.6); animation: livePulse 2s infinite; vertical-align: middle; }
@keyframes livePulse { 0% { box-shadow: 0 0 0 0 rgba(34,197,94,.55); } 70% { box-shadow: 0 0 0 7px rgba(34,197,94,0); } 100% { box-shadow: 0 0 0 0 rgba(34,197,94,0); } }
.live-tag { font-size: .68rem; font-weight: 700; letter-spacing: .04em; color: #16a34a; text-transform: uppercase; }

/* ================= OCC command center — status wall + command bar ======== */
.noc-wall { display: grid; grid-template-columns: repeat(auto-fit, minmax(148px, 1fr)); gap: .6rem; margin-bottom: .9rem; }
.noc-tile { background: var(--z-surface); border: 1px solid var(--z-border); border-top: 3px solid var(--z-muted);
    border-radius: var(--z-radius-sm); padding: .6rem .8rem; box-shadow: var(--z-shadow); }
.noc-tile-ok    { border-top-color: #22c55e; }
.noc-tile-warn  { border-top-color: #f59e0b; }
.noc-tile-crit  { border-top-color: #ef4444; }
.noc-tile-muted { border-top-color: var(--z-border); }
.noc-tile-label { font-size: .66rem; text-transform: uppercase; letter-spacing: .05em; color: var(--z-muted); font-weight: 700; }
.noc-tile-val { font-size: 1.9rem; font-weight: 800; line-height: 1.1; font-variant-numeric: tabular-nums; letter-spacing: -.01em; color: var(--z-text); }
.noc-tile-word { font-size: 1.35rem; }
.noc-tile-of { font-size: .95rem; font-weight: 600; color: var(--z-muted); }
.noc-tile-sub { font-size: .72rem; color: var(--z-muted); margin-top: .1rem; }
.noc-tile-crit .noc-tile-val, .noc-tile-crit .noc-tile-word { color: #ef4444; }
.noc-tile-warn .noc-tile-word { color: #d97706; }
:root[data-theme="dark"] .noc-tile-warn .noc-tile-word { color: #fbbf24; }

.noc-cmdbar { display: flex; flex-wrap: wrap; align-items: center; gap: .45rem; padding: .55rem .75rem; margin-bottom: 1rem;
    background: var(--z-surface); border: 1px solid var(--z-border); border-radius: var(--z-radius-sm); box-shadow: var(--z-shadow); }
.noc-cmdbar-title { font-size: .7rem; text-transform: uppercase; letter-spacing: .05em; color: var(--z-muted); font-weight: 700; margin-right: .25rem; }
@media (max-width: 575px) { .noc-cmdbar-title { flex: 1 0 100%; } .noc-cmdbar .ms-auto { margin-left: 0 !important; } }

/* ================= NOC single pane of glass ============================== */
.noc-shell { display: flex; align-items: flex-start; gap: 1rem; }
.noc-sidebar { background: var(--z-surface); border: 1px solid var(--z-border); border-radius: var(--z-radius-sm); box-shadow: var(--z-shadow); }
.noc-sidebar-body { padding: .5rem; }
.noc-side-head { display: flex; align-items: center; justify-content: space-between; font-size: .72rem; text-transform: uppercase; letter-spacing: .05em; font-weight: 700; color: var(--z-muted); padding: .35rem .5rem .5rem; }
.noc-side-group { font-size: .64rem; text-transform: uppercase; letter-spacing: .06em; color: var(--z-muted); font-weight: 700; padding: .55rem .5rem .2rem; }
.noc-side-list { display: flex; flex-direction: column; gap: .25rem; }
.noc-side-item { display: flex; align-items: center; gap: .6rem; width: 100%; text-align: left; background: var(--z-surface-2); border: 1px solid transparent; border-radius: 999px; padding: .5rem .85rem; cursor: pointer; color: var(--z-text); transition: background .15s, border-color .15s, box-shadow .15s; }
.noc-side-item:hover { border-color: var(--z-border); }
.noc-side-item.active { background: rgba(var(--z-primary-rgb), .14); border-color: rgba(var(--z-primary-rgb), .45); box-shadow: 0 1px 6px rgba(var(--z-primary-rgb), .18); }
.noc-side-name { font-size: .86rem; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
/* Health dot — the only status cue in the list: green/amber/red, live */
.noc-status-dot { width: 11px; height: 11px; border-radius: 50%; flex: 0 0 auto; background: var(--z-muted); position: relative; }
.noc-status-dot.noc-ok  { background: #22c55e; }
.noc-status-dot.noc-warn { background: #f59e0b; }
.noc-status-dot.noc-err { background: #ef4444; }
.noc-status-dot.noc-warn::after, .noc-status-dot.noc-err::after {
    content: ''; position: absolute; inset: -3px; border-radius: 50%;
    background: inherit; opacity: .55; animation: noc-dot-pulse 1.6s ease-out infinite; z-index: -1;
}
@keyframes noc-dot-pulse { 0% { transform: scale(1); opacity: .55; } 100% { transform: scale(2.1); opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .noc-status-dot::after { animation: none; } }
.noc-main { flex: 1 1 auto; min-width: 0; }
.noc-main-head { display: flex; align-items: center; gap: .5rem; margin-bottom: .8rem; }
.noc-main-dot { width: 12px; height: 12px; border-radius: 50%; background: var(--z-muted); flex: 0 0 auto; }
.noc-main-dot.server-dot-ok { background: #22c55e; } .noc-main-dot.server-dot-warn { background: #f59e0b; } .noc-main-dot.server-dot-err { background: #ef4444; }
.noc-main-title { font-size: 1.25rem; font-weight: 700; margin: 0; }
.noc-main-actions { display: flex; gap: .4rem; flex-wrap: wrap; }
.noc-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: .8rem; }
.noc-card { background: var(--z-surface); border: 1px solid var(--z-border); border-radius: var(--z-radius-sm); box-shadow: var(--z-shadow); overflow: hidden; }
.noc-card-wide { grid-column: 1 / -1; }
.noc-card-head { font-size: .72rem; text-transform: uppercase; letter-spacing: .04em; font-weight: 700; color: var(--z-muted); padding: .55rem .75rem; border-bottom: 1px solid var(--z-border); }
.noc-card-body { padding: .75rem; }
.noc-gauges { display: grid; grid-template-columns: repeat(auto-fit, minmax(88px, 1fr)); gap: .5rem; }
.noc-gauge { text-align: center; }
.noc-gauge svg { width: 100%; max-width: 120px; height: auto; }
.ng-track { fill: none; stroke: var(--z-border); stroke-width: 8; stroke-linecap: round; }
.ng-fill { fill: none; stroke-width: 8; stroke-linecap: round; transition: stroke-dasharray .5s ease, stroke .5s; }
.ng-val { font-size: 1.05rem; font-weight: 800; margin-top: -.4rem; font-variant-numeric: tabular-nums; }
.ng-label { font-size: .66rem; text-transform: uppercase; letter-spacing: .04em; color: var(--z-muted); }
.noc-chart { position: relative; height: 200px; }
.noc-kpi { display: grid; grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); gap: .5rem; }
.noc-kpi-tile { border: 1px solid var(--z-border); border-top: 3px solid var(--z-muted); border-radius: 8px; padding: .45rem .6rem; }
.noc-kpi-tile.noc-tile-ok { border-top-color: #22c55e; } .noc-kpi-tile.noc-tile-warn { border-top-color: #f59e0b; } .noc-kpi-tile.noc-tile-crit { border-top-color: #ef4444; } .noc-kpi-tile.noc-tile-muted { border-top-color: var(--z-border); }
.noc-kpi-val { font-size: 1.25rem; font-weight: 800; font-variant-numeric: tabular-nums; }
.noc-kpi-label { font-size: .64rem; text-transform: uppercase; letter-spacing: .04em; color: var(--z-muted); }
.noc-dl { margin: 0; display: grid; grid-template-columns: 1fr; gap: .25rem; }
.noc-dl > div { display: flex; justify-content: space-between; gap: .5rem; font-size: .82rem; border-bottom: 1px dashed var(--z-border); padding-bottom: .2rem; }
.noc-dl dt { color: var(--z-muted); font-weight: 600; margin: 0; } .noc-dl dd { margin: 0; text-align: right; overflow-wrap: anywhere; }
.noc-ctl { display: flex; flex-wrap: wrap; gap: .4rem; }
.noc-alerts { display: flex; flex-direction: column; gap: .35rem; }
.noc-alert { font-size: .8rem; padding: .35rem .55rem; border-radius: 6px; border-left: 3px solid var(--z-muted); background: var(--z-surface-2); }
.noc-alert-crit { border-left-color: #ef4444; } .noc-alert-warn { border-left-color: #f59e0b; } .noc-alert-info { border-left-color: var(--z-muted); }
.noc-runs { display: flex; flex-direction: column; gap: .3rem; }
.noc-run { display: flex; align-items: center; gap: .5rem; font-size: .78rem; }
.noc-run .server-dot { width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto; }
.noc-run-at { color: var(--z-muted); white-space: nowrap; } .noc-run-msg { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (min-width: 992px) { .noc-sidebar { flex: 0 0 250px; position: sticky; top: 1rem; } }

/* NOC v2 — flat node list tweaks */
.noc-side-ic { color: var(--z-muted); font-size: .8rem; flex: 0 0 auto; }
.noc-side-item.active .noc-side-ic { color: var(--z-primary); }
.noc-main-actions .dropdown-menu { font-size: .85rem; }
.noc-main-actions .dropdown-item form { display: block; }

/* ================= NOC fleet-ops (Home + controls + modals) ============== */
.noc-side-home { background: rgba(var(--z-primary-rgb), .10); font-weight: 700; }
.noc-side-home i { color: var(--z-primary); font-size: .95rem; }
.noc-side-home.active { background: rgba(var(--z-primary-rgb), .18); }
.noc-head-sub { float: right; font-weight: 500; text-transform: none; letter-spacing: 0; color: var(--z-muted); }

/* Rotation / backup rows with switches */
.noc-rot { display: flex; flex-direction: column; gap: .3rem; }
.noc-rot-row { display: flex; align-items: center; gap: .55rem; font-size: .84rem; }
.noc-rot-name { background: none; border: 0; padding: 0; color: var(--z-text); font-weight: 600; cursor: pointer; text-align: left; flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.noc-rot-name:hover { color: var(--z-primary); text-decoration: underline; }
.noc-rot-meta { font-size: .72rem; color: var(--z-muted); white-space: nowrap; }
.noc-rot-region { font-size: .62rem; text-transform: uppercase; letter-spacing: .06em; font-weight: 700; color: var(--z-muted); padding: .5rem 0 .15rem; }
.noc-rot-region:first-child { padding-top: 0; }
/* Region header row inside the admin storage-node table. */
.node-region-row th { font-size: .66rem; letter-spacing: .06em; padding: .75rem .5rem .15rem; border: 0; }
.node-region-row:first-child th { padding-top: .35rem; }
.noc-switch-row { display: flex; align-items: center; justify-content: space-between; gap: .5rem; font-size: .82rem; padding: .3rem 0 .5rem; border-bottom: 1px dashed var(--z-border); margin-bottom: .3rem; }

.noc-scheme-cur { font-size: .95rem; }
.noc-intg-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(90px, 1fr)); gap: .5rem; }

/* Radio list (scheme modal) */
.noc-radios { display: flex; flex-direction: column; gap: .5rem; }
.noc-radio { display: flex; align-items: center; gap: .5rem; padding: .5rem .75rem; border: 1px solid var(--z-border); border-radius: 10px; cursor: pointer; }
.noc-radio:hover { border-color: var(--z-primary); }

.noc-log { background: #0b0f17; color: #cdd6f4; border-radius: 8px; padding: .6rem .75rem; font-size: .74rem; line-height: 1.35; max-height: 320px; overflow: auto; white-space: pre-wrap; word-break: break-word; }

/* Toast */
.noc-toast { position: fixed; left: 50%; bottom: 1.25rem; transform: translate(-50%, 2rem); opacity: 0; pointer-events: none; z-index: 1090; padding: .55rem 1rem; border-radius: 999px; font-size: .85rem; font-weight: 600; color: #fff; background: #334155; box-shadow: var(--z-shadow); transition: opacity .2s, transform .2s; }
.noc-toast.show { opacity: 1; transform: translate(-50%, 0); }
.noc-toast.ok { background: #16a34a; }
.noc-toast.err { background: #dc2626; }

/* Fleet home — live telemetry table + distribution */
.noc-tele-wrap { overflow-x: auto; }
.noc-tele { width: 100%; border-collapse: collapse; font-size: .78rem; min-width: 640px; }
.noc-tele th { font-size: .64rem; text-transform: uppercase; letter-spacing: .04em; color: var(--z-muted); font-weight: 700; text-align: left; padding: .3rem .45rem; border-bottom: 1px solid var(--z-border); white-space: nowrap; }
.noc-tele td { padding: .35rem .45rem; border-bottom: 1px solid var(--z-border); vertical-align: middle; }
.noc-tele tr:last-child td { border-bottom: 0; }
.noc-tele .noc-num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.noc-tele-name { display: flex; align-items: center; gap: .45rem; white-space: nowrap; }
.noc-tele tr.noc-stale { opacity: .55; }
.noc-tele tr.noc-tele-region th { padding-top: .6rem; letter-spacing: .06em; color: var(--z-text); opacity: .75; }
.noc-tele tr.noc-tele-region:first-child th { padding-top: .3rem; }
.noc-meter { display: inline-block; width: 46px; height: 6px; border-radius: 3px; background: var(--z-border); overflow: hidden; vertical-align: middle; }
.noc-meter > span { display: block; height: 100%; border-radius: 3px; transition: width .4s ease; }
.noc-meter-v { margin-left: .35rem; font-variant-numeric: tabular-nums; font-size: .72rem; color: var(--z-muted); }
.noc-head-sub { font-weight: 500; text-transform: none; letter-spacing: 0; color: var(--z-muted); margin-left: .4rem; font-size: .68rem; }

/* ================= Sidebar device tree ================================== */
.noc-nav-item { display: flex; align-items: center; gap: .6rem; width: 100%; background: none; border: 0; border-radius: 8px; padding: .55rem .7rem; color: var(--z-text); font-size: .86rem; font-weight: 600; cursor: pointer; }
.noc-nav-item:hover { background: var(--z-surface-2); }
.noc-nav-item.active { background: rgba(var(--z-primary-rgb), .13); color: var(--z-primary); }
.noc-nav-item i { font-size: .95rem; }
.noc-tree-group { margin-top: .35rem; }
.noc-tree-head { display: flex; align-items: center; gap: .45rem; width: 100%; background: none; border: 0; padding: .4rem .55rem; border-radius: 6px; cursor: pointer; color: var(--z-muted); }
.noc-tree-head:hover { background: var(--z-surface-2); color: var(--z-text); }
.noc-tree-chev { font-size: .7rem; transition: transform .18s ease; }
.noc-tree-chev.open { transform: rotate(90deg); }
.noc-tree-ic { font-size: .8rem; }
.noc-tree-label { font-size: .66rem; text-transform: uppercase; letter-spacing: .07em; font-weight: 700; flex: 1 1 auto; text-align: left; }
.noc-tree-count { font-size: .64rem; font-weight: 700; padding: .05rem .4rem; border-radius: 999px; background: var(--z-surface-2); border: 1px solid var(--z-border); }
.noc-tree-count.noc-roll-ok { color: #22c55e; border-color: rgba(34,197,94,.4); }
.noc-tree-count.noc-roll-warn { color: #f59e0b; border-color: rgba(245,158,11,.45); }
.noc-tree-count.noc-roll-err { color: #ef4444; border-color: rgba(239,68,68,.45); background: rgba(239,68,68,.1); }
.noc-tree-body { display: flex; flex-direction: column; gap: 1px; padding-left: .55rem; margin-left: .5rem; border-left: 1px solid var(--z-border); }
.noc-node { display: flex; align-items: center; gap: .55rem; width: 100%; text-align: left; background: none; border: 0; border-radius: 6px; padding: .4rem .55rem; cursor: pointer; color: var(--z-text); font-size: .82rem; position: relative; }
.noc-node:hover { background: var(--z-surface-2); }
.noc-node.active { background: rgba(var(--z-primary-rgb), .13); font-weight: 600; }
.noc-node.active::before { content: ''; position: absolute; left: -.55rem; top: 50%; transform: translateY(-50%); width: 2px; height: 60%; background: var(--z-primary); border-radius: 2px; }
.noc-node-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
/* Geographic region headers inside the Storage group. Node rows stay minimal
   (dot + name); the count/health rollup lives on the header only. */
.noc-region + .noc-region { margin-top: .3rem; }
.noc-region-head { display: flex; align-items: baseline; gap: .4rem; padding: .3rem .55rem .15rem; color: var(--z-muted); }
.noc-region-name { font-size: .6rem; text-transform: uppercase; letter-spacing: .06em; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.noc-region-sum { font-size: .6rem; white-space: nowrap; margin-left: auto; font-variant-numeric: tabular-nums; opacity: .85; }

/* ================= Alarm / Operation rows =============================== */
.noc-rows { display: flex; flex-direction: column; gap: .3rem; }
.noc-row { display: flex; align-items: center; gap: .6rem; padding: .5rem .6rem; border: 1px solid var(--z-border); border-radius: 9px; background: var(--z-surface-2); }
.noc-row[role="button"] { cursor: pointer; }
.noc-row[role="button"]:hover { border-color: rgba(var(--z-primary-rgb), .5); }
.noc-row-main { flex: 1 1 auto; min-width: 0; }
.noc-row-title { font-size: .83rem; font-weight: 600; overflow: hidden; text-overflow: ellipsis; }
.noc-row-meta { font-size: .69rem; color: var(--z-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.noc-row-cleared { opacity: .6; }
.noc-row-sev { width: 4px; align-self: stretch; border-radius: 2px; flex: 0 0 auto; background: var(--z-muted); }
.noc-sev-crit > .noc-row-sev { background: #ef4444; }
.noc-sev-warn > .noc-row-sev { background: #f59e0b; }
.noc-sev-info > .noc-row-sev { background: #0ea5e9; }
.noc-op-badge { width: 26px; height: 26px; border-radius: 50%; display: flex; align-items: center; justify-content: center; flex: 0 0 auto; font-size: .75rem; }
.noc-op-badge.noc-op-ok { background: rgba(34,197,94,.15); color: #22c55e; }
.noc-op-badge.noc-op-err { background: rgba(239,68,68,.15); color: #ef4444; }
.noc-op-badge.noc-op-warn { background: rgba(245,158,11,.15); color: #f59e0b; }
.noc-op-badge.noc-op-run { background: rgba(var(--z-primary-rgb), .15); color: var(--z-primary); }
.noc-op-badge.noc-op-mut { background: var(--z-border); color: var(--z-muted); }
.noc-op-bar { height: 4px; margin-top: .3rem; background: var(--z-border); }
.noc-filters { flex-wrap: wrap; }
.noc-pagerow { display: flex; align-items: center; justify-content: space-between; gap: .5rem; margin-top: .6rem; flex-wrap: wrap; }
.noc-pagenote { font-size: .7rem; color: var(--z-muted); }
.noc-pager .page-link { padding: .15rem .5rem; font-size: .75rem; }

/* Modal detail sections */
.noc-modal-head { border-bottom: 1px solid var(--z-border); padding-bottom: .6rem; }
.noc-modal-sec { margin-top: 1rem; }
.noc-modal-sec h6 { font-size: .68rem; text-transform: uppercase; letter-spacing: .05em; color: var(--z-muted); font-weight: 700; }
.noc-pre { background: var(--z-surface-2); border: 1px solid var(--z-border); border-radius: 8px; padding: .6rem .7rem; font-size: .72rem; line-height: 1.5; max-height: 340px; overflow: auto; white-space: pre-wrap; word-break: break-word; margin: 0; }
.noc-oplog { max-height: 300px; }

/* ================= Home section nav + Actions panel ===================== */
.noc-secnav { display: flex; gap: .3rem; overflow-x: auto; padding-bottom: .5rem; margin-bottom: .2rem; grid-column: 1 / -1; scrollbar-width: thin; }
.noc-secbtn { display: inline-flex; align-items: center; gap: .4rem; white-space: nowrap; background: var(--z-surface-2); border: 1px solid var(--z-border); border-radius: 999px; padding: .4rem .85rem; font-size: .8rem; font-weight: 600; color: var(--z-muted); cursor: pointer; transition: all .15s; }
.noc-secbtn:hover { color: var(--z-text); border-color: var(--z-muted); }
.noc-secbtn.active { background: var(--z-primary); border-color: var(--z-primary); color: #fff; }
.noc-secbadge { font-size: .62rem; font-weight: 700; line-height: 1; padding: .15rem .35rem; border-radius: 999px; }
.noc-secbadge.noc-badge-warn { background: #ef4444; color: #fff; }
.noc-actions-panel { display: flex; flex-direction: column; gap: .9rem; }
.noc-actgrp-head { font-size: .68rem; text-transform: uppercase; letter-spacing: .05em; font-weight: 700; color: var(--z-muted); margin-bottom: .4rem; display: flex; align-items: baseline; gap: .5rem; flex-wrap: wrap; }
.noc-actgrp-note { text-transform: none; letter-spacing: 0; font-weight: 500; font-size: .68rem; opacity: .85; }
.noc-actrow { display: flex; flex-wrap: wrap; gap: .4rem; }
.noc-actbtn { white-space: nowrap; }
.noc-act-note { font-size: .72rem; color: var(--z-muted); border-top: 1px solid var(--z-border); padding-top: .6rem; }
@media (max-width: 575px) { .noc-actrow .noc-actbtn { flex: 1 1 100%; } }

/* ================= VPN tab ============================================== */
.vpn-secnav { display: flex; gap: .3rem; overflow-x: auto; padding-bottom: .75rem; scrollbar-width: thin; }
.vpn-table { font-size: .84rem; }
.vpn-table th { font-size: .66rem; text-transform: uppercase; letter-spacing: .04em; color: var(--z-muted); font-weight: 700; }
.vpn-table td { vertical-align: middle; }
.vpn-name { font-weight: 600; }
.vpn-sub { font-size: .7rem; color: var(--z-muted); }
.vpn-key { font-size: .68rem; word-break: break-all; }
.vpn-form { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: .7rem; }
.vpn-field { display: flex; flex-direction: column; gap: .2rem; min-width: 0; }
.vpn-field-wide { grid-column: 1 / -1; }
.vpn-field label { font-size: .7rem; font-weight: 600; color: var(--z-muted); text-transform: uppercase; letter-spacing: .03em; }
.vpn-hint { font-size: .66rem; color: var(--z-muted); }
.vpn-check { display: flex; align-items: center; gap: .5rem; font-size: .8rem; padding: .2rem 0; flex-wrap: wrap; }
.noc-secbadge.noc-badge-ok { background: #22c55e; color: #fff; }
.noc-toast { position: fixed; left: 50%; bottom: 1.5rem; transform: translateX(-50%); z-index: 1090;
    background: var(--z-surface); border: 1px solid var(--z-border); border-left: 3px solid #22c55e;
    border-radius: 8px; padding: .6rem .9rem; font-size: .84rem; box-shadow: var(--z-shadow); max-width: 90vw; }
.noc-toast.err { border-left-color: #ef4444; }
@media (max-width: 575px) { .vpn-form { grid-template-columns: 1fr; } }

/* VPN config delivery (download / QR) */
.vpn-cfg-actions { display: flex; flex-wrap: wrap; gap: .4rem; }
.vpn-qr { display: flex; flex-direction: column; align-items: center; gap: .4rem; padding: .75rem; background: #fff; border: 1px solid var(--z-border); border-radius: 10px; margin-bottom: .6rem; }
.vpn-qr canvas { max-width: 100%; height: auto; image-rendering: pixelated; }
.vpn-qr .vpn-hint { color: #444; text-align: center; }
.vpn-bulk-list { display: flex; flex-direction: column; gap: .25rem; max-height: 220px; overflow-y: auto; }
.vpn-bulk-row { display: flex; align-items: center; justify-content: space-between; gap: .5rem; font-size: .82rem; padding: .3rem .5rem; border: 1px solid var(--z-border); border-radius: 8px; background: var(--z-surface-2); }
@media (max-width: 575px) { .vpn-cfg-actions .btn { flex: 1 1 100%; } }

/* ================= VPN tunnel map (zoomable) ============================ */
.vpn-map-wrap { position: relative; width: 100%; border-radius: 12px; overflow: hidden; background: #0a0c1a; }
.vpn-map-svg { display: block; width: 100%; height: auto; cursor: grab; touch-action: none; }
.vpn-map-svg.dragging { cursor: grabbing; }
.vpn-world { --vinv: 1; }
.vpn-map-grid line { stroke: rgba(120,140,200,.10); stroke-width: calc(1px * var(--vinv)); }
.vpn-map-grid line.major { stroke: rgba(120,140,200,.20); }
.vpn-map-land path { fill: rgba(96,120,180,.20); stroke: rgba(150,180,240,.45);
    stroke-width: calc(1.4px * var(--vinv)); stroke-linejoin: round; }
/* Real Natural Earth geometry (assets/js/zf-world.js, generated by
   bin/build-map-data.php). One ring per country instead of one per continent,
   so the border stroke is now what carries the detail — but it is drawn against
   the same dark sea, and a bright hairline over 287 rings turns the map into a
   wireframe. Keep it dimmer than the coarse outline's, and non-scaling so it
   stays a hairline at 80x instead of needing the --vinv trick. */
.vpn-map-land.detailed path.vpn-land { fill: rgba(96,120,180,.22);
    stroke: rgba(150,180,240,.34); stroke-width: 0.7px; stroke-linejoin: round;
    vector-effect: non-scaling-stroke; }
/* Provinces: outline only, dimmer and thinner again so country borders still
   read as the stronger line. Hidden below 3x from applyView(). */
.vpn-states { pointer-events: none; }
.vpn-states path { fill: none; stroke: rgba(150,180,240,.17); stroke-width: 0.5px;
    stroke-linejoin: round; vector-effect: non-scaling-stroke; }
/* Ties a nudged label back to the pin it belongs to. */
.vpn-label-leader { stroke: rgba(219,226,247,.38); stroke-width: 1px;
    vector-effect: non-scaling-stroke; pointer-events: none; }
.vpn-arc { fill: none; stroke: #22c55e; opacity: .18; vector-effect: non-scaling-stroke; }
.vpn-arc.down { stroke: #ef4444; opacity: .12; stroke-dasharray: 5 5; }
.vpn-arc-flow { fill: none; stroke: #7dd3fc; stroke-width: 2.5; stroke-linecap: round;
    stroke-dasharray: 4 30; opacity: .95; vector-effect: non-scaling-stroke;
    animation: vpn-flow 3s linear infinite; }
@keyframes vpn-flow { to { stroke-dashoffset: -340; } }
@media (prefers-reduced-motion: reduce) { .vpn-arc-flow { animation: none; opacity: .55; } }
.vpn-pin { cursor: pointer; }
.vpn-pin circle { fill: #22c55e; }
.vpn-pin.down circle { fill: #ef4444; }
.vpn-pin.hub circle { fill: #6366f1; }
.vpn-pin:hover circle, .vpn-pin:focus circle { fill: #7dd3fc; }
.vpn-pin-ring { fill: none; stroke: #7dd3fc; stroke-width: 1.6; opacity: .85;
    animation: vpn-ring 2.2s ease-out infinite; }
@keyframes vpn-ring { 0% { r: 9; opacity: .85 } 100% { r: 22; opacity: 0 } }
.vpn-pin-label { fill: #dbe2f7; font-size: 13px; text-anchor: middle; font-weight: 600;
    paint-order: stroke; stroke: rgba(6,8,18,.9); stroke-width: 3.5px; pointer-events: none; }
.vpn-map-tools { position: absolute; top: .5rem; right: .5rem; z-index: 3; display: flex; flex-direction: column; gap: .25rem; }
.vpn-map-tools button { width: 30px; height: 30px; border-radius: 7px; border: 1px solid rgba(255,255,255,.15);
    background: rgba(16,18,34,.85); color: #dbe2f7; font-size: 1rem; line-height: 1; cursor: pointer; }
.vpn-map-tools button:hover { background: rgba(40,44,80,.95); }
.vpn-map-tip { position: absolute; z-index: 4; pointer-events: none; min-width: 200px; max-width: 250px;
    background: rgba(12,14,28,.97); border: 1px solid rgba(255,255,255,.14); border-radius: 10px;
    padding: .55rem .7rem; font-size: .74rem; color: #dbe2f7; box-shadow: 0 12px 30px rgba(0,0,0,.55); }
.vpn-map-tip .tip-h { font-weight: 700; font-size: .82rem; margin-bottom: .3rem; }
.vpn-map-tip .tip-r { display: flex; justify-content: space-between; gap: .6rem; padding: .1rem 0; }
.vpn-map-tip .tip-r span { opacity: .65; }
.vpn-map-tip .ok { color: #22c55e; } .vpn-map-tip .warn { color: #f59e0b; } .vpn-map-tip .err { color: #ef4444; }
.vpn-map-legend { display: flex; flex-wrap: wrap; gap: .9rem; align-items: center; padding: .6rem .8rem; font-size: .74rem; color: var(--z-muted); }
.vpn-key { width: 16px; height: 3px; border-radius: 2px; display: inline-block; margin-right: .35rem; vertical-align: middle; }
.vpn-key.ok { background: #22c55e; } .vpn-key.down { background: #ef4444; } .vpn-key.flow { background: #7dd3fc; }
.vpn-map-note { margin-left: auto; opacity: .8; }

/* VPN map — connected client pins */
.vpn-arc.user { stroke: #f59e0b; opacity: .45; }
.vpn-arc-flow.user { stroke: #fcd34d; animation-duration: 2.2s; }
.vpn-pin.user circle { fill: #f59e0b; }
.vpn-pin.user:hover circle, .vpn-pin.user:focus circle { fill: #fcd34d; }
.vpn-pin-ring.user { stroke: #fcd34d; }
.vpn-key.user { background: #f59e0b; }
.vpn-zoom-lvl { display: block; text-align: center; font-size: .62rem; color: #9aa3c0;
    background: rgba(16,18,34,.85); border: 1px solid rgba(255,255,255,.12);
    border-radius: 6px; padding: .1rem 0; font-variant-numeric: tabular-nums; }

/* ================= Self-service VPN (user page) ========================= */
.vpn-steps { padding-left: 1.15rem; margin: 0; font-size: .88rem; line-height: 1.75; }
.vpn-steps li { margin-bottom: .35rem; }
.vpn-warn { font-size: .8rem; color: var(--z-muted); border-left: 3px solid #f59e0b; padding-left: .6rem; }
.vpn-dev-list { display: flex; flex-direction: column; gap: .4rem; }
.vpn-dev { display: flex; align-items: center; gap: .7rem; padding: .6rem .75rem;
    border: 1px solid var(--z-border); border-radius: 10px; background: var(--z-surface-2); }
.vpn-dev-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--z-muted); flex: 0 0 auto; }
.vpn-dev-dot.on { background: #22c55e; }
.vpn-dev-main { flex: 1 1 auto; min-width: 0; }
.vpn-dev-name { font-weight: 600; font-size: .88rem; }
.vpn-dev-sub { font-size: .72rem; color: var(--z-muted); }
.vpn-dev-count { font-size: .72rem; color: var(--z-muted); margin: .6rem 0 0; }
/* Local network: the user's own devices that a group would cover. */
.vpn-local-list { list-style: none; padding: 0; margin: 0;
    display: flex; flex-direction: column; gap: .25rem; }
.vpn-local-list li { display: flex; align-items: baseline; gap: .5rem; }
.vpn-local-list code { font-size: .74rem; color: var(--z-muted); }
.vpn-self-steps { display: flex; flex-direction: column; gap: .5rem; font-size: .86rem; }
.vpn-self-steps .n { display: inline-flex; width: 20px; height: 20px; border-radius: 50%;
    background: var(--z-primary); color: #fff; align-items: center; justify-content: center;
    font-size: .7rem; font-weight: 700; margin-right: .5rem; }

/* DNS query log */
.qlog-wrap { max-height: 420px; overflow: auto; border: 1px solid var(--z-border); border-radius: 8px; }
.qlog { width: 100%; border-collapse: collapse; font-size: .72rem; }
.qlog thead th { position: sticky; top: 0; background: var(--z-surface-2); text-align: left;
    padding: .35rem .5rem; font-weight: 700; font-size: .65rem; text-transform: uppercase;
    letter-spacing: .04em; color: var(--z-muted); border-bottom: 1px solid var(--z-border); }
.qlog td { padding: .28rem .5rem; border-bottom: 1px solid rgba(128,128,128,.12); white-space: nowrap; }
.qlog tr.q-blocked td.q-d { color: #ef4444; }
.qlog td.q-t, .qlog td.q-c, .qlog td.q-y { color: var(--z-muted); font-variant-numeric: tabular-nums; }
.qlog td.q-d { max-width: 260px; overflow: hidden; text-overflow: ellipsis; }

/* ================= Filtering page layout ================================ */
/* Auto-fit rather than hand-assigned spans: cards claim a sensible minimum and
   then STRETCH to share whatever is left, so a row is always full and no card
   is ever squeezed below a usable width. Hand-tuned 12-column spans kept
   producing either stranded columns or crushed cards at some viewport width. */
.dns-cards {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 380px), 1fr));
    gap: .85rem;
    align-items: start;
}
/* Only genuinely wide content spans the whole row. */
.dns-cards > .col-12 { grid-column: 1 / -1; }
.dns-cards > .noc-card { min-width: 0; }

/* ================= Global layout safety ================================= */
/* Grid/flex children default to min-width:auto, which lets long words, code
   spans and wide tables push a card past its track and spill out of the
   parent. Pinning min-width:0 makes every card actually honour its column. */
.noc-cards > *, .dns-cards > *, .vpn-form > *, .noc-kpi > * { min-width: 0; }
.noc-card, .noc-card-body { min-width: 0; }
.noc-card-body { overflow-wrap: anywhere; }
/* Labels and hints wrap instead of being clipped mid-word. */
.vpn-field > label, .noc-kpi-label, .noc-card-head { overflow-wrap: anywhere; white-space: normal; }
.vpn-field { min-width: 0; }
.vpn-field input, .vpn-field select, .vpn-field textarea { max-width: 100%; }
/* Wide content scrolls inside its card rather than widening the page. */
.noc-card-body > table, .noc-card-body > pre { max-width: 100%; }
.noc-card-body pre { overflow-x: auto; }
/* Nothing may cause a horizontal scrollbar on the page itself. */
.noc-main, .noc-cards, .dns-cards { max-width: 100%; }


/* Input + button rows must not wrap the button's label ("Tes t"). */
.vpn-field .d-flex > .btn, .noc-card-body .d-flex > .btn { flex: 0 0 auto; white-space: nowrap; }
.vpn-field .d-flex > .form-control { min-width: 0; }

/* ================= Wide cards + dense tables ============================ */
/* col-12 previously only worked inside .dns-cards, so full-width cards in the
   VPN panel silently rendered as narrow grid items and their tables were
   crushed. Make the span classes work in any card grid. */
.noc-cards > .col-12, .dns-cards > .col-12 { grid-column: 1 / -1; }

/* Data tables must not wrap headers mid-word ("LATEN CY", "nyc.no de10").
   Let the table keep its natural width and scroll inside its own wrapper
   instead — the card itself never widens, so nothing spills out. */
.vpn-table { width: auto; min-width: 100%; }
.vpn-table th, .vpn-table td { white-space: nowrap; vertical-align: middle; }
.vpn-table th { font-size: .68rem; letter-spacing: .03em; }
/* The one column allowed to wrap is free-text, and only at a sensible width. */
.vpn-table td.wrap, .vpn-table td .vpn-sub { white-space: normal; }
.table-responsive { overflow-x: auto; -webkit-overflow-scrolling: touch; max-width: 100%; }
/* Monospace blocks scroll rather than stretching the card. */
.noc-card-body .noc-pre { overflow-x: auto; white-space: pre; }

/* VPN map — traceroute overlay */
.vpn-trace-bar { display: flex; gap: .4rem; margin-bottom: .5rem; flex-wrap: wrap; }
.vpn-trace-bar #traceTarget { flex: 1 1 16rem; min-width: 0; }
.vpn-trace-bar #traceFrom { flex: 0 0 auto; width: auto; }
.vpn-trace-leg { fill: none; stroke: #f472b6; stroke-width: 2; opacity: .85;
    stroke-dasharray: 6 4; vector-effect: non-scaling-stroke; }
.vpn-pin.trace circle { fill: #f472b6; }
.vpn-pin.trace:hover circle { fill: #fbcfe8; }

/* VPN map — live destination flows */
.vpn-flow-leg { fill: none; stroke: #38bdf8; opacity: .32; vector-effect: non-scaling-stroke; }
.vpn-pin.flow circle { fill: #38bdf8; }
.vpn-pin.flow:hover circle { fill: #bae6fd; }
.vpn-key.flow2 { background: #38bdf8; }
/* VPN map — traced hop paths (exit node -> destination) */
.vpn-hop-leg { fill: none; stroke: #38bdf8; stroke-width: 1.8; opacity: .9;
    stroke-linecap: round; stroke-dasharray: 7 5;
    vector-effect: non-scaling-stroke; animation: vpn-hop-march 1.4s linear infinite; }
@keyframes vpn-hop-march { to { stroke-dashoffset: -24; } }
@media (prefers-reduced-motion: reduce) { .vpn-hop-leg { animation: none; } }
.vpn-pin.hop circle { fill: #7dd3fc; }
.vpn-pin.hop:hover circle { fill: #e0f2fe; }
/* Live destination line (no traced path yet) */
.vpn-live-leg { fill: none; stroke: #38bdf8; stroke-width: 1.4; opacity: .5;
    stroke-dasharray: 5 6; vector-effect: non-scaling-stroke;
    animation: vpn-hop-march 1.8s linear infinite; }
