/* ============================================================
   织流 Weaveflow — 最终主题层
   加载顺序：style.css → main.css → weave.css（本文件必须最后）
   设计语言：画布分层（替代边框卡片）/ 章节排版 / 行式条目 /
            对象卡片（任务卡·构建记录·设备）/ 极光 accent / 弹簧动效
   ============================================================ */

/* ── 0. Tokens ─────────────────────────────────────────── */
:root {
  /* 画布三级深度（暖灰） */
  --w-canvas:  #f4f3f1;
  --w-surface: #fbfaf8;
  --w-raised:  #ffffff;
  --w-hairline: rgba(28, 25, 23, 0.09);
  --w-hairline-strong: rgba(28, 25, 23, 0.16);

  /* 墨色文字 */
  --w-ink:       #1c1917;
  --w-ink-soft:  #57534e;
  --w-ink-faint: #a8a29e;

  /* 极光 accent */
  --w-aurora: linear-gradient(120deg, #5b8cff, #8b5cf6 35%, #d946a0 70%, #f59e0b);
  --w-accent:      #6d6cf5;
  --w-accent-soft: rgba(109, 108, 245, 0.09);

  /* 非线性缓动 */
  --w-spring: linear(0, 0.009, 0.035 2.1%, 0.141 4.4%, 0.723 12.9%,
      0.938 16.7%, 1.017, 1.077 20.4%, 1.121, 1.149 24.3%, 1.159,
      1.163 27%, 1.154, 1.129 32.8%, 1.051 39.6%, 1.017 43.1%,
      0.991, 0.977 51%, 0.974 53.8%, 0.975 57.1%, 0.997 69.8%, 1);
  --w-swift: cubic-bezier(0.22, 1, 0.36, 1);
  --w-pop:   cubic-bezier(0.34, 1.56, 0.64, 1);
  --w-exit:  cubic-bezier(0.4, 0, 0.8, 0.4);
  --w-fast: 180ms;
  --w-base: 320ms;
  --w-slow: 560ms;

  /* 旧 token 重映射（让存量组件自动跟随） */
  --primary: var(--w-accent);
  --primary-hover: #5a59e0;
  --primary-light: var(--w-accent-soft);
  --primary-ring: rgba(109, 108, 245, 0.22);
  --bg-color: var(--w-canvas);
  --bg-muted: var(--w-surface);
  --card-bg: var(--w-raised);
  --text-main: var(--w-ink);
  --text-regular: #292524;
  --text-muted: var(--w-ink-soft);
  --text-faint: var(--w-ink-faint);
  --border-light: var(--w-hairline);
  --border-mid: var(--w-hairline-strong);
}
@supports not (animation-timing-function: linear(0, 1)) {
  :root { --w-spring: cubic-bezier(0.34, 1.4, 0.44, 1); }
}
@property --w-ang {
  syntax: "<angle>";
  initial-value: 0deg;
  inherits: false;
}

/* ── 1. 画布与排印 ─────────────────────────────────────── */
body {
  /* 压过 style.css 尾部的 SF Pro 栈：Windows 下让中文走微软雅黑，
     字重渲染与 demo 一致 */
  font-family: "PingFang SC", "Microsoft YaHei", -apple-system,
    BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial,
    "Noto Sans", sans-serif !important;
  background: var(--w-canvas) !important;
  color: var(--w-ink) !important;
}
h1, h2, h3 {
  font-family: inherit !important;
}
h1, h2, h3 { color: var(--w-ink) !important; }
a, .qa-ext-link { color: var(--w-accent); }
a:hover, .qa-ext-link:hover { color: #5a59e0; }
.muted { color: var(--w-ink-soft) !important; }
label { color: var(--w-ink-soft) !important; }

[style*="background: #fbfbfd"], [style*="background:#fbfbfd"] {
  background: var(--w-surface) !important;
}

/* ── 2. 左侧导航 rail（≥901px） ────────────────────────── */
@media (min-width: 901px) {
  body { padding-left: 232px !important; }

  #tabs {
    position: fixed !important;
    left: 0 !important;
    top: 0 !important;
    bottom: 0 !important;
    width: 212px !important;
    z-index: 1200 !important;
    display: flex !important;
    flex-direction: column !important;
    align-items: stretch !important;
    gap: 2px !important;
    margin: 0 !important;
    padding: 16px 12px 14px !important;
    background: transparent !important;
    border: none !important;
    border-right: 1px solid var(--w-hairline) !important;
    border-radius: 0 !important;
    box-shadow: none !important;
    overflow-y: auto !important;
    overflow-x: hidden !important;
  }

  /* rail 顶部品牌字：用伪元素生成，避免改动 index.html 结构 */
  #tabs::before {
    content: "OMNIQA · 测试平台";
    display: block;
    flex-shrink: 0;
    padding: 4px 12px 16px;
    font-size: 11px;
    font-weight: 800;
    letter-spacing: 0.12em;
    color: var(--w-ink-faint);
    background: var(--w-aurora);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    white-space: nowrap;
  }

  #tabs button {
    position: relative !important;
    z-index: 1 !important;
    width: 100% !important;
    justify-content: flex-start !important;
    text-align: left !important;
    border-radius: 10px !important;
    padding: 9px 12px !important;
    font-size: 13.5px !important;
    font-weight: 600 !important;
    min-height: 38px;
    background: transparent !important;
    color: var(--w-ink-soft) !important;
    border: none !important;
    box-shadow: none !important;
    transition: color var(--w-fast) ease-out, transform var(--w-fast) var(--w-swift) !important;
  }
  #tabs button:hover {
    color: var(--w-ink) !important;
    transform: translateX(2px);
  }
  #tabs button.active-tab {
    background: transparent !important;
    color: var(--w-ink) !important;
    transform: none !important;
  }
  #tabs button.active-tab:hover { background: transparent !important; }

  /* 实时连接徽标固定在 rail 底部 */
  #tabs .sse-conn-badge {
    margin-top: auto !important;
    align-self: stretch !important;
    justify-content: center !important;
  }
}

/* 流体指示器（weave-motion.js 注入并驱动 transform） */
#weaveRailIndicator {
  position: absolute;
  left: 0;
  top: 0;
  width: 0;
  height: 38px;
  border-radius: 10px;
  background: var(--w-raised);
  box-shadow: 0 1px 4px rgba(28, 25, 23, 0.08);
  transition: transform var(--w-slow) var(--w-spring),
              width var(--w-base) var(--w-swift),
              height var(--w-base) var(--w-swift),
              opacity var(--w-fast) ease-out;
  pointer-events: none;
  z-index: 0;
}
#weaveRailIndicator::before {
  content: "";
  position: absolute;
  left: 0;
  top: 8px;
  bottom: 8px;
  width: 3px;
  border-radius: 3px;
  background: var(--w-aurora);
}
@media (max-width: 900px) {
  /* 窄屏退回顶部横滑条 */
  #weaveRailIndicator { box-shadow: none; background: var(--w-raised); }
  #tabs { background: var(--w-surface) !important; border: 1px solid var(--w-hairline) !important; }
  #tabs button { position: relative; z-index: 1; font-weight: 600 !important; }
  #tabs button.active-tab { background: transparent !important; color: var(--w-ink) !important; }
}

/* ── 3. 顶栏（去卡片化） ───────────────────────────────── */
.app-header {
  background: color-mix(in srgb, var(--w-canvas) 82%, transparent) !important;
  backdrop-filter: saturate(160%) blur(14px) !important;
  border: none !important;
  border-bottom: 1px solid var(--w-hairline) !important;
  border-radius: 0 !important;
  box-shadow: none !important;
  top: 0 !important;
  padding: 12px 4px !important;
}
.app-header-brand-text h1 { color: var(--w-ink) !important; }
.app-header-brand-text span { color: var(--w-ink-faint) !important; }
.header-software-pill,
.header-user-pill {
  background: var(--w-surface) !important;
  border: 1px solid var(--w-hairline) !important;
}
.header-user-avatar { background: var(--w-aurora) !important; }
.header-action-group button {
  border-radius: 999px !important;
  color: var(--w-ink-soft) !important;
  border: 1px solid var(--w-hairline-strong) !important;
  background: transparent !important;
}
.header-action-group button:hover {
  color: var(--w-ink) !important;
  border-color: var(--w-ink-faint) !important;
  background: var(--w-surface) !important;
}
.header-action-group button.danger-btn {
  color: #b4232a !important;
  border-color: rgba(217, 44, 44, 0.35) !important;
}

/* ── 4. 章节化：section 不再是卡片 ─────────────────────── */
section.card {
  background: transparent !important;
  border: none !important;
  box-shadow: none !important;
  border-radius: 0 !important;
  padding: 8px 2px 24px !important;
  margin-bottom: 8px !important;
}
section.card > h2 {
  display: flex !important;
  align-items: baseline !important;
  gap: 14px !important;
  font-size: 26px !important;
  font-weight: 750 !important;
  letter-spacing: -0.02em !important;
  color: var(--w-ink) !important;
  border-bottom: none !important;
  padding-bottom: 0 !important;
  margin-bottom: 10px !important;
  position: relative;
}
/* 渐隐章节线 */
section.card > h2::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -10px;
  height: 1px;
  background: linear-gradient(90deg, var(--w-hairline-strong), transparent 85%);
}
section.card > h2 { margin-bottom: 30px !important; }

/* 章节编号（weave-motion.js 注入） */
.chapter-no {
  font-size: 13px;
  font-weight: 800;
  font-feature-settings: "tnum";
  letter-spacing: 0.06em;
  background: var(--w-aurora);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  flex-shrink: 0;
  margin-right: 12px;
  vertical-align: 4px;
}

/* 章节内的次级面板：全部铺到画布上，不再有"大白卡" */
.qa-panel, .qa-panel-soft,
.zentao-sync-shell-modern,
.zentao-sync-left, .zentao-sync-right,
.zentao-major-context {
  background: transparent !important;
  border: none !important;
  box-shadow: none !important;
  border-radius: 14px !important;
}
/* 嵌套的通用 .card（如 #reportContent、分配台面板）一律平铺；
   对象卡片（构建记录/禅道信息卡/图表盒）除外 */
section.card .card:not(.build-record-card):not(.zentao-info-card):not(.chart-box) {
  background: transparent !important;
  border: none !important;
  box-shadow: none !important;
  padding-left: 0 !important;
  padding-right: 0 !important;
}
/* 顶层面板（details 折叠块 / 带内联背景的 div）一律压平。
   注意：JS 触碰过 el.style 后属性会被重新序列化为 rgb() 形式，
   因此不能依赖 [style*="background:#fff"] 字符串匹配 */
section.card > details,
section.card > div[style*="background"] {
  background: transparent !important;
}
section.card details {
  border-color: var(--w-hairline) !important;
}
/* 分配台的候选需求滚动区 */
#linkCandidatesArea {
  background: transparent !important;
  border-color: var(--w-hairline) !important;
}

/* ── 5. 按钮：墨色弹簧 ───────────────────────────────────
   style.css 尾部的 Apple 覆盖段全部带 !important，
   这里必须同级 !important 才能（凭加载顺序）胜出 */
button {
  border-radius: 999px !important;
  background: var(--w-ink) !important;
  color: #fff !important;
  font-weight: 600 !important;
  letter-spacing: -0.1px !important;
  transition: transform var(--w-base) var(--w-spring),
              box-shadow var(--w-base) var(--w-swift),
              background var(--w-fast) ease-out,
              border-color var(--w-fast) ease-out,
              color var(--w-fast) ease-out !important;
}
button:hover {
  background: #33302c !important;
  box-shadow: 0 4px 18px rgba(139, 92, 246, 0.3) !important;
  transform: translateY(-1px) !important;
}
button:active {
  transform: scale(0.96) !important;
  transition-duration: 80ms !important;
  box-shadow: none !important;
}
button.secondary {
  background: var(--w-raised) !important;
  color: var(--w-ink) !important;
  border: 1px solid var(--w-hairline-strong) !important;
  box-shadow: none !important;
}
button.secondary:hover {
  background: var(--w-raised) !important;
  color: var(--w-ink) !important;
  border-color: var(--w-ink-faint) !important;
  box-shadow: 0 2px 10px rgba(28, 25, 23, 0.08) !important;
}
button.danger { background: #b4232a !important; }
button.danger:hover { background: #962129 !important; box-shadow: 0 4px 14px rgba(180, 35, 42, 0.25) !important; }
button:disabled { opacity: 0.4; transform: none !important; }
/* 表格/卡片里的小操作按钮保持药丸形 */
#tab-mine button, #tab-retest button, #tab-feedback button,
#tab-field-test button, #tab-zentao-sync button, #tab-overall-test button {
  border-radius: 999px !important;
}

/* ── 6. 输入控件 ──────────────────────────────────────── */
input, select, textarea, .prefix-input {
  background: var(--w-raised) !important;
  border-color: var(--w-hairline-strong) !important;
  border-radius: 10px !important;
  color: var(--w-ink) !important;
}
input:focus, select:focus, textarea:focus, .prefix-input:focus-within {
  border-color: var(--w-accent) !important;
  box-shadow: 0 0 0 3px var(--primary-ring) !important;
}
button:focus-visible, input:focus-visible,
select:focus-visible, textarea:focus-visible,
.prefix-input:focus-within {
  outline: 2px solid var(--w-accent) !important;
}
.prefix-input span {
  background: var(--w-surface) !important;
  color: var(--w-ink-soft) !important;
}
input[type="checkbox"], input[type="radio"] { accent-color: var(--w-accent); }

/* ── 7. 表格：毛细线行式 ───────────────────────────────── */
table, .qa-table, .qa-table-feedback, .qa-table-zentao-sync, .qa-table-field-test {
  border: none !important;
  border-radius: 0 !important;
  background: transparent !important;
}
th {
  background: transparent !important;
  color: var(--w-ink-faint) !important;
  border-bottom: 1px solid var(--w-hairline-strong) !important;
  font-size: 11.5px !important;
  font-weight: 700 !important;
}
td {
  color: var(--w-ink) !important;
  border-bottom: 1px solid var(--w-hairline) !important;
}
tbody tr { transition: background var(--w-fast) ease-out, box-shadow var(--w-fast) ease-out; }
tbody tr:hover td { background: rgba(28, 25, 23, 0.03) !important; }
/* hover accent beam（首列内侧细条） */
tbody tr:hover td:first-child { box-shadow: inset 3px 0 0 var(--w-accent); }
thead tr:hover th { background: transparent !important; box-shadow: none !important; }

/* ── 8. 指标：大数字（去卡片） ─────────────────────────── */
.metric-card {
  background: transparent !important;
  border: none !important;
  border-left: 1px solid var(--w-hairline) !important;
  border-radius: 0 !important;
  box-shadow: none !important;
  padding: 4px 16px !important;
}
.metric-title {
  color: var(--w-ink-soft) !important;
  font-size: 12px !important;
  font-weight: 650 !important;
}
.metric-value {
  font-size: 38px !important;
  font-weight: 640 !important;
  letter-spacing: -0.03em !important;
  line-height: 1.12 !important;
  font-feature-settings: "tnum";
  font-variant-numeric: tabular-nums;
}

/* 图表容器：白色 surface + 毛细线（图表需要稳定底色） */
.chart-box {
  background: var(--w-raised) !important;
  border: 1px solid var(--w-hairline) !important;
  border-radius: 14px !important;
  box-shadow: none !important;
}

/* ── 9. 对象卡片：任务卡 / 构建记录 / 设备 ─────────────── */
/* 任务看板列容器铺在画布上 */
#taskBoardColumns > div {
  background: transparent !important;
  border: none !important;
  padding: 0 2px !important;
}
/* 看板顶部统计条：彩色小卡 → 平铺指标 */
#taskBoardSummary > div {
  background: transparent !important;
  border: none !important;
  border-left: 1px solid var(--w-hairline) !important;
  border-radius: 0 !important;
  padding: 4px 16px !important;
}
[data-task-card] {
  background: var(--w-raised) !important;
  border: 1px solid var(--w-hairline) !important;
  border-radius: 14px !important;
  box-shadow: none !important;
  cursor: grab !important;
  position: relative;
  transition: transform var(--w-slow) var(--w-spring),
              box-shadow var(--w-base) var(--w-swift),
              border-color var(--w-fast) ease-out;
}
[data-task-card]:hover {
  transform: translateY(-3px) scale(1.01);
  box-shadow: 0 12px 28px rgba(28, 25, 23, 0.1) !important;
  border-color: transparent !important;
}
[data-task-card]:active { cursor: grabbing !important; transform: scale(0.99); transition-duration: 80ms; }

.build-record-card,
#tab-terminal section.card .card,
#tab-terminal .card {
  background: var(--w-raised) !important;
  border: 1px solid var(--w-hairline) !important;
  border-radius: 14px !important;
  box-shadow: none !important;
  transition: transform var(--w-slow) var(--w-spring),
              box-shadow var(--w-base) var(--w-swift),
              border-color var(--w-fast) ease-out !important;
}
.build-record-card:hover {
  transform: translateY(-3px) scale(1.005) !important;
  box-shadow: 0 12px 28px rgba(28, 25, 23, 0.1) !important;
  border-color: transparent !important;
}

/* 对象卡片 hover 左沿极光 beam */
[data-task-card]::before,
.build-record-card::before {
  content: "";
  position: absolute;
  left: -1px;
  top: 24%;
  bottom: 24%;
  width: 3px;
  border-radius: 3px;
  background: var(--w-aurora);
  opacity: 0;
  transform: scaleY(0.4);
  transition: opacity var(--w-fast) ease-out, transform var(--w-base) var(--w-pop);
  pointer-events: none;
}
[data-task-card]:hover::before,
.build-record-card:hover::before { opacity: 1; transform: scaleY(1); }
.build-record-card { position: relative; }

/* ── 10. 行式条目：工作台/复测的需求卡降级为行 ─────────── */
#tab-mine details.mine-req-card,
#tab-retest details.retest-req-card,
.activity-feed-item {
  background: transparent !important;
  border: none !important;
  border-bottom: 1px solid var(--w-hairline) !important;
  border-radius: 12px !important;
  box-shadow: none !important;
  position: relative;
  transition: transform var(--w-base) var(--w-swift), background var(--w-base) var(--w-swift) !important;
}
#tab-mine details.mine-req-card:hover,
#tab-retest details.retest-req-card:hover,
.activity-feed-item:hover {
  background: rgba(28, 25, 23, 0.03) !important;
  transform: translateX(4px);
}
#tab-mine details.mine-req-card::before,
#tab-retest details.retest-req-card::before,
.activity-feed-item::before {
  content: "";
  position: absolute;
  left: 2px;
  top: 22%;
  bottom: 22%;
  width: 3px;
  border-radius: 3px;
  background: var(--w-aurora);
  opacity: 0;
  transform: scaleY(0.4);
  transition: opacity var(--w-fast) ease-out, transform var(--w-base) var(--w-pop);
  pointer-events: none;
}
#tab-mine details.mine-req-card:hover::before,
#tab-retest details.retest-req-card:hover::before,
.activity-feed-item:hover::before { opacity: 1; transform: scaleY(1); }
/* 展开态的需求卡轻微染色，便于聚焦 */
#tab-mine details.mine-req-card[open],
#tab-retest details.retest-req-card[open] {
  background: rgba(28, 25, 23, 0.025) !important;
  transform: none;
}

/* ── 11. 模态：弹簧弹出（@starting-style 渐进增强） ────── */
[data-modal-display] > div,
.ft-modal-card {
  border-radius: 18px !important;
  border: none !important;
  box-shadow: 0 24px 64px rgba(28, 25, 23, 0.22) !important;
  transition: transform var(--w-slow) var(--w-spring), opacity var(--w-fast) ease-out;
}
@starting-style {
  [data-modal-display] > div,
  .ft-modal-mask:not(.hidden) .ft-modal-card {
    transform: scale(0.92) translateY(10px);
    opacity: 0;
  }
}
.ft-modal-mask, [data-modal-display] {
  background: rgba(28, 25, 23, 0.32) !important;
  backdrop-filter: blur(2px);
}

/* ── 12. 杂项统一 ─────────────────────────────────────── */
.timeline-dot {
  background: var(--w-accent) !important;
  box-shadow: 0 0 0 3px var(--w-accent-soft) !important;
}
.timeline-content { border-left-color: var(--w-hairline-strong); }
.sse-inline-notice {
  background: var(--w-accent-soft) !important;
  border: 1px solid rgba(109, 108, 245, 0.3) !important;
  color: var(--w-accent) !important;
  border-radius: 10px !important;
}
.workbench-subnav button {
  background: transparent !important;
  border: 1px solid var(--w-hairline-strong) !important;
  color: var(--w-ink-soft) !important;
  border-radius: 999px !important;
}
.workbench-subnav button:hover { color: var(--w-ink) !important; transform: none; box-shadow: none; }
.workbench-subnav button.active {
  background: var(--w-ink) !important;
  border-color: var(--w-ink) !important;
  color: #fff !important;
}
#tabs .sse-conn-badge {
  border-radius: 999px !important;
  border-color: var(--w-hairline) !important;
  background: var(--w-surface) !important;
  color: var(--w-ink-soft) !important;
}
.zentao-sync-sticky-panel, .zentao-info-card {
  background: transparent !important;
  border: none !important;
  box-shadow: none !important;
  border-radius: 14px !important;
}
.zentao-info-card { background: var(--w-raised) !important; border: 1px solid var(--w-hairline) !important; }
#healthPanel { border-left: 2px solid var(--w-accent) !important; }
.free-bug-box {
  background: var(--w-surface) !important;
  border: 1px solid var(--w-hairline) !important;
}
/* 旧的冷灰内联底色（筛选条/工具栏）→ 直接铺在画布上 */
[style*="background:#f8fafc"], [style*="background: #f8fafc"],
[style*="background:#f1f5f9"], [style*="background: #f1f5f9"] {
  background: transparent !important;
}
/* 但弹窗内部的这类色块保留浅染（白底弹窗里需要层次） */
[data-modal-display] [style*="background:#f8fafc"],
[data-modal-display] [style*="background: #f8fafc"],
[data-modal-display] [style*="background:#f1f5f9"],
[data-modal-display] [style*="background: #f1f5f9"] {
  background: var(--w-surface) !important;
}
[style*="border:1px solid #e2e8f0"], [style*="border: 1px solid #e2e8f0"] {
  border-color: var(--w-hairline) !important;
}

/* ── 13. 入场编排 ─────────────────────────────────────── */
.weave-enter {
  animation: weaveFloatIn var(--w-slow) var(--w-spring) backwards;
  animation-delay: calc(var(--wi, 0) * 42ms);
}
@keyframes weaveFloatIn {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ── 13b. 模糊搜索组合框（任务看板·新建禅道任务）──────── */
.zt-combo-list {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  z-index: 60;
  max-height: 220px;
  overflow: auto;
  background: var(--w-raised, #fff);
  border: 1px solid var(--w-hairline-strong, #cbd5e1);
  border-radius: 10px;
  box-shadow: 0 12px 28px rgba(28, 25, 23, 0.14);
  padding: 4px;
}
.zt-combo-item {
  padding: 7px 10px;
  border-radius: 7px;
  cursor: pointer;
  font-size: 13px;
  line-height: 1.4;
}
.zt-combo-item:hover,
.zt-combo-item.active {
  background: rgba(139, 92, 246, 0.10);
}

/* ── 14. SSE 极光统一（沿用现有 glow 机制，仅调色） ────── */
.sse-glow-wrap::before,
tr.sse-glow-enter td:first-child {
  /* 渐变采样自 --w-aurora，保持品牌一致 */
  --sse-c1: #5b8cff;
  --sse-c2: #8b5cf6;
  --sse-c3: #d946a0;
  --sse-c4: #f59e0b;
}

/* ── 14b. 工作台视口：给弹起条目与流光边留呼吸空间 ──────
   .workbench-viewport 必须保持 overflow:hidden（子页横向轮播靠它裁剪），
   但条目 hover 弹起（translateX/Y、scale）和 SSE 流光边（::before 外扩 2px）
   会越出条目边缘，恰好落在视口边界上被裁掉。
   处理：视口负外边距向四周外扩，面板等量内缩——内容视觉位置不变，
   越界的流光与投影落在扩出的空间里，不再被切。
   （外扩量 ≤ section.card 的最小内边距 16px/14px，不会挤出父容器。） */
.workbench-viewport {
  margin: -10px -12px !important;
}
.workbench-panel {
  padding: 10px 12px !important;
}

/* ── 14c. SSE 流光边缘动态化：色彩沿边缘缓缓流动 ────────
   原实现是静态 linear-gradient 描边环（style.css .sse-glow-*::before）。
   改为 conic 渐变 + 角度缓速自转（复用 R2 的 @property 角度插值模式）。
   角度变量放在宿主元素上做动画且声明为可继承，::before 的渐变随之旋转——
   不触碰 style.css 中 enter/hold/exit 三阶段对 ::before 的 animation 赋值，
   两套动画互不覆盖。渐变首尾同色保证循环无接缝；不支持 @property 的
   浏览器角度不插值，渐变静止在 0deg，安全降级为原来的静态描边。 */
@property --sse-ang {
  syntax: "<angle>";
  initial-value: 0deg;
  inherits: true;
}
@keyframes sseAngFlow { to { --sse-ang: 360deg; } }
.sse-glow { animation: sseAngFlow 4.8s linear infinite; }

/* 每种色调在 50% 处放一段亮色高光：随角度旋转形成一颗肉眼可辨的
   "光点"绕边缘游走，避免同色系渐变旋转过于含蓄被误认为静态。 */
.sse-glow-blue::before {
  background: conic-gradient(from var(--sse-ang),
      #6366f1, #8b5cf6 28%, #c7d2fe 50%, #3b82f6 62%, #06b6d4 82%, #6366f1) !important;
}
.sse-glow-teal::before {
  background: conic-gradient(from var(--sse-ang),
      #0891b2, #10b981 28%, #a5f3fc 50%, #06b6d4 62%, #22d3ee 82%, #0891b2) !important;
}
.sse-glow-green::before {
  background: conic-gradient(from var(--sse-ang),
      #10b981, #22c55e 28%, #d9f99d 50%, #84cc16 62%, #16a34a 82%, #10b981) !important;
}
.sse-glow-purple::before {
  background: conic-gradient(from var(--sse-ang),
      #7c3aed, #8b5cf6 28%, #f5d0fe 50%, #d946a0 62%, #6d28d9 82%, #7c3aed) !important;
}
.sse-glow-amber::before {
  background: conic-gradient(from var(--sse-ang),
      #f59e0b, #f97316 28%, #fef08a 50%, #fbbf24 62%, #d97706 82%, #f59e0b) !important;
}

/* 表格行条目（测试工作台/反馈等 SSE 高亮是 <tr>）：无法用 ::before 描边环，
   原实现只有单色内描边呼吸。补一条横向缓缓流过的极光渐变：tr 背景跨单元格
   连续绘制，td 的 hold 底色是半透明能透出流动。background-size 300% 配合
   位移 -150%（= 恰好一个图宽）保证循环无接缝，渐变首尾同色。 */
tr.sse-glow-hold {
  /* 用长属性而非 background 简写：!important 的简写会连 background-position
     一起锁死，动画（优先级低于 !important）就动不了了。position 不声明，
     完全交给 sseRowSweep 动画驱动。 */
  background-image: linear-gradient(100deg,
      rgba(99, 102, 241, 0.14), rgba(139, 92, 246, 0.20) 25%,
      rgba(217, 70, 160, 0.16) 50%, rgba(59, 130, 246, 0.18) 75%,
      rgba(99, 102, 241, 0.14)) !important;
  background-size: 300% 100% !important;
  background-repeat: repeat !important;
  animation: sseRowSweep 4.8s linear infinite;
}
@keyframes sseRowSweep {
  from { background-position: 0% 0; }
  to   { background-position: -150% 0; }
}

/* 行式条目/对象卡的 hover 左沿 beam 与流光环共用 ::before，且 beam 规则
   （ID 选择器）特异性更高，会把流光环压成左侧细条。流光激活期间把
   环形几何抢回来（beam 是 hover 瞬态装饰，让位无感知）。 */
[data-task-card].sse-glow::before,
.build-record-card.sse-glow::before,
#tab-mine details.mine-req-card.sse-glow::before,
#tab-retest details.retest-req-card.sse-glow::before,
.activity-feed-item.sse-glow::before {
  inset: -2px !important;
  width: auto !important;
  border-radius: inherit !important;
  transform: none !important;
  transition: none !important;
}

/* ── 14d. 悬停流光环：条目弹起时色彩沿边缘缓缓流动 ──────
   用户日常看到的「彩色边缘」是 hover 效果（SSE 流光环仅在有未读事件时
   出现，平时看不到）。把 hover 升级为绕四周流动的描边环：放在空闲的
   ::after 上（::before 已被 hover 左沿 beam 占用），conic 极光渐变 +
   --w-ang 角度自转（@property 已注册，动画作用在伪元素自身）。
   左沿彩色竖线 beam 保留，与流光环共同构成 hover 指示（用户点名要的）。
   整段包在 @supports 里：遮罩描边不可用的环境保持原 beam 行为不变。 */
@supports ((-webkit-mask-composite: destination-out) or (mask-composite: exclude)) {
  #tab-mine details.mine-req-card::after,
  #tab-retest details.retest-req-card::after,
  .activity-feed-item::after,
  [data-task-card]::after,
  .build-record-card::after {
    content: "";
    position: absolute;
    inset: -2px;
    border-radius: inherit;
    padding: 2.5px;
    /* 渐变必须在 ::after 自身重声明：继承 :root 的 --w-aurora-conic 时
       var(--w-ang) 已在 :root 处固化为 0deg，动画转不动（详见 R2 段注释） */
    --w-aurora-conic: conic-gradient(from var(--w-ang),
        #5b8cff, #8b5cf6, #d946a0, #f59e0b, #5b8cff);
    background: var(--w-aurora-conic);
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: destination-out;
    mask-composite: exclude;
    opacity: 0;
    transition: opacity var(--w-base) ease-out;
    pointer-events: none;
  }
  #tab-mine details.mine-req-card:hover::after,
  #tab-retest details.retest-req-card:hover::after,
  .activity-feed-item:hover::after,
  [data-task-card]:hover::after,
  .build-record-card:hover::after {
    opacity: 1;
    /* 3s 与 R2.2 宿主 1px 描边同速同相，两圈不会转出错位 */
    animation: weaveAngSpin 3s linear infinite;
  }
  /* 行式条目 hover 补一圈柔光，让流光环在浅色背景上更醒目 */
  #tab-mine details.mine-req-card:hover,
  #tab-retest details.retest-req-card:hover,
  .activity-feed-item:hover {
    box-shadow: 0 4px 18px rgba(139, 92, 246, 0.18) !important;
  }
  /* 展开态停用 hover 流光环与柔光：weaveAngSpin 动的是自定义属性，无法走
     合成器，每帧按整个卡片包围盒重绘 conic 渐变。折叠行 ~50px 无感；
     父任务展开后带子任务列表高达上千像素，逐帧整框重绘直接掉帧卡顿。
     展开即阅读态，hover 装饰本就多余——折叠行保留全部流光效果。 */
  #tab-mine details.mine-req-card[open]:hover::after,
  #tab-retest details.retest-req-card[open]:hover::after {
    animation: none !important;
    opacity: 0 !important;
  }
  #tab-mine details.mine-req-card[open]:hover,
  #tab-retest details.retest-req-card[open]:hover {
    box-shadow: none !important;
  }
}

/* ============================================================
   R2 修复轮（2026-06-12 用户反馈）：
   - 消灭刺眼纯白：raised 改暖白、输入控件改"凹陷"暖色
   - 焦点/悬停流光边缘（conic 渐变边框 + 旋转动画）
   - 对象卡片统一 hover 轻浮动效
   - 弹窗暖化 + 打开时锁定背景滚动
   ============================================================ */
:root {
  --w-raised: #faf9f7;            /* 卡片/弹窗：暖白 */
  --w-well: #edebe7;              /* 输入控件：比画布略深的凹陷色 */
  --w-glow-ring: rgba(139, 92, 246, 0.16);
  --w-aurora-conic: conic-gradient(from var(--w-ang),
      #5b8cff, #8b5cf6, #d946a0, #f59e0b, #5b8cff);
}
@keyframes weaveAngSpin { to { --w-ang: 360deg; } }

/* 旋转失效的根因修复：自定义属性里的 var() 是在“声明处”求值的——
   --w-aurora-conic 挂在 :root，var(--w-ang) 永远取 :root 的 0deg，
   后代继承到的是已固化的静态渐变；元素上 weaveAngSpin 再怎么转自己的
   --w-ang 都不影响背景（此前所有流光边缘一直是静止的）。
   在每个跑 weaveAngSpin 的元素上就地重声明，var(--w-ang) 改在元素
   自身求值，随元素动画逐帧重算，渐变才真正旋转。 */
input:not([type="checkbox"]):not([type="radio"]):not([type="file"]),
select, textarea, .prefix-input,
[data-task-card], .build-record-card,
#terminalGrid .card, #tab-cad-test .card,
#jenkinsDetailArea > div[style*="border"], #dataUsers > .card,
#tab-mine details.mine-req-card, #tab-retest details.retest-req-card,
#tab-learning .lc-topic, #tab-learning .lc-panel, #tab-learning .lc-row,
#tab-learning .lc-q, #tab-learning details.lc-rank {
  --w-aurora-conic: conic-gradient(from var(--w-ang),
      #5b8cff, #8b5cf6, #d946a0, #f59e0b, #5b8cff);
}

/* ── R2.1 输入控件：凹陷暖色 + 焦点流光边缘 ── */
input:not([type="checkbox"]):not([type="radio"]):not([type="file"]),
select, textarea {
  background: var(--w-well) !important;
  border: 1px solid rgba(28, 25, 23, 0.12) !important;
  border-radius: 10px !important;
}
input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):focus,
select:focus, textarea:focus {
  border-color: transparent !important;
  background: linear-gradient(var(--w-well), var(--w-well)) padding-box,
              var(--w-aurora-conic) border-box !important;
  animation: weaveAngSpin 2.4s linear infinite;
  box-shadow: 0 0 0 3px var(--w-glow-ring) !important;
  outline: none !important;
}
input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: none !important;
}
/* prefix-input：外壳一体化（修复中缝横线 + 内部圆角），焦点流光 */
.prefix-input {
  background: var(--w-well) !important;
  border: 1px solid rgba(28, 25, 23, 0.12) !important;
  border-radius: 10px !important;
}
.prefix-input span {
  background: transparent !important;
  border-right: none !important;
}
.prefix-input input,
.prefix-input input:focus {
  border: none !important;
  border-radius: 0 !important;
  background: transparent !important;
  box-shadow: none !important;
  animation: none !important;
  outline: none !important;
}
.prefix-input:focus-within {
  border-color: transparent !important;
  background: linear-gradient(var(--w-well), var(--w-well)) padding-box,
              var(--w-aurora-conic) border-box !important;
  animation: weaveAngSpin 2.4s linear infinite;
  box-shadow: 0 0 0 3px var(--w-glow-ring) !important;
  outline: none !important;
}

/* header 药丸里的软件切换下拉保持隐形 */
.header-software-pill select {
  background: transparent !important;
  border: none !important;
  box-shadow: none !important;
  animation: none !important;
}

/* ── R2.2 对象卡片统一：暖白底 + hover 轻浮 + 流光描边 ── */
[data-task-card],
.build-record-card,
#terminalGrid .card,
#tab-cad-test .card,
#jenkinsDetailArea > div[style*="border"],
#dataUsers > .card,
#tab-mine details.mine-req-card,
#tab-retest details.retest-req-card,
#tab-learning .lc-topic {
  background: var(--w-raised) !important;
  border: 1px solid var(--w-hairline) !important;
  border-radius: 14px !important;
  box-shadow: none !important;
  padding: 14px 16px !important;
  transition: transform var(--w-slow) var(--w-spring),
              box-shadow var(--w-base) var(--w-swift),
              background var(--w-fast) ease-out !important;
}
#tab-mine details.mine-req-card,
#tab-retest details.retest-req-card {
  margin-bottom: 10px;
  border-bottom: 1px solid var(--w-hairline) !important;
}
[data-task-card]:hover,
.build-record-card:hover,
#terminalGrid .card:hover,
#tab-cad-test .card:hover,
#jenkinsDetailArea > div[style*="border"]:hover,
#dataUsers > .card:hover,
#tab-mine details.mine-req-card:hover,
#tab-retest details.retest-req-card:hover,
#tab-learning .lc-topic:hover,
#tab-learning .lc-topic.active {
  transform: translateY(-3px) scale(1.005) !important;
  border-color: transparent !important;
  background: linear-gradient(var(--w-raised), var(--w-raised)) padding-box,
              var(--w-aurora-conic) border-box !important;
  animation: weaveAngSpin 3s linear infinite;
  box-shadow: 0 12px 28px rgba(28, 25, 23, 0.1) !important;
}
/* 展开态保持选中：略放慢流光、补一圈光晕（不上浮，避免与详情错位） */
#tab-learning .lc-topic.active {
  transform: none !important;
  animation: weaveAngSpin 6s linear infinite;
  box-shadow: 0 8px 22px rgba(28, 25, 23, 0.08), 0 0 0 3px var(--w-glow-ring) !important;
}
/* CAD 异常卡保留暖化红底信号 */
#tab-cad-test .card[style*="background:#fef2f2"] {
  background: #f7ebe8 !important;
  border-color: rgba(220, 38, 38, 0.25) !important;
}
#tab-cad-test .card[style*="background:#fef2f2"]:hover {
  background: linear-gradient(#f7ebe8, #f7ebe8) padding-box,
              var(--w-aurora-conic) border-box !important;
}

/* ── R2.3 表格行 hover：极光渐变 beam（替换纯色，统一 Jenkins） ── */
tbody tr:hover td:first-child {
  box-shadow: none !important;
  background-image: linear-gradient(180deg, #5b8cff, #8b5cf6, #d946a0) !important;
  background-size: 3px 62% !important;
  background-position: 0 50% !important;
  background-repeat: no-repeat !important;
}
/* Jenkins job 列表/详情内联白底压暖 */
#jenkinsJobsArea table { background: transparent !important; border-color: var(--w-hairline) !important; }
#jenkinsJobsArea thead tr { background: transparent !important; }
#jenkinsDetailArea table { background: transparent !important; border-color: var(--w-hairline) !important; }

/* 反馈筛选区：刷新按钮跟随关键字行，不独占整行 */
#tab-feedback .qa-filter-grid-feedback .qa-filter-actions {
  grid-column: auto;
  margin-top: 0;
  align-self: end;
  justify-content: flex-start;
}

/* ── R2.4 列表条目兜底：外业测试 / 反馈表格不允许白底 ── */
#tab-field-test .qa-table-field-test,
#tab-field-test .qa-table-field-test td,
#tab-field-test .field-test-row-card td,
#tab-feedback .qa-table-feedback td {
  background: transparent !important;
}

/* ── R2.5 图表盒暖化（报表中心） ── */
.chart-box { background: var(--w-raised) !important; }

/* ── R2.6 弹窗：暖白面板 + 背景滚动锁 ── */
[data-modal-display] > div,
.ft-modal-card,
div[style*="position: fixed"][style*="inset: 0"] > div,
div[style*="position:fixed"][style*="inset:0"] > div {
  background: var(--w-raised) !important;
}
div[style*="position: fixed"][style*="inset: 24px"],
div[style*="position:fixed"][style*="inset:24px"] {
  background: var(--w-raised) !important;
}
/* 弹窗打开时锁定页面滚动（覆盖三类弹窗实现） */
body:has([data-modal-display]:not(.hidden)),
body:has(.ft-modal-mask:not(.hidden)),
body:has(div[style*="position: fixed"][style*="inset: 0"]:not(.hidden):not([style*="display: none"])),
body:has(div[style*="position:fixed"][style*="inset:0"]:not(.hidden):not([style*="display: none"]):not([style*="display:none"])) {
  overflow: hidden !important;
}

/* ── 16. 学习中心：对象卡分层（明确分割，不被通用压平规则铺平）──
   说明：weave 默认把 section.card 里的 .card 压平以避免"大白卡"，
   但学习中心需要清晰的内容分块，故使用独立 .lc-* 类自带升起表面。 */
#tab-learning .lc-topic-list {
  display: grid !important;
  gap: 12px !important;
}
/* 区段面板：升起表面（暖白 + 发丝边 + 14px 圆角，与全站卡片一致）。
   主题磁贴 .lc-topic 的 hover 浮动/流光描边由上方共享对象卡规则统一提供。 */
#tab-learning .lc-panel {
  background: var(--w-raised) !important;
  border: 1px solid var(--w-hairline) !important;
  border-radius: 14px !important;
  box-shadow: 0 1px 3px rgba(28, 25, 23, 0.05) !important;
  padding: 16px 18px !important;
  margin-bottom: 16px !important;
  transition: transform var(--w-slow) var(--w-spring),
              box-shadow var(--w-base) var(--w-swift),
              background var(--w-fast) ease-out !important;
}
#tab-learning .lc-topic { cursor: pointer; }

/* 展开内容也"活起来"：面板/行/名次条 hover、题块 hover 或聚焦时
   轻微弹出 + 旋转极光描边（与全站对象卡一致）。
   面板用 :has() 让位于内部条目——hover 内部行/题块时只让内部条目弹出，
   避免父面板与子条目同时位移造成的抖动。 */
#tab-learning .lc-panel:hover:not(:has(.lc-row:hover, .lc-q:hover, .lc-q:focus-within, details.lc-rank:hover)),
#tab-learning .lc-row:hover {
  transform: translateY(-3px) scale(1.005);
  border-color: transparent !important;
  background: linear-gradient(var(--w-raised), var(--w-raised)) padding-box,
              var(--w-aurora-conic) border-box !important;
  animation: weaveAngSpin 3s linear infinite;
  box-shadow: 0 12px 28px rgba(28, 25, 23, 0.1), 0 0 0 3px var(--w-glow-ring) !important;
}

/* 面板内分区标题 */
#tab-learning .lc-section-head {
  display: flex !important;
  align-items: center !important;
  justify-content: space-between !important;
  gap: 10px;
  padding-bottom: 10px;
  margin-bottom: 12px;
  border-bottom: 1px solid var(--w-hairline) !important;
}
#tab-learning .lc-section-head .lc-title {
  font-size: 15px !important;
  font-weight: 700 !important;
  color: var(--w-ink) !important;
  letter-spacing: -0.01em;
}

/* 行式条目（资料/考核轮次/批改项）*/
#tab-learning .lc-row {
  display: flex !important;
  align-items: center !important;
  justify-content: space-between !important;
  gap: 10px;
  padding: 10px 12px !important;
  border: 1px solid transparent !important;
  border-radius: 10px !important;
  transition: transform var(--w-base) var(--w-spring),
              box-shadow var(--w-base) var(--w-swift),
              background var(--w-fast) ease-out !important;
}
#tab-learning .lc-row + .lc-row { border-top-color: var(--w-hairline) !important; }

/* 题目/作答块：柔和次级表面；获得焦点(焦点在内)时轻微弹出 + 流光边缘 */
#tab-learning .lc-q {
  background: var(--w-surface) !important;
  border: 1px solid var(--w-hairline) !important;
  border-radius: 12px !important;
  padding: 14px 16px !important;
  margin-bottom: 12px !important;
  transition: transform var(--w-base) var(--w-spring),
              box-shadow var(--w-base) var(--w-swift),
              background var(--w-fast) ease-out !important;
}
#tab-learning .lc-q:last-child { margin-bottom: 0 !important; }
#tab-learning .lc-q:hover,
#tab-learning .lc-q:focus-within,
#tab-learning details.lc-rank:hover {
  transform: translateY(-3px) scale(1.005);
  border-color: transparent !important;
  background: linear-gradient(var(--w-surface), var(--w-surface)) padding-box,
              var(--w-aurora-conic) border-box !important;
  animation: weaveAngSpin 3s linear infinite;
  box-shadow: 0 12px 28px rgba(28, 25, 23, 0.1), 0 0 0 3px var(--w-glow-ring) !important;
}

/* 上传进度条：极光填充 + 百分比 */
#tab-learning .lc-progress {
  display: flex !important;
  align-items: center !important;
  gap: 10px;
  margin: 2px 0 14px !important;
}
#tab-learning .lc-progress-track {
  flex: 1;
  height: 8px;
  background: var(--w-well) !important;
  border-radius: 999px !important;
  overflow: hidden;
}
#tab-learning .lc-progress-bar {
  height: 100%;
  width: 0;
  border-radius: 999px;
  background: var(--w-aurora) !important;
  background-size: 200% 100%;
  animation: weaveProgFlow 1.6s linear infinite;
  transition: width 0.2s ease-out;
}
@keyframes weaveProgFlow { to { background-position: 200% 0; } }
#tab-learning .lc-progress-label {
  font-size: 12px;
  color: var(--w-ink-soft) !important;
  min-width: 96px;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* 空状态 */
#tab-learning .lc-empty {
  padding: 18px !important;
  text-align: center;
  color: var(--w-ink-faint) !important;
  background: var(--w-surface) !important;
  border: 1px dashed var(--w-hairline-strong) !important;
  border-radius: 12px !important;
}

/* 成绩榜名次条目 */
#tab-learning details.lc-rank {
  background: var(--w-surface) !important;
  border: 1px solid var(--w-hairline) !important;
  border-radius: 12px !important;
  padding: 10px 14px !important;
  margin-bottom: 10px !important;
  transition: transform var(--w-base) var(--w-spring),
              box-shadow var(--w-base) var(--w-swift),
              background var(--w-fast) ease-out !important;
}
#tab-learning details.lc-rank > summary { list-style: none; cursor: pointer; font-weight: 700; }

/* ── 15. 降级与无障碍 ─────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .weave-enter { animation: none !important; }
  #weaveRailIndicator { transition: none !important; }
  button, [data-task-card], .build-record-card,
  #tab-mine details.mine-req-card, #tab-retest details.retest-req-card {
    transition-duration: 0.01ms !important;
  }
  #tab-learning .lc-topic,
  #tab-learning .lc-panel,
  #tab-learning .lc-row,
  #tab-learning .lc-q,
  #tab-learning details.lc-rank { transition-duration: 0.01ms !important; }
  #tab-learning .lc-topic.active,
  #tab-learning .lc-panel:hover,
  #tab-learning .lc-row:hover,
  #tab-learning .lc-q:hover,
  #tab-learning .lc-q:focus-within,
  #tab-learning details.lc-rank:hover { animation: none !important; }
  #tab-learning .lc-progress-bar { animation: none !important; }
  /* SSE 流光边缘：停用色彩流动，退回静态描边 */
  .sse-glow { animation: none !important; }
  tr.sse-glow-hold { animation: none !important; }
  /* 悬停流光环：保留描边但不旋转 */
  #tab-mine details.mine-req-card:hover::after,
  #tab-retest details.retest-req-card:hover::after,
  .activity-feed-item:hover::after,
  [data-task-card]:hover::after,
  .build-record-card:hover::after { animation: none !important; }
}

/* ── 12. 功能树状图谱 Feature Tree ─────────────────────── */

/* 入口按钮（顶部"功能图谱" / 工作台"全量测试树状图"） */
.ftree-entry-btn {
  border: 1px solid var(--w-hairline-strong) !important;
  background: var(--w-raised) !important;
  color: var(--w-ink) !important;
  border-radius: 10px !important;
  padding: 7px 13px !important;
  font-weight: 600 !important;
  cursor: pointer;
  transition: transform var(--w-fast) var(--w-pop), box-shadow var(--w-base) var(--w-swift) !important;
}
.ftree-entry-btn:hover {
  transform: translateY(-1px);
  box-shadow: 0 6px 18px rgba(109, 108, 245, 0.22) !important;
}
.ftree-entry-btn--test {
  position: relative;
  color: #fff !important;
  border-color: transparent !important;
  background: var(--w-aurora) !important;
  background-size: 200% 100% !important;
  animation: ftree-aurora-pan 6s linear infinite;
}
@keyframes ftree-aurora-pan { to { background-position: 200% 0; } }

/* 整页画布 */
.ftree-section {
  padding: 0 !important;
  overflow: hidden !important;
  position: relative;
}
.ftree-topbar {
  display: flex; align-items: center; gap: 14px;
  padding: 12px 18px;
  border-bottom: 1px solid var(--w-hairline);
  background: var(--w-surface);
}
.ftree-back {
  border: 1px solid var(--w-hairline-strong) !important;
  background: var(--w-raised) !important;
  border-radius: 9px !important; padding: 6px 12px !important;
  color: var(--w-ink-soft) !important; cursor: pointer; font-weight: 600 !important;
}
.ftree-title { display: flex; align-items: center; gap: 9px; font-size: 17px; font-weight: 800; color: var(--w-ink); }
.ftree-title-icon { font-size: 19px; }
.ftree-mode-badge {
  font-size: 12px; font-weight: 700; padding: 3px 10px; border-radius: 999px;
  background: var(--w-accent-soft); color: var(--w-accent); letter-spacing: 0.02em;
}
.ftree-mode-badge--test { color: #fff; background: var(--w-aurora); background-size: 200% 100%; animation: ftree-aurora-pan 6s linear infinite; }
.ftree-toolbar { margin-left: auto; display: flex; align-items: center; gap: 10px; }
.ftree-legend { display: flex; flex-wrap: wrap; gap: 10px; max-width: 46vw; overflow: hidden; }
.ftree-legend-item { display: inline-flex; align-items: center; gap: 5px; font-size: 12.5px; color: var(--w-ink-soft); }
.ftree-legend-dot { width: 10px; height: 10px; border-radius: 50%; box-shadow: 0 0 0 2px rgba(255,255,255,0.85); }
.ftree-legend-empty { font-size: 12.5px; color: var(--w-ink-faint); }

.ftree-canvas {
  width: 100%;
  height: calc(100vh - 150px);
  min-height: 540px;
  /* 中心向外发散：径向辉光底纹强化"中心" */
  background:
    radial-gradient(circle at 50% 48%, rgba(109,108,245,0.10), rgba(109,108,245,0) 42%),
    var(--w-canvas);
}
.ftree-hint {
  position: absolute; left: 18px; bottom: 14px;
  font-size: 12px; color: var(--w-ink-faint);
  background: rgba(255,255,255,0.7); padding: 5px 10px; border-radius: 8px;
  border: 1px solid var(--w-hairline); pointer-events: none;
}

/* ── 工作台子导航吸顶 ─────────────────────────────────────
   滚动越过头部后固定在顶部栏下方，并恢复为紧凑的常驻操作条；
   JS 会用 margin-bottom 补偿压缩的高度差，避免临界点布局反馈抖动。 */
.workbench-shell-header {
  position: sticky;
  top: var(--workbench-header-top, 116px);
  z-index: 1080;
  margin: 0 -8px;
  padding: 6px 8px;
  border-radius: 12px;
  border: 1px solid transparent;
  transition: background var(--w-fast) ease, box-shadow var(--w-fast) ease,
    border-color var(--w-fast) ease;
}
.workbench-shell-header.is-stuck {
  align-items: center;
  background: color-mix(in srgb, var(--w-canvas) 82%, transparent);
  backdrop-filter: saturate(160%) blur(14px);
  -webkit-backdrop-filter: saturate(160%) blur(14px);
  border-color: var(--w-hairline);
  box-shadow: 0 10px 24px rgba(28, 25, 23, 0.07);
}
.workbench-shell-header.is-stuck h2 { font-size: 15px !important; }
.workbench-shell-header.is-stuck .muted { display: none; }
.workbench-shell-header.is-stuck .workbench-subnav { gap: 6px; }
.workbench-shell-header.is-stuck .workbench-subnav button {
  padding: 4px 12px !important;
  font-size: 12.5px !important;
}

/* 复制节点选择态：顶部横幅 + 画布"可选"光标 */
.ftree-copy-banner {
  position: absolute; left: 50%; top: 16px; transform: translateX(-50%);
  z-index: 4001; display: flex; align-items: center; gap: 14px;
  max-width: min(92%, 680px);
  font-size: 13px; color: #fff;
  background: var(--w-aurora); background-size: 200% 100%;
  animation: ftree-aurora-pan 6s linear infinite;
  padding: 9px 14px; border-radius: 999px;
  box-shadow: 0 10px 30px rgba(28,25,23,0.22);
}
.ftree-copy-banner-text { line-height: 1.4; }
.ftree-copy-banner-text b { font-weight: 800; }
.ftree-copy-banner-cancel {
  flex: 0 0 auto; cursor: pointer; white-space: nowrap;
  background: rgba(255,255,255,0.22) !important; color: #fff !important;
  border: 1px solid rgba(255,255,255,0.5) !important;
  border-radius: 999px !important; padding: 5px 12px !important; font-size: 12.5px !important;
  box-shadow: none !important; transition: background var(--w-fast) var(--w-swift) !important;
}
.ftree-copy-banner-cancel:hover { background: rgba(255,255,255,0.34) !important; }
.ftree-copying .ftree-canvas { cursor: copy; }

/* 节点操作浮层 */
.ftree-menu {
  position: fixed; z-index: 4000; min-width: 184px;
  background: var(--w-raised); border: 1px solid var(--w-hairline-strong);
  border-radius: 14px; padding: 7px; box-shadow: 0 16px 44px rgba(28,25,23,0.20);
  animation: ftree-pop var(--w-base) var(--w-spring);
}
@keyframes ftree-pop { from { opacity: 0; transform: scale(0.9) translateY(6px); } to { opacity: 1; transform: none; } }
.ftree-menu-title { font-size: 12px; font-weight: 700; color: var(--w-ink-faint); padding: 5px 10px 7px; border-bottom: 1px solid var(--w-hairline); margin-bottom: 5px; max-width: 240px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ftree-menu-item {
  display: flex; align-items: center; gap: 8px; width: 100%;
  background: transparent !important; border: none !important; cursor: pointer;
  padding: 9px 11px !important; border-radius: 9px !important; font-size: 14px !important;
  color: var(--w-ink) !important; text-align: left;
  transition: background var(--w-fast) var(--w-swift) !important;
}
/* 图标列等宽居中，文字才会左对齐，不受 emoji 宽度差影响 */
.ftree-menu-icon { flex: 0 0 1.5em; width: 1.5em; text-align: center; font-size: 15px; line-height: 1; font-family: "Segoe UI Emoji", "Apple Color Emoji", sans-serif; }
.ftree-menu-label { flex: 1 1 auto; }
.ftree-menu-item:hover { background: var(--w-accent-soft) !important; }
/* 双类选择器优先级高于全局 button.danger，避免被实心红底覆盖文字 */
.ftree-menu-item.danger { color: #dc2626 !important; background: transparent !important; box-shadow: none !important; }
.ftree-menu-item.danger:hover { background: rgba(220,38,38,0.10) !important; color: #dc2626 !important; }
/* 不可点的提示项（含子分支节点的自动汇总说明） */
.ftree-menu-item--hint { color: var(--w-ink-faint) !important; cursor: default !important; font-size: 12.5px !important; opacity: 1 !important; }
.ftree-menu-item--hint:hover { background: transparent !important; }
.ftree-tip-auto { color: var(--w-accent); font-size: 11.5px; margin-left: 4px; }

/* tooltip（备注 / 标记说明气泡，ECharts 注入 body） */
.ftree-tip-name { font-weight: 800; color: var(--w-ink); margin-bottom: 5px; }
.ftree-tip-note { font-size: 13px; color: var(--w-ink-soft); line-height: 1.55; }
.ftree-tip-note img, .ftree-tip-markbody img { max-width: 100%; border-radius: 6px; }
.ftree-tip-mark { margin-top: 7px; font-size: 12.5px; color: var(--w-ink); display: flex; align-items: flex-start; gap: 6px; flex-wrap: wrap; }
.ftree-tip-dot { width: 9px; height: 9px; border-radius: 50%; margin-top: 4px; flex-shrink: 0; }
.ftree-tip-markbody { flex-basis: 100%; margin-top: 3px; color: var(--w-ink-soft); line-height: 1.5; }
.ftree-tip-collapsed { margin-top: 6px; font-size: 12px; color: var(--w-accent); }

/* tooltip 内关联用例列表（可预览 / 跳转 / 删除） */
.ftree-tip-cases { margin-top: 8px; padding-top: 7px; border-top: 1px dashed var(--w-hairline-strong); }
.ftree-tip-cases-head { font-size: 12px; font-weight: 700; color: #0e7490; margin-bottom: 4px; }
.ftree-tip-case { display: flex; align-items: center; gap: 6px; padding: 3px 0; font-size: 12.5px; }
.ftree-tip-case--deleted .ftree-tip-case-title { text-decoration: line-through; color: var(--w-ink-faint); }
.ftree-tip-case-id { font-weight: 700; color: #0e7490; flex-shrink: 0; }
.ftree-tip-case-title { flex: 1; min-width: 0; color: var(--w-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 170px; }
.ftree-tip-case-acts { display: inline-flex; gap: 4px; flex-shrink: 0; }
.ftree-tip-case-acts button {
  border: 1px solid var(--w-hairline-strong) !important; background: var(--w-surface) !important;
  color: var(--w-ink) !important; border-radius: 6px !important; font-size: 11.5px !important;
  line-height: 1 !important; padding: 3px 7px !important; cursor: pointer;
}
.ftree-tip-case-acts button:hover { background: var(--w-accent-soft) !important; }
.ftree-tip-case-acts .ftree-tip-case-del { color: #dc2626 !important; }
.ftree-tip-case-acts .ftree-tip-case-del:hover { background: rgba(220,38,38,0.10) !important; }

/* 关联用例弹窗：搜索框 + 已关联 chips + 结果列表 */
.ftree-case-modal { display: flex; flex-direction: column; max-height: 76vh; }
.ftree-case-search {
  margin: 14px 20px 0; padding: 10px 14px; font-size: 14px;
  border: 1px solid var(--w-hairline-strong) !important; border-radius: 12px !important;
  outline: none; background: #fff; color: var(--w-ink); width: auto !important;
}
.ftree-case-search:focus { border-color: var(--w-accent) !important; box-shadow: 0 0 0 3px var(--primary-ring); }
.ftree-case-linked { padding: 8px 20px 0; display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.ftree-case-linked-head { flex-basis: 100%; font-size: 12px; font-weight: 700; color: var(--w-ink-soft); }
.ftree-case-chip {
  display: inline-flex; align-items: center; gap: 5px; font-size: 12px;
  background: #ecfeff; color: #0e7490; border: 1px solid #a5f3fc;
  border-radius: 999px; padding: 3px 6px 3px 10px; max-width: 260px;
  overflow: hidden; white-space: nowrap;
}
.ftree-case-chip--deleted { text-decoration: line-through; opacity: 0.6; }
.ftree-case-chip-x {
  border: none !important; background: transparent !important; cursor: pointer;
  color: #0e7490 !important; font-size: 11px !important; padding: 1px 3px !important; line-height: 1 !important;
}
.ftree-case-chip-x:hover { color: #dc2626 !important; }
.ftree-case-results { margin: 12px 20px 18px; overflow-y: auto; min-height: 120px; border: 1px solid var(--w-hairline); border-radius: 12px; }
.ftree-case-empty { padding: 26px 0; text-align: center; font-size: 13px; color: var(--w-ink-faint); }
.ftree-case-row { display: flex; align-items: center; gap: 8px; padding: 8px 12px; border-bottom: 1px solid var(--w-hairline); font-size: 13px; }
.ftree-case-row:last-child { border-bottom: none; }
.ftree-case-row:hover { background: var(--w-accent-soft); }
.ftree-case-row-id { font-weight: 700; color: #0e7490; flex-shrink: 0; }
.ftree-case-row-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--w-ink); }
.ftree-case-row-status { font-size: 11.5px; color: var(--w-ink-faint); flex-shrink: 0; }
.ftree-case-row-link {
  flex-shrink: 0; border: 1px solid var(--w-accent) !important; background: var(--w-surface) !important;
  color: var(--w-accent) !important; border-radius: 8px !important; font-size: 12px !important;
  padding: 4px 12px !important; cursor: pointer; line-height: 1 !important;
}
.ftree-case-row-link:hover:not([disabled]) { background: var(--w-accent-soft) !important; }
.ftree-case-row-link[disabled] { border-color: var(--w-hairline-strong) !important; color: var(--w-ink-faint) !important; cursor: default; }

/* 富文本编辑弹窗 */
.ftree-modal-overlay {
  position: fixed; inset: 0; z-index: 4200;
  background: rgba(28,25,23,0.34); backdrop-filter: blur(3px);
  display: flex; align-items: center; justify-content: center;
  animation: ftree-fade var(--w-base) var(--w-swift);
}
@keyframes ftree-fade { from { opacity: 0; } to { opacity: 1; } }
.ftree-modal {
  width: min(640px, 92vw); background: var(--w-raised);
  border-radius: 18px; box-shadow: 0 28px 70px rgba(28,25,23,0.32);
  overflow: hidden; animation: ftree-pop var(--w-base) var(--w-spring);
}
.ftree-modal-head { display: flex; align-items: center; justify-content: space-between; padding: 16px 20px; border-bottom: 1px solid var(--w-hairline); }
.ftree-modal-head h3 { margin: 0 !important; font-size: 16px !important; }
.ftree-modal-close { background: transparent !important; border: none !important; font-size: 18px !important; color: var(--w-ink-faint) !important; cursor: pointer; }
.ftree-editor-toolbar { display: flex; gap: 6px; padding: 10px 20px 0; }
.ftree-editor-toolbar button {
  border: 1px solid var(--w-hairline-strong) !important; background: var(--w-surface) !important;
  border-radius: 8px !important; padding: 5px 11px !important; cursor: pointer; font-size: 13px !important; color: var(--w-ink) !important;
}
.ftree-editor-toolbar button:hover { background: var(--w-accent-soft) !important; }
.ftree-editor {
  margin: 12px 20px; padding: 12px 14px; min-height: 220px; max-height: 50vh; overflow-y: auto;
  border: 1px solid var(--w-hairline-strong); border-radius: 12px; outline: none;
  font-size: 14px; line-height: 1.6; background: #fff; color: var(--w-ink);
}
.ftree-editor:focus { border-color: var(--w-accent); box-shadow: 0 0 0 3px var(--primary-ring); }
.ftree-editor:empty::before { content: attr(data-placeholder); color: var(--w-ink-faint); }
.ftree-editor img { max-width: 100%; border-radius: 6px; }
.ftree-modal-foot { display: flex; justify-content: flex-end; gap: 10px; padding: 0 20px 18px; }

@media (prefers-reduced-motion: reduce) {
  .ftree-menu, .ftree-modal, .ftree-modal-overlay { animation: none !important; }
  .ftree-entry-btn--test, .ftree-mode-badge--test { animation: none !important; }
}


/* ── 用例审查（审查工作台 + 需求工作台联动标签）────────────────────────
   低饱和配色与 Weaveflow 中性色系融合：通过=灰绿、不通过=灰红、待复审=灰琥珀 */
.case-review-box { display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.case-review-tag {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 12px !important; line-height: 1; padding: 3px 8px !important;
  border-radius: 999px !important; white-space: nowrap; cursor: default;
}
.case-review-tag.review-pass {
  background: #e8f0ea !important; color: #3d6b4f !important; border: 1px solid #cfe0d4 !important;
}
.case-review-tag.review-fail {
  background: #f6ebeb !important; color: #9f3f3f !important; border: 1px solid #e7d2d2 !important;
  cursor: pointer;
}
.case-review-tag.review-fail:hover { background: #f0e0e0 !important; }
.case-review-tag.review-pending {
  background: #f4efe4 !important; color: #8a6d3b !important; border: 1px solid #e5dcc6 !important;
  cursor: pointer;
}
.case-review-tag.review-pending:hover { background: #ece5d3 !important; }
.case-review-tag.review-tag-mine { box-shadow: inset 0 0 0 1px rgba(90, 100, 180, .28); }
.case-review-btn {
  border: 1px solid var(--w-hairline-strong, #d8dce4) !important; background: var(--w-surface, #fff) !important;
  color: var(--w-ink, #334155) !important; font-size: 12px !important; line-height: 1;
  padding: 3px 9px !important; border-radius: 999px !important; cursor: pointer;
  transition: background .15s ease, border-color .15s ease;
}
.case-review-btn.review-btn-pass:hover { background: #e8f0ea !important; border-color: #cfe0d4 !important; color: #3d6b4f !important; }
.case-review-btn.review-btn-fail:hover { background: #f6ebeb !important; border-color: #e7d2d2 !important; color: #9f3f3f !important; }
.case-review-btn.review-btn-fix {
  background: #eef0f8 !important; border-color: #d9ddf0 !important; color: #4b5394 !important;
}
.case-review-btn.review-btn-fix:hover { background: #e3e7f5 !important; }
.case-review-history-link { font-size: 12px !important; color: var(--w-ink-faint, #94a3b8) !important; text-decoration: none; }
.case-review-history-link:hover { color: var(--w-accent, #6366f1) !important; }

/* ── 需求测试要点：富文本编辑弹窗（需求/审查）+ 只读展示（复测） ── */
.qa-notes-dialog {
  width: min(760px, 94vw); max-height: 92vh; display: flex; flex-direction: column;
  background: var(--w-surface, #fff); border-radius: 12px;
  box-shadow: 0 12px 28px rgba(0, 0, 0, .18); padding: 18px 18px 14px;
  transition: width .2s ease, height .2s ease;
}
/* 放大模式：接近满屏，方便长文/贴图编辑 */
.qa-notes-dialog.qa-notes-dialog--max { width: 96vw; height: 94vh; max-height: 94vh; }
.qa-notes-maxbtn { padding: 3px 10px !important; font-size: 12px !important; white-space: nowrap; }
.qa-notes-toolbar {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-bottom: 8px;
}
.qa-notes-toolbar button {
  border: 1px solid var(--w-hairline-strong, #d8dce4) !important; background: var(--w-surface, #fff) !important;
  color: var(--w-ink, #334155) !important; font-size: 13px !important; line-height: 1.2;
  padding: 4px 10px !important; border-radius: 8px !important; cursor: pointer;
}
.qa-notes-toolbar button:hover { background: var(--w-accent-soft, #eef0f8) !important; }
.qa-notes-toolbar select {
  border: 1px solid var(--w-hairline-strong, #d8dce4); background: var(--w-surface, #fff);
  color: var(--w-ink, #334155); font-size: 13px; padding: 3px 6px; border-radius: 8px; width: auto;
}
.qa-notes-colorwrap {
  display: inline-flex; align-items: center; gap: 2px; margin: 0; cursor: pointer;
  border: 1px solid var(--w-hairline-strong, #d8dce4); border-radius: 8px; padding: 2px 6px;
  font-size: 13px; font-weight: 700; color: #dc2626; background: var(--w-surface, #fff);
}
.qa-notes-colorwrap input[type="color"] {
  width: 22px; height: 20px; border: none; padding: 0; background: transparent; cursor: pointer;
}
.qa-notes-editor {
  flex: 1 1 auto; min-height: 280px; overflow-y: auto; outline: none;
  border: 1px solid var(--w-hairline-strong, #d8dce4); border-radius: 10px;
  padding: 12px 14px; font-size: 14px; line-height: 1.7; background: var(--w-surface, #fff);
}
.qa-notes-dialog--max .qa-notes-editor { min-height: 0; }
.qa-notes-editor:focus { border-color: var(--w-accent, #6366f1); box-shadow: 0 0 0 3px var(--primary-ring, rgba(99, 102, 241, .18)); }
.qa-notes-editor:empty::before { content: attr(data-placeholder); color: var(--w-ink-faint, #94a3b8); }
.qa-notes-editor { position: relative; }
.qa-notes-editor img {
  max-width: 100%; height: auto; border-radius: 6px; display: block;
  cursor: nwse-resize; user-select: none;
}
.qa-notes-image-resizer {
  position: fixed; z-index: 10020; box-sizing: border-box; pointer-events: none;
  border: 2px solid var(--w-accent, #6366f1); border-radius: 6px;
}
.qa-notes-image-resizer.hidden { display: none !important; }
.qa-notes-image-resize-handle {
  position: absolute; right: -7px; bottom: -7px; width: 12px; height: 12px;
  box-sizing: border-box; border: 2px solid #fff; border-radius: 3px;
  background: var(--w-accent, #6366f1); box-shadow: 0 1px 4px rgba(15, 23, 42, .28);
  cursor: nwse-resize; pointer-events: auto; touch-action: none;
}
.qa-notes-check-item {
  display: flex; align-items: center; gap: 7px; min-height: 24px;
  padding: 0 3px; margin: 0; border-radius: 6px; line-height: 1.55;
}
.qa-notes-check-item:hover { background: var(--w-accent-soft, #eef0f8); }
.qa-notes-check {
  position: static !important; width: 16px !important; height: 16px !important;
  margin: 0 !important; top: auto !important; flex: 0 0 auto;
  accent-color: var(--w-accent, #6366f1);
}
.qa-notes-check-text { min-width: 1em; flex: 1 1 auto; line-height: 1.55; }
.qa-notes-check-item.is-checked .qa-notes-check-text {
  color: var(--w-ink-faint, #94a3b8); text-decoration: line-through;
}
/* 只读富文本块：复测工作台原测试人要点 / 审查台查看 */
.qa-rich-view { font-size: 13px; color: #475569; line-height: 1.7; word-break: break-word; }
.qa-rich-view img { max-width: 100%; max-height: 320px; border-radius: 6px; display: block; margin: 4px 0; }
.qa-rich-view .qa-notes-check-item:hover { background: transparent; }
.qa-rich-view .qa-notes-check:disabled { opacity: 1; cursor: default; }

/* ── 需求 story 关联禅道任务标签（需求/复测工作台标题旁） ── */
.qa-task-chips {
  display: flex; flex-wrap: wrap; align-items: center; gap: 4px;
  margin-top: 6px; min-width: 0; font-weight: normal;
}
.qa-task-chip {
  display: inline-flex; align-items: center; gap: 4px;
  max-width: 300px; min-width: 0; padding: 2px 9px; border-radius: 999px;
  border: 1px solid; font-size: 12px; line-height: 1.5; cursor: pointer;
  transition: filter .15s ease;
}
.qa-task-chip:hover { filter: brightness(.96); }
.qa-task-chip-title {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; flex: 0 1 auto;
}
.qa-task-chip-assignee { white-space: nowrap; opacity: .85; }
.qa-task-chip-status { white-space: nowrap; opacity: .75; }
.qa-task-chip--closed .qa-task-chip-title { text-decoration: line-through; }
.qa-task-chip-more { background: var(--w-surface, #fff); color: var(--w-ink-faint, #64748b); border-color: var(--w-hairline-strong, #d8dce4); }
.qa-task-chips-rest { display: contents; }
