/* ══════════════════════════════════════════════════════
   Telemetry Monitor: shared design tokens & components

   A trimmed port of the solar dashboard's shared.css. Same tokens, same
   card system, same shell, so the two services read as one product. What
   was dropped: RBAC visibility gates (no roles here), vendor tags, nav
   sub-items and badges, donut primitives, print overrides.

   The rules in solar-dashboard/DESIGN.md apply in full. In particular:
   no new hues, no glow filters, no radius on tables/inputs/chips, no
   `transition: all`, no emoji as design elements.
   ══════════════════════════════════════════════════════ */

/* ── Design tokens ── */
:root {
    /* Primary */
    --color-primary: #133B6B;
    --color-primary-dark: #0f2d52;
    --color-primary-light: #1a5296;

    /* Accent */
    --color-accent: #46AC66;
    --color-accent-hover: #3d9659;
    --color-accent-subtle: rgba(70,172,102,0.15);

    /* Semantic */
    --color-success: #2e7d32;
    --color-warning: #e65100;
    --color-warning-bg: #fef4e5;
    --color-warning-border: #fcd9a8;
    --color-error: #dc2626;
    --color-error-bg: #f8d7da;
    --color-error-border: #f1aeb5;
    --color-info: #1565c0;

    /* Neutrals */
    --color-bg: #f0f2f5;
    --color-surface: #fff;
    --color-border: rgba(19,59,107,0.06);
    --color-border-strong: rgba(19,59,107,0.18);
    --color-text: #333;
    --color-text-primary: #133B6B;
    --color-text-secondary: #6b7280;
    --color-text-muted: #999;

    /* Sidebar-specific whites */
    --sidebar-text: rgba(255,255,255,0.85);
    --sidebar-text-dim: rgba(255,255,255,0.7);
    --sidebar-text-dimmer: rgba(255,255,255,0.45);
    --sidebar-text-faint: rgba(255,255,255,0.3);
    --sidebar-border: rgba(255,255,255,0.08);
    --sidebar-hover-bg: rgba(255,255,255,0.06);
    --sidebar-active-bg: rgba(255,255,255,0.1);

    /* Typography */
    --font-display: 'Chakra Petch', 'IBM Plex Sans', sans-serif;
    --font-family: 'IBM Plex Sans', -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", Arial, sans-serif;
    --font-mono: 'IBM Plex Mono', 'Courier New', monospace;
    --font-size-xs: 0.75rem;
    --font-size-sm: 0.875rem;
    --font-size-base: 1rem;
    --font-size-md: 1.25rem;
    --font-size-lg: 1.5rem;

    /* Spacing */
    --space-1: 4px;
    --space-2: 8px;
    --space-3: 12px;
    --space-4: 16px;
    --space-5: 20px;
    --space-6: 24px;
    --space-8: 32px;
    --space-10: 40px;
    --space-12: 48px;

    /* Shadows */
    --shadow-sm: 0 1px 4px rgba(19,59,107,0.06);
    --shadow-lg: 0 2px 6px rgba(0,0,0,0.08), 0 8px 24px rgba(0,0,0,0.06);

    /* Motion */
    --transition-fast: 0.15s ease;
    --transition-normal: 0.25s ease;

    /* Layout */
    --sidebar-width: 220px;
    --sidebar-width-collapsed: 56px;
    --header-z: 50;
    --sidebar-z: 100;

    /* Subtle status surfaces: alpha aliases of the semantic colours above */
    --color-warning-subtle: rgba(230,81,0,0.18);
    --color-error-subtle:   rgba(220,38,38,0.18);
    --color-info-subtle:    rgba(21,101,192,0.15);
    --color-primary-subtle: rgba(26,82,150,0.12);

    /* Card system tokens: Variant C "Modern Console" */
    --card-radius: 8px;
    --card-bg: linear-gradient(180deg, rgba(255,255,255,0.96), rgba(252,253,255,0.96));
    --card-shadow: 0 1px 2px rgba(19,59,107,0.05), 0 8px 32px -8px rgba(19,59,107,0.10);

    /* Page-level ambient tint: alpha variants of --color-accent and
       --color-primary-light, no new hues */
    --page-tint:
        radial-gradient(ellipse 800px 400px at 10% 0%, rgba(70,172,102,0.05), transparent 60%),
        radial-gradient(ellipse 600px 300px at 90% 100%, rgba(26,82,150,0.05), transparent 60%);
}

/* ── Base reset ── */
* { box-sizing: border-box; margin: 0; padding: 0; }
html {
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}
/* Bump the rem-based type scale up on desktop; phones keep the dense scale */
@media (min-width: 1024px) {
    html { font-size: 112.5%; }
}
body {
    font-family: var(--font-family);
    background: var(--color-bg);
    color: var(--color-text-primary);
    line-height: 1.6;
    background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.025'/%3E%3C/svg%3E");
}

h1, h2, h3,
.header-title,
.section-title,
.card-modern__title {
    text-wrap: balance;
    font-family: var(--font-display);
}
p, li,
.header-sub,
.empty-state,
.app-footer-label,
.app-footer-copy,
.card-modern__body,
.toast {
    text-wrap: pretty;
}

/* ── Scrollbar ── */
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--color-border-strong); border-radius: 3px; }

/* ── Focus ── */
:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }

/* ── Utilities ── */
.sr-only {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}

/* ── Animations ── */
@keyframes fadeSlideUp { from { opacity:0; transform:translateY(6px); } to { opacity:1; transform:translateY(0); } }
@keyframes spin { to { transform: rotate(360deg); } }
@keyframes slideInMsg {
    from { opacity: 0; transform: translateY(-4px); }
    to { opacity: 1; transform: translateY(0); }
}
@keyframes shimmer {
    from { background-position: -320px 0; }
    to   { background-position: 320px 0; }
}
.anim-entrance { opacity:0; animation: fadeSlideUp 0.3s ease-out forwards; }
.anim-delay-1 { animation-delay: 0s; }
.anim-delay-2 { animation-delay: 0.1s; }
.anim-delay-3 { animation-delay: 0.2s; }

@keyframes card-ripple {
    from { transform: translate(-50%, -50%) scale(0); opacity: 0.18; }
    to   { transform: translate(-50%, -50%) scale(2.4); opacity: 0; }
}

/* Cross-document view transition: quick root cross-fade between pages */
@view-transition { navigation: auto; }
::view-transition-old(root),
::view-transition-new(root) { animation-duration: 150ms; }

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }
    .card-rippleable::after { display: none !important; }
    .skeleton { animation: none !important; }
    @view-transition { navigation: none; }
}

/* ══════════════════════════════════════════════════════
   Card system: Variant C "Modern Console"
   ══════════════════════════════════════════════════════ */
body[data-modern-bg]::before {
    content: "";
    position: fixed;
    inset: 0;
    background: var(--page-tint);
    pointer-events: none;
    z-index: -1;
}

.card-modern {
    background: var(--card-bg);
    border-radius: var(--card-radius);
    box-shadow: var(--card-shadow);
    position: relative;
    /* Default accent (overridden by status modifiers below) */
    --mk-accent: var(--color-primary-light);
    --mk-accent-subtle: var(--color-primary-subtle);
}

.card-modern__header {
    padding: var(--space-4) var(--space-5);
    border-bottom: 1px solid var(--color-border);
    background: #f8f9fc;
    border-radius: var(--card-radius) var(--card-radius) 0 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    position: relative;
    z-index: 1;
}
/* A card title sits directly above controls set at 0.78rem, so at 0.95rem/600
   it read as another control rather than as the thing they act on. The step
   is what makes a stack of cards scannable. */
.card-modern__title {
    font-size: 1.0625rem;
    font-weight: 700;
    color: var(--color-primary);
    letter-spacing: -0.005em;
}
.card-modern__body {
    padding: var(--space-5);
    position: relative;
    z-index: 1;
}

/* Status modifiers: bind --mk-accent and --mk-accent-subtle to existing
   tokens. No new hues; every accent is already in the palette. */
.card-modern.is-online   { --mk-accent: var(--color-accent);        --mk-accent-subtle: var(--color-accent-subtle); }
.card-modern.is-warning  { --mk-accent: var(--color-warning);       --mk-accent-subtle: var(--color-warning-subtle); }
.card-modern.is-fault    { --mk-accent: var(--color-error);         --mk-accent-subtle: var(--color-error-subtle); }
.card-modern.is-info     { --mk-accent: var(--color-info);          --mk-accent-subtle: var(--color-info-subtle); }
.card-modern.is-neutral  { --mk-accent: var(--color-primary-light); --mk-accent-subtle: var(--color-primary-subtle); }

/* Hover ripple */
.card-rippleable { position: relative; overflow: hidden; }
.card-rippleable::after {
    content: "";
    position: absolute;
    top: 50%; left: 50%;
    width: 12px; height: 12px;
    border-radius: 50%;
    background: var(--mk-accent-subtle, rgba(70,172,102,0.35));
    transform: translate(-50%, -50%) scale(0);
    opacity: 0;
    pointer-events: none;
}
.card-rippleable:hover::after { animation: card-ripple 0.55s ease-out; }

/* Status pill: pulsing dot, current-colour aware */
/* Text only. It used to lead with a dot that breathed on a 2s loop, which
   claimed the eye continuously to say something that only changes once a
   minute. The pill's own colour already carries the state. */
.status-pill {
    display: inline-flex;
    align-items: center;
    padding: 3px 10px;
    background: var(--mk-accent-subtle);
    color: var(--mk-accent);
    font-family: var(--font-display);
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    border: 1px solid currentColor;
    white-space: nowrap;
}
.status-pill.is-online  { --mk-accent: var(--color-accent);        --mk-accent-subtle: var(--color-accent-subtle); }
.status-pill.is-warning { --mk-accent: var(--color-warning);       --mk-accent-subtle: var(--color-warning-subtle); }
.status-pill.is-fault   { --mk-accent: var(--color-error);         --mk-accent-subtle: var(--color-error-subtle); }
.status-pill.is-info    { --mk-accent: var(--color-info);          --mk-accent-subtle: var(--color-info-subtle); }
.status-pill.is-neutral { --mk-accent: var(--color-primary-light); --mk-accent-subtle: var(--color-primary-subtle); }
/* Card entrance: staggered fade-slide-up, gated on .mk-ready so the browser
   latches --mk-delay at animation start. */
.mk-enter { opacity: 0; }
.mk-enter.mk-ready {
    animation: fadeSlideUp 0.28s cubic-bezier(0.22, 1, 0.36, 1) forwards;
    animation-delay: var(--mk-delay, 0s);
}
/* Fallback: if Motion never runs, reveal at 1s rather than stay blank. */
@keyframes mk-fallback-reveal { to { opacity: 1; } }
.mk-enter:not(.mk-ready) {
    animation: mk-fallback-reveal 0.01s linear 1s forwards;
}
html.mk-skip-entrance .mk-enter,
html.mk-skip-entrance .anim-entrance {
    opacity: 1;
    animation: none;
}

/* ══════════════════════════════════════════════════════
   Layout
   ══════════════════════════════════════════════════════ */
.app-layout { display: flex; min-height: 100vh; }

/* ── Sidebar ── */
.sidebar {
    width: var(--sidebar-width); background: var(--color-primary-dark); color: var(--sidebar-text);
    flex-shrink: 0; display: flex; flex-direction: column;
    position: fixed; inset-block: 0; inset-inline-start: 0; z-index: var(--sidebar-z);
    overflow-y: auto; transition: width var(--transition-normal), transform 0.3s ease;
}
.sidebar.collapsed { width: var(--sidebar-width-collapsed); }

.sidebar-brand {
    padding: var(--space-4); display: flex; align-items: center; justify-content: center;
    border-bottom: 1px solid var(--sidebar-border); min-height: 64px; overflow: hidden;
}
.sidebar-brand a {
    display: grid;
    place-items: center;
    width: 160px;
    height: 44px;
    flex-shrink: 0;
}
.sidebar-brand-logo {
    grid-area: 1 / 1;
    width: 160px; height: 44px; object-fit: contain;
    opacity: 1;
    scale: 1;
    filter: blur(0);
    transition: opacity 0.3s cubic-bezier(0.2, 0, 0, 1),
                scale 0.3s cubic-bezier(0.2, 0, 0, 1),
                filter 0.3s cubic-bezier(0.2, 0, 0, 1);
}
/* Collapsed rail: the wide lockup would squash, swap to the square mark */
.sidebar-brand-logo-collapsed {
    grid-area: 1 / 1;
    display: block; width: 32px; height: 32px; object-fit: contain;
    opacity: 0;
    scale: 0.25;
    filter: brightness(0) invert(1) blur(4px);
    transition: opacity 0.3s cubic-bezier(0.2, 0, 0, 1),
                scale 0.3s cubic-bezier(0.2, 0, 0, 1),
                filter 0.3s cubic-bezier(0.2, 0, 0, 1);
}
.sidebar.collapsed .sidebar-brand-logo {
    opacity: 0;
    scale: 0.25;
    filter: blur(4px);
}
.sidebar.collapsed .sidebar-brand-logo-collapsed {
    opacity: 1;
    scale: 1;
    filter: brightness(0) invert(1) blur(0);
}

.sidebar-collapse-btn {
    display: flex; align-items: center; justify-content: center;
    padding: 10px 0; border: none; background: none;
    color: var(--sidebar-text-dimmer); cursor: pointer;
    transition: color var(--transition-fast), transform var(--transition-normal), scale var(--transition-fast);
    border-bottom: 1px solid rgba(255,255,255,0.06); width: 100%;
}
.sidebar-collapse-btn svg { width: 18px; height: 18px; }
.sidebar-collapse-btn:hover { color: #fff; }
.sidebar.collapsed .sidebar-collapse-btn { transform: rotate(180deg); }

.sidebar-nav { flex: 1; padding: var(--space-2) 0; }
.nav-section { margin-bottom: 2px; }

.nav-item {
    display: flex; align-items: center; gap: 10px; padding: 12px 18px; min-height: 44px;
    font-size: var(--font-size-sm); font-weight: 500; color: var(--sidebar-text-dim);
    cursor: pointer; transition: background-color 0.13s ease-out, color 0.13s ease-out, scale 0.13s ease-out; text-decoration: none;
    border: none; background: none; width: 100%; text-align: start;
    font-family: var(--font-display); letter-spacing: 0.015em; white-space: nowrap; overflow: hidden;
}
.nav-item:hover { background: var(--sidebar-hover-bg); color: #fff; }
.nav-item.active { background: var(--sidebar-active-bg); color: #fff; font-weight: 600; }
.nav-item.active:hover { background: rgba(255,255,255,0.12); }
.nav-item svg { width: 18px; height: 18px; flex-shrink: 0; opacity: 0.7; transition: opacity 0.13s ease-out; }
.nav-item:hover svg { opacity: 1; }
.nav-item.active svg { opacity: 1; }
.nav-item .nav-label { overflow: hidden; opacity: 1; transition: opacity 0.15s ease-out, transform 0.15s ease-out; }
.sidebar.collapsed .nav-item .nav-label { opacity: 0; transform: translateX(-4px); }

.sidebar-footer {
    padding: 14px 18px; border-top: 1px solid var(--sidebar-border);
    font-size: 0.68em; color: var(--sidebar-text-faint); text-align: center;
    white-space: nowrap; overflow: hidden; transition: opacity 0.2s;
}
.sidebar.collapsed .sidebar-footer { opacity: 0; }

/* Collapsed tooltips */
.sidebar.collapsed .nav-item { position: relative; }
.sidebar.collapsed .nav-item::after {
    content: attr(data-tooltip); position: absolute; inset-inline-start: var(--sidebar-width-collapsed); top: 50%;
    transform: translateY(-50%) translateX(4px); background: var(--color-text); color: #fff;
    padding: 4px 10px; border-radius: 6px; font-size: 0.78em; white-space: nowrap;
    z-index: 200; pointer-events: none; opacity: 0;
    transition: opacity 0.18s ease, transform 0.18s ease;
}
.sidebar.collapsed .nav-item:hover::after { opacity: 1; transform: translateY(-50%) translateX(0); }

/* Sidebar overlay (mobile) */
.sidebar-overlay {
    display: none; position: fixed; inset: 0;
    background: rgba(0,0,0,0.5); z-index: 99;
}

/* Hamburger (mobile) */
.hamburger-btn {
    display: none; background: none; border: none; color: #fff; cursor: pointer;
    padding: var(--space-1); border-radius: 6px; min-width: 40px; min-height: 40px;
    align-items: center; justify-content: center;
    transition: background-color var(--transition-fast), scale var(--transition-fast);
}
.hamburger-btn:hover { background: rgba(255,255,255,0.12); }
.hamburger-btn svg { width: 22px; height: 22px; }

/* ── Main content ── */
.main-content {
    flex: 1; min-width: 0; margin-inline-start: var(--sidebar-width); min-height: 100vh; padding: 0;
    transition: margin-inline-start var(--transition-normal);
}
.sidebar.collapsed ~ .sidebar-overlay ~ .main-content,
.sidebar.collapsed ~ .main-content { margin-inline-start: var(--sidebar-width-collapsed); }

/* ── Header ── */
.header {
    background: linear-gradient(135deg, #0a1f3d 0%, var(--color-primary) 40%, #1a5080 100%);
    color: #fff;
    padding: var(--space-5) var(--space-8);
    display: flex; align-items: center; justify-content: space-between;
    flex-wrap: wrap; gap: 12px;
    border-bottom: 1px solid var(--sidebar-border);
    position: sticky; top: 0; z-index: var(--header-z);
}
/* Faint circuit-line texture overlay */
.header::before {
    content: '';
    position: absolute; inset: 0;
    opacity: 0.04;
    background-image:
        linear-gradient(90deg, rgba(255,255,255,0.3) 1px, transparent 1px),
        linear-gradient(180deg, rgba(255,255,255,0.3) 1px, transparent 1px);
    background-size: 32px 32px;
    pointer-events: none;
}
/* Subtle radial glow behind the left area */
.header::after {
    content: '';
    position: absolute; top: -40%; left: -10%; width: 50%; height: 180%;
    background: radial-gradient(ellipse, rgba(70,172,102,0.08) 0%, transparent 70%);
    pointer-events: none;
}
.header-left { display: flex; align-items: center; gap: var(--space-3); position: relative; z-index: 1; }
/* Wordmark only. It used to lead with a battery glyph, which drew the eye to
   an icon that said the same thing the words beside it said. */
.header-title {
    color: #fff; font-size: var(--font-size-md); font-weight: 600;
    letter-spacing: 0.01em;
}
.header-sub { color: rgba(255,255,255,0.6); font-size: 0.85em; font-weight: 400; margin-top: 3px; font-family: var(--font-family); }
.header-right { display: flex; align-items: center; gap: var(--space-3); position: relative; z-index: 1; }
.header-meta { font-size: 0.78em; color: rgba(255,255,255,0.7); font-weight: 400; }

/* ── Refresh button ── */
.refresh-btn {
    background: rgba(255,255,255,0.15); color: #fff;
    border: 1px solid rgba(255,255,255,0.3);
    padding: 7px 18px; border-radius: 6px; cursor: pointer;
    font-size: 0.8em; font-family: var(--font-display);
    font-weight: 500; letter-spacing: 0.5px;
    transition: background-color 0.2s ease, border-color 0.2s ease, transform 0.2s ease, scale 0.15s ease-out;
    display: inline-flex; align-items: center; gap: 6px;
    min-height: 40px;
}
.refresh-btn:hover:not(:disabled) { background: var(--color-accent); border-color: var(--color-accent); transform: translateY(-1px); }
.refresh-btn:active:not(:disabled) { transform: translateY(0); scale: 0.96; }
.refresh-btn:disabled { opacity: 0.5; cursor: default; }
.refresh-btn svg { width: 14px; height: 14px; }
.refresh-btn.spinning svg { animation: spin 0.7s linear infinite; }

/* ── Page content area ── */
.page-content { padding: 36px var(--space-12); }

/* ── Section title ── */
.section-title {
    font-size: var(--font-size-sm); font-weight: 600; text-transform: uppercase;
    letter-spacing: 0.10em; color: var(--color-text-secondary);
    margin: var(--space-10) 0 var(--space-5);
    display: flex; align-items: center; gap: 10px;
}
.section-title svg { width: 18px; height: 18px; color: var(--color-accent); }

/* A row carrying controls that scope the section under it, optionally with a
   heading. The row owns the spacing, so a control sits in the heading's band
   rather than below its margin, and trails right with or without one. */
.section-row {
    display: flex; align-items: center;
    flex-wrap: wrap;
    gap: var(--space-3) var(--space-4);
    margin: var(--space-8) 0 var(--space-4);
}
.section-row .section-title { margin: 0; }
.section-row .field-control { margin-inline-start: auto; }

/* ── Labelled form control ── */
.field-control { display: inline-flex; align-items: center; gap: var(--space-2); }
.field-control > span {
    font-family: var(--font-display);
    font-size: 0.68rem; font-weight: 600;
    letter-spacing: 0.09em; text-transform: uppercase;
    color: var(--color-text-secondary);
}
.field-control select {
    min-height: 40px;
    padding: 7px 12px;
    border: 1px solid var(--color-border-strong);
    background: var(--color-surface);
    font-family: var(--font-family); font-size: 0.82em;
    color: var(--color-text-primary);
    cursor: pointer;
    transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}
.field-control select:focus {
    outline: none;
    border-color: var(--color-accent);
    box-shadow: 0 0 0 3px var(--color-accent-subtle);
}

/* ── Shared app footer ── */
.app-footer {
    margin: var(--space-8) 0 0;
    padding: 24px 28px;
    text-align: center;
    border-top: 1px solid var(--color-border);
    background: var(--color-surface);
    box-shadow: var(--shadow-sm);
}
.app-footer-label {
    margin: 0 0 6px;
    font-size: 0.9em;
    color: var(--color-text-secondary);
}
.app-footer-logo {
    display: inline-block;
    margin-bottom: 8px;
    transition: transform var(--transition-fast);
}
.app-footer-logo:hover { transform: scale(1.03); }
.app-footer-logo img {
    width: 183px;
    height: 25px;
    object-fit: contain;
    filter: brightness(0) saturate(100%) invert(16%) sepia(45%) saturate(1200%) hue-rotate(185deg) brightness(95%);
}
.app-footer-copy {
    margin: 0;
    font-size: 0.84em;
    color: var(--color-text-secondary);
}

/* ══════════════════════════════════════════════════════
   Buttons (soft pill)
   ══════════════════════════════════════════════════════ */
.btn {
    display: inline-flex; align-items: center; gap: 4px;
    font-family: var(--font-display); font-size: 0.78em; font-weight: 600;
    letter-spacing: 0.02em;
    padding: 8px 16px;
    border: 1px solid var(--color-border); background: var(--color-surface);
    color: var(--color-text-secondary); cursor: pointer;
    border-radius: 999px; box-shadow: 0 1px 2px rgba(19,59,107,0.06);
    transition: background-color var(--transition-fast), color var(--transition-fast), border-color var(--transition-fast), box-shadow var(--transition-fast), scale var(--transition-fast);
    min-height: 40px;
}
.btn svg { width: 14px; height: 14px; }
.btn:hover { background: #f8f9fc; color: var(--color-primary); box-shadow: 0 2px 6px rgba(19,59,107,0.10); }
.btn-primary { background: var(--color-primary); color: #fff; }
.btn-primary:hover { background: var(--color-primary-light); color: #fff; }
.btn:active:not(:disabled) { scale: 0.96; }
.btn:disabled { opacity: 0.4; cursor: default; scale: 1; }

.sidebar-collapse-btn:active,
.hamburger-btn:active,
.nav-item:active {
    scale: 0.96;
}

/* ══════════════════════════════════════════════════════
   Data table
   ══════════════════════════════════════════════════════ */
.data-table {
    width: 100%;
    border-collapse: collapse;
    background: var(--color-surface);
}
.data-table th {
    background: #f5f6f8;
    color: #666;
    padding: 10px 14px;
    text-align: start;
    font-weight: 600;
    font-size: 0.8125rem;
    letter-spacing: 0.2px;
    border-bottom: 1px solid #e0e0e0;
    white-space: nowrap;
    position: sticky;
    top: 0;
    z-index: 2;
}
.data-table td {
    padding: 10px 14px;
    border-bottom: 1px solid #f0f0f0;
    color: var(--color-text);
    font-size: var(--font-size-sm);
    text-align: start;
    white-space: nowrap;
}
.data-table th + th,
.data-table td + td { border-inline-start: 1px solid #e8e8e8; }
.data-table tbody tr { transition: background-color 0.1s ease-out; }
.data-table tbody tr:nth-child(even) { background: #fafbfc; }
.data-table tbody tr:hover { background: #eef5f0; }
.data-table tbody tr:last-child td { border-bottom: none; }
/* Capped so a sender that invents fields cannot push the page metres long.
   Sized to clear a typical schema without scrolling at all. */
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; max-height: 440px; overflow-y: auto; }

/* ══════════════════════════════════════════════════════
   Empty / loading / error states
   ══════════════════════════════════════════════════════ */
.empty-state {
    text-align: center;
    padding: 40px 20px;
    color: var(--color-text-muted);
}
.empty-state svg {
    width: 34px; height: 34px;
    color: var(--color-border-strong);
    margin-bottom: 10px;
}
.empty-state-text {
    font-size: 0.88em;
    font-weight: 500;
    color: var(--color-text-secondary);
}
.empty-state-hint {
    margin-top: 6px;
    font-size: 0.8em;
    color: var(--color-text-muted);
}

.skeleton {
    background: linear-gradient(90deg, #eef0f4 25%, #f6f8fa 50%, #eef0f4 75%);
    background-size: 640px 100%;
    animation: shimmer 1.4s linear infinite;
    color: transparent !important;
    border-radius: 3px;
}

.error-banner {
    display: none;
    align-items: center; gap: 10px;
    padding: var(--space-3) var(--space-4);
    margin-bottom: var(--space-5);
    font-size: 0.88em;
    background: var(--color-error-bg);
    color: #a81d1d;
    /* The fill and the border already say error. A third, heavier encoding
       down one edge only competes with the message it is framing. */
    border: 1px solid var(--color-error-border);
}
.error-banner.visible { display: flex; animation: slideInMsg 0.2s ease; }
.error-banner svg { width: 16px; height: 16px; flex-shrink: 0; }

/* ══════════════════════════════════════════════════════
   Toast notifications
   Requires <div class="toast-container" id="toast-container"> + /static/toast.js
   ══════════════════════════════════════════════════════ */
.toast-container {
    position: fixed;
    bottom: calc(24px + env(safe-area-inset-bottom));
    inset-inline-end: calc(24px + env(safe-area-inset-right));
    z-index: 9000;
    display: flex;
    flex-direction: column-reverse;
    gap: 8px;
    pointer-events: none;
}
.toast {
    pointer-events: auto;
    background: #1a1a2e;
    color: #fff;
    padding: 12px 20px;
    border-radius: 8px;
    font-family: var(--font-family);
    font-size: var(--font-size-sm);
    font-weight: 500;
    box-shadow: 0 4px 16px rgba(0,0,0,0.2);
    display: flex;
    align-items: center;
    gap: 10px;
    transform: translateX(120%);
    opacity: 0;
    transition: transform 0.35s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.35s ease;
    max-width: 340px;
}
.toast.visible { transform: translateX(0); opacity: 1; }
/* Exit is softer than enter: small fixed offset + fade, not a full slide-out */
.toast.toast-leaving { transform: translateX(16px); opacity: 0; }
.toast-icon { font-size: 1.1em; flex-shrink: 0; }
.toast-success { border-top: 3px solid var(--color-accent); }
.toast-error   { border-top: 3px solid var(--color-error); }
.toast-info    { border-top: 3px solid var(--color-warning); }

/* ══════════════════════════════════════════════════════
   Header user menu
   ══════════════════════════════════════════════════════ */
.user-menu { position: relative; z-index: 2; }
.user-menu-btn {
    display: inline-flex; align-items: center; gap: 8px;
    padding: 6px 12px;
    background: rgba(255,255,255,0.10);
    border: 1px solid rgba(255,255,255,0.18);
    border-radius: 999px;
    color: #fff; font-family: var(--font-family);
    font-size: 0.82em; font-weight: 600; cursor: pointer;
    min-height: 40px;
    transition: background-color var(--transition-fast);
}
.user-menu-btn:hover { background: rgba(255,255,255,0.18); }
.user-menu-btn svg { width: 14px; height: 14px; opacity: 0.85; }
.user-menu-name { max-width: 160px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.user-menu-dropdown {
    display: none; position: absolute; inset-inline-end: 0; top: calc(100% + 8px);
    min-width: 200px;
    background: #fff; color: var(--color-text);
    border: none;
    border-radius: 10px;
    box-shadow:
        0 0 0 1px oklch(0 0 0 / 0.06),
        var(--card-shadow),
        0 16px 40px -12px rgba(0,0,0,0.35);
    padding: 6px; z-index: 50;
}
.user-menu-dropdown.open { display: block; }
.user-menu-header {
    padding: 10px 12px; border-bottom: 1px solid var(--color-border);
    margin-bottom: 4px;
}
.user-menu-header .u-name { font-weight: 700; color: var(--color-text-primary); font-size: 0.92em; }
.user-menu-header .u-role { font-size: 0.72em; text-transform: uppercase; letter-spacing: 0.06em; color: var(--color-text-muted); margin-top: 2px; }
.user-menu-item {
    display: flex; align-items: center; gap: 10px;
    width: 100%; text-align: start;
    padding: 10px 12px; border: none; background: none;
    font-family: var(--font-family); font-size: 0.88em; color: var(--color-text);
    cursor: pointer; border-radius: calc(var(--card-radius) - 4px);
    text-decoration: none;
}
.user-menu-item:hover { background: #f1f5f9; }
.user-menu-item svg { width: 15px; height: 15px; opacity: 0.7; }

/* ══════════════════════════════════════════════════════
   Telemetry numerals: mono with tabular figures so values align and tick
   without jitter. Data accuracy is the product - let the numbers look it.
   ══════════════════════════════════════════════════════ */
.metric-value,
.reading-stamp,
.header-meta,
.data-table td.num {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum";
}

/* ══════════════════════════════════════════════════════
   Mobile responsive
   ══════════════════════════════════════════════════════ */
@media (max-width: 1024px) {
    .sidebar {
        transform: translateX(-100%);
        width: var(--sidebar-width) !important;
        visibility: hidden;
        transition: transform 0.3s ease-out, visibility 0s linear 0.3s;
    }
    [dir="rtl"] .sidebar {
        transform: translateX(100%);
    }
    .sidebar.open,
    [dir="rtl"] .sidebar.open {
        transform: translateX(0);
        visibility: visible;
        transition-delay: 0s;
    }
    .sidebar-overlay {
        display: block;
        visibility: hidden;
        opacity: 0;
        pointer-events: none;
        transition: opacity 0.3s ease-out, visibility 0s linear 0.3s;
    }
    .sidebar-overlay.visible {
        visibility: visible;
        opacity: 1;
        pointer-events: auto;
        transition-delay: 0s;
    }
    .sidebar.collapsed .sidebar-brand-logo {
        opacity: 1;
        scale: 1;
        filter: blur(0);
    }
    .sidebar.collapsed .sidebar-brand-logo-collapsed {
        opacity: 0;
        scale: 0.25;
        filter: brightness(0) invert(1) blur(4px);
    }
    .sidebar.collapsed .nav-item .nav-label { opacity: 1; transform: none; }
    .sidebar.collapsed .nav-item::after { content: none; }
    .sidebar.collapsed .sidebar-footer { opacity: 1; }
    .sidebar-collapse-btn { display: none; }
    .hamburger-btn { display: flex; }
    .main-content { margin-inline-start: 0 !important; }
}
@media (max-width: 768px) {
    .header { padding: var(--space-4) var(--space-5); }
    .page-content { padding: var(--space-6) var(--space-5); }
    .app-footer { margin: var(--space-6) 0 0; padding: 20px; }
    .header-right { flex-wrap: wrap; gap: var(--space-2); }
}
@media (max-width: 480px) {
    .page-content { padding: var(--space-4) var(--space-4); }
}
