/* ============================================================
   AI 讲台 · 应用样式（外壳 + 设计系统组件）
   类名与 design/ui-kit.html 同名同义，供 C/D/E 视图直接复用。
   颜色一律使用 tokens.css 里的 CSS 变量，禁止写死十六进制色值
   （cover_hue 生成的渐变除外）。
   ============================================================ */

/* 品牌渐变（--grad-brand/--grad-ai/--grad-av/--grad-av-p）已收归 tokens.css（U-203），
   此处只引用变量；此前本文件自带一份 :root 定义，与 ui-kit 内联字面量构成两处真源。 */

/* ============ base ============ */
*{box-sizing:border-box;margin:0;padding:0}
html,body{height:100%}
body{
  font-family:"PingFang SC","Microsoft YaHei",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;
  background:var(--bg);color:var(--ink);font-size:var(--fs-4);-webkit-font-smoothing:antialiased;
  height:100vh;overflow:hidden;display:flex;flex-direction:column;
}
/* 展开态侧栏的栏宽真源：账号弹层要对齐侧栏条目，必须读同一个数，
   不能各写一份（两份必然漂移）。三处共用：
   ① .appnav 展开态 width（见 @media min-width:761px）
   ② ≤1100 视口的 180 覆盖
   ③ .acctmenu.fit 的宽度 = 栏宽 − 21（左右 padding 10×2 + 右边框 1） */
body{--nav-w-exp:210px}
h1,h2,h3,h4{font-weight:500;letter-spacing:-.01em}
h1{font-size:22px}h2{font-size:17px}h3{font-size:var(--fs-4)}h4{font-size:var(--fs-3)}
a{color:var(--brand);text-decoration:none}
img{max-width:100%;display:block}
button{font-family:inherit}

/* 滚动条 */
::-webkit-scrollbar{width:9px;height:9px}
::-webkit-scrollbar-thumb{background:var(--line);border-radius:8px}
::-webkit-scrollbar-thumb:hover{background:var(--ink4)}
::-webkit-scrollbar-track{background:transparent}

/* ============ shell · 顶栏 ============ */
.top{height:56px;flex:none;display:flex;align-items:center;gap:var(--sp-5);padding:0 18px;background:var(--panel);border-bottom:1px solid var(--line);z-index:30}
/* 侧栏折叠按钮（顶栏最左，2026-10-21）。折叠后侧栏收成 64px 纯图标条（不显文字），靠它展开回来 */
.navtog{width:30px;height:30px;flex:none;display:flex;align-items:center;justify-content:center;border:0;background:transparent;color:var(--ink3);border-radius:8px;cursor:pointer;transition:.12s}
.navtog:hover{background:var(--fill);color:var(--ink)}
.navtog:focus-visible{outline:2px solid var(--brand);outline-offset:1px}
body.login-mode .navtog{display:none}
.logo{width:28px;height:28px;border-radius:8px;background:var(--grad-brand);display:flex;align-items:center;justify-content:center;color:var(--on-grad);font-size:var(--fs-2);font-weight:600;flex:none}
.brandname{font-size:14.5px;font-weight:600;letter-spacing:-.01em;white-space:nowrap}
.brandname small{font-weight:400;color:var(--ink3);font-size:var(--fs-2);margin-left:var(--sp-2)}
.spacer{margin-left:auto;display:flex;align-items:center;gap:10px}
.themetog{display:flex;gap:3px;background:var(--fill);padding:3px;border-radius:var(--r-md)}
.themetog button{border:0;background:transparent;height:28px;padding:0 11px;border-radius:7px;font:500 12.5px inherit;font-family:inherit;color:var(--ink3);cursor:pointer;display:flex;align-items:center;gap:5px}
.themetog button.on{background:var(--panel);color:var(--ink);box-shadow:var(--sh-xs)}
/* 主题切换位于「设置」页；顶栏只保留品牌与侧栏折叠按钮。 */

/* ============ shell · 舞台 ============ */
.stage{flex:1;display:flex;min-height:0}
/* 侧栏两态（2026-10-21 改，参照抖音桌面端）：
   折叠 = 64px 纯图标条（只留 em 图标，文字 .lb 隐藏）；展开 = 210px（≤1100 时 180）的完整侧栏。
   写法：折叠条就是基础规则，展开态是下面 @media (min-width:761px) 里的一份覆盖。
   这样「用户手动收起（.stage.nav-min）」与「窄屏 ≤760px 强制折叠」命中的是同一份规则，
   不存在两份需要同步的副本，也不需要用 JS + matchMedia 驱动（那会在首帧闪一下）。
   展开宽度与 localStorage['nav.min'] 持久化都保持不变。 */
.appnav{width:64px;flex:none;background:var(--panel);border-right:1px solid var(--line);padding:14px 5px 18px;overflow-y:auto;overflow-x:hidden;display:flex;flex-direction:column;gap:2px;transition:width .16s ease,padding .16s ease}

/* 折叠态分组标题：压成一条分隔线（沿用原做法，不新增文字） */
.appnav .grp{height:0;padding:0;margin:9px 4px 7px;border-top:1px solid var(--line2);overflow:hidden;font-size:0;line-height:0}
.appnav .grp:first-child{margin-top:2px;margin-bottom:0;border-top:0}

/* 折叠态条目：纯图标，单行居中；上下 12px 内距 + 20px 图标 = 44px 条目高，点按不会挤成一团。
   图标 20px（2026-10-21 定，之前 16px）：64px 栏里 16px 只占 25% 宽，12 个入口里 5 个要靠猜。
   宽度占满内宽（64 - 右边框 1 - 左右各 5 = 53）
   min-height:44（1.1.1 · N-101）：折叠态本来就是 12+12+20=44，这条只为把**展开态**补到 44——
   展开态 padding 是 8px、图标 16px、文字 13px，算下来 33px，比折叠态更难点。
   断点不动、不新增类：`min-height` 在两种状态同一条基础规则里，展开态只是被它兜住。 */
.appnav .it{display:flex;flex-direction:row;align-items:center;justify-content:center;gap:0;padding:12px 0;min-height:44px;border-radius:8px;font-size:var(--fs-3);color:var(--ink2);cursor:pointer;transition:.12s;user-select:none}
.appnav .it:hover{background:var(--bg)}
.appnav .it.on{background:var(--brand-soft);color:var(--brand-ink);font-weight:500}
/* 图标槽：折叠态 20×20。svg 撑满整格并 display:block，避免 inline 基线在下方留 3–4px 空隙把条目顶高 */
.appnav .it em{font-style:normal;width:20px;height:20px;display:flex;align-items:center;justify-content:center;flex:none;opacity:.85}
.appnav .it em svg{display:block;width:100%;height:100%}
/* 折叠态不显示文字，但 .lb 要留在 DOM 里（展开态还要显示）。
   悬浮提示改由下面 .navtip 单例承担，文字本身不参与折叠态排版。 */
.appnav .it .lb{display:none}
/* 折叠态悬浮提示（自绘，替代原生 title）：原生 title ~1s 才出且样式不可控，达不到「120ms 内出现」。
   气泡不能做成 .it::after —— .appnav 为了长列表可滚必须 overflow-y:auto，而一个轴是 auto 时
   另一个轴的 visible 会被规范算成 auto，气泡放到 right:100% 会被栏自己裁掉（实测 opacity=1 但看不见）。
   所以气泡是挂 body 的 fixed 单例 .navtip，位置由 router.js 在 hover/focus 时按条目 rect 算。
   配色 --ink / --panel 在双主题下正好反色（浅色主题深底白字、深色主题浅底深字），对比度实测 >14。
   只在折叠态出现（展开态文字就在旁边，不需要气泡）。 */
.navtip{
  position:fixed;left:0;top:0;z-index:60;
  background:var(--ink);color:var(--panel);font-size:var(--fs-2);line-height:1.4;
  padding:4px 8px;border-radius:6px;white-space:nowrap;pointer-events:none;
  opacity:0;transform:translateY(-50%) translateX(-3px);
  transition:opacity .08s ease,transform .08s ease;
}
.navtip.on{opacity:1;transform:translateY(-50%) translateX(0)}
/* 账号按钮：外层 .usrw 只承担「贴底 + 上分隔线 + 与导航的呼吸」，
   点击区永远只有 .usr 一个元素；箭头移除后头像仍可打开账户菜单。 */
.appnav .usrw{margin-top:auto;padding-top:10px;border-top:1px solid var(--line2)}
.appnav .usr{
  display:flex;align-items:center;justify-content:center;gap:4px;
  width:100%;height:44px;padding:0;
  border:0;border-radius:var(--r-md);background:transparent;
  font-family:inherit;text-align:left;color:var(--ink);cursor:pointer;
  transition:background .12s ease;
}
.appnav .usr:hover{background:var(--fill)}
/* 打开时保持底色：菜单开着而触发器没有「我按过」的反馈，读起来像菜单和按钮没关系 */
.appnav .usr[aria-expanded="true"]{background:var(--fill)}
.appnav .usr:focus-visible{outline:2px solid var(--brand);outline-offset:1px}
.appnav .usr .av{width:24px;height:24px;font-size:10.5px}
/* 文本列折叠态只隐不删：展开态要复活它，且身份文本始终只有可见的一处 */
.appnav .usr .grow{display:none;flex-direction:column;justify-content:center;gap:1px;flex:1;min-width:0}
.appnav .usr .nm{font-size:var(--fs-3);font-weight:500;line-height:1.3;color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* 空间名用 --ink2 而不是 --ink3：--ink3 在浅色下 3.05:1，且 10px 已低于最小可读字号（本次一并修掉） */
.appnav .usr .sub{font-size:11.5px;line-height:1.3;color:var(--ink2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* ============ 账号菜单（body 级 fixed 单例，2026-10-21） ============
   为什么不挂在 .appnav 里：栏为了长列表可滚有 overflow-y:auto，而规范规定一个轴是 auto 时
   另一轴的 visible 也按 auto 算 —— 挂在栏里的弹层会被 64px 栏自己裁掉：菜单宽比栏宽大一截，
   越出栏右沿的那段整条看不见。上一轮 tooltip 已踩过一次。所以它与 .navtip 同套路：document.body 直接子元素 + fixed，
   位置由 router.js 按触发器 rect 算（朝上弹，见 placeAcctMenu）。
   关闭时直接 remove()，不常驻 DOM：既保证「全页身份文本 = 1」可断言，也不给读屏器留一段
   永远隐藏的 aria-labelledby 目标。因此这里只有打开动效，没有关闭动效（元素已不在树上）。
   z-index 950（2026-10-21 复核修正，原文写 70）：
   1) 必须高于「壳专属」录制条 .recbar 的 900（studio/src/renderer/app/css/recorder.css:12），
      否则 ≤900px 时录制条横跨全宽，菜单右缘会被它切掉一条；
   2) 仍低于 .mask / .sheet(1000) 与 .toast-wrap(1200)，遮罩与提示仍压住菜单；
   3) 菜单不需要压过 1000：router.js 的 watchModals() 在 .mask/.sheet 出现时会强制关闭菜单，
      两者不会同时存在，950 留出的 50 只是给同层浮层的余量；
   4) 同时高于 .navtip(60)，tooltip 不会穿过菜单。 */
.acctmenu{
  position:fixed;z-index:950;width:220px;max-width:calc(100vw - 16px);padding:8px;
  background:var(--panel);border:1px solid var(--line);border-radius:var(--r-lg);
  box-shadow:var(--sh-lg);
  opacity:0;transform:translateY(4px);visibility:hidden;pointer-events:none;
  /* 基态不写 transition：关闭是同步 remove()，写了也永远不播，只是死代码。
     打开动效由 .acctmenu.on 自己那一份承担（元素入树后先落一帧基态再加 .on）。 */
}
/* ---- 展开态：与侧栏条目同列、同宽（2026-10-23 PM 要求「对齐 + 一样大」）----
   起因（实测，非目测）：展开态下弹层条目图标左沿 29 / 文字左沿 55，
   而侧栏 .it 条目是 20 / 46 —— 弹层多套了「面板 padding 8 + 条目 padding 10」，
   图标列整体右移 9px，文字列对不上；面板又按固定字面量取宽（折叠态那档），
   比侧栏条目宽一截，右沿探到侧栏外 21px。字号 / 图标 / 行高本来就一致。
   做法：展开态改用侧栏那套度量 —— 面板 padding 归零、条目 padding 与 .it 同为 8px 10px、
   宽度跟随侧栏栏宽（--nav-w-exp，真源见 body 上的定义），左沿随触发器（= 侧栏内容左沿）。
   边框不占位：改用 0 0 0 1px inset 描边，否则 1px 边框会把内容盒窄 2px，
   条目就与 .it 差 2px 宽（视觉上「一样大」会破功）。
   折叠态不变（64px 栏里没有可对齐的列，弹层仍按折叠态那档浮在内容区上方）。 */
.acctmenu.fit{
  width:calc(var(--nav-w-exp) - 21px);
  padding:0;border:0;
  box-shadow:0 0 0 1px var(--line),var(--sh-lg);
}
/* 条目度量与 .appnav .it 展开态逐项对齐：padding 8px 10px、min-height 44、圆角 8 */
.acctmenu.fit .am-it{padding:8px 10px;height:auto;min-height:44px}
/* 菜单头：空间图标落在与条目图标同一列（左沿 = 面板左沿 + 10 = 条目图标列） */
.acctmenu.fit .am-head{padding:12px 10px}
.acctmenu.fit .am-sep{margin:5px 10px}

.acctmenu.on{
  opacity:1;transform:none;visibility:visible;pointer-events:auto;
  transition:opacity .14s cubic-bezier(.2,.8,.2,1),transform .14s cubic-bezier(.2,.8,.2,1);
}
/* 菜单头：身份上下文，不参与命中、无 hover、不可聚焦（role 归 .am-list，头在 menu 之外） */
.acctmenu .am-head{padding:10px 10px 12px}
.acctmenu .am-nm{font-size:var(--fs-3);font-weight:500;line-height:18px;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.acctmenu .am-sp{display:flex;align-items:center;gap:6px;font-size:var(--fs-2);line-height:17px;color:var(--ink2);margin-top:2px}
.acctmenu .am-sp svg{flex:none;color:var(--ink3)}
.acctmenu .am-sp span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.acctmenu .am-sep{height:1px;background:var(--line2);margin:5px 10px}
.acctmenu .am-it{
  display:flex;align-items:center;gap:10px;width:100%;height:44px;padding:0 10px;
  border:0;border-radius:8px;background:transparent;
  font-family:inherit;font-size:var(--fs-3);font-weight:500;color:var(--ink2);
  text-align:left;cursor:pointer;transition:background .12s ease,color .12s ease;
}
.acctmenu .am-it svg{flex:none;color:var(--ink3);transition:color .12s ease}
.acctmenu .am-it:hover{background:var(--fill);color:var(--ink)}
.acctmenu .am-it:hover svg{color:var(--ink2)}
/* offset -2：内描边，避免 2px 环被 8px 圆角切角 */
.acctmenu .am-it:focus-visible{outline:2px solid var(--brand);outline-offset:-2px}
/* 危险/终止动作：--dg 族在本组件里只用于「结束会话」这一行，不表示失败，也不进任何状态提示
   （PM 2026-10-21 裁定，见 CONTRACT §4.4）。全页红只出现在这里。 */
.acctmenu .am-it.dg{color:var(--dg-ink)}
.acctmenu .am-it.dg svg{color:var(--dg-ink)}
.acctmenu .am-it.dg:hover{background:var(--dg-soft);color:var(--dg-ink)}
.acctmenu .am-it[disabled]{cursor:default}
.acctmenu .am-it[disabled]:hover{background:transparent;color:var(--ink3)}
.acctmenu .am-it[disabled] svg{color:var(--ink3)}
@media (prefers-reduced-motion:reduce){
  .acctmenu,.acctmenu.on{transition:none}
}

/* 展开态：只有「视口够宽」且「未被手动收起」时才生效。
   ≤760px 不满足 min-width，自动落回上面的折叠条 —— 窄屏不再 display:none。 */
@media (min-width:761px){
  .stage:not(.nav-min) .appnav{width:var(--nav-w-exp);padding-left:10px;padding-right:10px}
  .stage:not(.nav-min) .appnav .grp{height:auto;margin:0;padding:14px 10px 5px;border-top:0;overflow:visible;font-size:10.5px;line-height:1.4;letter-spacing:.08em;text-transform:uppercase;font-weight:500;color:var(--ink4)}
  .stage:not(.nav-min) .appnav .grp:first-child{padding-top:2px}
  .stage:not(.nav-min) .appnav .it{flex-direction:row;justify-content:flex-start;gap:10px;padding:var(--sp-3) 10px}
  /* 展开态图标回到 16px：旁边有 13px 文字，20px 图标会把行高撑开、视觉也重 */
  .stage:not(.nav-min) .appnav .it em{width:16px;height:16px}
  .stage:not(.nav-min) .appnav .it .lb{display:block;font-size:inherit;line-height:inherit;text-align:left;min-width:0;max-width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  /* 展开态账号卡：完整用户卡 189×48（≤1100 视口 180 栏时 159×48），文字列复活 */
  .stage:not(.nav-min) .appnav .usr{height:48px;justify-content:flex-start;gap:8px;padding:0 8px}
  .stage:not(.nav-min) .appnav .usr .av{width:32px;height:32px;font-size:12.5px}
  .stage:not(.nav-min) .appnav .usr .grow{display:flex}
}
.appmain{flex:1;min-width:0;overflow-y:auto;background:var(--bg)}
#view{min-height:100%}

/* ============ shell · 页面容器 ============ */
.pg{padding:var(--sp-6) var(--sp-7) 48px;max-width:1360px}
.pghd{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--sp-5);margin-bottom:var(--sp-5)}
.pghd h1{font-size:19px}
.pghd .sub{font-size:12.5px;color:var(--ink3);margin-top:var(--sp-1);line-height:1.6}
/* 页头左侧：返回按钮 + 标题块（2026-10-23 二级页统一返回）。
   按钮只负责放 [data-back] 和样式，点击行为由 router.js 的委托统一处理（见 App.back）。 */
.pghd-main{display:flex;align-items:flex-start;gap:10px;min-width:0}
.pgback{flex:none;width:32px;height:32px;margin-top:2px;border:1px solid var(--line);border-radius:8px;background:var(--panel);color:var(--ink2);font-size:15px;line-height:1;display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:.12s}
.pgback:hover{background:var(--fill);border-color:var(--ink4);color:var(--ink)}
.pgback:focus-visible{outline:2px solid var(--brand);outline-offset:1px}
/* 分享页（H5 卡片）没有标准页头：卡片上方单独一行返回，宽度与 .d-h5（430px）对齐 */
.d-h5bar{max-width:430px;margin:0 auto 10px;display:flex;align-items:center}
.vh{display:flex;align-items:flex-end;justify-content:space-between;gap:var(--sp-5);margin-bottom:14px}
.vh h2{font-size:var(--fs-5)}
.vh p{font-size:12.5px;color:var(--ink3);margin-top:3px;max-width:860px;line-height:1.6}

/* ============ utilities ============ */
.row{display:flex;align-items:center}
.col{display:flex;flex-direction:column}
.between{display:flex;align-items:center;justify-content:space-between}
.wrap{flex-wrap:wrap}
.grow{flex:1;min-width:0}
.g6{gap:var(--sp-2)}.g8{gap:var(--sp-3)}.g10{gap:10px}.g12{gap:var(--sp-4)}.g14{gap:14px}.g16{gap:var(--sp-5)}.g20{gap:var(--sp-6)}.g24{gap:var(--sp-7)}
.grid{display:grid;gap:14px}
.c2{grid-template-columns:repeat(2,minmax(0,1fr))}
.c3{grid-template-columns:repeat(3,minmax(0,1fr))}
.c4{grid-template-columns:repeat(4,minmax(0,1fr))}
.c5{grid-template-columns:repeat(5,minmax(0,1fr))}
.muted{color:var(--ink3)}
.dim{color:var(--ink2)}
.cap{font-size:var(--fs-2);line-height:1.65}
.mic{font-size:var(--fs-1);line-height:1.55}
.tnum{font-variant-numeric:tabular-nums}
.mono{font-family:ui-monospace,SFMono-Regular,Menlo,monospace}
.w500{font-weight:500}.w600{font-weight:600}
.tc{text-align:center}.tr{text-align:right}
.mt4{margin-top:var(--sp-1)}.mt6{margin-top:var(--sp-2)}.mt8{margin-top:var(--sp-3)}.mt10{margin-top:10px}.mt12{margin-top:var(--sp-4)}.mt14{margin-top:14px}.mt16{margin-top:var(--sp-5)}.mt20{margin-top:var(--sp-6)}.mt24{margin-top:var(--sp-7)}
.div{height:1px;background:var(--line2);margin:14px 0}

/* ============ components · 按钮 / 链接 ============ */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--sp-2);height:34px;padding:0 14px;border:1px solid transparent;border-radius:8px;font-family:inherit;font-size:13.5px;font-weight:500;cursor:pointer;background:var(--fill);color:var(--ink2);transition:.15s;white-space:nowrap}
.btn:hover{background:var(--fill-hover);color:var(--ink)}
.btn.p{background:var(--brand);color:var(--on-brand);box-shadow:var(--sh-xs)}
.btn.p:hover{background:var(--brand-hover);color:var(--on-brand)}
.btn.g{background:var(--panel);border-color:var(--line);color:var(--ink2)}
.btn.g:hover{background:var(--bg);border-color:var(--ink4);color:var(--ink)}
.btn.s{background:var(--brand-soft);color:var(--brand-ink)}
.btn.s:hover{background:var(--brand-soft);filter:brightness(.97)}
.btn.d{background:var(--panel);border-color:var(--dg-line);color:var(--dg-ink)}
.btn.d:hover{background:var(--dg-soft)}
.btn.ai{background:var(--grad-ai);color:var(--on-ai)}
.btn.ai:hover{filter:brightness(1.07)}
.btn.lg{height:42px;padding:0 var(--sp-6);font-size:14.5px;border-radius:var(--r-md)}
.btn.sm{height:28px;padding:0 10px;font-size:12.5px;border-radius:7px}
.btn.xs{height:24px;padding:0 var(--sp-3);font-size:11.5px;border-radius:var(--r-sm)}
.btn.ico{width:34px;padding:0}
.btn.ico.sm{width:28px}
.btn.ico.xs{width:24px}
.btn[disabled],.btn.off{opacity:.45;cursor:not-allowed}
.btn[disabled]:hover{background:var(--fill);color:var(--ink2)}

.link{color:var(--brand);font-size:var(--fs-3);cursor:pointer;font-weight:500}
.link.mut{color:var(--ink3);font-weight:400}

/* ============ components · 表单 ============ */
.lab{display:block;font-size:12.5px;font-weight:500;color:var(--ink2);margin-bottom:var(--sp-2)}
.inp{width:100%;height:36px;padding:0 var(--sp-4);border:1px solid var(--line);border-radius:8px;background:var(--panel);font-family:inherit;font-size:13.5px;color:var(--ink);transition:.15s}
.inp::placeholder{color:var(--ink4)}
.inp:focus{outline:0;border-color:var(--brand);box-shadow:0 0 0 3px var(--brand-soft)}
.inp.lg{height:44px;font-size:var(--fs-4);border-radius:var(--r-md)}
.inp.err{border-color:var(--dg);box-shadow:0 0 0 3px var(--dg-soft)}
textarea.inp{height:auto;padding:10px var(--sp-4);line-height:1.6;resize:vertical;font-family:inherit}
.sel{position:relative}
.sel::after{content:"\2304";position:absolute;right:12px;top:50%;transform:translateY(-56%);color:var(--ink3);font-size:var(--fs-3);pointer-events:none}
.sel select{appearance:none;padding-right:30px;cursor:pointer}
.hint{font-size:var(--fs-2);color:var(--ink3);margin-top:var(--sp-2)}
.hint.err{color:var(--dg-ink)}

.sw{width:38px;height:22px;border-radius:99px;background:var(--fill-hover);position:relative;cursor:pointer;flex:none;transition:.18s;border:0;padding:0}
.sw i{position:absolute;top:2px;left:2px;width:18px;height:18px;border-radius:50%;background:var(--panel);box-shadow:var(--sh-sm);transition:.18s}
.sw.on{background:var(--brand)}
.sw.on i{left:18px}
.ck{width:17px;height:17px;border-radius:5px;border:1.5px solid var(--line);background:var(--panel);flex:none;display:flex;align-items:center;justify-content:center;font-size:10px;color:transparent;cursor:pointer}
.ck.on{background:var(--brand);border-color:var(--brand);color:var(--on-brand)}
.rd{width:17px;height:17px;border-radius:50%;border:1.5px solid var(--line);background:var(--panel);flex:none;position:relative;cursor:pointer;transition:.15s}
.rd.on{border-color:var(--brand);border-width:5px}

/* ============ components · 标签 / 头像 ============ */
.tag{display:inline-flex;align-items:center;gap:var(--sp-1);height:21px;padding:0 var(--sp-3);border-radius:var(--r-sm);font-size:11.5px;font-weight:500;background:var(--fill);color:var(--ink2);white-space:nowrap}
.tag.br{background:var(--brand-soft);color:var(--brand-ink)}
.tag.ok{background:var(--ok-soft);color:var(--ok-ink)}
.tag.wn{background:var(--wn-soft);color:var(--wn-ink)}
.tag.dg{background:var(--dg-soft);color:var(--dg-ink)}
.tag.ai{background:var(--ai-soft);color:var(--ai-ink)}
.tag.ol{background:transparent;border:1px solid var(--line);color:var(--ink2)}
.tag .dt{width:6px;height:6px;border-radius:50%;background:currentColor;flex:none}
.tag.lg{height:25px;padding:0 10px;font-size:var(--fs-2);border-radius:7px}

.av{width:32px;height:32px;border-radius:50%;background:var(--grad-av);display:flex;align-items:center;justify-content:center;font-size:var(--fs-2);font-weight:600;color:var(--on-av);flex:none;overflow:hidden}
.av.sm{width:24px;height:24px;font-size:10.5px}
.av.lg{width:44px;height:44px;font-size:15px}
.av.xl{width:64px;height:64px;font-size:21px}
.av.p{background:var(--grad-av-p);color:var(--on-av-p)}
.av.sq{border-radius:9px}

/* ============ components · 卡片 / 缩略图 ============ */
.card{background:var(--panel);border:1px solid var(--line);border-radius:var(--r-lg);box-shadow:var(--sh-xs);overflow:hidden}
.card>.hd{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-4);padding:13px var(--sp-5);border-bottom:1px solid var(--line2)}
.card>.hd h3{font-size:13.5px}
.card>.bd{padding:var(--sp-5)}
.card>.ft{padding:var(--sp-4) var(--sp-5);border-top:1px solid var(--line2);background:var(--panel2)}
.card.flat{box-shadow:none}
.card.ai{border-color:var(--ai-line);background:linear-gradient(180deg,var(--ai-soft),var(--panel) 42%)}

.thumb{border-radius:9px;background:linear-gradient(135deg,var(--panel3),var(--panel2));border:1px solid var(--line2);display:flex;align-items:center;justify-content:center;color:var(--ink4);font-size:19px;position:relative;overflow:hidden}
/* 内容色：缩略图时长角标 —— 压在封面图上，深浅主题同值（属内容，不随令牌翻转） */
.thumb .dur{position:absolute;right:6px;bottom:6px;background:rgba(10,14,22,.72);color:#fff;font-size:10.5px;padding:1px var(--sp-2);border-radius:5px;font-variant-numeric:tabular-nums}

/* ============ components · 段控 / 页签 / 进度 ============ */
.seg{display:inline-flex;background:var(--fill);border-radius:9px;padding:3px;gap:2px}
.seg button{border:0;background:transparent;height:28px;padding:0 var(--sp-4);border-radius:7px;font-family:inherit;font-size:12.5px;font-weight:500;color:var(--ink3);cursor:pointer;transition:.15s}
.seg button.on{background:var(--panel);color:var(--ink);box-shadow:var(--sh-xs)}

.tabs{display:flex;gap:22px;border-bottom:1px solid var(--line)}
.tabs .t{padding:11px 0;font-size:13.5px;color:var(--ink3);cursor:pointer;position:relative}
.tabs .t.on{color:var(--ink);font-weight:500}
.tabs .t.on::after{content:"";position:absolute;left:0;right:0;bottom:-1px;height:2px;background:var(--brand);border-radius:2px}
.tabs .t b{font-size:var(--fs-1);font-weight:600;background:var(--dg);color:var(--on-dg);border-radius:99px;padding:1px var(--sp-2);margin-left:5px;vertical-align:1px}

.pb{height:6px;border-radius:99px;background:var(--fill);overflow:hidden}
.pb>i{display:block;height:100%;border-radius:99px;background:var(--brand);transition:width .3s ease}
.pb.ai>i{background:var(--grad-ai)}
.pb.ok>i{background:var(--ok)}
.pb.wn>i{background:var(--wn)}
.pb.dg>i{background:var(--dg)}
.pb.thin{height:4px}
.pb.thick{height:8px}

/* ============ components · KPI / 表格 / 步骤 ============ */
.kpi{background:var(--panel);border:1px solid var(--line);border-radius:var(--r-lg);padding:14px var(--sp-5);box-shadow:var(--sh-xs)}
.kpi .k{font-size:var(--fs-2);color:var(--ink3);display:flex;align-items:center;gap:var(--sp-2)}
.kpi .v{font-size:26px;font-weight:600;letter-spacing:-.025em;margin-top:7px;font-variant-numeric:tabular-nums;line-height:1.1}
.kpi .v small{font-size:var(--fs-3);font-weight:500;color:var(--ink3);margin-left:3px}
.kpi .d{font-size:var(--fs-2);margin-top:5px;color:var(--ink3)}
.up{color:var(--ok-ink);font-weight:500}
.dn{color:var(--dg-ink);font-weight:500}

.tb{width:100%;border-collapse:collapse;font-size:var(--fs-3)}
.tb th{text-align:left;font-size:11.5px;font-weight:500;color:var(--ink3);padding:9px var(--sp-4);border-bottom:1px solid var(--line);background:var(--panel2);white-space:nowrap}
.tb td{padding:11px var(--sp-4);border-bottom:1px solid var(--line2);color:var(--ink2);vertical-align:middle}
.tb tbody tr:last-child td,.tb tr:last-child td{border-bottom:0}
.tb tr:hover td{background:var(--panel2)}
.tb .t1{color:var(--ink);font-weight:500}

.step{display:flex;align-items:center;gap:9px;font-size:var(--fs-3);color:var(--ink3);white-space:nowrap}
.step em{width:22px;height:22px;border-radius:50%;background:var(--panel);border:1px solid var(--line);display:flex;align-items:center;justify-content:center;font-style:normal;font-size:11.5px;font-weight:500;color:var(--ink3);flex:none}
.step.done em{background:var(--ok);border-color:var(--ok);color:var(--on-ok)}
.step.now em{background:var(--brand);border-color:var(--brand);color:var(--on-brand)}
.step.done,.step.now{color:var(--ink);font-weight:500}
.st-line{flex:1;height:1px;background:var(--line);min-width:14px}

/* ============ components · 列表项 / 空态 / 骨架 ============ */
.item{display:flex;gap:var(--sp-4);align-items:center;padding:11px var(--sp-4);border-radius:var(--r-md);border:1px solid var(--line);background:var(--panel);cursor:pointer;transition:.13s}
.item:hover{border-color:var(--brand-line)}
.item.on{border-color:var(--brand);box-shadow:0 0 0 2px var(--brand-soft)}
.item .ic{width:34px;height:34px;border-radius:9px;background:var(--fill);display:flex;align-items:center;justify-content:center;font-size:15px;color:var(--ink2);flex:none}
.item .tt{font-size:var(--fs-3);color:var(--ink);font-weight:500}
.item .ss{font-size:11.5px;color:var(--ink3);margin-top:3px}

/* ============ 编辑器 · PPT 幻灯片导航 ============ */
.editor-grid{display:grid;grid-template-columns:218px minmax(0,1fr) 300px;gap:12px;align-items:start}
.editor-grid>#edLeft,.editor-grid>#edMid,.editor-grid>#edRight{min-width:0}
.editor-grid .card>.hd{padding:10px 14px}
.editor-grid .card>.bd{padding:14px}
/* 分镜列表：卡片体按 .shot 的 8px 密度，靠选择器优先级覆盖 .editor-grid .card>.bd，
   不用 !important（!important 会把「页面级密度」变成不可覆盖的死值）。 */
.editor-grid .card>.bd.editor-slide-list{display:flex;flex-direction:column;gap:6px;padding:var(--sp-3);max-height:64vh;overflow:auto}
/* 分镜行：右侧「上移/下移」列宽 = 设计稿 .btn.ico.xs 的 24px（ui-kit:189-191 图标按钮档） */
.ppt-slide-item{display:grid;grid-template-columns:minmax(0,1fr) 24px;gap:5px;align-items:center;padding:4px;border:1px solid transparent;border-radius:9px;cursor:pointer;transition:.13s}
.ppt-slide-item:hover{background:var(--panel2);border-color:var(--line)}
.ppt-slide-item.on{background:var(--brand-soft);border-color:var(--brand);box-shadow:0 0 0 1px var(--brand-soft)}
.ppt-slide-face{display:grid;grid-template-columns:minmax(0,1fr) 42px;gap:6px;align-items:center;min-width:0}
/* 内容色：幻灯片缩略图的媒体描边/投影 —— 随内容渲染，不随主题翻转 */
/* 内容字号：幻灯片缩略图内文案随缩略图等比缩放（8/6/9px），不是 UI 字号档位 */
.ppt-slide-thumb{position:relative;display:flex;flex-direction:column;justify-content:space-between;width:100%;min-width:0;aspect-ratio:16/9;padding:6px 7px;border:1px solid rgba(20,28,40,.1);border-radius:5px;overflow:hidden;box-shadow:0 1px 3px rgba(10,14,22,.12)}
.ppt-slide-thumb.is-experiment{border-color:var(--line)}
.ppt-slide-number{position:absolute;left:3px;top:3px;min-width:13px;height:13px;padding:0 3px;display:flex;align-items:center;justify-content:center;border-radius:3px;background:rgba(10,14,22,.72);color:#fff;font-size:8px;line-height:1;font-variant-numeric:tabular-nums}
.ppt-slide-brand{display:flex;justify-content:space-between;gap:4px;padding-left:13px;font-size:6px;line-height:1.1;opacity:.8;white-space:nowrap;overflow:hidden}
.ppt-slide-brand span:first-child{overflow:hidden;text-overflow:ellipsis}
.ppt-slide-copy{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;max-height:2.56em;overflow:hidden;font-size:9px;font-weight:700;line-height:1.28;word-break:break-word}
.ppt-slide-footer{max-width:calc(100% - 24px);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:6px;line-height:1.1;opacity:.75}
.ppt-slide-info{display:flex;flex-direction:column;align-items:flex-start;justify-content:center;gap:3px;min-width:0;color:var(--ink2);font-size:9px;line-height:1.25;overflow:hidden}
.ppt-slide-info>span:first-child{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ppt-slide-info .mic{font-size:9px}
.ppt-slide-order{display:flex;flex-direction:column;gap:4px}
/* 上移/下移按钮不再自造 22×22 覆盖：直接用设计稿的 .btn.ico.xs（24×24、padding 0、radius 6） */
.ppt-slide-order .btn{min-width:24px}
@media (max-width:1100px){
  .editor-grid{grid-template-columns:190px minmax(0,1fr) 270px;gap:10px}
  .ppt-slide-face{grid-template-columns:minmax(0,1fr) 38px;gap:5px}
}
@media (max-width:900px){
  .editor-grid{grid-template-columns:180px minmax(0,1fr);grid-template-areas:"slides stage" "slides props"}
  .editor-grid>#edLeft{grid-area:slides}
  .editor-grid>#edMid{grid-area:stage}
  .editor-grid>#edRight{grid-area:props}
}
@media (max-width:680px){
  .editor-grid{grid-template-columns:minmax(0,1fr);grid-template-areas:"slides" "stage" "props"}
  .editor-slide-list{max-height:260px}
}

.empty{display:flex;flex-direction:column;align-items:center;gap:9px;padding:44px var(--sp-6);text-align:center}
.empty .ic{width:46px;height:46px;border-radius:13px;background:var(--fill);display:flex;align-items:center;justify-content:center;font-size:var(--fs-6);color:var(--ink4)}
.empty .tt{font-size:13.5px;font-weight:500}
.empty .ss{font-size:12.5px;color:var(--ink3);max-width:340px;line-height:1.6}

.sk{background:linear-gradient(90deg,var(--fill) 25%,var(--panel2) 40%,var(--fill) 60%);background-size:400% 100%;border-radius:var(--r-sm);animation:sk 1.4s ease infinite}
@keyframes sk{0%{background-position:100% 50%}100%{background-position:0 50%}}

.pill{display:inline-flex;align-items:center;gap:var(--sp-2);height:26px;padding:0 10px;border-radius:99px;background:var(--fill);font-size:var(--fs-2);color:var(--ink2)}

/* ============ components · toast / modal ============ */
.toast{display:inline-flex;align-items:center;gap:9px;background:var(--ink);color:var(--bg);border-radius:var(--r-md);padding:10px 14px;font-size:var(--fs-3);box-shadow:var(--sh-lg)}
.toast.ai{background:var(--grad-ai);color:var(--on-ai)}
.toast.ok{background:var(--ok);color:var(--on-ok)}
.toast.err{background:var(--dg);color:var(--on-dg)}
.toast-wrap{position:fixed;right:20px;bottom:20px;z-index:1200;display:flex;flex-direction:column;align-items:flex-end;gap:10px;pointer-events:none}
.toast-wrap .toast{animation:toastIn .18s ease;transition:opacity .2s ease,transform .2s ease}
.toast-wrap .toast.out{opacity:0;transform:translateY(8px)}
@keyframes toastIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
.tip{background:var(--ink);color:var(--bg);font-size:var(--fs-2);padding:var(--sp-2) 9px;border-radius:7px;display:inline-block}
/* 内容色：全屏遮罩 —— 压在页面之上，深浅主题同为半透明深墨（遮罩语义，不随令牌翻转） */
.mask{position:fixed;inset:0;background:rgba(10,14,22,.45);display:flex;align-items:center;justify-content:center;padding:var(--sp-7);z-index:1000}
.modal{background:var(--panel);border-radius:16px;box-shadow:var(--sh-xl);border:1px solid var(--line);overflow:hidden;width:440px;max-width:100%;max-height:90vh;display:flex;flex-direction:column}
.modal .mh{padding:var(--sp-5) 18px;border-bottom:1px solid var(--line2);display:flex;align-items:center;justify-content:space-between}
.modal .mb{padding:18px;overflow:auto}
.modal .mf{padding:13px 18px;border-top:1px solid var(--line2);display:flex;justify-content:flex-end;gap:9px;background:var(--panel2)}

/* ============ 业务组件（供 C/D/E 复用，与 ui-kit 同名同义） ============ */
.shot{position:relative;display:flex;gap:10px;padding:var(--sp-3);border-radius:var(--r-md);border:1px solid var(--line);background:var(--panel);cursor:pointer;transition:.13s}
.shot:hover{border-color:var(--brand-line)}
.shot.on{border-color:var(--brand);box-shadow:0 0 0 2px var(--brand-soft)}
.shot .no{position:absolute;left:0;top:0;width:19px;height:19px;border-radius:9px 0 8px 0;background:var(--fill);font-size:10px;color:var(--ink3);display:flex;align-items:center;justify-content:center;font-variant-numeric:tabular-nums}
.shot .th{width:72px;height:42px;border-radius:var(--r-sm);flex:none;background:linear-gradient(135deg,var(--panel3),var(--panel2));border:1px solid var(--line2);display:flex;align-items:center;justify-content:center;color:var(--ink4);font-size:var(--fs-3)}

/* 内容色：播放器舞台与幻灯片页是内容本身（V-405）—— 深浅主题都必须深舞台 + 白页，
   故这里刻意使用字面色值而不是会随主题翻转的令牌。 */
.player{aspect-ratio:16/9;border-radius:12px;background:#0E131D;border:1px solid rgba(255,255,255,.07);position:relative;display:flex;align-items:center;justify-content:center;overflow:hidden;flex:none}
.player .slide{margin:auto;width:66%;aspect-ratio:16/9;background:#fff;border-radius:var(--r-sm);box-shadow:0 10px 30px rgba(0,0,0,.5);display:flex;flex-direction:column;padding:11px 13px;color:#141924}
.player .ctrl{position:absolute;left:10px;right:10px;bottom:10px;display:flex;align-items:center;gap:9px;background:rgba(12,16,24,.82);border-radius:9px;padding:7px 10px;color:#fff;font-size:11.5px}
.player .ctrl .pb{background:rgba(255,255,255,.22)}
.player .ctrl .pb>i{background:#fff}

.strip{display:flex;gap:3px}
.strip .s{height:32px;border-radius:5px;background:var(--fill);border:1px solid var(--line);display:flex;align-items:center;justify-content:center;font-size:9.5px;color:var(--ink4);font-variant-numeric:tabular-nums;cursor:pointer}
.strip .s.on{background:var(--brand);border-color:var(--brand);color:var(--on-brand)}
.strip .s.ai{background:var(--ai-soft);border-color:var(--ai-line);color:var(--ai-ink)}
.wave{height:20px;background:repeating-linear-gradient(90deg,var(--ink4) 0 2px,transparent 2px 4px);opacity:.5;border-radius:3px}

.bar-chart{display:flex;align-items:flex-end;gap:9px;height:118px}
.bar-chart .b{flex:1;display:flex;flex-direction:column;align-items:center;gap:var(--sp-2);height:100%;justify-content:flex-end}
.bar-chart .b i{width:100%;max-width:26px;border-radius:5px 5px 2px 2px;background:var(--brand-soft);border:1px solid var(--brand-line);display:block}
.bar-chart .b.hi i{background:var(--brand);border-color:var(--brand)}
.bar-chart .b span{font-size:10.5px;color:var(--ink3)}
.donut{width:104px;height:104px;border-radius:50%;background:conic-gradient(var(--brand) 0 62%,var(--ai) 62% 84%,var(--fill) 84% 100%);display:flex;align-items:center;justify-content:center;flex:none}
.donut i{width:70px;height:70px;border-radius:50%;background:var(--panel);display:flex;align-items:center;justify-content:center;font-style:normal;font-size:17px;font-weight:600;font-variant-numeric:tabular-nums}

.vcard .cover{aspect-ratio:16/9;border-radius:12px;background:linear-gradient(135deg,var(--panel3),var(--panel2));border:1px solid var(--line2);display:flex;align-items:center;justify-content:center;color:var(--ink4);font-size:22px;position:relative;overflow:hidden}
/* 内容色：封面角度标 —— 压在封面图上，深浅主题同值（属内容） */
.vcard .cover .dur{position:absolute;right:8px;bottom:8px;background:rgba(10,14,22,.72);color:#fff;font-size:var(--fs-1);padding:2px 7px;border-radius:var(--r-sm);font-variant-numeric:tabular-nums}
.vcard .cover .lock{position:absolute;left:8px;top:8px;background:rgba(10,14,22,.66);color:#fff;font-size:10.5px;padding:3px var(--sp-3);border-radius:var(--r-sm)}
.vcard .tt{font-size:var(--fs-4);font-weight:500;line-height:1.45;margin-top:9px}
.vcard .mt{font-size:11.5px;color:var(--ink3);margin-top:7px;display:flex;align-items:center;gap:var(--sp-3)}

.cells{display:grid;grid-template-columns:repeat(4,1fr);gap:10px var(--sp-3);text-align:center}
.cells .ic{width:40px;height:40px;border-radius:12px;background:var(--fill);margin:0 auto 7px;display:flex;align-items:center;justify-content:center;font-size:17px;color:var(--ink2)}
.cells span{font-size:var(--fs-1);color:var(--ink2)}
.sheet{position:fixed;left:0;right:0;bottom:0;background:var(--panel);border-radius:20px 20px 0 0;border-top:1px solid var(--line);box-shadow:0 -14px 36px rgba(0,0,0,.2);padding:var(--sp-5) var(--sp-5) var(--sp-7);z-index:1000}
.capsule{display:inline-flex;align-items:center;gap:var(--sp-3);border:1px solid var(--line);border-radius:99px;padding:3px 10px;font-size:11.5px;color:var(--ink2);background:var(--panel)}
.sec{border-top:1px solid var(--line2);padding:22px 0}
.sec:first-child{border-top:0;padding-top:2px}
.sech{display:flex;align-items:baseline;justify-content:space-between;gap:var(--sp-4);margin-bottom:var(--sp-5)}
.sech h3{font-size:13.5px}

/* ============ login · 单屏登录页（PRD §六，无顶栏/侧栏） ============ */
body.login-mode .top,
body.login-mode .appnav,
/* v1.2.4：分享落地页是公开链接，匿名访客不得看到创作端侧栏/工作台入口 —— 去壳（顶栏 + 侧栏都不渲染） */
body.share-mode .top,
body.share-mode .appnav,
/* v1.2.6 M6（§3.4 C2/C3）：五条消费路由同样去壳。上面两行一个字未改，本段为追加。
   ① 用 display 不用 visibility —— A12 断言 .appnav 的 offsetWidth === 0；
   ② 只隐藏、不删 DOM —— A12 的「侧栏子树豁免」依赖它仍在树上；
   ③ 侧栏是消费端唯一的退出入口，隐藏后由页内 .d-topbar 补「登录态 + 退出」（见下方 .d-topbar）。 */
body.learn-mode .top,
body.learn-mode .appnav{display:none}
.login-wrap{min-height:100%;display:flex;align-items:center;justify-content:center;padding:var(--sp-8) var(--sp-6)}
.login-card{width:380px;max-width:100%;background:var(--panel);border:1px solid var(--line);border-radius:16px;box-shadow:var(--sh-lg);padding:var(--sp-8) 30px var(--sp-7)}
.login-brand{display:flex;align-items:center;gap:11px}
.login-brand .logo{width:38px;height:38px;border-radius:11px;font-size:var(--fs-4)}
.login-title{font-size:19px;font-weight:600;letter-spacing:-.01em;color:var(--ink)}
.login-sub{font-size:12.5px;color:var(--ink3);margin-top:3px}
.login-code{display:flex;gap:var(--sp-3)}
.login-code .inp{flex:1;min-width:0}
.login-code .btn{flex:none;height:44px}
.login-agree{font-size:11.5px;color:var(--ink4);line-height:1.7;text-align:center;margin-top:var(--sp-5)}
.spin{width:14px;height:14px;border-radius:50%;border:2px solid var(--brand-soft);border-top-color:var(--brand);animation:spin .7s linear infinite;display:inline-block;flex:none}
.btn.p .spin{border-color:var(--brand-line);border-top-color:var(--on-brand)}
@keyframes spin{to{transform:rotate(360deg)}}
.shake{animation:shake .3s ease}
@keyframes shake{0%,100%{transform:none}25%{transform:translateX(-5px)}75%{transform:translateX(5px)}}

/* ============ 响应式 ============ */
@media (max-width:1100px){
  .c4{grid-template-columns:repeat(2,minmax(0,1fr))}
}
/* 展开宽 180：必须同时要求「够宽」与「未手动收起」，
   否则这条会盖掉 64px 折叠条（窄屏也落在 max-width:1100 里） */
@media (min-width:761px) and (max-width:1100px){
  body{--nav-w-exp:180px}
  .stage:not(.nav-min) .appnav{width:var(--nav-w-exp)}
}
@media (max-width:760px){
  .c2,.c3,.c4,.c5{grid-template-columns:minmax(0,1fr)}
  /* 窄屏不再隐藏侧栏：直接复用基础规则里的折叠条（与手动收起同一套视觉）。
     此时没有展开空间，按钮点了没东西可展开，留着只会让人以为坏了。 */
  .navtog{display:none}
}

/* ============ 演示访问口令（登录页入口，样式追加） ============ */
.login-gate{margin-top:var(--sp-2);text-align:center;line-height:1.6}
.login-gate .link{background:none;border:0;padding:0;font-family:inherit;font-size:11.5px}
.login-gate .link:hover{color:var(--brand-hover)}

/* ============ 消费端 v1.2.6（M 项专用，全部作用域化，不复用创作端网格） ============ */
/* M0 无成片阻塞态：与 16:9 舞台同形，只放一句实话 + 两个出口；不渲染任何播放控件 */
.d-blocked{aspect-ratio:16/9;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--sp-4);padding:var(--sp-6);text-align:center}
.d-blocked-ic{width:44px;height:44px;border-radius:var(--r-md);background:var(--panel);display:flex;align-items:center;justify-content:center;font-size:var(--fs-5);box-shadow:var(--sh-xs)}
.d-blocked-tt{font-size:var(--fs-5);font-weight:600;line-height:1.5}
/* M3「我的课程」：行沿用 .item 度量，仅补缩略图与置灰态；44px 动作区独立类，避免污染 .btn 档位 */
.d-my{margin-bottom:var(--sp-5)}
.myc__row{padding:10px var(--sp-4)}
/* 修饰符刻意不写 BEM 的 `--off`：选择器里的 `--` 会被 verify-ui-consistency 的 D7
   （防「块注释提前闭合」）判成红，语义不变，只换写法。 */
.myc__row-off{cursor:default;background:var(--panel2)}
.myc__row-off:hover{border-color:var(--line)}
.myc__thumb{width:76px;height:43px;flex:none;display:flex;align-items:center;justify-content:center;border-radius:var(--r-sm);font-size:var(--fs-3)}
.myc-act{height:44px;min-width:88px;padding:0 var(--sp-5);border:1px solid var(--line);border-radius:var(--r-md);background:var(--panel);color:var(--ink2);font-size:var(--fs-3);font-weight:500;cursor:pointer;transition:.13s}
.myc-act:hover{border-color:var(--ink4);color:var(--ink)}
/* hidden 属性要能盖住 .col{display:flex} 这类类选择器（否则四态切换会「切了但不生效」） */
.d-my [hidden]{display:none}
/* M5 分享面板：桌面居中弹层，窄屏自适应；面板内 hidden 同样要盖住类选择器 */
.d-sheet-mask{position:fixed;inset:0;background:var(--stage);opacity:.45;z-index:900}
.d-sheet{position:fixed;left:50%;top:50%;transform:translate(-50%,-50%);width:420px;max-width:calc(100vw - 32px);max-height:calc(100vh - 48px);overflow:auto;background:var(--panel);border:1px solid var(--line);border-radius:var(--r-lg);box-shadow:var(--sh-lg);padding:var(--sp-5);z-index:901}
.d-sheet [hidden],.d-sheet-mask[hidden]{display:none}
.d-sheet-code{margin-top:var(--sp-2);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:var(--fs-5);font-weight:600;letter-spacing:.06em;color:var(--brand-ink)}
.d-sheet-link{margin-top:var(--sp-3);word-break:break-all}
.d-sheet-qr{display:block;width:200px;height:200px;border:1px solid var(--line);border-radius:var(--r-sm);background:var(--panel)}

/* ---- M6 · 消费端外壳（§3.4 C2/C3） ----
   侧栏被 body.learn-mode 隐藏后，顶栏由 .d-topbar 承担：品牌 + 登录态 + 退出（唯一出口）。
   .d-page 是 #view 的首个子节点（全宽，不设 padding / max-width）：顶栏与 .pg 都放在它里面。
   为什么不能把顶栏直接当首子节点：verify-page-margins 按「#view 首子节点是否 .pg」认页面根，
   顶栏顶在最前会让它把顶栏当根（padding 0），learn.home 的边距等式必红（本轮实测 3 个视口全红）。 */
.d-page{min-height:100%}
.d-topbar{position:sticky;top:0;z-index:25;display:flex;align-items:center;gap:var(--sp-5);height:56px;padding:0 var(--sp-7);background:var(--panel);border-bottom:1px solid var(--line)}
.d-topbar-brand{font-size:var(--fs-4);font-weight:600;letter-spacing:-.01em;white-space:nowrap}
/* 窄屏（8090 只到平板宽度，但窗口可能被拖窄）：左右内距收到 --sp-4，登录态与退出仍要同排不换行 */
@media (max-width:760px){
  .d-topbar{padding:0 var(--sp-4);gap:var(--sp-3)}
}

/* ---- M7 · 首页网格（§3.4 C4/C5） ----
   只新建 .d-home / .d-grid 两个作用域类：
   · 不碰 .c3 / .c4 与 @media(max-width:1100) —— 那套被创作端 studio.js、管理端 admin.js 共用；
   · 不碰 .d-wrap{max-width:900} —— 播放页 / 作者页 / 首页共用这一个限宽。
   列数按视口：1440→4、1280→3、1024→3（≤1023 不再追求多列，直接单列）。
   分工：.d-grid 只管「网格 + 4 列」这个基元，.d-home 负责首页那套断点（列数覆盖都挂在 .d-home 下，
   别的页面将来复用 .d-grid 时不会被首页的断点悄悄改掉列数）。
   等高：grid 默认 align-items:stretch，卡片自身是 flex 列 + 体内 .bd flex:1 撑满，
   所以同一行卡片高度由行高决定，不靠给卡片写死高度。
   刻意不写 overflow-x 任何兜底：A11 明令禁止用 overflow 掩盖横向溢出。 */
.d-home{display:block}
.d-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:var(--sp-5);align-items:stretch}
.d-grid>.card{display:flex;flex-direction:column;min-width:0}
/* 只补「撑满」这件事：padding / margin / 类名与 .card>.bd 原值一致（C5 的等式判据依赖它） */
.d-grid>.card>.bd{flex:1}
@media (max-width:1280px){
  .d-home .d-grid{grid-template-columns:repeat(3,minmax(0,1fr))}
}
@media (max-width:1023px){
  .d-home .d-grid{grid-template-columns:minmax(0,1fr)}
}

/* ---- 首页在 .d-home 作用域内放开限宽（v1.2.6 遗留 4 / §3.4 C4） ----
   .d-wrap{max-width:900}（learn.css:10）被 C4 冻结：创作端 studio.js:232、管理端
   admin.js:270、播放页与作者页共用同一个类，改它等于静默改掉那些页面的列宽。
   所以**不动 .d-wrap 本身**，只给「同时带 .d-home」的那个容器更宽的限宽 —— 全仓只有
   消费端首页把 .d-home 加到页面根上（learn.js 的 learn.home render），作用域天然收窄。
   max-width 计在边框盒上（.pg 的左右内距各 24 在盒内），故内容盒 = 1240 − 48 = 1192：
   1440 档四列各 (1192 − 3×16) / 4 = 286px（实测 286）；
   1280 档容器仍是 1240（视口放得下）→ 1192，三列各 387px（实测 387）；
   1024 档容器 = 视口 1024 → 内容 976，三列各 315px（实测 315）。
   1280/1024 两档的宽度取自视口/内距，与改动前的 900 限宽相比只是「更宽且仍放得下」，
   不产生横向溢出（网格列用 minmax(0,1fr)，见 .d-grid）。 */
.d-wrap.d-home{max-width:1240px}

/* ---- S1 · 首页 Hero 标题区（v1.2.6，PRD §3.2 S1） ----
   · .pghd 类名保留（verify-ui-consistency 的 A0 与 §3.4 C5 都依赖它），且 .pghd 自身的
     padding / margin 一个字都没动（C5 的 `.pghd` 跨页等式盯着 margin-bottom）。
   · 不引衬线字体（PRD §8 第 1 条 Diana 未定稿）：三级层级只靠 --fs-* 字号阶梯 + 字重 +
     字距 —— 眉标 11/600/宽字距（.14em）、大标题 20/600/收字距（-.02em）、副文案 12/常规。
   · 选择器带 .pghd 前缀是为了压过 .pghd h1{font-size:19px} / .pghd .sub 这两条既有声明
     （同为 1 类 1 元素，靠文件顺序取胜太脆）。 */
.pghd .d-eyebrow{font-size:var(--fs-1);font-weight:600;letter-spacing:.14em;color:var(--ink3)}
.pghd .d-h1{font-size:var(--fs-6);font-weight:600;letter-spacing:-.02em;line-height:1.35;margin-top:var(--sp-1)}
.pghd .d-lede{font-size:var(--fs-2);line-height:1.65;color:var(--ink3);margin-top:var(--sp-2);max-width:640px}

/* ---- S3 · 讲师头像「纯色方块 + 姓氏单字」（v1.2.6，PRD §3.2 S3） ----
   【临时色板】PRD §8 第 2 条：5 色板等 Diana 定稿 —— **待 Diana 定稿后替换映射表**：
   改下面 5 条 .d-av-* 的背景/前景，以及 learn.js 里的 AV_TONES 顺序（两处必须同时改）。
   纪律：只映射到现有语义色令牌 --brand/--ai/--ok/--wn/--dg，不新增令牌、不写死 hex；
   前景一律用对应的 --on-* 压色（tokens.css 五个都齐：--on-brand/--on-ai/--on-ok/
   --on-wn/--on-dg），不在这里自己算白或黑。
   **深色 --ai 的对比度已修（2026-10-27）**：深色主题 --ai（#9B7BFF）配 --on-ai（白）
   实测只有 3.15:1，低于 4.5（头像字号 12/20px、600 字重，不适用大文本 3:1）。
   修法：仅在深色主题把 --ai 底色用 color-mix 向 --bg 压到 65%（纯令牌，不新增令牌、
   不写死 hex），实测约 6.5:1。浅色侧原本 4.70 不动。待 Diana 定稿 5 色板时，
   应改为正式的 --on-ai 定义，届时删掉下面那条 color-mix 覆盖即可。
   尺寸只用现有间距令牌（--sp-*），圆角只用 --r-*：24 常规 / 20 小 / 64 大（= --sp-8 × 2）。 */
.d-av{width:var(--sp-7);height:var(--sp-7);border-radius:var(--r-sm);display:flex;align-items:center;justify-content:center;font-size:var(--fs-2);font-weight:600;line-height:1;flex:none;overflow:hidden}
.d-av-sm{width:var(--sp-6);height:var(--sp-6);font-size:var(--fs-1)}
.d-av-xl{width:calc(var(--sp-8) * 2);height:calc(var(--sp-8) * 2);border-radius:var(--r-md);font-size:var(--fs-6)}
.d-av-brand{background:var(--brand);color:var(--on-brand)}
.d-av-ai{background:var(--ai);color:var(--on-ai)}
.d-av-ok{background:var(--ok);color:var(--on-ok)}
.d-av-wn{background:var(--wn);color:var(--on-wn)}
.d-av-dg{background:var(--dg);color:var(--on-dg)}
[data-theme="dark"] .d-av-ai{background:color-mix(in srgb, var(--ai) 65%, var(--bg))}

/* ---- 备案号页脚（法定要求，v1.2.7 备案迁移） ----
   挂在 body 末尾 = #view 之外：不进 A12 的 #view 子树，也不跟 #view 一起滚。
   只出现在消费端五条路由：显隐复用 router 既有的 body.learn-mode，不新增类、不新增路由判断。
   居中小字、只用现有令牌，不抢视觉；flex:none 让它在 body 的列布局里固定占一行。 */
#d-icp{display:none;flex:none;padding:var(--sp-2) var(--sp-4);text-align:center;
  font-size:var(--fs-1);line-height:1.6;color:var(--ink3);background:var(--bg)}
body.learn-mode #d-icp{display:block}
#d-icp a{color:var(--ink3);text-decoration:none}
#d-icp a:hover{color:var(--ink2);text-decoration:underline}
