/* 广角控制台 M10 — 微信风浅色＋品牌橙（token 见 theme.css；橙只点睛不铺底） */
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
  background: var(--bg-page); color: var(--text-primary);
  font: var(--fs-md)/1.6 -apple-system, "PingFang SC", "Microsoft YaHei", system-ui, sans-serif;
}
button {
  font: inherit; cursor: pointer; border: 1px solid var(--border-input);
  background: var(--bg-card); color: var(--text-primary);
  border-radius: var(--radius-button); padding: 6px 14px; transition: all var(--transition);
}
button:hover { border-color: var(--accent); color: var(--accent); }
button.primary { background: var(--accent); border-color: var(--accent); color: #fff; }
button.primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); color: #fff; }
button.danger { color: var(--error); }
button.danger:hover { border-color: var(--error); }
button:disabled { opacity: .45; cursor: not-allowed; }
input, select, textarea {
  font: inherit; background: var(--bg-card); color: var(--text-primary);
  border: 1px solid var(--border-input); border-radius: var(--radius-button); padding: 6px 10px;
}
input:focus, select:focus, textarea:focus { outline: none; border-color: var(--accent); }
table { width: 100%; border-collapse: collapse; }
th, td { text-align: left; padding: 8px 10px; border-bottom: 1px solid var(--border); }
th { color: var(--text-secondary); font-weight: 500; font-size: var(--fs-base); background: var(--bg-header); }
tbody tr:hover { background: var(--bg-hover); }
a { color: var(--accent); text-decoration: none; }

/* ── 登录 ── */
/* ── 3-4 登录页背景：**纯 CSS 渐变 ＋ 内联 SVG 纹理，零外链资源** ───────────────
   为什么不用位图：登录页是客户见到广角的第一屏，而广角要装进信创机 / 离线内网 / 老浏览器——
   位图＝多一个文件、多一次加载、多一个静默失败点（信创已吃过"字体缺失静默无字"的亏）。
   渐变＋SVG 体积近 0、任何环境一个样，也不受 CSP / 离线打包影响。
   纹理＝品牌橙的稀疏斜网格＋两团柔光，data:URI 内联，**不产生任何网络请求**。 */
.login-wrap {
  min-height: 100vh; display: grid; place-items: center; position: relative; isolation: isolate;
  background:
    radial-gradient(1100px 620px at 78% -8%, rgba(255,138,30,.16), transparent 62%),
    radial-gradient(880px 520px at 12% 108%, rgba(244,81,30,.13), transparent 60%),
    linear-gradient(168deg, #FFF9F3 0%, #FDF3EA 42%, #F6F1EC 100%);
}
/* 斜网格纹理（内联 SVG data:URI）：只做质感，不抢主体；深色/高对比环境下也只是淡淡一层 */
.login-wrap::before {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none; opacity: .5;
  background-image: url("data:image/svg+xml;utf8,\
<svg xmlns='http://www.w3.org/2000/svg' width='44' height='44' viewBox='0 0 44 44'>\
<g fill='none' stroke='%23F4511E' stroke-opacity='.09' stroke-width='1'>\
<path d='M0 44 44 0M-11 11 11 -11M33 55 55 33'/></g></svg>");
  background-size: 44px 44px;
}
.login-wrap .login-card { position: relative; z-index: 1; }
.login-card {
  background: var(--bg-card); border: 1px solid var(--border); border-radius: 14px;
  padding: 36px 40px; width: 360px;
  box-shadow: 0 18px 48px rgba(120, 60, 20, .13), 0 2px 6px rgba(0,0,0,.05);
}
/* 顶部一条品牌色细边：一眼认出是广角，且零图片成本 */
.login-card { border-top: 3px solid var(--accent); }
.login-card h1 { font-size: var(--fs-4xl); margin-bottom: 4px; text-align: center; }
.login-card .sub { color: var(--text-hint); font-size: var(--fs-sm); margin-bottom: 22px; text-align: center; }
.login-card label { display: block; color: var(--text-secondary); font-size: var(--fs-base); margin: 12px 0 4px; }
.login-card input { width: 100%; background: var(--bg-input); }
.login-card input:focus { background: var(--bg-card); }
.captcha-row { display: flex; gap: 8px; align-items: center; }
.captcha-row input { flex: 1; }
.captcha-row .cap-img { height: 40px; border-radius: var(--radius-button); background: #fff; border: 1px solid var(--border); cursor: pointer; }
.login-card .primary { width: 100%; margin-top: 20px; padding: 9px; }

/* ── 壳：顶栏＋侧栏＋页签（M10 八菜单 IA）── */
.shell { display: flex; flex-direction: column; min-height: 100vh; }
.topbar {
  height: 52px; flex-shrink: 0; display: flex; align-items: center; gap: 14px;
  background: var(--bg-card); border-bottom: 1px solid var(--border); padding: 0 18px;
  position: sticky; top: 0; z-index: 10;
}
.topbar .brand { font-size: var(--fs-2xl); font-weight: 600; display: flex; align-items: center; }
/* 橙红 logo 标（M10-OPT S9，P2）：产品短名首字 · 顶栏小标 / 登录页大标（.lg） */
.brand-mark {
  display: inline-grid; place-items: center; flex: none;
  width: 26px; height: 26px; margin-right: 8px; border-radius: 7px;
  background: linear-gradient(135deg, #FF8A1E, #F4511E);
  color: #fff; font-size: 15px; font-weight: 700; line-height: 1;
  box-shadow: 0 2px 6px rgba(244, 81, 30, .35);
}
.brand-mark.lg { width: 56px; height: 56px; border-radius: 14px; font-size: 30px; margin: 0 auto 14px; display: grid; }
/* 真 logo 图（默认广角，顶栏左上）：等高按比例，紧挨产品名 */
.topbar .brand .brand-logo { height: 30px; width: auto; margin-right: 9px; flex: none; display: block; }
.topbar .brand small { color: var(--text-hint); font-size: var(--fs-xs); font-weight: 400; margin-left: 8px; }
/* 顶栏单位名称（世界级信发做法：显客户单位名，未设置=非侵入行内提示） */
.topbar .unit-name { background: none; border: none; color: var(--text-secondary); font-size: var(--fs-md); cursor: pointer; padding: 5px 10px; border-radius: 8px; margin-left: 12px; display: inline-flex; align-items: center; gap: 4px; white-space: nowrap; }
.topbar .unit-name:hover:not([disabled]) { background: var(--bg-hover); color: var(--accent); }
.topbar .unit-name[disabled] { cursor: default; }
/* 批 12 · 5：未设置态从虚线框改实线幽灵钮——虚线在设计语言里是「占位/未完成」，挂顶栏常驻显得没做完 */
.topbar .unit-name.unset { color: #C77700; border: 1px solid var(--border-input); }
.topbar .unit-name.unset:hover { background: var(--tint-warning); color: #C77700; border-color: #E0A030; }
.topbar .spacer { flex: 1; }
.topbar a { font-size: var(--fs-base); }
/* 批 12 · 5：顶栏右侧「帮助/手机端」与账号 chip 统一节奏（同 padding/圆角/悬停反馈） */
.topbar a.top-link {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 5px 10px; border-radius: var(--radius-button); color: var(--text-secondary);
  transition: background var(--transition), color var(--transition);
}
.topbar a.top-link:hover { background: var(--bg-hover); color: var(--accent); }
.topbar a.top-link svg { width: 14px; height: 14px; }
/* 打磨批 2026-09-16 C：顶栏常显「退出」按钮（与 .top-link 同形；button 复位边框/背景） */
.topbar button.top-logout {
  display: inline-flex; align-items: center; gap: 5px; background: transparent; border: none; cursor: pointer;
  padding: 5px 10px; border-radius: var(--radius-button); color: var(--text-secondary); font-size: inherit;
  transition: background var(--transition), color var(--transition);
}
.topbar button.top-logout:hover { background: var(--bg-hover); color: var(--accent); }
.topbar button.top-logout svg { width: 14px; height: 14px; }

/* ── 批 12 · 8：页首 ? 角标（悬停/聚焦弹出细则；纯 CSS，data-tip 里 \n 断行）── */
.htip {
  display: inline-grid; place-items: center; width: 18px; height: 18px; border-radius: 50%;
  background: var(--neutral-100); color: var(--text-hint); font-size: 12px; font-weight: 600;
  cursor: help; vertical-align: 3px; margin-left: 7px; position: relative; user-select: none; line-height: 1;
}
.htip:hover, .htip:focus { background: var(--tint-accent); color: var(--accent); outline: none; }
/* 问号用 ::before 画（不进 textContent，防打断走查闸的 h2 全等断言） */
.htip::before { content: "?"; }
.htip::after {
  content: attr(data-tip); position: absolute; left: -10px; top: calc(100% + 9px); z-index: 85;
  width: max-content; max-width: min(440px, 72vw); white-space: pre-line; text-align: left;
  background: #2c2c30; color: #f2f2f4; font-size: var(--fs-sm); font-weight: 400; line-height: 1.8;
  border-radius: 8px; padding: 10px 13px; box-shadow: 0 8px 28px rgba(0, 0, 0, .28);
  opacity: 0; pointer-events: none; transition: opacity .12s;
}
.htip:hover::after, .htip:focus::after { opacity: 1; }

/* B6 顶栏用户下拉（显示名＋角色徽章＋组织＋修改密码＋退出；菜单项数组为 SSO 预留） */
.user-menu { position: relative; }
/* 小人图标＋姓名（限宽省略号，全名走 title 悬浮）＋下拉箭头；displayName 上限 50 字，
 * 不限宽会把顶栏「应急插播」等关键按钮挤走（实测 26 字名字 chip 达 355px）。 */
.user-chip {
  background: transparent; border: 1px solid transparent; color: var(--text-secondary);
  font-size: var(--fs-sm); padding: 5px 10px; border-radius: var(--radius-button);
  display: inline-flex; align-items: center; gap: 6px; max-width: 200px;
}
.user-chip:hover { background: var(--neutral-100); }
.user-chip .uc-ico { flex: none; display: inline-flex; color: var(--text-hint); }
.user-chip .uc-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.user-chip .caret { flex: none; font-size: 10px; color: var(--text-hint); }
.user-drop {
  position: absolute; right: 0; top: calc(100% + 6px); min-width: 220px; z-index: 30;
  background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius-card);
  box-shadow: 0 6px 24px rgba(0, 0, 0, .12); padding: 6px; text-align: left;
}
.user-drop .ud-head { padding: 8px 10px 10px; border-bottom: 1px solid var(--border); margin-bottom: 6px; }
.user-drop .ud-name { font-weight: 600; font-size: var(--fs-base); }
.user-drop .ud-org { color: var(--text-hint); font-size: var(--fs-sm); margin-top: 3px; }
.user-drop .ud-item {
  display: block; width: 100%; text-align: left; background: transparent; border: none;
  padding: 7px 10px; border-radius: var(--radius-button); font-size: var(--fs-base); color: var(--text-primary);
}
.user-drop .ud-item:hover { background: var(--neutral-100); }

/* K1 密码框「眼睛」明文切换（登录/首登改密/改密对话框/建账号初始密码统一） */
.pw-wrap { position: relative; display: block; }
.pw-wrap input { width: 100%; box-sizing: border-box; padding-right: 34px; }
.pw-eye {
  position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
  background: transparent; border: none; padding: 2px 6px; font-size: 14px;
  color: var(--text-hint); opacity: .55; line-height: 1;
}
.pw-eye:hover { opacity: .9; background: transparent; }
.pw-eye.on { opacity: 1; color: var(--accent); }
.emg-btn {
  background: var(--danger-strong); border-color: var(--danger-strong); color: #fff; font-weight: 600;
}
.emg-btn:hover { background: #b52a21; border-color: #b52a21; color: #fff; }
.emg-btn.live { animation: emg-blink 1s step-end infinite; }
@keyframes emg-blink { 50% { background: #8c1d16; border-color: #8c1d16; } }
/* 应急插播面板优化 */
.emg-active { display: flex; align-items: center; gap: 12px; background: #FDECEA; border: 1px solid var(--danger-strong); border-radius: 10px; padding: 12px 16px; margin: 12px 0; }
.emg-active-ico { font-size: 20px; line-height: 1; }
.emg-active-txt { flex: 1; color: var(--danger-strong); }
.emg-active-txt b { font-weight: 700; }
.emg-tabs { margin: 12px 0; }
.emg-form { display: flex; flex-direction: column; gap: 12px; }
.emg-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.emg-row.col { flex-direction: column; align-items: stretch; gap: 6px; }
.emg-row .emg-lbl { font-weight: 600; min-width: 64px; }
.emg-fire-btn, .emg-stopall { background: var(--danger-strong); border-color: var(--danger-strong); color: #fff; font-weight: 700; }
.emg-fire-btn:hover, .emg-stopall:hover { background: #b52a21; border-color: #b52a21; color: #fff; }
.emg-fire-btn { font-size: 17px; padding: 14px; width: 100%; margin-top: 2px; }
.emg-pl-list { max-height: 320px; overflow: auto; display: flex; flex-direction: column; gap: 4px; }
.emg-pl-row { text-align: left; padding: 8px 12px; border: 1px solid var(--border); border-radius: 8px; background: var(--bg-card); cursor: pointer; }
.emg-pl-row:hover { border-color: var(--accent); }
.emg-pl-row.on { border-color: var(--accent); background: var(--tint-accent); font-weight: 600; }
/* 关于系统面板 */
.about-kv { display: flex; gap: 12px; padding: 5px 0; font-size: var(--fs-md); align-items: baseline; }
.about-kv .muted { min-width: 88px; }
.about-dev { margin-top: 10px; display: flex; gap: 8px; align-items: center; }
.about-dev[hidden] { display: none; }
.about-dev input { width: 180px; }

.body { display: flex; flex: 1; min-height: 0; }
.side {
  width: 176px; background: var(--bg-card); border-right: 1px solid var(--border);
  padding: 12px 0; flex-shrink: 0;
}
/* 批 12 · 5：通铺色块＋左橙条 → 飞书式「圆角药丸」选中态（左右留边距，不顶到边）；
   每项带 18px 线性图标；分组用留白不画线（微信原则）。立体/渐变刻意不做——
   全站唯一的强调色是橙，八个菜单若做立体会与「立即发布/应急插播」抢眼。 */
.side nav a {
  display: flex; align-items: center; gap: 9px;
  margin: 2px 10px; padding: 8px 12px; border-radius: 8px;
  color: var(--text-primary); font-size: var(--fs-md);
  transition: background var(--transition), color var(--transition);
}
.side nav a .mi { display: inline-flex; flex: none; color: var(--text-hint); transition: color var(--transition); }
.side nav a .mi svg { width: 18px; height: 18px; stroke-width: 1.8; }
.side nav a:hover { background: var(--bg-hover); }
.side nav a:hover .mi { color: var(--text-secondary); }
.side nav a.active { color: var(--accent); background: var(--accent-light); font-weight: 600; }
.side nav a.active .mi { color: var(--accent); }
/* 批 15-4：分组留白＋居中一条极浅细线——纯留白的分组感太弱（业主体感），线用 --line 噪音最低 */
.side nav .nav-gap { height: 20px; position: relative; }
.side nav .nav-gap::after { content: ""; position: absolute; left: 12px; right: 12px; top: 50%; height: 1px; background: var(--line); }
.main { flex: 1; padding: 18px 24px 24px; min-width: 0; }
.tabs {
  display: flex; gap: 4px; border-bottom: 1px solid var(--border); margin-bottom: 16px;
}
.tabs a {
  padding: 8px 16px; color: var(--text-secondary); font-size: var(--fs-md);
  border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.tabs a:hover { color: var(--text-primary); }
.tabs a.on { color: var(--accent); border-bottom-color: var(--accent); font-weight: 600; }
.main h2 { font-size: var(--fs-2xl); margin-bottom: 4px; }
.main .desc { color: var(--text-hint); font-size: var(--fs-sm); margin-bottom: 18px; }
.bar { display: flex; gap: 10px; align-items: center; margin-bottom: 16px; flex-wrap: wrap; }
.bar .spacer { flex: 1; }
/* E6（M10-OPT S1）：编辑器顶栏吸顶——滚到画布深处仍随手可保存/返回 */
.editor-bar {
  position: sticky; top: 52px; z-index: 9;
  background: var(--bg-page); padding: 8px 0;
  box-shadow: 0 6px 8px -8px rgba(0, 0, 0, .25);
}
.panel {
  background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius-card);
  padding: 16px; margin-bottom: 16px; box-shadow: var(--shadow-card);
}

/* ── 状态 pill（浅色 tint 底＋语义色字）── */
.pill { display: inline-block; padding: 1px 10px; border-radius: 99px; font-size: var(--fs-sm); }
.pill.on   { background: var(--tint-success); color: var(--success); }
.pill.off  { background: var(--tint-error); color: var(--error); }
.pill.dim  { background: var(--neutral-100); color: var(--text-secondary); }
.pill.warn { background: var(--tint-warning); color: #C77700; }
/* 可点旋转徽章：按钮当 pill 用，重置 UA 边框，悬停橙框 */
button.rotpill { border: 1px solid transparent; cursor: pointer; line-height: 1.5; vertical-align: middle; }
button.rotpill:hover { border-color: var(--accent); color: var(--accent); background: var(--tint-accent); }

/* ── 卡片网格（素材库等）── */
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 14px; }
/* 批 12 补 · 通用网格空态：**跨满整行居中**。空态若当普通网格项塞进去，只占一列、文字挤成
   竖条（「我的模板」实锤）；grid-column:1/-1 在非 grid 容器里无副作用，两类容器通用。 */
.grid-empty { grid-column: 1 / -1; text-align: center; padding: 34px 12px; color: var(--text-hint); }
.card {
  background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius-card);
  overflow: hidden; box-shadow: var(--shadow-card);
  /* 批 12 补：竖向 flex ＋ 操作行贴底——同行卡片内容高度不一（标签多少/描述长短）时，
     grid 拉伸出的余量落在 meta 与操作行之间，按钮全行对齐，不再是深浅不一的底部空白 */
  display: flex; flex-direction: column;
}
.card .ops { margin-top: auto; }
.card.sel { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.card .thumb { height: 110px; background: var(--neutral-100); display: grid; place-items: center; color: var(--text-hint); font-size: 34px; overflow: hidden; }
.card .thumb img { width: 100%; height: 100%; object-fit: cover; }
.card .meta { padding: 8px 10px; font-size: var(--fs-sm); }
.card .meta .nm { color: var(--text-primary); font-size: var(--fs-base); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.card .meta .row { display: flex; justify-content: space-between; color: var(--text-hint); margin-top: 2px; align-items: center; }
.card .ops { display: flex; gap: 6px; padding: 0 10px 10px; }
.card .ops button { padding: 2px 8px; font-size: var(--fs-sm); }

/* ── 播出单编辑器（M10-OPT S7 E1 两栏重构：大画布 ~70% ＋ 右检查器/图层/条目列表）── */
.editor { display: flex; gap: 18px; align-items: flex-start; }
.editor .canvas-col { flex: 7; min-width: 0; }
/* 右栏 max-height 由 fitCanvas() 按视口剩余高设死并在栏内滚动——条目多时不再把整页撑高
   （整页一滚，刚做的「画布不出屏」就白做了）。 */
.editor .side-col { flex: 3; min-width: 300px; max-width: 400px; overflow-y: auto; }
/* 竖屏画布（2026-08-16）：9:16 在受限高度下只能吃掉左栏一小半宽（实测 966px 里只用 337px），
   剩下的与其空着不如让给右栏——条目名此前被截断成「示例·一网通办（1920×9…」。
   640px ＝ 画布下方那排「＋媒体…＋天气 复制选中区 删除选中区」按钮实测 595px 的安全余量。 */
.editor.tall-canvas .canvas-col { flex: 0 0 auto; width: 640px; max-width: 100%; }
.editor.tall-canvas .side-col { flex: 1; max-width: 560px; }
.canvas {
  background: #1c1c1e; border: 1px dashed var(--neutral-300); border-radius: var(--radius-card);
  margin: 0 auto 12px; position: relative; overflow: hidden;
}
/* 画布像素尺寸由 JS fitCanvas() 按「剩余宽 × 剩余高」算出后设死（2026-08-16）。
   以下两条只是 JS 未跑时的兜底——原先横屏 width:100%、竖屏 height:min(72vh,820px)
   都不看剩余高度：实测竖屏画布下缘出屏 65px（1600×1000）~127px（1440×780）、
   「＋媒体…」按钮条出屏 104~166px，同时左栏 966px 宽只用掉 405px。 */
.canvas.landscape { width: 100%; aspect-ratio: 16 / 9; }
.canvas.portrait  { height: min(72vh, 820px); width: auto; aspect-ratio: 9 / 16; }
.canvas .hint { position: absolute; inset: 0; display: grid; place-items: center; color: #9a9aa0; font-size: var(--fs-sm); text-align: center; }
.canvas img { width: 100%; height: 100%; object-fit: contain; }
.pl-items { list-style: none; }
.pl-items li {
  display: flex; gap: 8px; align-items: center; background: var(--bg-header);
  border: 1px solid var(--border); border-radius: var(--radius-button);
  padding: 6px 10px; margin-bottom: 6px; font-size: var(--fs-base);
}
.pl-items .nm { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pl-items input { width: 54px; padding: 2px 6px; text-align: right; }
.pl-items button { padding: 1px 7px; font-size: var(--fs-sm); }

/* E1 右栏条目列表头＋「＋添加素材」入口（素材库撤出主版面） */
.items-head { display: flex; gap: 8px; align-items: center; margin: 4px 0 8px; }
.items-head b { font-size: var(--fs-base); }
.items-head .spacer { flex: 1; }
.items-head[hidden], .pl-items[hidden] { display: none; } /* P2-③ 非媒体分区整块收起 */

/* P2-②（2026-08-16）条目缩略图：一列同名素材（「示例 · 党建引领…」）光看名字分不清哪张是哪张 */
.it-th {
  width: 40px; height: 26px; flex-shrink: 0; border-radius: 3px; overflow: hidden;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--neutral-100); font-size: 17px;   /* ＝类型图标尺寸（1em 内联 SVG，1-4） */
  color: var(--text-hint);
}
.it-th img { width: 100%; height: 100%; object-fit: cover; display: block; }
.pl-items li[draggable] { cursor: grab; }
.pl-items li.dragging { opacity: .45; }

/* E5 字幕联动：选中字幕分区时高亮顶栏字幕输入框 */
.mq-live { outline: 2px solid var(--accent); outline-offset: 1px; }

/* F4 分区图层面板（右栏；上=顶层） */
.zonelist { padding: 8px 10px; margin-bottom: 12px; font-size: var(--fs-sm); }
.zonelist[hidden] { display: none; }
.zl-head { margin-bottom: 4px; font-size: var(--fs-xs); }
.zl-row {
  display: flex; gap: 6px; align-items: center; padding: 4px 6px;
  border-radius: var(--radius-button); cursor: pointer;
}
.zl-row:hover { background: var(--neutral-100); }
.zl-row.sel { background: var(--tint-accent, rgba(255,122,0,.12)); box-shadow: 0 0 0 1px var(--accent) inset; }
.zl-row .zl-nm { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.zl-row button { padding: 0 6px; font-size: var(--fs-xs); }
.zl-dot { width: 10px; height: 10px; border-radius: 3px; flex-shrink: 0; }
.zl-dot.k-media { background: rgba(59,130,246,.8); }
.zl-dot.k-clock { background: rgba(168,85,247,.8); }
.zl-dot.k-countdown { background: rgba(236,72,153,.8); }
.zl-dot.k-text { background: rgba(34,197,94,.8); }
.zl-dot.k-marquee { background: rgba(245,158,11,.9); }
.zl-dot.k-web { background: rgba(6,182,212,.8); }
.zl-dot.k-weather { background: rgba(14,165,120,.85); }
.zl-dot.k-hotspot { background: transparent; border: 1.5px dashed #F97316; }

/* F4 对齐快捷钮（检查器内） */
.alns { display: inline-flex; gap: 3px; margin-left: 8px; }
.alns button { padding: 2px 7px; font-size: var(--fs-xs); }

/* E1 素材选择器弹窗（搜索＋类型筛选＋点选序号=播出顺序） */
dialog.media-pick { min-width: 720px; max-width: 92vw; }
.mp-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 10px;
  max-height: 54vh; overflow: auto; padding: 2px; margin-top: 10px;
}
.mp-card {
  position: relative; border: 1px solid var(--border); border-radius: var(--radius-card);
  overflow: hidden; cursor: pointer; background: var(--bg-card); user-select: none;
}
.mp-card:hover { border-color: var(--accent); }
.mp-card.on { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.mp-card .thumb { height: 84px; background: var(--neutral-100); display: grid; place-items: center; color: var(--text-hint); font-size: 26px; overflow: hidden; }
.mp-card .thumb img { width: 100%; height: 100%; object-fit: cover; }
.mp-card .meta { padding: 5px 8px; font-size: var(--fs-xs); }
.mp-card .meta .nm { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-primary); font-size: var(--fs-sm); }
.mp-ord {
  position: absolute; top: 4px; left: 4px; background: var(--accent); color: #fff;
  border-radius: 99px; min-width: 20px; height: 20px; padding: 0 4px;
  display: grid; place-items: center; font-size: var(--fs-xs); font-weight: 700;
}
/* 视频「1 路」名额已被别的分区占用时：卡片提前置灰不可点（2026-08-16，取代加完再 toast 跳过） */
.mp-card.blocked { opacity: .45; cursor: not-allowed; }
.mp-card.blocked:hover { border-color: var(--border); }
.mp-lock {
  position: absolute; top: 4px; right: 4px; z-index: 2; background: rgba(30,30,32,.82); color: #fff;
  border-radius: 4px; padding: 1px 5px; font-size: var(--fs-2xs); white-space: nowrap;
}
.mp-note {
  margin: 8px 0 0; padding: 7px 10px; border-radius: 6px; font-size: var(--fs-sm); line-height: 1.5;
  color: var(--warning-strong, #B26A00); background: #FFF6E5; border: 1px solid #F0C476;
}
/* 发布浮层「素材库」已选内容 chips（序号=播出顺序，可就地移除） */
.qm-chips { display: flex; flex-wrap: wrap; gap: 6px; min-height: 24px; }
.qm-chip {
  display: inline-flex; align-items: center; gap: 4px; max-width: 220px;
  padding: 3px 6px 3px 8px; border-radius: 6px; font-size: var(--fs-sm);
  background: var(--neutral-100); border: 1px solid var(--line);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.qm-chip b { color: var(--accent); font-weight: 700; }
.qm-chip .chip-x { color: var(--text-hint); font-weight: 700; text-decoration: none; padding: 0 2px; }
.qm-chip .chip-x:hover { color: var(--danger-strong); }
/* 快捷发布 compose-box（豆包/微信式：文字框＋按钮排＋内联行＋chips） */
.compose { border: 1px solid var(--line); border-radius: 10px; padding: 10px; background: var(--panel); transition: border-color .15s; }
.compose.over { border-color: var(--accent); background: var(--accent-light); }   /* 原 color-mix 需 Chromium 111+；改 token（A②） */
.compose > textarea { width: 100%; border: 0; resize: vertical; min-height: 46px; font-size: var(--fs-md); background: transparent; padding: 2px; }
.compose > textarea:focus { outline: none; }
.cb-tools { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; border-top: 1px solid var(--line); padding-top: 8px; }
.cb-btn {
  display: inline-flex; align-items: center; gap: 5px; padding: 6px 10px; border-radius: 8px;
  border: 1px solid var(--line); background: var(--neutral-100); color: var(--text-primary);
  font-size: var(--fs-sm); cursor: pointer; transition: all .12s;
}
.cb-btn:hover { border-color: var(--accent); color: var(--accent); }
.cb-btn .ico { font-size: 15px; line-height: 1; }
.cb-inline { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: 8px; }
.cb-inline[hidden] { display: none; } /* 自定义 display 会盖掉 UA [hidden]，须显式补 */
.cb-inline input { flex: 1; min-width: 120px; }

/* E3 编辑器全屏预览遮罩 */
.pv-full { position: fixed; inset: 0; z-index: 200; background: #000; display: grid; place-items: center; }
.pv-stage { position: relative; overflow: hidden; }
.pv-stage .pvz { position: absolute; overflow: hidden; }
.pv-stage .pvz img, .pv-stage .pvz video { width: 100%; height: 100%; object-fit: contain; display: block; }
.pv-exit { position: fixed; top: 14px; right: 16px; z-index: 210; }
.pv-exit button { background: rgba(30,30,32,.82); color: #fff; border: 1px solid rgba(255,255,255,.3); }
.pv-ph {
  height: 100%; display: grid; place-items: center; align-content: center; gap: 6px;
  color: #bbb; text-align: center; padding: 8px; font-size: var(--fs-sm);
}
.pv-ph .mono { font-size: var(--fs-xs); word-break: break-all; }
.pv-clockz { display: grid; place-items: center; height: 100%; }
.pv-clock { text-align: center; color: #fff; }
.pv-clock.card { background: rgba(20,20,24,.55); border-radius: 12px; padding: 6% 10%; }
.pv-clock .t { font-weight: 700; line-height: 1.1; font-variant-numeric: tabular-nums; }
.pv-clock .d { opacity: .85; margin-top: 4px; }
.pv-textz { height: 100%; overflow: hidden; white-space: pre-wrap; word-break: break-all; }
.pv-textz .pv-text { will-change: transform; } /* 自动纵滚：内层平移，外层裁切（与终端 box/textzone 同构） */
.pv-mqz { display: flex; align-items: center; white-space: nowrap; overflow: hidden; }
.pv-mqz .pv-mq { color: #fff; will-change: transform; }
.pv-webz iframe { width: 100%; height: 100%; border: 0; background: #fff; }

/* ── 回执三态条 ── */
.receipt-bar { display: flex; height: 8px; border-radius: 4px; overflow: hidden; background: var(--neutral-100); width: 140px; }
.receipt-bar i { display: block; height: 100%; }
.progress3 { font-size: var(--fs-sm); color: var(--text-secondary); }
.toast { position: fixed; top: 62px; right: 18px; z-index: 99; display: flex; flex-direction: column; gap: 8px; }
.toast div {
  background: var(--bg-card); border: 1px solid var(--border); border-left: 3px solid var(--accent);
  padding: 10px 16px; border-radius: var(--radius-button); max-width: 380px; box-shadow: var(--shadow-card);
}
.toast div.err { border-left-color: var(--error); }
.toast div.warn { border-left-color: var(--warning, #FF9F0A); }
.toast div.ok { border-left-color: var(--success); }
.muted { color: var(--text-hint); }
.mono { font-family: ui-monospace, monospace; }
.snapshot-img { max-width: 320px; border-radius: var(--radius-button); border: 1px solid var(--border); }
/* 监播室大图弹窗无图占位（B②：不支持截屏/未回图/离线也能进弹窗） */
.snapshot-ph { width: 320px; max-width: 100%; aspect-ratio: 16 / 9; display: flex; align-items: center; justify-content: center; background: var(--neutral-100); border-radius: var(--radius-button); border: 1px solid var(--border); }
dialog {
  /* ⚠️ margin:auto 必须显式写回——本表第 2 行的 `* { margin: 0 }` 会盖掉浏览器给 <dialog>
     的默认居中规则，漏了则全站所有对话框都贴在屏幕左上角（2026-08-16 编辑器走查揪出）。 */
  margin: auto;
  background: var(--bg-card); color: var(--text-primary); border: 1px solid var(--border);
  border-radius: var(--radius-card); padding: 22px; min-width: 380px; box-shadow: var(--shadow-modal);
  /* M13 批 1 S3：内容超过一屏（如几十条日期例外）时对话框自身滚动，底部按钮永远够得着 */
  max-height: calc(100vh - 32px); overflow: auto; box-sizing: border-box;
}
dialog::backdrop { background: rgba(0, 0, 0, .45); }
dialog h3 { margin-bottom: 12px; }
dialog .row { margin: 10px 0; }
dialog .row label { display: block; color: var(--text-secondary); font-size: var(--fs-base); margin-bottom: 4px; }
dialog .btns { display: flex; gap: 10px; justify-content: flex-end; margin-top: 16px; }

/* ── 整页寄宿对话框（M10：发现绑定/指令面板并入监播室·设备）── */
dialog.page-dlg { min-width: 880px; max-width: 94vw; }
dialog.page-dlg .dlg-page h2 { font-size: var(--fs-xl); }

/* ── 应急插播浮层（M10：撤出菜单，顶栏红按钮全页可达）── */
.overlay { position: fixed; inset: 0; background: rgba(0, 0, 0, .45); z-index: 90; display: grid; place-items: start center; overflow: auto; padding: 40px 16px; }
.overlay-box {
  background: var(--bg-page); border-radius: var(--radius-card); box-shadow: var(--shadow-modal);
  width: min(960px, 96vw); padding: 20px 24px;
}
.overlay-head { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; }
.overlay-head .spacer { flex: 1; }

/* ── M5 播出计划/开关机编辑行 ── */
.slot-row { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; margin: 4px 0; }
.slot-row input[type="time"], .slot-row input[type="date"] { padding: 4px 6px; }
.daychk { display: inline-flex; align-items: center; gap: 2px; font-size: var(--fs-sm); margin-right: 2px; user-select: none; }

/* ── M6 巡屏墙 ── */
.wall-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 14px; }
.wall-tile { position: relative; background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius-card); overflow: hidden; box-shadow: var(--shadow-card); }
.wall-tile.offline { opacity: .5; }
/* 卡片勾选框（左上角覆盖在画面上）＋选中高亮边框 */
.wall-tile.sel { border-color: var(--acc); box-shadow: 0 0 0 2px var(--acc); }
.wall-tile .tile-sel { position: absolute; top: 6px; left: 6px; z-index: 2; background: rgba(0,0,0,.45); border-radius: 6px; padding: 3px 5px; cursor: pointer; line-height: 0; }
.wall-tile .tile-sel input { width: 16px; height: 16px; cursor: pointer; margin: 0; accent-color: var(--acc); }
.wall-selall, .wall-auto { display: inline-flex; align-items: center; gap: 5px; }
.wall-tile .shot { aspect-ratio: 16/9; background: #000; display: grid; place-items: center; cursor: pointer; overflow: hidden; position: relative; }
/* 竖屏设备（旋转 90/270）：**画面框本身就是竖的**（9/16）——监播室的卡片要一眼看出
   「这是一台竖着装的电视」，而不是「横屏电视里放了张竖图」（后者左右两条黑边正是
   横屏屏幕的观感来源，2026-08-17 业主指出）。
   ⚠️ 关键是**竖框与横屏画面等高**，否则 grid 同一行会被它撑高、横屏卡片下方多出一片空白
   （这正是老代码 9/16 + max-width:210px 的毛病：高 373px vs 横屏 214px）。
   推导：横屏画面高 ＝ 卡片宽 × 9/16；竖框要同高且自身 9:16 → 竖框宽 ＝ 卡片宽 × 9/16 × 9/16
   ＝ **卡片宽 × 81/256**。于是 334px 的卡片得到 106×188 的竖框，与横屏画面 334×188 一样高。
   两侧露的是卡片底色（不是黑画面），看着就是一台竖屏机器立在卡片里。 */
.wall-tile.portrait .shot { aspect-ratio: 9/16; width: calc(100% * 81 / 256); margin: 0 auto; }
/* ⚠️ 必须**绝对定位**：`.shot` 的高度来自 aspect-ratio，img 的 `height:100%` 在这种父高度下
   不被解析 → 退化成「按宽度×内在比例」。横屏图 16:9 算出来正好等于框高（巧合，所以一直没露馅），
   竖屏图却算成 334×593、被 overflow 裁得只剩顶部一条 —— 这正是老代码要给竖屏另设
   aspect-ratio:9/16 的原因（在绕这个坑，而不是解决它）。inset:0 让 img 盒子精确等于框，
   contain 才真正把竖图等比缩到满高、左右留黑。 */
.wall-tile .shot img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; }
.wall-tile .shot .ph { color: #9a9aa0; font-size: var(--fs-base); }
/* I4：>10 分钟旧截屏灰蒙（画面还在但明示不新鲜） */
.wall-tile .shot .stale { position: absolute; inset: 0; background: rgba(24, 24, 26, .55); color: #e3e3e6; display: grid; place-items: center; font-size: var(--fs-sm); letter-spacing: 2px; }
/* 批 12 · 4：标题行**永不折行**——设备名作弹性项超长省略号（title 悬浮看全名），
   时间钉右端；挤不下牺牲的是"名称显示几个字"，不是折行/撑宽卡片（首页侧栏同款约定）。 */
.wall-tile .cap { padding: 7px 10px; font-size: var(--fs-sm); display: flex; gap: 8px; align-items: center; flex-wrap: nowrap; }
.wall-tile .cap .mono, .wall-tile .cap .pill { flex: none; }
.wall-tile .cap .cap-nm { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* I4：时间读数不换行、靠右（修长时间戳折行挤乱标题行） */
.wall-tile .cap .t { margin-left: auto; white-space: nowrap; font-size: 11px; flex: none; }
/* 批 12 · 7：正在等回图的卡片盖「刷新中…」淡遮罩（反馈落在受影响的对象上，回图即撤） */
.wall-tile .shot .refreshing {
  position: absolute; inset: 0; display: grid; place-items: center;
  background: rgba(24, 24, 26, .45); color: #e3e3e6; font-size: var(--fs-sm); letter-spacing: 2px;
}
/* 批 12 · 7：右侧状态文字在「等待回图」期间加深加粗（此前恒灰细字，业主反馈从没注意到过） */
#stat.busy { color: var(--text-primary); font-weight: 600; }
.snapshot-img { max-width: min(72vw, 900px); }

/* ── M6 告警角标（M10 挂监播室菜单项）── */
/* 「告警」页签上的未知悉角标（2026-08-17 从一级菜单下沉至此，口径＝未知悉、看过即清零）。
   ⚠️ `display:inline-block` 会**盖掉 `hidden` 属性的默认隐藏**（JS 用 el.hidden 控制显隐），
   故必须补一条 [hidden] 规则，否则「0 条待知悉」时会显示一个空红点。 */
.alert-badge {
  display: inline-block; min-width: 18px; text-align: center; background: var(--error); color: #fff;
  border-radius: 99px; font-size: var(--fs-xs); padding: 0 5px; margin-left: 6px;
}
.alert-badge[hidden] { display: none; }
.nav-badge { margin-left: auto; } /* 2026-09-19 「设备管理」菜单待绑定台数（右贴） */
/* 发布对话框选屏区内联提示：还有 N 台新设备未绑定（2026-09-19 待绑定三层提示③） */
.unbound-note {
  display: flex; align-items: center; gap: 8px; margin: 6px 0; padding: 8px 12px; background: var(--tint-warning);
  border: 1px solid #F0D9A8; border-radius: var(--radius-button); font-size: var(--fs-sm); color: #8A5300;
}
.unbound-note button { margin-left: auto; }
.toast div.act-toast .act { display: flex; gap: 8px; margin-top: 8px; justify-content: flex-end; }
/* 未知悉的告警行：行首一道橙条（2026-08-17）。红点说「N 条」，进来就靠它一眼认出是哪几行——
   提示与落点对得上，用户才不会在满屏记录里找不着北。 */
tr.alert-unacked td:first-child { box-shadow: inset 3px 0 0 0 var(--acc); }

/* ── M6 模板库卡片 ── */
.tpl-card .thumb { height: 130px; flex: none; }
/* 批 12 补：描述长短不一时「制作」行贴底，同行卡片按钮对齐（.card flex 列的配套） */
.tpl-card .meta { display: flex; flex-direction: column; flex: 1; }
/* M11-OPT P2-4：描述换行占满宽度会把「制作」按钮压成竖排两行并重叠——按钮不许缩、文字让位 */
.tpl-card .meta .row { gap: 8px; margin-top: auto; }
.tpl-card .meta .row .muted { flex: 1 1 auto; min-width: 0; }
.tpl-card .meta .row .mk { flex: 0 0 auto; min-width: 56px; white-space: nowrap; }

/* ── M10-OPT S3 素材库：列表视图/批量栏/预览弹窗/拖拽上传 ── */
.seg { display: inline-flex; border: 1px solid var(--border-input); border-radius: var(--radius-button); overflow: hidden; }
.seg button { border: 0; border-radius: 0; padding: 5px 12px; font-size: var(--fs-sm); background: var(--bg-card); }
.seg button + button { border-left: 1px solid var(--border-input); }
.seg button.on { background: var(--tint-accent); color: var(--accent); font-weight: 600; }
.pill.share { background: var(--tint-info); color: #1668B8; }
.media-table th.sortable { cursor: pointer; user-select: none; white-space: nowrap; }
.media-table th.sortable:hover { color: var(--accent); }
.media-table th.chk, .media-table td.chk { width: 30px; padding-right: 0; }
.media-table td.nmcell { display: flex; align-items: center; gap: 10px; min-width: 220px; }
/* 批 12 · 2：**固定正方形缩略格**＋等比缩放居中（业主 2026-08-20 提「大小比例不一致」）。
   此前按图片比例自适应宽度（16:9 宽条 / 9:16 细窄条），整列参差；正方形容器里
   16:9 渲染成 48×27、9:16 渲染成 27×48——恰好互为旋转 90°，任何比例 footprint 全一致
   （Windows 资源管理器/网盘列表视图的通行做法）。JS fitThumb 仍会写 aspect-ratio，
   但容器宽高都定死后 aspect-ratio 被忽略，无需动 JS。 */
.media-table .mthumb {
  flex-shrink: 0; width: 48px; height: 48px; position: relative;
  border-radius: 6px; overflow: hidden;
  /* font-size 同时是类型图标（1em 内联 SVG，1-4）的尺寸——原先 emoji 也是这么定大小的 */
  background: var(--neutral-100); display: grid; place-items: center; color: var(--text-hint); font-size: 20px;
}
/* ⚠️ img 必须**绝对定位钉满容器**（批 12 修，业主截图揪出）：place-items:center 的 grid 里
   img 的 height:100% 不被解析 → 退化成「按宽度×内在比例」（48×76.8），溢出被圆角容器裁掉，
   竖图只剩中间一截＝看着像 cover 裁切。监播室 8-17 同款坑（.wall-tile .shot img），同款药。 */
.media-table .mthumb img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; display: block; }
.media-table .mname { cursor: pointer; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 340px; }
.media-table td.mops { white-space: nowrap; }
.media-table td.mops button { padding: 2px 8px; font-size: var(--fs-sm); margin-right: 4px; }
.batch-bar {
  display: flex; gap: 10px; align-items: center; margin-bottom: 12px; padding: 8px 12px;
  background: var(--tint-accent); border: 1px solid var(--accent); border-radius: var(--radius-button);
}
/* display:flex/grid 会盖掉 UA 的 [hidden]{display:none}，必须显式补回 */
.batch-bar[hidden], .drop-mask[hidden] { display: none; }
.batch-bar .spacer { flex: 1; }

/* M11-S1 素材治理：标签 chips / 回收站说明 / 有效期控件 / 回收站按钮态 */
.media-table td.nmcell .nmwrap { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.mtags { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 2px; }
.mtags .tag, .card .mtags .tag {
  display: inline-block; padding: 0 7px; border-radius: 99px; font-size: var(--fs-sm);
  background: var(--neutral-100); color: var(--text-secondary); line-height: 18px;
}
.card .mtags { padding: 0 10px 4px; }
.recycle-note {
  margin: 0 0 12px; padding: 8px 12px; font-size: var(--fs-sm);
  background: var(--tint-warning); color: #8A5A00; border-radius: var(--radius-button);
}
.recycle-note[hidden] { display: none; }
#recBtn.on { background: var(--tint-accent); border-color: var(--accent); color: var(--accent); }
.exp-ctrl { display: inline-flex; gap: 8px; align-items: center; }
.exp-ctrl input[type=date][hidden] { display: none; }
.batch-bar button { padding: 3px 10px; font-size: var(--fs-sm); }
.card .ops { flex-wrap: wrap; }
.drop-mask {
  position: fixed; inset: 0; z-index: 95; pointer-events: none;
  background: rgba(255, 122, 0, .08); display: grid; place-items: center;
}
.drop-mask .drop-hint {
  border: 2px dashed var(--accent); border-radius: var(--radius-card); color: var(--accent);
  background: var(--bg-card); padding: 26px 48px; font-size: var(--fs-2xl); font-weight: 600;
}
.up-panel {
  position: fixed; right: 18px; bottom: 18px; z-index: 96; width: 340px; max-height: 46vh; overflow: auto;
  background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius-card);
  box-shadow: var(--shadow-modal); padding: 10px 14px 12px;
}
.up-panel .up-title { font-weight: 600; margin-bottom: 6px; display: flex; align-items: center; justify-content: space-between; }
.up-panel .up-x { border: 0; background: none; font-size: 16px; padding: 0 4px; color: var(--text-hint); }
.up-row { display: flex; gap: 8px; align-items: center; font-size: var(--fs-sm); margin: 6px 0; }
.up-row .nm { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.up-row .upbar { width: 90px; height: 6px; border-radius: 3px; background: var(--neutral-100); overflow: hidden; flex-shrink: 0; }
.up-row .upbar i { display: block; height: 100%; background: var(--accent); transition: width .2s; }
.up-row .upbar i.ok { background: var(--success); }
.up-row .upbar i.err { background: var(--error); }
.up-row .st { width: 46px; text-align: right; color: var(--text-hint); flex-shrink: 0; }
dialog.media-preview { min-width: 560px; max-width: min(920px, 94vw); }
.media-preview .pv-body { background: var(--neutral-100); border-radius: var(--radius-button); display: grid; place-items: center; padding: 8px; }
.media-preview .pv-img { max-width: 100%; max-height: 56vh; display: block; }
.media-preview .pv-video { max-width: 100%; max-height: 56vh; }
.media-preview .pv-doc-nav { display: flex; gap: 12px; align-items: center; justify-content: center; padding: 8px 0 2px; }
.media-preview .pv-stream { padding: 20px 8px; text-align: center; }
.media-preview .pv-stream .mono { word-break: break-all; margin-bottom: 10px; }
.media-preview .pv-meta { display: flex; gap: 14px; flex-wrap: wrap; color: var(--text-secondary); font-size: var(--fs-sm); margin-top: 10px; }
.media-preview .pv-refs { margin-top: 8px; font-size: var(--fs-sm); }
.media-preview .pv-refs .refpl { margin-right: 10px; }

/* ── M8 布局编辑器（画布分区/手柄/吸附线；画布保持深底衬分区色块）── */
/* ── 画布分区（2026-08-16「画布即舞台」改造）──────────────────────────────────
   改造前：每个分区一块 18%~28% 的彩色半透明蒙版＋一个文字标签，内容一概不画——
   分区模式下等于所见非所得（传统全屏单反而显示素材大图），而且刚做的整屏底图被蒙版染色。
   改造后：分区内容真渲染（见 app.js renderZoneOnCanvas），分区本身只留一圈虚线框＋
   左上角小标签；彩色只留在标签的圆点上（仍能一眼区分 kind）。 */
.canvas .zone { position: absolute; border: 1px dashed rgba(255,255,255,.42); cursor: move; overflow: hidden; touch-action: none; }
/* P2-②：拖放悬停的媒体分区（拖桌面文件进来 / 从条目列表把条目搬过来） */
.canvas .zone.drop-hot { border: 2px solid var(--accent); box-shadow: 0 0 0 3px rgba(255,122,0,.35) inset; }
.canvas .zone .zl {
  position: absolute; left: 0; top: 0; z-index: 4; display: flex; gap: 4px; align-items: center;
  font-size: var(--fs-2xs); color: #fff; white-space: nowrap; pointer-events: none;
  background: rgba(0,0,0,.62); padding: 1px 6px 2px 4px; border-bottom-right-radius: 6px;
}
.canvas .zone .zl i { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.canvas .zone.sel { border: 2px solid var(--accent); box-shadow: 0 0 0 1px var(--accent) inset; }
.canvas .zone.sel .zl { background: var(--accent); }
.canvas .zone.k-media .zl i { color: #3B82F6; }
.canvas .zone.k-clock .zl i { color: #A855F7; }
.canvas .zone.k-countdown .zl i { color: #EC4899; }
.canvas .zone.k-text .zl i { color: #22C55E; }
.canvas .zone.k-marquee .zl i { color: #F59E0B; }
.canvas .zone.k-web .zl i { color: #06B6D4; }
.canvas .zone.k-weather .zl i { color: #0EA578; }
.canvas .zone.k-hotspot .zl i { color: #F97316; }
/* M17 S2 触摸按钮：终端上透明，画布上用橙色虚线框＋浅底标出位置 */
.canvas .zone.k-hotspot { border-style: dashed !important; border-color: #F97316 !important; background: rgba(249,115,22,.12) !important; }
/* 「点击 → 目标」角标（左下，避开右下「共 N 条」） */
.canvas .zone .zc-tap {
  position: absolute; left: 0; bottom: 0; z-index: 4; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  background: rgba(249,115,22,.88); color: #fff; font-size: var(--fs-2xs); padding: 1px 5px; border-top-right-radius: 6px; pointer-events: none;
}
.insp-touch { border-top: 1px dashed var(--border, #ddd); margin-top: 8px; padding-top: 8px; }

/* 分区内容层：撑满分区、不吃鼠标（拖移/缩放手势仍落在 .zone 上）。 */
.canvas .zone .zc { position: absolute; inset: 0; overflow: hidden; pointer-events: none; }
.canvas .zone .zc img { width: 100%; height: 100%; object-fit: contain; display: block; }
/* 空分区：淡淡的类型提示，不喧宾夺主 */
.canvas .zone .zc-empty {
  position: absolute; inset: 0; display: grid; place-items: center; text-align: center;
  color: rgba(255,255,255,.42); font-size: var(--fs-xs); padding: 4px; line-height: 1.4;
}
/* 时钟/倒计时/天气：与终端同构的居中卡 */
.canvas .zone .zc-mid { position: absolute; inset: 0; display: grid; place-items: center; text-align: center; color: #fff; }
.canvas .zone .zc-mid .t { font-weight: 700; line-height: 1.1; letter-spacing: .02em; }
.canvas .zone .zc-mid .d { opacity: .82; line-height: 1.3; }
.canvas .zone .zc-mid.card > div { background: rgba(0,0,0,.34); border-radius: 8px; padding: 4% 8%; }
/* 文字分区：真文字（字号按画布缩放，与终端 sp 同源换算） */
.canvas .zone .zc-text { position: absolute; inset: 0; color: #fff; white-space: pre-wrap; word-break: break-all; overflow: hidden; }
/* 字幕分区：画布上静态显示（不做滚动动画——画布会随每次改动整树重绘，跑动画既费电又会闪） */
.canvas .zone .zc-mq {
  position: absolute; inset: 0; display: flex; align-items: center; gap: 6px;
  background: rgba(0,0,0,.55); color: #fff; white-space: nowrap; overflow: hidden; padding: 0 6px;
}
/* 网页/直播流：画布上一律占位卡（真嵌 iframe / 真拉流会让编辑器卡顿，也是 BrightAuthor 的做法） */
.canvas .zone .zc-ph {
  position: absolute; inset: 0; display: grid; place-items: center; align-content: center; gap: 3px;
  text-align: center; color: rgba(255,255,255,.72); font-size: var(--fs-xs); padding: 4px;
  background: rgba(255,255,255,.06);
}
.canvas .zone .zc-ph .u { font-size: var(--fs-2xs); opacity: .7; max-width: 92%; overflow: hidden; text-overflow: ellipsis; }
/* 媒体分区右下角「共 N 条」角标（画布只画第 1 条，得让用户知道后面还有） */
.canvas .zone .zc-n {
  position: absolute; right: 0; bottom: 0; z-index: 4; background: rgba(0,0,0,.62); color: #fff;
  font-size: var(--fs-2xs); padding: 1px 5px; border-top-left-radius: 6px; pointer-events: none;
}
.canvas .zone .hd { position: absolute; width: 10px; height: 10px; background: var(--accent); border: 1px solid #fff; border-radius: 2px; display: none; z-index: 5; touch-action: none; }
.canvas .zone.sel .hd { display: block; }
.hd-nw { left: 0; top: 0; cursor: nwse-resize; }
.hd-ne { right: 0; top: 0; cursor: nesw-resize; }
.hd-sw { left: 0; bottom: 0; cursor: nesw-resize; }
.hd-se { right: 0; bottom: 0; cursor: nwse-resize; }
.canvas .guide { position: absolute; background: var(--accent); display: none; pointer-events: none; z-index: 99; }
.canvas .guide.gv { top: 0; bottom: 0; width: 1px; }
.canvas .guide.gh { left: 0; right: 0; height: 1px; }

/* ── M8-S4 内联 SVG 图标＋指令面板分组条 ── */
button svg { vertical-align: -2px; }
button.icon { padding: 5px 9px; line-height: 1; }
button.icon svg { vertical-align: middle; }
.pill svg { vertical-align: -2px; width: 11px; height: 11px; }
.cmd-group { flex-wrap: wrap; gap: 8px; }
.cmd-group .grp { color: var(--text-hint); font-size: var(--fs-sm); min-width: 34px; text-align: right; }

.zone-bar { display: flex; gap: 6px; align-items: center; margin-bottom: 8px; flex-wrap: wrap; font-size: var(--fs-sm); }
.zone-bar button { padding: 3px 8px; font-size: var(--fs-sm); }
.zone-bar select { padding: 4px 8px; font-size: var(--fs-sm); flex: 1; min-width: 0; }
.zone-bar input[type=color] { width: 32px; height: 27px; padding: 1px 2px; border-radius: var(--radius-button); background: var(--bg-card); border: 1px solid var(--border-input); cursor: pointer; }
.insp { padding: 10px 12px; margin-bottom: 12px; font-size: var(--fs-sm); }
.insp-head { display: flex; gap: 8px; align-items: center; margin-bottom: 8px; }
.insp-head .spacer { flex: 1; }
/* P2-③：X/Y/宽/高 一行排齐（原先 flex-wrap 在 400px 右栏里必折成两行，白吃一行高度）。
   四等分网格＋输入框可压缩，右栏再窄也不换行。 */
.insp-rect { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; margin-bottom: 8px; }
.insp-rect label { display: inline-flex; gap: 2px; align-items: center; color: var(--text-secondary); min-width: 0; }
.insp-rect input { width: 100%; min-width: 0; padding: 2px 4px; text-align: right; }
/* P3：检查器多了「贴合邻区」一行（4 向钮＋填满钮），400px 右栏里要允许折行 */
.insp-ops { display: flex; gap: 6px; margin-bottom: 8px; align-items: center; flex-wrap: wrap; }
.insp-ops button { padding: 2px 8px; font-size: var(--fs-sm); }
/* P3 坐标单位切换：复用全站 .seg 分段控件，缩到能塞进检查器标题行 */
.seg.tiny button { padding: 1px 7px; font-size: var(--fs-xs); }
.insp-cfg label { display: flex; gap: 6px; align-items: center; margin: 6px 0; color: var(--text-secondary); flex-wrap: wrap; }
.insp-cfg input[type=text], .insp-cfg input[type=url], .insp-cfg input[type=datetime-local] { flex: 1; min-width: 120px; padding: 3px 8px; }
.insp-cfg input[type=number] { width: 68px; padding: 2px 6px; text-align: right; }
.insp-cfg input[type=color] { width: 30px; height: 24px; padding: 1px 2px; border-radius: 5px; background: var(--bg-card); border: 1px solid var(--border-input); cursor: pointer; }
.insp-cfg select { padding: 3px 8px; }
.insp-cfg textarea { width: 100%; min-height: 64px; font-size: var(--fs-sm); resize: vertical; }

/* ── 传输任务进度条 ── */
.tbar { width: 140px; height: 8px; border-radius: 4px; overflow: hidden; background: var(--neutral-100); flex-shrink: 0; }
.tbar i { display: block; height: 100%; background: var(--accent); transition: width .4s; }

/* ── 快捷发布素材点选卡（序号=点选顺序=播出顺序）── */
.qm-card { position: relative; width: 96px; cursor: pointer; background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius-card); overflow: hidden; }
.qm-card:hover { border-color: var(--accent); }
.qm-card.on { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.qm-thumb { height: 60px; background: var(--neutral-100); display: grid; place-items: center; color: var(--text-hint); font-size: 22px; overflow: hidden; }
.qm-thumb img { width: 100%; height: 100%; object-fit: cover; }
.qm-name { padding: 4px 6px; font-size: var(--fs-xs); color: var(--text-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.qm-badge { position: absolute; top: 4px; left: 4px; z-index: 1; min-width: 18px; height: 18px; border-radius: 9px; background: var(--accent); color: #fff; font-size: var(--fs-xs); font-weight: 700; display: grid; place-items: center; padding: 0 4px; }
.qm-badge[hidden] { display: none; }

/* ── M10-S2 首页：状态四卡＋发布大按钮＋快捷链＋三步引导 ── */
/* 打磨批 2026-09-16 首页②：列数由内联 --cols 定上限（≥6 张→3；≤5 张→张数一行排开），窄窗口媒体查询降列，
 * 治「5+1 落单」。auto-fit 的旧写法作无 --cols 时的回退。 */
.stat-cards { display: grid; grid-template-columns: repeat(var(--cols, auto-fit), minmax(0, 1fr)); gap: 14px; margin-bottom: 16px; }
@media (max-width: 1460px) { .stat-cards { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 700px) { .stat-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.stat-card {
  display: block; background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius-card);
  padding: 12px 16px; box-shadow: var(--shadow-card); color: var(--text-primary);
}
.stat-card:hover { border-color: var(--accent); }
.stat-card .lbl { color: var(--text-secondary); font-size: var(--fs-sm); }
.stat-card .num { font-size: 30px; font-weight: 700; line-height: 1.25; }
.stat-card .sub { color: var(--text-hint); font-size: var(--fs-sm); }
.stat-card.warn .num { color: var(--error); }
/* 待审·审核未开启态：灰显占位（不冒充有待办）；不可点卡（div）无悬停高亮 */
.stat-card.dim .num { color: var(--text-hint); }
div.stat-card { cursor: default; }
div.stat-card:hover { border-color: var(--border); }
.home-cols { display: flex; gap: 14px; align-items: stretch; }
.send-cta {
  flex: 1; border: 1.5px dashed var(--accent); background: var(--tint-accent); border-radius: var(--radius-card);
  padding: 34px 20px; cursor: pointer; text-align: center; transition: all var(--transition);
}
.send-cta:hover { background: #FFE9D6; border-style: solid; color: inherit; }
.send-cta b { font-size: 22px; color: var(--accent); }
.send-cta small { display: block; color: var(--text-secondary); font-size: var(--fs-base); margin-top: 8px; }
.home-quick {
  width: 176px; flex-shrink: 0; background: var(--bg-card); border: 1px solid var(--border);
  border-radius: var(--radius-card); box-shadow: var(--shadow-card); padding: 10px 0;
}
.home-quick .hq-title { color: var(--text-hint); font-size: var(--fs-sm); padding: 2px 16px 6px; }
.home-quick a { display: block; padding: 7px 16px; color: var(--text-primary); font-size: var(--fs-md); }
.home-quick a:hover { background: var(--bg-hover); color: var(--accent); }
.guide-steps { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.guide-step {
  display: inline-flex; gap: 6px; align-items: center; padding: 8px 14px; font-size: var(--fs-md);
  border: 1px solid var(--border); border-radius: var(--radius-card); color: var(--text-primary); background: var(--bg-header);
}
.guide-step:hover { border-color: var(--accent); color: var(--accent); }
.guide-step.done { border-color: var(--success); background: var(--tint-success); }
.guide-step.done .gs-mark { color: var(--success); font-weight: 700; }
.gs-arrow { color: var(--text-hint); }

/* 首页无副标题（每分区自带标题，页级 desc 是冗余）→ h2 自行留出与分区的间距 */
.home > h2 { margin-bottom: 18px; }

/* ── 首页上半区两栏：左（发布内容＋系统状态）＋右（系统信息侧栏）；下方通栏「需要关注」──
 * 对齐＝侧栏每行钳一行（.sys-v 省略号）→ 面板自然高度恒低于左栏 → stretch 拉伸填满，
 * 面板底边精确落在状态卡底边；更新许可证钮 margin-top:auto 沉底填空。 */
.home-grid { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 20px; align-items: stretch; margin-bottom: 22px; }
@media (max-width: 1000px) { .home-grid { grid-template-columns: 1fr; } }
.home-main-top { min-width: 0; }
/* min-width:0 必须贯穿 300px 列→省略号文字之间每一层 flex/grid，否则 nowrap 长文把列顶爆 */
.home-rail { min-width: 0; display: flex; }
.home-rail > .home-sec { flex: 1; min-width: 0; display: flex; flex-direction: column; margin: 0; }
.home-rail .panel.sysinfo { flex: 1; min-width: 0; display: flex; flex-direction: column; margin: 0; }
.home-rail .panel.sysinfo .sys-grid { grid-template-columns: minmax(0, 1fr); }
.home-rail .panel.sysinfo .bar { margin-top: auto; }

/* ── 首页分区外壳（统一：标题＋左说明；纵向节奏交给它统一）── */
.home-sec { margin-bottom: 22px; }
.home-sec:last-child { margin-bottom: 0; }
.home-sec-hd { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.home-sec-hd h3 { font-size: var(--fs-lg); font-weight: 600; color: var(--text-primary); margin: 0; }
.home-sec-hd .hs-note { color: var(--text-hint); font-size: var(--fs-sm); }
/* 段内内容自身不再带外边距——统一交给 .home-sec 的节奏 */
.home-sec .stat-cards, .home-sec .attn, .home-sec .panel, .home-sec .pub-paths { margin: 0; }

/* ── 首页：两种发布方式（并排对等卡片）── */
.pub-paths { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; align-items: stretch; }
@media (max-width: 900px) { .pub-paths { grid-template-columns: 1fr; } }
.ppath {
  border: 1px solid var(--border); border-radius: var(--radius-card); padding: 18px 20px; background: var(--bg-card);
  display: flex; flex-direction: column; gap: 10px; transition: box-shadow .15s, border-color .15s;
}
.ppath.quick { cursor: pointer; border-color: var(--accent-light); background: linear-gradient(180deg, var(--tint-accent), var(--bg-card) 62%); }
.ppath.quick:hover { border-color: var(--accent); box-shadow: 0 4px 18px rgba(255, 122, 0, .15); }
/* 只读态（许可过期/试用到期）：整卡去橙、不可点、主按钮禁用＋锁定原因说明 */
.ppath.quick.locked { cursor: default; background: var(--bg-card); border-color: var(--border); }
.ppath.quick.locked:hover { border-color: var(--border); box-shadow: none; }
.pp-oneline.lock-note { color: var(--warning); font-weight: 600; }
.home-sec-hd .hs-note.locked { color: var(--warning); font-weight: 600; }
.ppath.plan:hover { border-color: var(--text-hint); box-shadow: var(--shadow-card); }
.pp-head { display: flex; align-items: center; gap: 8px; }
.pp-head b { font-size: 19px; }
.pp-ico { font-size: 22px; }
.pp-note { color: var(--text-hint); font-size: var(--fs-sm); }
.pp-sub { color: var(--text-secondary); font-size: var(--fs-md); }
/* 左：大按钮 + 按钮下方一行字（垂直居中占满剩余空间） */
.pp-quickmain { flex: 1; display: flex; flex-direction: column; justify-content: center; gap: 12px; }
.pp-bigbtn { width: 100%; padding: 16px; font-size: 17px; font-weight: 600; }
.pp-oneline { text-align: center; color: var(--text-secondary); font-size: var(--fs-sm); line-height: 1.6; }
.pp-oneline i { color: var(--accent); font-style: normal; font-weight: 700; margin: 0 4px; }
/* 右：三步（第一步/第二步/第三步），关键词内联可点 */
.pp-steps3 { display: flex; flex-direction: column; gap: 12px; margin-top: 4px; }
.pp-s3 { font-size: var(--fs-md); line-height: 1.6; color: var(--text-primary); }
.pp-s3 b { color: var(--accent); margin-right: 2px; }
.pp-s3 a { color: var(--accent); border-bottom: 1px solid transparent; }
.pp-s3 a:hover { border-bottom-color: var(--accent); }
/* 首页常用链（次级） */
.home-links { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-top: 20px; }
.home-links .hl-title { font-size: var(--fs-sm); color: var(--text-hint); margin-right: 4px; }
.home-links a { padding: 5px 12px; border-radius: 8px; font-size: var(--fs-sm); color: var(--text-secondary); background: var(--neutral-100); }
.home-links a:hover { color: var(--accent); background: var(--tint-accent); }

/* ── M10-S2 统一发布对话框：五模式卡＋优先级脚注＋预检警示 ── */
.mode-cards { display: flex; gap: 8px; flex-wrap: wrap; }
.mode-card {
  flex: 1; min-width: 104px; border: 1px solid var(--border); border-radius: var(--radius-card);
  padding: 8px 10px; cursor: pointer; background: var(--bg-card); transition: all var(--transition-fast); user-select: none;
}
.mode-card b { display: block; font-size: var(--fs-md); }
.mode-card small { color: var(--text-hint); font-size: var(--fs-xs); }
.mode-card input { position: absolute; opacity: 0; pointer-events: none; }
.mode-card:hover { border-color: var(--accent); }
/* 选中态由 JS 加 .on（原 `:has(input:checked)` 需 Chromium 105+/Safari 15.4+，老版信创浏览器无高亮；打磨批 2026-09-16 A②） */
.mode-card.on { border-color: var(--accent); background: var(--accent-light); box-shadow: 0 0 0 1px var(--accent); }
.mode-card.on b { color: var(--accent); }
.prio-note {
  margin-top: 14px; padding: 8px 12px; background: var(--bg-header); border-left: 3px solid var(--accent);
  border-radius: var(--radius-badge); font-size: var(--fs-sm); color: var(--text-secondary);
}
.warn-box {
  margin-top: 6px; padding: 8px 10px; background: var(--tint-warning); border: 1px solid #F0D9A8;
  border-radius: var(--radius-button); font-size: var(--fs-sm); color: #8A5300;
}

/* ── M10-S3 播出单模板页签：seed 卡片＋迷你版式预览（与编辑器画布同色系）── */
.ptpl-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 12px; }
.ptpl-card {
  background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius-card);
  overflow: hidden; cursor: pointer; transition: all var(--transition-fast); user-select: none;
}
.ptpl-card:hover { border-color: var(--accent); }
.ptpl-card.on { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.ptpl-prev { position: relative; width: 100%; overflow: hidden; }
.ptpl-prev.portrait { width: 42%; margin: 10px auto 0; border: 1px solid var(--border); }
.ptpl-prev .pz {
  position: absolute; display: flex; align-items: center; justify-content: center;
  font-size: var(--fs-2xs); color: #fff; text-shadow: 0 1px 2px #000;
  border: 1px solid rgba(255,255,255,.25); overflow: hidden; white-space: nowrap;
}
/* 批 12 补：中心点被上层分区盖住的底层分区（叠放版式的满屏媒体等），标签挪到左上角防叠字 */
.ptpl-prev .pz.pz-corner { align-items: flex-start; justify-content: flex-start; padding: 2px 5px; }
.ptpl-prev .pz.k-media { background: rgba(59,130,246,.32); }
.ptpl-prev .pz.k-clock { background: rgba(168,85,247,.38); }
.ptpl-prev .pz.k-text { background: rgba(34,197,94,.34); }
.ptpl-prev .pz.k-marquee { background: rgba(245,158,11,.42); }
.ptpl-prev .pz.k-web { background: rgba(6,182,212,.38); }
.ptpl-prev .pz.k-countdown { background: rgba(236,72,153,.38); }
.ptpl-meta { padding: 8px 10px 10px; }
.ptpl-meta b { font-size: var(--fs-md); }
.ptpl-meta .muted { font-size: var(--fs-xs); margin: 2px 0 6px; }
.ptpl-meta .ptpl-tags { margin-top: 6px; }
.ptpl-tags { display: flex; gap: 6px; flex-wrap: wrap; }

/* D1（M10-OPT S7）模板卡交互：悬停浮现 CTA；预览弹窗；「从空白开始」卡 */
/* 批 12 补（业主截图揪出"卡片下方空白高度不一致"）：混排行里竖屏预览天生更高（42% 宽 → 高约
   卡宽×0.75 vs 横屏×0.5625），grid 同行按最高对齐 → 横屏卡下方拖出空白。统一成 **16:9 预览舞台**：
   横屏铺满；竖屏等高居中（宽＝卡宽×81/256，与监播室 8-17 的等高推导同一公式）——所有卡天然等高。
   「套用版式…」弹窗（tpl-grid）早已是固定高舞台，此处对齐。 */
.ptpl-prevwrap { position: relative; aspect-ratio: 16 / 9; overflow: hidden; display: flex; align-items: center; justify-content: center; }
.ptpl-prevwrap .ptpl-prev { flex: none; }
.ptpl-prevwrap .ptpl-prev.portrait { width: calc(100% * 81 / 256); margin: 0; }
.ptpl-use {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  opacity: 0; pointer-events: none; transition: opacity var(--transition-fast);
  box-shadow: 0 2px 10px rgba(0, 0, 0, .35); white-space: nowrap;
}
.ptpl-card:hover .ptpl-use { opacity: 1; pointer-events: auto; }
dialog.ptpl-dlg { min-width: 520px; max-width: min(640px, 92vw); }
.ptpl-dlg-prev .ptpl-prev.portrait { width: 38%; margin: 0 auto; border: 1px solid var(--border); }
.ptpl-blank { display: grid; place-items: center; min-height: 180px; border-style: dashed; }
/* 批 12 补：「我的模板」空态——跨满整行居中（原先当普通网格项塞进一个 240px 窄列，文字挤成竖条） */
.ptpl-empty {
  grid-column: 1 / -1; text-align: center; padding: 46px 20px 40px;
  display: flex; flex-direction: column; gap: 7px; color: var(--text-hint);
}
.ptpl-empty b { color: var(--text-secondary); font-size: var(--fs-md); font-weight: 600; }
.ptpl-blank-in { text-align: center; color: var(--text-secondary); }
.ptpl-blank-in .bp { font-size: 34px; line-height: 1; color: var(--accent); margin-bottom: 6px; }
.ptpl-blank-in .muted { font-size: var(--fs-xs); margin-top: 4px; }

/* ── M10-S3 双向深链：计划行 focus 高亮＋槽位「编辑单」跳转 ── */
tr.row-focus td { background: var(--accent-light); box-shadow: inset 3px 0 0 var(--accent); }
.slot-row .pled { font-size: var(--fs-sm); white-space: nowrap; }

/* ── M10-S4 设备页批量操作栏（原指令面板并入）＋控制计划两栏 ── */
.batch-bar {
  background: var(--accent-light); border: 1px solid var(--accent);
  border-radius: var(--radius-card); padding: 8px 12px; margin-bottom: 12px;
}
.batch-bar b { color: var(--accent); font-size: var(--fs-md); }
.ctrl-cols { display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); gap: 18px; align-items: start; }
@media (max-width: 1280px) { .ctrl-cols { grid-template-columns: 1fr; } }
.ctrl-col > h3 { margin-bottom: 4px; }
.ctrl-col > .desc { margin-bottom: 10px; }
/* 控制计划子页签（定时开关机 / 音量计划）——比一级页签轻，页面标题下二级导航 */
.subtabs { display: flex; gap: 6px; margin: 4px 0 14px; }
.subtab { background: transparent; border: 1px solid var(--border); border-radius: 999px; padding: 5px 16px; font-size: var(--fs-sm); color: var(--text-hint); cursor: pointer; }
.subtab:hover { border-color: var(--acc); color: var(--acc); }
.subtab.active { background: var(--acc); border-color: var(--acc); color: #fff; }
/* 传输计划：已选素材 chips 列表 */
.xfer-sel { display: flex; flex-direction: column; gap: 4px; max-height: 200px; overflow: auto; }
.xfer-chip { display: flex; gap: 8px; align-items: center; padding: 4px 8px; background: var(--bg-subtle, #f4f4f5); border-radius: 6px; }
.xfer-chip .nm { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.xfer-chip .rm { border: none; background: transparent; color: var(--text-hint); cursor: pointer; padding: 0 4px; }
.xfer-chip .rm:hover { color: var(--danger-strong, #d9342a); }

/* ── M10-OPT S4 设备页重构：J1 工具栏＋J2 详情抽屉＋J5 存储条＋J8 添加设备 ── */
.dev-toolbar { position: sticky; top: 52px; z-index: 20; }
.dev-table tbody tr { cursor: pointer; }
.dev-table tbody tr.nosel { cursor: default; }
.dev-table tbody tr:hover td { background: var(--bg-hover); }
.dev-table tbody tr.rsel td { background: var(--tint-accent); }
.nm-edit { border: 0; background: none; padding: 0 3px; opacity: .4; cursor: pointer; box-shadow: none; }
.dev-table tr:hover .nm-edit { opacity: 1; }
.stor { display: inline-flex; align-items: center; gap: 6px; }
.stor .tbar { display: inline-block; width: 70px; }
.tbar.low i { background: var(--danger-strong); }
.more-wrap { position: relative; display: inline-block; }
.more-menu {
  position: absolute; top: calc(100% + 4px); left: 0; z-index: 60; min-width: 168px;
  background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius-card);
  box-shadow: var(--shadow-modal); padding: 6px; display: flex; flex-direction: column;
}
.more-menu[hidden] { display: none; }
.more-menu button { border: 0; background: none; box-shadow: none; text-align: left; padding: 7px 10px; border-radius: 6px; font-size: var(--fs-sm); }
.more-menu button:hover { background: var(--neutral-100); }
.more-menu .sep { border-top: 1px solid var(--border); margin: 5px 2px; }
.more-menu button.danger { color: var(--danger-strong); }
.drawer-wrap { position: fixed; inset: 0; z-index: 90; background: rgba(0, 0, 0, .28); }
.drawer {
  position: absolute; top: 0; right: 0; bottom: 0; width: min(540px, 94vw);
  background: var(--bg-page); box-shadow: -8px 0 30px rgba(0, 0, 0, .18);
  display: flex; flex-direction: column; animation: drawerIn .16s ease;
}
@keyframes drawerIn { from { transform: translateX(36px); opacity: .4; } }
.drawer-head {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 13px 18px; border-bottom: 1px solid var(--border); background: var(--bg-card);
}
.drawer-head .x { padding: 2px 9px; }
.drawer-body { overflow-y: auto; padding: 14px 18px 26px; flex: 1; }
.drawer-body h4 { margin: 16px 0 6px; font-size: var(--fs-sm); color: var(--text-secondary); }
.kv { width: 100%; font-size: var(--fs-sm); border-collapse: collapse; }
.kv td { padding: 5px 6px; border-bottom: 1px dashed var(--border); vertical-align: top; }
.kv td:first-child { color: var(--text-secondary); width: 100px; white-space: nowrap; }
.shot-box { width: 100%; aspect-ratio: 16 / 9; background: #1a1a1a; border-radius: var(--radius-card); overflow: hidden; display: grid; place-items: center; }
/* 竖屏设备（rotation 90/270）监播框切 9:16，与监播墙同款，否则竖图塞进横框看不出是竖屏 */
.shot-box.portrait { aspect-ratio: 9 / 16; max-width: 240px; margin: 0 auto; }
.shot-box img { width: 100%; height: 100%; object-fit: contain; }
.d-ops { display: flex; flex-wrap: wrap; gap: 6px; }
/* 抽屉可折叠历史段（告警/自动清理/回执）：默认收起，摘要一行，点开看明细 */
.drawer-sec { border-top: 1px solid var(--line, var(--border)); margin-top: 4px; }
.drawer-sec > summary { list-style: none; cursor: pointer; padding: 10px 2px; font-weight: 600; font-size: 14px; display: flex; align-items: center; }
.drawer-sec > summary::-webkit-details-marker { display: none; }
.drawer-sec > summary::before { content: "▸"; color: var(--text-secondary); margin-right: 6px; font-size: 11px; transition: transform .12s; }
.drawer-sec[open] > summary::before { transform: rotate(90deg); }
.drawer-sec > summary .sec-sum { color: var(--text-secondary); font-weight: 400; font-size: 12px; }
.drawer-sec > div { padding: 0 2px 10px; }
.d-ops button { padding: 4px 10px; font-size: var(--fs-sm); }
.d-alert { padding: 4px 0; font-size: var(--fs-sm); }
.d-adv .row label { display: block; margin-bottom: 4px; color: var(--text-secondary); font-size: var(--fs-sm); }
dialog.add-dev { width: 760px; max-width: 95vw; }
dialog.add-dev #paneScan h2 { display: none; }
dialog.add-dev #paneScan .desc { margin-top: 0; }
/* 指派对话框 G3 注记（当前属 xx，勾选将改归本计划） */
.asn-note { font-size: var(--fs-xs); color: var(--warning); }

/* ── S6 迷你周历（G5/M3 三对话框共用；只读，7 天×24h 色块）── */
.wcal { margin-top: 2px; }
.wcal-hours { display: flex; justify-content: space-between; font-size: var(--fs-xs); color: var(--text-hint); padding-left: 26px; }
.wcal-day { display: flex; align-items: center; gap: 6px; margin-top: 2px; }
.wcal-lb { width: 20px; text-align: right; font-size: var(--fs-xs); color: var(--text-secondary); flex: none; }
.wcal-track { position: relative; flex: 1; height: 12px; background: var(--neutral-100); border-radius: 3px; overflow: hidden; }
.wcal-track u { position: absolute; top: 0; bottom: 0; width: 1px; background: var(--line); }
.wcal-track i { position: absolute; top: 0; bottom: 0; border-radius: 2px; min-width: 2px; }
.wcal-legend { margin-top: 6px; font-size: var(--fs-xs); color: var(--text-secondary); display: flex; flex-wrap: wrap; gap: 10px; }
.wcal-legend i { display: inline-block; width: 10px; height: 10px; border-radius: 2px; vertical-align: -1px; margin-right: 4px; }

/* ── M10-OPT S8 发布浮层（O1 摘要行＋N4 内容三入口）───────────────────────── */
.pubsec { margin: 10px 0; }
.pubsec-head { display: flex; align-items: center; gap: 8px; font-size: var(--fs-sm); }
.pubsec-head b { font-weight: 600; }
.pubsec-head b.warn-txt { color: var(--danger-strong); }
.sec-tog { font-size: var(--fs-xs); color: var(--accent); cursor: pointer; white-space: nowrap; }
.pubsec-body { margin-top: 8px; padding: 10px 12px; background: var(--neutral-50, #fafafa); border: 1px solid var(--border); border-radius: var(--radius-card); }
.pubsec-body[hidden] { display: none; }
.pub-drop { border: 2px dashed var(--border-input); border-radius: var(--radius-card); padding: 22px 14px; text-align: center; color: var(--text-secondary); cursor: pointer; font-size: var(--fs-sm); }
.pub-drop.over { border-color: var(--accent); background: var(--tint-accent); }
.pub-drop u { color: var(--accent); }
.up-row { display: flex; align-items: center; gap: 8px; margin-top: 6px; font-size: var(--fs-sm); }
.up-row .up-name { max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.up-row .up-bar { flex: 1; height: 6px; background: var(--neutral-100); border-radius: 3px; overflow: hidden; }
.up-row .up-bar i { display: block; height: 100%; background: var(--accent); transition: width .15s; }
.up-row.done .up-bar i { background: var(--neutral-300); } /* 批 15-3：完成后退场转灰（进行中保持品牌橙） */
.up-row.fail .up-st { color: var(--danger-strong); }
.pub-inrow { display: flex; align-items: center; gap: 8px; margin: 8px 0; flex-wrap: wrap; }
.pub-inrow b { font-size: var(--fs-sm); min-width: 64px; }
.pub-inrow input, .pub-inrow textarea { flex: 1; min-width: 160px; }
.pub-inrow textarea { resize: vertical; }
.web-chip { padding: 8px 12px; margin: 0 0 8px; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.web-chip b { word-break: break-all; }
.pub-devrow.append-na { opacity: .55; }
.pub-devrow .ap-hint { font-size: var(--fs-xs); border: 1px solid var(--border); border-radius: 8px; padding: 0 6px; }

/* N1 首页「需要关注」区 */
.attn { padding: 12px 16px; }
.attn-row { display: flex; align-items: center; gap: 10px; padding: 8px 6px; border-radius: 8px; color: var(--text-primary); text-decoration: none; }
.attn-row:hover { background: var(--neutral-100); }
.attn-row .attn-main { font-weight: 600; white-space: nowrap; }
.attn-row .attn-sub { font-size: var(--fs-xs); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; }
.attn-row .attn-go { color: var(--text-secondary); }
.attn-ok { color: var(--success); font-weight: 600; padding: 6px 2px; }

/* ── M12-S2 许可证：横幅 + 首页系统信息面板 + 上传对话框 ──────────────────── */
.lic-banner { display: flex; align-items: center; gap: 12px; padding: 8px 18px; font-size: var(--fs-md); }
.lic-banner .lic-msg { flex: 1; }
.lic-banner .lic-cta {
  flex: none; padding: 3px 12px; border-radius: 6px; cursor: pointer;
  background: rgba(255,255,255,.85); border: 1px solid rgba(0,0,0,.15); font-weight: 600;
}
.lic-banner.lic-expired { background: var(--tint-error); color: var(--error); border-bottom: 1px solid var(--error); }
.lic-banner.lic-soon    { background: var(--tint-warning); color: #A85A00; border-bottom: 1px solid var(--warning); }
.lic-banner.lic-trial   { background: var(--tint-info); color: #1668B8; border-bottom: 1px solid #6BA9E0; }

/* ── 打磨批 1 · 1-2 依赖缺失红条（系统设置页顶部；只在真缺失时渲染）───────────
   给命令行块而不是一句"依赖缺失"：现场运维多半不是程序员，能粘贴执行才叫可操作。 */
.panel.dep-warn { background: var(--tint-error); border-color: var(--error); color: var(--error); }
.panel.dep-warn .dep-cmd {
  background: rgba(0,0,0,.04); border: 1px solid rgba(0,0,0,.08); border-radius: 6px;
  padding: 8px 10px; font: var(--fs-base)/1.7 ui-monospace, Menlo, Consolas, monospace;
  color: var(--text-primary); white-space: pre-wrap; word-break: break-all; user-select: all;
}

.panel.sysinfo .sys-grid { display: grid; gap: 2px; }
.sys-row { display: flex; gap: 12px; padding: 5px 0; font-size: var(--fs-md); align-items: baseline; }
.sys-row .sys-k { min-width: 88px; flex: none; color: var(--text-secondary); }
.sys-row .sys-v { flex: 1; }
/* 侧栏态：每行钳一行（超出省略号，title 悬浮看全文）＝面板高度确定，两栏底边可精确对齐 */
.home-rail .sys-row .sys-k { min-width: 72px; }
.sys-sep { border-top: 1px solid var(--border); margin: 6px 0; }   /* 首页①：系统信息面板分组线（系统 / 我的账号 / 许可） */
.home-rail .sys-row .sys-v { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 打磨 2026-09-21（业主拍板）：窗口 ≤1000px 时首页已单列，侧栏与状态卡不再并排→没有「底边对齐」可破，
   这时改为换行；宽屏仍一行省略号。任何被截断的值**点击弹全文气泡**（触屏没有悬浮，点击是 title 的替身）。 */
@media (max-width: 1000px) { .home-rail .sys-row .sys-v { white-space: normal; overflow: visible; text-overflow: clip; overflow-wrap: anywhere; } }
.sys-row { position: relative; }
.sys-v.truncated { cursor: pointer; }
/* 首页「存储空间」行档位色（与关注区同口径：warn＝距上传停止线 10 点内，err＝已达线上传暂停） */
.sys-row .sys-v.warn { color: var(--warning); font-weight: 600; }
.sys-row .sys-v.err { color: var(--error); font-weight: 600; }
.sys-pop { position: absolute; left: 0; right: 0; top: 100%; z-index: 20; background: var(--bg-card); color: var(--text-primary);
  border: 1px solid var(--border); border-radius: 8px; box-shadow: var(--shadow-modal); padding: 10px 12px;
  font-size: var(--fs-base); white-space: normal; overflow-wrap: anywhere; }
.sys-pop .muted { display: block; margin-top: 4px; }

.lic-dlg { min-width: 380px; max-width: 92vw; }
/* 获取/更新许可证三步说明（试用态转化引导：机器码→厂家签发→上传激活） */
.lic-steps { margin: 0 0 12px; padding-left: 20px; color: var(--text-secondary); font-size: var(--fs-base); }
.lic-steps li { padding: 3px 0; line-height: 1.6; }
.lic-steps b { color: var(--text-primary); }
.lic-dlg .mono { font-size: var(--fs-md); }

/* 分区素材推荐尺寸提示（2026-08-16）：业主定调「模板与素材尺寸统一考虑」——用户按此尺寸做图，
   上屏正好铺满分区、零黑边。做成可读的一行而非角落灰字（此前 11px「≈W×Hpx」实测没人注意到）。 */
.zone-size { font-size: 12px; color: var(--text-primary); background: var(--accent-light);
  border: 1px solid var(--accent); border-radius: 6px; padding: 5px 9px; margin-bottom: 6px; }
.zone-size b { color: var(--accent-hover); font-variant-numeric: tabular-nums; }
/* 视频/直播「1 路」名额常显行（2026-08-16）：规则没变，变的是让用户**加之前**就知道。 */
.vslot { font-size: 12px; border-radius: 6px; padding: 4px 9px; margin-bottom: 6px; border: 1px solid transparent; }
.vslot.ok { color: var(--text-secondary); background: var(--neutral-100); border-color: var(--line); }
.vslot.taken { color: var(--warning-strong, #B26A00); background: #FFF6E5; border-color: #F0C476; }
.vslot b { font-weight: 600; }

/* ── 打磨批 2 · 2-6：编辑器选材弹窗顶部的内容添加区 ─────────────────────────
   与快捷发布同一套 .compose 样式；这里只补弹窗内的间距与「素材库」分隔标题。 */
.media-pick .compose { margin-bottom: 10px; }
.media-pick .mp-libttl {
  font-weight: 600; font-size: var(--fs-md); margin: 2px 2px 6px;
  padding-top: 8px; border-top: 1px solid var(--line);
}
/* 2-7：画布拖拽的上传进度条（空时不占位；多文件时自身滚动，不把画布顶出视口） */
.drop-uplist:empty { display: none; }
.drop-uplist { margin-top: 6px; max-height: 132px; overflow: auto; }

/* ── 2-2 空白画布态：虚线空框＋出路提示 ──────────────────────────────────────
   批 12 · 6：浅色斜纹 → **黑底**（业主拍板）。「画布即舞台」——画布默认背景色本就是黑、
   加了分区就是深色，唯独空态浅色等于空态与内容态两副面孔；黑底＋虚线框＋浅灰引导字，
   既是"一块屏幕"的观感，虚线仍保留"这里还是空的"信号（剪映/Premiere 预览区同为黑底）。 */
.canvas.blank {
  background: #141416;
  border: 2px dashed #3d3d44; display: grid; place-items: center; text-align: center;
}
.canvas.blank .blank-guide { max-width: 78%; color: #9a9aa0; }
.canvas.blank .bg-ttl { font-size: 18px; font-weight: 600; color: #e8e8ea; margin-bottom: 6px; }
.canvas.blank .bg-ways { font-size: var(--fs-base); line-height: 1.8; }
/* 批 12 · 6：空白态检查器整块隐藏（右栏那句提示与画布中央文字重复，业主点名二留一） */
.insp[hidden] { display: none; }

/* ── 2-1「套用版式…」弹窗：复用 .media-pick 网格，卡片里放模板迷你预览 ───────── */
dialog.tpl-pick { min-width: 760px; }
.tpl-grid .tpl-card .thumb { background: var(--neutral-100); padding: 6px; display: block; height: auto; }
/* 竖屏款别把整行撑高：预览按高度上限等比缩、居中（横屏款仍占满卡片宽） */
.tpl-grid .tpl-card .thumb .ptpl-prev { width: 100%; max-height: 132px; margin: 0 auto; }
.tpl-grid .tpl-card .thumb .ptpl-prev.portrait { width: auto; height: 132px; }
.zb-sep { width: 1px; align-self: stretch; background: var(--border); margin: 0 4px; }

/* ── 2-4 编辑器工具栏分两行（都在画布下方）：上＝分区操作，下＝画布级属性 ────── */
.canvas-bar { border-top: 1px dashed var(--border); padding-top: 6px; margin-top: 2px; }
.canvas-bar .cb-color { display: inline-flex; align-items: center; gap: 5px; font-size: var(--fs-sm); color: var(--text-secondary); }
.canvas-bar .cb-color input[type=color] { width: 28px; height: 22px; padding: 0; }
.canvas-bar button { display: inline-flex; align-items: center; gap: 5px; }

/* 2-4b：占位卡里的类型图标（原先是 emoji，靠字号定大小）——SVG 改按容器放大到接近原视觉重量 */
.canvas .zone .zc-ph > div:first-child svg { width: 22px; height: 22px; opacity: .9; }
.pv-ph svg { width: 26px; height: 26px; }
.mp-note svg, .warn-box svg, .vslot svg, .web-chip svg { vertical-align: -2px; }

/* ── 3-1 告警筛选：两个正交维度各自一组签（状态 × 知悉），组前带小标签 ────────── */
.fgrp { display: inline-flex; align-items: center; gap: 6px; }
.fgrp .fgl { font-size: var(--fs-sm); color: var(--text-secondary); }

/* ── 3-3 侧栏吸顶 ＋ 宽表横滚收进容器 ────────────────────────────────────────
   **真因是量出来的，不是猜的**（2026-08-18 实测）：`.topbar` 的 sticky **本来就生效**
   （滚 800px 后仍 top:0）。业主截图里「顶部 logo 被切半截」的真凶是**横向溢出**——
   窗口 ≤1024px 时素材库/设备/审计三张宽表把**整页**撑宽（scrollWidth 1033 > 视口），
   而 sticky 只吸垂直方向：用户一往右滚，顶栏连同 logo 就整体左移出视野。
   故这里两件事一起做：①侧栏真吸顶；②让宽表在**自己的容器里**横滚，整页永不横向滚动。
   ⚠️ 不用 `.main .panel { overflow-x:auto }` 一刀切：播出单列表的「更多 ▾」浮层就在表格行内，
      panel 一旦成为滚动容器，那个菜单会被裁掉（`overflow-x:auto` 会把 overflow-y 也算成 auto）。 */
.side {
  position: sticky; top: 52px; align-self: flex-start;
  height: calc(100vh - 52px); overflow-y: auto;
}
.tbl-scroll, #listWrap { overflow-x: auto; }

/* ── 批 10「背景音乐」面板（播出单编辑器右栏底部）───────────────────────────
   它是**整单级**的东西（不属于任何分区，画面怎么切都不断音），所以与「播出条目」
   并列摆在右栏，不进分区检查器。 */
.bgm-panel { margin-top: 10px; padding: 10px 12px 12px; }
.bgm-panel .items-head { margin: 0 0 6px; }
.bgm-panel .pl-items { max-height: 168px; overflow-y: auto; }
.bgm-opts {
  display: flex; flex-wrap: wrap; gap: 10px 16px; align-items: center;
  margin: 8px 0 4px; font-size: var(--fs-sm);
}
.bgm-opts label { display: inline-flex; gap: 5px; align-items: center; }
.bgm-duck { margin-top: 6px; border-top: 1px solid var(--line); padding-top: 8px; }
/* 三档避让做成竖排单选：每档都带一句「什么时候用它」——光看档名（暂停/压低/静音视频）
   用户猜不出该选哪个，这是 2-5 那条「分野必须写清」的同款问题。 */
.bgm-radio {
  display: flex; gap: 7px; align-items: flex-start;
  padding: 5px 6px; border-radius: 6px; cursor: pointer;
}
.bgm-radio:hover { background: var(--neutral-100); }
.bgm-radio input { margin-top: 3px; flex: none; }

/* ── 播放记录（M13 批 1 S2）：当日 24h 时间线色带＋刻度＋图例 ── */
.pr-tl { position: relative; height: 18px; background: var(--bg-hover); border-radius: 4px; overflow: hidden; }
.pr-tl i { position: absolute; top: 0; bottom: 0; display: block; }
.pr-ticks { position: relative; height: 16px; margin-bottom: 8px; font-size: 11px; color: var(--text-hint); }
.pr-ticks span { position: absolute; transform: translateX(-50%); }
.pr-ticks span:first-child { transform: none; }
.pr-ticks span:last-child { transform: translateX(-100%); }
.pr-legend { display: flex; gap: 14px; flex-wrap: wrap; font-size: 12px; color: var(--text-secondary); margin-bottom: 10px; }
.pr-legend i { display: inline-block; width: 10px; height: 10px; border-radius: 2px; margin-right: 4px; vertical-align: -1px; }
.stat-card .num small { font-size: 14px; font-weight: 500; color: var(--text-secondary); }

/* ── 批 18-1 电脑端遥控面板（与手机端同款） ── */
dialog.rc-dlg { min-width: 520px; }
.rc-transport { display: grid; grid-template-columns: 1fr 1.4fr 1fr; gap: 10px; margin: 10px 0 4px; }
.rc-transport button { display: flex; flex-direction: column; align-items: center; gap: 2px; padding: 10px 6px; }
.rc-transport button .ico { font-size: 26px; line-height: 1.1; }
.rc-transport button.big .ico { font-size: 32px; }
.rc-transport button.dim { opacity: .4; }
.rc-progress { margin: 8px 2px 0; }
.rc-progress input[type=range] { width: 100%; accent-color: var(--accent); margin: 2px 0 4px; }
.rc-prog-time { display: flex; justify-content: space-between; font-size: 12px; color: var(--text-secondary); }
.rc-dlg .vol-row { display: flex; align-items: center; gap: 10px; padding: 10px 2px 0; }
.rc-dlg .vol-row input[type=range] { flex: 1; accent-color: var(--accent); }
.rc-dlg #c-mute.on { border-color: var(--accent); color: var(--accent); }
.rc-list { max-height: 260px; overflow: auto; border: 1px solid var(--border-input); border-radius: var(--radius-button); }
.rc-item { display: flex; justify-content: space-between; align-items: center; gap: 10px; padding: 8px 10px; border-bottom: 1px solid var(--border-input); cursor: pointer; }
.rc-item:last-child { border-bottom: 0; }
.rc-item:hover { background: var(--neutral-100); }
.rc-item.on { background: var(--tint-warning); }
.rc-name { flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rc-sub { font-size: 12px; color: var(--text-secondary); white-space: nowrap; }
.rc-cur { color: var(--accent); font-weight: 600; margin-right: 6px; }
/* 批 18-4 时段行「全天」勾 */
.daychk.allday { font-weight: 600; margin-left: 4px; }

/* ── 批 19 S2 播出计划对话框：槽位卡「播什么 → 什么时候播」＋多单 chips＋周历角标 ── */
.slot-card { border: 1px solid var(--border); border-radius: var(--radius-card); background: var(--bg-card); padding: 8px 12px 6px; margin: 6px 0; }
.slot-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 4px; }
.slot-head[hidden] { display: none; }
.slot-no { font-weight: 600; color: var(--text-primary); font-size: var(--fs-base); }
.slot-head .rm { font-size: var(--fs-xs); padding: 2px 8px; }
.slot-sec { display: flex; gap: 10px; align-items: flex-start; padding: 4px 0; }
.sec-lb { flex: none; width: 76px; color: var(--text-secondary); font-size: var(--fs-base); line-height: 26px; }
.sec-body { flex: 1; min-width: 0; }
.plchips { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.plhint { font-size: var(--fs-xs); margin-top: 4px; }
.plhint.err-txt { color: var(--error); }
.pl-chip {
  display: inline-flex; align-items: center; gap: 4px; height: 26px; padding: 0 6px 0 4px;
  border: 1px solid var(--border-input); border-radius: 13px; background: var(--bg-header); font-size: var(--fs-sm);
  cursor: grab; user-select: none; max-width: 320px;
}
.pl-chip.dragging { opacity: .45; }
.pl-chip.over { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.pl-chip.missing { border-style: dashed; color: var(--error); }
.pl-chip .ord { display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; border-radius: 50%; background: var(--accent); color: #fff; font-size: var(--fs-2xs); font-weight: 700; flex: none; }
.pl-chip .nm { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pl-chip a { color: var(--text-hint); text-decoration: none; font-size: var(--fs-xs); padding: 0 1px; line-height: 1; }
.pl-chip a:hover { color: var(--accent); }
.pl-chip a.x { font-size: var(--fs-md); font-weight: 700; }
.pl-chip a.x:hover { color: var(--danger-strong); }
.pl-chip a[hidden] { display: none; }
.pl-chip .pled svg { vertical-align: -2px; width: 1em; height: 1em; }
.pladd { height: 26px; padding: 0 6px; font-size: var(--fs-sm); }
details.when { margin-top: 2px; }
details.when summary { display: flex; align-items: center; gap: 10px; cursor: pointer; list-style: none; padding: 4px 0; }
details.when summary::-webkit-details-marker { display: none; }
details.when .when-sum { color: var(--text-primary); font-size: var(--fs-base); }
details.when .when-chev { color: var(--text-hint); font-size: var(--fs-lg); transition: transform var(--transition-fast); }
details.when[open] .when-chev { transform: rotate(90deg); }
details.when summary:hover .when-sum { color: var(--accent); }
details.when .slot-row { margin: 4px 0 4px 86px; }
.plan-vol { margin-top: 8px; font-size: var(--fs-sm); }
.plan-vol.warn-box { margin-top: 8px; }
.wcal-track i b { position: absolute; right: 3px; top: 0; line-height: 12px; font-size: 9px; font-weight: 700; color: #fff; text-shadow: 0 0 2px rgba(0,0,0,.6); pointer-events: none; }

/* ── 海报制作对话框（打磨 2026-09-21，业主拍板）：左预览、右表单，与播出单编辑器「左舞台右选项」同构；
   预览随对话框打开自动渲染一次、改字后点「预览」刷新、点画面开全尺寸大图；窗口 ≤1200px 退化为上下（预览在上）。 */
dialog.tpl-dlg { width: min(1180px, 96vw); }
.tpl-dlg .tpl-cols { display: grid; grid-template-columns: minmax(0, 1fr) 380px; gap: 22px; align-items: start; }
.tpl-dlg .tpl-prev { position: sticky; top: 0; background: var(--neutral-100); border: 1px solid var(--border); border-radius: 8px;
  display: grid; place-items: center; min-height: 200px; overflow: hidden; }
.tpl-dlg .tpl-prev img { max-width: 100%; max-height: calc(100vh - 200px); display: block; cursor: zoom-in; }
.tpl-dlg .tpl-prev .ph { color: var(--text-hint); padding: 40px; text-align: center; }
.tpl-dlg .tpl-form .bar { margin-top: 0; }
@media (max-width: 1200px) { .tpl-dlg .tpl-cols { grid-template-columns: 1fr; } .tpl-dlg .tpl-prev { position: static; } }
dialog.tpl-lightbox { padding: 0; background: transparent; border: 0; box-shadow: none; max-width: 96vw; max-height: 96vh; overflow: hidden; }
dialog.tpl-lightbox img { max-width: 96vw; max-height: 96vh; display: block; cursor: zoom-out; border-radius: 6px; }
dialog.tpl-lightbox::backdrop { background: rgba(0, 0, 0, .82); }

/* ── 开放接口（API）页（M16 S1）──────────────────────────────────────────── */
dialog.okey-dlg { min-width: 560px; max-width: 92vw; }
.okey-tbl th { white-space: nowrap; }
.okey-scopes { display: flex; flex-wrap: wrap; gap: 6px 16px; }
.okey-scopes label { display: inline-flex; align-items: center; gap: 4px; }
.okey-reveal { display: flex; gap: 10px; align-items: center; background: var(--neutral-100); border-radius: 8px; padding: 10px 12px; margin-top: 8px; }
.okey-reveal code { flex: 1; font-family: ui-monospace, monospace; font-size: 13px; word-break: break-all; user-select: all; }
dialog.okdoc { min-width: 900px; }
.okdoc-op { border: 1px solid var(--border); border-radius: 8px; padding: 10px 12px; margin-bottom: 10px; }
.okdoc-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.okdoc-m { display: inline-block; min-width: 54px; text-align: center; padding: 1px 8px; border-radius: 6px; font-size: 12px; font-weight: 700; color: #fff; background: #6b7280; }
.okdoc-get { background: #2f855a; } .okdoc-post { background: #2b6cb0; } .okdoc-put, .okdoc-patch { background: #b7791f; } .okdoc-delete { background: #c53030; }
.okdoc-sub { font-weight: 600; font-size: 12px; margin: 8px 0 4px; color: var(--text-secondary); }
.okdoc-tbl td { padding: 3px 8px 3px 0; font-size: 12px; vertical-align: top; border-bottom: 1px dashed var(--border); }
.okdoc-pre { background: var(--neutral-100); border-radius: 6px; padding: 8px 10px; font-size: 12px; overflow: auto; margin: 6px 0; }

/* M17 §5 敏感词 */
.sens-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
@media (max-width: 900px) { .sens-grid { grid-template-columns: 1fr; } }
.sens-grid textarea { width: 100%; box-sizing: border-box; font-size: 13px; }
.sens-lbl { font-size: 13px; margin: 6px 0 4px; }
mark.sens-hit { background: #FFE2C2; color: #B34700; border-radius: 3px; padding: 0 2px; font-weight: 600; }
.sens-preview { margin-top: 6px; padding: 8px 10px; background: var(--neutral-100); border-radius: 6px; white-space: pre-wrap; color: var(--text-primary, #222); }
.sens-words { color: #B34700; }
.sens-hitbox { margin: 8px 0; padding: 8px 10px; border: 1px solid #FFC98F; background: #FFF6EC; border-radius: 6px; font-size: 13px; }
/* M17 §3 插播 */
.ins-form textarea { width: 100%; max-width: 640px; box-sizing: border-box; }
.ins-prev { width: 100%; max-width: 640px; height: 40px; border-radius: 6px; display: flex; align-items: center; padding: 0 14px; overflow: hidden; white-space: nowrap; font-weight: 700; background-image: linear-gradient(45deg, #ddd 25%, transparent 25%, transparent 75%, #ddd 75%), linear-gradient(45deg, #ddd 25%, #fff 25%, #fff 75%, #ddd 75%); background-size: 16px 16px; background-position: 0 0, 8px 8px; }
.ins-devs { max-height: 260px; overflow: auto; border: 1px solid var(--line); border-radius: 6px; padding: 4px 8px; }
.usb-steps { margin: 10px 0 8px 20px; line-height: 1.9; } .usb-steps li { font-size: 13px; }

/* M17 §7 手机 App 页 */
.ma-grid { display: flex; flex-wrap: wrap; gap: 16px; }
.ma-card { flex: 1 1 280px; max-width: 380px; display: flex; flex-direction: column; align-items: center; gap: 8px; text-align: center; }
.ma-card h3 { align-self: flex-start; margin: 0 0 4px; }
.ma-qr { width: 220px; height: 220px; image-rendering: pixelated; border: 1px solid var(--line); border-radius: 8px; }
.ma-sub { font-size: 14px; }
.ma-url { font-size: 12px; word-break: break-all; }

/* M17 S4 编辑器「多屏同步播放」勾选框 */
.editor-bar .sync-cb { display: inline-flex; align-items: center; gap: 4px; font-size: var(--fs-sm); color: var(--text-secondary); white-space: nowrap; cursor: pointer; }
/* D10 远程支持开启中横幅（橙＝提醒有外部技术人员在线，非故障） */
.lic-banner.sup-banner { background: var(--tint-warning); color: #A85A00; border-bottom: 1px solid var(--warning); }
.lic-banner.sup-banner a.lic-cta { text-decoration: none; }

/* ship1：设备详情「网络」两张卡（网线/WiFi：IP/掩码/网关/DNS/MAC）＋改网口对话框的推荐做法条 */
.net-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 8px; margin-top: 6px; }
.net-card { border: 1px solid var(--line); border-radius: 8px; padding: 6px 10px; font-size: 12px; line-height: 1.7; }
.net-card .mono { font-size: 12px; }
.hint-box { background: var(--bg2); border: 1px solid var(--line); border-radius: 8px; padding: 8px 10px; line-height: 1.6; }
