/* ==========================================================================
   智乾 IP 数据查询系统 · 统一设计系统
   --------------------------------------------------------------------------
   设计原则
     1. 所有颜色、圆角、阴影都走 CSS 变量，只在 :root 里改一次，全站生效。
     2. 默认跟随系统深浅色（prefers-color-scheme），也支持手动 data-theme 覆盖，
        便于同事在会议室投影（浅色）和加班盯屏（深色）之间切换。
     3. 老页面的 HTML 结构**一行不动**：这里通过 .zb-page 作用域去"接管"旧类名
        （.step / button / input / .preview-table ...），让存量页面直接变好看，
        把"改样式"和"改结构"的风险彻底分开。
   ========================================================================== */

/* --------------------------------------------------------------- 设计令牌 */
:root {
    --zb-bg: #f4f6fa;
    --zb-bg-elev: #ffffff;
    --zb-bg-sunken: #eef1f7;
    --zb-bg-hover: #f0f3f9;
    --zb-text: #1c2430;
    --zb-text-soft: #4a5568;
    /* 2026-09-23：由 #78849a 提到 #66738c。原来的值在白底上只有 3.6:1，
       而它的用途全是 12~13px 的小字（指标名、页脚、提示），
       达不到 WCAG AA 的 4.5:1 —— 这就是"看着费劲"的直接来源。
       新值在白底 4.78:1、在 sunken 底 4.22:1。深色主题那份本来就够（5.25:1），不动。 */
    --zb-text-muted: #66738c;
    --zb-border: #dde3ed;
    --zb-border-strong: #c3ccdb;

    --zb-primary: #2f5496;
    --zb-primary-hover: #27467e;
    --zb-primary-soft: #e7edf9;
    --zb-primary-ring: rgba(47, 84, 150, 0.18);
    --zb-accent: #d99a1a;
    --zb-accent-soft: #fdf3dc;

    --zb-ok: #1f9d55;
    --zb-ok-soft: #e4f5eb;
    --zb-warn: #c98a00;
    --zb-warn-soft: #fdf4dd;
    --zb-danger: #d0453f;
    --zb-danger-soft: #fdeceb;
    --zb-info: #2b7ab8;
    --zb-info-soft: #e6f2fb;

    /* ---- "浅底深字"配对（2026-09-23 追加）----
       soft 底 + 同色系深字。饱和色直接当浅底上的前景色，对比度只有 3.5~4:1，
       达不到 WCAG AA 的 4.5:1 —— 这正是"标签文字看着费劲"的来源。
       所以每种语义色单列一个"墨色"，专供浅底文字。 */
    --zb-ok-ink: #14663a;
    --zb-warn-ink: #7a5200;
    --zb-danger-ink: #a02e29;
    --zb-info-ink: #1d5c8c;
    --zb-accent-ink: #8a5a00;

    /* ---- 胶囊标签（代理师 / 专利动态）----
       这两个是"实心底 + 白字"，底与字必须**成对**定义。
       教训：原实现只写 background 没写 color，于是标签文字继承页面正文色
       （浅色主题下是 #1c2430），在 #2f5496 的深蓝实心底上几乎同色 ——
       代理师姓名与件数看起来就是一片糊的色块。 */
    --zb-tag-agent-bg: #2f5496;
    --zb-tag-agent-fg: #ffffff;
    --zb-tag-patent-bg: #6a4ba8;
    --zb-tag-patent-fg: #ffffff;

    --zb-radius: 14px;
    --zb-radius-sm: 9px;
    --zb-radius-pill: 999px;

    --zb-shadow-1: 0 1px 2px rgba(16, 24, 40, .05), 0 1px 3px rgba(16, 24, 40, .09);
    --zb-shadow-2: 0 6px 18px rgba(16, 24, 40, .09);
    --zb-shadow-3: 0 18px 44px rgba(16, 24, 40, .16);

    --zb-font: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
        "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", sans-serif;
    --zb-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
        "Liberation Mono", monospace;

    --zb-nav-h: 56px;
    --zb-speed: .18s;
}

/* 深色令牌（抽出来只在下面复用两次，避免三处漂移） */
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
        --zb-bg: #0e131d;
        --zb-bg-elev: #161d2a;
        --zb-bg-sunken: #101724;
        --zb-bg-hover: #1d2635;
        --zb-text: #e6ebf3;
        --zb-text-soft: #aeb9ca;
        --zb-text-muted: #7d899c;
        --zb-border: #263140;
        --zb-border-strong: #37455a;

        --zb-primary: #5b83c9;
        --zb-primary-hover: #7099dd;
        --zb-primary-soft: #1b2637;
        --zb-primary-ring: rgba(91, 131, 201, .26);
        --zb-accent: #e0ad3c;
        --zb-accent-soft: #2a2413;

        --zb-ok: #3fbb74;
        --zb-ok-soft: #14291f;
        --zb-warn: #dca62a;
        --zb-warn-soft: #2b2412;
        --zb-danger: #e2685f;
        --zb-danger-soft: #2e1a19;
        --zb-info: #56a6e0;
        --zb-info-soft: #132635;

        --zb-ok-ink: #7fd6a4;
        --zb-warn-ink: #f0c86a;
        --zb-danger-ink: #e2685f;
        --zb-info-ink: #8ec6ee;
        --zb-accent-ink: #e0ad3c;
        /* 深色下实心标签底要压暗一档：直接用 --zb-primary（#5b83c9）配白字
           只有 3.8:1，偏亮。压到 #35507d 后回到 8.1:1。 */
        --zb-tag-agent-bg: #35507d;
        --zb-tag-agent-fg: #ffffff;
        --zb-tag-patent-bg: #4e3a7d;
        --zb-tag-patent-fg: #ffffff;

        --zb-shadow-1: 0 1px 2px rgba(0, 0, 0, .4);
        --zb-shadow-2: 0 6px 18px rgba(0, 0, 0, .45);
        --zb-shadow-3: 0 18px 44px rgba(0, 0, 0, .6);
    }
}

:root[data-theme="dark"] {
    --zb-bg: #0e131d;
    --zb-bg-elev: #161d2a;
    --zb-bg-sunken: #101724;
    --zb-bg-hover: #1d2635;
    --zb-text: #e6ebf3;
    --zb-text-soft: #aeb9ca;
    --zb-text-muted: #7d899c;
    --zb-border: #263140;
    --zb-border-strong: #37455a;

    --zb-primary: #5b83c9;
    --zb-primary-hover: #7099dd;
    --zb-primary-soft: #1b2637;
    --zb-primary-ring: rgba(91, 131, 201, .26);
    --zb-accent: #e0ad3c;
    --zb-accent-soft: #2a2413;

    --zb-ok: #3fbb74;
    --zb-ok-soft: #14291f;
    --zb-warn: #dca62a;
    --zb-warn-soft: #2b2412;
    --zb-danger: #e2685f;
    --zb-danger-soft: #2e1a19;
    --zb-info: #56a6e0;
    --zb-info-soft: #132635;

    --zb-ok-ink: #7fd6a4;
    --zb-warn-ink: #f0c86a;
    --zb-danger-ink: #e2685f;
    --zb-info-ink: #8ec6ee;
    --zb-accent-ink: #e0ad3c;
    --zb-tag-agent-bg: #35507d;
    --zb-tag-agent-fg: #ffffff;
    --zb-tag-patent-bg: #4e3a7d;
    --zb-tag-patent-fg: #ffffff;

    --zb-shadow-1: 0 1px 2px rgba(0, 0, 0, .4);
    --zb-shadow-2: 0 6px 18px rgba(0, 0, 0, .45);
    --zb-shadow-3: 0 18px 44px rgba(0, 0, 0, .6);
}

/* ----------------------------------------------------------- 基础排版接管 */
/* 只给"带 .zb-page 的页面"换皮；登录页那种自带艺术背景的页面不受影响。 */
body.zb-page {
    background: var(--zb-bg) !important;
    color: var(--zb-text);
    font-family: var(--zb-font);
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}

.zb-page a { color: var(--zb-primary); }
.zb-page a:hover { color: var(--zb-primary-hover); }

.zb-page ::selection { background: var(--zb-primary-ring); }

/* 滚动条（WebKit / 新版 Firefox 都照顾到） */
.zb-page ::-webkit-scrollbar { width: 10px; height: 10px; }
.zb-page ::-webkit-scrollbar-track { background: transparent; }
.zb-page ::-webkit-scrollbar-thumb {
    background: var(--zb-border-strong);
    border-radius: var(--zb-radius-pill);
    border: 2px solid transparent;
    background-clip: content-box;
}
.zb-page ::-webkit-scrollbar-thumb:hover { background: var(--zb-text-muted); background-clip: content-box; }

/* ------------------------------------------------- 旧页面结构升级（卡片） */
.zb-page .step {
    background: var(--zb-bg-elev) !important;
    border: 1px solid var(--zb-border) !important;
    border-radius: var(--zb-radius) !important;
    box-shadow: var(--zb-shadow-1);
    padding: 18px 20px !important;
    margin-bottom: 18px !important;
    transition: box-shadow var(--zb-speed) ease;
}
.zb-page .step:hover { box-shadow: var(--zb-shadow-2); }

.zb-page .deadline-card {
    background: var(--zb-accent-soft) !important;
    border-left: 6px solid var(--zb-accent) !important;
    border-radius: var(--zb-radius) !important;
    box-shadow: var(--zb-shadow-1);
    color: var(--zb-text);
}
.zb-page .deadline-card h3 { color: var(--zb-text) !important; }

/* 统计块原先用 --zb-bg-elev，而它所在的卡片底色也是 --zb-bg-elev —— 白底白块，
   只靠一道浅描边分界，"标签背景色"基本看不出来。改用下沉底色把它托起来。 */
.zb-page .stat-item {
    background: var(--zb-bg-sunken) !important;
    border: 1px solid var(--zb-border);
    border-radius: var(--zb-radius-sm);
    box-shadow: none !important;
}
/* 数字换 accent-ink：原色 --zb-accent(#d99a1a) 在白底上只有 2.45:1，
   连"大号文字 3:1"这条都不到；accent-ink 在 sunken 底上是 4.07:1。 */
.zb-page .stat-number { color: var(--zb-accent-ink) !important; }
.zb-page .stat-label { color: var(--zb-text-soft) !important; }

.zb-page .category-item {
    background: var(--zb-bg-sunken) !important;
    color: var(--zb-text-soft);
    border: 1px solid var(--zb-border);
    transition: all var(--zb-speed) ease;
}
.zb-page .category-item:hover { background: var(--zb-primary-soft) !important; color: var(--zb-primary); }
.zb-page .gf-item { background: var(--zb-danger-soft) !important; color: var(--zb-danger-ink) !important; }

/* 实心标签必须**同时**给底色和文字色。原实现只写了 background，文字于是继承
   页面正文色（浅色主题下是 #1c2430），压在 #2f5496 的深蓝实心底上几乎同色 ——
   "各代理师待处理的案件量"下面那些姓名与件数，看起来就是一片糊住的色块。 */
.zb-page .agent-tag {
    background: var(--zb-tag-agent-bg) !important;
    color: var(--zb-tag-agent-fg) !important;
    border-radius: var(--zb-radius-pill);
    font-weight: 600;
    transition: transform var(--zb-speed) ease, filter var(--zb-speed) ease;
}
.zb-page .agent-tag:hover { transform: translateY(-1px); filter: brightness(1.08); }
/* 专利动态标签同理；原先底色写死 #7c5bb8，深色主题下也不够亮，一并改用令牌。 */
.zb-page .patent-tag {
    background: var(--zb-tag-patent-bg) !important;
    color: var(--zb-tag-patent-fg) !important;
    border-radius: var(--zb-radius-pill);
}

.zb-page .limited-notice {
    background: var(--zb-warn-soft) !important;
    border-left: 4px solid var(--zb-warn) !important;
    color: var(--zb-text);
    border-radius: var(--zb-radius-sm);
}
.zb-page .result-area { background: var(--zb-bg-sunken) !important; border-radius: var(--zb-radius) !important; }
.zb-page .error { color: var(--zb-danger) !important; }

/* ------------------------------------------------------------- 表单控件 */
.zb-page input[type="text"],
.zb-page input[type="password"],
.zb-page input[type="number"],
.zb-page input[type="email"],
.zb-page input[type="date"],
.zb-page input[type="search"],
.zb-page select,
.zb-page textarea {
    background: var(--zb-bg-elev);
    color: var(--zb-text);
    border: 1px solid var(--zb-border);
    border-radius: var(--zb-radius-sm);
    padding: 7px 10px;
    font-family: inherit;
    font-size: 14px;
    line-height: 1.5;
    transition: border-color var(--zb-speed) ease, box-shadow var(--zb-speed) ease;
}
.zb-page input[type="text"]:hover,
.zb-page select:hover,
.zb-page textarea:hover { border-color: var(--zb-border-strong); }

.zb-page input:focus,
.zb-page select:focus,
.zb-page textarea:focus {
    outline: none;
    border-color: var(--zb-primary);
    box-shadow: 0 0 0 3px var(--zb-primary-ring);
}

.zb-page input[type="checkbox"],
.zb-page input[type="radio"] { accent-color: var(--zb-primary); width: 15px; height: 15px; }

.zb-page label { color: var(--zb-text-soft); }

/* --------------------------------------------------------------- 按钮 */
/* 只动"外观质感"，不动配色 —— 旧页面按钮的 background 都是品牌蓝，
   留着不换色风险最小；这里统一圆角/字重/过渡/禁用态。 */
.zb-page button,
.zb-page .btn {
    border-radius: var(--zb-radius-sm);
    font-family: inherit;
    font-weight: 600;
    letter-spacing: .2px;
    transition: filter var(--zb-speed) ease, transform var(--zb-speed) ease,
        box-shadow var(--zb-speed) ease;
}
.zb-page button:hover:not(:disabled),
.zb-page .btn:hover { filter: brightness(1.08); box-shadow: var(--zb-shadow-1); }
.zb-page button:active:not(:disabled) { transform: translateY(1px); }
.zb-page button:disabled { opacity: .55; cursor: not-allowed; filter: grayscale(.4); }
.zb-page button:focus-visible,
.zb-page .btn:focus-visible { outline: 3px solid var(--zb-primary-ring); outline-offset: 1px; }

.zb-page .download-html-btn {
    border-color: var(--zb-primary) !important;
    color: var(--zb-primary) !important;
    border-radius: var(--zb-radius-pill);
    font-weight: 600;
}
.zb-page .download-html-btn:hover { background: var(--zb-primary-soft) !important; }

/* --------------------------------------------------------------- 表格 */
.zb-page .preview-table {
    border-collapse: separate;
    border-spacing: 0;
    border: 1px solid var(--zb-border);
    border-radius: var(--zb-radius-sm);
    overflow: hidden;
    font-size: 13px;
    background: var(--zb-bg-elev);
}
.zb-page .preview-table th {
    background: var(--zb-bg-sunken) !important;
    color: var(--zb-text-soft);
    font-weight: 600;
    text-align: left;
    padding: 9px 10px !important;
    border: none;
    border-bottom: 1px solid var(--zb-border);
    position: sticky;
    top: 0;
    z-index: 10;
    white-space: nowrap;
}
.zb-page .preview-table td {
    padding: 7px 10px !important;
    border: none;
    border-bottom: 1px solid var(--zb-border);
    color: var(--zb-text);
    vertical-align: top;
}
.zb-page .preview-table tbody tr:nth-child(even) td { background: var(--zb-bg-sunken); }
.zb-page .preview-table tbody tr:hover td { background: var(--zb-primary-soft); }
.zb-page .preview-table tbody tr:last-child td { border-bottom: none; }

/* ------------------------------------------------------------------ 提示条 */
.zb-page .toast,
.zb-toast {
    position: fixed;
    top: 22px;
    left: 50%;
    transform: translateX(-50%);
    background: var(--zb-bg-elev);
    color: var(--zb-text);
    border: 1px solid var(--zb-border);
    border-left: 4px solid var(--zb-ok);
    padding: 13px 20px;
    border-radius: var(--zb-radius);
    font-size: 15px;
    font-weight: 500;
    z-index: 9999;
    max-width: min(80vw, 560px);
    text-align: center;
    white-space: pre-wrap;
    word-break: break-word;
    box-shadow: var(--zb-shadow-3);
    animation: zb-toast-in .22s cubic-bezier(.2, .9, .3, 1.2);
}
.zb-page .toast.error,
.zb-toast.error { border-left-color: var(--zb-danger); }
.zb-page .toast.warn,
.zb-toast.warn { border-left-color: var(--zb-warn); }
.zb-page .toast.info,
.zb-toast.info { border-left-color: var(--zb-info); }

@keyframes zb-toast-in {
    from { opacity: 0; transform: translate(-50%, -14px) scale(.97); }
    to { opacity: 1; transform: translate(-50%, 0) scale(1); }
}

/* ======================================================================== */
/*            以下为 .zb-* 组件类：新页面（诊断页等）直接使用               */
/* ======================================================================== */

/* ------------------------------------------------------------------ 导航条 */
.zb-nav {
    position: sticky;
    top: 0;
    z-index: 900;
    display: flex;
    align-items: center;
    gap: 4px;
    /* ⚠️ 必须是 min-height，不能写死 height（v2.3.43 修）。
       原来写死 height: var(--zb-nav-h)=56px，而 .zb-nav-links 是 flex-wrap:wrap：
       全站导航项 17 个（普通员工至少 15 个），任何 900~1400px 的窗口都放不下，
       必然折成 2~3 行（30 天内测出的实际折法是 7+6+2）。
       固定 56px + align-items:center 会把折出来的行**上下各顶出一截**；
       而本元素是 position:sticky; top:0 —— 上边缘正好在视口 y=0，
       顶到上边缘以上的那一行直接被视口裁掉（邓老师 2026-10-07 截图：
       主页导航第一行只剩半个字，看起来像"位置太高被遮挡"）。
       改成 min-height + 上下各 7px 内边距后，导航条随内容长高，
       第一行永远有完整的行高在视口内。 */
    min-height: var(--zb-nav-h);
    padding: 7px 18px;
    background: color-mix(in srgb, var(--zb-bg-elev) 88%, transparent);
    backdrop-filter: saturate(180%) blur(12px);
    -webkit-backdrop-filter: saturate(180%) blur(12px);
    border-bottom: 1px solid var(--zb-border);
}

.zb-brand {
    display: flex;
    align-items: center;
    gap: 9px;
    font-weight: 700;
    font-size: 16px;
    letter-spacing: .3px;
    color: var(--zb-text);
    text-decoration: none;
    margin-right: 14px;
    white-space: nowrap;
}
.zb-brand:hover { color: var(--zb-text); }
.zb-brand .zb-dot {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: linear-gradient(135deg, var(--zb-primary), var(--zb-accent));
    box-shadow: 0 0 0 3px var(--zb-primary-soft);
}
.zb-brand small { font-weight: 500; color: var(--zb-text-muted); font-size: 12px; }

.zb-nav-links { display: flex; align-items: center; gap: 2px; flex: 1; flex-wrap: wrap; }

.zb-nav-link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 7px 13px;
    border-radius: var(--zb-radius-pill);
    color: var(--zb-text-soft);
    text-decoration: none;
    font-size: 14px;
    font-weight: 500;
    white-space: nowrap;
    transition: background var(--zb-speed) ease, color var(--zb-speed) ease;
}
.zb-nav-link:hover { background: var(--zb-bg-hover); color: var(--zb-text); }
.zb-nav-link.is-active { background: var(--zb-primary-soft); color: var(--zb-primary); font-weight: 600; }

.zb-nav-right { display: flex; align-items: center; gap: 6px; }

.zb-user {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px 10px 4px 4px;
    border-radius: var(--zb-radius-pill);
    background: var(--zb-bg-sunken);
    font-size: 13px;
    color: var(--zb-text-soft);
    white-space: nowrap;
}
.zb-avatar {
    width: 26px;
    height: 26px;
    border-radius: 50%;
    display: grid;
    place-items: center;
    background: linear-gradient(135deg, var(--zb-primary), #6b93d6);
    color: #fff;
    font-size: 12px;
    font-weight: 700;
    flex: none;
}

.zb-icon-btn {
    width: 34px;
    height: 34px;
    display: grid;
    place-items: center;
    border: 1px solid var(--zb-border);
    background: var(--zb-bg-elev);
    color: var(--zb-text-soft);
    border-radius: var(--zb-radius-sm);
    cursor: pointer;
    font-size: 15px;
    padding: 0;
    transition: all var(--zb-speed) ease;
}
.zb-icon-btn:hover { background: var(--zb-bg-hover); color: var(--zb-text); border-color: var(--zb-border-strong); filter: none; }

/* ------------------------------------------------- 旧主页顶部条瘦身升级 */
/* index.html 原来的导航是"跑马灯 + 蓝色大条"内联样式写死的（2006 年风格）。
   注入脚本把这几处内联样式换成了下面这几个类，HTML 结构完全没动。
   内联样式优先级最高，所以配色这里必须 !important 才能压过去。 */
.zb-topbar {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    z-index: 999;
    background: color-mix(in srgb, var(--zb-bg-elev) 90%, transparent);
    backdrop-filter: saturate(180%) blur(14px);
    -webkit-backdrop-filter: saturate(180%) blur(14px);
    border-bottom: 1px solid var(--zb-border);
    box-shadow: 0 1px 3px rgba(16, 24, 40, .07);
}

.zb-topbar-ticker {
    text-align: center;
    padding: 7px 12px 6px;
    background: transparent;
    border-bottom: 1px dashed var(--zb-border);
}
.zb-topbar-ticker marquee {
    font-size: 15px !important;
    font-weight: 600 !important;
    color: var(--zb-text-soft) !important;
    letter-spacing: .4px;
}

.zb-topbar-nav {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    padding: 7px 16px;
    background: transparent;
}

.zb-topbar-nav a {
    display: inline-block;
    color: var(--zb-text-soft) !important;
    margin: 0 3px !important;
    padding: 6px 12px;
    border-radius: var(--zb-radius-pill);
    text-decoration: none !important;
    font-size: 14px;
    font-weight: 500;
    transition: background var(--zb-speed) ease, color var(--zb-speed) ease;
}
.zb-topbar-nav a:hover {
    background: var(--zb-primary-soft) !important;
    color: var(--zb-primary) !important;
}

.zb-topbar-spacer { height: 96px; }

@media (max-width: 760px) {
    .zb-topbar-ticker marquee { font-size: 13px !important; }
    .zb-topbar-nav { padding: 6px 8px; }
    .zb-topbar-nav a { padding: 5px 9px; font-size: 13px; }
    .zb-topbar-spacer { height: 132px; }
}

/* ------------------------------------------------------------------ 容器 */
.zb-wrap { max-width: 1400px; margin: 0 auto; padding: 22px 18px 60px; }
.zb-wrap-narrow { max-width: 940px; }

.zb-page-head {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    justify-content: flex-start;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 20px;
}
.zb-page-head h1 { margin: 0; font-size: 24px; font-weight: 700; letter-spacing: -.3px; }
.zb-page-head p { margin: 6px 0 0; color: var(--zb-text-muted); font-size: 14px; }

/* ------------------------------------------------------------------ 卡片 */
.zb-card {
    background: var(--zb-bg-elev);
    border: 1px solid var(--zb-border);
    border-radius: var(--zb-radius);
    box-shadow: var(--zb-shadow-1);
    padding: 20px;
    margin-bottom: 18px;
}
.zb-card > h2,
.zb-card > h3 {
    margin: 0 0 14px;
    font-size: 16px;
    font-weight: 700;
    display: flex;
    align-items: center;
    gap: 8px;
}
.zb-card > h2:only-child, .zb-card > h3:only-child { margin-bottom: 0; }
.zb-card-flush { padding: 0; overflow: hidden; }

.zb-grid { display: grid; gap: 14px; }
.zb-grid-2 { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
.zb-grid-3 { grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); }
.zb-grid-4 { grid-template-columns: repeat(auto-fit, minmax(165px, 1fr)); }

/* ------------------------------------------------------------------ 指标 */
.zb-metric {
    background: var(--zb-bg-elev);
    border: 1px solid var(--zb-border);
    border-radius: var(--zb-radius);
    padding: 16px 18px;
    box-shadow: var(--zb-shadow-1);
}
.zb-metric .k { font-size: 12px; color: var(--zb-text-muted); font-weight: 500; letter-spacing: .4px; text-transform: uppercase; }
.zb-metric .v { font-size: 26px; font-weight: 700; margin-top: 6px; font-variant-numeric: tabular-nums; }
.zb-metric .s { font-size: 12px; color: var(--zb-text-muted); margin-top: 4px; word-break: break-all; }
/* 状态数字用 ink 而非亮色：亮色主题下 --zb-ok(#1f9d55) 压在卡片底(#ffffff)
 * 只有 3.49:1 —— 大号数字勉强够 AA 大字（3:1），但 warn/danger 会更低。
 * ink 令牌本就是为"亮底深字"准备的，这里统一过去，两主题都不需要再单独调。 */
.zb-metric.ok .v { color: var(--zb-ok-ink); }
.zb-metric.warn .v { color: var(--zb-warn-ink); }
.zb-metric.danger .v { color: var(--zb-danger-ink); }
.zb-metric.info .v { color: var(--zb-info-ink); }

/* ------------------------------------------------------------------ 徽标 */
.zb-badge {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 10px;
    border-radius: var(--zb-radius-pill);
    font-size: 12px;
    font-weight: 600;
    line-height: 1.6;
    white-space: nowrap;
}
/* 徽标一律走"浅底 + 同色系墨字"的配对。原先直接用饱和色当前景
   （例如 --zb-warn #c98a00 压在 #fdf4dd 上只有 3.4:1），12px 的小字
   达不到 AA 4.5:1，看着发虚。 */
.zb-badge.ok { background: var(--zb-ok-soft); color: var(--zb-ok-ink); }
.zb-badge.warn { background: var(--zb-warn-soft); color: var(--zb-warn-ink); }
.zb-badge.danger { background: var(--zb-danger-soft); color: var(--zb-danger-ink); }
.zb-badge.info { background: var(--zb-info-soft); color: var(--zb-info-ink); }
.zb-badge.muted { background: var(--zb-bg-sunken); color: var(--zb-text-soft); }
.zb-badge.primary { background: var(--zb-primary-soft); color: var(--zb-primary); }

/* ------------------------------------------------------------------ 表格 */
.zb-table {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    font-size: 13px;
    background: var(--zb-bg-elev);
    border: 1px solid var(--zb-border);
    border-radius: var(--zb-radius);
    overflow: hidden;
}
.zb-table th {
    text-align: left;
    font-weight: 600;
    color: var(--zb-text-soft);
    background: var(--zb-bg-sunken);
    padding: 10px 13px;
    border-bottom: 1px solid var(--zb-border);
    white-space: nowrap;
}
.zb-table td {
    padding: 9px 13px;
    border-bottom: 1px solid var(--zb-border);
    vertical-align: top;
    color: var(--zb-text);
}
.zb-table tbody tr:nth-child(even) td { background: var(--zb-bg-sunken); }
.zb-table tbody tr:hover td { background: var(--zb-primary-soft); }
.zb-table tbody tr:last-child td { border-bottom: none; }
.zb-table .num { text-align: right; font-variant-numeric: tabular-nums; }
.zb-table code, .zb-code {
    font-family: var(--zb-mono);
    font-size: 12px;
    background: var(--zb-bg-sunken);
    border: 1px solid var(--zb-border);
    border-radius: 6px;
    padding: 1px 6px;
    word-break: break-all;
}

/* ------------------------------------------------------------------ 按钮 */
.zb-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    padding: 8px 16px;
    border-radius: var(--zb-radius-sm);
    border: 1px solid transparent;
    background: var(--zb-primary);
    color: #fff;
    font-family: inherit;
    font-size: 14px;
    font-weight: 600;
    text-decoration: none;
    cursor: pointer;
    transition: all var(--zb-speed) ease;
}
.zb-btn:hover { background: var(--zb-primary-hover); color: #fff; box-shadow: var(--zb-shadow-1); }
.zb-btn:active { transform: translateY(1px); }
.zb-btn:disabled { opacity: .55; cursor: not-allowed; }
.zb-btn-ghost { background: var(--zb-bg-elev); color: var(--zb-text-soft); border-color: var(--zb-border); }
.zb-btn-ghost:hover { background: var(--zb-bg-hover); color: var(--zb-text); border-color: var(--zb-border-strong); }
.zb-btn-danger { background: var(--zb-danger); }
.zb-btn-danger:hover { background: #b83a35; }
.zb-btn-sm { padding: 5px 11px; font-size: 13px; }

/* ---------------------------------------------------------------------------
   ⚠️ 2026-09-23 修：链接型按钮的文字彻底看不见
   ---------------------------------------------------------------------------
   `.zb-page a` 的优先级是 (0,1,1)，`.zb-btn` 只有 (0,1,0) —— 前者更高。
   于是 <a class="zb-btn"> 的 color 被解析成 var(--zb-primary)，
   与它自己的 background var(--zb-primary) **完全相同**，字就没了。
   「📥 下载 Excel」正是这种写法：亮色、暗色主题下都一样看不见。
   （悬停时反而能看见 —— 因为 .zb-btn:hover 是 (0,2,0) 又高回来了。
   这个"只有指上去才现字"的细节就是当初锁定原因的入口。）
   下面用 (0,2,1) 的选择器把链接型按钮的文字色明确提回来。 */
.zb-page a.zb-btn,
.zb-page a.zb-btn-danger { color: #fff; }
.zb-page a.zb-btn-ghost { color: var(--zb-text-soft); }
.zb-page a.zb-btn-ghost:hover { color: var(--zb-text); }

/* ------------------------------------------------------------------ 表单 */
.zb-field { margin-bottom: 16px; }
.zb-field > label { display: block; font-size: 13px; font-weight: 600; color: var(--zb-text-soft); margin-bottom: 6px; }
.zb-field .hint { font-size: 12px; color: var(--zb-text-muted); margin-top: 5px; }
.zb-input, .zb-select {
    width: 100%;
    box-sizing: border-box;
    padding: 9px 12px;
    border: 1px solid var(--zb-border);
    border-radius: var(--zb-radius-sm);
    background: var(--zb-bg-elev);
    color: var(--zb-text);
    font-family: inherit;
    font-size: 14px;
    transition: border-color var(--zb-speed) ease, box-shadow var(--zb-speed) ease;
}
.zb-input:focus, .zb-select:focus {
    outline: none;
    border-color: var(--zb-primary);
    box-shadow: 0 0 0 3px var(--zb-primary-ring);
}

/* ------------------------------------------------------------------ 空态 */
.zb-empty { text-align: center; padding: 44px 20px; color: var(--zb-text-muted); }
.zb-empty .ic { font-size: 34px; opacity: .5; margin-bottom: 10px; }

/* ------------------------------------------------------------------ 分隔 */
.zb-divider { height: 1px; background: var(--zb-border); border: 0; margin: 18px 0; }

/* ---------------------------------------------------------------- 提示框 */
.zb-note {
    display: flex;
    gap: 10px;
    padding: 12px 15px;
    border-radius: var(--zb-radius-sm);
    border-left: 4px solid var(--zb-info);
    background: var(--zb-info-soft);
    color: var(--zb-text);
    font-size: 13.5px;
    line-height: 1.7;
}
.zb-note.warn { border-left-color: var(--zb-warn); background: var(--zb-warn-soft); }
.zb-note.danger { border-left-color: var(--zb-danger); background: var(--zb-danger-soft); }
.zb-note.ok { border-left-color: var(--zb-ok); background: var(--zb-ok-soft); }

/* ------------------------------------------------------------ 加载骨架 */
.zb-spinner {
    width: 16px;
    height: 16px;
    border: 2px solid currentColor;
    border-top-color: transparent;
    border-radius: 50%;
    display: inline-block;
    animation: zb-spin .7s linear infinite;
}
@keyframes zb-spin { to { transform: rotate(360deg); } }

/* --------------------------------------------------------- 底部构建信息 */
.zb-foot {
    margin-top: 34px;
    padding-top: 16px;
    border-top: 1px solid var(--zb-border);
    display: flex;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    font-size: 12px;
    color: var(--zb-text-muted);
}

/* ------------------------------------------------------------ 响应式 */
@media (max-width: 760px) {
    .zb-nav { height: auto; padding: 10px 12px; flex-wrap: wrap; gap: 8px; }
    .zb-nav-links { order: 3; width: 100%; overflow-x: auto; }
    .zb-user span.zb-uname { display: none; }
    .zb-wrap { padding: 16px 12px 48px; }
    .zb-page-head h1 { font-size: 20px; }
    .zb-metric .v { font-size: 22px; }
}

/* ------------------------------------------------------------ 打印友好 */
@media print {
    .zb-nav, .zb-icon-btn, .zb-foot { display: none !important; }
    body.zb-page { background: #fff !important; }
    .zb-card, .zb-table, .zb-metric { box-shadow: none !important; break-inside: avoid; }
}
