/* ==========================================================================
   漫剧工作台 · 界面样式
   配色取自已登录态 libtv 画布页的真实采样值：
     画布底 #141414 / 顶部芯片 #222222 / Dock 与工具条 #262626
     点阵 #404040（极淡白点）/ 主文字 #f7f7f7 / 强调 #6a5cff / 状态绿 #1cc886
   注意：libtv 的浮层比画布「亮」，且大多数控件不带边框，靠底色对比浮起。
   ========================================================================== */

:root {
  --canvas: #141414;

  --surface: #222222;        /* 顶部悬浮芯片 */
  --surface-2: #262626;      /* Dock、工具条、浮层面板 */
  --surface-hi: #2f2f2f;     /* hover */
  --surface-sunken: #1c1c1c; /* 节点内的下沉区域 */
  --surface-input: #1a1a1a;

  --line: rgba(var(--tint), 0.08);
  --line-hi: rgba(var(--tint), 0.16);

  --text: #f7f7f7;
  --text-2: #a8a8a8;
  --dim: #7a7a7a;

  --accent: #6a5cff;
  --accent-soft: rgba(106, 92, 255, 0.18);
  --ok: #1cc886;
  --warn: #ffb84d;
  --err: #ff6b7f;

  --r-sm: 8px;
  --r: 10px;
  --r-lg: 14px;

  --blur: saturate(130%) blur(16px);
  --shadow: 0 8px 28px rgba(0, 0, 0, 0.5);
  --shadow-lg: 0 18px 56px rgba(0, 0, 0, 0.62);

  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
  --ui: -apple-system, BlinkMacSystemFont, "system-ui", "PingFang SC", Inter, "Noto Sans SC", "Microsoft YaHei", sans-serif;

  /* 叠加色：所有「在底色上轻轻盖一层」的地方（hover、分隔线、点阵、高光）都走它。
     深色主题叠白，亮色主题叠黑 —— 全站 116 处 rgba(var(--tint), x) 共用这一个开关，
     不用为两套主题各写一遍规则。 */
  --tint: 255, 255, 255;
  --on-accent: #141414;      /* 彩色块上的图标色（亮色主题下仍是深色） */
  --tooltip-bg: #2e2e2e;     /* 悬浮提示底色：两套主题都偏深，保证可读 */
  --tooltip-fg: #ededed;
  --overlay: rgba(0,0,0,.68);
  --media-bg: #1a1a1f;
  --port-bg: #171717;
  --invert-bg: #bebebe;
  --invert-bg-hover: #d6d6d6;
  --invert-fg: #262626;
  color-scheme: dark;
}

/* ==========================================================================
   日间主题（偏白的纸面感，不是刺眼的纯白）
   只覆盖变量 —— 结构、尺寸、动效一律不动，避免两套主题各自漂移。
   ========================================================================== */
[data-theme="light"] {
  --canvas: #f5f5f3;
  --surface: #ffffff;
  --surface-2: #fbfbfa;
  --surface-hi: #efefec;
  --surface-sunken: #f4f4f1;
  --surface-input: #ffffff;

  --line: rgba(0, 0, 0, 0.09);
  --line-hi: rgba(0, 0, 0, 0.16);

  --text: #17201c;
  --text-2: #5a5f5c;
  --dim: #8b918d;

  --accent: #2f5ae8;
  --accent-soft: rgba(47, 90, 232, 0.10);
  --ok: #0d9c6c;
  --warn: #c47a12;
  --err: #d92f45;

  --tint: 0, 0, 0;
  --on-accent: #141414;
  --tooltip-bg: #2b2f2d;
  --tooltip-fg: #f2f2f0;

  --blur: saturate(120%) blur(16px);
  --shadow: 0 6px 22px rgba(23, 32, 28, 0.09), 0 1px 3px rgba(23, 32, 28, 0.06);
  --shadow-lg: 0 16px 48px rgba(23, 32, 28, 0.14), 0 2px 8px rgba(23, 32, 28, 0.06);
  --overlay: rgba(23,32,28,.34);
  --media-bg: #ecece9;
  --port-bg: #ffffff;
  --invert-bg: #2b2f2d;
  --invert-bg-hover: #3d4340;
  --invert-fg: #f7f7f5;
  color-scheme: light;
}

* { box-sizing: border-box; }

/* hidden 属性必须真的隐藏。浏览器默认的 [hidden]{display:none} 优先级极低，
   下面一条 `.user-drop button{display:flex}` 就能把它盖掉 —— 结果是
   管理员的「管理后台 / AI 后端设置」明明设了 hidden，普通用户照样看得见、点得进去。 */
[hidden] { display: none !important; }

html, body {
  margin: 0; height: 100%;
  background: var(--canvas);
  color: var(--text);
  font: 13px/1.5 var(--ui);
  overflow: hidden;
  -webkit-font-smoothing: antialiased;
}

button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; }

.ico {
  width: 16px; height: 16px;
  fill: none; stroke: currentColor;
  stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round;
  flex-shrink: 0;
}

::-webkit-scrollbar { width: 9px; height: 9px; }
::-webkit-scrollbar-thumb {
  background: rgba(var(--tint),.12); border-radius: 6px;
  border: 2px solid transparent; background-clip: padding-box;
}
::-webkit-scrollbar-thumb:hover { background: rgba(var(--tint),.2); background-clip: padding-box; }
::-webkit-scrollbar-track { background: transparent; }

/* ------------------------------ 启动遮罩 ------------------------------ */
#boot { position: fixed; inset: 0; z-index: 999; background: var(--canvas); display: grid; place-items: center; }
.boot-inner { text-align: center; color: var(--dim); }
.boot-logo {
  width: 58px; height: 58px; margin: 0 auto 15px; border-radius: 17px;
  background: linear-gradient(135deg, #3f6dff, #7b4dff);
  display: grid; place-items: center;
  box-shadow: 0 14px 44px rgba(106,92,255,.36);
}
/* 图形标是透明底白线的 SVG，压在渐变底上；比原来的「漫」字更轻，所以放大到 34px */
.boot-logo img { width: 34px; height: 34px; display: block; }

/* -------------------------------- 画布 -------------------------------- */
.viewport {
  position: fixed; inset: 0;
  overflow: hidden;
  cursor: default;
  background-color: var(--canvas);
  /* 两层极淡白点，对应 libtv 的 --dot-color / --dot-color-bright */
  background-image:
    radial-gradient(circle, rgba(var(--tint),.10) 1px, transparent 1px),
    radial-gradient(circle, rgba(var(--tint),.16) 1px, transparent 1px);
  background-repeat: repeat, repeat;
}
.viewport.panning, .viewport.space-mode { cursor: grab; }
.viewport.panning { cursor: grabbing; }
/* ⚠️ 这里**不要**加 will-change: transform / translateZ(0)。
   给 .world 提升成合成层后，缩到 40% 以下节点卡片的底色会整片不绘制
   （连线还在，卡片消失，鼠标划过才补画几块）—— 图层太大（节点铺到 y≈15000px），
   Chrome 的栅格化放弃了一部分瓦片。实测在 31% 下必现，且换成
   `will-change: auto` 也不一定能把已提升的层收回去。
   流畅度改由 canvas.js 的 rAF 合帧（#queueZoom / #queuePan）+ 视图变化不重绘保证。 */
.world { position: absolute; left: 0; top: 0; transform-origin: 0 0; }
.world.linking { cursor: crosshair; }
.edges { position: absolute; left: 0; top: 0; width: 1px; height: 1px; overflow: visible; pointer-events: none; }
.edges path.edge { pointer-events: stroke; }
/* 「隐藏节点连线」开关（照 libtv 左下） */
.viewport.hide-edges .edges { opacity: 0; pointer-events: none; }

/* ------------------------------ 空状态提示 ------------------------------ */
.canvas-hint {
  position: fixed; left: 50%; top: 36%;
  transform: translate(-50%, -50%);
  display: flex; align-items: center; gap: 9px;
  color: var(--dim); font-size: 13px;
  pointer-events: none;
  transition: opacity .4s;
}
.canvas-hint .ico { width: 15px; height: 15px; }
/* 空画布上留一个通往「3 分钟出一条」的口子：走到这儿的人多半是不知道自己该搭什么 */
.canvas-hint .ch-link {
  pointer-events: auto; color: #8ea9ff; text-decoration: none;
  border-bottom: 1px dashed rgba(142, 169, 255, .45); padding-bottom: 1px;
}
.canvas-hint .ch-link:hover { color: #b6c6ff; border-bottom-color: #b6c6ff; }
.canvas-hint[hidden] { display: none; }

.mode-tip {
  position: fixed; left: 50%; top: 44px;
  transform: translateX(-50%);
  background: var(--surface-2); backdrop-filter: var(--blur);
  border: 1px solid var(--line);
  padding: 6px 14px; border-radius: 999px;
  font-size: 11.5px; color: var(--text-2);
  opacity: 0; transition: opacity .2s; pointer-events: none;
}
.mode-tip.on { opacity: 1; }

/* ------------------------------ 顶部悬浮栏 ------------------------------ */
.topbar {
  position: fixed; left: 0; right: 0; top: 0;
  height: 34px;
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 10px;
  pointer-events: none;
  z-index: 40;
}
.topbar > * { pointer-events: auto; }
.tb-left, .tb-right, .tb-center { display: flex; align-items: center; gap: 5px; }

/* 统一控件尺寸，避免各控件比例失控。
   尺寸沿革：30 → 18（当时浏览器开着 175% 缩放，看着偏大）→ 30 / 40。
   用户把浏览器缩放归零（⌘0）后反馈「太小」——
   而 100% 缩放下的正确基准就是 libtv 实测值：顶栏芯片 30px。
   底栏延续「比顶栏大」的偏好：40 = 30 × 1.33。
   --ctl    顶栏及其所有胶囊（项目芯片 / 图标钮 / 同步 / 引擎 / 计次）
   --ctl-b  底栏专用（资产胶囊 / 缩放胶囊 / Agent 球） */
:root { --ctl: 30px; --ctl-b: 40px; }

.ws-chip {
  display: flex; align-items: center; gap: 7px;
  height: var(--ctl); padding: 0 10px 0 3px;
  background: var(--surface);
  border: none;
  border-radius: 999px;
  transition: .15s;
}
.ws-chip:hover { background: var(--surface-hi); }
.ws-logo {
  width: 22px; height: 22px; border-radius: 7px;
  background: linear-gradient(135deg, #6a5cff, #a78bfa);
  display: grid; place-items: center;
  font-size: 12px; font-weight: 700; color: #fff; flex-shrink: 0;
}
.ws-text { display: flex; flex-direction: column; line-height: 1; align-items: flex-start; }
.ws-name { font-size: 11.5px; font-weight: 600; }
.ws-sub { font-size: 9px; color: var(--dim); }
.ws-chip .chev { width: 11px; height: 11px; color: var(--dim); }

/* 顶栏中间的「换个梗」：只在三镜骨架工程里出现，其它工程这里是空的 */
.tb-center { display: flex; align-items: center; }
.tb-chip {
  display: flex; align-items: center; gap: 6px;
  height: var(--ctl); padding: 0 11px;
  background: var(--surface); border: none; border-radius: 999px;
  color: var(--text-2); font-size: 11.5px; white-space: nowrap;
  transition: .15s;
}
.tb-chip:hover { background: var(--surface-hi); color: var(--text); }
.tb-chip .ico { width: 13px; height: 13px; }
.tb-chip .chev { width: 11px; height: 11px; color: var(--dim); }
.tb-chip .tc-now { color: var(--text); font-weight: 600; }

/* 换梗菜单：一条两行（梗名 + 一句人话），当前那条打标 */
.concept-menu { padding: 6px; }
.cm-head { display: flex; align-items: baseline; gap: 8px; padding: 6px 9px 8px; font-size: 12px; color: var(--text); }
.cm-head span { font-size: 10.5px; color: var(--dim); }
.cm-list { display: flex; flex-direction: column; gap: 1px; max-height: 388px; overflow: auto; }
.cm-item {
  display: flex; gap: 10px; align-items: flex-start;
  width: 100%; text-align: left; padding: 8px 9px;
  background: none; border: none; border-radius: 8px; color: var(--text-2);
}
.cm-item:hover:not(:disabled) { background: rgba(var(--tint), .07); }
.cm-item.on { background: rgba(106, 92, 255, .1); }
.cm-item:disabled { cursor: default; }
.cm-ico {
  width: 24px; height: 24px; flex: none; border-radius: 7px;
  display: grid; place-items: center; font-size: 13px;
  background: rgba(var(--tint), .07); color: var(--text);
}
.cm-txt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.cm-txt b { font-size: 12.5px; font-weight: 600; color: var(--text); display: flex; align-items: center; gap: 6px; }
.cm-txt em { font-style: normal; font-size: 11px; color: var(--dim); line-height: 1.45; }
.cm-txt i {
  font-style: normal; font-size: 9.5px; font-weight: 400; color: #8ea9ff;
  border: 1px solid rgba(106, 92, 255, .35); border-radius: 4px; padding: 0 4px; line-height: 1.5;
}
.cm-foot { padding: 7px 9px 4px; margin-top: 4px; font-size: 10.5px; color: var(--dim); border-top: 1px solid rgba(var(--tint), .07); }
.cm-confirm { padding: 12px 10px 10px; }
.cm-confirm b { font-size: 12.5px; }
.cm-confirm p { font-size: 11.5px; color: var(--text-2); margin: 7px 0 12px; line-height: 1.6; }
.cm-acts { display: flex; gap: 8px; justify-content: flex-end; }
.cm-acts button { border: none; border-radius: 8px; padding: 7px 14px; font-size: 12px; cursor: pointer; background: rgba(var(--tint), .08); color: var(--text-2); }
.cm-acts .cm-ok { background: var(--accent); color: #fff; }
.cm-acts button:hover { filter: brightness(1.12); }

/* 项目芯片的下拉菜单（照 libtv：回到主页 / 全部项目 / 创建新项目 / 删除项目）
   菜单挂在 .tb-left 上，所以它要 relative；菜单本身脱离 flex 流，不参与排布。 */
.tb-left { position: relative; }
.ws-menu {
  position: absolute; top: calc(100% + 7px); left: 0;
  min-width: 118px; padding: 5px;
  background: var(--surface-2);
  border: 1px solid rgba(var(--tint),.08);
  border-radius: 10px;
  box-shadow: var(--shadow-lg);
  display: flex; flex-direction: column; gap: 1px;
  z-index: 60;
}
.ws-menu[hidden] { display: none; }
.ws-menu button {
  border: none; background: none; text-align: left;
  padding: 7px 10px; border-radius: 7px;
  font-size: 12.5px; color: var(--text-2); white-space: nowrap;
}
.ws-menu button:hover { background: rgba(var(--tint),.09); color: var(--text); }
.ws-menu button.danger:hover { background: rgba(255,107,127,.18); color: #ff9aa8; }

.icon-btn {
  width: var(--ctl); height: var(--ctl);
  display: grid; place-items: center;
  background: var(--surface);
  border: none;
  border-radius: 9px;
  color: var(--text);
  transition: .15s;
  position: relative;
  flex-shrink: 0;
}
.icon-btn:hover { background: var(--surface-hi); }
.icon-btn .ico { width: 14px; height: 14px; }
.icon-btn.sm { width: 24px; height: 24px; border-radius: 7px; }
.icon-btn.sm .ico { width: 13px; height: 13px; }
.icon-btn.active { color: #fff; background: var(--accent); }

.sync {
  display: inline-flex; align-items: center; gap: 5px;
  height: var(--ctl); padding: 0 10px;
  background: var(--surface);
  border: none; border-radius: 999px;
  font-size: 11px; color: var(--text-2);
  white-space: nowrap;
}
.sync i { width: 6px; height: 6px; border-radius: 50%; background: var(--ok); }
.sync.dirty i { background: var(--warn); }

.credit-wrap { position: relative; display: inline-flex; }
.credit-wrap[hidden] { display: none; }

.credit-pill {
  display: inline-flex; align-items: center; gap: 5px;
  height: var(--ctl); padding: 0 10px;
  background: var(--surface);
  border: none; border-radius: 999px;
  font-size: 11px; color: var(--text-2);
  font-variant-numeric: tabular-nums;
  cursor: pointer;
}
.credit-pill:hover { background: var(--surface-hi); color: var(--text); }
.credit-pill .ico { width: 11px; height: 11px; color: var(--warn); }

/* 积分浮层：位置对齐顶栏右侧，别超出窗口 */
.credit-pop {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 120;
  width: 246px; padding: 12px;
  background: var(--surface-2); border: 1px solid var(--line-hi);
  border-radius: var(--r-lg); box-shadow: var(--shadow-lg);
  backdrop-filter: var(--blur);
}
.credit-pop[hidden] { display: none; }
.cp-head { display: flex; align-items: baseline; gap: 6px; }
.cp-head b { font-size: 17px; font-weight: 600; color: var(--text); font-variant-numeric: tabular-nums; }
.cp-daily { margin-top: 3px; font-size: 11px; color: var(--dim); }
.cp-daily b { color: var(--ok); font-weight: 600; }
.cp-rows { margin: 10px 0 8px; padding-top: 8px; border-top: 1px solid var(--line); }
.cp-row {
  display: grid; grid-template-columns: 34px 1fr auto; gap: 8px;
  align-items: center; padding: 4px 0; font-size: 11.5px; color: var(--text-2);
}
.cp-row .cp-t { color: var(--dim); font-family: var(--mono); font-size: 10.5px; }
.cp-row .cp-l { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cp-row .cp-d { font-variant-numeric: tabular-nums; font-family: var(--mono); }
.cp-row .cp-d.up { color: var(--ok); }
.cp-row .cp-d.down { color: var(--text-2); }
.cp-empty { padding: 6px 0; font-size: 11.5px; color: var(--dim); }
.cp-foot {
  display: flex; flex-direction: column; gap: 3px;
  padding-top: 8px; border-top: 1px solid var(--line);
  font-size: 10.5px; color: var(--dim);
}
.cp-foot b { color: var(--text-2); font-variant-numeric: tabular-nums; }
.cp-hint { color: var(--dim); }

.tb-center { flex: 1; justify-content: center; min-width: 0; }

/* --------------------------- AI 引擎状态芯片 --------------------------- */
.engine-chip {
  display: inline-flex; align-items: center; gap: 6px;
  height: var(--ctl); padding: 0 12px;
  background: var(--surface);
  border: none; border-radius: 999px;
  color: var(--text-2); font-size: 12px;
  transition: .15s;
  max-width: min(360px, 42vw);
}
.engine-chip:hover { background: var(--surface-hi); }
.engine-dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--ok); flex-shrink: 0;
}
.engine-dot.busy { background: var(--warn); animation: pulse 1.4s ease-in-out infinite; }
.engine-dot.off { background: var(--dim); }
@keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: .35; } }
.engine-name { color: var(--text); font-weight: 600; white-space: nowrap; }
.engine-detail { color: var(--dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.engine-detail.hot { color: var(--warn); }

/* ══════════════════════ 底部三段式（flex 排布，永不重叠） ══════════════════════ */
.bottombar {
  position: fixed; left: 0; right: 0; bottom: 14px;
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; padding: 0 12px;
  pointer-events: none; z-index: 40;
}
.bottombar > * { pointer-events: auto; }
.bb-left, .bb-right { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }

.dock {
  flex: 1 1 auto; min-width: 0;
  display: flex; align-items: center; justify-content: center; gap: 7px;
  overflow: hidden;
  transition: transform .22s cubic-bezier(.2, .8, .3, 1);
}
/* 空画布时（照 libtv）：提示语在 ~45.5%，创作 Dock 抬到 ~53.4%，与提示语相邻。
   用 transform 只改视觉位置、不动布局，所以不会挤到左右两簇。 */
.bottombar.is-empty .dock { transform: translateY(calc(34px - 47vh)); }
.dock-item {
  display: flex; align-items: center; gap: 8px;
  height: 40px; padding: 0 12px 0 7px;
  background: var(--surface-2);
  border: none;
  border-radius: 12px;
  color: var(--text-2);
  font-size: 13px;
  transition: .16s;
  white-space: nowrap;
  flex-shrink: 0;
}
.dock-item:hover {
  background: var(--surface-hi); color: var(--text);
  transform: translateY(-3px);
  box-shadow: var(--shadow);
}
.dock-item .dock-ico {
  width: 26px; height: 26px; border-radius: 7px;
  background: rgba(var(--tint),.07);
  display: grid; place-items: center;
  color: var(--nc, var(--text-2));
  flex-shrink: 0;
}
.dock-item .dock-ico .ico { width: 14px; height: 14px; }
.dock-item:hover .dock-ico { background: var(--nc); color: var(--on-accent); }
.dock-item.assets .dock-ico { color: var(--text-2); }
.dock-sep { width: 1px; height: 22px; background: rgba(var(--tint),.1); margin: 0 2px; flex-shrink: 0; }

/* --------------------------- 左下 · 资产与视图 --------------------------- */
.pill-btn {
  display: flex; align-items: center; gap: 7px;
  height: var(--ctl-b); padding: 0 13px 0 10px;
  background: var(--surface-2);
  border: none; border-radius: 999px;
  color: var(--text-2); font-size: 12.5px;
  transition: .15s;
  white-space: nowrap;
}
.pill-btn:hover { background: var(--surface-hi); color: var(--text); }
.pill-btn .ico { width: 13px; height: 13px; }

/* 画布工具：隐藏连线 / 网格吸附（对齐 libtv 左下的两个开关） */
.canvas-tool {
  width: var(--ctl-b); height: var(--ctl-b);
  display: grid; place-items: center;
  background: var(--surface-2);
  border: none; border-radius: 999px;
  color: var(--text-2);
  transition: .15s;
  flex-shrink: 0;
}
.canvas-tool:hover { background: var(--surface-hi); color: var(--text); }
.canvas-tool.on { background: var(--accent); color: #fff; }
.canvas-tool .ico { width: 17px; height: 17px; }

.view-cluster {
  display: flex; align-items: center;
  background: var(--surface-2);
  border: none; border-radius: 999px;
  height: var(--ctl-b); padding: 0 5px;
}
.view-cluster .icon-btn {
  background: transparent; border: none;
  width: 26px; height: 26px; border-radius: 7px;
}
.view-cluster .icon-btn .ico { width: 14px; height: 14px; }
.view-cluster .icon-btn:hover { background: rgba(var(--tint),.1); }
.zoom-readout {
  display: flex; align-items: center; gap: 5px;
  background: transparent; border: none;
  color: var(--text-2); font-size: 12px;
  padding: 0 9px; height: 26px; border-radius: 7px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.zoom-readout:hover { background: rgba(var(--tint),.09); color: var(--text); }

/* --------------------------- 右下 · 工具集合与 Agent ---------------------------
   照 libtv 实测重做：一枚圆角胶囊，左组 5 枚图标 + 竖分隔线 + 右组 4 枚。
   胶囊 294×46.5、按钮 31×31、间距 9、圆角 14、底色 #262626；
   首枚「添加节点」是浅灰底 (#bebebe) + 深色加号的主按钮，其余图标为白色描边。 */
.tool-strip {
  display: flex; align-items: center; gap: 9px;
  background: var(--surface-2);
  border: none; border-radius: 14px;
  padding: 8px;
  /* 胶囊绝不压缩：要让空间就让给中间的 Dock，否则图标会被挤变形 */
  flex: 0 0 auto;
}
.tool-strip .icon-btn {
  background: transparent; border: none;
  width: 31px; height: 31px; border-radius: 9px;
}
.tool-strip .icon-btn .ico { width: 18px; height: 18px; }
.tool-strip .icon-btn:hover { background: rgba(var(--tint),.1); }

/* 主按钮：添加节点 */
.tool-strip .icon-btn.primary {
  background: var(--invert-bg); color: var(--invert-fg);
}
.tool-strip .icon-btn.primary:hover { background: var(--invert-bg-hover); }
.tool-strip .icon-btn.primary .ico { stroke-width: 2; }

/* 分组竖分隔线 */
.strip-sep {
  width: 1px; height: 20px; flex: 0 0 1px;
  background: rgba(var(--tint),.16);
  margin: 0 1px;
}

/* 悬停气泡提示 —— 取代浏览器原生 title
   原生 tooltip 有约 1 秒延迟且样式不可控，用户明确反馈「要等好一会」。
   用法：data-tip="说明" aria-label="说明"（后者给屏幕阅读器，因为图标按钮没有文字）。
   不带位移动画、过渡 0.08s，做到「鼠标一放上去就出来」。 */
[data-tip] { position: relative; }
[data-tip]::after,
[data-tip]::before {
  position: absolute; left: 50%; pointer-events: none;
  opacity: 0; z-index: 70;
  transition: opacity .08s;
  transform: translateX(-50%);
  white-space: nowrap;
}
[data-tip]::after {
  content: attr(data-tip);
  bottom: calc(100% + 10px);
  background: var(--tooltip-bg); color: var(--tooltip-fg);
  font-size: 12px; line-height: 1; font-weight: 400;
  padding: 7px 11px; border-radius: 7px;
  box-shadow: 0 6px 16px rgba(0,0,0,.5);
}
[data-tip]::before {
  content: ''; bottom: calc(100% + 5px);
  border: 5px solid transparent; border-top-color: var(--tooltip-bg);
}
[data-tip]:hover::after,
[data-tip]:hover::before { opacity: 1; }

/* 贴边的控件：气泡改为贴边对齐，避免在窄窗口下超出视口被裁 */
.tb-left > :first-child[data-tip]::after,
.bb-left > :first-child[data-tip]::after { left: 0; transform: none; }
.tb-left > :first-child[data-tip]::before,
.bb-left > :first-child[data-tip]::before { left: 14px; transform: none; }
.tb-right > :last-child[data-tip]::after,
.tool-strip > .icon-btn:last-child[data-tip]::after,
.bb-right > :last-child[data-tip]::after { left: auto; right: 0; transform: none; }
.tb-right > :last-child[data-tip]::before,
.tool-strip > .icon-btn:last-child[data-tip]::before,
.bb-right > :last-child[data-tip]::before { left: auto; right: 14px; transform: none; }

/* Agent 面板带 overflow:hidden，右下角发送键的气泡改为右对齐，避免被面板边缘裁掉 */
.agent-input [data-tip]::after { left: auto; right: 0; transform: none; }
.agent-input [data-tip]::before { left: auto; right: 12px; transform: none; }

/* 顶栏控件的气泡朝下，否则会被视口顶部切掉 */
.topbar [data-tip]::after { bottom: auto; top: calc(100% + 10px); }
.topbar [data-tip]::before {
  bottom: auto; top: calc(100% + 5px);
  border-top-color: transparent; border-bottom-color: var(--tooltip-bg);
}

.dot-badge {
  position: absolute; top: -3px; right: -3px;
  min-width: 14px; height: 14px; padding: 0 4px;
  background: var(--accent); color: #fff;
  border-radius: 7px; font-size: 9px; line-height: 14px;
  text-align: center; display: none;
  box-shadow: 0 0 0 1px var(--surface-2);
}

.agent-orb {
  display: flex; align-items: center; gap: 8px;
  height: 40px; padding: 0 14px 0 5px;
  background: var(--surface-2);
  border: none; border-radius: 999px;
  color: var(--text); font-size: 13px; font-weight: 500;
  transition: .16s;
  white-space: nowrap;
}
.agent-orb:hover { background: var(--surface-hi); box-shadow: var(--shadow); }
.orb {
  width: 28px; height: 28px; border-radius: 50%;
  background: conic-gradient(from 210deg, #6a5cff, #a78bfa, #f472b6, #6a5cff);
  position: relative; flex-shrink: 0;
}
.orb::after {
  content: ''; position: absolute; inset: 4.5px; border-radius: 50%;
  background: var(--surface-2);
}
.orb.sm { width: 26px; height: 26px; }
.orb.sm::after { inset: 4px; background: var(--surface-2); }

/* ═════════════════════ 节点（结构对齐 libtv：标题在外 + 大卡片 + 输入条） ═════════════════════
   libtv 100% 缩放下：媒体卡 620px 宽 / 16:9（~348px 高），下方输入条同宽 ~170px 高。
   标题在卡片外面上方，端口贴在卡片左右边缘中点。数值来自截图像素测量。 */
.node { position: absolute; user-select: none; }

/* 打组：把一批节点框起来。框本身不吃指针事件（只有标签可点），
   否则会挡住画布的框选和「点空白取消选择」。插在所有节点之前，自然压在节点底下。 */
.group-box {
  position: absolute;
  border: 1px dashed rgba(var(--tint),.16);
  border-radius: 16px;
  background: rgba(var(--tint),.015);
  pointer-events: none;
  transition: border-color .15s, background .15s;
}
.group-box.is-selected { border-color: rgba(106,92,255,.5); background: rgba(106,92,255,.05); }
.gb-label {
  position: absolute; left: 10px; top: -12px;
  display: inline-flex; align-items: center;
  height: 22px; padding: 0 9px;
  background: var(--surface-2);
  border: 1px solid rgba(var(--tint),.1);
  border-radius: 7px;
  font-size: 11.5px; color: var(--text-2);
  white-space: nowrap; pointer-events: auto; cursor: pointer;
  transition: .15s;
}
.gb-label:hover { background: var(--surface-hi); color: var(--text); }
.group-box.is-selected .gb-label { border-color: rgba(106,92,255,.55); color: var(--text); }

/* 标题：卡片外、上方 */
.node-title {
  display: flex; align-items: center; gap: 7px;
  padding: 0 3px 8px;
  font-size: 12px; color: var(--text-2);
  cursor: move;
}
.node-title .nt-ico { display: grid; place-items: center; color: var(--nc); flex-shrink: 0; }
.node-title .nt-ico .ico { width: 13px; height: 13px; stroke-width: 1.9; }
.node-title .nt-text { flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.node-title .nt-actions { display: flex; gap: 1px; opacity: 0; transition: .15s; }
.node:hover .node-title .nt-actions { opacity: 1; }
/* 属性按钮是图标，和旁边两个字符按钮对齐：统一盒子、缩到 12px */
.nt-actions .mini { display: grid; place-items: center; min-width: 20px; }
.nt-actions .mini .ico { width: 13px; height: 13px; stroke-width: 2; }

/* 主卡片
   立体的做法是「光影分级」，不是位移（位移会让端口和连线端点错位）：
     未选中 = 贴地，一道短而实的影；
     悬停   = 略微抬起；
     选中   = 明显抬起：接触影 + 中层 + 远景扩散三层递进，
             再叠蓝色光环，和顶部受光高光 / 底部厚度暗边的内描边。
   同时卡片底色提亮一档（靠近光源更亮），强化浮起来的错觉。 */
.node-card {
  position: relative;
  background: var(--surface);
  border: 1px solid rgba(var(--tint),.07);
  border-radius: 14px;
  box-shadow: 0 8px 20px rgba(0,0,0,.42);
  transition: border-color .15s, box-shadow .18s, background .18s;
}
.node:hover .node-card {
  border-color: rgba(var(--tint),.15);
  box-shadow: 0 12px 28px rgba(0,0,0,.5);
}
.node.selected .node-card {
  border-color: var(--accent);
  background: var(--surface-2);
  box-shadow:
    0 0 0 1.5px var(--accent),           /* 蓝色描边 */
    0 0 0 7px rgba(106,92,255,.10),       /* 蓝色光环，向外晕开 */
    inset 0 1px 0 rgba(var(--tint),.10), /* 顶部受光高光 */
    inset 0 -1px 0 rgba(0,0,0,.55),      /* 底部厚度暗边 */
    0 2px 4px rgba(0,0,0,.5),            /* 接触影：贴着卡片边缘，决定「离地高度」 */
    0 14px 30px rgba(0,0,0,.55),         /* 中层 */
    0 38px 76px rgba(0,0,0,.78);         /* 远景扩散：拉出体积感 */
}
/* 选中的节点标题也跟着提亮一档，和卡片「浮起来」保持一致 */
.node.selected .node-title { color: var(--text); }
/* 拖着整组走的时候再抬高一档，手感上「拿起来了」 */
.node.dragging .node-card { box-shadow: inset 0 1px 0 rgba(var(--tint),.1), inset 0 -1px 0 rgba(0,0,0,.55), 0 4px 8px rgba(0,0,0,.55), 0 20px 40px rgba(0,0,0,.6), 0 52px 96px rgba(0,0,0,.85), 0 0 0 1.5px var(--accent), 0 0 0 7px rgba(106,92,255,.12); }
.node-card.is-collapsed { padding: 0; }

/* 媒体预览区（16:9，占卡片主体） */
.node-media {
  position: relative;
  aspect-ratio: 16 / 9;
  border-radius: 13px;
  overflow: hidden;
  background: var(--media-bg);
  display: grid; place-items: center;
}
.node-media img, .node-media video { width: 100%; height: 100%; object-fit: cover; display: block; }
.node-media.is-audio { aspect-ratio: auto; height: 168px; }
.node-media.is-audio audio { width: 82%; }
.node-media.is-frames { aspect-ratio: auto; min-height: 180px; padding: 12px; }
.frame-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 7px; width: 100%; }
.frame-grid img { aspect-ratio: 16/9; object-fit: cover; border-radius: 7px; display: block; }
.media-ph { display: flex; flex-direction: column; align-items: center; gap: 10px; }
.media-ph > .ico { width: 42px; height: 42px; stroke-width: 1.3; color: #41414a; }
.media-hint { font-size: 12px; color: var(--dim); }

/* 生成失败：原因留在卡上，就地重试 */
.media-err {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 8px; padding: 14px 18px; text-align: center;
}
.me-badge {
  width: 26px; height: 26px; border-radius: 50%;
  display: grid; place-items: center; font-size: 14px; font-weight: 700;
  color: var(--err); background: rgba(255, 107, 127, .14); border: 1px solid rgba(255, 107, 127, .34);
}
.media-err b { font-size: 12.5px; color: var(--text); }
.me-msg { font-size: 11px; color: var(--text-2); line-height: 1.55; max-width: 88%; }
.media-err .try-item { margin-top: 2px; background: rgba(var(--tint), .07); }

/* 空态左侧的「尝试：」建议（照 libtv 节点卡片里的「尝试：图生图 / 图片高清」） */
.media-try {
  position: absolute; left: 2px; top: 50%; transform: translateY(-50%);
  display: flex; flex-direction: column; align-items: flex-start;
}
.media-try-h { font-size: 11px; color: var(--dim); padding: 0 9px 5px; }
.try-item {
  display: flex; align-items: center; gap: 7px;
  background: none; border: none; border-radius: 7px;
  color: var(--text-2); font-size: 11.5px;
  padding: 5px 9px; text-align: left; white-space: nowrap;
  transition: .13s;
}
.try-item:hover { background: rgba(var(--tint),.08); color: var(--text); }
.try-item .try-ico { display: grid; place-items: center; color: var(--dim); }
.try-item:hover .try-ico { color: var(--nc); }
.try-item .try-ico .ico { width: 12px; height: 12px; stroke-width: 1.8; }

/* 表单区（资产类节点，两列） */
.node-fields { padding: 16px 18px; display: grid; grid-template-columns: 1fr 1fr; gap: 12px 16px; }

/* ---- 资产卡（角色/道具/场景）：图为主体，字段悬停展开 ----
   以前这些卡是「一堆表单 + 角落小缩略图」，看不出长什么样；
   现在图铺满上半部分，下面一行名字/身份，鼠标移上去把字段抽出来。 */
.node-card.has-hero { padding: 0; overflow: hidden; }
.asset-hero { width: 100%; aspect-ratio: 16 / 10; background: rgba(var(--tint), .05); overflow: hidden; }
.asset-hero img { width: 100%; height: 100%; object-fit: cover; display: block; }
.asset-sum {
  display: flex; flex-direction: column; gap: 1px;
  padding: 7px 10px 8px; border-top: 1px solid rgba(var(--tint), .06);
}
.asset-sum b { font-size: 12px; font-weight: 600; letter-spacing: .2px; }
.asset-sum span { font-size: 10.5px; color: var(--dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.asset-fold { max-height: 0; overflow: hidden; transition: max-height .2s ease; }
.node:hover .asset-fold { max-height: 620px; overflow-y: auto; }
.node:hover .node-card.has-hero .asset-sum { border-top-color: rgba(var(--tint), .12); }

/* ---- 生成节点内的提示词：就地编辑 ---- */
.cp-labrow { display: flex; align-items: center; gap: 6px; margin: 2px 0 3px; }
.cp-labrow .cp-lab { flex: 1; margin: 0; }
.cp-expand {
  border: 1px solid rgba(var(--tint), .12); background: rgba(var(--tint), .05);
  color: var(--dim); border-radius: 6px; width: 22px; height: 20px;
  font-size: 11px; line-height: 1; cursor: pointer;
}
.cp-expand:hover { color: var(--fg); border-color: var(--accent); }

/* 已连资产缩略图条：编号对应 @图N */
.cp-refs { display: flex; align-items: center; gap: 5px; flex-wrap: wrap; margin-bottom: 6px; }
.cp-refs-h { font-size: 9.5px; color: var(--dim); letter-spacing: .3px; margin-right: 2px; }
.cp-ref {
  position: relative; width: 34px; height: 24px; padding: 0; border-radius: 5px;
  border: 1px solid rgba(var(--tint), .14); overflow: hidden; cursor: pointer;
  background: rgba(var(--tint), .06);
}
.cp-ref img { width: 100%; height: 100%; object-fit: cover; display: block; }
.cp-ref i {
  position: absolute; right: 1px; bottom: 0; font-size: 8px; font-style: normal;
  padding: 0 3px; border-radius: 3px 0 0 0; background: rgba(0, 0, 0, .6); color: #fff;
}
.cp-ref:hover { border-color: var(--accent); }
.cp-ref-ph { display: block; width: 100%; height: 100%; background: rgba(var(--tint), .08); }

/* @ 选择器 */
.cp-at {
  position: relative; z-index: 20; margin-top: -4px; padding: 4px;
  background: var(--surface); border: 1px solid rgba(var(--tint), .16);
  border-radius: 8px; box-shadow: 0 10px 24px rgba(0, 0, 0, .35);
  display: flex; flex-direction: column; gap: 2px; max-height: 180px; overflow: auto;
}
.cp-at[hidden] { display: none; }
.cp-at-i {
  display: flex; align-items: center; gap: 7px; padding: 3px 5px;
  border: 0; background: none; color: inherit; border-radius: 5px;
  font-size: 11px; cursor: pointer; text-align: left;
}
.cp-at-i:hover { background: rgba(var(--tint), .1); }
.cp-at-i img { width: 26px; height: 18px; object-fit: cover; border-radius: 3px; }

/* 放大编辑面板 */
.pe-wrap { display: flex; flex-direction: column; gap: 8px; }
.pe-ta {
  width: 100%; min-height: 220px; max-height: 460px; resize: vertical;
  padding: 10px 12px; border-radius: 10px; font: inherit; font-size: 13px; line-height: 1.7;
  color: inherit; background: rgba(var(--tint), .04); border: 1px solid rgba(var(--tint), .12);
}
.pe-ta:focus { outline: none; border-color: var(--accent); }
.cp-lab { font-size: 9.5px; letter-spacing: .3px; color: var(--dim); margin: 2px 0 -2px 1px; }
.cp-lab.dim { margin: 4px 0 -4px 1px; opacity: .7; }
.cp-extra {
  width: 100%; display: block; resize: vertical; min-height: 48px; max-height: 240px;
  padding: 7px 9px; border-radius: 8px; font: inherit; font-size: 11.5px; line-height: 1.55;
  color: inherit; background: rgba(var(--tint), .05);
  border: 1px solid rgba(var(--tint), .1);
}
.cp-extra:focus { outline: none; border-color: var(--accent); background: rgba(var(--tint), .08); }
.cp-extra::placeholder { color: var(--dim); }
.cp-prompt {
  width: 100%; min-height: 46px; max-height: 220px; resize: vertical;
  padding: 7px 9px; border-radius: 8px; font: inherit; font-size: 11.5px; line-height: 1.55;
  color: inherit; background: rgba(var(--tint), .05);
  border: 1px solid rgba(var(--tint), .1);
}
.cp-prompt:focus { outline: none; border-color: var(--accent); background: rgba(var(--tint), .08); }
.node-fields .field.full { grid-column: 1 / -1; }

/* 端口：⊙ 加号圆（照 libtv 截图中节点左右边缘的 ⊕），
   实测直径 13px，圆心在卡片边缘外 10px。颜色仍按端口类型区分，保留可读性。 */
.port-wrap { position: absolute; display: flex; align-items: center; transform: translateY(-50%); z-index: 3; }
.port-wrap.in { left: -16.5px; }
.port-wrap.out { right: -16.5px; }
.port {
  width: 13px; height: 13px; border-radius: 50%;
  background: var(--port-bg);
  border: 1px solid var(--pc, #889);
  cursor: crosshair; transition: .12s; flex-shrink: 0;
  position: relative;
}
.port::before, .port::after {
  content: ''; position: absolute; left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  background: var(--pc, #889); border-radius: 1px; transition: .12s;
}
.port::before { width: 5px; height: 1px; }
.port::after { width: 1px; height: 5px; }
.port:hover, .port.hot {
  background: var(--pc);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--pc) 32%, transparent);
  transform: scale(1.15);
}
.port:hover::before, .port:hover::after,
.port.hot::before, .port.hot::after { background: var(--canvas); }
.port-label {
  position: absolute;
  font-size: 10px; color: var(--text-2);
  background: rgba(16,16,19,.94);
  border: 1px solid var(--line);
  padding: 1px 7px; border-radius: 5px;
  opacity: 0; transition: .15s; white-space: nowrap; pointer-events: none;
}
/* 标签放到卡片外侧，避免盖住卡片内容 */
.port-wrap.in .port-label { right: 18px; }
.port-wrap.out .port-label { left: 18px; }
.node:hover .port-label, .node.selected .port-label { opacity: 1; }

/* ═════════════════ 文本节点（严格按 libtv 截图测量值重建） ═════════════════
   卡片 219×219；占位图标 3 根通栏 + 1 根半栏（34×30.5，条高 3.5、间距 9）；
   「尝试:」距卡顶 88 / 距卡左 16；建议项 4 条、行高 25.3、首行距卡顶 109。
   整张卡没有任何标签和输入框外壳 —— 空态是海报，点一下才变成输入区。 */
.tn-body {
  padding: 31px 16px 9px;
  min-height: 219px;
  box-sizing: border-box;
  display: flex; flex-direction: column;
}
.tn-ph { display: flex; justify-content: center; }
.tn-bars { width: 34px; height: 30.5px; fill: #4d4d4d; display: block; }

.tn-try { margin-top: 27px; display: flex; flex-direction: column; }
.tn-try-h { font-size: 11px; line-height: 14px; color: var(--dim); margin-bottom: 7px; }
.tn-sug {
  display: flex; align-items: center; gap: 6px;
  height: 25.3px; padding: 0 8px 0 12px;
  margin: 0 -6px; width: calc(100% + 12px);
  background: none; border: none; border-radius: 7px;
  color: var(--text-2); font-size: 11px; text-align: left; white-space: nowrap;
  transition: .13s;
}
.tn-sug:hover { background: rgba(var(--tint),.07); color: var(--text); }
.tn-sug-ico { width: 13px; height: 13px; display: grid; place-items: center; color: var(--dim); flex-shrink: 0; }
.tn-sug-ico .ico { width: 12px; height: 12px; stroke-width: 1.8; }
.tn-sug:hover .tn-sug-ico { color: var(--nc); }

/* 有内容：纯文字，无标签无边框 */
.tn-body.has-text { padding: 16px; }
.tn-text {
  font-size: 12px; line-height: 1.75; color: var(--text);
  white-space: pre-wrap; word-break: break-word;
  max-height: 460px; overflow: auto; cursor: text;
}
.tn-hint {
  margin-top: auto; padding-top: 10px;
  font-size: 10px; color: var(--dim); opacity: 0; transition: .15s;
}
.node:hover .tn-hint { opacity: 1; }
.tn-pending {
  margin-top: auto; padding-top: 10px;
  display: flex; align-items: center; gap: 6px;
  font-size: 10.5px; color: var(--accent);
}

/* 就地编辑：卡片临时放宽，方便写长设定 */
.tn-body.editing { padding: 14px; min-height: 190px; }
.tn-input {
  flex: 1; width: 100%; min-height: 168px;
  background: transparent; border: none; outline: none; resize: none;
  color: var(--text); font-family: inherit; font-size: 12.5px; line-height: 1.8;
  padding: 0; caret-color: var(--accent);
}
.tn-input::placeholder { color: var(--dim); }
.node.is-text .node-card { border-radius: 16px; }

/* —— 文本节点的 AI 改写入口 ——
   绝对定位在卡片右上角，平时 opacity:0 + pointer-events:none，
   只有鼠标移到卡片上（或键盘聚焦到卡片里）才出现。卡片本身保持极简，不添常驻控件。 */
.tn-act {
  position: absolute; right: 8px; top: 8px; z-index: 4;
  display: flex; gap: 4px;
}
.tn-abtn {
  width: 24px; height: 24px; padding: 0;
  display: grid; place-items: center;
  border: none; border-radius: 7px;
  background: rgba(16,16,16,.8);
  backdrop-filter: blur(6px);
  color: var(--text-2);
  opacity: 0; pointer-events: none;
  transition: opacity .12s, background .12s, color .12s;
}
.tn-abtn .ico { width: 13px; height: 13px; stroke-width: 1.7; }
.node:hover .tn-act .tn-abtn,
.tn-act:focus-within .tn-abtn { opacity: 1; pointer-events: auto; }
.tn-abtn:hover { background: rgba(106,92,255,.92); color: #fff; }
.tn-amore .ico { width: 11px; height: 11px; }
/* 触屏没有 hover，直接常驻 */
@media (hover: none) { .tn-act .tn-abtn { opacity: 1; pointer-events: auto; } }
.tn-abtn[data-tip]::after { left: auto; right: 0; transform: none; }
.tn-abtn[data-tip]::before { left: auto; right: 9px; transform: none; }

/* 下方输入条（媒体节点专用） */
.node-composer {
  margin-top: 8px;
  background: var(--surface);
  border: 1px solid rgba(var(--tint),.07);
  border-radius: 14px;
  padding: 10px 12px 11px;
  display: flex; flex-direction: column; gap: 9px;
}
.cp-tabs { display: flex; align-items: center; gap: 3px; }
.cp-tabs button {
  border: none; background: transparent; color: var(--dim);
  font-size: 12px; padding: 3px 9px; border-radius: 7px;
}
.cp-tabs button:hover { background: rgba(var(--tint),.09); color: var(--text); }
.cp-tabs button.on { color: var(--nc); }
.cp-grow { flex: 1; }
.cp-prompt {
  font-size: 11.5px; line-height: 1.55; color: var(--text-2);
  max-height: 42px; overflow: hidden;
  background: var(--surface-sunken);
  border-radius: 9px; padding: 9px 11px;
}
.cp-prompt:hover { max-height: 170px; overflow: auto; }
.cp-extra {
  width: 100%; background: var(--surface-input);
  border: 1px solid rgba(var(--tint),.07); border-radius: 9px;
  padding: 8px 11px; font-size: 12px; outline: none; color: var(--text);
}
.cp-extra:focus { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(106,92,255,.18); }
.cp-bar { display: flex; align-items: center; gap: 8px; }
.cp-nums { display: flex; align-items: center; gap: 5px; font-size: 11.5px; color: var(--dim); }
.cp-num {
  width: 60px; background: var(--surface-input);
  border: 1px solid rgba(var(--tint),.07); border-radius: 7px;
  padding: 5px 7px; font-size: 11.5px; outline: none; color: var(--text); text-align: center;
}
.cp-chip {
  background: var(--surface-input); border: 1px solid rgba(var(--tint),.07);
  border-radius: 8px; padding: 5px 9px; font-size: 11.5px; color: var(--text-2);
  outline: none; cursor: pointer; max-width: 140px;
}
/* 生成键左边那枚「这次要花多少」：只放数字，明细在 tooltip 里。
   比按钮弱一档，避免跟「生成」抢注意力；余额不够时由 app 那边加 .low。 */
.cp-cost {
  display: inline-flex; align-items: center; gap: 3px; flex-shrink: 0;
  height: 25px; padding: 0 7px; border-radius: 8px;
  font-size: 11px; font-variant-numeric: tabular-nums;
  color: var(--text-2);
  background: rgba(var(--tint), .05);
  border: 1px solid rgba(var(--tint), .06);
}
.cp-cost i { font-style: normal; font-size: 11px; color: #a99cff; line-height: 1; }
.cp-cost.low { color: #ff9a9a; border-color: rgba(255, 90, 90, .3); background: rgba(255, 90, 90, .08); }
.cp-cost.low i { color: #ff8080; }

/* 画幅：选项都很短（16:9 / 9:16 / 自适应），别占太宽，不然一条 bar 放不下 */
.cp-btn-ratio { display: inline-flex; align-items: center; gap: 4px; max-width: 88px; }
.cp-btn-ratio .cp-caret { flex-shrink: 0; font-size: 9px; line-height: 1; color: var(--dim); }

/* 清晰度：480P / 720P / 1080P / 4K，比画幅还短一截。
   同一档位只换清晰度时用它 —— 可灵的三档不再各占一行菜单。 */
.cp-res { max-width: 84px; padding-right: 5px; }
.cp-res-ro { max-width: 66px; font-variant-numeric: tabular-nums; letter-spacing: .02em; }
/* 画幅不可选时的静态说明（跟随首帧 / 跟随原片） */
.cp-chip-ro {
  color: var(--dim); cursor: default;
  border-style: dashed; background: transparent;
}

/* 输入条上的图标按钮（静音开关 / 优化提示词 / 高级设置） */
.cp-ibtn {
  display: inline-grid; place-items: center;
  width: 26px; height: 25px; padding: 0; flex-shrink: 0;
  color: var(--text-2);
}
.cp-ibtn .ico { width: 13px; height: 13px; }
.cp-ibtn:hover { color: var(--text); }
.cp-ibtn.on { color: #9d92ff; background: rgba(106,92,255,.16); border-color: rgba(106,92,255,.42); }
.cp-ibtn.is-off { color: var(--dim); opacity: .55; cursor: default; }
.cp-ibtn.busy { color: #9d92ff; }
.cp-run {
  border: none; background: var(--accent); color: #fff;
  font-size: 12.5px; font-weight: 600;
  padding: 7px 22px; border-radius: 9px;
  display: flex; align-items: center; justify-content: center; gap: 6px;
  transition: .15s; min-width: 84px;
}
.cp-run:hover { filter: brightness(1.13); }
.cp-run.busy { background: rgba(106,92,255,.3); color: #cfe0ff; }

/* 非媒体生成节点的底部按钮 */
.node-foot {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 12px;
  border-top: 1px solid rgba(var(--tint),.06);
  background: var(--surface-sunken);
  border-radius: 0 0 13px 13px;
}
.run-btn {
  flex: 1;
  border: none;
  background: rgba(var(--tint),.08);
  color: var(--text);
  padding: 8px; border-radius: 9px;
  font-size: 12.5px; font-weight: 500;
  transition: .15s;
  display: flex; align-items: center; justify-content: center; gap: 6px;
}
.run-btn:hover { background: rgba(var(--tint),.15); }
.run-btn.busy { color: #8aa8ff; background: rgba(106,92,255,.22); }
.spin {
  width: 11px; height: 11px; border-radius: 50%;
  border: 2px solid rgba(var(--tint),.18); border-top-color: var(--accent);
  animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
.consistency-dot { font-size: 13px; }
.consistency-dot.ok { color: var(--ok); }
.consistency-dot.warn { color: var(--warn); }

.mini {
  border: none; background: transparent; color: var(--dim);
  cursor: pointer; padding: 2px 6px; border-radius: 6px;
  font-size: 11px; line-height: 1.45;
}
.mini:hover { background: rgba(var(--tint),.1); color: var(--text); }

.node-summary { padding: 12px 16px; font-size: 12px; color: var(--dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.field { display: flex; flex-direction: column; gap: 4px; }
.field label { font-size: 10.5px; color: var(--dim); }
.field input[type="text"], .field input[type="number"], .field textarea, .field select {
  width: 100%;
  background: var(--surface-input);
  border: 1px solid rgba(var(--tint),.07);
  border-radius: 8px;
  padding: 5px 9px;
  font-size: 12px; outline: none; resize: vertical;
  transition: .13s;
}
.field input:focus, .field textarea:focus, .field select:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(106,92,255,.2);
}
.field textarea { line-height: 1.45; min-height: 34px; font-family: inherit; }
.field select { appearance: none; background-image: none; }

.img-slot {
  height: 78px; border-radius: 9px;
  border: 1px dashed rgba(var(--tint),.16);
  background: var(--surface-input);
  display: grid; place-items: center;
  cursor: pointer; position: relative; overflow: hidden;
  transition: .13s;
}
.img-slot:hover { border-color: var(--accent); }
.img-slot.has { border-style: solid; border-color: rgba(var(--tint),.08); }
.img-slot img, .img-slot video { width: 100%; height: 100%; object-fit: cover; display: block; }
/* 成片这类「整段视频」字段：78px 横条只够放参考图，视频塞进去只看得到顶上一条。
   改成按真实比例撑开、整帧 contain —— 完整比铺满重要，宁可留黑边。 */
.img-slot.is-video { height: auto; aspect-ratio: 16 / 9; max-height: 300px; background: #000; }
/* 绝对定位是必须的：格子高度是 auto（由 aspect-ratio 撑），height:100% 在这里
   解析不出来，视频会按自身比例顶到 700 多高、又被 overflow 裁掉。 */
.img-slot.is-video video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; }
.img-slot .ph { font-size: 11px; color: var(--dim); }
.img-slot .clr { position: absolute; top: 4px; right: 4px; background: rgba(0,0,0,.72); }
/* 缩略图右下角的下载箭头，跟右上角的清除键同一套底色，不抢画面 */
.img-slot .dl {
  position: absolute; bottom: 4px; right: 4px;
  background: rgba(0,0,0,.72); color: #fff;
  text-decoration: none; line-height: 1.3;
}
.img-slot .dl:hover { background: rgba(0,0,0,.9); color: #fff; }
.mini.dl-inline { text-decoration: none; }

.audio-slot { display: flex; flex-direction: column; gap: 6px; }
.audio-slot audio { width: 100%; height: 32px; }
.audio-slot .ph {
  height: 40px; border-radius: 9px;
  border: 1px dashed rgba(var(--tint),.16);
  background: var(--surface-input);
  display: grid; place-items: center;
  font-size: 11px; color: var(--dim);
}

.img-list { display: grid; grid-template-columns: repeat(4, 1fr); gap: 5px; }
.img-item { position: relative; aspect-ratio: 1; border-radius: 7px; overflow: hidden; border: 1px solid rgba(var(--tint),.1); }
.img-item img { width: 100%; height: 100%; object-fit: cover; display: block; }
.img-item .clr { position: absolute; top: 1px; right: 1px; background: rgba(0,0,0,.72); font-size: 9px; padding: 0 3px; }
.img-add {
  aspect-ratio: 1; border-radius: 7px;
  border: 1px dashed rgba(var(--tint),.16); background: transparent;
  color: var(--dim); font-size: 15px;
}
.img-add:hover { border-color: var(--accent); color: var(--accent); }

/* -------------------------------- 连线 -------------------------------- */
.edge { fill: none; stroke: var(--ec, #8899aa); stroke-width: 1.8; opacity: .5; transition: opacity .15s; }
.edge:hover { opacity: 1; stroke-width: 2.4; cursor: pointer; }
.edge-temp { stroke: var(--accent); stroke-dasharray: 5 4; opacity: .95; stroke-width: 2; }
.edge.flowing { stroke-dasharray: 7 5; animation: dash .55s linear infinite; opacity: .95; }
/* 亮色底上 0.5 的不透明度几乎看不见，提到 0.72；端口色本身不变，仍能区分类型 */
[data-theme="light"] .edge { opacity: .72; }

/* 亮色主题的投影要轻：深色那套 rgba(0,0,0,.5~.78) 在白底上会像脏污，
   换成带一点绿调的极淡投影，节点才有「纸片浮起」的清爽感。 */
[data-theme="light"] .node-card {
  box-shadow: 0 6px 16px rgba(23,32,28,.10), 0 1px 3px rgba(23,32,28,.06);
}
[data-theme="light"] .node:hover .node-card {
  box-shadow: 0 10px 24px rgba(23,32,28,.14), 0 2px 6px rgba(23,32,28,.08);
}
[data-theme="light"] .node.selected .node-card {
  box-shadow:
    0 0 0 1.5px var(--accent),
    0 0 0 7px rgba(47,90,232,.10),
    inset 0 1px 0 rgba(255,255,255,.9),
    0 2px 6px rgba(23,32,28,.10),
    0 14px 30px rgba(23,32,28,.14),
    0 30px 60px rgba(23,32,28,.10);
}
[data-theme="light"] .node.dragging .node-card {
  box-shadow: 0 0 0 1.5px var(--accent), 0 0 0 7px rgba(47,90,232,.12), 0 24px 56px rgba(23,32,28,.22);
}
@keyframes dash { to { stroke-dashoffset: -24; } }

.marquee {
  position: fixed; z-index: 5;
  border: 1px solid var(--accent);
  background: rgba(106,92,255,.14);
  border-radius: 4px; pointer-events: none;
}

/* 小地图导航（照教程 1.4.4，画布四大功能之一）
   放在左下、底栏之上；默认半透明，hover 才完全显形，空画布自动隐藏。 */
.minimap {
  position: fixed; left: 10px; bottom: 66px;
  width: 190px; height: 120px;
  background: rgba(24, 24, 26, .82);
  backdrop-filter: var(--blur);
  border: 1px solid rgba(var(--tint),.07);
  border-radius: 10px;
  overflow: hidden; cursor: pointer; z-index: 39;
  box-shadow: var(--shadow);
  opacity: .62; transition: opacity .18s, border-color .18s;
}
.minimap:hover { opacity: 1; border-color: rgba(var(--tint),.16); }
.minimap[hidden] { display: none; }
#minimap-svg { width: 100%; height: 100%; display: block; }
.mm-view { fill: rgba(106,92,255,.18); stroke: var(--accent); stroke-width: 1; }

/* 框选后浮出的批量操作条（跟随选区） */
.sel-bar {
  position: absolute; z-index: 30;
  display: flex; align-items: center; gap: 1px;
  height: 34px; padding: 0 5px;
  background: var(--surface-2);
  border-radius: 10px;
  box-shadow: 0 8px 26px rgba(0,0,0,.6);
  font-size: 12.5px; color: var(--text-2);
  white-space: nowrap;
  animation: pop .12s ease-out;
}
.sel-bar[hidden] { display: none; }
.sel-count { padding: 0 9px 0 5px; color: var(--text); font-weight: 500; }
.sel-sep { width: 1px; height: 16px; background: rgba(var(--tint),.14); margin: 0 3px; flex-shrink: 0; }
.sel-bar button {
  display: flex; align-items: center; gap: 6px;
  border: none; background: transparent; color: var(--text-2);
  font-size: 12.5px; padding: 6px 11px; border-radius: 7px;
}
.sel-bar button .ico { width: 14px; height: 14px; opacity: .85; }
.sel-bar button .caret { font-size: 9px; color: var(--dim); margin-left: -3px; }
.sel-bar button:hover { background: rgba(var(--tint),.1); color: var(--text); }
.sel-bar button[data-batch="delete"]:hover { background: rgba(255,107,127,.2); color: #ff9aa8; }
.sel-bar .sel-x { padding: 6px 9px; color: var(--dim); }
.sel-bar .sel-x:hover { background: rgba(var(--tint),.1); color: var(--text); }

/* 双击标题就地重命名 */
.nt-input {
  flex: 1; min-width: 0;
  background: var(--surface-sunken);
  border: 1px solid var(--accent);
  border-radius: 5px;
  color: var(--text); font-family: var(--ui); font-size: 12px; font-weight: 500;
  padding: 1px 6px; outline: none;
}

/* -------------------------------- 抽屉 -------------------------------- */
.drawer {
  position: fixed; top: 46px; bottom: 68px;
  width: 288px;
  background: var(--surface);
  border: 1px solid rgba(var(--tint),.07);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg);
  display: flex; flex-direction: column;
  z-index: 45; overflow: hidden;
  opacity: 0; pointer-events: none;
  transition: opacity .18s, transform .18s;
}
.drawer.left { left: 10px; transform: translateX(-14px); }
.drawer.right { right: 10px; width: 322px; transform: translateX(14px); }
.drawer.open { opacity: 1; pointer-events: auto; transform: translateX(0); }

.drawer-head {
  display: flex; align-items: center; gap: 8px;
  padding: 11px 12px;
  border-bottom: 1px solid var(--line);
  flex-shrink: 0;
}
.drawer-head b { font-size: 12.5px; flex: 1; }
.drawer-body { flex: 1; overflow: auto; padding: 12px; min-height: 0; }
.drawer-tabs { display: flex; gap: 3px; padding: 9px 10px 0; flex-wrap: wrap; flex-shrink: 0; }
.drawer-tabs button {
  border: none; background: transparent; color: var(--dim);
  padding: 4px 10px; border-radius: 7px; font-size: 11.5px;
}
.drawer-tabs button:hover { background: rgba(var(--tint),.07); color: var(--text-2); }
.drawer-tabs button.on { background: rgba(var(--tint),.11); color: var(--text); }

/* ------------------------------ Agent 面板 ------------------------------ */
.agent-panel {
  position: fixed; right: 10px; bottom: 68px;
  width: 336px;
  /* 固定高度而不是 max-height：max-height 只封顶，内容少时面板会缩成半截，
     聊天记录一多就挤。固定高度让对话区始终有足够空间。 */
  height: min(720px, calc(100vh - 120px));
  background: var(--surface);
  border: 1px solid rgba(var(--tint),.07);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg);
  display: flex; flex-direction: column;
  z-index: 46; overflow: hidden;
  opacity: 0; pointer-events: none; transform: translateY(10px) scale(.98);
  transition: opacity .18s, transform .18s;
}
.agent-panel.open { opacity: 1; pointer-events: auto; transform: none; }
.agent-head {
  display: flex; align-items: center; gap: 10px;
  padding: 11px 12px;
  border-bottom: 1px solid var(--line);
  flex-shrink: 0;
}
.agent-title { flex: 1; display: flex; flex-direction: column; line-height: 1.25; }
.agent-title b { font-size: 12.5px; }
.agent-title span { font-size: 10.5px; color: var(--dim); }

.agent-feed { flex: 1; overflow: auto; padding: 12px; display: flex; flex-direction: column; gap: 9px; min-height: 120px; }
.msg { font-size: 12px; line-height: 1.6; border-radius: 11px; padding: 9px 11px; max-width: 92%; }
.msg.user { align-self: flex-end; background: rgba(106,92,255,.22); border: 1px solid rgba(106,92,255,.36); }
.msg.bot { align-self: flex-start; background: rgba(var(--tint),.055); border: 1px solid var(--line); color: var(--text-2); }
.msg .msg-h { font-size: 10.5px; color: var(--dim); margin-bottom: 4px; }
/* 助手给的「确认花积分」按钮：只有点了才提交生成 */
.msg .msg-acts { margin-top: 9px; display: flex; gap: 8px; }
.msg-btn {
  font: inherit; font-size: 12px; line-height: 1; padding: 8px 12px; border-radius: 9px;
  color: #fff; background: var(--accent); border: 0; cursor: pointer;
  transition: filter .15s ease, opacity .15s ease;
}
.msg-btn:hover { filter: brightness(1.08); }
.msg-btn:disabled { opacity: .6; cursor: default; }
.msg .msg-tip { margin-top: 7px; font-size: 11px; color: var(--dim); line-height: 1.55; }
.msg pre {
  font-family: var(--mono); font-size: 10.5px; white-space: pre-wrap; word-break: break-word;
  margin: 6px 0 0; max-height: 180px; overflow: auto; color: var(--text);
}

.agent-quick { display: flex; flex-wrap: wrap; gap: 6px; padding: 0 12px 9px; flex-shrink: 0; }
.q-chip {
  border: 1px solid var(--line); background: rgba(var(--tint),.05);
  color: var(--text-2); font-size: 11px;
  padding: 5px 10px; border-radius: 999px;
  transition: .14s;
}
.q-chip:hover { background: rgba(var(--tint),.12); color: var(--text); border-color: var(--line-hi); }

/* ----全能创作助手空状态：四个创作入口（参考设计稿） ---- */
.agent-home { padding: 4px 2px 10px; }
.agent-orb-lg { width: 48px; height: 48px; margin: 10px auto 14px; display: grid; place-items: center; }
.agent-orb-lg .orb { width: 48px; height: 48px; }
.agent-orb-lg .orb::after { inset: 7px; background: var(--surface-2); }
.agent-home h3 {
  font-size: 14.5px; font-weight: 600; text-align: center;
  margin: 0 0 16px; color: var(--text); letter-spacing: .2px;
}
.entry-list { display: flex; flex-direction: column; gap: 2px; }
.entry-item {
  display: flex; align-items: center; gap: 11px; width: 100%;
  padding: 11px 10px; border-radius: 10px; text-align: left; color: var(--text-2);
  background: transparent; border: none;   /* button 默认白底，必须显式清掉 */
  transition: .14s;
}
.entry-item:hover { background: rgba(var(--tint),.055); color: var(--text); }
.entry-ico {
  width: 30px; height: 30px; border-radius: 8px; flex: 0 0 auto;
  background: rgba(var(--tint),.06); display: grid; place-items: center;
}
.entry-ico .ico { width: 15px; height: 15px; stroke: var(--text-2); fill: none; stroke-width: 1.6; }
.entry-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.entry-body b { font-size: 12.5px; font-weight: 550; color: var(--text); }
.entry-body span { font-size: 10.5px; color: var(--dim); line-height: 1.4; }
.entry-arrow {
  width: 14px; height: 14px; flex: 0 0 auto; opacity: .55;
  stroke: var(--dim); fill: none; stroke-width: 1.8;
}

/* ---- Skill 选择面板 ---- */
.panel-head { display: flex; align-items: center; gap: 8px; padding: 2px 0 10px; }
.panel-head b { font-size: 13px; }
.panel-back { flex: 0 0 auto; font-size: 13px; padding: 2px 7px; }
.skill-cats { display: flex; gap: 5px; flex-wrap: wrap; padding-bottom: 8px; }
.schip {
  font-size: 10.5px; padding: 4px 9px; border-radius: 999px;
  border: 1px solid var(--line); color: var(--dim); background: transparent;
}
.schip.on { background: var(--accent-soft); border-color: rgba(106,92,255,.5); color: #cdd9ff; }
.skill-search { padding-bottom: 8px; }
.skill-search input {
  width: 100%; background: var(--surface-input); border: 1px solid var(--line);
  border-radius: 8px; padding: 6px 9px; font-size: 11.5px; outline: none; color: var(--text);
}
.skill-search input:focus { border-color: var(--accent); }
.skill-list { display: flex; flex-direction: column; gap: 3px; }
.skill-item {
  display: flex; align-items: flex-start; gap: 9px; padding: 9px 8px;
  border-radius: 9px; text-align: left; background: transparent; border: none;
  transition: .14s;
}
.skill-item:hover { background: rgba(var(--tint),.05); }
.skill-ico {
  width: 28px; height: 28px; border-radius: 8px; flex: 0 0 auto;
  display: grid; place-items: center;
  background: color-mix(in srgb, var(--sc) 15%, transparent);
}
.skill-ico .ico { width: 14px; height: 14px; stroke: var(--sc); fill: none; stroke-width: 1.6; }
.skill-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.skill-body b { font-size: 12px; color: var(--text); font-weight: 550; }
.skill-body code { font-size: 9.5px; color: var(--dim); font-family: ui-monospace, SFMono-Regular, monospace; }
.skill-body span { font-size: 10.5px; color: var(--text-2); line-height: 1.45; margin-top: 2px; }
.skill-more {
  font-size: 10px; color: var(--dim); border: 1px solid var(--line);
  padding: 2px 7px; border-radius: 999px; flex: 0 0 auto; margin-top: 2px;
}
.skill-more:hover { color: var(--text); border-color: var(--line-hi); }

/* ---- 输入框上方的上下文 chip ---- */
.agent-ctx { display: flex; flex-wrap: wrap; gap: 5px; padding: 0 12px 8px; flex-shrink: 0; }
.ctx-chip {
  display: inline-flex; align-items: center; gap: 3px;
  font-size: 10.5px; padding: 3px 4px 3px 9px; border-radius: 999px;
  background: color-mix(in srgb, var(--cc) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--cc) 42%, transparent);
  color: var(--text);
}
.ctx-chip button {
  width: 15px; height: 15px; border-radius: 50%; font-size: 10px;
  color: var(--text-2); display: grid; place-items: center; line-height: 1;
}
.ctx-chip button:hover { background: rgba(var(--tint),.14); color: var(--text); }

/* ---- 剧本设定器 ---- */
.genre-wizard { display: flex; gap: 14px; min-height: 330px; }
.gw-list { width: 152px; flex: 0 0 auto; border-right: 1px solid var(--line); padding-right: 10px; }
.gw-list-h { font-size: 10.5px; color: var(--dim); padding: 2px 4px 8px; }
.gw-item {
  display: flex; align-items: center; gap: 3px; width: 100%;
  padding: 6px; border-radius: 7px; font-size: 11px; color: var(--text-2); text-align: left;
  background: transparent; border: none;
}
.gw-item:hover { background: rgba(var(--tint),.06); }
.gw-item.on { background: var(--accent-soft); color: #d5e0ff; }
.gw-idx { color: var(--dim); font-size: 10px; flex: 0 0 auto; }
.gw-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 10px; }
.gw-h { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.gw-h b { font-size: 13px; }
.gw-fields { display: grid; grid-template-columns: 1fr 1fr; gap: 7px; }
.gw-field {
  background: var(--surface-sunken); border-radius: 8px;
  padding: 7px 9px; display: flex; flex-direction: column; gap: 2px;
}
.gw-field span { font-size: 9.5px; color: var(--dim); }
.gw-field b { font-size: 11px; color: var(--text-2); font-weight: 500; line-height: 1.4; }
.gw-tags { display: flex; gap: 5px; flex-wrap: wrap; }
.gw-grid { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 8px; }
.gw-note { margin: 0; }

/* ---- 剧本设定器 v2：题材融合 + 六个属性选择（对齐 libtv） ---- */
.gw-list-tip { display: block; margin-top: 3px; font-size: 9.5px; color: var(--accent); opacity: .85; }

/* 题材球 + 融合按钮 */
.gw-orbit { position: relative; display: flex; justify-content: center; align-items: center; padding: 4px 0 6px; }
.gw-ring {
  width: 196px; height: 196px; border-radius: 50%;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px;
  text-align: center; padding: 0 18px;
  background:
    radial-gradient(circle at 34% 28%, rgba(120,150,255,.30), transparent 62%),
    radial-gradient(circle at 70% 78%, rgba(180,120,255,.22), transparent 60%),
    var(--surface-sunken);
  border: 1px solid var(--line-hi);
  box-shadow: inset 0 0 46px rgba(80,110,255,.18), 0 10px 30px rgba(0,0,0,.35);
}
.gw-ring b { font-size: 13.5px; line-height: 1.35; word-break: break-word; max-width: 160px; }
.gw-ring span { font-size: 10.5px; color: var(--dim); line-height: 1.4; max-width: 160px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gw-fuse {
  position: absolute; right: calc(50% - 178px); bottom: 10px;
  width: 86px; height: 86px; border-radius: 50%;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  background: rgba(var(--tint), .04);
  border: 1px dashed rgba(var(--tint), .28);
  color: var(--text-2); cursor: pointer;
  transition: border-color .15s, background .15s, color .15s;
}
.gw-fuse:hover { border-color: rgba(106,92,255,.6); color: var(--text); background: rgba(106,92,255,.10); }
.gw-fuse.on { border-style: solid; border-color: rgba(106,92,255,.75); color: #cfe0ff; background: rgba(106,92,255,.18); }
.gw-fuse b { font-size: 18px; line-height: 1; }
.gw-fuse span { font-size: 10px; }

/* 六个属性 chip */
.gw-chips { display: flex; gap: 7px; flex-wrap: wrap; margin-top: 2px; }
.gw-chip {
  display: grid; grid-template-columns: 14px auto; grid-template-rows: auto auto;
  column-gap: 6px; row-gap: 1px; align-items: center;
  padding: 7px 10px 8px; border-radius: 10px;
  border: 1px solid var(--line); background: rgba(var(--tint), .02);
  color: var(--text-2); cursor: pointer; text-align: left;
  transition: border-color .15s, background .15s;
}
.gw-chip:hover { border-color: rgba(var(--tint), .2); background: rgba(var(--tint), .05); }
.gw-chip.on { border-color: rgba(106,92,255,.5); background: var(--accent-soft); color: #d5e0ff; }
.gw-chip i { grid-row: 1 / span 2; font-style: normal; font-size: 12px; color: var(--dim); }
.gw-chip-l { font-size: 9.5px; color: var(--dim); }
.gw-chip.on .gw-chip-l { color: rgba(213,224,255,.75); }
.gw-chip-v { font-size: 11px; max-width: 118px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* 弹层：挂在 body 上，必须压过 .modal（z-index 200） */
.gw-pop {
  position: fixed; z-index: 260; width: 330px; padding: 11px 12px 12px;
  background: var(--surface-2); border: 1px solid var(--line-hi);
  border-radius: 12px; box-shadow: 0 18px 50px rgba(0,0,0,.55);
}
.gw-pop-h { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 9px; }
.gw-pop-h b { font-size: 12px; }
.gw-pop-h span { font-size: 10px; color: var(--dim); }
.gw-pop-grid { display: flex; flex-wrap: wrap; gap: 6px; max-height: 268px; overflow-y: auto; }
.gw-opt {
  padding: 5px 9px; border-radius: 8px; font-size: 11px;
  border: 1px solid var(--line); background: transparent; color: var(--text-2); cursor: pointer;
  transition: background .12s, border-color .12s, color .12s;
}
.gw-opt:hover { border-color: rgba(var(--tint), .22); color: var(--text); }
.gw-opt.on { background: var(--accent-soft); border-color: rgba(106,92,255,.55); color: #dbe4ff; }
.gw-pop-scale { display: grid; gap: 8px; }
.gw-pop-scale label { display: flex; align-items: center; justify-content: space-between; gap: 10px; font-size: 11px; color: var(--dim); }
.gw-pop-scale input, .gw-pop-scale select { width: 132px; }
.gw-pop-foot { display: flex; justify-content: flex-end; margin-top: 10px; }

/* ---- 经验库 · 避坑清单（注入给全能创作助手的硬约束，这里摊开给人看） ---- */
.pf-intro { margin: 0 0 12px; line-height: 1.55; }
.pf-list {
  display: grid; grid-template-columns: 1fr 1fr; gap: 12px;
  max-height: 58vh; overflow-y: auto; padding-right: 4px;
}
.pf-group {
  border: 1px solid var(--line); border-radius: 12px;
  padding: 10px 12px 4px; background: rgba(var(--tint), .02);
}
.pf-group h4 {
  margin: 0 0 6px; font-size: 12px; font-weight: 600;
  display: flex; align-items: center; gap: 6px;
}
.pf-group h4 i { font-style: normal; color: var(--accent); }
.pf-group h4 span { margin-left: auto; font-size: 10px; color: var(--dim); }
.pf-item { padding: 8px 0; border-top: 1px dashed rgba(var(--tint), .09); }
.pf-item:first-of-type { border-top: none; padding-top: 2px; }
.pf-item b { font-size: 11.5px; font-weight: 600; }
.pf-rule { margin: 3px 0 0; font-size: 11px; line-height: 1.55; color: var(--text-2); }
.pf-why { margin: 3px 0 0; font-size: 10.5px; line-height: 1.5; color: var(--dim); }
@media (max-width: 920px) { .pf-list { grid-template-columns: 1fr; } }

/* ---- 分镜表：整集镜头一览 ---- */
.sb-head { display: flex; align-items: center; gap: 12px; margin-bottom: 10px; }
.sb-stat { font-size: 11.5px; color: var(--text-2); }
.sb-stat b { color: var(--text); }
.sb-filters { margin-left: auto; display: flex; gap: 6px; }
.sb-f {
  padding: 4px 11px; border-radius: 999px; font-size: 11px; cursor: pointer;
  border: 1px solid var(--line); background: transparent; color: var(--dim);
  transition: background .12s, border-color .12s, color .12s;
}
.sb-f:hover { color: var(--text); border-color: rgba(var(--tint), .2); }
.sb-f.on { background: var(--accent-soft); border-color: rgba(106,92,255,.5); color: #d5e0ff; }
.sb-wrap { max-height: 62vh; overflow: auto; border: 1px solid var(--line); border-radius: 10px; }
.sb-table { width: 100%; border-collapse: collapse; font-size: 11.5px; }
.sb-table thead th {
  position: sticky; top: 0; z-index: 1; text-align: left;
  background: var(--surface-2); border-bottom: 1px solid var(--line);
  padding: 7px 9px; font-size: 10.5px; font-weight: 500; color: var(--dim);
}
.sb-table td { padding: 7px 9px; border-bottom: 1px solid rgba(var(--tint), .06); vertical-align: top; color: var(--text-2); }
.sb-table tbody tr:hover { background: rgba(var(--tint), .04); cursor: pointer; }
.sb-key b { display: block; font-size: 11.5px; color: var(--text); }
.sb-grp { display: block; margin-top: 2px; font-size: 9.5px; color: var(--dim); }
.sb-act { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.sb-line { color: var(--dim); }
.sb-mode { font-size: 9.5px; padding: 1px 6px; border-radius: 6px; white-space: nowrap; }
.sb-mode.ff { background: rgba(251, 191, 36, .14); color: #fbbf24; border: 1px solid rgba(251, 191, 36, .3); }
.sb-mode.ref { background: rgba(34, 211, 238, .12); color: #22d3ee; border: 1px solid rgba(34, 211, 238, .28); }
.sb-table .ok { color: #34d399; }
.sb-table .no { color: #fbbf24; }
tr.is-pending .sb-key b { color: var(--dim); }

/* ----全能创作助手内核模型选择（面板头部的小胶囊） ---- */
.agent-model {
  flex: 0 0 auto; max-width: 118px;
  background: var(--surface-sunken); border: 1px solid var(--line);
  border-radius: 999px; padding: 3px 7px; font-size: 10px;
  color: var(--text-2); outline: none; cursor: pointer;
  text-overflow: ellipsis;
}
.agent-model:hover { border-color: var(--line-hi); color: var(--text); }
.agent-model:focus { border-color: var(--accent); }

/* ---- 意图识别中的思考气泡 ---- */
.msg.thinking { padding: 10px 14px; }
.think-dots { display: inline-flex; gap: 4px; align-items: center; height: 10px; }
.think-dots i {
  width: 5px; height: 5px; border-radius: 50%; background: var(--text-2);
  animation: thinkPulse 1.1s infinite ease-in-out;
}
.think-dots i:nth-child(2) { animation-delay: .16s; }
.think-dots i:nth-child(3) { animation-delay: .32s; }
@keyframes thinkPulse {
  0%, 80%, 100% { opacity: .25; transform: translateY(0); }
  40% { opacity: 1; transform: translateY(-2px); }
}

.agent-input {
  display: flex; align-items: flex-end; gap: 7px;
  padding: 10px 12px 12px;
  border-top: 1px solid var(--line);
  flex-shrink: 0;
}
.agent-input textarea {
  flex: 1; resize: none; max-height: 110px;
  background: var(--surface-input);
  border: 1px solid var(--line);
  border-radius: 10px; padding: 8px 10px;
  font-size: 12px; outline: none; line-height: 1.5;
}
.agent-input textarea:focus { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(106,92,255,.2); }
.send-btn {
  width: 34px; height: 34px; flex-shrink: 0;
  display: grid; place-items: center;
  background: var(--accent); border: none; border-radius: 10px; color: #fff;
  transition: .15s;
}
.send-btn:hover { filter: brightness(1.12); }
.send-btn:disabled { opacity: .4; cursor: default; }

/* ------------------------------ 任务抽屉 ------------------------------ */
.task-drawer {
  position: fixed; left: 50%; bottom: 68px;
  transform: translateX(-50%) translateY(10px);
  width: min(880px, calc(100vw - 48px));
  max-height: 300px;
  background: var(--surface);
  border: 1px solid rgba(var(--tint),.07);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg);
  display: flex; flex-direction: column;
  z-index: 44; overflow: hidden;
  opacity: 0; pointer-events: none;
  transition: opacity .18s, transform .18s;
}
.task-drawer.open { opacity: 1; pointer-events: auto; transform: translateX(-50%); }
.job-list { overflow: auto; }
.job-row {
  display: grid;
  grid-template-columns: 62px 78px minmax(140px, 1fr) 68px 52px minmax(0, 190px) 52px;
  align-items: center; gap: 10px;
  padding: 8px 14px;
  border-bottom: 1px solid rgba(var(--tint),.05);
  font-size: 11.5px;
}
.job-row:hover { background: rgba(var(--tint),.04); }
.job-type { color: var(--accent); font-size: 10.5px; }
.job-prov { color: var(--dim); font-size: 10.5px; }
.job-prompt { color: var(--text-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.status { font-size: 10px; padding: 2px 8px; border-radius: 6px; text-align: center; }
.status-queued { background: rgba(var(--tint),.09); color: var(--text-2); }
.status-running { background: rgba(106,92,255,.24); color: #9db4ff; }
.status-done { background: rgba(61,220,151,.16); color: var(--ok); }
.status-error { background: rgba(255,107,127,.16); color: var(--err); }
.status-canceled { background: rgba(var(--tint),.07); color: var(--dim); }
.mini-link { color: var(--accent); text-decoration: none; font-size: 11px; }
.err-inline { color: var(--err); font-size: 10.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* ------------------------------ 检查器 ------------------------------ */
.insp-head { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.chip {
  font-size: 10.5px; padding: 3px 8px; border-radius: 6px;
  background: color-mix(in srgb, var(--nc) 20%, transparent);
  color: var(--nc);
  border: 1px solid color-mix(in srgb, var(--nc) 38%, transparent);
  white-space: nowrap;
}
.insp-title {
  flex: 1; background: transparent; border: none; outline: none;
  font-size: 12.5px; font-weight: 600; padding: 3px 0;
  border-bottom: 1px dashed transparent;
}
.insp-title:focus { border-bottom-color: var(--accent); }
.insp-desc { font-size: 11px; color: var(--dim); margin: 0 0 13px; line-height: 1.55; }

.insp-block {
  background: rgba(var(--tint),.035);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 11px; margin-bottom: 10px;
}
.insp-block-h {
  font-size: 11px; color: var(--dim); margin-bottom: 8px;
  display: flex; align-items: center; justify-content: space-between;
}
.compiled {
  font-family: var(--mono); font-size: 10.5px; line-height: 1.65;
  background: var(--surface-sunken);
  border: 1px solid rgba(var(--tint),.06); border-radius: 8px;
  padding: 9px; white-space: pre-wrap; word-break: break-word;
  margin: 0; max-height: 210px; overflow: auto; color: #cfd7e4;
}
.neg { font-size: 11px; color: var(--dim); margin-top: 7px; }
.refs { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 8px; }
.ref-chip {
  font-size: 10px; padding: 2px 8px; border-radius: 6px;
  background: color-mix(in srgb, var(--rc) 18%, transparent);
  color: var(--rc);
  border: 1px solid color-mix(in srgb, var(--rc) 34%, transparent);
}
.warns { margin: 9px 0 0; padding: 0; list-style: none; font-size: 11px; color: var(--warn); }
.warns li { margin-top: 4px; line-height: 1.5; }
.ok-line { font-size: 11px; color: var(--ok); margin-top: 8px; }

.insp-actions { display: flex; gap: 6px; margin-top: 11px; flex-wrap: wrap; }
.btn {
  border: none;
  background: rgba(var(--tint),.08);
  color: var(--text-2);
  padding: 6px 12px; border-radius: 9px;
  font-size: 12px; transition: .15s; white-space: nowrap;
  text-decoration: none; display: inline-block; text-align: center;
}
.btn:hover { background: rgba(var(--tint),.16); color: var(--text); }
.btn.primary { background: var(--accent); color: #fff; font-weight: 600; }
/* 危险动作：删除类按钮 */
.btn.danger { background: #dc2626; border-color: #dc2626; color: #fff; font-weight: 600; }
.btn.danger:hover { filter: brightness(1.1); }
.btn.primary:hover { filter: brightness(1.15); }
.btn.ghost { background: transparent; }
.btn.ghost:hover { background: rgba(var(--tint),.1); }
.insp-actions .btn { flex: 1; padding: 7px 8px; font-size: 11.5px; }

.insp-result { margin-top: 11px; }
.insp-result img, .insp-result video { width: 100%; border-radius: 9px; display: block; border: 1px solid var(--line); background: #000; }
.insp-result audio { width: 100%; margin-top: 2px; }
.insp-result-bar { display: flex; gap: 6px; margin-top: 8px; }
.insp-result-bar .btn { flex: 1; padding: 5px; font-size: 11px; text-decoration: none; }

.empty-hint { padding: 24px 6px; color: var(--text-2); font-size: 12px; text-align: center; }
.empty-hint p { margin: 0 0 9px; }
.empty-hint .dim { font-size: 11px; line-height: 1.65; }

.job-log {
  font-family: var(--mono); font-size: 10.5px; color: var(--text-2);
  background: var(--surface-sunken); border: 1px solid rgba(var(--tint),.06); border-radius: 8px;
  padding: 8px; max-height: 150px; overflow: auto; line-height: 1.65;
}
.err { color: var(--err); font-size: 11px; margin-top: 7px; line-height: 1.55; }

/* ------------------------------ 资产库 ------------------------------ */
.lib-group { margin-bottom: 15px; }
.lib-group-h { font-size: 11px; color: var(--dim); margin: 0 2px 8px; display: flex; justify-content: space-between; }
.lib-items { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
.lib-item {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 10px;
  background: rgba(var(--tint),.045);
  border: 1px solid var(--line);
  border-left: 2px solid var(--nc, var(--line-hi));
  border-radius: 9px; font-size: 12px; text-align: left;
  transition: .13s;
}
.lib-item:hover { background: rgba(var(--tint),.1); border-color: var(--line-hi); }
.lib-icon { color: var(--nc); font-size: 12px; }

.asset-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 5px; }
.asset-item {
  position: relative;
  aspect-ratio: 16/10; border-radius: 7px; overflow: hidden;
  background: rgba(var(--tint),.05);
  border: 1px solid var(--line);
  cursor: grab; display: grid; place-items: center;
}
.asset-item:hover { border-color: var(--accent); }
/* 删除按钮：只在 hover 时露出来，平时不干扰浏览 */
.asset-del {
  position: absolute; top: 4px; right: 4px;
  width: 20px; height: 20px; border-radius: 50%;
  display: grid; place-items: center;
  border: 1px solid rgba(255, 255, 255, .18);
  background: rgba(12, 14, 20, .72); color: #cbd5e1;
  font-size: 10px; line-height: 1; cursor: pointer;
  opacity: 0; transition: opacity .12s, background .12s, color .12s;
}
.asset-item:hover .asset-del { opacity: 1; }
.asset-del:hover { background: #dc2626; border-color: #dc2626; color: #fff; }
.asset-item img { width: 100%; height: 100%; object-fit: cover; display: block; }
.asset-file { font-size: 10px; color: var(--dim); }
.small { font-size: 11px; }
.dim { color: var(--dim); }

/* ------------------------------- 弹层 ------------------------------- */
.modal {
  position: fixed; inset: 0; z-index: 200;
  background: var(--overlay);
  backdrop-filter: blur(4px);
  display: none; padding: 50px 20px; overflow: auto;
}
.modal.open { display: block; }
.modal-card {
  max-width: 700px; margin: 0 auto;
  background: var(--surface);
  border: 1px solid rgba(var(--tint),.1);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}
.modal-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 13px 15px; border-bottom: 1px solid var(--line);
}
.modal-body { padding: 16px; }
.modal-foot { display: flex; gap: 8px; justify-content: flex-end; margin-top: 16px; }
/* 成片预览用窄弹窗，别让竖屏片子两边挂着大片空白 */
.modal-card.movie { max-width: 460px; }

/* 成片预览：竖屏片子在宽弹窗里居中，高度吃掉窗口的六成，别让人还得滚。
   黑底只包住片子本身（fit-content），不然 9:16 的视频两侧会挂两条大黑边。 */
.movie-wrap { display: flex; justify-content: center; }
.movie-player {
  max-height: 62vh; max-width: 100%; display: block;
  background: #000; border-radius: 12px; border: 1px solid rgba(var(--tint), .1);
}
.movie-meta {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  margin-top: 12px; font-size: 11.5px; color: var(--text-2); flex-wrap: wrap;
}
.movie-meta .dim { color: var(--dim); }
.movie-acts { display: flex; gap: 8px; justify-content: flex-end; margin-top: 16px; flex-wrap: wrap; }
.movie-acts .btn { padding: 8px 14px; font-size: 12.5px; }

.menu {
  position: fixed; z-index: 300; min-width: 240px;
  background: var(--surface-2);
  border: 1px solid rgba(var(--tint),.1);
  border-radius: 12px; box-shadow: var(--shadow-lg);
  padding: 5px;
  animation: pop .12s ease-out;
}
@keyframes pop { from { opacity: 0; transform: translateY(-5px); } }
.menu-item {
  display: flex; align-items: center; gap: 9px;
  width: 100%; text-align: left;
  padding: 8px 10px; border: none; background: transparent;
  border-radius: 8px; font-size: 12px; color: var(--text-2);
}
.menu-item:hover { background: var(--accent); color: #fff; }
.menu-item:hover .m-ico { background: rgba(var(--tint),.22); color: #fff; }
.menu-item .m-ico {
  width: 22px; height: 22px; border-radius: 6px;
  background: color-mix(in srgb, var(--nc, #888) 22%, transparent);
  color: var(--nc, #888);
  display: grid; place-items: center; font-size: 11px; flex-shrink: 0;
}
.menu-item .m-ico .ico { width: 13px; height: 13px; }
.menu-item .dim { margin-left: auto; }
.menu-item:hover .dim { color: rgba(var(--tint),.85); }
/* 润色菜单：当前选中的改法打勾，带二级菜单的项右侧露箭头 */
.menu-item.on { color: var(--text); }
.menu-item.on .m-ico { background: rgba(106,92,255,.24); color: #8ea9ff; }
.m-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.m-check { display: grid; place-items: center; color: #8ea9ff; flex-shrink: 0; }
.m-check .ico { width: 12px; height: 12px; stroke-width: 2.2; }
.m-arrow { display: grid; place-items: center; color: var(--dim); flex-shrink: 0; }
.m-arrow .ico { width: 11px; height: 11px; }
.menu-item:hover .m-arrow { color: #fff; }
.menu.submenu { min-width: 200px; z-index: 320; animation: none; }
.menu-sep { height: 1px; background: rgba(var(--tint),.1); margin: 5px 4px; }
.menu-search {
  width: 100%; border: none; background: var(--surface-input);
  border-radius: 9px; padding: 9px 11px; margin-bottom: 5px;
  outline: none; font-size: 12px;
}
.menu-search:focus { box-shadow: 0 0 0 2px rgba(106,92,255,.32); }
.menu-list { max-height: 330px; overflow: auto; }

/* ══════════════ 模型选择器（点开是一列型号，悬停时下面展开一行说明） ══════════════
   照参考站的交互：型号名一行，鼠标停上去，那一项**下面**才长出描述。
   说明默认高度 0（grid-template-rows 0fr），hover 时到 1fr —— 用 grid 动画而不是
   max-height，是因为描述有一行也有两行，max-height 得猜一个够大的值，展开速度会不一致。 */
.cp-picker {
  display: inline-flex; align-items: center; gap: 5px;
  max-width: 186px; text-align: left;
}
/* 品牌标：14px 线稿，跟着按钮的文字颜色走 */
.cp-brand {
  flex-shrink: 0; width: 14px; height: 14px;
  display: grid; place-items: center;
  color: var(--bc, var(--text-2));
}
.cp-brand .brand-ico { width: 14px; height: 14px; }
.cp-picker:hover .cp-brand, .cp-picker.is-open .cp-brand { color: var(--bc, var(--text)); filter: brightness(1.15); }
/* 档位胶囊（768P / 2K / 1080p）：和型号名分开，扫的时候不用读完整串 */
.cp-tag {
  flex-shrink: 0; font-size: 9.5px; line-height: 1.6; padding: 0 5px;
  border-radius: 5px; background: rgba(var(--tint),.1); color: var(--dim);
}
.cp-picker:hover .cp-tag { color: var(--text-2); }
.cp-picker .cp-pick-t { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cp-picker .cp-caret { flex-shrink: 0; font-size: 9px; line-height: 1; color: var(--dim); }
.cp-picker:hover .cp-caret { color: var(--text-2); }
.cp-picker.is-open { border-color: rgba(106,92,255,.55); }

.mp-pop {
  position: fixed; z-index: 420; width: 306px; max-width: calc(100vw - 16px);
  background: var(--surface-2);
  border: 1px solid rgba(var(--tint),.1);
  border-radius: 13px; box-shadow: var(--shadow-lg);
  padding: 6px; animation: pop .12s ease-out;
}
.mp-head { display: flex; align-items: baseline; justify-content: space-between; padding: 4px 8px 5px; }
.mp-head b { font-size: 11.5px; font-weight: 600; color: var(--text-2); }
.mp-hint { font-size: 10px; color: var(--dim); }
.mp-list { overflow: auto; overscroll-behavior: contain; padding-bottom: 2px; }
/* 还能往下滚时底部渐隐：最后一行被切一半看起来像坏了，而不是「还有内容」 */
.mp-list.more {
  -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 22px), transparent);
  mask-image: linear-gradient(to bottom, #000 calc(100% - 22px), transparent);
}
/* 型号合并成「一行一个模型」后，视频还有 13 行 —— 组头和行距各收 2px，
   一屏能多装两三行，免得用户以为「下面没了」。 */
.mp-group { font-size: 10px; color: var(--dim); padding: 5px 8px 2px; letter-spacing: .06em; }
.mp-row {
  display: grid; grid-template-columns: 1fr auto; align-items: start;
  width: 100%; text-align: left; border: none; background: transparent;
  border-radius: 8px; padding: 5px 8px; color: var(--text-2);
  transition: background .13s, color .13s;
}
.mp-row:hover, .mp-row.kbd { background: rgba(var(--tint),.07); color: var(--text); }
/* 行首的小品牌标：和输入条上那枚一样，帮着扫型号归属 */
/* 行首的品牌标：18px 圆角底板 + 品牌色。
   一水的灰太素，扫列表分不出谁是谁；每个牌子一个主色之后，
   眼睛先认颜色再认字，横扫一遍就知道这组都是 MiniMax。
   --bc / --bc-bg / --bc-line 由 picker.js 按品牌写进行内 style。 */
.mp-brand {
  flex-shrink: 0; width: 18px; height: 18px;
  display: grid; place-items: center;
  border-radius: 5px;
  background: var(--bc-bg, rgba(var(--tint), .07));
  box-shadow: inset 0 0 0 1px var(--bc-line, rgba(var(--tint), .06));
  color: var(--bc, var(--text-2));
  transition: background .13s, color .13s, box-shadow .13s;
}
.mp-brand .brand-ico { width: 13px; height: 13px; }
.mp-row:hover .mp-brand { box-shadow: inset 0 0 0 1px var(--bc, rgba(var(--tint), .12)); }
/* 选中行：标铺满品牌色 + 白图标，整行左侧那条也跟着换成品牌色，
   这样「选中的是 Kling」和「Kling 是蓝的」是同一件事，不会打架。 */
.mp-row.on .mp-brand { background: var(--bc, var(--accent)); color: #fff; box-shadow: none; }
.mp-row.on { color: var(--text); box-shadow: inset 2px 0 0 var(--bc, var(--accent)); }
.mp-top { display: flex; align-items: center; gap: 6px; min-width: 0; }
/* min-width:0 不能省：flex 子项默认 min-width:auto，名字一长就不收缩，
   「MiniMax H3 Regeneration」会被菜单右边直接切掉，连省略号都没有。 */
.mp-name { font-size: 12.5px; font-weight: 500; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mp-tag {
  flex-shrink: 0; font-size: 9.5px; line-height: 1.5; padding: 0 5px;
  border-radius: 5px; background: rgba(var(--tint),.1); color: var(--dim);
}
.mp-price {
  margin-left: 8px; padding-top: 2px; flex-shrink: 0;
  font-size: 10.5px; color: var(--dim); font-variant-numeric: tabular-nums; white-space: nowrap;
}
.mp-desc {
  grid-column: 1 / -1; display: grid; grid-template-rows: 0fr;
  opacity: 0; margin-top: 0;
  transition: grid-template-rows .16s ease, opacity .16s ease, margin-top .16s ease;
}
.mp-desc > span { overflow: hidden; font-size: 11px; line-height: 1.55; color: var(--dim); }
.mp-row:hover .mp-desc, .mp-row.kbd .mp-desc { grid-template-rows: 1fr; opacity: 1; margin-top: 4px; }
.mp-row:hover .mp-desc > span, .mp-row.kbd .mp-desc > span { color: var(--text-2); }

/* ── 画幅面板：三列小卡片，每张画一个按比例的方框 ── */
.rp-pop { width: 286px; }
.rp-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; padding: 2px; }
.rp-item {
  display: flex; flex-direction: column; align-items: center; gap: 5px;
  border: 1px solid rgba(var(--tint),.08); background: transparent;
  border-radius: 10px; padding: 8px 4px 7px; color: var(--text-2);
  transition: background .13s, border-color .13s, color .13s;
}
.rp-item:hover { background: rgba(var(--tint),.06); color: var(--text); }
.rp-item.on {
  border-color: rgba(106,92,255,.62); background: rgba(106,92,255,.14); color: var(--text);
}
.rp-box { height: 30px; display: grid; place-items: center; }
.rp-box i { display: block; border: 1.5px solid currentColor; border-radius: 3px; opacity: .9; }
.rp-box i.rp-any { width: 26px; height: 26px; border-style: dashed; }
.rp-name { font-size: 11.5px; font-weight: 500; }
.rp-desc {
  font-size: 9.5px; line-height: 1.35; color: var(--dim); text-align: center;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.rp-item.on .rp-desc { color: var(--text-2); }
.tg-pop { width: 292px; }
.tg-list { display: flex; flex-direction: column; gap: 2px; padding: 2px; }
.tg-row {
  display: flex; align-items: center; gap: 10px; width: 100%;
  text-align: left; border: none; background: transparent;
  border-radius: 9px; padding: 8px 9px; color: var(--text-2);
}
.tg-row:hover { background: rgba(var(--tint),.06); color: var(--text); }
.tg-row:disabled { opacity: .45; cursor: default; }
.tg-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.tg-label { font-size: 12.5px; font-weight: 500; }
.tg-desc { font-size: 10.5px; line-height: 1.45; color: var(--dim); }
.tg-switch {
  position: relative; flex-shrink: 0; width: 30px; height: 17px;
  border-radius: 9px; background: rgba(var(--tint),.16); transition: background .16s;
}
.tg-switch::after {
  content: ''; position: absolute; top: 2px; left: 2px;
  width: 13px; height: 13px; border-radius: 50%; background: #fff; transition: transform .16s;
}
.tg-row.on .tg-switch { background: var(--accent); }
.tg-row.on .tg-switch::after { transform: translateX(13px); }

.rp-note {
  margin: 4px 4px 2px; padding-top: 7px; border-top: 1px solid rgba(var(--tint),.07);
  font-size: 10px; line-height: 1.5; color: var(--dim);
}


/* ------------------------------- 设置面板 ------------------------------- */
.set-row { margin-bottom: 18px; }
.set-h { display: flex; align-items: center; gap: 8px; font-size: 12px; margin-bottom: 9px; }
.set-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 9px; }
.set-field { display: flex; flex-direction: column; gap: 4px; font-size: 11px; color: var(--dim); }
.set-field.wide { grid-column: span 2; }
.set-field input, .set-field select {
  background: var(--surface-input); border: 1px solid rgba(var(--tint),.07);
  border-radius: 8px; padding: 7px 10px; outline: none; font-size: 12px; color: var(--text);
}
.set-field input:focus, .set-field select:focus { border-color: var(--accent); }
/* 默认模型那一排：和输入框同尺寸的按钮，点开的是自绘型号面板 */
.set-pick {
  display: flex; align-items: center; justify-content: space-between; gap: 6px;
  width: 100%; text-align: left; cursor: pointer;
  background: var(--surface-input); border: 1px solid rgba(var(--tint),.07);
  border-radius: 8px; padding: 7px 10px; font-size: 12px; color: var(--text);
}
.set-pick:hover { border-color: rgba(var(--tint),.18); }
.set-pick.is-open { border-color: var(--accent); }
.set-pick .set-pick-t { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.set-pick .set-pick-c { flex-shrink: 0; font-size: 9px; line-height: 1; color: var(--dim); }
.set-prov { border: 1px solid rgba(var(--tint),.06); border-radius: var(--r); padding: 13px; margin-bottom: 10px; background: rgba(var(--tint),.035); }
.set-note { grid-column: span 2; font-size: 11px; color: var(--dim); margin: 4px 0 0; line-height: 1.6; }
.set-note code, .modal-body code {
  font-family: var(--mono); font-size: 10.5px;
  background: var(--surface-input); padding: 1px 5px; border-radius: 5px; border: 1px solid rgba(var(--tint),.06);
}
.switch { position: relative; display: inline-flex; cursor: pointer; }
.switch input { position: absolute; opacity: 0; }
.switch span { width: 32px; height: 18px; border-radius: 10px; background: rgba(var(--tint),.16); transition: .18s; position: relative; display: block; }
.switch span::after {
  content: ''; position: absolute; top: 2px; left: 2px;
  width: 14px; height: 14px; border-radius: 50%; background: #8b8b96; transition: .18s;
}
.switch input:checked + span { background: var(--accent); }
.switch input:checked + span::after { left: 16px; background: #fff; }

/* --------------------------- 体检 / 工程 / 队列 --------------------------- */
.audit-summary { display: flex; gap: 8px; margin-bottom: 14px; flex-wrap: wrap; }
.badge { font-size: 11px; padding: 4px 11px; border-radius: 8px; }
.badge.err { background: rgba(255,107,127,.16); color: var(--err); }
.badge.warn { background: rgba(255,184,77,.16); color: var(--warn); }
.badge.info { background: rgba(106,92,255,.2); color: #9db4ff; }
.audit-list { display: flex; flex-direction: column; gap: 6px; }
.audit-item {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px; border-radius: 9px;
  background: rgba(var(--tint),.04); border: 1px solid var(--line);
  font-size: 12px;
}
.audit-item .dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; }
.audit-item.lv-error .dot { background: var(--err); }
.audit-item.lv-warn .dot { background: var(--warn); }
.audit-item.lv-info .dot { background: var(--accent); }
.audit-item span:nth-child(2) { flex: 1; }

/* --------------------------- 快捷键面板 / 帮助面板 --------------------------- */
.key-group { margin-bottom: 18px; }
.key-group h4 {
  font-size: 12px; font-weight: 600; color: var(--text-2);
  margin: 0 0 9px; letter-spacing: .04em;
}
.key-row {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 8px 12px; border-radius: 9px;
  background: rgba(var(--tint),.04);
  font-size: 12px; color: var(--text-2);
  margin-bottom: 5px;
}
.key-row span { flex: 1; }
.key-row kbd, kbd {
  font-family: var(--ui);
  font-size: 11px; color: var(--text);
  background: rgba(var(--tint),.08);
  border: 1px solid rgba(var(--tint),.1);
  border-radius: 6px; padding: 3px 8px;
  white-space: nowrap;
}
.help-lead p { font-size: 12.5px; line-height: 1.85; color: var(--text-2); margin: 0 0 16px; }
.help-lead b { color: var(--text); }
.help-steps { margin: 0; padding-left: 20px; font-size: 12.5px; line-height: 1.9; color: var(--text-2); }
.help-steps b { color: var(--text); }
.help-p { font-size: 12.5px; line-height: 1.85; color: var(--text-2); margin: 0; }
.help-p code {
  font-family: var(--mono); font-size: 11px;
  background: rgba(0,0,0,.4); padding: 1px 6px; border-radius: 5px;
  border: 1px solid var(--line);
}

.proj-list { display: flex; flex-direction: column; gap: 6px; }
.proj-row {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px; border-radius: 9px;
  background: rgba(var(--tint),.04); border: 1px solid var(--line); font-size: 12px;
}
.proj-row span:first-child { flex: 1; font-weight: 500; }
.proj-row.active { border-color: var(--accent); }

.q-list { display: flex; flex-direction: column; gap: 6px; margin-top: 12px; }
.q-row { display: flex; justify-content: space-between; padding: 10px 12px; border-radius: 9px; background: rgba(var(--tint),.04); border: 1px solid var(--line); font-size: 12px; }

/* ------------------------------- Toast ------------------------------- */
#toasts {
  position: fixed; bottom: 78px; left: 50%; transform: translateX(-50%);
  z-index: 400; display: flex; flex-direction: column; gap: 8px; align-items: center;
  pointer-events: none;
}
.toast {
  background: var(--surface-2);
  border: 1px solid rgba(var(--tint),.1);
  color: var(--text);
  padding: 9px 17px; border-radius: 10px; font-size: 12px;
  box-shadow: var(--shadow-lg);
  opacity: 0; transform: translateY(8px); transition: .22s;
  max-width: 520px;
}
.toast.in { opacity: 1; transform: none; }
.toast-error { border-color: rgba(255,107,127,.42); color: #ffc6ce; }
.toast-info { border-color: rgba(106,92,255,.45); }

.scrim { position: fixed; inset: 0; z-index: 38; display: none; }
.scrim.on { display: block; }

/* ══════════════════════════ 添加节点菜单（照搬 libtv） ══════════════════════════ */
.add-menu { width: 268px; padding: 8px; }
.menu-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 4px 8px 8px; font-size: 12px; color: var(--text-2);
}
.m-search-ico { display: grid; place-items: center; color: var(--dim); }
.m-search-ico .ico { width: 14px; height: 14px; }
.add-menu .menu-search { margin-bottom: 6px; }
.add-menu .menu-list { max-height: 420px; }
.menu-item { padding: 9px 10px; }
.m-label { flex: 1; }
.m-badge {
  font-size: 9.5px; padding: 1px 6px; border-radius: 5px;
  background: rgba(var(--tint),.12); color: var(--text-2);
  letter-spacing: .02em;
}
.m-badge.new { background: rgba(28,200,134,.2); color: var(--ok); }
.menu-item:hover .m-badge { background: rgba(var(--tint),.25); color: #fff; }
.m-chev { color: var(--dim); font-size: 14px; line-height: 1; }
.menu-group-h {
  font-size: 10.5px; color: var(--dim); padding: 8px 10px 4px;
  letter-spacing: .06em;
}
.submenu { min-width: 150px; }
.submenu .menu-item { padding: 8px 12px; }

/* ══════════════════════════ 角色库（照搬 libtv） ══════════════════════════ */
.modal-card.wide { max-width: 1040px; }
#charlib { display: flex; flex-direction: column; min-height: 460px; }

.charlib-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 0 14px;
}
.charlib-tabs { display: flex; align-items: center; gap: 14px; }
.charlib-tabs button {
  border: none; background: transparent; color: var(--dim);
  font-size: 14px; font-weight: 500; padding: 4px 0; position: relative;
}
.charlib-tabs button.on { color: var(--text); }
.charlib-tabs button.on::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: -6px;
  height: 2px; background: var(--text); border-radius: 2px;
}
.charlib-tabs button:not(.on)::before {
  content: ''; position: absolute; right: -8px; top: 6px;
  width: 1px; height: 12px; background: rgba(var(--tint),.14);
}

.charlib-bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; padding-bottom: 14px; border-bottom: 1px solid var(--line);
  flex-wrap: wrap;
}
.charlib-filters { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.filter-chip {
  position: relative;
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 11px; border-radius: 999px;
  background: rgba(var(--tint),.07);
  color: var(--text-2); font-size: 12px;
  cursor: pointer; user-select: none;
}
.filter-chip:hover, .filter-chip.open { background: rgba(var(--tint),.14); color: var(--text); }
.filter-chip.set { background: rgba(106,92,255,.22); color: #c3d3ff; }
.filter-chip .caret { font-size: 9px; color: var(--dim); }
.filter-pop {
  display: none; position: absolute; top: calc(100% + 6px); left: 0;
  min-width: 128px; z-index: 20;
  background: var(--surface-2); border: 1px solid rgba(var(--tint),.1);
  border-radius: 10px; padding: 5px; box-shadow: var(--shadow-lg);
}
.filter-chip.open .filter-pop { display: block; }
.filter-pop button {
  display: block; width: 100%; text-align: left;
  border: none; background: transparent; color: var(--text-2);
  padding: 7px 10px; border-radius: 7px; font-size: 12px;
}
.filter-pop button:hover { background: rgba(var(--tint),.1); color: var(--text); }
.search-inline {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 5px 12px; border-radius: 999px;
  background: rgba(var(--tint),.07); color: var(--dim);
}
.search-inline .ico { width: 14px; height: 14px; }
.search-inline input {
  border: none; background: transparent; outline: none;
  width: 96px; font-size: 12px; color: var(--text);
}
.view-modes { display: flex; gap: 2px; }

.charlib-body {
  flex: 1; overflow: auto; padding: 18px 2px; min-height: 260px;
  display: grid; gap: 16px; align-content: start;
}
.charlib-body.view-grid { grid-template-columns: repeat(auto-fill, minmax(148px, 1fr)); }
.charlib-body.view-rows { grid-template-columns: 1fr; gap: 8px; }
.charlib-body.view-table { grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 10px; }

.char-card {
  cursor: pointer; border-radius: 12px; padding: 8px;
  border: 1px solid transparent; transition: .15s;
}
.char-card:hover { background: rgba(var(--tint),.06); border-color: var(--line); }
.char-thumb {
  aspect-ratio: 3/4; border-radius: 10px; overflow: hidden;
  background: var(--media-bg);
  display: grid; place-items: center;
  border: 1px solid rgba(var(--tint),.06);
}
.char-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.mannequin { width: 62%; display: grid; place-items: center; }
.mannequin-svg { width: 100%; height: auto; display: block; }
.char-meta { padding: 9px 4px 2px; }
.char-name { font-size: 12.5px; color: var(--text); }
.char-role { font-size: 11px; color: var(--dim); margin-top: 2px; }

.charlib-body.view-rows .char-card { display: flex; align-items: center; gap: 14px; }
.charlib-body.view-rows .char-thumb { width: 52px; aspect-ratio: 1; border-radius: 8px; flex-shrink: 0; }
.charlib-body.view-rows .mannequin { width: 70%; }
.charlib-body.view-rows .char-meta { padding: 0; }

.charlib-body.view-table .char-card {
  display: flex; align-items: center; gap: 12px;
  background: rgba(var(--tint),.04); border-color: var(--line); padding: 10px;
  border-radius: 10px;
}
.charlib-body.view-table .char-thumb { width: 46px; aspect-ratio: 1; border-radius: 8px; flex-shrink: 0; }
.charlib-body.view-table .char-meta { padding: 0; }

.charlib-foot {
  display: flex; justify-content: center;
  padding-top: 16px; border-top: 1px solid var(--line);
}
.charlib-foot .btn {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 10px 26px; border-radius: 10px; font-size: 13px;
}
.charlib-foot .btn .ico { width: 15px; height: 15px; }

/* ══════════════════ 响应式：空间不够时依次收字，绝不重叠 ══════════════════ */
.pill-label-short { display: none; }

@media (max-width: 1400px) {
  .pill-label { display: none; }
  .pill-label-short { display: inline; }
  .pill-btn { padding: 0 9px; }
  /* 工具集合：先收间距，再收按钮，最后才收图标 —— 不隐藏任何功能 */
  .tool-strip { gap: 8px; padding: 6px; }
  .tool-strip .icon-btn { width: 29px; height: 29px; }
}

@media (max-width: 1180px) {
  .tool-strip { gap: 5px; padding: 6px; border-radius: 12px; }
  .tool-strip .icon-btn { width: 28px; height: 28px; }
  .tool-strip .icon-btn .ico { width: 16px; height: 16px; }
  .strip-sep { margin: 0; }
}

@media (max-width: 1100px) {
  .dock-label { display: none; }
  .dock-item { padding: 0 9px; gap: 0; }
  .agent-orb { padding: 0 10px 0 4px; }
  .bb-left, .bb-right { gap: 4px; }
}

@media (max-width: 980px) {
  .pill-label-short { display: none; }
  .orb-label { display: none; }
  .agent-orb { padding: 0 7px; }
  .tool-strip { gap: 3px; padding: 5px; }
  .tool-strip .icon-btn { width: 26px; height: 26px; }
  .tool-strip .icon-btn .ico { width: 16px; height: 16px; }
  .drawer { width: min(288px, calc(100vw - 24px)); }
  .drawer.right { width: min(322px, calc(100vw - 24px)); }
  .agent-panel { width: min(322px, calc(100vw - 24px)); }
  .engine-chip { max-width: 36vw; }
}

/* ══════════════════════════════════════════════════════════════════════════
   首页（打开网站先看到的那一屏）
   参照 libtv 首页的三段式：新建画布 / 能力入口 / 最近项目；
   砍掉了积分、会员、社区、活动位这些与本工作台无关的内容，所以比 libtv 精简。
   配色沿用画布页那一套深色语言，不引入第二套主题。
   ══════════════════════════════════════════════════════════════════════════ */
.home {
  position: fixed; inset: 0; z-index: 100;
  display: none; flex-direction: column;
  background: var(--canvas);
  overflow: hidden;
}
body.home-mode .home { display: flex; }
/* 首页时把画布那一整套收起来，避免两套界面叠在一起 */
body.home-mode .viewport,
body.home-mode .topbar,
body.home-mode .bottombar,
body.home-mode .canvas-hint,
body.home-mode .minimap,
body.home-mode .sel-bar,
body.home-mode .drawer,
body.home-mode .agent-panel,
body.home-mode .task-drawer,
body.home-mode .mode-tip { display: none !important; }

/* 顶部一层极淡的冷光，纯 #141414 会显得太平 */
.home::before {
  content: ''; position: absolute; left: 0; right: 0; top: 0; height: 460px;
  background: radial-gradient(58% 100% at 50% 0%, rgba(106,92,255,.10), transparent 72%);
  pointer-events: none;
}

.home-top {
  /* z-index 必须高于 .home-scroll（同为 1 时后出现的滚动层会盖住头部，
     账号下拉菜单虽然画得出来，但点击会被 home-scroll 吃掉 —— 表现为
     「点日间模式没反应」）。 */
  position: relative; z-index: 30;
  flex: 0 0 auto; height: 58px; padding: 0 24px;
  display: flex; align-items: center; justify-content: space-between;
}
.home-brand { display: flex; align-items: center; gap: 10px; }
.brand-logo {
  width: 30px; height: 30px; border-radius: 9px;
  background: linear-gradient(150deg, #3f6dff, #7b4dff);
  display: grid; place-items: center;
  box-shadow: 0 4px 14px rgba(63,109,255,.32);
  flex: 0 0 auto;
}
.brand-logo img { width: 20px; height: 20px; display: block; }
/* 英文名做成小字标，跟中文名拉开层级 */
.brand-en {
  font-size: 10px; font-weight: 500; letter-spacing: .08em;
  color: var(--dim); margin-left: 4px;
}
.brand-text { display: flex; flex-direction: column; line-height: 1.28; }
.brand-text b { font-size: 13.5px; font-weight: 500; letter-spacing: .04em; color: var(--text); }
.brand-text span { font-size: 11px; color: var(--dim); }
.home-top-right { display: flex; align-items: center; gap: 8px; }
.engine-chip.static { cursor: default; }
.engine-chip.static:hover { background: var(--surface); }

.home-scroll { position: relative; z-index: 1; flex: 1 1 auto; overflow-y: auto; overflow-x: hidden; }
.home-wrap {
  width: min(1060px, calc(100% - 48px));
  margin: 0 auto; padding: 8px 0 64px;
}

/* —— 首屏两个入口：左边「3 分钟出一条」（主），右边空画布（次） —— */
.home-hero {
  display: grid; grid-template-columns: minmax(0, 1fr) 240px; gap: 12px;
}
.home-start {
  position: relative; overflow: hidden;
  display: flex; flex-direction: column; align-items: flex-start; gap: 8px;
  height: 176px; padding: 20px 24px; text-align: left;
  border-radius: 18px;
  border: 1px solid rgba(106, 92, 255, .42);
  background:
    radial-gradient(520px 200px at 12% 0%, rgba(106, 92, 255, .3), transparent 72%),
    linear-gradient(180deg, rgba(106, 92, 255, .14), rgba(106, 92, 255, .05));
  transition: border-color .16s, transform .16s;
}
.home-start:hover { border-color: rgba(140, 120, 255, .85); transform: translateY(-1px); }
.hs-head { display: flex; align-items: center; gap: 9px; width: 100%; }
.hs-badge {
  font-size: 10.5px; color: #cfd9ff; background: rgba(106, 92, 255, .34);
  border-radius: 999px; padding: 2px 9px; letter-spacing: .02em;
}
.hs-time { font-size: 11px; color: rgba(255, 255, 255, .55); margin-left: auto; }
.hs-title { font-size: 23px; font-weight: 650; letter-spacing: .2px; color: #fff; }
.hs-sub { font-size: 12.5px; color: rgba(255, 255, 255, .62); line-height: 1.65; max-width: 520px; }
.hs-go {
  margin-top: auto; font-size: 12.5px; font-weight: 600; color: #fff;
  display: inline-flex; align-items: center; gap: 6px;
}
.home-new {
  height: 176px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px;
  background-color: rgba(var(--tint), .022);
  background-image: radial-gradient(rgba(var(--tint), .13) 1px, transparent 1px);
  background-size: 22px 22px;
  border: 1px solid rgba(var(--tint), .07);
  border-radius: 18px;
  transition: background-color .16s, border-color .16s;
}
.home-new:hover { background-color: rgba(var(--tint), .05); border-color: rgba(var(--tint), .16); }
.hn-box {
  width: 48px; height: 48px; border-radius: 14px;
  background: var(--invert-bg); color: var(--invert-fg);
  display: grid; place-items: center;
  transition: transform .16s;
}
.hn-box .ico { width: 20px; height: 20px; stroke-width: 2.1; }
.home-new:hover .hn-box { transform: translateY(-2px); }
.hn-label { font-size: 13px; color: var(--text-2); }
.hn-tip { font-size: 11px; color: var(--dim); }

/* —— 能力入口：每一条都真的落到画布上建节点 —— */
.home-quick {
  margin-top: 22px;
  display: grid; grid-template-columns: repeat(7, 1fr); gap: 10px;
}
.quick-item {
  height: 84px; border: none; border-radius: 14px;
  background: var(--surface-sunken);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 9px;
  transition: background .15s, transform .15s;
}
.quick-item:hover { background: var(--surface-2); transform: translateY(-1px); }
.quick-item .qi-ico { color: var(--nc, var(--text-2)); display: grid; place-items: center; }
.quick-item .qi-ico .ico { width: 21px; height: 21px; stroke-width: 1.6; }
.quick-item .qi-label { font-size: 12px; color: var(--text-2); }

/* —— 区块标题 —— */
.home-sec { margin-top: 32px; }
.home-sec-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; }
.home-sec-head h2 { margin: 0; font-size: 14px; font-weight: 600; color: var(--text); }
.home-link {
  display: flex; align-items: center; gap: 3px;
  border: none; background: none; color: var(--dim);
  font-size: 12.5px; padding: 4px 7px; border-radius: 7px;
}
.home-link:hover { background: rgba(var(--tint),.08); color: var(--text); }
.home-link .ico { width: 13px; height: 13px; }

/* 工程多了要能找得到：搜索框 + 排序切换（点一下换一种，不做下拉菜单） */
.home-sec-tools { display: flex; align-items: center; gap: 8px; }
.home-search {
  display: flex; align-items: center; gap: 6px;
  height: 30px; padding: 0 10px;
  background: var(--surface-sunken);
  border: 1px solid rgba(var(--tint),.07);
  border-radius: 9px; transition: border-color .15s;
}
.home-search:focus-within { border-color: var(--accent); }
.home-search .ico { width: 13px; height: 13px; color: var(--dim); flex-shrink: 0; }
.home-search input {
  width: 128px; border: none; background: none; outline: none;
  color: var(--text); font-size: 12.5px;
}
.home-search input::placeholder { color: var(--dim); }
.home-search input::-webkit-search-cancel-button { -webkit-appearance: none; }
.home-sort {
  height: 30px; padding: 0 11px;
  background: var(--surface-sunken);
  border: 1px solid rgba(var(--tint),.07);
  border-radius: 9px;
  color: var(--text-2); font-size: 12.5px;
  transition: .15s;
}
.home-sort:hover { background: var(--surface-2); color: var(--text); border-color: rgba(var(--tint),.14); }

/* —— 最近项目 —— */
.home-projects {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(196px, 1fr)); gap: 16px;
}
.hp-card {
  position: relative;
  border: none; background: none; padding: 0; text-align: left;
  display: flex; flex-direction: column; gap: 9px;
  cursor: pointer;
  user-select: none; /* 卡片现在是 div（里面要放删除键），不加这条拖一下会选中文字 */
}
.hp-card:focus-visible { outline: none; }
.hp-card:focus-visible .hp-cover { border-color: rgba(106,92,255,.55); }
.hp-cover {
  position: relative; aspect-ratio: 16 / 9; border-radius: 12px; overflow: hidden;
  background: var(--surface-sunken);
  border: 1px solid rgba(var(--tint),.06);
  display: grid; place-items: center;
  transition: border-color .15s, transform .15s;
}
.hp-card:hover .hp-cover { border-color: rgba(var(--tint),.2); transform: translateY(-2px); }
/* 封面图铺在点阵占位之上；图挂了就露出占位，不是一个白洞 */
.hp-cover img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
.hp-ph {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  color: #3f3f49;
  background-image: radial-gradient(rgba(var(--tint),.085) 1px, transparent 1px);
  background-size: 18px 18px;
}
.hp-ph .ico { width: 30px; height: 30px; stroke-width: 1.2; }
/* 当前正在编辑的那个工程，在首页标出来 */
.hp-card.is-current .hp-cover { border-color: rgba(106,92,255,.55); }
.hp-flag {
  position: absolute; left: 8px; top: 8px; z-index: 2;
  background: rgba(106,92,255,.92); color: #fff;
  font-size: 10px; line-height: 1.5; padding: 2px 7px; border-radius: 6px;
}
.hp-name { font-size: 12.5px; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hp-sub { font-size: 11px; color: var(--dim); }

/* 卡片右上角的删除键：平时藏着，悬浮 / 键盘聚焦 / 触屏才出来。
   放在 .hp-cover **外面**当兄弟节点 —— cover 是 overflow:hidden，塞进去气泡会被裁；
   但 cover 悬浮时会抬 2px，所以这里补一个同样的位移，两者一起动。 */
.hp-del {
  position: absolute; right: 8px; top: 8px; z-index: 3;
  width: 26px; height: 26px; padding: 0;
  display: grid; place-items: center;
  border: none; border-radius: 8px;
  background: rgba(16,16,16,.78);
  backdrop-filter: blur(6px);
  color: var(--text-2);
  opacity: 0; pointer-events: none;
  transition: opacity .12s, background .12s, color .12s, transform .15s;
}
.hp-del .ico { width: 14px; height: 14px; stroke-width: 1.5; }
.hp-card:hover .hp-del,
.hp-card:focus-within .hp-del { opacity: 1; pointer-events: auto; transform: translateY(-2px); }
.hp-del:hover { background: rgba(210,60,60,.95); color: #fff; }
/* 触屏没有 hover，直接常驻 */
@media (hover: none) { .hp-del { opacity: 1; pointer-events: auto; } }
/* 贴右的控件气泡也右对齐，否则窄窗口会顶出视口 */
.hp-del[data-tip]::after { left: auto; right: 0; transform: none; }
.hp-del[data-tip]::before { left: auto; right: 11px; transform: none; }
.home-empty {
  grid-column: 1 / -1; padding: 28px;
  border: 1px dashed rgba(var(--tint),.12); border-radius: 14px;
  text-align: center; font-size: 12.5px; color: var(--dim);
}

/* 首页顶部那枚设置键的气泡：朝下 + 贴右，否则窄窗口会超出视口 */
.home-top [data-tip]::after { bottom: auto; top: calc(100% + 10px); }
.home-top [data-tip]::before {
  bottom: auto; top: calc(100% + 5px);
  border-top-color: transparent; border-bottom-color: var(--tooltip-bg);
}
.home-top-right > :last-child[data-tip]::after { left: auto; right: 0; transform: none; }
.home-top-right > :last-child[data-tip]::before { left: auto; right: 14px; transform: none; }

@media (max-width: 1180px) { .home-quick { grid-template-columns: repeat(4, 1fr); } }
@media (max-width: 880px) {
  .home-sec-head { flex-wrap: wrap; gap: 10px; }
  .home-search input { width: 96px; }
}
@media (max-width: 760px) {
  .home-wrap { width: calc(100% - 28px); }
  .home-quick { grid-template-columns: repeat(3, 1fr); }
  .home-hero { grid-template-columns: 1fr; }
  .home-new { height: 120px; }
  .hs-title { font-size: 20px; }
  .brand-text span { display: none; }
}

@media (max-width: 760px) {
  .sync, .engine-detail { display: none; }
  .engine-chip { max-width: none; }
  .bb-left .view-cluster { display: none; }
}

/* 窄而矮的窗口：面板贴着上下栏 */
@media (max-height: 640px) {
  .drawer { top: 42px; bottom: 64px; }
  .agent-panel, .task-drawer { bottom: 64px; }
}


/* ============================================================
   节点上的生成进度条
   ------------------------------------------------------------
   云端生图一张要几十秒到几分钟，光有转圈按钮用户不知道跑到哪了。
   适配器会推「采样中… 12/20 步」，这里解析成百分比画成进度条。
   解析不到百分比（比如在加载模型）就走不确定态的来回滑动。
   ============================================================ */

.job-prog {
  margin-top: 8px;
  display: flex;
  flex-direction: column;
  gap: 5px;
  user-select: none;
}

.job-prog-bar {
  height: 3px;
  border-radius: 2px;
  background: var(--surface-sunken);
  overflow: hidden;
  position: relative;
}

.job-prog-bar > i {
  display: block;
  height: 100%;
  width: 0;
  border-radius: 2px;
  background: var(--accent);
  transition: width 0.25s ease;
}

/* 不确定态：左右来回滑，表示「在动但不知道到哪」 */
.job-prog-bar > i.indet {
  width: 36%;
  animation: job-prog-slide 1.15s ease-in-out infinite;
}

@keyframes job-prog-slide {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(278%); }
}

.job-prog-txt {
  font-size: 11px;
  color: var(--dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: 1.4;
}

/* ============================================================
   登录 / 注册
   ============================================================ */
.auth-gate {
  position: fixed; inset: 0; z-index: 900;
  display: grid; place-items: center;
  background: radial-gradient(1200px 700px at 50% -10%, rgba(63,109,255,.16), transparent 60%), var(--canvas);
  padding: 24px;
}
/* ⚠️ hidden 属性只是 UA 样式里的 display:none，会被下面的 display:grid/flex 覆盖，
   必须显式兜底 —— 否则登录层「隐藏」了还盖在页面上。 */
.auth-gate[hidden] { display: none; }
#auth-form label[hidden] { display: none; }

.auth-card {
  width: min(380px, 100%);
  background: var(--surface);
  border: 1px solid rgba(var(--tint),.08);
  border-radius: 18px;
  padding: 28px 26px 22px;
  box-shadow: 0 30px 80px rgba(0,0,0,.55);
}
.auth-logo {
  width: 44px; height: 44px; margin-bottom: 14px; padding: 9px; border-radius: 13px;
  /* mark.svg 是透明底纯白线条，设计前提就是放在品牌渐变上；
     不给底色的话，亮色主题下等于白底白线，整个 logo 消失。 */
  background: linear-gradient(150deg, #3f6dff, #7b4dff);
  box-shadow: 0 8px 22px rgba(63,109,255,.28);
}
.auth-logo img { width: 100%; height: 100%; display: block; }
.auth-card h1 { font-size: 19px; margin: 0 0 4px; font-weight: 500; letter-spacing: .12em; }
.auth-card h1 span { font-size: 12px; color: var(--dim); font-weight: 500; letter-spacing: 1px; }
.auth-sub { margin: 0 0 18px; font-size: 12px; color: var(--text-2); line-height: 1.6; }
.auth-tabs { display: flex; gap: 4px; background: var(--surface-sunken); padding: 3px; border-radius: 10px; margin-bottom: 16px; }
.auth-tabs button {
  flex: 1; padding: 7px; border-radius: 8px; font-size: 12.5px;
  color: var(--text-2); background: transparent; border: none; transition: .15s;
}
.auth-tabs button.on { background: var(--surface-hi); color: var(--text); font-weight: 550; }
#auth-form { display: flex; flex-direction: column; gap: 11px; }
#auth-form label { display: flex; flex-direction: column; gap: 5px; font-size: 11px; color: var(--dim); }
#auth-form input {
  background: var(--surface-input); border: 1px solid var(--line);
  border-radius: 9px; padding: 9px 11px; font-size: 13px; outline: none; color: var(--text);
}
#auth-form input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(106,92,255,.18); }
.auth-submit {
  margin-top: 4px; padding: 10px; border-radius: 9px; border: none;
  background: linear-gradient(135deg, #3f6dff, #6d5cff); color: #fff;
  font-size: 13px; font-weight: 600; transition: .15s;
}
.auth-submit:hover { filter: brightness(1.1); }
.auth-submit:disabled { opacity: .55; cursor: default; }
.auth-msg { min-height: 18px; margin-top: 10px; font-size: 11.5px; color: var(--err); line-height: 1.5; }
.auth-msg.ok { color: var(--ok); }
.auth-foot { margin: 10px 0 0; font-size: 10.5px; color: var(--dim); line-height: 1.6; }

/* ============================================================
   顶栏账号菜单
   ============================================================ */
.user-menu { position: relative; }
.user-chip {
  display: flex; align-items: center; gap: 7px;
  padding: 4px 9px 4px 4px; border-radius: 999px;
  background: rgba(var(--tint),.06); border: 1px solid var(--line);
  color: var(--text-2); font-size: 11.5px; transition: .15s;
}
.user-chip:hover { background: rgba(var(--tint),.11); color: var(--text); }
.user-avatar {
  width: 22px; height: 22px; border-radius: 50%; display: grid; place-items: center;
  background: linear-gradient(135deg, #3f6dff, #a78bfa);
  color: #fff; font-size: 11px; font-weight: 700;
}
.user-name { max-width: 90px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.user-caret { width: 12px; height: 12px; stroke: currentColor; fill: none; stroke-width: 2; opacity: .7; }
.user-drop {
  position: absolute; right: 0; top: calc(100% + 8px); z-index: 120;
  width: 218px; padding: 6px;
  background: var(--surface-2); border: 1px solid var(--line-hi);
  border-radius: 12px; box-shadow: 0 18px 50px rgba(0,0,0,.5);
  display: flex; flex-direction: column; gap: 1px;
}
.user-drop[hidden] { display: none; }
.user-drop-head {
  padding: 8px 10px 9px; display: flex; flex-direction: column; gap: 2px;
  border-bottom: 1px solid var(--line); margin-bottom: 4px;
}
.user-drop-head b { font-size: 12.5px; }
.user-drop-head span { font-size: 10.5px; color: var(--dim); }
.user-drop-head .drop-credits { margin-top: 4px; font-size: 11px; color: var(--text-2); }
.user-drop-head .drop-credits b { font-size: 11.5px; color: var(--warn); font-variant-numeric: tabular-nums; }
.user-drop-head .drop-credits[hidden] { display: none; }
.user-drop button {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 8px 10px; border-radius: 8px; font-size: 12px; text-align: left;
  background: transparent; border: none; color: var(--text-2);
}
.user-drop button:hover { background: rgba(var(--tint),.07); color: var(--text); }
.user-drop button.danger { color: var(--err); }
.user-drop button.danger:hover { background: rgba(255,107,127,.12); }
.user-drop-sep { height: 1px; background: var(--line); margin: 4px 2px; }
.udot { width: 6px; height: 6px; border-radius: 50%; background: var(--ok); }
.udim { font-size: 10px; color: var(--dim); }

/* ============================================================
   团队面板 / 管理后台
   ============================================================ */
/* ---- 个人资料面板（昵称 + 头像） ---- */
.pf-wrap { display: flex; gap: 16px; align-items: flex-start; padding: 4px 0 2px; }
.pf-av {
  width: 64px; height: 64px; border-radius: 50%; flex: none; padding: 0;
  display: grid; place-items: center; overflow: hidden; cursor: pointer;
  background: linear-gradient(135deg, #3f6dff, #a78bfa);
  color: #fff; font-size: 22px; font-weight: 700; border: 1px solid var(--line);
}
.pf-av img { width: 100%; height: 100%; object-fit: cover; }
.pf-av:hover { filter: brightness(1.06); }
.pf-fields { flex: 1; min-width: 0; }
.pf-label { display: flex; flex-direction: column; gap: 6px; font-size: 11px; color: var(--dim); }
.pf-label input {
  font: inherit; font-size: 13px; color: var(--ink);
  background: var(--surface-input); border: 1px solid var(--line); border-radius: 8px;
  padding: 8px 10px; outline: none;
}
.pf-label input:focus { border-color: var(--accent); }
.pf-tip { margin: 8px 0 0; font-size: 11px; color: var(--dim); line-height: 1.5; }
.pf-tip.err { color: var(--err); }

.team-sec { margin-bottom: 4px; }
.team-sec + .team-sec {
  margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--line);
}
.team-sec-title { font-size: 11px; letter-spacing: .06em; color: var(--dim); margin-bottom: 8px; }
.team-new-row { display: flex; gap: 8px; margin-top: 12px; }
.team-new-row input {
  flex: 1; min-width: 0; font: inherit; font-size: 12px;
  background: var(--surface-input); border: 1px solid var(--line);
  color: var(--ink); border-radius: 8px; padding: 7px 10px; outline: none;
}
.team-new-row input:focus { border-color: var(--accent); }
.team-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.team-code-row {
  display: flex; align-items: center; gap: 8px; margin: 14px 0 12px;
  padding: 8px 11px; background: var(--surface-sunken); border-radius: 9px; font-size: 11.5px;
}
.team-code-row span { color: var(--dim); }
.team-code-row code { flex: 1; font-family: ui-monospace, monospace; font-size: 12.5px; letter-spacing: 1px; }
.team-members { display: flex; flex-direction: column; gap: 2px; max-height: 300px; overflow: auto; }
.team-row { display: flex; align-items: center; gap: 9px; padding: 7px 4px; border-bottom: 1px solid var(--line); }
.team-row:last-child { border-bottom: none; }
.team-row-name { flex: 1; display: flex; flex-direction: column; gap: 1px; font-size: 12px; }
/* 团队列表里的行是可点的：点一下只换「看谁」，不换工作区 */
.team-row.pick { cursor: pointer; border-radius: 8px; padding-left: 6px; padding-right: 6px; outline: none; }
.team-row.pick:hover { background: var(--surface-sunken); }
.team-row.pick.on { background: var(--surface-sunken); }
.team-row.pick.on .team-row-name { font-weight: 600; }
.team-row.pick:focus-visible { box-shadow: 0 0 0 2px rgba(var(--tint),.35); }
.team-row-go { color: var(--dim); font-size: 14px; line-height: 1; padding: 0 4px; }
.chip-mini {
  font-size: 10px; padding: 2px 7px; border-radius: 999px;
  border: 1px solid var(--line); color: var(--dim); white-space: nowrap;
}
.chip-mini.ok { color: var(--ok); border-color: rgba(28,200,134,.35); }
.chip-mini.err { color: var(--err); border-color: rgba(255,107,127,.35); }
.mini.danger { color: var(--err); }
.mini.danger:hover { background: rgba(255,107,127,.12); }

.admin-stats { display: grid; grid-template-columns: repeat(5, 1fr); gap: 8px; }
.admin-stat {
  background: var(--surface-sunken); border-radius: 10px; padding: 10px 12px;
  display: flex; flex-direction: column; gap: 2px;
}
.admin-stat b { font-size: 18px; font-weight: 650; letter-spacing: .5px; }
.admin-stat span { font-size: 10px; color: var(--dim); }
.admin-tabs { display: flex; gap: 4px; margin: 16px 0 10px; border-bottom: 1px solid var(--line); }
.admin-tabs button {
  padding: 7px 11px; font-size: 12px; color: var(--dim);
  background: transparent; border: none; border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.admin-tabs button.on { color: var(--text); border-bottom-color: var(--accent); }
.admin-list { display: flex; flex-direction: column; max-height: 360px; overflow: auto; }
.admin-row {
  display: flex; align-items: center; gap: 9px; padding: 8px 4px;
  border-bottom: 1px solid var(--line);
}
.admin-row:last-child { border-bottom: none; }
.admin-row-main { flex: 1; display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.admin-row-main b { font-size: 12px; font-weight: 550; }
.admin-row-main .udim { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* 管理后台 · 注册设置区块 */
.reg-setting {
  margin-bottom: 14px; padding: 11px 13px;
  background: var(--surface-sunken); border-radius: 10px;
  border: 1px solid var(--line);
}
.reg-setting-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; margin-bottom: 9px;
}
.reg-setting-head b { font-size: 12.5px; }
.reg-setting-row { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.reg-setting-row code {
  flex: 1; min-width: 140px;
  font-family: ui-monospace, monospace; font-size: 14px; letter-spacing: 2px;
  padding: 6px 10px; border-radius: 7px;
  background: var(--surface-input); color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ---- 清理未引用资产 ---- */
.orph-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
  gap: 8px; max-height: 52vh; overflow-y: auto; padding-right: 4px;
}
.orph-item {
  position: relative; aspect-ratio: 16/10; border-radius: 7px; overflow: hidden;
  border: 1px solid var(--line); background: rgba(var(--tint), .04);
  display: grid; place-items: center;
}
.orph-item img { width: 100%; height: 100%; object-fit: cover; display: block; }
.orph-size {
  position: absolute; right: 4px; bottom: 4px;
  padding: 1px 5px; border-radius: 6px;
  background: rgba(0, 0, 0, .62); color: #cbd5e1; font-size: 9px;
}

/* 角色卡的第二动作（音色试听）：比主按钮轻一档，不抢「生成四视图」 */
.run-btn.ghost {
  background: rgba(var(--tint), .06);
  border: 1px solid rgba(var(--tint), .14);
  color: var(--fg);
  opacity: .85;
}
.run-btn.ghost:hover { opacity: 1; border-color: var(--accent); }

/* 回门户的小胶囊 */
.portal-home{
  flex: none;
  display: inline-flex; align-items: center; gap: 3px;
  font-size: 12px; letter-spacing: .04em; font-weight: 500;
  color: var(--text-2); text-decoration: none;
  padding: 4px 11px 4px 8px;
  border: 1px solid var(--line-hi); border-radius: 999px;
  background: var(--surface);
  margin-right: 2px;
  transition: color .15s, border-color .15s, background .15s;
}
.portal-home svg{
  width: 12px; height: 12px; flex: none;
  fill: none; stroke: currentColor; stroke-width: 2.2;
  stroke-linecap: round; stroke-linejoin: round;
}
.portal-home:hover{
  color: var(--text); border-color: var(--accent); background: var(--accent-soft);
}
/* ---- 画布文字随缩放补偿 ----
   卡片宽度是世界坐标里的固定值，字号按 --nt 放大之后，缩到 0.5 倍时屏幕上的字
   才不会碎成一片。--nt 由 canvas.applyView 按缩放档位写入（1 / 1.3 / 1.7），
   只放大文字，预览图框照旧跟着缩放走。 */
.world { --nt: 1; }
.node-title { font-size: calc(12px * var(--nt)); }
.node-title .nt-ico .ico { width: calc(13px * var(--nt)); height: calc(13px * var(--nt)); }
.field label { font-size: calc(10.5px * var(--nt)); }
.field input[type="text"], .field input[type="number"], .field textarea, .field select {
  font-size: calc(12px * var(--nt));
  padding: calc(5px * var(--nt)) calc(9px * var(--nt));
}
.field textarea { min-height: calc(34px * var(--nt)); }
.asset-sum b { font-size: calc(12px * var(--nt)); }
.asset-sum span { font-size: calc(11px * var(--nt)); }
.media-hint { font-size: calc(12px * var(--nt)); }
.try-item { font-size: calc(11.5px * var(--nt)); }
/* ---- 出片进度条（按依赖顺序跑的时候挂在底部） ---- */
.pipe-bar {
  position: fixed; left: 50%; bottom: 96px; transform: translate(-50%, 12px);
  display: flex; align-items: center; gap: 10px;
  padding: 9px 12px 9px 14px; border-radius: 12px;
  background: var(--surface-2); border: 1px solid rgba(var(--tint), .12);
  box-shadow: 0 18px 40px rgba(0, 0, 0, .55);
  font-size: 12.5px; color: var(--text); z-index: 60;
  opacity: 0; pointer-events: none; transition: opacity .18s, transform .18s;
}
.pipe-bar.on { opacity: 1; transform: translate(-50%, 0); pointer-events: auto; }
.pipe-bar .pb-dot {
  width: 7px; height: 7px; border-radius: 50%; background: var(--accent);
  box-shadow: 0 0 0 4px rgba(106, 92, 255, .18);
  animation: pbPulse 1.4s ease-in-out infinite;
}
@keyframes pbPulse { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
.pipe-bar .pb-count { color: var(--text-2); font-variant-numeric: tabular-nums; }
.pipe-bar .pb-x {
  background: none; border: none; color: var(--dim); cursor: pointer;
  font-size: 12px; padding: 2px 4px; border-radius: 6px; line-height: 1;
}
.pipe-bar .pb-x:hover { background: rgba(var(--tint), .1); color: var(--text); }

/* ================= 首页 v2：作品墙 =================
   设计取向：一屏之内尽量是「画面」，文字只留标题和一行说明。
   卡片=一张真实生成图 + 标题，点击直接进向导并预选 —— 不再是说明书式的入口。 */
.fy-hero { display: grid; grid-template-columns: minmax(0,2.05fr) minmax(0,1fr); gap: 14px; margin-bottom: 30px; }

.fy-main {
  position: relative; overflow: hidden; text-align: left;
  height: 232px; border-radius: 18px; padding: 0;
  border: 1px solid rgba(var(--tint), .10);
  background: #14161c; cursor: pointer;
}
.fy-main-bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; transition: transform .5s ease; }
.fy-main:hover .fy-main-bg { transform: scale(1.035); }
.fy-veil {
  position: absolute; inset: 0;
  background: linear-gradient(100deg, rgba(8,9,12,.92) 8%, rgba(8,9,12,.62) 46%, rgba(8,9,12,.18) 82%),
              linear-gradient(0deg, rgba(8,9,12,.75), transparent 55%);
}
.fy-main-body { position: absolute; left: 26px; bottom: 24px; display: flex; flex-direction: column; gap: 8px; max-width: 62%; }
.fy-main-body b { font-size: 23px; font-weight: 650; letter-spacing: .3px; color: #fff; }
.fy-main-body em { font-size: 12.5px; font-style: normal; color: rgba(255,255,255,.72); line-height: 1.5; }
.fy-cta {
  align-self: flex-start; margin-top: 6px; padding: 7px 15px; border-radius: 999px;
  font-size: 12.5px; font-weight: 600; color: #fff;
  background: linear-gradient(135deg, #3f6dff, #7b4dff);
}

.fy-side { display: grid; gap: 14px; grid-template-rows: 1fr; }
.fy-side-card {
  position: relative; overflow: hidden;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 9px;
  border-radius: 18px; border: 1px dashed rgba(var(--tint), .18);
  background: rgba(var(--tint), .022); color: var(--text-2);
  cursor: pointer; transition: background .16s, border-color .16s;
}
.fy-side-card:hover { background: rgba(var(--tint), .06); border-color: rgba(var(--tint), .3); color: var(--text); }
.fy-side-ico { width: 40px; height: 40px; border-radius: 12px; display: grid; place-items: center; background: rgba(var(--tint), .08); }
.fy-side-ico svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
.fy-side-card b { font-size: 13px; font-weight: 600; }
.fy-side-card em { font-size: 11.5px; font-style: normal; color: var(--dim); }

.fy-sec { margin-bottom: 30px; }
.fy-sec-head { display: flex; align-items: baseline; gap: 12px; margin-bottom: 14px; }
.fy-sec-head h2 { font-size: 14.5px; font-weight: 600; letter-spacing: .02em; }
.fy-sec-sub { font-size: 11.5px; color: var(--dim); }
.fy-more {
  margin-left: auto; display: inline-flex; align-items: center; gap: 3px;
  background: none; border: none; padding: 0; cursor: pointer;
  font-size: 12px; color: var(--dim);
}
.fy-more:hover { color: var(--text); }
.fy-more svg { width: 13px; height: 13px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }

.fy-concepts { display: grid; grid-template-columns: repeat(5, minmax(0,1fr)); gap: 12px; }
.fy-card {
  position: relative; overflow: hidden; padding: 0; cursor: pointer;
  aspect-ratio: 16 / 10; border-radius: 13px;
  border: 1px solid rgba(var(--tint), .08); background: #14161c;
}
.fy-card img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform .45s ease, opacity .2s; opacity: .92; }
.fy-card:hover img { transform: scale(1.06); opacity: 1; }
.fy-card:hover { border-color: rgba(122,96,255,.55); }
.fy-card.is-loading { pointer-events: none; }
.fy-card.is-loading::after {
  content: "正在铺工作流…"; position: absolute; inset: 0; display: grid; place-items: center;
  background: rgba(6, 7, 10, .64); color: #fff; font-size: 12px; letter-spacing: .04em;
}
.fy-card-cap {
  position: absolute; left: 0; right: 0; bottom: 0; padding: 18px 11px 9px;
  font-size: 12px; font-weight: 500; color: #fff; text-align: left;
  background: linear-gradient(0deg, rgba(6,7,10,.9), rgba(6,7,10,.35) 55%, transparent);
}

/* 最近项目：固定 5 列放一行，多了走「查看全部」 */
.home-projects { grid-template-columns: repeat(5, minmax(0,1fr)); }

@media (max-width: 1180px) {
  .fy-concepts { grid-template-columns: repeat(4, minmax(0,1fr)); }
  .home-projects { grid-template-columns: repeat(4, minmax(0,1fr)); }
}
@media (max-width: 900px) {
  .fy-hero { grid-template-columns: 1fr; }
  .fy-main { height: 200px; }
  .fy-side-card { min-height: 92px; }
  .fy-concepts { grid-template-columns: repeat(3, minmax(0,1fr)); }
  .home-projects { grid-template-columns: repeat(3, minmax(0,1fr)); }
}

/* 最近项目不足一行时补的「新建」格：虚线，和工程卡同高 */
.hp-new {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 7px;
  aspect-ratio: 16 / 9; border-radius: 12px; cursor: pointer;
  border: 1px dashed rgba(var(--tint), .16); background: rgba(var(--tint), .015);
  color: var(--dim); font-size: 12px; transition: background .15s, border-color .15s, color .15s;
}
.hp-new:hover { background: rgba(var(--tint), .05); border-color: rgba(var(--tint), .3); color: var(--text); }
.hp-new-plus { font-size: 20px; line-height: 1; }

/* 梗卡：静态封面 + 悬停播放的预览片。两层叠在一起，靠 opacity 切换，
   不做 display 切换 —— 那样每次移开会闪一下白。 */
.fy-card-img, .fy-card-v { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.fy-card-v { opacity: 0; transition: opacity .25s ease; pointer-events: none; }
.fy-card-v.on { opacity: 1; }
.fy-card:hover .fy-card-img { transform: none; }

/* ================= 升 2K =================
   视频节点出片后浮在右上角的一个小胶囊。
   放右上不放右下：右下是播放器进度条的位置，会挡住拖拽。 */
.node-upscale {
  position: absolute; top: 8px; right: 8px; z-index: 2;
  display: inline-flex; align-items: center; gap: 4px;
  padding: 4px 9px 4px 7px; border-radius: 999px; cursor: pointer;
  font-size: 11px; line-height: 1; color: #fff;
  background: rgba(10, 11, 16, .66);
  border: 1px solid rgba(255, 255, 255, .2);
  backdrop-filter: blur(6px);
  transition: background .15s, border-color .15s, transform .15s;
}
.node-upscale:hover { background: rgba(106, 92, 255, .88); border-color: transparent; transform: translateY(-1px); }
.node-upscale .nu-ico { display: inline-flex; }
.node-upscale .nu-ico svg { width: 11px; height: 11px; }

/* 升 2K 的确认弹层 */
.up-lead { font-size: 13px; color: var(--text); margin: 0 0 10px; }
.up-list { margin: 0 0 18px; padding-left: 18px; font-size: 12.5px; color: var(--text-2); line-height: 1.8; }
.up-list li::marker { color: var(--dim); }
.up-list b { color: var(--text); font-weight: 600; }
.up-acts { display: flex; gap: 8px; justify-content: flex-end; }
