/* ============================================================
 * style.css - 智能灌溉管理系统 全局样式
 * 主题：emerald / teal / cyan 渐变（农业/灌溉主题）
 * 设计参考：Next.js preview (login-view.tsx, dashboard-view.tsx)
 * 移动端优先，响应式布局
 * ============================================================ */

/* ---------- CSS Variables ---------- */
:root {
    /* 主色：emerald / teal / cyan */
    --emerald-50: #ecfdf5;
    --emerald-100: #d1fae5;
    --emerald-200: #a7f3d0;
    --emerald-300: #6ee7b7;
    --emerald-400: #34d399;
    --emerald-500: #10b981;
    --emerald-600: #059669;
    --emerald-700: #047857;
    --emerald-800: #065f46;
    --emerald-900: #064e3b;

    --teal-500: #14b8a6;
    --teal-600: #0d9488;
    --teal-700: #0f766e;

    --cyan-400: #22d3ee;
    --cyan-500: #06b6d4;
    --cyan-600: #0891b2;

    --sky-400: #38bdf8;
    --sky-500: #0ea5e9;
    --sky-600: #0284c7;

    --amber-400: #fbbf24;
    --amber-500: #f59e0b;
    --orange-500: #f97316;
    --orange-600: #ea580c;

    --red-500: #ef4444;
    --red-600: #dc2626;

    --slate-50: #f8fafc;
    --slate-100: #f1f5f9;
    --slate-200: #e2e8f0;
    --slate-300: #cbd5e1;
    --slate-400: #94a3b8;
    --slate-500: #64748b;
    --slate-600: #475569;
    --slate-700: #334155;
    --slate-800: #1e293b;
    --slate-900: #0f172a;

    --bg: #f6faf9;
    --bg-soft: #ecfdf5;
    --card: #ffffff;
    --text: #0f172a;
    --text-soft: #475569;
    --text-mute: #94a3b8;
    --border: #e2e8f0;
    --border-soft: #f1f5f9;

    --primary: #10b981;
    --primary-dark: #059669;
    --primary-light: #d1fae5;

    --gradient-primary: linear-gradient(135deg, #10b981 0%, #0d9488 100%);
    --gradient-primary-strong: linear-gradient(135deg, #059669 0%, #0f766e 100%);
    --gradient-bg: linear-gradient(135deg, #ecfdf5 0%, #f0fdfa 50%, #ecfeff 100%);

    --shadow-sm: 0 1px 2px rgba(15,23,42,0.04);
    --shadow: 0 4px 6px -1px rgba(15,23,42,0.06), 0 2px 4px -2px rgba(15,23,42,0.04);
    --shadow-md: 0 10px 15px -3px rgba(15,23,42,0.06), 0 4px 6px -4px rgba(15,23,42,0.05);
    --shadow-lg: 0 20px 25px -5px rgba(15,23,42,0.08), 0 8px 10px -6px rgba(15,23,42,0.06);
    --shadow-emerald: 0 10px 30px -10px rgba(16,185,129,0.35);

    --radius-sm: 8px;
    --radius: 12px;
    --radius-lg: 16px;
    --radius-xl: 20px;
    --radius-full: 9999px;

    --sidebar-w: 220px;
    --topbar-h: 60px;
}

/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
html, body {
    margin: 0; padding: 0;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
                 "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Arial, sans-serif;
    font-size: 14px;
    line-height: 1.5;
    color: var(--text);
    background: var(--bg);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}
body { min-height: 100vh; display: flex; flex-direction: column; }
a { color: var(--emerald-600); text-decoration: none; }
a:hover { color: var(--emerald-700); text-decoration: underline; }
button { font-family: inherit; cursor: pointer; border: none; background: none; }
input, select, textarea { font-family: inherit; font-size: inherit; }
img, svg { display: block; max-width: 100%; }
code, pre { font-family: "SFMono-Regular", Menlo, Monaco, Consolas, monospace; }
ul { margin: 0; padding-left: 1.2em; }

/* ============================================================
 * Topbar
 * ============================================================ */
.topbar {
    position: sticky; top: 0; z-index: 50;
    height: var(--topbar-h);
    background: rgba(255,255,255,0.85);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    border-bottom: 1px solid var(--border-soft);
}
.topbar-inner {
    max-width: 1400px;
    margin: 0 auto;
    height: 100%;
    padding: 0 16px;
    display: flex; align-items: center; justify-content: space-between;
    gap: 12px;
}
.topbar-left { display: flex; align-items: center; gap: 12px; }
.topbar-right { display: flex; align-items: center; gap: 8px; }

.sidebar-toggle {
    display: none;
    width: 36px; height: 36px;
    border-radius: var(--radius-sm);
    align-items: center; justify-content: center;
    color: var(--slate-600);
    background: transparent;
}
.sidebar-toggle:hover { background: var(--slate-100); }

.brand { display: flex; align-items: center; gap: 10px; color: var(--text); text-decoration: none; }
.brand:hover { text-decoration: none; }
.brand-logo {
    width: 36px; height: 36px;
    border-radius: var(--radius);
    background: var(--gradient-primary);
    color: #fff;
    display: flex; align-items: center; justify-content: center;
    box-shadow: var(--shadow-emerald);
}
.brand-title { font-size: 14px; font-weight: 700; line-height: 1.2; }
.brand-sub { font-size: 11px; color: var(--text-mute); }

.topbar-icon-btn {
    width: 36px; height: 36px;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: var(--radius-sm);
    color: var(--slate-600);
    background: transparent;
    transition: all .15s;
}
.topbar-icon-btn:hover { background: var(--slate-100); color: var(--emerald-600); text-decoration: none; }

.topbar-user {
    display: flex; align-items: center; gap: 8px;
    padding: 4px 10px;
    border-radius: var(--radius-sm);
    background: var(--slate-50);
}
.avatar {
    width: 28px; height: 28px;
    border-radius: 50%;
    background: var(--gradient-primary);
    color: #fff;
    display: flex; align-items: center; justify-content: center;
    font-size: 12px; font-weight: 600;
}
.topbar-user-name { font-size: 13px; font-weight: 600; line-height: 1.2; }
.topbar-user-meta { font-size: 11px; color: var(--text-mute); }

/* ============================================================
 * Layout (Sidebar + Main)
 * ============================================================ */
.layout {
    flex: 1;
    display: flex;
    align-items: stretch;
    min-height: 0;
}

.sidebar {
    width: var(--sidebar-w);
    background: rgba(255,255,255,0.6);
    backdrop-filter: blur(10px);
    border-right: 1px solid var(--border-soft);
    padding: 16px 12px;
    display: flex; flex-direction: column;
    gap: 4px;
    position: sticky; top: var(--topbar-h);
    height: calc(100vh - var(--topbar-h));
    overflow-y: auto;
}
.side-nav { display: flex; flex-direction: column; gap: 4px; }
.side-nav-item {
    display: flex; align-items: center; gap: 10px;
    padding: 10px 12px;
    border-radius: var(--radius-sm);
    color: var(--text-soft);
    font-size: 14px; font-weight: 500;
    text-decoration: none;
    transition: all .15s;
}
.side-nav-item:hover {
    background: var(--slate-100);
    color: var(--text);
    text-decoration: none;
}
.side-nav-item.active {
    background: var(--gradient-primary);
    color: #fff;
    box-shadow: var(--shadow-emerald);
}
.side-nav-item svg { flex-shrink: 0; }

.side-status {
    margin-top: auto;
    padding: 12px;
    border-radius: var(--radius);
    background: var(--emerald-50);
    border: 1px solid var(--emerald-100);
}
.side-status-row {
    display: flex; align-items: center; gap: 6px;
    font-size: 12px;
    color: var(--emerald-700);
    font-weight: 600;
}
.side-status-sub { font-size: 11px; color: var(--text-mute); margin-top: 2px; }

.sidebar-backdrop {
    display: none;
    position: fixed; inset: 0;
    background: rgba(0,0,0,0.4);
    z-index: 49;
}

.main-content {
    flex: 1;
    min-width: 0;
    padding: 24px;
}
.main-content > * { max-width: 1200px; margin-left: auto; margin-right: auto; }

/* ============================================================
 * Footer
 * ============================================================ */
.footer {
    padding: 16px;
    text-align: center;
    font-size: 12px;
    color: var(--text-mute);
    border-top: 1px solid var(--border-soft);
    background: rgba(255,255,255,0.5);
    margin-top: auto;
}
.footer a { color: var(--emerald-600); }

/* ============================================================
 * Buttons
 * ============================================================ */
.btn {
    display: inline-flex; align-items: center; justify-content: center;
    gap: 6px;
    padding: 8px 14px;
    border-radius: var(--radius-sm);
    font-size: 14px; font-weight: 600;
    line-height: 1.2;
    border: 1px solid transparent;
    cursor: pointer;
    transition: all .15s;
    text-decoration: none;
    white-space: nowrap;
}
.btn:hover { text-decoration: none; }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }
.btn-sm { padding: 6px 10px; font-size: 13px; }
.btn-lg { padding: 12px 20px; font-size: 15px; }
.btn-block { display: flex; width: 100%; }

.btn-primary {
    background: var(--gradient-primary);
    color: #fff;
    box-shadow: 0 4px 14px -4px rgba(16,185,129,0.5);
}
.btn-primary:hover { background: var(--gradient-primary-strong); color: #fff; transform: translateY(-1px); box-shadow: 0 6px 20px -6px rgba(16,185,129,0.6); }

.btn-ghost {
    background: transparent;
    color: var(--text-soft);
    border-color: var(--border);
}
.btn-ghost:hover { background: var(--slate-100); color: var(--text); }

.btn-danger-ghost {
    background: transparent;
    color: var(--red-600);
    border-color: var(--red-500);
}
.btn-danger-ghost:hover { background: var(--red-500); color: #fff; }

.btn-email {
    background: linear-gradient(135deg, #fbbf24 0%, #f97316 100%);
    color: #fff;
    box-shadow: 0 4px 14px -4px rgba(249,115,22,0.4);
}
.btn-email:hover { background: linear-gradient(135deg, #f59e0b 0%, #ea580c 100%); color: #fff; }

.btn-wechat {
    background: linear-gradient(135deg, #22c55e 0%, #10b981 100%);
    color: #fff;
}
.btn-wechat:hover { color: #fff; filter: brightness(0.95); }

.btn-alipay {
    background: linear-gradient(135deg, #1677ff 0%, #0958d9 100%);
    color: #fff;
}
.btn-alipay:hover { color: #fff; filter: brightness(0.95); }

/* Relay control buttons */
.btn-relay-on {
    background: var(--emerald-500);
    color: #fff;
    padding: 10px 20px;
}
.btn-relay-on:hover { background: var(--emerald-600); color: #fff; }
.btn-relay-on.active { background: var(--emerald-700); box-shadow: inset 0 2px 4px rgba(0,0,0,0.2); }

.btn-relay-off {
    background: var(--slate-200);
    color: var(--slate-700);
    padding: 10px 20px;
}
.btn-relay-off:hover { background: var(--slate-300); }
.btn-relay-off.active { background: var(--slate-800); color: #fff; box-shadow: inset 0 2px 4px rgba(0,0,0,0.2); }

/* ============================================================
 * Cards
 * ============================================================ */
.card {
    background: var(--card);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    border: 1px solid var(--border-soft);
    margin-bottom: 20px;
    overflow: hidden;
}
.card-head {
    padding: 16px 20px;
    display: flex; align-items: center; justify-content: space-between;
    border-bottom: 1px solid var(--border-soft);
    gap: 12px;
}
.card-title { margin: 0; font-size: 15px; font-weight: 700; }
.card-sub { margin: 2px 0 0; font-size: 12px; color: var(--text-mute); }
.card-body { padding: 20px; }
.card-tag {
    font-size: 12px;
    padding: 3px 10px;
    border-radius: var(--radius-full);
    font-weight: 600;
}
.tag-on { background: var(--emerald-100); color: var(--emerald-700); }
.tag-off { background: var(--slate-100); color: var(--slate-600); }
.card-danger { border-color: rgba(239,68,68,0.2); }

/* ============================================================
 * Page Header
 * ============================================================ */
.page-head {
    display: flex; align-items: flex-start; justify-content: space-between;
    gap: 16px; flex-wrap: wrap;
    margin-bottom: 24px;
}
.page-title {
    margin: 0;
    font-size: 24px; font-weight: 800;
    letter-spacing: -0.02em;
    display: flex; align-items: center; gap: 12px;
    flex-wrap: wrap;
}
.page-desc { margin: 6px 0 0; font-size: 13px; color: var(--text-mute); }
.back-link {
    display: inline-flex; align-items: center; gap: 4px;
    font-size: 13px;
    color: var(--text-mute);
    margin-bottom: 8px;
}
.back-link:hover { color: var(--emerald-600); text-decoration: none; }

/* ============================================================
 * Stats Grid (Dashboard)
 * ============================================================ */
.stats-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 14px;
    margin-bottom: 20px;
}
.stat-card {
    background: var(--card);
    border-radius: var(--radius-lg);
    padding: 18px;
    box-shadow: var(--shadow-sm);
    border: 1px solid var(--border-soft);
    display: flex; align-items: flex-start; justify-content: space-between;
    gap: 12px;
}
.stat-label { font-size: 12px; color: var(--text-mute); margin-bottom: 4px; }
.stat-value { font-size: 24px; font-weight: 800; letter-spacing: -0.02em; }
.stat-icon {
    width: 40px; height: 40px;
    border-radius: var(--radius);
    color: #fff;
    display: flex; align-items: center; justify-content: center;
    flex-shrink: 0;
}
.stat-icon-emerald { background: linear-gradient(135deg, #10b981, #0d9488); }
.stat-icon-sky     { background: linear-gradient(135deg, #38bdf8, #0284c7); }
.stat-icon-amber   { background: linear-gradient(135deg, #fbbf24, #ea580c); }
.stat-icon-cyan    { background: linear-gradient(135deg, #22d3ee, #06b6d4); }

/* ============================================================
 * Device Rows (Dashboard list)
 * ============================================================ */
.device-rows { display: flex; flex-direction: column; gap: 8px; }
.device-row {
    display: flex; align-items: center; gap: 14px;
    padding: 12px;
    border-radius: var(--radius);
    border: 1px solid var(--border-soft);
    color: var(--text);
    text-decoration: none;
    transition: all .15s;
}
.device-row:hover {
    background: var(--slate-50);
    border-color: var(--border);
    text-decoration: none;
}
.device-row-icon {
    width: 40px; height: 40px;
    border-radius: var(--radius-sm);
    display: flex; align-items: center; justify-content: center;
    flex-shrink: 0;
}
.device-row-icon.online { background: var(--emerald-100); color: var(--emerald-600); }
.device-row-icon.offline { background: var(--slate-100); color: var(--slate-400); }
.device-row-info { flex: 1; min-width: 0; }
.device-row-name { font-size: 14px; font-weight: 600; display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.device-row-meta { font-size: 12px; color: var(--text-mute); margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.device-row-stats { display: flex; gap: 18px; }
.mini-stat { text-align: center; }
.mini-stat-label { font-size: 11px; color: var(--text-mute); }
.mini-stat-value { font-size: 13px; font-weight: 700; }
.device-row-arrow { color: var(--text-mute); flex-shrink: 0; }

/* ============================================================
 * Badges & Dots
 * ============================================================ */
.badge {
    display: inline-flex; align-items: center;
    padding: 2px 8px;
    border-radius: var(--radius-full);
    font-size: 11px; font-weight: 600;
}
.badge-irrigating { background: #fee2e2; color: #b91c1c; }
.badge-alert { background: #fef3c7; color: #b45309; }
.badge-provider { background: var(--emerald-100); color: var(--emerald-700); }
.dot { display: inline-block; width: 6px; height: 6px; border-radius: 50%; vertical-align: middle; }
.dot-green { background: var(--emerald-500); }
.dot-blue { background: var(--cyan-500); }
.dot-red { background: var(--red-500); animation: pulse 1.5s ease-in-out infinite; }
.dot-gray { background: var(--slate-400); }
@keyframes pulse {
    0%, 100% { opacity: 1; transform: scale(1); }
    50% { opacity: 0.6; transform: scale(1.2); }
}

/* ============================================================
 * Empty State
 * ============================================================ */
.empty-state {
    text-align: center;
    padding: 40px 20px;
}
.empty-icon {
    width: 80px; height: 80px;
    margin: 0 auto 16px;
    border-radius: 50%;
    background: var(--emerald-50);
    color: var(--emerald-400);
    display: flex; align-items: center; justify-content: center;
}
.empty-state h3 { margin: 0 0 8px; font-size: 18px; }
.empty-state p { margin: 0 0 16px; color: var(--text-mute); font-size: 13px; }

/* ============================================================
 * Device Grid (devices.php)
 * ============================================================ */
.device-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 16px;
}
.device-card {
    background: var(--card);
    border-radius: var(--radius-lg);
    padding: 16px;
    border: 1px solid var(--border-soft);
    box-shadow: var(--shadow-sm);
    color: var(--text);
    text-decoration: none;
    transition: all .2s;
    display: flex; flex-direction: column; gap: 12px;
}
.device-card:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-md);
    border-color: var(--emerald-200);
    text-decoration: none;
}
.device-card-head { display: flex; align-items: center; gap: 10px; }
.device-card-icon {
    width: 40px; height: 40px;
    border-radius: var(--radius);
    display: flex; align-items: center; justify-content: center;
    flex-shrink: 0;
}
.device-card-icon.online { background: var(--emerald-100); color: var(--emerald-600); }
.device-card-icon.offline { background: var(--slate-100); color: var(--slate-400); }
.device-card-name { flex: 1; font-weight: 700; font-size: 15px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.device-card-status {
    font-size: 11px; font-weight: 600;
    padding: 2px 8px; border-radius: var(--radius-full);
}
.device-card-status.online { background: var(--emerald-100); color: var(--emerald-700); }
.device-card-status.offline { background: var(--slate-100); color: var(--slate-500); }
.device-card-loc {
    font-size: 12px; color: var(--text-mute);
    display: flex; align-items: center; gap: 4px;
}
.device-card-metrics {
    display: grid; grid-template-columns: repeat(2, 1fr);
    gap: 10px;
    padding: 10px 0;
    border-top: 1px solid var(--border-soft);
    border-bottom: 1px solid var(--border-soft);
}
.metric { }
.metric-label { font-size: 11px; color: var(--text-mute); }
.metric-value { font-size: 16px; font-weight: 700; margin-top: 2px; }
.metric-warn { color: var(--orange-600); }
.device-card-foot {
    display: flex; justify-content: space-between;
    font-size: 12px; color: var(--text-mute);
    align-items: center;
}

/* ============================================================
 * Device Detail
 * ============================================================ */
.device-status-pill {
    display: inline-flex; align-items: center; gap: 6px;
    font-size: 12px; font-weight: 600;
    padding: 4px 12px;
    border-radius: var(--radius-full);
}
.device-status-pill.online { background: var(--emerald-100); color: var(--emerald-700); }
.device-status-pill.offline { background: var(--slate-100); color: var(--slate-500); }

.page-head-actions { display: flex; gap: 8px; align-items: center; }

/* Sensor Grid */
.sensor-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 14px;
    margin-bottom: 20px;
}
.sensor-card {
    background: var(--card);
    border-radius: var(--radius-lg);
    padding: 18px;
    border: 1px solid var(--border-soft);
    box-shadow: var(--shadow-sm);
    position: relative;
    overflow: hidden;
}
.sensor-card::before {
    content: '';
    position: absolute; top: 0; left: 0; right: 0; height: 3px;
}
.sensor-soil::before { background: linear-gradient(90deg, #10b981, #0d9488); }
.sensor-temp::before { background: linear-gradient(90deg, #f59e0b, #ef4444); }
.sensor-hum::before  { background: linear-gradient(90deg, #06b6d4, #0891b2); }
.sensor-rain::before { background: linear-gradient(90deg, #3b82f6, #6366f1); }

.sensor-card-icon {
    width: 40px; height: 40px;
    border-radius: var(--radius);
    display: flex; align-items: center; justify-content: center;
    margin-bottom: 12px;
    color: #fff;
}
.sensor-soil .sensor-card-icon { background: linear-gradient(135deg, #10b981, #0d9488); }
.sensor-temp .sensor-card-icon { background: linear-gradient(135deg, #f59e0b, #ef4444); }
.sensor-hum .sensor-card-icon  { background: linear-gradient(135deg, #06b6d4, #0891b2); }
.sensor-rain .sensor-card-icon { background: linear-gradient(135deg, #3b82f6, #6366f1); }

.sensor-card-label { font-size: 12px; color: var(--text-mute); }
.sensor-card-value { font-size: 28px; font-weight: 800; margin: 4px 0; letter-spacing: -0.02em; }
.sensor-card-value .unit { font-size: 14px; font-weight: 500; color: var(--text-mute); margin-left: 4px; }
.sensor-card-foot { font-size: 11px; color: var(--text-mute); display: flex; align-items: center; gap: 4px; }

.sensor-card-bar { margin-top: 10px; }
.bar-track {
    position: relative;
    height: 6px;
    background: var(--slate-100);
    border-radius: 3px;
    overflow: visible;
}
.bar-fill {
    height: 100%;
    border-radius: 3px;
    transition: width .4s ease;
}
.bar-soil { background: linear-gradient(90deg, #ef4444, #f59e0b, #10b981); }
.bar-threshold {
    position: absolute;
    top: -3px;
    width: 2px;
    height: 12px;
    background: var(--slate-700);
    border-radius: 1px;
}

/* Relay Control */
.relay-control-body { display: flex; flex-direction: column; gap: 16px; }
.relay-status {
    display: flex; align-items: center; gap: 14px;
    padding: 16px;
    border-radius: var(--radius);
    background: var(--slate-50);
    border: 1px solid var(--border-soft);
}
.relay-status.is-on { background: var(--emerald-50); border-color: var(--emerald-200); }
.relay-light {
    width: 16px; height: 16px;
    border-radius: 50%;
    background: var(--slate-300);
    flex-shrink: 0;
    box-shadow: inset 0 1px 2px rgba(0,0,0,0.1);
}
.relay-status.is-on .relay-light {
    background: var(--emerald-500);
    box-shadow: 0 0 0 4px rgba(16,185,129,0.2), 0 0 12px var(--emerald-400);
    animation: pulse-green 1.5s ease-in-out infinite;
}
@keyframes pulse-green {
    0%, 100% { box-shadow: 0 0 0 4px rgba(16,185,129,0.2), 0 0 12px var(--emerald-400); }
    50%      { box-shadow: 0 0 0 8px rgba(16,185,129,0.1), 0 0 20px var(--emerald-400); }
}
.relay-title { font-weight: 700; font-size: 15px; }
.relay-sub { font-size: 12px; color: var(--text-mute); margin-top: 2px; }
.relay-buttons { display: flex; gap: 8px; flex-wrap: wrap; }

/* Settings Rows */
.setting-row {
    display: flex; justify-content: space-between; align-items: center;
    gap: 16px;
    padding: 12px 0;
}
.setting-title { font-weight: 600; font-size: 14px; }
.setting-desc { font-size: 12px; color: var(--text-mute); margin-top: 2px; }
.setting-divider { height: 1px; background: var(--border-soft); margin: 4px 0; }
.setting-control { display: flex; align-items: center; gap: 12px; min-width: 220px; }

/* Switch */
.switch {
    position: relative; display: inline-block;
    width: 44px; height: 24px;
}
.switch input { opacity: 0; width: 0; height: 0; }
.switch-slider {
    position: absolute; inset: 0;
    background: var(--slate-300);
    border-radius: var(--radius-full);
    transition: .2s;
    cursor: pointer;
}
.switch-slider::before {
    content: '';
    position: absolute;
    width: 18px; height: 18px;
    left: 3px; top: 3px;
    background: #fff;
    border-radius: 50%;
    transition: .2s;
    box-shadow: 0 2px 4px rgba(0,0,0,0.2);
}
.switch input:checked + .switch-slider {
    background: var(--gradient-primary);
}
.switch input:checked + .switch-slider::before { transform: translateX(20px); }

/* Range Slider */
input[type="range"] {
    -webkit-appearance: none; appearance: none;
    width: 140px;
    height: 6px;
    background: var(--slate-200);
    border-radius: 3px;
    outline: none;
}
input[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none; appearance: none;
    width: 18px; height: 18px;
    border-radius: 50%;
    background: var(--emerald-500);
    cursor: pointer;
    box-shadow: 0 2px 6px rgba(16,185,129,0.5);
    border: 2px solid #fff;
}
input[type="range"]::-moz-range-thumb {
    width: 18px; height: 18px;
    border-radius: 50%;
    background: var(--emerald-500);
    cursor: pointer;
    border: 2px solid #fff;
}
.range-value { font-size: 13px; font-weight: 700; min-width: 42px; color: var(--emerald-700); }

/* Info Grid */
.info-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 16px;
}
.info-item { }
.info-label { font-size: 11px; color: var(--text-mute); margin-bottom: 4px; }
.info-value { font-size: 14px; font-weight: 500; word-break: break-all; }
.info-value code { background: var(--slate-100); padding: 2px 6px; border-radius: 4px; font-size: 12px; }
.pairing-code { background: var(--emerald-100) !important; color: var(--emerald-700) !important; font-weight: 700; }

.device-danger-zone {
    display: flex; gap: 8px; justify-content: flex-end;
    margin-top: 16px;
    padding-top: 16px;
    border-top: 1px solid var(--border-soft);
}

/* Charts */
.chart-tabs { display: flex; gap: 4px; background: var(--slate-100); padding: 3px; border-radius: var(--radius-sm); }
.chart-tab {
    padding: 6px 12px;
    font-size: 12px; font-weight: 600;
    border-radius: 6px;
    color: var(--text-soft);
    transition: all .15s;
}
.chart-tab.active { background: #fff; color: var(--emerald-600); box-shadow: var(--shadow-sm); }
.chart-container { position: relative; height: 320px; }
.chart-meta { font-size: 12px; color: var(--text-mute); text-align: center; margin-top: 12px; }

/* ============================================================
 * Login Page
 * ============================================================ */
.login-page {
    background: linear-gradient(135deg, #ecfdf5 0%, #f0fdfa 50%, #ecfeff 100%);
    overflow-x: hidden;
    position: relative;
}
.login-bg {
    position: fixed; inset: 0; pointer-events: none; z-index: 0; overflow: hidden;
}
.blob {
    position: absolute;
    border-radius: 50%;
    filter: blur(80px);
    opacity: 0.5;
}
.blob-1 { width: 400px; height: 400px; top: -100px; right: -100px; background: var(--emerald-300); }
.blob-2 { width: 400px; height: 400px; bottom: -100px; left: -100px; background: var(--teal-300); }
.blob-3 { width: 300px; height: 300px; top: 40%; left: 30%; background: var(--cyan-300); opacity: 0.3; }

.login-wrap {
    position: relative; z-index: 1;
    flex: 1;
    display: flex; align-items: center; justify-content: center;
    gap: 60px;
    padding: 24px;
    max-width: 1100px;
    margin: 0 auto;
    width: 100%;
}

/* Hero */
.login-hero {
    max-width: 460px;
    text-align: left;
    display: none;
}
.hero-badge {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 6px 12px;
    border-radius: var(--radius-full);
    background: var(--emerald-100);
    color: var(--emerald-700);
    font-size: 12px; font-weight: 600;
    margin-bottom: 20px;
}
.hero-title {
    font-size: 42px;
    font-weight: 800;
    letter-spacing: -0.025em;
    line-height: 1.1;
    margin: 0 0 16px;
    background: linear-gradient(135deg, #059669, #0d9488, #06b6d4);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
}
.hero-desc {
    font-size: 16px;
    color: var(--text-soft);
    line-height: 1.6;
    margin: 0 0 24px;
}
.hero-features {
    display: grid; grid-template-columns: repeat(3, 1fr);
    gap: 12px;
    max-width: 400px;
}
.hero-feature {
    text-align: center;
    padding: 12px 8px;
    border-radius: var(--radius);
    background: rgba(255,255,255,0.7);
    backdrop-filter: blur(10px);
    border: 1px solid rgba(255,255,255,0.6);
    color: var(--emerald-600);
}
.hero-feature-label { font-size: 11px; color: var(--text-mute); margin-top: 4px; }
.hero-feature-value { font-size: 13px; font-weight: 700; margin-top: 2px; color: var(--text); }

/* Login Card */
.login-card-wrap {
    width: 100%;
    max-width: 420px;
}
.login-card {
    background: rgba(255,255,255,0.85);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    border-radius: var(--radius-xl);
    box-shadow: var(--shadow-lg), 0 0 60px -10px rgba(16,185,129,0.15);
    border: 1px solid rgba(255,255,255,0.6);
    padding: 28px;
    min-height: 460px;
    display: flex; align-items: center; justify-content: center;
}
.login-step { display: none; width: 100%; }
.login-step[style*="display:block"], .login-step.active { display: block; }

.login-card-head { text-align: center; margin-bottom: 24px; }
.login-logo {
    width: 56px; height: 56px;
    margin: 0 auto 12px;
    border-radius: var(--radius-lg);
    background: var(--gradient-primary);
    color: #fff;
    display: flex; align-items: center; justify-content: center;
    box-shadow: var(--shadow-emerald);
}
.login-logo-qq { background: linear-gradient(135deg, #38bdf8, #0284c7); box-shadow: 0 10px 30px -10px rgba(56,189,248,0.5); }
.login-logo-email { background: linear-gradient(135deg, #fbbf24, #f97316); box-shadow: 0 10px 30px -10px rgba(249,115,22,0.5); }
.login-logo-wechat { background: linear-gradient(135deg, #22c55e, #10b981); }
.login-logo-alipay { background: linear-gradient(135deg, #1677ff, #0958d9); }
.login-card-head h2 { margin: 0 0 4px; font-size: 22px; font-weight: 800; }
.login-card-head p { margin: 0; font-size: 13px; color: var(--text-mute); }

/* Auth Methods */
.auth-methods { display: flex; flex-direction: column; gap: 10px; }
.auth-method {
    display: flex; align-items: center; gap: 14px;
    padding: 12px;
    border-radius: var(--radius);
    border: 1px solid var(--border);
    background: #fff;
    text-align: left;
    cursor: pointer;
    transition: all .15s;
    width: 100%;
}
.auth-method:hover {
    border-color: var(--emerald-300);
    box-shadow: var(--shadow);
    transform: translateY(-1px);
}
.auth-icon {
    width: 44px; height: 44px;
    border-radius: var(--radius);
    color: #fff;
    display: flex; align-items: center; justify-content: center;
    flex-shrink: 0;
}
.auth-icon-qq { background: linear-gradient(135deg, #38bdf8, #0284c7); }
.auth-icon-alipay { background: linear-gradient(135deg, #1677ff, #0958d9); }
.auth-icon-wechat { background: linear-gradient(135deg, #22c55e, #10b981); }
.auth-icon-email { background: linear-gradient(135deg, #fbbf24, #f97316); }
.auth-text { flex: 1; min-width: 0; }
.auth-name { font-size: 14px; font-weight: 600; }
.auth-desc { font-size: 12px; color: var(--text-mute); margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.auth-arrow { color: var(--text-mute); flex-shrink: 0; transition: transform .15s; }
.auth-method:hover .auth-arrow { transform: translateX(2px); color: var(--emerald-500); }

.login-foot {
    display: flex; align-items: center; justify-content: center; gap: 4px;
    font-size: 11px; color: var(--text-mute);
    margin-top: 18px;
    flex-wrap: wrap;
}
.login-foot a { color: var(--emerald-600); }

/* Form */
.login-form { display: flex; flex-direction: column; gap: 14px; }
.form-group { display: flex; flex-direction: column; gap: 6px; }
.form-group label { font-size: 13px; font-weight: 600; color: var(--text-soft); }
.form-group input {
    width: 100%;
    padding: 10px 12px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border);
    background: #fff;
    color: var(--text);
    transition: all .15s;
}
.form-group input:focus {
    outline: none;
    border-color: var(--emerald-500);
    box-shadow: 0 0 0 3px rgba(16,185,129,0.1);
}
.form-hint { font-size: 11px; color: var(--text-mute); text-align: center; margin-top: 12px; }

.back-btn {
    display: inline-flex; align-items: center; gap: 4px;
    font-size: 13px;
    color: var(--text-mute);
    margin-bottom: 16px;
    background: transparent;
    padding: 4px 8px;
    border-radius: var(--radius-sm);
}
.back-btn:hover { background: var(--slate-100); color: var(--text); }

/* QQ Redirect Info */
.qq-redirect-info { padding: 16px 0; }
.qq-redirect-loading {
    display: flex; align-items: center; justify-content: center; gap: 8px;
    color: var(--sky-600);
    font-size: 12px;
    margin-bottom: 16px;
}
.qq-callback-box {
    padding: 12px;
    border-radius: var(--radius);
    background: var(--sky-50);
    border: 1px solid var(--sky-100);
    font-size: 12px;
}
.qq-callback-label {
    font-family: monospace;
    color: var(--sky-700);
    margin-bottom: 4px;
    font-weight: 700;
}
.qq-callback-url { color: var(--text-soft); word-break: break-all; }

/* QR */
.qr-area { display: flex; flex-direction: column; align-items: center; gap: 10px; padding: 12px 0; }
.qr-box {
    position: relative;
    width: 192px; height: 192px;
    border-radius: var(--radius-lg);
    background: #fff;
    padding: 12px;
    box-shadow: var(--shadow);
    border: 2px solid var(--emerald-100);
}
.qr-pattern {
    width: 100%; height: 100%;
    display: grid; grid-template-columns: repeat(12, 1fr); grid-template-rows: repeat(12, 1fr);
    gap: 1px;
}
.qr-cell { background: #fff; border-radius: 1px; }
.qr-cell.on { background: var(--slate-900); }
.qr-center {
    position: absolute;
    top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    width: 48px; height: 48px;
    border-radius: var(--radius);
    background: #fff;
    display: flex; align-items: center; justify-content: center;
    box-shadow: var(--shadow);
}
.qr-title { font-size: 14px; font-weight: 600; }
.qr-sub { font-size: 12px; color: var(--text-mute); }
.qr-sub code { background: var(--emerald-100); color: var(--emerald-700); padding: 2px 6px; border-radius: 4px; font-weight: 700; }
.qr-tip {
    display: flex; align-items: center; gap: 6px;
    font-size: 11px;
    color: #b45309;
    background: #fef3c7;
    padding: 6px 10px;
    border-radius: var(--radius-sm);
}

/* Spinner */
.spinner {
    display: inline-block;
    width: 14px; height: 14px;
    border: 2px solid currentColor;
    border-top-color: transparent;
    border-radius: 50%;
    animation: spin .8s linear infinite;
}
.spinner-lg { width: 36px; height: 36px; border-width: 3px; }
.spinner-emerald { color: var(--emerald-500); }
@keyframes spin { to { transform: rotate(360deg); } }

.loading-area, .success-area {
    padding: 60px 20px;
    text-align: center;
    display: flex; flex-direction: column; align-items: center; gap: 12px;
}
.loading-text, .success-title { font-size: 14px; font-weight: 600; color: var(--text-soft); }
.success-text { font-size: 12px; color: var(--text-mute); }
.success-circle {
    width: 64px; height: 64px;
    border-radius: 50%;
    background: var(--emerald-100);
    color: var(--emerald-600);
    display: flex; align-items: center; justify-content: center;
    animation: pop .4s ease-out;
}
@keyframes pop {
    0% { transform: scale(0); }
    60% { transform: scale(1.1); }
    100% { transform: scale(1); }
}

.login-footer {
    position: relative; z-index: 1;
    text-align: center;
    padding: 16px;
    font-size: 12px;
    color: var(--text-mute);
    border-top: 1px solid rgba(16,185,129,0.1);
}
.login-footer a { color: var(--emerald-600); }

/* ============================================================
 * Add Device Page
 * ============================================================ */
.add-device-wrap { max-width: 640px; margin: 0 auto; }
.add-device-card { }
.add-device-hero { text-align: center; padding: 24px 0 32px; }
.add-device-icon {
    width: 80px; height: 80px;
    margin: 0 auto 16px;
    border-radius: var(--radius-xl);
    background: linear-gradient(135deg, #10b981, #0d9488);
    color: #fff;
    display: flex; align-items: center; justify-content: center;
    box-shadow: var(--shadow-emerald);
}
.add-device-hero h2 { margin: 0 0 8px; font-size: 22px; }
.add-device-hero p { margin: 0; font-size: 13px; color: var(--text-mute); }
.code-example {
    background: var(--emerald-100);
    color: var(--emerald-700);
    padding: 2px 8px;
    border-radius: 4px;
    font-weight: 700;
}

.add-device-form { display: flex; flex-direction: column; gap: 14px; max-width: 400px; margin: 0 auto; }
.code-input-wrap { position: relative; }
.code-input-wrap input {
    width: 100%;
    padding: 14px 14px 14px 44px;
    border-radius: var(--radius);
    border: 2px solid var(--border);
    font-size: 18px;
    font-weight: 700;
    letter-spacing: 3px;
    text-align: center;
    text-transform: uppercase;
    background: #fff;
    transition: all .15s;
}
.code-input-wrap input:focus {
    outline: none;
    border-color: var(--emerald-500);
    box-shadow: 0 0 0 4px rgba(16,185,129,0.15);
}
.code-input-icon {
    position: absolute;
    left: 14px; top: 50%;
    transform: translateY(-50%);
    color: var(--text-mute);
}

.add-device-steps {
    margin-top: 32px;
    padding-top: 24px;
    border-top: 1px solid var(--border-soft);
    display: flex; flex-direction: column; gap: 16px;
}
.step { display: flex; gap: 12px; align-items: flex-start; }
.step-num {
    width: 26px; height: 26px;
    border-radius: 50%;
    background: var(--gradient-primary);
    color: #fff;
    display: flex; align-items: center; justify-content: center;
    font-weight: 700;
    font-size: 12px;
    flex-shrink: 0;
}
.step-title { font-size: 14px; font-weight: 600; }
.step-desc { font-size: 12px; color: var(--text-mute); margin-top: 2px; }

/* ============================================================
 * Settings Page
 * ============================================================ */
.settings-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
    gap: 16px;
}
.profile-area { display: flex; gap: 16px; align-items: center; }
.profile-avatar {
    width: 64px; height: 64px;
    border-radius: 50%;
    background: var(--gradient-primary);
    color: #fff;
    display: flex; align-items: center; justify-content: center;
    font-size: 22px; font-weight: 700;
    flex-shrink: 0;
    box-shadow: var(--shadow-emerald);
}
.profile-name { font-size: 18px; font-weight: 700; }
.profile-meta { margin-top: 4px; font-size: 13px; color: var(--text-soft); display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.profile-sub { font-size: 11px; color: var(--text-mute); margin-top: 4px; }

.stats-row { display: flex; gap: 24px; }
.stats-item { }
.stats-value { font-size: 28px; font-weight: 800; letter-spacing: -0.02em; color: var(--emerald-600); }
.stats-label { font-size: 12px; color: var(--text-mute); margin-top: 2px; }

.info-list { display: flex; flex-direction: column; gap: 12px; }
.info-row { display: flex; justify-content: space-between; gap: 12px; font-size: 13px; }
.info-row-label { color: var(--text-mute); }
.info-row-value { font-weight: 500; }
.info-row-value code { background: var(--slate-100); padding: 1px 6px; border-radius: 4px; font-size: 12px; }

.about-text { font-size: 13px; line-height: 1.7; }
.about-text ul { padding-left: 1.4em; }
.about-text li { margin: 4px 0; }
.about-version { color: var(--text-mute); font-size: 12px; margin-top: 12px !important; }

.danger-row { display: flex; justify-content: space-between; align-items: center; }
.danger-title { font-size: 14px; font-weight: 600; }
.danger-desc { font-size: 12px; color: var(--text-mute); margin-top: 2px; }

/* ============================================================
 * Toast Notifications
 * ============================================================ */
#toastContainer {
    position: fixed;
    top: 76px; right: 16px;
    z-index: 1000;
    display: flex; flex-direction: column; gap: 8px;
    pointer-events: none;
}
.toast {
    background: #fff;
    border-radius: var(--radius);
    box-shadow: var(--shadow-lg);
    padding: 12px 16px;
    font-size: 13px;
    border-left: 3px solid var(--emerald-500);
    min-width: 240px; max-width: 360px;
    pointer-events: auto;
    animation: slideIn .3s ease-out;
    display: flex; align-items: flex-start; gap: 10px;
}
.toast.error { border-left-color: var(--red-500); }
.toast.warn { border-left-color: var(--amber-500); }
.toast.info { border-left-color: var(--sky-500); }
.toast-icon { flex-shrink: 0; margin-top: 2px; }
.toast-body { flex: 1; }
.toast-title { font-weight: 700; }
.toast-msg { color: var(--text-soft); margin-top: 2px; font-size: 12px; }
@keyframes slideIn {
    from { transform: translateX(100%); opacity: 0; }
    to { transform: translateX(0); opacity: 1; }
}
.toast.hiding { animation: slideOut .25s ease-in forwards; }
@keyframes slideOut {
    to { transform: translateX(100%); opacity: 0; }
}

/* Modal */
.modal-backdrop {
    position: fixed; inset: 0;
    background: rgba(15,23,42,0.5);
    backdrop-filter: blur(4px);
    z-index: 100;
    display: none;
    align-items: center; justify-content: center;
    padding: 16px;
}
.modal-backdrop.show { display: flex; }
.modal {
    background: #fff;
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    width: 100%; max-width: 440px;
    overflow: hidden;
    animation: pop .25s ease-out;
}
.modal-head {
    padding: 16px 20px;
    border-bottom: 1px solid var(--border-soft);
    font-weight: 700;
    font-size: 16px;
}
.modal-body { padding: 20px; }
.modal-foot {
    padding: 12px 20px;
    border-top: 1px solid var(--border-soft);
    display: flex; justify-content: flex-end; gap: 8px;
}

/* ============================================================
 * Responsive
 * ============================================================ */
@media (min-width: 1024px) {
    .login-hero { display: block; }
}

@media (max-width: 768px) {
    .sidebar {
        position: fixed;
        top: var(--topbar-h);
        left: 0;
        z-index: 50;
        transform: translateX(-100%);
        transition: transform .25s ease;
        background: #fff;
        box-shadow: var(--shadow-lg);
    }
    .sidebar.open { transform: translateX(0); }
    .sidebar.open ~ .sidebar-backdrop { display: block; }
    .sidebar-toggle { display: inline-flex; }
    .main-content { padding: 16px; }
    .brand-text { display: none; }
    .topbar-user-info { display: none; }
    .page-title { font-size: 20px; }
    .stats-grid { grid-template-columns: 1fr; }
    .stat-value { font-size: 20px; }
    .device-row-stats { display: none; }
    .device-row-arrow { display: none; }
    .hero-title { font-size: 32px; }
    .hero-desc { font-size: 14px; }
    .login-wrap { padding: 16px; }
    .login-card { padding: 20px; min-height: 420px; }
    .chart-container { height: 240px; }
    .setting-control { min-width: 160px; }
    .info-grid { grid-template-columns: 1fr; }
    .relay-buttons { flex-direction: column; }
    .relay-buttons .btn { width: 100%; }
}

@media (max-width: 480px) {
    .stats-grid { grid-template-columns: 1fr 1fr; }
    .stat-value { font-size: 18px; }
    .topbar-icon-btn { width: 32px; height: 32px; }
    .qr-box { width: 160px; height: 160px; }
}

/* ============================================================
 * r2-7 新增样式：告警中心 / 设备分组 / CSV 导出
 * ============================================================ */

/* ---------- 通用 Modal 覆盖层（替代旧 modal-backdrop 用法） ---------- */
.modal-overlay {
    position: fixed; inset: 0;
    background: rgba(15,23,42,0.55);
    backdrop-filter: blur(4px);
    z-index: 200;
    display: flex;
    align-items: center; justify-content: center;
    padding: 16px;
    animation: fadeIn .2s ease-out;
}
.modal-overlay[style*="display:none"] { display: none !important; }
.modal.modal-sm { max-width: 480px; width: 100%; }
.modal-head {
    display: flex; align-items: center; justify-content: space-between;
}
.modal-title { font-size: 16px; font-weight: 700; color: var(--text); margin: 0; }
.modal-close {
    background: none; border: none; cursor: pointer;
    color: var(--text-mute);
    width: 32px; height: 32px;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 8px;
}
.modal-close:hover { background: var(--slate-100); color: var(--text); }
.modal-body { max-height: 70vh; overflow-y: auto; }
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }

/* ---------- 表单 ---------- */
.form-group { margin-bottom: 14px; }
.form-label {
    display: block; font-size: 13px; font-weight: 600;
    color: var(--text-soft); margin-bottom: 6px;
}
.form-input {
    width: 100%;
    padding: 9px 12px;
    border: 1px solid var(--border);
    border-radius: 10px;
    font-size: 14px;
    color: var(--text);
    background: #fff;
    transition: border-color .15s, box-shadow .15s;
    box-sizing: border-box;
}
.form-input:focus {
    outline: none;
    border-color: var(--emerald-500);
    box-shadow: 0 0 0 3px rgba(16,185,129,0.15);
}
.form-input-sm { padding: 6px 10px; font-size: 13px; }
.form-row-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }

/* ---------- 统计卡片行（4 张告警卡片） ---------- */
.stat-cards-row {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 12px;
    margin-bottom: 20px;
}
.stat-card {
    background: #fff;
    border-radius: 14px;
    padding: 16px;
    box-shadow: 0 1px 3px rgba(15,23,42,0.04);
    display: flex; align-items: flex-start; justify-content: space-between;
    border: 1px solid var(--border-soft);
}
.stat-card-body { flex: 1; }
.stat-card-label {
    font-size: 12px; color: var(--text-mute);
    margin-bottom: 4px;
}
.stat-card-value {
    font-size: 24px; font-weight: 700;
    color: var(--text);
    line-height: 1.2;
}
.stat-card-sub {
    font-size: 11px; color: var(--text-mute);
    margin-top: 2px;
}
.stat-card-icon {
    width: 36px; height: 36px;
    border-radius: 10px;
    display: inline-flex; align-items: center; justify-content: center;
    color: #fff;
}
.stat-emerald .stat-card-icon { background: linear-gradient(135deg, #10b981, #14b8a6); }
.stat-amber   .stat-card-icon { background: linear-gradient(135deg, #f59e0b, #f97316); }
.stat-sky     .stat-card-icon { background: linear-gradient(135deg, #38bdf8, #0284c7); }
.stat-red     .stat-card-icon { background: linear-gradient(135deg, #ef4444, #f43f5e); }
.stat-cyan    .stat-card-icon { background: linear-gradient(135deg, #22d3ee, #0891b2); } /* r5-6 新增 */

/* ---------- 告警 Tab 切换 ---------- */
.alert-tabs {
    display: inline-flex; gap: 4px;
    padding: 4px;
    background: var(--slate-100);
    border-radius: 10px;
    margin-bottom: 14px;
}
.alert-tab {
    background: none; border: none; cursor: pointer;
    padding: 6px 14px;
    border-radius: 8px;
    font-size: 13px; font-weight: 500;
    color: var(--text-mute);
    display: inline-flex; align-items: center; gap: 6px;
    transition: all .15s;
}
.alert-tab:hover { color: var(--text); }
.alert-tab.active {
    background: #fff; color: var(--text);
    box-shadow: 0 1px 2px rgba(0,0,0,0.05);
}
.alert-tab-badge {
    background: #ef4444; color: #fff;
    font-size: 10px; padding: 1px 6px;
    border-radius: 999px;
}
.alert-tab-panel { display: none; }
.alert-tab-panel.active { display: block; }

/* ---------- 严重级别徽章 ---------- */
.severity-badge {
    display: inline-flex; align-items: center;
    padding: 1px 8px;
    border-radius: 999px;
    font-size: 11px; font-weight: 600;
    border: 1px solid;
    line-height: 1.4;
}
.severity-info     { background: #eff6ff; color: #2563eb; border-color: #dbeafe; }
.severity-warning  { background: #fffbeb; color: #d97706; border-color: #fef3c7; }
.severity-critical { background: #fef2f2; color: #dc2626; border-color: #fee2e2; }
.badge-muted {
    display: inline-flex; align-items: center; gap: 3px;
    padding: 1px 8px;
    border-radius: 999px;
    font-size: 11px;
    background: var(--slate-100); color: var(--text-mute);
}

/* ---------- 告警规则卡片 ---------- */
.alert-rule-card {
    background: #fff;
    border: 1px solid var(--border-soft);
    border-radius: 12px;
    padding: 14px;
    display: flex; align-items: flex-start; gap: 12px;
    margin-bottom: 10px;
    transition: box-shadow .15s, border-color .15s;
}
.alert-rule-card:hover {
    box-shadow: 0 4px 12px rgba(15,23,42,0.06);
    border-color: var(--border);
}
.alert-rule-card.is-disabled { opacity: 0.6; }
.alert-rule-icon {
    flex-shrink: 0;
    width: 40px; height: 40px;
    border-radius: 10px;
    border: 1px solid;
    display: inline-flex; align-items: center; justify-content: center;
}
.alert-rule-main { flex: 1; min-width: 0; }
.alert-rule-title-row {
    display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
    margin-bottom: 4px;
}
.alert-rule-name {
    font-size: 14px; font-weight: 600; color: var(--text);
}
.alert-rule-meta {
    font-size: 12px; color: var(--text-mute);
    display: flex; flex-wrap: wrap; gap: 12px;
    margin-bottom: 6px;
}
.alert-rule-meta span {
    display: inline-flex; align-items: center; gap: 3px;
}
.alert-rule-channels {
    display: flex; gap: 6px; flex-wrap: wrap;
}
.channel-chip {
    display: inline-flex; align-items: center; gap: 3px;
    padding: 2px 8px;
    border-radius: 999px;
    background: var(--slate-100);
    color: var(--text-soft);
    font-size: 11px;
}
.alert-rule-actions {
    display: flex; align-items: center; gap: 4px;
    flex-shrink: 0;
}
.switch.switch-sm { width: 36px; height: 20px; }
.switch.switch-sm .switch-slider::before {
    width: 14px; height: 14px;
}
.switch.switch-sm input:checked + .switch-slider::before { transform: translateX(16px); }

/* ---------- 告警事件卡片 ---------- */
.alert-events-head {
    display: flex; align-items: center; justify-content: space-between;
    margin-bottom: 10px;
}
.alert-events-count { font-size: 13px; color: var(--text-mute); }
.alert-event-card {
    background: #fff;
    border: 1px solid var(--border-soft);
    border-radius: 12px;
    padding: 14px;
    display: flex; align-items: flex-start; gap: 12px;
    margin-bottom: 10px;
}
.alert-event-card.is-acked { opacity: 0.6; }
.alert-event-icon {
    flex-shrink: 0;
    width: 40px; height: 40px;
    border-radius: 10px;
    border: 1px solid;
    display: inline-flex; align-items: center; justify-content: center;
}
.alert-event-main { flex: 1; min-width: 0; }
.alert-event-title-row {
    display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
    margin-bottom: 4px;
}
.alert-event-name { font-size: 14px; font-weight: 600; }
.alert-event-msg {
    font-size: 13px; color: var(--text-soft);
    margin: 4px 0;
}
.alert-event-meta {
    font-size: 12px; color: var(--text-mute);
    display: flex; flex-wrap: wrap; gap: 12px;
}

/* ---------- 严重级别选择器 ---------- */
.severity-picker {
    display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 6px;
}
.severity-pick {
    padding: 7px 10px;
    border: 1px solid var(--border);
    border-radius: 8px;
    background: #fff;
    color: var(--text-mute);
    font-size: 13px; font-weight: 500;
    cursor: pointer;
    transition: all .15s;
}
.severity-pick:hover { background: var(--slate-50); }
.severity-pick.severity-info.active     { background: #eff6ff; color: #2563eb; border-color: #93c5fd; }
.severity-pick.severity-warning.active  { background: #fffbeb; color: #d97706; border-color: #fcd34d; }
.severity-pick.severity-critical.active { background: #fef2f2; color: #dc2626; border-color: #fca5a5; }

/* ---------- 通知渠道选项 ---------- */
.channels-list { display: flex; flex-direction: column; gap: 6px; }
.channel-option {
    display: flex; align-items: center; gap: 10px;
    padding: 8px 10px;
    border: 1px solid var(--border);
    border-radius: 10px;
    cursor: pointer;
    transition: all .15s;
    color: var(--text-soft);
}
.channel-option:hover { background: var(--slate-50); }
.channel-option:has(.ch-toggle:checked) {
    border-color: var(--emerald-500);
    background: var(--emerald-50);
}
.channel-option-title { font-size: 13px; font-weight: 500; color: var(--text); }
.channel-option-desc  { font-size: 11px; color: var(--text-mute); }

/* ---------- 设备分组筛选 ---------- */
.group-filter-bar {
    display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
    padding: 8px 10px;
    background: var(--slate-100);
    border-radius: 12px;
    margin-bottom: 16px;
}
.group-filter-label {
    display: inline-flex; align-items: center; gap: 4px;
    font-size: 12px; color: var(--text-mute);
    padding: 0 6px;
}
.group-chip {
    background: none;
    border: none;
    cursor: pointer;
    padding: 6px 12px;
    border-radius: 999px;
    font-size: 13px; font-weight: 500;
    color: var(--text-soft);
    display: inline-flex; align-items: center; gap: 6px;
    transition: all .15s;
}
.group-chip:hover { background: rgba(255,255,255,0.7); color: var(--text); }
.group-chip.active {
    background: #fff;
    color: var(--text);
    box-shadow: 0 1px 3px rgba(0,0,0,0.06);
}
.group-chip-dot {
    width: 8px; height: 8px;
    border-radius: 50%;
    display: inline-block;
}
.group-chip-count {
    background: var(--slate-200);
    color: var(--text-soft);
    padding: 0 6px;
    border-radius: 999px;
    font-size: 11px;
    min-width: 18px;
    text-align: center;
}
.group-chip.active .group-chip-count { background: var(--emerald-100); color: var(--emerald-700); }
.group-chip-manage { color: var(--text-mute); margin-left: auto; }

/* 设备卡片上的分组标签 */
.device-group-tag {
    display: inline-flex; align-items: center; gap: 4px;
    padding: 1px 8px;
    border-radius: 999px;
    font-size: 11px; font-weight: 500;
    border: 1px solid;
    margin-left: 6px;
    vertical-align: middle;
}
.device-group-tag .dot {
    width: 6px; height: 6px; border-radius: 50%;
}

/* ---------- 分组管理弹窗 ---------- */
.group-manager-list { display: flex; flex-direction: column; gap: 8px; margin-bottom: 16px; }
.group-manager-item {
    display: flex; align-items: center; gap: 8px;
    padding: 8px;
    border: 1px solid var(--border-soft);
    border-radius: 10px;
}
.group-manager-item .group-name-input { flex: 1; }
.group-manager-item .group-color-input {
    width: 30px; height: 32px;
    padding: 0; border: 1px solid var(--border);
    border-radius: 8px; cursor: pointer; background: none;
}
.group-manager-empty {
    text-align: center; color: var(--text-mute);
    padding: 24px 0; font-size: 13px;
}
.group-manager-create {
    border-top: 1px solid var(--border-soft);
    padding-top: 14px;
}
.group-manager-create h4 {
    margin: 0 0 8px; font-size: 13px; color: var(--text-soft);
}
.group-manager-create-row {
    display: flex; align-items: center; gap: 8px;
}
.group-manager-create-row .group-color-input {
    width: 30px; height: 32px;
    padding: 0; border: 1px solid var(--border);
    border-radius: 8px; cursor: pointer; background: none;
}
.group-manager-create-row .form-input { flex: 1; }

/* ---------- 图表头操作行（导出 CSV） ---------- */
.chart-head-actions {
    display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
}
.btn-outline {
    background: #fff;
    border: 1px solid var(--border);
    color: var(--text-soft);
    padding: 7px 12px;
    border-radius: 10px;
    font-size: 13px; font-weight: 500;
    cursor: pointer;
    display: inline-flex; align-items: center; gap: 6px;
    transition: all .15s;
    text-decoration: none;
}
.btn-outline:hover {
    background: var(--slate-50);
    color: var(--text);
    border-color: var(--slate-300);
}

/* ---------- 响应式适配（r2-7 新增） ---------- */
@media (max-width: 768px) {
    .stat-cards-row { grid-template-columns: 1fr 1fr; }
    .form-row-2 { grid-template-columns: 1fr; }
    .group-chip-manage { margin-left: 0; }
    .chart-head-actions { width: 100%; }
}
@media (max-width: 480px) {
    .stat-cards-row { grid-template-columns: 1fr; }
    .alert-rule-actions { flex-direction: column; align-items: flex-end; }
}

/* ============================================================
 * r3-6 新增：数据大屏样式（.ds-* 前缀）
 * 深色主题，全屏独立布局，不依赖 header.php
 * ============================================================ */
.ds-body {
    margin: 0;
    min-height: 100vh;
    background: linear-gradient(135deg, #0f172a 0%, #134e4a 50%, #0f172a 100%);
    color: #e2e8f0;
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif;
    font-size: 14px;
    overflow-x: hidden;
}

/* 顶部标题栏 */
.ds-topbar {
    position: sticky;
    top: 0;
    z-index: 20;
    background: rgba(15, 23, 42, 0.85);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    border-bottom: 1px solid rgba(16, 185, 129, 0.18);
}
.ds-topbar-inner {
    display: flex; align-items: center; justify-content: space-between;
    padding: 10px 16px;
    max-width: 1600px; margin: 0 auto;
    gap: 12px; flex-wrap: wrap;
}
.ds-topbar-left { display: flex; align-items: center; gap: 12px; }
.ds-topbar-right { display: flex; align-items: center; gap: 10px; }
.ds-back-btn {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 6px 12px; border-radius: 8px;
    background: rgba(255,255,255,0.08);
    color: #e2e8f0; font-size: 13px;
    text-decoration: none; transition: background .15s;
}
.ds-back-btn:hover { background: rgba(255,255,255,0.18); }
.ds-brand { display: flex; align-items: center; gap: 8px; }
.ds-brand-logo {
    width: 32px; height: 32px; border-radius: 8px;
    background: linear-gradient(135deg, #10b981, #0d9488);
    display: flex; align-items: center; justify-content: center;
    color: #fff;
}
.ds-brand-title { font-weight: 700; font-size: 14px; line-height: 1.2; }
.ds-brand-sub { font-size: 10px; color: rgba(110, 231, 183, 0.7); }

/* 时间范围切换 */
.ds-range-tabs {
    display: inline-flex; align-items: center; gap: 2px;
    padding: 3px;
    border-radius: 8px;
    background: rgba(255,255,255,0.08);
}
.ds-range-tab {
    padding: 5px 10px;
    border-radius: 6px;
    border: none;
    background: transparent;
    color: rgba(167, 243, 208, 0.7);
    font-size: 12px; font-weight: 500;
    cursor: pointer;
    transition: all .15s;
}
.ds-range-tab:hover { color: #fff; }
.ds-range-tab.active {
    background: #10b981;
    color: #fff;
}

/* 实时徽章 */
.ds-live-badge {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 5px 12px;
    border-radius: 8px;
    background: rgba(16, 185, 129, 0.18);
    border: 1px solid rgba(16, 185, 129, 0.3);
    color: #6ee7b7;
    font-size: 12px;
}
.ds-live-dot {
    width: 8px; height: 8px; border-radius: 50%;
    background: #34d399;
    box-shadow: 0 0 8px #10b981;
    animation: ds-pulse 1.4s ease-in-out infinite;
}
@keyframes ds-pulse {
    0%, 100% { opacity: 1; transform: scale(1); }
    50% { opacity: 0.5; transform: scale(0.8); }
}

/* 主区域 */
.ds-main {
    padding: 16px;
    max-width: 1600px; margin: 0 auto;
    display: flex; flex-direction: column; gap: 16px;
}

/* KPI 卡片 */
.ds-kpi-grid {
    display: grid;
    grid-template-columns: repeat(8, 1fr);
    gap: 12px;
}
.ds-kpi-card {
    background: rgba(255,255,255,0.05);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border: 1px solid rgba(255,255,255,0.08);
    border-radius: 12px;
    padding: 12px;
    transition: background .15s;
}
.ds-kpi-card:hover { background: rgba(255,255,255,0.1); }
.ds-kpi-top {
    display: flex; align-items: center; justify-content: space-between;
    margin-bottom: 6px;
}
.ds-kpi-icon { color: var(--accent); display: flex; }
.ds-kpi-trend {
    font-size: 10px;
    color: rgba(110, 231, 183, 0.6);
}
.ds-kpi-value {
    font-size: 22px; font-weight: 700;
    color: #fff;
    font-variant-numeric: tabular-nums;
    line-height: 1.2;
}
.ds-kpi-label {
    font-size: 10px;
    color: rgba(167, 243, 208, 0.6);
    margin-top: 2px;
}

/* 通用卡片 */
.ds-card {
    background: rgba(255,255,255,0.05);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border: 1px solid rgba(255,255,255,0.08);
    border-radius: 12px;
    padding: 18px;
}
.ds-card-title {
    display: flex; align-items: center; gap: 6px;
    font-size: 13px; font-weight: 600;
    color: #fff;
    margin: 0 0 14px 0;
}
.ds-card-head { margin-bottom: 14px; }
.ds-card-head h3 {
    display: flex; align-items: center; gap: 6px;
    font-size: 13px; font-weight: 600;
    margin: 0;
    color: #fff;
}
.ds-card-head p {
    font-size: 11px; color: rgba(110, 231, 183, 0.6);
    margin: 4px 0 0 0;
}

/* 行布局 */
.ds-row {
    display: grid;
    gap: 16px;
}
.ds-row-3 { grid-template-columns: repeat(3, 1fr); }
.ds-row-2-1 > .ds-card-trend { grid-column: span 2; }

/* 图表容器 */
.ds-chart-wrap {
    position: relative;
    width: 100%;
}
.ds-chart-wrap canvas { background: transparent !important; }

/* 状态饼图 legend */
.ds-pie-legend {
    display: flex; align-items: center; justify-content: center;
    gap: 16px;
    margin-top: 8px;
}
.ds-pie-legend-item {
    display: flex; align-items: center; gap: 6px;
    font-size: 12px;
    color: rgba(167, 243, 208, 0.8);
}
.ds-pie-legend-item b { color: #fff; }
.ds-dot {
    width: 10px; height: 10px; border-radius: 50%;
    display: inline-block;
}

/* 继电器状态 */
.ds-relay-row {
    display: flex; gap: 8px;
    margin-top: 16px; padding-top: 16px;
    border-top: 1px solid rgba(255,255,255,0.08);
}
.ds-relay-stat {
    flex: 1;
    display: flex; align-items: center; gap: 8px;
    padding: 10px;
    border-radius: 8px;
    background: rgba(255,255,255,0.05);
}
.ds-relay-num {
    font-size: 16px; font-weight: 700;
    color: #fff;
    line-height: 1;
}
.ds-relay-label {
    font-size: 10px;
    color: rgba(167, 243, 208, 0.6);
    margin-top: 2px;
}

/* 设备排行 */
.ds-ranking {
    display: flex; flex-direction: column; gap: 8px;
    max-height: 200px; overflow-y: auto; padding-right: 4px;
}
.ds-ranking::-webkit-scrollbar { width: 4px; }
.ds-ranking::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.15); border-radius: 4px; }
.ds-rank-item {
    display: flex; align-items: center; gap: 8px;
}
.ds-rank-no {
    width: 22px; height: 22px;
    border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    font-size: 11px; font-weight: 700;
    background: rgba(255,255,255,0.08);
    color: rgba(167, 243, 208, 0.6);
    flex-shrink: 0;
}
.ds-rank-no.rank-1 { background: #fbbf24; color: #78350f; }
.ds-rank-no.rank-2 { background: #cbd5e1; color: #334155; }
.ds-rank-no.rank-3 { background: #fb923c; color: #7c2d12; }
.ds-rank-name {
    flex: 1;
    font-size: 12px; color: #e2e8f0;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ds-rank-bar {
    width: 80px; height: 6px;
    border-radius: 3px;
    background: rgba(255,255,255,0.1);
    overflow: hidden;
}
.ds-rank-bar-fill {
    height: 100%; border-radius: 3px;
    transition: width .4s ease;
}
.ds-rank-val {
    font-size: 12px;
    color: #fff;
    font-variant-numeric: tabular-nums;
    width: 36px; text-align: right;
}

/* 设备实时表 */
.ds-card-table { padding-bottom: 8px; }
.ds-table-count {
    margin-left: 8px;
    padding: 2px 8px;
    background: rgba(16, 185, 129, 0.15);
    color: #6ee7b7;
    border-radius: 999px;
    font-size: 10px; font-weight: 600;
}
.ds-table-wrap { overflow-x: auto; }
.ds-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 12px;
}
.ds-table thead th {
    text-align: left;
    padding: 10px 8px;
    font-weight: 500;
    color: rgba(110, 231, 183, 0.6);
    border-bottom: 1px solid rgba(255,255,255,0.1);
    white-space: nowrap;
}
.ds-table tbody td {
    padding: 10px 8px;
    border-bottom: 1px solid rgba(255,255,255,0.05);
    color: #e2e8f0;
    white-space: nowrap;
}
.ds-table tbody tr:hover { background: rgba(255,255,255,0.04); }
.ds-table .text-c { text-align: center; }
.ds-table .text-r { text-align: right; }
.ds-table .mono { font-variant-numeric: tabular-nums; font-family: 'SF Mono', 'Menlo', monospace; }
.ds-table .muted { color: rgba(110, 231, 183, 0.6); }
.ds-table .temp { color: #fbbf24; }
.ds-table .hum { color: #22d3ee; }
.ds-table .rain { color: #38bdf8; }
.ds-table .soil-low { color: #ef4444; }
.ds-table .soil-mid { color: #f59e0b; }
.ds-table .soil-ok { color: #10b981; }
.ds-table .signal { color: rgba(110, 231, 183, 0.7); }
.ds-tbl-device { display: flex; align-items: center; gap: 8px; }
.ds-tbl-dot {
    width: 6px; height: 6px; border-radius: 50%;
    flex-shrink: 0;
}
.ds-tbl-dot.on  { background: #34d399; box-shadow: 0 0 6px #10b981; animation: ds-pulse 1.4s ease-in-out infinite; }
.ds-tbl-dot.off { background: #475569; }
.ds-tbl-name { font-weight: 500; color: #fff; }
.ds-tbl-loc { font-size: 10px; color: rgba(110, 231, 183, 0.4); }
.ds-badge {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 999px;
    font-size: 10px;
    font-weight: 500;
}
.ds-badge-on  { background: rgba(16, 185, 129, 0.2); color: #6ee7b7; border: 1px solid rgba(16, 185, 129, 0.3); }
.ds-badge-off { background: rgba(100, 116, 139, 0.2); color: #94a3b8; }
.ds-relay-on { color: #ef4444; display: inline-flex; align-items: center; gap: 4px; }
.ds-relay-off { color: #64748b; }

.ds-empty {
    padding: 24px; text-align: center;
    color: rgba(110, 231, 183, 0.4);
    font-size: 12px;
}
.ds-empty-row {
    text-align: center; padding: 32px 8px;
    color: rgba(110, 231, 183, 0.4);
}

/* 数据大屏响应式 */
@media (max-width: 1280px) {
    .ds-kpi-grid { grid-template-columns: repeat(4, 1fr); }
}
@media (max-width: 1024px) {
    .ds-row-3 { grid-template-columns: 1fr; }
    .ds-row-2-1 > .ds-card-trend { grid-column: span 1; }
}
@media (max-width: 768px) {
    .ds-kpi-grid { grid-template-columns: repeat(2, 1fr); }
    .ds-topbar-inner { padding: 8px 12px; }
    .ds-brand-sub { display: none; }
    .ds-main { padding: 12px; }
}

/* ============================================================
 * r3-6 新增：用户管理页面样式
 * ============================================================ */
.users-page { /* 容器 */ }

.page-head {
    display: flex; align-items: center; justify-content: space-between;
    gap: 12px; flex-wrap: wrap;
    margin-bottom: 18px;
}
.page-head-text { flex: 1; min-width: 0; }
.page-title {
    display: flex; align-items: center; gap: 8px;
    font-size: 22px; font-weight: 700;
    color: var(--text);
    margin: 0;
}
.page-sub {
    font-size: 13px; color: var(--text-soft);
    margin: 6px 0 0 0;
}

/* 4 张统计卡（复用 .stat-cards-row） */
.stat-cards-4 .stat-card {
    display: flex; align-items: flex-start; justify-content: space-between;
    padding: 16px;
    background: #fff;
    border-radius: 12px;
    border: 1px solid var(--border);
    box-shadow: 0 1px 2px rgba(0,0,0,0.04);
}
.stat-card-amber { background: linear-gradient(135deg, #fffbeb 0%, #fef3c7 100%); border-color: #fde68a; }
.stat-card-emerald { background: linear-gradient(135deg, #ecfdf5 0%, #d1fae5 100%); border-color: #a7f3d0; }
.stat-card-sky { background: linear-gradient(135deg, #f0f9ff 0%, #e0f2fe 100%); border-color: #bae6fd; }
.stat-card-cyan { background: linear-gradient(135deg, #ecfeff 0%, #cffafe 100%); border-color: #a5f3fc; }
.stat-card-info { flex: 1; }
.stat-card-label { font-size: 12px; color: var(--text-soft); }
.stat-card-value { font-size: 26px; font-weight: 700; color: var(--text); margin-top: 4px; }
.stat-card-icon {
    width: 36px; height: 36px;
    border-radius: 10px;
    display: flex; align-items: center; justify-content: center;
    color: #fff;
}
.stat-icon-emerald { background: linear-gradient(135deg, #10b981, #0d9488); }
.stat-icon-amber   { background: linear-gradient(135deg, #f59e0b, #ea580c); }
.stat-icon-sky      { background: linear-gradient(135deg, #0ea5e9, #0284c7); }
.stat-icon-cyan     { background: linear-gradient(135deg, #06b6d4, #0891b2); }

/* 工具栏：搜索 + 角色筛选 */
.users-toolbar {
    display: flex; align-items: center; gap: 12px;
    margin-bottom: 14px;
    flex-wrap: wrap;
}
.search-input-wrap {
    position: relative;
    flex: 1; min-width: 200px; max-width: 360px;
}
.search-input-wrap > svg {
    position: absolute;
    left: 12px; top: 50%;
    transform: translateY(-50%);
    color: var(--text-mute);
    pointer-events: none;
}
.search-input {
    padding-left: 36px;
    width: 100%;
}

.role-filter-bar {
    display: inline-flex;
    align-items: center; gap: 2px;
    padding: 4px;
    border-radius: 10px;
    background: rgba(0,0,0,0.04);
}
.role-filter-chip {
    padding: 6px 14px;
    border-radius: 7px;
    border: none; background: transparent;
    color: var(--text-soft);
    font-size: 13px; font-weight: 500;
    cursor: pointer;
    transition: all .15s;
}
.role-filter-chip:hover { color: var(--text); }
.role-filter-chip.active {
    background: #fff;
    color: var(--text);
    box-shadow: 0 1px 3px rgba(0,0,0,0.08);
}

/* 用户表格卡片 */
.users-table-card {
    background: #fff;
    border-radius: 12px;
    border: 1px solid var(--border);
    overflow: hidden;
    box-shadow: 0 1px 2px rgba(0,0,0,0.04);
}
.users-table-wrap { overflow-x: auto; }
.users-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 14px;
}
.users-table thead th {
    padding: 12px 16px;
    text-align: left;
    font-weight: 500;
    color: var(--text-soft);
    background: var(--slate-50);
    border-bottom: 1px solid var(--border);
    white-space: nowrap;
}
.users-table tbody td {
    padding: 12px 16px;
    border-bottom: 1px solid var(--border);
    color: var(--text);
}
.users-table tbody tr:hover { background: var(--slate-50); }
.users-table .text-c { text-align: center; }
.users-table .text-r { text-align: right; }
.users-table .mono { font-variant-numeric: tabular-nums; }

.col-user { min-width: 160px; }
.col-email { min-width: 200px; }
.col-role { min-width: 110px; }
.col-provider, .col-devices, .col-status { min-width: 90px; }
.col-lastlogin { min-width: 120px; }
.col-actions { min-width: 120px; }

/* 用户单元格 */
.user-cell {
    display: flex; align-items: center; gap: 12px;
}
.user-avatar {
    width: 36px; height: 36px;
    border-radius: 10px;
    display: flex; align-items: center; justify-content: center;
    color: #fff; font-weight: 600; font-size: 13px;
    flex-shrink: 0;
}
.user-cell-info { flex: 1; min-width: 0; }
.user-name {
    font-weight: 500; color: var(--text);
    display: flex; align-items: center; gap: 6px;
}
.crown-icon { flex-shrink: 0; }
.user-meta { font-size: 11px; color: var(--text-mute); margin-top: 2px; }
.user-email-cell {
    color: var(--text-soft);
    font-family: 'SF Mono', 'Menlo', monospace;
    font-size: 13px;
}
.last-login-text { font-size: 12px; color: var(--text-mute); }

/* 角色下拉框（行内） */
.role-select {
    padding: 5px 10px;
    border-radius: 7px;
    border: 1px solid var(--border);
    background: var(--slate-50);
    color: var(--text);
    font-size: 12px;
    cursor: pointer;
    outline: none;
}
.role-select:focus { border-color: var(--emerald-500); }

/* 登录方式徽章 */
.provider-badge {
    display: inline-block;
    padding: 2px 10px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 500;
    background: var(--slate-100);
    color: var(--text-soft);
}
.provider-qq     { background: #fef3c7; color: #92400e; }
.provider-email  { background: #d1fae5; color: #047857; }
.provider-alipay { background: #dbeafe; color: #1d4ed8; }
.provider-wechat { background: #dcfce7; color: #166534; }

/* 状态徽章 */
.status-badge {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 3px 10px;
    border-radius: 999px;
    font-size: 11px; font-weight: 500;
}
.status-badge .status-dot {
    width: 6px; height: 6px; border-radius: 50%;
}
.status-active {
    background: #d1fae5;
    color: #047857;
}
.status-active .status-dot { background: #10b981; }
.status-disabled {
    background: var(--slate-100);
    color: var(--text-mute);
}
.status-disabled .status-dot { background: var(--text-mute); }

/* 操作按钮 */
.user-actions {
    display: flex; align-items: center; justify-content: center; gap: 4px;
}
.action-btn {
    width: 30px; height: 30px;
    border: none; background: transparent;
    border-radius: 7px;
    display: inline-flex; align-items: center; justify-content: center;
    color: var(--text-soft);
    cursor: pointer;
    transition: all .15s;
}
.action-btn:hover { background: var(--slate-100); color: var(--text); }
.action-btn.text-emerald { color: var(--emerald-600); }
.action-btn.text-emerald:hover { background: var(--emerald-50); }
.action-btn.text-amber { color: var(--amber-500); }
.action-btn.text-amber:hover { background: #fef3c7; }
.action-btn.text-red { color: var(--red-500); }
.action-btn.text-red:hover { background: #fee2e2; }

.empty-row {
    text-align: center; padding: 40px 16px;
    color: var(--text-mute);
}

/* 角色选择按钮（弹窗内） */
.role-pick-row {
    display: grid; grid-template-columns: 1fr 1fr;
    gap: 10px;
}
.role-pick-btn {
    display: flex; align-items: center; justify-content: center; gap: 8px;
    padding: 14px;
    border: 1px solid var(--border);
    background: #fff;
    border-radius: 10px;
    font-size: 14px; font-weight: 500;
    color: var(--text-soft);
    cursor: pointer;
    transition: all .15s;
}
.role-pick-btn:hover { border-color: var(--slate-300); }
.role-pick-btn.active[data-role="user"]  {
    border-color: var(--emerald-500);
    background: var(--emerald-50);
    color: var(--emerald-700);
}
.role-pick-btn.active[data-role="admin"] {
    border-color: var(--amber-500);
    background: #fffbeb;
    color: #b45309;
}
.form-hint {
    font-size: 12px;
    color: var(--text-mute);
    margin: 6px 0 0 0;
}

/* 用户表响应式 */
@media (max-width: 1024px) {
    .col-lastlogin { display: none; }
}
@media (max-width: 768px) {
    .col-email, .col-provider { display: none; }
    .stat-cards-4 { grid-template-columns: 1fr 1fr; }
    .users-toolbar { flex-direction: column; align-items: stretch; }
    .search-input-wrap { max-width: none; }
}
@media (max-width: 540px) {
    .col-devices, .col-status { display: none; }
    .stat-cards-4 { grid-template-columns: 1fr; }
}

/* ============================================================
 * r4-6 新增：设备地图 + 传感器校准样式
 * ============================================================ */

/* ---------- 通用：地图/校准页面顶部 ---------- */
.map-refresh-actions { display: flex; gap: 8px; align-items: center; }

/* ---------- 地图工具栏 ---------- */
.map-toolbar {
    display: flex; align-items: center; gap: 12px;
    margin-bottom: 16px;
    flex-wrap: wrap;
}
.map-search-wrap {
    position: relative;
    flex: 1 1 240px;
    max-width: 320px;
}
.map-search-icon {
    position: absolute;
    left: 12px; top: 50%;
    transform: translateY(-50%);
    color: var(--text-mute);
    pointer-events: none;
}
.map-search-input {
    width: 100%;
    padding: 9px 12px 9px 36px;
    border-radius: 10px;
}
.map-filter-group {
    display: inline-flex;
    padding: 4px;
    background: var(--slate-100);
    border-radius: 10px;
    gap: 2px;
}
.map-filter-btn {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 6px 14px;
    border-radius: 7px;
    font-size: 13px;
    color: var(--text-soft);
    background: transparent;
    transition: all .15s;
}
.map-filter-btn:hover { color: var(--text); }
.map-filter-btn.active {
    background: #fff;
    color: var(--emerald-700);
    box-shadow: var(--shadow-sm);
}
.map-stats {
    display: flex; align-items: center; gap: 16px;
    margin-left: auto;
    font-size: 12px;
    color: var(--text-soft);
}
.map-stat {
    display: inline-flex; align-items: center; gap: 6px;
}
.map-stat strong { color: var(--text); font-size: 13px; }
.map-stat-dot {
    width: 8px; height: 8px;
    border-radius: 50%;
}
.map-stat-dot-online  { background: var(--emerald-500); }
.map-stat-dot-offline { background: var(--slate-300); }

/* ---------- 地图主网格 ---------- */
.map-grid {
    display: grid;
    grid-template-columns: 2fr 1fr;
    gap: 16px;
}
.map-card {
    overflow: hidden;
    padding: 0;
}
.map-container {
    position: relative;
    width: 100%;
    aspect-ratio: 4 / 3;
    background: linear-gradient(135deg, #f0f9ff 0%, #ecfeff 100%);
    overflow: hidden;
}
.map-svg {
    position: absolute;
    inset: 0;
    width: 100%; height: 100%;
    color: var(--slate-300);
}

/* SVG 设备标记动画 */
@keyframes mapMarkerPulse {
    0%   { r: 2.5; opacity: 0.35; }
    70%  { r: 5;   opacity: 0;    }
    100% { r: 2.5; opacity: 0;    }
}

/* ---------- 地图图例 / 比例尺 ---------- */
.map-legend {
    position: absolute;
    bottom: 12px; left: 12px;
    padding: 10px 12px;
    background: rgba(255,255,255,0.85);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border: 1px solid var(--border);
    border-radius: 10px;
    font-size: 12px;
    box-shadow: var(--shadow-sm);
}
.map-legend-title {
    font-size: 10px;
    color: var(--text-mute);
    margin-bottom: 6px;
    font-weight: 600;
}
.map-legend-row {
    display: flex; align-items: center; gap: 8px;
    margin: 4px 0;
    font-size: 11px;
}
.map-legend-dot {
    width: 9px; height: 9px;
    border-radius: 50%;
}
.map-legend-dot-online  { background: var(--emerald-500); }
.map-legend-dot-irrig   { background: var(--red-500); }
.map-legend-dot-offline { background: var(--slate-300); }

.map-scale-hint {
    position: absolute;
    top: 12px; right: 12px;
    padding: 6px 10px;
    background: rgba(255,255,255,0.85);
    backdrop-filter: blur(8px);
    border: 1px solid var(--border);
    border-radius: 8px;
    font-size: 10px;
    color: var(--text-soft);
    display: flex; align-items: center; gap: 6px;
}

.map-empty {
    position: absolute; inset: 0;
    display: flex; flex-direction: column;
    align-items: center; justify-content: center;
    color: var(--text-mute);
}
.map-empty svg { color: var(--slate-300); margin-bottom: 8px; }
.map-empty p { font-size: 13px; }

/* ---------- 地图设备列表侧栏 ---------- */
.map-side-card {
    padding: 16px;
    display: flex; flex-direction: column;
}
.map-side-head {
    display: flex; align-items: center; justify-content: space-between;
    margin-bottom: 12px;
}
.map-side-title {
    display: flex; align-items: center; gap: 6px;
    font-size: 14px; font-weight: 600;
    margin: 0;
}
.map-side-list {
    flex: 1;
    max-height: 540px;
    overflow-y: auto;
    padding-right: 4px;
}
.map-side-item {
    width: 100%;
    display: flex; align-items: center; gap: 10px;
    padding: 10px 12px;
    border: 1px solid var(--border);
    border-radius: 10px;
    margin-bottom: 8px;
    background: #fff;
    cursor: pointer;
    text-align: left;
    transition: all .15s;
}
.map-side-item:hover { background: var(--slate-50); border-color: var(--slate-300); }
.map-side-item.active {
    border-color: var(--emerald-500);
    background: var(--emerald-50);
}
.map-side-item-marker {
    position: relative;
    flex-shrink: 0;
    width: 10px; height: 10px;
}
.map-side-item-dot {
    display: block;
    width: 10px; height: 10px;
    border-radius: 50%;
}
.map-side-item-dot.online  { background: var(--emerald-500); }
.map-side-item-dot.irrig   { background: var(--red-500); }
.map-side-item-dot.offline { background: var(--slate-300); }
.map-side-item.online .map-side-item-marker::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: 50%;
    background: var(--emerald-500);
    animation: mapSidePing 1.8s ease-out infinite;
    opacity: 0.4;
}
@keyframes mapSidePing {
    0%   { transform: scale(1);   opacity: 0.4; }
    80%  { transform: scale(2.5); opacity: 0; }
    100% { transform: scale(2.5); opacity: 0; }
}
.map-side-item-body {
    flex: 1; min-width: 0;
}
.map-side-item-name {
    font-size: 13px; font-weight: 500;
    color: var(--text);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.map-side-item-loc {
    display: flex; align-items: center; gap: 4px;
    font-size: 11px; color: var(--text-mute);
    margin-top: 2px;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.map-side-item-loc .cal-coord {
    font-family: var(--mono-font, "SFMono-Regular", Menlo, Monaco, Consolas, monospace);
    font-size: 10px;
    opacity: 0.7;
}
.map-side-item-metric {
    text-align: right;
    font-size: 11px;
}
.map-side-item-metric-value {
    font-size: 14px; font-weight: 700;
}
.map-side-item-metric-value.warn { color: var(--red-500); }
.map-side-item-metric-value.ok   { color: var(--emerald-600); }
.map-side-item-metric-label {
    color: var(--text-mute);
    font-size: 10px;
}

/* ---------- 地图设备详情弹窗 ---------- */
.map-popup-overlay {
    position: fixed;
    bottom: 24px; left: 50%;
    transform: translateX(-50%);
    z-index: 60;
    width: calc(100% - 32px);
    max-width: 720px;
    pointer-events: none; /* 容器不挡交互，子元素重新启用 */
}
.map-popup {
    pointer-events: auto;
    background: #fff;
    border-radius: 14px;
    box-shadow: var(--shadow-lg);
    padding: 16px;
    display: flex; align-items: flex-start; gap: 14px;
    border: 1px solid var(--border);
    animation: mapPopupIn .25s ease-out;
}
@keyframes mapPopupIn {
    from { opacity: 0; transform: translateY(20px); }
    to   { opacity: 1; transform: translateY(0); }
}
.map-popup-icon {
    width: 44px; height: 44px;
    border-radius: 12px;
    background: var(--emerald-50);
    color: var(--emerald-600);
    display: flex; align-items: center; justify-content: center;
    flex-shrink: 0;
}
.map-popup-icon.offline {
    background: var(--slate-100);
    color: var(--text-mute);
}
.map-popup-body { flex: 1; min-width: 0; }
.map-popup-title-row {
    display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.map-popup-title-row h3 {
    font-size: 15px; font-weight: 600;
    margin: 0;
}
.map-popup-badge {
    font-size: 11px;
    padding: 2px 8px;
}
.map-popup-badge-irrig {
    background: #fee2e2;
    color: #b91c1c;
    display: inline-flex; align-items: center; gap: 4px;
}
.map-popup-loc {
    font-size: 12px;
    color: var(--text-mute);
    margin: 4px 0 0;
}
.map-popup-metrics {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: 8px;
    margin-top: 12px;
}
.map-popup-metric {
    text-align: center;
    padding: 8px 6px;
    border-radius: 8px;
    background: var(--slate-50);
}
.map-popup-metric-label {
    font-size: 10px;
    color: var(--text-mute);
}
.map-popup-metric-value {
    font-size: 13px;
    font-weight: 700;
    margin-top: 2px;
}
.map-popup-metric-value.emerald { color: var(--emerald-600); }
.map-popup-metric-value.orange  { color: var(--orange-500); }
.map-popup-metric-value.sky     { color: var(--sky-500); }
.map-popup-metric-value.cyan    { color: var(--cyan-600); }
.map-popup-metric-value.slate   { color: var(--text-soft); }
.map-popup-actions {
    display: flex; flex-direction: column; gap: 6px;
}
.map-popup-close {
    width: 28px; height: 28px;
    border-radius: 7px;
    color: var(--text-soft);
    background: transparent;
    display: inline-flex; align-items: center; justify-content: center;
}
.map-popup-close:hover { background: var(--slate-100); color: var(--text); }

/* ---------- 传感器校准页面 ---------- */
.cal-device-select-wrap {
    min-width: 220px;
}
.cal-device-select {
    width: 100%;
    padding: 9px 12px;
    border-radius: 10px;
}

.cal-info-card {
    display: flex;
    align-items: flex-start;
    gap: 14px;
    padding: 16px;
    background: linear-gradient(135deg, #f0f9ff 0%, #ecfeff 100%);
    border: 1px solid #bae6fd;
    margin-bottom: 16px;
}
.cal-info-icon {
    width: 40px; height: 40px;
    border-radius: 10px;
    background: #e0f2fe;
    color: var(--sky-600);
    display: flex; align-items: center; justify-content: center;
    flex-shrink: 0;
}
.cal-info-title {
    font-size: 13px; font-weight: 600;
    color: var(--sky-700);
    margin-bottom: 4px;
}
.cal-info-text {
    font-size: 12px;
    color: var(--text-soft);
    line-height: 1.6;
    margin: 0;
}
.cal-info-text strong { color: var(--text); font-weight: 600; }

.cal-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 16px;
    margin-bottom: 16px;
}
.cal-card {
    padding: 18px;
}
.cal-card-head {
    margin-bottom: 14px;
}
.cal-card-head-row {
    display: flex; align-items: center; justify-content: space-between;
    gap: 12px;
}
.cal-card-title {
    display: flex; align-items: center; gap: 6px;
    font-size: 15px; font-weight: 600;
    margin: 0;
}
.cal-card-sub {
    font-size: 12px;
    color: var(--text-mute);
    margin: 4px 0 0;
}
.cal-card-body { display: flex; flex-direction: column; gap: 16px; }

/* ---------- 校准滑块 ---------- */
.cal-slider {
    -webkit-appearance: none;
    appearance: none;
    width: 100%;
    height: 6px;
    background: var(--slate-200);
    border-radius: 999px;
    outline: none;
    margin: 4px 0;
    cursor: pointer;
}
.cal-slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 18px; height: 18px;
    border-radius: 50%;
    background: var(--emerald-500);
    border: 3px solid #fff;
    box-shadow: 0 1px 4px rgba(16,185,129,0.4);
    cursor: pointer;
    transition: transform .15s;
}
.cal-slider::-webkit-slider-thumb:hover { transform: scale(1.15); }
.cal-slider::-webkit-slider-thumb:active { transform: scale(1.25); }
.cal-slider::-moz-range-thumb {
    width: 18px; height: 18px;
    border-radius: 50%;
    background: var(--emerald-500);
    border: 3px solid #fff;
    box-shadow: 0 1px 4px rgba(16,185,129,0.4);
    cursor: pointer;
}
.cal-slider-depth::-webkit-slider-thumb { background: var(--cyan-500); box-shadow: 0 1px 4px rgba(6,182,212,0.4); }
.cal-slider-depth::-moz-range-thumb     { background: var(--cyan-500); }
.cal-slider-rain::-webkit-slider-thumb  { background: var(--sky-500); box-shadow: 0 1px 4px rgba(14,165,233,0.4); }
.cal-slider-rain::-moz-range-thumb      { background: var(--sky-500); }

.cal-preview-row {
    display: flex; align-items: center; justify-content: space-between;
}
.cal-preview-label {
    display: flex; align-items: center; gap: 6px;
    font-size: 13px; font-weight: 500;
}
.cal-preview-values {
    display: flex; align-items: center; gap: 10px;
    font-size: 12px;
}
.cal-preview-raw {
    color: var(--text-mute);
}
.cal-preview-raw code {
    font-family: var(--mono-font, "SFMono-Regular", Menlo, Monaco, Consolas, monospace);
    color: var(--text-soft);
}
.cal-preview-display {
    display: inline-flex; align-items: center; gap: 4px;
    padding: 3px 10px;
    border-radius: 999px;
    font-size: 12px;
    font-weight: 600;
}
.cal-preview-display-soil   { background: var(--emerald-50);  color: var(--emerald-700); }
.cal-preview-display-depth  { background: var(--cyan-50);      color: var(--cyan-600); }
.cal-preview-display-rain   { background: var(--sky-50);       color: var(--sky-600); }

.cal-slider-scale {
    display: flex; align-items: center; gap: 8px;
    font-size: 11px;
    color: var(--text-mute);
}
.cal-slider-scale code {
    font-family: var(--mono-font, "SFMono-Regular", Menlo, Monaco, Consolas, monospace);
}
.cal-slider-bar {
    flex: 1; height: 6px;
    border-radius: 999px;
}
.cal-slider-bar-soil {
    background: linear-gradient(to right, var(--emerald-500), var(--amber-400));
}

.cal-divider {
    border: none;
    border-top: 1px dashed var(--border);
    margin: 0;
}
.cal-preview-hint {
    display: flex; align-items: flex-start; gap: 6px;
    padding: 10px 12px;
    background: var(--slate-50);
    border-radius: 8px;
    font-size: 11px;
    color: var(--text-soft);
}
.cal-preview-hint svg { flex-shrink: 0; margin-top: 1px; color: var(--amber-500); }

/* ---------- 校准参数卡片 ---------- */
.cal-param-card {
    padding: 12px 14px;
    border-radius: 10px;
    display: flex; flex-direction: column; gap: 10px;
}
.cal-param-soil  { background: rgba(16,185,129,0.06); border: 1px solid rgba(16,185,129,0.15); }
.cal-param-depth { background: rgba(6,182,212,0.06);  border: 1px solid rgba(6,182,212,0.15); }
.cal-param-rain  { background: rgba(14,165,233,0.06); border: 1px solid rgba(14,165,233,0.15); }
.cal-param-temp  { background: rgba(249,115,22,0.06); border: 1px solid rgba(249,115,22,0.15); }

.cal-param-head {
    display: flex; align-items: center; justify-content: space-between;
    gap: 8px;
}
.cal-param-label {
    display: flex; align-items: center; gap: 6px;
    font-size: 13px; font-weight: 600;
}
.cal-param-actions {
    display: flex; gap: 6px;
}
.cal-dry-btn, .cal-wet-btn {
    padding: 4px 10px;
    font-size: 12px;
}
.cal-param-grid-2 {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
}
.cal-param-field {
    display: flex; flex-direction: column; gap: 4px;
}
.cal-param-field-label {
    font-size: 11px;
    color: var(--text-mute);
}
.cal-param-input {
    padding: 6px 10px;
    font-family: var(--mono-font, "SFMono-Regular", Menlo, Monaco, Consolas, monospace);
    font-size: 13px;
    border-radius: 8px;
}

.cal-save-btn {
    width: 100%;
    padding: 12px;
    font-size: 14px;
    font-weight: 600;
    background: linear-gradient(135deg, #10b981 0%, #0d9488 100%);
    border: none;
    color: #fff;
    border-radius: 10px;
    display: inline-flex; align-items: center; justify-content: center; gap: 6px;
    cursor: pointer;
    transition: all .15s;
    box-shadow: var(--shadow-emerald);
}
.cal-save-btn:hover { transform: translateY(-1px); }

/* ---------- 校准状态表 ---------- */
.cal-status-card {
    padding: 18px;
}
.cal-status-table-wrap {
    overflow-x: auto;
}
.cal-status-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 13px;
}
.cal-status-table thead th {
    text-align: left;
    padding: 10px 12px;
    font-weight: 500;
    color: var(--text-mute);
    border-bottom: 1px solid var(--border);
    font-size: 12px;
    white-space: nowrap;
}
.cal-status-table tbody td {
    padding: 12px;
    border-bottom: 1px solid var(--border-soft);
}
.cal-status-row {
    cursor: pointer;
    transition: background .15s;
}
.cal-status-row:hover { background: var(--slate-50); }
.cal-status-row.active { background: var(--emerald-50); }
.cal-status-dot {
    display: inline-block;
    width: 8px; height: 8px;
    border-radius: 50%;
    margin-right: 8px;
    vertical-align: middle;
}
.cal-status-dot-online  { background: var(--emerald-500); }
.cal-status-dot-offline { background: var(--slate-400); }
.cal-status-name {
    font-weight: 500;
    vertical-align: middle;
}
.cal-col-center { text-align: center; }
.cal-col-right  { text-align: right; }
.cal-mono {
    font-family: var(--mono-font, "SFMono-Regular", Menlo, Monaco, Consolas, monospace);
    font-size: 12px;
    color: var(--text-soft);
}
.cal-mute { color: var(--text-mute); }
.cal-status-badge {
    display: inline-flex; align-items: center; gap: 4px;
    padding: 2px 8px;
    font-size: 11px;
}

/* ---------- 响应式 ---------- */
@media (max-width: 1024px) {
    .map-grid { grid-template-columns: 1fr; }
    .cal-grid { grid-template-columns: 1fr; }
    .map-side-list { max-height: 360px; }
}
@media (max-width: 768px) {
    .map-toolbar { gap: 8px; }
    .map-stats { margin-left: 0; width: 100%; flex-wrap: wrap; }
    .map-search-wrap { flex: 1 1 100%; max-width: none; }
    .map-popup-metrics { grid-template-columns: repeat(3, 1fr); }
    .cal-param-grid-2 { grid-template-columns: 1fr; }
    .map-popup { flex-direction: column; }
    .map-popup-actions { flex-direction: row; justify-content: flex-end; }
}
@media (max-width: 540px) {
    .map-popup-metrics { grid-template-columns: repeat(2, 1fr); }
    .cal-status-table .cal-col-center:nth-child(2),
    .cal-status-table .cal-col-center:nth-child(3) { display: none; }
}

/* ============================================================
 * r5-6 新增：灌溉计划页面样式 (.sched-*)
 * ============================================================ */

/* ---------- 通用 badge 类（计划/报表使用） ---------- */
.badge-secondary { background: var(--slate-100); color: var(--text-soft); }
.badge-success   { background: var(--emerald-100); color: var(--emerald-700); display: inline-flex; align-items: center; gap: 3px; }
.badge-warning   { background: #fef3c7; color: #d97706; }

/* ---------- 设备筛选栏 ---------- */
.sched-filter-bar {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin-bottom: 16px;
}
.sched-filter-label {
    font-size: 12px;
    color: var(--text-mute);
    white-space: nowrap;
}
.sched-filter-chips {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 4px;
    background: var(--slate-100);
    border-radius: 10px;
    flex-wrap: wrap;
}
.sched-filter-chip {
    padding: 6px 12px;
    border: none;
    background: transparent;
    color: var(--text-soft);
    font-size: 12px;
    font-weight: 500;
    border-radius: 6px;
    cursor: pointer;
    transition: all .15s;
}
.sched-filter-chip:hover { color: var(--text); }
.sched-filter-chip.active {
    background: var(--card);
    color: var(--emerald-700);
    box-shadow: var(--shadow-sm);
}

/* ---------- 计划卡片 ---------- */
.sched-list {
    display: flex;
    flex-direction: column;
    gap: 12px;
}
.sched-card {
    background: var(--card);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
    padding: 16px;
    display: flex;
    align-items: flex-start;
    gap: 14px;
    transition: box-shadow .15s;
}
.sched-card:hover { box-shadow: var(--shadow); }
.sched-card.is-disabled { opacity: 0.55; }

/* 时间指示器（渐变方块） */
.sched-time-indicator {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    width: 64px;
    height: 64px;
    border-radius: 12px;
    background: linear-gradient(135deg, var(--emerald-500) 0%, var(--teal-600) 100%);
    color: #fff;
    flex-shrink: 0;
    box-shadow: var(--shadow-emerald);
}
.sched-time-indicator svg {
    width: 14px; height: 14px;
    margin-bottom: 2px;
    opacity: 0.9;
}
.sched-time-text {
    font-size: 13px;
    font-weight: 700;
    letter-spacing: 0.5px;
}

/* 主体内容 */
.sched-main {
    flex: 1;
    min-width: 0;
}
.sched-title-row {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px;
    margin-bottom: 8px;
}
.sched-name {
    font-size: 14px;
    font-weight: 600;
    color: var(--text);
}
.sched-device-badge {
    background: var(--slate-100);
    color: var(--text-soft);
    font-size: 11px;
}
.sched-enabled-badge {
    display: inline-flex;
    align-items: center;
    gap: 3px;
}
.sched-today-badge {
    background: #fef3c7;
    color: #d97706;
}

/* 7 天 chips */
.sched-weekday-chips {
    display: flex;
    gap: 4px;
    margin-bottom: 8px;
}
.sched-weekday-chip {
    width: 24px;
    height: 24px;
    border-radius: 6px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 10px;
    font-weight: 500;
    background: var(--slate-100);
    color: var(--text-mute);
}
.sched-weekday-chip.active {
    background: var(--emerald-500);
    color: #fff;
}
.sched-weekday-chip.active.is-today {
    box-shadow: 0 0 0 2px var(--emerald-300);
}

/* 详情行 */
.sched-meta-row {
    display: flex;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
    font-size: 11px;
    color: var(--text-soft);
}
.sched-meta-item {
    display: inline-flex;
    align-items: center;
    gap: 4px;
}
.sched-run-row {
    display: flex;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
    font-size: 11px;
    margin-top: 6px;
    color: var(--text-mute);
}
.sched-run-item strong {
    color: var(--text-soft);
    font-weight: 500;
}
.sched-run-item strong.text-emerald { color: var(--emerald-600); font-weight: 600; }
.sched-run-item strong.text-mute { color: var(--text-mute); }

/* 操作区 */
.sched-actions {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 8px;
    flex-shrink: 0;
}
.sched-run-btn {
    font-size: 11px;
    height: 28px;
    padding: 0 10px;
}
.sched-actions-row {
    display: flex;
    align-items: center;
    gap: 4px;
}

/* ---------- 计划编辑弹窗：weekday picker ---------- */
.sched-weekday-picker {
    display: flex;
    gap: 6px;
    margin-bottom: 8px;
}
.sched-weekday-pick {
    flex: 1;
    padding: 10px 0;
    border: 1px solid var(--border);
    background: var(--card);
    color: var(--text-soft);
    border-radius: 8px;
    cursor: pointer;
    font-size: 12px;
    font-weight: 500;
    transition: all .15s;
}
.sched-weekday-pick:hover {
    background: var(--slate-50);
    border-color: var(--slate-300);
}
.sched-weekday-pick.active {
    background: var(--emerald-500);
    border-color: var(--emerald-500);
    color: #fff;
    box-shadow: var(--shadow-sm);
}
.sched-weekday-quick {
    display: flex;
    gap: 12px;
    align-items: center;
}
.sched-quick-btn {
    padding: 0;
    border: none;
    background: transparent;
    color: var(--emerald-600);
    font-size: 12px;
    cursor: pointer;
    text-decoration: underline;
}
.sched-quick-btn:hover { color: var(--emerald-700); }
.sched-quick-clear {
    color: var(--text-mute);
    text-decoration: none;
    margin-left: auto;
}

/* 触发条件 */
.sched-condition-row {
    display: flex;
    align-items: center;
    gap: 8px;
}
.sched-condition-unit {
    font-size: 14px;
    color: var(--text-soft);
}
.sched-condition-hint {
    font-size: 11px;
    color: var(--text-mute);
    margin-top: 6px;
}

/* 启用行 */
.sched-enabled-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 14px;
    background: var(--slate-50);
    border-radius: 10px;
    margin-top: 4px;
}
.sched-enabled-info {
    display: flex;
    align-items: center;
    gap: 10px;
}
.sched-enabled-title {
    font-size: 13px;
    font-weight: 500;
    color: var(--text);
}
.sched-enabled-desc {
    font-size: 11px;
    color: var(--text-mute);
}

/* ============================================================
 * r5-6 新增：数据报表页面样式 (.report-*)
 * ============================================================ */

.report-config-card {
    padding: 20px;
}
.report-config-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 16px;
    align-items: end;
}
.report-date-range {
    display: flex;
    align-items: center;
    gap: 6px;
}
.report-date-range .form-input {
    flex: 1;
    font-size: 12px;
    padding: 8px 10px;
}
.report-date-sep {
    color: var(--text-mute);
    font-size: 12px;
}
.report-generate-wrap {
    display: flex;
}
.btn-block {
    width: 100%;
    justify-content: center;
}

/* ---------- 报表头（渐变） ---------- */
.report-header {
    background: linear-gradient(135deg, var(--emerald-500) 0%, var(--teal-600) 100%);
    color: #fff;
    border-radius: var(--radius);
    padding: 20px 24px;
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 12px;
    box-shadow: var(--shadow-emerald);
}
.report-header-title {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 6px;
}
.report-header-title h2 {
    font-size: 18px;
    font-weight: 700;
    margin: 0;
    color: #fff;
}
.report-header-meta {
    font-size: 13px;
    color: rgba(255,255,255,0.85);
}
.report-export-buttons {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
}
.btn-report-export {
    background: rgba(255,255,255,0.2);
    color: #fff;
    border: 1px solid rgba(255,255,255,0.3);
    padding: 6px 12px;
    font-size: 12px;
    border-radius: 8px;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    transition: background .15s;
}
.btn-report-export:hover {
    background: rgba(255,255,255,0.3);
}

/* ---------- 4 张统计卡片 ---------- */
.report-stat-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 12px;
    margin-top: 16px;
}
.report-stat-card {
    background: var(--card);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
    padding: 16px;
}
.report-stat-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 8px;
}
.report-stat-label {
    font-size: 11px;
    color: var(--text-mute);
}
.report-stat-value {
    font-size: 20px;
    font-weight: 700;
}
.report-stat-sub {
    font-size: 10px;
    color: var(--text-mute);
    margin-top: 2px;
}
.report-stat-card.stat-soil      .report-stat-value { color: var(--emerald-600); }
.report-stat-card.stat-temp      .report-stat-value { color: var(--orange-500); }
.report-stat-card.stat-humidity  .report-stat-value { color: var(--sky-500); }
.report-stat-card.stat-rain      .report-stat-value { color: var(--cyan-600); }

/* ---------- 3 列网格：灌溉统计 + 在线率 + 数据概览 ---------- */
.report-3col {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 16px;
    margin-top: 16px;
}
.report-card {
    background: var(--card);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
    overflow: hidden;
}
.report-card-head {
    padding: 14px 16px 6px;
    font-size: 14px;
    font-weight: 600;
    color: var(--text);
    display: flex;
    align-items: center;
    gap: 6px;
}
.report-card-body {
    padding: 0 16px 16px;
}

/* 灌溉统计 */
.report-stat-line {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px;
    border-radius: 10px;
    margin-bottom: 10px;
}
.report-stat-line:last-child { margin-bottom: 0; }
.report-stat-line.line-amber   { background: #fffbeb; }
.report-stat-line.line-cyan    { background: #ecfeff; }
.report-stat-line.line-emerald { background: #ecfdf5; }
.report-stat-line .left {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 13px;
    color: var(--text-soft);
}
.report-stat-line .right {
    font-size: 18px;
    font-weight: 700;
}
.report-stat-line.line-amber   .right { color: #d97706; }
.report-stat-line.line-cyan    .right { color: #06b6d4; }
.report-stat-line.line-emerald .right { color: var(--emerald-600); }

/* 在线率图表 */
.report-chart-wrap {
    position: relative;
    height: 180px;
    margin: 0 auto;
}
.report-chart-wrap.center-text::after {
    content: attr(data-text);
    position: absolute;
    top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    font-size: 22px;
    font-weight: 700;
    color: var(--emerald-600);
    pointer-events: none;
}
.report-chart-caption {
    text-align: center;
    font-size: 11px;
    color: var(--text-mute);
    margin-top: 6px;
}

/* 数据概览 */
.report-overview {
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.report-overview-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 13px;
    padding: 6px 0;
}
.report-overview-row + .report-overview-row {
    border-top: 1px solid var(--border-soft);
}
.report-overview-row .label { color: var(--text-mute); }
.report-overview-row .value {
    font-family: var(--mono-font, "SFMono-Regular", Menlo, Monaco, Consolas, monospace);
    font-weight: 600;
    color: var(--text);
}

/* 大图表卡片 */
.report-chart-card {
    background: var(--card);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
    margin-top: 16px;
}
.report-chart-card .report-card-head {
    padding: 16px 16px 0;
}
.report-chart-card .report-card-desc {
    padding: 0 16px;
    font-size: 11px;
    color: var(--text-mute);
    margin-bottom: 8px;
}
.report-chart-canvas {
    height: 280px;
    padding: 8px 16px 16px;
    min-height: 280px;
}
.report-chart-canvas-sm {
    height: 180px;
    padding: 8px 16px 16px;
    min-height: 180px;
}

/* ---------- 响应式 ---------- */
@media (max-width: 1024px) {
    .report-config-grid { grid-template-columns: 1fr 1fr; }
    .report-stat-grid   { grid-template-columns: 1fr 1fr; }
    .report-3col        { grid-template-columns: 1fr; }
}
@media (max-width: 768px) {
    .sched-card { flex-direction: column; align-items: stretch; }
    .sched-actions {
        flex-direction: row;
        justify-content: space-between;
        width: 100%;
        align-items: center;
    }
    .sched-actions-row { gap: 8px; }
    .sched-run-btn { flex: 1; }
}
@media (max-width: 540px) {
    .report-config-grid { grid-template-columns: 1fr; }
    .report-stat-grid   { grid-template-columns: 1fr; }
    .sched-weekday-picker .sched-weekday-pick { padding: 8px 0; font-size: 11px; }
    .report-header { padding: 16px; }
    .report-chart-canvas { height: 220px; min-height: 220px; }
}


/* ============================================================
 * r6-5 新增：OTA 固件升级页面样式 (.ota-*)
 * ============================================================ */

/* ---------- 版本卡片（渐变 header） ---------- */
.ota-version-card {
    background: var(--card);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
    overflow: hidden;
    margin-bottom: 16px;
}
.ota-version-header {
    background: linear-gradient(135deg, var(--emerald-500) 0%, var(--teal-600) 100%);
    color: #fff;
    padding: 20px 24px;
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 12px;
    box-shadow: var(--shadow-emerald);
}
.ota-version-header-left { flex: 1; min-width: 220px; }
.ota-version-title-row {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 4px;
}
.ota-version-title-row h3 {
    margin: 0;
    font-size: 18px;
    font-weight: 700;
    color: #fff;
}
.ota-version-meta {
    font-size: 13px;
    color: rgba(255,255,255,0.85);
}
.ota-version-download {
    background: rgba(255,255,255,0.2);
    color: #fff;
    border: 1px solid rgba(255,255,255,0.3);
    padding: 7px 14px;
    font-size: 12px;
    border-radius: 8px;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    text-decoration: none;
    transition: background .15s;
}
.ota-version-download:hover {
    background: rgba(255,255,255,0.3);
    text-decoration: none;
    color: #fff;
}
.ota-version-body { padding: 20px 24px; }
.ota-changelog-title {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 14px;
    font-weight: 600;
    margin-bottom: 10px;
    color: var(--text);
}
.ota-changelog-list {
    list-style: none;
    padding: 0;
    margin: 0 0 16px;
}
.ota-changelog-list li {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    padding: 4px 0;
    font-size: 13px;
    color: var(--text-soft);
}
.ota-changelog-list li svg { flex-shrink: 0; margin-top: 3px; }
.ota-checksum-row {
    display: flex;
    align-items: center;
    gap: 4px;
    padding-top: 12px;
    border-top: 1px solid var(--border-soft);
    font-size: 11px;
    color: var(--text-mute);
}
.ota-checksum {
    font-family: "SFMono-Regular", Menlo, Monaco, Consolas, monospace;
    color: var(--text-soft);
    background: var(--slate-50);
    padding: 2px 6px;
    border-radius: 4px;
}

/* ---------- 设备固件列表 ---------- */
.ota-device-list {
    display: flex;
    flex-direction: column;
    gap: 12px;
    margin-bottom: 16px;
}
.ota-device-card {
    background: var(--card);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
    overflow: hidden;
    transition: box-shadow .15s;
}
.ota-device-card:hover { box-shadow: var(--shadow); }
.ota-device-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px 16px;
    cursor: pointer;
    transition: background .15s;
}
.ota-device-row:hover { background: rgba(241,245,249,0.6); }

.ota-device-icon {
    flex-shrink: 0;
    width: 44px;
    height: 44px;
    border-radius: 12px;
    display: flex;
    align-items: center;
    justify-content: center;
}
.ota-icon-available,
.ota-icon-upgrading,
.ota-icon-success,
.ota-icon-idle,
.ota-icon-failed {
    display: flex;
    align-items: center;
    justify-content: center;
}
.ota-icon-available { background: #fef3c7; color: #d97706; }
.ota-icon-upgrading { background: #e0f2fe; color: #0284c7; }
.ota-icon-success   { background: #d1fae5; color: #059669; }
.ota-icon-idle      { background: #f1f5f9; color: #94a3b8; }
.ota-icon-failed    { background: #fee2e2; color: #dc2626; }

.ota-device-info { flex: 1; min-width: 0; }
.ota-device-title-row {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}
.ota-device-name {
    font-size: 14px;
    font-weight: 600;
    color: var(--text);
}
.ota-version-badge {
    font-family: "SFMono-Regular", Menlo, Monaco, Consolas, monospace;
    font-size: 11px;
    font-weight: 500;
}
.ota-update-badge {
    background: #fef3c7;
    color: #b45309;
    font-size: 11px;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 8px;
    border-radius: 9999px;
    font-weight: 500;
}
.ota-upgrading-badge {
    background: #e0f2fe;
    color: #0369a1;
    font-size: 11px;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 8px;
    border-radius: 9999px;
    font-weight: 500;
}
.ota-device-sub {
    font-size: 11px;
    color: var(--text-mute);
    margin-top: 3px;
}

/* 进度条 */
.ota-progress-bar-wrap {
    flex: 0 0 130px;
    height: 6px;
    background: var(--slate-100);
    border-radius: 9999px;
    overflow: hidden;
    margin: 0 8px;
}
.ota-progress-bar {
    height: 100%;
    background: linear-gradient(90deg, var(--sky-500), var(--cyan-500));
    border-radius: 9999px;
    transition: width .35s ease;
    position: relative;
}
.ota-progress-bar::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg, transparent, rgba(255,255,255,0.4), transparent);
    animation: ota-progress-shine 1.5s linear infinite;
}
@keyframes ota-progress-shine {
    0%   { transform: translateX(-100%); }
    100% { transform: translateX(100%); }
}

.ota-device-actions {
    display: flex;
    align-items: center;
    gap: 6px;
}
.ota-chevron {
    transition: transform .2s;
}
.ota-device-card.expanded .ota-chevron {
    transform: rotate(90deg);
}

/* ---------- 升级历史面板 ---------- */
.ota-history-panel {
    border-top: 1px solid var(--border-soft);
    background: var(--slate-50);
    padding: 16px;
}
.ota-history-head {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 13px;
    font-weight: 600;
    color: var(--text);
    margin-bottom: 12px;
}
.ota-history-empty {
    padding: 16px;
    text-align: center;
    font-size: 13px;
    color: var(--text-mute);
}
.ota-history-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.ota-history-item {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 12px;
    background: var(--card);
    border-radius: 10px;
    border: 1px solid var(--border-soft);
}
.ota-history-icon {
    flex-shrink: 0;
    width: 32px;
    height: 32px;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
}
.ota-history-info { flex: 1; min-width: 0; }
.ota-history-version {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
}
.ota-version-code {
    font-family: "SFMono-Regular", Menlo, Monaco, Consolas, monospace;
    font-size: 11px;
    color: var(--text-soft);
    background: var(--slate-50);
    padding: 1px 6px;
    border-radius: 4px;
}
.ota-version-code.strong { color: var(--emerald-700); background: var(--emerald-50); font-weight: 600; }
.ota-history-time {
    font-size: 11px;
    color: var(--text-mute);
    margin-top: 2px;
}
.ota-history-meta {
    text-align: right;
    font-size: 11px;
}
.ota-history-duration {
    display: flex;
    align-items: center;
    gap: 3px;
    color: var(--text-mute);
    justify-content: flex-end;
}
.ota-history-error {
    color: #dc2626;
    margin-top: 2px;
}

/* ---------- 安全提示卡片 ---------- */
.ota-safety-card {
    background: linear-gradient(135deg, #fffbeb 0%, #fff7ed 100%);
    border: 1px solid #fed7aa;
    border-radius: var(--radius);
    padding: 16px;
    display: flex;
    gap: 12px;
    margin-bottom: 16px;
}
.ota-safety-icon {
    flex-shrink: 0;
    width: 40px;
    height: 40px;
    background: #fef3c7;
    border-radius: 10px;
    display: flex;
    align-items: center;
    justify-content: center;
}
.ota-safety-content { flex: 1; }
.ota-safety-title {
    font-size: 13px;
    font-weight: 600;
    color: #92400e;
    margin-bottom: 6px;
}
.ota-safety-list {
    list-style: none;
    padding: 0;
    margin: 0;
    font-size: 12px;
    color: var(--text-soft);
}
.ota-safety-list li {
    padding: 2px 0;
    position: relative;
    padding-left: 12px;
}
.ota-safety-list li::before {
    content: '•';
    position: absolute;
    left: 0;
    color: #d97706;
}

.spin {
    animation: ota-spin 1s linear infinite;
}
@keyframes ota-spin {
    0% { transform: rotate(0); }
    100% { transform: rotate(360deg); }
}

/* ---------- 响应式 ---------- */
@media (max-width: 768px) {
    .ota-version-header { padding: 16px; }
    .ota-device-row { flex-wrap: wrap; }
    .ota-progress-bar-wrap { flex: 1 0 100%; margin: 8px 0 0; }
    .ota-history-item { flex-wrap: wrap; }
}
@media (max-width: 540px) {
    .ota-version-title-row h3 { font-size: 16px; }
    .ota-device-name { font-size: 13px; }
}


/* ============================================================
 * r6-5 新增：设备共享页面样式 (.share-*)
 * ============================================================ */

/* 设备筛选 chip */
.share-filter-bar {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    margin-bottom: 12px;
}
.share-filter-label {
    font-size: 11px;
    color: var(--text-mute);
}
.share-filter-chips {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 4px;
    background: var(--slate-50);
    border-radius: 10px;
    flex-wrap: wrap;
}
.share-filter-chip {
    padding: 6px 12px;
    font-size: 12px;
    border-radius: 7px;
    color: var(--text-soft);
    background: transparent;
    border: none;
    cursor: pointer;
    transition: all .15s;
    font-weight: 500;
}
.share-filter-chip.active {
    background: #fff;
    color: var(--emerald-700);
    box-shadow: var(--shadow-sm);
}
.share-filter-chip:hover:not(.active) {
    background: rgba(255,255,255,0.6);
}

/* 共享列表 */
.share-list {
    display: flex;
    flex-direction: column;
    gap: 12px;
    margin-bottom: 16px;
}
.share-card {
    background: var(--card);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
    padding: 14px 16px;
    display: flex;
    align-items: flex-start;
    gap: 12px;
    transition: opacity .15s, box-shadow .15s;
}
.share-card:hover { box-shadow: var(--shadow); }
.share-card.is-revoked { opacity: 0.6; }

.share-avatar {
    flex-shrink: 0;
    width: 44px;
    height: 44px;
    border-radius: 50%;
    background: linear-gradient(135deg, var(--emerald-400), var(--teal-500));
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 14px;
    font-weight: 600;
}
.share-info { flex: 1; min-width: 0; }
.share-title-row {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    margin-bottom: 4px;
}
.share-user-name {
    font-size: 14px;
    font-weight: 600;
    color: var(--text);
}
.share-device-badge {
    font-size: 11px;
    font-weight: 500;
}
.share-status-badge {
    font-size: 11px;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 8px;
    border-radius: 9999px;
    font-weight: 500;
}
.share-email {
    font-size: 12px;
    color: var(--text-mute);
    margin-bottom: 8px;
}

/* 权限选择 */
.share-perm-row {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 6px;
}
.share-perm-label {
    font-size: 11px;
    color: var(--text-mute);
}
.share-perm-select {
    height: 28px;
    padding: 0 8px;
    font-size: 12px;
    border-radius: 6px;
    border: 1px solid var(--border);
    background: var(--card);
    color: var(--text);
    cursor: pointer;
    width: auto;
    min-width: 110px;
}
.share-perm-select:focus {
    outline: none;
    border-color: var(--emerald-500);
}
.share-perm-select:disabled {
    background: var(--slate-50);
    cursor: not-allowed;
    color: var(--text-mute);
}
.share-perm-badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 3px 8px;
    border-radius: 6px;
    font-size: 10px;
    font-weight: 500;
}
.perm-view    { background: #e0f2fe; color: #0369a1; }
.perm-control { background: #fef3c7; color: #b45309; }
.perm-admin   { background: #f3e8ff; color: #7c3aed; }

.share-time-row {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-top: 6px;
}
.share-time-item {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    font-size: 11px;
    color: var(--text-mute);
}

.share-actions {
    display: flex;
    align-items: center;
    gap: 4px;
    flex-shrink: 0;
}

/* 快速共享链接卡片 */
.share-link-card { margin-bottom: 16px; }
.share-link-title {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 14px;
    font-weight: 600;
    color: var(--text);
}
.share-link-desc {
    font-size: 11px;
    color: var(--text-mute);
    margin-top: 2px;
}
.share-link-config {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 12px;
    flex-wrap: wrap;
}
.share-link-config .form-input {
    flex: 1;
    min-width: 160px;
}
.share-link-box {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 12px;
    background: #ecfdf5;
    border: 1px solid #a7f3d0;
    border-radius: 8px;
    margin-bottom: 12px;
}
.share-link-input {
    flex: 1;
    border: none;
    background: transparent;
    font-family: "SFMono-Regular", Menlo, Monaco, Consolas, monospace;
    font-size: 12px;
    color: var(--emerald-700);
    outline: none;
    min-width: 0;
}

/* 权限说明卡片 */
.share-perm-explain {
    display: flex;
    gap: 8px;
    padding: 12px;
    background: #fffbeb;
    border: 1px solid #fde68a;
    border-radius: 8px;
}
.share-perm-explain-title {
    font-size: 12px;
    font-weight: 600;
    color: #92400e;
    margin-bottom: 4px;
}
.share-perm-explain-list {
    list-style: none;
    padding: 0;
    margin: 0;
    font-size: 11px;
    color: var(--text-soft);
}
.share-perm-explain-list li { padding: 2px 0; }
.share-perm-explain-list strong { color: var(--text); font-weight: 600; }

/* 权限 radio 选择卡片（弹窗中） */
.share-perm-radio-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.share-perm-radio {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 12px;
    border: 1px solid var(--border);
    border-radius: 10px;
    cursor: pointer;
    transition: all .15s;
}
.share-perm-radio:hover { background: var(--slate-50); }
.share-perm-radio.selected {
    border-color: var(--emerald-500);
    background: var(--emerald-50);
}
.share-perm-radio-icon {
    flex-shrink: 0;
    width: 32px;
    height: 32px;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
}
.share-perm-radio-info { flex: 1; }
.share-perm-radio-title {
    font-size: 13px;
    font-weight: 600;
    color: var(--text);
}
.share-perm-radio-desc {
    font-size: 11px;
    color: var(--text-mute);
    margin-top: 2px;
}

/* ---------- 响应式 ---------- */
@media (max-width: 768px) {
    .share-card { flex-wrap: wrap; }
    .share-actions { width: 100%; justify-content: flex-end; margin-top: 4px; }
    .share-link-config { flex-direction: column; align-items: stretch; }
    .share-link-config .form-input { min-width: 0; }
}
@media (max-width: 540px) {
    .share-avatar { width: 36px; height: 36px; font-size: 12px; }
    .share-perm-row { flex-wrap: wrap; }
    .share-time-row { flex-direction: column; align-items: flex-start; gap: 4px; }
}

/* ============================================================
 * r7-5 新增：场景模式（scene.php）
 * ============================================================ */

/* 当前场景卡（渐变背景） */
.scene-current-card {
    border-radius: var(--radius-lg);
    padding: 20px;
    color: #fff;
    box-shadow: var(--shadow-md);
    margin-bottom: 16px;
    transition: background 0.4s ease;
}
.scene-current-top {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    flex-wrap: wrap;
    gap: 12px;
}
.scene-current-info {
    display: flex;
    align-items: center;
    gap: 14px;
}
.scene-current-icon {
    width: 56px;
    height: 56px;
    border-radius: 16px;
    background: rgba(255,255,255,0.2);
    backdrop-filter: blur(8px);
    border: 1px solid rgba(255,255,255,0.3);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 28px;
    line-height: 1;
}
.scene-current-name {
    font-size: 20px;
    font-weight: 700;
    margin: 0;
}
.scene-current-desc {
    font-size: 13px;
    color: rgba(255,255,255,0.85);
    margin: 4px 0 0;
}
.scene-current-badge {
    padding: 4px 10px;
    background: rgba(255,255,255,0.2);
    border: 1px solid rgba(255,255,255,0.3);
    border-radius: 9999px;
    font-size: 11px;
    font-weight: 600;
    color: #fff;
}
.scene-current-params {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 10px;
    margin-top: 16px;
}
.scene-param-box {
    padding: 10px;
    background: rgba(255,255,255,0.1);
    backdrop-filter: blur(6px);
    border-radius: 8px;
}
.scene-param-label {
    font-size: 11px;
    color: rgba(255,255,255,0.75);
    margin-bottom: 4px;
}
.scene-param-value {
    font-size: 14px;
    font-weight: 700;
    color: #fff;
}
@media (max-width: 640px) {
    .scene-current-params { grid-template-columns: repeat(2, 1fr); }
}

/* 场景区块标题 */
.scene-section-title {
    font-size: 15px;
    font-weight: 600;
    color: var(--text);
    margin: 0 0 14px;
}

/* 场景选择网格 */
.scene-grid {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: 12px;
}
@media (max-width: 960px) { .scene-grid { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 640px) { .scene-grid { grid-template-columns: repeat(2, 1fr); } }

.scene-option {
    position: relative;
    padding: 14px 12px;
    border: 2px solid var(--border);
    border-radius: 12px;
    background: var(--card);
    text-align: left;
    cursor: pointer;
    transition: all 0.18s ease;
    font-family: inherit;
}
.scene-option:hover {
    transform: translateY(-2px);
    border-color: var(--emerald-300);
    box-shadow: var(--shadow);
}
.scene-option.active {
    box-shadow: var(--shadow-md);
    border-color: transparent;
}
.scene-option-check {
    position: absolute;
    top: 8px;
    right: 8px;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
}
.scene-option-icon {
    font-size: 28px;
    margin-bottom: 8px;
    line-height: 1;
}
.scene-option-name {
    font-size: 13px;
    font-weight: 600;
    color: var(--text);
    margin-bottom: 4px;
}
.scene-option-desc {
    font-size: 11px;
    color: var(--text-mute);
    line-height: 1.4;
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    min-height: 30px;
}
.scene-option-dots {
    display: flex;
    gap: 4px;
    margin-top: 8px;
}
.scene-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--slate-300);
}
.scene-dot.on { background: var(--emerald-500); }

/* 自定义场景面板 */
.scene-custom-panel { margin-top: 16px; }
.scene-custom-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 12px;
    background: var(--slate-50);
    border-radius: 8px;
    margin-bottom: 10px;
}
.scene-custom-info { flex: 1; min-width: 0; }
.scene-custom-name {
    font-size: 13px;
    font-weight: 500;
    color: var(--text);
}
.scene-custom-desc {
    font-size: 11px;
    color: var(--text-mute);
    margin-top: 2px;
}
.scene-custom-slider-row { flex-direction: column; align-items: stretch; }
.scene-custom-slider-head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 8px;
}
.scene-custom-threshold-value {
    font-size: 14px;
    font-weight: 700;
    color: var(--amber-500);
}
.scene-slider {
    width: 100%;
    -webkit-appearance: none;
    appearance: none;
    height: 6px;
    background: var(--slate-200);
    border-radius: 9999px;
    outline: none;
}
.scene-slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: var(--amber-500);
    cursor: pointer;
    box-shadow: 0 1px 3px rgba(245,158,11,0.5);
}
.scene-slider::-moz-range-thumb {
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: var(--amber-500);
    cursor: pointer;
    border: none;
}
.scene-slider-marks {
    display: flex;
    justify-content: space-between;
    font-size: 10px;
    color: var(--text-mute);
    margin-top: 4px;
}
.scene-custom-actions {
    margin-top: 16px;
    display: flex;
    justify-content: flex-end;
}

/* 场景对比表 */
.scene-comparison-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 13px;
}
.scene-comparison-table th {
    padding: 10px 12px;
    text-align: left;
    font-weight: 500;
    color: var(--text-mute);
    border-bottom: 1px solid var(--border);
    font-size: 12px;
}
.scene-comparison-table td {
    padding: 12px;
    border-bottom: 1px solid var(--border-soft);
    cursor: pointer;
    transition: background 0.15s;
}
.scene-comparison-table tr:hover td { background: var(--slate-50); }
.scene-comparison-table tr.is-active td { background: var(--emerald-50); }
.scene-comparison-table tr.is-active td:first-child { box-shadow: inset 3px 0 0 var(--emerald-500); }
.scene-compare-name {
    display: flex;
    align-items: center;
    gap: 8px;
    font-weight: 500;
}
.scene-compare-icon { font-size: 18px; }
.scene-compare-badge {
    font-size: 10px;
    padding: 2px 6px;
    border-radius: 4px;
    font-weight: 600;
}
.scene-compare-dash { color: var(--slate-300); }
.scene-threshold { font-family: "SFMono-Regular", Menlo, monospace; }

/* 场景说明卡 */
.scene-info-card {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 16px;
    margin-top: 16px;
    background: linear-gradient(135deg, #f0f9ff 0%, #ecfeff 100%);
    border: 1px solid #bae6fd;
    border-radius: var(--radius);
}
.scene-info-icon {
    flex-shrink: 0;
    width: 40px;
    height: 40px;
    border-radius: 10px;
    background: #e0f2fe;
    display: flex;
    align-items: center;
    justify-content: center;
}
.scene-info-title {
    font-size: 13px;
    font-weight: 600;
    color: #0369a1;
    margin-bottom: 4px;
}
.scene-info-text {
    font-size: 12px;
    color: var(--text-soft);
    line-height: 1.6;
    margin: 0;
}
.scene-info-text strong { color: var(--text); font-weight: 600; }

/* ============================================================
 * r7-5 新增：消耗统计（consumption.php）
 * ============================================================ */

.cons-head-actions {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}
.cons-range-tabs {
    display: inline-flex;
    padding: 3px;
    background: var(--slate-100);
    border-radius: 8px;
    gap: 2px;
}
.cons-range-tab {
    padding: 5px 12px;
    border: none;
    background: transparent;
    border-radius: 6px;
    font-size: 12px;
    color: var(--text-mute);
    cursor: pointer;
    transition: all 0.15s;
    font-family: inherit;
}
.cons-range-tab:hover { color: var(--text-soft); }
.cons-range-tab.active {
    background: var(--card);
    color: var(--text);
    box-shadow: var(--shadow-sm);
    font-weight: 600;
}

/* KPI 卡片 */
.cons-kpi-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 12px;
    margin-bottom: 16px;
}
@media (max-width: 900px) { .cons-kpi-grid { grid-template-columns: repeat(2, 1fr); } }

.cons-kpi-card {
    background: var(--card);
    border-radius: var(--radius);
    padding: 14px;
    box-shadow: var(--shadow-sm);
    border: 1px solid var(--border-soft);
}
.cons-kpi-head {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    margin-bottom: 10px;
}
.cons-kpi-icon {
    width: 32px;
    height: 32px;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
}
.cons-kpi-water     { background: linear-gradient(135deg, #06b6d4, #0284c7); }
.cons-kpi-energy    { background: linear-gradient(135deg, #f59e0b, #ea580c); }
.cons-kpi-irrigation{ background: linear-gradient(135deg, #10b981, #0d9488); }
.cons-kpi-cost      { background: linear-gradient(135deg, #8b5cf6, #db2777); }

.cons-trend {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    font-size: 11px;
    font-weight: 600;
    padding: 2px 6px;
    border-radius: 4px;
}
.cons-trend.up   { color: var(--red-500);   background: #fef2f2; }
.cons-trend.down { color: var(--emerald-600); background: var(--emerald-50); }

.cons-kpi-value {
    font-size: 24px;
    font-weight: 700;
    color: var(--text);
    font-variant-numeric: tabular-nums;
}
.cons-kpi-unit {
    font-size: 13px;
    color: var(--text-mute);
    margin-left: 4px;
    font-weight: 500;
}
.cons-kpi-label {
    font-size: 12px;
    color: var(--text-soft);
    margin-top: 4px;
}
.cons-kpi-sub {
    font-size: 10px;
    color: var(--text-mute);
    margin-top: 2px;
}

/* 区块标题 */
.cons-section-title {
    font-size: 15px;
    font-weight: 600;
    color: var(--text);
    margin: 0 0 12px;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
}
.cons-section-sub {
    font-size: 11px;
    font-weight: 400;
    color: var(--text-mute);
    margin-left: 8px;
}

.cons-chart-wrap {
    position: relative;
    width: 100%;
}

/* 双图行 */
.cons-charts-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
    margin-bottom: 16px;
}
@media (max-width: 900px) { .cons-charts-row { grid-template-columns: 1fr; } }

/* 设备消耗明细表 */
.cons-device-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 13px;
}
.cons-device-table th {
    padding: 10px 12px;
    text-align: left;
    font-weight: 500;
    color: var(--text-mute);
    border-bottom: 1px solid var(--border);
    font-size: 12px;
}
.cons-device-table td {
    padding: 12px;
    border-bottom: 1px solid var(--border-soft);
}
.cons-device-table tr:hover td { background: var(--slate-50); }
.cons-device-name { font-weight: 500; color: var(--text); }
.cons-water       { color: var(--cyan-600);   font-family: "SFMono-Regular", Menlo, monospace; }
.cons-energy      { color: var(--amber-500);  font-family: "SFMono-Regular", Menlo, monospace; }
.cons-cost        { color: var(--text);       font-family: "SFMono-Regular", Menlo, monospace; font-weight: 600; }
.cons-cost-strong { color: var(--emerald-600); font-family: "SFMono-Regular", Menlo, monospace; font-weight: 700; }
.cons-mute        { color: var(--text-mute); }
.cons-empty-row   { text-align: center; color: var(--text-mute); padding: 30px 12px; }

.cons-pct-bar-wrap {
    display: flex;
    align-items: center;
    gap: 8px;
    justify-content: center;
}
.cons-pct-bar {
    width: 80px;
    height: 6px;
    background: var(--slate-100);
    border-radius: 9999px;
    overflow: hidden;
}
.cons-pct-fill {
    height: 100%;
    background: linear-gradient(90deg, #06b6d4, #0ea5e9);
    border-radius: 9999px;
    transition: width 0.4s ease;
}
.cons-pct-text {
    font-size: 11px;
    color: var(--text-mute);
    width: 40px;
    text-align: left;
    font-family: "SFMono-Regular", Menlo, monospace;
}

.cons-device-table tfoot td {
    border-top: 2px solid var(--border);
    border-bottom: none;
    font-weight: 600;
    padding-top: 12px;
    padding-bottom: 12px;
}

/* 节能建议卡片 */
.cons-tips-card {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 16px;
    margin-top: 16px;
    background: linear-gradient(135deg, #ecfdf5 0%, #f0fdfa 100%);
    border: 1px solid #a7f3d0;
    border-radius: var(--radius);
}
.cons-tips-icon {
    flex-shrink: 0;
    width: 40px;
    height: 40px;
    border-radius: 10px;
    background: #d1fae5;
    display: flex;
    align-items: center;
    justify-content: center;
}
.cons-tips-title {
    font-size: 13px;
    font-weight: 600;
    color: var(--emerald-700);
    margin-bottom: 6px;
}
.cons-tips-list {
    list-style: none;
    padding: 0;
    margin: 0;
    font-size: 12px;
    color: var(--text-soft);
    line-height: 1.8;
}
.cons-tips-list li { padding: 1px 0; }

/* ============================================================
 * r8-5 新增：AI 智能建议页面样式（.ai-* 前缀）
 * ============================================================ */

/* AI 引擎卡（渐变） */
.ai-engine-card {
    background: linear-gradient(135deg, #10b981 0%, #14b8a6 50%, #06b6d4 100%);
    border-radius: var(--radius-lg);
    padding: 20px;
    color: #fff;
    margin-bottom: 16px;
    box-shadow: var(--shadow-emerald);
    overflow: hidden;
}
.ai-engine-top { display: flex; align-items: flex-start; gap: 14px; }
.ai-engine-icon {
    flex-shrink: 0;
    width: 56px; height: 56px;
    border-radius: 16px;
    background: rgba(255,255,255,0.2);
    backdrop-filter: blur(8px);
    border: 1px solid rgba(255,255,255,0.3);
    display: flex; align-items: center; justify-content: center;
    color: #fff;
}
.ai-engine-info { flex: 1; min-width: 0; }
.ai-engine-title-row { display: flex; align-items: center; gap: 8px; margin-bottom: 4px; }
.ai-engine-title-row h2 { font-size: 18px; font-weight: 700; margin: 0; }
.ai-engine-version {
    font-size: 11px;
    background: rgba(255,255,255,0.2);
    color: #fff;
    padding: 2px 8px;
    border-radius: 9999px;
    border: 1px solid rgba(255,255,255,0.3);
}
.ai-engine-meta { font-size: 13px; color: rgba(255,255,255,0.85); margin: 0 0 12px; }
.ai-engine-meta strong { color: #fff; font-weight: 700; }
.ai-engine-progress {
    width: 100%;
    height: 6px;
    background: rgba(255,255,255,0.2);
    border-radius: 9999px;
    overflow: hidden;
}
.ai-engine-progress-bar {
    height: 100%;
    background: #fff;
    border-radius: 9999px;
    transition: width 0.5s ease;
}
.ai-engine-progress-label {
    font-size: 11px;
    color: rgba(255,255,255,0.7);
    margin-top: 4px;
    text-align: right;
}

/* 统计卡片 */
.ai-stat-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 12px;
    margin-bottom: 16px;
}
@media (max-width: 900px) { .ai-stat-grid { grid-template-columns: repeat(2, 1fr); } }
.ai-stat-card {
    background: var(--card);
    border-radius: var(--radius);
    padding: 14px;
    box-shadow: var(--shadow-sm);
    border: 1px solid var(--border-soft);
    display: flex;
    align-items: center;
    gap: 12px;
}
.ai-stat-icon {
    width: 36px; height: 36px;
    border-radius: 8px;
    display: flex; align-items: center; justify-content: center;
    color: #fff;
    flex-shrink: 0;
}
.ai-stat-amber   { background: linear-gradient(135deg, #f59e0b, #ea580c); }
.ai-stat-red     { background: linear-gradient(135deg, #ef4444, #e11d48); }
.ai-stat-emerald { background: linear-gradient(135deg, #10b981, #0d9488); }
.ai-stat-sky     { background: linear-gradient(135deg, #0ea5e9, #0284c7); }
.ai-stat-label   { font-size: 12px; color: var(--text-soft); }
.ai-stat-value   { font-size: 22px; font-weight: 700; color: var(--text); line-height: 1.2; }

/* 类型筛选 */
.ai-filter-bar {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    margin-bottom: 14px;
}
.ai-filter-label {
    font-size: 12px;
    color: var(--text-mute);
    display: inline-flex;
    align-items: center;
    gap: 4px;
}
.ai-filter-chip {
    padding: 6px 12px;
    border-radius: 6px;
    font-size: 12px;
    font-weight: 500;
    border: 1px solid transparent;
    background: transparent;
    color: var(--text-mute);
    cursor: pointer;
    transition: all 0.2s;
    display: inline-flex;
    align-items: center;
    gap: 4px;
}
.ai-filter-chip:hover { background: var(--slate-100); color: var(--text); }
.ai-filter-chip.active {
    background: var(--card);
    color: var(--text);
    border-color: var(--border);
    box-shadow: var(--shadow-sm);
}

/* 建议列表 */
.ai-rec-list { display: flex; flex-direction: column; gap: 12px; }
.ai-rec-card {
    background: var(--card);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
    border: 1px solid var(--border-soft);
    overflow: hidden;
    transition: opacity 0.2s;
}
.ai-rec-card.is-resolved { opacity: 0.6; }
.ai-rec-card.is-dismissed { opacity: 0.4; }
.ai-rec-card .ai-rec-main {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 14px;
    cursor: pointer;
    transition: background 0.2s;
}
.ai-rec-card .ai-rec-main:hover { background: var(--slate-50); }
.ai-rec-type-icon {
    width: 44px; height: 44px;
    border-radius: 12px;
    display: flex; align-items: center; justify-content: center;
    font-size: 24px;
    flex-shrink: 0;
    background: var(--slate-100);
}
.ai-rec-card.pri-high .ai-rec-type-icon    { background: #fef2f2; }
.ai-rec-card.pri-medium .ai-rec-type-icon  { background: #fffbeb; }
.ai-rec-card.pri-low .ai-rec-type-icon     { background: #f0f9ff; }
.ai-rec-body { flex: 1; min-width: 0; }
.ai-rec-head {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    margin-bottom: 4px;
}
.ai-rec-title { font-size: 14px; font-weight: 600; color: var(--text); }
.ai-rec-pri {
    font-size: 11px;
    padding: 2px 8px;
    border-radius: 4px;
    font-weight: 500;
    border: 1px solid;
}
.ai-pri-high   { color: #dc2626; background: #fef2f2; border-color: #fecaca; }
.ai-pri-medium { color: #d97706; background: #fffbeb; border-color: #fde68a; }
.ai-pri-low    { color: #0284c7; background: #f0f9ff; border-color: #bae6fd; }
.ai-rec-device {
    font-size: 11px;
    padding: 2px 8px;
    border-radius: 4px;
    background: var(--slate-100);
    color: var(--text-soft);
}
.ai-rec-tag {
    font-size: 11px;
    padding: 2px 6px;
    border-radius: 4px;
    display: inline-flex;
    align-items: center;
    gap: 2px;
}
.ai-rec-tag.tag-applied   { color: #059669; background: #d1fae5; }
.ai-rec-tag.tag-dismissed { color: var(--text-mute); background: var(--slate-100); }
.ai-rec-desc {
    font-size: 13px;
    color: var(--text-soft);
    margin: 0 0 8px;
    line-height: 1.5;
}
.ai-rec-confidence {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}
.ai-conf-label { font-size: 11px; color: var(--text-mute); }
.ai-conf-bar-wrap { display: flex; align-items: center; gap: 6px; }
.ai-conf-bar {
    width: 80px; height: 6px;
    background: var(--slate-100);
    border-radius: 9999px;
    overflow: hidden;
}
.ai-conf-fill {
    height: 100%;
    border-radius: 9999px;
    transition: width 0.4s ease;
}
.ai-conf-fill.high   { background: var(--emerald-500); }
.ai-conf-fill.medium { background: var(--amber-500); }
.ai-conf-fill.low    { background: var(--slate-400); }
.ai-conf-value {
    font-size: 11px;
    font-weight: 600;
    color: var(--text);
    font-family: "SFMono-Regular", Menlo, monospace;
}
.ai-rec-time { font-size: 11px; color: var(--text-mute); }
.ai-rec-chevron {
    flex-shrink: 0;
    color: var(--text-mute);
    transition: transform 0.2s;
}
.ai-rec-card.expanded .ai-rec-chevron { transform: rotate(90deg); }

/* 展开详情 */
.ai-rec-detail {
    padding: 14px;
    background: var(--slate-50);
    border-top: 1px solid var(--border-soft);
}
.ai-detail-section { margin-bottom: 8px; }
.ai-detail-label {
    font-size: 12px;
    font-weight: 600;
    color: var(--emerald-700);
    margin-bottom: 4px;
    display: flex;
    align-items: center;
    gap: 6px;
}
.ai-detail-label.sky { color: var(--sky-600); }
.ai-detail-text {
    font-size: 13px;
    color: var(--text-soft);
    line-height: 1.6;
    margin: 0;
}
.ai-detail-sep { border: none; border-top: 1px dashed var(--border); margin: 10px 0; }
.ai-detail-actions {
    display: flex;
    gap: 8px;
    margin-top: 10px;
    padding-top: 8px;
}

/* 空状态 */
.ai-empty {
    text-align: center;
    padding: 48px 16px;
    color: var(--text-mute);
}
.ai-empty-title { font-size: 14px; font-weight: 600; margin: 8px 0 4px; color: var(--text); }
.ai-empty-desc  { font-size: 12px; }

/* ============================================================
 * r8-5 新增：Webhook 集成页面样式（.wh-* 前缀）
 * ============================================================ */

.wh-stat-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 12px;
    margin-bottom: 16px;
}
@media (max-width: 900px) { .wh-stat-grid { grid-template-columns: repeat(2, 1fr); } }
.wh-stat-card {
    background: var(--card);
    border-radius: var(--radius);
    padding: 14px;
    box-shadow: var(--shadow-sm);
    border: 1px solid var(--border-soft);
    display: flex;
    align-items: center;
    gap: 12px;
}
.wh-stat-icon {
    width: 36px; height: 36px;
    border-radius: 8px;
    display: flex; align-items: center; justify-content: center;
    color: #fff;
    flex-shrink: 0;
}
.wh-stat-emerald { background: linear-gradient(135deg, #10b981, #0d9488); }
.wh-stat-sky     { background: linear-gradient(135deg, #0ea5e9, #0284c7); }
.wh-stat-green   { background: linear-gradient(135deg, #22c55e, #15803d); }
.wh-stat-red     { background: linear-gradient(135deg, #ef4444, #e11d48); }
.wh-stat-label   { font-size: 12px; color: var(--text-soft); }
.wh-stat-value   { font-size: 22px; font-weight: 700; color: var(--text); line-height: 1.2; }
.wh-stat-sub     { font-size: 11px; color: var(--text-mute); margin-top: 2px; }

/* Tab 切换 */
.wh-tabs {
    display: inline-flex;
    gap: 4px;
    padding: 4px;
    background: var(--slate-100);
    border-radius: var(--radius-sm);
    margin-bottom: 14px;
}
.wh-tab {
    padding: 6px 14px;
    border-radius: 6px;
    font-size: 13px;
    font-weight: 500;
    border: none;
    background: transparent;
    color: var(--text-mute);
    cursor: pointer;
    transition: all 0.2s;
    display: inline-flex;
    align-items: center;
    gap: 6px;
}
.wh-tab.active {
    background: var(--card);
    color: var(--text);
    box-shadow: var(--shadow-sm);
}
.wh-tab-badge {
    background: var(--red-500);
    color: #fff;
    font-size: 10px;
    padding: 1px 6px;
    border-radius: 9999px;
    font-weight: 700;
}

/* Webhook 卡片 */
.wh-list { display: flex; flex-direction: column; gap: 10px; margin-bottom: 16px; }
.wh-card {
    background: var(--card);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
    border: 1px solid var(--border-soft);
    padding: 14px;
    display: flex;
    align-items: flex-start;
    gap: 12px;
}
.wh-card.is-disabled { opacity: 0.6; }
.wh-card-icon {
    width: 44px; height: 44px;
    border-radius: 12px;
    display: flex; align-items: center; justify-content: center;
    flex-shrink: 0;
}
.wh-card-icon.active   { background: var(--emerald-100); color: var(--emerald-600); }
.wh-card-icon.inactive { background: var(--slate-100);   color: var(--slate-400); }
.wh-card-body { flex: 1; min-width: 0; }
.wh-card-head {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
    margin-bottom: 4px;
}
.wh-card-name { font-size: 14px; font-weight: 600; color: var(--text); }
.wh-method-badge {
    font-size: 11px;
    padding: 1px 6px;
    border-radius: 4px;
    background: var(--slate-100);
    color: var(--text-soft);
    font-family: "SFMono-Regular", Menlo, monospace;
    border: 1px solid var(--border-soft);
}
.wh-status-chip {
    font-size: 11px;
    padding: 1px 6px;
    border-radius: 4px;
    display: inline-flex;
    align-items: center;
    gap: 2px;
}
.wh-status-chip.active   { color: var(--emerald-600); background: var(--emerald-50); }
.wh-status-chip.inactive { color: var(--text-mute); background: var(--slate-100); }
.wh-card-url {
    font-size: 12px;
    color: var(--text-mute);
    font-family: "SFMono-Regular", Menlo, monospace;
    margin-bottom: 8px;
    word-break: break-all;
}
.wh-card-events {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
    margin-bottom: 8px;
}
.wh-event-chip {
    font-size: 11px;
    padding: 2px 8px;
    border-radius: 9999px;
    background: var(--slate-100);
    color: var(--text-soft);
    display: inline-flex;
    align-items: center;
    gap: 4px;
}
.wh-card-stats {
    display: flex;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
    font-size: 11px;
    color: var(--text-mute);
}
.wh-stat-line {
    display: inline-flex;
    align-items: center;
    gap: 3px;
}
.wh-stat-line.emerald { color: var(--emerald-600); }
.wh-stat-line.red     { color: var(--red-500); }
.wh-card-actions {
    display: flex;
    align-items: center;
    gap: 4px;
    flex-shrink: 0;
}
.btn-icon {
    background: transparent;
    border: none;
    width: 32px; height: 32px;
    border-radius: 6px;
    display: flex; align-items: center; justify-content: center;
    color: var(--text-soft);
    cursor: pointer;
    transition: background 0.2s;
}
.btn-icon:hover { background: var(--slate-100); }

/* 响应码徽章 */
.wh-code-badge {
    font-size: 11px;
    padding: 1px 6px;
    border-radius: 4px;
    font-family: "SFMono-Regular", Menlo, monospace;
    font-weight: 600;
    border: 1px solid;
}
.wh-code-badge.ok  { color: var(--emerald-600); background: var(--emerald-50); border-color: var(--emerald-200); }
.wh-code-badge.err { color: var(--red-500);     background: #fef2f2;            border-color: #fecaca; }

/* 投递日志卡片 */
.wh-log-list { display: flex; flex-direction: column; gap: 10px; }
.wh-log-card {
    background: var(--card);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
    border: 1px solid var(--border-soft);
    padding: 14px;
    display: flex;
    align-items: flex-start;
    gap: 12px;
}
.wh-log-icon {
    width: 32px; height: 32px;
    border-radius: 8px;
    display: flex; align-items: center; justify-content: center;
    flex-shrink: 0;
}
.wh-log-icon.success { background: var(--emerald-100); color: var(--emerald-500); }
.wh-log-icon.failed  { background: #fee2e2;            color: var(--red-500); }
.wh-log-body { flex: 1; min-width: 0; }
.wh-log-head {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
    margin-bottom: 6px;
}
.wh-log-name { font-size: 13px; font-weight: 600; color: var(--text); }
.wh-log-payload {
    font-size: 11px;
    font-family: "SFMono-Regular", Menlo, monospace;
    background: var(--slate-100);
    color: var(--text-soft);
    padding: 8px 10px;
    border-radius: 6px;
    word-break: break-all;
    margin-bottom: 8px;
}
.wh-log-meta {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    font-size: 11px;
    color: var(--text-mute);
}
.wh-log-meta span { display: inline-flex; align-items: center; gap: 3px; }
.wh-log-error { color: var(--red-500); }

/* 事件类型参考卡 */
.wh-event-ref {
    background: linear-gradient(135deg, #f0f9ff 0%, #ecfeff 100%);
    border: 1px solid #bae6fd;
    border-radius: var(--radius);
    padding: 14px;
    margin-top: 14px;
}
.wh-event-ref-title {
    font-size: 14px;
    font-weight: 600;
    color: var(--sky-600);
    margin-bottom: 10px;
    display: flex;
    align-items: center;
    gap: 6px;
}
.wh-event-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 8px;
}
@media (max-width: 600px) { .wh-event-grid { grid-template-columns: 1fr; } }
.wh-event-item {
    display: flex;
    align-items: flex-start;
    gap: 6px;
    padding: 8px;
    border-radius: 6px;
    background: rgba(255,255,255,0.5);
}
.wh-event-item svg { margin-top: 2px; flex-shrink: 0; }
.wh-event-name { font-size: 12px; font-weight: 600; color: var(--text); }
.wh-event-desc { font-size: 10px; color: var(--text-mute); margin-top: 1px; }

/* 开关组件 */
.wh-switch {
    position: relative;
    display: inline-block;
    width: 36px; height: 20px;
    flex-shrink: 0;
}
.wh-switch input { opacity: 0; width: 0; height: 0; }
.wh-switch-track {
    position: absolute;
    inset: 0;
    background: var(--slate-300);
    border-radius: 9999px;
    transition: background 0.2s;
    cursor: pointer;
}
.wh-switch-track::after {
    content: '';
    position: absolute;
    width: 16px; height: 16px;
    background: #fff;
    border-radius: 50%;
    top: 2px; left: 2px;
    transition: transform 0.2s;
    box-shadow: var(--shadow-sm);
}
.wh-switch input:checked + .wh-switch-track {
    background: var(--emerald-500);
}
.wh-switch input:checked + .wh-switch-track::after {
    transform: translateX(16px);
}

/* 空状态 */
.wh-empty {
    text-align: center;
    padding: 48px 16px;
    color: var(--text-mute);
}
.wh-empty-title { font-size: 14px; font-weight: 600; margin: 8px 0 4px; color: var(--text); }
.wh-empty-desc  { font-size: 12px; }

/* 添加/编辑弹窗 */
.wh-modal {
    position: fixed;
    inset: 0;
    z-index: 1000;
    display: flex;
    align-items: center;
    justify-content: center;
}
.wh-modal-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(0,0,0,0.4);
    backdrop-filter: blur(2px);
}
.wh-modal-content {
    position: relative;
    background: var(--card);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    width: 95%;
    max-width: 540px;
    max-height: 90vh;
    overflow: hidden;
    display: flex;
    flex-direction: column;
}
.wh-modal-header {
    padding: 14px 16px;
    border-bottom: 1px solid var(--border);
    display: flex;
    align-items: center;
    justify-content: space-between;
}
.wh-modal-header h3 { font-size: 16px; font-weight: 600; margin: 0; }
.wh-modal-close {
    background: transparent;
    border: none;
    width: 28px; height: 28px;
    border-radius: 6px;
    color: var(--text-mute);
    cursor: pointer;
    display: flex; align-items: center; justify-content: center;
}
.wh-modal-close:hover { background: var(--slate-100); }
.wh-modal-body {
    padding: 16px;
    overflow-y: auto;
    flex: 1;
}
.wh-modal-footer {
    padding: 12px 16px;
    border-top: 1px solid var(--border);
    display: flex;
    justify-content: flex-end;
    gap: 8px;
}

.wh-form-group { margin-bottom: 14px; }
.wh-form-group label {
    display: block;
    font-size: 12px;
    font-weight: 500;
    color: var(--text-soft);
    margin-bottom: 6px;
}
.wh-form-group input,
.wh-form-group select {
    width: 100%;
    padding: 8px 10px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    font-size: 13px;
    font-family: inherit;
    background: var(--card);
    color: var(--text);
}
.wh-form-group input:focus,
.wh-form-group select:focus {
    outline: none;
    border-color: var(--emerald-500);
    box-shadow: 0 0 0 3px rgba(16,185,129,0.1);
}
.wh-form-row {
    display: flex;
    gap: 8px;
    align-items: flex-end;
}
.wh-form-row .wh-form-group { margin-bottom: 14px; }

/* 事件选择器 */
.wh-event-selector {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 8px;
}
.wh-event-toggle {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px;
    border: 1px solid var(--border);
    border-radius: 8px;
    cursor: pointer;
    transition: all 0.2s;
}
.wh-event-toggle:hover { border-color: var(--emerald-300); background: var(--emerald-50); }
.wh-event-toggle-info { flex: 1; min-width: 0; }
.wh-event-toggle-name {
    font-size: 12px;
    font-weight: 600;
    color: var(--text);
}
.wh-event-toggle-desc {
    font-size: 10px;
    color: var(--text-mute);
    margin-top: 2px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* 密钥行 */
.wh-secret-row {
    display: flex;
    gap: 8px;
    align-items: center;
}
.wh-secret-input {
    flex: 1;
    font-family: "SFMono-Regular", Menlo, monospace !important;
    font-size: 12px !important;
}
.wh-secret-hint {
    font-size: 11px;
    color: var(--text-mute);
    margin-top: 6px;
    line-height: 1.5;
}
.wh-secret-hint code {
    font-family: "SFMono-Regular", Menlo, monospace;
    background: var(--slate-100);
    padding: 1px 4px;
    border-radius: 3px;
    color: var(--emerald-700);
    font-size: 10px;
}

/* ============================================================
 * r9 新增：设备健康度评分页面样式（health.php）
 * 设计与 Next.js health-view.tsx 一致
 * 渐变头部 + A-F 等级徽章 + 6 因子分解 + 维护建议
 * ============================================================ */

/* 渐变头部卡：平均健康度 + 等级分布 */
.health-header-card {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 16px;
    background: linear-gradient(135deg, #10b981 0%, #14b8a6 50%, #06b6d4 100%);
    border-radius: var(--radius-lg);
    padding: 24px;
    color: #fff;
    box-shadow: var(--shadow-emerald);
    margin-bottom: 16px;
}
.health-header-left { display: flex; align-items: center; gap: 16px; }
.health-header-icon {
    width: 64px; height: 64px;
    background: rgba(255,255,255,0.2);
    backdrop-filter: blur(8px);
    border: 1px solid rgba(255,255,255,0.3);
    border-radius: 16px;
    display: flex; align-items: center; justify-content: center;
    color: #fff;
    flex-shrink: 0;
}
.health-header-label {
    font-size: 13px;
    color: rgba(255,255,255,0.75);
    margin-bottom: 4px;
}
.health-header-score {
    font-size: 32px;
    font-weight: 700;
    line-height: 1.1;
    display: flex;
    align-items: baseline;
    gap: 8px;
}
.health-header-score-unit {
    font-size: 16px;
    font-weight: 500;
    color: rgba(255,255,255,0.8);
}
.health-header-meta {
    font-size: 13px;
    color: rgba(255,255,255,0.85);
    margin-top: 4px;
}
.health-grade-dist { display: flex; gap: 8px; }
.health-grade-cell { text-align: center; }
.health-grade-badge {
    width: 44px; height: 44px;
    border-radius: 10px;
    display: flex; align-items: center; justify-content: center;
    font-weight: 700;
    font-size: 16px;
}
.health-grade-cell .health-grade-empty { color: rgba(255,255,255,0.4); }
.health-grade-count {
    font-size: 11px;
    margin-top: 4px;
    color: rgba(255,255,255,0.85);
}

/* 4 张统计卡 */
.health-stat-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 12px;
    margin-bottom: 16px;
}
@media (max-width: 768px) { .health-stat-grid { grid-template-columns: repeat(2, 1fr); } }
.health-stat-card {
    background: var(--card);
    border-radius: var(--radius);
    padding: 16px;
    box-shadow: var(--shadow-sm);
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
}
.health-stat-icon {
    width: 36px; height: 36px;
    border-radius: 9px;
    display: flex; align-items: center; justify-content: center;
    color: #fff;
    flex-shrink: 0;
}
.health-stat-emerald { background: linear-gradient(135deg, #10b981, #14b8a6); }
.health-stat-green   { background: linear-gradient(135deg, #10b981, #16a34a); }
.health-stat-amber   { background: linear-gradient(135deg, #f59e0b, #ea580c); }
.health-stat-sky      { background: linear-gradient(135deg, #0ea5e9, #2563eb); }
.health-stat-label {
    font-size: 12px;
    color: var(--text-mute);
}
.health-stat-value {
    font-size: 24px;
    font-weight: 700;
    color: var(--text);
    line-height: 1.2;
}

/* 设备健康度列表 */
.health-device-list { display: flex; flex-direction: column; gap: 12px; margin-bottom: 16px; }
.health-device-card {
    background: var(--card);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
    overflow: hidden;
}
.health-device-head {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 16px;
}
.health-grade-badge-lg {
    width: 64px; height: 64px;
    border-radius: 12px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    font-weight: 700;
    font-size: 18px;
    gap: 2px;
}
.health-device-info { flex: 1; min-width: 0; }
.health-device-name-row {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    margin-bottom: 4px;
}
.health-device-name { font-weight: 600; font-size: 14px; color: var(--text); }
.health-device-online {
    font-size: 11px;
    padding: 2px 8px;
    border-radius: var(--radius-full);
    border: 1px solid var(--border);
    color: var(--text-mute);
}
.health-device-online.online { color: var(--emerald-700); background: var(--emerald-50); border-color: var(--emerald-200); }
.health-device-online.offline { color: var(--red-600); background: #fee2e2; border-color: #fecaca; }
.health-device-score-label { font-size: 11px; color: var(--text-mute); }
.health-device-score { font-size: 18px; font-weight: 700; }
.health-device-desc { font-size: 12px; color: var(--text-mute); }
.health-device-last { font-size: 11px; color: var(--text-mute); margin-top: 2px; }
.health-device-progress { width: 128px; text-align: center; flex-shrink: 0; }
.health-score-bar {
    height: 8px;
    border-radius: 4px;
    background: var(--slate-100);
    overflow: hidden;
}
.health-score-bar-fill {
    height: 100%;
    border-radius: 4px;
    transition: width 0.6s ease;
}
.health-score-bar-text {
    font-size: 11px;
    color: var(--text-mute);
    margin-top: 4px;
}
@media (max-width: 640px) {
    .health-device-progress { display: none; }
    .health-device-head { gap: 12px; padding: 12px; }
    .health-grade-badge-lg { width: 52px; height: 52px; }
}

/* 因子分解网格 */
.health-factor-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 8px;
    padding: 0 16px 16px;
}
@media (max-width: 1024px) { .health-factor-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 480px)  { .health-factor-grid { grid-template-columns: 1fr; } }
.health-factor-item {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    padding: 10px;
    border-radius: 9px;
    background: var(--slate-50);
}
.health-factor-icon {
    width: 32px; height: 32px;
    border-radius: 8px;
    display: flex; align-items: center; justify-content: center;
    flex-shrink: 0;
}
.health-factor-item.good      .health-factor-icon { background: var(--emerald-100); color: var(--emerald-600); }
.health-factor-item.warning   .health-factor-icon { background: #fef3c7;             color: #d97706; }
.health-factor-item.critical   .health-factor-icon { background: #fee2e2;             color: var(--red-600); }
.health-factor-body { flex: 1; min-width: 0; }
.health-factor-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
}
.health-factor-label { font-size: 12px; font-weight: 500; color: var(--text); }
.health-factor-score { font-size: 12px; font-weight: 700; }
.health-factor-item.good      .health-factor-score { color: var(--emerald-600); }
.health-factor-item.warning   .health-factor-score { color: #d97706; }
.health-factor-item.critical   .health-factor-score { color: var(--red-600); }
.health-factor-detail {
    font-size: 10px;
    color: var(--text-mute);
    margin-top: 2px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.health-factor-bar {
    height: 4px;
    background: var(--slate-200);
    border-radius: 2px;
    overflow: hidden;
    margin-top: 4px;
}
.health-factor-bar-fill { height: 100%; border-radius: 2px; transition: width 0.5s ease; }
.health-factor-bar-fill.good    { background: var(--emerald-500); }
.health-factor-bar-fill.warning { background: #f59e0b; }
.health-factor-bar-fill.critical{ background: var(--red-500); }

/* 维护建议 */
.health-recommendations {
    padding: 12px 16px;
    background: var(--slate-50);
    border-top: 1px solid var(--border);
}
.health-recommendations-title {
    font-size: 12px;
    font-weight: 600;
    color: var(--text-soft);
    display: flex;
    align-items: center;
    gap: 4px;
    margin-bottom: 6px;
}
.health-recommendations-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.health-recommendations-list li {
    display: flex;
    align-items: flex-start;
    gap: 6px;
    font-size: 12px;
    color: var(--text-soft);
}
.health-recommendations-list svg { color: var(--emerald-500); margin-top: 2px; flex-shrink: 0; }

/* 空状态 */
.health-empty {
    text-align: center;
    padding: 48px 24px;
    color: var(--text-mute);
}
.health-empty-title { font-weight: 600; margin-top: 12px; color: var(--text-soft); }
.health-empty-desc  { font-size: 12px; margin-top: 4px; }

/* 评分标准卡 */
.health-standard-card {
    background: linear-gradient(135deg, #f0f9ff 0%, #ecfeff 100%);
    border-radius: var(--radius);
    padding: 16px;
    border: 1px solid var(--border);
    box-shadow: var(--shadow-sm);
}
.health-standard-title {
    font-size: 14px;
    font-weight: 600;
    color: var(--text);
    display: flex;
    align-items: center;
    gap: 6px;
    margin-bottom: 12px;
}
.health-standard-grid {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: 8px;
}
@media (max-width: 768px) { .health-standard-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 480px) { .health-standard-grid { grid-template-columns: 1fr; } }
.health-standard-cell {
    padding: 10px;
    border-radius: 9px;
    border: 1px solid rgba(0,0,0,0.04);
}
.health-standard-grade { font-size: 18px; font-weight: 700; }
.health-standard-label { font-size: 12px; font-weight: 500; }
.health-standard-desc  { font-size: 10px; color: var(--text-mute); margin-top: 2px; }
.health-standard-weights {
    margin-top: 12px;
    padding-top: 12px;
    border-top: 1px solid var(--border);
    font-size: 11px;
    color: var(--text-mute);
}

/* ============================================================
 * r9 新增：灌溉日志页面样式（irrigation_log.php）
 * 设计与 Next.js irrigation-log-view.tsx 一致
 * 触发 emoji 徽章 + 状态徽章 + 土壤变化进度条
 * ============================================================ */

/* 4 张统计卡 */
.irrig-stat-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 12px;
    margin-bottom: 16px;
}
@media (max-width: 768px) { .irrig-stat-grid { grid-template-columns: repeat(2, 1fr); } }
.irrig-stat-card {
    background: var(--card);
    border-radius: var(--radius);
    padding: 16px;
    box-shadow: var(--shadow-sm);
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
}
.irrig-stat-icon {
    width: 36px; height: 36px;
    border-radius: 9px;
    display: flex; align-items: center; justify-content: center;
    color: #fff;
    flex-shrink: 0;
}
.irrig-stat-emerald { background: linear-gradient(135deg, #10b981, #14b8a6); }
.irrig-stat-cyan    { background: linear-gradient(135deg, #06b6d4, #0891b2); }
.irrig-stat-amber   { background: linear-gradient(135deg, #f59e0b, #ea580c); }
.irrig-stat-red     { background: linear-gradient(135deg, #ef4444, #e11d48); }
.irrig-stat-label { font-size: 12px; color: var(--text-mute); }
.irrig-stat-value {
    font-size: 22px;
    font-weight: 700;
    color: var(--text);
    line-height: 1.2;
}
.irrig-stat-unit { font-size: 12px; font-weight: 500; color: var(--text-mute); margin-left: 2px; }
.irrig-stat-sub  { font-size: 11px; color: var(--text-mute); margin-top: 2px; }

/* 图表区 */
.irrig-charts-row {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 12px;
    margin-bottom: 16px;
}
@media (max-width: 768px) { .irrig-charts-row { grid-template-columns: 1fr; } }
.irrig-section-title {
    font-size: 14px;
    font-weight: 600;
    color: var(--text);
    margin: 0 0 12px 0;
}
.irrig-chart-wrap { position: relative; }

/* 筛选器 */
.irrig-filter-bar {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 16px;
}
.irrig-filter-label {
    font-size: 12px;
    color: var(--text-mute);
    display: flex;
    align-items: center;
    gap: 4px;
}
.irrig-filter-device {
    padding: 6px 12px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--card);
    color: var(--text);
    font-size: 12px;
    font-family: inherit;
}
.irrig-filter-triggers {
    display: flex;
    gap: 4px;
    padding: 4px;
    background: var(--slate-100);
    border-radius: var(--radius-sm);
    flex-wrap: wrap;
}
.irrig-trigger-chip {
    padding: 6px 10px;
    border: none;
    background: transparent;
    border-radius: 6px;
    font-size: 12px;
    font-weight: 500;
    color: var(--text-mute);
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 4px;
    transition: all 0.2s;
    font-family: inherit;
}
.irrig-trigger-chip:hover { color: var(--text); }
.irrig-trigger-chip.active {
    background: var(--card);
    color: var(--text);
    box-shadow: var(--shadow-sm);
}
.irrig-trigger-emoji { font-size: 14px; }

/* 日志列表 */
.irrig-log-list { display: flex; flex-direction: column; gap: 8px; }
.irrig-log-card {
    background: var(--card);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
    padding: 16px;
    display: flex;
    gap: 12px;
    transition: box-shadow 0.2s;
}
.irrig-log-card:hover { box-shadow: var(--shadow-md); }
.irrig-log-trigger-icon {
    width: 40px; height: 40px;
    border-radius: 12px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.irrig-log-trigger-emoji { font-size: 20px; }
.irrig-log-body { flex: 1; min-width: 0; }
.irrig-log-head {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    margin-bottom: 6px;
}
.irrig-log-device-name { font-weight: 600; font-size: 13px; color: var(--text); }
.irrig-trigger-badge {
    font-size: 11px;
    padding: 2px 8px;
    border-radius: var(--radius-full);
    font-weight: 500;
}
.irrig-status-badge {
    font-size: 11px;
    padding: 2px 8px;
    border-radius: var(--radius-full);
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-weight: 500;
}
.irrig-schedule-badge {
    font-size: 11px;
    padding: 2px 8px;
    border-radius: var(--radius-full);
    background: var(--slate-100);
    color: var(--text-soft);
    display: inline-flex;
    align-items: center;
    gap: 4px;
}
.irrig-log-meta {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    font-size: 11px;
    color: var(--text-mute);
    margin-bottom: 8px;
}
.irrig-log-meta svg { vertical-align: -2px; margin-right: 2px; }
.irrig-log-water { color: #06b6d4; }

/* 土壤湿度变化 */
.irrig-log-soil {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 11px;
    flex-wrap: wrap;
}
.irrig-soil-label { color: var(--text-mute); }
.irrig-soil-before { font-family: "SFMono-Regular", Menlo, monospace; color: var(--red-500); }
.irrig-soil-after  { font-family: "SFMono-Regular", Menlo, monospace; color: var(--emerald-600); }
.irrig-soil-delta {
    font-size: 10px;
    padding: 1px 6px;
    border-radius: var(--radius-full);
    font-weight: 500;
}
.irrig-soil-delta.up   { color: var(--emerald-600); background: var(--emerald-50); }
.irrig-soil-delta.down { color: var(--red-500);     background: #fee2e2; }
.irrig-soil-progress {
    flex: 1;
    min-width: 120px;
    max-width: 200px;
    height: 6px;
    border-radius: 3px;
    background: var(--slate-100);
    overflow: hidden;
    display: flex;
}
.irrig-soil-progress-before { background: #f87171; transition: width 0.4s ease; }
.irrig-soil-progress-after  { background: var(--emerald-500); transition: width 0.4s ease; }

.irrig-log-reason {
    margin-top: 6px;
    font-size: 11px;
    color: var(--text-mute);
    display: flex;
    align-items: flex-start;
    gap: 4px;
}
.irrig-log-reason svg { flex-shrink: 0; margin-top: 2px; }

/* 空状态 */
.irrig-empty {
    text-align: center;
    padding: 48px 24px;
    color: var(--text-mute);
    background: var(--card);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
}
.irrig-empty-title { font-weight: 600; margin-top: 12px; color: var(--text-soft); }
.irrig-empty-desc  { font-size: 12px; margin-top: 4px; }

/* ============================================================
 * r10 新增：天气预报 + 植物生长档案页面样式
 * ============================================================ */

/* 紫色统计卡（植物页"可收获"用，与 emerald/sky/amber/cyan 配套） */
.stat-card-purple { background: linear-gradient(135deg, #faf5ff 0%, #f3e8ff 100%); border-color: #e9d5ff; }
.stat-icon-purple { background: linear-gradient(135deg, #a855f7, #7c3aed); }

/* ==================== 天气预报页 ==================== */

/* 顶部：当前天气卡 + 灌溉建议卡 并排 */
.weather-top-grid {
    display: grid;
    grid-template-columns: 2fr 1fr;
    gap: 16px;
    margin-bottom: 18px;
}
@media (max-width: 900px) {
    .weather-top-grid { grid-template-columns: 1fr; }
}

/* 当前天气卡（渐变 sky-blue → cyan → blue） */
.weather-current-card {
    background: linear-gradient(135deg, #38bdf8 0%, #06b6d4 50%, #2563eb 100%);
    border-radius: 14px;
    padding: 24px;
    color: #fff;
    box-shadow: 0 8px 24px -8px rgba(2, 132, 199, 0.5);
}
.weather-current-main {
    display: flex;
    align-items: flex-start;
    gap: 16px;
    flex-wrap: wrap;
}
.weather-current-icon {
    font-size: 56px;
    line-height: 1;
    flex-shrink: 0;
}
.weather-current-temp-info { flex: 1; min-width: 120px; }
.weather-current-temp {
    font-size: 40px;
    font-weight: 800;
    line-height: 1.1;
}
.weather-current-cond { font-size: 16px; opacity: 0.95; margin-top: 2px; }
.weather-current-feels { font-size: 12px; opacity: 0.8; margin-top: 4px; }
.weather-current-meta {
    text-align: right;
    font-size: 12px;
    opacity: 0.85;
    margin-left: auto;
    min-width: 120px;
}
.weather-current-loc {
    display: inline-flex; align-items: center; gap: 4px;
    margin-bottom: 4px;
}
.weather-current-time {
    display: inline-flex; align-items: center; gap: 4px;
    opacity: 0.75;
    font-size: 11px;
}
.weather-current-mock {
    margin-top: 6px;
    padding: 4px 8px;
    background: rgba(255, 255, 255, 0.18);
    border-radius: 6px;
    font-size: 10px;
    display: inline-block;
}

/* 6 项玻璃拟态指标网格 */
.weather-metric-grid {
    display: grid;
    grid-template-columns: repeat(6, 1fr);
    gap: 10px;
    margin-top: 22px;
}
@media (max-width: 700px) {
    .weather-metric-grid { grid-template-columns: repeat(3, 1fr); }
}
.weather-metric-tile {
    padding: 10px;
    border-radius: 10px;
    background: rgba(255, 255, 255, 0.15);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
}
.weather-metric-tile svg { opacity: 0.85; }
.weather-metric-label { font-size: 10px; opacity: 0.75; margin-top: 4px; }
.weather-metric-value { font-size: 14px; font-weight: 700; margin-top: 2px; }

/* 灌溉建议卡 */
.weather-advice-card {
    border-radius: 14px;
    padding: 18px;
    box-shadow: 0 1px 3px rgba(0,0,0,0.04);
    border: 1px solid var(--border);
}
.weather-advice-skip    { background: #fef2f2; border-color: #fecaca; }
.weather-advice-reduce  { background: #fffbeb; border-color: #fde68a; }
.weather-advice-normal  { background: #ecfdf5; border-color: #a7f3d0; }
.weather-advice-increase{ background: #f0f9ff; border-color: #bae6fd; }

.weather-advice-head {
    display: flex; align-items: center; gap: 10px;
    margin-bottom: 10px;
}
.weather-advice-icon { font-size: 30px; }
.weather-advice-label-sm { font-size: 11px; color: var(--text-mute); }
.weather-advice-label-lg { font-size: 17px; font-weight: 700; }
.weather-advice-skip    .weather-advice-label-lg { color: var(--red-600); }
.weather-advice-reduce  .weather-advice-label-lg { color: #d97706; }
.weather-advice-normal  .weather-advice-label-lg { color: var(--emerald-600); }
.weather-advice-increase .weather-advice-label-lg { color: var(--sky-600); }

.weather-advice-desc { font-size: 12px; color: var(--text-soft); margin: 0; }
.weather-advice-divider { height: 1px; background: rgba(0,0,0,0.08); margin: 12px 0; }
.weather-advice-stat-list { display: flex; flex-direction: column; gap: 8px; }
.weather-advice-stat-row {
    display: flex; justify-content: space-between; align-items: center;
    font-size: 12px; color: var(--text-soft);
}
.weather-advice-stat-num { font-family: ui-monospace, "SF Mono", Menlo, monospace; font-weight: 600; color: var(--text); }
.weather-advice-stat-num-red { color: var(--red-600); }

/* 7 日预报网格 */
.weather-forecast-grid {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 10px;
}
@media (max-width: 900px) {
    .weather-forecast-grid { grid-template-columns: repeat(4, 1fr); }
}
@media (max-width: 500px) {
    .weather-forecast-grid { grid-template-columns: repeat(2, 1fr); }
}
.weather-forecast-card {
    padding: 12px 8px;
    border-radius: 12px;
    border: 1px solid var(--border);
    background: #fff;
    text-align: center;
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.weather-forecast-card:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(0,0,0,0.08); }
.weather-forecast-today {
    border: 2px solid var(--emerald-500);
    background: linear-gradient(180deg, #ecfdf5 0%, #ffffff 60%);
}
.weather-forecast-date { font-size: 12px; font-weight: 700; }
.weather-forecast-dow  { font-size: 10px; color: var(--text-mute); }
.weather-forecast-icon { font-size: 28px; margin: 6px 0; }
.weather-forecast-cond { font-size: 11px; font-weight: 500; }
.weather-forecast-temps { margin-top: 4px; font-size: 12px; }
.weather-temp-high { color: var(--red-500); font-weight: 700; }
.weather-temp-low  { color: var(--sky-500); font-weight: 700; }
.weather-temp-sep  { color: var(--text-mute); margin: 0 2px; }
.weather-forecast-rain {
    margin-top: 6px;
    display: inline-flex; align-items: center; gap: 3px;
    font-size: 11px; color: var(--text-mute);
}
.weather-rain-high { color: var(--sky-600); font-weight: 700; }
.weather-forecast-rain-mm { font-size: 10px; color: var(--sky-500); margin-top: 2px; }

/* 灌溉建议小徽章（预报卡内 + 建议列表内） */
.weather-advice-badge {
    margin-top: 8px;
    padding: 3px 6px;
    border-radius: 6px;
    font-size: 10px;
    font-weight: 600;
    display: inline-block;
    text-align: center;
}
.weather-advice-skip    .weather-advice-badge,
.weather-advice-badge.weather-advice-skip     { background: #fee2e2; color: var(--red-600); }
.weather-advice-reduce  .weather-advice-badge,
.weather-advice-badge.weather-advice-reduce   { background: #fef3c7; color: #d97706; }
.weather-advice-normal  .weather-advice-badge,
.weather-advice-badge.weather-advice-normal   { background: #d1fae5; color: var(--emerald-600); }
.weather-advice-increase .weather-advice-badge,
.weather-advice-badge.weather-advice-increase { background: #e0f2fe; color: var(--sky-600); }

/* 智能灌溉建议列表 */
.weather-suggestion-list { display: flex; flex-direction: column; gap: 10px; }
.weather-suggestion-item {
    display: flex; align-items: flex-start; gap: 12px;
    padding: 12px;
    border-radius: 10px;
    background: var(--slate-50);
}
.weather-suggestion-icon { font-size: 22px; flex-shrink: 0; }
.weather-suggestion-body { flex: 1; min-width: 0; }
.weather-suggestion-head {
    display: flex; align-items: center; gap: 8px;
    flex-wrap: wrap;
    margin-bottom: 4px;
}
.weather-suggestion-date { font-weight: 600; font-size: 13px; }
.weather-suggestion-meta { font-size: 11px; color: var(--text-mute); }
.weather-suggestion-text { font-size: 12px; color: var(--text-soft); margin: 0; }

/* 数据源说明卡 */
.weather-source-card {
    margin-top: 16px;
    padding: 16px;
    border-radius: 12px;
    background: linear-gradient(135deg, #f0f9ff 0%, #ecfeff 100%);
    border: 1px solid #bae6fd;
    display: flex; gap: 12px;
    align-items: flex-start;
}
.weather-source-icon {
    width: 36px; height: 36px;
    border-radius: 10px;
    background: #e0f2fe;
    display: flex; align-items: center; justify-content: center;
    flex-shrink: 0;
}
.weather-source-title { font-weight: 700; color: var(--sky-700, #0369a1); margin-bottom: 4px; }
.weather-source-text { font-size: 12px; color: var(--text-soft); line-height: 1.6; margin: 0; }
.weather-source-text strong { color: var(--sky-700, #0369a1); }
.weather-source-mode { margin-top: 8px; font-size: 11px; color: var(--text-mute); }
.weather-source-mode-on   { color: var(--emerald-600); font-weight: 600; }
.weather-source-mode-mock { color: #d97706; font-weight: 600; }

/* ==================== 植物生长档案页 ==================== */

/* 植物列表 */
.plant-list { display: flex; flex-direction: column; gap: 12px; }
.plant-card {
    background: var(--card);
    border-radius: 12px;
    border: 1px solid var(--border);
    box-shadow: 0 1px 2px rgba(0,0,0,0.04);
    overflow: hidden;
    transition: box-shadow 0.15s ease;
}
.plant-card:hover { box-shadow: 0 4px 12px rgba(0,0,0,0.06); }

/* 卡片头部 */
.plant-card-head {
    display: flex; align-items: center; gap: 12px;
    padding: 14px 16px;
    cursor: pointer;
    transition: background 0.15s ease;
}
.plant-card-head:hover { background: var(--slate-50); }
.plant-card-icon {
    width: 44px; height: 44px;
    border-radius: 11px;
    display: flex; align-items: center; justify-content: center;
    font-size: 24px;
    flex-shrink: 0;
}
.plant-card-info { flex: 1; min-width: 0; }
.plant-card-name-row {
    display: flex; align-items: center; gap: 6px;
    flex-wrap: wrap;
    margin-bottom: 6px;
}
.plant-card-name { font-size: 14px; font-weight: 700; color: var(--text); }
.plant-card-meta {
    display: flex; align-items: center; gap: 12px;
    flex-wrap: wrap;
    font-size: 11px; color: var(--text-mute);
}
.plant-card-meta svg { vertical-align: -2px; margin-right: 2px; }
.plant-card-days-harvest { color: #d97706; }
.plant-card-harvest-ready { color: var(--emerald-600); font-weight: 600; }

/* 阶段徽章 */
.plant-stage-badge {
    padding: 2px 8px;
    border-radius: 6px;
    font-size: 11px;
    font-weight: 600;
    display: inline-flex; align-items: center; gap: 3px;
}

/* 健康徽章 3 色 */
.plant-health-badge {
    padding: 2px 8px;
    border-radius: 6px;
    font-size: 11px;
    font-weight: 600;
    display: inline-flex; align-items: center; gap: 3px;
}
.plant-health-optimal  { background: #d1fae5; color: var(--emerald-600); }
.plant-health-warning  { background: #fef3c7; color: #d97706; }
.plant-health-critical { background: #fee2e2; color: var(--red-600); }

/* 阶段进度点（5 个，激活的填色） */
.plant-stage-progress { display: flex; align-items: center; gap: 5px; }
.plant-stage-dot {
    width: 7px; height: 7px;
    border-radius: 50%;
    background: var(--slate-200, #e2e8f0);
}
.plant-stage-dot.active { background: var(--emerald-500); }

/* 展开箭头 */
.plant-chevron {
    transition: transform 0.2s ease;
    color: var(--text-mute);
    flex-shrink: 0;
}
.plant-card.expanded .plant-chevron { transform: rotate(90deg); }

/* 展开内容 */
.plant-card-detail {
    max-height: 0;
    overflow: hidden;
    transition: max-height 0.3s ease;
    border-top: 1px solid transparent;
}
.plant-card.expanded .plant-card-detail {
    max-height: 1200px;
    border-top: 1px solid var(--border);
}
.plant-detail-inner { padding: 16px; display: flex; flex-direction: column; gap: 16px; }

/* 区块标题 */
.plant-section-title {
    display: flex; align-items: center; gap: 5px;
    font-size: 12px;
    font-weight: 600;
    color: var(--text-mute);
    margin-bottom: 8px;
}

/* 适宜生长条件网格（3 列） */
.plant-condition-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 10px;
}
@media (max-width: 600px) {
    .plant-condition-grid { grid-template-columns: 1fr; }
}
.plant-condition-item {
    padding: 10px;
    border-radius: 8px;
    background: #fff;
    border: 1px solid var(--border);
}
.plant-condition-item.in-range  { border-color: #a7f3d0; background: #ecfdf5; }
.plant-condition-item.out-range { border-color: #fde68a; background: #fffbeb; }
.plant-condition-head {
    display: flex; align-items: center; gap: 5px;
    font-size: 12px; font-weight: 600;
    margin-bottom: 4px;
}
.plant-condition-ideal { font-size: 11px; color: var(--text-mute); }
.plant-condition-current { font-size: 13px; font-weight: 700; margin-top: 4px; }
.plant-condition-current.ok   { color: var(--emerald-600); }
.plant-condition-current.warn { color: #d97706; }

/* 里程碑时间轴 */
.plant-timeline {
    position: relative;
    padding-left: 16px;
}
.plant-timeline-line {
    position: absolute;
    left: 5px; top: 6px; bottom: 6px;
    width: 1px;
    background: var(--border);
}
.plant-timeline-empty { font-size: 12px; color: var(--text-mute); padding: 8px 0; }
.plant-timeline-item {
    position: relative;
    padding-bottom: 14px;
}
.plant-timeline-item:last-child { padding-bottom: 0; }
.plant-timeline-dot {
    position: absolute;
    left: -16px;
    top: 4px;
    width: 11px; height: 11px;
    border-radius: 50%;
    border: 2px solid #fff;
    box-shadow: 0 0 0 1px var(--border);
}
.plant-timeline-body { padding-left: 4px; }
.plant-timeline-head {
    display: flex; align-items: center; gap: 8px;
    flex-wrap: wrap;
    margin-bottom: 2px;
}
.plant-timeline-title { font-size: 13px; font-weight: 600; color: var(--text); }
.plant-timeline-date { font-size: 11px; color: var(--text-mute); }
.plant-timeline-desc { font-size: 11px; color: var(--text-soft); margin: 0; }

/* 备注 */
.plant-notes {
    padding: 10px 12px;
    border-radius: 8px;
    background: var(--slate-50);
    border: 1px solid var(--border);
}
.plant-notes-title { font-size: 11px; font-weight: 600; color: var(--text-mute); margin-bottom: 4px; }
.plant-notes-text { font-size: 12px; color: var(--text); margin: 0; }

/* 操作区 */
.plant-actions {
    display: flex; align-items: center; gap: 8px;
    flex-wrap: wrap;
    padding-top: 8px;
    border-top: 1px dashed var(--border);
}
.plant-action-label { font-size: 12px; color: var(--text-mute); }
.plant-stage-select {
    padding: 4px 8px;
    border-radius: 6px;
    border: 1px solid var(--border);
    background: #fff;
    font-size: 12px;
    color: var(--text);
    cursor: pointer;
}
.plant-stage-select:focus { outline: 2px solid var(--emerald-500); outline-offset: 1px; }

/* 空状态 */
.plant-empty {
    text-align: center;
    padding: 48px 24px;
    color: var(--text-mute);
    background: var(--card);
    border-radius: 12px;
    border: 1px dashed var(--border);
}
.plant-empty-title { font-weight: 600; margin-top: 12px; color: var(--text-soft); }
.plant-empty-desc  { font-size: 12px; margin-top: 4px; }

/* 说明卡 */
.plant-explain-card {
    margin-top: 16px;
    padding: 16px;
    border-radius: 12px;
    background: linear-gradient(135deg, #ecfdf5 0%, #f0fdf4 100%);
    border: 1px solid #a7f3d0;
    display: flex; gap: 12px;
    align-items: flex-start;
}
.plant-explain-icon {
    width: 36px; height: 36px;
    border-radius: 10px;
    background: #d1fae5;
    display: flex; align-items: center; justify-content: center;
    flex-shrink: 0;
}
.plant-explain-title { font-weight: 700; color: var(--emerald-700); margin-bottom: 4px; }
.plant-explain-text { font-size: 12px; color: var(--text-soft); line-height: 1.6; margin: 0; }

/* 弹窗 */
.plant-modal {
    position: fixed; inset: 0;
    z-index: 1000;
    display: none;
    align-items: center; justify-content: center;
}
.plant-modal.open { display: flex; }
.plant-modal-backdrop {
    position: absolute; inset: 0;
    background: rgba(15, 23, 42, 0.55);
    backdrop-filter: blur(2px);
}
.plant-modal-content {
    position: relative;
    width: 560px;
    max-width: calc(100vw - 32px);
    max-height: calc(100vh - 64px);
    overflow-y: auto;
    background: #fff;
    border-radius: 12px;
    box-shadow: 0 24px 60px -12px rgba(0,0,0,0.4);
}
.plant-modal-content-sm { width: 460px; }
.plant-modal-head {
    display: flex; align-items: center; justify-content: space-between;
    padding: 16px 20px;
    border-bottom: 1px solid var(--border);
}
.plant-modal-title { font-size: 15px; font-weight: 700; margin: 0; }
.plant-modal-close {
    background: transparent;
    border: none;
    cursor: pointer;
    color: var(--text-mute);
    padding: 4px;
    border-radius: 6px;
}
.plant-modal-close:hover { background: var(--slate-100); color: var(--text); }
.plant-modal-form { padding: 20px; display: flex; flex-direction: column; gap: 14px; }
.plant-form-row { display: flex; flex-direction: column; gap: 4px; }
.plant-form-row-2 {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
}
@media (max-width: 500px) {
    .plant-form-row-2 { grid-template-columns: 1fr; }
}
.plant-form-label { font-size: 12px; font-weight: 600; color: var(--text-soft); }
.plant-form-input {
    padding: 7px 10px;
    border-radius: 6px;
    border: 1px solid var(--border);
    background: #fff;
    font-size: 13px;
    color: var(--text);
    font-family: inherit;
}
.plant-form-input:focus { outline: 2px solid var(--emerald-500); outline-offset: 1px; }
.plant-form-input-sm { width: 80px; }
.plant-form-textarea { resize: vertical; min-height: 50px; }
.plant-form-range { display: flex; align-items: center; gap: 8px; }
.plant-form-actions { display: flex; justify-content: flex-end; gap: 8px; padding-top: 8px; }

/* hidden-sm utility (复用现有规则) */
.hidden-sm { display: flex; }
@media (max-width: 640px) {
    .hidden-sm { display: none !important; }
}

/* ============================================================
 * r11 新增：代码下发页面样式（.cd-* 前缀）
 * ============================================================
 */

/* 统计卡补充：红/紫色调（在原有 .stat-card-amber/.emerald/.sky/.cyan 之外扩展） */
.stat-card-red    { background: linear-gradient(135deg, #fef2f2 0%, #fee2e2 100%); border-color: #fecaca; }
.stat-card-purple { background: linear-gradient(135deg, #faf5ff 0%, #ede9fe 100%); border-color: #ddd6fe; }
.stat-icon-red    { background: linear-gradient(135deg, #ef4444, #dc2626); }
.stat-icon-purple { background: linear-gradient(135deg, #8b5cf6, #6366f1); }

/* 部署进度卡 */
.cd-progress-wrap {
    margin: 14px 0;
}
.cd-progress-card {
    background: #fff;
    border-radius: 14px;
    overflow: hidden;
    box-shadow: var(--shadow-md);
    border: 1px solid var(--border);
}
.cd-progress-header {
    background: linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%);
    padding: 16px 20px;
    color: #fff;
}
.cd-progress-title-row {
    display: flex; align-items: center; gap: 8px;
    margin-bottom: 10px;
    font-weight: 600;
    font-size: 14px;
}
.cd-progress-title-row .spin {
    animation: spin 1s linear infinite;
}
.cd-progress-bar-wrap {
    width: 100%;
    height: 8px;
    background: rgba(255,255,255,0.2);
    border-radius: 999px;
    overflow: hidden;
}
.cd-progress-bar {
    height: 100%;
    background: #fff;
    border-radius: 999px;
    transition: width 0.4s ease;
}
.cd-progress-meta {
    font-size: 12px;
    color: rgba(255,255,255,0.85);
    margin-top: 6px;
}
.cd-progress-body {
    background: #0f172a;
    padding: 12px 16px;
}
.cd-progress-log-title {
    font-size: 12px;
    color: #94a3b8;
    display: flex; align-items: center; gap: 6px;
    margin-bottom: 8px;
}

/* 实时日志终端（深色背景） */
.cd-log-terminal {
    background: #0f172a;
    color: #cbd5e1;
    font-family: "SFMono-Regular", Menlo, Monaco, Consolas, monospace;
    font-size: 12px;
    line-height: 1.6;
    max-height: 200px;
    overflow-y: auto;
    padding: 4px 0;
}
.cd-log-terminal .cd-log-line {
    white-space: pre-wrap;
    word-break: break-all;
    padding: 1px 0;
}
.cd-log-info    { color: #cbd5e1; }
.cd-log-error   { color: #f87171; }
.cd-log-success { color: #34d399; }
.cd-log-warn    { color: #fbbf24; }

/* 任务列表 + 详情两栏布局 */
.cd-layout {
    display: grid;
    grid-template-columns: 320px 1fr;
    gap: 14px;
    margin-top: 14px;
}
@media (max-width: 900px) {
    .cd-layout { grid-template-columns: 1fr; }
}

/* 任务列表卡 */
.cd-job-list-card {
    background: #fff;
    border: 1px solid var(--border);
    border-radius: 12px;
    box-shadow: var(--shadow-sm);
    overflow: hidden;
    display: flex; flex-direction: column;
    max-height: 600px;
}
.cd-job-list-head {
    padding: 12px 14px;
    border-bottom: 1px solid var(--border);
    font-size: 13px;
    font-weight: 600;
    color: var(--text);
    display: flex; align-items: center; gap: 6px;
    background: var(--slate-50);
}
.cd-job-list-body {
    flex: 1;
    overflow-y: auto;
    padding: 8px;
    display: flex; flex-direction: column; gap: 6px;
}
.cd-job-item {
    text-align: left;
    width: 100%;
    padding: 10px;
    border: 1px solid var(--border);
    border-radius: 8px;
    background: #fff;
    cursor: pointer;
    transition: all 0.15s ease;
    display: flex; align-items: flex-start; gap: 8px;
}
.cd-job-item:hover {
    background: var(--slate-50);
    border-color: var(--slate-300);
}
.cd-job-item.active {
    border-color: var(--emerald-500);
    background: var(--emerald-50);
}
.cd-job-icon {
    font-size: 18px;
    line-height: 1.2;
}
.cd-job-info {
    flex: 1; min-width: 0;
}
.cd-job-name {
    font-size: 13px;
    font-weight: 600;
    color: var(--text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.cd-job-device {
    font-size: 11px;
    color: var(--text-mute);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    margin-top: 2px;
}
.cd-job-meta {
    display: flex; align-items: center; gap: 6px;
    margin-top: 6px;
    flex-wrap: wrap;
}
.cd-job-time {
    font-size: 11px;
    color: var(--text-mute);
}

/* 状态徽章（7 色） */
.cd-status-badge {
    display: inline-flex; align-items: center; gap: 2px;
    font-size: 11px;
    font-weight: 600;
    padding: 2px 7px;
    border-radius: 999px;
    line-height: 1.4;
}

/* 空状态 */
.cd-empty {
    text-align: center;
    padding: 32px 16px;
    color: var(--text-mute);
}
.cd-empty-icon {
    font-size: 32px;
    margin-bottom: 8px;
}
.cd-empty-title {
    font-size: 14px;
    font-weight: 600;
    color: var(--text-soft);
}
.cd-empty-desc {
    font-size: 12px;
    margin-top: 4px;
}

/* 任务详情卡 */
.cd-job-detail-card {
    background: #fff;
    border: 1px solid var(--border);
    border-radius: 12px;
    box-shadow: var(--shadow-sm);
    min-height: 400px;
    overflow: hidden;
}
.cd-detail-empty {
    text-align: center;
    padding: 80px 20px;
    color: var(--text-mute);
}
.cd-detail-empty-icon {
    font-size: 40px;
    opacity: 0.4;
    margin-bottom: 8px;
}
.cd-detail-empty-title {
    font-size: 14px;
    font-weight: 600;
    color: var(--text-soft);
    margin: 0 0 4px 0;
}
.cd-detail-empty-desc {
    font-size: 12px;
    color: var(--text-mute);
    margin: 0;
}
.cd-detail-content {
    padding: 16px 20px;
}
.cd-detail-head {
    display: flex; justify-content: space-between; align-items: flex-start;
    gap: 12px;
    padding-bottom: 12px;
    border-bottom: 1px solid var(--border-soft);
    margin-bottom: 14px;
}
.cd-detail-title {
    font-size: 16px;
    font-weight: 700;
    color: var(--text);
    display: flex; align-items: center; gap: 6px;
}
.cd-detail-meta {
    font-size: 12px;
    color: var(--text-mute);
    margin-top: 4px;
}
.cd-detail-actions {
    display: flex; align-items: center; gap: 8px;
}

/* 详情信息磁贴（4 列） */
.cd-info-tiles {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 8px;
    margin-bottom: 14px;
}
@media (max-width: 700px) {
    .cd-info-tiles { grid-template-columns: repeat(2, 1fr); }
}
.cd-info-tile {
    background: var(--slate-50);
    padding: 8px 10px;
    border-radius: 8px;
}
.cd-info-tile-label {
    font-size: 11px;
    color: var(--text-mute);
}
.cd-info-tile-value {
    font-size: 13px;
    font-weight: 600;
    color: var(--text);
    margin-top: 2px;
}

/* 错误信息卡 */
.cd-error-box {
    background: #fef2f2;
    border: 1px solid #fecaca;
    border-radius: 10px;
    padding: 10px 12px;
    margin-bottom: 14px;
    display: flex; align-items: flex-start; gap: 8px;
    font-size: 13px;
    color: #b91c1c;
}
.cd-error-box-title {
    font-weight: 600;
    margin-bottom: 2px;
}
.cd-error-box-msg {
    font-size: 12px;
    word-break: break-all;
}

/* 代码预览（深色主题） */
.cd-code-section {
    margin-bottom: 14px;
}
.cd-code-section-head {
    display: flex; align-items: center; justify-content: space-between;
    margin-bottom: 6px;
}
.cd-code-section-title {
    font-size: 12px;
    font-weight: 600;
    color: var(--text-soft);
    display: flex; align-items: center; gap: 4px;
}
.cd-code-preview {
    background: #0f172a;
    color: #cbd5e1;
    font-family: "SFMono-Regular", Menlo, Monaco, Consolas, monospace;
    font-size: 12px;
    line-height: 1.55;
    padding: 12px;
    border-radius: 8px;
    overflow: auto;
    max-height: 280px;
    white-space: pre;
}
.cd-log-preview {
    background: #0f172a;
    font-family: "SFMono-Regular", Menlo, Monaco, Consolas, monospace;
    font-size: 12px;
    line-height: 1.55;
    padding: 12px;
    border-radius: 8px;
    overflow: auto;
    max-height: 220px;
}
.cd-log-preview .cd-log-line {
    white-space: pre-wrap;
    word-break: break-all;
}

/* 链接按钮（复制等） */
.cd-link-btn {
    font-size: 11px;
    color: var(--emerald-600);
    background: none;
    border: none;
    padding: 2px 6px;
    cursor: pointer;
    display: inline-flex; align-items: center; gap: 3px;
}
.cd-link-btn:hover { color: var(--emerald-700); text-decoration: underline; }

/* 删除按钮 */
.cd-delete-btn {
    width: 28px; height: 28px;
    border: none; background: none;
    color: var(--red-500);
    cursor: pointer;
    border-radius: 6px;
    display: inline-flex; align-items: center; justify-content: center;
}
.cd-delete-btn:hover { background: #fee2e2; }

/* ============================================================
 * 代码编辑器弹窗（.cd-modal / .cd-editor）
 * ============================================================
 */
.cd-modal {
    position: fixed;
    inset: 0;
    z-index: 1000;
    display: flex; align-items: center; justify-content: center;
    padding: 16px;
}
.cd-modal-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(15, 23, 42, 0.55);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
}
.cd-modal-dialog {
    position: relative;
    background: #fff;
    border-radius: 16px;
    box-shadow: 0 25px 50px -12px rgba(0,0,0,0.5);
    width: 100%;
    max-width: 920px;
    max-height: 90vh;
    overflow: hidden;
    display: flex; flex-direction: column;
    animation: cdModalIn 0.2s ease-out;
}
@keyframes cdModalIn {
    from { opacity: 0; transform: translateY(20px) scale(0.96); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
}
.cd-modal-head {
    display: flex; align-items: center; justify-content: space-between;
    padding: 14px 20px;
    border-bottom: 1px solid var(--border);
}
.cd-modal-title-row {
    display: flex; align-items: center; gap: 8px;
    font-weight: 700;
    color: var(--text);
    font-size: 15px;
}
.cd-modal-close {
    width: 30px; height: 30px;
    border: none; background: none;
    color: var(--text-mute);
    cursor: pointer;
    border-radius: 6px;
    display: inline-flex; align-items: center; justify-content: center;
}
.cd-modal-close:hover { background: var(--slate-100); color: var(--text); }
.cd-modal-body {
    flex: 1;
    overflow-y: auto;
    padding: 16px 20px;
}
.cd-modal-foot {
    display: flex; align-items: center; justify-content: space-between;
    gap: 10px;
    padding: 12px 20px;
    border-top: 1px solid var(--border);
    background: var(--slate-50);
}
.cd-modal-foot-hint {
    font-size: 12px;
    color: var(--text-soft);
    display: flex; align-items: center; gap: 6px;
}
.cd-modal-foot-actions {
    display: flex; align-items: center; gap: 8px;
}

/* 表单 */
.cd-form-row-2 {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
    margin-bottom: 12px;
}
@media (max-width: 600px) {
    .cd-form-row-2 { grid-template-columns: 1fr; }
}
.cd-form-group {
    margin-bottom: 12px;
}
.cd-form-label {
    display: block;
    font-size: 12px;
    font-weight: 600;
    color: var(--text-soft);
    margin-bottom: 6px;
}
.cd-form-input {
    width: 100%;
    padding: 8px 10px;
    font-size: 13px;
    border: 1px solid var(--border);
    border-radius: 8px;
    background: #fff;
    color: var(--text);
    font-family: inherit;
}
.cd-form-input:focus {
    outline: none;
    border-color: var(--emerald-500);
    box-shadow: 0 0 0 3px rgba(16,185,129,0.12);
}

/* 模板选择网格（5 个） */
.cd-template-grid {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: 8px;
}
@media (max-width: 700px) {
    .cd-template-grid { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 480px) {
    .cd-template-grid { grid-template-columns: repeat(2, 1fr); }
}
.cd-template-item {
    text-align: left;
    padding: 10px;
    border: 1px solid var(--border);
    border-radius: 8px;
    background: #fff;
    cursor: pointer;
    transition: all 0.15s ease;
}
.cd-template-item:hover {
    border-color: var(--slate-300);
    background: var(--slate-50);
}
.cd-template-item.active {
    border-color: var(--emerald-500);
    background: var(--emerald-50);
}
.cd-template-icon {
    font-size: 22px;
    margin-bottom: 4px;
}
.cd-template-name {
    font-size: 12px;
    font-weight: 600;
    color: var(--text);
}
.cd-template-desc {
    font-size: 10px;
    color: var(--text-mute);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    margin-top: 2px;
}

/* 代码编辑区头部 */
.cd-code-area-head {
    display: flex; align-items: center; justify-content: space-between;
    margin-bottom: 6px;
}
.cd-code-textarea {
    width: 100%;
    min-height: 280px;
    padding: 12px;
    background: #0f172a;
    color: #e2e8f0;
    border: 1px solid #334155;
    border-radius: 8px;
    font-family: "SFMono-Regular", Menlo, Monaco, Consolas, monospace;
    font-size: 12px;
    line-height: 1.55;
    resize: vertical;
    outline: none;
}
.cd-code-textarea:focus {
    border-color: var(--emerald-500);
    box-shadow: 0 0 0 3px rgba(16,185,129,0.2);
}
.cd-code-textarea::placeholder {
    color: #64748b;
}

/* 引脚参考卡 */
.cd-pin-reference {
    background: #f0f9ff;
    border: 1px solid #bae6fd;
    border-radius: 10px;
    padding: 10px 12px;
    margin-top: 8px;
}
.cd-pin-reference-title {
    font-size: 12px;
    font-weight: 600;
    color: #0284c7;
    display: flex; align-items: center; gap: 4px;
    margin-bottom: 6px;
}
.cd-pin-reference-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 4px 8px;
    font-size: 12px;
    color: var(--text-soft);
}
@media (max-width: 500px) {
    .cd-pin-reference-grid { grid-template-columns: repeat(2, 1fr); }
}

/* 部署按钮 loading 态 */
.cd-btn-loading {
    pointer-events: none;
    opacity: 0.8;
}
.cd-btn-loading .spin {
    animation: spin 1s linear infinite;
    display: inline-block;
    vertical-align: -2px;
    margin-right: 4px;
}
