*{box-sizing:border-box;margin:0;padding:0}
:root{
  --bg:#e9e7e0;
  --panel:#ffffff;
  --panel-2:#faf7ef;
  --ink:#1d1e18;
  --muted:#6f6f63;
  --soft:#9a998b;
  --line:#eae6da;
  --line-2:#ddd8c9;
  --accent:#f4c945;          /* 主色:黄 */
  --accent-strong:#e0ac10;
  --accent-bg:#fdf4d2;
  --dark:#1d1e18;
  --green:#3f9b6b;
  --green-bg:#e7f5ec;
  --blue:#2f6bd8;
  --blue-bg:#eaf1ff;
  --amber:#a8720a;
  --amber-bg:#fdf0d3;
  --red:#c2443b;
  --red-bg:#fdeeec;
  --violet:#7a54cf;
  --violet-bg:#f1ecfb;
  --shadow:0 18px 40px rgba(70,60,25,.10);
  --shadow-sm:0 6px 18px rgba(70,60,25,.07);
  --r:22px;
  --r-md:16px;
  --r-sm:11px;
}
body{
  min-height:100vh;
  color:var(--ink);
  font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Microsoft YaHei",Arial,sans-serif;
  font-size:13px;
  line-height:1.5;
  font-weight:400;
  -webkit-font-smoothing:antialiased;
  background:
    radial-gradient(1200px 500px at 92% -8%, rgba(244,201,69,.32), transparent 60%),
    radial-gradient(800px 480px at 100% 34%, rgba(244,201,69,.16), transparent 55%),
    linear-gradient(180deg,#edeae2 0%,#e9e7e0 100%);
  background-attachment:fixed;
}
button,input,select,textarea{font:inherit}
button{cursor:pointer}

/* ===== 左侧栏布局 ===== */
.app{min-height:100vh;display:grid;grid-template-columns:236px minmax(0,1fr)}
.side{
  position:sticky;top:0;height:100vh;overflow:auto;
  display:flex;flex-direction:column;gap:6px;
  background:var(--dark);color:#e9e8de;
  padding:20px 14px;
}
.brand{display:flex;gap:11px;align-items:center;padding:4px 8px 18px}
.mark{
  width:40px;height:40px;border-radius:13px;background:var(--accent);color:#3a2f05;
  display:flex;align-items:center;justify-content:center;font-weight:700;font-size:14px;letter-spacing:.5px;flex:0 0 auto;
}
.brand strong{display:block;font-size:16px;line-height:1.15;font-weight:600;color:#fff}
.brand span{display:block;color:#9a998b;font-size:11.5px;margin-top:1px}

/* 侧栏导航 */
.nav{display:flex;flex-direction:column;gap:3px}
/* 「更多」只在**真的装不下**时才有意义。电脑端侧边栏是竖排的,十个入口全展开着,
   底下还挂一个「更多」—— 点开是同一批东西,纯噪音(老板:「只有展示不出来再用」)。
   收起按钮那条规则 .nav-hide{display:none} 本来就只写在手机的 media query 里,
   而这个「更多」当初漏了配对的规则,于是电脑上一直露着。 */
.nav .nav-more{display:none}
.nav button{
  border:0;background:transparent;color:#b7b6ab;text-align:left;
  border-radius:12px;min-height:40px;padding:9px 12px;
  display:flex;align-items:center;gap:11px;font-size:13.5px;font-weight:500;
  transition:background .2s,color .2s;
}
.nav button .ico{opacity:.7}
.nav button:hover{color:#fff;background:rgba(255,255,255,.06)}
.nav button.on{background:var(--accent);color:#3a2f05;font-weight:600}
.nav button.on .ico{opacity:1}
.ico{width:18px;height:18px;display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto}
.side-foot{margin-top:auto;padding-top:16px;display:flex;flex-direction:column;gap:8px;align-items:stretch}
.side-foot .tag{background:rgba(255,255,255,.07);border-color:rgba(255,255,255,.12);color:#cfcec4;justify-content:center}
.side-foot .tag.green{background:rgba(63,155,107,.22);border-color:rgba(63,155,107,.4);color:#8fdcae}
.side-foot .tag.warn{background:rgba(168,114,10,.24);border-color:rgba(168,114,10,.4);color:#f0c877}
.side-foot .select{background:rgba(255,255,255,.08);border-color:rgba(255,255,255,.14);color:#fff}
.side-foot .select option{color:#1d1e18}
.top-left{display:none}

/* ===== 内容区 ===== */
.main{min-width:0}
.content{max-width:1320px;width:100%;margin:0 auto;padding:26px 30px 48px}
.hidden{display:none!important}
.head{display:flex;justify-content:space-between;align-items:flex-start;gap:16px;margin-bottom:22px;animation:fadeDown .4s ease both}
.head h1{font-size:36px;line-height:1.06;margin-bottom:7px;font-weight:300;letter-spacing:-1px}
.head h1 .tag{font-weight:600;letter-spacing:0}
.head p{color:var(--muted);font-size:13px;max-width:780px}
.grid{display:grid;gap:16px}
.kpis{grid-template-columns:repeat(auto-fit,minmax(190px,1fr));margin-bottom:16px}

/* ===== 卡片 ===== */
.card{
  background:var(--panel);border:1px solid rgba(255,255,255,.6);border-radius:var(--r);
  box-shadow:var(--shadow-sm);overflow:hidden;
  animation:cardIn .42s cubic-bezier(.2,.7,.3,1) both;
}
.card.pad{padding:20px}
/* KPI:图2 风格——小图标 + 细大数字 + 下方标签 */
.kpi{padding:20px 21px;min-height:120px;transition:transform .22s,box-shadow .22s}
.kpi-row{display:flex;align-items:center;gap:13px;margin-bottom:9px}
.kpi-ico{width:38px;height:38px;border-radius:12px;background:var(--panel-2);display:flex;align-items:center;justify-content:center;color:var(--ink);flex:0 0 auto}
.kpi strong{display:block;font-size:42px;line-height:.9;font-weight:200;letter-spacing:-2px}
.kpi label{display:block;color:var(--muted);font-size:12.5px;font-weight:500}
.kpi span{font-size:11px;color:var(--soft);display:block;margin-top:3px}
.kpi.click{cursor:pointer}
.kpi.click:hover,.card.pad.lift:hover{transform:translateY(-3px);box-shadow:var(--shadow)}
.split{display:grid;grid-template-columns:minmax(0,1.6fr) minmax(330px,.8fr);gap:16px}
.split.equal{grid-template-columns:1fr 1fr}
.section-title{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;margin-bottom:14px;flex-wrap:wrap}
.section-title>*{min-width:0}
.section-title h2{font-size:17px;font-weight:600}
.section-title p{font-size:12px;color:var(--muted);margin-top:3px}

/* ===== 今日待办:图1 深色卡 ===== */
.todo-card{background:var(--dark);color:#e9e8de;border-radius:var(--r);padding:22px 24px;margin-bottom:18px;box-shadow:var(--shadow);animation:cardIn .42s cubic-bezier(.2,.7,.3,1) both}
.todo-head{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;margin-bottom:14px}
.todo-head h2{color:#fff;font-weight:500;font-size:19px}
.todo-head p{color:#9a998b;font-size:12.5px;margin-top:3px}
.todo-count{font-size:38px;font-weight:200;color:#fff;line-height:1;letter-spacing:-1px;white-space:nowrap;text-align:right}
.todo-count b{color:var(--accent);font-weight:200}
/* 说明这两个数各是什么 —— 光一个「7/8」会被读成「已完成 1 项」(真发生过) */
.todo-count span{display:block;font-size:11px;color:#9a998b;letter-spacing:0;margin-top:5px}
/* 按「要做什么动作」分组。组标题只是个小标签,不抢大数字和条目本身的注意力 */
.todo-group{margin-top:6px}
.todo-group-t{color:#9a998b;font-size:11.5px;letter-spacing:.3px;padding:10px 0 2px;border-top:1px solid rgba(255,255,255,.09)}
.todo-group .todo-item:first-of-type{border-top:none}
.todo-item{display:flex;align-items:center;gap:14px;padding:13px 0;border-top:1px solid rgba(255,255,255,.09)}
.todo-ico{width:44px;height:44px;border-radius:50%;background:rgba(255,255,255,.08);display:flex;align-items:center;justify-content:center;color:#e6e5db;flex:0 0 auto}
.todo-ico.light{background:#f5f3eb;color:#2a2b23}
.todo-main{flex:1;min-width:0}
.todo-main strong{display:block;color:#fff;font-weight:500;font-size:14.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.todo-main .s{color:#9a998b;font-size:12px;margin-top:2px}
.todo-go{
  width:34px;height:34px;border-radius:50%;flex:0 0 auto;border:0;cursor:pointer;
  background:rgba(255,255,255,.1);color:#e9e8de;display:flex;align-items:center;justify-content:center;
  transition:transform .15s,background .2s;
}
.todo-go:hover{transform:scale(1.08)}
.todo-go.urgent{background:var(--accent);color:#3a2f05}
.todo-empty{color:#9a998b;padding:16px 0;font-size:13px}

/* 环形图 */
.donut{transform:rotate(-90deg)}
.donut circle{fill:none;stroke-linecap:round}
.donut-wrap{display:flex;align-items:center;gap:16px}
.donut-center{position:relative}
.donut-center .dc-num{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center}
.donut-center .dc-num b{font-size:22px;font-weight:300;line-height:1}
.donut-center .dc-num span{font-size:10.5px;color:var(--muted)}
.legend{display:flex;flex-direction:column;gap:7px;font-size:12px}
.legend div{display:flex;align-items:center;gap:7px}
.legend i{width:10px;height:10px;border-radius:3px;flex:0 0 auto}

/* ===== 全局「正在忙」指示 =====
 * 固定在右下角,不挡内容、不拦点击(pointer-events:none)。
 * 只在真有请求在飞时出现 —— 常驻的加载条会被无视,偶尔出现的才有信息量。 */
/* 「停止」按钮:老板要的 —— 输入错了能中断,别白等也别白烧积分。
   pointer-events 要单独打开:#globalBusy 整体是 none(不挡点击),按钮得能点。 */
#globalBusyStop{margin-left:10px;padding:2px 10px;border-radius:8px;border:1px solid rgba(255,255,255,.35);
  background:transparent;color:inherit;font-size:12px;cursor:pointer;pointer-events:auto}
#globalBusyStop:hover{background:rgba(255,255,255,.16)}
/* 「别关页面」那句:比主文案弱一档,但不能弱到看不见 —— 它说的是一件会让人白等的事。
   空文本时自动不占位(:empty),免得非 AI 请求也留一道空隙。 */
.busy-hint{font-size:11.5px;opacity:.72;border-left:1px solid var(--line);padding-left:9px;margin-left:1px}
.busy-hint:empty{display:none}
/* 「正在跑」面板的条目。和 todo-item 长得像但不复用 —— 那个是深色卡里的,这个在普通卡里 */
.run-row{display:flex;align-items:center;gap:11px;padding:10px 0;border-top:1px solid var(--line)}
.run-row:first-of-type{border-top:none}
.run-main{flex:1;min-width:0}
.run-main strong{display:block;font-size:14px}
.run-main .s{color:var(--muted,#8a8a7a);font-size:12px;margin-top:2px;line-height:1.5}
#globalBusy{position:fixed;right:18px;bottom:18px;z-index:9998;
  display:flex;align-items:center;gap:9px;
  background:var(--panel);border:1px solid var(--line);border-radius:10px;
  padding:9px 14px;font-size:12.5px;color:var(--ink);
  box-shadow:0 6px 20px rgba(0,0,0,.13);
  opacity:0;transform:translateY(8px);pointer-events:none;
  transition:opacity .18s, transform .18s}
#globalBusy.on{opacity:1;transform:none}
#globalBusy .spin{width:14px;height:14px;flex:0 0 auto;border-radius:50%;
  border:2px solid var(--line);border-top-color:var(--accent-strong);
  animation:busySpin .7s linear infinite}
@keyframes busySpin{to{transform:rotate(360deg)}}
@media(prefers-reduced-motion:reduce){#globalBusy .spin{animation-duration:2s}}
@media(max-width:720px){#globalBusy{right:10px;bottom:74px;font-size:12px;padding:8px 11px}}

/* ===== 表格 =====
 * 表格比容器宽时,横向滚动条落在**长表格的最底部** —— 屏幕上看不到,
 * 于是右边那几列就这么消失了,而页面看起来只是"加载不完整"。
 * (员工原话:「仪表盘页面加载BUG,显示不完整」;顺带还以为项目行不能点,
 *  其实是行的右半边被切在视口外,鼠标划过去没有反馈。)
 * 两件事解决它:① 右边缘加一道渐隐,一眼看出"右边还有";
 * ② 上边也放一条滚动条(scrollbar-gutter 让它常驻,不用滚到底才发现)。 */
.table-wrap{overflow:auto;position:relative;
  /* 右边缘渐隐:滚到最右时因为背景色贴合而自然消失。
   * ⚠️ 只能写 background-image,**不能用 background 简写** ——
   * 简写会把 .card 的 background-color 一起重置成 transparent,
   * `.card.table-wrap`(仪表盘那张项目表)于是整块变透明,
   * body 那层米色 + 右上角金色渐变直接透上来,看着就是「这块颜色坏了」,
   * 而旁边的「管理层摘要」「项目健康度」还是白的,对比之下更明显。 */
  background-image:
    linear-gradient(to left, var(--panel) 0, rgba(255,255,255,0) 28px);
  background-position:right center;
  background-size:40px 100%;
  background-repeat:no-repeat;
  background-attachment:local;
}
.table-wrap::-webkit-scrollbar{height:9px}
.table-wrap::-webkit-scrollbar-thumb{background:var(--line);border-radius:5px}
.table-wrap::-webkit-scrollbar-thumb:hover{background:var(--soft)}
/* 提示条:只在真的能横滚时由 JS 加上 .can-scroll */
.table-wrap.can-scroll::after{content:'← 左右滑动看更多列';position:sticky;left:0;bottom:0;
  display:block;font-size:11px;color:var(--soft);padding:4px 2px 0;white-space:nowrap}
table{width:100%;border-collapse:collapse;min-width:860px}
th,td{padding:13px 14px;border-bottom:1px solid var(--line);text-align:left;vertical-align:middle}
th{color:var(--soft);font-size:11.5px;font-weight:700;text-transform:none}
tr:last-child td{border-bottom:0}
tbody tr{transition:background .15s}
tbody tr:hover{background:var(--panel-2)}
.name{font-weight:750}
.sub{font-size:11.5px;color:var(--soft);margin-top:2px}

/* ===== 标签 ===== */
.tag{
  display:inline-flex;align-items:center;gap:5px;border:1px solid var(--line);border-radius:999px;
  padding:4px 10px;font-size:11.5px;color:var(--muted);white-space:nowrap;background:#fff;font-weight:600;
}
.tag.green{background:var(--green-bg);border-color:#c9e9d4;color:var(--green)}
.tag.blue{background:var(--blue-bg);border-color:#cbdcff;color:var(--blue)}
.tag.warn{background:var(--amber-bg);border-color:#f0d69a;color:var(--amber)}
.tag.bad{background:var(--red-bg);border-color:#f2c9c4;color:var(--red)}
.tag.violet{background:var(--violet-bg);border-color:#ddd0f5;color:var(--violet)}
.tag.accent{background:var(--accent-bg);border-color:#f2df9c;color:var(--accent-strong)}

/* ===== 列表 / item ===== */
.list{display:flex;flex-direction:column;gap:10px}
.item{border:1px solid var(--line);border-radius:var(--r-md);background:var(--panel-2);padding:13px 14px;transition:transform .18s,box-shadow .18s}
.item:hover{box-shadow:var(--shadow-sm)}
.item-top{display:flex;justify-content:space-between;align-items:center;gap:10px;margin-bottom:5px}
.item strong{font-size:13px}
.item p{font-size:12px;color:var(--muted)}
.progress{height:9px;background:#eceadf;border-radius:999px;overflow:hidden;margin-top:10px}
.progress span{display:block;height:100%;background:var(--accent);border-radius:999px;transition:width .6s cubic-bezier(.2,.7,.3,1)}
.progress span.warn{background:var(--amber)}
.progress span.bad{background:var(--red)}

/* ===== 表单 ===== */
.form-grid{display:grid;grid-template-columns:1fr 1fr;gap:13px}
.field{margin-bottom:12px}
.field label{display:block;font-size:11.5px;color:var(--soft);margin-bottom:6px;font-weight:600}
.input,.select,.area{
  width:100%;border:1px solid var(--line);background:#fff;border-radius:var(--r-sm);
  padding:10px 12px;outline:none;color:var(--ink);transition:border-color .18s,box-shadow .18s;
}
.input:focus,.select:focus,.area:focus{border-color:var(--accent);box-shadow:0 0 0 3px rgba(244,201,69,.28)}
.area{min-height:80px;resize:vertical}
.check-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:9px}
.check-item{display:flex!important;align-items:center;gap:9px;margin:0!important;color:var(--ink)!important;font-size:12.5px!important;cursor:pointer}
/* 图1 风格圆形 checkbox:选中黄底白勾,未选灰圈 */
.check-item input[type=checkbox]{
  appearance:none;-webkit-appearance:none;width:21px;height:21px;border-radius:50%;
  border:2px solid var(--line-2);background:#fff;position:relative;cursor:pointer;flex:0 0 auto;
  transition:background .18s,border-color .18s,transform .1s;
}
.check-item input[type=checkbox]:hover{border-color:var(--accent-strong)}
.check-item input[type=checkbox]:checked{background:var(--accent);border-color:var(--accent)}
.check-item input[type=checkbox]:checked::after{
  content:'';position:absolute;left:6.5px;top:2.5px;width:5px;height:9px;
  border:solid #3a2f05;border-width:0 2.4px 2.4px 0;transform:rotate(45deg);
}
.check-item input[type=checkbox]:active{transform:scale(.9)}
.report-box{min-height:120px;background:var(--panel-2);border:1px solid var(--line);border-radius:var(--r-md);padding:15px;white-space:pre-wrap;color:#2b2c24}

/* ===== 按钮 ===== */
.btn{
  min-height:36px;border:1px solid var(--line);background:#fff;color:var(--ink);
  border-radius:11px;padding:8px 14px;display:inline-flex;align-items:center;justify-content:center;gap:6px;
  font-weight:600;transition:transform .1s,box-shadow .18s,background .18s,border-color .18s;
  /* 按钮文字**永不断行**。中文可以在任意两个字之间断,所以按钮一被挤窄,
   * 「记录结果」就会变成竖着的四个字、按钮拉成一根高条 —— 产出库里五个按钮挤一行时
   * 整片卡片都是这种竖条(2026-08-21 老板截图)。宁可让它溢出/换行,也不能把字拆开。 */
  white-space:nowrap;
}
.btn:hover{border-color:var(--line-2);box-shadow:var(--shadow-sm)}
.btn:active{transform:scale(.97)}
.btn.primary{background:var(--dark);border-color:var(--dark);color:#fff}
.btn.primary:hover{box-shadow:0 8px 20px rgba(29,30,24,.28)}
.btn.green{background:var(--accent);border-color:var(--accent);color:#3a2f05}
.btn.green:hover{background:var(--accent-strong);border-color:var(--accent-strong)}
.btn.danger{color:var(--red);border-color:#f2c9c4;background:#fff}
.btn.small{min-height:30px;padding:5px 10px;font-size:12px;border-radius:9px}
.btn.icon{width:36px;padding:0}

/* ===== 其它组件 ===== */
.cards{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:14px}
.kb-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:14px}
.asset{padding:16px;min-height:120px}
.asset h3{font-size:14px;margin-bottom:7px;font-weight:700}
.asset p{font-size:12px;color:var(--muted);margin-bottom:10px;white-space:pre-wrap}
.asset-meta{display:flex;gap:6px;flex-wrap:wrap;align-items:center}
.toolbar{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-bottom:14px}
.toolbar .input{max-width:280px}
.metric-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:11px;margin-bottom:13px}
.metric{border:1px solid var(--line);background:var(--panel-2);border-radius:var(--r-md);padding:13px}
.metric label{display:block;color:var(--soft);font-size:11.5px;margin-bottom:6px;font-weight:600}
.metric strong{display:block;font-size:20px;line-height:1.2;font-weight:800}
.detail-grid{display:grid;grid-template-columns:minmax(0,.75fr) minmax(0,1.45fr);gap:16px;align-items:start}
.project-list{display:flex;flex-direction:column;gap:10px}
.project-row{border:1px solid var(--line);background:var(--panel-2);border-radius:var(--r-md);padding:13px;cursor:pointer;transition:transform .18s,box-shadow .18s,border-color .18s}
.project-row:hover{border-color:var(--line-2);transform:translateY(-2px);box-shadow:var(--shadow-sm)}
.project-row.active{border-color:var(--accent);background:var(--accent-bg)}
.project-row .item-top{margin-bottom:7px}
.timeline{display:flex;flex-direction:column;gap:11px}
.log-entry{border:1px solid var(--line);background:var(--panel-2);border-radius:var(--r-md);padding:14px;transition:box-shadow .18s}
.log-entry:hover{box-shadow:var(--shadow-sm)}
.log-entry header{display:flex;align-items:flex-start;justify-content:space-between;gap:10px;margin-bottom:7px}
.log-entry h3{font-size:13px;display:flex;align-items:center;gap:6px;flex-wrap:wrap;font-weight:700}
.log-entry p{font-size:12px;color:var(--muted);margin-top:4px}
.date-range{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:11px}
.action-row{display:flex;gap:8px;flex-wrap:wrap;margin-top:14px}
.status-board{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:14px}
.status-column{border:1px solid var(--line);border-radius:var(--r-md);background:var(--panel-2);padding:14px;min-height:260px}
.status-column h2{font-size:13px;margin-bottom:10px;display:flex;align-items:center;justify-content:space-between;gap:8px;font-weight:750}
.capability-item{background:#fff;border:1px solid var(--line);border-radius:var(--r-sm);padding:13px;margin-bottom:10px;transition:transform .16s,box-shadow .16s}
.capability-item:hover{transform:translateY(-2px);box-shadow:var(--shadow-sm)}
.capability-item h3{font-size:13px;margin-bottom:4px;font-weight:700}
.capability-item p{font-size:12px;color:var(--muted);margin-bottom:8px}
.capability-meta{display:flex;gap:6px;flex-wrap:wrap;align-items:center}

/* ===== 弹窗 ===== */
/* 2026-09-03 老板:「打开skill的弹窗会很卡,打开复盘的弹窗也会卡」。
 * 去掉 backdrop-filter:blur(3px):它要求浏览器把**整页背景**重新光栅化再做高斯模糊,
 * 而且遮罩自身 overflow:auto —— 弹窗一滚动,那层模糊每帧重算一次。页面内容越多越明显
 * (产出库/技能页几十张卡),手机和集显笔记本上尤其。遮罩加深到 .55 补回层次感,
 * 视觉几乎无差,合成开销直接归零。
 * contain:layout paint —— 告诉浏览器遮罩内部的布局/绘制不外溢,弹窗里的滚动和重绘
 * 不再触发整页重排(背后那一屏卡片不用跟着重算)。 */
.modal-overlay{
  position:fixed;inset:0;background:rgba(29,30,24,.55);display:none;align-items:flex-start;justify-content:center;
  padding:48px 18px;z-index:30;overflow:auto;contain:layout paint;
}
.modal-overlay.on{display:flex;animation:overlayIn .2s ease both}
.modal{background:#fff;border-radius:var(--r);border:1px solid rgba(255,255,255,.6);box-shadow:var(--shadow);width:min(920px,100%);min-width:0;max-width:100%;animation:modalIn .28s cubic-bezier(.2,.7,.3,1) both}
/* flex 子项默认 min-width:auto —— 里面只要有一个不肯换行的东西(长 option 的 select、textarea),
   整个弹窗就会被撑到比屏幕宽,手机上表现为整页可以左右拖动。这三行是兜底。 */
.modal select,.modal textarea,.modal input{max-width:100%}
.modal.narrow{width:min(600px,100%)}
.modal.wide{width:min(1080px,100%)}
.modal.wide .modal-body{padding:22px 26px}
/* 技能工作台:大而干净的对话区(对标 Manus/WorkBuddy) */
.run-composer{border:1px solid var(--line-2);border-radius:18px;background:#fff;padding:10px 12px;box-shadow:0 2px 10px rgba(70,60,25,.05);transition:border-color .18s,box-shadow .18s}
.run-composer:focus-within{border-color:var(--accent);box-shadow:0 0 0 3px rgba(244,201,69,.22)}
.run-composer textarea{border:0;outline:0;background:transparent;padding:6px 4px;resize:none;width:100%;font-size:14px;line-height:1.6}
.run-composer .cbar{display:flex;align-items:center;gap:7px;margin-top:4px}
.run-composer .cbar .btn{border-radius:999px}
.run-send{width:38px;height:38px;border-radius:50%;display:flex;align-items:center;justify-content:center;background:var(--dark);color:#fff;border:0;font-size:16px;flex:0 0 auto;transition:transform .12s,opacity .18s}
.run-send:hover{transform:scale(1.06)}
.run-send:disabled{opacity:.35}
/* 创作项目型 Skill:对话仍可补充，但不让用户面对空白框自己猜输入 */
.skill-flow{display:grid;grid-template-columns:250px minmax(0,1fr);gap:16px;align-items:start}
.spreadsheet-workspace>*{min-width:0}
.spreadsheet-workspace{overflow-wrap:anywhere}
.spreadsheet-workspace .table{min-width:540px}
.spreadsheet-workspace .skill-flow-actions{flex-wrap:wrap}
.skill-brief{position:sticky;top:0;border:1px solid var(--line);border-radius:16px;background:var(--panel-2);padding:15px}
.skill-brief-head{display:flex;justify-content:space-between;align-items:center;font-size:13px}.skill-brief-head span{font-size:10.5px;color:var(--accent-strong)}
.skill-brief-bar{height:5px;border-radius:99px;background:var(--line);overflow:hidden;margin:10px 0 15px}.skill-brief-bar i{display:block;height:100%;background:var(--accent-strong);transition:width .2s}
.skill-brief-row{margin-bottom:10px}.skill-brief-row small,.skill-brief-files small{display:block;color:var(--muted);font-size:10.5px;margin-bottom:2px}.skill-brief-row div{font-size:12.5px;line-height:1.45}.skill-brief-row .missing{color:#b47716}
/* 可选项没填 —— **中性,不是警告**。刚打开弹窗时一个字都没填,
   整栏亮警告色会让人以为哪里出错了,而且警告色一多就不再有警告的意思。 */
.skill-brief-row .blank{color:var(--muted);opacity:.7}
.skill-brief-files{border-top:1px solid var(--line);padding-top:12px;margin-top:13px}.skill-brief-files p{font-size:10.5px;line-height:1.45;color:var(--muted);margin:6px 0 0}
.skill-steps{display:flex;justify-content:flex-end;gap:5px;margin-bottom:10px}.skill-steps span{font-size:10.5px;color:var(--muted);border:1px solid var(--line);background:#fff;border-radius:999px;padding:5px 10px}.skill-steps span.on{background:var(--dark);border-color:var(--dark);color:#fff}
.skill-flow-card{border:1px solid var(--line);border-radius:17px;background:#fff;padding:18px}.skill-ai-intro{display:flex;gap:11px;border-bottom:1px solid var(--line);padding-bottom:15px;margin-bottom:16px}.skill-ai-intro>b{width:32px;height:32px;display:grid;place-items:center;border-radius:50%;background:var(--accent);font-size:11px}.skill-ai-intro strong{font-size:14px}.skill-ai-intro p{font-size:12px;color:var(--muted);margin:4px 0 0}
.skill-form-grid{display:grid;grid-template-columns:1fr 1fr;gap:13px}.skill-form-grid label>span,.skill-extra>span{display:block;font-size:11.5px;color:var(--muted);margin-bottom:5px}.skill-form-grid label>small{display:block;color:var(--muted);font-size:10.5px;line-height:1.45;margin-top:4px}.skill-form-grid .cfg-field-wide{grid-column:1/-1}.skill-extra{display:block;margin-top:13px}.skill-extra textarea{min-height:70px}
.skill-flow-actions{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:15px;padding:10px 0 0;border-top:1px solid var(--line)}.skill-flow-actions small{color:var(--muted);font-size:10.5px}
.skill-card-head{display:flex;align-items:start;justify-content:space-between;gap:10px;margin-bottom:14px}.skill-card-head small{color:var(--accent-strong);font-weight:700}.skill-card-head h3{font-size:15px;margin:3px 0 0}
.skill-plan-list{display:grid;gap:7px}.skill-plan-list>div{display:flex;gap:12px;border:1px solid var(--line);border-radius:11px;padding:11px}.skill-plan-list>div>b{color:var(--accent-strong);font-size:11px}.skill-plan-list span{display:flex;flex-direction:column;gap:3px}.skill-plan-list strong{font-size:12.5px}.skill-plan-list small{font-size:11px;line-height:1.5;color:var(--muted)}
.skill-plan-list.compact{margin-top:12px}.skill-plan-list.compact>div{padding:9px 10px;background:var(--panel-2)}
/* 确认页只在**缺必填**时才出现的那条。都齐了一个字都不显示 ——
   完成度左边简报顶上就有,重复一遍纯占地方(老板点名)。 */
.cfg-ready.warn{margin:2px 0 4px;padding:10px 12px;border-radius:10px;background:#fff7ed;border:1px solid #fed7aa;color:#9a3412;font-size:12.5px;line-height:1.6}
/* ===== AI 文本的 markdown 排版(见 public/app.js 的 mdToHtml) =====
   刻意克制:模型的标题一律降到 h4/h5/h6,不许压过页面自己的标题;
   表格自己横向滚动,不把版面撑破(复盘的指标表列数不定)。 */
/* 外层常常是 .pre(带 white-space:pre-wrap)。渲染之后换行已经是 <br>/<p> 了,
   再让 pre-wrap 穿透进来,源码里的缩进会二次生效。代码块自己另外设。 */
.md{line-height:1.75;overflow-wrap:anywhere;white-space:normal}
.md>*:first-child{margin-top:0}
.md>*:last-child{margin-bottom:0}
.md p{margin:0 0 9px}
.md .md-h{margin:14px 0 6px;font-weight:700;line-height:1.45}
.md h4.md-h{font-size:14.5px}.md h5.md-h{font-size:13.5px}.md h6.md-h{font-size:12.5px;color:var(--muted)}
.md .md-list{margin:0 0 9px;padding-left:20px;display:flex;flex-direction:column;gap:3px}
.md .md-list li{margin:0}
.md .md-quote{margin:0 0 9px;padding:8px 12px;border-left:3px solid var(--accent-strong);background:var(--panel-2);border-radius:0 8px 8px 0}
.md .md-code{margin:0 0 9px;padding:9px 11px;background:var(--panel-2);border:1px solid var(--line);border-radius:8px;white-space:pre-wrap;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;overflow-x:auto}
.md code{background:var(--panel-2);border:1px solid var(--line);border-radius:4px;padding:0 4px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.92em}
.md .md-hr{margin:12px 0;border:0;border-top:1px solid var(--line)}
.md .md-tablewrap{margin:0 0 9px;overflow-x:auto;border:1px solid var(--line);border-radius:8px}
.md .md-table{border-collapse:collapse;width:100%;font-size:12.5px}
.md .md-table th,.md .md-table td{border-bottom:1px solid var(--line);padding:7px 10px;text-align:left;vertical-align:top}
.md .md-table thead th{background:var(--panel-2);font-weight:600;white-space:nowrap}
.md .md-table tbody tr:last-child td{border-bottom:0}
/* 数据诊断:两条路的二选一 + 右边的上传区 */
.cfg-way{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-bottom:12px}
.cfg-way-opt{appearance:none;text-align:left;cursor:pointer;background:#fff;border:1px solid var(--line);border-radius:12px;padding:13px 15px;display:flex;flex-direction:column;gap:4px;color:var(--ink)}
.cfg-way-opt:hover{border-color:var(--accent-strong)}
.cfg-way-opt.on{border-color:var(--accent-strong);box-shadow:0 0 0 2px rgba(244,201,69,.18);background:var(--accent-bg)}
.cfg-way-opt b{font-size:13px}
.cfg-way-opt small{font-size:11px;color:var(--muted);line-height:1.5}
.cfg-upbox{display:flex;align-items:center;gap:10px;flex-wrap:wrap;border:1px dashed var(--line);border-radius:11px;padding:12px 14px;margin-bottom:12px;background:var(--panel-2)}
.cfg-upbox .sub{font-size:11.5px}
/* 抽到的值挂一行出处 —— 「这个数哪来的」比数本身更该被看见 */
.cfg-src{display:block;font-style:normal;font-size:10px;color:var(--muted);margin-top:3px}
@media(max-width:760px){.cfg-way{grid-template-columns:1fr}}
.cfg-coverage{display:flex;align-items:center;gap:10px;margin-bottom:12px}.cfg-coverage>div{height:8px;background:var(--panel-2);border-radius:99px;overflow:hidden;flex:1}.cfg-coverage i{display:block;height:100%;background:var(--accent-strong);border-radius:99px}.cfg-coverage>b{font-size:12px;color:var(--accent-strong)}
.cfg-metric-grid{display:grid;grid-template-columns:1fr 1fr;gap:8px}.cfg-metric-grid>div{display:flex;gap:9px;border:1px solid var(--line);border-radius:11px;padding:10px;background:#fff}.cfg-metric-grid>div>span{width:22px;height:22px;border-radius:50%;display:grid;place-items:center;font-size:11px;font-weight:800;background:#fee2e2;color:#b91c1c}.cfg-metric-grid>div.ok>span{background:#dcfce7;color:#15803d}
/* 第三种状态:表单没填、但带了附件 —— 中性,不是告警。
   红色「!」配上「会去附件里找」的文案 = 画面和文字互相打脸,人只信画面。 */
.cfg-metric-grid>div.att>span{background:var(--panel-2);color:var(--muted);font-size:12px}
.cfg-metric-grid>div.att{border-style:dashed}.cfg-metric-grid section{display:flex;flex-direction:column;gap:3px;min-width:0}.cfg-metric-grid b{font-size:11.5px}.cfg-metric-grid small{font-size:10.5px;color:var(--muted);overflow-wrap:anywhere}.cfg-notice{margin-top:10px;border-radius:10px;background:#fff7ed;color:#9a3412;padding:9px 11px;font-size:11px;line-height:1.55}.cfg-notice.ok{background:#ecfdf5;color:#166534}
.cfg-source-grid{display:grid;grid-template-columns:1fr 1fr;gap:8px}.cfg-source{appearance:none;border:1px solid var(--line);background:#fff;border-radius:12px;padding:11px;display:grid;grid-template-columns:24px minmax(0,1fr) auto;gap:8px;text-align:left;color:var(--ink);cursor:pointer}.cfg-source:hover,.cfg-source.on{border-color:var(--accent-strong);box-shadow:0 0 0 2px rgba(244,201,69,.16)}.cfg-source.off{cursor:not-allowed;opacity:.62;box-shadow:none}.cfg-source.off:hover{border-color:var(--line);box-shadow:none}.cfg-source>i{width:22px;height:22px;display:grid;place-items:center;border-radius:50%;background:var(--panel-2);font-style:normal;font-weight:800}.cfg-source.on>i{background:var(--accent);color:#111}.cfg-source>span{display:flex;flex-direction:column;gap:3px;min-width:0}.cfg-source b{font-size:11.5px}.cfg-source small{font-size:10px;color:var(--muted);line-height:1.45}.cfg-source em{font-size:9px;font-style:normal;color:var(--accent-strong);white-space:nowrap}.cfg-evidence{border:1px dashed var(--line);background:var(--panel-2);border-radius:11px;padding:10px 12px;margin-top:12px}.cfg-evidence>b{font-size:11px}.cfg-evidence p{font-size:10.5px;color:var(--muted);margin:5px 0 0}
.skill-dir-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:9px}.skill-dir{appearance:none;text-align:left;background:#fff;border:1px solid var(--line);border-radius:14px;padding:13px;cursor:pointer;color:var(--ink);display:flex;flex-direction:column;min-width:0}.skill-dir:hover,.skill-dir.on{border-color:var(--accent-strong);box-shadow:0 0 0 2px rgba(244,201,69,.18)}.skill-dir-shot{width:calc(100% + 26px);margin:-13px -13px 9px;border-radius:13px 13px 0 0;display:block;aspect-ratio:16/4.5;object-fit:cover;object-position:left center;border-bottom:1px solid var(--line)}.cfg-dir-shot{width:100%;border-radius:9px;display:block;margin-bottom:9px;cursor:zoom-in;border:1px solid var(--line)}.skill-dir small{font-size:10px;color:var(--accent-strong);font-weight:700}.skill-dir strong{font-size:12.5px;margin-top:3px}.cfg-upbox.extra{display:flex;align-items:center;gap:10px;flex-wrap:wrap;border:1px dashed var(--line);border-radius:12px;padding:11px 13px;margin-bottom:10px;background:var(--panel-2)}.cfg-upbox.extra>div:first-child{flex:1;min-width:180px}.cfg-upbox.extra b{font-size:12px;display:block}.cfg-upbox.extra small{font-size:10.5px;line-height:1.5;display:block}.skill-steps span.back{cursor:pointer;text-decoration:underline;text-decoration-style:dotted;text-underline-offset:3px}.skill-steps span.back:hover{color:var(--accent-strong)}.cfg-run-steps{margin:8px 0;border:1px solid var(--line);border-radius:12px;padding:10px 12px;background:var(--panel-2)}.cfg-run-steps>div{display:flex;align-items:center;gap:8px;padding:3px 0;font-size:12px;color:var(--ink-3)}.cfg-run-steps>div b{width:20px;font-size:10.5px;color:var(--muted)}.cfg-run-steps>div.done{color:var(--muted)}.cfg-run-steps>div.done b{color:var(--accent-strong)}.cfg-run-steps>div.on{color:var(--ink);font-weight:650}.cfg-run-steps>div.on b{color:var(--accent-strong)}.cfg-run-steps small{display:block;margin-top:6px;font-size:10.5px}.gen-cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(132px,1fr));gap:9px;margin-bottom:7px}.gen-cards figure{margin:0;border:1px solid var(--line);border-radius:10px;overflow:hidden;background:#fff}.gen-cards img{display:block;width:100%;aspect-ratio:3/4;object-fit:cover;cursor:zoom-in}.gen-cards figcaption{display:flex;align-items:center;justify-content:space-between;gap:6px;padding:5px 7px}.gen-cards figcaption b{font-size:10.5px;color:var(--muted)}.gen-cards figcaption .btn{font-size:10.5px;padding:2px 7px;min-height:0}.cfg-plan-title{display:block;margin-top:10px}.cfg-plan-title small{display:block;margin-bottom:3px;color:var(--muted);font-size:10px}.cfg-plan-title .input{width:100%}.cfg-plan-list{display:grid;gap:10px;margin-top:10px}.cfg-plan-screen{border:1px solid var(--line);border-radius:12px;padding:11px 13px;background:#fff}.cfg-plan-screen header{display:flex;align-items:center;justify-content:space-between;margin-bottom:7px}.cfg-plan-screen header b{font-size:11.5px;color:var(--accent-strong)}.cfg-plan-tools{display:flex;gap:5px}.cfg-plan-screen label{display:block;margin-bottom:6px}.cfg-plan-screen label small{font-size:10px;color:var(--muted);display:block;margin-bottom:3px}.cfg-plan-screen .input{width:100%;font-size:12px;min-height:0;padding:6px 9px}.cfg-plan-images{display:grid;grid-template-columns:repeat(auto-fill,minmax(120px,1fr));gap:8px;margin-top:8px}.cfg-plan-thumb{margin:0;border:1px solid var(--line);border-radius:9px;overflow:hidden;background:var(--panel-2)}.cfg-plan-thumb img{display:block;width:100%;height:86px;object-fit:cover}.cfg-plan-thumb figcaption{display:flex;align-items:center;justify-content:space-between;gap:5px;padding:5px 6px;font-size:10px;white-space:nowrap;overflow:hidden}.cfg-plan-thumb figcaption .btn{flex:none}.cfg-plan-image-add{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:8px}.cfg-plan-image-add small{color:var(--muted);font-size:10px}.cfg-dir-visual{margin-top:10px;border:1px solid var(--accent-strong);background:var(--panel-2);border-radius:12px;padding:11px 13px}.cfg-dir-visual b{font-size:11.5px;color:var(--accent-strong);display:block}.cfg-dir-visual p{font-size:11.5px;line-height:1.7;color:var(--ink);margin:5px 0 0}.skill-dir p{font-size:10.8px;line-height:1.55;color:var(--muted);margin:0;flex:1}.skill-dir em{font-style:normal;font-size:9.5px;color:var(--ink-3);margin-top:8px}
.cfg-plan-upload-status{flex-basis:100%;border-radius:8px;padding:6px 8px;font-size:10.5px;font-weight:650;background:#eef4ff;color:#2458a6}.cfg-plan-upload-status.success{background:#eaf7ef;color:#247443}.cfg-plan-upload-status.partial,.cfg-plan-upload-status.failed{background:#fff3e8;color:#a24b13}
.skill-output-preview{display:grid;grid-template-columns:1fr 1fr;gap:14px}.skill-output-preview>div{min-height:330px;border:1px solid var(--line);border-radius:14px;background:linear-gradient(145deg,var(--panel-2),#fff2be);display:flex;flex-direction:column;align-items:center;justify-content:center}.skill-output-preview>div i{font-size:60px;color:#b89b37;font-style:normal}.skill-output-preview>div span{font-size:12px;color:var(--muted);margin-top:10px}.skill-output-preview section{display:flex;flex-direction:column;gap:8px}.skill-output-preview label{border:1px solid var(--line);border-radius:11px;padding:10px}.skill-output-preview label small{color:var(--muted)}.skill-output-preview label p{font-size:11.5px;line-height:1.55;margin:4px 0 0}
@media(max-width:760px){.skill-flow{grid-template-columns:1fr}.skill-brief{position:static}.skill-form-grid,.skill-output-preview,.cfg-metric-grid,.cfg-source-grid{grid-template-columns:1fr}.skill-dir-grid{grid-template-columns:1fr}.skill-steps{justify-content:flex-start;overflow:auto}.skill-flow-actions{align-items:flex-end}}
.modal-head{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;border-bottom:1px solid var(--line);padding:17px 19px}
.modal-head>div{min-width:0}                    /* 不给收缩的话,长标题会把整个弹窗撑出屏幕(手机上横向滚动) */
.modal-head h2,.modal-head .sub{overflow-wrap:anywhere}
.modal-head h2{font-size:16px;font-weight:750}
.modal-head .sub{font-size:12px;color:var(--muted);margin-top:3px}
.modal-body{padding:19px}
.modal-foot{display:flex;gap:8px;flex-wrap:wrap;justify-content:flex-end;padding:0 19px 19px}
/* 二级弹窗(如历史生成,叠在一级弹窗之上) */
.modal2-overlay{z-index:45}
.btn.danger{background:#fbe9e7;border-color:#f0c4bc;color:#b83a31}
.btn.danger:hover{background:#f7ddd8}
/* 登录页 */
.login-root{position:fixed;inset:0;z-index:80;display:none;align-items:center;justify-content:center;padding:24px;overflow:auto;
  background:radial-gradient(900px 420px at 50% -10%, rgba(244,201,69,.30), transparent 62%), #efe9dc}
.login-root.on{display:flex}
.login-card{width:min(384px,100%);background:#fff;border-radius:22px;box-shadow:var(--shadow);padding:30px 28px;animation:modalIn .3s cubic-bezier(.2,.7,.3,1) both}
.login-brand{display:flex;gap:12px;align-items:center;margin-bottom:22px}
.login-brand .mark{width:44px;height:44px;border-radius:13px;background:var(--accent);color:#3a2f05;display:flex;align-items:center;justify-content:center;font-weight:700;letter-spacing:.5px}
.login-brand strong{display:block;font-size:18px;font-weight:600}
.login-brand span{display:block;color:var(--muted);font-size:12.5px;margin-top:2px}
.login-card .field{margin-bottom:14px}
.login-msg{min-height:18px;color:#b83a31;font-size:12.5px;margin:2px 0 12px}
.login-btn{width:100%;justify-content:center;padding:12px;font-size:14px}
.logout-btn{width:100%;justify-content:center;background:rgba(255,255,255,.08);border-color:rgba(255,255,255,.16);color:#cfcec4}
.logout-btn:hover{background:rgba(255,255,255,.14);color:#fff}
/* 品牌登录页(两栏:左品牌 + 右登录) */
.login-card2{width:min(880px,100%);display:grid;grid-template-columns:1.05fr .95fr;background:#fff;
  border-radius:26px;overflow:hidden;box-shadow:0 30px 72px rgba(60,50,20,.24);animation:modalIn .35s cubic-bezier(.2,.7,.3,1) both}
.lc-brand{position:relative;overflow:hidden;background:#1b1c16;color:#e9e8de;padding:36px 32px;display:flex;flex-direction:column;gap:24px;min-height:440px}
.lc-brand::before{content:"";position:absolute;inset:0;pointer-events:none;
  background:radial-gradient(520px 300px at 8% -12%, rgba(244,201,69,.26), transparent 60%),radial-gradient(420px 320px at 118% 120%, rgba(244,201,69,.12), transparent 60%)}
.lc-brand>*{position:relative}
.lc-top{display:flex;gap:11px;align-items:center}
.lc-top .mark{width:40px;height:40px;border-radius:12px;background:var(--accent);color:#3a2f05;display:flex;align-items:center;justify-content:center;font-weight:800;letter-spacing:.5px;flex:0 0 auto}
.lc-top strong{display:block;color:#fff;font-size:16px;font-weight:600;line-height:1.15}
.lc-top span{display:block;color:#9a998b;font-size:11.5px;margin-top:1px}
.lc-hero{margin-top:4px}
.lc-badge{display:inline-block;font-family:ui-monospace,Menlo,monospace;font-size:10.5px;letter-spacing:.22em;color:var(--accent);border:1px solid rgba(244,201,69,.42);padding:3px 10px;border-radius:999px;margin-bottom:14px}
.lc-hero h2{font-weight:300;font-size:30px;line-height:1.16;color:#fff;margin:0 0 12px;letter-spacing:.6px}
.lc-hero h2 em{font-style:normal;font-weight:600;color:var(--accent)}
.lc-hero p{color:#b1b0a4;font-size:13px;line-height:1.65;margin:0;max-width:34ch}
.lc-tags{display:flex;flex-wrap:wrap;gap:8px;margin-top:auto}
.lc-tags span{font-size:12px;padding:6px 12px;border-radius:999px;background:rgba(255,255,255,.055);border:1px solid rgba(255,255,255,.1);color:#d6d5ca;animation:tagIn .5s ease both}
.lc-tags span:nth-child(3n+1){background:rgba(244,201,69,.14);border-color:rgba(244,201,69,.34);color:#f2d98a}
.lc-form{padding:40px 36px;display:flex;flex-direction:column;justify-content:center}
.lc-form h3{font-size:22px;font-weight:600;margin:0}
.lc-sub{color:var(--muted);font-size:13px;margin:5px 0 22px}
.lc-form .field{margin-bottom:14px}
.lc-foot{margin-top:20px;color:#a29e90;font-size:11.5px}
@keyframes tagIn{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
@media(prefers-reduced-motion:reduce){.lc-tags span{animation:none}}
@media(max-width:720px){
  .login-card2{grid-template-columns:1fr;width:min(430px,100%)}
  .lc-brand{min-height:0;padding:26px 26px 22px;gap:16px}
  .lc-hero h2{font-size:24px}
  .lc-hero p{display:none}
  .lc-form{padding:26px}
}
/* 密码可见切换 */
.pw-wrap{position:relative}
.pw-wrap .input{padding-right:40px;width:100%}
.pw-eye{position:absolute;right:6px;top:50%;transform:translateY(-50%);border:0;background:transparent;cursor:pointer;font-size:16px;line-height:1;padding:4px;opacity:.7}
.pw-eye:hover{opacity:1}
/* 语音输入面板(叠在复盘弹窗之上) */
.voice-overlay{z-index:60;align-items:center}
.voice-langs{display:flex;gap:6px;margin-bottom:11px;justify-content:center}
.voice-lang{border:1px solid var(--line-2);background:#fff;border-radius:999px;padding:5px 13px;font-size:12.5px;cursor:pointer;color:var(--muted);transition:.15s}
.voice-lang.on{background:var(--dark);color:#fff;border-color:var(--dark)}
.voice-mic{width:100%;border:0;border-radius:16px;background:var(--dark);color:#fff;padding:16px;font-size:16px;font-weight:600;display:flex;align-items:center;justify-content:center;gap:9px;cursor:pointer;transition:background .2s;-webkit-tap-highlight-color:transparent}
.voice-mic:disabled{opacity:.5;cursor:not-allowed}
.voice-mic.recording{background:#b83a31;animation:voicePulse 1.3s ease-in-out infinite}
.voice-status{min-height:18px;color:#b83a31;font-size:12.5px;margin:10px 0;text-align:center;font-weight:600}
@keyframes voicePulse{0%,100%{box-shadow:0 0 0 0 rgba(184,58,49,.45)}50%{box-shadow:0 0 0 12px rgba(184,58,49,0)}}
.toast{
  position:fixed;right:24px;bottom:24px;max-width:360px;background:var(--dark);color:#fff;
  border-radius:14px;padding:12px 16px;box-shadow:var(--shadow);opacity:0;transform:translateY(12px);
  pointer-events:none;transition:.22s;z-index:50;font-weight:600;
}
.toast.show{opacity:1;transform:translateY(0)}
svg{display:block}
.bar-row{margin-bottom:10px}
.bar-top{display:flex;justify-content:space-between;gap:8px;font-size:12px;color:var(--muted);margin-bottom:3px}
.bar-top b{color:var(--ink);font-weight:700}
.field-row{
  display:grid;grid-template-columns:minmax(130px,1.2fr) 88px 90px 74px auto 30px;gap:8px;align-items:center;
  border:1px solid var(--line);border-radius:var(--r-sm);background:var(--panel-2);padding:9px;margin-bottom:8px;
}
.field-row .checks{display:flex;gap:10px;flex-wrap:wrap;font-size:12px;color:var(--muted)}
.field-row .checks label{display:flex;align-items:center;gap:4px;white-space:nowrap;cursor:pointer}
.field-row .checks input{accent-color:var(--accent-strong)}
.empty{border:1px dashed var(--line-2);border-radius:var(--r-md);padding:24px;text-align:center;color:var(--muted);font-size:12.5px}
.pre{white-space:pre-wrap;background:var(--panel-2);border:1px solid var(--line);border-radius:var(--r-md);padding:15px;font-size:12.5px;max-height:440px;overflow:auto;line-height:1.6}
.row-actions{display:flex;gap:6px;flex-wrap:wrap;align-items:center}
.chips{display:flex;gap:6px;flex-wrap:wrap}
.select.inline{width:auto;min-height:30px;padding:5px 8px;font-size:12px}
.muted{color:var(--muted)}
.mt{margin-top:16px}
/* AI 角色:能力勾选网格 */
.chk-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(148px,1fr));gap:5px 12px;max-height:180px;overflow:auto;padding:2px}
.chk{display:flex;align-items:center;gap:7px;font-size:13px;cursor:pointer;padding:3px 0;color:var(--ink)}
.chk input{width:15px;height:15px;flex:none;accent-color:var(--accent-strong)}
/* 弹出式下拉菜单(专家助力 / 技能选择)。
 * 原来写死 min-width:210~230px —— 手机上就那么窄,「报告厅音视频设计方案」
 * 这种名字必然折成两行,一折行整列就乱了。
 * 改成:**吃满可用宽度**(窄屏 92vw,宽屏封顶 400px),让绝大多数名字一行放得下。
 * left:0 + max-width 用 vw 而不是 %,是因为父容器本身可能很窄(按钮那一条),
 * 用 % 算出来还是窄的 —— 这个菜单是浮层,该按屏幕算不该按父元素算。 */
/* ⚠️ 宽度必须写**显式值**,不能用 width:max-content。
 * 试过 `width:max-content; max-width:min(92vw,400px)` —— 实测只撑到 240px(=min-width)。
 * 原因是行里的 .chk-name 带 min-width:0(那是让省略号生效的前提),
 * flex 子项能缩到 0,于是容器算 max-content 时**根本不计文字宽度**,
 * max-content 退化成 min-width。 */
.pop-menu{position:absolute;left:0;z-index:60;width:min(92vw,400px);
  overflow:auto;padding:9px;box-shadow:0 8px 28px rgba(0,0,0,.13)}

/* 菜单里的每一行:老板要「最好是一行」。
 * 原来名字和右边的「出Word」标签在同一个文字流里,名字一折行,
 * 单选钮被顶到两行中间、标签被推到第二行末尾,一列标签参差不齐。
 * 改成三段:钮 / 名字(单行,超长省略号)/ 标签钉最右不参与换行。
 * 省略号是兜底 —— 菜单放宽之后极少触发,真触发时 title 里有全名。 */
.chk-row{align-items:center}
.chk-row .chk-name{flex:1;min-width:0;line-height:1.5;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.chk-row .tag{flex:none;margin-left:2px}

/* ===== 动画 ===== */
@keyframes cardIn{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
@keyframes fadeDown{from{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:none}}
@keyframes overlayIn{from{opacity:0}to{opacity:1}}
@keyframes modalIn{from{opacity:0;transform:translateY(16px) scale(.98)}to{opacity:1;transform:none}}
@media(prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}

/* ===== 响应式 ===== */
@media(max-width:1120px){
  .app{grid-template-columns:1fr}
  .side{position:static;height:auto;flex-direction:row;flex-wrap:wrap;align-items:center;gap:8px;padding:12px 16px}
  .brand{padding:0 8px 0 0}
  .nav{flex-direction:row;flex-wrap:wrap;gap:6px;flex:1 1 100%;order:3;margin-top:8px}
  .nav button{white-space:nowrap;min-height:36px;flex:0 0 auto}
  .side-foot{margin:0 0 0 auto;flex-direction:row;padding:0}
  .side-foot .select{max-width:180px}
  .split,.split.equal,.detail-grid{grid-template-columns:1fr}
  /* 只把列数改成 1 是不够的:grid/flex 子项默认 min-width:auto,
     里面有一行不肯换行的东西就照样撑出屏幕(项目跟进页在手机上一直能左右拖,就是这个原因)。 */
  .split>*,.detail-grid>*{min-width:0}
  .kpis,.cards,.kb-grid,.status-board{grid-template-columns:repeat(2,minmax(0,1fr))}
  .head h1{font-size:28px}
}
@media(max-width:720px){
  /* ===== 手机:导航挪到底部 =====
     原来 10 个导航按钮在顶部换行铺开,吃掉 460px —— 超过半个屏幕。
     外勤销售打开先看到一整屏按钮,而他要的是「打开就能记一条」。
     底部固定栏是手机上唯一合理的形态:拇指够得到,而且不占内容空间。
     只放 4 个最常用的 + 一个「更多」,其余收进弹层。 */
  .content{padding:12px 14px 84px}   /* 底部留出导航条 + 安全区 */
  /* 页面导航与快捷录入位于弹窗遮罩(30)之下，不能拦截表单底部按钮。 */
  .side{position:fixed;left:0;right:0;bottom:0;top:auto;z-index:20;
    padding:6px 6px calc(6px + env(safe-area-inset-bottom));
    background:#141414;border-top:1px solid rgba(255,255,255,.08);
    flex-direction:row;flex-wrap:nowrap;gap:0;height:auto;overflow:visible}
  .side .brand,.side-foot{display:none}   /* 品牌和退出收进「更多」里 */
  .nav{flex-direction:row;flex-wrap:nowrap;gap:0;flex:1 1 auto;order:0;margin:0}
  .nav button{flex:1 1 0;min-width:0;min-height:48px;padding:5px 2px;font-size:11px;
    flex-direction:column;gap:2px;justify-content:center;white-space:nowrap;
    overflow:hidden;text-overflow:ellipsis;border-radius:10px}
  .nav button svg,.nav button .ico{width:18px;height:18px;flex:0 0 auto}
  /* 第 5 个之后的全部收起来 —— 「更多」那个按钮由 JS 插在最后,只有这里才显示它 */
  .nav button.nav-hide{display:none}
  .nav .nav-more{display:flex}
  /* ⚠️ .top-left 不要打开 —— 每个页面自己的 .head 已经在渲染同一个标题了,
     两个一起显示就是「企业大脑」连着出现两遍。压扁 .head 就够,少一个活动部件。 */
  .head{margin-bottom:14px}
  .head h1{font-size:21px;letter-spacing:-.4px;margin-bottom:4px}
  .head p{font-size:12.5px;line-height:1.5}
  .side .brand{flex:1 1 auto}
  .side-foot{margin:0;flex:0 0 auto}
  .logout-btn{width:auto;padding:8px 14px}
  .head{flex-direction:column}
  .head h1{font-size:24px}
  .kpis,.cards,.kb-grid,.form-grid,.metric-grid,.detail-grid,.date-range,.status-board{grid-template-columns:1fr}
  .field-row{grid-template-columns:1fr}
  /* 手机端:弹窗接近全屏、对话区更高、输入条留足拇指区 */
  .modal-overlay{padding:0;align-items:flex-end}
  .modal,.modal.wide,.modal.narrow{width:100%;max-height:94vh;overflow:auto;border-radius:20px 20px 0 0}
  .modal.wide .modal-body,.modal-body{padding:15px 14px}
  .modal-head{padding:14px 15px;position:sticky;top:0;background:#fff;z-index:2}
  /* 对话随整个弹窗滚动；限制高度却允许内容溢出会盖住下方修改输入框。 */
  .run-composer{border-radius:16px;padding:9px 10px}
  .run-composer .cbar{flex-wrap:wrap;gap:5px}
  .run-composer .cbar .btn{font-size:11.5px;padding:4px 9px;min-height:30px}
  .run-send{width:36px;height:36px}
  .grid,#outList .grid{grid-template-columns:1fr!important}
  .chips{gap:5px}
}

/* ===== 「记一条」悬浮按钮 =====
   外勤销售打开系统的第一件事就是记一条,不该让他点四层进去
   (项目页 → 找到那个项目 → 进详情 → 找到「填今日复盘」)。
   只在手机上、且这个人确实参与了「每天多条」的项目时才出现 —— 别的角色看不到它。 */
#quickRec{display:none}
@media(max-width:720px){
  #quickRec.on{display:block}
  #quickRec .fab{position:fixed;right:16px;bottom:calc(76px + env(safe-area-inset-bottom));z-index:20;
    min-height:52px;padding:0 20px;border-radius:26px;font-size:15px;font-weight:600;
    background:var(--gold,#e8b62c);color:#1a1a1a;border:0;
    box-shadow:0 6px 20px rgba(0,0,0,.28);display:inline-flex;align-items:center;gap:7px}
  #quickRec .fab:active{transform:scale(.97)}

  /* 会议纪要的行:窄屏让控件换行。
   * 实测 375 宽度下,待办第一行是 输入框 + 120px 的「挂给谁」下拉 + 删除按钮 并排,
   * 下拉是固定宽,把输入框挤到只剩 158px —— 一条待办写不了几个字就看不见了,
   * 而外勤和越南同事大量用手机改这些。
   * 换行之后:正文独占一行看得全,下拉和删除按钮排第二行。 */
  .mtRow > div[style*="display:flex"]{flex-wrap:wrap}
  /* 这几个输入框在 HTML 里带着内联 style="flex:1",内联优先级高于类规则 ——
   * 不加 !important 的话这条完全不生效(第一版就是这样,量出来还是 158px)。 */
  .mtRow .input[class*="mtTodoWhat"],
  .mtRow .input[class*="mtSupWhat"],
  .mtRow .input[class*="mtKpPoint"]{flex:1 1 100%!important;min-width:0}
  .mtRow .select{flex:1 1 auto;min-width:120px}
  /* 日期和「做到什么程度」两格在手机上也各占一行,不然一样被挤窄 */
  .mtRow input[type="date"],
  .mtRow .input[placeholder*="做到什么程度"],
  .mtRow .input[placeholder*="交出什么"]{flex:1 1 100%;width:auto!important;min-width:0}
}

/* ===== 空间预警横幅(上游不可用 / 积分快用完 / 服务快到期)===== */
.alert-bar{display:flex;align-items:flex-start;gap:10px;padding:11px 14px;border-radius:10px;
  border:1px solid var(--line-2);background:var(--panel-2);margin:0 0 12px}
.alert-bar+.alert-bar{margin-top:-4px}
.alert-bar.danger{border-color:#f0c2c2;background:#fdeeee}
.alert-bar.warn{border-color:#efdca8;background:#fdf6e0}
.alert-ico{font-size:15px;line-height:1.35;flex:none}
.alert-body{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.alert-body b{font-size:13.5px;color:var(--ink)}
.alert-body span{font-size:12.5px;color:var(--muted);line-height:1.5}
.alert-bar .btn{flex:none;align-self:center}
@media(max-width:820px){
  .alert-bar{flex-wrap:wrap}
  .alert-bar .btn{width:100%;margin-top:6px}
}

/* 发送键切成停止键时的样子:同一个位置、同一个圆,只换图标和颜色 ——
   老板要的是 Claude 那种"一个键两态",不是在旁边再加一个按钮。 */
.run-send.stopping{background:#c0392b}
.run-send.stopping:hover{transform:scale(1.06)}
/* 排队中的那几句:样式比已发出的淡一档,让人一眼看出"还没轮到" */
.q-pending{opacity:.55;border-style:dashed !important}

/* 项目健康度挪到表格上面之后要横排:占整行,但高度很矮,不把表格挤窄。
 * (竖排的话它自己就占掉大半屏,而它只是三个数字的注脚。) */
.donut-row{display:flex;align-items:center;gap:26px;flex-wrap:wrap}
.donut-row .legend{display:flex;gap:18px;flex-wrap:wrap;align-items:center}
.donut-row .legend > div{margin-top:0 !important}
@media (max-width:600px){.donut-row{gap:16px}.donut-row .legend{gap:10px 14px}}

/* Editable PPT: content confirmation, then design confirmation. */
.ppt-workspace{grid-template-columns:220px minmax(0,1fr)}
.ppt-workspace .skill-steps{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:8px;margin-bottom:18px}
.ppt-step{display:flex;align-items:center;gap:8px;padding:10px 8px;border:1px solid var(--line);border-radius:10px;background:var(--panel-2);color:var(--muted);font:inherit;text-align:left;min-height:44px}
.ppt-step b{display:grid;place-items:center;flex:none;width:24px;height:24px;border-radius:50%;background:#fff;font-size:12px}
.ppt-step span{font-size:12px;font-weight:650}.ppt-step.on{border-color:var(--accent-strong);color:var(--ink);background:#fff}.ppt-step.done{color:var(--ink-3)}.ppt-step[data-step]{cursor:pointer}.ppt-step:disabled{opacity:1;cursor:default}
.ppt-workspace button:focus-visible,.ppt-workspace .cfg-plan-screen:focus-visible,.ppt-design-detail:focus-visible{outline:3px solid var(--accent-strong);outline-offset:3px}
.ppt-workspace .skill-card-head h3{font-size:19px;line-height:1.45}.ppt-workspace .skill-card-head p{font-size:13px;line-height:1.65}
.ppt-workspace .cfg-plan-screen{padding:18px;scroll-margin-block:18px}.ppt-workspace .cfg-plan-screen label small,.ppt-workspace .cfg-plan-title small{font-size:12px}
.ppt-workspace .cfg-plan-screen .input{font-size:14px;line-height:1.65;padding:10px 12px}.ppt-workspace .cfg-plan-screen textarea{min-height:120px;resize:vertical}
.ppt-workspace .cfg-plan-screen header{gap:12px;flex-wrap:wrap}.ppt-workspace .cfg-plan-screen header b{font-size:14px}.ppt-workspace .cfg-plan-tools{flex-wrap:wrap}.ppt-workspace .cfg-plan-tools .btn,.ppt-workspace .cfg-plan-image-add .btn{min-height:40px}
.ppt-workspace .cfg-plan-thumb img{object-fit:contain;background:var(--panel-2);height:112px}.ppt-workspace .cfg-plan-image-add small{font-size:12px;line-height:1.5}
.ppt-page-nav{margin-top:18px;padding:14px;border:1px solid var(--line);border-radius:12px;background:var(--panel-2)}.ppt-page-nav>b{font-size:13px}.ppt-page-nav>div{display:flex;flex-wrap:wrap;gap:6px;margin:9px 0}.ppt-page-nav .btn{min-width:38px;min-height:38px}.ppt-page-nav>small{font-size:12px;color:var(--muted)}
.ppt-split-panel>button[data-psplit-at]{display:flex;flex-direction:column;align-items:flex-start;text-align:left;gap:4px;width:100%;white-space:normal;margin:8px 0;padding:12px}.ppt-split-panel>button span{font-size:13px;line-height:1.6;overflow-wrap:anywhere}
.ppt-design-summary{display:grid;grid-template-columns:1fr 1fr;gap:16px;border:1px solid var(--line);border-radius:12px;padding:18px;background:var(--panel-2);margin:18px 0}.ppt-design-summary small{display:block;font-size:12px;color:var(--muted);margin-bottom:7px}.ppt-design-summary strong{font-size:16px;line-height:1.5}.ppt-design-summary p{font-size:12px;color:var(--ink-3);margin:7px 0 0}
.ppt-design-detail{border:1px solid var(--accent-strong);border-radius:12px;padding:18px;margin:16px 0;scroll-margin-top:12px}.ppt-design-detail h4{font-size:16px;margin:0 0 12px}.ppt-design-detail p{font-size:13px;line-height:1.8;overflow-wrap:anywhere}.ppt-design-detail figure{margin:0}.ppt-design-detail img{display:block;width:100%;height:auto;border-radius:8px;border:1px solid var(--line)}.ppt-design-detail figcaption{font-size:12px;color:var(--muted);line-height:1.5;margin-top:8px}
.ppt-gallery-heading{display:flex;align-items:center;justify-content:space-between;gap:12px;margin:24px 0 12px;flex-wrap:wrap}.ppt-gallery-heading h4{font-size:16px;margin:0}.ppt-gallery-heading span{font-size:12px;color:var(--muted)}
.ppt-template-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:14px}.ppt-template-grid .skill-dir{padding:15px;gap:5px}.ppt-template-grid .skill-dir-shot{width:calc(100% + 30px);margin:-15px -15px 9px;aspect-ratio:16/9;object-fit:contain}.ppt-template-grid .skill-dir strong{font-size:15px}.ppt-template-grid .skill-dir p{font-size:12px;line-height:1.65}.ppt-template-grid .skill-dir em{font-size:12px}.ppt-selection-label{display:block;font-size:12px;font-weight:650;border-top:1px solid var(--line);padding-top:10px;margin-top:8px;color:var(--ink-3)}.ppt-template-grid .on .ppt-selection-label{color:var(--accent-strong)}
.ppt-action-bar{position:sticky;bottom:0;z-index:2;background:#fff;padding:14px 0;flex-wrap:wrap;box-shadow:0 -8px 16px rgba(0,0,0,.03)}.ppt-action-bar small,.ppt-action-bar>span{font-size:12px;line-height:1.5;color:var(--ink-3)}.ppt-action-bar .btn{min-height:44px}.ppt-template-stage .ppt-action-bar{top:0;bottom:auto;border-bottom:1px solid var(--line);box-shadow:0 5px 10px rgba(0,0,0,.03)}
.ppt-generation{text-align:center;padding:34px 22px}.ppt-generation h3{font-size:17px;line-height:1.6}.ppt-generation p{font-size:13px;line-height:1.7;color:var(--ink-3)}.ppt-pending{display:inline-block;width:28px;height:28px;border:3px solid var(--line);border-top-color:var(--accent-strong);border-radius:50%;animation:ppt-pending 1s linear infinite}
@keyframes ppt-pending{to{transform:rotate(360deg)}}
@media(prefers-reduced-motion:reduce){.ppt-pending{animation:none}}
@media(max-width:900px){.ppt-workspace{grid-template-columns:1fr}.ppt-workspace .skill-brief{position:static}.ppt-workspace .skill-steps{gap:4px}.ppt-step{gap:5px;padding:8px 4px}.ppt-step span{font-size:11px}}
@media(max-width:560px){.ppt-template-grid,.ppt-design-summary{grid-template-columns:1fr}.ppt-workspace .skill-flow-card{padding:14px}.ppt-workspace .cfg-plan-screen{padding:13px}.ppt-step{flex-direction:column;text-align:center}.ppt-action-bar>.btn.green{width:100%}.ppt-action-bar{gap:8px}.ppt-workspace .cfg-plan-tools{gap:6px}}

.ppt-template-stage{scroll-margin-top:80px}
