/* ==========================================================================
   Longcos OTA · Web v2
   现代浅色 B 端控制台：浅色侧栏 + 圆角卡片 + 彩色指标块 + 圆角搜索/筛选。
   状态用色（绿=已发布 / 蓝=内测中 / 琥珀=已下架 / 红=失败），每个状态都带文字，
   不靠颜色单独承载信息。
   ========================================================================== */

@font-face {
  font-family: "Plus Jakarta Sans";
  src: url("/static/fonts/PlusJakartaSans-latin.woff2") format("woff2");
  font-style: normal;
  font-weight: 500 800;
  font-display: swap;
}

@font-face {
  font-family: "JetBrains Mono";
  src: url("/static/fonts/JetBrainsMono-latin.woff2") format("woff2");
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
}

:root {
  --bg:         #f4f5f9;
  --card:       #fdfdff;   /* 纯白会显得"死"，往品牌色相偏一点 */
  --card-2:     #fafbfd;
  --card-3:     #f7f8fc;
  --line:       #eaecf3;
  --line-2:     #f1f3f8;

  /* 文字层级：三级都满足 WCAG AA（对白底 ≥4.5:1）
     --ink-4 只用于装饰（分隔符/图标），不承载任何文字 */
  --ink:        #171a2b;   /* 17.2:1 */
  --ink-2:      #4a4f63;   /*  8.1:1 */
  --ink-3:      #666b80;   /*  4.6:1 以上（对所有软底都达标） */
  --ink-4:      #7e8397;   /*  3.8:1 —— 仅装饰 */

  --brand:      #5b5bd6;
  --brand-2:    #7b7bf0;
  --brand-soft: #eeeeff;
  --brand-ink:  #4a4ac0;

  /* 状态色：*-ink 是该状态在软底上的文字色，逐个压到 ≥4.5:1 */
  --mint:       #00a971;  --mint-soft:   #e2f8f0;  --mint-ink:   #007f4f;
  --sky:        #3b82f6;  --sky-soft:    #e7f0ff;  --sky-ink:    #1b6bd0;
  --amber-soft: #fff3df;  --amber-ink:  #a46000;
  --coral:      #ef4444;  --coral-soft:  #fdeaea;  --coral-ink:  #c53030;
  --orange-soft: #ffeee3;  --orange-ink: #c2410c;
  --slate-soft: #eef1f6;  --slate-ink:   #5e6e85;

  /* 有序色阶（升级漏斗 / 序数量值）：单色相、亮度单调、相邻 ΔL≥0.06
     已过 dataviz ordinal 校验；对轨道底 #eef0f6 全部 ≥3:1 */
  --ramp-1:     #688dba;
  --ramp-2:     #3f6299;
  --ramp-3:     #2a497c;
  --ramp-4:     #1b3357;

  /* 图表辅助 */
  --track:      #eef0f6;   /* 条形 / 漏斗轨道底 */
  --hatch:      #c9cbd5;   /* 无数据斜纹（线） */
  --hatch-2:    #eef0f7;   /* 无数据斜纹（底） */
  --fill-2:     #f2f4fa;   /* 悬浮/行 hover 底 */

  /* 其余固定色，统一收进 token，避免散落的魔法色值 */
  --line-3:      #ccd1e2;  /* 弱连接线 / 虚线框 */
  --hover-line:  #c9cbe8;  /* 品牌色淡描边（hover） */
  --danger-deep: #b91c1c;  /* toast 底 */
  --amber-deep:  #8a5606;  /* 提示文字（深） */
  --amber-deep2: #6d4405;
  --danger-deep2:#9d2626;
  --danger-deep3:#8b1f1f;

  --on-accent:   #ffffff;  /* 深色块上的文字 */

  /* 浅底（登录页 / 轨道面板） */
  --login-glow-1:#e6e7ff;
  --login-glow-2:#e2f6ef;
  --login-lede-1:#f7f7ff;
  --board-g-2:   #fbfbfe;

  --brand-soft-2:#e3e3ff;  /* .btn.soft hover */
  --coral-soft-2: #fbdede; /* .btn.danger hover */

  /* 字号刻度：全站只用这几档，不再散落半档取值 */
  --fs-3xs: 10px;    /* 角标、chip 前的图标 */
  --fs-2xs: 11px;    /* 表头、等宽小字 */
  --fs-xs:  11.5px;  /* 脚注、状态 chip */
  --fs-sm:  12.5px;  /* 卡片副标题、说明段 */
  --fs-md:  13.5px;  /* 表格正文、列表主文案 */
  --fs-lg:  15.5px;  /* 卡片标题 */
  --fs-xl:  17px;    /* 弹窗标题 */
  --fs-2xl: 20px;    /* 页面 / 抽屉标题 */
  --fs-3xl: 24px;    /* 指标数字 */
  --fs-4xl: 30px;    /* 登录页大标题 */

  --r-card: 18px;
  --r-btn:  10px;
  --r-pill: 999px;

  --shadow:    0 1px 2px rgba(16, 24, 40, .04), 0 8px 24px rgba(16, 24, 40, .05);
  --shadow-lg: 0 2px 6px rgba(16, 24, 40, .05), 0 20px 48px rgba(16, 24, 40, .10);

  /* 拉丁字体在前：Plus Jakarta 不含中文字形，中文会自动落到 PingFang / Noto SC。
     数字与中文分属两套字体是中文产品的常规做法，不是缺陷。 */
  --font: "Plus Jakarta Sans", "PingFang SC", "Noto Sans SC", "Microsoft YaHei", system-ui, sans-serif;
  --font-mono: "JetBrains Mono", "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  --rail-w: 236px;
  --drawer-w: 560px;
}

* { box-sizing: border-box; }
html { min-height: 100%; overflow-x: hidden; }
body { min-height: 100%; overflow-x: clip; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: var(--fs-md)/1.55 var(--font);
  -webkit-font-smoothing: antialiased;
}

html.auth-restoring #login { display: none !important; }
html.auth-restoring #shell { display: grid !important; }

h1, h2, h3, p, ol, ul, dl, dd, figure { margin: 0; }
ol, ul { padding: 0; list-style: none; }
button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; background: none; border: 0; padding: 0; }
a { color: var(--brand-ink); text-decoration: none; }
table { border-collapse: collapse; width: 100%; }
[hidden] { display: none !important; }

:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; border-radius: 4px; }

.mono { font-family: var(--font-mono); font-size: .92em; letter-spacing: -.01em; }
.muted { color: var(--ink-3); }
.right { text-align: right; }
.nowrap { white-space: nowrap; }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

/* ============================ 登录 ==================================== */

.login {
  /* body now uses min-height so mobile pages can scroll; keep the login card
     centred against the actual viewport instead of its own content height. */
  min-height: 100vh;
  min-height: 100dvh;
  display: grid; place-items: center; padding: 32px 20px;
  background:
    radial-gradient(1100px 520px at 12% -8%, var(--login-glow-1) 0%, transparent 60%),
    radial-gradient(900px 480px at 96% 8%, var(--login-glow-2) 0%, transparent 58%),
    var(--bg);
}

.login-card {
  width: min(900px, 100%);
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 24px;
  box-shadow: var(--shadow-lg);
  display: grid; grid-template-columns: 1.05fr 1fr;
  overflow: hidden;
}

.login-lede { padding: 46px 42px; background: linear-gradient(160deg, var(--login-lede-1) 0%, var(--card) 62%); }

.mark {
  width: 40px; height: 40px; border-radius: 13px;
  display: grid; place-items: center; color: var(--on-accent);
  /* 渐变两端都 ≥4.5:1（白字），浅紫那端撑不住所以不用它 */
  background: linear-gradient(135deg, var(--brand) 0%, var(--brand-ink) 100%);
  font: 700 var(--fs-lg)/1 var(--font-mono); letter-spacing: .02em;
}

.login-lede h1 { margin: 30px 0 0; font-size: var(--fs-4xl); font-weight: 800; letter-spacing: -.025em; }
.login-lede p { margin: 12px 0 0; color: var(--ink-2); max-width: 32ch; }

.pipeline {
  margin-top: 32px; padding-top: 20px; border-top: 1px solid var(--line);
  display: flex; flex-wrap: wrap; gap: 8px 10px; align-items: center;
  font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--ink-3);
}
.pipeline span { color: var(--ink-2); }
.pipeline i { font-style: normal; color: var(--ink-4); }

.login-form { padding: 46px 42px; display: grid; align-content: center; gap: 16px; }

/* ============================ 外壳 ==================================== */

.shell { display: grid; grid-template-columns: var(--rail-w) minmax(0, 1fr); min-height: 100%; }

.sidebar {
  background: var(--card);
  border-right: 1px solid var(--line);
  padding: 18px 14px;
  display: flex; flex-direction: column;
  position: sticky; top: 0; height: 100vh;
}

.brand-row { display: flex; align-items: center; gap: 11px; padding: 4px 8px 18px; }
.brand-row strong { font-size: var(--fs-lg); font-weight: 800; letter-spacing: -.01em; display: block; }
.brand-row small { display: block; font-size: var(--fs-xs); color: var(--ink-3); }

.nav { flex: 1; overflow-y: auto; padding-bottom: 8px; }
.nav-group + .nav-group { margin-top: 14px; }
.nav-group > span {
  display: block; padding: 8px 12px 6px;
  font-size: var(--fs-2xs); font-weight: 700; letter-spacing: .06em; color: var(--ink-3);
  text-transform: uppercase;
}
.nav a {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 12px; border-radius: 10px;
  color: var(--ink-2); font-size: var(--fs-md); font-weight: 600;
}
.nav a:hover { background: var(--card-3); color: var(--ink); }
.nav a:active { background: var(--brand-soft-2); }
.nav a[aria-current="page"] { background: var(--brand-soft); color: var(--brand-ink); }
.nav a .g { width: 18px; text-align: center; font-size: var(--fs-md); opacity: .85; }

.side-foot {
  margin-top: auto; padding: 12px; border-top: 1px solid var(--line-2);
  display: flex; align-items: center; gap: 8px; font-size: var(--fs-sm); color: var(--ink-3);
}
.side-foot .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--mint); }

/* ============================ 顶栏 ==================================== */

.top {
  position: sticky; top: 0; z-index: 20;
  display: flex; align-items: center; justify-content: space-between; gap: 18px;
  padding: 14px 26px; background: rgba(244, 245, 249, .86);
  backdrop-filter: blur(14px); border-bottom: 1px solid var(--line);
}
.top h1 { font-size: var(--fs-2xl); font-weight: 800; letter-spacing: -.02em; }
.crumb { font-size: var(--fs-sm); color: var(--ink-3); display: flex; align-items: center; gap: 6px; }
.crumb b { color: var(--ink-2); font-weight: 600; }
.crumb i { font-style: normal; color: var(--ink-3); }
.top-actions { display: flex; align-items: center; gap: 10px; }

.search {
  display: flex; align-items: center; gap: 8px;
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-pill); padding: 7px 14px; min-width: 260px;
  color: var(--ink-3); font-size: var(--fs-md);
}
.search input { border: 0; background: none; outline: none; width: 100%; font-size: var(--fs-md); }
.search input::placeholder { color: var(--ink-3); }

.icon-btn {
  width: 34px; height: 34px; border-radius: 10px;
  display: grid; place-items: center; color: var(--ink-2);
  background: var(--card); border: 1px solid var(--line);
  position: relative;
}
.icon-btn:hover { background: var(--card-3); }
.icon-btn:active { background: var(--line-2); }
/* 文字型按钮（语言切换）：宽度自适应，避免固定方形裁掉文字 */
.icon-btn.wide { width: auto; padding: 0 11px; font-size: var(--fs-sm); font-weight: 700; letter-spacing: .01em; }
.icon-btn .badge {
  position: absolute; top: -5px; right: -5px; min-width: 16px; height: 16px;
  border-radius: var(--r-pill); background: var(--danger-deep); color: var(--on-accent);
  font-size: var(--fs-3xs); font-weight: 700; display: grid; place-items: center; padding: 0 4px;
}

.avatar {
  width: 34px; height: 34px; border-radius: 50%;
  background: linear-gradient(135deg, var(--brand) 0%, var(--brand-ink) 100%);
  color: var(--on-accent); display: grid; place-items: center; font-size: var(--fs-sm); font-weight: 700;
}

.acct { position: relative; }
.acct-btn {
  display: flex; align-items: center; gap: 9px; border-radius: var(--r-pill);
  padding: 4px 12px 4px 4px; background: var(--card); border: 1px solid var(--line);
  font-size: var(--fs-md); font-weight: 600;
}
.acct-btn:hover { background: var(--card-3); }
.acct-btn .caret { color: var(--ink-3); font-size: var(--fs-3xs); }

.acct-menu {
  position: absolute; right: 0; top: calc(100% + 8px); z-index: 60;
  width: 224px; background: var(--card); border: 1px solid var(--line);
  border-radius: 14px; box-shadow: var(--shadow-lg); padding: 6px; overflow: hidden;
}
.acct-menu .hd { padding: 10px 12px 12px; border-bottom: 1px solid var(--line-2); margin-bottom: 6px; }
.acct-menu .hd b { display: block; font-size: var(--fs-md); }
.acct-menu .hd span { font-size: var(--fs-xs); color: var(--ink-3); }
.acct-menu button {
  display: block; width: 100%; text-align: left; padding: 9px 12px;
  font-size: var(--fs-md); font-weight: 600; border-radius: 9px; color: var(--ink-2);
}
.acct-menu button:hover { background: var(--card-3); color: var(--ink); }
.acct-menu button.danger { color: var(--coral); }
.acct-menu button.danger:hover { background: var(--coral-soft); }

/* ============================ 页面容器 ================================ */

.main { min-width: 0; }
.page { display: none; padding: 22px 26px 60px; }
.page.is-active { display: block; }

.card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  box-shadow: var(--shadow);
  display: flex; flex-direction: column;
}
.card + .card { margin-top: 16px; }

.card-head {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  padding: 16px 18px 12px; flex: 0 0 auto;
}
.card-head h2 { font-size: var(--fs-lg); font-weight: 700; letter-spacing: -.01em; }
.card-head .sub { font-size: var(--fs-sm); color: var(--ink-3); margin-top: 2px; }
.card-head .tools { display: flex; gap: 8px; align-items: center; }

/* 卡片内纵向弹性：同排卡片等高时，条形列表吸收剩余高度，末尾说明贴底 */
.card-body { padding: 4px 18px 18px; flex: 1 1 auto; display: flex; flex-direction: column; }
.card-body > * { flex: 0 0 auto; }
.card-body > .bars.fill { flex: 1 1 auto; align-content: space-between; }
.card-body > .funnel.fill { flex: 1 1 auto; align-content: space-between; }
/* tight：只收掉上下留白，左右仍保留 18px，避免内容贴到卡片描边上 */
.card-body.tight { padding: 0 18px 4px; }
/* 卡片内的次级小节标题（与「最近发布」里的渠道分布同级） */
.block-title { font-size: var(--fs-md); font-weight: 700; margin: 18px 0 4px; }

/* 页面级小节标题（报表页的「升级漏斗」） */
.section-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 12px; }
.section-head h2 { font-size: var(--fs-lg); font-weight: 700; letter-spacing: -.01em; }
.section-head .sub { font-size: var(--fs-sm); color: var(--ink-3); }

.grid { display: grid; gap: 16px; }
.grid.two { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid.three { grid-template-columns: repeat(3, minmax(0, 1fr)); }
/* 数量不定的一组（分组卡）：按可用宽度自动排，不留空位 */
.grid.auto { grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }
.grid.split { grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr); }

/* ============================ 指标条 ==================================
   不用「渐变图标块 + 大数字 + 迷你折线」那套指标卡模板：四个指标排在同一条里，
   靠留白与字重分层。数字是唯一的主角，装饰全部拿掉。 */

.stat-strip {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 18px 32px; align-items: start;
}
.stat { display: grid; gap: 3px; align-content: start; }
/* 标签用 ink-2，注释用 ink-3，靠字号+字重拉开层级（两者都满足 4.5:1） */
.stat-label { font-size: var(--fs-sm); color: var(--ink-2); font-weight: 600; }
.stat-value { font-size: var(--fs-3xl); font-weight: 800; letter-spacing: -.03em; line-height: 1.15; font-variant-numeric: tabular-nums; }
.stat-note { font-size: var(--fs-xs); color: var(--ink-3); display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }

.delta {
  display: inline-flex; align-items: center; gap: 3px;
  font-size: var(--fs-xs); font-weight: 700; padding: 2px 8px; border-radius: var(--r-pill);
}
.delta.up   { color: var(--mint-ink); background: var(--mint-soft); }
.delta.down { color: var(--coral-ink); background: var(--coral-soft); }
.delta.flat { color: var(--slate-ink); background: var(--slate-soft); }


/* ============================ 按钮 ==================================== */

.btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 8px 14px; border-radius: var(--r-btn);
  font-size: var(--fs-md); font-weight: 700; white-space: nowrap;
  background: var(--brand); color: var(--on-accent); border: 1px solid transparent;
  box-shadow: 0 1px 2px rgba(16, 24, 40, .06);
}
.btn:hover { background: var(--brand-ink); }
/* 按下态：下沉 1px + 内阴影，给出"按下去了"的反馈 */
.btn:active { transform: translateY(1px); box-shadow: inset 0 2px 6px rgba(16, 24, 40, .22); }
.btn:disabled { opacity: .45; cursor: not-allowed; box-shadow: none; transform: none; }

/* 提交中：按钮禁用并转圈，防止重复提交 */
.btn[aria-busy="true"] { pointer-events: none; opacity: .8; }
.btn[aria-busy="true"]::before {
  content: ""; width: 13px; height: 13px; flex: 0 0 13px;
  border: 2px solid currentColor; border-right-color: transparent;
  border-radius: 50%; animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.btn.ghost { background: var(--card); color: var(--ink-2); border-color: var(--line); box-shadow: none; }
.btn.ghost:hover { background: var(--card-3); color: var(--ink); }
.btn.ghost:active { background: var(--line-2); }

.btn.soft { background: var(--brand-soft); color: var(--brand-ink); box-shadow: none; }
.btn.soft:hover { background: var(--brand-soft-2); }
.btn.soft:active { background: var(--brand-soft-2); }

.btn.danger { background: var(--coral-soft); color: var(--coral-ink); box-shadow: none; }
.btn.danger:hover { background: var(--coral-soft-2); }
.btn.danger:active { background: var(--coral-soft-2); }

.btn.sm { padding: 6px 11px; font-size: var(--fs-sm); border-radius: 9px; }
.btn.block { width: 100%; justify-content: center; }

.linkbtn { color: var(--brand-ink); font-size: var(--fs-sm); font-weight: 700; padding: 4px 2px; }
.linkbtn:hover { text-decoration: underline; }
.linkbtn:active { opacity: .55; }
.linkbtn:disabled { color: var(--ink-4); cursor: not-allowed; text-decoration: none; }
.linkbtn.danger { color: var(--coral-ink); }
.linkbtn.mute { color: var(--ink-3); font-weight: 600; }
.linkbtn.mute:hover { color: var(--ink); }

.btn-row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }

/* ============================ 筛选条 ================================== */

.filters {
  display: flex; gap: 10px; align-items: center; flex-wrap: wrap;
  padding: 12px 14px; margin-bottom: 16px;
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-card); box-shadow: var(--shadow);
}
.filters .field { min-width: 140px; }
.filters .field.grow { flex: 1 1 220px; }
/* 筛选项：<label for> + <select> 兄弟结构。
   包裹式 label 的可访问名会把选项文字一起算进去，不能用 */
.filters .f-item { display: flex; align-items: center; gap: 8px; }
.filters .f-item > label {
  font-size: var(--fs-sm); color: var(--ink-3); font-weight: 600;
  white-space: nowrap; flex: 0 0 auto;
}

.version-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: 12px;
}
.version-toolbar h2 { font-size: var(--fs-lg); font-weight: 750; }
.version-toolbar .sub { margin-top: 3px; color: var(--ink-3); font-size: var(--fs-sm); }

/* ============================ 表单 ==================================== */

.field { display: grid; gap: 6px; }
/* 标签用 <label for>，不再是 <span> —— 读屏与点击聚焦都能拿到名字 */
.field > label { font-size: var(--fs-sm); color: var(--ink-2); font-weight: 600; }
.field > label .req { color: var(--coral-ink); margin-left: 2px; }
/* 分组标签（radiogroup / group）用 span + aria-labelledby */
.field > .f-label, .field > .f-static-lbl { font-size: var(--fs-sm); color: var(--ink-2); font-weight: 600; }
.field > .f-label .req { color: var(--coral-ink); margin-left: 2px; }
.field .hint { font-size: var(--fs-xs); color: var(--ink-3); font-weight: 500; }
/* 字段级错误：就地显示在字段下面。右下角 toast 离字段太远，读屏也读不到 */
.field .err {
  font-size: var(--fs-xs); color: var(--coral-ink); font-weight: 600;
  display: flex; align-items: center; gap: 5px;
}
.field .err::before { content: "✕"; font-size: var(--fs-3xs); }
.field.is-error input, .field.is-error select, .field.is-error textarea {
  border-color: var(--coral); background: var(--coral-soft);
}
.field.is-error input:focus, .field.is-error select:focus, .field.is-error textarea:focus {
  box-shadow: 0 0 0 3px var(--coral-soft);
}

input[type="text"], input[type="number"], input[type="password"], input[type="search"],
select, textarea {
  width: 100%; background: var(--card-3); color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--r-btn);
  padding: 9px 12px; font-size: var(--fs-md);
}
/* 焦点态：描边必须可见（对比度 5.4:1），不能只靠一圈浅色阴影 */
input:focus, select:focus, textarea:focus {
  background: var(--card); border-color: var(--brand);
  box-shadow: 0 0 0 3px var(--brand-soft);
}
input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: 2px solid var(--brand); outline-offset: 2px;
}
input::placeholder, textarea::placeholder { color: var(--ink-3); }
textarea { min-height: 92px; resize: vertical; }
select {
  appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'><path d='M3 4.5 6 8l3-3.5' fill='none' stroke='%236b7085' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-repeat: no-repeat; background-position: right 11px center;
  padding-right: 30px;
}

.search-select { position: relative; }
.search-select-trigger {
  width: 100%; min-height: 40px; padding: 9px 12px;
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  color: var(--ink); text-align: left; font-size: var(--fs-md);
  background: var(--card-3); border: 1px solid var(--line); border-radius: var(--r-btn);
}
.search-select-trigger > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.search-select-trigger > span.placeholder { color: var(--ink-3); }
.search-select-trigger > svg { width: 12px; flex: 0 0 12px; fill: none; stroke: var(--ink-3); stroke-width: 1.4; }
.search-select-trigger[aria-expanded="true"] > svg { transform: rotate(180deg); }
.field.is-error .search-select-trigger { border-color: var(--coral); background: var(--coral-soft); }
.search-select-menu {
  position: absolute; top: calc(100% + 5px); left: 0; right: 0; z-index: 40;
  padding: 8px; background: var(--card); border: 1px solid var(--line);
  border-radius: 12px; box-shadow: 0 14px 36px rgba(20, 24, 40, .18);
}
.search-select-query {
  min-width: 0; padding: 6px 10px; border-radius: 9px; background: var(--card-2);
}
.search-select-query > svg {
  width: 15px; height: 15px; flex: 0 0 15px;
  fill: none; stroke: var(--ink-3); stroke-width: 1.5; stroke-linecap: round;
}
.search-select-options { display: grid; max-height: 250px; overflow-y: auto; margin-top: 6px; }
.search-select-option {
  display: block; width: 100%; padding: 9px 10px; border: 0; border-radius: 8px;
  overflow: hidden; color: var(--ink); background: transparent;
  font-size: var(--fs-md); text-align: left; text-overflow: ellipsis; white-space: nowrap;
}
.search-select-option:hover, .search-select-option:focus-visible { background: var(--card-3); }
.search-select-option[aria-selected="true"] { color: var(--brand); background: var(--brand-soft); font-weight: 700; }
.search-select-empty { padding: 12px 10px; color: var(--ink-3); font-size: var(--fs-sm); text-align: center; }

.grid-2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
.grid-2 .full { grid-column: 1 / -1; }

/* 互斥三选一 */
.choices { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
.choice {
  border: 1px solid var(--line); border-radius: 14px; padding: 14px 15px;
  cursor: pointer; display: grid; gap: 6px; background: var(--card-2); text-align: left;
}
.choice:hover { border-color: var(--hover-line); background: var(--card); }
.choice input { position: absolute; opacity: 0; pointer-events: none; }
.choice .t { font-weight: 700; font-size: var(--fs-md); display: flex; align-items: center; gap: 8px; }
.choice .t::before {
  content: ""; width: 16px; height: 16px; border-radius: 50%; flex: 0 0 16px;
  border: 2px solid var(--ink-3); background: var(--card);
}
.choice .d { font-size: var(--fs-sm); color: var(--ink-3); }
.choice:has(input:checked) { border-color: var(--brand); background: var(--brand-soft); }
.choice:has(input:checked) .t::before { border-color: var(--brand); background: var(--brand); box-shadow: inset 0 0 0 3px var(--brand-soft); }
.choice:has(input:focus-visible) { outline: 2px solid var(--brand); outline-offset: 2px; }

/* ============================ 状态标记 ================================ */

.chip {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: var(--fs-xs); font-weight: 700; padding: 2px 9px; border-radius: var(--r-pill);
  background: var(--slate-soft); color: var(--slate-ink); white-space: nowrap;
}
.chip i { font-style: normal; font-size: var(--fs-3xs); }
.chip.published { background: var(--mint-soft);   color: var(--mint-ink); }
.chip.testing   { background: var(--sky-soft);    color: var(--sky-ink); }
.chip.draft     { background: var(--slate-soft);  color: var(--slate-ink); }
.chip.passed    { background: var(--sky-soft);    color: var(--sky-ink); }
.chip.partial   { background: var(--amber-soft);  color: var(--amber-ink); }
.chip.offline   { background: var(--amber-soft);  color: var(--amber-ink); }
.chip.empty,
.chip.unavailable { background: var(--slate-soft); color: var(--slate-ink); }
.chip.failed,
.chip.revoked   { background: var(--coral-soft);  color: var(--coral-ink); }
.chip.active    { background: var(--mint-soft);   color: var(--mint-ink); }
.chip.brand     { background: var(--brand-soft);  color: var(--brand-ink); }
.chip.orange    { background: var(--orange-soft); color: var(--orange-ink); }
/* 列表行里的 chip：抬高一档特异性，避免被 .list-row .r span 覆盖成灰色 */
.list-row .r .chip { color: var(--ink-2); }
.list-row .r .chip.published { color: var(--mint-ink); }
.list-row .r .chip.testing   { color: var(--sky-ink); }
.list-row .r .chip.draft     { color: var(--slate-ink); }
.list-row .r .chip.offline   { color: var(--amber-ink); }
.list-row .r .chip.failed,
.list-row .r .chip.revoked   { color: var(--coral-ink); }
.list-row .r .chip.brand     { color: var(--brand-ink); }
.list-row .r .chip.orange    { color: var(--orange-ink); }
.list-row .r .chip.active    { color: var(--mint-ink); }

/* ============================ 表格 ==================================== */

/* 窄屏必须能横向滚动：overflow:hidden 会把右侧列裁掉且用户无法触达 */
.table-wrap {
  border: 1px solid var(--line); border-radius: 14px;
  overflow-x: auto; overflow-y: hidden;
  background: var(--card);
  -webkit-overflow-scrolling: touch;
}
.table-wrap::-webkit-scrollbar { height: 8px; }
.table-wrap::-webkit-scrollbar-thumb { background: var(--line); border-radius: var(--r-pill); }
.tbl { font-size: var(--fs-md); min-width: 680px; }
.tbl thead th {
  text-align: left; font-weight: 700; font-size: var(--fs-xs); color: var(--ink-3);
  padding: 11px 14px; background: var(--card-2); border-bottom: 1px solid var(--line);
  white-space: nowrap; letter-spacing: .01em;
}
.tbl tbody td { padding: 12px 14px; border-bottom: 1px solid var(--line-2); vertical-align: middle; }
.tbl tbody tr:last-child td { border-bottom: 0; }
.tbl tbody tr:hover { background: var(--fill-2); }
.tbl td.num, .tbl th.num { text-align: right; font-variant-numeric: tabular-nums; }
.tbl .row-title { font-weight: 700; }
.tbl .row-sub { font-family: var(--font-mono); font-size: var(--fs-2xs); color: var(--ink-3); margin-top: 2px; }
.tbl .actions { display: flex; gap: 4px; flex-wrap: wrap; justify-content: flex-end; }

/* Long hashes, package sizes and timestamp strings must not widen the drawer or
   modal body. Fixed table layout keeps the surrounding spacing stable. */
.tbl.package-table { min-width: 0; table-layout: fixed; }
.tbl.package-table th, .tbl.package-table td { overflow: hidden; text-overflow: ellipsis; }
.tbl.package-table thead th { padding: 10px 8px; white-space: normal; line-height: 1.25; }
.tbl.package-table tbody td { padding: 10px 8px; }
.tbl.package-table .hash { white-space: nowrap; }
.tbl.diff-table th:nth-child(1) { width: 7%; }
.tbl.diff-table th:nth-child(2) { width: 12%; }
.tbl.diff-table th:nth-child(3) { width: 20%; }
.tbl.diff-table th:nth-child(4) { width: 16%; }
.tbl.diff-table th:nth-child(5) { width: 10%; }
.tbl.diff-table th:nth-child(6) { width: 9%; }
.tbl.diff-table th:nth-child(7) { width: 14%; }
.tbl.diff-table th:nth-child(8) { width: 12%; }
.tbl.drawer-package-table th:nth-child(1) { width: 8%; }
.tbl.drawer-package-table th:nth-child(2) { width: 10%; }
.tbl.drawer-package-table th:nth-child(3) { width: 19%; }
.tbl.drawer-package-table th:nth-child(4) { width: 12%; }
.tbl.drawer-package-table th:nth-child(5) { width: 13%; }
.tbl.drawer-package-table th:nth-child(6) { width: 22%; }
.tbl.drawer-package-table th:nth-child(7) { width: 16%; }

/* Operation-log details are summaries, not raw JSON payloads. Keep every tab
   inside the card width and let long summaries truncate with a title tooltip. */
[data-page="logs"] .tbl { min-width: 0; table-layout: fixed; }
#panel-ops .tbl th:nth-child(1) { width: 104px; }
#panel-ops .tbl th:nth-child(2) { width: 120px; }
#panel-ops .tbl th:nth-child(3) { width: 150px; }
#panel-ops .tbl th:nth-child(4) { width: auto; }
#panel-ops .tbl th:nth-child(5) { width: 96px; }
#panel-realtime .tbl th:nth-child(1) { width: 104px; }
#panel-realtime .tbl th:nth-child(2) { width: 132px; }
#panel-realtime .tbl th:nth-child(3) { width: 80px; }
#panel-realtime .tbl th:nth-child(4) { width: 90px; }
#panel-realtime .tbl th:nth-child(5) { width: 136px; }
#panel-devicelogs .tbl th:nth-child(1) { width: 104px; }
#panel-devicelogs .tbl th:nth-child(2) { width: 160px; }
#panel-devicelogs .tbl th:nth-child(3) { width: 90px; }
#panel-devicelogs .tbl th:nth-child(4) { width: 136px; }
#panel-devicelogs .tbl th:nth-child(5) { width: 88px; }
.log-detail-cell { display: flex; align-items: center; gap: 8px; min-width: 180px; }
.log-detail { min-width: 0; max-width: 420px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.log-detail-cell .linkbtn { flex: 0 0 auto; }
.log-detail-text { white-space: pre-wrap; }
.log-raw { margin-top: 16px; border-top: 1px solid var(--line-2); padding-top: 12px; }
.log-raw summary { cursor: pointer; color: var(--brand); font-size: var(--fs-sm); font-weight: 600; }
.log-raw pre { margin-top: 10px; max-height: 320px; overflow: auto; white-space: pre-wrap; overflow-wrap: anywhere; font-size: var(--fs-xs); background: var(--card-3); padding: 12px; border-radius: 10px; }

.pager { display: flex; align-items: center; gap: 8px; padding: 12px 4px 0; }
.pager .note { font-size: var(--fs-sm); color: var(--ink-3); margin-right: auto; }

/* ============================ 版本轨道 ================================ */

.board {
  background: linear-gradient(180deg, var(--login-lede-1) 0%, var(--board-g-2) 100%);
  border: 1px solid var(--line); border-radius: var(--r-card);
  box-shadow: var(--shadow); padding: 18px; margin-bottom: 16px;
}
.board-head { display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap; margin-bottom: 16px; }
.board-head h2 { font-size: var(--fs-lg); font-weight: 700; }
.board-head .meta { font-size: var(--fs-sm); color: var(--ink-3); margin-top: 2px; }

.track-panel {
  padding: 0;
  margin-top: 16px;
  margin-bottom: 0;
  overflow: hidden;
}
.track-panel-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 16px 18px;
  cursor: pointer;
  list-style: none;
}
.track-panel-summary::-webkit-details-marker { display: none; }
.track-panel-summary > span:first-child { display: grid; gap: 3px; min-width: 0; }
.track-panel-summary b { font-size: var(--fs-md); }
.track-panel-summary small { color: var(--ink-3); font-size: var(--fs-sm); }
.track-panel-toggle { color: var(--brand-ink); font-size: var(--fs-sm); font-weight: 650; }
.track-panel-toggle::after { content: ' ▾'; }
.track-panel[open] .track-panel-toggle::after { content: ' ▴'; }
.track-panel-body,
.track-panel .board-body { padding: 0 18px 18px; }
.track-panel .board-head { padding-top: 4px; border-top: 1px solid var(--line); }

@media (max-width: 560px) {
  .version-toolbar { align-items: flex-start; }
  .version-toolbar .btn-row { width: 100%; }
  .version-toolbar .btn { flex: 1 1 0; }
  .track-panel-summary { padding: 14px; }
  .track-panel .board-body { padding: 0 14px 14px; }
}

.track { display: flex; align-items: stretch; overflow-x: auto; padding: 4px 2px 10px; scroll-snap-type: x proximity; }
.track .vnode, .track .vconn { scroll-snap-align: start; }

.vnode {
  flex: 0 0 178px; width: 178px; text-align: left;
  background: var(--card); border: 1px solid var(--line); border-radius: 14px;
  padding: 12px 13px 11px; box-shadow: 0 1px 2px rgba(16, 24, 40, .04);
  display: grid; gap: 5px; align-content: start;
}
.vnode:hover { border-color: var(--hover-line); box-shadow: var(--shadow); }
.vnode.is-origin { border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-soft); }
.vnode-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.vnode-top .ord { font-family: var(--font-mono); font-size: var(--fs-2xs); color: var(--ink-3); }
.vnode-key { font-family: var(--font-mono); font-size: var(--fs-md); font-weight: 600; overflow-wrap: anywhere; }
.vnode-foot { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: var(--fs-xs); color: var(--ink-3); }
.vnode-foot .hop { font-family: var(--font-mono); font-size: var(--fs-2xs); }
.vnode-foot .hop.bad { color: var(--coral-ink); font-weight: 700; }
.vnode-foot .hop.origin { color: var(--brand-ink); font-weight: 700; }

.vconn { flex: 0 0 34px; position: relative; align-self: center; height: 24px; }
.vconn::before { content: ""; position: absolute; left: 0; right: 9px; top: 50%; border-top: 2px solid var(--sky); }
.vconn::after {
  content: ""; position: absolute; right: 2px; top: 50%; transform: translateY(-50%) rotate(45deg);
  width: 7px; height: 7px; border-top: 2px solid var(--sky); border-right: 2px solid var(--sky);
}
.vconn[data-kind="broken"]::before { border-top-color: var(--coral); border-top-style: dashed; }
.vconn[data-kind="broken"]::after { border-color: var(--coral); }
.vconn[data-kind="testing"]::before { border-top-color: var(--line-3); }
.vconn[data-kind="testing"]::after { border-color: var(--line-3); }
.vconn i {
  position: absolute; left: 50%; top: -16px; transform: translateX(-50%);
  font-style: normal; font-size: var(--fs-2xs); font-weight: 700; color: var(--coral-ink); white-space: nowrap;
}

.track-legend { display: flex; flex-wrap: wrap; gap: 8px 18px; margin-top: 8px; padding-top: 12px; border-top: 1px solid var(--line); font-size: var(--fs-xs); color: var(--ink-3); }.track-legend .k { display: inline-flex; align-items: center; gap: 6px; }
.track-legend .k i { width: 18px; height: 0; border-top: 2px solid var(--sky); display: inline-block; }
.track-legend .k i.broken { border-top-color: var(--coral); border-top-style: dashed; }
.track-legend .k i.testing { border-top-color: var(--line-3); }

.callout {
  margin-top: 14px; padding: 12px 14px; border-radius: 12px;
  background: var(--brand-soft); color: var(--ink-2); font-size: var(--fs-md); line-height: 1.6;
}
.callout b { color: var(--ink); font-weight: 700; }
.callout.bad { background: var(--coral-soft); }
.callout.bad b { color: var(--coral-ink); }
.callout.warn { background: var(--amber-soft); }
.callout.warn b { color: var(--amber-ink); }

/* 轨道结论：中性底 + 逐行表达好坏（不把整块染成告警色） */
.track-summary { font-weight: 700; color: var(--ink); }
.track-list { margin: 8px 0 0; padding: 0; list-style: none; display: grid; gap: 5px; }
.track-list li { position: relative; padding-left: 16px; }
.track-list li::before {
  content: ""; position: absolute; left: 0; top: 8px;
  width: 6px; height: 6px; border-radius: 50%; background: var(--ink-3);
}
.track-list li.good::before { background: var(--mint); }
.track-list li.bad::before { background: var(--coral); }
.track-list li.bad b { color: var(--coral-ink); }
.track-list li.muted { color: var(--ink-3); }
.track-foot { margin-top: 8px; padding-top: 8px; border-top: 1px dashed var(--line); font-size: var(--fs-sm); color: var(--ink-2); }

/* 轨道右侧剩余提示 */
#track-hint {
  display: block; margin-top: 4px; padding: 0; text-align: right;
  font-size: var(--fs-xs); font-weight: 700; color: var(--brand-ink);
  background: none; cursor: pointer;
}

/* ============================ 图表 ==================================== */

/* 漏斗：轨道 + 有序色阶 */
.funnel { display: grid; gap: 12px; }
.funnel-row { display: grid; grid-template-columns: 92px minmax(0, 1fr) 108px; align-items: center; gap: 12px; }
.funnel-row .lbl { font-size: var(--fs-md); color: var(--ink-2); font-weight: 600; }
.funnel-row .val { text-align: right; font-size: var(--fs-md); font-weight: 700; }
.funnel-row .val span { color: var(--ink-3); font-weight: 500; font-size: var(--fs-xs); margin-left: 5px; }
.meter { height: 14px; background: var(--track); border-radius: var(--r-pill); overflow: hidden; }
.meter > span { display: block; height: 100%; border-radius: var(--r-pill); }

/* 大比例块 */
.ratio { display: grid; gap: 10px; }
.ratio-top { display: flex; align-items: baseline; gap: 10px; }
.ratio-num { font-size: var(--fs-4xl); font-weight: 800; letter-spacing: -.03em; }
.ratio-of { font-size: var(--fs-lg); color: var(--ink-3); font-weight: 600; }
.ratio-pct { margin-left: auto; font-size: var(--fs-lg); font-weight: 800; color: var(--mint-ink); }
.ratio-bar { height: 10px; border-radius: var(--r-pill); background: var(--track); overflow: hidden; display: flex; }
.ratio-bar > span { display: block; height: 100%; }

/* 占比条：单色直接标注 */
.bars { display: grid; gap: 11px; }
.bar-row { display: grid; grid-template-columns: minmax(110px, 32%) minmax(0, 1fr) 128px; align-items: center; gap: 12px; }
.bar-row .lbl { font-size: var(--fs-md); overflow-wrap: anywhere; }
.bar-row .val { text-align: right; font-size: var(--fs-md); color: var(--ink-2); font-variant-numeric: tabular-nums; }
.bar-track { height: 11px; background: var(--track); border-radius: var(--r-pill); overflow: hidden; }
.bar-track > span { display: block; height: 100%; border-radius: var(--r-pill); background: var(--brand); }
.bar-row.bad .bar-track > span { background: var(--coral); }
.bar-row.bad .lbl { font-family: var(--font-mono); font-size: var(--fs-sm); }

.donut-layout {
  display: grid;
  grid-template-columns: 190px minmax(0, 1fr);
  align-items: center;
  gap: 24px;
}
.donut {
  width: 184px;
  aspect-ratio: 1;
  border-radius: 50%;
  display: grid;
  place-items: center;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--line) 70%, transparent);
}
.donut-hole {
  width: 108px;
  aspect-ratio: 1;
  border-radius: 50%;
  background: var(--card);
  display: grid;
  place-content: center;
  text-align: center;
  box-shadow: 0 0 0 1px var(--line);
}
.donut-hole b { font-size: 23px; line-height: 1.1; font-variant-numeric: tabular-nums; }
.donut-hole span { color: var(--ink-3); font-size: var(--fs-xs); margin-top: 3px; }
.donut-legend { min-width: 0; display: grid; gap: 7px; }
.donut-legend-row {
  display: grid;
  grid-template-columns: 9px minmax(0, 1fr) auto 54px;
  align-items: center;
  gap: 8px;
  min-width: 0;
  font-size: var(--fs-sm);
}
.donut-legend-row i { width: 9px; height: 9px; border-radius: 3px; }
.donut-legend-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.donut-legend-row b { font-variant-numeric: tabular-nums; }
.donut-legend-row small { color: var(--ink-3); text-align: right; font-variant-numeric: tabular-nums; }
.donut-legend-row.bad .donut-legend-label { color: var(--coral-ink); }
.share-footer {
  display: flex;
  gap: 8px 18px;
  flex-wrap: wrap;
  margin-top: 18px;
  padding-top: 12px;
  border-top: 1px solid var(--line);
  color: var(--ink-3);
  font-size: var(--fs-sm);
}
.share-footer b { color: var(--ink); }
.attention-list { display: grid; gap: 8px; }
.attention-row {
  display: grid;
  grid-template-columns: 30px minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
  padding: 10px 11px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--card-2);
}
.attention-row.bad { border-color: color-mix(in srgb, var(--coral) 28%, var(--line)); }
.attention-icon {
  width: 28px;
  height: 28px;
  border-radius: 9px;
  display: grid;
  place-items: center;
  background: var(--sky-soft);
  color: var(--sky-ink);
  font-weight: 800;
}
.attention-row.bad .attention-icon { background: var(--coral-soft); color: var(--coral-ink); }
.attention-copy { min-width: 0; display: grid; gap: 2px; }
.attention-copy b { font-size: var(--fs-sm); }
.attention-copy small { color: var(--ink-3); font-size: var(--fs-xs); overflow-wrap: anywhere; }

/* 柱状图：每日升级量
   --x-h 固定日期行高度，保证 6 根柱的基线在同一水平线上 */
.cols-chart {
  --x-h: 17px; --col-gap: 8px;
  position: relative;
  display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 12px;
  height: 220px; max-width: 760px;
}
/* 基线 */
.cols-chart::before {
  content: ""; position: absolute; left: 0; right: 0;
  top: calc(100% - var(--x-h) - var(--col-gap));
  border-top: 1px solid var(--line-2);
}
.col { display: grid; grid-template-rows: minmax(0, 1fr) var(--x-h); gap: var(--col-gap); height: 100%; }
.col-plot { display: flex; align-items: flex-end; justify-content: center; min-height: 0; }
.col .bar {
  width: 100%; max-width: 56px; border-radius: 8px 8px 4px 4px;
  background: linear-gradient(180deg, var(--brand-2) 0%, var(--brand) 100%);
  position: relative;
}
/* 无数据日：满高斜纹柱。斜纹只表示"没有记录"，不画成某个高度，
   否则会被读成"数量约等于这个高度" */
.col .bar.ghost { background: repeating-linear-gradient(135deg, var(--hatch) 0 5px, var(--hatch-2) 5px 10px); }
.col .bar b {
  position: absolute; top: -21px; left: 50%; transform: translateX(-50%);
  font-size: var(--fs-xs); font-weight: 700; white-space: nowrap;
}
/* 无数据标记放在柱体内部，这样日期行高度一致，基线才对得齐 */
.col .bar b.in {
  position: static; display: block; transform: none; text-align: center;
  padding-top: 8px; color: var(--ink-3); font-size: var(--fs-3xs); font-weight: 700;
}
.col .x { font-size: var(--fs-2xs); color: var(--ink-3); text-align: center; height: var(--x-h); }

/* 键值 */
.kv { display: grid; grid-template-columns: 128px minmax(0, 1fr); gap: 9px 14px; font-size: var(--fs-md); }
.kv dt { color: var(--ink-3); }
.kv dd { overflow-wrap: anywhere; font-weight: 600; }

/* ============================ 列表 ==================================== */

.list { display: grid; }
.list-row {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 0; border-bottom: 1px solid var(--line-2);
}
.list-row:last-child { border-bottom: 0; }
.list-row .t { min-width: 0; }
.list-row .t b { font-size: var(--fs-md); font-weight: 700; display: block; }
.list-row .t span { font-size: var(--fs-xs); color: var(--ink-3); }
.list-row .r { margin-left: auto; text-align: right; white-space: nowrap; }
.list-row .r b { font-size: var(--fs-md); font-weight: 700; display: block; }
/* 排除 chip：否则这条 (0,3,1) 会盖掉 .chip.published (0,2,0)，状态色全变灰。
   用 > 只匹配直接子元素，避免误伤 chip 内部的文本节点 */
.list-row .r > span:not(.chip) { font-size: var(--fs-xs); color: var(--ink-3); }

.thumb {
  width: 34px; height: 34px; border-radius: 10px; flex: 0 0 34px;
  display: grid; place-items: center; font-size: var(--fs-md); font-weight: 800;
  background: var(--brand-soft); color: var(--brand-ink);
}

/* ============================ 标签页 ================================== */

.tabs { display: flex; gap: 6px; padding: 5px; background: var(--card-3); border-radius: var(--r-pill); width: fit-content; margin-bottom: 16px; }
.tabs button {
  padding: 7px 16px; border-radius: var(--r-pill); font-size: var(--fs-md); font-weight: 700; color: var(--ink-3);
}
.tabs button:hover { color: var(--ink); }
.tabs button:active { color: var(--ink); }
.tabs button[aria-selected="true"] { background: var(--ink); color: var(--on-accent); }
.tabs button[aria-selected="true"]:active { background: var(--ink-2); }
.tabs .count { font-size: var(--fs-2xs); opacity: .65; margin-left: 5px; }

/* ============================ 抽屉 ==================================== */

.scrim { position: fixed; inset: 0; background: rgba(19, 22, 38, .34); opacity: 0; pointer-events: none; transition: opacity .2s ease; z-index: 40; }
.scrim.is-open { opacity: 1; pointer-events: auto; }

.drawer {
  position: fixed; top: 0; right: 0; bottom: 0; width: min(var(--drawer-w), 100%);
  background: var(--bg); z-index: 50; display: flex; flex-direction: column;
  transform: translateX(100%); transition: transform .24s cubic-bezier(.2, .7, .3, 1);
  box-shadow: -20px 0 60px rgba(16, 24, 40, .16);
}
.drawer.is-open { transform: none; }
/* 关闭时彻底移出焦点顺序：否则抽屉里的按钮仍可被 Tab 命中（落在视口外） */
.drawer:not(.is-open) { visibility: hidden; }
.drawer.is-open { visibility: visible; }
.drawer-head { padding: 18px 20px 14px; background: var(--card); border-bottom: 1px solid var(--line); }
.drawer-head .crumb { margin-bottom: 6px; }
.drawer-head h2 { font-size: var(--fs-2xl); font-weight: 800; letter-spacing: -.02em; }
.drawer-head .sub { font-size: var(--fs-sm); color: var(--ink-3); margin-top: 3px; }
.drawer-body { flex: 1; min-width: 0; overflow-y: auto; padding: 16px 20px 20px; display: grid; gap: 14px; align-content: start; }
.drawer-foot { display: flex; justify-content: flex-end; gap: 8px; padding: 14px 20px; background: var(--card); border-top: 1px solid var(--line); }
.drawer .block { min-width: 0; max-width: 100%; background: var(--card); border: 1px solid var(--line); border-radius: 16px; padding: 15px 17px; box-shadow: var(--shadow); }
.drawer .block > h3 { font-size: var(--fs-md); font-weight: 700; margin-bottom: 12px; }
.drawer .table-wrap { width: 100%; min-width: 0; }

/* ============================ 提示 ==================================== */

.toasts { position: fixed; right: 20px; bottom: 20px; z-index: 90; display: grid; gap: 8px; }
.toasts[aria-live="polite"] { pointer-events: none; }
.toast {
  background: var(--ink); color: var(--on-accent); padding: 11px 15px; font-size: var(--fs-md); font-weight: 600;
  border-radius: 12px; box-shadow: var(--shadow-lg); max-width: 340px;
}
.toast.bad { background: var(--danger-deep); }

/* ============================ 移动端 ================================== */

.mobile-nav { display: none; }

@media (max-width: 1240px) {
  .grid.split { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 1040px) {
  .grid.two, .grid.three { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 900px) {
  .shell { grid-template-columns: minmax(0, 1fr); }
  .sidebar { display: none; }
  .top { padding: 12px 16px; flex-wrap: wrap; }
  .top .search { display: none; }
  .page { padding: 16px 16px 92px; }
  .board-head .btn-row {
    width: 100%;
    display: grid;
    grid-template-columns: minmax(0, 1.45fr) minmax(0, 1fr);
  }
  .board-head .btn-row select { width: 100% !important; min-width: 0 !important; }
  .board-head .btn-row #track-reset { grid-column: 1 / -1; justify-self: start; }
  .mobile-nav {
    display: flex; position: fixed; left: 0; right: 0; bottom: 0; z-index: 30;
    background: rgba(255, 255, 255, .95); border-top: 1px solid var(--line);
    backdrop-filter: blur(14px); padding: 6px 4px calc(6px + env(safe-area-inset-bottom));
  }
  .mobile-nav a {
    flex: 1; text-align: center; font-size: var(--fs-2xs); color: var(--ink-3);
    padding: 5px 2px; border-radius: 9px; font-weight: 600;
  }
  .mobile-nav a[aria-current="page"] { background: var(--brand-soft); color: var(--brand-ink); }
  .mobile-nav a .g { display: block; font-size: var(--fs-md); margin-bottom: 1px; }
  .login-card { grid-template-columns: minmax(0, 1fr); }
  .login-lede { padding: 34px 28px; }
  .login-form { padding: 30px 28px; }
  .grid-2, .choices { grid-template-columns: minmax(0, 1fr); }
  .drawer { width: 100%; }
  .policy-summary { flex-direction: column; }
  .policy-summary .btn { width: 100%; }
  .funnel-row { grid-template-columns: 76px minmax(0, 1fr) 92px; }
  .bar-row { grid-template-columns: minmax(0, 1fr) 108px; }
  .bar-row .bar-track { grid-column: 1 / -1; }
  .donut-layout { grid-template-columns: minmax(0, 1fr); justify-items: center; }
  .donut-legend { width: 100%; }
  .cols-chart { height: 150px; }
  .stat-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* 窄屏筛选条：改成一行横向滚动，不再竖着堆 5 行占掉 1/5 屏 */
  .filters { flex-wrap: nowrap; overflow-x: auto; padding: 10px 12px; }
  .filters .field, .filters .field.grow { flex: 0 0 auto; min-width: 130px; }
  /* 窄屏收起筛选标签的文字，但保留给读屏 */
  .filters .f-item > label {
    position: absolute; width: 1px; height: 1px; overflow: hidden;
    clip-path: inset(50%); white-space: nowrap;
  }
  .filters .btn { flex: 0 0 auto; }
}

@media (max-width: 560px) {
  .kv { grid-template-columns: minmax(0, 1fr); gap: 2px 0; }
  .kv dd { margin-bottom: 8px; }
  .stat-value { font-size: var(--fs-3xl); }
  .stat-strip { grid-template-columns: minmax(0, 1fr); }
  .tabs {
    width: 100%;
    overflow-x: auto;
    flex-wrap: nowrap;
    scrollbar-width: none;
  }
  .tabs::-webkit-scrollbar { display: none; }
  .tabs button { flex: 0 0 auto; white-space: nowrap; }
  .card-head { flex-wrap: wrap; }
  .card-head .tools { margin-left: auto; flex-wrap: wrap; }
}

/* ============================ 动效 ==================================== */

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .001ms !important; transition-duration: .001ms !important; }
}

@keyframes rise {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}
.is-active .board { animation: rise .3s cubic-bezier(.2, .7, .3, 1) both; }

/* ============================ 弹窗 ====================================
   规则：右侧抽屉 = 只读详情；居中弹窗 = 表单与操作。 */

.modal-backdrop {
  position: fixed; inset: 0; z-index: 70;
  background: rgba(19, 22, 38, .42); backdrop-filter: blur(2px);
  display: grid; place-items: center; padding: 24px;
  opacity: 0; pointer-events: none; transition: opacity .18s ease;
}
.modal-backdrop.is-open { opacity: 1; pointer-events: auto; }

.modal {
  width: min(660px, 100%); max-height: calc(100vh - 48px);
  background: var(--card); border-radius: 20px; box-shadow: var(--shadow-lg);
  display: flex; flex-direction: column; overflow: hidden;
  transform: translateY(10px) scale(.985); transition: transform .18s ease;
}
.modal-backdrop.is-open .modal { transform: none; }
.modal.wide { width: min(900px, 100%); }
.modal.xwide { width: min(1200px, 100%); height: min(900px, calc(100vh - 48px)); }
.modal.narrow { width: min(430px, 100%); }

.modal-head { padding: 18px 20px 14px; border-bottom: 1px solid var(--line); flex: 0 0 auto; position: relative; }
.modal-head h2 { font-size: var(--fs-xl); font-weight: 800; letter-spacing: -.02em; padding-right: 36px; }
.modal-head .sub { font-size: var(--fs-sm); color: var(--ink-3); margin-top: 3px; padding-right: 36px; }
/* 关闭按钮：每个弹窗都必须有一个显式出口 */
.modal-x {
  position: absolute; top: 12px; right: 12px;
  width: 30px; height: 30px; border-radius: 9px;
  display: grid; place-items: center;
  color: var(--ink-3); font-size: var(--fs-md); line-height: 1;
}
.modal-x:hover { background: var(--card-3); color: var(--ink); }
.modal-body { padding: 18px 20px; overflow-y: auto; flex: 1 1 auto; }
.modal-foot {
  padding: 14px 20px; border-top: 1px solid var(--line); background: var(--card-2);
  display: flex; justify-content: flex-end; gap: 8px; flex: 0 0 auto; flex-wrap: wrap;
}
.modal-foot .spacer { margin-right: auto; }

/* 表单 */
.form-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
.form-grid .full { grid-column: 1 / -1; }

.form-upload-progress {
  display: grid; gap: 8px; padding: 12px 14px;
  border: 1px solid var(--line); border-radius: 12px; background: var(--card-3);
}
.form-upload-progress[hidden] { display: none; }
.form-upload-progress-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; font-size: var(--fs-sm); }
.form-upload-progress-head span { color: var(--ink-2); font-weight: 600; }
.form-upload-progress-head b { color: var(--brand-ink); font-size: var(--fs-sm); }
.form-upload-progress-track { height: 7px; overflow: hidden; border-radius: var(--r-pill); background: var(--line-2); }
.form-upload-progress-track > span {
  display: block; width: 0; height: 100%; border-radius: inherit;
  background: linear-gradient(90deg, var(--brand), var(--sky)); transition: width .18s ease;
}
.form-upload-progress-track.is-indeterminate > span {
  width: 36% !important; animation: upload-progress-move 1.1s ease-in-out infinite;
}
@keyframes upload-progress-move {
  from { transform: translateX(-110%); }
  to { transform: translateX(310%); }
}

.form-note {
  padding: 11px 13px; border-radius: 12px; background: var(--card-3);
  font-size: var(--fs-sm); color: var(--ink-2); line-height: 1.6;
}
.form-note b { color: var(--ink); }
.form-note.warn { background: var(--amber-soft); color: var(--amber-deep); }
.form-note.warn b { color: var(--amber-deep2); }
.form-note.bad { background: var(--coral-soft); color: var(--danger-deep2); }
.form-note.bad b { color: var(--danger-deep3); }
.policy-summary { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; }
.policy-summary .btn { flex: 0 0 auto; }
.archive-section { margin: 24px 0 0; }
.section-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 10px; }
.section-head h3 { margin: 0 0 3px; }
.archive-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.archive-card { border: 1px solid var(--line); border-radius: 12px; padding: 14px; background: var(--card-2); }
.archive-card-head { display: flex; justify-content: space-between; gap: 12px; align-items: flex-start; }
.archive-meta { display: grid; gap: 4px; margin-top: 12px; min-width: 0; overflow-wrap: anywhere; }
.archive-history { margin-top: 12px; border-top: 1px solid var(--line); padding-top: 10px; }
.archive-history summary { cursor: pointer; color: var(--ink-2); font-weight: 600; }
.ota-section { margin: 0 0 20px; }
.ota-section .table-wrap { min-height: 240px; }

@media (max-width: 720px) {
  .archive-grid { grid-template-columns: minmax(0, 1fr); }
  .archive-card-head { flex-direction: column; }
}

.check-list { display: grid; gap: 8px; max-height: 250px; overflow: auto; padding: 2px; }
.check-line {
  display: flex; align-items: flex-start; gap: 10px; padding: 9px 11px;
  border: 1px solid var(--line); border-radius: 11px; background: var(--card-2); cursor: pointer;
}
.check-line:hover { border-color: var(--hover-line); background: var(--card); }
.check-line input { margin-top: 2px; accent-color: var(--brand); }
.check-line .t { font-size: var(--fs-md); font-weight: 600; display: block; }
.check-line .s { font-size: var(--fs-xs); color: var(--ink-3); }

.file-drop {
  border: 1px dashed var(--line-3); border-radius: 12px; padding: 20px; text-align: center;
  background: var(--card-2); color: var(--ink-3); font-size: var(--fs-md);
}
.file-drop b { display: block; color: var(--ink); margin-bottom: 3px; }

/* 确认弹窗 */
.modal.confirm .modal-body p { font-size: var(--fs-md); color: var(--ink-2); line-height: 1.65; }
.modal.confirm .modal-body p b { color: var(--ink); }

/* 空状态 */
.empty-state { padding: 46px 20px; text-align: center; color: var(--ink-3); }
.empty-state .ico {
  width: 46px; height: 46px; margin: 0 auto 12px; border-radius: 14px;
  display: grid; place-items: center; background: var(--card-3); color: var(--ink-4); font-size: var(--fs-2xl);
}
.empty-state b { display: block; color: var(--ink); font-size: var(--fs-md); margin-bottom: 4px; }
.empty-state p { font-size: var(--fs-sm); max-width: 36ch; margin: 0 auto 14px; line-height: 1.6; }
.tbl td .empty-state { padding: 26px 16px; }

/* 骨架屏 */
.skeleton {
  background: linear-gradient(90deg, var(--track) 25%, var(--fill-2) 37%, var(--track) 63%);
  background-size: 400% 100%; animation: shimmer 1.2s ease infinite; border-radius: 8px;
}
@keyframes shimmer { 0% { background-position: 100% 50% } 100% { background-position: 0 50% } }
/* 表格行骨架：加载态用它，不要用转圈 */
.sk-row { display: grid; gap: 8px; padding: 14px; }
.sk-line { height: 10px; border-radius: 6px; }
.sk-line.w80 { width: 80%; } .sk-line.w60 { width: 60%; } .sk-line.w40 { width: 40%; }

/* 分段控件（时间范围这类小选择） */
.seg { display: inline-flex; gap: 2px; padding: 3px; background: var(--card-3); border-radius: 9px; }
.seg button {
  padding: 4px 10px; border-radius: 7px;
  font-size: var(--fs-xs); font-weight: 700; color: var(--ink-3);
}
.seg button:hover { color: var(--ink); }
.seg button[aria-pressed="true"] { background: var(--card); color: var(--ink); box-shadow: 0 1px 2px rgba(16, 24, 40, .06); }

/* 产品配置：层级常驻展示，在对应层级就地新增 */
.master-layout { display: block; }
.master-tree-card .card-body { min-height: 420px; }
.master-head-actions { display: flex; align-items: center; justify-content: flex-end; gap: 10px; flex-wrap: wrap; }
#show-disabled[aria-pressed="true"] { color: var(--brand); border-color: var(--brand); background: var(--brand-soft); }
.master-search { min-width: 0; margin-bottom: 12px; border-radius: var(--r-btn); }
.master-search > svg { width: 15px; height: 15px; flex: 0 0 15px; fill: none; stroke: var(--ink-3); stroke-width: 1.5; stroke-linecap: round; }
.master-search input { min-width: 0; }
.master-summary { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }
.master-summary .chip { white-space: nowrap; }
.master-tree { display: grid; gap: 12px; }
.master-channel {
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--card-2);
  overflow: hidden;
}
.master-channel.is-disabled, .master-brand.is-disabled, .master-model.is-disabled { opacity: .62; }
.danger-text { color: var(--danger-deep) !important; }
.master-channel-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  background: linear-gradient(90deg, var(--brand-soft) 0%, var(--card-2) 72%);
  border-bottom: 1px solid var(--line-2);
}
.master-node-icon {
  width: 30px;
  height: 30px;
  border-radius: 9px;
  flex: 0 0 30px;
  display: grid;
  place-items: center;
  font-size: var(--fs-xs);
  font-weight: 800;
}
.master-node-icon.channel { background: var(--brand-soft); color: var(--brand-ink); }
.master-node-icon.brand { background: var(--sky-soft); color: var(--sky-ink); }
.master-node-icon.model { background: var(--mint-soft); color: var(--mint-ink); }
.master-channel-head .t { min-width: 0; display: grid; gap: 1px; }
.master-channel-head .t b { font-size: var(--fs-md); font-weight: 800; }
.master-channel-head .t span { font-size: var(--fs-xs); color: var(--ink-3); }
.master-channel-head .t .desc { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.master-channel-head .t .level-title { display: flex; align-items: center; gap: 7px; color: var(--ink); }
.master-channel-head .r { margin-left: auto; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.level-tag {
  display: inline-flex; align-items: center; min-height: 20px; padding: 1px 7px;
  border-radius: 6px; background: var(--card-3); color: var(--ink-3);
  font-size: var(--fs-3xs); font-weight: 700; white-space: nowrap;
}
.master-brands { display: grid; }
.master-brand {
  display: grid;
  grid-template-columns: 26px minmax(0, 1fr) auto;
  gap: 8px 10px;
  align-items: start;
  padding: 12px 14px;
  border-bottom: 1px solid var(--line-2);
}
.master-brand:last-child { border-bottom: 0; }
.master-brand::before {
  content: "";
  width: 8px;
  height: 8px;
  margin: 7px auto 0;
  border-radius: 50%;
  background: var(--sky);
  box-shadow: 0 0 0 3px var(--sky-soft);
}
.master-brand-main { min-width: 0; display: grid; gap: 3px; }
.master-brand-main b { font-size: var(--fs-md); font-weight: 700; }
.master-brand-main b .level-tag { margin-right: 7px; vertical-align: 2px; }
.master-brand-main .meta { font-size: var(--fs-xs); color: var(--ink-3); }
.master-brand-actions { display: flex; align-items: center; justify-content: flex-end; gap: 6px; flex-wrap: wrap; }
.master-brand-models { grid-column: 2 / -1; display: flex; flex-wrap: wrap; gap: 6px; }
.master-model {
  display: inline-flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  padding: 4px 9px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--card);
  font-size: var(--fs-xs);
  color: var(--ink-2);
  max-width: 100%;
}
.master-model b { color: var(--ink); font-size: var(--fs-xs); }
.master-model .level-tag { min-height: 17px; padding: 0 5px; font-size: var(--fs-3xs); }
.master-model small { color: var(--ink-3); font-size: var(--fs-3xs); text-transform: uppercase; }
.master-model .model-edit {
  border: 0; padding: 0 0 0 2px; color: var(--ink-3);
  background: transparent; font-size: var(--fs-sm); line-height: 1;
}
.master-model .model-edit:hover { color: var(--brand); }
.master-model .btn { min-height: 22px; padding: 1px 6px; font-size: var(--fs-3xs); }
.master-model .chip { min-height: 18px; padding: 0 5px; font-size: var(--fs-3xs); }
.master-empty { padding: 26px 14px; text-align: center; color: var(--ink-3); font-size: var(--fs-sm); }

@media (max-width: 720px) {
  .master-head-actions { justify-content: flex-start; width: 100%; }
  .master-summary { justify-content: flex-start; }
  .master-channel-head { align-items: flex-start; flex-wrap: wrap; }
  .master-channel-head .r { margin-left: 40px; width: calc(100% - 40px); }
  .master-brand { grid-template-columns: 20px minmax(0, 1fr); }
  .master-brand-actions { grid-column: 2; justify-content: flex-start; }
  .master-brand-models { grid-column: 2; }
  .package-cards,
  .package-cards tbody,
  .package-cards tr,
  .package-cards td { display: block; width: 100%; }
  .package-cards thead { display: none; }
  .package-cards tbody { display: grid; gap: 12px; }
  .package-cards tr {
    padding: 12px;
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    background: var(--card);
  }
  .package-cards td {
    min-height: 28px;
    padding: 6px 0;
    border: 0;
    overflow-wrap: anywhere;
  }
  .package-cards td.num { text-align: left; }
  .package-cards td[data-label]::before {
    content: attr(data-label);
    display: block;
    margin-bottom: 3px;
    color: var(--ink-3);
    font-family: var(--font-sans);
    font-size: var(--fs-2xs);
    font-weight: 600;
  }
  .package-cards .package-actions {
    margin-top: 6px;
    padding-top: 10px;
    border-top: 1px solid var(--line);
  }
  .package-cards .actions { flex-wrap: wrap; }
}

/* 标签页容器可聚焦，方便键盘直接跳到面板 */
.tab-panel:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; border-radius: 8px; }

@media (max-width: 560px) {
  .form-grid { grid-template-columns: minmax(0, 1fr); }
  .modal-backdrop { padding: 12px; align-items: flex-end; }
  .modal { max-height: calc(100vh - 24px); }
}

/* 等宽输入 */
input.mono-input { font-family: var(--font-mono); font-size: var(--fs-sm); }

/* 开关组（表单里的复选项） */
.toggle-row { display: flex; gap: 20px; flex-wrap: wrap; }
.toggle { display: flex; align-items: center; gap: 7px; font-size: var(--fs-md); font-weight: 600; cursor: pointer; }
.toggle input { width: 16px; height: 16px; margin: 0; accent-color: var(--brand); }

/* 表单栅格槽位（条件字段显隐时占位） */
.form-slot { min-width: 0; }
.form-slot > .field { height: 100%; }

/* 移动端底栏「更多」按钮 */
.mobile-nav button {
  flex: 1; text-align: center; font-size: var(--fs-2xs); color: var(--ink-3);
  padding: 5px 2px; border-radius: 9px; font-weight: 600;
}
.mobile-nav button .g { display: block; font-size: var(--fs-md); margin-bottom: 1px; }

/* 用户指南 */
.guide-intro { max-width: 860px; color: var(--ink-2); font-size: var(--fs-md); line-height: 1.75; }
.guide-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; margin-top: 18px; }
.guide-card { border: 1px solid var(--line); border-radius: var(--r-lg); padding: 18px; background: var(--surface); }
.guide-card h3 { margin: 0 0 12px; font-size: var(--fs-lg); }
.guide-card ol { margin: 0; padding-left: 20px; display: grid; gap: 12px; }
.guide-card li { padding-left: 4px; color: var(--ink-2); font-size: var(--fs-sm); }
.guide-card li b { color: var(--ink); }
.guide-card p { margin: 4px 0 0; line-height: 1.6; }
.guide-shot { margin: 20px 0 0; border: 1px solid var(--line); border-radius: var(--r-lg); overflow: hidden; background: var(--surface); }
.guide-shot img { display: block; width: 100%; height: auto; }
.guide-shot figcaption { padding: 10px 14px; color: var(--ink-3); font-size: var(--fs-xs); }

@media (max-width: 860px) {
  .guide-grid { grid-template-columns: minmax(0, 1fr); }
}
