/* ============================================================
   AI Canvas — 控制台静态原型
   纯 CSS，无外部依赖（离线可看）。
   所有数据都是假的，用来和真实后端字段对齐：
   ai-canvas/app/models.py
   ============================================================ */

:root {
  --bg: #f6f7f9;
  --panel: #ffffff;
  --panel-2: #fbfbfd;
  --sidebar: #1b2130;
  --sidebar-2: #252c3d;
  --topbar: #1b2130;
  --border: #e6e8ee;
  --text: #1a1d26;
  --muted: #6b7280;
  --muted-2: #9aa1ad;
  --primary: #4f46e5;
  --primary-soft: #eef0ff;
  --ok: #16a34a;
  --ok-soft: #e8f7ee;
  --warn: #d97706;
  --warn-soft: #fdf3e3;
  --err: #dc2626;
  --err-soft: #fdecec;
  --info: #0284c7;
  --info-soft: #e6f4fb;
  --radius: 10px;
  --shadow: 0 1px 2px rgba(16, 24, 40, .06), 0 8px 24px -12px rgba(16, 24, 40, .18);
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Cascadia Mono", monospace;
}

* { box-sizing: border-box; }

html, body { height: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 14px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", "Microsoft YaHei", Roboto, sans-serif;
  -webkit-font-smoothing: antialiased;
}

a { color: inherit; text-decoration: none; }
button { font: inherit; cursor: pointer; }

/* ---------- 顶栏 ---------- */
.topbar {
  height: 56px;
  background: var(--topbar);
  color: #e8ebf2;
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 0 18px;
  position: sticky;
  top: 0;
  z-index: 30;
}
.brand {
  display: flex; align-items: center; gap: 9px;
  font-weight: 700; font-size: 15px; letter-spacing: .2px;
  margin-right: 14px; white-space: nowrap;
}
.brand .logo {
  width: 26px; height: 26px; border-radius: 7px;
  background: linear-gradient(135deg, #6d6bf5, #38bdf8);
  display: grid; place-items: center;
  font-size: 13px; color: #fff; font-weight: 800;
}
.nav { display: flex; align-items: center; gap: 2px; }
.nav a {
  padding: 7px 12px; border-radius: 8px;
  color: #b9c0cf; font-size: 13.5px; font-weight: 500;
}
.nav a:hover { background: rgba(255,255,255,.07); color: #fff; }
.nav a.active { background: rgba(255,255,255,.12); color: #fff; }

.top-right { margin-left: auto; display: flex; align-items: center; gap: 10px; }
.search {
  display: flex; align-items: center; gap: 7px;
  background: rgba(255,255,255,.08);
  border: 1px solid rgba(255,255,255,.09);
  border-radius: 8px; padding: 6px 10px; width: 190px;
  color: #9aa3b4; font-size: 13px;
}
.search input {
  border: 0; background: transparent; outline: none;
  color: #e8ebf2; width: 100%; font: inherit;
}
.search input::placeholder { color: #8b93a5; }

.btn {
  border: 1px solid var(--border);
  background: var(--panel);
  color: var(--text);
  border-radius: 8px;
  padding: 7px 13px;
  font-size: 13.5px;
  font-weight: 500;
  display: inline-flex; align-items: center; gap: 6px;
}
.btn:hover { background: var(--panel-2); }
.btn-primary {
  background: var(--primary); border-color: var(--primary); color: #fff;
}
.btn-primary:hover { background: #4338ca; }
.btn-ghost { background: rgba(255,255,255,.08); border-color: transparent; color: #dfe4ee; }
.btn-ghost:hover { background: rgba(255,255,255,.14); }
.btn-sm { padding: 5px 10px; font-size: 12.5px; }
.btn-danger { color: var(--err); border-color: #f3d2d2; }
.btn-danger:hover { background: var(--err-soft); }

.avatar {
  width: 30px; height: 30px; border-radius: 50%;
  background: linear-gradient(135deg, #6366f1, #0ea5e9);
  color: #fff; display: grid; place-items: center;
  font-size: 12px; font-weight: 700;
}

/* ---------- 布局 ---------- */
.shell { display: flex; min-height: calc(100vh - 56px); }

.sidebar {
  width: 226px; flex: 0 0 226px;
  background: var(--sidebar);
  color: #a8b0c0;
  padding: 14px 10px 24px;
  position: sticky; top: 56px;
  align-self: flex-start;
  height: calc(100vh - 56px);
  overflow-y: auto;
}
.side-group { margin-bottom: 16px; }
.side-group > .label {
  font-size: 11px; text-transform: uppercase; letter-spacing: .08em;
  color: #6d7689; padding: 6px 10px; font-weight: 600;
}
.sidebar a {
  display: flex; align-items: center; gap: 9px;
  padding: 8px 10px; border-radius: 8px;
  font-size: 13.5px; color: #b6bdcb;
}
.sidebar a:hover { background: rgba(255,255,255,.06); color: #fff; }
.sidebar a.active { background: var(--sidebar-2); color: #fff; box-shadow: inset 2px 0 0 #6d6bf5; }
.sidebar .ico { width: 16px; text-align: center; opacity: .85; }
.sidebar .pill {
  margin-left: auto; font-size: 10.5px; padding: 1px 6px;
  border-radius: 20px; background: #3a4256; color: #cfd6e4;
}
.sidebar .pill.new { background: #4f46e5; color: #fff; }

/* ---------- 内容区 ---------- */
.main { flex: 1; min-width: 0; padding: 22px 26px 60px; }
.page-head {
  display: flex; align-items: flex-start; gap: 14px;
  margin-bottom: 18px; flex-wrap: wrap;
}
.page-head h1 { margin: 0; font-size: 20px; font-weight: 700; letter-spacing: -.2px; }
.page-head p { margin: 3px 0 0; color: var(--muted); font-size: 13px; }
.page-head .actions { margin-left: auto; display: flex; gap: 8px; align-items: center; }

.card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 16px;
}
.card + .card { margin-top: 16px; }
.card-head {
  display: flex; align-items: center; gap: 10px; margin-bottom: 12px;
}
.card-head h2 { margin: 0; font-size: 14.5px; font-weight: 650; }
.card-head .sub { color: var(--muted-2); font-size: 12px; }
.card-head .right { margin-left: auto; display: flex; gap: 8px; }

.grid { display: grid; gap: 16px; }
.grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (max-width: 1100px) {
  .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.stat { display: flex; flex-direction: column; gap: 6px; }
.stat .k { color: var(--muted); font-size: 12.5px; }
.stat .v { font-size: 26px; font-weight: 750; letter-spacing: -.5px; }
.stat .d { font-size: 12px; color: var(--muted-2); }
.stat .v.mono { font-family: var(--mono); font-size: 22px; }

/* ---------- 表格 ---------- */
.table-wrap { overflow-x: auto; margin: 0 -16px -16px; padding: 0 16px 4px; }
table.tbl { width: 100%; border-collapse: collapse; font-size: 13px; }
table.tbl th {
  text-align: left; color: var(--muted); font-weight: 600;
  padding: 8px 10px; border-bottom: 1px solid var(--border);
  white-space: nowrap; font-size: 12px; text-transform: uppercase; letter-spacing: .04em;
}
table.tbl td {
  padding: 10px; border-bottom: 1px solid #f1f2f6; vertical-align: middle;
}
table.tbl tr:last-child td { border-bottom: 0; }
table.tbl tr:hover td { background: var(--panel-2); }
.mono { font-family: var(--mono); font-size: 12.5px; }
.nowrap { white-space: nowrap; }
.truncate { max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---------- 标签 ---------- */
.tag {
  display: inline-flex; align-items: center; gap: 5px;
  border-radius: 20px; padding: 2px 9px;
  font-size: 11.5px; font-weight: 600; white-space: nowrap;
}
.tag.ok { background: var(--ok-soft); color: var(--ok); }
.tag.warn { background: var(--warn-soft); color: var(--warn); }
.tag.err { background: var(--err-soft); color: var(--err); }
.tag.info { background: var(--info-soft); color: var(--info); }
.tag.mute { background: #f0f1f5; color: var(--muted); }
.tag.primary { background: var(--primary-soft); color: var(--primary); }
.tag .dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }

/* ---------- 进度条 ---------- */
.bar { height: 6px; background: #eef0f4; border-radius: 20px; overflow: hidden; min-width: 70px; }
.bar > i { display: block; height: 100%; background: var(--primary); border-radius: 20px; }
.bar.ok > i { background: var(--ok); }
.bar.err > i { background: var(--err); }

/* ---------- 表单 ---------- */
.field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 14px; }
.field > label { font-size: 12.5px; font-weight: 600; color: #374151; }
.field .hint { font-size: 11.5px; color: var(--muted-2); }
input[type="text"], input[type="number"], input[type="password"], input[type="email"], select, textarea {
  width: 100%; padding: 8px 11px;
  border: 1px solid var(--border); border-radius: 8px;
  background: #fff; color: var(--text); font: inherit; outline: none;
}
textarea { resize: vertical; min-height: 84px; }
input:focus, select:focus, textarea:focus { border-color: var(--primary); box-shadow: 0 0 0 3px rgba(79,70,229,.12); }
.row { display: flex; gap: 12px; flex-wrap: wrap; }
.row > * { flex: 1; min-width: 160px; }

.switch {
  width: 36px; height: 20px; border-radius: 20px; background: #d3d6dd;
  position: relative; display: inline-block; flex: 0 0 auto;
}
.switch::after {
  content: ""; position: absolute; top: 2px; left: 2px;
  width: 16px; height: 16px; border-radius: 50%; background: #fff;
  box-shadow: 0 1px 3px rgba(0,0,0,.25); transition: left .15s;
}
.switch.on { background: var(--ok); }
.switch.on::after { left: 18px; }

/* ---------- 提示条 ---------- */
.note {
  display: flex; gap: 9px; align-items: flex-start;
  border: 1px dashed #cfd4e0; background: #fafbff;
  color: #4b5563; border-radius: 9px; padding: 10px 12px;
  font-size: 12.5px; margin-bottom: 16px;
}
.note b { color: #1f2937; }
.note .k { font-family: var(--mono); font-size: 11.5px; background: #eef0ff; color: #4338ca; padding: 1px 5px; border-radius: 5px; }

/* 右侧“元素来源”注记（原型专用，方便你划清单） */
.src {
  float: right; font-size: 11px; color: var(--muted-2);
  border: 1px solid var(--border); border-radius: 20px;
  padding: 2px 9px; background: var(--panel-2); font-weight: 500;
}
.src.keep { border-color: #bfe6cd; background: var(--ok-soft); color: var(--ok); }
.src.todo { border-color: #f0d9b5; background: var(--warn-soft); color: var(--warn); }

/* ---------- playground ---------- */
.play { display: grid; grid-template-columns: 300px minmax(0, 1fr); gap: 16px; }
@media (max-width: 1000px) { .play { grid-template-columns: 1fr; } }
.model-item {
  border: 1px solid var(--border); border-radius: 9px; padding: 10px 11px;
  margin-bottom: 8px; cursor: pointer;
}
.model-item:hover { border-color: #c7cbd8; }
.model-item.on { border-color: var(--primary); background: var(--primary-soft); }
.model-item .n { font-weight: 650; font-size: 13.5px; display: flex; align-items: center; gap: 7px; }
.model-item .m { color: var(--muted); font-size: 12px; margin-top: 3px; display: flex; gap: 8px; flex-wrap: wrap; }

.chips { display: flex; flex-wrap: wrap; gap: 8px; margin: 10px 0 14px; }
.chip {
  border: 1px solid var(--border); background: var(--panel);
  border-radius: 20px; padding: 5px 12px; font-size: 12.5px; color: #4b5563;
}
.chip:hover { border-color: var(--primary); color: var(--primary); }

.bubble {
  background: var(--panel-2); border: 1px solid var(--border);
  border-radius: 10px; padding: 11px 12px; font-size: 13px; color: #374151;
}
.bubble.me { background: var(--primary-soft); border-color: #dcdcfb; }

/* ---------- 画布 ---------- */
.canvas-host {
  position: relative; height: 460px; border-radius: var(--radius);
  border: 1px solid var(--border); overflow: hidden;
  background-color: #fbfbfd;
  background-image: radial-gradient(#e2e5ee 1px, transparent 1px);
  background-size: 18px 18px;
}
.canvas-tools {
  position: absolute; left: 12px; top: 12px; z-index: 4;
  display: flex; gap: 6px; background: #fff; border: 1px solid var(--border);
  border-radius: 9px; padding: 5px; box-shadow: var(--shadow);
}
.canvas-tools button {
  border: 0; background: transparent; border-radius: 6px;
  padding: 5px 9px; font-size: 12.5px; color: #4b5563;
}
.canvas-tools button:hover { background: var(--panel-2); }
.canvas-tools button.on { background: var(--primary-soft); color: var(--primary); }
.canvas-zoom {
  position: absolute; right: 12px; bottom: 12px; z-index: 4;
  display: flex; align-items: center; gap: 8px;
  background: #fff; border: 1px solid var(--border); border-radius: 9px;
  padding: 5px 10px; font-size: 12.5px; box-shadow: var(--shadow);
}
.node {
  position: absolute; width: 176px;
  background: #fff; border: 1px solid var(--border); border-radius: 11px;
  box-shadow: var(--shadow); overflow: hidden;
}
.node.on { border-color: var(--primary); box-shadow: 0 0 0 3px rgba(79,70,229,.15), var(--shadow); }
.node .h {
  padding: 8px 10px; font-size: 12.5px; font-weight: 650;
  border-bottom: 1px solid var(--border); display: flex; align-items: center; gap: 6px;
}
.node .b { padding: 10px; font-size: 12px; color: var(--muted); }
.node .thumb {
  height: 74px; border-radius: 7px; margin-bottom: 8px;
  background: linear-gradient(135deg, #e9ecf6, #dfe4f3);
  display: grid; place-items: center; color: #98a0b3; font-size: 11px;
}
.canvas-svg { position: absolute; inset: 0; pointer-events: none; }

/* ---------- 其它 ---------- */
.empty {
  border: 1px dashed #d8dbe4; border-radius: var(--radius);
  padding: 34px; text-align: center; color: var(--muted-2); font-size: 13px;
}
.kv { display: grid; grid-template-columns: 150px 1fr; gap: 10px 14px; font-size: 13px; }
.kv dt { color: var(--muted); }
.kv dd { margin: 0; }
.footnote { color: var(--muted-2); font-size: 12px; margin-top: 10px; }
hr.sep { border: 0; border-top: 1px solid var(--border); margin: 18px 0; }
.hidden { display: none !important; }
.right { margin-left: auto; }
.flex { display: flex; align-items: center; gap: 10px; }

/* ---------- 图表（纯 CSS/SVG，零依赖） ---------- */
.chart { width: 100%; height: 190px; display: block; }
.chart .axis { stroke: #e6e8ee; stroke-width: 1; }
.chart .grid { stroke: #f1f2f6; stroke-width: 1; }
.chart .line { fill: none; stroke: var(--primary); stroke-width: 2.5; stroke-linejoin: round; stroke-linecap: round; }
.chart .area { fill: url(#grad); opacity: .18; }
.chart .pt { fill: #fff; stroke: var(--primary); stroke-width: 2; }
.chart .tick { fill: #9aa1ad; font-size: 10.5px; font-family: var(--mono); }
.chart-2 { stroke: #0ea5e9; stroke-dasharray: 4 4; stroke-width: 2; fill: none; }

.bars { display: flex; align-items: flex-end; gap: 12px; height: 170px; padding-top: 20px; }
.bars > .col { flex: 1; display: flex; flex-direction: column; justify-content: flex-end; height: 100%; }
.bars > .col > .v {
  border-radius: 6px 6px 0 0;
  background: linear-gradient(180deg, #8b8bf5, #4f46e5);
  position: relative; min-height: 3px;
}
.bars > .col > .v.alt { background: linear-gradient(180deg, #67d3f5, #0ea5e9); }
.bars > .col > .v > b {
  position: absolute; top: -17px; left: 0; right: 0; text-align: center;
  font-size: 11px; font-weight: 600; color: var(--muted); font-family: var(--mono);
}
.bars-x { display: flex; gap: 12px; margin-top: 8px; }
.bars-x > span { flex: 1; text-align: center; font-size: 11.5px; color: var(--muted-2); font-family: var(--mono); }

.donut { display: flex; align-items: center; gap: 18px; }
.legend { display: flex; flex-direction: column; gap: 9px; font-size: 12.5px; }
.legend .li { display: flex; align-items: center; gap: 8px; }
.legend .sw { width: 10px; height: 10px; border-radius: 3px; }
.legend .mono { margin-left: auto; color: var(--muted); }

.spark { height: 34px; width: 90px; }
.form-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 16px; }
@media (max-width: 1000px) { .form-grid { grid-template-columns: 1fr; } }

/* ============================================================
   真实应用补充样式（登录页 / toast / 图表 / 产物 / 分页）
   ============================================================ */

.boot { display: grid; place-items: center; min-height: 60vh; color: var(--muted-2); }

.auth-wrap { min-height: 100vh; display: grid; place-items: center; padding: 24px; }
.auth-card { width: 100%; max-width: 400px; padding: 26px; }
.auth-card h1 { margin: 0 0 18px; font-size: 19px; }

.toast-host {
  position: fixed; right: 20px; bottom: 20px; z-index: 100;
  display: flex; flex-direction: column; gap: 10px;
}
.toast {
  background: #1f2937; color: #fff; padding: 10px 14px; border-radius: 9px;
  font-size: 13px; box-shadow: var(--shadow); max-width: 380px;
  opacity: 0; transform: translateY(8px); transition: opacity .2s, transform .2s;
}
.toast.show { opacity: 1; transform: none; }
.toast.err { background: #b91c1c; }
.toast.ok { background: #15803d; }

.chart { width: 100%; height: 170px; display: block; }
.linechart { display: flex; gap: 10px; }
.lc-y {
  display: flex; flex-direction: column; justify-content: space-between;
  font: 10.5px var(--mono); color: var(--muted-2); text-align: right;
  padding-bottom: 24px; min-width: 44px;
}
.lc-body { flex: 1; min-width: 0; }
.lc-x {
  display: flex; justify-content: space-between;
  font: 10.5px var(--mono); color: var(--muted-2); margin-top: 6px;
}
.donut-svg { width: 130px; height: 130px; display: block; margin: 6px auto 14px; }
.donut-top { font: 700 17px var(--mono); fill: #1a1d26; }
.donut-sub { font: 11px sans-serif; fill: #9aa1ad; }

.error-state { border-color: #f3d2d2; color: var(--err); background: var(--err-soft); }
.loading { color: var(--muted-2); }

.asset-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(118px, 1fr)); gap: 10px; }
.asset { border: 1px solid var(--border); border-radius: 8px; overflow: hidden; background: #fff; }
.asset img, .asset .ph {
  width: 100%; height: 100px; object-fit: cover; display: grid; place-items: center;
  background: linear-gradient(135deg, #eef1f9, #dde3f4); color: #98a0b3; font-size: 11px;
}
.asset .cap { padding: 6px 8px; font-size: 11.5px; color: var(--muted); }

.bar > i { transition: width .3s ease; }
.row-actions { display: flex; gap: 6px; justify-content: flex-end; }
.pager { display: flex; align-items: center; gap: 10px; margin-top: 12px; font-size: 12.5px; color: var(--muted); }
.code {
  font: 12.5px var(--mono); background: #f5f6fa; border: 1px solid var(--border);
  border-radius: 8px; padding: 8px 10px; word-break: break-all;
}

/* ---------- 弹窗 ---------- */
.modal-mask {
  position: fixed; inset: 0; z-index: 200;
  background: rgba(16, 24, 40, .45);
  display: grid; place-items: center; padding: 20px;
}
.modal-box {
  background: #fff; border-radius: 12px; padding: 20px;
  width: 100%; max-width: 430px;
  box-shadow: 0 20px 60px -20px rgba(0, 0, 0, .45);
}
.modal-box h3 { margin: 0 0 6px; font-size: 16px; }
.modal-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 16px; }
.modal-tip {
  background: var(--err-soft); color: var(--err);
  border-radius: 8px; padding: 8px 10px; font-size: 12.5px; margin-top: 10px;
}
.mono-cell { font-family: var(--mono); font-size: 12.5px; }

/* ---------- 侧栏底部固定区 ---------- */
.sidebar { display: flex; flex-direction: column; }
.side-bottom {
  margin-top: auto;
  padding-top: 10px;
  border-top: 1px solid rgba(255, 255, 255, .09);
}

/* ---------- 工作台 ---------- */
.welcome {
  background: linear-gradient(120deg, #1b2130 0%, #2b3350 55%, #3b3f7a 100%);
  color: #eef0f7;
  border-radius: 12px;
  padding: 22px 24px;
  margin-bottom: 16px;
}
.welcome .kicker {
  font-size: 11px; letter-spacing: .16em; text-transform: uppercase;
  color: #9aa6d6; font-weight: 700;
}
.welcome h2 { margin: 8px 0 4px; font-size: 22px; letter-spacing: -.3px; }
.welcome p { margin: 0 0 14px; color: #b7bfe0; font-size: 13px; }
.welcome .btn { background: #fff; color: #1b2130; border-color: #fff; }
.welcome .btn:hover { background: #eef0f7; }

.model-cards { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; }
@media (max-width: 1000px) { .model-cards { grid-template-columns: 1fr; } }
.model-card {
  border: 1px solid var(--border); border-radius: 12px; background: #fff;
  padding: 16px; display: flex; flex-direction: column; gap: 8px;
}
.model-card .ttl { font-size: 15px; font-weight: 700; display: flex; align-items: center; gap: 8px; }
.model-card .price { color: var(--muted); font-size: 12.5px; }
.model-card .acts { margin-top: auto; display: flex; gap: 8px; flex-wrap: wrap; }
.model-card .blurb { color: var(--muted); font-size: 12.5px; line-height: 1.6; }

/* ---------- 项目卡片 ---------- */
.proj-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 14px; }
.proj-card {
  border: 1px solid var(--border); border-radius: 10px; background: #fff;
  overflow: hidden; display: flex; flex-direction: column;
}
.proj-card .cover {
  height: 96px; background: linear-gradient(135deg, #eef1f9, #dde3f4);
  display: grid; place-items: center; color: #9aa0b4; font-size: 12px;
  border-bottom: 1px solid var(--border);
}
.proj-card .meta { padding: 10px 12px; display: flex; flex-direction: column; gap: 4px; }
.proj-card .nm { font-size: 13.5px; font-weight: 600; display: flex; align-items: center; gap: 6px; }
.proj-card .sub { font-size: 11.5px; color: var(--muted-2); }
.proj-card .acts { display: flex; gap: 6px; padding: 0 12px 12px; }

.tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--border); margin-bottom: 16px; }
.tabs a {
  padding: 8px 14px; font-size: 13.5px; color: var(--muted);
  border-bottom: 2px solid transparent; cursor: pointer;
}
.tabs a:hover { color: var(--text); }
.tabs a.on { color: var(--primary); border-bottom-color: var(--primary); font-weight: 600; }

/* ============================================================
   画布页（React Flow）
   ============================================================ */
.canvas-host {
  position: fixed; inset: 56px 0 0 0;   /* 顶栏以下 */
  /* 底色对齐参考站：比纯白略灰一点，点阵才看得出来 */
  background: #eef1f5;
}
.canvas-host .react-flow { background: transparent; }

/* 顶部条 */
.cv-topbar {
  position: absolute; top: 12px; left: 12px; right: 12px; z-index: 12;
  display: flex; align-items: center; gap: 10px;
  background: rgba(255,255,255,.96); border: 1px solid var(--border);
  border-radius: 10px; padding: 8px 10px; box-shadow: var(--shadow);
}
.cv-topbar .name { font-weight: 650; font-size: 14px; }
.cv-topbar .save-state { font-size: 11.5px; color: var(--muted-2); }
.cv-topbar .right { margin-left: auto; display: flex; align-items: center; gap: 8px; }

/* 底部浮动工具栏 */
.cv-toolbar {
  position: absolute; bottom: 18px; left: 50%; transform: translateX(-50%); z-index: 12;
  display: flex; align-items: center; gap: 6px;
  background: rgba(255,255,255,.98); border: 1px solid var(--border);
  border-radius: 12px; padding: 6px; box-shadow: var(--shadow);
}
.cv-toolbar button {
  border: 0; background: transparent; border-radius: 8px;
  padding: 7px 11px; font-size: 13px; color: #3f4756; cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px;
}
.cv-toolbar button:hover { background: var(--panel-2); }
.cv-toolbar button.primary { background: var(--primary); color: #fff; }
.cv-toolbar button.primary:hover { background: #4338ca; }
.cv-sep { width: 1px; height: 22px; background: var(--border); margin: 0 3px; }

/* 左下角：缩放 + 返回 */
.cv-hint {
  background: rgba(30,30,28,.72) !important;
  color: #e6e6e0 !important;
  position: absolute; left: 14px; bottom: 20px; z-index: 11;
  font-size: 11.5px; color: var(--muted-2);
  background: rgba(255,255,255,.9); border: 1px solid var(--border);
  border-radius: 8px; padding: 6px 10px;
}

/* 画布节点 */
.cn {
  width: 232px; background: #fff; border: 1px solid var(--border);
  border-radius: 11px; box-shadow: var(--shadow); overflow: hidden;
  font-size: 12.5px;
}
.cn.sel { border-color: var(--primary); box-shadow: 0 0 0 3px rgba(79,70,229,.16), var(--shadow); }
.cn-head {
  display: flex; align-items: center; gap: 6px;
  padding: 7px 10px; border-bottom: 1px solid var(--border);
  font-weight: 650; font-size: 12.5px; background: var(--panel-2);
}
.cn-kind {
  font-size: 10.5px; padding: 1px 7px; border-radius: 20px;
  background: var(--primary-soft); color: var(--primary); font-weight: 600;
}
.cn-kind.video { background: var(--info-soft); color: var(--info); }
.cn-kind.text { background: #f0f1f5; color: var(--muted); }
.cn-body { padding: 10px; display: flex; flex-direction: column; gap: 8px; }
/*
 * 注意选择器特异性：
 *   `.cn textarea` 是「类 + 元素」= (0,1,1)，
 *   比后面 `.cn-prompt` / `.cn-pill` 那种纯类选择器 (0,1,0) 优先级更高，
 *   会把它们写的 padding / min-height 全部盖掉
 *   —— 之前调节点间距怎么改都不生效，就是卡在这儿。
 *   所以这里用 :not() 把带自己类名的排除掉。
 */
.cn textarea:not(.cn-prompt),
.cn select:not(.cn-pill),
.cn input:not(.cn-pill) {
  width: 100%; font: inherit; font-size: 12.5px;
  border: 1px solid var(--border); border-radius: 7px; padding: 6px 8px;
  resize: vertical; outline: none; background: #fff;
}
.cn textarea:not(.cn-prompt) { min-height: 56px; }
.cn textarea:focus, .cn select:focus { border-color: var(--primary); }
.cn-foot { display: flex; align-items: center; gap: 6px; }
.cn-foot .btn { padding: 4px 10px; font-size: 12px; }
.cn-status { font-size: 11px; color: var(--muted-2); margin-left: auto; }
.cn-thumb {
  border-radius: 7px; overflow: hidden; background: linear-gradient(135deg,#eef1f9,#dde3f4);
  min-height: 90px; display: grid; place-items: center; color: #9aa0b4;
}
.cn-thumb img, .cn-thumb video { width: 100%; display: block; }
.cn .react-flow__handle {
  /* 原来是 9px —— 画布一缩小就几乎点不中。18px 比较顺手。 */
  width: 18px;
  height: 18px;
  background: var(--primary);
  border: 2px solid #fff;
  box-shadow: 0 1px 4px rgba(16, 24, 40, .28);
}
/*
 * 透明热区：视觉上还是 18px 的小圆点，但可点范围再往外扩 12px。
 * React Flow 拖拽靠的是 handle 元素本身，所以扩热区能真的让连线更好拖。
 */
.cn .react-flow__handle::after {
  content: "";
  position: absolute;
  inset: -12px;
  border-radius: 50%;
}

/* ---------- 画布右键菜单 ---------- */
.ctx-menu {
  position: fixed; z-index: 60;
  min-width: 196px; background: #fff; border: 1px solid var(--border);
  border-radius: 10px; padding: 5px; display: flex; flex-direction: column;
  box-shadow: 0 12px 32px -8px rgba(16, 24, 40, .28);
}
.ctx-menu button {
  border: 0; background: transparent; text-align: left;
  padding: 7px 10px; border-radius: 7px; font-size: 13px;
  color: #3f4756; cursor: pointer; font-family: inherit;
}
.ctx-menu button:hover:not(:disabled) { background: var(--panel-2); }
.ctx-menu button:disabled { color: var(--muted-2); cursor: default; }
.ctx-menu button.danger { color: var(--err); }
.ctx-menu button.danger:hover { background: var(--err-soft); }
.ctx-sep { height: 1px; background: var(--border); margin: 4px 6px; }

/* ---------- 产物缩略图（生成记录 / 创作中心） ---------- */
.thumb-row { display: flex; gap: 6px; flex-wrap: wrap; }
.thumb {
  width: 46px; height: 46px; object-fit: cover; border-radius: 6px;
  border: 1px solid var(--border); cursor: zoom-in; background: #f5f6fa;
  transition: border-color .15s, transform .15s;
}
.thumb:hover { border-color: var(--primary); transform: scale(1.06); }
.thumb-video { display: block; background: #111; }
.thumb-audio {
  display: grid; place-items: center; padding: 0; color: var(--primary);
  font-size: 22px; line-height: 1; font-family: inherit;
}
.asset img { cursor: zoom-in; }
.asset video { width: 100%; min-height: 160px; background: #000; display: block; }
.asset audio { width: calc(100% - 20px); margin: 34px 10px; }

/* ============================================================
   登录页：动态背景（纯 CSS，零依赖）
   几团缓慢漂浮的彩色光斑 + 细网格 + 毛玻璃卡片。
   动画只用 transform / opacity，GPU 合成，不占 CPU。
   ============================================================ */
.auth-wrap {
  position: relative; overflow: hidden;
  background:
    radial-gradient(1100px 700px at 18% 8%, #1c2a63 0%, transparent 60%),
    radial-gradient(900px 640px at 88% 92%, #3b1a66 0%, transparent 58%),
    linear-gradient(165deg, #070b18 0%, #0c1226 52%, #080c1c 100%);
}
.auth-bg { position: absolute; inset: 0; overflow: hidden; pointer-events: none; }
.auth-bg .blob {
  position: absolute; display: block; border-radius: 50%;
  filter: blur(72px); opacity: .55; will-change: transform;
  animation: blobFloat 26s ease-in-out infinite;
}
.auth-bg .b1 { width: 520px; height: 520px; left: -9%; top: -14%; background: #4f46e5; }
.auth-bg .b2 { width: 460px; height: 460px; right: -7%; top: 6%; background: #0ea5e9;
               animation-delay: -6s;  animation-duration: 32s; }
.auth-bg .b3 { width: 430px; height: 430px; left: 22%; bottom: -20%; background: #a855f7;
               animation-delay: -13s; animation-duration: 29s; }
.auth-bg .b4 { width: 300px; height: 300px; right: 16%; bottom: -12%; background: #22d3ee;
               animation-delay: -19s; animation-duration: 35s; }
@keyframes blobFloat {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
  33%      { transform: translate3d(72px, -52px, 0) scale(1.18); }
  66%      { transform: translate3d(-62px, 58px, 0) scale(.88); }
}
.auth-bg .grid-lines {
  position: absolute; inset: 0; opacity: .06;
  background-image:
    linear-gradient(#fff 1px, transparent 1px),
    linear-gradient(90deg, #fff 1px, transparent 1px);
  background-size: 48px 48px;
  -webkit-mask-image: radial-gradient(circle at 50% 42%, #000 0%, transparent 76%);
  mask-image: radial-gradient(circle at 50% 42%, #000 0%, transparent 76%);
}
/* 系统开了「减少动态效果」就不动，尊重无障碍设置 */
@media (prefers-reduced-motion: reduce) {
  .auth-bg .blob { animation: none; }
}

/* 卡片：毛玻璃 + 深色配色 */
.auth-card {
  position: relative; z-index: 1;
  background: rgba(13, 18, 34, .74);
  border: 1px solid rgba(255, 255, 255, .10);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  box-shadow: 0 28px 80px -24px rgba(0, 0, 0, .75);
  padding: 26px;
}
.auth-brand {
  display: flex; align-items: center; gap: 9px;
  margin-bottom: 16px; padding-bottom: 14px;
  border-bottom: 1px solid rgba(255, 255, 255, .08);
}
.auth-brand .logo {
  width: 30px; height: 30px; border-radius: 8px;
  background: linear-gradient(135deg, #6d6bf5, #38bdf8);
  display: grid; place-items: center;
  font-size: 13px; font-weight: 800; color: #fff;
}
.auth-brand .nm { font-weight: 700; font-size: 15px; color: #eef1f8; }
.auth-card h1 { color: #f2f5fc; font-size: 18px; }
.auth-card .field > label { color: #aeb8ce; }
.auth-card input {
  background: rgba(255, 255, 255, .06);
  border-color: rgba(255, 255, 255, .13);
  color: #eef1f8;
}
.auth-card input::placeholder { color: #6d7993; }
.auth-card input:focus {
  border-color: #6d6bf5;
  box-shadow: 0 0 0 3px rgba(109, 107, 245, .22);
  background: rgba(255, 255, 255, .09);
}
.auth-card hr.sep { border-top-color: rgba(255, 255, 255, .09); }
.auth-card .btn:not(.btn-primary) {
  background: rgba(255, 255, 255, .07);
  border-color: rgba(255, 255, 255, .13);
  color: #dfe5f2;
}
.auth-card .btn:not(.btn-primary):hover { background: rgba(255, 255, 255, .13); }
.auth-card .footnote { color: #8590a8; }

/* ============================================================
   登录页背景图支持
   约定：把图片放到 web/assets/login-bg.jpg（或 .png / .webp），
   这里会自动用它当背景；文件不存在就退回上面的渐变 + 光斑，
   不会报错也不会白屏（CSS 图片加载失败是静默的）。
   ============================================================ */
.auth-wrap {
  background:
    linear-gradient(180deg, rgba(6, 10, 22, .55) 0%, rgba(6, 10, 22, .78) 100%),
    url("./assets/login-bg.jpg") center / cover no-repeat,
    radial-gradient(1100px 700px at 18% 8%, #1c2a63 0%, transparent 60%),
    radial-gradient(900px 640px at 88% 92%, #3b1a66 0%, transparent 58%),
    linear-gradient(165deg, #070b18 0%, #0c1226 52%, #080c1c 100%);
}
/* 有背景图时，光斑稍微收一点，别把画面糊住 */
.auth-bg .blob { opacity: .38; }
.auth-bg .grid-lines { opacity: .045; }

/* ============================================================
   白色极简主题（对齐 DreamMaker：纯白 + 暖橙点缀）
   ------------------------------------------------------------
   原来顶栏/侧栏是深色（#1b2130），这里整体改成白底。
   登录页的 .auth-* 样式是独立的一套，不受影响。
   ============================================================ */
:root {
  --bg: #fafafa;
  --panel: #ffffff;
  --panel-2: #f7f8fa;
  --sidebar: #ffffff;
  --sidebar-2: #fff1e9;
  --topbar: #ffffff;
  --border: #ebedf0;
  --primary: #ff7a45;
  --primary-soft: #fff1e9;
  --shadow: 0 1px 2px rgba(16, 24, 40, .04), 0 8px 24px -18px rgba(16, 24, 40, .14);
}

body { background: #fafafa; }

/* ---------- 顶栏：白底 + 细边框 ---------- */
.topbar {
  background: #fff;
  color: var(--text);
  border-bottom: 1px solid var(--border);
}
.brand { color: var(--text); }
.brand .logo { background: linear-gradient(135deg, #ff9a6b, #ff7a45); }
.nav a { color: var(--muted); }
.nav a:hover { background: var(--panel-2); color: var(--text); }
.nav a.active { background: var(--primary-soft); color: var(--primary); }
.search {
  background: var(--panel-2);
  border-color: var(--border);
  color: var(--muted);
}
.search input { color: var(--text); }
.search input::placeholder { color: var(--muted-2); }
.btn-ghost {
  background: var(--panel-2);
  color: var(--text);
  border: 1px solid var(--border);
}
.btn-ghost:hover { background: #eef0f3; }
.avatar { background: linear-gradient(135deg, #ff9a6b, #ff7a45); }

/* ---------- 侧栏：白底 + 深色文字 + 橙色高亮 ---------- */
.sidebar {
  background: #fff;
  color: var(--muted);
  border-right: 1px solid var(--border);
}
.side-group > .label { color: var(--muted-2); }
.sidebar a { color: #4b5563; }
.sidebar a:hover { background: var(--panel-2); color: var(--text); }
.sidebar a.active {
  background: var(--primary-soft);
  color: var(--primary);
  box-shadow: inset 2px 0 0 var(--primary);
  font-weight: 600;
}
.sidebar .pill { background: #eef0f3; color: var(--muted); }
.sidebar .pill.new { background: var(--primary); color: #fff; }
.side-bottom { border-top: 1px solid var(--border); }

/* ---------- 工作台欢迎区：淡橙，不再是深色渐变 ---------- */
.welcome {
  background: linear-gradient(120deg, #fff6f1 0%, #ffe9dc 100%);
  color: var(--text);
  border: 1px solid #ffe1d2;
}
.welcome .kicker { color: #ff7a45; }
.welcome p { color: var(--muted); }
.welcome .btn {
  background: var(--primary);
  border-color: var(--primary);
  color: #fff;
}
.welcome .btn:hover { background: #f26a33; }

/* ---------- 画布顶部条与工具栏也跟着换成白 ---------- */
.cv-topbar, .cv-toolbar { background: rgba(255, 255, 255, .97); }
.cv-toolbar button.primary { background: var(--primary); }
.cv-toolbar button.primary:hover { background: #f26a33; }

/* ---------- 画布空态 / 模板卡 ---------- */
.cv-empty {
  position: absolute; inset: 0; z-index: 5;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 4px;
  pointer-events: none;   /* 空白处仍然能双击加节点 */
}
.cv-empty h2 { margin: 0; font-size: 20px; color: var(--text); letter-spacing: -.2px; }
.cv-empty > p { margin: 0 0 16px; color: var(--muted); font-size: 13px; }
.cv-tpl-grid {
  display: grid; grid-template-columns: repeat(4, 208px); gap: 12px;
  pointer-events: auto;
}
@media (max-width: 1100px) { .cv-tpl-grid { grid-template-columns: repeat(2, 200px); } }
.cv-tpl {
  background: #fff; border: 1px solid var(--border); border-radius: 12px;
  padding: 14px 15px; cursor: pointer;
  box-shadow: 0 1px 2px rgba(16, 24, 40, .04);
  transition: transform .16s, box-shadow .16s, border-color .16s;
}
.cv-tpl:hover {
  border-color: var(--primary);
  transform: translateY(-2px);
  box-shadow: 0 10px 26px -14px rgba(255, 122, 69, .55);
}
.cv-tpl-icon {
  width: 34px; height: 34px; border-radius: 9px;
  background: var(--primary-soft); color: var(--primary);
  display: grid; place-items: center; font-size: 17px;
}
.cv-tpl-name { font-weight: 650; font-size: 13.5px; margin: 8px 0 4px; }
.cv-tpl-desc { font-size: 12px; color: var(--muted); line-height: 1.55; }

/* ============================================================
   主题切换：浅色 / 深色 / 跟随系统
   ------------------------------------------------------------
   所有颜色都走变量，切换时只换 <html data-theme="...">。
   深色的具体取值集中在 [data-theme="dark"] 里，别散落在各处。
   ============================================================ */
:root {
  color-scheme: light;
  --hover: #f2f3f5;
  --topbar: #ffffff;
  --sidebar: #ffffff;
  --node-bg: #ffffff;
}

[data-theme="dark"] {
  color-scheme: dark;
  --bg: #101216;
  --panel: #171a20;
  --panel-2: #1c2028;
  --hover: #232830;
  --topbar: #171a20;
  --sidebar: #171a20;
  --sidebar-2: #33210f;
  --node-bg: #1c2028;
  --border: #282d37;
  --text: #e9ecf1;
  --muted: #99a2b0;
  --muted-2: #6d7684;
  --primary: #ff8a5c;
  --primary-soft: #33210f;
  --shadow: 0 1px 2px rgba(0, 0, 0, .3), 0 10px 30px -18px rgba(0, 0, 0, .6);
}

/* ---------- 顶栏 / 侧栏：跟着主题走 ---------- */
.topbar { background: var(--topbar); }
.sidebar { background: var(--sidebar); }
.btn-ghost:hover { background: var(--hover); }
.sidebar .pill { background: var(--hover); }
body { background: var(--bg); }

/* ---------- 深色下把写死的白色面板统一换掉 ---------- */
[data-theme="dark"] .model-card,
[data-theme="dark"] .proj-card,
[data-theme="dark"] .asset,
[data-theme="dark"] .cn,
[data-theme="dark"] .cv-tpl,
[data-theme="dark"] .modal-box,
[data-theme="dark"] .ctx-menu,
[data-theme="dark"] .canvas-tools,
[data-theme="dark"] .canvas-zoom {
  background: var(--node-bg);
  border-color: var(--border);
  color: var(--text);
}

[data-theme="dark"] .cv-topbar,
[data-theme="dark"] .cv-toolbar {
  background: rgba(23, 26, 32, .97);
  border-color: var(--border);
}
[data-theme="dark"] .cv-hint { background: rgba(23, 26, 32, .9); border-color: var(--border); }
[data-theme="dark"] .canvas-host,
[data-theme="dark"] .canvas-host .react-flow { background: #14171c; }
[data-theme="dark"] .canvas-host {
  background-color: #14171c;
  background-image: radial-gradient(#252a33 1px, transparent 1px);
}

/* 输入控件 */
[data-theme="dark"] input,
[data-theme="dark"] select,
[data-theme="dark"] textarea,
[data-theme="dark"] .cn input,
[data-theme="dark"] .cn select,
[data-theme="dark"] .cn textarea {
  background: var(--panel-2);
  border-color: var(--border);
  color: var(--text);
}

/* 表格 */
[data-theme="dark"] .tbl th { border-bottom-color: var(--border); color: var(--muted); }
[data-theme="dark"] .tbl td { border-bottom-color: #22262e; }
[data-theme="dark"] .tbl tr:hover td { background: var(--panel-2); }

/* 工作台的欢迎区：深色下换成暗橙 */
[data-theme="dark"] .welcome {
  background: linear-gradient(120deg, #241813 0%, #33200f 100%);
  border-color: #3d2716;
  color: var(--text);
}

/* 杂项 */
[data-theme="dark"] .thumb,
[data-theme="dark"] .cn-thumb,
[data-theme="dark"] .proj-card .cover { background: #232830; }
[data-theme="dark"] .empty { border-color: var(--border); }
[data-theme="dark"] .code { background: #1c2028; border-color: var(--border); }
[data-theme="dark"] .toast { background: #2a2f39; }
[data-theme="dark"] .bar { background: #262b34; }
[data-theme="dark"] .lc-y,
[data-theme="dark"] .lc-x { color: var(--muted-2); }

/* ---------- 主题选择器（顶栏） ---------- */
.theme-sel {
  width: auto;
  padding: 5px 8px;
  font-size: 12.5px;
  border-radius: 8px;
  background: var(--panel-2);
  border: 1px solid var(--border);
  color: var(--text);
  cursor: pointer;
}

/* ---------- 画布节点：补齐元素（工具条 / 参数 / 预估消耗） ---------- */
.cn { width: 258px; }               /* 宽一点，放得下一排工具 */
.cn-tools { display: flex; gap: 4px; flex-wrap: wrap; }
.cn-tool {
  border: 1px solid var(--border); background: var(--panel-2);
  border-radius: 6px; padding: 3px 7px; font-size: 11px;
  color: var(--muted); cursor: pointer; font-family: inherit;
  transition: border-color .14s, color .14s;
}
.cn-tool:hover { border-color: var(--primary); color: var(--primary); }
.cn-params { display: flex; gap: 6px; }
.cn-params select { flex: 1; min-width: 0; }
.cn-foot { align-items: center; }
.cn-cost { font-size: 12px; color: var(--muted); margin-right: auto; white-space: nowrap; }
.cn-status { font-size: 11px; color: var(--muted-2); text-align: right; min-height: 14px; }
[data-theme="dark"] .cn-tool { background: var(--panel-2); border-color: var(--border); }

/* ============================================================
   画布深色化 —— 对齐 DreamMaker 的无限画布
   采样自它的真实界面：顶栏 #47473d、画布底 #595a5a、工具条 #5f5f61
   注意画布**始终深色**，不跟随站点浅色/深色主题（DreamMaker 也这样）
   ============================================================ */
.canvas-host {
  background-color: #595a5a !important;
  background-image: radial-gradient(circle, rgba(255,255,255,.09) 1px, transparent 1px) !important;
  background-size: 22px 22px !important;
  color: #e9e9e6;
}
[data-theme="dark"] .canvas-host { background-color: #4a4a49 !important; }

/* 顶栏 */
.cv-topbar {
  background: #47473d !important;
  border-bottom: 1px solid rgba(255,255,255,.07) !important;
  color: #f0f0ec !important;
}
.cv-topbar .cv-btn,
.cv-topbar .cv-pill {
  color: #d8d8d2 !important;
  background: transparent !important;
  border-color: transparent !important;
}
.cv-topbar .cv-btn:hover,
.cv-topbar .cv-pill:hover {
  background: rgba(255,255,255,.09) !important;
  color: #fff !important;
}
.cv-topbar .cv-pill.primary {
  background: #e8e6dd !important;
  color: #2b2b26 !important;
}

/* 底部两排工具条 */
.cv-bar {
  background: #5f5f61 !important;
  border: 1px solid rgba(255,255,255,.08) !important;
  box-shadow: 0 8px 22px rgba(0,0,0,.28) !important;
}
.cv-bar button {
  color: #dededa !important;
}
.cv-bar button:hover {
  background: rgba(255,255,255,.13) !important;
  color: #fff !important;
}
.cv-bar button.active {
  background: rgba(255,255,255,.2) !important;
  color: #fff !important;
}

/* 画布上的节点在深底上要更清晰 */
.canvas-host .react-flow__node { --node-shadow: 0 6px 20px rgba(0,0,0,.35); }
.canvas-host .react-flow__node .cn { box-shadow: var(--node-shadow); }
.canvas-host .react-flow__handle {
  background: #e8e6dd !important;
  border-color: #47473d !important;
}
.canvas-host .react-flow__minimap { background: #4a4a49 !important; }
.canvas-host .react-flow__attribution { display: none; }

/* 空态模板卡在深底上的呈现 */
.canvas-host .cv-empty h2 { color: #f4f4f0; }
.canvas-host .cv-empty p { color: #c9c9c3; }
.canvas-host .cv-tpl {
  background: rgba(255,255,255,.07);
  border-color: rgba(255,255,255,.14);
  color: #ececE7;
}
.canvas-host .cv-tpl:hover {
  background: rgba(255,255,255,.13);
  border-color: rgba(255,255,255,.3);
}
.canvas-host .cv-tpl-name { color: #fff; }
.canvas-host .cv-tpl-desc { color: #c2c2bc; }

/* ============================================================
   画布外壳重做 —— 对齐 DreamMaker 的无限画布
   顶栏（回到首页/全部项目/项目名/画布N/作品广场/发布/分享/点数/账户）
   + 左下工具条（一屏控制）+ 底部中工具条（创作动作）
   ============================================================ */
.cv-topbar {
  position: absolute; top: 0; left: 0; right: 0;
  height: 52px; padding: 0 12px;
  display: flex; align-items: center; gap: 4px;
  z-index: 20;
}
.cv-name { font-weight: 650; font-size: 13.5px; padding: 0 6px; white-space: nowrap; }
.cv-crumb { font-size: 12px; opacity: .68; }
.cv-save { font-size: 11.5px; opacity: .62; margin-left: 6px; white-space: nowrap; }
.cv-spacer { flex: 1 1 auto; }

.cv-chip {
  display: inline-flex; align-items: center; justify-content: center;
  height: 30px; padding: 0 11px; gap: 5px;
  border: 1px solid transparent; border-radius: 8px; background: transparent;
  font: inherit; font-size: 12.5px; white-space: nowrap;
  cursor: pointer; transition: background .14s, color .14s, border-color .14s;
}
.cv-chip.primary { font-weight: 600; }

.cv-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; flex: 0 0 30px;
  border: 0; border-radius: 8px; background: transparent;
  font-size: 15px; line-height: 1; cursor: pointer;
  transition: background .14s;
}

.cv-points {
  display: inline-flex; align-items: center; height: 32px; padding: 0 12px;
  border: 1px solid transparent; border-radius: 8px; background: transparent;
  font: inherit; font-size: 12.5px; font-variant-numeric: tabular-nums;
  cursor: pointer; white-space: nowrap;
}

/* 底部两条工具条 */
.cv-bar {
  position: absolute; bottom: 16px;
  display: flex; align-items: center; gap: 2px;
  padding: 5px; border-radius: 11px;
  z-index: 20;
}
.cv-bar-left { left: 16px; }
.cv-bar-center { left: 50%; transform: translateX(-50%); }
.cv-bar .cv-chip { height: 28px; padding: 0 9px; font-size: 12px; }

/* 深色画布下，工具条按钮的文字和悬停 */
.canvas-host .cv-topbar { background: #47473d !important; }
.canvas-host .cv-topbar .cv-chip,
.canvas-host .cv-topbar .cv-icon,
.canvas-host .cv-topbar .cv-points { color: #d9d9d2; }
.canvas-host .cv-topbar .cv-chip:hover,
.canvas-host .cv-topbar .cv-icon:hover,
.canvas-host .cv-topbar .cv-points:hover { background: rgba(255,255,255,.1); color: #fff; }
.canvas-host .cv-topbar .cv-chip.primary { background: #e8e6dd; color: #2b2b26; }
.canvas-host .cv-topbar .cv-chip.primary:hover { background: #f3f1e9; }
.canvas-host .cv-topbar .cv-name { color: #f2f2ec; }
.canvas-host .cv-topbar .cv-crumb,
.canvas-host .cv-topbar .cv-save { color: #b9b9b0; }

.canvas-host .cv-bar { background: #5f5f61; border: 1px solid rgba(255,255,255,.09); }
.canvas-host .cv-bar .cv-chip { color: #dededa; }
.canvas-host .cv-bar .cv-chip:hover { background: rgba(255,255,255,.13); color: #fff; }
.canvas-host .cv-bar .cv-chip.primary { background: #e8e6dd; color: #2b2b26; font-weight: 600; }
.canvas-host .cv-bar .cv-chip.primary:hover { background: #f5f3eb; }

/* 提示条移到更低，别跟工具条打架 */
.canvas-host .cv-hint { bottom: 62px; opacity: .75; }

/* 反应流本身也用深色 */
.canvas-host .react-flow { background: transparent !important; }
.canvas-host .react-flow__controls {
  background: #5f5f61; border-radius: 9px; overflow: hidden;
  box-shadow: 0 4px 14px rgba(0,0,0,.3);
}
.canvas-host .react-flow__controls-button {
  background: transparent; border-bottom: 1px solid rgba(255,255,255,.08);
  fill: #dededa;
}
.canvas-host .react-flow__controls-button:hover { background: rgba(255,255,255,.13); }

/* ============================================================
   双击画布的节点选择器 + 画布弹窗（对齐 DreamMaker）
   ============================================================ */
.cv-picker {
  position: fixed; z-index: 40; width: 272px; padding: 10px;
  border-radius: 12px; background: #2f2f2c;
  border: 1px solid rgba(255,255,255,.12);
  box-shadow: 0 16px 40px rgba(0,0,0,.45);
}
.cv-picker-title {
  display: flex; align-items: center; gap: 5px;
  font-size: 11.5px; color: #a9a9a2; margin: 2px 2px 8px;
}
.cv-picker-grid {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: 6px; margin-bottom: 12px;
}
.cv-kind {
  position: relative; display: flex; align-items: center; justify-content: center; gap: 4px;
  height: 34px; border: 1px solid rgba(255,255,255,.1); border-radius: 8px;
  background: rgba(255,255,255,.05); color: #e8e8e2;
  font: inherit; font-size: 12.5px; cursor: pointer;
  transition: background .14s, border-color .14s;
}
.cv-kind:hover { background: rgba(255,255,255,.14); border-color: rgba(255,255,255,.28); }
.cv-kind.soon { color: #8d8d86; }
.cv-badge {
  font-size: 9px; font-style: normal; font-weight: 700; letter-spacing: .3px;
  color: #fff; background: #ff7a45; border-radius: 4px; padding: 1px 4px;
}

/* 弹窗（画布设置 / AI 水印 / 快捷键） */
.cv-mask {
  position: fixed; inset: 0; z-index: 60; background: rgba(0,0,0,.5);
  display: flex; align-items: center; justify-content: center;
}
.cv-panel {
  width: 480px; max-width: calc(100vw - 40px); max-height: 78vh;
  display: flex; flex-direction: column; overflow: hidden;
  background: #fff; border-radius: 14px;
  box-shadow: 0 24px 60px rgba(0,0,0,.4);
}
.cv-panel-head {
  padding: 14px 18px; font-weight: 650; font-size: 14.5px;
  border-bottom: 1px solid var(--border);
}
.cv-panel-body {
  padding: 16px 18px; overflow: auto;
  display: flex; flex-direction: column; gap: 14px;
}
.cv-panel-foot {
  padding: 12px 18px; border-top: 1px solid var(--border);
  display: flex; justify-content: flex-end; gap: 8px;
}
.cv-field { display: flex; flex-direction: column; gap: 8px; }
.cv-field label { font-size: 12.5px; color: var(--muted); }
.cv-seg {
  display: inline-flex; width: fit-content;
  border: 1px solid var(--border); border-radius: 9px; overflow: hidden;
}
.cv-seg button {
  border: 0; background: transparent; padding: 6px 18px;
  font: inherit; font-size: 12.5px; cursor: pointer;
}
.cv-seg button.on { background: var(--primary); color: #fff; }
.cv-note { font-size: 12.5px; line-height: 1.75; color: var(--muted); margin: 0; }
.cv-switch { display: flex; gap: 10px; align-items: flex-start; font-size: 13px; cursor: pointer; }
.cv-switch b { display: block; font-weight: 600; }
.cv-switch small { display: block; color: var(--muted); font-size: 11.5px; margin-top: 2px; }

.cv-keys { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.cv-keys td { padding: 6px 8px; border-bottom: 1px solid var(--border); }
.cv-keys .grp { color: var(--muted); width: 54px; }
.cv-keys .key { text-align: right; width: 112px; }
.cv-keys kbd {
  border: 1px solid var(--border); border-bottom-width: 2px; border-radius: 5px;
  padding: 1px 7px; font-size: 11.5px; background: var(--panel-2);
}

/* 右键菜单里右对齐的快捷键角标 */
.ctx-menu button { display: flex; align-items: center; width: 100%; }
.ctx-menu .ctx-hint { margin-left: auto; padding-left: 16px; font-size: 11px; color: #9aa1ad; }

/* ============================================================
   画布容器铺满
   原本用 `inset: 56px 0 0 0` 让 fixed 自适应，但实测高度被算成 460
   （祖先链上没有 transform/filter，原因不明）。直接给死高度，别赌自适应。
   ============================================================ */
.canvas-host {
  position: fixed !important;
  top: 56px !important;
  left: 0 !important;
  right: 0 !important;
  bottom: 0 !important;
  width: auto !important;
  height: calc(100vh - 56px) !important;
  overflow: hidden;
}

/* ============================================================
   表格里的迷你进度条（任务实时进度）
   ============================================================ */
.mini-bar {
  position: relative; width: 100%; min-width: 64px; height: 6px;
  border-radius: 999px; background: var(--panel-2, #eef0f4);
  overflow: hidden;
}
.mini-bar > i {
  display: block; height: 100%; width: 0;
  border-radius: 999px; background: var(--primary, #ff7a45);
  transition: width .45s ease;
}
td .mini-bar { margin: 2px 0; }

/* ============================================================
   节点参数：按钮组（替代原来的下拉框）
   ============================================================ */
.cn-param-list { display: flex; flex-direction: column; gap: 9px; }
.cn-param { display: flex; flex-direction: column; gap: 5px; }
.cn-param-label { font-size: 11px; color: var(--muted); }
.cn-seg { display: flex; flex-wrap: wrap; gap: 4px; }
.cn-seg button {
  border: 1px solid var(--border);
  background: var(--panel-2);
  border-radius: 6px;
  padding: 3px 9px;
  font: inherit;
  font-size: 11.5px;
  color: var(--muted);
  cursor: pointer;
  transition: background .14s, border-color .14s, color .14s;
}
.cn-seg button:hover { border-color: var(--primary); color: var(--primary); }
.cn-seg button.on {
  background: var(--primary);
  border-color: var(--primary);
  color: #fff;
  font-weight: 600;
}
/* 深色画布上也要看得清 */
[data-theme="dark"] .cn-seg button { background: #23242a; border-color: #33343c; }

/* ============================================================
   节点头：编号 + 可编辑标题 + 类型标签
   ============================================================ */
.cn-no {
  flex: 0 0 auto;
  font-size: 11px;
  font-weight: 700;
  color: var(--muted-2);
  font-variant-numeric: tabular-nums;
  letter-spacing: .02em;
}
.cn-title {
  flex: 1 1 auto;
  min-width: 0;
  border: 0;
  background: transparent;
  font: inherit;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text);
  padding: 2px 5px;
  border-radius: 5px;
  outline: none;
  transition: background .14s, box-shadow .14s;
}
.cn-title::placeholder { color: var(--muted-2); font-weight: 400; }
.cn-title:hover { background: var(--panel-2); }
.cn-title:focus { background: #fff; box-shadow: 0 0 0 2px var(--primary-soft); }

/* 深色画布上也要看得清 */
.canvas-host .cn-head { gap: 6px; }
.canvas-host .cn-title { color: #f0f0ea; }
.canvas-host .cn-title::placeholder { color: #7d7d76; }
.canvas-host .cn-title:hover { background: rgba(255,255,255,.08); }
.canvas-host .cn-title:focus { background: rgba(255,255,255,.14); box-shadow: 0 0 0 2px rgba(255,122,69,.5); }
.canvas-host .cn-no { color: #9a9a92; }

/* ============================================================
   画布改回浅色 + 节点大卡片
   ------------------------------------------------------------
   之前按参考站做了深色画布，但站内其它页面都是浅色，
   唯独画布深色显得割裂。这里改回跟站点一致的浅色。
   ============================================================ */
.canvas-host {
  /* 底色对齐参考站（#eef1f5，比纯白略灰，点阵才看得出来）。
     点阵不在这里画 —— React Flow 的 <Background> 组件负责，
     好处是它跟着画布缩放，缩放时点距会变，更像真画布。
     这里再画一层会跟它重叠，所以只留底色。 */
  background-color: #eef1f5 !important;
  background-image: none !important;
  color: var(--text) !important;
}
[data-theme="dark"] .canvas-host {
  background-color: #17191f !important;
  background-image: none !important;
}

/* 顶栏 */
.canvas-host .cv-topbar {
  background: #ffffff !important;
  border-bottom: 1px solid var(--border) !important;
  color: var(--text) !important;
}
.canvas-host .cv-topbar .cv-chip,
.canvas-host .cv-topbar .cv-icon,
.canvas-host .cv-topbar .cv-points { color: var(--muted) !important; }
.canvas-host .cv-topbar .cv-chip:hover,
.canvas-host .cv-topbar .cv-icon:hover,
.canvas-host .cv-topbar .cv-points:hover {
  background: var(--panel-2) !important;
  color: var(--text) !important;
}
.canvas-host .cv-topbar .cv-chip.primary {
  background: var(--primary) !important;
  color: #fff !important;
  font-weight: 600;
}
.canvas-host .cv-topbar .cv-name { color: var(--text) !important; }
.canvas-host .cv-topbar .cv-crumb,
.canvas-host .cv-topbar .cv-save { color: var(--muted-2) !important; }

/* 底部两条工具条 */
.canvas-host .cv-bar {
  background: #ffffff !important;
  border: 1px solid var(--border) !important;
  box-shadow: 0 6px 20px rgba(16, 24, 40, .08) !important;
}
.canvas-host .cv-bar .cv-chip { color: var(--muted) !important; }
.canvas-host .cv-bar .cv-chip:hover {
  background: var(--panel-2) !important;
  color: var(--text) !important;
}
.canvas-host .cv-bar .cv-chip.primary {
  background: var(--primary) !important;
  color: #fff !important;
  font-weight: 600;
}

/* DreamMaker 风格的画布操作提示：固定在画布顶部，不拦截鼠标操作。 */
.canvas-host .cv-hint {
  top: 72px;
  left: 50%;
  bottom: auto;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 4px 6px;
  background: transparent !important;
  color: #8f98a5 !important;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  font-size: 13px;
  opacity: 1;
  pointer-events: none;
  white-space: nowrap;
}
.canvas-host .cv-hint::before {
  content: "";
  width: 12px;
  height: 16px;
  flex: 0 0 auto;
  background: currentColor;
  clip-path: polygon(0 0, 100% 62%, 58% 68%, 77% 100%, 59% 100%, 42% 71%, 0 100%);
  opacity: .85;
}

/* 深色主题下也跟着走 */
[data-theme="dark"] .canvas-host .cv-topbar,
[data-theme="dark"] .canvas-host .cv-bar {
  background: #1b1e25 !important;
  border-color: #2b2f38 !important;
}
[data-theme="dark"] .canvas-host .cv-hint {
  background: transparent !important;
  color: #9ca3af !important;
}

/* 节点小标签在浅色下重新着色 */
.canvas-host .cn-no { color: var(--muted-2) !important; }
.canvas-host .cn-title { color: var(--text) !important; }
.canvas-host .cn-title::placeholder { color: var(--muted-2) !important; }
.canvas-host .cn-title:hover { background: var(--panel-2) !important; }
.canvas-host .cn-title:focus {
  background: #fff !important;
  box-shadow: 0 0 0 2px var(--primary-soft) !important;
}
[data-theme="dark"] .canvas-host .cn-title { color: #f0f0ea !important; }
[data-theme="dark"] .canvas-host .cn-title:focus { background: rgba(255,255,255,.14) !important; }

/* ---------- 节点：大卡片 ---------- */
.canvas-host .cn { width: 340px !important; }
.canvas-host .cn-body { padding: 12px !important; gap: 10px !important; }
.canvas-host .cn-head { padding: 9px 11px !important; }
.canvas-host .cn-thumb img,
.canvas-host .cn-thumb video { width: 100%; display: block; border-radius: 8px; }

/* 缩略图区域给个浅底，图片没加载完也不难看 */
.canvas-host .cn-thumb { background: var(--panel-2); border-radius: 8px; min-height: 80px; }

/* ============================================================
   节点底部：压成一行（模型 · 参数 · 预估 · 生成）
   参考站就是这个结构 —— 参数不铺开，要看再点开。
   ============================================================ */
.cn-foot {
  display: flex;
  align-items: center;
  gap: 6px;
  padding-top: 8px;
  border-top: 1px solid var(--border);
  flex-wrap: nowrap;
}
.cn-model {
  flex: 0 1 auto;
  min-width: 0;
  max-width: 140px;
  border: 1px solid var(--border);
  background: var(--panel-2);
  border-radius: 6px;
  padding: 3px 6px;
  font: inherit;
  font-size: 11.5px;
  color: var(--muted);
  cursor: pointer;
}
.cn-params {
  flex: 0 0 auto;
  border: 1px solid var(--border);
  background: var(--panel-2);
  border-radius: 6px;
  padding: 3px 8px;
  font: inherit;
  font-size: 11.5px;
  color: var(--muted);
  cursor: pointer;
  white-space: nowrap;
  transition: border-color .14s, color .14s, background .14s;
}
.cn-params:hover { border-color: var(--primary); color: var(--primary); }
.cn-params.open {
  background: var(--primary);
  border-color: var(--primary);
  color: #fff;
}
.cn-foot .cn-cost {
  margin-left: auto;
  margin-right: 0;
  font-size: 11.5px;
  color: var(--muted);
  white-space: nowrap;
}
.cn-param-panel {
  display: flex;
  flex-direction: column;
  gap: 9px;
  padding: 10px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--panel-2);
}
/* 深色画布下 */
[data-theme="dark"] .cn-model,
[data-theme="dark"] .cn-params { background: #23242a; border-color: #33343c; }
[data-theme="dark"] .cn-param-panel { background: #1e2027; border-color: #2f313a; }

/* ============================================================
   节点重做：按 DreamMaker 的真实尺寸和结构
   ------------------------------------------------------------
   实测数据（登录后从 DOM 读的，不是截图猜的）：
     面板宽 934px、工具按钮高 32px、快捷块 48x48、输入区 932x88、底栏高 32px
   ============================================================ */
.cn {
  width: 934px !important;
  background: #fff;
  border-radius: 14px;
  box-shadow: 0 2px 4px rgba(16,24,40,.06), 0 12px 32px rgba(16,24,40,.10);
  overflow: hidden;
}
.cn.sel { box-shadow: 0 0 0 2px var(--primary), 0 12px 32px rgba(16,24,40,.14); }

/* ---------- 标题行 ---------- */
.cn-top {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--border);
}
.cn-top .cn-no { font-size: 12px; font-weight: 700; color: var(--muted-2); }
.cn-top .cn-title { flex: 1 1 auto; font-size: 14px; font-weight: 650; }
.cn-top .cn-kind {
  flex: 0 0 auto; font-size: 11px; padding: 2px 8px;
  border-radius: 999px; background: var(--panel-2); color: var(--muted);
}
.cn-top .cn-kind.video { background: #eef4ff; color: #3b6fd4; }

/* ---------- 工具条（7 个 + 右侧图标） ---------- */
.cn-tools {
  display: flex; align-items: center; gap: 6px;
  padding: 8px 14px;
  border-bottom: 1px solid var(--border);
  flex-wrap: nowrap; overflow-x: auto;
}
.cn-grow { flex: 1 1 auto; }
.cn-tool {
  flex: 0 0 auto;
  display: inline-flex; align-items: center; gap: 6px;
  height: 32px; padding: 0 10px;
  border: 1px solid var(--border); border-radius: 8px;
  background: #fff; color: var(--text-2, #4a5260);
  font: inherit; font-size: 12.5px; cursor: pointer;
  white-space: nowrap;
  transition: background .14s, border-color .14s;
}
.cn-tool:hover { background: var(--panel-2); border-color: #d6dae1; }
.cn-tool.icon { width: 32px; padding: 0; justify-content: center; }

/* ---------- 舞台（产物区） ---------- */
/* 预览区。
   展开后图片保持和折叠卡差不多大小（约 452x245）并居中 ——
   照参考站来的：它点开前后图片的位置和宽度完全没变，只是下面
   『长』出快捷块 / 输入框 / 底栏。我们原来把图放成整行宽（1800+），
   视觉上像是图片被换掉了。 */
.cn-stage {
  min-height: 245px;
  display: flex; align-items: center; justify-content: center;
  background: #f7f8fa;
  border-bottom: 1px solid var(--border);
  overflow: hidden;
  padding: 14px 0;
}
.cn-stage img, .cn-stage video {
  max-width: 452px;
  max-height: 245px;
  display: block;
  border-radius: 8px;
}
.cn-stage-hint { font-size: 12.5px; color: var(--muted-2); }

/* ---------- 快捷入口（48x48） ---------- */
.cn-quick {
  display: flex; align-items: center; gap: 8px;
  padding: 12px 14px 0;
}
.cn-quick-btn {
  width: 48px; height: 48px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  border: 1px solid var(--border); border-radius: 10px;
  background: #fff; color: var(--muted);
  font: inherit; font-size: 10.5px; cursor: pointer;
  transition: border-color .14s, color .14s;
}
.cn-quick-btn:hover { border-color: var(--primary); color: var(--primary); }
.cn-quick-ico { font-size: 15px; line-height: 1; }

/* ---------- 提示词输入区（大） ---------- */.cn-prompt:focus { outline: none; border-color: var(--primary); }

/* ---------- 参数面板 ---------- */
.cn-param-panel {
  display: flex; flex-direction: column; gap: 10px;
  margin: 0 14px 12px;
  padding: 12px;
  border: 1px solid var(--border); border-radius: 10px;
  background: var(--panel-2);
}

/* ---------- 底栏一行 ---------- */
.cn-foot {
  display: flex; align-items: center; gap: 8px;
  padding: 12px 14px;
  border-top: 1px solid var(--border);
  flex-wrap: nowrap; overflow-x: auto;
}
.cn-pill {
  flex: 0 0 auto;
  display: inline-flex; align-items: center; gap: 6px;
  height: 32px; padding: 0 8px;
  border: 1px solid var(--border); border-radius: 8px;
  background: #fff; color: var(--text-2, #4a5260);
  font: inherit; font-size: 12.5px; cursor: pointer;
  white-space: nowrap;
  transition: background .14s, border-color .14s;
}
.cn-pill:hover { background: var(--panel-2); border-color: #d6dae1; }
.cn-pill.open { background: var(--primary); border-color: var(--primary); color: #fff; }
.cn-pill.cn-static { cursor: default; color: var(--muted); }
.cn-pill.cn-static:hover { background: #fff; border-color: var(--border); }
select.cn-pill.cn-model {
  max-width: 190px; cursor: pointer;
  text-overflow: ellipsis;
}
.cn-foot .cn-cost {
  flex: 0 0 auto; margin-left: auto;
  font-size: 12.5px; color: var(--muted); white-space: nowrap;
}
.cn-run {
  flex: 0 0 auto;
  width: 40px; height: 32px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 0; border-radius: 8px;
  background: var(--primary); color: #fff;
  font-size: 16px; cursor: pointer;
}
.cn-run:disabled { opacity: .55; cursor: default; }
.cn-run:not(:disabled):hover { filter: brightness(1.06); }

/* 错误行 */
.cn-err { padding: 0 14px 10px; font-size: 12px; color: #dc2626; }
.cn-param-warning {
  margin: 10px 14px 0;
  padding: 8px 10px;
  border: 1px solid #fecaca;
  border-radius: 8px;
  background: #fff7f7;
  color: #b42318;
  font-size: 12px;
  line-height: 1.45;
}
[data-theme="dark"] .cn-param-warning {
  border-color: #7f1d1d;
  background: #2b1719;
  color: #fca5a5;
}

/* 深色主题 */
[data-theme="dark"] .cn { background: #1b1e25; }
[data-theme="dark"] .cn-tool,
[data-theme="dark"] .cn-pill,
[data-theme="dark"] .cn-quick-btn { background: #23242a; border-color: #33343c; color: #d2d6de; }
[data-theme="dark"] .cn-stage { background: #15171c; }[data-theme="dark"] .cn-param-panel { background: #1e2027; border-color: #2f313a; }

/* ============================================================
   节点两态：折叠卡片（默认）/ 展开编辑
   ------------------------------------------------------------
   折叠态照 DreamMaker 的真实尺寸：432x245、16:9、圆角 14px、
   左上角浮一个类型标签（svg 图标 + 文字）。之前我把"展开态"的
   934x1046 当成了默认尺寸，做出来又大又不像。
   ============================================================ */
.cn.cn-card-mode {
  position: relative;
  width: 432px !important;
  height: 245px;
  background: transparent;
  border: 0;
  box-shadow: none;
  overflow: visible;
}

/* 左上角浮动的类型标签 */
.cn-badge {
  position: absolute;
  top: 0; left: 0;
  display: flex; align-items: center; gap: 5px;
  height: 28px; padding: 0 10px;
  font-size: 12.5px; color: #5b6270;
  pointer-events: none;
}
.cn-badge-ico { font-size: 13px; line-height: 1; }
.cn-badge-text { max-width: 60%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* 卡片本体。top 原来是 28px —— 给左上角那个类型标签留的位置；
   标签去掉了，卡片就铺满整块。 */
.cn-card {
  position: absolute;
  top: 0; left: 0; right: 0; bottom: 0;
  border: 1px solid rgba(16,24,40,.08);
  border-radius: 14px;
  background: rgb(251, 253, 255);
  overflow: hidden;
  cursor: pointer;
  transition: box-shadow .16s, border-color .16s;
}
.cn-card:hover { border-color: rgba(16,24,40,.18); box-shadow: 0 6px 18px rgba(16,24,40,.10); }
.cn-card img, .cn-card video {
  width: 100%; height: 100%; object-fit: cover; display: block;
  -webkit-user-drag: none;
  user-select: none;
  /* 让鼠标按下落到 .cn-card，React Flow 才能从预览图区域启动节点拖动。 */
  pointer-events: none;
}
.cn-stage img, .cn-stage video,
.cn-ref img, .cn-ref video,
.cn-ref-dialog img, .cn-ref-dialog video {
  -webkit-user-drag: none;
  user-select: none;
}
.cn-audio-card {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 28px;
  cursor: default;
  background:
    radial-gradient(circle at 18% 22%, rgba(250, 96, 28, .10), transparent 36%),
    linear-gradient(145deg, #fff, #f5f7fa);
}
.cn-audio-node-icon {
  width: 72px;
  height: 72px;
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  border-radius: 20px;
  color: #fff;
  background: #fa601c;
  box-shadow: 0 8px 20px rgba(250, 96, 28, .24);
  font-size: 34px;
  font-weight: 700;
}
.cn-audio-node-copy {
  min-width: 0;
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.cn-audio-node-copy strong {
  overflow: hidden;
  color: #20242c;
  font-size: 15px;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cn-audio-node-copy span { color: #8a919e; font-size: 12px; }
.cn-audio-player {
  width: 205px;
  max-width: 48%;
  flex: 0 0 auto;
  display: grid;
  grid-template-columns: 32px minmax(72px, 1fr);
  align-items: center;
  gap: 4px 8px;
}
.cn-audio-player audio { display: none; }
.cn-audio-toggle {
  grid-row: 1 / span 2;
  width: 32px;
  height: 32px;
  display: grid;
  place-items: center;
  padding: 0 0 0 2px;
  border: 0;
  border-radius: 50%;
  color: #fff;
  background: #2c313a;
  font-size: 11px;
  cursor: pointer;
}
.cn-audio-toggle.playing { padding-left: 0; background: #fa601c; }
.cn-audio-player input[type="range"] {
  width: 100%;
  min-width: 0;
  height: 3px;
  accent-color: #fa601c;
  cursor: pointer;
}
.cn-audio-player time {
  color: #7c8491;
  font-size: 10px;
  line-height: 1;
  white-space: nowrap;
}
[data-theme="dark"] .cn-audio-card {
  background: linear-gradient(145deg, #24262d, #1b1d22);
}
[data-theme="dark"] .cn-audio-node-copy strong { color: #f4f6f8; }
.cn.cn-card-mode.sel .cn-card {
  border-color: var(--primary);
  box-shadow: 0 0 0 2px var(--primary), 0 8px 22px rgba(16,24,40,.14);
}

/* 空卡：没有产物时就是一块空白（原来显示「未命名节点 / 点开填写提示词」，已去掉） */
.cn-card-empty {
  height: 100%;
}

/* 卡片上的进度条 */
.cn-card-bar {
  position: absolute; left: 0; right: 0; bottom: 0; height: 3px;
  background: rgba(16,24,40,.08);
}
.cn-card-bar > i {
  display: block; height: 100%; width: 0;
  background: var(--primary); transition: width .45s ease;
}

/* ---------- 展开态 ---------- */
.cn.cn-open { width: 934px !important; }
.cn-close {
  flex: 0 0 auto;
  width: 28px; height: 28px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--border); border-radius: 7px;
  background: #fff; color: var(--muted); font-size: 13px; cursor: pointer;
}
.cn-close:hover { border-color: var(--primary); color: var(--primary); }

/* 卡片态不需要标题行那些 */
.cn.cn-card-mode .cn-top,
.cn.cn-card-mode .cn-tools,
.cn.cn-card-mode .cn-foot { display: none; }

/* 深色主题下的卡片 */
[data-theme="dark"] .cn.cn-card-mode .cn-card { background: #1e2027; border-color: #2f313a; }
[data-theme="dark"] .cn-badge { color: #9aa0ac; }

/* ============================================================
   画布全屏：盖住站点顶栏和左侧栏
   ------------------------------------------------------------
   模板（DreamMaker）的画布是沉浸式的：整屏只有画布自己的顶栏
   「未命名项目 | 画布 1」，没有站点导航。我们原来留了 56px 给站点
   顶栏、侧栏也还露着，所以对不上。
   这里直接把画布铺满可视区，并把站点外壳藏掉。
   ============================================================ */
.canvas-host {
  top: 0 !important;
  height: 100vh !important;
  z-index: 900;
}

/* 画布在的时候，站点顶栏和侧栏都不该出现 */
body.canvas-mode .topbar,
body.canvas-mode .sidebar {
  display: none !important;
}
body.canvas-mode .shell { display: block !important; }
body.canvas-mode .main {
  margin-left: 0 !important;
  padding: 0 !important;
}

/* ============================================================
   预览区改成 Seedance 那版：红框 + 中间播放三角
   ------------------------------------------------------------
   红框色 #fa601c 是从用户给的那张截图上量出来的（主色 #fa601c，
   亮边 #f97236）。跟站点主色 --primary 是同一套暖橙。
   ============================================================ */
.cn.cn-open .cn-stage {
  border: 1.5px solid #fa601c;
  border-radius: 12px;
  background: #fff;
  overflow: hidden;
}

/* 没有产物时：播放三角 + 一行提示，竖排居中 */
.cn-stage-hint {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  font-size: 12.5px;
  color: var(--muted-2);
}
.cn-play {
  width: 54px; height: 54px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: #fa601c;
  box-shadow: 0 4px 14px rgba(250, 96, 28, .35);
  flex: 0 0 auto;
}
.cn-play::after {
  content: "";
  display: block;
  margin-left: 4px;
  border-left: 16px solid #fff;
  border-top: 10px solid transparent;
  border-bottom: 10px solid transparent;
}

/* ============================================================
   展开态重排：上下两块
   ------------------------------------------------------------
   上半：橙色描边的预览容器（单独一块，和下面拉开 12px）
   下半：白色圆角卡片 —— 里面是提示词输入框 + 一行操作控件
   原来是整个节点糊在一起，现在拆成两块，结构清楚些。
   ============================================================ */
.cn.cn-open {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 0;
  background: transparent;
  border: 0;
  box-shadow: none;
}

/* 预览容器——单独一块，底部不要那根分隔线了（卡片自己有边界） */
.cn.cn-open .cn-stage {
  border-bottom: 0;
}

/* 下半部分：白色圆角卡片 */
.cn-panel {
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 12px;
  /*
   * 这里必须是 visible，不能是 hidden。
   * @ 引用素材的浮层是往上弹的（bottom: 100%），会跑到卡片外面去；
   * 一旦这里 hidden，浮层上半截就被裁掉了 —— 表现就是
   * 「打 @ 之后素材列表被挡住」。
   * 圆角不受影响：卡片里那两块（输入框、控件行）本来就是透明的。
   */
  overflow: visible;
}
/* 输入框在卡片里，不要再自己带外边距和边框 */.cn-panel .cn-prompt:focus {
  box-shadow: inset 0 0 0 2px rgba(250, 96, 28, .18);
}
.cn-panel .cn-foot {
  border-top: 1px solid var(--border);
  overflow: visible;
}

/* DreamMaker 风格的视频时长滑块。 */
.cn-duration-control {
  position: relative;
  flex: 0 0 auto;
}
.cn-duration-control > .cn-pill {
  min-width: 56px;
  justify-content: center;
}
.cn-duration-popover {
  position: absolute;
  z-index: 80;
  left: 50%;
  bottom: calc(100% + 10px);
  width: 280px;
  transform: translateX(-50%);
  padding: 14px 16px 12px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: #fff;
  box-shadow: 0 12px 32px rgba(16, 24, 40, .18);
}
.cn-duration-head,
.cn-duration-bounds {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.cn-duration-head {
  margin-bottom: 12px;
  color: var(--text-2, #4a5260);
  font-size: 13px;
}
.cn-duration-head strong { color: var(--text); font-size: 13px; }
.cn-duration-bounds {
  margin-top: 5px;
  color: var(--muted-2);
  font-size: 10px;
}
.cn-duration-slider {
  width: 100%;
  height: 18px;
  margin: 0;
  padding: 0;
  border: 0;
  outline: none;
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  cursor: pointer;
}
.cn-duration-slider::-webkit-slider-runnable-track {
  height: 5px;
  border-radius: 999px;
  background: linear-gradient(
    to right,
    #16b9e8 0 var(--duration-progress),
    #30343a var(--duration-progress) 100%
  );
}
.cn-duration-slider::-webkit-slider-thumb {
  width: 15px;
  height: 15px;
  margin-top: -5px;
  border: 0;
  border-radius: 50%;
  appearance: none;
  -webkit-appearance: none;
  background: #0eafe1;
  box-shadow: 0 0 0 2px #fff;
}
.cn-duration-slider::-moz-range-track {
  height: 5px;
  border: 0;
  border-radius: 999px;
  background: #30343a;
}
.cn-duration-slider::-moz-range-progress {
  height: 5px;
  border-radius: 999px;
  background: #16b9e8;
}
.cn-duration-slider::-moz-range-thumb {
  width: 15px;
  height: 15px;
  border: 2px solid #fff;
  border-radius: 50%;
  background: #0eafe1;
}
[data-theme="dark"] .cn-duration-popover {
  background: #23242a;
  border-color: #33343c;
}

/* 生成按钮：从方块箭头改成带字的橙按钮 */
.cn-run {
  flex: 0 0 auto;
  width: auto; height: 34px;
  padding: 0 16px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 0; border-radius: 8px;
  background: #fa601c; color: #fff;
  font: inherit; font-size: 13px; font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  transition: background .14s;
}
.cn-run::after { content: "→"; margin-left: 6px; font-size: 14px; line-height: 1; }
.cn-run:hover:not(:disabled) { background: #e8540f; }
.cn-run:disabled { background: #e3e6ea; color: #9aa1ad; cursor: not-allowed; }

/* 预估文字：推到右边，紧贴生成按钮左边（参考站就是这样） */
.cn-foot .cn-cost { margin-left: auto; margin-right: 8px; }

/* ============================================================
   底栏下拉的宽度收敛
   ------------------------------------------------------------
   <select> 在 flex 里有个老毛病：它的"内容宽度"会被浏览器按最长的
   option 撑开，`flex: 0 0 auto` 也拦不住，结果一个「文生视频」的下拉
   渲染成了 900+ 宽，把整行挤爆。
   办法是给死 max-width + min-width: 0 + 省略号。
   ============================================================ */
.cn-foot .cn-pill {
  flex: 0 0 auto;
  width: auto;
  min-width: 0;
  max-width: 132px;
  text-overflow: ellipsis;
}
/* 比例/分辨率/时长这种短的，给个小一点的上限就够了 */
.cn-foot .cn-pill:not(.cn-model):not(.cn-static) { max-width: 92px; }
/* 「文生视频」那种静态文字不用限 */
.cn-foot .cn-pill.cn-static { max-width: none; }

/* ============================================================
   展开态的预览框：收窄 + 居中 + 保持 16:9
   ------------------------------------------------------------
   原来是铺满整个节点宽度（934px），但高度只有 245，
   宽高比到了 3.8:1，看着又扁又长。
   参考站里它是居中的一块，所以这里限制宽度并保持比例。
   ============================================================ */
.cn.cn-open .cn-stage {
  width: 100%;
  max-width: 620px;
  margin: 0 auto;
  aspect-ratio: 16 / 9;
  min-height: 0;
  padding: 0;
}
.cn.cn-open .cn-stage img,
.cn.cn-open .cn-stage video {
  max-width: 100%;
  max-height: 100%;
}

/* ============================================================
   展开态：去掉最外层那圈
   ------------------------------------------------------------
   .cn 基类自带白底 + 边框 + 阴影，选中时还有橙色外圈；
   另外 .canvas-host .react-flow__node .cn 又给了一层阴影。
   这些合起来就是"最外面那圈灰色底板框"。
   注意特异性：.canvas-host .react-flow__node .cn 是 (0,2,1)，
   比 .cn.cn-open 的 (0,2,0) 高，所以必须写全路径才能盖住。
   ============================================================ */
.canvas-host .react-flow__node .cn.cn-open,
.canvas-host .react-flow__node .cn.cn-open.sel {
  background: transparent !important;
  border: 0 !important;
  box-shadow: none !important;
  border-radius: 0 !important;
  overflow: visible !important;
  padding: 0 !important;
}

/* 选中时也别再给橙色外圈 —— 展开态本来就不需要"卡片"的边界 */
.canvas-host .react-flow__node .cn.cn-open.sel {
  outline: 0 !important;
}

/* 白卡片里那圈该有的边界保留（它是表单自己的边框） */
.canvas-host .react-flow__node .cn.cn-open .cn-panel {
  box-shadow: 0 1px 3px rgba(16, 24, 40, .06);
}

/* ============================================================
   展开态的连接点（Handle）
   ------------------------------------------------------------
   展开态最外层是 flex column，Handle 会被当成普通子元素排在顶部，
   所以必须绝对定位到左右边界、垂直居中。
   这也是「图片连不上视频」的原因之一 —— 原来展开态压根没有 target 点。
   ============================================================ */
.canvas-host .react-flow__node .cn.cn-open > .react-flow__handle {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 18px; height: 18px;
  border-radius: 50%;
  background: #fa601c;
  border: 2px solid #fff;
  box-shadow: 0 1px 4px rgba(16, 24, 40, .28);
  z-index: 3;
}
.canvas-host .react-flow__node .cn.cn-open > .react-flow__handle-left { left: -11px; }
.canvas-host .react-flow__node .cn.cn-open > .react-flow__handle-right { right: -11px; }

/*
 * 位置：贴着橙色预览框的左右边缘。
 * 预览框是 620 宽、在节点里居中，所以左右留白都是 (100% - 620px) / 2。
 * 垂直方向对齐预览框的中点（620x349 的 16:9，中点约 174px）。
 *
 * 颜色必须带 !important —— 上面那条深色画布的规则
 * `.canvas-host .react-flow__handle { background: #e8e6dd !important }`
 * 会把它盖成灰白。
 */
.canvas-host .react-flow__node .cn.cn-open > .react-flow__handle {
  top: 174px !important;
}
.canvas-host .react-flow__node .cn.cn-open > .react-flow__handle-left {
  left: calc((100% - 620px) / 2 - 11px) !important;
}
.canvas-host .react-flow__node .cn.cn-open > .react-flow__handle-right {
  right: calc((100% - 620px) / 2 - 11px) !important;
}
.canvas-host .react-flow__node .cn.cn-open > .react-flow__handle {
  background: #fa601c !important;
  border: 2px solid #fff !important;
  box-shadow: 0 1px 5px rgba(16, 24, 40, .32) !important;
  z-index: 4 !important;
}

/* 悬停时放大一点，好点中 */
.canvas-host .react-flow__node .cn.cn-open > .react-flow__handle:hover {
  transform: translateY(-50%) scale(1.25);
}

/* ============================================================
   @ 引用素材的浮层
   ------------------------------------------------------------
   在提示词输入框上方弹出，列出账号里的素材（图 / 视频），
   点一条就在光标位置插入 @图片12 这种引用。
   做法跟聊天框的 @ 提人类似。
   ============================================================ */
.cn-panel { position: relative; }
.cn-prompt-wrap { position: relative; }
.cn-prompt-expand {
  position: absolute;
  z-index: 2;
  top: 9px;
  right: 12px;
  width: 28px;
  height: 28px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  border-radius: 7px;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
}
.cn-prompt-expand:hover {
  background: var(--panel-2);
  color: var(--primary);
}
.cn-prompt-expand svg {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}
[data-theme="dark"] .cn-prompt-expand {
  color: #aeb4c0;
}

/* DreamMaker 风格：放大时整张提示词卡片脱离画布缩放，居中盖在视口上。 */
.cn-prompt-overlay {
  position: fixed;
  inset: 0;
  z-index: 1150;
  display: grid;
  place-items: center;
  padding: 32px;
  background: rgba(52, 59, 67, .22);
  backdrop-filter: blur(1.5px);
}
.cn-prompt-modal-panel {
  width: min(960px, calc(100vw - 48px));
  height: min(600px, calc(100vh - 64px));
  display: flex;
  flex-direction: column;
  overflow: visible;
  border-radius: 16px;
  box-shadow: 0 24px 70px rgba(16, 24, 40, .22);
}
.cn-prompt-modal-panel .cn-reference-tools,
.cn-prompt-modal-panel .cn-refs,
.cn-prompt-modal-panel .cn-foot {
  flex: 0 0 auto;
}
.cn-prompt-modal-panel .cn-prompt-wrap {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
}
.cn-prompt-modal-panel .cn-prompt-wrap .cn-prompt {
  flex: 1 1 auto;
  min-height: 0;
  max-height: none;
}

.cn-mentions {
  position: absolute;
  left: 14px; right: auto;
  bottom: calc(100% + 6px);
  width: min(360px, calc(100% - 28px));
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 10px 28px -6px rgba(16, 24, 40, .22);
  max-height: 232px;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-gutter: stable;
  touch-action: pan-y;
  z-index: 30;
  padding: 4px;
}
.cn-mention-item {
  display: flex; align-items: center; gap: 9px;
  width: 100%;
  padding: 7px 8px;
  border: 0;
  border-radius: 7px;
  background: transparent;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
  font-size: 12.5px;
}
.cn-mention-item:hover { background: #f5f7fa; }
.cn-mention-thumb {
  width: 30px; height: 30px;
  border-radius: 6px;
  object-fit: cover;
  background: #eef1f5;
  flex: 0 0 auto;
  display: block;
}
.cn-mention-name { flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cn-mention-kind { font-size: 11px; color: var(--muted-2); flex: 0 0 auto; }
.cn-mention-empty { padding: 12px 10px; font-size: 12px; color: var(--muted-2); text-align: center; }

/* 深色主题 */
[data-theme="dark"] .cn-mentions { background: #1e2027; border-color: #2f313a; }
[data-theme="dark"] .cn-mention-item:hover { background: #262832; }
[data-theme="dark"] .cn-mention-name { color: #eceef2; }

/* ============================================================
   已选素材的缩略图 + @ 列表里的上传入口
   ------------------------------------------------------------
   参考站把引用的素材以缩略图摆在输入框上方（它代码里有「已选」字样），
   而不是只在提示词里插一行文字。这里照做。
   ============================================================ */
.cn-refs {
  display: flex; flex-wrap: wrap; gap: 8px;
  padding: 12px 14px 0;
}
.cn-reference-tools {
  display: flex; align-items: center; gap: 8px;
  padding: 12px 14px 0;
}
.cn-reference-tool {
  height: 36px; padding: 0 10px;
  display: inline-flex; align-items: center; gap: 6px;
  border: 1px solid #e5e8ed; border-radius: 9px;
  background: #fff; color: #344054;
  font: inherit; font-size: 12px; cursor: pointer;
  transition: border-color .14s, background .14s, box-shadow .14s;
}
.cn-reference-tool:hover {
  border-color: #cfd5df; background: #fafbfc;
  box-shadow: 0 2px 7px rgba(16, 24, 40, .06);
}
.cn-reference-tool-icon {
  width: 18px; height: 18px; display: grid; place-items: center;
  color: #667085; font-size: 13px;
}
.cn-reference-tool b { color: #98a2b3; font-size: 10px; font-weight: 500; }
.cn-ref {
  position: relative;
  width: 46px; height: 46px;
  border-radius: 8px;
  overflow: hidden;
  border: 1px solid var(--border);
  background: #f4f6f8;
}
.cn-ref-thumb { width: 100%; height: 100%; object-fit: cover; display: block; }
.cn-ref-rejected {
  border-color: #ef4444;
  box-shadow: 0 0 0 2px rgba(239, 68, 68, .22);
}
.cn-ref-rejected-label {
  position: absolute; left: 2px; top: 2px; z-index: 2;
  padding: 1px 3px; border-radius: 4px;
  background: #dc2626; color: #fff;
  font-size: 8px; font-weight: 700; line-height: 1.35;
}
.cn-audio-preview {
  display: grid !important; place-items: center;
  color: #667085; background: linear-gradient(145deg, #f3f5f8, #e8ecf2);
  font-size: 19px; font-weight: 700;
}
.cn-ref-kind {
  position: absolute; left: 2px; bottom: 2px;
  padding: 1px 4px; border-radius: 4px;
  background: rgba(16, 24, 40, .68); color: #fff;
  font-size: 8px; line-height: 1.35;
}
.cn-ref-del {
  position: absolute; top: 1px; right: 1px;
  width: 16px; height: 16px;
  display: grid; place-items: center;
  border: 0; border-radius: 50%;
  background: rgba(16, 24, 40, .62);
  color: #fff; font-size: 12px; line-height: 1;
  cursor: pointer; padding: 0;
}
.cn-ref-del:hover { background: #d94d10; }

/* @ 列表里的上传入口 */
.cn-mention-upload .cn-mention-plus {
  width: 30px; height: 30px;
  display: grid; place-items: center;
  border-radius: 6px;
  background: #fff1ea;
  color: #fa601c;
  font-size: 17px; font-weight: 600;
  flex: 0 0 auto;
}
.cn-mention-upload:hover .cn-mention-plus { background: #ffe3d5; }
.cn-mention-sep { height: 1px; background: var(--border); margin: 4px 6px; }

[data-theme="dark"] .cn-mention-upload .cn-mention-plus { background: #3a2418; }
[data-theme="dark"] .cn-ref { border-color: #33343c; background: #23242a; }
[data-theme="dark"] .cn-reference-tool {
  border-color: #33343c; background: #23242a; color: #eceef2;
}

/* 参考素材管理 / 添加素材：放到 body 的 portal，避免跟着 React Flow 节点缩放。 */
.cn-ref-overlay {
  position: fixed; inset: 0; z-index: 1200;
  display: grid; place-items: center; padding: 24px;
  background: rgba(15, 23, 42, .42);
  backdrop-filter: blur(2px);
}
.cn-ref-dialog {
  width: min(760px, calc(100vw - 40px));
  max-height: min(760px, calc(100vh - 40px));
  display: flex; flex-direction: column;
  overflow: hidden;
  border: 1px solid #e4e7ec; border-radius: 16px;
  background: #fff; color: #101828;
  box-shadow: 0 24px 64px rgba(16, 24, 40, .24);
}
.cn-asset-picker { width: min(900px, calc(100vw - 40px)); }
.cn-ref-dialog-head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 16px;
  padding: 20px 22px 16px; border-bottom: 1px solid #eaecf0;
}
.cn-ref-dialog-head h3 { margin: 0 0 5px; font-size: 18px; font-weight: 650; }
.cn-ref-dialog-head p { margin: 0; color: #667085; font-size: 12px; }
.cn-ref-close {
  width: 32px; height: 32px; padding: 0; flex: none;
  border: 0; border-radius: 8px; background: transparent;
  color: #667085; font-size: 23px; line-height: 1; cursor: pointer;
}
.cn-ref-close:hover { background: #f2f4f7; color: #101828; }
.cn-ref-manager-body { padding: 8px 22px 18px; overflow-y: auto; }
.cn-ref-group { padding-top: 16px; }
.cn-ref-group-title {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 8px; font-size: 13px; font-weight: 650;
}
.cn-ref-group-title b { color: #667085; font-size: 11px; font-weight: 500; }
.cn-ref-group-empty {
  padding: 17px; border: 1px dashed #d0d5dd; border-radius: 10px;
  color: #98a2b3; text-align: center; font-size: 12px;
}
.cn-ref-manager-list { display: grid; gap: 7px; }
.cn-ref-manager-item {
  display: flex; align-items: center; gap: 11px;
  min-height: 58px; padding: 7px 9px;
  border: 1px solid #eaecf0; border-radius: 10px;
}
.cn-ref-manager-thumb {
  width: 44px; height: 44px; flex: 0 0 44px;
  border-radius: 8px; object-fit: cover; overflow: hidden; display: block;
}
.cn-ref-manager-copy { min-width: 0; flex: 1; display: grid; gap: 3px; }
.cn-ref-manager-copy strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12.5px; }
.cn-ref-manager-copy span { color: #98a2b3; font-size: 10.5px; }
.cn-ref-manager-item > button {
  border: 0; border-radius: 7px; padding: 6px 9px;
  background: transparent; color: #667085; font: inherit; font-size: 11px; cursor: pointer;
}
.cn-ref-manager-item > button:hover { background: #fff1ed; color: #d9480f; }
.cn-ref-dialog-foot {
  display: flex; align-items: center; justify-content: flex-end; gap: 9px;
  padding: 14px 22px; border-top: 1px solid #eaecf0; background: #fcfcfd;
}
.cn-ref-dialog-foot button {
  height: 36px; padding: 0 15px; border-radius: 9px;
  font: inherit; font-size: 12px; font-weight: 600; cursor: pointer;
}
.cn-ref-dialog-foot button:disabled { cursor: not-allowed; opacity: .45; }
.cn-ref-secondary { border: 1px solid #d0d5dd; background: #fff; color: #344054; }
.cn-ref-primary { border: 1px solid #fa601c; background: #fa601c; color: #fff; }
.cn-ref-primary:hover:not(:disabled) { background: #e8540f; }
.cn-asset-tabs {
  display: flex; gap: 4px; padding: 12px 22px 0; overflow-x: auto;
}
.cn-asset-tabs button, .cn-asset-filter button {
  border: 0; border-radius: 8px; background: transparent; color: #667085;
  font: inherit; font-size: 12px; cursor: pointer; white-space: nowrap;
}
.cn-asset-tabs button { height: 34px; padding: 0 12px; }
.cn-asset-tabs button:hover, .cn-asset-tabs button.active { background: #f2f4f7; color: #101828; }
.cn-asset-tabs button.active { font-weight: 650; }
.cn-asset-filter {
  display: flex; gap: 5px; padding: 12px 22px;
  border-bottom: 1px solid #f2f4f7;
}
.cn-asset-filter button { height: 30px; padding: 0 10px; }
.cn-asset-filter button.active { background: #fff1ea; color: #e8540f; }
.cn-asset-filter small { margin-left: 5px; color: #98a2b3; font-size: 9px; }
.cn-local-upload { padding: 14px 22px 0; }
.cn-upload-drop {
  min-height: 142px; display: flex; flex-direction: column; align-items: center; justify-content: center;
  border: 1px dashed #cbd2dc; border-radius: 12px; background: #fafbfc;
  text-align: center; transition: border-color .14s, background .14s;
}
.cn-upload-drop:hover { border-color: #fa8a55; background: #fffaf7; }
.cn-upload-cloud {
  width: 34px; height: 34px; margin-bottom: 7px; display: grid; place-items: center;
  border-radius: 10px; background: #fff1ea; color: #fa601c; font-size: 19px;
}
.cn-upload-drop strong { font-size: 12.5px; }
.cn-upload-drop p { margin: 4px 0 0; color: #98a2b3; font-size: 10.5px; }
.cn-upload-progress {
  width: min(310px, 74%); height: 5px; margin-top: 9px; overflow: hidden;
  border-radius: 999px; background: #fee7dc;
}
.cn-upload-progress i {
  display: block; height: 100%; border-radius: inherit; background: #fa601c;
  transition: width .16s ease;
}
.cn-upload-drop > div { display: flex; gap: 8px; margin-top: 11px; }
.cn-upload-drop > .cn-upload-progress { display: block; }
.cn-upload-drop button {
  height: 31px; padding: 0 11px; border: 1px solid #d0d5dd; border-radius: 8px;
  background: #fff; color: #344054; font: inherit; font-size: 11px; cursor: pointer;
}
.cn-asset-grid {
  min-height: 210px; padding: 2px 22px 18px; overflow-y: auto;
  display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 10px;
}
.cn-asset-card {
  position: relative; min-width: 0; padding: 5px 5px 7px;
  display: grid; gap: 5px; text-align: left;
  border: 1px solid #eaecf0; border-radius: 10px; background: #fff;
  color: #344054; font: inherit; cursor: pointer;
}
.cn-asset-card:hover:not(:disabled) { border-color: #f6a47c; box-shadow: 0 3px 12px rgba(16, 24, 40, .08); }
.cn-asset-card.selected { border-color: #fa601c; box-shadow: 0 0 0 1px #fa601c; }
.cn-asset-card.existing { opacity: .58; cursor: default; }
.cn-asset-card-thumb {
  width: 100%; aspect-ratio: 1.35; border-radius: 7px; overflow: hidden;
  object-fit: cover; display: block; background: #f2f4f7;
}
.cn-asset-card > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding: 0 2px; font-size: 10.5px; }
.cn-asset-card > small { padding: 0 2px; color: #98a2b3; font-size: 9px; }
.cn-asset-card > i {
  position: absolute; right: 8px; top: 8px; width: 20px; height: 20px;
  display: grid; place-items: center; border-radius: 50%;
  background: #fa601c; color: #fff; font-size: 12px; font-style: normal;
}
.cn-asset-empty {
  grid-column: 1 / -1; min-height: 180px; display: grid; place-items: center;
  color: #98a2b3; font-size: 12px;
}

@media (max-width: 760px) {
  .cn-ref-overlay { padding: 10px; }
  .cn-ref-dialog, .cn-asset-picker { width: calc(100vw - 20px); max-height: calc(100vh - 20px); }
  .cn-asset-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .cn-reference-tool > span:not(.cn-reference-tool-icon) { display: none; }
}

/* 输入框里的富文本引用：缩略图 + 文件名 + 生效标记。 */
.cn-prompt-token {
  display: inline-flex; align-items: center; gap: 5px;
  max-width: 230px; height: 30px; margin: 0 3px;
  padding: 2px 6px 2px 3px; vertical-align: -9px;
  border: 1px solid #b9dfe0; border-radius: 8px;
  background: #eaf7f7; color: #344054;
  box-shadow: 0 1px 2px rgba(16, 24, 40, .05);
  line-height: 1; user-select: all;
}
.cn-prompt-token-preview {
  width: 24px; height: 24px; flex: 0 0 24px;
  display: grid; place-items: center; overflow: hidden;
  border-radius: 6px; background: #dfe8ed; color: #56727a;
  font-size: 14px; font-weight: 700;
}
.cn-prompt-token-preview img,
.cn-prompt-token-preview video { width: 100%; height: 100%; display: block; object-fit: cover; }
.cn-prompt-token-name {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 11.5px; line-height: 1.2;
}
.cn-prompt-token-state {
  width: 15px; height: 15px; flex: 0 0 15px;
  display: grid; place-items: center;
  border: 1px solid #58aeb0; border-radius: 50%;
  color: #3b9295; font-size: 9px; font-weight: 700;
}
[data-theme="dark"] .cn-prompt-token {
  border-color: #356d70; background: #173a3c; color: #e6f6f6;
}

/* ============================================================
   提示词输入框
   ------------------------------------------------------------
   刻意做到最简单：没有边框、没有底色、没有阴影，就是一块干净的
   书写区 —— 之前这里叠了 8 条互相覆盖的规则（border / 圆角 / 白底 /
   阴影 / 描边），既看不出重点，改也改不动。

   只留一个聚焦标记：左边一条橙色竖线。保留它是有原因的 ——
   曾经出现过"点了输入框其实焦点没进去、用户以为打不进字"的情况，
   界面上没有任何反馈就没法自查，一条竖线就能一眼确认。
   ============================================================ */
.cn-panel .cn-prompt {
  display: block;
  width: 100%;
  margin: 0;
  padding: 14px 70px 14px 16px;
  min-height: 84px;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  outline: none;
  color: var(--text);
  font: inherit;
  font-size: 13px;
  line-height: 1.75;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  overflow-y: auto;
  max-height: 180px;
  overscroll-behavior: contain;
  scrollbar-gutter: stable;
  touch-action: pan-y;
  cursor: text;
  caret-color: var(--primary);
}

/* 聚焦：左边缘一条橙色竖线 + 极淡底色 */
.cn-panel .cn-prompt:focus,
.cn-panel .cn-prompt:focus-visible {
  background: #fffaf7;
  box-shadow: inset 3px 0 0 0 var(--primary);
}

.progress-cell { display: flex; align-items: center; gap: 8px; min-width: 120px; }
.progress-cell .bar { flex: 1 1 auto; min-width: 70px; }
.progress-cell .footnote { flex: 0 0 auto; min-width: 30px; text-align: right; }

/* 空的时候显示提示文字 */
.cn-panel .cn-prompt:empty::before {
  content: attr(data-placeholder);
  color: var(--muted-2);
  pointer-events: none;
}

/* 深色主题 */
[data-theme="dark"] .cn-panel .cn-prompt {
  background: transparent;
  color: #eceef2;
}
[data-theme="dark"] .cn-panel .cn-prompt:focus,
[data-theme="dark"] .cn-panel .cn-prompt:focus-visible {
  background: #26272e;
  box-shadow: inset 3px 0 0 0 var(--primary);
}

/* @ 列表每项前面的序号角标 —— 素材多了靠它和输入框里的 @图片N 对上 */
.cn-mention-no {
  flex: none;
  width: 20px;
  height: 20px;
  margin-right: 8px;
  border-radius: 50%;
  background: #f0f2f5;
  color: var(--muted);
  font-size: 11px;
  font-weight: 600;
  line-height: 20px;
  text-align: center;
}
