/* AI 原生组件自动编排平台 工作流编辑器。外观照 JeecgBoot 门户，细则见 docs/STYLE_PORTAL.md“编辑器与工厂页”。
 * 颜色只用 app.css 里 :root 的变量：先取门户的新变量，外壳还没定义时退回旧变量，再退回参考图取样的值。
 * 类名一律 afe- 开头，不依赖外壳的类。卡片圆角 6，按钮与输入框 4，标签 2；卡片只用细边框，浮层才有阴影。 */
.afe, .afe-pop, .afe-pop-gone, .afe-dr, .afe-foot, .afe-ghost, .afe-cc, .afe-v, .afe-fx-mask {
  /* 动效照外壳的规范 docs/MOTION.md，外壳没定义时用同样的值 */
  --afe-ease: var(--ease-out, cubic-bezier(.16, 1, .3, 1));
  --afe-ease-in: var(--ease-in, cubic-bezier(.55, 0, 1, .45));
  --afe-move: var(--ease-move, cubic-bezier(.65, 0, .35, 1));
  --afe-panel: var(--ease-panel, cubic-bezier(.32, .72, 0, 1));
  --afe-primary: var(--primary, #3685F2);
  --afe-primary-hover: var(--primary-hover, #4A91F3);
  --afe-primary-active: var(--primary-active, #3075D5);
  --afe-primary-bg: var(--primary-bg, #EAF2FD);
  --afe-on-primary: var(--on-primary, #fff);
  --afe-page: var(--page, var(--bg, #F7F8FA));
  --afe-card: var(--card, var(--surface, #fff));
  --afe-border: var(--border, var(--line2, #E8EAED));
  --afe-divider: var(--divider, var(--line2, #F2F4F7));
  --afe-input: var(--input-border, var(--line, #D0D4DA));
  --afe-ink: var(--ink, #232E40);
  --afe-ink2: var(--ink2, #3D4D66);
  --afe-ink3: var(--ink3, #647185);
  --afe-ink4: var(--ink4, var(--ink3, #9EA6B2));
  --afe-danger: var(--danger, #E65251);
  --afe-red: var(--red, #E65251);
  --afe-orange: var(--orange, #FAAA39);
  --afe-indigo: var(--indigo, #1E4092);
  --afe-sky: var(--sky, #23BEEF);
  --afe-success: var(--success, #13CD66);
  --afe-success-ink: var(--success-ink, #0D9047);
  --afe-success-bg: var(--success-bg, #E1F4E7);
  --afe-sky-ink: var(--sky-ink, #1885A7);
  --afe-orange-ink: var(--orange-ink, #AF7728);
  --afe-edge: var(--afe-ink4);
  /* 压白字白图标的实心块用按钮底色，深色下不跟文字蓝一起提亮 */
  --afe-primary-fill: var(--btn-pri, var(--afe-primary));
  --afe-coral: var(--coral, #E65251);
  --afe-cell: var(--grid-cell, #F4F8FE);
  --afe-cell-line: #D7E7FC;
  --afe-node-line: #DCDFE4;
  --afe-dot: #D0D4DA;
  --afe-th-bg: var(--th-bg, #F7F8FA);
  --afe-head-bg: var(--grey-bg, #F2F4F7);
  --afe-side-shadow: -6px 0 16px rgba(0, 0, 0, .08);
  --afe-hover: var(--hover, #F2F4F7);
  --afe-code: var(--th-bg, #F7F8FA);
  --afe-red-bg: var(--red-bg, #FFECEC);
  --afe-orange-bg: var(--orange-bg, #FEEED7);
  --afe-sky-bg: var(--sky-bg, #E9F8FD);
  --afe-grey-bg: var(--grey-bg, #F2F4F7);
  --afe-shadow: var(--pop-shadow, 0 6px 16px rgba(0, 0, 0, .08));
  --afe-ring: 0 0 0 2px var(--focus-ring, rgba(54, 133, 242, .2));
  --afe-r: 4px; --afe-rc: 6px; --afe-rt: 2px;
  --afe-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
}
/* 深色：外壳的变量自己换值，这里只换编辑器自己的两样：格子虚线与节点边框 */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) :is(.afe, .afe-pop, .afe-pop-gone, .afe-dr, .afe-foot, .afe-ghost, .afe-cc, .afe-v, .afe-fx-mask) { --afe-edge: var(--afe-ink3); --afe-cell-line: #292F45; --afe-node-line: var(--border, #363E55); --afe-dot: #292F45; --afe-side-shadow: -6px 0 16px rgba(0, 0, 0, .45); }
}
:root[data-theme="dark"] :is(.afe, .afe-pop, .afe-pop-gone, .afe-dr, .afe-foot, .afe-ghost, .afe-cc, .afe-v, .afe-fx-mask) { --afe-edge: var(--afe-ink3); --afe-cell-line: #292F45; --afe-node-line: var(--border, #363E55); --afe-dot: #292F45; --afe-side-shadow: -6px 0 16px rgba(0, 0, 0, .45); }

.afe {
  position: relative; display: flex; flex-direction: column; gap: 12px; height: 100%; min-height: 320px; overflow: hidden;
  background: var(--afe-page); color: var(--afe-ink); font-size: 14px; line-height: 22px;
}
.afe.afe-pad { padding: 12px; }
.afe *, .afe *::before, .afe *::after, .afe-pop, .afe-pop *, .afe-pop-gone, .afe-pop-gone *, .afe-dr *, .afe-foot *, .afe-fx-mask, .afe-fx-mask *, .afe-fx-mask *::before, .afe-fx-mask *::after { box-sizing: border-box; }
:where(.afe, .afe-pop, .afe-pop-gone, .afe-dr, .afe-foot, .afe-fx-mask) :where(button, input, select, textarea) { font: inherit; color: inherit; }
.afe-i { width: 20px; height: 20px; fill: currentColor; flex: none; display: block; }
.afe-mono { font-family: var(--mono, var(--afe-mono)); font-size: 12.5px; }
.afe-muted { color: var(--afe-ink3); }
.afe [hidden], .afe-pop [hidden], .afe-pop-gone [hidden], .afe-dr [hidden], .afe-foot [hidden], .afe-fx-mask [hidden] { display: none !important; }
@keyframes afe-fade { from { opacity: 0; } }
@keyframes afe-pop-in { from { opacity: 0; transform: translateY(var(--afe-pdy, -4px)) scale(.97); } }
@keyframes afe-pop-out { to { opacity: 0; transform: scale(.98); } }
@keyframes afe-icon { from { opacity: 0; transform: scale(.4); } }

/* 按钮：主按钮主色实心白字；普通按钮白底灰框，悬停框与字变主色；危险按钮红框红字；文字按钮主色字无框 */
.afe-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px; height: 32px; padding: 0 15px; flex: none;
  border: 1px solid var(--afe-input); border-radius: var(--afe-r); background: var(--afe-card); color: var(--afe-ink);
  font-size: 14px; font-weight: 400; line-height: 22px; cursor: pointer; white-space: nowrap; text-decoration: none;
  transition: color .12s ease, border-color .12s ease, background-color .12s ease, transform .14s var(--afe-ease);
}
.afe-btn:active:not(.dis) { transform: scale(.97); transition-duration: .06s; }
.afe-btn:hover { color: var(--afe-primary); border-color: var(--afe-primary); text-decoration: none; }
.afe-btn:active { color: var(--afe-primary-active); border-color: var(--afe-primary-active); }
.afe-btn.pri { background: var(--afe-primary-fill); border-color: var(--afe-primary-fill); color: var(--afe-on-primary); }
.afe-btn.pri:hover { background: var(--afe-primary-hover); border-color: var(--afe-primary-hover); color: var(--afe-on-primary); }
.afe-btn.pri:active { background: var(--afe-primary-active); border-color: var(--afe-primary-active); }
.afe-btn.danger { color: var(--afe-danger); border-color: var(--afe-danger); }
.afe-btn.danger:hover { color: var(--afe-danger); border-color: var(--afe-danger); background: color-mix(in srgb, var(--afe-danger) 8%, var(--afe-card)); }
.afe-btn.txt { border-color: transparent; background: none; color: var(--afe-primary); padding: 0 8px; }
.afe-btn.txt:hover { color: var(--afe-primary-hover); border-color: transparent; }
.afe-btn.txt.danger { color: var(--afe-danger); }
.afe-btn.txt.danger:hover { background: none; }
.afe-btn.sm { height: 24px; padding: 0 7px; font-size: 13px; }
.afe-btn .afe-i { width: 16px; height: 16px; }
.afe-btn[data-on="true"] .afe-i { color: var(--afe-primary); }
.afe-btn.dis, .afe-btn.dis:hover, .afe-btn.pri.dis, .afe-btn.pri.dis:hover {
  color: var(--afe-ink4); background: var(--afe-th-bg); border-color: var(--afe-input); cursor: not-allowed;
}
.afe-btn.dis .afe-i { color: inherit; }
.afe-btn.txt.dis, .afe-btn.txt.dis:hover { background: none; border-color: transparent; }
.afe-btn .afe-spin { width: 14px; height: 14px; }
.afe-ib {
  width: 32px; height: 32px; flex: none; display: inline-flex; align-items: center; justify-content: center; padding: 0;
  border: 0; border-radius: var(--afe-r); background: none; color: var(--afe-ink3); cursor: pointer; transition: color .12s ease, background-color .12s ease, transform .14s var(--afe-ease);
}
.afe-ib:hover { background: var(--afe-hover); color: var(--afe-primary); text-decoration: none; }
.afe-ib:active:not(.dis) { transform: scale(.9); transition-duration: .06s; }
.afe-ib.dis, .afe-ib.dis:hover { color: var(--afe-ink4); background: none; cursor: not-allowed; opacity: .6; }
.afe-ib .afe-i { width: 18px; height: 18px; }
.afe-spin { display: inline-block; width: 16px; height: 16px; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: afe-spin .8s linear infinite; flex: none; }
@keyframes afe-spin { to { transform: rotate(360deg); } }

/* 标签：2 像素圆角，12 号字；失败红底白字，其余浅底加对应色的字 */
.afe-tag { display: inline-flex; align-items: center; gap: 4px; height: 20px; padding: 0 4px; border-radius: var(--afe-rt); font-size: 12px; line-height: 20px; font-weight: 400; white-space: nowrap; flex: none; }
.afe-tag.ok { color: var(--afe-success-ink); background: var(--afe-success-bg); }
.afe-tag.bad { color: #fff; background: var(--afe-red); }
.afe-tag.run { color: var(--afe-sky-ink); background: var(--afe-sky-bg); }
.afe-tag.wait, .afe-tag.orange { color: var(--afe-orange-ink); background: var(--afe-orange-bg); }
.afe-tag.off { color: var(--afe-ink3); background: var(--afe-grey-bg); }
.afe-tag.teal { color: var(--afe-primary); background: var(--afe-primary-bg); }
.afe-tag .afe-spin { width: 10px; height: 10px; border-width: 1.5px; }

/* 平台方块图标：18 像素彩色圆角方块，白色图标 */
.afe-pic { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; border-radius: var(--afe-r); color: #fff; background: var(--afe-ink4); }
.afe-pic .afe-i { width: 12px; height: 12px; }
.afe-pic.pc-indigo { background: var(--afe-indigo); }
.afe-pic.pc-sky { background: var(--afe-sky); }
.afe-pic.pc-orange { background: var(--afe-orange); }
.afe-pic.pc-coral { background: var(--afe-coral); }
.afe-pic.pc-teal { background: var(--afe-primary-fill); }
.afe-pic.pc-grey { background: var(--afe-ink4); }

/* 输入框：高 32，4 像素圆角，聚焦时主色框加 2 像素浅主色外圈 */
.afe-in {
  display: block; width: 100%; height: 32px; padding: 4px 11px; border: 1px solid var(--afe-input); border-radius: var(--afe-r);
  background: var(--afe-card); color: var(--afe-ink); outline: 0; min-width: 0; line-height: 22px; transition: border-color .2s, box-shadow .2s;
}
.afe-in:hover { border-color: var(--afe-primary-hover); }
.afe-in:focus { border-color: var(--afe-primary); box-shadow: var(--afe-ring); }
textarea.afe-in { height: auto; min-height: 56px; padding: 4px 11px; resize: vertical; }
textarea.afe-in.afe-mono { line-height: 20px; }
select.afe-in { padding: 0 6px 0 8px; }
.afe-in.bad, .afe-in.bad:hover { border-color: var(--afe-red); }
.afe-in.bad:focus { border-color: var(--afe-red); box-shadow: 0 0 0 2px color-mix(in srgb, var(--afe-red) 20%, transparent); }
.afe-in:disabled, .afe-in[readonly] { background: var(--afe-th-bg); color: var(--afe-ink3); border-color: var(--afe-input); }
.afe-in:disabled:hover, .afe-in[readonly]:hover { border-color: var(--afe-input); }
.afe-in[readonly]:focus { box-shadow: none; border-color: var(--afe-input); }
.afe-in::placeholder { color: var(--afe-ink4); }
.afe-check { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; user-select: none; min-height: 32px; }
.afe-check input { width: 16px; height: 16px; margin: 0; accent-color: var(--afe-primary); cursor: pointer; }
.afe-check input:disabled { cursor: not-allowed; }
/* 开关：照门户的写法，圆头 */
.afe-sw { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; user-select: none; min-height: 32px; }
.afe-sw input {
  appearance: none; -webkit-appearance: none; width: 44px; height: 22px; border-radius: 11px; background: var(--afe-ink4); border: 0;
  position: relative; cursor: pointer; margin: 0; flex: none; transition: background-color .2s;
}
.afe-sw input::after { content: ""; position: absolute; top: 2px; left: 2px; width: 18px; height: 18px; border-radius: 50%; background: #fff; transition: left .2s; box-shadow: 0 2px 4px rgba(35, 46, 64, .2); }
.afe-sw input:checked { background: var(--afe-primary-fill); }
.afe-sw input:checked::after { left: 24px; }
.afe-sw input:focus-visible { box-shadow: var(--afe-ring); outline: 0; }
.afe-sw input:disabled { cursor: not-allowed; opacity: .5; }
.afe-sw.dis { cursor: not-allowed; color: var(--afe-ink4); }
/* 取值方式：参数标题右边一个引用图标，引用上游字段时主色底白图标 */
.afe-bind {
  display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 24px; padding: 0; flex: none;
  border: 1px solid transparent; border-radius: var(--afe-r); background: none; color: var(--afe-ink4); cursor: pointer; transition: color .15s, background-color .15s, border-color .15s;
}
.afe-bind .afe-i { width: 16px; height: 16px; }
.afe-bind:hover { color: var(--afe-primary); background: var(--afe-hover); }
.afe-bind.on { color: var(--afe-on-primary); background: var(--afe-primary-fill); }
.afe-bind.on:hover { background: var(--afe-primary-hover); color: var(--afe-on-primary); }
.afe-bind:focus-visible { outline: 0; box-shadow: var(--afe-ring); }
.afe-bind:disabled { cursor: not-allowed; opacity: .5; }

/* 工具条：白色卡片，左边工作流名，右边按钮组 */
.afe-head {
  flex: none; display: flex; align-items: center; gap: 8px 16px; min-height: 56px; padding: 8px 16px 8px 12px; position: relative; z-index: 3;
  background: var(--afe-card); border: 1px solid var(--afe-border); border-radius: var(--afe-rc);
}
.afe-titles { display: flex; align-items: center; gap: 4px 12px; flex: 1 1 auto; min-width: 0; }
.afe-name {
  display: block; flex: 0 1 auto; width: 200px; min-width: 64px; max-width: 400px; height: 32px; padding: 0 8px;
  border: 1px solid transparent; border-radius: var(--afe-r); background: none; color: var(--afe-ink); outline: 0;
  font-size: 16px; font-weight: 600; line-height: 30px; text-overflow: ellipsis; transition: border-color .2s, box-shadow .2s;
}
.afe-name:hover { border-color: var(--afe-input); }
.afe-name:focus { border-color: var(--afe-primary); box-shadow: var(--afe-ring); background: var(--afe-card); }
.afe-name[readonly]:hover, .afe-name[readonly]:focus { border-color: transparent; box-shadow: none; }
.afe-meas { position: absolute; left: -9999px; top: 0; visibility: hidden; white-space: pre; pointer-events: none; }
.afe-meta { display: flex; align-items: center; gap: 12px; flex: none; min-height: 32px; font-size: 13px; color: var(--afe-ink3); white-space: nowrap; }
.afe-ver {
  display: inline-flex; align-items: center; gap: 4px; height: 24px; padding: 0 4px; border: 0; border-radius: var(--afe-r);
  background: none; color: var(--afe-ink3); font-size: 13px; cursor: pointer; transition: color .2s;
}
.afe-ver .afe-i { width: 15px; height: 15px; }
.afe-ver:hover { color: var(--afe-primary); }
.afe-ver.dis, .afe-ver.dis:hover { color: var(--afe-ink3); cursor: default; }
.afe-ver.dis .afe-i { display: none; }
.afe-dirty { display: inline-flex; align-items: center; gap: 6px; min-width: 4em; color: var(--afe-ink3); }
.afe-dirty::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--afe-orange); flex: none; }
.afe-dirty { transition: opacity .2s ease, visibility 0s; }
.afe-dirty.off { visibility: hidden; opacity: 0; transition: opacity .2s ease, visibility 0s linear .2s; }
.afe-vchip {
  display: inline-flex; align-items: center; gap: 4px; height: 24px; padding: 0 4px; border: 0; border-radius: var(--afe-r);
  background: none; color: var(--afe-ink2); cursor: pointer; font-size: 13px; white-space: nowrap;
}
.afe-vchip:hover { color: var(--afe-primary); }
.afe-vchip .afe-i { width: 16px; height: 16px; }
.afe-vchip .e { color: var(--afe-red); } .afe-vchip .w { color: var(--afe-orange); } .afe-vchip .ok { color: var(--afe-success-ink); }
.afe-vchip span + .afe-i { margin-left: 6px; }
.afe-acts { display: flex; align-items: center; gap: 8px; margin-left: auto; flex: none; }
.afe-acts .afe-more { display: none; }
.afe-acts .afe-ib.afe-more { width: 32px; height: 32px; border: 1px solid var(--afe-input); }
.afe-prog { position: absolute; left: 6px; right: 6px; bottom: -1px; height: 2px; overflow: hidden; }
.afe-prog.on::after { content: ""; display: block; height: 100%; width: 30%; background: var(--afe-primary); animation: afe-prog 1.2s infinite ease-in-out; }
@keyframes afe-prog { 0% { transform: translateX(-100%); } 100% { transform: translateX(340%); } }

/* 主体：一张白卡，左组件面板，中间画布，右设置面板 */
.afe-body {
  flex: 1; min-height: 0; display: flex; position: relative; overflow: hidden;
  background: var(--afe-card); border: 1px solid var(--afe-border); border-radius: var(--afe-rc);
}
/* 外壳给了右侧对话栏时：画布与对话左右排，二比一，中间留 12 像素；对话栏的样子归外壳 */
.afe-split { flex: 1; min-height: 0; display: flex; gap: 12px; position: relative; }
.afe-split > .afe-body { flex: 2 1 0; min-width: 0; }
.afe.small .afe-split { gap: 8px; }

/* 组件面板：搜索，用途页签，按平台分组的清单 */
.afe-pal { width: 232px; flex: none; display: flex; flex-direction: column; min-height: 0; background: var(--afe-card); border-right: 1px solid var(--afe-border); z-index: 2; }
.afe-pal-s { flex: none; display: flex; align-items: center; gap: 4px; padding: 12px 12px 4px; }
.afe-search {
  flex: 1; display: flex; align-items: center; gap: 6px; height: 32px; padding: 0 11px; min-width: 0;
  border: 1px solid var(--afe-input); border-radius: var(--afe-r); background: var(--afe-card); transition: border-color .2s, box-shadow .2s;
}
.afe-search:hover { border-color: var(--afe-primary-hover); }
.afe-search:focus-within { border-color: var(--afe-primary); box-shadow: var(--afe-ring); }
.afe-search .afe-i { width: 16px; height: 16px; color: var(--afe-ink4); }
.afe-search input { flex: 1; min-width: 0; border: 0; outline: 0; background: none; height: 28px; padding: 0; color: var(--afe-ink); }
.afe-search input::placeholder { color: var(--afe-ink4); }
.afe-pal-x { display: none; }
.afe-pal-c.afe-ib { width: 28px; height: 32px; color: var(--afe-ink4); }
.afe.small .afe-pal-c { display: none; }
.afe.afe-palc .afe-pal { display: none; }
.afe.afe-palc .afe-cvbtns { display: flex; }
.afe.afe-palc .afe-cv > .afe-note:not([hidden]) ~ .afe-cvbtns { top: 60px; }
/* 用途页签：全部，读取，处理，AI，写入。下划线标出当前一项 */
.afe-roles { flex: none; display: flex; gap: 11px; padding: 0 12px; border-bottom: 1px solid var(--afe-border); }
.afe-roles button {
  position: relative; height: 36px; padding: 0 1px; border: 0; background: none; color: var(--afe-ink2); font-size: 13px; cursor: pointer;
  white-space: nowrap; transition: color .2s;
}
.afe-roles button:hover { color: var(--afe-primary); }
.afe-roles button.on { color: var(--afe-primary); font-weight: 500; }
.afe-roles button.on::after { content: ""; position: absolute; left: 0; right: 0; bottom: -1px; height: 2px; background: var(--afe-primary); }
.afe-roles button:focus-visible { outline: 0; box-shadow: var(--afe-ring); border-radius: var(--afe-rt); }
.afe-pal-list { flex: 1; min-height: 0; overflow-y: auto; padding: 4px 0 16px; touch-action: pan-y; }
.afe-pg-h {
  display: flex; align-items: center; gap: 8px; width: 100%; height: 38px; padding: 0 12px 0 14px; border: 0; background: none;
  color: var(--afe-ink); font-size: 13px; font-weight: 600; cursor: pointer; text-align: left;
}
.afe-pg-h:hover { color: var(--afe-primary); }
.afe-pg-h .gt { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.afe-pg-c { flex: none; width: 16px; height: 16px; margin-left: auto; color: var(--afe-ink4); transition: transform .2s; }
.afe-pg.shut .afe-pg-c { transform: rotate(-90deg); }
.afe-pg.shut .afe-pi { display: none; }
.afe-pi {
  position: relative; display: flex; align-items: center; gap: 8px; height: 34px; padding: 0 12px 0 40px; cursor: grab;
  user-select: none; -webkit-user-select: none; font-size: 13.5px; color: var(--afe-ink2); outline: 0; transition: color .15s, background-color .15s;
}
.afe-pi:hover, .afe-pi:focus-visible { background: var(--afe-primary-bg); color: var(--afe-primary); }
.afe-pi:active { cursor: grabbing; }
.afe-pi .t { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.afe-pi.ro { cursor: default; }
.afe-pal-none { padding: 16px; color: var(--afe-ink3); font-size: 13px; }

/* 组件卡：悬停组件面板的一项时浮在右边。说明，输入，输出，连接 */
.afe-cc {
  position: fixed; z-index: 72; width: 320px; max-height: calc(100vh - 16px); overflow: auto; padding: 12px 14px 12px; color: var(--afe-ink);
  background: var(--afe-card); border: 1px solid var(--afe-divider); border-radius: var(--afe-r); box-shadow: var(--afe-shadow);
  font-size: 13px; line-height: 20px; pointer-events: none; box-sizing: border-box; animation: afe-fade .16s ease-out both;
}
.afe-cc * { box-sizing: border-box; }
.afe-cc .afe-i { width: 16px; height: 16px; fill: currentColor; display: block; }
.afe-cc-h { display: flex; align-items: flex-start; gap: 10px; }
.afe-cc-h .afe-pic { width: 28px; height: 28px; margin-top: 1px; }
.afe-cc-h .tt { flex: 1; min-width: 0; }
.afe-cc-h .t { font-size: 14px; font-weight: 600; line-height: 20px; }
.afe-cc-h .s { font-size: 12px; line-height: 18px; color: var(--afe-ink3); }
.afe-cc-d { margin: 10px 0 0; color: var(--afe-ink2); display: -webkit-box; -webkit-line-clamp: 5; -webkit-box-orient: vertical; overflow: hidden; overflow-wrap: anywhere; }
.afe-cc-sub { margin: 12px 0 4px; font-size: 12px; color: var(--afe-ink3); }
.afe-cc-t { width: 100%; border-collapse: collapse; table-layout: fixed; }
.afe-cc-t td { padding: 3px 0; border-top: 1px solid var(--afe-divider); vertical-align: top; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.afe-cc-t td.tt .req { color: var(--afe-red); margin-left: 2px; font-family: SimSun, sans-serif; }
.afe-cc-t td.tt { color: var(--afe-ink2); padding-right: 8px; }
.afe-cc-t td.ty { width: 22%; text-align: right; color: var(--afe-ink4); font-size: 12px; }
.afe-cc-none { color: var(--afe-ink4); font-size: 12px; }
.afe-cc-c { display: flex; gap: 8px; margin-top: 12px; padding-top: 8px; border-top: 1px solid var(--afe-divider); font-size: 12px; color: var(--afe-ink2); }
.afe-cc-c .k { color: var(--afe-ink3); }

/* 画布：灰底点阵 */
.afe-cv { position: relative; flex: 1; min-width: 0; overflow: hidden; background: var(--afe-page); touch-action: none; outline: 0; user-select: none; -webkit-user-select: none; }
.afe-cv.panning { cursor: grabbing; }
.afe-grid { position: absolute; left: 0; top: 0; width: 100%; height: 100%; pointer-events: none; }
.afe-grid .dot { fill: var(--afe-dot); }
.afe-world { position: absolute; left: 0; top: 0; width: 0; height: 0; transform-origin: 0 0; }
.afe-edges, .afe-guides { position: absolute; left: 0; top: 0; width: 1px; height: 1px; overflow: visible; pointer-events: none; }
.afe-guides { z-index: 3; }
.afe-guides line { stroke: var(--afe-primary); stroke-width: 1; stroke-dasharray: 4 3; vector-effect: non-scaling-stroke; }
/* 连线：引用是实线，只连先后顺序的是虚线，开始节点连出去的是浅虚线；悬停，选中与连着选中节点的线用主色 */
.afe-e .hit { fill: none; stroke: transparent; stroke-width: 16; pointer-events: stroke; cursor: pointer; }
.afe-e .ln { fill: none; stroke: var(--afe-edge); stroke-width: 1.5; transition: stroke .15s; }
.afe-e .ar { fill: var(--afe-edge); stroke: none; transition: fill .15s; }
.afe-e.manual .ln { stroke-dasharray: 6 4; }
.afe-e.st .ln { stroke: var(--afe-ink4); stroke-dasharray: 2 4; }
.afe-e.st.ref .ln { stroke-dasharray: none; }
.afe-e.st .ar { fill: var(--afe-ink4); }
.afe-e.hov .ln, .afe-e.hl .ln { stroke: var(--afe-primary); } .afe-e.hov .ar, .afe-e.hl .ar { fill: var(--afe-primary); }
.afe-e.sel .ln { stroke: var(--afe-primary); stroke-width: 2.5; } .afe-e.sel .ar { fill: var(--afe-primary); }
.afe-e.ins .ln { stroke: var(--afe-primary); stroke-width: 3; } .afe-e.ins .ar { fill: var(--afe-primary); }
.afe-e.flow .ln { stroke: var(--afe-sky); stroke-dasharray: 6 5; animation: afe-flow .7s linear infinite; } .afe-e.flow .ar { fill: var(--afe-sky); }
/* 新连上的线从出口描到入口，箭头最后出来；虚线不好描，淡入。--d 是等多久再开始，重画时接着上一次的进度 */
.afe-e.afe-born:not(.manual):not(.st) .ln { stroke-dasharray: 1; stroke-dashoffset: 1; animation: afe-draw .46s var(--afe-ease) var(--d, 0s) both; }
.afe-e.afe-born .ar { animation: afe-fade .2s ease-out calc(var(--d, 0s) + .3s) both; }
.afe-e.afe-born.manual .ln, .afe-e.afe-born.st .ln { animation: afe-fade .36s ease-out var(--d, 0s) both; }
@keyframes afe-draw { to { stroke-dashoffset: 0; } }
@keyframes afe-flow { to { stroke-dashoffset: -11; } }
.afe-e.ro .hit { cursor: default; }
.afe-tmp { fill: none; stroke: var(--afe-primary); stroke-width: 1.5; stroke-dasharray: 5 4; }
.afe-tmp.on { stroke-dasharray: none; stroke-width: 2; }
/* 连线工具条：写传的字段，插入组件，删除 */
.afe-etools {
  position: absolute; z-index: 5; display: flex; align-items: center; transform: translate(-50%, calc(-100% - 10px)); padding: 1px;
  background: var(--afe-card); border: 1px solid var(--afe-border); border-radius: var(--afe-r); box-shadow: var(--afe-shadow); white-space: nowrap;
  animation: afe-fade .16s ease-out both;
}
/* 传的几项都写出来，一行放不下就换行，不截成省略号 */
.afe-elab { max-width: 280px; padding: 4px 8px; font-size: 12px; line-height: 18px; color: var(--afe-ink2); white-space: normal; overflow-wrap: anywhere; }
.afe-etools .afe-elab:not([hidden]) + button { border-left: 1px solid var(--afe-divider); border-top-left-radius: 0; border-bottom-left-radius: 0; }
.afe-etools button { width: 26px; height: 26px; display: flex; align-items: center; justify-content: center; padding: 0; border: 0; border-radius: var(--afe-rt); background: none; color: var(--afe-ink3); cursor: pointer; }
.afe-etools button + button { margin-left: 1px; }
.afe-etools .afe-i { width: 16px; height: 16px; }
.afe-etools .afe-eadd:hover { color: var(--afe-primary); background: var(--afe-hover); }
.afe-etools .afe-edel:hover { color: var(--afe-danger); background: var(--afe-hover); }

/* 节点卡片：白底，6 像素圆角，1 像素浅框。头部是平台图标，标题，平台与用途；下半是参数与输出 */
.afe-node, .afe-start {
  position: absolute; width: 248px; background: var(--afe-card); color: var(--afe-ink);
  border: 1px solid var(--afe-node-line); border-radius: var(--afe-rc); cursor: pointer; touch-action: none; transition: border-color .15s, box-shadow .15s, opacity .15s;
}
.afe-start { width: 208px; }
.afe-node:hover, .afe-start:hover { border-color: var(--afe-ink4); }
.afe-node.sel, .afe-start.sel { border-color: var(--afe-primary); box-shadow: 0 0 0 1px var(--afe-primary); }
/* 新放上的节点从小一圈长到原大，AI 放上来的一张接一张出来；--d 是先后 */
.afe-node.afe-born { animation: afe-node-in .4s var(--afe-ease) var(--d, 0s) both; }
@keyframes afe-node-in { from { opacity: 0; transform: translateY(6px) scale(.92); } }
/* AI 改过的节点：边框亮一下主色再退回 */
.afe-node.afe-hit { animation: afe-hit 1.4s ease-out var(--d, 0s) both; }
@keyframes afe-hit { 0%, 30% { border-color: var(--afe-primary); box-shadow: 0 0 0 1px var(--afe-primary); } }
/* 运行状态的小图标换了就弹一下 */
.afe-node .st > * { animation: afe-icon .32s var(--afe-ease) both; }
.afe-node.dragging { box-shadow: 0 0 0 1px var(--afe-primary), var(--afe-shadow); z-index: 2; }
.afe-node:focus-visible, .afe-start:focus-visible { outline: 0; box-shadow: var(--afe-ring); }
.afe-node .hd, .afe-start .hd { position: relative; display: flex; align-items: flex-start; gap: 10px; min-height: 52px; padding: 10px 10px 8px 12px; }
/* 右上角给“更多”留出位置，悬停时出现不挤动标题 */
.afe:not(.afe-ro) .afe-node .hd { padding-right: 34px; }
.afe-node .afe-pic, .afe-start .afe-pic { width: 28px; height: 28px; margin-top: 2px; }
.afe-node .afe-pic .afe-i, .afe-start .afe-pic .afe-i { width: 17px; height: 17px; }
.afe-node .tt, .afe-start .tt { flex: 1; min-width: 0; }
.afe-node .t, .afe-start .t { font-size: 14px; font-weight: 600; line-height: 20px; color: var(--afe-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.afe-node .s, .afe-start .s { display: flex; align-items: center; gap: 6px; height: 18px; margin-top: 1px; font-size: 12px; line-height: 18px; color: var(--afe-ink3); white-space: nowrap; overflow: hidden; }
.afe-start .s { display: block; text-overflow: ellipsis; }
.afe-node .s .p { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.afe-node .s .fl { margin-left: auto; display: inline-flex; align-items: center; gap: 4px; flex: none; }
.afe-node .fl > span { height: 18px; padding: 0 4px; border-radius: var(--afe-rt); line-height: 18px; font-size: 12px; }
.afe-node .fl .ea { color: var(--afe-primary); background: var(--afe-primary-bg); }
/* 总 Agent 刚改过的节点（docs/WORKSPACE.md）：画布上方那一条关了或撤回了就去掉 */
.afe-node .fl .ai { color: var(--afe-primary); background: var(--afe-primary-bg); font-weight: 600; }
.afe-node .fl .cd { color: var(--afe-ink2); background: var(--afe-grey-bg); }
.afe-node .fl .w { color: var(--afe-orange-ink); background: var(--afe-orange-bg); }
.afe-node .fl .sk { color: var(--afe-sky-ink); background: var(--afe-sky-bg); max-width: 96px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.afe-node .iss { display: inline-flex; align-items: center; gap: 4px; flex: none; height: 20px; font-size: 12px; }
.afe-node .iss:empty { display: none; }
.afe-node .iss .afe-i { width: 14px; height: 14px; }
.afe-node .iss .e { color: var(--afe-red); display: inline-flex; align-items: center; gap: 2px; }
.afe-node .iss .w2 { color: var(--afe-orange-ink); display: inline-flex; align-items: center; gap: 2px; }
.afe-node .iss .w2 .afe-i { color: var(--afe-orange); }
.afe-node .st { flex: none; display: inline-flex; width: 16px; height: 20px; align-items: center; justify-content: center; }
.afe-node .st:empty { display: none; }
.afe-node .st .afe-i { width: 16px; height: 16px; }
.afe-node .st .afe-spin { width: 13px; height: 13px; color: var(--afe-sky); }
/* 更多：悬停或选中时出现在卡片头右上角 */
.afe-nmore {
  position: absolute; right: 6px; top: 8px; width: 24px; height: 24px; display: flex; align-items: center; justify-content: center; padding: 0;
  border: 0; border-radius: var(--afe-r); background: var(--afe-card); color: var(--afe-ink3); cursor: pointer; opacity: 0; transition: opacity .12s, color .15s, background-color .15s;
}
.afe-nmore .afe-i { width: 18px; height: 18px; }
.afe-nmore:hover { color: var(--afe-primary); background: var(--afe-hover); }
.afe-node:hover .afe-nmore, .afe-node.sel .afe-nmore { opacity: 1; }
.afe-ro .afe-nmore, .afe-cv.connecting .afe-nmore, .afe-placing .afe-nmore { display: none; }
/* 卡片下半是芯片的引脚：一行左边一个输入口，右边一个输出口，口压在卡片的左右边框上；行高 20，卡片高度按口多的一边算。
   名字写在口里侧：输入口写参数的中文名，必填的后面红星，再往后写写死的值或全局来源；输出口写字段的中文名。键名只在悬停提示里 */
.afe-node .io, .afe-start .io { position: relative; padding: 6px 0 8px; }
/* 卡片头与下半之间的分隔线两端内缩，和文字对齐 */
.afe-node .io::before, .afe-start .io::before { content: ""; position: absolute; left: 12px; right: 12px; top: 0; height: 1px; background: var(--afe-divider); }
.afe-node .io .r, .afe-start .io .r { position: relative; display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; column-gap: 10px; height: 20px; padding: 0 12px; font-size: 12px; line-height: 20px; }
.afe-node .io .ci, .afe-start .io .ci { display: flex; align-items: center; gap: 6px; min-width: 0; }
.afe-node .io .co, .afe-start .io .co { display: flex; align-items: center; justify-content: flex-end; min-width: 0; max-width: 104px; }
.afe-node .io .k, .afe-start .io .k { flex: none; min-width: 0; max-width: 84px; color: var(--afe-ink2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.afe-node .io .co .k, .afe-start .io .co .k { flex: 0 1 auto; max-width: 100%; color: var(--afe-ink3); }
.afe-node .io .co:has(.on) .k, .afe-start .io .co:has(.on) .k { color: var(--afe-ink2); }
.afe-node .io .rq { flex: none; margin-left: -5px; color: var(--afe-red); font-family: SimSun, sans-serif; }
.afe-node .io .v, .afe-start .io .v { flex: 1 1 auto; min-width: 0; color: var(--afe-ink3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.afe-node .io .v.ref { display: flex; gap: 4px; }
.afe-node .io .v.ref .src { flex: none; color: var(--afe-ink4); }
/* 运行参数：来源后面带“›”，和字段路径一个写法 */
.afe-node .io .v.ref.pg .src::after { content: " ›"; }
.afe-node .io .v.ref .pth, .afe-node .io .rf { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; color: var(--afe-primary); }
.afe-node .io .rf { padding: 0 1px; }
.afe-node .io .ci.miss .v { color: var(--afe-red); }
.afe-node .io .ci.sp .k { color: var(--afe-ink3); }
.afe:not(.afe-ro) .afe-node .io .ci[data-k]:hover .k { color: var(--afe-primary); }
/* 引脚：8 像素小方块压在边框上。必填实心，选填空心，接上线的主色，必填没填红框；输出口被下游用到的主色 */
.afe-pin { position: absolute; top: 50%; z-index: 1; width: 8px; height: 8px; margin-top: -4px; box-sizing: border-box;
  border: 1.5px solid var(--afe-edge); background: var(--afe-card); box-shadow: 0 0 0 2px var(--afe-page); transition: background-color .15s, border-color .15s, transform .15s var(--afe-ease); }
.afe-pin.i { left: -4.5px; }
.afe-pin.o { right: -4.5px; }
.afe-pin.req { background: var(--afe-ink3); border-color: var(--afe-ink3); }
.afe-pin.on { background: var(--afe-primary-fill); border-color: var(--afe-primary-fill); }
.afe-pin.bad { background: var(--afe-card); border-color: var(--afe-red); }
.afe-node.sel .afe-pin, .afe-node:hover .afe-pin { box-shadow: 0 0 0 2px var(--afe-card); }
/* 开始节点的输出口是工作流输入，也能拖到节点的输入口上 */
.afe:not(.afe-ro) .afe-node .afe-pin.o, .afe:not(.afe-ro) .afe-node .afe-pin.i, .afe:not(.afe-ro) .afe-start .afe-pin.o { cursor: crosshair; }
.afe:not(.afe-ro) .afe-node .afe-pin:hover, .afe:not(.afe-ro) .afe-start .afe-pin.o:hover { transform: scale(1.4); border-color: var(--afe-primary-fill); }
/* 从一个口拖线时：另一头接得上的口描主色并放大一点，对不上类型的压淡，指着的那个实心 */
.afe-cv.pinning .afe-pin.ok { border-color: var(--afe-primary-fill); transform: scale(1.25); }
.afe-cv.pinning .afe-pin.no { opacity: .3; }
.afe-cv.pinning .afe-pin.drop { background: var(--afe-primary-fill); border-color: var(--afe-primary-fill); transform: scale(1.6); }
/* 从口拖线时目标就是口，卡片头的入口不出 */
.afe-cv.pinning .afe-node .afe-port.in, .afe-cv.pinning .afe-node:hover .afe-port.in, .afe-cv.connecting.pinning .afe-node.cand .afe-port.in { opacity: 0; }
/* 悬停或选中一条口对口的线，两头的口放大并换主色 */
.afe-node .afe-pin.eh { transform: scale(1.4); background: var(--afe-primary-fill); border-color: var(--afe-primary-fill); }
/* 组件详情与组件工厂的引脚图：和画布上的节点同一张卡片，不浮在画布上，留出两边压在边框上的口 */
.afe-chipbox { padding: 6px 8px; }
.afe-chipbox .afe-node { position: relative; cursor: default; }
.afe-chipbox .afe-node:hover { border-color: var(--afe-node-line); }
.afe-chipbox .afe-pin { box-shadow: 0 0 0 2px var(--afe-card); }
/* 运行状态：失败红框，运行中青蓝框，按条件跳过的虚线框 */
.afe-node.st-succeeded .st { color: var(--afe-success-ink); }
.afe-node.st-failed { border-color: var(--afe-red); }
.afe-node.st-failed .st { color: var(--afe-red); }
.afe-node.st-running { border-color: var(--afe-sky); }
.afe-node.st-running::after { content: ""; position: absolute; left: 0; right: 0; top: -1px; height: 2px; background: var(--afe-sky); animation: afe-run 1.2s infinite ease-in-out; }
@keyframes afe-run { 0% { clip-path: inset(0 100% 0 0); } 50% { clip-path: inset(0 30% 0 25%); } 100% { clip-path: inset(0 0 0 100%); } }
.afe-node.st-queued .st { color: var(--afe-orange); }
.afe-node.st-skipped .st, .afe-node.st-cancelled .st, .afe-node.st-pending .st { color: var(--afe-ink4); }
.afe-node.st-bypassed { border-style: dashed; border-color: var(--afe-ink4); }
.afe-node.st-bypassed .st { color: var(--afe-ink4); }
.afe-node.st-bypassed .t, .afe-node.st-bypassed .io .v { color: var(--afe-ink3); }
.afe-node.sel.st-failed, .afe-node.sel.st-running { border-color: var(--afe-primary); }
.afe-node.st-bypassed.sel { border-color: var(--afe-primary); box-shadow: none; }
/* 在写回里记了（任务同步整次同步里记账的那一步，账在写的那一次运行里记过，11-02 E3）：不是跳过，不画虚线框；勾画灰，不画成这一次跑成的绿 */
.afe-node.st-elsewhere .st { color: var(--afe-ink3); }
.afe-node.missing .s .p { color: var(--afe-red); }
/* 缩得很小时卡片头的字放大，下半的引脚照样画着，只藏掉口旁边的小字：几个输入口，几个输出口，哪些必填，远看也数得清 */
.afe-cv.far .afe-node .s, .afe-cv.far .afe-start .s { display: none; }
.afe-cv.far .afe-node .io .k, .afe-cv.far .afe-node .io .v, .afe-cv.far .afe-node .io .rq, .afe-cv.far .afe-start .io .k, .afe-cv.far .afe-start .io .v { visibility: hidden; }
/* 缩到 60% 以下：卡片头固定 80 高，出入口在它的中线上；标题字号随缩放反向放大，屏幕上约 13px，世界里最大 32px */
.afe-cv.far .afe-node .hd, .afe-cv.far .afe-start .hd { align-items: center; height: 80px; min-height: 0; padding: 0 12px; }
.afe-cv.far .afe-node .afe-pic, .afe-cv.far .afe-start .afe-pic { width: 40px; height: 40px; margin: 0; }
.afe-cv.far .afe-node .afe-pic .afe-i, .afe-cv.far .afe-start .afe-pic .afe-i { width: 24px; height: 24px; }
.afe-cv.far .afe-node .t, .afe-cv.far .afe-start .t {
  font-size: min(30px, calc(13px / var(--afe-k, .5))); line-height: 1.2; max-height: 2.4em; white-space: normal; text-wrap: balance; overflow-wrap: anywhere;
}
.afe-cv.far .afe-node .st, .afe-cv.far .afe-node .st .afe-i { width: 28px; height: 28px; }
.afe-cv.far .afe-node .iss { height: 28px; font-size: 20px; }
.afe-cv.far .afe-node .iss .afe-i { width: 22px; height: 22px; }
.afe-cv.far .afe-port { top: 40px; }
/* 远看时有错误或提醒的节点用边框标出来 */
.afe-cv.far .afe-node.v-err { border-color: var(--afe-red); }
.afe-cv.far .afe-node.v-warn { border-color: var(--afe-orange); }
/* 悬停或选中一条线时，两端的出口与入口变主色 */
.afe-node.eh-src .afe-port.out { border-color: var(--afe-primary); }
.afe-node.eh-dst .afe-port.in { opacity: 1; border-color: var(--afe-primary-fill); background: var(--afe-primary-fill); }
.afe-cv.far .afe-nmore { display: none; }
/* 出入口：都在卡片头的中线上。入口小圆点；出口悬停时变成加号，拖出连线，点一下接组件 */
.afe-port {
  position: absolute; top: 26px; width: 10px; height: 10px; margin-top: -5px; border-radius: 50%;
  border: 1.5px solid var(--afe-edge); background: var(--afe-card); z-index: 1; transition: border-color .15s, background-color .15s, transform .15s, color .15s, opacity .15s;
  display: flex; align-items: center; justify-content: center; color: transparent; box-shadow: 0 0 0 2px var(--afe-page);
}
.afe-port::after { content: ""; position: absolute; inset: -10px; }
.afe-port.in { left: -6px; }
.afe-port.out { right: -6px; cursor: crosshair; }
.afe-port .afe-i { width: 12px; height: 12px; }
/* 入口平时不画圆点，箭头已经指着它；悬停，选中与连线时才出来。卡片头的出口也一样：字段已经一个个画成右边的输出口，
   卡片头这个只用来接下一个组件，平时藏着，免得看成多一个输出口 */
.afe-port.in, .afe-node .afe-port.out { opacity: 0; }
.afe-node:hover .afe-port.out, .afe-node.sel .afe-port.out { opacity: 1; }
.afe-node:hover .afe-port.in, .afe-node.sel .afe-port.in, .afe-cv.connecting .afe-node.cand .afe-port.in { opacity: 1; }
/* 接着藏起来的口（组件自己管的口，卡片上不画）的引用：线接在卡片头的入口与出口上，两头的小圆点常亮，照接上的口用主色实心，缩小一点 */
.afe-node.hin .afe-port.in, .afe-node.hout:not(:hover):not(.sel) .afe-port.out { opacity: 1; border-color: var(--afe-primary-fill); background: var(--afe-primary-fill); transform: scale(.8); }
.afe-node:hover .afe-port, .afe-node.sel .afe-port, .afe-start:hover .afe-port { border-color: var(--afe-primary); }
.afe-node:hover .afe-port.out, .afe-node.sel .afe-port.out, .afe-start .afe-port.out { transform: scale(1.6); color: var(--afe-primary); }
.afe-port.out:hover { background: var(--afe-primary-fill); border-color: var(--afe-primary-fill); color: var(--afe-on-primary); }
.afe-port.out .afe-i { transform: scale(.62); }
.afe-ro .afe-port, .afe-cv.connecting .afe-port.out, .afe-placing .afe-port { display: none; }
.afe-cv.connecting .afe-node.nocand { opacity: .45; }
.afe-cv.connecting .afe-node.cand .afe-port.in { border-color: var(--afe-primary); transform: scale(1.3); }
.afe-cv.connecting .afe-node.drop, .afe-cv.connecting .afe-start.drop { border-color: var(--afe-primary); box-shadow: 0 0 0 3px var(--afe-primary-bg); }
.afe-cv.connecting .afe-node.drop .afe-port.in { background: var(--afe-primary-fill); border-color: var(--afe-primary-fill); }
.afe-cv.connecting, .afe-cv.connecting .afe-node { cursor: crosshair; }
/* 空工作流：开始节点右边的虚线框 */
.afe-first {
  position: absolute; width: 248px; height: 64px; display: flex; align-items: center; justify-content: center; gap: 6px; padding: 0;
  border: 1px dashed var(--afe-input); border-radius: var(--afe-rc); background: var(--afe-card); color: var(--afe-ink3); font-size: 14px; cursor: pointer;
  transition: color .15s, border-color .15s, background-color .15s;
}
.afe-first .afe-i { width: 18px; height: 18px; }
.afe-first:hover, .afe-first:focus-visible { color: var(--afe-primary); border-color: var(--afe-primary); background: var(--afe-primary-bg); outline: 0; }
.afe-placing .afe-first { border-color: var(--afe-primary); color: var(--afe-primary); }

/* 画布上的浮层：运行条，缩放工具条，小地图，空画布，提示条 */
.afe-tools {
  position: absolute; left: 12px; bottom: 12px; display: flex; align-items: center; gap: 0; padding: 3px; z-index: 4;
  background: var(--afe-card); border: 1px solid var(--afe-border); border-radius: var(--afe-r);
}
.afe-tools .afe-ib { width: 30px; height: 30px; }
.afe-tools .sep { width: 1px; height: 16px; background: var(--afe-border); margin: 0 4px; }
.afe-tools .afe-zoom { min-width: 50px; height: 30px; border: 0; background: none; border-radius: var(--afe-r); cursor: pointer; font-size: 12px; color: var(--afe-ink2); padding: 0 4px; font-variant-numeric: tabular-nums; }
.afe-tools .afe-zoom:hover { background: var(--afe-hover); color: var(--afe-primary); }
.afe-tools .afe-ib.on { background: var(--afe-primary-bg); color: var(--afe-primary); }
.afe-mini {
  position: absolute; right: 12px; bottom: 12px; z-index: 4; width: 168px; height: 108px; overflow: hidden; cursor: pointer;
  background: var(--afe-card); border: 1px solid var(--afe-border); border-radius: var(--afe-r); touch-action: none; transition: right .34s var(--afe-panel);
}
.afe-sidevis .afe-mini { right: calc(var(--afe-side-w, 0px) + 12px); }
.afe-cramped .afe-mini { display: none; }
.afe-mini-s { display: block; width: 100%; height: 100%; }
.afe.mid .afe-mini { width: 144px; height: 92px; }
/* 小地图：节点与开始节点都是实心小块不描边，选中的主色，运行状态照状态色；看到的范围细框加一层很淡的主色 */
.afe-mini .nd { fill: var(--afe-input); stroke: none; }
.afe-mini .nd.sel { fill: var(--afe-primary-fill); }
.afe-mini .nd.st-failed { fill: var(--afe-red); } .afe-mini .nd.st-running { fill: var(--afe-sky); } .afe-mini .nd.st-succeeded { fill: var(--afe-success); }
.afe-mini .vp { fill: color-mix(in srgb, var(--afe-primary) 8%, transparent); stroke: var(--afe-primary); stroke-width: 1; vector-effect: non-scaling-stroke; }
.afe-cvbtns { position: absolute; left: 12px; top: 12px; display: none; gap: 8px; z-index: 4; }
.afe-runbar {
  position: absolute; left: 50%; top: 12px; transform: translateX(-50%); display: flex; align-items: center; gap: 12px; z-index: 4;
  max-width: calc(100% - 24px); height: 40px; padding: 0 4px 0 12px; background: var(--afe-card); border: 1px solid var(--afe-border);
  border-radius: var(--afe-r); font-size: 13px; white-space: nowrap; animation: afe-fade .3s ease-out both; transition: left .34s var(--afe-panel);
}
.afe-runbar .rn { color: var(--afe-ink3); overflow: hidden; text-overflow: ellipsis; font-variant-numeric: tabular-nums; }
/* 设置面板浮出时，运行条居中在面板左边剩下的画布里，不被盖住 */
.afe-sidevis .afe-runbar { left: calc((100% - var(--afe-side-w, 0px)) / 2); max-width: calc(100% - var(--afe-side-w, 0px) - 24px); }
.afe-runbar a { color: var(--afe-primary); }
.afe-runbar a:hover { color: var(--afe-primary-hover); }
.afe-empty { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px; color: var(--afe-ink3); pointer-events: none; padding: 24px; text-align: center; }
.afe-empty .afe-i { width: 48px; height: 48px; color: var(--afe-ink4); }
.afe-empty .afe-btn { pointer-events: auto; }
/* 拖着的组件：和节点一样的卡片头，在画布上按当前缩放显示 */
.afe-ghost {
  position: fixed; left: 0; top: 0; z-index: 75; width: 248px; transform-origin: 0 0; pointer-events: none; opacity: .94;
  background: var(--afe-card); border: 1px solid var(--afe-primary); border-radius: var(--afe-rc); box-shadow: var(--afe-shadow); color: var(--afe-ink);
  font-size: 14px; line-height: 22px; box-sizing: border-box;
}
.afe-ghost * { box-sizing: border-box; }
.afe-ghost .afe-i { width: 17px; height: 17px; fill: currentColor; display: block; }
.afe-ghost .hd { display: flex; align-items: flex-start; gap: 10px; min-height: 52px; padding: 10px 12px 8px; }
.afe-ghost .afe-pic { width: 28px; height: 28px; margin-top: 2px; }
.afe-ghost .tt { flex: 1; min-width: 0; }
.afe-ghost .t { font-weight: 600; line-height: 20px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.afe-ghost .s { font-size: 12px; line-height: 18px; color: var(--afe-ink3); margin-top: 1px; }
.afe-placing, .afe-placing * { cursor: grabbing !important; }
.afe-ghost.ins { width: auto; max-width: 240px; }
.afe-ghost.ins .hd { min-height: 0; align-items: center; gap: 8px; padding: 5px 10px 5px 6px; }
.afe-ghost.ins .afe-pic { width: 22px; height: 22px; margin-top: 0; }
.afe-ghost.ins .afe-pic .afe-i { width: 14px; height: 14px; }
.afe-ghost.ins .s { display: none; }
.afe-insmark {
  position: absolute; z-index: 3; width: 22px; height: 22px; margin: -11px 0 0 -11px; display: flex; align-items: center; justify-content: center;
  border-radius: 50%; background: var(--afe-primary-fill); color: var(--afe-on-primary); box-shadow: 0 0 0 3px var(--afe-page); pointer-events: none;
  animation: afe-icon .22s var(--afe-ease) both;
}
.afe-insmark .afe-i { width: 16px; height: 16px; }
.afe-rubber { position: absolute; z-index: 3; border: 1px solid var(--afe-primary); background: color-mix(in srgb, var(--afe-primary) 6%, transparent); pointer-events: none; }
.afe-cv.boxmode { cursor: crosshair; }
.afe-cv.space, .afe-cv.space .afe-node { cursor: grab; }
/* 草稿与回退的提示：浅主色底的提示条，撤销是主色文字按钮 */
.afe-note {
  display: flex; align-items: center; gap: 8px; min-width: 0; position: absolute; left: 12px; right: 12px; top: 12px; z-index: 5; max-width: 560px;
  height: 40px; padding: 0 4px 0 12px; font-size: 14px; color: var(--afe-ink);
  background: var(--afe-primary-bg); border: 1px solid color-mix(in srgb, var(--afe-primary) 35%, var(--afe-card)); border-radius: var(--afe-r);
  animation: afe-note-in .34s var(--afe-ease) both;
}
@keyframes afe-note-in { from { opacity: 0; transform: translateY(-6px); } }
.afe-note .afe-note-i { width: 16px; height: 16px; color: var(--afe-primary); }
.afe-note .t { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--afe-ink); }
.afe-note .afe-btn.sm { height: 26px; padding: 0 6px; font-size: 14px; }
.afe-note .afe-ib { width: 26px; height: 26px; }
.afe-note .afe-ib .afe-i { width: 16px; height: 16px; }
/* 照的流程改过（10-31）：一句写改了哪几步，比放草稿的那一条长，放宽一些，放不下的照样省略，悬停看全 */
.afe-note.afe-flownote { max-width: 760px; }
/* 总 Agent 改了工作流的那一条：照字数宽，撤回与关闭紧跟在字后面，不撑满画布 */
.afe-note.afe-ainote { right: auto; width: max-content; max-width: min(760px, calc(100% - 24px)); padding-right: 4px; }
.afe-note.afe-ainote .t { flex: 0 1 auto; margin-right: 8px; }
/* 运行没成，功能页报错平台只通知的那一条（11-03 S2，自修闭环）：浅橙底（照卡片色调出来，深色下不透底），位置与大小同提示条 */
.afe-note.afe-healnote { background: color-mix(in srgb, var(--afe-orange) 12%, var(--afe-card)); border-color: color-mix(in srgb, var(--afe-orange) 45%, var(--afe-card)); }
.afe-note.afe-healnote .afe-note-i { color: var(--afe-orange-ink); }
/* 右边“工作流”一栏的状态：开发中与已上线两个键，下面一两行小字写出错怎么处理 */
.afe-stage-w { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }
.afe-stage-t { font-size: 13px; line-height: 20px; color: var(--afe-ink2); }
.afe-stage-t.afe-muted { color: var(--afe-ink3); }
.afe-stage button:disabled { cursor: default; }
/* 条上的节点名：点了选中那个节点，主色文字，同“看流程” */
.afe-note .afe-note-n { padding: 0; border: 0; background: none; font: inherit; color: var(--afe-primary); cursor: pointer; }
.afe-note .afe-note-n:hover { text-decoration: underline; }
.afe-note .afe-note-n:focus-visible { outline: 2px solid var(--afe-primary); outline-offset: 1px; border-radius: 2px; }

/* 右侧设置：白底，标题行，页签，折叠分组 */
/* 设置面板浮在画布右侧，选中节点或点开始节点时滑出，不挤画布；左边缘可拖动改宽 */
.afe-side {
  position: absolute; top: 0; right: 0; bottom: 0; width: 400px; max-width: 100%; z-index: 6; display: flex; flex-direction: column; min-height: 0;
  background: var(--afe-card); border-left: 1px solid var(--afe-border); box-shadow: var(--afe-side-shadow);
  transform: translateX(104%); visibility: hidden; transition: transform .22s var(--afe-ease-in), visibility 0s linear .22s;
}
.afe-side.open { transform: none; visibility: visible; transition: transform .34s var(--afe-panel), visibility 0s; }
/* 换了一个节点：面板里的内容淡入 */
.afe-side-b.afe-swap, .afe-grp-b.afe-swap { animation: afe-swap .26s var(--afe-ease) both; }
@keyframes afe-swap { from { opacity: 0; transform: translateY(6px); } }
.afe-side-rs { position: absolute; left: -4px; top: 0; bottom: 0; width: 8px; cursor: col-resize; z-index: 3; }
.afe-side-rs::after { content: ""; position: absolute; left: 3px; top: 0; bottom: 0; width: 2px; background: transparent; transition: background-color .15s; }
.afe-side-rs:hover::after, .afe-resizing .afe-side-rs::after { background: var(--afe-primary); }
.afe-resizing, .afe-resizing * { cursor: col-resize !important; user-select: none; }
.afe-resizing .afe-side, .afe-resizing .afe-mini { transition: none; }
.afe.small .afe-side-rs { display: none; }
/* 盖在右边对话上的设置面板：铺满对话栏，下沿让出对话的输入框，宽度不能拖 */
.afe-chat > .afe-side { left: 0; right: 0; bottom: var(--as-in-h, 96px); width: auto; max-width: none; border: 1px solid var(--afe-border); border-radius: var(--afe-rc) var(--afe-rc) 0 0; box-shadow: none; }
.afe-sidedock .afe-side-rs { display: none; }
.afe-side-h { flex: none; display: flex; align-items: center; gap: 4px; min-height: 52px; padding: 10px 8px 10px 16px; border-bottom: 1px solid var(--afe-border); }
.afe-side-h h2 { margin: 0; flex: 1; min-width: 0; font-size: 16px; line-height: 24px; font-weight: 600; color: var(--afe-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.afe-side-h .afe-ntitle { flex: 1; height: 32px; padding: 0 8px; font-size: 15px; font-weight: 600; border-color: transparent; background: none; }
.afe-side-h .afe-ntitle:hover { border-color: var(--afe-input); }
.afe-side-h .afe-ntitle:focus { border-color: var(--afe-primary); background: var(--afe-card); }
.afe-side-h .afe-ntitle[readonly]:hover, .afe-side-h .afe-ntitle[readonly]:focus { border-color: transparent; box-shadow: none; }
.afe-side-h .afe-smore { width: 28px; height: 28px; }
.afe-norun { padding: 32px 16px; text-align: center; color: var(--afe-ink3); font-size: 13px; }
.afe-side-h .afe-btn.sm { height: 28px; font-size: 14px; }
.afe-tabs { flex: none; display: flex; gap: 24px; border-bottom: 1px solid var(--afe-border); padding: 0 16px; }
.afe-tabs button {
  position: relative; display: inline-flex; align-items: center; gap: 6px; height: 44px; padding: 0 2px; border: 0; background: none;
  color: var(--afe-ink2); font-size: 14px; cursor: pointer; transition: color .2s;
}
.afe-tabs button:hover { color: var(--afe-primary); }
.afe-tabs button.on { color: var(--afe-primary); font-weight: 500; }
.afe-tabs button.on::after { content: ""; position: absolute; left: 0; right: 0; bottom: -1px; height: 2px; background: var(--afe-primary); }
.afe-tabst { display: inline-flex; }
.afe-tabst .afe-i { width: 15px; height: 15px; }
.afe-tabst .afe-spin { width: 12px; height: 12px; }
.afe-tabst.ok { color: var(--afe-success-ink); } .afe-tabst.bad { color: var(--afe-red); } .afe-tabst.off { color: var(--afe-ink4); }
.afe-side-b { flex: 1; min-height: 0; overflow-y: auto; padding: 0 0 24px; }
.afe-grp-h {
  display: flex; align-items: center; gap: 8px; width: 100%; height: 40px; padding: 0 16px 0 12px; border: 0; border-bottom: 1px solid var(--afe-border);
  background: var(--afe-head-bg); color: var(--afe-ink); font-size: 14px; font-weight: 400; text-align: left; cursor: pointer;
}
.afe-grp-h:hover { color: var(--afe-primary); }
.afe-grp-h .afe-i { width: 16px; height: 16px; color: var(--afe-ink2); transform: rotate(90deg); transition: transform .2s; }
.afe-grp.shut .afe-grp-h .afe-i { transform: none; }
.afe-grp-b { padding: 12px 16px 12px; border-bottom: 1px solid var(--afe-border); }
.afe-grp.shut .afe-grp-b { display: none; }
.afe-grp:last-child .afe-grp-b, .afe-grp.shut:last-child .afe-grp-h { border-bottom: 0; }
.afe-sec { padding: 14px 16px 4px; }
.afe-sec-h { display: flex; align-items: center; gap: 8px; min-height: 22px; margin: 0 0 10px; font-size: 14px; line-height: 22px; font-weight: 600; color: var(--afe-ink); }
.afe-sec-h::before { content: ""; flex: none; width: 3px; height: 14px; border-radius: 1px; background: var(--afe-primary); }
.afe-sec-h .r { margin-left: auto; display: flex; gap: 4px; }
.afe-kv { display: grid; grid-template-columns: 56px minmax(0, 1fr); gap: 6px 12px; margin: 0 0 8px; font-size: 14px; line-height: 22px; }
.afe-kv dt { color: var(--afe-ink3); margin: 0; }
.afe-kv dd { margin: 0; min-width: 0; overflow-wrap: anywhere; display: flex; align-items: center; flex-wrap: wrap; gap: 4px 8px; }
.afe-kv dd .afe-mono { color: var(--afe-ink3); }
.afe-desc-t { margin: 4px 0 8px; font-size: 13px; color: var(--afe-ink3); line-height: 20px; overflow-wrap: anywhere; }
/* 节点设置面板标题下面一行：平台图标，组件标题，组件名，节点编号，写入，说明 */
.afe-meta-l { flex: none; display: flex; align-items: center; gap: 8px; min-height: 40px; padding: 4px 8px 4px 16px; border-bottom: 1px solid var(--afe-border); font-size: 13px; color: var(--afe-ink2); white-space: nowrap; }
.afe-meta-l .t { min-width: 0; overflow: hidden; text-overflow: ellipsis; color: var(--afe-ink); }
.afe-meta-l .afe-mono { font-size: 12px; color: var(--afe-ink3); min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.afe-meta-l .afe-mono.i { flex: none; color: var(--afe-ink4); }
.afe-meta-l .sp { flex: 1; }
.afe-meta-l .afe-info { width: 26px; height: 26px; }
.afe-meta-l .afe-info .afe-i { width: 16px; height: 16px; }
.afe-desc-pop { padding: 10px 14px; font-size: 13px; line-height: 21px; color: var(--afe-ink2); overflow-wrap: anywhere; white-space: pre-wrap; }
.afe-nlv:empty { display: none; }
.afe-nlv { padding: 10px 16px 2px; border-bottom: 1px solid var(--afe-divider); }
.afe-nissue { display: flex; align-items: flex-start; gap: 6px; margin: 0 0 8px; font-size: 13px; line-height: 20px; }
.afe-nissue .afe-i { width: 16px; height: 16px; margin-top: 2px; }
.afe-nissue.e { color: var(--afe-red); } .afe-nissue.w { color: var(--afe-orange-ink); }
.afe-nissue.w .afe-i { color: var(--afe-orange); }
.afe-fld { padding: 0 0 2px; border-radius: var(--afe-r); }
.afe-fld.flash { animation: afe-flash 1.4s ease-out; }
@keyframes afe-flash { 0%, 40% { background: var(--afe-primary-bg); box-shadow: 0 0 0 6px var(--afe-primary-bg); } 100% { background: transparent; box-shadow: 0 0 0 6px transparent; } }
.afe-fld-l { display: flex; align-items: center; gap: 4px; min-height: 30px; font-size: 14px; color: var(--afe-ink); }
.afe-fld-l .lt { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.afe-fld-l .req, .afe-flab .req, .afe-tb-h .req { color: var(--afe-red); font-family: SimSun, sans-serif; margin-right: 2px; }
.afe-fld-l .r { margin-left: auto; display: flex; align-items: center; gap: 4px; flex: none; }
.afe-fld-l .afe-ib { width: 26px; height: 26px; }
.afe-fld-l .afe-ib .afe-i { width: 16px; height: 16px; }
.afe-fld-m { min-height: 18px; padding-top: 2px; font-size: 12px; line-height: 16px; color: var(--afe-red); overflow-wrap: anywhere; white-space: pre-line; }
.afe-fld-m.w { color: var(--afe-orange-ink); }
/* 技能：挂了的一行一个，名称，通用的带灰字，右边预览，做法，去掉；下面选择框再挂一个，旁边用 AI 新建 */
.afe-sklist { display: flex; flex-direction: column; border: 1px solid var(--afe-border); border-radius: 4px; margin-bottom: 8px; }
.afe-skrow { display: flex; align-items: center; gap: 6px; min-height: 34px; padding: 0 2px 0 10px; font-size: 13px; }
.afe-skrow + .afe-skrow { border-top: 1px solid var(--afe-border); }
.afe-skrow .t { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--afe-ink); }
.afe-skrow .g { flex: none; font-size: 12px; color: var(--afe-ink3); }
.afe-skrow.bad .t { color: var(--afe-red); }
.afe-skacts { display: flex; align-items: center; flex: none; gap: 2px; }
.afe-skacts a.afe-btn { text-decoration: none; }
.afe-skacts .afe-skx { width: 26px; height: 26px; }
.afe-skadd { display: flex; align-items: center; gap: 6px; }
.afe-skadd select { flex: 1; min-width: 0; }
.afe-skbody { max-height: 360px; overflow-y: auto; }
.afe-skbody b { display: block; margin-bottom: 6px; color: var(--afe-ink); }
.afe-ref {
  display: flex; align-items: center; gap: 8px; width: 100%; min-height: 32px; padding: 4px 8px 4px 11px; text-align: left;
  border: 1px solid var(--afe-input); border-radius: var(--afe-r); background: var(--afe-card); cursor: pointer; color: var(--afe-ink); transition: border-color .2s, box-shadow .2s;
}
.afe-ref:hover { border-color: var(--afe-primary-hover); }
.afe-ref:focus-visible { outline: 0; border-color: var(--afe-primary); box-shadow: var(--afe-ring); }
.afe-ref:disabled { cursor: default; background: var(--afe-th-bg); border-color: var(--afe-input); }
.afe-ref.bad { border-color: var(--afe-red); }
.afe-ref .src { flex: none; max-width: 45%; color: var(--afe-ink3); font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.afe-ref .p { flex: 1; min-width: 0; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.afe-ref .ty { flex: none; color: var(--afe-ink4); font-size: 12px; }
.afe-ref .ph { flex: 1; color: var(--afe-ink4); }
.afe-ref .afe-i { width: 16px; height: 16px; color: var(--afe-ink4); }
.afe-io { margin: 0; }
.afe-io-row { display: grid; grid-template-columns: minmax(0, 1fr) 84px 40px 32px; gap: 6px; align-items: center; margin-bottom: 6px; }
.afe-io-row > :nth-child(3) { justify-self: center; text-align: center; }
.afe-io-row .afe-ib { color: var(--afe-ink4); }
.afe-io-row .afe-ib:hover { color: var(--afe-danger); }
.afe-io-row.h { font-size: 12px; color: var(--afe-ink3); margin-bottom: 4px; }
.afe-io-row .afe-check { justify-content: center; min-height: 32px; }
.afe-pre {
  margin: 0; padding: 8px 12px; background: var(--afe-code); border: 1px solid var(--afe-divider); border-radius: var(--afe-r);
  font: 12px/18px var(--mono, var(--afe-mono)); white-space: pre-wrap; word-break: break-word; max-height: 320px; overflow: auto; color: var(--afe-ink);
}
.afe-pre.err { background: none; border: 0; border-left: 3px solid var(--afe-red); border-radius: 0; color: var(--afe-red); font-family: inherit; font-size: 13px; line-height: 20px; padding: 2px 0 2px 10px; }
.afe-logs { margin: 0; padding: 0; list-style: none; font: 12px/18px var(--mono, var(--afe-mono)); color: var(--afe-ink2); }
.afe-logs li { padding: 4px 0; border-top: 1px solid var(--afe-divider); overflow-wrap: anywhere; }
.afe-logs li:first-child { border-top: 0; }
.afe-st { flex: none; }
.afe-links { display: flex; flex-direction: column; gap: 4px; margin: 0 0 8px; }
.afe-links a { display: inline-flex; align-items: center; gap: 6px; color: var(--afe-primary); overflow-wrap: anywhere; font-size: 13px; }
.afe-links a .afe-i { width: 16px; height: 16px; }
.afe-links a .afe-lt { color: var(--afe-ink3); }
.afe-inw { position: relative; }
.afe-inw > .afe-in { padding-right: 34px; }
/* 多行框的插入引用图标在右上角，满行的中文会顶到它，多留一些 */
.afe-inw > textarea.afe-in { padding-right: 42px; }
.afe-inw > .afe-ins { position: absolute; right: 4px; top: 4px; width: 24px; height: 24px; }
.afe-inw > .afe-ins .afe-i { width: 16px; height: 16px; }
.afe-inw > .afe-ins { opacity: 0; transition: opacity .1s; }
.afe-inw:hover > .afe-ins, .afe-inw:focus-within > .afe-ins, .afe-inw > .afe-ins:focus-visible { opacity: 1; }
.afe-inw.has-fcb > .afe-in { padding-right: 30px; }
.afe-inw.has-fcb > .afe-ins { right: 30px; }
.afe-inw.has-fcb > .afe-in:is(input) { padding-right: 58px; }
.afe-inw > .afe-fcb { position: absolute; right: 3px; top: 3px; width: 24px; height: 24px; }
.afe-inw > .afe-fcb .afe-i { width: 16px; height: 16px; }
.afe-side .jv { max-height: 300px; padding-left: 30px; }
.afe-pre.skip { background: none; border: 0; border-left: 3px solid var(--afe-ink4); border-radius: 0; color: var(--afe-ink3); font-family: inherit; font-size: 13px; line-height: 20px; padding: 2px 0 2px 10px; }

/* 表格编辑 */
.afe-tb { display: flex; flex-direction: column; gap: 4px; }
.afe-tb-h, .afe-tb-r { display: grid; gap: 4px; align-items: center; }
.afe-tb-h { font-size: 12px; line-height: 18px; color: var(--afe-ink3); }
.afe-tb-h.none { display: none !important; }
.afe-tb-h > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.afe-tb-h > span.c, .afe-tb-c.c { text-align: center; justify-self: center; }
.afe-tb-c { min-width: 0; }
.afe-tb-c .afe-in { height: 28px; padding: 0 7px; font-size: 13px; }
.afe-tb-c select.afe-in { padding: 0 2px 0 4px; }
.afe-tb-c .afe-in:disabled { background: var(--afe-th-bg); border-color: var(--afe-input); color: var(--afe-ink4); cursor: not-allowed; }
.afe-tb-c .afe-inw.has-fcb > .afe-in { padding-right: 28px; }
.afe-tb-c .afe-tb-ref > .afe-in { padding-right: 28px; }
.afe-tb-c .afe-tb-ref > .afe-ins { top: 2px; right: 2px; opacity: 1; color: var(--afe-ink4); }
.afe-tb-c .afe-tb-ref > .afe-ins:hover { color: var(--afe-primary); }
.afe-tb-c .afe-inw > .afe-fcb { top: 2px; right: 2px; }
.afe-tb-ck { min-height: 28px; }
.afe-tb-x.afe-ib { width: 26px; height: 26px; color: var(--afe-ink4); }
.afe-tb-x.afe-ib:hover { color: var(--afe-danger); background: none; }
.afe-tb-x .afe-i { width: 16px; height: 16px; }
.afe-tb-add { align-self: flex-start; margin-left: -8px; }
.afe-fopts { max-height: 280px; overflow-y: auto; }

/* 运行结果 */
.afe-fold.long:not(.open) { max-height: var(--fold-h, 240px); overflow: hidden; border-bottom: 1px solid var(--afe-divider); }
.afe-fold .jv, .afe-fold .afe-pre { max-height: none; }
.afe-fold-t { display: inline-flex; align-items: center; gap: 4px; height: 28px; margin-top: 4px; padding: 0 6px 0 0; border: 0; background: none; color: var(--afe-primary); font-size: 13px; cursor: pointer; }
.afe-fold-t:hover { color: var(--afe-primary-hover); }
.afe-fold-t .afe-i { width: 16px; height: 16px; transition: transform .2s; }
.afe-fold-t[aria-expanded="true"] .afe-i { transform: rotate(180deg); }
.afe-lastrun { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 12px; font-size: 13px; }
.afe-lastrun a { color: var(--afe-primary); }
.afe-mlist { margin: 0; padding: 0; list-style: none; }
.afe-mlist li { border-bottom: 1px solid var(--afe-divider); }
.afe-mlist button { display: flex; align-items: center; gap: 10px; width: 100%; min-height: 44px; padding: 4px 4px; border: 0; background: none; color: var(--afe-ink2); text-align: left; cursor: pointer; }
.afe-mlist button:hover { background: var(--afe-th-bg); color: var(--afe-primary); }
.afe-mlist .t { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.afe-mlist .afe-mono { color: var(--afe-ink3); font-size: 12px; }
.afe-mlist .afe-mono.i { color: var(--afe-ink4); min-width: 2.5em; text-align: right; }

/* 弹出层：校验清单，引用选择，字段选择，更多 */
.afe-pop, .afe-pop-gone {
  position: fixed; z-index: 66; min-width: 220px; max-height: 70vh; overflow: auto; padding: 4px 0; color: var(--afe-ink);
  background: var(--afe-card); border: 1px solid var(--afe-divider); border-radius: var(--afe-r); box-shadow: var(--afe-shadow); font-size: 14px; line-height: 22px;
}
/* 从点开它的地方长出来；往上开的从下沿长。关掉时换成 afe-pop-gone 淡出，查找弹出层时不再算它 */
.afe-pop { transform-origin: var(--afe-pox, left) var(--afe-poy, top); animation: afe-pop-in .18s var(--afe-ease) both; }
.afe-pop-gone { pointer-events: none; transform-origin: var(--afe-pox, left) var(--afe-poy, top); animation: afe-pop-out .12s ease-in both; }
.afe-pop-s { position: sticky; top: -4px; z-index: 1; padding: 8px 8px 6px; background: var(--afe-card); border-bottom: 1px solid var(--afe-divider); margin-top: -4px; }
.afe-pop-s .afe-search { height: 32px; }
.afe-pop-gh { padding: 10px 12px 4px; font-size: 12px; color: var(--afe-ink3); }
.afe-pop-nh { display: flex; align-items: center; gap: 8px; padding: 6px 12px 2px; font-weight: 600; color: var(--afe-ink); }
.afe-pop-nh .afe-mono { color: var(--afe-ink4); font-weight: 400; font-size: 12px; }
.afe-pop-row {
  display: flex; align-items: center; gap: 8px; width: 100%; min-height: 32px; padding: 5px 12px 5px 20px; border: 0; background: none;
  text-align: left; cursor: pointer; color: var(--afe-ink2); transition: background-color .08s ease, color .08s ease;
}
.afe-pop-row:hover { background: var(--afe-hover); color: var(--afe-ink); }
.afe-pop-row.on { background: var(--afe-primary-bg); color: var(--afe-primary); }
.afe-pop-row .p { font-size: 13px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.afe-pop-row .tt { color: var(--afe-ink3); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; font-size: 13px; }
.afe-pop-row .ty { margin-left: auto; color: var(--afe-ink4); font-size: 12px; flex: none; }
.afe-pop-row.dis { cursor: not-allowed; color: var(--afe-ink4); }
.afe-pop-row.dis:hover { background: none; }
.afe-pop-row.dis .p, .afe-pop-row.dis .tt { color: var(--afe-ink4); }
.afe-pop-row.plain { padding-left: 12px; }
.afe-pop-row .afe-i { width: 16px; height: 16px; }
.afe-pop-none { padding: 12px; color: var(--afe-ink3); }.afe-iss-row { display: grid; grid-template-columns: 18px minmax(0, 1fr); gap: 8px; align-items: start; width: 100%; padding: 8px 12px; border: 0; border-top: 1px solid var(--afe-divider); background: none; text-align: left; cursor: pointer; color: var(--afe-ink); }
.afe-iss-row:first-child { border-top: 0; }
.afe-iss-row:hover { background: var(--afe-hover); }
.afe-iss-row .afe-i { width: 16px; height: 16px; margin-top: 3px; }
.afe-iss-row.e .afe-i { color: var(--afe-red); } .afe-iss-row.w .afe-i { color: var(--afe-orange); }
.afe-iss-row .wh { display: block; color: var(--afe-ink3); font-size: 12px; }
.afe-iss-row .wh b { font-weight: 500; color: var(--afe-ink); margin-left: 6px; }
.afe-pop-menu { padding: 4px 0; }
.afe-pop-menu .afe-pop-row { padding-left: 16px; min-height: 36px; font-size: 14px; }

/* 侧滑内容：一句话生成，定时，外部触发，版本，运行参数。表单标签在左，右对齐，宽 100 */
.afe-dr { display: flex; flex-direction: column; gap: 16px; font-size: 14px; line-height: 22px; color: var(--afe-ink); }
.afe-dr textarea.afe-in { min-height: 112px; }
.afe-form { gap: 20px; }
.afe-frow { display: grid; grid-template-columns: 100px minmax(0, 1fr); gap: 0 12px; align-items: start; }
.afe-flab { min-height: 32px; padding-top: 5px; line-height: 22px; text-align: right; color: var(--afe-ink); overflow-wrap: anywhere; }
.afe-fctl { min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.afe-fctl > .afe-sw, .afe-fctl > .afe-check { align-self: flex-start; }
.afe-fctl > .afe-tag, .afe-fctl > .afe-st { align-self: flex-start; margin-top: 6px; }
.afe-dr .afe-sub { font-size: 14px; font-weight: 600; color: var(--afe-ink); margin: 0 0 8px; display: flex; align-items: center; gap: 8px; }
.afe-dr .afe-sub::before { content: ""; flex: none; width: 3px; height: 14px; border-radius: 1px; background: var(--afe-primary); }
.afe-steps { margin: 0; padding: 0; list-style: none; border-top: 1px solid var(--afe-divider); }
.afe-steps li { display: grid; grid-template-columns: 64px minmax(0, 1fr) 18px; gap: 8px; align-items: center; min-height: 36px; padding: 6px 0; border-bottom: 1px solid var(--afe-divider); font-size: 13px; }
/* 进度新来的一步从下面浮上来 */
.afe-steps li.afe-new { animation: afe-step-in .34s var(--afe-ease) both; }
@keyframes afe-step-in { from { opacity: 0; transform: translateY(6px); } }
.afe-steps li.afe-tick .afe-i { animation: afe-icon .3s var(--afe-ease) both; }
.afe-steps li .afe-tm { color: var(--afe-ink4); font-variant-numeric: tabular-nums; font-size: 12px; }
.afe-steps li .afe-i { width: 16px; height: 16px; color: var(--afe-primary); }
.afe-steps li .afe-spin { width: 13px; height: 13px; color: var(--afe-sky); }
.afe-steps-t { display: inline-flex; align-items: center; gap: 4px; height: 28px; padding: 0 6px 0 0; border: 0; background: none; color: var(--afe-ink2); font-size: 14px; font-weight: 600; cursor: pointer; margin-bottom: 4px; }
.afe-steps-t:hover { color: var(--afe-primary); }
.afe-steps-t .afe-i { width: 16px; height: 16px; transition: transform .2s; }
.afe-steps-t[aria-expanded="false"] .afe-i { transform: rotate(-90deg); }
.afe-bar { height: 2px; background: var(--afe-divider); overflow: hidden; }
.afe-bar::after { content: ""; display: block; height: 100%; width: 30%; background: var(--afe-primary); animation: afe-prog 1.2s infinite ease-in-out; }
.afe-summary { margin: 0; line-height: 22px; overflow-wrap: anywhere; }
.afe-warns { margin: 0; padding: 0; list-style: none; }
.afe-warns li { display: flex; gap: 6px; align-items: flex-start; font-size: 13px; line-height: 20px; padding: 3px 0; color: var(--afe-ink); }
.afe-warns li .afe-i { width: 16px; height: 16px; color: var(--afe-orange); margin-top: 2px; }
.afe-warns li.ok .afe-i { color: var(--afe-success-ink); }
/* 一句话生成抽屉里选 Know-how：下拉下面一行 12px 灰字写照几步的流程 */
.afe-fhint { font-size: 12px; line-height: 18px; color: var(--afe-ink3); }
.afe-fhint[hidden] { display: none; }
.afe-dnodes { margin: 0; padding: 0; list-style: none; border-top: 1px solid var(--afe-divider); }
.afe-dnodes li { display: flex; align-items: center; gap: 10px; min-height: 40px; border-bottom: 1px solid var(--afe-divider); font-size: 14px; color: var(--afe-ink2); }
.afe-dnodes li .afe-mono { color: var(--afe-ink3); margin-left: auto; }
.afe-dnodes li .afe-id { color: var(--afe-ink4); width: 24px; flex: none; font-family: var(--mono, var(--afe-mono)); font-size: 12px; }
.afe-err { margin: 0; padding: 2px 0 2px 10px; border-left: 3px solid var(--afe-red); color: var(--afe-red); overflow-wrap: anywhere; }
.afe-foot { display: flex; align-items: center; justify-content: flex-end; gap: 8px; width: 100%; flex-wrap: wrap; }
.afe-foot .afe-grow { flex: 1; }
.afe-foot .afe-res { font-size: 13px; color: var(--afe-ink3); white-space: nowrap; }
/* 定时：频率，星期或日期，时间一行摆开，窄了折行 */
.afe-sch-row { display: flex; flex-wrap: wrap; gap: 8px; }
.afe-sch-row > .afe-in { flex: none; width: auto; min-width: 88px; }
.afe-sch-row > .afe-sch-f { min-width: 120px; }
.afe-sch-row > [hidden] { display: none; }
.afe-next { display: flex; align-items: center; gap: 8px; min-height: 32px; padding-top: 5px; line-height: 22px; color: var(--afe-ink3); }
.afe-next b { font-weight: 500; color: var(--afe-ink); }
/* 版本表：表头浅灰底，行线，悬停浅灰 */
.afe-vt { width: 100%; border-collapse: collapse; table-layout: fixed; font-size: 14px; }
.afe-vt th, .afe-vt td { text-align: left; height: 46px; padding: 0 8px; border-bottom: 1px solid var(--afe-divider); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--afe-ink2); }
.afe-vt th { height: 40px; background: var(--afe-th-bg); color: var(--afe-ink); font-weight: 600; }
.afe-vt th:first-child, .afe-vt td:first-child { padding-left: 12px; width: 120px; }
.afe-vt td .afe-cur { margin-left: 6px; }
.afe-vt th.ops, .afe-vt td.ops { width: 112px; text-align: right; padding-right: 4px; overflow: visible; }
.afe-vt td.ops .afe-btn.sm { height: 26px; padding: 0 6px; font-size: 14px; }
.afe-vt tbody tr:hover td { background: var(--afe-th-bg); }
.afe-cur { display: inline-flex; align-items: center; height: 20px; padding: 0 4px; border-radius: var(--afe-rt); font-size: 12px; line-height: 20px; color: var(--afe-primary); background: var(--afe-primary-bg); font-weight: 400; }
.afe-vhead { display: flex; align-items: baseline; justify-content: space-between; flex-wrap: wrap; gap: 4px 16px; }
.afe-vtitle { display: flex; align-items: center; gap: 8px; font-size: 16px; }
.afe-vtitle b { font-weight: 600; }
.afe-vmeta { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 12px; font-size: 13px; color: var(--afe-ink3); }
.afe-vst { display: inline-flex; align-items: center; gap: 4px; color: var(--afe-ink2); }
.afe-vst .afe-i { width: 16px; height: 16px; }
.afe-vst .ok { color: var(--afe-success-ink); } .afe-vst .e { color: var(--afe-red); } .afe-vst .w { color: var(--afe-orange); }
.afe-thumb { border: 1px solid var(--afe-border); border-radius: var(--afe-rc); background: var(--afe-page); overflow: hidden; }
.afe-thumb svg { display: block; }
.afe-thumb .nd { fill: var(--afe-card); stroke: var(--afe-node-line); stroke-width: 1; }
.afe-thumb .ln { fill: none; stroke: var(--afe-ink4); stroke-width: 1.2; }
.afe-thumb .ar { fill: var(--afe-ink4); }
.afe-thumb .tx { fill: var(--afe-ink); font-size: 11px; }
.afe-vnodes td:last-child { color: var(--afe-ink3); }
.afe-vnodes td { height: 40px; }

/* 中宽：组件面板留着，设置面板滑出时把组件面板收起 */
.afe.mid .afe-pal { width: 216px; }
.afe.small .afe-cvbtns, .afe.mid.afe-palhide .afe-cvbtns { display: flex; }
.afe.small .afe-tools { flex-direction: column; }
.afe.small .afe-tools .sep { width: 16px; height: 1px; margin: 3px 0; }
.afe.small .afe-tools .afe-ib { width: 30px; height: 28px; }
.afe.small .afe-tools .afe-zoom { min-width: 44px; height: 24px; padding: 0; font-size: 11px; }
.afe.small .afe-tools .afe-mini-sep, .afe.small .afe-tools .afe-ib[aria-label="小地图"], .afe.small .afe-tools .afe-ib[aria-label="快捷键"] { display: none; }
.afe.mid.afe-palhide .afe-pal { display: none; }
.afe.mid .afe-acts .afe-wide, .afe.small .afe-acts .afe-wide { display: none; }
.afe.mid .afe-acts .afe-more, .afe.small .afe-acts .afe-more { display: inline-flex; }
.afe.mid .afe-runbar, .afe.small .afe-runbar { left: 12px; transform: none; }
.afe.mid .afe-runbar:not([hidden]) ~ .afe-cvbtns, .afe.small .afe-runbar:not([hidden]) ~ .afe-cvbtns { top: 60px; }

/* 窄屏：组件面板也浮起来，工具条只留名称，运行，保存与更多 */
.afe.small { gap: 8px; }
.afe.small.afe-pad { padding: 8px; }
.afe.small .afe-head { flex-wrap: nowrap; min-height: 52px; padding: 6px 8px; gap: 6px; }
.afe.small .afe-name { font-size: 15px; width: auto !important; flex: 1 1 auto; min-width: 0; padding: 0 4px; }
.afe.small .afe-titles { flex: 1 1 auto; gap: 2px; }
.afe.small .afe-meta { gap: 2px; margin-left: 0; }
.afe.small .afe-ver, .afe.small .afe-dirty, .afe.small .afe-vchip .afe-vw, .afe.small .afe-acts .afe-gen { display: none; }
.afe.small .afe-acts { margin-left: 0; gap: 6px; }
.afe.small .afe-acts .afe-btn { padding: 0 10px; height: 32px; }
.afe.small .afe-acts .afe-btn .afe-i { display: none; }
.afe.small.afe-sideopen .afe-head { display: none; }
.afe.small .afe-pal {
  position: absolute; top: 0; left: 0; bottom: 0; width: 300px; max-width: 100%; z-index: 7; box-shadow: var(--afe-shadow); border-right: 0;
  transform: translateX(-104%); visibility: hidden; transition: transform .22s var(--afe-ease-in), visibility 0s linear .22s;
}
.afe.small .afe-pal.open { transform: none; visibility: visible; transition: transform .34s var(--afe-panel), visibility 0s; }
.afe.small .afe-pal-x { display: inline-flex; }
.afe.small .afe-side { width: 100%; }
.afe.small .afe-runbar { right: 12px; max-width: none; }
.afe.small .afe-cv > .afe-note:not([hidden]) ~ .afe-cvbtns { top: 60px; }
@media (max-width: 480px) { .afe-frow { grid-template-columns: 76px minmax(0, 1fr); } }

/* 逐个运行 */
.afe-each-kv { grid-template-columns: 56px minmax(0, 1fr); }
.afe-each-kv dd.bad.on { color: var(--afe-red); }
.afe-efail { margin: 4px 0 8px; padding: 0; list-style: none; border-top: 1px solid var(--afe-divider); }
.afe-efail li { display: grid; grid-template-columns: 56px minmax(0, 1fr); gap: 12px; padding: 6px 0; border-bottom: 1px solid var(--afe-divider); font-size: 13px; line-height: 20px; }
.afe-efail .i { color: var(--afe-ink3); }
.afe-efail .m { color: var(--afe-red); overflow-wrap: anywhere; }

/* 侧滑表单里只读的几行：行距收紧，字与标签对齐 */
.afe-form > .afe-frow.ro + .afe-frow.ro { margin-top: -8px; }
.afe-frow.ro .afe-flab, .afe-frow.ro .afe-next { min-height: 22px; padding-top: 0; }
.afe-frow.ro .afe-fctl > .afe-tag, .afe-frow.ro .afe-fctl > .afe-st { margin-top: 1px; }

/* AI 智能体：可用组件，选组件的弹出框，连接槽位，运行结果里的调用记录 */
.afe-atl { margin: 0; padding: 0; list-style: none; }
.afe-atl li { display: flex; align-items: center; gap: 8px; min-height: 36px; padding: 2px 0; border-bottom: 1px solid var(--afe-divider); font-size: 13px; line-height: 20px; color: var(--afe-ink); }
.afe-atl li:first-child { border-top: 1px solid var(--afe-divider); }
.afe-atl li .t { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.afe-atl li.bad .t { color: var(--afe-red); }
.afe-atl li.none { color: var(--afe-ink3); }
.afe-atl-x.afe-ib { flex: none; width: 26px; height: 26px; color: var(--afe-ink4); }
.afe-atl-x.afe-ib:hover { color: var(--afe-danger); background: none; }
.afe-atl-x .afe-i { width: 16px; height: 16px; }
.afe-atools .afe-atl-add { margin: 4px 0 0 -8px; }
.afe-aref { margin: 0 0 6px; padding: 2px 0 2px 8px; border-left: 3px solid var(--afe-red); color: var(--afe-ink3); font-size: 12px; line-height: 18px; overflow-wrap: anywhere; }
.afe-atp-gh { display: flex; align-items: center; gap: 6px; }
.afe-atp-gh .afe-pic { width: 16px; height: 16px; }
.afe-atp-gh .afe-pic .afe-i { width: 11px; height: 11px; }
.afe-atp-row { padding-left: 12px; }
.afe-atp-row .ck { flex: none; display: inline-flex; width: 16px; height: 16px; color: var(--afe-primary); }
.afe-atp-row .t { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--afe-ink); }
.afe-atp-row.sel .t { color: var(--afe-primary); }
.afe-atp-row.dis .t { color: var(--afe-ink4); }
.afe-aslot { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr) 26px; gap: 6px; align-items: center; margin-bottom: 6px; }
.afe-aslot .l { display: flex; align-items: baseline; gap: 6px; min-width: 0; font-size: 13px; color: var(--afe-ink2); }
.afe-aslot .l > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.afe-calls-n { font-size: 12px; font-weight: 400; color: var(--afe-ink3); }
.afe-calls-w { margin: 0 0 8px; overflow-x: auto; }
.afe-calls { width: 100%; border-collapse: collapse; table-layout: fixed; font-size: 13px; line-height: 20px; }
.afe-calls th { padding: 6px; text-align: left; font-size: 12px; font-weight: 600; color: var(--afe-ink); background: var(--afe-th-bg); white-space: nowrap; }
.afe-calls td { padding: 6px; vertical-align: top; border-bottom: 1px solid var(--afe-divider); }
.afe-calls tr.m td { border-bottom: 0; padding-bottom: 2px; }
.afe-calls tr.m, .afe-calls tr.x { cursor: pointer; }
.afe-calls tr.m:focus-visible { outline: 2px solid var(--afe-primary); outline-offset: -2px; }
.afe-calls tr.x td { padding-top: 0; }
.afe-calls tr.x.open td { border-bottom: 0; }
.afe-calls tr.dt td { padding-top: 2px; }
.afe-calls .i { width: 44px; color: var(--afe-ink3); white-space: nowrap; }
.afe-calls .i .cv { display: inline-block; width: 14px; height: 14px; margin-left: 2px; vertical-align: -2px; color: var(--afe-ink4); transition: transform .2s; }
.afe-calls tr.m.open .i .cv { transform: rotate(180deg); }
.afe-calls .s { width: 60px; }
.afe-calls .d { width: 72px; color: var(--afe-ink3); white-space: nowrap; }
.afe-calls .c .t { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--afe-ink); }
.afe-calls .a { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; overflow-wrap: anywhere; font-size: 12px; line-height: 18px; color: var(--afe-ink3); }
.afe-calls .rs { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; line-height: 18px; color: var(--afe-ink3); }
.afe-calls tr.x.open .rs { display: none; }
.afe-calls tr.x.open .a { display: block; -webkit-line-clamp: none; }
.afe-calls .dt .k { margin: 4px 0 2px; font-size: 12px; line-height: 18px; color: var(--afe-ink3); }
.afe-calls .dt .afe-pre { max-height: 240px; }
.afe-calls .dt .v { font-size: 13px; line-height: 20px; color: var(--afe-ink); overflow-wrap: anywhere; }
.afe-calls .e { margin-top: 2px; font-size: 12px; line-height: 18px; color: var(--afe-red); overflow-wrap: anywhere; }

/* 添加组件的弹出框：搜索，用途页签，推荐与按平台分组的清单 */
.afe-anchor { position: fixed; width: 0; height: 0; pointer-events: none; }
.afe-add .afe-pop-s { padding-bottom: 0; }
.afe-add .afe-roles { padding: 0 2px; margin-top: 6px; border-bottom: 0; }
.afe-add .afe-roles button { height: 32px; }
.afe-add-l { padding: 2px 0 4px; }
.afe-add-r { padding-left: 12px; min-height: 34px; }
.afe-add-r .afe-pic { width: 18px; height: 18px; }
.afe-add-r .afe-pic .afe-i { width: 12px; height: 12px; }
.afe-add-r .t { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--afe-ink); }
.afe-add-r.on .t { color: var(--afe-primary); }
.afe-add-r .p { flex: none; max-width: 30%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--afe-ink4); font-size: 12px; }
/* 接线：对不准字段时给人挑 */
.afe-map-h { display: flex; align-items: center; gap: 6px; padding: 8px 12px 6px; font-size: 13px; font-weight: 600; color: var(--afe-ink); border-bottom: 1px solid var(--afe-divider); }
.afe-map-h > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.afe-map-h .ar { flex: none; color: var(--afe-ink4); font-weight: 400; }
.afe-map-r { padding-left: 12px; gap: 6px; }
.afe-map-r .k { flex: none; max-width: 40%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--afe-ink); }
.afe-map-r .ar { flex: none; color: var(--afe-ink4); }
.afe-map-r .p { color: var(--afe-primary); }
.afe-map-f { display: flex; justify-content: flex-end; padding: 4px 6px 2px; border-top: 1px solid var(--afe-divider); margin-top: 4px; }
/* 右键菜单：图标，名称，快捷键 */
.afe-ctx .afe-pop-row { padding-left: 12px; gap: 10px; min-height: 34px; color: var(--afe-ink); }
.afe-ctx .afe-pop-row .afe-i { width: 16px; height: 16px; color: var(--afe-ink3); }
.afe-ctx .afe-ctx-i { width: 16px; flex: none; }
.afe-ctx .afe-pop-row .l { flex: 1; min-width: 0; }
.afe-ctx .afe-pop-row .kb { flex: none; color: var(--afe-ink4); font-size: 12px; font-variant-numeric: tabular-nums; }
.afe-ctx .afe-pop-row.danger, .afe-ctx .afe-pop-row.danger .afe-i { color: var(--afe-danger); }
.afe-ctx .afe-pop-row.dis, .afe-ctx .afe-pop-row.dis .afe-i, .afe-ctx .afe-pop-row.dis .kb { color: var(--afe-ink4); }
.afe-pop-sep { height: 1px; margin: 4px 0; background: var(--afe-divider); }
/* 快捷键 */
.afe-keys { padding: 6px 12px 8px; }
.afe-keys table { width: 100%; border-collapse: collapse; font-size: 13px; }
.afe-keys td { padding: 5px 0; border-bottom: 1px solid var(--afe-divider); color: var(--afe-ink2); vertical-align: top; }
.afe-keys tr:last-child td { border-bottom: 0; }
.afe-keys td.kb { text-align: right; color: var(--afe-ink); padding-left: 12px; }

/* 打包：版本号与这一版改了什么，打不了的原因，包里带什么，客户那边要配的连接，打包记录。见 docs/PACKAGING.md 与 STYLE_PORTAL.md“打包” */
.afe-pk .afe-pk-ver { width: 160px; }
.afe-pk textarea.afe-pk-notes { min-height: 72px; }
.afe-pk .afe-hint { font-size: 12px; line-height: 18px; color: var(--afe-ink3); }
.afe-pk .afe-sub.afe-pk-h { margin: 4px 0 -8px; }
.afe-pk-kv { grid-template-columns: 72px minmax(0, 1fr); margin: 0; }
.afe-pk-bad { display: flex; gap: 8px; align-items: flex-start; padding: 10px 12px; border: 1px solid var(--afe-red); border-radius: var(--afe-r); background: var(--afe-red-bg); color: var(--afe-ink); }
.afe-pk-bad .afe-i { width: 18px; height: 18px; flex: none; color: var(--afe-red); margin-top: 2px; }
.afe-pk-bad b { font-weight: 600; }
.afe-pk-bad ul { margin: 2px 0 0; padding-left: 18px; font-size: 13px; line-height: 20px; }
.afe-pk-warn { margin: 0; padding: 0; list-style: none; }
.afe-pk-warn li { display: flex; gap: 6px; align-items: flex-start; font-size: 13px; line-height: 20px; padding: 3px 0; }
.afe-pk-warn li .afe-i { width: 16px; height: 16px; flex: none; color: var(--afe-orange); margin-top: 2px; }
.afe-pk-none { margin: 0; }
.afe-tbl { width: 100%; border-collapse: collapse; font-size: 13px; line-height: 20px; }
.afe-tbl td { padding: 8px 12px 8px 0; border-bottom: 1px solid var(--afe-divider); vertical-align: top; overflow-wrap: anywhere; }
.afe-tbl td:last-child { padding-right: 0; text-align: right; white-space: nowrap; }
.afe-tbl tr:first-child td { border-top: 1px solid var(--afe-divider); }
.afe-tbl .afe-muted { font-size: 12px; }
.afe-pk-conns td:first-child { width: 34%; }
.afe-pk-builds td:first-child { width: 72px; }
.afe-pk-dl { display: inline-flex; align-items: center; gap: 2px; color: var(--afe-primary); text-decoration: none; }
.afe-pk-dl:hover { text-decoration: underline; }
.afe-pk-dl .afe-i { width: 16px; height: 16px; }

/* ---------- 节点上的 AI：AI 写参数的对话，Vibe Coding，知识口；细则见 docs/STYLE_PORTAL.md“节点上的 AI” ---------- */
.afe-tag.sky { color: var(--afe-sky-ink); background: var(--afe-sky-bg); }
/* 对话一段：放在设置面板顶上，和右栏 AI 助手同一套消息样子，字小一号 */
.afe-nai { display: flex; flex-direction: column; gap: 10px; padding: 12px 16px 14px; border-bottom: 1px solid var(--afe-border); background: var(--afe-card); }
.afe-nai-msgs { max-height: 260px; overflow-y: auto; display: flex; flex-direction: column; gap: 14px; scrollbar-width: thin; overflow-anchor: none; }
.afe-nai-msgs:empty { display: none; }
.afe-nai-turn { display: flex; flex-direction: column; gap: 10px; }
.afe-nai-turn.in { animation: afe-swap .26s var(--afe-ease) both; }
.afe-nai .as-u { max-width: 92%; padding: 7px 12px; font-size: 13.5px; line-height: 21px; border-radius: 10px; }
.afe-nai .as-a { gap: 8px; }
.afe-nai .as-text, .afe-nai .as-work { font-size: 13.5px; line-height: 22px; }
.afe-nai .as-err { font-size: 13px; line-height: 20px; }
.afe-nai-sys { align-self: center; font-size: 12px; line-height: 18px; color: var(--afe-ink3); }
.afe-nai-empty { font-size: 13px; line-height: 21px; color: var(--afe-ink3); }
.afe-nai-ch { display: flex; align-items: center; gap: 6px; margin-top: 6px; font-size: 12.5px; line-height: 20px; color: var(--afe-ink2); }
.afe-nai-ch .afe-btn.sm { height: 22px; }
/* “改了 2 处：”与参数名之间，参数名之间的逗号，不吃上面的 6px 间距，中文标点紧贴着字 */
.afe-nai-ch > .lb { margin-right: -6px; }
/* 从项目进的套件里：输入表这个工作流另设了的参数，套件原样的值后面主色写“这个工作流里是 某某”（11-01 第二轮 D4） */
.afe-plan-ovw { display: inline-flex; flex-wrap: wrap; align-items: baseline; column-gap: 10px; row-gap: 2px; }
.afe-plan-ovw > :first-child { color: var(--afe-ink3); text-decoration: line-through; text-decoration-color: var(--afe-ink4); }
.afe-plan-ov { color: var(--afe-primary); }
/* 节点大框的改动等确认（会写外部系统的节点这一类，同 AI 存版，主控 11-01）：答完那一行下面一块，橙色左条，一样一行；
   确认过的与没有生效的只留一行灰字 */
.afe-nai-wait { margin-top: 6px; padding: 5px 10px 6px; border-left: 2px solid var(--afe-orange); border-radius: 0 var(--afe-r) var(--afe-r) 0;
  background: var(--afe-orange-bg); font-size: 12.5px; line-height: 19px; color: var(--afe-ink); }
.afe-nai-wait .h { display: flex; align-items: center; gap: 6px; }
.afe-nai-wait .h .afe-i { flex: none; width: 14px; height: 14px; color: var(--afe-orange-ink); }
.afe-nai-wait ul { margin: 2px 0 0; padding-left: 20px; color: var(--afe-ink2); }
.afe-nai-wait.done, .afe-nai-wait.off { border-left-color: var(--afe-border); background: none; color: var(--afe-ink3); }
.afe-nai-wait.done .h .afe-i, .afe-nai-wait.off .h .afe-i { color: var(--afe-ink3); }
/* 这一问用了多久：答完那一行最后，灰字靠右（11-01 第二轮 D4） */
.afe-nai-dur { margin-left: auto; padding-left: 8px; flex: none; font-size: 12px; color: var(--afe-ink3); font-variant-numeric: tabular-nums; }
.afe-nai-ch > .sep { margin: 0 -6px; }
.afe-nai-ch.held { flex-wrap: wrap; row-gap: 0; color: var(--afe-ink); }
/* 只回了话没交参数：答复下面一行灰字“这次没有改参数”，不标红（R2 评审 P2-6） */
.afe-nai-ch.afe-nai-none { color: var(--afe-ink3); }
.afe-nai-k { padding: 0; border: 0; background: none; font: inherit; color: var(--afe-primary); cursor: pointer; }
.afe-nai-k:hover { text-decoration: underline; }
.afe-nai-k:focus-visible { outline: 2px solid var(--afe-primary); outline-offset: 1px; border-radius: 2px; }
.afe-nai-k.run { color: var(--afe-ink); cursor: default; }
.afe-nai-k.run:hover { text-decoration: none; }
.afe-nai-used { display: flex; align-items: center; gap: 4px; margin-top: 2px; font-size: 12px; line-height: 18px; color: var(--afe-ink3); min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.afe-nai-used .afe-i { flex: none; width: 14px; height: 14px; color: var(--afe-sky); }
.afe-nai-used .tx { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.afe-nai-fold { align-self: center; padding: 2px 8px; border: 0; background: none; color: var(--afe-primary); font: inherit; font-size: 12.5px; line-height: 20px; cursor: pointer; }
.afe-nai-fold:hover { text-decoration: underline; }
.afe-nai .as-box { border-radius: 10px; padding: 8px 8px 6px 12px; }
.afe-nai .as-box textarea { font-size: 13.5px; line-height: 22px; max-height: 144px; }
.afe-nai .as-bar { display: flex; align-items: center; gap: 8px; }
.afe-nai .as-send { width: 28px; height: 28px; }
.afe-nai .as-send svg.i { width: 16px; height: 16px; }
/* AI 刚改过的参数：底色闪一下再退，2.6 秒，换面板重画时接着同一个进度 */
.afe-fld.ai-set { animation: afe-aiset 2.6s ease-out both; animation-delay: var(--ai-d, 0ms); }
@keyframes afe-aiset { 0%, 45% { background: var(--afe-primary-bg); box-shadow: 0 0 0 6px var(--afe-primary-bg); } 100% { background: transparent; box-shadow: 0 0 0 6px transparent; } }
/* 代码类参数：只读的代码预览，点了在大框中间的框里打开 */
.afe-codepv { margin: 0; padding: 7px 10px; overflow: hidden; border: 1px solid var(--afe-input); border-radius: var(--afe-r); background: var(--code-bg, var(--afe-card));
  font: 12.5px/19px var(--mono, var(--afe-mono)); color: var(--afe-ink); white-space: pre-wrap; overflow-wrap: anywhere; cursor: pointer; transition: border-color .12s ease; }
.afe-codepv:hover, .afe-codepv:focus-visible { border-color: var(--afe-primary); outline: 0; }
.afe-codepv.empty { white-space: normal; font-family: inherit; font-size: 13px; line-height: 20px; color: var(--afe-ink4); }
.afe-fld-l .afe-codebtn { height: 24px; padding: 0 6px; font-size: 13px; }
.afe-fld-l .afe-codebtn .afe-i { width: 15px; height: 15px; }
/* Know-how 节点选知识库；知识口一组 */
.afe-kbpick select { width: 100%; }
.afe-kbinfo { display: flex; align-items: center; gap: 8px; margin-top: 6px; font-size: 12px; line-height: 18px; color: var(--afe-ink3); }
.afe-kbinfo a { margin-left: auto; flex: none; }
.afe-know-r { display: flex; align-items: center; gap: 8px; min-height: 32px; font-size: 14px; }
.afe-know-r .t { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.afe-know-r .afe-mono.i { flex: none; color: var(--afe-ink4); font-size: 12px; }
.afe-know-r .afe-ib { width: 26px; height: 26px; }
.afe-know-r .afe-ib .afe-i { width: 16px; height: 16px; }
.afe-know-none { font-size: 13px; line-height: 20px; }
.afe-know-add { margin-top: 8px; }
.afe-know-add select { width: 100%; }
/* 从 Know-how 节点拖知识口：没有知识口的卡片整张能接 */
.afe-cv.knowing .afe-node.kcand { border-color: color-mix(in srgb, var(--afe-sky) 60%, var(--afe-node-line)); }

/* ================================================================== 2026 版界面：编辑页
 * 画布去掉外框，点阵铺满；页头，组件面板，右边对话三块白卡浮在点阵四周，节点挪出去像钻到卡片底下，照 Dify 与扣子的画布。
 * 节点白底 14 圆角，左上角平台色小方块；选中是帆软蓝框加一圈淡光。这一段压在上面旧版写法后面，同名选择器盖掉旧外观 */
.afe, .afe-pop, .afe-pop-gone, .afe-dr, .afe-foot, .afe-ghost, .afe-cc, .afe-v, .afe-fx-mask {
  --afe-r: 8px; --afe-rc: 12px; --afe-rt: 6px;
  --afe-primary-fill: var(--primary-fill); --afe-node-line: var(--border); --afe-dot: var(--cv-dot); --afe-edge: var(--ink4);
  --afe-shadow: var(--pop-shadow); --afe-side-shadow: -8px 0 24px rgba(16, 24, 40, .08); --afe-hover: var(--hover2); --afe-head-bg: var(--th-bg);
  --afe-cell-line: var(--border);
}
.afe { background: var(--cv-bg); }
/* 按钮：主按钮黑色，深色下白色；普通按钮白底细框 */
.afe-btn { height: 34px; padding: 0 13px; font-weight: 500; color: var(--ink2); box-shadow: var(--sh-xs); border-color: var(--input-border); }
.afe-btn:hover { color: var(--ink); border-color: var(--input-border); background: var(--th-bg); }
.afe-btn.pri { background: var(--btn-pri); border-color: var(--btn-pri); color: var(--on-btn-pri); }
.afe-btn.pri:hover { background: var(--btn-pri-hover); border-color: var(--btn-pri-hover); color: var(--on-btn-pri); }
.afe-btn.pri:active { background: var(--btn-pri-active); border-color: var(--btn-pri-active); }
.afe-btn.txt { box-shadow: none; color: var(--ink2); }
.afe-btn.txt:hover { color: var(--ink); background: var(--hover2); }
.afe-btn.sm { height: 28px; }
.afe-btn.dis, .afe-btn.dis:hover, .afe-btn.pri.dis, .afe-btn.pri.dis:hover { box-shadow: none; background: var(--th-bg); border-color: var(--border); }
.afe-ib:hover { color: var(--ink); }
/* 页头：一条白卡。校验，定时，触发，功能页，打包是轻按钮，不带框；运行带框，保存是黑色主按钮 */
.afe-head { min-height: 60px; padding: 10px 14px 10px 12px; box-shadow: var(--sh-xs); }
.afe-name { font-size: 17px; }
.afe-head .afe-acts .afe-btn:not(.pri) { border-color: transparent; background: none; box-shadow: none; padding: 0 10px; }
.afe-head .afe-acts .afe-btn:not(.pri):hover { background: var(--hover2); color: var(--ink); }
.afe-head .afe-acts .afe-btn.afe-runbtn, .afe-head .afe-acts .afe-btn[data-act="run"] { border-color: var(--input-border); background: var(--card); box-shadow: var(--sh-xs); }
.afe-head .afe-acts .afe-btn.dis { background: none; border-color: transparent; }
/* 主体不要外框，画布就是点阵 */
.afe-body { border: 0; border-radius: 0; box-shadow: none; background: none; }
.afe-cv { background: var(--cv-bg); }
/* 组件面板：一块浮起的白卡 */
.afe-pal { margin: 0 12px 0 0; border: 1px solid var(--border); border-radius: var(--r-lg); box-shadow: var(--sh-sm); background: var(--card); }
.afe-pal-s { padding: 10px 10px 4px; }
/* 节点 */
.afe-node, .afe-start { border-radius: 14px; box-shadow: var(--sh-sm); }
.afe-node:hover, .afe-start:hover { border-color: var(--input-border); box-shadow: var(--sh-md); }
.afe-node.sel, .afe-start.sel { border-color: var(--primary-fill); box-shadow: 0 0 0 3px var(--focus-ring), var(--sh-md); }
.afe-node .hd, .afe-start .hd { padding: 12px 12px 10px 14px; }
/* 平台色小方块：一个平台一种颜色，没列出的平台按名字落在石板灰，青，橙里 */
.afe-pic { border-radius: 8px; background: var(--indigo); }
.afe-node .afe-pic, .afe-start .afe-pic { width: 30px; height: 30px; border-radius: 9px; }
.afe-pic.pc-violet { background: var(--violet); } .afe-pic.pc-pink { background: var(--pink); } .afe-pic.pc-indigo { background: var(--indigo); } .afe-pic.pc-blue { background: var(--blue); }
.afe-pic.pc-teal { background: var(--teal); } .afe-pic.pc-green { background: var(--green); } .afe-pic.pc-sky { background: var(--sky); } .afe-pic.pc-amber { background: var(--amber); }
.afe-pic.pc-rose { background: var(--rose); } .afe-pic.pc-grey { background: var(--ink4); } .afe-pic.pc-coral { background: var(--rose); }
.afe-pic.pc-slate { background: #4E5BA6; } .afe-pic.pc-cyan { background: #06AED4; } .afe-pic.pc-orange { background: #EF6820; }
/* 开始节点的图标块：深色下不能跟着字色变白 */
.afe-start .afe-pic { background: #101828; color: #fff; }
:root[data-theme="dark"] .afe-start .afe-pic { background: #333741; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .afe-start .afe-pic { background: #333741; } }
.afe-e .ln { stroke: var(--ink4); stroke-width: 1.6; }
.afe-e.hov .ln, .afe-e.hl .ln, .afe-e.sel .ln { stroke: var(--primary-fill); }
.afe-mini { border-radius: var(--r-lg); box-shadow: var(--sh-md); border-color: var(--border); }
.afe-etools, .afe-pop { border-radius: var(--r-lg); }
.afe-tag { border-radius: var(--r-sm); padding: 0 6px; font-weight: 500; }
.afe-tag.bad { color: var(--red-ink); background: var(--red-bg); }
/* 设置面板：圆角白卡；小节标题不要竖条，参数一组的头不用灰色条带，只留下面一条细线 */
.afe-side { border: 1px solid var(--border); border-radius: var(--r-lg); box-shadow: var(--afe-side-shadow); }
.afe-sec-h::before { display: none; }
.afe-grp-h { background: none !important; border-bottom: 1px solid var(--border); font-weight: 600; }
/* 引用开关打开：浅蓝底蓝图标，和画布上接上的口一个意思，不做成实心主按钮 */
.afe-bind.on { background: var(--primary-bg); color: var(--primary); }
.afe-bind.on:hover { background: var(--primary-bg); color: var(--primary-hover); }
/* 开关打开是帆软蓝；深色下关着的轨道暗灰，不比输入框亮 */
.afe-sw input:checked { background: var(--primary-fill); }
:root[data-theme="dark"] .afe-sw input:not(:checked) { background: #333741; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .afe-sw input:not(:checked) { background: #333741; } }
.afe-tb-h .req { margin-right: 4px; }
/* 右边的对话栏定宽，画布拿剩下的，照 Cursor 与 Dify 的右侧面板；设置面板盖在对话上时，问整个工作流的示例说法收起来 */
.afe-split > .afe-chat { flex: 0 0 clamp(340px, 30%, 420px); }
.afe.afe-sidevis .afe-chat .as-ex { display: none; }
/* 画布铺到边：页头下沿，组件面板右沿，对话栏左沿与窗口底边就是画布的边；窄到一栏时照旧 */
.afe.afe-pad:not(.small) { gap: 0; }
.afe.afe-pad:not(.small) > .afe-split, .afe.afe-pad:not(.small) > .afe-body { margin: 0 -12px -12px; }
.afe.afe-pad:not(.small) .afe-split { gap: 0; }
.afe.afe-pad:not(.small) .afe-pal { margin: 12px 0 12px 12px; }
.afe.afe-pad:not(.small) .afe-split > .afe-chat { margin: 12px 12px 12px 0; }
.afe.afe-pad:not(.small) .afe-body > .afe-side { top: 12px; right: 12px; bottom: 12px; }
.afe.afe-pad:not(.small) .afe-tools, .afe.afe-pad:not(.small) .afe-mini { bottom: 16px; }

/* 依据：照 Know-how 生成的节点照的是哪份图哪一步，摆在 AI 理解上面；左边灰竖条，表头底色，灯泡与“依据”，出处一行灰字，下面原文一句 */
.afe-basis { flex: none; margin: 14px 16px 0; padding: 8px 12px 10px; border-left: 2px solid var(--afe-ink4); border-radius: 0 var(--afe-r) var(--afe-r) 0; background: var(--afe-th-bg); }
.afe-basis + .afe-und { margin-top: 10px; }
.afe-basis-h { display: flex; align-items: center; gap: 6px; min-height: 20px; margin: 0 0 2px; }
.afe-basis-h .afe-i { flex: none; width: 14px; height: 14px; color: var(--afe-ink3); }
.afe-basis-h .l { flex: none; font-size: 12.5px; line-height: 20px; font-weight: 600; color: var(--afe-ink2); }
.afe-basis-h .f { min-width: 0; margin-left: auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; line-height: 18px; color: var(--afe-ink3); }
.afe-basis-steps { display: flex; flex-wrap: wrap; gap: 4px; margin: 4px 0 0; }
.afe-basis-st { max-width: 100%; padding: 1px 8px; border: 1px solid var(--afe-border); border-radius: 6px; background: var(--afe-card); font-size: 12px; line-height: 18px; color: var(--afe-ink2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.afe-basis-q { max-height: 126px; margin: 8px 0 0; overflow-y: auto; font-size: 13px; line-height: 21px; color: var(--afe-ink2); overflow-wrap: anywhere; scrollbar-width: thin; }
/* AI 理解：AI 编辑组件顶上一块，左边青蓝竖条浅青蓝底；正在照改动重写时上一版灰着，右头写进度。只读的人摆在设置一栏顶上 */
.afe-und { flex: none; margin: 14px 16px 0; padding: 8px 12px 10px; border-left: 2px solid var(--afe-sky); border-radius: 0 var(--afe-r) var(--afe-r) 0; background: var(--afe-sky-bg); }
.afe-und.busy { border-left-color: var(--afe-ink4); }
.afe-und-h { display: flex; align-items: center; gap: 8px; min-height: 20px; margin: 0 0 4px; white-space: nowrap; }
.afe-und-h .l { flex: none; font-size: 12.5px; line-height: 20px; font-weight: 600; color: var(--afe-ink2); }
.afe-und-h .st { display: inline-flex; align-items: center; gap: 6px; min-width: 0; margin-left: auto; overflow: hidden; text-overflow: ellipsis; font-size: 12px; line-height: 18px; color: var(--afe-ink3); }
.afe-und-h .st.bad { color: var(--afe-red); }
.afe-und-h .afe-spin { flex: none; width: 12px; height: 12px; }
.afe-und-re { flex: none; padding: 0; border: 0; background: none; font: inherit; color: var(--afe-primary); cursor: pointer; }
.afe-und-re:hover { text-decoration: underline; }
.afe-und p { max-height: 168px; margin: 0; overflow-y: auto; font-size: 13px; line-height: 21px; color: var(--afe-ink2); white-space: pre-wrap; overflow-wrap: anywhere; scrollbar-width: thin; }
.afe-und p.old, .afe-und p.afe-muted { color: var(--afe-ink3); }
/* 10-28 起理解是编号条列：数字与正文对齐，一条一行，长了折行仍缩进在数字后面 */
.afe-und-ol { max-height: 168px; margin: 0; padding: 0 0 0 20px; overflow-y: auto; font-size: 13px; line-height: 21px; color: var(--afe-ink2); overflow-wrap: anywhere; scrollbar-width: thin; }
.afe-und-ol li { padding-left: 2px; }
.afe-und-ol li + li { margin-top: 2px; }
.afe-und-ol li::marker { color: var(--afe-ink3); font-variant-numeric: tabular-nums; }
.afe-und-ol.old { color: var(--afe-ink3); }
.afe-und-ol.afe-swap { animation: afe-swap .26s var(--afe-ease) both; }
.afe-und p.afe-swap { animation: afe-swap .26s var(--afe-ease) both; }
/* 这个节点用了哪几个技能（11-01 原生对齐 N3）：理解下面一行，“技能”12px 灰字，后面一个技能一个白底细框小块，拼图图标加名称，点了到技能页 */
.afe-und-sk { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; margin: 8px 0 0; padding-top: 8px; border-top: 1px solid color-mix(in srgb, var(--afe-sky) 22%, transparent); }
.afe-und-sk .l { flex: none; margin-right: 2px; font-size: 12px; line-height: 22px; color: var(--afe-ink3); }
.afe-skc { display: inline-flex; align-items: center; gap: 4px; max-width: 100%; height: 22px; padding: 0 8px 0 6px; border: 1px solid var(--afe-border); border-radius: 6px;
  background: var(--afe-card); color: var(--afe-ink2); font-size: 12px; line-height: 20px; text-decoration: none; transition: border-color .12s ease, color .12s ease; }
.afe-skc span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.afe-skc .afe-i { flex: none; width: 13px; height: 13px; color: var(--afe-ink3); }
a.afe-skc:hover { border-color: var(--afe-primary); color: var(--afe-primary); }
a.afe-skc:hover .afe-i { color: var(--afe-primary); }
a.afe-skc:focus-visible { outline: 0; box-shadow: 0 0 0 3px var(--afe-focus, var(--focus-ring)); }
.afe-skc.off { color: var(--afe-ink4); background: none; }
.afe-und-wait { display: flex; align-items: center; gap: 8px; }
.afe-und-wait .afe-spin { width: 14px; height: 14px; }
/* 一次也没写过理解（11-01 第二轮 D4 起打开大框不自动调模型）：一个文字按钮，点了让 AI 读一遍 */
.afe-und-go { display: inline-flex; align-items: center; gap: 6px; height: 28px; margin: 2px 0 0; padding: 0 12px 0 10px;
  border: 1px solid color-mix(in srgb, var(--afe-primary) 35%, transparent);
  border-radius: 14px; background: transparent; font: inherit; font-size: 13px; line-height: 26px; color: var(--afe-primary); cursor: pointer; }
.afe-und-go:hover { border-color: var(--afe-primary); }
.afe-und-go .afe-i { width: 14px; height: 14px; }
/* 从项目进的套件里：AI 编辑组件顶上一行“只改这个工作流里的这一份”，下面一行写这个工作流另设了哪几样（11-01 第二轮 D4） */
.afe-nai-scope { flex: none; display: flex; align-items: flex-start; gap: 8px; margin: 14px 16px 0; padding: 8px 12px; border: 1px solid var(--afe-border);
  border-radius: var(--afe-r); background: var(--afe-card); font-size: 12.5px; line-height: 19px; color: var(--afe-ink2); }
.afe-nai-scope[hidden] { display: none; }
.afe-nai-scope .afe-nai-scope-i { flex: none; width: 16px; height: 16px; margin-top: 1px; color: var(--afe-primary); }
.afe-nai-scope .tx { min-width: 0; }
.afe-nai-scope .sub { margin-top: 2px; color: var(--afe-ink3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.afe-nai-scope + .afe-basis, .afe-nai-scope + .afe-und { margin-top: 10px; }
.afe-fx-p > .afe-und { margin: 12px 16px 4px; }
/* 手改代码以后问要不要记进 Know-how：理解下面一行浅框，灯泡，一句话，选库，记进去与不用 */
.afe-kh { flex: none; display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin: 10px 16px 0; padding: 8px 10px; border: 1px solid var(--afe-border); border-radius: var(--afe-r); font-size: 13px; line-height: 20px; }
.afe-kh.afe-swap { animation: afe-swap .26s var(--afe-ease) both; }
.afe-kh > .afe-i { width: 16px; height: 16px; color: var(--afe-sky); }
.afe-kh .tx { flex: 1 1 220px; min-width: 0; color: var(--afe-ink2); }
.afe-kh select.afe-in { width: auto; max-width: 220px; height: 28px; }
.afe-kh .afe-ib { width: 26px; height: 26px; }
/* 预览里用的：空着，没成，表格，用到的知识 */
.afe-pv-empty { display: flex; align-items: center; gap: 8px; }
.afe-pv-empty .afe-spin { width: 14px; height: 14px; }
.afe-pv-err { display: flex; align-items: flex-start; gap: 6px; margin: 0 0 10px; color: var(--afe-red); overflow-wrap: anywhere; }
.afe-pv-err .afe-i { width: 16px; height: 16px; margin-top: 2px; }
.afe-pv-meta { display: block; margin: 0 0 6px; font-size: 12px; line-height: 18px; }
.afe-fxo-bar .afe-pv-meta { display: inline; margin: 0; }
.afe-pv-tw { overflow: auto; border: 1px solid var(--afe-divider); border-radius: var(--afe-r); }
/* 表格放不下要左右滑时，哪一边还有列那一边的边上一道淡影（随内容滚的底色盖着，滑到头就没了，11-01 R2 复审） */
.afe-pv-tw {
  background:
    linear-gradient(to right, var(--afe-card) 40%, transparent) left center / 28px 100% no-repeat local,
    linear-gradient(to left, var(--afe-card) 40%, transparent) right center / 28px 100% no-repeat local,
    linear-gradient(to right, color-mix(in srgb, var(--afe-ink) 18%, transparent), transparent) left center / 14px 100% no-repeat scroll,
    linear-gradient(to left, color-mix(in srgb, var(--afe-ink) 18%, transparent), transparent) right center / 14px 100% no-repeat scroll;
  background-color: var(--afe-card);
}
/* 表头底色透一点，边上那道淡影表头这一行也看得到（框不限高，表头不用贴顶） */
.afe-pv-tw > .afe-pv-tbl th { background: color-mix(in srgb, var(--afe-th-bg) 80%, transparent); }
/* 格子里点开浮出的一小块盖在表格上：框线用输入框色；深色下底色提一级（浮起的面），投影加深，跟底下的表格分得开 */
.afe-pop:has(> .afe-vpop) { border-color: var(--afe-input); }
:root[data-theme="dark"] .afe-pop:has(> .afe-vpop) { --afe-card: var(--raised, #1A1E25); box-shadow: 0 16px 36px rgba(0, 0, 0, .6); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .afe-pop:has(> .afe-vpop) { --afe-card: var(--raised, #1A1E25); box-shadow: 0 16px 36px rgba(0, 0, 0, .6); } }
.afe-pv-tbl { border-collapse: collapse; min-width: 100%; font-size: 12.5px; line-height: 18px; }
.afe-pv-tbl th, .afe-pv-tbl td { max-width: 240px; padding: 5px 10px; border-bottom: 1px solid var(--afe-divider); text-align: left; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.afe-pv-tbl th { position: sticky; top: 0; background: var(--afe-th-bg); color: var(--afe-ink2); font-weight: 500; }
.afe-pv-tbl tr:last-child td { border-bottom: 0; }
.afe-pv-kbs { display: flex; align-items: flex-start; gap: 6px; margin: 0 0 8px; }
.afe-pv-kbs .afe-i { width: 16px; height: 16px; margin-top: 2px; color: var(--afe-sky); }
.afe-pv-used { list-style: none; margin: 0; padding: 0; }
/* 用到的知识分两块时的小标题：不缩进，跟上面“知识库：”一行左对齐，比框里的块名小一号 */
.afe-pv-part + .afe-pv-part { margin-top: 10px; }
.afe-pv-sh { margin: 0 0 2px; font-size: 12.5px; line-height: 20px; font-weight: 600; color: var(--afe-ink2, var(--afe-ink)); }
.afe-pv-used li { display: flex; align-items: center; gap: 8px; min-height: 28px; }
.afe-pv-used .tt { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: var(--mono, var(--afe-mono)); font-size: 12.5px; }

/* ---------- 节点大框：几乎占满窗口，一屏摆接线，设置，参数源码预览一个框，AI 编辑组件；细则见 docs/STYLE_PORTAL.md“节点大框” ---------- */
.afe-fx-mask { position: fixed; inset: 0; z-index: 48; display: flex; padding: 16px; background: var(--scrim, rgba(16, 24, 40, .36)); color: var(--afe-ink); font-size: 14px; line-height: 22px; animation: afe-fade .2s ease-out both; }
.afe-fx-mask.out { pointer-events: none; animation: afe-fade-out .2s ease-in both; }
@keyframes afe-fade-out { to { opacity: 0; } }
.afe-fx { position: relative; flex: 1; min-width: 0; min-height: 0; display: flex; flex-direction: column; overflow: hidden; background: var(--afe-card); border-radius: var(--r-xl, 16px); box-shadow: var(--sh-xl, 0 20px 24px -4px rgba(16, 24, 40, .1)); outline: 0; animation: afe-fx-in .3s var(--afe-ease) both; }
.afe-fx-mask.out .afe-fx { animation: afe-fx-out .2s var(--afe-ease-in) both; }
@keyframes afe-fx-in { from { opacity: 0; transform: translateY(12px) scale(.985); } }
@keyframes afe-fx-out { to { opacity: 0; transform: translateY(6px) scale(.985); } }
/* 页头 60 高：平台图标，可改的标题，下面一行组件，组件名，节点编号；右边上一个下一个，更多，关闭 */
.afe-fx-h { flex: none; display: flex; align-items: center; gap: 12px; height: 60px; padding: 0 12px 0 16px; border-bottom: 1px solid var(--afe-border); }
.afe-fx-h .sp { flex: 1; }
.afe-fx-pic { flex: none; display: flex; }
.afe-fx-pic .afe-pic { width: 32px; height: 32px; border-radius: 9px; }
.afe-fx-pic .afe-pic .afe-i { width: 19px; height: 19px; }
.afe-fx-tt { min-width: 0; display: flex; flex-direction: column; }
.afe-fx-h .afe-ntitle { width: min(440px, 42vw); height: 28px; margin-left: -7px; padding: 0 6px; font-size: 16px; font-weight: 600; line-height: 26px; border-color: transparent; background: none; box-shadow: none; }
.afe-fx-h .afe-ntitle:hover { border-color: var(--afe-input); }
.afe-fx-h .afe-ntitle:focus { border-color: var(--afe-primary); background: var(--afe-card); }
.afe-fx-h .afe-ntitle[readonly]:hover, .afe-fx-h .afe-ntitle[readonly]:focus { border-color: transparent; box-shadow: none; }
.afe-fx-sub { display: flex; align-items: center; gap: 8px; min-width: 0; height: 20px; font-size: 12.5px; line-height: 20px; color: var(--afe-ink3); white-space: nowrap; }
.afe-fx-sub .t { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.afe-fx-sub .afe-mono { font-size: 12px; color: var(--afe-ink4); }
.afe-fx-sub .afe-tag { height: 18px; line-height: 18px; font-size: 12px; }
.afe-fx-sub .afe-info { width: 22px; height: 22px; }
.afe-fx-sub .afe-info .afe-i { width: 16px; height: 16px; }
.afe-fx-nav { display: inline-flex; gap: 2px; padding-right: 6px; margin-right: 2px; border-right: 1px solid var(--afe-border); }
.afe-fx-h .afe-ib { width: 32px; height: 32px; }
.afe-fx-aibtn { display: none; }
.afe-fx-aibtn.on { color: var(--afe-primary); border-color: var(--afe-primary); background: var(--afe-primary-bg); }
.afe-fx-tabs { display: none; }
/* 主体：左边设置收成一列图标，从上到底；中间上面接线，下面一个框三个页签，高按 7:3 分（10-29 用户：“接线框高度改大 预览框高度减小 6：4或者7：3合理”），
   下面的框至少 260px，矮窗口就近 6:4；接线收起时只占一行，下面的框占满。右边整列 AI 编辑组件。
   浮出的设置贴着图标列，从接线上沿到底，盖在接线与中间的框上，参数多时不被压矮 */
.afe-fx-b { position: relative; flex: 1; min-height: 0; display: grid; grid-template-columns: 64px minmax(0, 1fr) minmax(330px, 27%);
  grid-template-rows: minmax(0, 7fr) minmax(260px, 3fr); grid-template-areas: "r w a" "r m a"; }
.afe-fx-b:has(> .afe-fx-w.shut) { grid-template-rows: auto minmax(0, 1fr); }
.afe-fx-w { grid-area: w; }
.afe-fx-rail { grid-area: r; }
.afe-fx-m { grid-area: m; }
.afe-fx-p { grid-area: 1 / 2 / 3 / 3; }
.afe-fx-a { grid-area: a; }
/* 每一块的头 44 高：块名 13.5px 加粗，右边是这一块的操作 */
.afe-fx-ph { flex: none; display: flex; align-items: center; gap: 8px; height: 44px; padding: 0 12px 0 16px; border-bottom: 1px solid var(--afe-divider); white-space: nowrap; }
.afe-fx-ph h3 { flex: none; margin: 0; font-size: 13.5px; line-height: 20px; font-weight: 600; color: var(--afe-ink); }
.afe-fx-ph .sp { flex: 1; }
.afe-fx-ph .afe-btn.sm { height: 28px; }
.afe-fx-empty { font-size: 13px; line-height: 21px; color: var(--afe-ink3); }
/* 接线：点阵底，和画布一个样子；高照上面主体的分法，放不下时这一条自己滚 */
.afe-fx-w { position: relative; min-height: 0; overflow: auto; border-bottom: 1px solid var(--afe-border); background-color: var(--cv-bg, var(--afe-page));
  background-image: radial-gradient(var(--afe-dot) 1px, transparent 1.2px); background-size: 20px 20px; scrollbar-width: thin; }
/* 左上角“接线”：点了收起或展开。展开时浮在点阵左上角，不占一行；收起时一行写上游 → 这个节点 → 下游 */
.afe-fw-bar { position: sticky; left: 0; top: 0; z-index: 3; display: flex; align-items: center; gap: 12px; width: max-content; max-width: 100%; height: 0; padding: 0 12px 0 8px; overflow: visible; }
.afe-fw-bar > .afe-fw-l { transform: translateY(22px); }
.afe-fw-l { flex: none; display: inline-flex; align-items: center; gap: 2px; height: 28px; padding: 0 8px 0 2px; border: 0; border-radius: var(--afe-r); background: none;
  font: inherit; font-size: 13.5px; line-height: 20px; font-weight: 600; color: var(--afe-ink); cursor: pointer; transition: background-color .12s ease; }
.afe-fw-l:hover { background: var(--afe-hover); }
.afe-fw-l:focus-visible { outline: 0; box-shadow: var(--afe-ring); }
.afe-fw-l .afe-i { width: 18px; height: 18px; color: var(--afe-ink3); transform: rotate(90deg); transition: transform .2s var(--afe-ease); }
/* 下面还有接线的内容时（矮窗口，上游多），底边 28px 淡出 */
.afe-fx-w.more::after { content: ""; position: sticky; left: 0; bottom: 0; display: block; height: 28px; margin-top: -28px; pointer-events: none;
  background: linear-gradient(to bottom, transparent, var(--cv-bg, var(--afe-page))); }
/* 接线与下面框的分界：9px 高的拖动区压在接线下沿，悬停，拖动与键盘选中时中间一条 2px 主色线；接线收起时不摆 */
.afe-fx-sep { grid-area: w; align-self: end; position: relative; z-index: 4; height: 9px; margin-bottom: -5px; cursor: row-resize; touch-action: none; }
.afe-fx-sep::after { content: ""; position: absolute; left: 0; right: 0; top: 4px; height: 2px; border-radius: 1px; background: transparent; transition: background-color .12s ease; }
.afe-fx-sep:hover::after, .afe-fx-sep.on::after, .afe-fx-sep:focus-visible::after { background: var(--afe-primary-fill); }
.afe-fx-sep:focus-visible { outline: 0; }
.afe-fx-b:has(> .afe-fx-w.shut) > .afe-fx-sep { display: none; }
.afe-fx-w.shut { overflow: hidden; background-image: none; background-color: var(--afe-th-bg); }
.afe-fx-w.shut .afe-fw-bar { position: static; height: 44px; width: auto; }
.afe-fx-w.shut .afe-fw-bar > .afe-fw-l { transform: none; }
.afe-fx-w.shut .afe-fw-l .afe-i { transform: none; }
.afe-fw-brief { display: flex; align-items: center; gap: 6px; min-width: 0; overflow: hidden; white-space: nowrap; }
.afe-fw-chip { flex: none; display: inline-flex; align-items: center; gap: 6px; max-width: 200px; height: 28px; padding: 0 9px 0 4px; border: 1px solid var(--afe-node-line); border-radius: 8px; background: var(--afe-card);
  color: var(--afe-ink2); font: inherit; font-size: 12.5px; cursor: pointer; transition: border-color .12s ease; }
.afe-fw-chip:hover { border-color: var(--afe-primary-fill); }
.afe-fw-chip .afe-pic { flex: none; width: 20px; height: 20px; border-radius: 6px; }
.afe-fw-chip .afe-pic .afe-i { width: 13px; height: 13px; }
.afe-fw-chip .t { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.afe-fw-chip.me { border-color: var(--afe-primary-fill); color: var(--afe-ink); font-weight: 600; cursor: default; box-shadow: 0 0 0 2px var(--focus-ring, rgba(54, 133, 242, .2)); }
.afe-fw-ar { flex: none; color: var(--afe-ink4); }
.afe-fw-no { flex: none; font-size: 12.5px; color: var(--afe-ink4); }
/* 平时三列上下居中；上游或下游多到这一条放不下要滚时，三列都靠顶，比较矮的两列贴在顶上跟着滚，芯片一直看得见 */
.afe-fw-g { position: relative; display: flex; align-items: center; justify-content: center; gap: 80px; width: max-content; min-width: 100%; padding: 46px 40px 18px; }
.afe-fw-g.tall { align-items: flex-start; }
.afe-fw-col { position: relative; z-index: 1; display: flex; flex-direction: column; gap: 10px; }
.afe-fw-g.tall > .afe-fw-col, .afe-fw-g.tall > .afe-fw-me { position: sticky; top: 42px; }
.afe-fw-col.up { align-items: flex-end; }
.afe-fw-col.dn { align-items: flex-start; }
.afe-fw-s { position: absolute; left: 0; top: 0; z-index: 0; overflow: visible; pointer-events: none; }
.afe-fw-s path { fill: none; stroke: var(--afe-primary-fill); stroke-width: 1.6; transition: opacity .15s ease, stroke-width .15s ease; }
.afe-fw-s path.kn { stroke: var(--afe-sky); }
.afe-fw-s path.mn { stroke: var(--afe-edge); stroke-dasharray: 4 3; }
.afe-fw-s.hov path { opacity: .22; }
.afe-fw-s.hov path.hl { opacity: 1; stroke-width: 2.2; }
/* 上下游的小卡片：卡片头是平台图标与标题，下面一行一个连着的口，口压在朝着中间的那条边上 */
.afe-fw-n { position: relative; display: block; width: 200px; padding: 0 0 6px; border: 1px solid var(--afe-node-line); border-radius: 10px; background: var(--afe-card); box-shadow: var(--sh-xs);
  color: var(--afe-ink); font: inherit; text-align: left; cursor: pointer; transition: border-color .15s ease, box-shadow .15s ease; }
.afe-fw-n:hover { border-color: var(--afe-primary-fill); box-shadow: var(--sh-sm); }
.afe-fw-n:focus-visible { outline: 0; box-shadow: var(--afe-ring); }
.afe-fw-n .hd { display: flex; align-items: center; gap: 8px; height: 36px; padding: 0 10px; }
.afe-fw-n .afe-pic { flex: none; width: 20px; height: 20px; border-radius: 6px; }
.afe-fw-n .afe-pic .afe-i { width: 13px; height: 13px; }
.afe-fw-n .t { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12.5px; line-height: 18px; font-weight: 600; }
.afe-fw-n .io { display: block; padding-top: 4px; border-top: 1px solid var(--afe-divider); margin: 0 0 0; }
.afe-fw-n .r { position: relative; display: flex; align-items: center; height: 22px; padding: 0 12px; font-size: 12px; color: var(--afe-ink2); }
.afe-fw-n.up .r { justify-content: flex-end; }
.afe-fw-n .r .k { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.afe-fw-n .afe-pin { box-shadow: 0 0 0 2px var(--afe-card); }
.afe-fw-st { background: #101828; color: #fff; }
:root[data-theme="dark"] .afe-fw-st { background: #333741; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .afe-fw-st { background: #333741; } }
.afe-fw-morew { position: sticky; left: 0; bottom: 10px; z-index: 3; display: flex; align-items: flex-end; justify-content: flex-end; height: 0; padding: 0 16px; overflow: visible; pointer-events: none; }
.afe-fw-more { flex: none; height: 28px; padding: 0 12px; border: 1px solid var(--afe-border); border-radius: 14px; background: var(--afe-card); box-shadow: var(--sh-sm);
  color: var(--afe-ink2); font: inherit; font-size: 12.5px; white-space: nowrap; cursor: pointer; pointer-events: auto; }
.afe-fw-more:hover { color: var(--afe-primary); border-color: var(--afe-primary-fill); }
.afe-fw-none { display: flex; align-items: center; justify-content: center; width: 140px; height: 40px; border: 1px dashed var(--afe-input); border-radius: 10px; background: var(--afe-card); font-size: 12px; color: var(--afe-ink4); }
/* 中间这个节点：和画布上的卡片同一张芯片，帆软蓝框，口旁边不写值 */
.afe-fw-me { position: relative; z-index: 1; width: 288px; cursor: default; border-color: var(--afe-primary-fill); box-shadow: 0 0 0 3px var(--focus-ring, rgba(54, 133, 242, .2)), var(--sh-md); }
.afe-fw-me:hover { border-color: var(--afe-primary-fill); box-shadow: 0 0 0 3px var(--focus-ring, rgba(54, 133, 242, .2)), var(--sh-md); }
.afe-fw-me .hd { padding-right: 12px; }
.afe-fw-me .io .k { max-width: 132px; }
.afe-fw-me .io .co { max-width: 132px; }
.afe-fw-me .afe-pin { box-shadow: 0 0 0 2px var(--afe-card); }
.afe-fw-me .io .ci[data-k] { cursor: pointer; }
.afe-fw-me .io .ci[data-k]:hover .k { color: var(--afe-primary); }
/* 手机宽接线竖着排（R2 评审 P2-9，原来三列横排 928px 宽，390 宽只露出这个节点一个字）：上游一列在上靠左，这个节点居中，下游一列在下靠右，
   宽度放得下不用左右滑；上游卡片的口挪到左边，下游的挪到右边，线在两边鼓出去绕：进来的从左边接到这个节点的入口，出去的从出口右边接下去 */
@media (max-width: 759px) {
  .afe-fw-g, .afe-fw-g.tall { flex-direction: column; align-items: stretch; gap: 28px; width: 100%; min-width: 0; padding: 24px 36px 28px; }
  /* 页签上已写着接线，这一块展开时不再写“接线”与收起的三角（整屏一块，收起来没有用）；从宽屏带来的收起状态照旧摆着，点了展开 */
  .afe-fx-w:not(.shut) .afe-fw-bar { display: none; }
  .afe-fw-g.tall > .afe-fw-col, .afe-fw-g.tall > .afe-fw-me { position: relative; top: auto; }
  .afe-fw-col.up { align-items: flex-start; }
  .afe-fw-col.dn { align-items: flex-end; }
  .afe-fw-n { width: min(240px, 100%); }
  .afe-fw-n.up .r { justify-content: flex-start; }
  .afe-fw-n.up .afe-pin.o { right: auto; left: -4.5px; }
  .afe-fw-n.dn .r { justify-content: flex-end; }
  .afe-fw-n.dn .afe-pin.i { left: auto; right: -4.5px; }
  .afe-fw-me { align-self: center; width: min(288px, 100%); }
}
/* 参数：分组照旧，这一栏自己滚 */
/* 设置的图标列：一组一个 52 见方的键，图标下面写组名；浮着的那一组浅主色底主色字；组里有问题右上角红点，只有提醒是橙点 */
.afe-fx-rail { display: flex; flex-direction: column; align-items: center; gap: 4px; min-height: 0; padding: 10px 0; overflow-y: auto; scrollbar-width: none;
  border-right: 1px solid var(--afe-border); background: var(--afe-card); }
.afe-fx-ri { position: relative; flex: none; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px; width: 52px; height: 52px; padding: 0;
  border: 0; border-radius: var(--afe-r); background: none; color: var(--afe-ink2); font: inherit; cursor: pointer; transition: color .12s ease, background-color .12s ease; }
.afe-fx-ri .afe-i { width: 20px; height: 20px; }
.afe-fx-ri .t { font-size: 11.5px; line-height: 14px; white-space: nowrap; }
.afe-fx-ri:hover { color: var(--afe-ink); background: var(--afe-hover); }
.afe-fx-ri.on { color: var(--afe-primary); background: var(--afe-primary-bg); }
.afe-fx-ri:focus-visible { outline: 0; box-shadow: var(--afe-ring); }
.afe-fx-ri .dot { position: absolute; top: 7px; right: 10px; width: 7px; height: 7px; border-radius: 50%; background: var(--afe-red); box-shadow: 0 0 0 2px var(--afe-card); }
.afe-fx-ri .dot.w { background: var(--afe-orange); }
/* 浮出的设置：贴着图标列，盖在中间的框上，右边一道投影；平时不摆 */
.afe-fx-p { position: relative; z-index: 5; justify-self: start; display: none; flex-direction: column; width: min(400px, 82%); min-height: 0;
  border-right: 1px solid var(--afe-border); background: var(--afe-card); box-shadow: 16px 0 36px rgba(16, 24, 40, .16); }
.afe-fx.fly .afe-fx-p { display: flex; animation: afe-fly-in .22s var(--afe-ease) both; }
/* 深色下底色和框一样，投影加深，右边框提亮，看得出浮在上面 */
:root[data-theme="dark"] .afe-fx-p { border-right-color: var(--afe-input); box-shadow: 16px 0 36px rgba(0, 0, 0, .55); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .afe-fx-p { border-right-color: var(--afe-input); box-shadow: 16px 0 36px rgba(0, 0, 0, .55); } }
@keyframes afe-fly-in { from { opacity: 0; transform: translateX(-12px); } }
.afe-fx-flyic { flex: none; display: inline-flex; color: var(--afe-ink3); }
.afe-fx-flyic .afe-i { width: 18px; height: 18px; }
.afe-fx-flyx { width: 28px; height: 28px; }
.afe-fx-pb { flex: 1; min-height: 0; overflow-y: auto; padding: 0 0 24px; scrollbar-width: thin; }
/* 只摆浮着的那一组：组头的折叠不用，收着的组也摆开 */
.afe-fx-pb.one > .afe-grp:not(.on) { display: none; }
.afe-fx-pb.one > .afe-grp > .afe-grp-h { display: none; }
.afe-fx-pb.one > .afe-grp.shut > .afe-grp-b { display: block; }
.afe-fx-pb.one > .afe-grp > .afe-grp-b { border-bottom: 0; }
/* 几块滚动区的底边 14 像素淡出，滚到一半的那行字不贴着大框边硬切，和组件工厂的在线开发页一样 */
.afe-fx-pb, .afe-fx-vb { -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 14px), transparent 100%); mask-image: linear-gradient(to bottom, #000 calc(100% - 14px), transparent 100%); }
.afe-fx-a .afe-nai-msgs { -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 12px, #000 calc(100% - 12px), transparent 100%); mask-image: linear-gradient(to bottom, transparent 0, #000 12px, #000 calc(100% - 12px), transparent 100%); }
/* 中间一栏：一个框，头上一排页签，预览，结果，输入，日志，用到的知识，代码；右边写结果从哪来与几个按钮；代码页签下面多一排看哪一份代码，参数与源码共用编辑器 */
.afe-fx-m { display: flex; flex-direction: column; min-width: 0; min-height: 0; }
.afe-fx-k { flex: 1; min-height: 0; display: flex; flex-direction: column; margin: 12px 16px 16px; border: 1px solid var(--afe-border); border-radius: var(--afe-rc); overflow: hidden; background: var(--afe-card); }
.afe-fx-kbar { flex: none; display: flex; align-items: center; flex-wrap: wrap; gap: 4px 6px; min-height: 44px; padding: 6px 8px 6px 6px; border-bottom: 1px solid var(--afe-border); background: var(--afe-th-bg); white-space: nowrap; }
/* 页签不缩；右边的语言名与按钮靠右，一行放不下时整组折到第二行，页签一个都不挤掉 */
.afe-fx-ktools { display: flex; align-items: center; gap: 6px; margin-left: auto; }
.afe-fx-kbar .afe-btn.sm { flex: none; height: 28px; }
.afe-fx-kt { flex: none; display: flex; gap: 2px; max-width: 100%; overflow-x: auto; scrollbar-width: none; }
.afe-fx-kt button { flex: none; display: inline-flex; align-items: center; height: 30px; padding: 0 12px; border: 0; border-radius: var(--afe-r); background: none; color: var(--afe-ink2); font-size: 13px; cursor: pointer; white-space: nowrap; transition: color .12s ease, background-color .12s ease; }
.afe-fx-kt button:hover { color: var(--afe-primary); }
.afe-fx-kt button.on { background: var(--afe-card); color: var(--afe-primary); box-shadow: inset 0 0 0 1px var(--afe-border); }
.afe-fx-kt button:focus-visible { outline: 0; box-shadow: var(--afe-ring); }
/* 编辑器里这一份改了没保存：代码页签与那一份的小页签字后面一个橙色小圆点 */
.afe-fx-kt button.dirty > span::after, .afe-fx-ct button.dirty > span::after { content: ""; display: inline-block; width: 6px; height: 6px; margin: 0 0 1px 6px; border-radius: 50%; background: var(--afe-orange); vertical-align: middle; }
.afe-fx-knote { flex: none; padding: 6px 12px; font-size: 12.5px; line-height: 20px; color: var(--afe-orange-ink); background: var(--afe-orange-bg); }
.afe-fx-ked { flex: 1; min-height: 0; display: flex; background: var(--code-bg, var(--afe-card)); }
.afe-fx-ked > .cm-editor { flex: 1; min-width: 0; height: 100%; }
.afe-fx-ked .cm-scroller { overflow: auto; scrollbar-width: thin; scrollbar-color: var(--afe-ink4) transparent;
  /* 底边 14 像素淡出：代码比框长时最后一行淡下去，看得出下面还有，和组件工厂的代码区一样 */
  -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 14px), transparent 100%); mask-image: linear-gradient(to bottom, #000 calc(100% - 14px), transparent 100%); }
.afe-fx-ked .cm-editor .cm-content { padding-bottom: 14px; }
.afe-fx-kerr { padding: 12px; color: var(--afe-red); font-size: 13px; }
.afe-fx-kwait { padding: 16px; }
.afe-fx-ksub { flex: none; display: flex; align-items: center; flex-wrap: wrap; gap: 2px 8px; min-height: 44px; padding: 6px 16px; border-bottom: 1px solid var(--afe-divider); }
/* 看代码以外的页签时编辑器收起来，里面没保存的改动留着；看代码时下面那一块收起来，右头不写结果从哪来 */
.afe-fx-k.pv .afe-fx-ked, .afe-fx-k.pv .afe-fx-knote, .afe-fx-k.pv .afe-fx-ksub { display: none; }
.afe-fx-k:not(.pv) .afe-fx-vb, .afe-fx-k:not(.pv) .afe-fx-vm { display: none; }
/* 代码页签里看哪一份：分段切换，浅灰底轨道，选中的一块白底浮起，和结果的“表格，数据”一个样子，和框头的页签分开层级 */
.afe-fx-ct { display: inline-flex; flex: none; max-width: 100%; gap: 0; padding: 2px; overflow-x: auto; scrollbar-width: none; border-radius: var(--afe-r); background: var(--afe-grey-bg); }
.afe-fx-ct button { flex: none; display: inline-flex; align-items: center; height: 26px; padding: 0 12px; border: 0; border-radius: 6px; background: none; color: var(--afe-ink3); font-size: 12.5px; cursor: pointer; white-space: nowrap; transition: color .12s ease, background-color .12s ease, box-shadow .12s ease; }
.afe-fx-ct button:hover { color: var(--afe-ink); }
.afe-fx-ct button.on { background: var(--afe-card); color: var(--afe-ink); box-shadow: var(--sh-xs); }
.afe-fx-ct button:focus-visible { outline: 0; box-shadow: var(--afe-ring); }
/* 框头右边：结果从哪来，状态，用时，跟在按钮前面 */
.afe-fx-vm { display: inline-flex; align-items: center; flex-wrap: wrap; gap: 0 8px; min-width: 0; margin-right: 4px; font-size: 12.5px; color: var(--afe-ink3); }
.afe-fx-vm:empty { display: none; }
.afe-fx-vm a { color: var(--afe-primary); text-decoration: none; }
.afe-fx-vm a:hover { color: var(--afe-primary-hover, var(--afe-primary)); text-decoration: underline; }
.afe-fx-vm .afe-tag { height: 20px; line-height: 20px; font-size: 12px; }
.afe-fx-vb { flex: 1; min-height: 0; overflow: auto; padding: 12px 16px 16px; font-size: 13px; line-height: 20px; scrollbar-width: thin; }
.afe-fx-vb.web { display: flex; flex-direction: column; }
.afe-fx-vb .afe-links { margin: 0 0 10px; }
.afe-fxo { min-width: 0; }
.afe-fxo.web { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.afe-fxo-bar { flex: none; display: flex; align-items: center; gap: 8px; margin: 0 0 8px; }
.afe-fxo-bar .sp { flex: 1; }
.afe-fx-seg { display: inline-flex; padding: 2px; border-radius: var(--afe-r); background: var(--afe-grey-bg); }
.afe-fx-seg button { height: 26px; padding: 0 12px; border: 0; border-radius: 6px; background: none; color: var(--afe-ink3); font-size: 12.5px; cursor: pointer; transition: color .12s ease, background-color .12s ease, box-shadow .12s ease; }
.afe-fx-seg button:hover { color: var(--afe-ink); }
.afe-fx-seg button.on { background: var(--afe-card); color: var(--afe-ink); box-shadow: var(--sh-xs); }
.afe-fxo-open { display: inline-flex; align-items: center; gap: 4px; font-size: 12.5px; color: var(--afe-primary); text-decoration: none; }
.afe-fxo-open:hover { text-decoration: underline; }
.afe-fxo-open .afe-i { width: 15px; height: 15px; }
.afe-fx-page { flex: 1; min-height: 160px; width: 100%; border: 1px solid var(--afe-border); border-radius: var(--afe-r); background: #fff; }
/* 发布功能页的页面跟平台的深浅色画自己的底，载入前不闪一块白 */
.afe-fx-page.app { background: var(--afe-card); }
/* 没跑过的节点的输入：参数一行一个，左边参数名，右边写的值；接着上游的写来源与字段（字段主色），代码摆前三行 */
.afe-plan-tbl { width: 100%; border-collapse: collapse; table-layout: fixed; font-size: 13px; line-height: 20px; }
/* 只管这张表自己的行（跑过的输入里展开的对象与列表也是表，套在格子里，不吃外面这一层的宽与边距） */
.afe-plan-tbl > tbody > tr > th, .afe-plan-tbl > tbody > tr > td { padding: 8px 0; border-bottom: 1px solid var(--afe-divider); text-align: left; vertical-align: top; }
.afe-plan-tbl > tbody > tr:last-child > th, .afe-plan-tbl > tbody > tr:last-child > td { border-bottom: 0; }
/* 点一行到这个参数：悬停浅灰底，键盘停上去有焦点框 */
.afe-plan-tbl > tbody > tr { cursor: pointer; }
.afe-plan-tbl > tbody > tr:hover > th, .afe-plan-tbl > tbody > tr:hover > td { background: var(--afe-hover); }
.afe-plan-tbl > tbody > tr:focus-visible { outline: 0; box-shadow: var(--afe-ring); }
.afe-plan { margin: 0 -8px; }
.afe-plan-tbl > tbody > tr > th { padding-left: 8px; }
.afe-plan-tbl > tbody > tr > td { padding-right: 8px; }
.afe-plan-tbl > tbody > tr > th { width: 200px; padding-right: 16px; color: var(--afe-ink3); font-weight: 400; overflow-wrap: anywhere; }
.afe-plan-dim { color: var(--afe-ink4); }
.afe-plan-miss { color: var(--afe-red); }
.afe-plan-tbl > tbody > tr > td { min-width: 0; color: var(--afe-ink); overflow-wrap: anywhere; }
.afe-plan-t { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden; white-space: pre-wrap; }
.afe-plan-ref { display: inline-flex; align-items: baseline; flex-wrap: wrap; gap: 0 4px; }
.afe-plan-ref .src { color: var(--afe-ink3); }
.afe-plan-ref .sep { color: var(--afe-ink4); }
.afe-plan-ref .pth { color: var(--afe-primary); }
.afe-plan-code { margin: 0; padding: 6px 10px; border: 1px solid var(--afe-input); border-radius: 4px; background: var(--code-bg, var(--afe-card));
  font: 12.5px/19px var(--mono, var(--afe-mono)); color: var(--afe-ink); white-space: pre-wrap; overflow-wrap: anywhere; }
/* 跑过的输入与结果里一个字段一行的表（R2 评审 P1-1）：同没跑过的那张，只看，不点到参数，悬停不变底色 */
.afe-plan-tbl.ro > tbody > tr { cursor: default; }
.afe-plan-tbl.ro > tbody > tr:hover > th, .afe-plan-tbl.ro > tbody > tr:hover > td { background: none; }
/* 长文字最多三行，放不下的点一下看全；结果里的一段话不收 */
.afe-plan-t.more { cursor: pointer; }
.afe-plan-t.more:focus-visible { outline: 0; box-shadow: var(--afe-ring); border-radius: 4px; }
.afe-plan-t.open { display: block; -webkit-line-clamp: none; overflow: visible; }
.afe-vfull { white-space: pre-wrap; overflow-wrap: anywhere; }
/* 收起的对象与列表：“3 个字段”“5 项”带一个小三角，点了就地往下展开（表格的格子里浮出一小块），悬停看里面写的什么 */
.afe-vtog { display: inline-flex; align-items: center; gap: 2px; height: 22px; padding: 0 8px 0 2px; border: 0; border-radius: 6px; background: var(--afe-grey-bg);
  color: var(--afe-ink2); font: inherit; font-size: 12.5px; line-height: 22px; white-space: nowrap; cursor: pointer; vertical-align: middle; transition: color .12s ease, background-color .12s ease; }
.afe-vtog:hover { color: var(--afe-primary); }
.afe-vtog:focus-visible { outline: 0; box-shadow: var(--afe-ring); }
.afe-vtog .afe-i { width: 16px; height: 16px; color: var(--afe-ink3); transition: transform .15s var(--afe-ease); }
.afe-vtog[aria-expanded="true"] .afe-i { transform: rotate(90deg); }
.afe-vtog > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.afe-pv-tbl td .afe-vtog { max-width: 100%; height: 20px; line-height: 20px; margin: -1px 0; }
.afe-vw { min-width: 0; }
.afe-vw > .afe-plan-tbl, .afe-vw > .afe-pv-tw { margin-top: 6px; }
/* 展开的对象：左边一道竖线，名字照内容宽，不折行 */
.afe-plan-tbl.afe-vx { table-layout: auto; border-left: 2px solid var(--afe-divider); font-size: 12.5px; line-height: 19px; }
.afe-plan-tbl.afe-vx > tbody > tr > th, .afe-plan-tbl.afe-vx > tbody > tr > td { padding: 4px 0; }
.afe-plan-tbl.afe-vx > tbody > tr > th { width: 1%; min-width: 96px; padding: 4px 14px 4px 10px; white-space: nowrap; }
/* 值一格拿剩下的宽，里面的表格放不下在自己的框里左右滑，不把外面撑宽 */
.afe-plan-tbl.afe-vx > tbody > tr > td { max-width: 0; }
/* 一个字段一行的表里展开的：放在那一行下面占满整行，往里缩进 12px，那一行下面不画分隔线，看得出是它展开的 */
.afe-plan-tbl > tbody > tr.afe-vxo > th, .afe-plan-tbl > tbody > tr.afe-vxo > td { border-bottom-color: transparent; }
.afe-plan-tbl > tbody > tr.afe-vxr > td[colspan] { padding: 0 8px 10px 20px; }
.afe-plan-tbl.afe-vx > tbody > tr.afe-vxr > td[colspan] { padding: 0 0 6px 12px; }
.afe-vpop { max-height: min(420px, 60vh); overflow: auto; padding: 6px 12px 8px; font-size: 12.5px; line-height: 19px; scrollbar-width: thin; }
.afe-vpop > .afe-plan-tbl.afe-vx { padding-left: 0; border-left: 0; }
/* 结果里有几份列表：一份一节，节头写名字与几行 */
.afe-fxo-sec + .afe-fxo-sec { margin-top: 16px; }
.afe-fxo-sh { display: flex; align-items: baseline; gap: 8px; margin: 0 0 6px; font-size: 13px; line-height: 20px; }
.afe-fxo-sh .t { font-weight: 600; color: var(--afe-ink); }
.afe-fxo-sh .afe-muted { font-size: 12px; }
/* AI 编辑组件：整列，顶上 AI 理解，消息区占满，输入框贴底 */
.afe-fx-a { display: flex; flex-direction: column; min-height: 0; border-left: 1px solid var(--afe-border); background: var(--afe-card); }
.afe-fx-aic { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; border-radius: var(--afe-r); background: var(--afe-ink); color: var(--afe-card); }
.afe-fx-aic .afe-i { width: 14px; height: 14px; }
.afe-fx-aix { display: none; }
.afe-fx-a .afe-nai { flex: 1; min-height: 0; gap: 12px; padding: 14px 16px 16px; border-bottom: 0; }
.afe-fx-a .afe-nai-msgs { flex: 1; min-height: 0; max-height: none; padding: 8px 0 16px; }
.afe-fx-a .afe-nai-msgs:empty { display: flex; }
.afe-fx-a .afe-fx-empty { padding: 14px 16px; }
.afe-pop-menu .afe-pop-row.danger { color: var(--afe-danger); }
/* 窄于 1180：两栏，AI 编辑组件从右边浮出，页头一个键开关 */
@media (max-width: 1179px) {
  .afe-fx-b { grid-template-columns: 64px minmax(0, 1fr); grid-template-areas: "r w" "r m"; }
  .afe-fx-aibtn { display: inline-flex; }
  .afe-fx-aix { display: flex; }
  .afe-fx-a { position: absolute; top: 0; right: 0; bottom: 0; z-index: 4; width: min(400px, 92%); border-left: 1px solid var(--afe-border); box-shadow: -12px 0 32px rgba(16, 24, 40, .14);
    transform: translateX(104%); visibility: hidden; transition: transform .22s var(--afe-ease-in), visibility 0s linear .22s; }
  .afe-fx.ai-open .afe-fx-a { transform: none; visibility: visible; transition: transform .34s var(--afe-panel), visibility 0s; }
}
/* 窄于 760：整屏，一次看一块，页头下面一排页签切换 */
@media (max-width: 759px) {
  .afe-fx-mask { padding: 0; }
  .afe-fx { border-radius: 0; }
  .afe-fx-h { gap: 8px; padding: 0 6px 0 12px; }
  .afe-fx-h .afe-ntitle { width: 100%; }
  .afe-fx-aibtn, .afe-fx-aix { display: none; }
  .afe-fx-nav { padding-right: 0; margin-right: 0; border-right: 0; }
  /* 手机宽一级页签是下划线，和框里的胶囊页签分开层级 */
  .afe-fx-tabs { flex: none; display: flex; gap: 4px; overflow-x: auto; padding: 0 8px; border-bottom: 1px solid var(--afe-border); scrollbar-width: none; }
  .afe-fx-tabs button { position: relative; flex: none; height: 42px; padding: 0 10px; border: 0; background: none; color: var(--afe-ink2); font-size: 14px; }
  .afe-fx-tabs button.on { color: var(--afe-ink); font-weight: 600; }
  .afe-fx-tabs button.on::after { content: ""; position: absolute; left: 10px; right: 10px; bottom: -1px; height: 2px; border-radius: 1px; background: var(--afe-primary-fill); }
  .afe-fx-b { display: block; }
  .afe-fx-b > * { display: none !important; position: absolute; inset: 0; max-height: none; border: 0; }
  .afe-fx[data-pane="wire"] .afe-fx-w, .afe-fx[data-pane="par"] .afe-fx-p, .afe-fx[data-pane="code"] .afe-fx-m, .afe-fx[data-pane="ai"] .afe-fx-a { display: flex !important; }
  .afe-fx[data-pane="wire"] .afe-fx-w { display: block !important; }
  .afe-fx-k { margin: 8px; }
  /* 框头固定两行：页签一行，结果从哪来与按钮一行靠右，换页签时框头高度不变 */
  .afe-fx-ktools { flex-basis: 100%; justify-content: flex-end; min-height: 28px; }
  .afe-plan-tbl > tbody > tr > th { width: 38%; }
  .afe-fx-a { width: auto; transform: none; visibility: visible; box-shadow: none; transition: none; }
  /* 设置一块摆全部几组，不浮出，不要浮出时的头与投影；AI 编辑组件一块不要块头，页签上已写着 */
  .afe-fx-p, :root .afe-fx .afe-fx-p { justify-self: stretch; width: auto; box-shadow: none; animation: none; }
  .afe-fx-a > .afe-fx-ph { display: none; }
  .afe-fx-p > .afe-fx-ph { display: none; }
  .afe-fx-pb.one > .afe-grp { display: block; }
  .afe-fx-pb.one > .afe-grp > .afe-grp-h { display: flex; }
  .afe-fx-pb.one > .afe-grp.shut > .afe-grp-b { display: none; }
  /* 页签上已经写着是哪一块，块头不再写名字；页头第二行只留组件名，不写代码名 */
  .afe-fx-ph h3 { display: none; }
  .afe-fx-sub .afe-mono.c { display: none; }
}
/* 矮的窗口：AI 理解最多五行，多了滚动（接线与下面框的分法见主体，下面的框至少 260px） */
@media (max-height: 820px) {
  .afe-und p { max-height: 105px; }
}

/* 套件里面（docs/DESIGN.md 4.7）：页头“返回工作流”与“套件，第几版”小标签，侧栏交出去的字段，用到它的工作流 */
.afe-in-suite .afe-titles { gap: 8px; }
.afe-sback { flex: none; height: 28px; padding: 0 8px 0 4px; }
.afe-skind {
  flex: none; display: inline-flex; align-items: center; height: 22px; padding: 0 8px; border-radius: 6px;
  background: var(--afe-hover); color: var(--afe-ink2); font-size: 12px; font-weight: 500; white-space: nowrap;
}
.afe-io-row.afe-sout { grid-template-columns: minmax(0, 1fr) minmax(0, 1.5fr) 32px; }
.afe-sused { margin: 0; padding-left: 18px; font-size: 13px; line-height: 22px; }
/* 套件节点的大框页头“进入套件”：手机宽只留图标 */
@media (max-width: 759px) {
  .afe-fx-enter > span { display: none; }
}
/* 套件里面的页头：手机宽“返回工作流”与“套件设置”只留图标，名称多放几个字；节点大框的拆开套件收进更多 */
@media (max-width: 759px) {
  .afe-sback > span, .afe-sset > span { display: none; }
  .afe-sback { padding: 0 4px; }
  .afe-fx-split { display: none; }
}
/* 套件里面：交出去的字段在输出口旁边标“交出” */
.afe-node .io .co.xo { max-width: 140px; }
.afe-xo {
  flex: none; margin-right: 4px; padding: 0 4px; border-radius: 4px; font-size: 10px; line-height: 15px;
  color: var(--afe-ink2); background: var(--afe-hover); border: 1px solid var(--afe-border);
}
/* 多选时画布顶上的一条：已选几个节点，组成套件，创建副本，删除；画布顶上有提示条时排在它下面 */
.afe-selbar {
  position: absolute; top: 12px; left: 50%; z-index: 6; transform: translateX(-50%);
  display: flex; align-items: center; gap: 2px; height: 40px; padding: 0 4px 0 14px; white-space: nowrap;
  background: var(--afe-card); border: 1px solid var(--afe-border); border-radius: var(--afe-r); box-shadow: var(--afe-shadow);
  animation: afe-selbar-in .24s var(--afe-ease) both;
}
@keyframes afe-selbar-in { from { opacity: 0; transform: translate(-50%, -6px); } }
.afe-selbar .n { font-size: 13px; color: var(--afe-ink2); }
.afe-selbar .sep { width: 1px; height: 16px; margin: 0 6px 0 10px; background: var(--afe-border); }
.afe-note:not([hidden]) ~ .afe-selbar { top: 60px; }
@media (max-width: 759px) { .afe-selbar { display: none; } }
/* 套件设置开着时页头那个键是按下的样子 */
.afe-sset.on { background: var(--afe-hover); box-shadow: inset 0 0 0 1px var(--afe-border); }

/* 项目组件（11-01 第四段，docs/WORKSPACE.md 第十一节）：组件面板里“本项目”与“来自某某”两类组，别的工作流做的组件那边改过时节点卡片写“已更新”；
   页头“项目文件”开着时是按下的样子 */
.afe-node .fl .up { color: var(--afe-primary); background: var(--afe-primary-bg); }
.afe-tag.up { color: var(--afe-primary); background: var(--afe-primary-bg); }
.afe-pg.proj .afe-pg-h .gt { font-weight: 600; }
.afe-cc-src { margin: -2px 0 8px; font-size: 12px; line-height: 18px; color: var(--afe-ink3); }
.afe-fx-src { display: inline-flex; align-items: center; gap: 6px; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.afe-head .afe-acts .afe-btn.afe-filesbtn.on { background: var(--hover2); color: var(--ink); box-shadow: inset 0 0 0 1px var(--border); }
.afe-fx-sub .t + .afe-fx-src::before { content: "·"; margin-right: 6px; color: var(--afe-ink4); }

/* 11-01 评审 P1-4：别的工作流的组件那边有新版时，节点大框标题下面那一行的“换上新版”，跟着这一行的高度，不撑高 */
.afe-fx-sub .afe-fx-take { height: 20px; padding: 0 6px; font-size: 12px; font-weight: 500; border-radius: var(--afe-rt); }

/* 单独试运行时上游还没有运行结果：试运行键下面浮出的一小块（R2b P2-5），一句话加“连上游一起试运行”（R2c P1-1，不起正式运行） */
.afe-needrun { padding: 12px 14px; display: flex; flex-direction: column; gap: 10px; outline: 0; }
.afe-needrun p { margin: 0; font-size: 13px; line-height: 20px; color: var(--afe-ink); }
.afe-needrun-b { display: flex; justify-content: flex-end; }

/* 产出卡（11-04）：运行交出的页面预览与文件，挂在交它的节点右边，虚线连到那个节点的口（editor.js paintOuts）；不是节点，不能选不能拖，点了打开 */
.afe-outln { position: absolute; left: 0; top: 0; width: 1px; height: 1px; overflow: visible; pointer-events: none; }
.afe-outln-p { fill: none; stroke: var(--afe-ink4); stroke-width: 1.5; stroke-dasharray: 5 4; vector-effect: non-scaling-stroke; }
/* 这一次跑完：虚线先亮主色淡入，再退回灰（照旧是虚线，Gemini 审图） */
.afe-outln-p.afe-born { animation: afe-outln-in 1.6s var(--afe-ease) both; }
@keyframes afe-outln-in { 0% { opacity: 0; stroke: var(--afe-primary); } 20%, 70% { opacity: 1; stroke: var(--afe-primary); } }
.afe-outs { position: absolute; left: 0; top: 0; width: 0; height: 0; }
.afe-out { position: absolute; width: 288px; background: var(--afe-card); color: var(--afe-ink); border: 1px dashed var(--afe-ink4); border-radius: 12px;
  cursor: pointer; transition: border-color .15s; }
/* 虚线框，不带投影：跟节点（实线框带投影）一眼分开，是跑出来的结果，不是能配置的积木（Gemini 审图） */
.afe-out:hover { border-color: var(--afe-ink3); }
.afe-out-hd { display: flex; align-items: center; gap: 8px; height: 40px; padding: 0 6px 0 12px; }
.afe-out.sm .afe-out-hd { height: 50px; }
.afe-out-ic { width: 16px; height: 16px; flex: none; display: inline-flex; color: var(--afe-ink3); }
.afe-out-ic .afe-i { width: 16px; height: 16px; fill: currentColor; }
.afe-out-tt { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.afe-out-t { font-size: 13px; font-weight: 600; line-height: 18px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.afe-out-s { font-size: 12px; line-height: 16px; color: var(--afe-ink3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.afe-out .afe-tag { flex: none; }
.afe-out-go { width: 30px; height: 30px; flex: none; padding: 0; border: 0; border-radius: 8px; background: none; color: var(--afe-ink3); display: inline-flex; align-items: center; justify-content: center; cursor: pointer; }
.afe-out-go:hover { background: var(--afe-hover); color: var(--afe-ink); }
/* 鼠标停在卡片上时打开键变主色，看得出整张能点（Gemini 审图：深色下打开键偏暗） */
.afe-out:hover .afe-out-go { color: var(--afe-primary); }
.afe-out-go .afe-i { width: 17px; height: 17px; fill: currentColor; }
.afe-out-pv { position: relative; display: block; width: 272px; height: 170px; margin: 0 8px 8px; padding: 0; border: 1px solid var(--afe-node-line); border-radius: 8px;
  overflow: hidden; background: #fff; cursor: pointer; }
.afe-out-f { position: absolute; left: 0; top: 0; width: 1024px; height: 640px; border: 0; background: #fff; transform: scale(.265625); transform-origin: 0 0; pointer-events: none; }
.afe-out-go:focus-visible, .afe-out-pv:focus-visible { outline: 0; box-shadow: var(--afe-ring); }
.afe-out.afe-born { animation: afe-node-in .4s var(--afe-ease) both; }
/* 这一次跑完才交出来的：从节点那边滑出来，线从口描过去，“打开”键亮一下主色再退回（不描整圈，免得像选中了节点，Gemini 审图） */
.afe-out.afe-out-new { animation: afe-out-new 1.6s var(--afe-ease) both; }
@keyframes afe-out-new { 0% { opacity: 0; transform: translateX(-12px); } 20% { opacity: 1; transform: none; } }
.afe-out.afe-out-new .afe-out-go { animation: afe-out-go 1.6s var(--afe-ease) both; }
@keyframes afe-out-go { 0%, 15% { background: none; color: var(--afe-ink3); } 30%, 70% { background: var(--afe-primary); color: #fff; } }
/* 缩到 60% 以下：卡头的字同节点标题反向放大，屏幕上约 13px */
.afe-cv.far .afe-out-t { font-size: min(22px, calc(13px / var(--afe-k, .5))); line-height: 1.15; }
.afe-cv.far .afe-out-s { display: none; }
