/* AI 原生组件自动编排平台 外壳样式。2026 版界面，细则见 docs/STYLE_PORTAL.md：
 * 方向是可视化画布风，学 Dify，扣子，n8n 的点阵画布与白色圆角卡片，外壳与交互学 Claude，ChatGPT，Linear。
 * 宽屏没有顶栏，左栏放品牌，搜索（Ctrl K 命令面板），导航，AI 助手与账号；内容区浅灰底，白色卡片。
 * 颜色黑白为主，帆软蓝 #3685F2 只做强调：选中，链接，焦点，画布上接上的口；主按钮黑色，深色下白色。
 * 形：控件 8 像素圆角，卡片与面板 12，大输入框 20；卡片细边框加很淡的阴影，浮层阴影淡而散；渐变，发光，彩色光晕，毛玻璃不用。
 * 颜色一律用 :root 里的变量，编辑器与组件工厂也只用这些变量；旧变量名指向新值，旧写法照常能用。 */
:root {
  /* 强调色是帆软蓝；主按钮另用一组黑色。灰阶是偏冷的中性灰，状态色与画布上的类别色取同一套，深一档的字色给浅底上的小字 */
  --primary: #3685F2; --primary-hover: #2D75DC; --primary-active: #2563C2; --primary-bg: #EEF4FE; --primary-fill: #3685F2; --on-primary: #fff;
  --btn-pri: #101828; --btn-pri-hover: #1D2939; --btn-pri-active: #0C111D; --on-btn-pri: #fff;
  --header-bg: #3685F2; --header-ink: #fff; --header-active: rgba(255, 255, 255, .14);
  --page: #F2F4F7; --card: #fff; --raised: #fff; --border: #EAECF0; --divider: #F2F4F7; --input-border: #D0D5DD;
  --th-bg: #F9FAFB; --row-hover: #F9FAFB; --cv-dot: #D0D5DD; --cv-bg: #F2F4F7;
  --ink: #101828; --ink2: #344054; --ink3: #667085; --ink4: #98A2B3;
  --danger: #D92D20; --red: #F04438; --red-bg: #FEF3F2; --red-ink: #B42318;
  --orange: #F79009; --orange-bg: #FFFAEB; --orange-ink: #B54708;
  --success: #12B76A; --success-bg: #ECFDF3; --success-ink: #027A48;
  --sky: #0BA5EC; --sky-bg: #F0F9FF; --sky-ink: #026AA2;
  --violet: #7A5AF8; --violet-bg: #F4F3FF; --violet-ink: #5925DC;
  /* 画布上按平台与用途上色的几种，只用在节点左上角的小方块与缩略图上 */
  --pink: #EE46BC; --indigo: #6172F3; --teal: #15B79E; --rose: #F63D68; --blue: #2E90FA; --green: #12B76A; --amber: #F79009; --coral: #F04438;
  --grey-bg: #F2F4F7; --grid-cell: #F5F8FF;
  --hover: rgba(16, 24, 40, .04); --hover2: rgba(16, 24, 40, .07);
  /* 阴影四档：控件，卡片，浮起的卡片，浮层；最大一档给命令面板与对话框 */
  --sh-xs: 0 1px 2px rgba(16, 24, 40, .05); --sh-sm: 0 1px 3px rgba(16, 24, 40, .07), 0 1px 2px rgba(16, 24, 40, .04);
  --sh-md: 0 4px 8px -2px rgba(16, 24, 40, .08), 0 2px 4px -2px rgba(16, 24, 40, .04);
  --pop-shadow: 0 12px 16px -4px rgba(16, 24, 40, .08), 0 4px 6px -2px rgba(16, 24, 40, .03);
  --sh-xl: 0 20px 24px -4px rgba(16, 24, 40, .10), 0 8px 8px -4px rgba(16, 24, 40, .04);
  --focus-ring: rgba(54, 133, 242, .20); --scrim: rgba(16, 24, 40, .36);
  /* 圆角：标签 6，控件 8，卡片与面板 12，浮层 16，大输入框 20 */
  --r-sm: 6px; --r: 8px; --r-lg: 12px; --r-xl: 16px; --r-2xl: 20px;
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
  /* 代码编辑器（AFCode）的颜色，全取帆软色板与它混出来的几种，见 tests/test_palette.py */
  --code-bg: #fff; --code-kw: #1E4092; --code-str: #BA853B; --code-num: #3075D5; --code-com: #9EA6B2; --code-fn: #1885A7; --code-type: #0D9047;
  --code-prop: #AF7728; --code-tag: #1E4092; --code-def: var(--ink); --code-meta: #AF7728; --code-bad: var(--red);
  --code-sel: #DCE9FD; --code-line: rgba(16, 24, 40, .03); --code-match: rgba(54, 133, 242, .14); --code-find: rgba(250, 170, 57, .3);
  /* 旧名：编辑器与组件工厂的样式还在用，一律指向上面的新值 */
  --blue-ink: var(--primary); --blue-bg: var(--primary-bg); --blue-hover: var(--primary-hover); --on-blue: var(--on-primary);
  --bg: var(--page); --surface: var(--card); --surface2: var(--th-bg); --line: var(--input-border); --line2: var(--border);
  --green-bg: var(--success-bg); --amber-bg: var(--orange-bg); --grey: var(--ink3);
  --shadow: var(--pop-shadow); --focus: var(--primary); --code: var(--th-bg); --grp: var(--th-bg);
  --logo-a: #fff; --logo-b: #D7E7FC; --snack: #fff; --snack-ink: var(--ink); --avatar: #344054; --on-avatar: #fff;
  color-scheme: light;
}
/* 深色：同名变量换值。底是近黑偏冷，卡片高一档，浮起的再高一档；强调色提亮，主按钮反过来是白底黑字。
   类别色里粉，青绿，玫红，蓝，绿，琥珀两套主题同值，靛蓝与珊瑚深色下另取 */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --primary: #6EA8F7; --primary-hover: #8CBBF9; --primary-active: #5A97EE; --primary-bg: rgba(54, 133, 242, .16); --primary-fill: #3685F2; --on-primary: #fff;
    --btn-pri: #F5F5F6; --btn-pri-hover: #fff; --btn-pri-active: #E4E7EC; --on-btn-pri: #0C0E12;
    --header-bg: #1E4092; --header-ink: #fff; --header-active: rgba(255, 255, 255, .18);
    --page: #0C0E12; --card: #15181E; --raised: #1A1E25; --border: #22262E; --divider: #1C2027; --input-border: #333741;
    --th-bg: #12151A; --row-hover: #1A1E25; --cv-dot: #2B2F38; --cv-bg: #0C0E12;
    --ink: #F5F5F6; --ink2: #CECFD2; --ink3: #94969C; --ink4: #61646C;
    --danger: #F97066; --red: #F04438; --red-bg: rgba(240, 68, 56, .14); --red-ink: #FDA29B;
    --orange: #F79009; --orange-bg: rgba(247, 144, 9, .14); --orange-ink: #FEC84B;
    --success: #12B76A; --success-bg: rgba(18, 183, 106, .14); --success-ink: #47CD89;
    --sky: #0BA5EC; --sky-bg: rgba(11, 165, 236, .14); --sky-ink: #7CD4FD;
    --violet: #875BF7; --violet-bg: rgba(122, 90, 248, .16); --violet-ink: #BDB4FE;
    --indigo: #5497F4; --coral: #E65251; --grey-bg: #1C2027; --grid-cell: #141B26;
    --hover: rgba(255, 255, 255, .05); --hover2: rgba(255, 255, 255, .08);
    --sh-xs: 0 1px 2px rgba(0, 0, 0, .3); --sh-sm: 0 1px 3px rgba(0, 0, 0, .35); --sh-md: 0 4px 12px rgba(0, 0, 0, .35);
    --pop-shadow: 0 12px 24px rgba(0, 0, 0, .45); --sh-xl: 0 24px 48px rgba(0, 0, 0, .5);
    --focus-ring: rgba(110, 168, 247, .28); --scrim: rgba(0, 0, 0, .55); --snack: #1A1E25; --avatar: #333741;
    --code-bg: #12151A; --code-kw: #72AAF6; --code-str: #FAAA39; --code-num: #5497F4; --code-com: #878D9F; --code-fn: #23BEEF; --code-type: #13CD66;
    --code-prop: #D6E0EC; --code-tag: #72AAF6; --code-meta: #FBB03B; --code-sel: #1E3354; --code-line: rgba(255, 255, 255, .03); --code-match: rgba(114, 170, 246, .22);
    color-scheme: dark;
  }
}
:root[data-theme="dark"] {
  --primary: #6EA8F7; --primary-hover: #8CBBF9; --primary-active: #5A97EE; --primary-bg: rgba(54, 133, 242, .16); --primary-fill: #3685F2; --on-primary: #fff;
  --btn-pri: #F5F5F6; --btn-pri-hover: #fff; --btn-pri-active: #E4E7EC; --on-btn-pri: #0C0E12;
  --header-bg: #1E4092; --header-ink: #fff; --header-active: rgba(255, 255, 255, .18);
  --page: #0C0E12; --card: #15181E; --raised: #1A1E25; --border: #22262E; --divider: #1C2027; --input-border: #333741;
  --th-bg: #12151A; --row-hover: #1A1E25; --cv-dot: #2B2F38; --cv-bg: #0C0E12;
  --ink: #F5F5F6; --ink2: #CECFD2; --ink3: #94969C; --ink4: #61646C;
  --danger: #F97066; --red: #F04438; --red-bg: rgba(240, 68, 56, .14); --red-ink: #FDA29B;
  --orange: #F79009; --orange-bg: rgba(247, 144, 9, .14); --orange-ink: #FEC84B;
  --success: #12B76A; --success-bg: rgba(18, 183, 106, .14); --success-ink: #47CD89;
  --sky: #0BA5EC; --sky-bg: rgba(11, 165, 236, .14); --sky-ink: #7CD4FD;
  --violet: #875BF7; --violet-bg: rgba(122, 90, 248, .16); --violet-ink: #BDB4FE;
  --indigo: #5497F4; --coral: #E65251; --grey-bg: #1C2027; --grid-cell: #141B26;
  --hover: rgba(255, 255, 255, .05); --hover2: rgba(255, 255, 255, .08);
  --sh-xs: 0 1px 2px rgba(0, 0, 0, .3); --sh-sm: 0 1px 3px rgba(0, 0, 0, .35); --sh-md: 0 4px 12px rgba(0, 0, 0, .35);
  --pop-shadow: 0 12px 24px rgba(0, 0, 0, .45); --sh-xl: 0 24px 48px rgba(0, 0, 0, .5);
  --focus-ring: rgba(110, 168, 247, .28); --scrim: rgba(0, 0, 0, .55); --snack: #1A1E25; --avatar: #333741;
  --code-bg: #12151A; --code-kw: #72AAF6; --code-str: #FAAA39; --code-num: #5497F4; --code-com: #878D9F; --code-fn: #23BEEF; --code-type: #13CD66;
  --code-prop: #D6E0EC; --code-tag: #72AAF6; --code-meta: #FBB03B; --code-sel: #1E3354; --code-line: rgba(255, 255, 255, .03); --code-match: rgba(114, 170, 246, .22);
  color-scheme: dark;
}

/* 版面尺寸：宽屏没有顶栏；左栏 248，收起成图标条 68 */
:root { --hd-h: 0px; --tb-h: 40px; --sd-w: 248px; --as-w: 400px; --brand-w: 200px; }
body.side-mini { --sd-w: 68px; }

/* 动效，细则见 docs/MOTION.md：进场快出慢停，退场更快更轻；只动位移，缩放与透明度，不牵动周围版面。
   系统关了动画（浏览器报少动画）时照样播，用户在提问框里定的 */
:root {
  --ease-out: cubic-bezier(.16, 1, .3, 1);
  --ease-in: cubic-bezier(.55, 0, 1, .45);
  --ease-move: cubic-bezier(.65, 0, .35, 1);
  --ease-panel: cubic-bezier(.32, .72, 0, 1);
  --t-fast: .12s; --t-pop: .18s; --t-dlg: .26s; --t-panel: .34s; --t-page: .3s;
}
@keyframes fade-in { from { opacity: 0; } }
@keyframes fade-out { to { opacity: 0; } }
@keyframes rise-in { from { opacity: 0; transform: translateY(8px); } }
@keyframes pop-in { from { opacity: 0; transform: translateY(var(--pop-dy, -4px)) scale(.97); } }
@keyframes pop-out { to { opacity: 0; transform: scale(.98); } }
@keyframes icon-in { from { opacity: 0; transform: scale(.5); } }
/* 换主题时整页从旧颜色渐变到新颜色，过渡中点击照样落在页面上 */
::view-transition { pointer-events: none; }
::view-transition-old(root), ::view-transition-new(root) { animation-duration: .2s; animation-timing-function: ease-out; }

* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; }
#root { height: 100%; }
body {
  background: var(--page); color: var(--ink);
  font: 14px/22px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Noto Sans CJK SC", sans-serif;
  -webkit-font-smoothing: antialiased; font-variant-numeric: tabular-nums;
}
a { color: var(--primary); text-decoration: none; transition: color var(--t-fast) ease; }
a:hover { color: var(--primary-hover); }
svg.i { width: 18px; height: 18px; fill: currentColor; flex: none; }
button, input, select, textarea { font: inherit; color: inherit; }
:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 1px; }
input:focus-visible, select:focus-visible, textarea:focus-visible { outline: none; }
.muted { color: var(--ink3); }
.faint { color: var(--ink4); }
.mono { font-family: var(--mono); font-size: 12.5px; }
.nowrap { white-space: nowrap; }
.num { font-variant-numeric: tabular-nums; }
.m-only { display: none; }
[hidden] { display: none !important; }

/* 顶栏：主色底白字，只放全局的东西。标识展开时按产品名量出宽度，不窄于左栏，搜索框跟在标识后面；左栏收起时标识只留图标，搜索框与内容区对齐；右边提醒，头像 */
header.top {
  position: fixed; inset: 0 0 auto 0; height: var(--hd-h); z-index: 30; display: flex; align-items: stretch;
  background: var(--header-bg); color: var(--header-ink);
}
header.top .brand { display: flex; align-items: center; gap: 10px; width: var(--brand-w); padding: 0 16px; color: var(--header-ink); font-size: 16px; font-weight: 600; white-space: nowrap; flex: none; overflow: hidden;
  transition: width var(--t-panel) var(--ease-panel), padding var(--t-panel) var(--ease-panel); }
header.top .brand:hover { color: var(--header-ink); }
body.side-mini header.top .brand { width: var(--sd-w); padding: 0 15px; }
body.side-mini header.top .brand span { opacity: 0; }
.logo { width: 26px; height: 26px; flex: none; display: block; }
header.top .logo .la { stroke: #fff; } header.top .logo .lb { stroke: #D7E7FC; } header.top .logo .lf { fill: #fff; }
header.top .grow { flex: 1; }
.hd-btn { position: relative; display: inline-flex; align-items: center; justify-content: center; width: 44px; border: 0; background: none; color: #fff; cursor: pointer; padding: 0; flex: none; }
.hd-btn, .hd-user, .hd-ai { transition: background-color var(--t-fast) ease; }
.hd-btn svg.i, .hd-ai svg.i { transition: transform .2s var(--ease-out); }
.hd-btn:active svg.i, .hd-ai:active svg.i { transform: scale(.88); }
.hd-btn.on { background: var(--header-active); color: #fff; }
/* 悬停的底色只给有鼠标的设备：手机上点过的键会一直算悬停，抽屉关了菜单键还留着一块底色 */
@media (hover: hover) { .hd-btn:hover { background: var(--header-active); color: #fff; } }
.hd-btn svg.i { width: 18px; height: 18px; }
.hd-user { display: inline-flex; align-items: center; gap: 8px; padding: 0 12px 0 10px; border: 0; background: none; color: #fff; cursor: pointer; white-space: nowrap; flex: none; max-width: 200px; }
.hd-user.on { background: var(--header-active); }
@media (hover: hover) { .hd-user:hover { background: var(--header-active); } }
.hd-user .nm { overflow: hidden; text-overflow: ellipsis; }
.hd-user svg.i { width: 16px; height: 16px; opacity: .85; }
.avatar { width: 26px; height: 26px; border-radius: 50%; background: rgba(255, 255, 255, .22); color: #fff; font-size: 13px; font-weight: 600; display: inline-flex; align-items: center; justify-content: center; flex: none; }
#menu-btn, #gs-btn { display: none; }
.hd-ai { display: inline-flex; align-items: center; gap: 6px; padding: 0 14px; border: 0; background: none; color: #fff; cursor: pointer; white-space: nowrap; flex: none; font-weight: 600; }
.hd-ai.on { background: var(--header-active); }
@media (hover: hover) { .hd-ai:hover { background: var(--header-active); } }
.hd-ai svg.i { width: 18px; height: 18px; }

/* 全局搜索：宽屏是顶栏里常驻的搜索框，压在顶栏上，聚焦时变白底并浮到遮罩上面；结果浮在框下面。窄屏见宽度适配 */
.gs-panel { position: fixed; top: calc((var(--hd-h) - 32px) / 2); left: calc(var(--brand-w) + 12px); width: 320px; z-index: 31; transition: left var(--t-panel) var(--ease-panel); }
body.side-mini .gs-panel { left: calc(var(--sd-w) + 12px); }
.gs-panel:focus-within { z-index: 61; }
.gs-panel .box { display: flex; align-items: center; gap: 8px; height: 32px; padding: 0 10px; border-radius: 4px; background: rgba(255, 255, 255, .16); color: #fff; transition: background-color var(--t-fast) ease, color var(--t-fast) ease; }
.gs-panel .box:hover { background: rgba(255, 255, 255, .22); }
.gs-panel .box svg.i { width: 16px; height: 16px; color: rgba(255, 255, 255, .85); }
.gs-panel input { flex: 1; min-width: 0; height: 32px; padding: 0; border: 0; outline: 0; background: none; color: inherit; }
.gs-panel input::placeholder { color: rgba(255, 255, 255, .75); opacity: 1; }
.gs-panel:focus-within .box { background: var(--card); color: var(--ink); }
.gs-panel:focus-within .box svg.i { color: var(--ink3); }
.gs-panel:focus-within input::placeholder { color: var(--ink4); }
.gs-pop { position: absolute; top: calc(100% + 12px); left: 0; width: 480px; max-width: calc(100vw - var(--sd-w) - 24px); max-height: 60vh; overflow-y: auto; padding: 4px 0; background: var(--card); color: var(--ink); border: 1px solid var(--border); border-radius: 6px; box-shadow: var(--pop-shadow);
  transform-origin: top left; animation: pop-in var(--t-pop) var(--ease-out) both; }
.gs-pop .gh { padding: 8px 16px 4px; font-size: 12px; color: var(--ink3); }
.gs-pop a { display: flex; align-items: center; gap: 10px; min-height: 36px; padding: 4px 16px; color: var(--ink); transition: background-color .08s ease, color .08s ease; }
.gs-pop a:hover, .gs-pop a.on { background: var(--primary-bg); color: var(--primary); }
.gs-pop a svg.i { color: var(--ink3); width: 16px; height: 16px; }
.gs-pop a .t { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gs-pop a .s { color: var(--ink4); font-size: 12px; white-space: nowrap; }
.gs-pop .none { padding: 12px 16px; color: var(--ink3); }

/* 左栏：白底，一份完整的分组菜单，门户在最上，下面编排，组件，资源，系统四组，每个页面一次点到；
   底部收起，收起后只留图标，组名换成一道分隔线 */
.side {
  position: fixed; top: var(--hd-h); bottom: 0; left: 0; width: var(--sd-w); z-index: 20; display: flex; flex-direction: column;
  background: var(--card); border-right: 1px solid var(--border); transition: width var(--t-panel) var(--ease-panel);
}
.side .items { position: relative; flex: 1; overflow-y: auto; overflow-x: hidden; padding: 8px 0; }
.side .grp { padding: 16px 20px 4px; font-size: 12px; line-height: 20px; color: var(--ink3); white-space: nowrap; overflow: hidden; }
body.side-mini .side .grp { padding: 0; margin: 8px 16px; border-top: 1px solid var(--border); }
body.side-mini .side .grp span { display: none; }
.side a { position: relative; z-index: 1; display: flex; align-items: center; gap: 10px; height: 40px; padding: 0 16px 0 20px; color: var(--ink2); white-space: nowrap; overflow: hidden; transition: color var(--t-fast) ease, background-color var(--t-fast) ease; }
.side a svg.i { width: 16px; height: 16px; color: var(--ink3); transition: color var(--t-fast) ease; }
/* 收起时字先很快淡掉；展开时等宽度走出一段再淡入，字不在窄的时候硬露出来 */
.side a span, .side .fold span, header.top .brand span { transition: opacity .16s ease .1s; }
body.side-mini .side a span, body.side-mini .side .fold span, body.side-mini header.top .brand span { transition: opacity .08s ease; }
.side a:hover { color: var(--primary); }
.side a:hover svg.i { color: var(--primary); }
.side a.on { background: var(--primary-bg); color: var(--primary); }
.side a.on svg.i { color: var(--primary); }
/* 当前页的浅蓝底是一块单独的底，换页时从上一项滑到这一项；脚本放好它以后各项自己的底色去掉 */
.side .ink { position: absolute; left: 0; right: 0; top: 0; height: 40px; background: var(--primary-bg); pointer-events: none; opacity: 0;
  transform: translateY(var(--ink-y, 0)); transition: transform .36s var(--ease-out), opacity .2s ease; }
.side.inked a.on { background: transparent; }
.side.inked .ink.on { opacity: 1; }
.side .fold { display: flex; align-items: center; gap: 10px; height: 40px; padding: 0 20px; border: 0; border-top: 1px solid var(--divider); background: none; color: var(--ink3); cursor: pointer; width: 100%; text-align: left; flex: none; transition: color var(--t-fast) ease; }
.side .fold:hover { color: var(--primary); }
.side .fold svg.i { width: 16px; height: 16px; }
body.side-mini .side a span, body.side-mini .side .fold span { opacity: 0; }
body.side-mini .side a, body.side-mini .side .fold { padding-left: 20px; }
#scrim { position: fixed; inset: 0; background: var(--scrim); z-index: 40; opacity: 0; pointer-events: none; transition: opacity .28s ease; }
#scrim.on { opacity: 1; pointer-events: auto; }

/* 内容区：灰底，四周留 12 像素，卡片之间 12 像素。左栏收起与助手面板开关时，内容区跟着平滑地让位 */
main { padding: var(--hd-h) 0 0 var(--sd-w); min-height: 100%; transition: padding var(--t-panel) var(--ease-panel); }
main.full { height: 100vh; height: 100dvh; min-height: 0; overflow: hidden; }
main.full #view { height: 100%; }
/* 任务同步：内容区整块是一个框架，嵌任务同步自己的一页（/ts/），框架里的页面自己画浅灰底 */
.ts-frame { display: block; width: 100%; height: 100%; border: 0; background: var(--page); }
/* 任务同步的入口打开的是总 Agent 写的那一页时，框上面一行：左边页名，右边“设置”到平台默认页面的项目清单（11-02 E3，R1c P2-7，app.js 的 tsCfgHead）。
   底色同框里那一页（--page），左右与上沿跟那一页的内容对齐，框往下让这一行；页名比框里那一页的页头卡片标题小一档，不抢 */
#view:has(> .ts-cfg-head) { display: flex; flex-direction: column; background: var(--page); }
#view:has(> .ts-cfg-head) > .fa-site { flex: 1 1 auto; min-height: 0; height: auto; }
.ts-cfg-head { flex: none; display: flex; align-items: center; gap: 12px; margin: 20px 24px 0; }
.ts-cfg-head.narrow { margin: 16px 16px 0; }
.ts-cfg-t { flex: 1; min-width: 0; margin: 0; font-size: 16px; line-height: 24px; font-weight: 600; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.editor-host { position: relative; height: 100%; overflow: hidden; background: var(--page); animation: fade-in var(--t-page) ease-out both; }
/* 换页：页名立刻出来，不整页浮动；内容到了一次淡入。占位的空白卡片前 0.3 秒不露，数据快时看不到它 */
.page { padding: 12px 12px 32px; min-width: 0; }
.fade-in { animation: fade-in .22s ease-out both; }
.skel, .card:has(> .skel:only-child) { animation: fade-in .3s ease-out .3s both; }
/* 等了 0.3 秒数据还没到：露三条浅灰的占位条，轻轻明暗，不扫光 */
.skel { position: relative; }
.skel::before { content: ""; position: absolute; left: 16px; right: 16px; top: 18px; height: 72px; animation: skel-pulse 1.6s ease-in-out infinite;
  background: linear-gradient(var(--divider), var(--divider)) 0 0 / 36% 12px no-repeat, linear-gradient(var(--divider), var(--divider)) 0 28px / 88% 10px no-repeat,
    linear-gradient(var(--divider), var(--divider)) 0 50px / 70% 10px no-repeat; }
@keyframes skel-pulse { 50% { opacity: .45; } }
/* 列表页顶上一行页名：页签栏去掉以后靠它认出在哪一页，窄屏左栏收起时也看得到 */
.pg-t { margin: 2px 4px 12px; font-size: 16px; line-height: 24px; font-weight: 600; color: var(--ink); }
.page-head { display: flex; align-items: center; gap: 12px; min-height: 56px; flex-wrap: wrap; padding: 10px 16px; margin-bottom: 12px; background: var(--card); border: 1px solid var(--border); border-radius: 6px; }
.page-head h1 { margin: 0; font-size: 16px; line-height: 24px; font-weight: 600; min-width: 0; overflow-wrap: anywhere; }
.page-head .meta { display: flex; gap: 12px; align-items: center; color: var(--ink3); font-size: 13px; flex-wrap: wrap; }
.page-head .actions { margin-left: auto; display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.page-head .back { margin-left: -6px; }
.page-head.bare { display: none; }
.progress { height: 2px; margin: -12px -12px 10px; overflow: hidden; background: transparent; }
.progress.on { background: var(--primary-bg); }
.progress.on::after { content: ""; display: block; height: 100%; width: 30%; background: var(--primary); animation: prog 1.2s infinite ease-in-out; }
@keyframes prog { 0% { transform: translateX(-100%); } 100% { transform: translateX(340%); } }
.tabs { position: relative; display: flex; gap: 0; border-bottom: 1px solid var(--border); margin: 0 0 12px; overflow-x: auto; scrollbar-width: none; }
.tabs a, .tabs button {
  position: relative; padding: 0 16px; height: 44px; line-height: 44px; color: var(--ink2); white-space: nowrap;
  border: 0; background: none; cursor: pointer; font-size: 14px; transition: color var(--t-fast) ease;
}
.tabs a:hover, .tabs button:hover { color: var(--primary); }
.tabs .on { color: var(--primary); font-weight: 500; }
.tabs .on::after { content: ""; position: absolute; left: 16px; right: 16px; bottom: 0; height: 2px; background: var(--primary); }
/* 页签下划线：脚本接管以后是一条单独的线，换页签时滑过去并伸缩到新页签的宽度；编辑器与系统设置的页签同样 */
.tab-ink { position: absolute; left: 0; bottom: 0; width: 1px; height: 2px; background: var(--primary); pointer-events: none; transform-origin: 0 0;
  transform: translateX(var(--ink-x, 0)) scaleX(var(--ink-w, 0)); transition: transform .36s var(--ease-out); }
.inked > .on::after, .inked > .on:hover::after { opacity: 0; }
.page > .tabs { background: var(--card); border: 1px solid var(--border); border-radius: 6px; padding: 0 8px; }
/* 带页签的设置页与详情页（pageFrame）手机宽一行放不下横着滚：滚出去的那一边淡出（同示例说法那一排），看得出还有，不硬切半个字（11-02 E3）。
   淡出的是压在字上的一层卡片色，卡片的框与圆角不动；app.js 的 pageFrame 照滚到哪给 fl（左边还有）与 fr（右边还有） */
#ph-tabs::before, #ph-tabs::after { content: ""; position: sticky; flex: none; width: 36px; z-index: 2; pointer-events: none; opacity: 0; transition: opacity var(--t-fast) ease; }
/* 贴住的位置照页签一行左右的内边距（12）往外挪，从框里边起：内边距那 12 像素是卡片色，再往里 24 像素淡开。
   盖得太宽左边空一大块，滚出去的页签也看不见了（Gemini 二到四轮来回比过：残字淡掉就行，不整块盖住） */
#ph-tabs::before { left: -12px; margin-right: -36px; background: linear-gradient(to right, var(--card) 33%, transparent); }
#ph-tabs::after { right: -12px; margin-left: -36px; background: linear-gradient(to left, var(--card) 33%, transparent); }
#ph-tabs.fl::before, #ph-tabs.fr::after { opacity: 1; }
.card { background: var(--card); border: 1px solid var(--border); border-radius: 6px; margin-bottom: 12px; min-width: 0; }
.card-h { display: flex; align-items: center; gap: 10px; min-height: 52px; padding: 12px 16px 8px; }
.card-h h2 { margin: 0; font-size: 15px; line-height: 24px; font-weight: 600; display: flex; align-items: center; gap: 8px; }
.card-h h2::before { content: ""; width: 3px; height: 14px; background: var(--primary); border-radius: 1px; flex: none; }
.card-h .r { margin-left: auto; display: flex; gap: 4px; align-items: center; }
.card-b { padding: 0 16px 16px; }
.card-b.pt { padding-top: 16px; }
.grid2 { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 12px; align-items: start; }
.grid-main { display: grid; grid-template-columns: minmax(0, 2fr) minmax(300px, 1fr); gap: 12px; align-items: start; }
.grid2 > .card, .grid-main > .card, .grid2 > div > .card { margin-bottom: 0; }
.stack { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.stack > .card { margin: 0; }
.skel { min-height: 120px; }
/* 面板里的小节标题：左边一条主色竖条 */
.sec-h { margin: 24px 0 10px; font-size: 14px; font-weight: 600; color: var(--ink); display: flex; align-items: center; gap: 8px; min-height: 22px; }
.sec-h::before { content: ""; width: 3px; height: 14px; background: var(--primary); border-radius: 1px; flex: none; }
.sec-h:first-child { margin-top: 0; }
.sec-h .r { margin-left: auto; display: flex; gap: 8px; align-items: center; font-weight: 400; }
.sub-h { margin: 12px 0 6px; font-size: 13px; color: var(--ink3); }

/* 按钮：高 32，主按钮实心，普通按钮白底灰框悬停变主色，危险按钮红框红字，文字按钮无框 */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px; height: 32px; padding: 0 15px; border-radius: 4px;
  border: 1px solid transparent; background: none; color: var(--primary); font-size: 14px; cursor: pointer; white-space: nowrap; flex: none;
  transition: color var(--t-fast) ease, border-color var(--t-fast) ease, background-color var(--t-fast) ease, box-shadow var(--t-fast) ease, transform .14s var(--ease-out);
}
/* 按下时略微缩一下，松开弹回 */
.btn:active:not([disabled]):not(.dis):not(.lk) { transform: scale(.97); transition-duration: .06s; }
.btn svg.i { width: 16px; height: 16px; margin-left: -2px; }
.btn:hover { color: var(--primary-hover); }
.btn.pri { background: var(--btn-pri); border-color: var(--btn-pri); color: var(--on-primary); }
.btn.pri:hover { background: var(--primary-hover); border-color: var(--primary-hover); color: var(--on-primary); }
.btn.pri:active { background: var(--primary-active); border-color: var(--primary-active); }
.btn.out { background: var(--card); border-color: var(--input-border); color: var(--ink); }
.btn.out:hover { border-color: var(--primary); color: var(--primary); }
.btn.danger { color: var(--danger); }
.btn.out.danger { border-color: var(--danger); color: var(--danger); }
.btn.out.danger:hover { border-color: var(--red); color: var(--red); }
.btn.pri.danger { background: var(--red); border-color: var(--red); color: #fff; }
.btn.pri.danger:hover { background: var(--danger); border-color: var(--danger); }
.btn[disabled], .btn.dis { color: var(--ink4); cursor: not-allowed; }
.btn.out[disabled], .btn.out.dis { background: var(--grey-bg); border-color: var(--input-border); color: var(--ink4); }
.btn.pri[disabled] { background: var(--grey-bg); border-color: var(--input-border); color: var(--ink4); }
.btn.sm { height: 28px; padding: 0 10px; font-size: 13px; }
.btn.lk { height: auto; padding: 0; border: 0; }
.btn .spin { width: 13px; height: 13px; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: spin .8s linear infinite, fade-in .2s ease-out; }
@keyframes spin { to { transform: rotate(360deg); } }
.icon-btn {
  width: 32px; height: 32px; border-radius: 4px; border: 0; background: none; color: var(--ink3); padding: 0;
  display: inline-flex; align-items: center; justify-content: center; cursor: pointer; flex: none;
  transition: background-color var(--t-fast) ease, color var(--t-fast) ease, transform .14s var(--ease-out);
}
.icon-btn:active:not([disabled]) { transform: scale(.9); transition-duration: .06s; }
.icon-btn:hover { background: var(--hover); color: var(--primary); }
.icon-btn[disabled] { color: var(--ink4); cursor: not-allowed; background: none; opacity: .6; }
.icon-btn svg.i { width: 18px; height: 18px; }
.icon-btn.sm { width: 28px; height: 28px; }
.icon-btn.sm svg.i { width: 16px; height: 16px; }
.icon-btn.on { background: var(--primary-bg); color: var(--primary); }

/* 状态标签：2 像素圆角，12 号字；失败用红底白字，其余浅底加对应色的字 */
.chip {
  display: inline-flex; align-items: center; height: 20px; padding: 0 6px; border-radius: 2px;
  font-size: 12px; line-height: 20px; white-space: nowrap; vertical-align: middle; max-width: 100%;
}
.chip.ok { color: var(--success-ink); background: var(--success-bg); }
.chip.warn, .chip.info { color: var(--orange-ink); background: var(--orange-bg); }
.chip.error { color: #fff; background: var(--red); }
.chip.off { color: var(--ink3); background: var(--grey-bg); }
.chip.run { color: var(--sky-ink); background: var(--sky-bg); }
.chip.run::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; margin-right: 5px; animation: pulse 1s infinite alternate; }
@keyframes pulse { to { opacity: .25; } }
/* 轮询时状态变了的那一格：轻轻弹一下 */
.chip.st-chg { animation: chip-pop .42s var(--ease-out) both; }
@keyframes chip-pop { from { opacity: .2; transform: scale(.86); } }
.tag { display: inline-flex; align-items: center; height: 20px; padding: 0 6px; border-radius: 2px; font-size: 12px; line-height: 20px; color: var(--ink3); white-space: nowrap; vertical-align: middle; font-weight: 400; background: var(--grey-bg); }
.tag.warn { color: var(--orange-ink); background: var(--orange-bg); }
.tag.me { background: var(--primary-bg); color: var(--primary); }
.with-tag { display: flex; align-items: center; gap: 8px; min-width: 0; }
.with-tag input, .with-tag textarea { flex: 1; min-width: 0; }
.with-tag:has(> textarea) { align-items: flex-start; }
.sm-t { font-size: 12px; }

/* 表格：表头浅灰底加粗，行高 46，行线浅，悬停浅灰 */
.tbl-wrap { overflow-x: auto; }
table.tbl { width: 100%; border-collapse: collapse; table-layout: fixed; }
.tbl th, .tbl td { text-align: left; padding: 0 12px; height: 46px; border-bottom: 1px solid var(--divider); vertical-align: middle; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tbl th { background: var(--th-bg); color: var(--ink); font-weight: 600; font-size: 14px; border-bottom-color: var(--border); }
.tbl th:first-child, .tbl td:first-child { padding-left: 16px; }
.tbl th:last-child, .tbl td:last-child { padding-right: 16px; }
.tbl tbody tr:last-child td { border-bottom: 0; }
.tbl tr.row { cursor: pointer; }
.tbl td { transition: background-color .1s ease; }
.tbl tbody tr:hover td { background: var(--row-hover); }
/* 轮询时新来的一行：浅主色底慢慢褪掉 */
.tbl tbody tr.row-new td { animation: row-new 1.8s ease-out both; }
@keyframes row-new { 0%, 20% { background-color: var(--primary-bg); } 100% { background-color: transparent; } }
.tbl td.ops, .tbl th.ops { text-align: right; overflow: visible; }
.tbl td.ops > div { display: inline-flex; align-items: center; justify-content: flex-end; gap: 0; }
.ops .op { display: inline-flex; align-items: center; gap: 2px; height: 22px; padding: 0; border: 0; background: none; color: var(--primary); cursor: pointer; font-size: 14px; white-space: nowrap; transition: color var(--t-fast) ease; }
.ops .op:hover { color: var(--primary-hover); }
.ops .op.danger { color: var(--danger); }
.ops .op[disabled] { color: var(--ink4); cursor: not-allowed; }
.ops .op svg.i { width: 14px; height: 14px; }
.ops .op + .op::before { content: ""; display: inline-block; width: 1px; height: 12px; background: var(--input-border); margin: 0 10px; }
.tbl td.two { white-space: normal; line-height: 18px; padding-top: 6px; padding-bottom: 6px; }
.tbl td.two > div { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tbl td.two .sub { color: var(--ink4); font-size: 12px; }
.tbl td.wrap { white-space: normal; word-break: break-word; line-height: 20px; padding-top: 10px; padding-bottom: 10px; }
.tbl td .clamp { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; white-space: normal; }
.tbl .lnk { color: var(--primary); }
.tbl tr.grp td { height: 36px; background: var(--card); color: var(--ink3); font-size: 12px; }
.tbl tr.grp td b { color: var(--ink); font-weight: 600; font-size: 13px; margin-right: 8px; }
.tbl tr.grp td b::before { content: ""; display: inline-block; width: 3px; height: 12px; margin-right: 8px; background: var(--primary); border-radius: 1px; vertical-align: -1px; }
.tbl td.num, .tbl th.num { text-align: right; padding-right: 24px; }
.tbl td.idx, .tbl th.idx { text-align: center; padding-left: 8px; padding-right: 8px; }
.tbl.top td { vertical-align: top; padding-top: 12px; padding-bottom: 12px; height: auto; line-height: 22px; }
.tbl.top td.two .sub { line-height: 18px; }
.tbl tfoot td { border-top: 1px solid var(--border); font-weight: 600; background: var(--th-bg); }
.tbl-foot { display: flex; align-items: center; justify-content: flex-end; gap: 8px; min-height: 48px; padding: 8px 16px; border-top: 1px solid var(--divider); color: var(--ink3); font-size: 13px; flex-wrap: wrap; }
/* 只有一页时条数与页码都不写，底下那一条不留空着 */
.tbl-foot:empty { display: none; }
.tbl-foot .grow { flex: 1; }
.tbl.mini th, .tbl.mini td { height: 40px; }
.tbl.mini th:first-child, .tbl.mini td:first-child { padding-left: 8px; }
.tbl.mini th:last-child, .tbl.mini td:last-child { padding-right: 8px; }
.tbl.mini { border: 1px solid var(--border); border-radius: 4px; border-collapse: separate; border-spacing: 0; overflow: hidden; }
input.chk { width: 16px; height: 16px; accent-color: var(--primary); margin: 0; vertical-align: middle; cursor: pointer; }
.empty { padding: 36px 20px; text-align: center; color: var(--ink4); white-space: normal; }
.empty svg.i { width: 40px; height: 40px; display: block; margin: 0 auto 8px; color: var(--input-border); }
.empty .btn { margin-top: 12px; }
.empty .em-sub { margin-top: 4px; font-size: 13px; }

/* 分页：表格右下 */
.pager { display: inline-flex; align-items: center; gap: 6px; }
.pager button { min-width: 30px; height: 30px; padding: 0 6px; border: 1px solid var(--input-border); border-radius: 4px; background: var(--card); color: var(--ink2); cursor: pointer; display: inline-flex; align-items: center; justify-content: center; font-size: 13px; transition: color var(--t-fast) ease, border-color var(--t-fast) ease; }
.pager button:hover { border-color: var(--primary); color: var(--primary); }
.pager button.on { border-color: var(--primary); color: var(--primary); font-weight: 600; }
.pager button[disabled] { color: var(--ink4); border-color: var(--border); cursor: not-allowed; background: var(--card); }
.pager button svg.i { width: 16px; height: 16px; }
.pager .gap { display: inline-flex; align-items: center; justify-content: center; width: 24px; color: var(--ink4); }
.pager .gap svg.i { width: 16px; height: 16px; }

/* 列表页上面的查询卡片：标签加输入框横排，右边查询与重置 */
.query { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 24px; padding: 16px; }
.query .qi { display: flex; align-items: center; gap: 8px; min-width: 0; }
.query .qi > span { color: var(--ink); white-space: nowrap; }
.query .qi input, .query .qi select { width: 220px; max-width: 100%; height: 32px; padding: 0 11px; border: 1px solid var(--input-border); border-radius: 4px; background: var(--card); outline: 0; color: var(--ink); transition: border-color var(--t-fast) ease, box-shadow var(--t-fast) ease; }
.query .qi input:focus, .query .qi select:focus { border-color: var(--primary); box-shadow: 0 0 0 2px var(--focus-ring); }
.query .qa { display: flex; gap: 8px; margin-left: auto; }
/* 表格卡片头：左边操作按钮 */
.card-tb { display: flex; align-items: center; gap: 8px; padding: 12px 16px; flex-wrap: wrap; min-height: 56px; }
.card-tb .grow { flex: 1; }
.card-tb .t { font-size: 15px; font-weight: 600; margin-right: 8px; }

/* 旧的工具栏与筛选，组件页与表单里还在用 */
.toolbar { display: flex; align-items: center; gap: 8px; padding: 12px 16px; flex-wrap: wrap; min-height: 56px; }
.toolbar .grow { flex: 1; }
.search { display: flex; align-items: center; gap: 8px; height: 32px; padding: 0 10px; border-radius: 4px; background: var(--card); border: 1px solid var(--input-border); width: 260px; max-width: 100%; transition: border-color var(--t-fast) ease, box-shadow var(--t-fast) ease; }
.search:focus-within { border-color: var(--primary); box-shadow: 0 0 0 2px var(--focus-ring); }
.search input { border: 0; outline: 0; background: none; width: 100%; height: 30px; min-width: 0; }
.search svg.i { color: var(--ink4); width: 16px; height: 16px; }
.toolbar select { height: 32px; padding: 0 8px; border: 1px solid var(--input-border); border-radius: 4px; background: var(--card); max-width: 240px; }
.cell-sel { height: 30px; border: 1px solid transparent; border-radius: 4px; background: transparent; padding: 0 4px; max-width: 100%; width: auto; cursor: pointer; }
.cell-sel.faint { color: var(--ink4); }
.cell-sel:hover, .cell-sel:focus { border-color: var(--input-border); background: var(--card); }
.cell-sel:disabled { cursor: default; color: var(--ink); appearance: none; -webkit-appearance: none; }
.cell-sel:disabled:hover { border-color: transparent; background: transparent; }
.seg { display: inline-flex; border: 1px solid var(--input-border); border-radius: 4px; overflow: hidden; max-width: 100%; flex: none; }
.seg button, .seg a { display: inline-flex; align-items: center; height: 30px; padding: 0 14px; border: 0; background: var(--card); color: var(--ink2); cursor: pointer; font-size: 13px; white-space: nowrap; transition: background-color var(--t-fast) ease, color var(--t-fast) ease; }
.seg button + button, .seg a + a { border-left: 1px solid var(--input-border); }
.seg button:hover, .seg a:hover { color: var(--primary); }
.seg .on, .seg .on:hover { background: var(--btn-pri); color: var(--on-primary); }
.seg button[disabled] { color: var(--ink4); cursor: not-allowed; }

/* 门户首页：白底，上面是灰底点阵的画布只演工作流本身，下面是输入框，正好占满一屏；进度条压在画布上沿，不多占高 */
.page.pg-portal { padding: 0; background: var(--card); }
.page.pg-portal .progress { position: relative; z-index: 3; margin: 0 0 -2px; }
.cx-hero { display: flex; flex-direction: column; height: calc(100vh - var(--hd-h)); height: calc(100dvh - var(--hd-h)); min-height: 540px; }
/* 画布：节点卡片照编辑器，白底浅框，左边平台方块图标，标题，平台与用途；连线画出来，跑的时候变主色，小圆点沿线走 */
.dm { position: relative; flex: 1 1 auto; min-height: 0; overflow: hidden; background-color: var(--page); background-image: radial-gradient(var(--cv-dot) 1px, transparent 1.2px); background-size: 20px 20px; border-bottom: 1px solid var(--border); }
.dm-hd { position: absolute; z-index: 3; left: 20px; right: 20px; top: 14px; display: flex; align-items: center; gap: 8px; min-width: 0; height: 22px; pointer-events: none; }
.dm.empty .dm-hd { display: none; }
.dm-tag { flex: none; color: var(--ink3); font-size: 12px; line-height: 22px; }
.dm-st { flex: none; margin-left: auto; display: inline-flex; }
/* 运行状态：小圆点加字，不用彩色底块 */
.pv-st { display: inline-flex; align-items: center; gap: 6px; color: var(--ink2); font-size: 12px; line-height: 22px; font-variant-numeric: tabular-nums; }
.pv-st i { width: 6px; height: 6px; border-radius: 50%; background: var(--ink4); }
.pv-st.run i { background: var(--sky); animation: pulse 1s infinite alternate; }
.pv-st.ok i { background: var(--success); }
/* 画布内容裁在名字一行下面，镜头平移时节点不压到名字上 */
.dm-vp { position: absolute; left: 0; right: 0; top: 46px; bottom: 0; overflow: hidden; perspective: 1600px; }
.dm-stage { position: absolute; left: 0; top: 0; width: 0; height: 0; transform-origin: 0 0; }
/* 镜头倾斜：贴近时画布斜着，拉远时慢慢放平 */
.dm-tilt { position: absolute; inset: 0; transform-origin: 50% 40%; transition: transform 1.4s cubic-bezier(.2, .7, .2, 1), opacity .16s ease; }
.dm-tilt.on { transform: rotateX(14deg) rotateZ(-3deg); transition: opacity .16s ease; }
.dm-tilt.out { opacity: 0; }
.dm-tilt.dim { opacity: .35; transition: opacity .3s ease; }
/* 镜头平移时，出界的那一边淡出 */
.dm-vp.pan-x { -webkit-mask-image: linear-gradient(to right, transparent 0, rgba(0, 0, 0, 1) 32px, rgba(0, 0, 0, 1) calc(100% - 32px), transparent 100%); mask-image: linear-gradient(to right, transparent 0, rgba(0, 0, 0, 1) 32px, rgba(0, 0, 0, 1) calc(100% - 32px), transparent 100%); }
.dm-vp.pan-y { -webkit-mask-image: linear-gradient(to bottom, transparent 0, rgba(0, 0, 0, 1) 32px, rgba(0, 0, 0, 1) calc(100% - 28px), transparent 100%); mask-image: linear-gradient(to bottom, transparent 0, rgba(0, 0, 0, 1) 32px, rgba(0, 0, 0, 1) calc(100% - 28px), transparent 100%); }
/* 特写：画面四边都淡出，切到的邻居不留硬边 */
.dm-vp.close { -webkit-mask-image: linear-gradient(to right, transparent 0, rgba(0, 0, 0, 1) 72px, rgba(0, 0, 0, 1) calc(100% - 72px), transparent 100%), linear-gradient(to bottom, transparent 0, rgba(0, 0, 0, 1) 48px, rgba(0, 0, 0, 1) calc(100% - 48px), transparent 100%); -webkit-mask-composite: source-in;
  mask-image: linear-gradient(to right, transparent 0, rgba(0, 0, 0, 1) 72px, rgba(0, 0, 0, 1) calc(100% - 72px), transparent 100%), linear-gradient(to bottom, transparent 0, rgba(0, 0, 0, 1) 48px, rgba(0, 0, 0, 1) calc(100% - 48px), transparent 100%); mask-composite: intersect; }
.dm-edges { position: absolute; left: 0; top: 0; width: 1px; height: 1px; overflow: visible; }
.dm-e .ln { fill: none; stroke: var(--ink4); stroke-width: 1.5; stroke-dasharray: 1; stroke-dashoffset: 1; transition: stroke-dashoffset .3s ease, stroke .2s; }
.dm-e .ar { fill: var(--ink4); opacity: 0; transition: opacity .12s ease .22s, fill .2s; }
.dm-e.on .ln { stroke-dashoffset: 0; }
.dm-e.on .ar { opacity: 1; }
.dm-e.hot .ln { stroke: var(--primary); stroke-width: 2; }
.dm-e.hot .ar { fill: var(--primary); }
.dm-dot { fill: var(--primary); stroke: var(--primary-bg); stroke-width: 3; }
.dm-n { position: absolute; width: 248px; height: 52px; display: flex; align-items: center; gap: 10px; padding: 0 32px 0 12px; background: var(--card); border: 1px solid var(--border); border-radius: 6px; box-shadow: 0 1px 3px rgba(0, 0, 0, .06); opacity: 0; transform: translateY(8px) scale(.96); transition: opacity .3s ease, transform .3s ease; }
.dm-n.v { width: 170px; gap: 8px; padding: 0 28px 0 10px; }
.dm-n.on { opacity: 1; transform: none; animation: pv-pop .34s cubic-bezier(.3, 1.6, .5, 1) both; }
@keyframes pv-pop { from { opacity: 0; transform: scale(.6); } }
.dm-n.run { border-color: var(--primary); box-shadow: 0 0 0 1px var(--primary); }
.dm-e { transition: opacity .3s ease; }
.dm-stage.close .dm-n:not(.focus), .dm-stage.close .dm-e:not(.focus) { opacity: .15; }
.dm-n.start { width: 208px; }
.dm-n.start.v { width: 170px; }
.dm-e.st .ln { stroke-dasharray: 3 5; stroke-dashoffset: 0; opacity: 0; transition: opacity .3s ease, stroke .2s; }
.dm-e.st.on .ln { opacity: 1; }
.dm-pic { flex: none; width: 28px; height: 28px; border-radius: 4px; display: inline-flex; align-items: center; justify-content: center; color: #fff; background: var(--btn-pri); }
.dm-pic.sky { background: var(--sky); }
.dm-pic svg.i { width: 17px; height: 17px; }
.dm-n.v .dm-pic { width: 24px; height: 24px; }
.dm-n.v .dm-pic svg.i { width: 15px; height: 15px; }
.dm-tt { flex: 1; min-width: 0; }
.dm-tt .t { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 14px; font-weight: 600; line-height: 20px; color: var(--ink); }
.dm-n.v .dm-tt .t { font-size: 13px; line-height: 18px; }
.dm-tt .s { display: flex; align-items: center; gap: 6px; overflow: hidden; white-space: nowrap; font-size: 12px; line-height: 18px; color: var(--ink3); }
.dm-tt .s .w { flex: none; height: 18px; padding: 0 4px; border-radius: 2px; color: var(--orange-ink); background: var(--orange-bg); }
.dm-b { position: absolute; right: 8px; top: 7px; width: 16px; height: 16px; display: inline-flex; align-items: center; justify-content: center; }
.dm-n.v .dm-b { right: 5px; top: 5px; }
.dm-b svg.i { width: 16px; height: 16px; color: var(--success); }
.dm-b .spin-i { width: 12px; height: 12px; }
.dm-out { position: absolute; left: 0; top: calc(100% + 8px); display: inline-flex; align-items: center; gap: 4px; height: 26px; padding: 0 10px 0 7px; border: 1px solid var(--border); border-radius: 4px; background: var(--card); color: var(--ink2); font-size: 12px; white-space: nowrap; animation: dm-pop .35s ease both; }
.dm-out svg.i { width: 14px; height: 14px; color: var(--ink3); }
.dm-out .s { color: var(--success-ink); }
@keyframes dm-pop { from { opacity: 0; transform: translateY(-4px) scale(.9); } }
/* 输入框：贴着画布下面，居中；演示里那句话发出去时框闪一下主色 */
.cx-chat { flex: none; display: flex; flex-direction: column; align-items: center; padding: 20px 24px 24px; }
.cx-box.sent { animation: cx-sent .6s ease; }
@keyframes cx-sent { 30% { border-color: var(--primary); box-shadow: 0 0 0 3px var(--focus-ring); } }
@media (prefers-reduced-motion: reduce) {
  .dm-stage, .dm-n, .dm-e, .dm-e .ln, .dm-e .ar, .dm-tilt { transition: none !important; }
  .dm-n.on, .dm-out, .cx-ghost i, .pv-st i, .cx-box.sent { animation: none !important; }
}
.cx-chat .cx-box { width: 100%; max-width: 768px; flex: none; }
/* 矮的窗口：输入框少一行，画布多一点 */
@media (max-height: 820px) and (min-width: 641px) {
  .cx-chat { padding: 14px 24px 16px; }
  .cx-chat .cx-box textarea { min-height: 48px; }
  .cx-ghost { max-height: 48px; }
}
.cx-box { position: relative; display: flex; flex-direction: column; gap: 8px; padding: 14px 12px 12px 18px; border: 1px solid var(--input-border); border-radius: 8px; background: var(--card); box-shadow: 0 1px 2px rgba(0, 0, 0, .04); cursor: text; transition: border-color .15s, box-shadow .15s; }
.cx-box:focus-within { border-color: var(--primary); box-shadow: 0 0 0 2px var(--focus-ring); }
.cx-box textarea { width: 100%; min-height: 72px; max-height: 240px; padding: 0 6px 0 0; border: 0; background: none; outline: 0; resize: none; color: var(--ink); font-size: 15px; line-height: 24px; overflow-y: hidden; }
.cx-box textarea::placeholder { color: var(--ink4); }
/* 演示时在输入框里打字的那一层：正文颜色，后面一个闪烁的主色光标，点得透 */
.cx-ghost { position: absolute; left: 18px; right: 18px; top: 14px; max-height: 72px; overflow: hidden; pointer-events: none; color: var(--ink); font-size: 15px; line-height: 24px; white-space: pre-wrap; overflow-wrap: anywhere; }
.cx-ghost[hidden] { display: none; }
.cx-ghost i { display: inline-block; width: 2px; height: 18px; margin-left: 1px; vertical-align: -3px; background: var(--primary); animation: cx-caret 1s step-end infinite; }
.cx-ghost.typing i { animation: none; }
.cx-ghost.sent { color: var(--ink3); }
.cx-ghost.sent i { display: none; }
@keyframes cx-caret { 50% { opacity: 0; } }
.cx-bar { display: flex; align-items: center; gap: 8px; min-height: 32px; cursor: default; }
/* 示例说法：左下一排浅灰小圆块，放不下的整块收起 */
.cx-bar .ask-ex { flex: 1; min-width: 0; display: flex; flex-wrap: wrap; gap: 6px; height: 28px; overflow: hidden; }
.cx-bar .ask-ex .ex { height: 28px; max-width: 200px; padding: 0 10px; border: 0; border-radius: 4px; background: var(--grey-bg); color: var(--ink2); font-size: 13px; cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; transition: color var(--t-fast) ease, background-color .2s ease; }
/* 悬停只变字色；浅蓝底只给正在演示的那一个 */
.cx-bar .ask-ex .ex:hover { color: var(--primary); background: var(--grey-bg); }
.cx-bar .ask-ex .ex.on { color: var(--primary); background: var(--primary-bg); }
.cx-bar .btn { height: 32px; padding: 0 16px; }
.cx-ask { margin-left: auto; }
.cx-ask:not(.pri) { background: var(--grey-bg); color: var(--ink); }
.cx-ask:not(.pri):hover:not([disabled]) { background: var(--primary-bg); color: var(--primary); }
.chip.pub, .tag.pub { color: var(--primary); background: var(--primary-bg); }
.pl-empty { padding: 28px 0; text-align: center; color: var(--ink4); }
/* 工作流页的一句话新建弹框：大文本框，下面示例说法 */
.ask { display: flex; flex-direction: column; gap: 10px; }
.ask textarea { width: 100%; min-height: 76px; resize: vertical; padding: 8px 11px; border: 1px solid var(--input-border); border-radius: 4px; background: var(--card); color: var(--ink); line-height: 22px; outline: 0; transition: border-color var(--t-fast) ease, box-shadow var(--t-fast) ease; }
.ask textarea:hover { border-color: var(--primary-hover); }
.ask textarea:focus { border-color: var(--primary); box-shadow: 0 0 0 2px var(--focus-ring); }
.ask-f { display: flex; align-items: center; gap: 12px; }
.ask-ex { flex: 1; min-width: 0; display: flex; gap: 8px; overflow: hidden; height: 28px; flex-wrap: wrap; }
.ask-ex .ex { height: 28px; padding: 0 10px; border: 1px solid var(--border); border-radius: 14px; background: var(--card); color: var(--ink2); font-size: 13px; cursor: pointer; white-space: nowrap; max-width: 220px; overflow: hidden; text-overflow: ellipsis; transition: color var(--t-fast) ease, border-color var(--t-fast) ease, background-color var(--t-fast) ease; }
.ask-ex .ex:hover { color: var(--primary); border-color: var(--primary-hover); background: var(--primary-bg); }

/* 产出的小块：图标，名字，状态字。可访问的绿字，旧版与已删除灰字，已删除的名字划掉 */
.oc { display: inline-flex; align-items: center; gap: 4px; min-width: 0; max-width: 100%; height: 24px; padding: 0 8px 0 6px; border: 1px solid var(--border); border-radius: 4px; background: var(--card); color: var(--ink2); font-size: 13px; white-space: nowrap; flex: 0 1 auto; transition: border-color var(--t-fast) ease, color var(--t-fast) ease; }
.oc svg.i { width: 14px; height: 14px; color: var(--ink3); }
.oc .t { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.oc .s { flex: none; font-size: 12px; color: var(--ink3); }
.oc.live .s { color: var(--success-ink); }
a.oc:hover { border-color: var(--primary-hover); color: var(--primary); }
a.oc:hover svg.i { color: var(--primary); }
.oc.gone .t { text-decoration: line-through; color: var(--ink4); }
.oc-more { flex: none; color: var(--ink3); font-size: 12px; white-space: nowrap; }
.oc-more.n-only { display: none; }
.ocs { display: flex; align-items: center; gap: 8px; min-width: 0; overflow: hidden; }
.running { display: inline-flex; align-items: center; gap: 6px; color: var(--sky-ink); font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
.running .spin-i { width: 12px; height: 12px; }
.tbl.rn .err { display: block; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--red); font-size: 13px; }
.tbl.rn td.outs { overflow: hidden; }
.tbl.outs-t .on-t { display: flex; align-items: center; gap: 6px; min-width: 0; }
.tbl.outs-t .on-t svg.i { width: 16px; height: 16px; color: var(--ink3); }
.tbl.outs-t .on-t > span:not(.tag) { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink); }
.tbl.outs-t .on-t .gone { text-decoration: line-through; color: var(--ink4) !important; }
.page-head .meta .running { margin-left: 4px; }
.page-head .meta .dot { color: var(--ink4); margin: 0 -6px; }   /* 页头一行几样之间的点，两边各留 6 像素 */

/* 事实清单：名称在上，值在下 */
dl.facts { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 16px 24px; margin: 0; padding: 4px 16px 16px; }
dl.facts > .wide { grid-column: 1 / -1; }
dl.facts.two { grid-template-columns: repeat(2, minmax(0, 1fr)); }
dl.facts.four { grid-template-columns: repeat(4, minmax(0, 1fr)); }
dl.facts.three { grid-template-columns: repeat(3, minmax(0, 1fr)); }
dl.facts > div { min-width: 0; }
dl.facts dt { font-size: 12px; line-height: 18px; color: var(--ink3); margin-bottom: 4px; }
dl.facts dd { margin: 0; min-height: 22px; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; overflow-wrap: anywhere; color: var(--ink); }
dl.facts dd .big { font-weight: 600; }
/* 运行参数里一列取值（任务同步的待写任务）：写“共几条”，点开再列（11-02 E3，R2c P1-4）；列出来的那一块另起一行，不撑开同一行的别的几项 */
dl.facts dd details.pv-list { width: 100%; }
dl.facts dd details.pv-list > summary { display: inline-flex; align-items: center; gap: 4px; cursor: pointer; color: var(--primary); list-style: none; }
dl.facts dd details.pv-list > summary::-webkit-details-marker { display: none; }
dl.facts dd details.pv-list > summary::after { content: ""; width: 6px; height: 6px; margin-left: 2px; border-right: 1.5px solid var(--ink3); border-bottom: 1.5px solid var(--ink3); transform: rotate(45deg) translateY(-2px); transition: transform var(--t-fast) ease; }
dl.facts dd details.pv-list[open] > summary::after { transform: rotate(-135deg) translateY(-1px); }
dl.facts dd details.pv-list > summary:hover { color: var(--primary-hover); }
dl.facts dd details.pv-list > summary::after { border-color: currentColor; }
dl.facts dd .pv-it { white-space: nowrap; }      /* 一项不从中间断开（“飞书第 5 行”不劈成两行） */
dl.facts dd .pv-items { margin-top: 6px; color: var(--ink2); font-size: 13px; line-height: 20px; }
dl.facts.one { grid-template-columns: minmax(0, 1fr); }
.sheet dl.facts { padding: 0 0 4px; }

/* 表单：标签在左，右对齐，宽 100；必填的红星在标签前 */
.form { display: flex; flex-direction: column; gap: 18px; }
.fld { display: grid; grid-template-columns: 100px minmax(0, 1fr); column-gap: 12px; align-items: start; }
.fld > * { grid-column: 2; min-width: 0; }
.fld > label.l, .fld > .l { grid-column: 1; grid-row: 1 / span 3; display: flex; align-items: center; justify-content: flex-end; flex-wrap: wrap; gap: 4px; min-height: 32px; margin: 0; text-align: right; color: var(--ink); font-size: 14px; line-height: 18px; }
#mk-form .fld { grid-template-columns: 124px minmax(0, 1fr); }   /* 接入密钥：“可查的 Know-how”一行放得下，不在 Know-how 中间折行 */
#sm-form .fld { grid-template-columns: 116px minmax(0, 1fr); }
@media (min-width: 641px) { #sm-form .form-foot { padding-left: 128px; } }   /* 模型：“后台整理每日上限”八个字一行放得下（11-11 Gemini 看出折成两行） */
.fld .l .req { order: -1; color: var(--red); margin-right: 2px; }
.fld .l .tag { order: 2; }
.fld.stack { display: block; }
.fld.stack > .l { justify-content: flex-start; margin-bottom: 6px; min-height: 0; text-align: left; }
.fld input[type=text], .fld input[type=password], .fld input[type=number], .fld select, .fld textarea, .fld .inp {
  width: 100%; height: 32px; padding: 0 11px; border: 1px solid var(--input-border); border-radius: 4px; background: var(--card); outline: 0; color: var(--ink);
  transition: border-color .15s, box-shadow .15s;
}
.fld textarea { height: auto; min-height: 64px; padding: 5px 11px; resize: none; line-height: 22px; }
.card .fld input[type=text], .card .fld input[type=password], .card .fld input[type=number], .card .fld select { max-width: 420px; }
.fld textarea.mono, .fld input.mono { font-family: var(--mono); font-size: 12.5px; }
.fld input:hover, .fld select:hover, .fld textarea:hover { border-color: var(--primary-hover); }
.fld input:focus, .fld select:focus, .fld textarea:focus { border-color: var(--primary); box-shadow: 0 0 0 2px var(--focus-ring); }
.fld.bad input, .fld.bad select, .fld.bad textarea { border-color: var(--red); }
.fld.bad input:focus, .fld.bad textarea:focus { box-shadow: 0 0 0 2px var(--red-bg); }
.fld .err { margin-top: 4px; color: var(--red); font-size: 12px; line-height: 16px; }
.fld .err:empty { display: none; }
.fld .with-suffix { display: flex; align-items: center; gap: 8px; }
.fld .with-suffix span { color: var(--ink3); white-space: nowrap; }
.fld .with-suffix input { width: 160px; flex: none; }
.fld .with-suffix.sm-pair input { width: 96px; }
.fld .with-suffix.sm-pair span + input { margin-left: 20px; }
.fld input:disabled, .fld select:disabled, .fld textarea:disabled { background: var(--grey-bg); color: var(--ink3); border-color: var(--input-border); cursor: not-allowed; }
.fld .set-line { display: flex; align-items: center; gap: 8px; min-height: 32px; color: var(--ink3); flex-wrap: wrap; }
.rows { display: flex; flex-direction: column; gap: 8px; }
.rows .rw { display: flex; gap: 8px; align-items: center; }
.rows .rw input { flex: 1; min-width: 0; width: auto; }
.rows .btn { align-self: flex-start; }
.check { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; user-select: none; min-height: 32px; }
.check input { width: 16px; height: 16px; margin: 0; accent-color: var(--primary); cursor: pointer; flex: none; }
.check input:disabled { cursor: not-allowed; }
.checks { display: flex; flex-wrap: wrap; gap: 0 24px; }
/* 竖着排的几个勾选：接入密钥的组件开发，第二项缩进一格，跟在第一项下面 */
.checks.col { flex-direction: column; flex-wrap: nowrap; align-items: flex-start; }
.checks.col .check { align-items: flex-start; padding-top: 6px; min-height: 0; line-height: 20px; }
.checks.col .check input { margin-top: 3px; flex: none; }
.switch { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; user-select: none; min-height: 32px; }
.switch input { appearance: none; -webkit-appearance: none; width: 32px; height: 18px; border-radius: 9px; background: var(--ink4); border: 0; position: relative; cursor: pointer; margin: 0; transition: background .15s; flex: none; }
.switch input::after { content: ""; position: absolute; top: 2px; left: 2px; width: 14px; height: 14px; border-radius: 50%; background: #fff; transition: left .15s; box-shadow: 0 1px 2px rgba(0, 0, 0, .2); }
.switch input:checked { background: var(--btn-pri); }
.switch input:checked::after { left: 16px; }
.switch input:disabled { cursor: not-allowed; opacity: .5; }
.form-foot { display: flex; gap: 8px; padding-top: 4px; align-items: center; flex-wrap: wrap; padding-left: 112px; }
.code-wrap { position: relative; }
.code-wrap > .cp { position: absolute; top: 4px; right: 6px; z-index: 1; background: var(--code); }
.code-wrap > .jv, .code-wrap > .code { padding-right: 64px; }
.form.narrow { max-width: 560px; }
.res { display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 13px; color: var(--ink3); min-width: 0; }
.res:empty { display: none; }
/* 连接抽屉底栏的测试结果（11-02 FIX1，Gemini）：宽屏一行放不下时省略，悬停看全，取消与保存不被挤到下一行；手机宽照旧折行 */
@media (min-width: 641px) {
  #cn-res { flex: 0 1 auto; flex-wrap: nowrap; max-width: calc(100% - 212px); overflow: hidden; }      /* 让出测试，取消，保存三个键与间距 */
  #cn-res > span:not(.chip) { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
}
/* 手机宽折行时一长串不带空格的（服务器目录测试结果里的主机指纹，11-03 FIX10）也折开，不撑出抽屉 */
@media (max-width: 640px) { #cn-res > span:not(.chip) { overflow-wrap: anywhere; } }

/* 代码与 JSON */
pre.code, .code { margin: 0; padding: 10px 12px; background: var(--code); border: 1px solid var(--border); border-radius: 4px; font: 12.5px/19px var(--mono); white-space: pre-wrap; word-break: break-word; overflow-x: auto; color: var(--ink); max-height: 520px; overflow-y: auto; }
.code.err { background: var(--red-bg); border-color: transparent; color: var(--red); font-family: inherit; font-size: 13px; line-height: 20px; }
.code.warn { background: var(--orange-bg); border-color: transparent; color: var(--orange-ink); font-family: inherit; font-size: 13px; line-height: 20px; }
.jv { font: 12.5px/20px var(--mono); background: var(--code); border: 1px solid var(--border); border-radius: 4px; padding: 10px 12px 10px 30px; overflow-x: auto; color: var(--ink); max-height: 560px; overflow-y: auto; }
.jv ul { list-style: none; margin: 0; padding: 0 0 0 18px; }
.jv > ul { padding-left: 0; }
.jv li { position: relative; white-space: pre-wrap; word-break: break-word; }
.jv .tg { position: absolute; left: -19px; top: 2px; width: 16px; height: 16px; border: 0; padding: 0; background: none; color: var(--ink3); cursor: pointer; display: inline-flex; align-items: center; justify-content: center; }
.jv .tg svg.i { width: 16px; height: 16px; transition: transform .1s; }
.jv li.shut > .tg svg.i { transform: rotate(-90deg); }
.jv li.shut > ul { display: none; }
.jv .k { color: var(--ink3); }
.jv .s { color: var(--ink); }
.jv .n, .jv .b { color: var(--primary); }
.jv .z { color: var(--ink4); }
.jv .sum { color: var(--ink4); }
.jv .more { border: 0; background: none; color: var(--primary); cursor: pointer; padding: 0; margin-left: 8px; font: inherit; }
.sheet .jv, .sheet pre.code { max-height: none; }
.jv .cb { display: block; }
.jv li.shut > .cb { display: inline; }
.jv li:not(.shut) > .sum { display: none; }

/* 抽屉：标题 16 号，右上关闭，底栏按钮靠右 */
/* 滑出：进来慢慢停稳，收回去快一些；里面换页签时内容淡入 */
.sheet {
  position: fixed; top: 0; right: 0; bottom: 0; width: 560px; max-width: 100%; z-index: 50; display: flex; flex-direction: column;
  background: var(--card); box-shadow: var(--pop-shadow); border-left: 1px solid var(--border); transform: translateX(100%); visibility: hidden;
  transition: transform .22s var(--ease-in), visibility 0s linear .22s;
}
.sheet.on { transform: none; visibility: visible; transition: transform var(--t-panel) var(--ease-panel), visibility 0s; }
.sheet .sb.swap, .sheet .sf.swap { animation: fade-in .2s ease-out both; }
.sheet .sh { display: flex; align-items: center; gap: 8px; min-height: 56px; padding: 8px 12px 8px 24px; border-bottom: 1px solid var(--border); flex: none; }
.sheet .sh h2 { margin: 0; font-size: 16px; line-height: 24px; font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sheet .sh .sub { display: block; font-size: 12px; color: var(--ink3); line-height: 16px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sheet .sh .acts { display: flex; gap: 8px; align-items: center; margin-right: 8px; }
.sheet .tabs { margin: 0; padding: 0 12px; flex: none; }
.sheet .sb { flex: 1; overflow-y: auto; padding: 20px 24px 32px; min-height: 0; }
.sheet .sf { display: flex; align-items: center; justify-content: flex-end; gap: 8px; min-height: 52px; padding: 10px 16px; border-top: 1px solid var(--border); flex: none; flex-wrap: wrap; }
.sheet .sf > div { justify-content: flex-end; }
.sheet .sf .grow { flex: 1; }
.sheet .desc { margin: 0 0 16px; line-height: 22px; white-space: pre-wrap; overflow-wrap: anywhere; color: var(--ink2); }
.sheet .form { max-width: 640px; }
.sheet .form-foot { padding-left: 112px; }

/* 对话框：标题栏，内容，底栏按钮靠右 */
#dialog { position: fixed; inset: 0; z-index: 70; display: none; align-items: flex-start; justify-content: center; background: var(--scrim); padding: 12vh 16px 16px; }
#dialog.on { display: flex; animation: fade-in .2s ease-out both; }
#dialog.on .dlg { animation: dlg-in var(--t-dlg) var(--ease-out) both; }
/* 关掉时先淡出再拆，点不到也聚焦不到 */
#dialog.out { display: flex; pointer-events: none; animation: fade-out .16s ease-in both; }
#dialog.out .dlg { animation: dlg-out .16s var(--ease-in) both; }
/* 打开时焦点停在框本身（dialog 的 focus: 'dialog'，写外部系统的确认框）：框不画焦点框，Tab 照常到按钮。
   不靠 :focus-visible 分键盘鼠标：框是从框里的页面点出来的，浏览器判反了（点鼠标打开的算键盘，11-02 量过） */
#dialog .dlg[tabindex="-1"]:focus { outline: none; }
@keyframes dlg-in { from { opacity: 0; transform: translateY(12px) scale(.97); } }
@keyframes dlg-out { to { opacity: 0; transform: translateY(4px) scale(.98); } }
.dlg { width: 480px; max-width: 100%; max-height: calc(100vh - 14vh - 16px); overflow-y: auto; background: var(--card); border-radius: 6px; box-shadow: var(--pop-shadow); display: flex; flex-direction: column; }
.dlg .dh { display: flex; align-items: center; gap: 8px; min-height: 54px; padding: 0 12px 0 24px; border-bottom: 1px solid var(--border); }
.dlg .dh h3 { flex: 1; margin: 0; font-size: 16px; line-height: 24px; font-weight: 600; min-width: 0; }
.dlg .db { padding: 20px 24px; display: flex; flex-direction: column; gap: 16px; }
.dlg .body { color: var(--ink2); overflow-wrap: anywhere; }
/* 技能：组件详情的技能页签，看做法的对话框（标题与按钮不动，中间滚动），用 AI 新建或修改的抽屉 */
.dlg.sk-dlg { overflow: hidden; }
.dlg.sk-dlg .db { flex: 1; min-height: 0; overflow-y: auto; }
.sk-tbl td.two .sub { white-space: normal; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.dlg .body .desc { margin: 0 0 16px; line-height: 22px; color: var(--ink2); }
/* 组件详情：左边引脚图，右边说明与事实；窄屏上下排 */
.cp-head { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 8px 24px; align-items: start; margin-bottom: 4px; }
.cp-head .afe-chipbox { margin: -6px 0 0 -8px; }
.cp-head .cp-sum .desc { margin-bottom: 12px; }
@media (max-width: 760px) { .cp-head { grid-template-columns: minmax(0, 1fr); } }
.dlg .body .sec-h:first-of-type { margin-top: 16px; }
pre.code.sk-body { font-family: inherit; font-size: 13px; line-height: 21px; max-height: 360px; }
.sheet pre.code.sk-body { max-height: none; }
/* 附件一个一行，点开看全文；做法右上预览与导出 */
.sk-files { display: flex; flex-direction: column; border: 1px solid var(--border); border-radius: 4px; }
.sk-file + .sk-file { border-top: 1px solid var(--border); }
.sk-file summary { display: flex; align-items: center; gap: 12px; min-height: 36px; padding: 0 12px; cursor: pointer; font-size: 13px; }
.sk-file summary .muted { margin-left: auto; font-size: 12px; }
.sk-file pre.code { margin: 0 12px 12px; max-height: 280px; }
.sk-file[open] > pre.code { animation: rise-in .26s var(--ease-out) both; }
.sk-file summary { transition: background-color var(--t-fast) ease; }
.sk-file summary:hover { background: var(--hover); }
.sec-h .r .sk-ex { margin-left: 16px; }
/* 适用组件：通用，或者指定组件；指定时下面一块可搜的勾选清单，按平台分组 */
.sk-for { display: flex; flex-direction: column; gap: 8px; }
.sk-fmode { display: flex; flex-wrap: wrap; gap: 8px 24px; }
.sk-rd { display: inline-flex; align-items: center; gap: 6px; font-size: 14px; cursor: pointer; }
.sk-rd input { margin: 0; accent-color: var(--primary); }
.sk-fsome[hidden] { display: none; }
.sk-fsome { border: 1px solid var(--border); border-radius: 4px; }
.sk-fbar { display: flex; align-items: center; gap: 12px; padding: 8px; border-bottom: 1px solid var(--border); }
.sk-fbar .sk-fq { flex: 1; min-width: 0; height: 32px; }
.sk-fcnt { flex: none; font-size: 12px; }
.sk-flist { max-height: 240px; overflow-y: auto; padding: 4px 0; }
.sk-fgh { padding: 8px 12px 2px; font-size: 12px; color: var(--ink3); }
.sk-fc { display: flex; align-items: center; gap: 8px; min-height: 32px; padding: 0 12px; font-size: 13px; cursor: pointer; }
.sk-fc:hover { background: var(--hover); }
.sk-fnone { padding: 12px; font-size: 13px; }
.sk-forfld { margin-bottom: 4px; }
.sk-forbox .desc { margin-bottom: 12px; }
.tbl td .clamp1 { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sk-run { display: flex; align-items: center; gap: 8px; font-size: 14px; }
.sk-run .muted { margin-left: auto; font-size: 12px; }
.sk-steps { margin: 16px 0 0; padding-left: 22px; color: var(--ink2); line-height: 26px; }
.sk-ok { display: flex; align-items: center; gap: 8px; font-size: 15px; margin-bottom: 12px; }
.sk-ok svg.i { width: 20px; height: 20px; color: var(--success); flex: none; }
.dlg .body p { margin: 0 0 8px; }
.dlg .body p:last-child { margin-bottom: 0; }
.dlg .acts { display: flex; justify-content: flex-end; gap: 8px; padding: 10px 16px; border-top: 1px solid var(--border); }
.dlg .fld.typed { display: block; }
.dlg .fld.typed > .l { justify-content: flex-start; text-align: left; min-height: 0; margin-bottom: 6px; gap: 8px; }

/* 下拉菜单 */
#menu { position: fixed; z-index: 80; min-width: 160px; max-width: 340px; padding: 4px 0; background: var(--card); border-radius: 4px; box-shadow: var(--pop-shadow); border: 1px solid var(--border); display: none;
  transform-origin: var(--pop-ox, right) var(--pop-oy, top); }
#menu.on { display: block; animation: pop-in var(--t-pop) var(--ease-out) both; }
#menu.out { display: block; pointer-events: none; animation: pop-out .12s ease-in both; }
#menu button { display: flex; align-items: center; gap: 10px; width: 100%; min-height: 34px; padding: 0 16px; border: 0; background: none; text-align: left; cursor: pointer; color: var(--ink); white-space: nowrap; transition: background-color .08s ease, color .08s ease; }
#menu button:hover { background: var(--primary-bg); color: var(--primary); }
#menu button:hover svg.i { color: var(--primary); }
#menu button svg.i { color: var(--ink3); width: 16px; height: 16px; }
#menu button.danger, #menu button.danger svg.i { color: var(--danger); }
#menu button[disabled], #menu button[disabled] svg.i { color: var(--ink4); cursor: not-allowed; background: none; }
#menu button .ck { width: 16px; height: 16px; flex: none; color: var(--primary); display: inline-flex; }
#menu button .ck svg.i { color: var(--primary); }
#menu button .mt { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
#menu button .ms { color: var(--ink4); font-size: 12px; }
#menu hr { border: 0; border-top: 1px solid var(--divider); margin: 4px 0; }
#menu .mh { padding: 10px 16px; border-bottom: 1px solid var(--divider); margin-bottom: 4px; display: flex; flex-direction: column; gap: 2px; }
#menu .mh b { font-weight: 600; }
#menu .mh span { color: var(--ink3); font-size: 12px; }
#menu .mg { padding: 8px 16px 2px; color: var(--ink4); font-size: 12px; }
/* 长名字折行的菜单（对话里选 Know-how 库）：宽一点，名字折行看全，右边的小字不折 */
#menu.wrap { max-width: min(380px, calc(100vw - 16px)); }
#menu.wrap button { white-space: normal; padding-top: 7px; padding-bottom: 7px; line-height: 20px; }
#menu.wrap button .mt { overflow: visible; }
#menu.wrap button .ms { flex: none; white-space: nowrap; }

/* 提示：左下角 */
#toast { position: fixed; left: calc(var(--sd-w) + 24px); bottom: 24px; z-index: 90; display: flex; flex-direction: column; gap: 8px; pointer-events: none; transition: left var(--t-panel) var(--ease-panel); }
.toast { display: flex; align-items: center; gap: 10px; min-height: 44px; max-width: 560px; padding: 8px 8px 8px 14px; border-radius: 4px; background: var(--snack); color: var(--snack-ink); box-shadow: var(--pop-shadow); border: 1px solid var(--border); pointer-events: auto; animation: tin .34s var(--ease-out) both; }
.toast.out { pointer-events: none; animation: tout .22s var(--ease-in) both; }
@keyframes tout { to { opacity: 0; transform: translateX(-12px); } }
.toast > span { padding: 4px 6px 4px 0; overflow-wrap: anywhere; }
.toast svg.i { width: 18px; height: 18px; }
.toast .ic-ok { color: var(--success); } .toast .ic-err { color: var(--red); } .toast .ic-info { color: var(--sky); }
.toast .btn { height: 28px; padding: 0 8px; }
@keyframes tin { from { transform: translateY(16px) scale(.97); opacity: 0; } }

/* AI 助手：右侧常驻面板，从顶栏下开始，宽屏时内容区往左让；编辑页里停靠在画布右边一栏。
   样子照 Claude 的对话：自己说的话放右边圆角气泡，助手的话平铺，前面一个青蓝小标；输入是圆角大框，发送在框里右下 */
.assist { position: fixed; top: var(--hd-h); right: 0; bottom: 0; width: var(--as-w); z-index: 25; display: flex; flex-direction: column; background: var(--card); border-left: 1px solid var(--border); }
body.assist-open main { padding-right: var(--as-w); }
/* 面板从右边滑进来，内容区同时让位；关时先滑出再收 */
.assist:not(.docked):not([hidden]) { animation: as-in var(--t-panel) var(--ease-panel) both; }
.assist.leaving { pointer-events: none; animation: as-out .2s var(--ease-in) both; }
@keyframes as-in { from { opacity: 0; transform: translateX(40px); } }
@keyframes as-out { to { opacity: 0; transform: translateX(28px); } }
.as-h { display: flex; align-items: center; gap: 2px; height: 48px; padding: 0 8px 0 10px; border-bottom: 1px solid var(--divider); flex: none; }
.as-title { flex: 1; min-width: 0; display: inline-flex; align-items: center; gap: 4px; height: 32px; padding: 0 6px 0 6px; border: 0; border-radius: 6px; background: none; color: var(--ink); font-size: 14px; font-weight: 600; cursor: pointer; text-align: left; }
.as-title > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.as-title svg.i { color: var(--ink3); width: 16px; height: 16px; flex: none; }
.as-title:hover { background: var(--hover); }
.as-title { transition: background-color var(--t-fast) ease; }
.as-msgs { flex: 1; min-height: 0; overflow-y: auto; padding: 20px 16px 8px; display: flex; flex-direction: column; gap: 20px; background: var(--card); scrollbar-width: thin; overflow-anchor: none; }
.as-u { align-self: flex-end; max-width: 86%; background: var(--grey-bg); border-radius: 14px; padding: 9px 14px; white-space: pre-wrap; overflow-wrap: anywhere; line-height: 22px; color: var(--ink); transform-origin: right bottom; }
.as-a { display: flex; gap: 10px; min-width: 0; }
/* 新消息：自己的话从输入框方向浮上来，助手的答复跟着淡入 */
.as-u.in { animation: msg-u .38s var(--ease-out) both; }
/* 功能页上框一块说的那一句：气泡上面摆框的那一块的小图与“框选的一块”（同功能页的 AI 抽屉 .fa-u-sel，D2 报告） */
.as-uw { align-self: flex-end; display: flex; flex-direction: column; align-items: flex-end; gap: 6px; max-width: 86%; min-width: 0; }
.as-uw .as-u { max-width: 100%; }
.as-uw.in { transform-origin: right bottom; animation: msg-u .38s var(--ease-out) both; }
.as-u-sel { display: inline-flex; flex-direction: column; align-items: flex-end; gap: 4px; font-size: 12px; color: var(--ink3); }
.as-u-sel img { display: block; max-width: 220px; max-height: 128px; border-radius: var(--r); border: 1px solid var(--border); background: var(--card); object-fit: contain; }
.as-a.in { animation: rise-in .36s var(--ease-out) .06s both; }
@keyframes msg-u { from { opacity: 0; transform: translateY(14px) scale(.98); } }
.as-msgs > .gone { animation: fade-out .18s ease-in both; pointer-events: none; }
.as-av { flex: none; width: 22px; height: 22px; margin-top: 1px; border-radius: 6px; display: inline-flex; align-items: center; justify-content: center; color: #fff; background: var(--sky); }
.as-av svg.i { width: 14px; height: 14px; }
/* 答复中：小标里的星轻轻一收一放，不转圈；答完回到原大，带一点余势 */
.as-av.busy svg.i { animation: as-spark 1.6s ease-in-out infinite; }
@keyframes as-spark { 50% { transform: scale(.74); opacity: .72; } }
.as-av.rest svg.i { animation: as-rest .42s var(--ease-out) both; }
@keyframes as-rest { from { transform: scale(.8); opacity: .8; } }
.as-c { flex: 1; min-width: 0; }
.as-text { white-space: pre-wrap; overflow-wrap: anywhere; line-height: 24px; color: var(--ink); }
.as-text:empty { display: none; }
/* 正在写的字：新露出的几个字淡入，只变透明度，字的底边不抖 */
.as-f { animation: as-f .26s ease-out both; }
@keyframes as-f { from { opacity: 0; } }
/* 答完以后的查看记录与按钮：字写完了再浮出来 */
.as-tail { opacity: 0; transform: translateY(6px); transition: opacity .32s ease, transform .4s var(--ease-out); }
.as-tail.on { opacity: 1; transform: none; }
.as-tail:empty { display: none; }
.as-steps-t { display: inline-flex; align-items: center; gap: 2px; margin-top: 6px; padding: 0; border: 0; background: none; color: var(--ink3); font-size: 12px; cursor: pointer; transition: color var(--t-fast) ease; }
.as-steps-t:hover { color: var(--primary); }
.as-steps-t svg.i { width: 14px; height: 14px; transition: transform .24s var(--ease-out); }
.as-steps-t[aria-expanded="false"] svg.i { transform: rotate(-90deg); }
.as-steps { list-style: none; margin: 6px 0 0; padding: 0 0 0 12px; border-left: 2px solid var(--divider); color: var(--ink3); font-size: 12px; line-height: 18px; overflow: hidden; }
.as-steps li { padding: 2px 0; overflow-wrap: anywhere; }
.as-steps li .faint { margin-right: 6px; font-variant-numeric: tabular-nums; }
.as-work { display: flex; align-items: center; gap: 8px; color: var(--ink3); font-size: 13px; min-height: 24px; }
/* 进度换一句时像翻牌：旧的整行往上退出，新的稍晚一点从下面整行升上来，框外的部分裁掉，两行不叠在一起 */
.as-wt { display: grid; min-width: 0; height: 24px; overflow: hidden; }
.as-wt > span { grid-area: 1 / 1; min-width: 0; line-height: 24px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.as-wt > .in { animation: tick-in .3s var(--ease-out) .06s both; }
.as-wt > .out { animation: tick-out .16s var(--ease-in) both; }
@keyframes tick-in { from { opacity: 0; transform: translateY(100%); } }
@keyframes tick-out { to { opacity: 0; transform: translateY(-100%); } }
.spin-i { width: 14px; height: 14px; border: 2px solid var(--border); border-right-color: var(--primary); border-radius: 50%; animation: spin .8s linear infinite; flex: none; }
.as-act { margin-top: 12px; padding: 12px 14px; border: 1px solid var(--border); border-radius: 10px; display: flex; flex-direction: column; gap: 8px; background: var(--card); }
.as-act .t { font-weight: 600; overflow-wrap: anywhere; }
.as-act .d { color: var(--ink3); font-size: 13px; overflow-wrap: anywhere; }
.as-act .row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.as-act ul.warn { margin: 0; padding-left: 18px; color: var(--orange-ink); font-size: 12px; line-height: 18px; }
/* 11-01 评审 P1-10：AI 存版时等确认的几样，一样一行，13px 正文色 */
.as-act ul.as-wait-l { margin: 0; padding-left: 18px; color: var(--ink2); font-size: 13px; line-height: 20px; }
.as-act ul.as-wait-l li { overflow-wrap: anywhere; }
.as-act.as-wait .t { display: flex; align-items: center; gap: 6px; color: var(--orange-ink); }
.as-act.as-wait .t svg.i { width: 16px; height: 16px; flex: none; }
.as-act.as-wait.done .t { color: var(--success-ink); }
.as-act.as-wait.off .t { color: var(--ink3); font-weight: 500; }
.as-act.as-wait.off ul.as-wait-l { color: var(--ink3); }
/* 照 Know-how 生成的草稿头一条：流程几步都有对应节点，绿字打勾，不带圆点 */
.as-act ul.warn li.ok { list-style: none; margin-left: -18px; display: flex; align-items: flex-start; gap: 4px; color: var(--success-ink); }
.as-act ul.warn li.ok svg.i { flex: none; width: 14px; height: 14px; margin-top: 2px; }
.as-ok { display: inline-flex; align-items: center; gap: 4px; margin-right: auto; color: var(--success-ink); font-size: 13px; }
.as-ok svg.i { width: 16px; height: 16px; }
/* 项目的对话（docs/WORKSPACE.md）：一句改了工作流，答复下面一行写存成第几版，右边撤回；画布又改过没直接换上的，一行问换不换 */
.as-ver { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 10px; min-height: 28px; font-size: 13px; }
.as-ver .as-ok { margin-right: 4px; }
.as-ver.held { color: var(--ink2); column-gap: 6px; row-gap: 6px; }
/* 画布又改过的那一句：提醒一行，换上与不用挨着放在下一行，跟提醒的字左对齐 */
.as-ver.held > .as-warn { flex-basis: 100%; margin-right: 0; }
.as-ver.held > .btn:first-of-type { margin-left: 20px; }
.as-ver .as-ok.off { color: var(--ink3); }
.as-warn { display: inline-flex; align-items: flex-start; gap: 4px; margin-right: auto; color: var(--ink2); font-size: 13px; line-height: 20px; }
.as-warn svg.i { flex: none; width: 16px; height: 16px; margin-top: 2px; color: var(--orange); }
/* 计划清单（总 Agent 用 TodoWrite 列的步骤）：答复下面一块细框，一步一行；做完的打勾，字淡一档；正在做的主色转圈，答完没做完的停在主色实心小点；
   没做的空心圈。每一行最矮 22px，换状态只换记号与字色，不跳 */
.as-plan { margin-top: 10px; padding: 8px 12px 9px; border: 1px solid var(--border); border-radius: var(--r); background: var(--card); }
.as-plan[hidden] { display: none; }
.as-plan-h { margin-bottom: 4px; color: var(--ink3); font-size: 12px; font-weight: 600; line-height: 18px; }
.as-plan-l { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
.as-plan-l li { display: flex; align-items: flex-start; gap: 8px; min-height: 22px; color: var(--ink2); font-size: 13px; line-height: 20px; overflow-wrap: anywhere; }
.as-plan-l li .tx { min-width: 0; }
.as-plan-l li > svg.i, .as-plan-l li > .spin-i, .as-plan-l li > .dot { flex: none; margin-top: 3px; }
.as-plan-l li > svg.i { width: 14px; height: 14px; color: var(--success-ink); }
.as-plan-l li.done { color: var(--ink3); }
.as-plan-l li.doing { color: var(--ink); font-weight: 500; }
.as-plan-l li > .dot { width: 14px; height: 14px; box-sizing: border-box; border: 1.5px solid var(--ink4); border-radius: 50%; }
/* 等人的一步（11-03 FIX7 A36）：人形小图标同字一个灰度，后面一个“等你”的小标签，平台不接着做它 */
.as-plan-l li.wait > svg.i { color: var(--ink3); }
.as-plan-w { flex: none; margin-left: 2px; padding: 0 6px; border-radius: 9px; background: var(--grey-bg); color: var(--ink2); font-size: 12px; line-height: 18px; font-weight: 500; }
.as-plan-l li.doing > .dot { border: 0; background: radial-gradient(circle, var(--primary) 0 4px, transparent 4.5px); }      /* 停在这一步：主色实心小点，不画圈（画圈像单选框） */
/* 没做完：状态标签，右边“接着做” */
.as-ver.as-part .chip { flex: none; }
/* 平台接着做的那一段：一行灰字，同节点大框那一行（.as-nask）不可点的样子 */
.as-seg svg.i { color: var(--ink4); }
/* 没答出来：原因与重试一行 */
.as-fail { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.as-fail .as-err { display: inline-flex; align-items: flex-start; gap: 4px; }
.as-fail .as-err svg.i { flex: none; width: 16px; height: 16px; margin-top: 3px; }
/* 一个项目一段对话：标题只是名字，不点开历史 */
.as-title .as-vis { flex: none; margin-left: 4px; }
.as-title .as-vis[hidden] { display: none; }
.as-title.static { cursor: default; }
.as-title.static:hover { background: none; }
.as-title.static svg.i { display: none; }
.as-err { color: var(--red); overflow-wrap: anywhere; }
.as-in { flex: none; padding: 8px 12px 12px; display: flex; flex-direction: column; gap: 8px; }
.as-ex { display: flex; flex-wrap: wrap; gap: 6px; }
.as-exb { max-width: 100%; height: 28px; padding: 0 10px; border: 1px solid var(--border); border-radius: 14px; background: var(--card); color: var(--ink2); font-size: 13px; cursor: pointer; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  transition: color var(--t-fast) ease, border-color var(--t-fast) ease, background-color var(--t-fast) ease; animation: fade-in .18s ease-out both; }
.as-exb:hover { color: var(--primary); border-color: var(--primary-hover); background: var(--primary-bg); }
.as-box { display: flex; flex-direction: column; gap: 6px; padding: 10px 10px 8px 14px; border: 1px solid var(--input-border); border-radius: 14px; background: var(--card); cursor: text; transition: border-color .15s, box-shadow .15s; }
.as-box:focus-within { border-color: var(--primary); box-shadow: 0 0 0 2px var(--focus-ring); }
.as-box textarea { width: 100%; height: 24px; min-height: 24px; max-height: 168px; padding: 0; border: 0; background: none; outline: 0; resize: none; color: var(--ink); line-height: 24px; overflow-y: hidden; transition: height .16s var(--ease-out); }
.as-bar { display: flex; align-items: center; gap: 8px; min-height: 32px; }
.as-ctx { flex: 1; min-width: 0; display: inline-flex; align-items: center; gap: 4px; max-width: fit-content; height: 24px; padding: 0 8px; border-radius: 12px; background: var(--sky-bg); color: var(--sky-ink); font-size: 12px; overflow: hidden; animation: pop-in .2s var(--ease-out) both; transform-origin: left center; }
.as-ctx span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.as-ctx svg.i { width: 14px; height: 14px; flex: none; }
.as-send { flex: none; width: 32px; height: 32px; margin-left: auto; border: 0; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; background: var(--btn-pri); color: var(--on-primary); cursor: pointer;
  transition: background-color .16s ease, color .16s ease, transform .14s var(--ease-out); }
.as-send:active:not(:disabled) { transform: scale(.88); transition-duration: .06s; }
.as-send svg.i { width: 18px; height: 18px; animation: icon-in .24s var(--ease-out) both; }
.as-send:hover { background: var(--primary-hover); }
.as-send:disabled { background: var(--grey-bg); color: var(--ink4); cursor: not-allowed; }
.as-send.stop svg.i { width: 14px; height: 14px; }
.as-ctx-x { flex: none; width: 18px; height: 18px; margin: 0 -4px 0 2px; padding: 0; border: 0; border-radius: 50%; background: none; color: inherit; display: inline-flex; align-items: center; justify-content: center; cursor: pointer; }
.as-ctx-x svg.i { width: 12px; height: 12px; }
.as-ctx-x:hover { background: rgba(0, 0, 0, .08); }
/* 对话收起后画布右上角的展开把手，和对话栏的收起键同一高度；设置面板开着时让给面板 */
/* 对话收起后画布右上角的“AI 对话”键（用户 11-04：AI 的入口要明显）：同画布上浮着的工具条与小地图，白卡细边框，右边对齐小地图，
   对话气泡图标用帆软蓝；不用黑底，免得跟页头的“保存”上下两个黑块（Gemini 审图） */
.ed-chat-open { position: absolute; right: 14px; top: 12px; z-index: 7; height: 36px; padding: 0 12px 0 10px; border: 1px solid var(--border); border-radius: 8px;
  background: var(--card); color: var(--ink); display: inline-flex; align-items: center; gap: 6px; font-size: 14px; font-weight: 600; line-height: 1; cursor: pointer;
  box-shadow: var(--sh-sm); transition: border-color var(--t-fast) ease, box-shadow var(--t-fast) ease; animation: fade-in .24s ease-out both; }
.ed-chat-open svg.i { width: 18px; height: 18px; fill: var(--primary); }
.ed-chat-open:hover { border-color: var(--primary); color: var(--primary); box-shadow: var(--sh-md); }
.ed-chat-open:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
.afe.afe-sidevis .ed-chat-open { display: none; }
/* 停靠在编辑页：画布右边一栏，和画布一样是卡片；窄屏时盖住整屏，缺省收着 */
.afe-chat { position: relative; flex: 1 1 0; min-width: 340px; min-height: 0; display: flex; }
.afe-chat[hidden] { display: none; }
.assist.docked { position: static; width: 100%; height: 100%; z-index: auto; border: 1px solid var(--border); border-radius: 6px; overflow: hidden; }
body.as-dock main { padding-right: 0; }
@media (max-width: 1279px) {
  .afe-chat { position: fixed; top: var(--hd-h); right: 0; bottom: 0; width: var(--as-w); z-index: 44; min-width: 0; box-shadow: var(--pop-shadow); }
  .assist.docked { border: 0; border-left: 1px solid var(--border); border-radius: 0; }
}
@media (max-width: 900px) {
  .afe-chat { left: 0; width: auto; }
  .assist.docked { border-left: 0; }
}

/* 登录：浅色渐变底，左上标识，中间一张卡片，左半主色块，右半表单 */
.login { min-height: 100vh; display: flex; flex-direction: column; background: linear-gradient(160deg, #EAF2FD 0%, #F4F8FE 55%, #F7F8FA 100%); padding: 0 16px 40px; }
.login .lg-top { display: flex; align-items: center; gap: 10px; height: 88px; padding: 0 64px; font-size: 20px; font-weight: 600; color: var(--ink); }
.login .lg-top .logo { width: 32px; height: 32px; }
.login .logo .la, .login .logo .lf { stroke: var(--primary); } .login .logo .lf { fill: var(--primary); stroke: none; } .login .logo .lb { stroke: #23BEEF; }
.login .lg-card { display: flex; width: 880px; max-width: 100%; min-height: 460px; margin: 4vh auto 0; background: var(--card); border-radius: 6px; box-shadow: 0 8px 24px rgba(0, 0, 0, .08); overflow: hidden; animation: rise-in .5s var(--ease-out) both; }
.login .lg-l { flex: 1; min-width: 0; display: flex; flex-direction: column; justify-content: center; align-items: center; text-align: center; gap: 14px; padding: 48px 44px; background: var(--btn-pri); color: #fff; }
.login .lg-l h1 { margin: 0; font-size: 30px; line-height: 40px; font-weight: 600; }
.login .lg-l .lg-zh { margin-top: -6px; font-size: 16px; line-height: 24px; font-weight: 500; opacity: .92; }
.login .lg-l p { margin: 0; font-size: 15px; line-height: 26px; opacity: .92; }
.login .lg-r { width: 400px; max-width: 100%; flex: none; padding: 40px 40px 32px; display: flex; flex-direction: column; }
.login .lg-r h2 { align-self: center; margin: 0 0 28px; font-size: 18px; font-weight: 600; }
.login .sso { width: 100%; height: 40px; font-size: 15px; }
.login .or { display: flex; align-items: center; gap: 12px; margin: 24px 0 18px; color: var(--ink4); font-size: 12px; }
.login .or::before, .login .or::after { content: ""; flex: 1; border-top: 1px solid var(--divider); }
.login .local-lnk { align-self: center; margin-top: 20px; font-size: 13px; }
.login .sso.out { width: 100%; }
.login .form { gap: 16px; }
.login .fld { display: block; }
.login .fld > .l { justify-content: flex-start; min-height: 0; margin-bottom: 6px; text-align: left; }
.login .fld input[type=text], .login .fld input[type=password] { height: 40px; }
.login .form-foot { padding: 4px 0 0; }
.login .form-foot .btn { width: 100%; height: 40px; font-size: 15px; }
.login .msg { color: var(--red); font-size: 13px; margin: 0; }
.login .msg:empty { display: none; }
.login .box { width: 400px; max-width: 100%; margin: 12vh auto 0; background: var(--card); border-radius: 6px; padding: 32px; box-shadow: 0 8px 24px rgba(0, 0, 0, .08); animation: rise-in .5s var(--ease-out) both; }

select.m-sel { display: none; }

/* 宽度适配 */
/* 列表页收列也照内容区宽（R2b P2-8）：右边开着 AI 助手时 1440 宽的内容区只剩七百多像素，窗口宽的几条照旧摆全部列，技能名挤成几个字。
   主内容里的表格外框当容器，照它的宽收：不到 980 收起 c-lg，不到 800 收起 c-md，不到 620 收起 c-sm 并摆标题下面那一行（m-only）。
   照窗口宽的几条照旧，两样里窄的那一样说了算；抽屉里的表格不在主内容里，照旧只看窗口宽 */
#vb .tbl-wrap { container: lt / inline-size; }
@container lt (max-width: 979px) { .tbl col.c-lg, .tbl th.c-lg, .tbl td.c-lg { display: none; } }
@container lt (max-width: 799px) { .tbl col.c-md, .tbl th.c-md, .tbl td.c-md { display: none; } }
@container lt (max-width: 619px) {
  .tbl col.c-sm, .tbl th.c-sm, .tbl td.c-sm { display: none; }
  .tbl .m-only { display: block; }
  .tbl.m-fit { min-width: 0; }
}
body.assist-open .tbl col.c-lg, body.assist-open .tbl th.c-lg, body.assist-open .tbl td.c-lg { display: none; }
body.assist-open .grid-main { grid-template-columns: minmax(0, 1fr); }
@media (max-width: 1439px) {
  body.assist-open .grid2 { grid-template-columns: minmax(0, 1fr); }
  body.assist-open .tbl col.c-md, body.assist-open .tbl th.c-md, body.assist-open .tbl td.c-md { display: none; }
}
@media (max-width: 1279px) {
  /* 右边开着 AI 助手时内容区只剩三四百宽：四列的概要（运行详情的开始，结束时刻）挤在一起叠字，改成两列；
     运行详情的节点表照手机宽收起序号与用时，节点一列放到四成（原来只剩七十多宽，名字剩两个字，“展开里面几个组件”挤成三行，报错一列宽 0） */
  body.assist-open dl.facts.four { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  body.assist-open #rd-nodes col.c-sm, body.assist-open #rd-nodes th.c-sm, body.assist-open #rd-nodes td.c-sm { display: none; }
  body.assist-open #rd-nodes col.m-40p { width: 40% !important; }
  .query { gap: 12px 16px; }
  .query .qi input, .query .qi select { width: 150px; }
  .tbl col.c-lg, .tbl th.c-lg, .tbl td.c-lg { display: none; }
  .grid-main { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 1023px) {
  :root, body.side-mini { --sd-w: 0px; }
  #menu-btn, #gs-btn { display: inline-flex; }
  header.top .brand, body.side-mini header.top .brand { width: auto; padding: 0 4px; }
  body.side-mini header.top .brand span { display: inline; }
  /* 搜索收成顶栏的搜索图标，点开整宽铺在顶栏下面，后面压一层遮罩 */
  .gs-panel, body.side-mini .gs-panel { display: none; top: var(--hd-h); left: 0; width: 100%; z-index: 60; background: var(--card); border-bottom: 1px solid var(--border); box-shadow: var(--pop-shadow); }
  .gs-panel.on { display: block; }
  .gs-panel .box, .gs-panel .box:hover, .gs-panel:focus-within .box { height: 48px; padding: 0 16px; border-radius: 0; background: var(--card); color: var(--ink); border-bottom: 1px solid var(--divider); }
  .gs-panel .box svg.i { width: 18px; height: 18px; color: var(--ink3); }
  .gs-panel input { height: 44px; }
  .gs-panel input::placeholder { color: var(--ink4); }
  .gs-pop { position: static; width: auto; max-width: none; border: 0; border-radius: 0; box-shadow: none; }
  body.gs-open #scrim { top: var(--hd-h); opacity: 1; pointer-events: auto; }
  /* 左栏成抽屉，从顶栏下面滑出，分组跟宽屏一样，不受收起影响 */
  .side { width: 200px; z-index: 45; transform: translateX(-100%); visibility: hidden; border-right: 0; transition: transform .22s var(--ease-in), visibility 0s linear .22s; }
  .side.on { transform: none; box-shadow: 4px 0 12px rgba(0, 0, 0, .12); visibility: visible; transition: transform var(--t-panel) var(--ease-panel), visibility 0s; }
  .gs-panel.on { animation: fade-in .2s ease-out both; }
  .side .fold { display: none; }
  body.side-mini .side a span, body.side-mini .side .grp span { display: inline; opacity: 1; }
  body.side-mini .side .grp { padding: 16px 20px 4px; margin: 0; border-top: 0; }
  body.nav-open #scrim { top: var(--hd-h); }
  .assist { width: 100%; z-index: 44; border-left: 0; }
  body.assist-open main { padding-right: 0; }
  .tbl { min-width: 640px; }
  .tbl col.c-md, .tbl th.c-md, .tbl td.c-md { display: none; }
  .tbl.mini, .tbl.fit { min-width: 0; }
  .grid2 { grid-template-columns: minmax(0, 1fr); }
  .login .lg-l { display: none; }
  .login .lg-card { width: 420px; }
  .login .lg-r { width: 100%; }
  .login .lg-top { padding: 0 24px; }
}
@media (max-width: 640px) {
  .page { padding: 8px 8px 32px; }
  .progress { margin: -8px -8px 8px; }
  header.top .brand { padding: 0 2px; font-size: 15px; gap: 8px; }
  header.top .brand span, body.side-mini header.top .brand span { display: none; }
  .login .lg-top { font-size: 17px; }
  .hd-btn { width: 40px; }
  .hd-user .nm, .hd-user > svg.i { display: none; }
  .hd-user { padding: 0 10px 0 6px; }
  .hd-ai { padding: 0 10px; }
  .hd-ai span { display: none; }
  .page-head { min-height: 52px; padding: 8px 12px; }
  .m-only { display: block; }
  .m-hide { display: none !important; }
  .ops .m-hide + .op::before { display: none; }
  .tbl col.c-sm, .tbl th.c-sm, .tbl td.c-sm { display: none; }
  .tbl.m-fit { min-width: 0; }
  .tbl col.m-104 { width: 104px !important; }
  .tbl col.m-120 { width: 120px !important; }
  .tbl col.m-96 { width: 96px !important; }
  .tbl col.m-76 { width: 76px !important; }
  .tbl col.m-40p { width: 40% !important; }
  .tbl.rn td.m-right { padding-left: 4px; padding-right: 8px; }
  .tbl td.m-wrap { white-space: normal; line-height: 18px; padding-top: 6px; padding-bottom: 6px; }
  .tbl td.m-wrap .muted { display: block; margin-top: 4px; font-size: 12px; line-height: 16px; }
  .tbl td.m-right, .tbl th.m-right { text-align: right; }
  .tbl th:first-child, .tbl td:first-child { padding-left: 12px; }
  .jv { padding-left: 24px; }
  .jv ul { padding-left: 12px; }
  /* 门户：标题小一号，示例说法一排可横着划，两个键在下面一行靠右；今天几个数换到列表头第二行；产出放到名字下面 */
  .cx-hero { min-height: 600px; }
  .dm-hd { left: 12px; right: 12px; top: 10px; }
  .dm-vp { top: 40px; }
  .cx-chat { padding: 12px 12px 14px; }
  .cx-box { padding: 12px 10px 10px 14px; }
  .cx-box textarea { min-height: 48px; }
  .cx-bar { flex-wrap: wrap; row-gap: 10px; }
  .cx-bar .ask-ex { flex-basis: 100%; flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; -webkit-mask-image: linear-gradient(to right, rgba(0, 0, 0, 1) calc(100% - 56px), transparent 100%); mask-image: linear-gradient(to right, rgba(0, 0, 0, 1) calc(100% - 56px), transparent 100%); }
  .cx-ghost { left: 14px; right: 14px; top: 12px; max-height: 48px; }
  .cx-bar .ask-ex::-webkit-scrollbar { display: none; }
  .cx-bar .ask-ex .ex { flex: none; }
  /* 一句话新建：示例说法折成几行，都看得见，生成单占一行靠右 */
  .ask-f { flex-wrap: wrap; }
  .ask-ex { flex-basis: 100%; height: auto; overflow: visible; }
  .ask-ex .ex { max-width: 100%; }
  .pg-t { margin: 2px 4px 8px; }
  /* 产出只放得下一块 */
  .w-only { display: none !important; }
  .oc-more.n-only { display: inline; }
  /* 运行详情的产出：表格改成两行，上面名字与状态，下面操作靠右；类型与节点收起 */
  .tbl.outs-t { min-width: 0; }
  .tbl.outs-t colgroup, .tbl.outs-t thead { display: none; }
  .tbl.outs-t tbody tr { display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "name state" "ops ops"; align-items: center; row-gap: 6px; padding: 10px 12px; border-bottom: 1px solid var(--divider); }
  .tbl.outs-t tbody tr:last-child { border-bottom: 0; }
  .tbl.outs-t tbody td { display: block; height: auto; padding: 0 !important; border: 0; }
  .tbl.outs-t tbody td:nth-child(1) { grid-area: name; }
  .tbl.outs-t tbody td:nth-child(3) { grid-area: state; }
  .tbl.outs-t tbody td.ops { grid-area: ops; }
  .tbl.outs-t tbody td.c-sm, .tbl.outs-t tbody td.c-md { display: none; }
  .query .qi > span { min-width: 3em; text-align: right; }
  .query { padding: 12px; gap: 10px; }
  .query .qi { width: 100%; }
  .query .qi input, .query .qi select { width: auto; flex: 1; }
  .query .qa { width: 100%; justify-content: flex-end; }
  .card-tb { padding: 10px 12px; min-height: 52px; }
  .tbl-foot { padding: 8px 12px; }
  .toolbar { padding: 10px 12px; }
  .search { width: 100%; }
  .toolbar select { max-width: 100%; flex: 1; }
  dl.facts, dl.facts.four { grid-template-columns: repeat(2, minmax(0, 1fr)); padding: 4px 12px 12px; gap: 14px 16px; }
  .fld { display: block; }
  .fld > label.l, .fld > .l { justify-content: flex-start; min-height: 0; margin-bottom: 6px; text-align: left; }
  .form-foot, .sheet .form-foot { padding-left: 0; }
  .login { padding: 0 12px 32px; }
  .login .lg-top { height: 64px; padding: 0 8px; font-size: 18px; }
  .login .lg-card { margin-top: 2vh; min-height: 0; }
  .login .lg-r { padding: 28px 20px 24px; }
  .sheet dl.facts { padding: 0 0 4px; }
  .sheet { width: 100% !important; }
  .sheet .sb { padding: 16px; }
  .sheet .sf { padding: 10px 12px; }
  .sheet .sh { padding-left: 16px; }
  #dialog { padding-top: 8vh; }
  #toast { left: 12px; right: 12px; }
  .card-h { padding-left: 12px; padding-right: 12px; }
  .card-b { padding: 0 12px 12px; }
  .seg.m-sel { display: none; }
  select.m-sel { display: block; }
}

/* 系统设置：接入密钥，建好的密钥只显示一次，接入说明三种写法放在一个页签框里 */
.mk-wfs { display: flex; flex-direction: column; margin-top: 4px; }
.mk-wfs .check { min-height: 30px; }
.mk-wfs .check .mono { margin-right: 4px; }
.mk-once { display: flex; align-items: center; gap: 6px; margin: 8px 0 0; font-size: 13px; color: var(--ink2); }
.mk-once svg.i { width: 16px; height: 16px; color: var(--orange); flex: none; }
.mk-next { margin: 4px 0 0; font-size: 13px; color: var(--ink3); }
.mk-keybox { display: flex; align-items: flex-start; gap: 6px; padding: 4px 4px 4px 12px; background: var(--code); border: 1px solid var(--border); border-radius: 4px; }
.mk-keybox .mk-key { flex: 1; min-width: 0; padding-top: 4px; font: 12.5px/20px var(--mono); word-break: break-all; color: var(--ink); }
.ex-box { border: 1px solid var(--border); border-radius: 4px; overflow: hidden; background: var(--code); }
.ex-bar { display: flex; align-items: center; gap: 8px; padding: 0 4px 0 12px; border-bottom: 1px solid var(--border); background: var(--card); }
.ex-tabs { flex: 1; min-width: 0; display: flex; gap: 20px; }
.ex-tabs button { position: relative; height: 38px; padding: 0 2px; border: 0; background: none; color: var(--ink2); font-size: 13px; cursor: pointer; }
.ex-tabs button:hover { color: var(--primary); }
.ex-tabs button.on { color: var(--primary); font-weight: 500; }
.ex-tabs button.on::after { content: ""; position: absolute; left: 0; right: 0; bottom: -1px; height: 2px; background: var(--primary); }
.ex-box > pre.code { border: 0; border-radius: 0; }
.ex-box > pre.code[hidden] { display: none; }
pre.code.mk-ex { white-space: pre-wrap; word-break: normal; overflow-wrap: anywhere; max-height: 360px; }

/* AI 智能体的调用记录：组件与参数预览占大头，点一行展开完整参数与交回的摘要 */
.tbl.calls td.cc .t { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tbl.calls td.cc .p { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; white-space: normal; overflow-wrap: anywhere; color: var(--ink3); font-size: 12px; line-height: 18px; }
.tbl.calls tr.row.open td.cc .p { display: block; }
.tbl.calls td.cc .rs { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink3); font-size: 12px; line-height: 18px; }
.tbl.calls tr.row.open td.cc .rs { display: none; }
.tbl.calls tr.row.open td { border-bottom-color: transparent; }
.tbl.calls tr.dt td { height: auto; white-space: normal; padding-top: 0; padding-bottom: 12px; }
.tbl.calls tr.dt .k { margin: 4px 0 2px; color: var(--ink3); font-size: 12px; line-height: 18px; }
.tbl.calls tr.dt pre.code { max-height: 260px; overflow: auto; margin: 0; }
/* 组件库表格：组件名左边是平台小方块图标，和画布上的一样 */
#cp-tbl .cp-n { display: flex; align-items: center; gap: 10px; min-width: 0; }
#cp-tbl .cp-n .afe-pic { width: 26px; height: 26px; }
#cp-tbl .cp-n .afe-pic .afe-i { width: 16px; height: 16px; }
#cp-tbl .cp-t { min-width: 0; }

/* ------------------------------------------------------------------ 应用：运行底座的应用清单，装包，功能页；平台上打包前预览功能页。见 docs/PACKAGING.md 与 STYLE_PORTAL.md“应用与功能页” */
.hd-rt { flex: none; height: 20px; padding: 0 6px; border: 1px solid rgba(255, 255, 255, .5); border-radius: 4px; color: #fff; font-size: 12px; font-style: normal; font-weight: 400; line-height: 18px; white-space: nowrap; }
body.side-mini header.top .brand .hd-rt { opacity: 0; }
.fld .hint { margin-top: 4px; font-size: 12px; line-height: 18px; color: var(--orange-ink); }
.fld .hint.ro { color: var(--ink3); }
.fld input[readonly] { background: var(--th-bg); color: var(--ink2); }
/* 应用要的连接：锁着的类型与编号挨着放，字照常深，看得清，底色表示改不了 */
.fld-lock { display: flex; flex-direction: column; gap: 12px; }
.fld-lock > .hint { margin-top: -6px; padding-left: 112px; }
.fld input.locked[readonly], .fld select.locked:disabled { background: var(--th-bg); color: var(--ink); -webkit-text-fill-color: var(--ink); opacity: 1; cursor: default; }
.fld select.locked:disabled { appearance: none; -webkit-appearance: none; }
@media (max-width: 640px) { .fld-lock > .hint { padding-left: 0; } }
.tbl .ap-why { margin-top: 2px; font-size: 12px; line-height: 16px; color: var(--ink3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* 装包：拖文件的框，选了文件以后写计划 */
.ap-inst { display: flex; flex-direction: column; gap: 16px; }
.ap-drop { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; min-height: 120px; padding: 16px; border: 1px dashed var(--input-border); border-radius: 6px; background: var(--page); color: var(--ink2); cursor: pointer; text-align: center; transition: border-color var(--t-fast) ease, background-color var(--t-fast) ease; }
.ap-drop:hover, .ap-drop:focus-visible, .ap-drop.over { border-color: var(--primary); background: var(--primary-bg); outline: 0; }
.ap-drop svg.i { width: 28px; height: 28px; color: var(--primary); }
.ap-drop .t { font-size: 14px; color: var(--ink); overflow-wrap: anywhere; }
.ap-drop .s { font-size: 12px; color: var(--ink3); }
.ap-drop.picked { min-height: 64px; flex-direction: row; gap: 10px; justify-content: flex-start; text-align: left; }
.ap-drop.picked svg.i { width: 20px; height: 20px; }
.ap-drop.picked .s { margin-left: auto; color: var(--primary); }
.ap-plan { display: flex; flex-direction: column; gap: 16px; }
.ap-wait { display: flex; align-items: center; gap: 8px; color: var(--ink3); }
.ap-ph .n { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; font-size: 16px; }
.ap-ph .n b { font-weight: 600; }
.ap-ph .n .mono { color: var(--ink3); font-size: 13px; }
.ap-ph .s { margin-top: 4px; font-size: 12px; color: var(--ink3); overflow-wrap: anywhere; }
.ap-sec h4 { display: flex; align-items: center; gap: 8px; margin: 0 0 8px; font-size: 14px; font-weight: 600; }
.ap-sec h4::before { content: ""; width: 3px; height: 14px; background: var(--primary); border-radius: 1px; flex: none; }
.ap-sec h4 .faint { font-weight: 400; font-size: 12px; }
.ap-sec p { margin: 0; line-height: 22px; overflow-wrap: anywhere; }
.ap-notes { white-space: pre-wrap; }
.ap-sec .tbl.mini td { vertical-align: top; padding-top: 8px; padding-bottom: 8px; }
.ap-sec .tbl.mini td.bad { color: var(--red); }
.ap-sec .tbl.mini .sub { font-size: 12px; color: var(--ink3); }
.ap-msgs { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 4px; font-size: 13px; line-height: 20px; }
.ap-msgs li { position: relative; padding-left: 14px; overflow-wrap: anywhere; }
.ap-msgs li::before { content: ""; position: absolute; left: 2px; top: 7px; width: 6px; height: 6px; border-radius: 50%; background: var(--ink4); }
.ap-msgs.bad { padding: 10px 12px; border: 1px solid var(--red); border-radius: 6px; background: var(--red-bg); }
.ap-msgs.bad li::before, .ap-msgs li.warn::before { background: var(--red); }
.ap-msgs.warn li::before, .ap-msgs li.warn::before { background: var(--orange); }
.ap-msgs li.ok::before { background: var(--success); }
/* 功能页：平台上的预览条，AI 排的一版等保存，还不能跑的原因，页头，运行表单，取数说明，区块 */
.ap-bar { margin-bottom: 12px; }
.ap-bar-in, .ap-draftbar, .ap-warn { display: flex; align-items: center; gap: 10px; padding: 10px 16px; }
.ap-bar-in > svg.i, .ap-draftbar > svg.i, .ap-warn > svg.i { width: 18px; height: 18px; flex: none; color: var(--primary); }
.ap-bar-in .t { display: flex; flex-direction: column; min-width: 0; flex: 1; font-size: 13px; line-height: 20px; color: var(--ink3); }
.ap-bar-in .t b { color: var(--ink); font-size: 14px; font-weight: 600; }
.ap-bar-in .acts, .ap-draftbar .acts { display: flex; gap: 8px; flex-wrap: wrap; justify-content: flex-end; }
.ap-draftbar { border-color: var(--primary); background: var(--primary-bg); }
.ap-draftbar .t { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.ap-warn { align-items: flex-start; border-color: var(--orange); }
.ap-warn > svg.i { color: var(--orange); margin-top: 2px; }
.ap-warn .t { flex: 1; min-width: 0; }
.ap-warn ul { margin: 6px 0 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 6px; }
.ap-warn li { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; font-size: 13px; }
.ap-warn li .mono { font-weight: 500; }
.ap-head { padding: 16px 20px 0; }
.ap-h1 { display: flex; align-items: flex-start; gap: 12px 20px; flex-wrap: wrap; }
.ap-h1 .back { margin: -2px -4px 0 -8px; }
.ap-title { flex: 1 1 280px; min-width: 0; }
.ap-title h1 { margin: 0; font-size: 20px; line-height: 28px; font-weight: 600; overflow-wrap: anywhere; }
.ap-title p { margin: 2px 0 0; font-size: 13px; line-height: 20px; color: var(--ink3); overflow-wrap: anywhere; }
.ap-meta { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 20px; min-height: 32px; font-size: 13px; color: var(--ink3); }
.ap-meta > span { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.ap-meta .nowrap { color: var(--ink2); }
.ap-acts { display: flex; align-items: center; flex-wrap: wrap; gap: 12px; min-height: 32px; }
.ap-sch { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; color: var(--ink2); cursor: pointer; user-select: none; white-space: nowrap; }
.ap-sch input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.ap-sch .sw { position: relative; width: 32px; height: 18px; border-radius: 9px; background: var(--ink4); flex: none; transition: background .15s; }
.ap-sch .sw::after { content: ""; position: absolute; top: 2px; left: 2px; width: 14px; height: 14px; border-radius: 50%; background: #fff; box-shadow: 0 1px 2px rgba(0, 0, 0, .2); transition: left .15s; }
.ap-sch input:checked + .sw { background: var(--btn-pri); }
.ap-sch input:checked + .sw::after { left: 16px; }
.ap-sch input:focus-visible + .sw { box-shadow: 0 0 0 2px var(--focus-ring); }
.ap-sch svg.i { width: 16px; height: 16px; color: var(--ink3); vertical-align: -3px; margin-right: 2px; }
.ap-sch.ro, .ap-sch.dis { cursor: default; }
.ap-sch.dis .sw { opacity: .5; }
.ap-h2 { display: flex; align-items: flex-end; gap: 12px; margin-top: 8px; }
.ap-h2 .tabs.ap-tabs { flex: 1; min-width: 0; margin: 0 0 0 -16px; border-bottom: 0; }
.ap-plats { display: flex; gap: 16px; padding: 0 0 12px; font-size: 13px; color: var(--ink2); white-space: nowrap; overflow: hidden; }
.ap-plats i { font-style: normal; color: var(--ink4); margin-right: -6px; }
.ap-q .qi > span .req { color: var(--red); font-style: normal; margin-left: 2px; }
.ap-strip { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 8px; margin: -2px 0 10px; padding: 0 4px; font-size: 13px; color: var(--ink3); }
.ap-strip .nowrap { color: var(--ink2); }
.ap-strip .op { margin-left: 4px; }
.ap-strip.run { color: var(--sky-ink); }
.ap-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 0 12px; align-items: start; }
.ap-sec.full { grid-column: 1 / -1; }
.ap-sec .card-h .muted, .ap-sec .card-h .chip { margin-left: auto; }
.ap-sec .card-h .chip + .op { margin-left: 8px; }
.ap-sec .card-h .op { display: inline-flex; align-items: center; gap: 2px; }
.ap-sec .card-h .op svg.i { width: 15px; height: 15px; }
.ap-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
.ap-stat { padding: 16px 20px; border-left: 1px solid var(--divider); }
.ap-stat:first-child { border-left: 0; }
.ap-stat .v { font-size: 26px; line-height: 34px; font-weight: 600; color: var(--ink); }
.ap-stat .l { margin-top: 2px; font-size: 13px; color: var(--ink3); }
.ap-tw { max-height: 520px; overflow: auto; border-top: 1px solid var(--divider); }
.ap-tw .tbl th { position: sticky; top: 0; z-index: 1; }
.ap-tw .tbl td { max-width: 360px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ap-frame { display: block; width: 100%; height: 640px; border: 0; border-top: 1px solid var(--divider); border-radius: 0 0 6px 6px; background: var(--card); }
.ap-text { white-space: pre-wrap; overflow-wrap: anywhere; line-height: 24px; color: var(--ink); }
/* 表单区块（10-28）：同源嵌着平台画的表单，按内容撑开，左边与卡片标题对齐（框里留 3px 给输入框的焦点圈）；
   框的配色方案随平台，与表单页的一致，框底透明。最近提交另一张卡片，同表格区块 */
.ap-form { padding: 12px 17px 8px; border-top: 1px solid var(--divider); }
.ap-fframe { display: block; width: 100%; max-width: 726px; height: 520px; border: 0; background: transparent; }
.ap-files { margin: 0; padding: 0 16px 8px; list-style: none; }
.ap-files li { display: flex; align-items: center; gap: 10px; min-height: 44px; border-top: 1px solid var(--divider); }
.ap-files li svg.i { width: 18px; height: 18px; color: var(--ink3); flex: none; }
.ap-files li .t { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ap-files li .s { color: var(--ink3); font-size: 12px; margin-right: auto; }
@media (max-width: 1023px) {
  .ap-grid { grid-template-columns: minmax(0, 1fr); }
  .ap-sec.half { grid-column: 1 / -1; }
}
@media (max-width: 640px) {
  .ap-head { padding: 12px 12px 0; }
  .ap-h1 { gap: 8px 12px; }
  .ap-meta { gap: 2px 12px; }
  .ap-h2 { flex-direction: column; align-items: stretch; gap: 0; }
  .ap-plats { order: -1; padding: 4px 0 0; gap: 12px; }
  .ap-bar-in, .ap-draftbar { flex-wrap: wrap; }
  .ap-bar-in .acts, .ap-draftbar .acts { width: 100%; justify-content: flex-start; }
  .ap-stat { padding: 12px 14px; }
  .ap-stat .v { font-size: 22px; line-height: 30px; }
  .ap-frame { height: 480px; }
  header.top .brand .hd-rt { display: none; }
}

/* Know-how 知识库页：列表照别的列表页；详情页的页签是表，说明，例子，文档，关系，检索 */
.kh-desc { margin: 0 0 12px; padding: 10px 16px; background: var(--card); border: 1px solid var(--border); border-radius: 6px; color: var(--ink2); line-height: 22px; white-space: pre-wrap; }
.card-h .faint { font-size: 13px; }
.kh-srcs { display: flex; flex-direction: column; padding: 0 16px; }
.kh-none { padding: 4px 0 12px; line-height: 22px; }
.kh-src { display: flex; align-items: center; gap: 10px; min-height: 52px; padding: 8px 0; border-top: 1px solid var(--divider); }
.kh-src:first-child { border-top: 0; }
.kh-src > svg.i { width: 20px; height: 20px; color: var(--primary); flex: none; }
.kh-src .t { flex: 1; min-width: 0; display: flex; flex-direction: column; line-height: 20px; }
.kh-src .t .faint { font-size: 12.5px; }
.kh-addsrc { display: flex; align-items: center; gap: 8px; padding: 8px 16px 16px; flex-wrap: wrap; }
.kh-al { flex: none; font-size: 13px; color: var(--ink2); }
.kh-ih .ops, .kh-src .ops { display: inline-flex; align-items: center; flex: none; }
.kh-addsrc select { width: 280px; max-width: 100%; height: 32px; padding: 0 8px; border: 1px solid var(--input-border); border-radius: 4px; background: var(--card); color: var(--ink); outline: 0; transition: border-color var(--t-fast) ease; }
.kh-addsrc select:focus { border-color: var(--primary); box-shadow: 0 0 0 2px var(--focus-ring); }
.kh-filter { display: flex; align-items: center; gap: 6px; height: 32px; padding: 0 10px; width: 320px; max-width: 100%; border: 1px solid var(--input-border); border-radius: 4px; background: var(--card); }
.kh-filter:focus-within { border-color: var(--primary); box-shadow: 0 0 0 2px var(--focus-ring); }
.kh-filter svg.i { width: 16px; height: 16px; color: var(--ink3); flex: none; }
.kh-filter input { flex: 1; min-width: 0; border: 0; outline: 0; background: none; height: 30px; padding: 0; }
.kh-list { display: flex; flex-direction: column; padding: 0 16px 8px; }
/* 只读的人卡片顶上没有加一条的按钮，清单直接在卡片顶上 */
.card > .kh-list:first-child { padding-top: 12px; }
.kh-list > .empty { padding: 28px 12px; }
.kh-item { padding: 12px 0; border-top: 1px solid var(--divider); }
.kh-item:first-child { border-top: 0; padding-top: 4px; }
.kh-ih { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; min-height: 28px; }
.kh-ih b { font-weight: 600; }
.kh-ih .faint { font-size: 12.5px; }
.kh-ih .sp { flex: 1; }
.kh-ib { margin: 4px 0 0; white-space: pre-wrap; line-height: 22px; color: var(--ink2); overflow-wrap: anywhere; }
pre.code.kh-code { margin-top: 8px; max-height: 260px; }
.kh-rels { margin: 0; padding: 0; list-style: none; }
.kh-rels li { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; min-height: 30px; border-bottom: 1px solid var(--divider); }
.kh-graph { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 12px; padding: 16px; }
.kh-gt { border: 1px solid var(--border); border-radius: 6px; padding: 8px 12px; min-width: 0; }
.kh-gn { font-weight: 600; color: var(--ink); line-height: 24px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kh-gt ul { margin: 4px 0 0; padding: 0; list-style: none; }
.kh-gt li { display: flex; align-items: center; gap: 6px; min-height: 26px; font-size: 13px; flex-wrap: wrap; }
.kh-ask { display: flex; gap: 8px; padding: 16px; }
.kh-ask input { flex: 1; min-width: 0; }
.kh-hits { margin: 0; padding: 0 16px 16px 36px; }
.kh-hits li { padding: 8px 0; }
.kh-hits pre.code { margin-top: 6px; max-height: 220px; }
.kh-empty { line-height: 22px; }
@media (max-width: 640px) {
  .kh-addsrc select, .kh-filter { width: 100%; }
  .kh-graph { grid-template-columns: minmax(0, 1fr); }
}

/* ================================================================== 2026 版界面
 * 用户 10-26 定：可视化画布风，黑白为主帆软蓝只做强调，圆角阴影照 AI 大厂放开。这一段压在上面旧版写法后面，
 * 同名选择器盖掉旧外观，旧规则里没盖到的照旧生效；编辑器与组件工厂自己的部分在 editor.css，factory.css 末尾同名一段。 */
body { background: var(--page); letter-spacing: 0; }
::selection { background: var(--code-sel); }
a { color: var(--primary); }

/* ------------------------------------------------------------------ 外壳：宽屏没有顶栏，左栏和页面同一个浅灰底；当前项是一块浮起的白色圆角块 */
header.top { display: none; }
.side {
  top: 0; width: var(--sd-w); background: var(--page); border-right: 0; padding: 12px 12px 10px; gap: 6px;
}
.sd-top { flex: none; display: flex; flex-direction: column; gap: 12px; padding: 2px 0 6px; }
.sd-brand { display: flex; align-items: center; gap: 10px; min-height: 40px; padding: 0 6px; color: var(--ink); overflow: hidden; }
.sd-brand:hover { color: var(--ink); }
.sd-brand .logo { width: 28px; height: 28px; }
.sd-brand .logo .la, .sd-brand .logo .lf { stroke: var(--primary-fill); } .sd-brand .logo .lf { fill: var(--primary-fill); stroke: none; } .sd-brand .logo .lb { stroke: var(--sky); }
.sd-name { display: flex; flex-direction: column; min-width: 0; line-height: 16px; white-space: nowrap; }
.sd-name b { font-size: 15px; line-height: 20px; font-weight: 650; letter-spacing: -.01em; color: var(--ink); }
.sd-name small { font-size: 12px; color: var(--ink3); }
.sd-brand .hd-rt { color: var(--ink3); border-color: var(--border); }
.sd-search {
  display: flex; align-items: center; gap: 8px; height: 36px; padding: 0 8px 0 10px; border: 1px solid var(--border); border-radius: var(--r);
  background: var(--card); color: var(--ink3); cursor: pointer; text-align: left; box-shadow: var(--sh-xs); white-space: nowrap; overflow: hidden;
  transition: border-color var(--t-fast) ease, color var(--t-fast) ease;
}
.sd-search:hover { border-color: var(--input-border); color: var(--ink2); }
.sd-search svg.i { width: 16px; height: 16px; }
.sd-search span { flex: 1; }
kbd, .sd-search kbd { display: inline-flex; align-items: center; height: 20px; padding: 0 6px; border: 1px solid var(--border); border-radius: 5px; background: var(--page); color: var(--ink3); font: 500 11px/18px var(--mono); }
.side .items { padding: 2px 0; scrollbar-width: none; }
.side .grp { padding: 14px 10px 4px; font-size: 12px; line-height: 18px; color: var(--ink4); font-weight: 500; }
.side a { height: 36px; padding: 0 10px; gap: 10px; border-radius: var(--r); color: var(--ink2); font-weight: 500; margin: 1px 0; }
.side a svg.i { width: 18px; height: 18px; color: var(--ink3); }
.side a:hover { color: var(--ink); background: var(--hover2); }
.side a:hover svg.i { color: var(--ink2); }
.side a.on { color: var(--ink); background: var(--card); box-shadow: var(--sh-sm); }
.side a.on svg.i { color: var(--primary-fill); }
.side .ink { height: 36px; left: 0; right: 0; border-radius: var(--r); background: var(--card); box-shadow: var(--sh-sm); margin-top: 1px; }
.side.inked a.on { box-shadow: none; }
.sd-bot { flex: none; display: flex; flex-direction: column; gap: 6px; padding-top: 8px; border-top: 1px solid var(--border); }
/* AI 助手：外壳上不用紫色，紫色只留给画布上的 AI 类节点。开着不加底块，图标从灰变黑，免得和导航当前项像是选中了两个 */
.sd-ai {
  display: flex; align-items: center; gap: 10px; height: 36px; padding: 0 10px; border: 0; border-radius: var(--r); background: none; color: var(--ink2);
  font-weight: 500; cursor: pointer; white-space: nowrap; overflow: hidden; transition: background-color var(--t-fast) ease, color var(--t-fast) ease;
}
.sd-ai svg.i { width: 18px; height: 18px; color: var(--ink3); }
.sd-ai:hover { background: var(--hover2); color: var(--ink); }
.sd-ai.on { background: none; color: var(--ink); box-shadow: none; }
.sd-ai.on svg.i { color: var(--ink); }
.sd-ai.on:hover { background: var(--hover2); }
.sd-me { display: flex; align-items: center; gap: 4px; }
.sd-user { flex: 1; min-width: 0; display: flex; align-items: center; gap: 10px; height: 40px; padding: 0 6px; border: 0; border-radius: var(--r); background: none; color: var(--ink); cursor: pointer; white-space: nowrap; overflow: hidden; }
.sd-user:hover, .sd-user.on { background: var(--hover2); }
.sd-user .nm { overflow: hidden; text-overflow: ellipsis; font-weight: 500; }
.avatar { width: 28px; height: 28px; background: var(--avatar); color: var(--on-avatar); font-size: 12px; }
.side .fold { width: 36px; height: 36px; padding: 0; justify-content: center; border: 0; border-radius: var(--r); color: var(--ink3); flex: none; }
.side .fold:hover { background: var(--hover2); color: var(--ink); }
/* 收成图标条：只留图标，头像与展开键都在中轴上，分隔线短一点 */
body.side-mini .side { padding: 12px 10px 10px; }
body.side-mini .sd-name, body.side-mini .sd-search span, body.side-mini .sd-search kbd, body.side-mini .sd-ai span, body.side-mini .sd-user .nm, body.side-mini .sd-brand .hd-rt { display: none; }
body.side-mini .sd-brand { padding: 0 10px; }
body.side-mini .sd-search { justify-content: center; padding: 0; }
body.side-mini .side a, body.side-mini .sd-ai { padding: 0 15px; }
body.side-mini .sd-me { flex-direction: column; align-items: center; }
body.side-mini .sd-user { padding: 0 8px; }
body.side-mini .sd-bot { border-top: 0; position: relative; }
body.side-mini .sd-bot::before { content: ""; position: absolute; top: 0; left: 50%; width: 28px; height: 1px; margin-left: -14px; background: var(--border); }
body.side-mini .side .fold { padding: 0; }
main { padding: 0 0 0 var(--sd-w); }
.page { padding: 20px 28px 40px; }
main:not(.full) #view { max-width: 1680px; }

/* 命令面板：Ctrl K 或斜杠，正中偏上弹出，后面压一层遮罩；结果按菜单，工作流，组件分组 */
.gs-panel { display: none; position: fixed; left: 50%; top: 14vh; width: min(640px, calc(100vw - 32px)); transform: translateX(-50%); z-index: 70;
  background: var(--raised); border: 1px solid var(--border); border-radius: var(--r-xl); box-shadow: var(--sh-xl); overflow: hidden; }
body.side-mini .gs-panel { left: 50%; }
/* 旧版搜索框聚焦时把层级降到 61，面板会落到遮罩（65）底下，点不到结果；聚焦时也留在 70 */
.gs-panel:focus-within { z-index: 70; }
.gs-panel.on { display: block; animation: pop-in var(--t-pop) var(--ease-out) both; }
.gs-panel .box, .gs-panel .box:hover, .gs-panel:focus-within .box { height: 56px; padding: 0 16px 0 18px; border-radius: 0; background: none; color: var(--ink); border-bottom: 1px solid var(--border); }
.gs-panel .box svg.i, .gs-panel:focus-within .box svg.i { width: 20px; height: 20px; color: var(--ink3); }
.gs-panel input { height: 54px; font-size: 16px; color: var(--ink); }
.gs-panel input::placeholder, .gs-panel:focus-within input::placeholder { color: var(--ink4); }
.gs-esc { flex: none; }
.gs-pop { position: static; width: auto; max-width: none; max-height: min(52vh, 460px); border: 0; border-radius: 0; box-shadow: none; padding: 6px; animation: none; background: none; }
.gs-pop .gh { padding: 10px 10px 4px; font-weight: 500; color: var(--ink4); }
.gs-pop a { min-height: 40px; padding: 4px 10px; border-radius: var(--r); }
.gs-pop a:hover, .gs-pop a.on { background: var(--hover2); color: var(--ink); }
.gs-pop a.on svg.i { color: var(--primary-fill); }
body.gs-open #scrim { opacity: 1; pointer-events: auto; z-index: 65; }

/* ------------------------------------------------------------------ 页面：页名大一号，卡片 12 圆角，细框加很淡的阴影；小节标题不要竖条 */
.pg-t { margin: 4px 2px 18px; font-size: 22px; line-height: 30px; font-weight: 650; letter-spacing: -.01em; }
.page-head { min-height: 64px; padding: 14px 20px; margin-bottom: 16px; border-radius: var(--r-lg); border-color: var(--border); box-shadow: var(--sh-xs); }
.page-head h1 { font-size: 18px; line-height: 26px; }
.card { border-radius: var(--r-lg); border-color: var(--border); box-shadow: var(--sh-xs); margin-bottom: 16px; }
.card-h { min-height: 56px; padding: 14px 20px 8px; }
.card-h h2 { font-size: 15px; }
.card-h h2::before, .sec-h::before, .tbl tr.grp td b::before { display: none; }
.card-b { padding: 0 20px 20px; }
.card-b.pt { padding-top: 20px; }
.grid2, .grid-main, .stack { gap: 16px; }
.sec-h { margin: 22px 0 10px; font-size: 13px; font-weight: 600; color: var(--ink); }
.page > .tabs { border-radius: var(--r-lg); padding: 0 12px; box-shadow: var(--sh-xs); }
.tabs { border-bottom-color: var(--border); }
.tabs a, .tabs button { color: var(--ink3); font-weight: 500; padding: 0 14px; }
.tabs a:hover, .tabs button:hover { color: var(--ink); }
.tabs .on { color: var(--ink); font-weight: 600; }
.tabs .on::after, .tab-ink { background: var(--ink); height: 2px; border-radius: 2px; }
.progress.on { background: var(--primary-bg); }

/* ------------------------------------------------------------------ 按钮：8 圆角；主按钮黑底白字（深色下白底黑字）；普通按钮白底细框带一点阴影；文字按钮无框 */
.btn { height: 34px; padding: 0 14px; border-radius: var(--r); font-weight: 500; color: var(--ink2); gap: 6px; }
.btn:hover { color: var(--ink); }
.btn.pri { background: var(--btn-pri); border-color: var(--btn-pri); color: var(--on-btn-pri); box-shadow: var(--sh-xs); }
.btn.pri:hover { background: var(--btn-pri-hover); border-color: var(--btn-pri-hover); color: var(--on-btn-pri); }
.btn.pri:active { background: var(--btn-pri-active); border-color: var(--btn-pri-active); }
.btn.out { background: var(--card); border-color: var(--input-border); color: var(--ink2); box-shadow: var(--sh-xs); }
.btn.out:hover { border-color: var(--input-border); background: var(--th-bg); color: var(--ink); }
.btn.danger, .btn.out.danger { color: var(--danger); }
.btn.pri.danger { background: var(--danger); border-color: var(--danger); color: #fff; }
.btn[disabled], .btn.dis { color: var(--ink4); }
.btn.out[disabled], .btn.out.dis, .btn.pri[disabled] { background: var(--th-bg); border-color: var(--border); color: var(--ink4); box-shadow: none; }
/* 删除这类危险操作不用红框：红字无框，悬停一层浅红底。写在灰着的写法后面，照旧盖住它 */
.btn.out.danger { background: none; border-color: transparent; box-shadow: none; color: var(--danger); }
.btn.out.danger:hover { background: var(--red-bg); border-color: transparent; color: var(--danger); }
.btn.sm { height: 28px; padding: 0 10px; font-size: 13px; border-radius: 7px; }
.icon-btn { border-radius: var(--r); color: var(--ink3); }
.icon-btn:hover { background: var(--hover2); color: var(--ink); }
.icon-btn.on { background: var(--primary-bg); color: var(--primary); }
/* 开关：打开是帆软蓝；关着浅色下灰，深色下暗灰，不比输入框亮 */
.switch input:checked { background: var(--primary-fill); }
:root[data-theme="dark"] .switch input:not(:checked) { background: #333741; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .switch input:not(:checked) { background: #333741; } }

/* 标签：6 圆角，浅底深字，前面一个小圆点；失败也是浅红底红字，不用实心块 */
.chip, .tag { height: 22px; padding: 0 8px; border-radius: var(--r-sm); font-weight: 500; line-height: 22px; }
.chip.ok { color: var(--success-ink); background: var(--success-bg); }
.chip.warn, .chip.info, .tag.warn { color: var(--orange-ink); background: var(--orange-bg); }
.chip.error { color: var(--red-ink); background: var(--red-bg); }
.chip.off, .tag { color: var(--ink3); background: var(--grey-bg); }
.chip.run { color: var(--sky-ink); background: var(--sky-bg); }
.chip::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; margin-right: 6px; flex: none; }
.chip.off::before { background: var(--ink4); }
.tag.me, .chip.pub, .tag.pub { color: var(--primary); background: var(--primary-bg); }

/* 输入框与下拉：34 高，8 圆角；聚焦时框变强调色加一圈淡光 */
.query .qi input, .query .qi select, .search, .toolbar select, .fld input:not([type=checkbox]):not([type=radio]), .fld select, .fld textarea, .form input:not([type=checkbox]):not([type=radio]), .form select, .form textarea {
  border-radius: var(--r); border-color: var(--input-border); box-shadow: var(--sh-xs);
}
.query .qi input, .query .qi select, .search, .toolbar select { height: 34px; }
.query .qi input:focus, .query .qi select:focus, .search:focus-within { border-color: var(--primary); box-shadow: 0 0 0 4px var(--focus-ring); }
.query { padding: 14px 20px; gap: 12px 20px; }
.query .qi > span { color: var(--ink3); font-size: 13px; }

/* 表格：表头不铺灰底，小一号灰字，只留下面一条细线；行高 52，行线浅，悬停浅灰；链接用深色字，强调色只留给悬停 */
.tbl th, .tbl td { height: 52px; border-bottom-color: var(--border); }
.tbl th { background: var(--card); color: var(--ink3); font-weight: 500; font-size: 12.5px; height: 40px; }
.tbl th:first-child, .tbl td:first-child { padding-left: 20px; }
.tbl th:last-child, .tbl td:last-child { padding-right: 20px; }
.tbl .lnk { color: var(--ink); font-weight: 500; }
.tbl .lnk:hover { color: var(--primary); }
/* 窄栏里的小表格去掉外框 */
.tbl.mini { border: 0; border-radius: 0; }
.tbl.mini th { border-top: 0; }
/* 行操作：删除平时灰字，悬停才变红 */
.ops .op { color: var(--ink2); font-weight: 500; }
.ops .op:hover { color: var(--primary); }
.ops .op + .op::before { background: var(--border); }
.ops .op.danger { color: var(--ink3); }
.ops .op.danger:hover { color: var(--danger); }
.tbl-foot { border-top-color: var(--border); padding: 10px 20px; }
/* 分页：只有一页时不画页码；当前页浅灰底 */
.pager button { border-radius: var(--r); border-color: var(--border); }
.pager button.on { border-color: transparent; background: var(--grey-bg); color: var(--ink); }
.card-tb { padding: 14px 20px; }

/* 分段切换：浅灰底轨道，选中的一块白底浮起，照 macOS 与今年 AI 产品的写法。
   深色下轨道（--grey-bg）比卡片亮一档，选中的一块用卡片色就陷下去了，看着偏暗（D2 留下的，11-02 E3）：比轨道再亮一档，不靠阴影（深色下看不出），
   同合并新版框里的那一个（appai.css）；工具条里白底细框的那一个另有写法（.qbar .seg）。项目文件与节点大框里同样写法的两处（对比与全文，表格与数据）一起 */
.seg { border: 0; border-radius: var(--r); background: var(--grey-bg); padding: 3px; gap: 2px; --seg-on: var(--card); --seg-on-sh: var(--sh-sm); }
.seg button, .seg a { height: 28px; padding: 0 12px; border-radius: 6px; background: none; color: var(--ink3); font-weight: 500; }
.seg button + button, .seg a + a { border-left: 0; }
.seg button:hover, .seg a:hover { color: var(--ink); }
.seg .on, .seg .on:hover { background: var(--seg-on); color: var(--ink); box-shadow: var(--seg-on-sh); }
.seg svg.i { width: 16px; height: 16px; }
:root[data-theme="dark"] .seg { --seg-on: color-mix(in srgb, var(--ink) 18%, var(--card)); --seg-on-sh: none; }
:root[data-theme="dark"] :is(.pf-seg, .afe-fx-seg) button.on { background: color-mix(in srgb, var(--ink) 18%, var(--card)); box-shadow: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .seg { --seg-on: color-mix(in srgb, var(--ink) 18%, var(--card)); --seg-on-sh: none; }
  :root:not([data-theme="light"]) :is(.pf-seg, .afe-fx-seg) button.on { background: color-mix(in srgb, var(--ink) 18%, var(--card)); box-shadow: none; }
}

/* 菜单，抽屉，对话框，提示：圆角放大，阴影淡而散 */
#menu .mn, .menu-pop, #menu > div { border-radius: var(--r-lg); }
#menu { --menu-r: 12px; }
.sheet { border-radius: var(--r-xl) 0 0 var(--r-xl); box-shadow: var(--sh-xl); }
#dialog .dlg, .dlg { border-radius: var(--r-xl); box-shadow: var(--sh-xl); }
#toast > * { border-radius: var(--r-lg); box-shadow: var(--pop-shadow); }

/* ------------------------------------------------------------------ 列表页筛选：一行工具条，不要卡片；搜索框带放大镜，下拉是小号的，字写在框里；右边放这页的按钮 */
.query.qbar { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; padding: 0; margin: 0 0 16px; }
.qbar .qi { gap: 0; }
.qbar .qtxt { position: relative; display: flex; align-items: center; }
.qbar .qtxt svg.i { position: absolute; left: 10px; width: 16px; height: 16px; color: var(--ink4); pointer-events: none; }
.qbar .qtxt input { width: 240px; height: 34px; padding: 0 12px 0 32px; border: 1px solid var(--border); border-radius: var(--r); background: var(--card); box-shadow: var(--sh-xs); outline: 0; color: var(--ink); }
.qbar .qtxt input::placeholder { color: var(--ink4); }
.qbar .qtxt input:focus { border-color: var(--primary); box-shadow: 0 0 0 4px var(--focus-ring); }
.qbar .qsel { position: relative; display: flex; align-items: center; height: 34px; padding: 0 0 0 10px; border: 1px solid var(--border); border-radius: var(--r); background: var(--card); box-shadow: var(--sh-xs); }
.qbar .qsel:hover { border-color: var(--input-border); }
.qbar .qsel:focus-within { border-color: var(--primary); box-shadow: 0 0 0 4px var(--focus-ring); }
.qbar .qsel > span { color: var(--ink3); font-size: 13px; white-space: nowrap; }
.qbar .qsel > span::after { content: "："; }
.qbar .qsel select { width: auto; max-width: 160px; height: 32px; padding: 0 26px 0 0; border: 0; background: transparent; box-shadow: none; color: var(--ink); font-weight: 500; font-size: 13px; outline: 0; cursor: pointer; }
.qbar .qsel select:focus { box-shadow: none; }
.qbar .qa { margin-left: 0; }
.qbar .qrst { color: var(--ink3); border: 0; background: none; }
.qbar .qrst:hover { color: var(--ink); background: var(--hover2); }
.qbar .qx { margin-left: auto; display: flex; align-items: center; gap: 10px; }
/* 工具条里的卡片与列表切换和输入框一样白底细框，和新建按钮一样高；选中的一块浅色下浅灰，深色下亮一档 */
.qbar .seg { height: 34px; box-sizing: border-box; align-items: center; padding: 2px; background: var(--card); border: 1px solid var(--border); box-shadow: var(--sh-xs); }
.qbar .seg button, .qbar .seg a { height: 28px; }
.qbar .seg .on, .qbar .seg .on:hover { background: color-mix(in srgb, var(--ink) 10%, var(--card)); box-shadow: none; }

/* ------------------------------------------------------------------ 工作流：卡片看法。上半小画布，节点按用途上色；下半名字，说明，节点数，触发，上次运行 */
.wf-box { background: none; border: 0; box-shadow: none; }
.wf-box > .card-tb { padding: 0 0 14px; min-height: 0; }
.wf-view { margin-left: auto; }
.wf-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 16px; }
.wf-grid > .empty { grid-column: 1 / -1; background: var(--card); border: 1px dashed var(--input-border); border-radius: var(--r-lg); }
.wf-box .tbl-wrap { background: var(--card); border: 1px solid var(--border); border-radius: var(--r-lg); box-shadow: var(--sh-xs); }
.wf-box .tbl-foot { border-top: 0; padding: 14px 0 0; }
.wf-box > .tbl-foot { border: 0; }
.wf-card { display: flex; flex-direction: column; min-width: 0; background: var(--card); border: 1px solid var(--border); border-radius: var(--r-lg); box-shadow: var(--sh-xs); overflow: hidden; cursor: pointer;
  transition: box-shadow .2s var(--ease-out), border-color .2s ease, transform .2s var(--ease-out); }
.wf-card:hover { box-shadow: var(--sh-md); border-color: var(--input-border); transform: translateY(-1px); }
.wf-cv { height: 148px; background-color: var(--cv-bg); background-image: radial-gradient(var(--cv-dot) 1px, transparent 1.2px); background-size: 14px 14px; border-bottom: 1px solid var(--border); display: flex; align-items: stretch; }
.wf-thumb { width: 100%; height: 100%; display: block; }
.wf-thumb.empty { display: flex; align-items: center; justify-content: center; color: var(--ink4); font-size: 13px; }
.wf-thumb .e path { fill: none; stroke: var(--ink4); stroke-width: 5; opacity: .7; }
.wf-thumb g > rect:first-child { fill: var(--card); stroke: var(--border); stroke-width: 3; }
.wf-thumb .ln, .wf-thumb .ln2 { fill: var(--grey-bg); stroke: none; }
.wf-thumb .ic { fill: var(--ink4); }
.wf-thumb .r-read .ic { fill: var(--sky); } .wf-thumb .r-transform .ic { fill: var(--amber); } .wf-thumb .r-ai .ic { fill: var(--violet); } .wf-thumb .r-write .ic { fill: var(--green); }
.wf-card:hover .wf-thumb .e path { stroke: var(--primary); opacity: .55; }
.wf-cb { display: flex; flex-direction: column; gap: 6px; padding: 14px 16px 14px; min-width: 0; }
.wf-ct { display: flex; align-items: center; gap: 8px; min-width: 0; }
.wf-ct .lnk { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink); font-weight: 600; font-size: 15px; }
.wf-ops { display: inline-flex; align-items: center; gap: 2px; opacity: 0; transition: opacity .15s ease; }
.wf-card:hover .wf-ops, .wf-card:focus-within .wf-ops { opacity: 1; }
.wf-ops .op { height: 26px; padding: 0 8px; border-radius: 6px; color: var(--ink2); font-size: 13px; }
.wf-ops .op:hover { background: var(--hover2); color: var(--ink); }
.wf-ops .op + .op::before { display: none; }
/* 说明两行；没写说明时是按执行先后串起来的节点名，字更淡 */
.wf-cd { margin: 0; color: var(--ink3); font-size: 13px; line-height: 20px; height: 40px; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.wf-cd.none { color: var(--ink4); }
.wf-cm { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 12px; margin-top: 4px; font-size: 12.5px; color: var(--ink3); }
/* 任务同步那个工作流的“功能页”：靠右，跟左边的触发方式分开，悬停一块浅蓝底，跟点卡片进画布分清 */
.wf-cm .wf-page { display: inline-flex; align-items: center; gap: 2px; margin-left: auto; height: 26px; padding: 0 6px 0 10px; border-radius: 6px; background: var(--primary-bg); color: var(--primary); font-weight: 500; text-decoration: none; transition: background .15s ease; }
.wf-cm .wf-page svg { width: 16px; height: 16px; }
.wf-cm .wf-page:hover { background: color-mix(in srgb, var(--primary) 18%, transparent); }
.wf-m { display: inline-flex; align-items: center; gap: 4px; white-space: nowrap; }
.wf-m svg.i { width: 14px; height: 14px; color: var(--ink4); }
.wf-dot { width: 8px; height: 8px; border-radius: 2px; margin-right: -8px; }
.wf-dot.r-read { background: var(--sky); } .wf-dot.r-transform { background: var(--amber); } .wf-dot.r-ai { background: var(--violet); } .wf-dot.r-write { background: var(--green); }
.wf-last { margin-left: auto; display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.wf-last:empty { display: none; }

/* ------------------------------------------------------------------ 门户：整页点阵画布，演示的工作流在上面跑，一句话输入框和示例说法浮在下面 */
body:has(.page.pg-portal) { background-color: var(--cv-bg); background-image: radial-gradient(var(--cv-dot) 1px, transparent 1.2px); background-size: 20px 20px; }
.page.pg-portal { background: none; padding: 0; }
.page.pg-portal .cx-hero { height: calc(100vh - var(--hd-h)); height: calc(100dvh - var(--hd-h)); gap: 0; }
.page.pg-portal .dm { background: none; border: 0; border-radius: 0; box-shadow: none; }
.page.pg-portal .cx-chat { padding: 12px 24px 24px; }
/* 角上的示例与运行进度做成白底小块，像画布上的浮层 */
.dm-hd { pointer-events: none; height: 26px; top: 16px; left: 16px; right: 16px; }
.dm-tag, .dm-st:not(:empty) { height: 26px; padding: 0 10px; display: inline-flex; align-items: center; border: 1px solid var(--border); border-radius: var(--r); background: var(--card); box-shadow: var(--sh-xs); color: var(--ink2); font-size: 12px; }
.dm-n { border-radius: var(--r-lg); border-color: var(--border); box-shadow: var(--sh-sm); height: 56px; }
/* 正在跑的节点与线用运行中的天蓝，和编辑页运行时，运行记录的“运行中”一个颜色；帆软蓝整圈只留给选中 */
.dm-n.run { border-color: var(--sky); box-shadow: 0 0 0 1px var(--sky); }
.dm-e .ln { stroke: var(--ink4); }
.dm-e.hot .ln { stroke: var(--sky); }
.dm-e.hot .ar { fill: var(--sky); }
.dm-dot { fill: var(--sky); stroke: var(--sky-bg); }
.dm-pic { width: 30px; height: 30px; border-radius: 8px; background: var(--indigo); }
.dm-pic.violet { background: var(--violet); } .dm-pic.blue { background: var(--blue); } .dm-pic.teal { background: var(--teal); } .dm-pic.green { background: var(--green); }
.dm-pic.sky { background: var(--sky); } .dm-pic.amber { background: var(--amber); } .dm-pic.indigo { background: var(--indigo); } .dm-pic.rose { background: var(--rose); }
/* 开始节点的图标块：深色下不跟着字色变白 */
.dm-pic.pri { background: #101828; color: #fff; }
:root[data-theme="dark"] .dm-pic.pri { background: #333741; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .dm-pic.pri { background: #333741; } }
.dm-out { border-radius: var(--r); box-shadow: var(--sh-xs); }
/* 输入框：表单是外层，里面上面大输入框，下面一排示例说法，居中，照 v0 */
.cx-f { width: 100%; max-width: 820px; display: flex; flex-direction: column; align-items: stretch; gap: 12px; }
.cx-f .cx-box { width: 100%; }
.cx-f.sent .cx-box { animation: cx-sent .6s ease; }
.cx-chat .cx-box { max-width: 820px; }
.cx-box { border-radius: var(--r-2xl); border-color: var(--border); padding: 16px 14px 12px 20px; box-shadow: var(--sh-md); }
.cx-box textarea, .cx-ghost { font-size: 16px; line-height: 26px; }
.cx-grow { flex: 1; }
.cx-bar .ask-ex .ex { border-radius: var(--r); border: 1px solid var(--border); background: var(--card); color: var(--ink2); }
.cx-bar .ask-ex .ex:hover { color: var(--ink); background: var(--th-bg); }
.cx-bar .ask-ex .ex.on { color: var(--primary); background: var(--primary-bg); border-color: transparent; }
.cx-bar .btn { border-radius: 10px; }
.cx-ask:not(.pri) { background: var(--hover2); color: var(--ink); }
.cx-ask:not(.pri)[disabled] { color: var(--ink4); }
/* 示例说法：8 圆角小块；亮着的那一句带一圈浅蓝细框，看得出是点得动的 */
.cx-exs { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; min-height: 30px; }
.cx-exs .ex { height: 30px; max-width: 240px; padding: 0 12px; border: 1px solid var(--border); border-radius: var(--r); background: var(--card); color: var(--ink2); font-size: 13px; cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; box-shadow: var(--sh-xs); transition: color var(--t-fast) ease, background-color .2s ease, border-color .2s ease; }
.cx-exs .ex:hover { color: var(--ink); border-color: var(--input-border); }
.cx-exs .ex.on { color: var(--primary); background: var(--primary-bg); border-color: color-mix(in srgb, var(--primary) 40%, transparent); box-shadow: none; }

/* ------------------------------------------------------------------ AI 助手：浮在别的页面上是右侧面板，停在编辑页是一块圆角卡片 */
.assist { border-left: 1px solid var(--border); background: var(--card); }
.assist.docked { border-color: var(--border); border-radius: var(--r-lg); box-shadow: var(--sh-xs); }
/* 发送键：黑底白箭头，深色下白底黑箭头；没字时灰 */
.as-send { color: var(--on-btn-pri); }
.as-send:hover { background: var(--btn-pri-hover); }
.as-send:disabled, .as-send:disabled:hover { background: var(--grey-bg); color: var(--ink4); }
/* AI 的头像：外壳不用彩色，黑底白星，深色下白底黑星 */
.as-av { background: var(--ink); color: var(--card); }
/* 选中的节点：点得动的块，带一圈浅蓝细框 */
.as-ctx { border: 1px solid color-mix(in srgb, var(--primary) 40%, transparent); background: var(--primary-bg); color: var(--primary); border-radius: var(--r-sm); }
/* 照 Know-how 生成：空画布时输入框左下一个浅灰小键“Know-how”，点开选库；选了库换成和选中节点一样的浅蓝块“照 库名”，带小叉 */
.as-kh { flex: 0 1 auto; min-width: 0; display: inline-flex; align-items: center; height: 26px; border: 1px solid transparent; border-radius: var(--r-sm); background: var(--hover); color: var(--ink2); font-size: 12.5px;
  animation: pop-in .2s var(--ease-out) both; transform-origin: left center; transition: background-color .12s, color .12s; }
.as-kh[hidden] { display: none; }
.as-kh-b { min-width: 0; height: 100%; display: inline-flex; align-items: center; gap: 5px; padding: 0 9px 0 8px; border: 0; border-radius: inherit; background: none; color: inherit; font: inherit; cursor: pointer; }
.as-kh-b span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.as-kh-b svg.i { flex: none; width: 15px; height: 15px; color: var(--ink3); }
.as-kh-b:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; }
.as-kh:not(.on):hover { background: var(--hover2); color: var(--ink); }
.as-kh:not(.on):hover .as-kh-b svg.i { color: var(--ink2); }
.as-kh.on { padding-right: 6px; border-color: color-mix(in srgb, var(--primary) 40%, transparent); background: var(--primary-bg); color: var(--primary); }
.as-kh.on .as-kh-b { padding-right: 2px; }
.as-kh.on .as-kh-b svg.i { color: var(--primary); }
/* 停在编辑页还没说话：消息区空着；示例说法在输入框上面一排，8 圆角小块 */
.as-exb { border-radius: var(--r); box-shadow: var(--sh-xs); }
.as-exb:hover { color: var(--ink); border-color: var(--input-border); background: var(--th-bg); }
/* 转圈的底环深色下也看得见 */
.spin-i { border-color: var(--input-border); border-right-color: var(--primary); }

/* 大输入框：聚焦时框线换帆软蓝，不加外圈；里面灰着的键没有框，一层很淡的底，字压暗 */
.cx-box:focus-within, .as-box:focus-within { border-color: var(--primary); box-shadow: var(--sh-md); }
.as-box:focus-within { box-shadow: var(--sh-xs); }
.cx-box .btn[disabled] { background: var(--hover); border-color: transparent; box-shadow: none; color: var(--ink4); }
/* 深色下大输入框高一档，框线亮一点，不和底色混在一起 */
:root[data-theme="dark"] :is(.cx-box, .as-box) { background: var(--raised); border-color: var(--input-border); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) :is(.cx-box, .as-box) { background: var(--raised); border-color: var(--input-border); } }
/* 上面两条压过了聚焦时的帆软蓝，深色下聚焦照样换框线（11-01 审图看出来的） */
:root[data-theme="dark"] :is(.cx-box, .as-box):focus-within { border-color: var(--primary); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) :is(.cx-box, .as-box):focus-within { border-color: var(--primary); } }

/* ------------------------------------------------------------------ 窄屏：左栏成抽屉，回到一条白色顶栏 */
@media (max-width: 1023px) {
  :root, body.side-mini { --sd-w: 0px; --hd-h: 52px; }
  header.top { display: flex; background: var(--card); color: var(--ink); border-bottom: 1px solid var(--border); }
  header.top .brand { color: var(--ink); font-size: 15px; }
  header.top .logo .la, header.top .logo .lf { stroke: var(--primary-fill); } header.top .logo .lf { fill: var(--primary-fill); stroke: none; } header.top .logo .lb { stroke: var(--sky); }
  .hd-btn, .hd-user { color: var(--ink2); }
  @media (hover: hover) { .hd-btn:hover, .hd-user:hover { background: var(--hover2); color: var(--ink); } }
  .hd-btn.on, .hd-user.on { background: var(--hover2); color: var(--ink); }
  main { padding-top: var(--hd-h); }
  .side { top: var(--hd-h); width: 264px; background: var(--card); padding: 10px; }
  .sd-top { display: none; }
  .gs-panel { top: calc(var(--hd-h) + 12px); }
  .page { padding: 16px 16px 32px; }
}
@media (max-width: 640px) {
  .wf-grid { grid-template-columns: minmax(0, 1fr); }
  .pg-t { font-size: 20px; margin-bottom: 12px; }
}

/* ------------------------------------------------------------------ 一句话新建的弹框：输入框和门户同一个样子，16 圆角，聚焦框线换帆软蓝；示例说法 8 圆角小块 */
.ask textarea { min-height: 96px; padding: 12px 16px; border: 1px solid var(--border); border-radius: var(--r-xl); font-size: 15px; line-height: 24px; box-shadow: var(--sh-xs); resize: none; }
.ask textarea::placeholder { color: var(--ink4); }
.ask textarea:hover { border-color: var(--input-border); }
.ask textarea:focus { border-color: var(--primary); box-shadow: var(--sh-md); }
:root[data-theme="dark"] .ask textarea { background: var(--raised); border-color: var(--input-border); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .ask textarea { background: var(--raised); border-color: var(--input-border); } }
.ask-ex .ex { border-radius: var(--r); box-shadow: var(--sh-xs); }
.ask-ex .ex:hover { color: var(--ink); border-color: var(--input-border); background: var(--th-bg); }

/* ------------------------------------------------------------------ 登录页：整页点阵画布，中间一张 16 圆角的卡片；左半写产品，右半登录。
 * 登录页是平台的入口，跟帆软的品牌走蓝色（用户 10-26 定）：左半帆软蓝底白字，铺一层白点阵，像一块蓝色的画布；登录键也是帆软蓝，深色下一样。
 * 站内的主按钮照旧是黑色。统一登录那一页的主色由 deploy/sso_rename.py 设成同一个蓝 */
.login { background: var(--cv-bg); background-image: radial-gradient(var(--cv-dot) 1px, transparent 1.2px); background-size: 20px 20px; }
.login .lg-top { color: var(--ink); }
.login .logo .la, .login .logo .lf { stroke: var(--primary-fill); } .login .logo .lf { fill: var(--primary-fill); stroke: none; } .login .logo .lb { stroke: var(--sky); }
.login .lg-card, .login .box { border: 1px solid var(--border); border-radius: var(--r-xl); box-shadow: var(--sh-xl); }
/* 卡片的细框只画在右半：左半蓝块一直铺到卡片边上，不裹一圈灰线；窄屏不画左半时右半四边都有框 */
.login .lg-card { border: 0; }
.login .lg-r { border: 1px solid var(--border); border-left: 0; border-radius: 0 var(--r-xl) var(--r-xl) 0; }
@media (max-width: 1023px) { .login .lg-r { border-left: 1px solid var(--border); border-radius: var(--r-xl); } }
/* 只有统一登录一个键时，右半上下居中，和左半的产品名对齐；有表单时照旧靠上，出错提示冒出来不带着整块往上跳 */
.login .lg-r:not(:has(.form)) { justify-content: center; }
.login .lg-l { background-color: #3685F2; background-image: radial-gradient(rgba(255, 255, 255, .22) 1px, transparent 1.2px); background-size: 20px 20px; color: #fff; }
.login .lg-l .lg-zh, .login .lg-l p { opacity: 1; }
.login .btn.pri:not([disabled]) { background: #3685F2; border-color: #3685F2; color: #fff; }
.login .btn.pri:not([disabled]):hover { background: #2D75DC; border-color: #2D75DC; color: #fff; }
.login .btn.pri:not([disabled]):active { background: #2563C2; border-color: #2563C2; }
.login .lg-r h2 { font-size: 20px; font-weight: 650; }
.login .fld input[type=text], .login .fld input[type=password] { border-radius: var(--r); }
.login .form-foot .btn, .login .sso { border-radius: var(--r); }

/* 手机宽的组件库只剩名字与操作两列：名字一列拿操作以外的全部宽度，不照桌面的 28%，组件名不被挤成两个字 */
@media (max-width: 640px) {
  #cp-tbl table { table-layout: auto; }
  #cp-tbl col { width: auto !important; }
  #cp-tbl td:first-child { width: 100%; }
  /* 工具条的下拉占满一行时，箭头跟到右边；右边那组键占满一行，切换在左，新建在右。
     下拉不宽过一行：选项里有很长的名字（工作流名）时原先照最长的那一项撑开，整页横向滚动 */
  .qbar .qsel { max-width: 100%; }
  .qbar .qsel select { flex: 1; max-width: none; min-width: 0; }
  .qbar .qx { width: 100%; justify-content: space-between; }
}
/* 组件库里组件的英文名不从中间断开，放不下用省略号 */
#cp-tbl .cp-t .mono { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* 左栏从 200 宽到 248，内容区窄了 48：表格收起次要列的宽度门槛跟着往上挪 48 */
@media (max-width: 1327px) {
  .tbl col.c-lg, .tbl th.c-lg, .tbl td.c-lg { display: none; }
}
/* 手机宽：表格底下的条数与页码收紧，页码一排放得下 */
@media (max-width: 640px) {
  .tbl-foot { padding: 10px 12px; }
  .pager { gap: 4px; }
  .pager button { min-width: 28px; height: 28px; padding: 0 4px; }
}

/* 套件（docs/DESIGN.md 4.7）：运行详情里套件节点能展开里面的节点；组件库详情列由哪几个组件组成 */
.rd-sub { margin-left: 6px; padding: 0; border: 0; background: none; color: var(--primary); font-size: 12px; cursor: pointer; white-space: nowrap; }
/* 节点一列窄时（右边开着 AI 助手，或 1024 宽）：名字放不下只截名字，“展开里面几个组件”挪到下一行，再窄就折行，一直露全点得到；
   原来名字与它挤在一行一起截掉，点不到 */
.tbl td.two > div.rd-t { display: flex; flex-wrap: wrap; align-items: baseline; column-gap: 6px; min-width: 0; }
/* 节点名放不下时折成两行，再长才省略（原来一行省略，窄了只剩两个字，又没有悬停全名） */
.tbl td.two > div.rd-t > .lnk { min-width: 0; max-width: 100%; overflow: hidden; white-space: normal; overflow-wrap: anywhere; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; }
/* 字号照 .rd-sub 的 12px：后面 .lnk-btn 的 font: inherit 同一级排在后面，原来把它盖成 14px，窄了一行摆不下 */
.tbl td.two > div.rd-t > .rd-sub { flex: none; max-width: 100%; margin-left: 0; white-space: normal; text-align: left; font-size: 12px; }
.rd-sub:hover { text-decoration: underline; }
tr.rd-kid td.two { position: relative; padding-left: calc(12px + var(--rd-d, 1) * 18px); }
/* 里面的节点左边一道竖线连到套件节点那一行，看得出归它管 */
tr.rd-kid td.two::before { content: ""; position: absolute; top: 0; bottom: 0; left: calc(12px + (var(--rd-d, 1) - 1) * 18px + 6px); border-left: 2px solid var(--line2, #E8EAED); }
tr.rd-kid td.two .lnk { color: var(--ink2); }
tr.rd-kid { background: color-mix(in srgb, var(--primary-bg) 35%, transparent); }
.cp-suite { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; padding: 4px 0 8px; }
.cp-suite ol { margin: 0; padding-left: 20px; font-size: 13px; line-height: 24px; color: var(--ink2); }
.cp-suite li .muted { margin-left: 8px; font-size: 12px; }
.cp-suite .btn { flex: none; }

/* ================================================================== Know-how 的 Wiki 与飞书来源（10-28，kwiki）
 * Wiki 页签左边目录，右边一页；正文照平台排的 Markdown 摆：小标题，编号与圆点条目，表格，名词与口径是两列表。
 * 左栏只列页名与状态，上面一个找页面的框，手机宽收成一条，点开才展开。飞书来源页签一张卡片：上面添加来源，下面列来源，点开看各篇。 */
.kw { display: grid; grid-template-columns: 280px minmax(0, 1fr); gap: 16px; align-items: start; }
.kw-nav { position: sticky; top: 12px; max-height: calc(100vh - 160px); overflow-y: auto; padding: 8px; scrollbar-width: thin; }
.kw-mt { display: none; }
.kw-q { display: flex; align-items: center; gap: 6px; height: 34px; margin: 2px 2px 0; padding: 0 10px; border: 1px solid var(--input-border); border-radius: var(--r);
  background: var(--card); box-shadow: var(--sh-xs); transition: border-color var(--t-fast, .12s) ease; }
.kw-q:focus-within { border-color: var(--primary); box-shadow: 0 0 0 4px var(--focus-ring); }
.kw-q svg.i { width: 16px; height: 16px; color: var(--ink3); flex: none; }
.kw-q input { flex: 1; min-width: 0; height: 32px; padding: 0; border: 0; outline: 0; background: none; color: var(--ink); }
.kw-q input::placeholder { color: var(--ink4); }
/* 目录上面只在找页面与有待合并时写一行，没有这一行时清单离搜索框也留一点 */
#kw-nl { margin-top: 6px; }
.kw-nh { padding: 4px 10px; font-size: 12.5px; line-height: 18px; }
.kw-list { display: flex; flex-direction: column; }
.kw-none { padding: 8px 10px; font-size: 13px; }
.kw-it { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; width: 100%; min-height: 36px; padding: 7px 10px; border: 0; border-radius: var(--r); background: none;
  text-align: left; color: var(--ink); cursor: pointer; transition: background-color var(--t-fast, .12s) ease; }
.kw-it:hover { background: var(--hover2, var(--grey-bg)); }
.kw-it.on { background: var(--primary-bg); }
.kw-it.on .t { color: var(--primary); }
.kw-it .t { flex: 1 1 auto; min-width: 0; font-weight: 500; font-size: 13.5px; line-height: 20px; overflow-wrap: anywhere; }
.kw-it.idx { margin-bottom: 4px; border-bottom: 1px solid var(--divider); border-radius: var(--r) var(--r) 0 0; font-weight: 600; }
.kw-it.idx .t { font-weight: 600; }
.kw-it.gone .t { color: var(--ink4); }
.kw-it .chip { flex: none; height: 20px; line-height: 20px; font-size: 12px; }
.kw-page { padding: 20px 24px 28px; min-width: 0; }
.kw-ph { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; padding-bottom: 12px; border-bottom: 1px solid var(--divider); }
.kw-ph h2 { flex: 1 1 auto; margin: 0; font-size: 20px; line-height: 28px; overflow-wrap: anywhere; }
.kw-pm { flex: 1 1 100%; order: 3; font-size: 12.5px; display: flex; flex-wrap: wrap; align-items: center; gap: 4px; }
.kw-pm a { display: inline-flex; align-items: center; gap: 3px; color: var(--primary); text-decoration: none; }
.kw-pm a svg.i { width: 14px; height: 14px; }
.kw-pm .dot { color: var(--ink4); margin: 0 2px; }
.kw-pm .kw-src { display: inline-flex; align-items: center; gap: 4px; white-space: nowrap; }
.kw-act { display: flex; flex-wrap: wrap; gap: 8px; }
.kw-pend { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; margin: 14px 0 0; padding: 10px 14px; border-radius: var(--r); background: var(--orange-bg); color: var(--orange-ink); }
.kw-pend.off { background: var(--grey-bg); color: var(--ink3); }
.kw-pend > svg.i { width: 18px; height: 18px; flex: none; }
.kw-pend .t { flex: 1; min-width: 200px; display: flex; flex-direction: column; line-height: 20px; }
.kw-pend .t span { font-size: 12.5px; opacity: .9; }
.kw-pend .ops { display: inline-flex; flex-wrap: wrap; gap: 8px; }
.kw-sum { margin: 16px 0 0; font-size: 15px; line-height: 24px; color: var(--ink); font-weight: 500; }
.kw-md { margin-top: 8px; color: var(--ink2); font-size: 14px; line-height: 24px; overflow-wrap: anywhere; }
.kw-md h2, .kw-md h3, .kw-md h4 { margin: 20px 0 6px; color: var(--ink); font-size: 15px; line-height: 24px; font-weight: 600; }
.kw-md h2 { font-size: 16px; }
.kw-md p { margin: 6px 0; }
.kw-md ol, .kw-md ul { margin: 6px 0; padding-left: 22px; }
.kw-md li { margin: 2px 0; }
.kw-md li::marker { color: var(--ink3); }
.kw-md a { color: var(--primary); text-decoration: none; }
.kw-md a:hover { text-decoration: underline; }
.kw-md code { padding: 1px 5px; border-radius: 4px; background: var(--grey-bg); font-size: 12.5px; }
.kw-idx li { margin: 4px 0; color: var(--ink3); }
.kw-idx a.kw-lnk { color: var(--ink); font-weight: 500; }
.kw-idx a.kw-lnk:hover { color: var(--primary); text-decoration: none; }
.kw-tw { margin: 8px 0; overflow-x: auto; border: 1px solid var(--border); border-radius: var(--r); }
.kw-tbl { width: 100%; border-collapse: collapse; font-size: 13px; }
.kw-tbl th, .kw-tbl td { padding: 6px 10px; border-bottom: 1px solid var(--divider); text-align: left; white-space: nowrap; }
.kw-tbl th { background: var(--th-bg, var(--grey-bg)); color: var(--ink2); font-weight: 600; }
.kw-tbl tr:last-child th, .kw-tbl tr:last-child td { border-bottom: 0; }
.kw-terms th { width: 28%; min-width: 120px; white-space: normal; vertical-align: top; color: var(--ink); }
.kw-terms td { white-space: normal; color: var(--ink2); }
.kw-load { display: flex; align-items: center; gap: 8px; padding: 16px; color: var(--ink3); }
.kw-load svg.i { width: 18px; height: 18px; }
.kw-empty { display: flex; flex-direction: column; align-items: center; gap: 12px; padding: 56px 24px; text-align: center; line-height: 22px; }
.kw-dh { margin-bottom: 10px; font-size: 13px; }
.kw-diff { max-height: 60vh; overflow: auto; border: 1px solid var(--border); border-radius: var(--r); font-size: 13.5px; line-height: 22px; }
.kw-diff > div { display: flex; gap: 8px; padding: 0 10px; white-space: pre-wrap; overflow-wrap: anywhere; }
.kw-diff > div i { flex: none; width: 10px; font-style: normal; color: var(--ink4); }
.kw-diff .add { background: var(--success-bg); color: var(--success-ink); }
.kw-diff .del { background: var(--red-bg); color: var(--red-ink); }
.kw-diff .same { color: var(--ink3); }
.kw-diff .g { color: var(--ink4); background: var(--grey-bg); min-height: 8px; font-size: 12px; }
.kw-diff b { color: var(--ink); }
.kw-diff mark { padding: 0 1px; border-radius: 3px; color: inherit; }
.kw-diff .del mark { background: color-mix(in srgb, var(--danger) 22%, transparent); text-decoration: line-through; }
.kw-diff .add mark { background: color-mix(in srgb, var(--success) 28%, transparent); }
.kw-nod { padding: 12px 0; }
.kw-vl .tbl { min-width: 800px; }
.kw-vl { overflow-x: auto; max-height: 60vh; }
.kw-vl .tbl th.ops, .kw-vl .tbl td.ops { text-align: left; }
.kw-vl .tbl td.ops > div { justify-content: flex-start; }
/* Wiki 页里的画板流程（10-28）：和别的小节一样平铺，头上“流程”与“照这份流程生成工作流”；下面一块点阵底的圆角框照画板的行列摆方框，
   箭头照流程图的走法连；再下面照箭头先后一步一条，左边一道细线串起来，起点是实心点。这一块窄于 560 只留一步一条（kf-f.narrow，脚本量） */
.kf { margin: 4px 0 8px; }
.kf-h { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px; margin: 20px 0 10px; }
.kw-md .kf-h h2 { flex: 1 1 auto; margin: 0; }
.kf-h .btn { flex: none; }
.kf-meta { flex: 1 1 100%; color: var(--ink3); font-size: 12.5px; line-height: 20px; }
/* 照这份流程生成的工作流（10-31）：标题下一行名字，点了打开 */
.kf-gens { flex: 1 1 100%; color: var(--ink3); font-size: 12.5px; line-height: 20px; }
.kf-meta .sep, .kf-fh .sep { margin: 0 6px; color: var(--ink4); }
.kf-orig { padding: 0; border: 0; background: none; color: var(--primary); font: inherit; cursor: pointer; }
.kf-orig:hover { text-decoration: underline; }
.kf-fh { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 8px; margin: 16px 0 8px; color: var(--ink); font-size: 14px; line-height: 22px; }
.kf-fh .faint { font-size: 12.5px; }
.kf-mapw { position: relative; overflow-x: auto; overflow-y: hidden; border: 1px solid var(--border); border-radius: var(--r-lg); background-color: var(--cv-bg);
  background-image: radial-gradient(var(--cv-dot) 1px, transparent 1.2px); background-size: 20px 20px; scrollbar-width: thin; }
.kf-mapz { position: relative; }
.kf-map { position: absolute; left: 0; top: 0; display: grid; grid-auto-rows: minmax(56px, auto); gap: 24px 40px; padding: 24px; box-sizing: border-box; transform-origin: 0 0; }
.kf-mapw.scroll { -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 40px), transparent); mask-image: linear-gradient(to right, #000 calc(100% - 40px), transparent); }
.kf-more { display: none; margin-top: 6px; text-align: right; color: var(--ink4); font-size: 12px; line-height: 18px; }
.kf-mapw.scroll + .kf-more { display: block; }
.kf-svg { position: absolute; left: 0; top: 0; pointer-events: none; overflow: visible; }
.kf-n { position: relative; z-index: 1; display: flex; align-items: center; gap: 8px; min-width: 0; min-height: 56px; padding: 8px 12px; border: 1px solid var(--border); border-radius: 10px;
  background: var(--raised); box-shadow: var(--sh-sm); color: var(--ink); font: inherit; text-align: left; cursor: pointer;
  transition: border-color var(--t-fast, .12s) ease, box-shadow var(--t-fast, .12s) ease, transform var(--t-fast, .12s) ease, opacity var(--t-fast, .12s) ease; }
.kf-n .tx { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.kf-n .t { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; font-size: 12.5px; line-height: 18px; font-weight: 600; overflow-wrap: anywhere; }
.kf-n .d { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; color: var(--ink3); font-size: 11.5px; line-height: 16px; }
.kf-n .dot { display: inline-block; width: 7px; height: 7px; margin: 0 6px 0 1px; border-radius: 50%; background: var(--ink2); vertical-align: 1px; }
.kf-n .pic { display: inline-flex; flex: none; align-self: flex-start; margin-top: 2px; color: var(--ink4); }
.kf-n .pic svg.i { width: 15px; height: 15px; }
.kf-n:hover, .kf-n.on { border-color: var(--primary); box-shadow: var(--sh-md); transform: translateY(-1px); }
.kf-n:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
.kf-n.dim { box-shadow: none; }
.kf-n.dim .tx, .kf-n.dim .pic { opacity: .38; }
.kf-e .ln { fill: none; stroke: var(--ink4); stroke-width: 1.5; stroke-linejoin: round; transition: stroke var(--t-fast, .12s) ease; }
.kf-e .ah { fill: var(--ink4); transition: fill var(--t-fast, .12s) ease; }
.kf-e.line .ln { stroke-dasharray: 4 3; }
.kf-e { transition: opacity var(--t-fast, .12s) ease; }
.kf-f.hl .kf-e { opacity: .2; }
.kf-f.hl .kf-e.on { opacity: 1; }
.kf-e.on .ln { stroke: var(--primary); stroke-width: 2; }
.kf-e.on .ah { fill: var(--primary); }
.kw-md .kf-steps { list-style: none; margin: 10px 0 0; padding: 0; }
.kw-md .kf-s { position: relative; margin: 0; padding: 8px 12px 12px 30px; border-radius: var(--r); }
.kf-s::before { content: ""; position: absolute; left: 10px; top: 15px; width: 10px; height: 10px; box-sizing: border-box; border-radius: 50%; border: 2px solid var(--ink4); background: var(--card); z-index: 1; }
.kf-s.src::before { border-color: var(--ink2); background: var(--ink2); }
.kf-s.flash { animation: kf-flash 2.4s ease; }
@keyframes kf-flash { 0%, 40% { background-color: var(--primary-bg); } 100% { background-color: transparent; } }
.kf-sh { display: flex; flex-wrap: wrap; align-items: center; gap: 2px 8px; color: var(--ink); font-size: 14px; line-height: 24px; }
.kf-sh b { font-weight: 600; overflow-wrap: anywhere; }
.kf-sh .chip { height: 20px; line-height: 20px; font-size: 12px; }
.kf-x { color: var(--ink2); font-size: 13.5px; line-height: 22px; white-space: pre-wrap; overflow-wrap: anywhere; }
.kf-pic { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; margin-top: 6px; }
.kf-img { display: block; max-width: 100%; padding: 0; border: 1px solid var(--border); border-radius: var(--r); background: #fff; overflow: hidden; cursor: zoom-in;
  transition: border-color var(--t-fast, .12s) ease, box-shadow var(--t-fast, .12s) ease; }
.kf-img img { display: block; max-width: 100%; max-height: 200px; }
.kf-img:hover { border-color: var(--primary); box-shadow: var(--sh-md); }
.kf-view { max-height: 60vh; overflow: auto; padding: 16px; border: 1px solid var(--border); border-radius: var(--r); background: #fff; scrollbar-gutter: stable; }
.kf-view img { display: block; max-width: 100%; margin: 0 auto; }
.kf-to { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.kf-go { display: inline-flex; align-items: center; gap: 4px; max-width: 100%; height: 24px; padding: 0 8px 0 6px; border: 1px solid var(--border); border-radius: var(--r-sm);
  background: var(--card); color: var(--ink2); font: inherit; font-size: 12.5px; line-height: 22px; cursor: pointer; transition: border-color var(--t-fast, .12s) ease, color var(--t-fast, .12s) ease; }
.kf-go svg.i { width: 13px; height: 13px; flex: none; color: var(--ink4); }
.kf-go > span { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.kf-go .lb { margin-left: 6px; color: var(--ink3); }
.kf-go:hover { border-color: var(--primary); color: var(--primary); }
.kf-go:hover svg.i { color: var(--primary); }
.kf-bad { display: flex; align-items: flex-start; gap: 8px; margin: 10px 0; padding: 10px 12px; border-radius: var(--r); background: var(--grey-bg); color: var(--ink3); font-size: 13px; line-height: 20px; }
.kf-bad svg.i { width: 16px; height: 16px; margin-top: 2px; flex: none; }
.kf-f.narrow .kf-mapw { display: none; }
@media (max-width: 640px) {
  .kf-h .btn { order: 3; width: 100%; justify-content: center; }
}
:root[data-theme="dark"] .kf-img img { filter: brightness(.86); }
:root[data-theme="dark"] .kf-img:hover img { filter: none; }
:root[data-theme="dark"] .kf-e:not(.on) .ln { stroke: color-mix(in srgb, var(--ink2) 55%, var(--ink3)); }
:root[data-theme="dark"] .kf-e:not(.on) .ah { fill: color-mix(in srgb, var(--ink2) 55%, var(--ink3)); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .kf-img img { filter: brightness(.86); }
  :root:not([data-theme="light"]) .kf-img:hover img { filter: none; }
  :root:not([data-theme="light"]) .kf-e:not(.on) .ln { stroke: color-mix(in srgb, var(--ink2) 55%, var(--ink3)); }
  :root:not([data-theme="light"]) .kf-e:not(.on) .ah { fill: color-mix(in srgb, var(--ink2) 55%, var(--ink3)); }
}
/* 深色下提醒条里的普通按钮不压成黑块 */
:root[data-theme="dark"] .kw-pend .btn.out { background: transparent; border-color: color-mix(in srgb, var(--orange-ink) 45%, transparent); color: var(--ink); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .kw-pend .btn.out { background: transparent; border-color: color-mix(in srgb, var(--orange-ink) 45%, transparent); color: var(--ink); }
}
/* 飞书来源页签的卡片不另起标题：添加来源的一行就在卡片顶上；只读的人没有这一行，第一个来源上面不画线 */
.ks-addf { display: flex; flex-wrap: wrap; gap: 8px; padding: 20px 20px 16px; }
.ks-addf input, .ks-addf select { height: 34px; padding: 0 12px; border: 1px solid var(--input-border); border-radius: var(--r); background: var(--card); color: var(--ink);
  box-shadow: var(--sh-xs); outline: 0; transition: border-color var(--t-fast, .12s) ease; }
.ks-addf input { flex: 1 1 320px; min-width: 0; }
.ks-addf input::placeholder { color: var(--ink4); }
.ks-addf select { width: auto; padding: 0 8px; }
.ks-addf input:focus, .ks-addf select:focus { border-color: var(--primary); box-shadow: 0 0 0 4px var(--focus-ring); }
.ks-noconn { display: flex; align-items: center; gap: 8px; margin: 20px 20px 16px; padding: 10px 14px; border-radius: var(--r); background: var(--grey-bg); color: var(--ink2); font-size: 13px; }
.ks-noconn svg.i { width: 16px; height: 16px; color: var(--ink3); flex: none; }
.ks-noconn a { color: var(--primary); }
.ks-list { display: flex; flex-direction: column; padding: 0 20px 4px; }
#ks-add:empty + .ks-list > .ks-src:first-child { border-top: 0; }
.ks-src { padding: 10px 0; border-top: 1px solid var(--divider); }
.ks-h { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; min-height: 44px; }
.ks-h > svg.i { width: 20px; height: 20px; color: var(--primary); flex: none; }
.ks-h .t { flex: 1; min-width: 220px; display: flex; flex-direction: column; line-height: 20px; }
.ks-h .t b { overflow-wrap: anywhere; }
.ks-h .t .faint { font-size: 12.5px; }
.ks-h .ops { display: inline-flex; flex-wrap: wrap; align-items: center; }
.ks-every { height: 30px; padding: 0 6px; border: 1px solid var(--input-border); border-radius: var(--r); background: var(--card); color: var(--ink2); font-size: 13px; box-shadow: var(--sh-xs); }
.ks-why { margin: 4px 0 0 32px; font-size: 12.5px; color: var(--ink3); line-height: 18px; }
.ks-why.bad { color: var(--red-ink); }
td .ks-why { margin: 2px 0 0; }
.ks-docs { margin: 10px 0 4px 32px; }
a.ks-dt { color: var(--ink); text-decoration: none; }
a.ks-dt:hover { color: var(--primary); }
.ks-empty { padding: 24px 12px; line-height: 22px; }
@media (max-width: 900px) {
  .kw { grid-template-columns: minmax(0, 1fr); }
  .kw-nav { position: static; max-height: none; padding: 6px; }
  .kw-mt { display: flex; align-items: center; gap: 8px; width: 100%; min-height: 40px; padding: 6px 10px; border: 0; border-radius: var(--r); background: none; color: var(--ink);
    font-weight: 600; text-align: left; cursor: pointer; }
  .kw-mt .mt-t { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .kw-mt .mt-n { font-weight: 400; font-size: 12.5px; }
  .kw-mt svg.i { width: 18px; height: 18px; flex: none; color: var(--ink3); transition: transform var(--t-fast, .12s) ease; }
  .kw-nav:not(.open) .kw-nb { display: none; }
  .kw-nav.open .kw-mt svg.i:last-child { transform: rotate(180deg); }
  .kw-nav.open .kw-nb { margin-top: 4px; padding-top: 6px; border-top: 1px solid var(--divider); }
  .kw-nav.open .kw-list { max-height: 40vh; overflow-y: auto; }
  .kw-page { padding: 16px; }
  .ks-list { padding: 0 16px 4px; }
  .ks-addf { padding: 16px; }
  .ks-why, .ks-docs { margin-left: 0; }
}
@media (max-width: 640px) {
  .kw-pm .kw-src { flex-basis: 100%; }
  .kw-pm .kw-src .dot { display: none; }
  .kw-ph .kw-act { order: 4; }          /* 手机宽：标题，版本与时间，再是按钮（10-28 第二轮评审） */
  .ks-h .ops { margin-left: auto; }
}

/* 系统设置的模型页签（11-11 接回原生 Claude：看图模型一张去掉）：服务商一行只读，型号下面一行价目 */
.fld .hint:empty { display: none; }
.lnk-btn { padding: 0; border: 0; background: none; color: var(--primary); font: inherit; cursor: pointer; }
.lnk-btn:hover:not(:disabled) { text-decoration: underline; }
.lnk-btn:disabled { color: var(--ink4); cursor: not-allowed; }
#sm-form .ro-v { min-height: 32px; display: flex; align-items: center; }
#sm-form .sub-t { margin-top: 4px; font-size: 12px; line-height: 18px; color: var(--ink3); }
/* AI 能打开的网站（11-02 E2）：说明在名单上面一行，名单一行一格；写得不对的一行框变红，原因写在那一行下面（R2c P2-7） */
#sd-form .sd-col { min-width: 0; }
#sd-form .fld > .l { align-items: flex-start; padding-top: 7px; }       /* 名单长：标签停在第一行旁边，不落到中间 */
@media (max-width: 640px) { #sd-form .fld > .l { padding-top: 0; } }
#sd-form .sd-hint { margin-top: 8px; }
#sd-form .form-foot { gap: 8px; }
#sd-form .rows .rw.bad { flex-wrap: wrap; row-gap: 4px; }
#sd-form .rows .rw.bad input { border-color: var(--red); }
#sd-form .rows .rw.bad input:focus { border-color: var(--red); box-shadow: 0 0 0 2px var(--red-bg); }
#sd-form .rw-err { flex: 0 0 100%; color: var(--red); font-size: 12px; line-height: 16px; }

/* Know-how 收流程图（10-28）：左栏传流程图，图的那一页原图与看图读出的流程并排，悬停一步在原图上圈出来 */
.kw-add { display: flex; align-items: center; justify-content: center; gap: 6px; width: calc(100% - 4px); margin: 8px 2px 2px; height: 34px; border: 1px dashed var(--input-border, var(--border)); border-radius: var(--r);
  background: none; color: var(--ink2); font: inherit; font-size: 13px; cursor: pointer; transition: border-color var(--t-fast, .12s) ease, color var(--t-fast, .12s) ease, background-color var(--t-fast, .12s) ease; }
.kw-add svg.i { width: 16px; height: 16px; }
.kw-add:hover:not(:disabled) { border-color: var(--primary); color: var(--primary); background: var(--primary-bg); }
.kw-add:disabled { cursor: progress; opacity: .7; }
.kw-it.img { flex-wrap: nowrap; }
.kw-it.img .t { flex: 1 1 0; }
.kw-it.img > svg.i { flex: none; width: 15px; height: 15px; color: var(--ink4); }
.kw-it.img.on > svg.i { color: var(--primary); }
.kw-eo { display: inline-flex; flex-wrap: wrap; justify-content: center; gap: 8px; }
.kw-pend.bad { background: var(--red-bg); color: var(--red-ink); }
.ki { container-type: inline-size; }
.ki-note { display: flex; align-items: flex-start; gap: 8px; margin: 0 0 12px; padding: 8px 12px; border-radius: var(--r); background: var(--primary-bg); color: var(--ink2); font-size: 13px; line-height: 20px; }
.ki-note svg.i { width: 16px; height: 16px; margin-top: 2px; flex: none; color: var(--primary); }
.ki-note b { color: var(--ink); font-weight: 600; }
.ki-two { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; align-items: start; }
@container (min-width: 880px) { .ki-two:has(> .ki-mapc) { grid-template-columns: minmax(0, .8fr) minmax(0, 1.2fr); } .ki-pic { position: sticky; top: 12px; } }
.ki-pic, .ki-mapc { margin: 0; min-width: 0; }
.ki-pic figcaption, .ki-cap { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 8px; margin: 0 0 8px; font-size: 13px; line-height: 20px; color: var(--ink); }
.ki-pic figcaption b, .ki-cap b { font-weight: 600; }
.ki-pic figcaption .kf-orig { margin-left: auto; font-size: 12.5px; }
.ki-cap .faint { font-size: 12.5px; }
.ki-pw { position: relative; overflow: hidden; border: 1px solid var(--border); border-radius: var(--r-lg); background: #fff; cursor: crosshair; aspect-ratio: 16 / 10; }
.ki-pw img { display: block; width: 100%; max-width: none; user-select: none; opacity: 0; transition: opacity .2s ease; }
.ki-pw.ok img { opacity: 1; }
.ki-bx { position: absolute; box-sizing: border-box; border: 1px dashed rgba(54, 133, 242, .55); border-radius: 4px; opacity: 0; pointer-events: none; transition: opacity var(--t-fast, .12s) ease; }
.ki-pw:hover .ki-bx { opacity: 1; }
.ki-pw .ki-bx.near { opacity: 1; border-style: solid; border-color: rgba(54, 133, 242, .6); background: rgba(54, 133, 242, .06); }
.ki-hl { position: absolute; box-sizing: border-box; border: 2px solid var(--primary-fill); border-radius: 5px; background: rgba(54, 133, 242, .12); box-shadow: 0 0 0 4px rgba(54, 133, 242, .18); pointer-events: none; z-index: 2; }
.ki-hl[hidden] { display: none; }
.ki-wait { display: flex; align-items: center; justify-content: center; min-height: 220px; border: 1px dashed var(--border); border-radius: var(--r-lg); background: var(--cv-bg, var(--grey-bg)); }
.ki-run { display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 24px; text-align: center; line-height: 20px; }
.ki-run b { font-size: 14px; }
.ki-run .faint { font-size: 12.5px; max-width: 360px; overflow-wrap: anywhere; }
.ki-run > svg.i { width: 28px; height: 28px; color: var(--ink4); }
.ki-run .spin { width: 22px; height: 22px; border: 2px solid var(--border); border-right-color: var(--primary); border-radius: 50%; animation: spin .8s linear infinite; }
.ki-f .kf-steps { margin-top: 16px; }
.ki-f.narrow .kf-steps { margin-top: 4px; }
.ki-f.narrow .ki-mapc .kf-mapw, .ki-f.narrow .ki-mapc .kf-more, .ki-f.narrow .ki-cap { display: none; }
.kf-ntw { width: fit-content; min-width: min(100%, 420px); max-width: 100%; max-height: 264px; overflow: auto; border: 1px solid var(--border); border-radius: var(--r); scrollbar-width: thin; }
.kf-ntw.more { -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 28px), transparent); mask-image: linear-gradient(to bottom, #000 calc(100% - 28px), transparent); }
.kf-nt { width: 100%; }
.kf-nt thead th { position: sticky; top: 0; z-index: 1; }
.kf-nt { border-collapse: collapse; font-size: 12.5px; line-height: 18px; white-space: nowrap; }
.kf-nt th, .kf-nt td { padding: 3px 10px; border-bottom: 1px solid var(--divider); text-align: left; }
.kf-nt th { background: var(--grey-bg); color: var(--ink2); font-weight: 600; }
.kf-nt tr:last-child td { border-bottom: 0; }
.kf-nt td:empty::after { content: ""; }
.kf-nt-p { color: var(--ink2); font-size: 13px; line-height: 20px; }
:root[data-theme="dark"] .ki-pw img { filter: brightness(.78) contrast(.96); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .ki-pw img { filter: brightness(.78) contrast(.96); } }

/* 全平台库：工作流项目的 Know-how 与组件（docs/WORKSPACE.md 第七节）。正文照 Wiki 页（.kw-md）排，代码块照代码框 */
.kw-md pre.kw-pre { margin: 10px 0; max-height: 420px; font-size: 12.5px; line-height: 19px; }
.lk-doc .kw-md { margin-top: 0; }
.lk-doc .kw-md > :first-child { margin-top: 0; }
.lk-doc .kw-tw { overflow-x: auto; }
.sheet .sh .sub .lk-wf { color: var(--primary); text-decoration: none; }
.sheet .sh .sub .lk-wf:hover { text-decoration: underline; }
/* 同名的工作流后面灰字写新建的时刻（R2b P1-5）；工作流卡片标题下面一行 12px 灰字（R2c P1-2） */
.lk-hint { color: var(--ink4); white-space: nowrap; }
.wf-hint { margin-top: -2px; font-size: 12px; line-height: 16px; color: var(--ink4); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* 表格里同名工作流的“某某新建”：手机上第一列窄，整句折行不截断，在日子后面断，时刻与“新建”连着（11-02 F4，Gemini 指出 390 宽截掉了秒） */
.tbl td.two > div.nh { white-space: normal; word-break: keep-all; overflow-wrap: anywhere; }
/* 手机宽运行记录名字下面开始的时刻前面一个小钟（运行记录的图标），跟上面那一行“某某新建”分得开 */
.tbl td.two .sub.rn-at .i { width: 12px; height: 12px; margin-right: 3px; vertical-align: -1px; fill: currentColor; }
.sheet .sh .sub .dot, .se-last .dot, .tbl td.two .sub.m-only .dot { margin: 0 6px; color: var(--ink4); }
.tbl td.two .sub.lk-sn { color: var(--ink3); }
.lk-sn mark, .lk-doc mark { padding: 0 1px; border-radius: 3px; background: var(--primary-bg); color: var(--primary); }
.cp-sum .lk-wf { color: var(--primary); text-decoration: none; }
.cp-sum .lk-wf:hover { text-decoration: underline; }
.lk-code { display: flex; height: calc(100vh - 176px); min-height: 320px; border: 1px solid var(--border); border-radius: var(--r); overflow: hidden; background: var(--code, var(--card)); }
.lk-code > .cm-editor { flex: 1; min-width: 0; height: 100%; }
.lk-code .cm-scroller { overflow: auto; scrollbar-width: thin; }
.lk-code > .empty, .lk-code > .skel { flex: 1; border: 0; }
/* 11-01 评审 P1-1：代码页签看的是组件面板里在用的那一份；项目里另有改过没核对的草稿时顶上一行写明，右边换着看 */
.lk-code { flex-direction: column; }
.lk-code-ed { flex: 1; min-height: 0; display: flex; }
.lk-code-ed > .cm-editor { flex: 1; min-width: 0; height: 100%; }
.lk-code-bar { display: flex; align-items: center; gap: 8px; min-height: 40px; padding: 6px 8px 6px 12px; border-bottom: 1px solid var(--border);
  background: var(--orange-bg); color: var(--orange-ink); font-size: 12.5px; line-height: 18px; }
.lk-code-bar > svg.i { width: 16px; height: 16px; flex: none; }
.lk-code-bar > span { flex: 1; min-width: 0; }
/* 系统设置的 AI 引擎：两样版本，上次检查；查的时候写正在做哪一步 */
#se-card dl.facts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.se-step { display: inline-flex; align-items: center; gap: 8px; color: var(--ink2); }
/* 上次检查：时刻，间隔点，结果照一段字排，放不下在结果里折行，间隔点粘着结果，不落单挂在第一行末（R2 P2-16） */
.se-last { display: block; flex: 1 1 auto; min-width: 0; color: var(--ink2); line-height: 22px; }
.se-last .bad { color: var(--red-ink); overflow-wrap: anywhere; }
.se-last .good { color: var(--success-ink); }
.se-last .warn { color: var(--orange-ink); }        /* 跑命令不用沙箱（管理员改的，11-02 F6） */
/* Agent SDK 下面一行：新版已就绪，下次重启生效；开机没换成的原因（红字）；上次检查下面：校验摘要取自镜像 */
.se-pend { display: block; flex: 0 0 100%; width: 100%; margin-top: 2px; color: var(--ink2); font-size: 12.5px; line-height: 18px; }
.se-pend.bad { color: var(--red-ink); }
.se-pend .nw { white-space: nowrap; }

/* 代码的可视化（11-01 第四段）：对话里一句改了哪几份文件，一份一行，点了在画布这一块上看前后对比；
   组件库工作流项目的组件详情顶上写放没放进组件面板，没过核对的原因，用了连接要审过 */
.as-files { display: flex; flex-direction: column; gap: 2px; margin-top: 8px; padding: 4px; border: 1px solid var(--border); border-radius: var(--r); background: var(--card); }
.as-file { display: flex; align-items: center; gap: 8px; width: 100%; min-height: 28px; padding: 0 8px; border: 0; border-radius: var(--r-sm); background: none; color: var(--ink2);
  font: inherit; font-size: 12.5px; text-align: left; cursor: pointer; transition: background-color var(--t-fast) ease, color var(--t-fast) ease; }
.as-file:hover { background: var(--hover); color: var(--ink); }
.as-file:focus-visible { outline: 0; box-shadow: 0 0 0 3px var(--focus-ring); }
.as-file.lock { color: var(--ink4); cursor: default; }
.as-file.lock:hover { background: none; color: var(--ink4); }
.as-file.more { color: var(--ink3); }
.as-file.more:hover { color: var(--primary); }
.as-fn { flex: 1; min-width: 0; display: flex; align-items: baseline; overflow: hidden; white-space: nowrap; }
.as-fn .dir { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; direction: rtl; color: var(--ink4); }
.as-fn .nm { flex: 0 0 auto; max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
.as-fchip { flex: none; height: 18px; padding: 0 5px; border-radius: var(--r-sm); font-size: 11.5px; font-weight: 500; line-height: 18px; }
.as-fchip.added { color: var(--success-ink); background: var(--success-bg); }
.as-fchip.modified { color: var(--primary); background: var(--primary-bg); }
.as-fchip.deleted { color: var(--red-ink); background: var(--red-bg); }
.as-fnum { flex: none; display: inline-flex; gap: 6px; font: 12px/18px var(--mono); }
.as-fnum .a { color: var(--success-ink); }
.as-fnum .d { color: var(--red-ink); }
.lc-st { margin: 0 0 14px; }
.lc-st .t b { font-weight: 600; }
.lc-errs { margin: 6px 0 0; padding-left: 20px; font-size: 12.5px; line-height: 20px; }
.lc-errs li + li { margin-top: 2px; }
/* 没过核对的红条（R2 P1-10）：图标跟“没过核对”一行，右边“让 AI 改”贴着上沿，不跟着原因的条数往下沉 */
.lc-st.lc-bad { align-items: flex-start; }
.lc-st.lc-bad > svg.i { margin-top: 1px; }
.lc-st.lc-bad .btn svg.i { width: 15px; height: 15px; }
:root[data-theme="dark"] .kw-pend.bad .btn.out { background: transparent; border-color: color-mix(in srgb, var(--red-ink) 45%, transparent); color: var(--ink); }
:root[data-theme="dark"] .kw-pend.bad .btn.out[disabled] { border-color: var(--border); color: var(--ink4); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .kw-pend.bad .btn.out { background: transparent; border-color: color-mix(in srgb, var(--red-ink) 45%, transparent); color: var(--ink); }
  :root:not([data-theme="light"]) .kw-pend.bad .btn.out[disabled] { border-color: var(--border); color: var(--ink4); }
}
/* 库页的抽屉开着时左下角 AI 助手接这个工作流（R2 P2-17）：面板浮在遮罩与抽屉上面；宽屏抽屉挪到面板左边，两个并排都看得见，
   窄于 1024 面板整屏盖在抽屉上，关了回到抽屉 */
body.lk-sheet .assist { z-index: 52; }
body.lk-sheet .sheet.on { transition: transform var(--t-panel) var(--ease-panel), right var(--t-panel) var(--ease-panel), visibility 0s; }
@media (min-width: 1024px) { body.lk-sheet.assist-open .sheet { right: var(--as-w); max-width: calc(100% - var(--as-w)); } }
@media (max-width: 1023px) { body.lk-sheet .assist { top: 0; } }
/* 撤回这一句时没跟着回的几份（后来又改过，组件还有工作流在用）：橙色提醒图标一行，下面一份一行，文件名与原因 */
.as-kept { margin-top: 6px; font-size: 12.5px; line-height: 20px; color: var(--ink2); }
.as-kept .h { display: flex; align-items: center; gap: 4px; color: var(--orange-ink); }
.as-kept .h svg.i { width: 15px; height: 15px; }
.as-kept .r { padding-left: 19px; min-width: 0; }
.as-kept .r .as-fn { display: inline-flex; max-width: 100%; vertical-align: bottom; }
.as-kept .r .why { margin-left: 8px; color: var(--ink3); }
.as-kept .r.more { color: var(--ink3); }
/* 撤回过的一句：跟着回去的那几份文件淡下来，小标签与加删几行换灰，点开照样看当时改了什么 */
.as-file.off { color: var(--ink3); }
.as-file.off .as-fchip { color: var(--ink3); background: var(--grey-bg); }
.as-file.off .as-fnum .a, .as-file.off .as-fnum .d { color: var(--ink4); }
/* 节点大框里说的话（11-01 R2 P2-7）：照时刻插在对话里的一行灰字，靠左跟对话里的事件一列（同“已撤回”那一行），最多两行；
   编辑页里是一块 1px 细框 8 圆角的入口，节点名主色，右边小箭头，点了打开那个节点的大框（同对话里改了哪几份文件那一块的细框）。
   连着几行挨近一点，不照消息之间的间距 */
.as-nask { align-self: flex-start; max-width: calc(100% - 32px); display: flex; align-items: flex-start; gap: 6px; margin: 0 0 0 32px; padding: 3px 8px; border: 1px solid transparent; border-radius: var(--r);
  background: none; color: var(--ink3); font: inherit; font-size: 13px; line-height: 20px; text-align: left; }
.as-nask svg.i { flex: none; width: 14px; height: 14px; margin-top: 3px; color: var(--ink4); }
.as-nask .tx { min-width: 0; overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow-wrap: anywhere; }
.as-nask .nm { color: var(--ink2); }
button.as-nask { padding: 5px 6px 5px 10px; border-color: var(--border); background: var(--card); cursor: pointer; transition: background-color var(--t-fast) ease, color var(--t-fast) ease, border-color var(--t-fast) ease; }
button.as-nask .nm { color: var(--primary); }
button.as-nask > svg.i:last-child { width: 16px; height: 16px; margin-top: 2px; transition: color var(--t-fast) ease; }
button.as-nask:hover { background: var(--hover); border-color: var(--input-border); color: var(--ink2); }
button.as-nask:hover > svg.i:last-child { color: var(--ink2); }
button.as-nask:focus-visible { outline: 0; box-shadow: 0 0 0 3px var(--focus-ring); }
.as-msgs > .as-nask + .as-nask { margin-top: -12px; }
.as-nask.in { animation: rise-in .36s var(--ease-out) both; }
/* 运行没成，功能页报错平台记的那一行（11-03 S2，自修闭环）：橙色提醒图标，那次运行的说法是链接，开着的通知右边“让 AI 修”；
   平台起的自修那一句前面那一行用扳手，字跟接着做那一行一样淡 */
.as-nask.as-runfail { color: var(--ink2); }
.as-nask.as-runfail > svg.i { color: var(--orange-ink); }
.as-nask.as-runfail .lnk { color: var(--primary); text-decoration: none; }
.as-nask.as-runfail .lnk:hover { text-decoration: underline; }
.as-runfail-fix { flex: none; align-self: center; height: 26px; margin-left: 4px; padding: 0 8px; }
.as-nask.as-heal > svg.i { color: var(--ink3); }
/* 删工作流的确认框：它做的组件别的工作流还在用的一个一行 */
.dl-used { margin: 4px 0 0; padding-left: 20px; font-size: 13px; line-height: 21px; color: var(--ink2); }
/* 工作流项目的 Know-how 放与改（11-01 第二轮 D3，docs/STYLE_PORTAL.md Know-how 一节）：表格卡片头“添加”与“回收处”，回收处有几篇写在键上；
   抽屉头上几个小号描边键（让 AI 改，编辑，版本记录 N，更多），手机宽只留图标与条数；挂进来的那一篇正文上面一行出处（链接图标，灰字，主色“去知识库看”），
   有新版时换成橙色提示条（同 Wiki 页待合并那一条），知识库那篇删了换成灰条 */
.lk-binn { color: var(--ink3); font-variant-numeric: tabular-nums; }
.btn .n { margin-left: 4px; color: var(--ink3); font-variant-numeric: tabular-nums; }
.btn.pri .n { color: inherit; opacity: .8; }
.lk-acts { display: inline-flex; align-items: center; gap: 8px; flex-wrap: nowrap; }
.lk-acts .btn.sm { gap: 5px; }
.lk-acts .btn.sm svg.i { width: 16px; height: 16px; }
.lk-more svg.i.chev { margin-right: -4px; }
.lk-more svg.i.dots { display: none; }
.lk-srcw { margin-bottom: 16px; }
.lk-srcw[hidden] { display: none; }
.lk-src.kw-pend { margin: 0; align-items: flex-start; }
.lk-src.kw-pend > svg.i { margin-top: 2px; flex-shrink: 0; }   /* 窄屏字折成几行时，图标跟第一行标题对齐（11-01 第二轮 D3，Gemini 第四轮） */
.lk-src.plain { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 8px; padding: 8px 12px; border: 1px solid var(--border); border-radius: var(--r);
  background: var(--th-bg); font-size: 13px; line-height: 20px; color: var(--ink2); }
.lk-src.plain > svg.i { width: 16px; height: 16px; color: var(--ink3); flex: none; }
.lk-src.plain .t { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.lk-src.plain a { color: var(--primary); text-decoration: none; white-space: nowrap; }
.lk-src.plain a:hover { text-decoration: underline; }
.lk-src.kw-pend .ops a.btn { text-decoration: none; }
/* 知识库这一篇挂进了哪些工作流：Wiki 页页头灰字一行，说明卡片与文档表里同样一行 */
.kh-mnt { display: flex; align-items: center; gap: 4px; font-size: 12.5px; line-height: 20px; color: var(--ink3); min-width: 0; }
.kw-ph .kh-mnt { flex: 1 1 100%; order: 4; }
.kh-item .kh-mnt { margin-top: 6px; }
.kh-mnt.cell { margin-top: 2px; }
.kh-mnt > svg.i { width: 14px; height: 14px; flex: none; color: var(--ink4); }
.kh-mnt span { min-width: 0; overflow-wrap: anywhere; }
.kh-mnt a { color: var(--primary); text-decoration: none; }
.kh-mnt a:hover { text-decoration: underline; }
/* 一个搜索框搜两边：打了字时表格下面另一张卡，内容（标题与命中的那一句），类别，来源 */
.lk-hits { margin-top: 16px; }
.lk-hits[hidden] { display: none; }
.lk-hits .card-h { min-height: 0; padding-bottom: 4px; }
.lk-ht a.lnk { color: var(--ink); text-decoration: none; }
.lk-ht a.lnk:hover { color: var(--primary); }
.lk-ht mark { padding: 0 2px; border-radius: 3px; background: var(--primary-bg); color: var(--primary); }
/* 知识库页签里因为内容搜到的库：第二行写找到的那一条与那一句，两行以内 */
.tbl td.two .sub.kh-hit { white-space: normal; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
/* 上传文件的对话框：选文件的键，右边写选了哪一份与多大 */
.lk-file { display: flex; align-items: center; gap: 10px; min-width: 0; flex: 1; }
.lk-fn { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink2); font-size: 13px; }
/* 回收处的抽屉 */
.lk-bin .tbl td.two > div:first-child { overflow-wrap: anywhere; }
.lk-vl .tbl td:nth-child(3) { white-space: nowrap; }
/* 手机宽：抽屉头分两行，标题与来源一行（右边关闭，来源与更新时刻写得全），下面一行是几个键，键上照旧写字；
   版本记录一版一块：第几版与当前，右边操作，下面更新方式与谁，时刻，说明 */
@media (max-width: 640px) {
  .sheet .sh:has(.lk-acts) { padding-top: 10px; padding-bottom: 10px; }
  .sheet .sh:has(.lk-acts) .sub { white-space: normal; }
  .sheet .sh:has(.lk-acts) > .acts { margin-right: 0; }
  .lk-acts { gap: 6px; }
  .lk-acts .btn.sm { padding: 0 8px; }
  .lk-acts .btn.sm .t { display: none; }
  .lk-acts .btn.sm .n { margin-left: 2px; }
  .lk-more svg.i.chev { display: none; }
  .lk-more svg.i.dots { display: block; }
  .lk-vl { overflow-x: visible; max-height: none; }
  .lk-vl .tbl { min-width: 0; display: block; }
  .lk-vl .tbl colgroup, .lk-vl .tbl thead { display: none; }
  .lk-vl .tbl tbody { display: block; }
  .lk-vl .tbl tr { display: grid; grid-template-columns: auto 1fr auto; column-gap: 8px; row-gap: 2px; align-items: center; padding: 10px 0; border-bottom: 1px solid var(--divider); }
  .lk-vl .tbl tr:last-child { border-bottom: 0; }
  .lk-vl .tbl td { display: block; padding: 0; border: 0; height: auto; min-height: 0; line-height: 20px; white-space: normal; }
  .lk-vl .tbl td:nth-child(1) { grid-area: 1 / 1; font-weight: 600; }
  .lk-vl .tbl td:nth-child(2) { grid-area: 1 / 2; }
  .lk-vl .tbl td:nth-child(6) { grid-area: 1 / 3 / 3 / 4; align-self: start; }
  .lk-vl .tbl td:nth-child(3) { grid-area: 2 / 1 / 3 / 3; font-size: 13px; color: var(--ink2); }
  .lk-vl .tbl td:nth-child(5) { grid-area: 3 / 1 / 4 / 4; font-size: 12.5px; color: var(--ink3); }
  .lk-vl .tbl td:nth-child(4) { grid-area: 4 / 1 / 5 / 4; font-size: 12.5px; overflow-wrap: anywhere; }
  .lk-vl .tbl td:nth-child(4):empty { display: none; }
  .lk-vl .tbl td.ops > div { flex-direction: column; align-items: flex-end; gap: 10px; }
  .lk-vl .ops .op + .op::before { display: none; }
}
/* AI 引擎里“跑命令”那一行（11-01 第三轮 N1）：在沙箱里写绿字；起不来写原因（红字，长的折行），后面“重新检查” */
.se-sbx { display: flex; flex-wrap: wrap; align-items: baseline; column-gap: 12px; row-gap: 4px; }
.se-sbx .lnk-btn { flex: none; }
.se-sbx .se-acts { flex: none; display: inline-flex; gap: 16px; }      /* 两个文字按钮一起折行，窄屏上同一行（11-02 F6，Gemini） */
/* 安全检查关着时不拦的几样（11-03 S1）：一样一行，灰字，同卡片的正文对齐 */
.sc-off { margin: 4px 0 0; padding: 0 16px 16px 34px; color: var(--ink2); font-size: 13px; line-height: 20px; }
.sc-off li + li { margin-top: 4px; }
/* 窄屏上按钮那一组一律另起一行，几种原因的按钮在同一个位置（Gemini 第四轮）；组里的两个按钮同一行（11-02 F6） */
@media (max-width: 480px) { .se-sbx .se-acts { flex-basis: 100%; } }

/* ------------------------------------------------------------------ 11-01 第三轮 N2：技能页三个页签，套件库，组件库的在用，Know-how 交给 AI 整理（docs/STYLE_PORTAL.md） */
/* 在用的工作流：名字是主色链接，太多时后面灰字写一共几个 */
.sheet dl.facts .lk-wf { color: var(--primary); text-decoration: none; }
.sheet dl.facts .lk-wf:hover { text-decoration: underline; }
.lk-uses .muted { margin-left: 6px; }
/* 技能，助手，命令的抽屉：做法照文档排（同 Know-how 的抽屉），正文贴着小节标题 */
.sheet .kw-md.sk-md { margin-top: 0; }
.sheet .kw-md.sk-md > :first-child { margin-top: 0; }
.sheet .kw-md.sk-md h2 { font-size: 15px; }
.sheet .kw-md.sk-md h3, .sheet .kw-md.sk-md h4 { font-size: 14px; }
/* 版本记录：一张小表，当前那一版带浅主色小标签，行矮一点 */
.sk-vers { border: 1px solid var(--border); border-radius: var(--r); }
.sk-vers .tbl th, .sk-vers .tbl td { height: 38px; }
.sk-vers .tbl th:first-child, .sk-vers .tbl td:first-child { padding-left: 14px; }
.sk-vers .tbl tbody tr:last-child td { border-bottom: 0; }
.sk-vers .tbl tr.cur td { color: var(--ink); }
.sk-vers .tbl .chip { margin-left: 6px; height: 20px; line-height: 20px; font-size: 12px; }
/* 助手表：能做的与带的技能两行以内，小一号 */
.sk-ag td.c-sm .clamp { font-size: 13px; color: var(--ink2); }
/* 套件库：由这几个组件组成，一步一行，左边序号小圆，右边逐个运行，有运行条件的小标签 */
.su-flow { list-style: none; margin: 0; padding: 0; border: 1px solid var(--border); border-radius: var(--r-lg); overflow: hidden; }
.su-flow li { display: flex; align-items: flex-start; gap: 12px; padding: 10px 14px; }
.su-flow li + li { border-top: 1px solid var(--divider); }
.su-flow .n { flex: none; width: 22px; height: 22px; margin-top: 1px; border-radius: 50%; background: var(--grey-bg); color: var(--ink2); font-size: 12px; font-weight: 500; line-height: 22px; text-align: center; font-variant-numeric: tabular-nums; }
.su-flow .b { flex: 1; min-width: 0; }
.su-flow .t { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; min-height: 24px; }
.su-flow .tt { font-size: 14px; font-weight: 500; color: var(--ink); overflow-wrap: anywhere; }
.su-flow .tags { display: inline-flex; gap: 6px; }
.su-flow .tag { height: 20px; line-height: 20px; font-size: 12px; }
.su-flow .s { margin-top: 2px; font-size: 12.5px; line-height: 18px; color: var(--ink3); overflow-wrap: anywhere; }
.su-flow .s .dot { margin: 0 6px; color: var(--ink4); }
/* 交给 AI 整理：选了的文件一份一行，文件名，大小（不收的红字写原因），右边去掉的叉 */
.lk-cubody { display: flex; flex-direction: column; gap: 16px; }
.lk-cufs { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.lk-cul { list-style: none; margin: 0; padding: 2px 0; border: 1px solid var(--border); border-radius: var(--r); max-height: 196px; overflow-y: auto; }
.lk-cul[hidden] { display: none; }
.lk-cul li { display: flex; align-items: center; gap: 8px; min-height: 36px; padding: 0 4px 0 10px; font-size: 13px; }
.lk-cul li + li { border-top: 1px solid var(--divider); }
.lk-cul li > svg.i { flex: none; width: 16px; height: 16px; color: var(--ink3); }
.lk-cul .nm { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink); }
.lk-cul .sz { flex: none; color: var(--ink3); font-size: 12px; font-variant-numeric: tabular-nums; }
.lk-cul li.bad > svg.i, .lk-cul li.bad .sz { color: var(--red); }
.lk-cul .icon-btn.sm { flex: none; }
.lk-cudlg textarea::placeholder { color: var(--ink4); }
@media (max-width: 640px) {
  .su-flow li { padding: 10px 12px; }
}
/* 套件库与助手表：说明两行以内 */
.tbl td.two .sub.d2 { white-space: normal; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; line-height: 18px; }
/* 套件抽屉头上只有“进入套件”一个键：手机宽也照旧写字 */
.su-acts { display: inline-flex; align-items: center; }
.su-acts .btn.sm { gap: 5px; }
.su-acts .btn.sm svg.i { width: 16px; height: 16px; }
/* 版本记录：“第几版”与“当前”同一行，不截 */
.sk-vers .tbl td:first-child { white-space: nowrap; }

/* 项目对话里原生的几样交互（11-02 E2）：用户那一句悬停时左边一个“回退到这一句以前”，回退掉的几句淡下来写“已回退”；
   另起一段与回退的那一行同接着做那一行；输入框左下的“+”是常用命令与选文件，选好的文件在输入框上面一行，一份一块 */
.as-u { position: relative; }
.as-u-rw { position: absolute; top: 50%; right: calc(100% + 6px); width: 26px; height: 26px; margin-top: -13px; padding: 0; border: 0; border-radius: var(--r-sm);
  display: inline-flex; align-items: center; justify-content: center; background: none; color: var(--ink3); cursor: pointer; opacity: 0;
  transition: opacity var(--t-fast) ease, background-color var(--t-fast) ease, color var(--t-fast) ease; }
.as-u-rw svg.i { width: 16px; height: 16px; }
.as-u:hover .as-u-rw, .as-u-rw:focus-visible { opacity: 1; }
.as-u-rw:hover:not(:disabled) { background: var(--hover); color: var(--ink); }
.as-u-rw:focus-visible { outline: 0; box-shadow: 0 0 0 3px var(--focus-ring); }
.as-u-rw:disabled { color: var(--ink4); cursor: not-allowed; }
@media (hover: none) { .as-u-rw { opacity: .7; } }
.as-u.rw { color: var(--ink3); background: var(--hover); }
.as-u.rw .as-u-t { text-decoration: line-through; text-decoration-color: var(--ink4); }
.as-u-tag { display: block; margin-top: 2px; font-size: 12px; line-height: 18px; color: var(--ink3); text-align: right; }
/* AI 答着的时候说的话（11-03 FIX7 A35）：排着的气泡淡一档，下面一行“排着 · 撤回”；交到了写“已交给 AI” */
.as-u.q { background: var(--hover); color: var(--ink2); }
.as-u-q { display: flex; justify-content: flex-end; align-items: center; gap: 8px; }
.as-u-wd { padding: 0; border: 0; background: none; color: var(--primary); font: inherit; font-size: 12px; line-height: 18px; cursor: pointer; border-radius: var(--r-sm); }
.as-u-wd:hover:not(:disabled) { text-decoration: underline; }
.as-u-wd:focus-visible { outline: 0; box-shadow: 0 0 0 3px var(--focus-ring); }
.as-u-wd:disabled { color: var(--ink4); cursor: default; }
.as-uw.rw .as-u-sel { opacity: .55; }
/* 一句带上的文件（R2c P2-5）：气泡下面一行，同输入框上面那种浅蓝小块；编辑页里点了在项目文件里看 */
.as-ufs { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 6px; max-width: 100%; margin-top: -2px; }      /* 离气泡 4px，看得出是这一句的 */
.as-ufile { flex: 0 1 auto; max-width: 220px; font: inherit; font-size: 12px; animation: none; }
button.as-ufile { cursor: pointer; transition: border-color var(--t-fast) ease, box-shadow var(--t-fast) ease; }
button.as-ufile:hover { border-color: var(--primary); }
button.as-ufile:focus-visible { outline: 0; box-shadow: 0 0 0 3px var(--focus-ring); }
.as-uw.rw .as-ufs { opacity: .55; }
.as-a.rw .as-text, .as-a.rw .as-plan { color: var(--ink3); }
.as-a.rw .as-av { opacity: .45; }
/* 另起一段与回退的那一行是对话的分水岭：居中，两边一条淡线 */
.as-msgs > .as-mark { align-self: stretch; max-width: none; margin: 0; justify-content: center; align-items: center; gap: 8px; color: var(--ink3); font-size: 12.5px; }
.as-msgs > .as-mark::before, .as-msgs > .as-mark::after { content: ''; flex: 1 1 12px; min-width: 12px; height: 1px; background: var(--border); }
.as-mark svg.i { margin-top: 0; color: var(--ink3); }
/* 放不下折两行时两行一样长，只在逗号处折（.nw 一段不拆，R2c P2-3）；图标在字里，贴着头一段 */
.as-mark .tx { flex: 0 1 auto; display: block; overflow: visible; -webkit-line-clamp: none; overflow-wrap: normal; text-align: center; text-wrap: balance; line-height: 20px; }
.as-mark .tx .nw { white-space: nowrap; }
.as-mark .tx svg.i { display: inline-block; width: 14px; height: 14px; margin: 0 6px 0 0; vertical-align: -2px; }
.as-msgs > .as-mark + .as-mark { margin-top: -10px; }
.as-seg-btn { height: 28px; padding: 0 8px; gap: 4px; color: var(--ink2); }
.as-seg-btn svg.i { width: 16px; height: 16px; }
.as-plus { flex: none; width: 28px; height: 28px; margin-left: -6px; color: var(--ink3); }
.as-plus:hover { color: var(--ink); }
.as-picked { display: flex; flex-wrap: wrap; gap: 6px; }
.as-picked[hidden] { display: none; }
.as-pchip { flex: none; max-width: 220px; }
.as-uping .spin-i { width: 12px; height: 12px; }          /* 对话框里上传的那几份还在传（11-02 FIX1 A3） */
/* 带上的文件（11-05 粘贴，拖进来的，web/clip.js）：输入框上面与气泡下面一样高（32），左边 24 的小方块：图是缩略图（细描边，白底的图也看得出边），
   文件与文件夹是图标；一行放得下两块（Gemini 11-05：高矮不一，一块一行太空） */
.as-picked .as-pchip, .as-ufs .as-ufile { height: 32px; max-width: 176px; padding-left: 4px; gap: 6px; border-radius: 8px; }
/* 输入框上面一行排成等宽的格子（Gemini 11-05 第二轮：两块加起来不齐），小叉靠右 */
.as-picked:has(.as-pchip) { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 6px; }
.as-picked .as-pchip { width: 100%; max-width: none; }
.as-picked .as-pchip > .as-ctx-x { margin-left: auto; }
.as-picked .as-pchip > svg.i, .as-ufs .as-ufile > svg.i, .as-picked .as-pchip > .spin-i { flex: none; box-sizing: border-box; width: 24px; height: 24px; padding: 4px; border-radius: 6px; background: var(--card); }
.af-thumb { flex: none; width: 24px; height: 24px; border-radius: 6px; object-fit: cover; background: var(--card); outline: 1px solid rgba(16, 24, 40, .08); outline-offset: -1px; }
/* 拖文件到对话这一栏上：整块盖一层，虚线框写“松开就带上”；带不了时灰色写原因（web/clip.js） */
.af-drop-rel { position: relative; }
.af-drop::after { content: attr(data-drop-tip); position: absolute; inset: 8px; z-index: 60; display: flex; align-items: center; justify-content: center;
  padding: 16px; border: 2px dashed var(--primary); border-radius: 12px; background: color-mix(in srgb, var(--card) 90%, var(--primary-bg));
  color: var(--primary); font-size: 14px; font-weight: 600; text-align: center; pointer-events: none; }
.af-drop.af-drop-no::after { border-color: var(--input-border); background: var(--card); color: var(--ink2); }
/* 字上面一个上传的图标（Gemini 11-05 第二轮：整栏只有一行字太空）；带不了时不摆 */
.af-drop:not(.af-drop-no)::before { content: ''; position: absolute; left: 50%; top: 50%; z-index: 61; width: 28px; height: 28px; transform: translate(-50%, calc(-50% - 30px));
  background: var(--primary); pointer-events: none;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M11 16V7.85l-2.6 2.6L7 9l5-5 5 5-1.4 1.45-2.6-2.6V16h-2Zm-5 4q-.825 0-1.413-.588T4 18v-3h2v3h12v-3h2v3q0 .825-.588 1.413T18 20H6Z'/%3E%3C/svg%3E") center / contain no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M11 16V7.85l-2.6 2.6L7 9l5-5 5 5-1.4 1.45-2.6-2.6V16h-2Zm-5 4q-.825 0-1.413-.588T4 18v-3h2v3h12v-3h2v3q0 .825-.588 1.413T18 20H6Z'/%3E%3C/svg%3E") center / contain no-repeat; }
/* 上传文件对话框“放进”那一格的下拉箭头（浏览器给带候选的输入框画的）淡一档，同平台下拉框的箭头 */
#pf-upd::-webkit-calendar-picker-indicator { opacity: .5; cursor: pointer; }
.dlg-pick { width: 520px; max-width: calc(100vw - 32px); }
.as-pk { display: flex; flex-direction: column; gap: 10px; }
/* 选文件框的搜索框：同平台的输入框（34 高，8 圆角，细框，聚焦帆软蓝加一圈淡光），左边放大镜（R2c P2-4） */
.as-pk-qb { display: flex; align-items: center; gap: 6px; height: 34px; margin-bottom: 4px; padding: 0 10px; border: 1px solid var(--input-border); border-radius: var(--r); background: var(--card);
  box-shadow: var(--sh-xs); cursor: text; transition: border-color var(--t-fast, .12s) ease, box-shadow var(--t-fast, .12s) ease; }
.as-pk-qb:focus-within { border-color: var(--primary); box-shadow: 0 0 0 4px var(--focus-ring); }
.as-pk-qb svg.i { flex: none; width: 16px; height: 16px; color: var(--ink3); }
.as-pk-q { flex: 1; min-width: 0; width: 100%; height: 32px; padding: 0; border: 0; outline: 0; background: none; color: var(--ink); font: inherit; }
.as-pk-q::placeholder { color: var(--ink4); }
.as-pk-l { display: flex; flex-direction: column; max-height: min(360px, 50vh); overflow-y: auto; border: 1px solid var(--border); border-radius: var(--r); padding: 4px 0; }
.as-pk-i { display: flex; align-items: center; gap: 8px; min-height: 34px; padding: 0 12px; cursor: pointer; }
.as-pk-i:hover { background: var(--hover); }
.as-pk-i .as-fn { min-width: 0; }
.as-pk-e { padding: 16px 12px; color: var(--ink3); text-align: center; }
.as-pk-n { font-size: 12px; color: var(--ink3); }

/* ------------------------------------------------------------------ 工作台专注（11-11 用户：“进入工作台后自动收折最左边原本的侧栏 留一个返回按钮”，“可以做一个丝滑的动画”）
 * 进 #/work 时 body 加 wk-focus：平台左栏整条向左滑出去，内容区左边距同一条曲线收到 0，工作台铺满；出去时反过来滑回来。
 * 窄屏左栏本来是抽屉，收的是平台那条顶栏（向上滑走），工作台自己的页头留着，返回键在页头最左边（web/work.css）。
 * 第一次打开就在工作台的（shell-still，只一帧）直接是收好的样子；少动画时不滑，直接换（MOTION：滑入换硬切）。 */
.side { transition: width var(--t-panel) var(--ease-panel), transform var(--t-panel) var(--ease-panel), visibility 0s; }
body.wk-focus .side { transform: translateX(-100%); visibility: hidden; pointer-events: none;
  transition: width var(--t-panel) var(--ease-panel), transform var(--t-panel) var(--ease-panel), visibility 0s linear var(--t-panel); }
body.wk-focus main { padding-left: 0; }
body.wk-focus #toast { left: 24px; }
@media (max-width: 1023px) {
  body.wk-focus { --hd-h: 0px; }
  header.top { transition: transform var(--t-panel) var(--ease-panel), visibility 0s; }
  body.wk-focus header.top { transform: translateY(-100%); visibility: hidden; pointer-events: none;
    transition: transform var(--t-panel) var(--ease-panel), visibility 0s linear var(--t-panel); }
}
body.shell-still .side, body.shell-still main, body.shell-still header.top, body.shell-still #toast { transition: none !important; }
@media (prefers-reduced-motion: reduce) {
  .side, body.wk-focus .side, header.top, body.wk-focus header.top, main { transition: none !important; }
}
