/* EdgePanel UI foundation styles: mobile-first, theme-aware.
 *
 * Layered ON TOP of Bootstrap 5 via CSS variables and a thin set of component
 * polish rules — no build step, no framework swap. The design tokens live in
 * :root and are overridden per theme, so a colour or radius change is one line.
 */

/* ============================ design tokens ============================ */
:root {
    --ep-radius: 14px;
    --ep-radius-sm: 10px;
    --ep-gap: 1rem;
    --ep-ease: cubic-bezier(.2, .7, .3, 1);
    --ep-accent: #4dabf7;
    --ep-accent-2: #b197fc;

    /* Elevation — soft, layered shadows read as "designed" rather than boxed. */
    --ep-shadow: 0 1px 2px rgba(0,0,0,.06), 0 4px 16px -6px rgba(0,0,0,.12);
    --ep-shadow-hover: 0 2px 6px rgba(0,0,0,.10), 0 14px 34px -10px rgba(0,0,0,.28);
}

/* Dark: deep charcoal, never pure black — softer, and lets glows read. */
[data-bs-theme="dark"] {
    --bs-body-bg: #0f1216;
    --bs-body-bg-rgb: 15,18,22;
    --bs-tertiary-bg: #171b21;
    --bs-border-color: #262c35;
    --bs-border-color-translucent: rgba(255,255,255,.08);
    --ep-card-bg: #161a20;
    --ep-card-border: #262c35;
    --ep-elevate: #1b2027;
    --ep-shadow: 0 1px 2px rgba(0,0,0,.4), 0 8px 24px -8px rgba(0,0,0,.55);
    --ep-shadow-hover: 0 2px 6px rgba(0,0,0,.5), 0 18px 44px -12px rgba(0,0,0,.7);
}
[data-bs-theme="light"] {
    --bs-body-bg: #f4f6fa;
    --ep-card-bg: #ffffff;
    --ep-card-border: #e6e9ef;
    --ep-elevate: #ffffff;
}

/* ============================ base ============================ */
body {
    padding-bottom: 3rem;
    font-family: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
    font-feature-settings: 'cv02','cv03','cv04','ss01';
    letter-spacing: -.01em;
    background-image:
        radial-gradient(1200px 600px at 80% -10%, rgba(77,171,247,.06), transparent 60%),
        radial-gradient(1000px 500px at -10% 0%, rgba(177,151,252,.05), transparent 55%);
    background-attachment: fixed;
}
h1, h2, h3, h4, h5, h6, .navbar-brand { letter-spacing: -.02em; }
.mono, .font-mono { font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace; }
.navbar-brand { font-weight: 700; letter-spacing: -.02em; }

/* Numbers that update (KPIs, counters) want tabular figures so they don't
 * jitter as digits change. */
.fs-3, .fs-4, .h4, .kpi-num, [id^="stat-"], [id^="cf-"] { font-variant-numeric: tabular-nums; }

/* ============================ cards ============================ */
.card {
    background: var(--ep-card-bg);
    border: 1px solid var(--ep-card-border);
    border-radius: var(--ep-radius);
    box-shadow: var(--ep-shadow);
    transition: transform .18s var(--ep-ease), box-shadow .18s var(--ep-ease), border-color .18s var(--ep-ease);
}
.card-header {
    background: transparent;
    border-bottom: 1px solid var(--bs-border-color-translucent);
    font-weight: 600;
}
/* Only cards that are meant to be interactive lift — KPI tiles and links. */
.kpi-card:hover,
a > .card:hover {
    transform: translateY(-2px);
    box-shadow: var(--ep-shadow-hover);
    border-color: color-mix(in srgb, var(--ep-accent) 40%, var(--ep-card-border));
}

/* A subtle top accent line on KPI cards — the small detail that reads premium. */
.kpi-card::before {
    content: ''; position: absolute; inset: 0 0 auto 0; height: 2px;
    background: linear-gradient(90deg, var(--ep-accent), var(--ep-accent-2));
    opacity: 0; transition: opacity .2s var(--ep-ease);
}
.kpi-card:hover::before { opacity: .9; }
.card.border-danger { box-shadow: var(--ep-shadow), 0 0 0 1px rgba(255,107,107,.35), 0 0 22px -6px rgba(255,107,107,.5); }

.stat-card .display-6 { font-weight: 700; }
.table-sm td, .table-sm th { vertical-align: middle; }
.badge-online { background: #198754; }
.badge-offline { background: #6c757d; }
.tier-active { background: rgba(25,135,84,.18); }
.tier-active-throttled { background: rgba(220,53,69,.18); }
.tier-consumed { opacity: .55; }
.pulse { animation: pulse 2s infinite; }
@keyframes pulse { 0%{opacity:1} 50%{opacity:.4} 100%{opacity:1} }

/* Badges & buttons: a touch rounder, snappier press feedback. */
.badge { border-radius: 999px; font-weight: 600; letter-spacing: 0; }
.btn { border-radius: var(--ep-radius-sm); transition: transform .12s var(--ep-ease), box-shadow .12s var(--ep-ease), background-color .12s var(--ep-ease); }
.btn:active { transform: translateY(1px) scale(.99); }
.form-control, .form-select { border-radius: var(--ep-radius-sm); }

/* ============================ KPI cards ============================ */
.kpi-card { position: relative; overflow: hidden; }
.kpi-card .kpi-spark { position: absolute; inset: auto 0 0 0; height: 34px; opacity: .85; pointer-events: none; }
.kpi-card .card-body { padding-bottom: 2.4rem; }
.kpi-live-dot {
    width: 8px; height: 8px; border-radius: 50%; background: #51cf66; display: inline-block;
    animation: pulse 2s infinite; box-shadow: 0 0 8px rgba(81,207,102,.8);
}

/* ============================ count-up + skeletons ============================ */
/* A number mid-animation shouldn't wrap or shift layout. */
.kpi-counting { transition: none; }

.ep-skeleton {
    position: relative; overflow: hidden;
    background: color-mix(in srgb, var(--bs-secondary-color) 16%, transparent);
    border-radius: 6px; color: transparent !important;
}
.ep-skeleton::after {
    content: ''; position: absolute; inset: 0;
    background: linear-gradient(90deg, transparent, rgba(255,255,255,.10), transparent);
    transform: translateX(-100%); animation: ep-shimmer 1.3s infinite;
}
@keyframes ep-shimmer { 100% { transform: translateX(100%); } }

/* ============================ sortable tables ============================ */
th.ep-sortable { cursor: pointer; user-select: none; white-space: nowrap; }
th.ep-sortable::after { content: '↕'; opacity: .3; margin-left: .3em; font-size: .8em; }
th.ep-sortable[data-dir="asc"]::after { content: '↑'; opacity: .9; }
th.ep-sortable[data-dir="desc"]::after { content: '↓'; opacity: .9; }
.table-hover > tbody > tr { transition: background-color .12s var(--ep-ease); }

/* ============================ chart containers ============================ */
.chart-box { position: relative; height: 260px; }
.chart-box-sm { position: relative; height: 180px; }

/* ============================ toasts ============================ */
#ep-toasts { z-index: 1090; }
.toast { border-radius: var(--ep-radius-sm); box-shadow: var(--ep-shadow-hover); }

/* ============================ nav ============================ */
/* backdrop-filter makes the navbar its own stacking context, which would trap
 * the dropdown menu BELOW the absolutely-positioned Gridstack cards that come
 * later in the DOM. Lifting the whole navbar above the grid keeps the menu on
 * top. 1030 = Bootstrap's fixed-element tier, still under modals/toasts. */
.navbar { position: relative; z-index: 1030; backdrop-filter: saturate(1.4) blur(6px); }
.nav-link { border-radius: var(--ep-radius-sm); transition: background-color .12s var(--ep-ease), color .12s var(--ep-ease); }
.navbar-nav .nav-link.active { color: var(--bs-emphasis-color); }
.dropdown-menu { border-radius: var(--ep-radius); box-shadow: var(--ep-shadow-hover); border-color: var(--bs-border-color-translucent); }

/* ============================ dashboard grid (Gridstack) ============================ */
.grid-stack { margin: 0 -6px; }
.grid-stack-item-content { inset: 6px; }
.grid-stack-item-content > .card { height: 100%; margin: 0; }
/* The drag handle only appears in edit mode, so a locked dashboard looks and
 * behaves exactly like the old static one. */
.ep-grid-handle {
    display: none; position: absolute; top: 8px; right: 10px; z-index: 5;
    cursor: move; color: var(--bs-secondary-color); font-size: 1.05rem; line-height: 1;
    opacity: .6; user-select: none;
}
.ep-editing .ep-grid-handle { display: block; }
.ep-editing .grid-stack-item-content > .card {
    outline: 1px dashed color-mix(in srgb, var(--ep-accent) 55%, transparent);
    outline-offset: -1px;
}
.ep-editing .kpi-card:hover { transform: none; }  /* don't fight the drag */
.grid-stack-item.ui-draggable-dragging .card,
.grid-stack-item.ui-resizable-resizing .card { box-shadow: var(--ep-shadow-hover); }
.grid-stack > .grid-stack-placeholder > .placeholder-content {
    border: 1px dashed color-mix(in srgb, var(--ep-accent) 60%, transparent);
    border-radius: var(--ep-radius); background: color-mix(in srgb, var(--ep-accent) 8%, transparent);
}
@media (prefers-reduced-motion: reduce) {
    * { animation-duration: .001ms !important; transition-duration: .001ms !important; }
}

/* ---------------- Mobile ---------------- */
@media (max-width: 767.98px) {
    body { padding-bottom: calc(4.4rem + env(safe-area-inset-bottom)); }
    .container-fluid { padding-left: .75rem; padding-right: .75rem; }
    h4 { font-size: 1.15rem; }
    .fs-3 { font-size: 1.35rem !important; }

    /* Bottom tab bar */
    .ep-bottomnav {
        position: fixed; left: 0; right: 0; bottom: 0; z-index: 1080;
        display: flex; justify-content: space-around; align-items: stretch;
        border-top: 1px solid var(--bs-border-color);
        background: color-mix(in srgb, var(--bs-body-bg) 88%, transparent);
        backdrop-filter: saturate(1.4) blur(10px);
        padding-bottom: env(safe-area-inset-bottom);
    }
    .ep-bottomnav a {
        flex: 1; text-align: center; padding: .45rem 0 .35rem;
        font-size: .68rem; text-decoration: none; color: var(--bs-secondary-color);
        line-height: 1.15; transition: color .12s var(--ep-ease);
    }
    .ep-bottomnav a .ep-bn-ico { display: block; font-size: 1.25rem; line-height: 1.2; }
    .ep-bottomnav a.active { color: var(--bs-emphasis-color); font-weight: 600; }
    .ep-bottomnav a:active { color: var(--ep-accent); }

    /* Card-collapse tables: any table marked data-mobile="cards" */
    table[data-mobile="cards"] thead { display: none; }
    table[data-mobile="cards"] tbody tr {
        display: block; border: 1px solid var(--bs-border-color);
        border-radius: var(--ep-radius-sm); margin: .5rem; padding: .25rem .6rem;
        background: var(--ep-card-bg);
    }
    table[data-mobile="cards"] tbody td {
        display: flex; justify-content: space-between; gap: 1rem;
        border: 0; padding: .28rem 0; text-align: right !important;
    }
    table[data-mobile="cards"] tbody td::before {
        content: attr(data-th); font-weight: 600; color: var(--bs-secondary-color);
        text-align: left;
    }
    table[data-mobile="cards"] tbody td[data-th=""]::before { content: none; }
}
@media (min-width: 768px) { .ep-bottomnav { display: none; } }

/* Light-theme tweaks */
[data-bs-theme="light"] .navbar { background: rgba(255,255,255,.8) !important; }
[data-bs-theme="light"] .tier-active { background: rgba(25,135,84,.12); }
[data-bs-theme="light"] .tier-active-throttled { background: rgba(220,53,69,.12); }
