/* 美筑空间 mzkj — 现代 SaaS 风格（Linear/Notion 质感） */
:root {
  --bg: #f7f8fa;
  --surface: #ffffff;
  --border: #e8eaed;
  --border-soft: #f0f1f3;
  --text: #1a1d21;
  --text-2: #5f6672;
  --text-3: #9aa1ad;
  --primary: #6366f1;
  --primary-soft: #eef0ff;
  --green: #10b981;
  --green-soft: #ecfdf5;
  --red: #ef4444;
  --red-soft: #fef2f2;
  --amber: #f59e0b;
  --amber-soft: #fffbeb;
  --blue: #3b82f6;
  --blue-soft: #eff6ff;
  --purple: #8b5cf6;
  --purple-soft: #f5f3ff;
  --cyan: #06b6d4;
  --cyan-soft: #ecfeff;
  --pink: #ec4899;
  --pink-soft: #fdf2f8;
  --shadow-sm: 0 1px 2px rgba(16,24,40,.05);
  --shadow-md: 0 4px 16px rgba(16,24,40,.08);
  --shadow-lg: 0 12px 32px rgba(16,24,40,.12);
  --radius: 12px;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: -apple-system, "PingFang SC", "Microsoft YaHei", "Segoe UI", sans-serif; background: var(--bg); color: var(--text); -webkit-font-smoothing: antialiased; }
.page { min-height: 100vh; }

/* ========== 登录页 ========== */
/* D268：100dvh 适配移动端地址栏/键盘（原 100vh 在键盘弹起时视口变小内容偏上）；超高时可滚动保证卡片始终可见居中 */
#login-page { display: flex; align-items: center; justify-content: center; background: radial-gradient(circle at 30% 20%, #818cf8 0%, #6366f1 40%, #4f46e5 100%); min-height: 100vh; min-height: 100dvh; overflow-y: auto; padding: 24px 16px; }
.login-card { background: var(--surface); padding: 44px 36px; border-radius: 20px; width: 360px; max-width: 92vw; box-shadow: var(--shadow-lg); text-align: center; }
.login-card h1 { font-size: 28px; margin-bottom: 6px; background: linear-gradient(135deg, #6366f1, #8b5cf6); -webkit-background-clip: text; -webkit-text-fill-color: transparent; }
.login-card .subtitle { font-size: 13px; color: var(--text-3); margin-bottom: 32px; }
.login-card input { width: 100%; padding: 13px 16px; margin-bottom: 14px; border: 1.5px solid var(--border); border-radius: 10px; font-size: 15px; outline: none; transition: border .15s; }
.login-card input:focus { border-color: var(--primary); }
.hint { font-size: 12px; color: var(--text-3); margin-top: 16px; }
.err { color: var(--red); font-size: 13px; min-height: 18px; }

/* ========== 按钮 ========== */
.btn-primary { background: var(--primary); color: #fff; border: none; padding: 13px 20px; border-radius: 10px; font-size: 15px; font-weight: 600; cursor: pointer; width: 100%; transition: all .15s; box-shadow: 0 2px 8px rgba(99,102,241,.3); }
.btn-primary:hover { background: #5558e6; transform: translateY(-1px); box-shadow: 0 4px 12px rgba(99,102,241,.4); }
.btn-ghost { background: var(--surface); border: 1.5px solid var(--border); padding: 8px 14px; border-radius: 9px; cursor: pointer; font-size: 14px; color: var(--text-2); transition: all .15s; }
.btn-ghost:hover { border-color: var(--primary); color: var(--primary); }
/* D36h396（老板 2026-10-15「两个展开和收起按钮不和谐，不需要阴影和立体感觉，和其他按钮统一风格」）：
   `.btn-mini` 全站从来没有定义过（JS 里用了 40 多处）⇒ 它一直吃的是**浏览器默认按钮样式**：
   实测 底 rgb(240,240,240) + 边 2px outset rgb(0,0,0) + 字 13.33px/400（上一轮 pill.css 又把圆角套成 999px
   ⇒ 圆头 + 立体边框并存，跟别的按钮不一路）。
   这里对齐本系统既有的「展开/收起」按钮规范 app.css 里 `.project-fold-bar button`：白底 + 1px 浅边框 + 无阴影 + 药丸头。
   ★放在 D36h341 那个「统一高度」块之前、且不带 !important —— 避免撞 test/settings-uniform-height-guard 的 ⑧-1b。
   ▲注：本注释**故意不写那一块的完整名字**（`阶段D36h` 开头那串）—— 那条护栏是用 indexOf 定位它的，
     这里一提就会把护栏锚点提前到本注释、害它把整份文件的 !important 都算进去（D36h396 实测因此撞红两条护栏）。 */
.btn-mini { -webkit-appearance: none; appearance: none; background: var(--surface); border: 1px solid var(--border); color: var(--text); border-radius: 999px; padding: 6px 14px; font-size: 12px; font-weight: 600; line-height: 1.5; cursor: pointer; box-shadow: none; transition: all .15s; }
.btn-mini:hover { border-color: var(--primary); color: var(--primary); }
.btn-mini:disabled { opacity: .55; cursor: default; }

/* ========== 顶栏 ========== */
/* D331j：去掉 backdrop-filter + 提高 z-index——iOS Safari sticky+backdrop-filter 有已知渲染坑（停留后按钮点击失效、刷新恢复）；实色底防此问题 */
.topbar { background: rgba(255,255,255,.98); padding: 14px 28px; display: flex; align-items: center; gap: 24px; border-bottom: 1px solid var(--border-soft); position: sticky; top: 0; z-index: 80; touch-action: manipulation; }
.topbar button { touch-action: manipulation; }
.brand { font-size: 19px; font-weight: 700; background: linear-gradient(135deg, #6366f1, #8b5cf6); -webkit-background-clip: text; -webkit-text-fill-color: transparent; }
.nav { display: flex; gap: 6px; background: var(--bg); padding: 4px; border-radius: 10px; }
.nav-btn { background: none; border: none; padding: 8px 18px; border-radius: 7px; cursor: pointer; font-size: 14px; color: var(--text-2); font-weight: 500; transition: all .15s; }
.nav-btn.active { background: var(--surface); color: var(--primary); font-weight: 600; box-shadow: var(--shadow-sm); }
.user-info { margin-left: auto; font-size: 13px; color: var(--text-3); display: flex; align-items: center; gap: 10px; }
.user-info a { color: var(--text-2); text-decoration: none; padding: 6px 12px; border-radius: 7px; transition: all .15s; }
.user-info a:hover { background: var(--red-soft); color: var(--red); }

/* ========== 视图 ========== */
.view { padding: 28px; max-width: 1200px; margin: 0 auto; }
.view-header { display: flex; align-items: center; gap: 16px; margin-bottom: 24px; }
.view-header h2 { font-size: 22px; font-weight: 700; flex: 1; }

/* ========== 项目卡片网格 ========== */
.card-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 18px; }
.project-card { background: var(--surface); border-radius: var(--radius); padding: 22px; cursor: pointer; border: 1px solid var(--border); transition: all .2s; box-shadow: var(--shadow-sm); }
.project-card:hover { box-shadow: var(--shadow-md); transform: translateY(-3px); border-color: #d8dae0; }
.project-card .pname { font-size: 17px; font-weight: 600; margin-bottom: 8px; }
.project-card .pmeta { font-size: 13px; color: var(--text-3); margin-bottom: 16px; display: flex; gap: 8px; align-items: center; }
.project-card .pmeta .tag { background: var(--primary-soft); color: var(--primary); padding: 2px 8px; border-radius: 5px; font-size: 11px; font-weight: 500; }
.progress-bar { height: 7px; background: var(--border-soft); border-radius: 4px; overflow: hidden; }
.progress-bar > div { height: 100%; background: linear-gradient(90deg, #6366f1, #8b5cf6); border-radius: 4px; transition: width .4s; }
.progress-text { font-size: 12px; color: var(--text-3); margin-top: 8px; display: flex; justify-content: space-between; }

/* ========== 时间线（核心，现代设计） ========== */
.timeline-compose { background: var(--surface); border-radius: var(--radius); padding: 8px; display: flex; gap: 8px; margin-bottom: 24px; border: 1px solid var(--border); box-shadow: var(--shadow-sm); }
.timeline-compose input { flex: 1; padding: 12px 14px; border: none; border-radius: 8px; font-size: 14px; outline: none; background: transparent; }
.timeline-compose .btn-primary { width: auto; padding: 10px 22px; }

/* 业务操作快捷入口 */
.quick-actions { display: flex; gap: 8px; margin-bottom: 24px; flex-wrap: wrap; }
.quick-btn { background: var(--surface); border: 1px solid var(--border); padding: 9px 16px; border-radius: 9px; cursor: pointer; font-size: 13px; color: var(--text-2); display: flex; align-items: center; gap: 6px; transition: all .15s; }
.quick-btn:hover { border-color: var(--primary); color: var(--primary); background: var(--primary-soft); }
.quick-btn .ico { font-size: 15px; }
/* AI 渐变按钮（装修管家等 grad:true 项）：纯渐变底白字药丸，无阴影。
   !important 覆盖后置的 .quick-menu .quick-btn{background:var(--bg)}（同特异性后者胜，必须提权） */
.quick-btn.grad-ai { background: linear-gradient(135deg, #f0b43d, #d99b16) !important; border: none !important; color: #fff !important; border-radius: 999px; font-weight: 600; }
.quick-btn.grad-ai:hover { background: linear-gradient(135deg, #e3a52b, #b97c05) !important; color: #fff !important; }

/* 时间线容器 + 左侧轴线 */
.timeline { position: relative; padding-left: 28px; }
.timeline::before { content: ''; position: absolute; left: 11px; top: 8px; bottom: 8px; width: 2px; background: linear-gradient(180deg, var(--border) 0%, var(--border-soft) 100%); border-radius: 2px; }

.event-card { position: relative; background: var(--surface); border-radius: var(--radius); padding: 16px 18px; border: 1px solid var(--border); margin-bottom: 14px; transition: all .18s; box-shadow: var(--shadow-sm); }
.event-card:hover { box-shadow: var(--shadow-md); border-color: #d8dae0; }
/* 时间轴节点 */
.event-card::before { content: ''; position: absolute; left: -23px; top: 20px; width: 12px; height: 12px; border-radius: 50%; background: var(--surface); border: 2.5px solid var(--ev-color, var(--primary)); box-shadow: 0 0 0 3px var(--bg); }

.event-head { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.event-icon { width: 30px; height: 30px; border-radius: 8px; display: flex; align-items: center; justify-content: center; font-size: 15px; background: var(--ev-bg, var(--primary-soft)); flex-shrink: 0; }
.event-actor { font-weight: 600; color: var(--text); font-size: 14px; }
.event-type-badge { background: var(--ev-bg, var(--primary-soft)); color: var(--ev-color, var(--primary)); padding: 3px 9px; border-radius: 6px; font-size: 11px; font-weight: 600; }
.event-time { color: var(--text-3); margin-left: auto; font-size: 12px; }
.event-body { font-size: 14px; color: var(--text-2); line-height: 1.65; padding-left: 40px; }
.event-body .ev-title { font-weight: 600; color: var(--text); font-size: 15px; margin-bottom: 4px; }
.event-body .ev-row { display: flex; gap: 16px; flex-wrap: wrap; margin-top: 6px; font-size: 13px; }
.event-body .ev-row .k { color: var(--text-3); }
.event-body .ev-row .v { color: var(--text); font-weight: 500; }
.event-body .ev-amount { font-size: 18px; font-weight: 700; }
.event-body .ev-amount.in { color: var(--green); }
.event-body .ev-amount.out { color: var(--red); }

/* 状态徽章 */
.badge { font-size: 11px; padding: 3px 9px; border-radius: 6px; font-weight: 600; display: inline-block; }
.badge.pending { background: var(--amber-soft); color: #b45309; }
.badge.approved, .badge.confirmed, .badge.signed, .badge.completed, .badge.received, .badge.paid { background: var(--green-soft); color: #047857; }
.badge.rejected { background: var(--red-soft); color: #b91c1c; }
.badge.partial { background: var(--blue-soft); color: #1d4ed8; }

/* 审批按钮 */
.event-actions { margin-top: 12px; padding-left: 40px; display: flex; gap: 8px; }
.event-actions button { border: none; padding: 8px 18px; border-radius: 8px; font-size: 13px; font-weight: 600; cursor: pointer; transition: all .15s; display: flex; align-items: center; gap: 5px; }
.event-actions button.confirm { background: var(--green); color: #fff; box-shadow: 0 2px 6px rgba(16,185,129,.3); }
.event-actions button.confirm:hover { background: #059669; transform: translateY(-1px); }
.event-actions button.reject { background: var(--surface); color: var(--red); border: 1.5px solid #fecaca; }
.event-actions button.reject:hover { background: var(--red-soft); }
.event-actions button.sign, .event-actions button.complete, .event-actions button.approve { background: var(--primary); color: #fff; box-shadow: 0 2px 6px rgba(99,102,241,.3); }
.event-actions button.sign:hover, .event-actions button.complete:hover, .event-actions button.approve:hover { background: #5558e6; transform: translateY(-1px); }

.event-ops { margin-top: 10px; padding-left: 40px; font-size: 12px; color: var(--text-3); display: flex; align-items: center; gap: 6px; }
.event-ops::before { content: '✓'; color: var(--green); font-weight: 700; }

/* 系统消息（弱化） */
.event-card.ev-system { background: transparent; border: none; box-shadow: none; padding: 8px 0; }
.event-card.ev-system::before { width: 8px; height: 8px; left: -21px; border-width: 2px; border-color: var(--text-3); }
.event-card.ev-system .event-body { padding-left: 0; font-size: 13px; color: var(--text-3); text-align: center; }
.event-card.ev-text { border-left: 3px solid var(--primary); }

/* ========== 财务 ========== */
.finance-mini { font-size: 13px; color: var(--text-2); display: flex; gap: 14px; align-items: center; }
.finance-mini .in { color: var(--green); font-weight: 600; } .finance-mini .out { color: var(--red); font-weight: 600; }
.stats-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 16px; margin-bottom: 24px; }
.stat-card { background: var(--surface); border-radius: var(--radius); padding: 20px; border: 1px solid var(--border); box-shadow: var(--shadow-sm); }
.stat-card .label { font-size: 13px; color: var(--text-3); margin-bottom: 8px; display: flex; align-items: center; gap: 6px; }
.stat-card .value { font-size: 24px; font-weight: 700; }
.stat-card .value.in { color: var(--green); } .stat-card .value.out { color: var(--red); } .stat-card .value.profit { color: var(--primary); }
.stat-card .sub { font-size: 11.5px; color: var(--text-3); margin-top: 5px; font-weight: 600; line-height: 1.5; }
.tx-list { display: flex; flex-direction: column; gap: 10px; }
.tx-item { background: var(--surface); border-radius: var(--radius); padding: 16px 18px; border: 1px solid var(--border); display: flex; align-items: center; gap: 14px; transition: all .15s; box-shadow: var(--shadow-sm); }
.tx-item:hover { box-shadow: var(--shadow-md); }
.tx-item .tx-cat { font-weight: 600; font-size: 14px; }
.tx-item .tx-meta { font-size: 12px; color: var(--text-3); margin-top: 3px; }
.tx-item .tx-amount { margin-left: auto; font-size: 17px; font-weight: 700; }
.tx-item .tx-amount.in { color: var(--green); } .tx-item .tx-amount.out { color: var(--red); }

.empty { text-align: center; color: var(--text-3); padding: 60px 20px; font-size: 14px; }
.empty .big { font-size: 40px; margin-bottom: 12px; }

/* 弹窗（替代 prompt） */
.modal-mask { position: fixed; inset: 0; background: rgba(16,24,40,.45); backdrop-filter: blur(4px); display: flex; align-items: center; justify-content: center; z-index: 100; }
/* D36ahb：后台工作台 z-index:2000 会压住普通弹窗(100)——凡在工作台之后追加的弹窗/预览遮罩提到 2200 之上 */
.workbench-root ~ .modal-mask,
.workbench-root ~ .img-preview-mask { z-index: 2200 !important; }
/* D36h423/D36h457：操作区发起的设计弹窗必须压在项目总览、工作台之上。
   D36h457 起把层级固定成一套「越后打开越靠上」的次序：
   设计总览浮层(100180) < 设计功能/确认弹窗(100200) < 图片查看器(100300)
   < 上传进度(100400) < 提示 toast(100500)。 */
body .modal-mask.dc-top { z-index: 100200 !important; }
#quick-menu-mask.dc-top { z-index: 100070 !important; }
body .dc-overlay { z-index: 100180 !important; }
body .modal-mask.dc-top ~ .img-preview-mask,
body .modal-mask.dc-top ~ .pz-mask,
body .dc-overlay ~ .img-preview-mask,
body .dc-overlay ~ .pz-mask { z-index: 100300 !important; }
html #dsh-upload-mask { z-index: 100400 !important; }
#d289-toast { z-index: 100500 !important; }
.modal { background: var(--surface); border-radius: 16px; padding: 28px; width: 420px; max-width: 92vw; box-shadow: var(--shadow-lg); }
.modal h3 { font-size: 18px; margin-bottom: 18px; }
.modal label { display: block; font-size: 13px; color: var(--text-2); margin-bottom: 6px; margin-top: 14px; font-weight: 500; }
.modal input, .modal select, .modal textarea { width: 100%; padding: 11px 13px; border: 1.5px solid var(--border); border-radius: 9px; font-size: 14px; outline: none; font-family: inherit; }
.modal input:focus, .modal select:focus, .modal textarea:focus { border-color: var(--primary); }
.modal-actions { display: flex; gap: 10px; margin-top: 22px; justify-content: flex-end; }
.modal-actions button { padding: 10px 22px; border-radius: 9px; font-size: 14px; font-weight: 600; cursor: pointer; border: none; }
.modal-actions .cancel { background: var(--bg); color: var(--text-2); }
.modal-actions .ok { background: var(--primary); color: #fff; }

/* ========== 打卡卡片（照片 + GPS） ========== */
.checkin-card { }
.checkin-photos { display: flex; gap: 8px; margin: 10px 0; flex-wrap: wrap; }
.checkin-photos img { width: 88px; height: 88px; object-fit: cover; border-radius: 10px; border: 1px solid var(--border); cursor: pointer; transition: transform .15s; }
.checkin-photos img:hover { transform: scale(1.05); }
.checkin-photo-add { width: 88px; height: 88px; border: 2px dashed var(--border); border-radius: 10px; display: flex; align-items: center; justify-content: center; color: var(--text-3); font-size: 24px; cursor: pointer; }
.checkin-photo-add:hover { border-color: var(--primary); color: var(--primary); }
.gps-row { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-3); margin-top: 8px; padding: 7px 10px; background: var(--bg); border-radius: 8px; }
.gps-row .pin { color: var(--red); font-size: 14px; }
.gps-coord { font-family: "SF Mono", monospace; font-size: 11px; color: var(--text-3); }
.checkin-time-big { font-size: 22px; font-weight: 700; color: var(--text); letter-spacing: 1px; }
.checkin-type-tag { display: inline-block; padding: 3px 10px; border-radius: 6px; font-size: 12px; font-weight: 600; }
.checkin-type-tag.in { background: var(--green-soft); color: #047857; }
.checkin-type-tag.out { background: var(--amber-soft); color: #b45309; }

/* ========== 底部功能切换栏 ========== */
.bottom-tabs { display: flex; gap: 6px; padding: 10px 0 4px; border-top: 1px solid var(--border-soft); margin-top: 16px; }
.bottom-tab { flex: 1; padding: 10px 8px; border: 1px solid var(--border); border-radius: 10px; background: var(--surface); color: var(--text-2); font-size: 13px; font-weight: 500; cursor: pointer; text-align: center; transition: all .15s; display: flex; flex-direction: column; align-items: center; gap: 3px; }
.bottom-tab .tab-ico { font-size: 16px; }
.bottom-tab.active, .bottom-tab:hover { background: var(--primary-soft); color: var(--primary); border-color: var(--primary); }

/* 工作台面板 */
.workbench-panel { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 20px; margin-top: 16px; box-shadow: var(--shadow-sm); }
.workbench-panel h4 { font-size: 15px; margin-bottom: 14px; display: flex; align-items: center; gap: 8px; }
.wb-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 12px; }
.wb-card { background: var(--bg); border-radius: 10px; padding: 16px 10px; text-align: center; cursor: pointer; transition: all .15s; border: 1px solid transparent; }
.wb-card:hover { border-color: var(--primary); background: var(--primary-soft); transform: translateY(-2px); }
.wb-card .wb-ico { font-size: 26px; margin-bottom: 6px; }
.wb-card .wb-label { font-size: 12px; color: var(--text-2); font-weight: 500; }
.wb-stat-row { display: flex; justify-content: space-between; padding: 11px 0; border-bottom: 1px solid var(--border-soft); font-size: 13px; }
.wb-stat-row:last-child { border-bottom: none; }
.wb-stat-row .k { color: var(--text-3); }
.wb-stat-row .v { font-weight: 600; color: var(--text); }

/* 待办面板 */
.todo-panel { margin-top: 16px; }
.todo-item { background: var(--surface); border: 1px solid var(--border); border-left: 3px solid var(--amber); border-radius: 10px; padding: 14px 16px; margin-bottom: 10px; display: flex; flex-direction: column; align-items: stretch; gap: 10px; box-shadow: var(--shadow-sm); }
.todo-item .todo-ico { font-size: 20px; }
.todo-item .todo-info { flex: 1; }
.todo-item .todo-title { font-size: 14px; font-weight: 600; line-height: 1.5; }
.todo-item .todo-meta { font-size: 12px; color: var(--text-3); margin-top: 3px; }
/* D102：待办按钮行换到信息下方（上下排布，信息好读） */
.todo-item > [data-action], .todo-item > div[style*="flex"] { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 2px; }
.todo-item .todo-actions { display: flex; gap: 6px; flex-wrap: wrap; padding-top: 8px; border-top: 1px dashed var(--border-soft); }

/* ========== 左侧项目抽屉（移动端） ========== */
.drawer-fab { display: none; position: fixed; left: 0; top: 76px; width: 30px; height: 60px; border-radius: 0 10px 10px 0; background: var(--primary); color: #fff; border: none; box-shadow: var(--shadow-md); align-items: center; justify-content: center; font-size: 14px; z-index: 90; cursor: pointer; writing-mode: vertical-rl; }
.drawer-overlay { display: none; position: fixed; inset: 0; background: rgba(16,24,40,.4); z-index: 95; }

/* ========== 图片预览大图 ========== */
.img-preview-mask { position: fixed; inset: 0; background: rgba(0,0,0,.9); display: flex; align-items: center; justify-content: center; z-index: 200; cursor: zoom-out; }
.img-preview-mask img { max-width: 95vw; max-height: 95vh; border-radius: 8px; }

/* ========== 移动端完整适配 ========== */
@media (max-width: 768px) {
  .view { padding: 16px; }
  .topbar { padding: 12px 16px; gap: 12px; }
  .brand { font-size: 17px; }
  .nav-btn { padding: 7px 12px; font-size: 13px; }
  .user-info span#user-name { display: none; }
  .card-grid { grid-template-columns: 1fr; gap: 12px; }
  .timeline { padding-left: 22px; }
  .event-card::before { left: -17px; width: 10px; height: 10px; }
  .event-body, .event-actions, .event-ops { padding-left: 0; }
  .event-body .ev-amount { font-size: 16px; }
  .quick-actions { gap: 6px; }
  .quick-btn { padding: 8px 12px; font-size: 12px; }
  .stats-row { grid-template-columns: repeat(2, 1fr); gap: 10px; }
  .stat-card { padding: 14px; }
  .stat-card .value { font-size: 19px; }
  .modal { padding: 22px; }
  /* 移动端抽屉 */
  .drawer-fab { display: flex; }
  .view-header h2 { font-size: 18px; }
  .timeline-compose input { font-size: 16px; }
  .checkin-photos img { width: 72px; height: 72px; }
}

/* ========== 微交互与细节打磨 ========== */
.event-card { animation: fadeUp .3s ease; }
@keyframes fadeUp { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }
.project-card, .tx-item, .stat-card, .wb-card { animation: fadeUp .3s ease; }
/* 滚动条美化 */
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: #d8dae0; border-radius: 4px; }
::-webkit-scrollbar-thumb:hover { background: #c0c3ca; }
/* 选中态 */
::selection { background: rgba(99,102,241,.2); }

/* ===== 阶段C：移动端/界面打磨 ===== */
@media (max-width: 600px) {
  .topbar { position: sticky; top: 0; z-index: 80; }
  .bottom-tabs { position: sticky; bottom: 0; z-index: 50; padding-bottom: env(safe-area-inset-bottom); }
  .modal { width: 92vw; max-height: 82vh; overflow: auto; }
  .quick-actions { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .quick-btn { min-width: 72px; flex-shrink: 0; }
  .timeline-compose { padding-bottom: env(safe-area-inset-bottom); }
  .notif-panel { width: auto; left: 10px; right: 10px; }
}
.quick-btn, .bottom-tab, .nav-btn, .btn-primary, .btn-ghost { touch-action: manipulation; }

/* ===== 阶段D：群聊界面 ===== */
#view-projects.view { padding: 0; max-width: 720px; }
.chat-list { padding: 8px 0; background: #fff; min-height: 100%; }
.group-item { display: flex; align-items: center; gap: 12px; padding: 12px 16px; border-bottom: 1px solid var(--border-soft); cursor: pointer; background: #fff; }
.group-item:active { background: var(--primary-soft); }
.group-avatar { width: 46px; height: 46px; border-radius: 12px; background: linear-gradient(135deg, #e8b339, #d98a2b); color: #fff; display: flex; align-items: center; justify-content: center; font-size: 20px; font-weight: 700; flex-shrink: 0; }
.group-main { flex: 1; min-width: 0; }
.group-title { display: flex; justify-content: space-between; align-items: baseline; font-weight: 600; font-size: 15px; }
.group-time { font-size: 11px; color: var(--text-3); font-weight: 400; }
.group-last { font-size: 12px; color: var(--text-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-top: 2px; }
.group-item .progress-bar { margin-top: 6px; height: 3px; }
#view-timeline { display: flex; flex-direction: column; position: relative; padding: 0; height: calc(100vh - 52px); }
#view-timeline > [id^="tab-"] { overflow-y: auto; flex: 1; min-height: 0; padding: 0 16px 16px; }
.chat-messages { flex: 1; overflow-y: auto; padding: 12px; background: #f0f1f3; min-height: 0; }
/* D36h363（老板 2026-10-05「图片或者视频作者的名称或者发言者的姓名 logo 图标在发布信息的**左上部**，不是左下部」）：
   原来 `align-items: flex-end` ⇒ 头像贴气泡**底边**：文字气泡矮、看不出来，可图片/视频的气泡很高，
   头像就跑到左下角去了。改成顶部对齐（`flex-start`），头像回到气泡左上（与 WeChat 一致）。
   只动这一个词；**不加 `!important`**（文件尾部那块受 `test/settings-uniform-height-guard.test.mjs` ⑧-1b 约束）。 */
.msg-row { display: flex; margin-bottom: 10px; align-items: flex-start; }
.msg-row.mine { justify-content: flex-end; }
.msg-avatar { width: 34px; height: 34px; border-radius: 8px; background: var(--primary); color: #fff; display: flex; align-items: center; justify-content: center; font-size: 14px; font-weight: 700; margin-right: 8px; flex-shrink: 0; }
.msg-bubble { max-width: 72%; padding: 9px 12px; border-radius: 12px; background: #fff; box-shadow: 0 1px 2px rgba(0,0,0,.06); font-size: 14px; line-height: 1.5; word-break: break-word; }
.msg-row.mine .msg-bubble { background: #95ec69; border-top-right-radius: 2px; }
.msg-row.other .msg-bubble { border-top-left-radius: 2px; }
.msg-time { font-size: 10px; color: var(--text-3); margin-top: 3px; text-align: right; }
.msg-sys { background: rgba(0,0,0,.06); color: var(--text-3); font-size: 12px; padding: 4px 12px; border-radius: 8px; max-width: 92%; margin: 0 auto; text-align: center; }
.biz-card { background: #fff; border: 1px solid var(--border-soft); border-radius: 12px; padding: 10px 12px; max-width: 88%; box-shadow: 0 1px 2px rgba(0,0,0,.06); }
.event-head { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.event-icon { font-size: 18px; }
.event-actor { font-weight: 600; font-size: 13px; }
.event-type-badge { font-size: 11px; background: var(--border-soft); padding: 1px 8px; border-radius: 8px; color: var(--text-2); }
.event-time { font-size: 11px; color: var(--text-3); margin-left: auto; }
.event-body { font-size: 14px; line-height: 1.6; }
.event-actions { display: flex; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
.event-actions button { padding: 6px 14px; border-radius: 8px; font-size: 12px; font-weight: 600; border: none; cursor: pointer; }
.event-actions .confirm, .event-actions .approve, .event-actions .sign, .event-actions .complete { background: #34c759; color: #fff; }
.event-actions .reject { background: #ffebee; color: #e5484d; }
.event-ops { font-size: 11px; color: var(--text-3); margin-top: 8px; border-top: 1px dashed var(--border-soft); padding-top: 6px; }
.chat-inputbar { display: flex; align-items: center; gap: 8px; padding: 8px 10px; background: #fff; border-top: 1px solid var(--border-soft); }
.chat-inputbar input { flex: 1; border: 1px solid var(--border-soft); border-radius: 18px; padding: 8px 14px; font-size: 14px; outline: none; }
.quick-plus { width: 36px; height: 36px; border-radius: 50%; border: none; background: var(--primary); color: #fff; font-size: 22px; cursor: pointer; flex-shrink: 0; }
.quick-sheet { position: absolute; left: 10px; right: 10px; bottom: 100px; background: #fff; border-radius: 12px; box-shadow: 0 4px 20px rgba(0,0,0,.15); padding: 10px; z-index: 90; }
.sheet-title { font-size: 12px; color: var(--text-3); margin-bottom: 8px; }
.quick-sheet .quick-actions { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin-bottom: 0; }
@media (max-width: 768px) {
  #view-timeline { height: calc(100vh - 44px); }
  .quick-sheet .quick-actions { grid-template-columns: repeat(3, 1fr); }
}
.checkin-photos img { width: 72px; height: 72px; object-fit: cover; border-radius: 8px; margin: 4px 4px 0 0; }
/* ===== 阶段D2：卡片清晰化 + 按钮弹窗 + 固定底边栏 ===== */
/* 1) 聊天布局：头部 + 内容区（可滚动）+ 固定底边栏 */
#view-timeline { height: calc(100vh - 52px); }
.chat-header { padding: 8px 14px; margin: 0; background: #fff; border-bottom: 1px solid var(--border-soft); gap: 10px; flex-shrink: 0; }
.chat-header h2 { font-size: 17px; font-weight: 700; }
/* D310：聊天顶栏固定布局——项目名称省略 + 按钮不被遮挡 */
.chat-header-row { display: flex; align-items: center; gap: 8px; flex-wrap: nowrap; width: 100%; }
.chat-project-name { margin: 0; font-size: 14px; font-weight: 700; flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.chat-header .finance-mini { font-size: 12px; margin-top: 2px; }
.chat-back { border: none; background: var(--bg); width: 32px; height: 32px; border-radius: 50%; font-size: 16px; cursor: pointer; color: var(--text-2); flex-shrink: 0; line-height: 1; }
.chat-body { flex: 1; min-height: 0; display: flex; flex-direction: column; overflow: hidden; }
.chat-messages { flex: 1; overflow-y: auto; padding: 12px; background: #f0f1f3; }
.wb-scroll { overflow-y: auto; }
.chat-body .todo-panel { margin-top: 0; padding: 14px; }
.chat-body .workbench-panel { margin-top: 0; }
.contracts-panel { padding: 14px; }

/* 2) 固定底边栏：背景与聊天背景一致，输入框 + 功能页签集中 */
.chat-dock { flex-shrink: 0; background: #f0f1f3; border-top: 1px solid #e2e5e9; padding-bottom: env(safe-area-inset-bottom); }
.chat-inputbar { display: flex; align-items: center; gap: 8px; padding: 8px 10px; background: transparent; border-top: none; }
.chat-inputbar input { flex: 1; border: none; background: #fff; border-radius: 20px; padding: 9px 14px; font-size: 14px; outline: none; box-shadow: 0 1px 2px rgba(0,0,0,.05); min-width: 0; }
.quick-plus { width: 36px; height: 36px; border-radius: 50%; border: none; background: var(--primary); color: #fff; font-size: 20px; cursor: pointer; flex-shrink: 0; box-shadow: 0 2px 6px rgba(99,102,241,.35); }
/* D298：刷新按钮——文字「刷新」，点击后转圈；不旋转图标 */
.refresh-btn { min-width: 44px; height: 36px; padding: 0 12px; border-radius: 999px; border: none; background: var(--text-2); color: #fff; font-size: 13px; font-weight: 600; cursor: pointer; flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; gap: 4px; }
.refresh-btn .spin { border: 2px solid rgba(255,255,255,.4); border-top-color: #fff; margin-right: 0; }
.send-btn { border: none; background: var(--primary); color: #fff; padding: 9px 16px; border-radius: 20px; font-size: 13px; font-weight: 600; cursor: pointer; flex-shrink: 0; }
.bottom-tabs { display: flex; gap: 2px; padding: 4px 6px 6px; background: transparent; border-top: 1px solid #e2e5e9; margin-top: 0; }
.bottom-tab { flex: 1; padding: 8px 4px; border: none; background: transparent; color: var(--text-2); font-size: 12px; font-weight: 500; cursor: pointer; text-align: center; display: flex; flex-direction: column; align-items: center; gap: 2px; border-radius: 8px; }
.bottom-tab .tab-ico { font-size: 17px; }
.bottom-tab.active { color: var(--primary); background: #e8e9fd; font-weight: 600; }

/* 3) 业务卡片清晰化：白底 + 左色条 + 圆角 + 阴影，标题/金额/按钮层次分明 */
.biz-card { background: #fff; border: 1px solid #e5e7eb; border-left: 4px solid var(--ev-color, var(--primary)); border-radius: 14px; padding: 12px 14px; max-width: 88%; box-shadow: 0 2px 6px rgba(16,24,40,.06); }
.biz-card .event-head { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.biz-card .event-icon { width: 30px; height: 30px; border-radius: 8px; display: flex; align-items: center; justify-content: center; font-size: 15px; background: var(--ev-bg, var(--primary-soft)); flex-shrink: 0; }
.biz-card .event-actor { font-weight: 600; font-size: 13px; }
.biz-card .event-type-badge { font-size: 11px; background: var(--ev-bg, var(--primary-soft)); color: var(--ev-color, var(--primary)); padding: 2px 8px; border-radius: 6px; font-weight: 600; }
.biz-card .event-time { font-size: 11px; color: var(--text-3); margin-left: auto; }
.biz-card .event-body { font-size: 14px; line-height: 1.6; color: var(--text); padding-left: 0; }
.biz-card .event-body .ev-title { font-weight: 600; font-size: 15px; margin-bottom: 4px; }
.biz-card .event-body .ev-amount { font-size: 18px; font-weight: 700; margin: 4px 0; }
.biz-card .event-body .ev-row { margin-top: 6px; }
.biz-card .event-actions { display: flex; gap: 8px; margin-top: 10px; padding-left: 0; flex-wrap: wrap; }
.biz-card .event-actions button { border: none; padding: 8px 16px; border-radius: 10px; font-size: 13px; font-weight: 600; cursor: pointer; }
.biz-card .event-actions button.confirm, .biz-card .event-actions button.approve, .biz-card .event-actions button.sign, .biz-card .event-actions button.complete { background: var(--green); color: #fff; }
.biz-card .event-actions button.reject { background: var(--red-soft); color: var(--red); }
.biz-card .event-ops { font-size: 11px; color: var(--text-3); margin-top: 8px; border-top: 1px dashed var(--border-soft); padding-top: 6px; padding-left: 0; }

/* 4) 快捷操作弹窗（居中，网格按钮；右上角悬浮 X 关闭） */
.quick-menu { width: 320px; max-width: 92vw; }
.quick-menu .modal-x { top: 10px; right: 10px; }
.quick-menu h3 { padding-right: 28px; }
.quick-menu .quick-actions { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; margin: 4px 0 8px; }
.quick-menu .quick-btn { background: var(--bg); border: 1px solid var(--border); border-radius: 12px; padding: 14px 10px; cursor: pointer; font-size: 13px; color: var(--text-2); display: flex; flex-direction: column; align-items: center; gap: 6px; transition: all .15s; }
.quick-menu .quick-btn:hover { border-color: var(--primary); color: var(--primary); background: var(--primary-soft); }
.quick-menu .quick-btn .ico { font-size: 22px; }

/* 5) 确认弹窗正文 */
.confirm-body { font-size: 14px; color: var(--text-2); line-height: 1.7; padding: 6px 0 2px; }
.confirm-body b { color: var(--text); }
/* ===== 阶段D2 修正：页签面板撑满内容区可滚动 ===== */
.chat-body > [id^="tab-"] { flex: 1; min-height: 0; }
@media (max-width: 768px) { #view-timeline { height: calc(100vh - 41px); } }
/* ===== 阶段D3：聊天为底 + 项目列表常驻按钮 + 功能全部弹窗 ===== */
.menu-btn { border: none; background: var(--bg); width: 34px; height: 34px; border-radius: 10px; font-size: 18px; cursor: pointer; color: var(--text-2); flex-shrink: 0; line-height: 1; }
.menu-btn:active { background: var(--primary-soft); color: var(--primary); }

/* 项目群列表弹窗（☰ 触发） */
.list-modal { width: 400px; max-width: 92vw; max-height: 82vh; display: flex; flex-direction: column; padding: 18px; }
.list-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 14px; }
.list-head h3 { margin: 0; font-size: 17px; }
.list-head .btn-primary { width: auto; padding: 7px 14px; font-size: 13px; }
.list-scroll { flex: 1; overflow-y: auto; min-height: 220px; padding: 0; background: #fff; border: 1px solid var(--border-soft); border-radius: 12px; }
.list-modal .modal-actions { margin-top: 12px; }

/* 功能弹窗（待办/工作台/总览/合同/财务） */
.func-modal { width: 680px; max-width: 94vw; height: 84vh; max-height: 84vh; display: flex; flex-direction: column; padding: 18px; overflow: hidden; }
.func-modal h3 { margin: 0 0 12px; display: flex; align-items: center; justify-content: space-between; gap: 10px; padding-right: 26px; }
.func-modal h3 .btn-primary { width: auto; padding: 7px 14px; font-size: 13px; }
.func-body { flex: 1; overflow-y: auto; min-height: 0; }

/* 底边栏功能按钮行（点击弹窗，聊天界面始终为底） */
.func-row { display: flex; gap: 6px; padding: 6px 8px 8px; border-top: 1px solid #e2e5e9; }
.func-btn { flex: 1; padding: 8px 4px; border: none; background: transparent; color: var(--text-2); font-size: 12px; font-weight: 500; cursor: pointer; text-align: center; display: flex; flex-direction: column; align-items: center; gap: 2px; border-radius: 8px; }
.func-btn .tab-ico { font-size: 17px; }
.func-btn:active { background: #e8e9fd; color: var(--primary); }
/* ===== 阶段D4：用户管理 ===== */
.users-list { flex: 1; overflow-y: auto; min-height: 220px; }
.user-item { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border-bottom: 1px solid var(--border-soft); }
.user-item .u-avatar { width: 34px; height: 34px; border-radius: 50%; background: var(--primary-soft); color: var(--primary); display: flex; align-items: center; justify-content: center; font-weight: 700; flex-shrink: 0; }
.user-item .u-main { flex: 1; min-width: 0; }
.user-item .u-name { font-weight: 600; font-size: 14px; display: flex; align-items: center; gap: 6px; }
.user-item .u-phone { font-size: 12px; color: var(--text-3); margin-top: 2px; }
.user-item .u-roles { display: flex; gap: 4px; flex-wrap: wrap; margin-top: 4px; }
.role-chip { font-size: 11px; padding: 2px 8px; border-radius: 8px; background: var(--primary-soft); color: var(--primary); font-weight: 500; }
.u-status-badge { font-size: 11px; padding: 2px 8px; border-radius: 8px; font-weight: 600; }
.u-status-badge.active { background: var(--green-soft); color: #047857; }
.u-status-badge.disabled { background: var(--red-soft); color: #b91c1c; }
.user-item .u-actions { display: flex; gap: 6px; flex-shrink: 0; }
.user-item .u-actions button { border: none; padding: 6px 10px; border-radius: 8px; font-size: 12px; cursor: pointer; font-weight: 600; }
.user-item .u-actions .u-edit { background: var(--primary-soft); color: var(--primary); }
.user-item .u-actions .u-reset { background: var(--bg); color: var(--text-2); }
.role-pick { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-top: 6px; }
.role-chk { display: flex; align-items: center; gap: 6px; font-size: 13px; color: var(--text-2); background: var(--bg); border: 1px solid var(--border-soft); border-radius: 8px; padding: 8px 10px; cursor: pointer; }
.role-chk input { accent-color: var(--primary); }
@media (max-width: 600px) { .role-pick { grid-template-columns: repeat(2, 1fr); } }
/* ===== 阶段D5：常规功能完善（消息分页/任务看板/回收站/待办已办/财务筛选/改密码） ===== */
/* 消息加载更早 */
.load-more { display: block; width: 100%; margin: 0 0 12px; padding: 7px 0; border: none; background: rgba(0,0,0,.05); color: var(--text-3); font-size: 12px; border-radius: 10px; cursor: pointer; }
.load-more:hover { background: rgba(0,0,0,.09); color: var(--text-2); }

/* 待办 待处理/已处理 页签 */
.todo-tabs { display: flex; gap: 8px; margin-bottom: 12px; }
.todo-tab { flex: 1; padding: 9px 0; border: 1px solid var(--border); border-radius: 10px; background: var(--surface); color: var(--text-2); font-size: 13px; font-weight: 600; cursor: pointer; }
.todo-tab.active { background: var(--primary-soft); color: var(--primary); border-color: var(--primary); }

/* 任务看板 */
.kb-grid { display: flex; gap: 10px; overflow-x: auto; padding-bottom: 8px; align-items: flex-start; }
.kb-col { flex: 0 0 210px; background: var(--bg); border-radius: 12px; padding: 10px; }
.kb-head { font-size: 13px; font-weight: 700; margin-bottom: 10px; display: flex; justify-content: space-between; align-items: center; }
.kb-count { background: var(--surface); border-radius: 10px; padding: 1px 8px; font-size: 12px; color: var(--text-3); }
.kb-card { background: var(--surface); border: 1px solid var(--border-soft); border-radius: 10px; padding: 10px 12px; margin-bottom: 8px; cursor: pointer; box-shadow: var(--shadow-sm); }
.kb-card:hover { border-color: var(--primary); }
.kb-card .kb-title { font-size: 13px; font-weight: 600; line-height: 1.4; }
.kb-card .kb-meta { font-size: 11px; color: var(--text-3); margin-top: 5px; }
.kb-empty { text-align: center; color: var(--text-3); font-size: 12px; padding: 10px 0; }

/* 任务操作弹窗按钮 */
.modal .task-next { display: inline-block; border: none; background: var(--primary); color: #fff; padding: 8px 16px; border-radius: 10px; font-size: 13px; font-weight: 600; cursor: pointer; }
.modal .del { background: var(--red-soft); color: var(--red); border: none; padding: 10px 22px; border-radius: 9px; font-size: 14px; font-weight: 600; cursor: pointer; }

/* 财务筛选行 */
.tx-filter { display: flex; gap: 8px; margin-bottom: 14px; flex-wrap: wrap; }
.tx-filter select, .tx-filter input { padding: 8px 10px; border: 1px solid var(--border); border-radius: 9px; font-size: 13px; background: #fff; }
.tx-filter input { flex: 1; min-width: 140px; }
.tx-filter .send-btn { padding: 8px 16px; border-radius: 9px; font-size: 13px; }
/* ===== 阶段D6：去图标纯文字 + 我的中心 ===== */
.text-btn { border: none; background: var(--bg); padding: 8px 14px; border-radius: 9px; font-size: 13px; font-weight: 600; color: var(--text-2); cursor: pointer; }
.text-btn:active { background: var(--primary-soft); color: var(--primary); }
.quick-plus { width: auto; border-radius: 10px; padding: 9px 14px; font-size: 13px; font-weight: 600; }
.func-btn { padding: 9px 4px; font-size: 13px; }
.quick-menu .quick-actions { grid-template-columns: repeat(3, 1fr); }
.quick-menu .quick-btn { padding: 12px 8px; font-size: 13px; }
.me-modal { width: 340px; max-width: 92vw; }
.me-info { background: var(--bg); border-radius: 12px; padding: 16px; margin-bottom: 14px; text-align: center; }
.me-name { font-size: 18px; font-weight: 700; }
.me-roles { font-size: 13px; color: var(--text-2); margin-top: 6px; }
.me-phone { font-size: 12px; color: var(--text-3); margin-top: 4px; }
.me-menu { display: flex; flex-direction: column; gap: 8px; }
.me-menu button { border: 1px solid var(--border); background: var(--surface); padding: 10px 12px; border-radius: 10px; font-size: 14px; font-weight: 500; color: var(--text); cursor: pointer; display: flex; align-items: center; justify-content: space-between; gap: 8px; width: 100%; text-align: left; }
.me-menu button:active { background: var(--primary-soft); border-color: var(--primary); }
.me-menu .me-logout { color: var(--red); }
.event-ops::before { content: none; }
.wb-card { padding: 20px 10px; }
.wb-label { font-size: 14px; }
/* ===== 阶段D7：侧边悬浮按钮 + 项目列表抽屉 ===== */
.drawer-fab { position: fixed; left: 0; top: 50%; transform: translateY(-50%); width: 38px; padding: 20px 0; border-radius: 0 12px 12px 0; background: var(--primary); color: #fff; border: none; font-size: 14px; font-weight: 600; cursor: pointer; z-index: 90; writing-mode: vertical-rl; letter-spacing: 3px; box-shadow: 0 4px 12px rgba(99,102,241,.4); touch-action: manipulation; }
.drawer-fab:active { background: #5558e6; }
.drawer-overlay { position: fixed; inset: 0; background: rgba(16,24,40,.4); z-index: 95; display: none; }
.drawer-panel { position: fixed; left: 0; top: 0; bottom: 0; width: 82%; max-width: 340px; background: var(--surface); z-index: 96; box-shadow: var(--shadow-lg); transform: translateX(-100%); transition: transform .25s; display: flex; flex-direction: column; }
.drawer-panel.open { transform: translateX(0); }
.drawer-head { padding: 18px 16px 12px; border-bottom: 1px solid var(--border-soft); }
.drawer-head h3 { margin: 0 0 12px; font-size: 17px; }
.drawer-search { width: 100%; padding: 9px 12px; border: 1px solid var(--border); border-radius: 10px; font-size: 14px; outline: none; }
.drawer-search:focus { border-color: var(--primary); }
.drawer-list { flex: 1; overflow-y: auto; padding: 6px 0; min-height: 0; }
.drawer-foot { padding: 10px 16px; border-top: 1px solid var(--border-soft); }
.drawer-foot .btn-primary { width: 100%; padding: 11px 0; font-size: 14px; }
/* ===== 阶段D8：所有按钮统一药丸形状（pill） ===== */
.btn-primary, .btn-ghost, .text-btn, .quick-plus, .send-btn, .func-btn,
.quick-btn, .todo-tab, .todo-item [data-action], .task-next, .u-edit,
.u-reset, .load-more, .modal-actions button, .me-menu button,
.event-actions button, .tx-filter .send-btn, .c-sign, .c-print, .c-del,
.drawer-fab {
  border-radius: 999px !important;
}
/* ===== 阶段D9：通知跳转消息定位高亮 ===== */
.msg-row.ev-flash { border-radius: 12px; animation: evFlash 3s ease; }
@keyframes evFlash {
  0% { background: rgba(99,102,241,.28); box-shadow: 0 0 0 3px rgba(99,102,241,.25); }
  100% { background: transparent; box-shadow: none; }
}
/* ===== 阶段D10：聊天区悬浮按钮（左上项目列表 / 左下项目收支） ===== */
.chat-body { position: relative; }
.fab-chat { position: absolute; z-index: 60; width: 46px; padding: 12px 0; border: none; border-radius: 999px; background: var(--primary); color: #fff; font-size: 13px; font-weight: 600; cursor: pointer; writing-mode: vertical-rl; letter-spacing: 1px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; box-shadow: 0 4px 12px rgba(99,102,241,.4); touch-action: manipulation; }
.fab-chat:active { background: #5558e6; }
.fab-top { top: 10px; left: 10px; }
.fab-bottom { bottom: 10px; left: 10px; }
/* ===== 阶段D11：待办=未读消息 + 待办角标 ===== */
.todo-badge { position: absolute; top: 2px; right: 10px; background: #e5484d; color: #fff; font-size: 10px; border-radius: 10px; padding: 1px 5px; font-weight: 700; line-height: 1.4; }
.todo-item { cursor: pointer; }
.todo-item:active { background: var(--primary-soft); }
/* ===== 阶段D12：底边栏固定（不随页面滚动）+ 导航重构 ===== */
.chat-dock { position: fixed; left: 0; right: 0; bottom: 0; max-width: 1200px; margin: 0 auto; z-index: 80; }
.chat-body { padding-bottom: 106px; } /* 给固定底栏（输入行+功能行）留出空间 */
#ov-finance { border-top: 1px solid var(--border-soft); padding-top: 14px; }
#ov-finance h4, #ov-contracts .workbench-panel h4, #ov-tasks .workbench-panel h4 { font-size: 15px; margin: 0 0 12px; }
/* ===== 阶段D13：待办并入通知，底边栏精简 ===== */
.func-row .func-btn:only-child { flex: 0 0 auto; margin: 0 auto; padding: 9px 40px; }
.notif-tabs { display: flex; gap: 6px; padding: 10px 14px 0; }
.notif-tab { flex: 1; padding: 8px 0; border: 1px solid var(--border); border-radius: 999px; background: var(--surface); color: var(--text-2); font-size: 12px; font-weight: 600; cursor: pointer; }
.notif-tab.active { background: var(--primary-soft); color: var(--primary); border-color: var(--primary); }
#notif-body { max-height: 56vh; overflow-y: auto; }
/* ===== 阶段D14：底边栏精简为一行（操作 + 输入 + 发送） ===== */
.chat-body { padding-bottom: 62px; }
/* ===== 阶段D15：项目总览 = 项目名称后的有色按钮 ===== */
.overview-btn { border: none; background: var(--primary); color: #fff; padding: 4px 12px; border-radius: 999px; font-size: 11px; font-weight: 600; cursor: pointer; box-shadow: 0 2px 6px rgba(99,102,241,.3); touch-action: manipulation; flex-shrink: 0; white-space: nowrap; }
.overview-btn:active { background: #5558e6; }
/* D142：AI 装修管家顶栏按钮（渐变 AI 视觉，与操作区 grad-ai 一致；D36h525 统一金色体系） */
.grad-ai-btn { background: linear-gradient(135deg, #e9ad2e 0%, #d99b16 55%, #c18408 100%) !important; box-shadow: 0 2px 8px rgba(185,124,5,.35) !important; }
.grad-ai-btn:active { background: linear-gradient(135deg, #d99b16 0%, #bf8308 55%, #a86f02 100%) !important; }
/* ===== 阶段D16：项目列表按钮白色吸边 ===== */
.fab-chat { background: #fff; color: var(--primary); border: 1px solid var(--border); box-shadow: 0 2px 8px rgba(16,24,40,.08); }
.fab-chat:active { background: var(--primary-soft); }
.fab-top { top: 10px; left: 0; border-radius: 0 12px 12px 0; }
/* ===== 阶段D17：操作弹窗按角色分组（D85 改 modal-scroll：头/底固定 + 内容滚动，X 悬浮） ===== */
.quick-menu { max-height: 82vh; }
.quick-menu.modal-scroll .modal-body { overflow-y: auto; flex: 1 1 auto; min-height: 0; }
.qgroup { margin-bottom: 16px; }
.qgroup:last-child { margin-bottom: 4px; }
.qgroup-title { font-size: 12px; color: var(--text-3); margin-bottom: 8px; padding-left: 2px; }
.qgroup .quick-actions { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 600px) { .qgroup .quick-actions { grid-template-columns: repeat(2, 1fr); } }
/* ===== 阶段D18：操作按钮纵向单列 + 按钮减小（移动端友好） ===== */
.qgroup .quick-actions { grid-template-columns: 1fr; gap: 6px; }
.quick-menu .quick-btn { padding: 9px 12px; font-size: 13px; border-radius: 999px; }
/* ===== 阶段D20：操作按角色分组横向排列，自动换行（无横向滚动条） ===== */
.qgroup .quick-actions { display: flex; flex-wrap: wrap; gap: 6px; }
.quick-menu .quick-btn { flex: 0 0 auto; padding: 8px 14px; font-size: 13px; border-radius: 999px; }
/* ===== 阶段D21：操作弹窗 = 角色卡片网格（两列，卡内按钮横向换行） ===== */
.role-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.role-card { background: var(--bg); border: 1px solid var(--border-soft); border-radius: 12px; padding: 10px 12px; }
.role-card-title { font-size: 12px; font-weight: 700; color: var(--text-2); margin-bottom: 8px; display: flex; justify-content: space-between; align-items: center; }
.role-card-count { font-size: 11px; color: var(--text-3); background: var(--surface); border-radius: 999px; padding: 1px 8px; font-weight: 600; }
.role-card .quick-actions { display: flex; flex-wrap: wrap; gap: 5px; }
.quick-menu .quick-btn { flex: 0 0 auto; padding: 5px 10px; font-size: 12px; border-radius: 999px; }
@media (max-width: 600px) { .role-grid { grid-template-columns: 1fr; } }
/* ===== 阶段D22：角色卡单列（一行一个角色），卡内按钮自动换行 ===== */
.role-grid { grid-template-columns: 1fr; }
/* ===== 阶段D23：操作弹窗加宽，角色卡横向拉满 ===== */
.quick-menu { width: 520px; max-width: 92vw; }
/* ===== 阶段D24：角色卡按钮等宽铺满整行，从左到右排列自动换行 ===== */
.quick-menu .quick-btn { flex: 1 1 auto; text-align: center; }
/* ===== 阶段D25：按钮恢复内容宽度（不再拉伸），卡片仍占满弹窗 ===== */
.quick-menu .quick-btn { flex: 0 0 auto; }
/* ===== 阶段D26：按钮等宽铺满卡片整行（1/1 横向，右侧不留空） ===== */
.quick-menu .quick-btn { flex: 1 1 auto; text-align: center; }
/* ===== 阶段D27：卡片占满弹窗宽度（1fr 已实现），按钮按内容宽度不拉伸 ===== */
.quick-menu .quick-btn { flex: 0 0 auto; }
/* ===== 阶段D28：强制角色卡占满弹窗宽度，减小弹窗内边距 ===== */
.role-grid { display: grid; grid-template-columns: 1fr; gap: 8px; }
.role-card { width: 100%; box-sizing: border-box; }
.quick-menu { padding: 16px; }
/* ===== 阶段D29：根治——弹窗容器单列，角色卡占满弹窗整宽 ===== */
.quick-menu .quick-actions { display: grid; grid-template-columns: 1fr; gap: 8px; margin: 0; }
.role-grid { display: contents; }
/* ===== 阶段D30（最终）：外层容器单列；卡内按钮跟随文字宽度、横向排列自动换行 ===== */
#quick-menu-list { display: grid; grid-template-columns: 1fr; gap: 8px; }
/* D63：去掉 !important（D30 遗留），否则覆盖 D31 的折叠 display:none，导致收起/展开无效 */
.role-card .quick-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.quick-menu .quick-btn { flex: 0 0 auto !important; width: auto; min-width: 0; }
/* ===== 阶段D31：角色卡可折叠（默认收起，点击展开/收起） ===== */
.role-card .quick-actions { display: none; }
.role-card.open .quick-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.role-card-title { cursor: pointer; user-select: none; }
.role-card-right { display: flex; align-items: center; gap: 6px; }
.role-card-toggle { border: none; background: var(--surface); color: var(--primary); font-size: 12px; font-weight: 600; padding: 3px 10px; border-radius: 999px; cursor: pointer; }
/* ===== 阶段D33：流程卡片（阶段条 / 执行人 / 详情按钮） ===== */
.flow-card .event-head { flex-wrap: wrap; }
.flow-detail { margin-left: auto; border: none; background: var(--primary-soft); color: var(--primary); font-size: 12px; font-weight: 600; padding: 3px 12px; border-radius: 999px; cursor: pointer; }
/* 快速记账卡片删除按钮（超管/商务/财务可见） */
.qb-del { border: 1px solid var(--red); background: var(--red-soft); color: var(--red); font-size: 12px; font-weight: 600; padding: 3px 12px; border-radius: 999px; cursor: pointer; }
/* 快速记账卡片审批按钮（财务/超管可见）：通过=实心绿，驳回=红描边 */
.qb-ok { flex: 1; border: none; background: var(--green); color: #fff; font-size: 12px; font-weight: 600; padding: 7px 12px; border-radius: 10px; cursor: pointer; }
.qb-no { flex: 1; border: 1.5px solid var(--red); background: var(--red-soft); color: var(--red); font-size: 12px; font-weight: 600; padding: 6px 12px; border-radius: 10px; cursor: pointer; }
.flow-people { display: flex; gap: 16px; flex-wrap: wrap; font-size: 12px; color: var(--text-2); margin-top: 8px; padding: 7px 10px; background: var(--bg); border-radius: 8px; }
.flow-people .k { color: var(--text-3); }
.flow-stages { display: flex; gap: 4px; margin-top: 10px; }
.flow-dot { flex: 1; height: 6px; border-radius: 3px; background: #dfe2e7; }
.flow-dot.done { background: var(--green); }
.flow-dot.current { background: var(--amber); }
.flow-dot.rejected { background: var(--red); }
.flow-labels { display: flex; gap: 4px; margin-top: 4px; }
.flow-st-label { flex: 1; text-align: center; font-size: 10px; color: var(--text-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; padding: 0 1px; }
/* 流程卡当前阶段 + 责任人提示 */
.flow-current-step { color: #b45309; background: var(--amber-soft); border-radius: 6px; padding: 2px 8px; }
.flow-st-label.done { color: var(--green); }
.flow-st-label.current { color: #b45309; font-weight: 700; }
.flow-st-label.rejected { color: var(--red); }
/* ===== 阶段D34：流程卡片四要素简化（名称/详情/阶段负责人/阶段进度） ===== */
.flow-card .flow-title { font-size: 15px; font-weight: 700; margin-top: 6px; line-height: 1.5; }
/* D238：收支卡片封面增强——金额大字 + 备注直显（最多 2 行截断） */
.flow-card .flow-title .flow-amt { font-size: 22px; font-weight: 800; margin-right: 2px; }
.flow-remark { margin-top: 8px; font-size: 12px; color: var(--text-2); background: var(--bg); border: 1px solid var(--border-soft); border-radius: 8px; padding: 6px 10px; line-height: 1.7; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
/* ★D36h165（2026-09-23）**删掉了这一条**：`.flow-card .event-body { display: none; }`
 *   D34 当年加它是为了"四要素流程卡"把正文收进 flow-title / flow-people / 阶段条，隐藏遗留的 event-body。
 *   但全仓排查下来，**只有「借支卡」把正文装在 event-body 里**（public/app.js:11883 的 advanceCardHtml
 *   + 外挂 public/js/advance-card-fix.js）—— 这条规则把借支卡的【借支人 / 金额 / 事由 / 可支口径 /
 *   下一步该谁 / 详情·确认发放按钮】**整块藏掉**，屏幕上只剩卡头「蒋平 借支 13:20」：
 *   老板 2026-09-23 两次报「怎么就借支两个字」「还是啥没有」就是这个。
 *   其余用 event-body 的都是普通 biz-card（app.js:3588/3638/3694/3706/4063/4075/4239），不受影响；
 *   四要素流程卡（app.js:4307/4371）根本不输出 event-body。所以删掉这条没有副作用。
 *   教训：核对卡片"有没有内容"必须验**可见性**（getComputedStyle/offsetHeight），只看 textContent 会被 display:none 骗。 */
/* ===== 阶段D36：消息区底部留白加大（防固定底栏遮挡卡片按钮） ===== */
.chat-body { padding-bottom: 96px; }
/* ===== 阶段D36：流程按钮可点击性加固 ===== */
.chat-body { padding-bottom: 96px; }
.flow-card { position: relative; z-index: 1; }
.flow-card .event-actions { position: relative; z-index: 5; }
.flow-card .event-actions button { pointer-events: auto; }
/* ===== 阶段D37：派工协议弹窗 ===== */
.agreement-modal { width: 560px; max-width: 94vw; }
.agreement-modal .agree-text { max-height: 46vh; overflow-y: auto; background: var(--bg); border: 1px solid var(--border-soft); border-radius: 10px; padding: 14px 16px; font-size: 13px; line-height: 1.9; color: var(--text-2); white-space: normal; }
.agreement-modal .agree-check { display: flex; align-items: center; gap: 8px; margin-top: 14px; font-size: 13px; color: var(--text); font-weight: 500; cursor: pointer; }
.agreement-modal .agree-check input { width: 18px; height: 18px; accent-color: var(--primary); }
.agreement-modal .modal-actions .ok:disabled { opacity: .4; cursor: not-allowed; }
/* ===== 阶段D38：表单升级（人员搜索选择 / 日历日期 / 工种下拉） ===== */
.person-pick { position: relative; }
.person-pick .person-search { width: 100%; padding: 11px 13px; border: 1.5px solid var(--border); border-radius: 9px; font-size: 14px; outline: none; }
.person-pick .person-list { position: absolute; left: 0; right: 0; top: 100%; background: #fff; border: 1px solid var(--border); border-radius: 10px; box-shadow: 0 8px 24px rgba(0,0,0,.12); max-height: 320px; overflow-y: auto; z-index: 30; }
.person-item { padding: 9px 12px; font-size: 13px; cursor: pointer; display: flex; justify-content: space-between; align-items: center; }
.person-item:hover { background: var(--primary-soft); }
.person-item .person-role { font-size: 11px; color: var(--text-3); }
.person-empty { padding: 12px; font-size: 12px; color: var(--text-3); text-align: center; }
.modal input[type="date"] { width: 100%; padding: 11px 13px; border: 1.5px solid var(--border); border-radius: 9px; font-size: 14px; outline: none; font-family: inherit; }
/* ===== 阶段D41：上传改为拖拽框（点击选择 / 拖拽上传） ===== */
.photo-drop { margin-top: 6px; }
.drop-zone { border: 2px dashed var(--border); border-radius: 10px; padding: 26px 12px; text-align: center; font-size: 13px; color: var(--text-3); cursor: pointer; transition: all .15s; }
.drop-zone:hover, .drop-zone.dragover { border-color: var(--primary); color: var(--primary); background: var(--primary-soft); }
.photo-drop .photo-preview { display: flex; flex-wrap: wrap; margin-top: 6px; }
/* ===== 阶段D42：项目名称与项目总览按钮固定不滚动 ===== */
#view-timeline { overflow: hidden; }
.chat-header { position: sticky; top: 0; z-index: 30; }
/* ===== 阶段D43：打卡相机弹窗 ===== */
.cam-modal { width: 420px; max-width: 94vw; }
/* ===== 阶段D44：施工中黄色提示（打卡统一走操作按钮） ===== */
.flow-working { display: inline-block; background: var(--amber-soft); color: #b45309; font-size: 12px; font-weight: 700; padding: 6px 18px; border-radius: 999px; }
/* ===== 阶段D46：合同向导与模板管理 ===== */
.cw-modal { width: 640px; max-width: 94vw; }
.cw-modal textarea { width: 100%; padding: 10px 12px; border: 1.5px solid var(--border); border-radius: 9px; font-size: 13px; font-family: inherit; line-height: 1.8; outline: none; resize: vertical; }
.cw-stage { display: flex; align-items: center; gap: 6px; margin-bottom: 6px; }
.cw-stage input, .cw-stage select { padding: 7px 9px; border: 1px solid var(--border); border-radius: 8px; font-size: 12px; outline: none; }
.cw-stage .st-del { border: none; background: var(--red-soft); color: var(--red); padding: 6px 10px; border-radius: 999px; font-size: 11px; cursor: pointer; }
/* ===== 阶段D47：合同电子盖章 ===== */
.contract-seals { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 8px; }
.cseal { font-size: 11px; padding: 2px 8px; border-radius: 8px; background: var(--bg); color: var(--text-3); }
.cseal.on { background: var(--green-soft); color: #047857; font-weight: 600; }
/* ===== 阶段D48：付款阶段行布局修正（描述加宽 / 模式选择缩小） ===== */
.cw-stage { flex-wrap: wrap; }
.cw-stage .st-name { flex: 2 1 150px !important; min-width: 130px; }
.cw-stage select.st-mode { width: 74px !important; flex: 0 0 auto; padding: 7px 2px; font-size: 12px; }
.cw-stage .st-val { width: 86px !important; }
.cw-stage .st-due { width: 118px !important; }
/* ===== 阶段D49：彻底固定项目名称（禁止页面整体滚动） ===== */
html, body { height: 100%; overflow: hidden; }
#view-timeline { height: calc(100dvh - 52px); }
@media (max-width: 768px) { #view-timeline { height: calc(100dvh - 41px); } }

/* ===== 阶段D51：设置弹窗 Logo 三种版式（横版主/竖版/图标），预览（左）+ 拖拽框（右）等高 ===== */
.logo-slot { display: flex; gap: 6px; margin-bottom: 10px; align-items: stretch; }
.logo-slot:last-of-type { margin-bottom: 0; }
.logo-slot-tag { writing-mode: vertical-rl; font-size: 11px; color: var(--text-3); letter-spacing: 2px; display: flex; align-items: center; justify-content: center; border: 1px solid var(--border); border-radius: 8px; padding: 4px 2px; background: var(--bg); flex: 0 0 24px; }
.logo-row { display: flex; gap: 10px; height: 120px; align-items: stretch; flex: 1; min-width: 0; }
.logo-row > * { height: 100%; box-sizing: border-box; }
.logo-row .logo-preview { flex: 0 0 160px; border: 2px dashed var(--border); border-radius: 10px; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 6px; background: var(--bg); overflow: hidden; }
.logo-preview-img { flex: 1; width: 100%; display: flex; align-items: center; justify-content: center; }
.logo-preview-img img { max-width: 100%; max-height: 100%; object-fit: contain; }
.logo-preview-img span { font-size: 12px; color: var(--text-3); }
.logo-row .photo-drop { flex: 1; margin-top: 0; display: flex; flex-direction: column; position: relative; min-width: 0; }
.logo-row .photo-drop .drop-zone { flex: 1; display: flex; align-items: center; justify-content: center; }
.logo-row .photo-drop .photo-preview { position: absolute; inset: 0; overflow-y: auto; display: flex; flex-wrap: wrap; align-content: flex-start; gap: 6px; padding: 6px; background: rgba(255,255,255,.92); border-radius: 10px; z-index: 2; }
.logo-row .photo-drop .photo-preview:empty { display: none; }
.cw-modal { max-height: calc(100dvh - 48px); overflow-y: auto; }
/* ===== 阶段D65：弹窗右上角 X 关闭按钮 ===== */
/* D67：所有弹窗容器内部滚动（max-height+overflow），X sticky 悬浮于容器顶部 → 滚动时始终可见 */
.modal { position: relative; max-height: calc(100dvh - 48px); overflow-y: auto; }
/* 功能弹窗（待办/工作台/总览）：整体不滚动，标题+✕固定，仅内容区滚动（覆盖上方 .modal overflow-y:auto） */
.modal.func-modal { overflow: hidden; }
.modal.func-modal .func-body { flex: 1 1 0; height: 0; min-height: 0; overflow: hidden; } /* 高度由 flex 分配，不随内容撑开 */
/* 功能弹窗内容区的滚动面板：自己滚动（tab 栏 sticky 相对面板固定，内容滚动） */
.modal.func-modal .func-body > .wb-scroll,
.modal.func-modal .func-body > .ov-scroll { overflow-y: auto; height: 100%; }
.modal-x { position: absolute; top: 12px; right: 12px; border: none; background: none; color: var(--text-3); font-size: 17px; line-height: 1; cursor: pointer; padding: 6px 10px; border-radius: 8px; z-index: 6; }
.modal-x:hover { color: var(--red); background: var(--red-soft); }
.list-head { padding-right: 34px; }
/* D76：登录页密码/短信切换 */
.login-tabs { display: flex; gap: 6px; margin-bottom: 14px; }
.login-tab { flex: 1; border: 1px solid var(--border); background: #fff; color: var(--text-2); padding: 8px 0; border-radius: 999px; font-size: 13px; font-weight: 600; cursor: pointer; }
.login-tab.active { background: var(--primary); border-color: var(--primary); color: #fff; }
.sms-row { display: flex; gap: 8px; align-items: stretch; }
.sms-row input { flex: 1; }
.login-card .sms-row { margin-bottom: 14px; }
.login-card .sms-row input { margin-bottom: 0; }
.sms-send-btn { border: 1.5px solid var(--border); background: #fff; color: var(--primary); padding: 0 16px; border-radius: 10px; font-size: 13px; font-weight: 600; cursor: pointer; white-space: nowrap; }
.sms-send-btn:disabled { color: var(--text-3); }
/* D78：忘记密码（短信找回） */
.forgot-link { margin-top: 12px; font-size: 13px; }
.forgot-link a { color: var(--primary); text-decoration: none; font-weight: 600; }
.reset-tip { font-size: 12px; color: var(--text-3); margin-bottom: 12px; }
/* D67v4：弹窗头部（X+标题）固定，内容区独立滚动 → X 永不滚出 */
.modal-scroll { display: flex; flex-direction: column; overflow: hidden !important; }
.modal-scroll .modal-body { overflow-y: auto; flex: 1 1 auto; min-height: 0; }
.modal-scroll > h3, .modal-scroll > .list-head, .modal-scroll > .modal-actions { flex: 0 0 auto; }
/* D96：modal-scroll 的底部按钮条必须撑满弹窗宽度（否则 flex 子项收缩、按钮孤零零贴右侧） */
.modal-scroll > .modal-actions { width: 100%; box-sizing: border-box; margin-top: 14px; }
.modal-scroll .modal-body video { max-height: 45vh; }
/* D36fy2：我的企业（企业切换）卡片式列表——长地址不再把企业名挤成竖排 */
/* D36h27：我的公司弹窗分区标题（企业 / 公司账本 两层） */
.me-ent-sec { font-size: 12px; font-weight: 700; color: var(--text-2); margin: 2px 0 8px; padding-left: 2px; }
.me-ent-card { display: flex; align-items: center; gap: 12px; padding: 12px 14px; border: 1px solid var(--border-soft); border-radius: 14px; margin-bottom: 10px; background: #fff; transition: border-color .15s, box-shadow .15s; }
.me-ent-card:hover { border-color: var(--primary); box-shadow: 0 4px 14px rgba(99,102,241,.12); }
.me-ent-card.is-cur { border-color: #c7d2fe; background: linear-gradient(135deg, #eef2ff, #fafbff); }
.me-ent-ava { flex: 0 0 auto; width: 40px; height: 40px; border-radius: 12px; display: flex; align-items: center; justify-content: center; color: #fff; font-size: 17px; font-weight: 700; background: linear-gradient(135deg, #6366f1, #8b5cf6); }
.me-ent-main { flex: 1 1 0; min-width: 0; overflow: hidden; }
.me-ent-name { font-size: 14px; font-weight: 700; line-height: 1.6; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.me-ent-sub { font-size: 12px; color: var(--text-3); margin-top: 3px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.me-ent-dot { display: inline-block; width: 6px; height: 6px; border-radius: 50%; margin-right: 5px; vertical-align: 1px; }
.me-ent-act { flex: 0 0 auto; }
.me-ent-go { border: none; background: var(--primary); color: #fff; border-radius: 9px; padding: 8px 16px; font-size: 13px; font-weight: 600; cursor: pointer; white-space: nowrap; box-shadow: 0 2px 7px rgba(99,102,241,.28); transition: background .15s; }
.me-ent-go:hover { background: #5558e6; }
.me-ent-go:disabled { background: #c7cbd4; box-shadow: none; cursor: not-allowed; }
.me-ent-cur { display: inline-block; font-size: 12px; font-weight: 600; color: #047857; background: var(--green-soft); border-radius: 8px; padding: 7px 12px; white-space: nowrap; }
@media (max-width: 420px) {
  .me-ent-card { padding: 10px 12px; gap: 10px; }
  .me-ent-ava { width: 34px; height: 34px; border-radius: 10px; font-size: 15px; }
  .me-ent-go { padding: 7px 12px; }
  .me-ent-cur { padding: 6px 10px; }
}
/* ===== 阶段D54：项目列表悬浮按钮阴影分层（与聊天内容拉开层次） ===== */
.fab-chat { box-shadow: 0 6px 18px rgba(16,24,40,.22), 0 2px 6px rgba(16,24,40,.12); border-width: 1.5px; }
.fab-chat:hover { box-shadow: 0 8px 22px rgba(16,24,40,.26), 0 3px 8px rgba(16,24,40,.14); }
/* ===== 阶段D53：顶栏品牌前图标 Logo（图标版 logo_url3） ===== */
.brand { display: inline-flex; align-items: center; gap: 8px; }
.brand-logo { height: 24px; width: auto; max-width: 110px; object-fit: contain; }
/* ===== 阶段D56：电子单据打印按钮样式 ===== */
.flow-print { border: 1px solid var(--border); background: #fff; color: var(--text-2); font-size: 12px; font-weight: 600; padding: 3px 12px; border-radius: 999px; cursor: pointer; }
.flow-print:hover { border-color: var(--primary); color: var(--primary); }
/* ===== 阶段D57：项目总览分 tab ===== */
.ov-tabs { display: flex; gap: 6px; margin-bottom: 12px; flex-wrap: wrap; position: sticky; top: 0; background: var(--surface); padding: 4px 0; z-index: 5; }
.ov-tab { border: 1px solid var(--border); background: #fff; color: var(--text-2); padding: 7px 16px; border-radius: 999px; font-size: 13px; font-weight: 600; cursor: pointer; }
.ov-tab.active { background: var(--primary); border-color: var(--primary); color: #fff; }
.ov-panel { display: none; }
.ov-panel.active { display: block; }
/* ===== 阶段D59：设置弹窗编号规则 ===== */
.code-rules { display: flex; flex-direction: column; gap: 6px; }
.code-rule-row { display: flex; align-items: center; gap: 8px; }
.code-rule-name { flex: 0 0 48px; font-size: 13px; font-weight: 600; color: var(--text-2); }
.code-rule-row input, .code-rule-row select { padding: 7px 9px; border: 1px solid var(--border); border-radius: 8px; font-size: 13px; outline: none; }
.code-rule-row .rule-prefix { flex: 1; }
/* ===== 阶段D60：设置弹窗顶部 tab + 编号规则优化 ===== */
.st-tabs { display: flex; gap: 6px; margin-bottom: 12px; flex-wrap: wrap; }
.st-tab { border: 1px solid var(--border); background: #fff; color: var(--text-2); padding: 7px 16px; border-radius: 999px; font-size: 13px; font-weight: 600; cursor: pointer; }
.st-tab.active { background: var(--primary); border-color: var(--primary); color: #fff; }
.st-panel { display: none; }
.st-panel.active { display: block; }
.code-rule-row .rule-digits { width: 60px; }
.code-rule-note { font-size: 12px; color: var(--text-3); line-height: 1.7; margin: 2px 0 10px; }
.code-rule-example { flex: 1; font-size: 12px; color: var(--primary); font-weight: 600; text-align: right; font-family: Consolas, monospace; }
/* ===== 阶段D61：邀请注册 ===== */
.inv-pick { display: flex; gap: 8px; flex-wrap: wrap; }
.inv-chk { display: flex; align-items: center; gap: 6px; border: 1px solid var(--border); border-radius: 999px; padding: 7px 14px; font-size: 13px; cursor: pointer; }
.inv-chk:has(input:checked) { border-color: var(--primary); background: var(--primary-soft); color: var(--primary); font-weight: 600; }
/* ===== 阶段D80：项目总览任务状态汇总卡 ===== */
.task-stat-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); gap: 10px; }
.task-stat-card { background: var(--surface); border: 1px solid var(--border-soft); border-radius: 12px; padding: 14px 12px; text-align: center; cursor: pointer; transition: all .15s; box-shadow: var(--shadow-sm); }
.task-stat-card:hover { border-color: var(--primary); transform: translateY(-1px); box-shadow: var(--shadow-md); }
.task-stat-name { font-size: 13px; color: var(--text-2); font-weight: 600; }
.task-stat-count { font-size: 26px; font-weight: 700; margin: 6px 0 2px; color: var(--text); }
.task-stat-hint { font-size: 11px; color: var(--text-3); }
.task-g-item { border: 1px solid var(--border-soft); border-radius: 10px; padding: 12px 14px; margin-bottom: 8px; cursor: pointer; background: var(--surface); transition: border .15s; }
.task-g-item:hover { border-color: var(--primary); }
.task-g-title { font-size: 14px; font-weight: 600; }
.task-g-meta { font-size: 12px; color: var(--text-3); margin-top: 4px; }
/* ===== 阶段D81：工程进度计划表（甘特图） ===== */
.sch-gantt { border: 1px solid var(--border-soft); border-radius: 10px; overflow: hidden; }
.sch-gantt-row { display: flex; align-items: center; border-bottom: 1px solid var(--border-soft); }
.sch-gantt-row:last-child { border-bottom: none; }
.sch-gantt-hdr { background: var(--bg); font-weight: 600; color: var(--text-2); }
.sch-gantt-label { flex: 0 0 190px; padding: 8px 10px; font-size: 12px; font-weight: 600; border-right: 1px solid var(--border-soft); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sch-gantt-bar-wrap { position: relative; flex: 1; height: 34px; margin: 4px 6px; background: var(--bg); border-radius: 6px; overflow: hidden; }
.sch-gantt-bar { position: absolute; top: 4px; bottom: 4px; border-radius: 4px; opacity: .85; }
.sch-phase { display: flex; align-items: center; gap: 6px; padding: 8px 10px; border: 1px solid var(--border-soft); border-radius: 10px; margin-bottom: 8px; background: var(--surface); }
.sch-phase-name { flex: 1; min-width: 80px; padding: 7px 10px; border: 1.5px solid var(--border); border-radius: 8px; font-size: 13px; outline: none; }
.sch-phase input[type=number] { padding: 7px 8px; border: 1.5px solid var(--border); border-radius: 8px; font-size: 13px; outline: none; text-align: center; background: #fff; color: var(--text); }
/* ===== 阶段D82b：进度计划完整版（角色库拖拽 + 阶段拖拽 + 卡片） ===== */
.sch-mid { display: flex; gap: 14px; align-items: flex-start; }
.sch-pools { width: 150px; flex-shrink: 0; border: 1px solid var(--border-soft); border-radius: 10px; padding: 8px; background: var(--surface); }
.sch-pool { margin-bottom: 6px; }
.sch-pool-hdr { display: flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600; cursor: pointer; padding: 6px 4px; border-bottom: 1px solid var(--border-soft); }
.sch-pool-body { padding: 4px 2px; }
.sch-pool-item { font-size: 12px; padding: 5px 8px; border: 1px solid var(--border-soft); border-radius: 6px; margin-bottom: 4px; cursor: grab; background: var(--surface); }
.sch-pool-item:hover { border-color: var(--primary); }
.sch-pool-item[draggable="true"], .sch-tl-card[draggable="true"], .sch-phase-drag { touch-action: none; }
.sch-timeline { flex: 1; min-width: 0; }
.sch-phase { border: 1px solid var(--border-soft); border-radius: 10px; margin-bottom: 10px; background: var(--surface); padding: 8px 10px; }
.sch-phase[draggable="true"] { cursor: grab; }
.sch-phase-hdr { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.sch-phase-drag { cursor: grab; color: var(--text-3); font-size: 14px; margin-right: 2px; }
.sch-phase-cards { display: flex; flex-wrap: wrap; gap: 6px; padding: 8px 4px 2px; min-height: 34px; }
.sch-phase-empty { font-size: 11px; color: var(--text-3); padding: 6px 4px; }
.sch-tl-card { font-size: 12px; padding: 5px 10px; border-radius: 8px; display: inline-flex; align-items: center; gap: 6px; }
.sch-tl-desc { font-size: 10px; color: var(--text-3); max-width: 120px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sch-tl-close { font-size: 10px; color: var(--red); cursor: pointer; padding: 0 2px; }
.sch-phase-ro { padding: 10px; }
/* ===== 阶段D82：后台工作台（超管全屏；财务门户 + 进度计划） ===== */
.workbench-root { position: fixed; inset: 0; z-index: 2000; display: flex; flex-direction: column; background: var(--bg); }
.workbench-top { display: flex; align-items: center; gap: 16px; padding: 12px 20px; background: var(--surface); border-bottom: 1px solid var(--border-soft); box-shadow: var(--shadow-sm); }
.workbench-title { font-size: 18px; font-weight: 700; }
.workbench-tabs { display: flex; gap: 6px; }
.wb-tab { border: 1px solid var(--border); background: #fff; color: var(--text-2); padding: 8px 20px; border-radius: 999px; font-size: 13px; font-weight: 600; cursor: pointer; }
.wb-tab.active { background: var(--primary); border-color: var(--primary); color: #fff; }
.workbench-close { margin-left: auto; border: 1px solid var(--border); background: #fff; color: var(--text-2); padding: 8px 20px; border-radius: 999px; font-size: 13px; font-weight: 600; cursor: pointer; }
.workbench-close:hover { border-color: var(--red); color: var(--red); }
.workbench-body { flex: 1; overflow: hidden; padding: 16px 20px; }
.wb-panel { display: none; height: 100%; overflow-y: auto; }
.wb-panel.active { display: block; }
.wb-kpis { display: flex; gap: 12px; flex-wrap: wrap; margin-bottom: 16px; }
.wb-kpi { background: var(--surface); border: 1px solid var(--border-soft); border-radius: 12px; padding: 14px 18px; min-width: 130px; box-shadow: var(--shadow-sm); }
.wb-kpi-label { font-size: 12px; color: var(--text-3); margin-bottom: 4px; }
.wb-kpi-val { font-size: 18px; font-weight: 700; }
.wb-subnav { display: flex; gap: 6px; margin-bottom: 14px; flex-wrap: wrap; }
.wb-sub { border: 1px solid var(--border); background: #fff; color: var(--text-2); padding: 6px 14px; border-radius: 999px; font-size: 12px; font-weight: 600; cursor: pointer; }
.wb-sub.active { background: var(--primary); border-color: var(--primary); color: #fff; }
.wb-bar { display: flex; gap: 8px; align-items: center; margin-bottom: 12px; flex-wrap: wrap; }
.wb-bar select, .wb-bar input { padding: 8px 10px; border: 1.5px solid var(--border); border-radius: 9px; font-size: 13px; outline: none; background: #fff; }
.wb-btn { border: 1px solid var(--border); background: #fff; color: var(--text); padding: 8px 16px; border-radius: 999px; font-size: 13px; font-weight: 600; cursor: pointer; }
.wb-btn:hover { border-color: var(--primary); color: var(--primary); }
.wb-mini { border: 1px solid var(--border); background: #fff; color: var(--text-2); padding: 3px 10px; border-radius: 999px; font-size: 11px; cursor: pointer; margin-right: 4px; }
.wb-mini:hover { border-color: var(--primary); color: var(--primary); }
.wb-table-wrap { overflow: auto; max-height: 62vh; background: var(--surface); border: 1px solid var(--border-soft); border-radius: 12px; }
.wb-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.wb-table th { background: var(--bg); padding: 10px 10px; text-align: left; font-weight: 600; color: var(--text-2); border-bottom: 1px solid var(--border-soft); white-space: nowrap; position: sticky; top: 0; }
.wb-table td { padding: 9px 10px; border-bottom: 1px solid var(--border-soft); white-space: nowrap; }
.wb-table tr:hover td { background: var(--primary-soft); }
.wb-pill { display: inline-block; padding: 2px 10px; border-radius: 999px; font-size: 11px; font-weight: 600; }
.wb-pill.green { background: var(--green-soft); color: var(--green); }
.wb-pill.red { background: var(--red-soft); color: var(--red); }
.wb-h4 { margin: 0 0 12px; font-size: 15px; }
.wb-report-cards { display: flex; gap: 12px; flex-wrap: wrap; margin-bottom: 14px; }
.wb-report-card { background: var(--surface); border: 1px solid var(--border-soft); border-radius: 12px; padding: 14px 18px; min-width: 140px; box-shadow: var(--shadow-sm); }
.wb-report-card .wb-kpi-val { font-size: 20px; }

/* 项目列表折叠：第 7 个起折叠，展开/收起按钮 */
.project-fold-bar { display: flex; justify-content: center; padding: 12px 16px; border-bottom: 1px solid var(--border-soft); }
.project-fold-bar button { border: 1px solid var(--border); background: #fff; border-radius: 999px; padding: 7px 18px; font-size: 12px; font-weight: 600; cursor: pointer; }

/* ===== AI 装修管家（D84+ 渐变 AI 视觉） ===== */
.da-modal { padding: 0 !important; }
.da-modal .modal-x { top: 14px; right: 16px; }
.da-hero { background: linear-gradient(135deg, #e9ad2e 0%, #d99b16 55%, #c18408 100%); color: #fff; padding: 22px 24px 18px; }
.da-hero-title { font-size: 18px; font-weight: 700; }
.da-hero-sub { font-size: 11px; opacity: .85; margin-top: 4px; }
.da-modal #da-msgs { margin: 14px 16px 0; }
.da-modal #da-input, .da-modal #da-send, .da-modal .code-rule-note { margin-left: 16px; margin-right: 16px; }
.da-modal > div:last-child { margin-bottom: 16px; }

/* 快速记账弹窗：加载动画 */
.spin { display: inline-block; width: 14px; height: 14px; border: 2px solid rgba(99,102,241,.3); border-top-color: var(--primary); border-radius: 50%; animation: rot .8s linear infinite; vertical-align: -2px; margin-right: 6px; }
/* D272：加载等待动画（圆形旋转，仿 harness 公网加载）——所有"加载中..."提示统一加转圈，让用户知道在加载 */
.loading-state { display: flex; align-items: center; justify-content: center; gap: 10px; padding: 28px 0; color: var(--text-3); font-size: 13px; }
.loading-state .loading-spinner { width: 26px; height: 26px; border: 3px solid rgba(99,102,241,.2); border-top-color: var(--primary); border-radius: 50%; animation: rot .8s linear infinite; flex-shrink: 0; }
@keyframes rot { to { transform: rotate(360deg); } }
/* D272b：顶栏品牌显示完整口号（较长），窄屏允许换行防止挤压右侧按钮 */
.topbar { flex-wrap: wrap; row-gap: 4px; }

/* ===== 项目文件夹（D86：项目总览「文件」tab） ===== */
.pf-row:last-child { border-bottom: none !important; }
.pf-row[data-dir]:hover { background: var(--primary-soft) !important; }
#pf-upload:hover { border-color: var(--primary); color: var(--primary); background: var(--primary-soft) !important; }

/* ===== 阶段D123：流程卡片超管删除按钮 ===== */
.flow-del { border: 1px solid var(--red); background: #fff; color: var(--red); font-size: 12px; font-weight: 600; padding: 3px 12px; border-radius: 999px; cursor: pointer; flex-shrink: 0; }
.flow-del:hover { background: var(--red-soft); }

/* ===== 阶段D139：角色功能配置——选中角色按钮高亮（原来 JS 有 .active 但 CSS 无样式，点选无反馈） ===== */
#rf-roles .rf-role { transition: all .15s ease; }
#rf-roles .rf-role:hover { border-color: var(--primary); color: var(--primary); }
#rf-roles .rf-role.active { background: var(--primary) !important; border-color: var(--primary) !important; color: #fff !important; font-weight: 600; box-shadow: 0 2px 8px rgba(99,102,241,.35); }

/* ===== 手机端：通知面板全宽自适应（D334 底部固定导航已按用户要求移除；[通知][我的]回归顶栏右侧显示） ===== */
@media (max-width: 768px) {
  /* 通知面板手机全宽自适应（桌面固定 width:320px 在窄屏会溢出） */
  #notif-panel { left: 8px !important; right: 8px !important; width: auto !important; top: 50px !important; }
}

/* ===== D340d：考勤人员卡片视觉（浅灰底衬托白卡 + 边框阴影，避免卡片与背景融为一体） ===== */
.att-grid {
  display: flex; flex-wrap: wrap; gap: 12px;
  background: #e9ebef;
  border: 1px solid #e2e5e9;
  border-radius: 16px;
  padding: 14px;
}
.att-card {
  position: relative;
  background: #fff;
  border: 1px solid #dde0e5;
  border-radius: 12px;
  box-shadow: 0 1px 2px rgba(15,23,42,.06);
}
.att-card:hover {
  border-color: #b9bfc9;
  box-shadow: 0 4px 14px rgba(15,23,42,.12);
}
.att-card .btn-ghost { box-shadow: none; }

/* ===== D36n：进度计划甘特图打印按钮（主端弹窗标题栏 / 门户工具栏，统一样式） ===== */
.sch-print-btn {
  display: inline-flex; align-items: center; gap: 6px;
  border: 1px solid #cfe0f5;
  background: linear-gradient(180deg, #f4f9ff, #e8f2fe);
  color: #1d4e79; border-radius: 999px; padding: 7px 16px;
  font-size: 12px; font-weight: 600; cursor: pointer; white-space: nowrap;
  box-shadow: 0 1px 2px rgba(29, 78, 121, .06);
  transition: background .15s, border-color .15s, box-shadow .15s, transform .1s;
}
.sch-print-btn:hover { background: linear-gradient(180deg, #eaf4ff, #d9eaff); border-color: #a9cdf0; color: #15406a; box-shadow: 0 2px 6px rgba(29, 78, 121, .14); }
.sch-print-btn:active { transform: translateY(1px); }
.sch-print-btn.sm { padding: 5px 12px; font-size: 11px; }
.sch-print-btn.lg { padding: 9px 20px; font-size: 13px; }

/* ===== 阶段D85：项目列表悬浮按钮不触碰时半透明（减少遮挡聊天区阅读），触碰时恢复不透明 ===== */
#fab-projects { opacity: .7; transition: opacity .18s ease; }
#fab-projects:hover, #fab-projects:active, #fab-projects:focus-visible { opacity: 1; }

/* ===== 阶段D36h340（老板 2026-09-30 亲报：「卡片模版页面高度会自动慢慢减小是为什么，不应该是固定的吗？」）=====
   老板这一句**否掉了上一轮（D36h339）为「卡片模板」页开的那条例外** —— 上一轮的原话是"除了卡片模版可以不同"，
   本轮改成：**所有设置页（含卡片模板）共用同一个固定高度**，不许再有任何一页把高度放回内容自适应。

   ■ 「慢慢减小」的真机制（三条叠加；逐条用代码/样式判据复核过，详见开发日志 D36h340 第 0 步）
     ① 闭环（根因）：上一轮那条例外让 `.modal` 的高度 = 内容高度 = f(画布高 H)；
        而 flow-board.js 的 fitBoard() 反过来把 H 算成"画布要贴到容器底边" ⇒ H = g(弹窗底边) ⇒ H = g(f(H))，自我反馈。
        又因为上面 .modal-mask 那条把弹窗**竖直居中**（display:flex + align-items:center），
        高度变 Δ 时**底边只移动 Δ/2**（顶边反向 Δ/2）⇒ 闭环增益 = ½ ⇒ 每迭代一次位移减半：
        序列 R, R/2, R/4 …（指数衰减）—— 这就是"慢慢"而不是"一下"。
     ② 驱动（"自动"）：flow-board.js 那边原来是 `setInterval(fitBoard, 1200)` **无条件永久**每 1.2 秒重测一次；
        而 ResizeObserver 盯的又正是承载画布的那个滚动容器（它当时的高度也是画布高度的函数）⇒ 自己触发自己。
     ③ 叠加（不收敛到 0）：`.modal-body` 原来是 overflow-y:auto ⇒ 滚动条随内容出现/消失 ⇒ 可用宽度 ±15px ⇒
        选卡带（repeat(auto-fill,minmax(74px,1fr)) 的网格）与工具条（flex-wrap:nowrap + overflow-x:auto）的
        列数/换行跟着变 ⇒ 画布上下的内容高度又变 ⇒ 闭环永远在不动点附近微微动。
     ⇔ 排除项（本轮逐条核过，都不是）：全 app.css 23 处 transition / 3 处 animation 没有一条落在
        .modal / .modal-body / .st-panel / 画布上，也没有 height、max-height、all 这类目标（命中的都是按钮/卡片/
        抽屉/进度条）；@media (max-height:640px) 只看**视口**，内容高度穿不过它 ⇒ 不是媒体查询在来回切。

   ■ 本轮怎么堵（三处独立，任何一处单独拿出来都能断掉这条链）
     A. 切断闭环：删掉卡片模板那条例外，`.modal.st-modal` 一个固定高度管所有设置页 ——
        弹窗高度不再是画布高度的函数 ⇒ fitBoard 量出来的 room 变成**常数** ⇒ 一次对齐就到位，没有第二次位移。
     B. 消掉滚动条反馈环：`.modal-body` 改成常显滚动条（overflow-y:scroll）——
        可用宽度不再随内容变 ⇒ 选卡带列数、工具条换行稳定。
     C. 去掉永久重测：触发器合并成同一帧只量一次（requestAnimationFrame 合并），
        且"连续几次量出来都一样就自停"，不再无条件每 1.2 秒轮询一次（在 public/js/flow-board.js 里）。

   ■ 卡片模板页现在怎么滚：高度与别的设置页**一模一样**；返回条 `.st-backbar` 吸顶、工具条在面板顶部，
     滚的是 `.modal-body` 里那一块内容（41 张卡的画布在中间；画布自身 overflow:hidden，靠拖动/缩放看全，
     不靠滚动条）。
   ■ 窄屏**保留**回落（宽度 ≤720px 或视口高 ≤640px ⇒ 回内容自适应 + 上限贴视口，手机上固定高会把内容裁掉）——
     回落对所有设置页一视同仁，不留任何针对某一页的特例。 */
.modal.st-modal { height: min(84vh, 920px); }
.modal.st-modal .modal-body { overflow-y: scroll; }
/* 窄屏 / 窗口很矮：回落成自适应高度 + 上限贴视口（手机上固定高会把内容裁掉、看不全） */
@media (max-width: 720px), (max-height: 640px) {
  .modal.st-modal { height: auto; max-height: calc(100dvh - 32px); }
}

/* ===== 阶段D36h341（老板 2026-09-30 亲报：「宽度也会变」＋「卡片模版的子tab按钮文字和背景色需要和其他统一」）=====
   本轮只做两件事，**高度一个字不动**（D36h340 的固定高度 min(84vh,920px) 与窄屏 @media 回落原样保留）：
     ① 设置弹窗的**宽度**也钉成常数 —— 与高度同一个口径：所有设置页同一个尺寸，切页签/切类别纹丝不动；
     ② 注入的两个页签（卡片模板 / 规则模板）配色回归标准 `.st-tab`（改的是注入脚本自己带的样式，不是再叠一层覆盖）。

   ■ 「宽度也会变」的真机制（第 0 步逐条查证，见开发日志 D36h341）—— **不是内容把盒子顶开的**：
     public/js/flow-board.js 的 ensureCss() 往 <head> 注入过一条
       `.modal-mask:has(.st-tabs) .modal{max-width:97vw!important;width:97vw!important}`
     它带 !important，压过 `.cw-modal{width:640px;max-width:94vw}`（本文件 :664）⇒ 一进「卡片模板」页就把设置弹窗拉到 97vw；
     而那个样式节点注入之后**从不移除**（ensureCss 见 exists 就 return）⇒ 切回别的页签也回不到窄的样子。
     ⇒ 根治＝**删掉那条规则**（本轮已在 public/js/flow-board.js 里删除），宽度只由下面这一条常数决定。

   ■ 为什么还要 min-width:0：`.modal` 是 `.modal-mask`（display:flex）的 flex 子项，默认 `min-width:auto`
     ＝ min-content ⇒ 一旦某页内容的 min-content 比 640px 宽，弹窗**照样会被内容顶宽**（内容驱动）。
     `min-width:0` 把这条自动下限摘掉 ⇒ 宽度 = 常数，与页签内容无关；过宽的内容由 `.modal-body`
     自己横向滚（它已是滚动容器：`overflow-y:scroll` ⇒ `overflow-x` 计算为 auto）。

   ■ 宽度取 640px 的理由：这是**现状值**（`.cw-modal{width:640px}`，老板截图里"初始窄的那个"就是这个），
     本轮**不擅自变宽**，只把"会变"变成"不变"。
   ■ 卡片模板页在窄框里怎么办：画布容器 `.fb-canvas` 改由**自己横向滚**（public/js/flow-board.js），
     不再往外层弹窗借宽度；画布的拖动/缩放/「适应屏幕」照旧。
   ■ 窄屏：`min(640px,94vw)` 自带 94vw 上限（手机上就是 94vw）；高度那条窄屏 @media 回落保留，本轮不动。 */
.modal.st-modal { width: min(640px, 94vw); max-width: 94vw; min-width: 0; }

/* ===== 阶段D36h342（老板 2026-09-30 亲口要：「设置页面帮我加一个弹窗最大化的按钮，根据页面需求自己切换」）=====
   ■ 本轮只做**手动切换**：右上角一颗「最大化 / 还原」按钮（app.js 运行时建在设置弹窗盒子下、.modal-x 左边）。
     切页签 / 切类别 / 进出「卡片模板」时宽高**一个字都不许动** —— 「阶段D36h340」的固定高度与「阶段D36h341」的
     固定宽度两条规则**原样保留、逐字未改**；**不做"自动最大化"**（那是另一个决定，见 app.js 里 applyMax 那段的说明）。

   ■ 两种态的尺寸（都是**常数**，与内容多少无关）：
       普通态（现状，一个字没改）：  width: min(640px, 94vw)  ＋ max-width: 94vw ＋ min-width: 0
                                     height: min(84vh, 920px)
       最大化态（下面那条规则）：    width: min(1600px, 97vw) ＋ max-width: 97vw ＋ min-width: 0
                                     height: min(94vh, 1100px)
   ■ 为什么宽高都取「常数 + 上限」这个形状：
       · 宽度取 **97vw** —— 与老板说"最大化"时的直觉一致（D36h341 删掉的那条注入规则当年就是 97vw），
         留 3vw 边距 ⇒ **永远不会溢出屏幕**（是"放到最大"而不是"全屏"）；再加 **1600px 上限**：
         超宽屏（2560 / 3440）上不铺成一条又长又扁的带子，正文一行别拉太长（可读性）。
       · 高度取 **94vh**（比普通态 84vh 抬一档，给画布 / 长清单多留可视区），再加 **1100px 上限**：
         超高屏上不把内容摊成一大片空白。
       · min-width: 0 与普通态同因：.modal 是 .modal-mask（display:flex）的 flex 子项，默认
         min-width:auto＝min-content ⇒ 不摘掉，"内容比框宽"时弹窗**照样会被内容顶宽**（内容驱动）。
       · 这条规则**只吃 .modal.st-modal.st-max**（设置弹窗 + 老板点过最大化）⇒ 不外溢到别的 cw-modal，
         也不影响普通态（普通态根本不带 st-max 这个类）。
   ■ 结构性不变量（最大化**只改尺寸**，结构一个字不动）：
       · 弹窗盒子仍是 .modal-scroll（app.js applyModalScroll 加的）：app.js 的标题与 .modal-x 留在
         弹窗盒子里（不滚），其余内容整体进 .modal-body；
       · 于是**固定的**是：标题 + ✕（含本轮的按钮）＋ 位于滚动区内部的吸顶返回条（sticky top:0）
         ＋ 底部 .modal-actions（「保存」，它在 .modal-body **外面**）；
         **滚的只有**中间的 .modal-body（overflow-y:scroll，滚动条常显 ⇒ 宽度不随内容抖）。
       · 下面这条最大化规则**只声明尺寸类属性**（width / max-width / min-width / height / max-height），
         一个字都不碰 position / display / overflow / flex ⇒ **不可能改变谁滚谁不滚**（护栏钉住这条）。
   ■ 窄屏 / 矮窗口：最大化态走**同一条**回落（高度回内容自适应 + 上限贴视口）——
     手机上视口本来就不比 640px 宽多少，"最大化"在那里约等于 97vw × 自适应高，**绝不溢出屏幕**。 */
.modal.st-modal .st-max-btn { position: absolute; top: 12px; right: 56px; z-index: 6; box-sizing: border-box; border: 1px solid var(--border); background: #fff; color: var(--text-2); border-radius: 999px; padding: 6px 12px; font-size: 12.5px; font-weight: 600; line-height: 1.2; cursor: pointer; }
.modal.st-modal .st-max-btn:hover { border-color: var(--primary); color: var(--primary); background: var(--primary-soft); }
.modal.st-modal.st-max { width: min(1600px, 97vw); max-width: 97vw; min-width: 0; height: min(94vh, 1100px); }
/* 窄屏 / 窗口很矮：最大化态也回"内容自适应 + 上限贴视口"（手机上不许溢出屏幕） */
@media (max-width: 720px), (max-height: 640px) {
  .modal.st-modal.st-max { height: auto; max-height: calc(100dvh - 32px); }
}

/* ===== 阶段D36h357：项目头部横条（项目名 + 项目总览 + AI装修管家）不被左侧「项目列表」竖标签压住 =====
   老板 2026-10-01 亲报：「项目名称，项目总览和 ai 装修管家这一个横条老是会被挡住」。
   真浏览器实测（CDP，390×844 / 500×1000，顶部/中间/底部三个滚动位置）改前几何：
     · 横条 .chat-header        = y 60→101（41px 高，position:sticky），**z-index 只有 30**
     · 左侧竖标签 #fab-projects = x 0→46、y 111→193，position:absolute 在 #chat-body(position:relative) 里，**z-index 60**
     · 两者垂直间隙 = 111 − 101 = **只有 10px**；而竖标签的阴影 `0 6px 18px` 向上溢 18 − 6 = **12px**
       ⇒ 阴影实际够到 y≈99，**已经爬进横条底边 2px**（老板看到的"横条被挡掉一截"就是这个）
   根因：**层叠顺序反了** —— 竖标签的 z-index(60) 高于横条(30)，中间又只剩 10px，
   任何一点几何变化都由横条承担后果（"老是会被挡住"）。
   修法（只调 z-index / top / box-shadow；不动 position、不动结构、不碰 app.js）：
     · 横条提到 z-index 70：比竖标签(60)、聊天内容都高；**仍低于**底栏 .chat-dock(80)
       与各类遮罩(95/96/100/150) ⇒ 弹窗与底栏的层级一点没变。
     · 竖标签从 top:10px 让到 16px（安全间距 10px → 16px），并把向上溢出的阴影收成
       `0 2px 8px`（向上只够 8 − 2 = 6px < 16px）⇒ 阴影再也够不到横条。
   ★已查清、**本轮没改**（越出范围）：手机端通知面板 #notif-panel 锚在 top:50px（沿用一个"顶栏 41px 高"的
     过时口径，实测顶栏 60px），展开时顶边比顶栏底边还高 10px，并整条盖住横条 ——
     实测交集 362×24 = 8688 px²（390×844）/ 472×24 = 11328 px²（500×1000）、横条三件可点率 0/12。
     它压的是"横条"，而横条本来就在顶栏**下面** ⇒ 任何挂在顶栏上的下拉都会盖住它；要盖不住得把
     top 提到 109px（顶栏60＋横条41＋8），代价是下拉框与「通知」按钮之间空出 41px。留待老板定。
   护栏：`test/d36h357-header-overlap-guard.test.mjs`（机械判定层叠顺序 / 安全间距 / 阴影够不到横条）。 */
.chat-header { z-index: 70; }
#fab-projects { top: 16px; box-shadow: 0 2px 8px rgba(16,24,40,.10), 0 0 1px rgba(16,24,40,.18); }

/* ===== 阶段D36h369d + D36h369e：手机端(≤700px)后台工作台外壳 =====
   老板 2026-10-09：「财务一本账手机端我看了一下界面很乱」—— 我实测（CDP 390×844，同一账号）：
     · .workbench-body 左右各 20px padding ⇒ 嵌进去的一本账**只有 350px 宽**（屏 390）
     · .workbench-tabs 是 `display:flex` 且**没有 flex-wrap** ⇒ 4 个页签在 390px 里被挤到
       每个只剩几十像素，"财务一本账"竖着排成**一个字一行**，白占顶部约 270px（截图 d369d4-工作台-一本账.png）
   修法（只在这个媒体查询里加规则；不动 .workbench-root 的 fixed/inset，不动任何 JS 逻辑）：
     · 顶栏允许换行；页签行独占一行 + 不换行 ⇒ 不再竖排
     · 标题缩小、公司chip只留名字、body 内边距收到 10px（把宽度还给内容）
   配套：`public/app-extra.js` 的 renderLedgerTab 在手机宽度下**整页打开**一本账（不再套 iframe，
   否则永远是"350px 的框里滚 3.9 屏"）。护栏见 test/d36h369d-fe2-mobile-skin.test.mjs。

   ★D36h369e（当天晚上老板反馈「那其他出纳台、控制台等页面我怎么没找到入口？」后统一改的）：
     第一版我把 .workbench-tabs / .wb-subnav 做成了**横滑不换行**（overflow-x:auto + nowrap）——
     省高度，但手机上**没有"这里能滑"的提示**，后面的页签（进度计划 / 工程报价 / 各子页）等于藏起来了，
     和一本账那边一模一样的毛病。现在统一成 **入口类一律换行铺开**：只有宽表才横滑。
     4 个页签在 390px 里换行后约 2 行（每行 40px），比竖排字那 270px 省得多，而且一个都不藏。 */
@media (max-width:700px) {
  .workbench-top { flex-wrap: wrap; gap: 8px 10px; padding: 10px 12px; }
  .workbench-title { font-size: 15px; }
  /* 页签：换行铺开（D36h369e 改），不要再加 overflow-x:auto —— 横滑会把入口藏起来 */
  .workbench-tabs { order: 3; flex: 1 1 100%; display: flex; flex-wrap: wrap; gap: 6px; }
  .wb-tab { flex: 0 1 auto; white-space: nowrap; padding: 9px 15px; min-height: 40px; }
  .workbench-right { gap: 8px; }
  #wb-ent { padding: 7px 11px; font-size: 12px; }
  #wb-ent #wb-ent-name { max-width: 96px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .workbench-close { padding: 9px 15px; min-height: 40px; }
  .workbench-body { padding: 10px; }
  /* 子导航同理：换行铺开 */
  .wb-subnav { flex-wrap: wrap; }
  .wb-sub { flex: 0 1 auto; white-space: nowrap; min-height: 38px; }
}

/* ===== 阶段D36h508（老板 2026-11-07：「好的，现在把副本更新到主系统中吧」）=====
   工人打卡弹窗换皮：设计稿在 deliverables/d36h505-checkin-redesign/index.html。
   铁律（与 D36h507 一致）：**只换皮肤，不动逻辑** ——
     · #wck-dist / #wck-btns / #wck-makeup-* / #wck-flow / #wck-drop / #wck-preview /
       #wck-video-* / #wck-ok 这些 id 一个都没改，app.js 里的绑定与提交链路原样；
     · 三按钮的「能不能点 / 选中态 / aria-disabled / opacity .38」仍由 renderWckState 驱动，
       本块只负责图标、卡片形状、间距与配色；
     · 手机端（≤700px）整屏下拉式（100dvh），桌面端仍是居中的窄卡片。
   为什么不用 :has()：settings-uniform-height-guard ⑧-2 明令禁止在 app.css 里给弹窗开
   `.modal-mask:has(...)` 特例 —— 这里靠 app.js 给弹窗盒子加的 .wck2 类名作用域化。 */
.wck2 {
  display: flex;
  flex-direction: column;
  box-sizing: border-box;
  width: min(430px, calc(100vw - 24px));
  max-width: calc(100vw - 24px);
  height: min(900px, calc(100dvh - 40px));
  max-height: calc(100dvh - 40px);
  padding: 0;
  border-radius: 24px;
  background: #fff;
  overflow: hidden;
}
.wck2 > h3 {
  flex: 0 0 auto;
  margin: 0;
  padding: 20px 60px 14px 20px;
  border-bottom: 1px solid #f1f3f7;
  font-size: 19px;
  font-weight: 800;
  line-height: 1.35;
  letter-spacing: -.2px;
  color: #0f172a;
}
.wck2 > .modal-x {
  top: 14px;
  right: 14px;
  width: 34px;
  height: 34px;
  padding: 0;
  border-radius: 50%;
  background: #f3f5f9;
  color: #64748b;
  font-size: 15px;
  display: grid;
  place-items: center;
}
.wck2 > .modal-x:hover { background: #e9edf5; color: #334155; }
.wck2 > .modal-body { padding: 14px 18px 18px; -webkit-overflow-scrolling: touch; }
.wck2 *,
.wck2 *::before,
.wck2 *::after { box-sizing: border-box; }
.wck2 > .modal-body { flex: 1 1 auto; min-height: 0; overflow-x: hidden; }

.wck2 .wck2-state {
  display: flex;
  align-items: center;
  gap: 9px;
  margin: 2px 0 2px;
  padding: 12px 14px;
  border: 1px solid #eef1f6;
  border-radius: 16px;
  background: #f8fafc;
}
.wck2 .wck2-dot {
  flex: 0 0 9px;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: #f59e0b;
  box-shadow: 0 0 0 4px #fef3c7;
}
.wck2 .wck2-state-copy {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 12px;
  font-weight: 600;
  line-height: 1.55;
  color: #334155;
}
.wck2 .wck2-state-time { flex: 0 0 auto; font-size: 11px; color: #94a3b8; white-space: nowrap; }

.wck2 .wck2-label {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin: 18px 0 9px;
  font-size: 13px;
  font-weight: 800;
  color: #334155;
}
.wck2 .wck2-label small { font-size: 11px; font-weight: 500; color: var(--text-3); }
.wck2 .wck2-modes { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.wck2 .wck-mode {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 100%;
  max-width: 100%;
  min-width: 0;
  min-height: 84px;
  transition: border-color .15s, background .15s, transform .15s;
}
.wck2 .wck-mode svg { width: 20px; height: 20px; margin-bottom: 6px; }
.wck2 .wck-mode .wck2-mlabel { display: block; font-size: 13px; font-weight: 800; line-height: 1.3; white-space: nowrap; }
.wck2 .wck-mode .wck2-msub {
  display: block;
  max-width: 100%;
  margin-top: 3px;
  font-size: 10px;
  font-weight: 400;
  line-height: 1.35;
  color: #a1a9bb;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.wck2 .wck-mode[aria-disabled="true"] { background: #fbfbfd; }
.wck2 .wck-mode[data-on="1"] { box-shadow: 0 4px 14px rgba(79,70,229,.12); }

.wck2 .wck2-alert {
  display: flex;
  gap: 10px;
  padding: 12px 14px;
  border: 1px solid #fde4b3;
  border-radius: 16px;
  background: #fff7e6;
  color: #92400e;
}
.wck2 .wck2-alert strong { display: block; font-size: 12.5px; font-weight: 800; line-height: 1.55; }
.wck2 .wck2-alert span { display: block; margin-top: 3px; font-size: 11.5px; line-height: 1.55; opacity: .82; }

.wck2 .wck2-field-label {
  display: block;
  margin: 14px 0 6px;
  font-size: 12.5px;
  font-weight: 700;
  color: #475569;
}
.wck2 .wck2-field-label small { margin-left: 4px; font-weight: 500; color: var(--text-3); }
.wck2 select,
.wck2 input[type="text"] {
  width: 100%;
  box-sizing: border-box;
  border: 1.5px solid #e7eaf1;
  border-radius: 14px;
  padding: 12px 14px;
  font-size: 13px;
  color: #334155;
  background: #fff;
  outline: none;
}
.wck2 select:focus,
.wck2 input[type="text"]:focus { border-color: var(--primary); box-shadow: 0 0 0 4px rgba(79,70,229,.09); }

.wck2 .wck2-photo {
  padding: 22px 14px;
  border: 1.5px dashed #cfd5e3;
  border-radius: 16px;
  background: #fbfcff;
  text-align: center;
  font-size: 13px;
  font-weight: 600;
  color: #64748b;
  cursor: pointer;
}
.wck2 .wck2-photo:active { border-color: #a5b4fc; background: #f8f8ff; }
.wck2 .wck2-preview { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }

.wck2 .wck2-video { margin-top: 14px; }
.wck2 .wck2-video-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 8px;
  padding: 12px 13px;
  border: 1px solid #eef1f6;
  border-radius: 15px;
  background: #fafbfe;
  font-size: 12.5px;
  font-weight: 700;
  color: #475569;
  cursor: pointer;
}
.wck2 .wck2-video-row span { flex: 1 1 100%; font-size: 10.5px; font-weight: 400; color: #a0a8b8; }
.wck2 .wck2-video-preview { margin-top: 6px; font-size: 12px; color: var(--text-2); }

.wck2 .wck2-safety {
  display: flex;
  align-items: flex-start;
  gap: 6px;
  margin: 14px 2px 0;
  font-size: 10.5px;
  line-height: 1.55;
  color: #98a1b1;
}

.wck2 > .modal-actions {
  position: static;
  inset: auto;
  width: 100%;
  margin: 0;
  padding: 12px 18px calc(14px + env(safe-area-inset-bottom));
  background: #fff;
  border-top: 1px solid #eef1f6;
  box-shadow: 0 -10px 24px rgba(15,23,42,.05);
}
.wck2 > .modal-actions .ok {
  flex: 1 1 100%;
  width: 100%;
  padding: 15px 16px;
  border-radius: 16px;
  background: linear-gradient(180deg, #6366f1, #4f46e5);
  font-size: 15px;
  font-weight: 800;
  letter-spacing: .2px;
  box-shadow: 0 8px 20px rgba(79,70,229,.22);
}
.wck2 > .modal-actions .ok:disabled { background: #dfe3ec; box-shadow: none; }

@media (max-width: 820px) {
  .wck2 {
    width: 100vw;
    max-width: 100vw;
    height: 100dvh;
    max-height: 100dvh;
    border-radius: 0;
  }
  .wck2 > h3 { padding: calc(16px + env(safe-area-inset-top)) 58px 13px 18px; font-size: 18px; }
  .wck2 > .modal-x { top: calc(12px + env(safe-area-inset-top)); right: 12px; }
  .wck2 > .modal-body { padding: 12px 16px 16px; }
}

/* ===== D36h522（老板 2026-11-09）：工人打卡弹窗 = 打卡设计副本的定位卡 + 弹窗内换项目 ===== */
.wck2-loc { margin-bottom: 10px; padding: 14px 15px; border: 1px solid #e6eaf2; border-radius: 18px; background: linear-gradient(180deg, #fbfcff, #f8faff); }
.wck2-loc-top { display: flex; align-items: flex-start; gap: 9px; }
.wck2-pin { flex: 0 0 24px; width: 24px; height: 24px; border-radius: 9px; background: var(--primary-soft, #eef2ff); color: var(--primary); display: grid; place-items: center; }
.wck2-pin svg { width: 14px; height: 14px; }
.wck2-loc-copy { flex: 1 1 auto; min-width: 0; }
.wck2-loc-copy strong { display: block; font-size: 14px; line-height: 1.45; font-weight: 800; color: #1e293b; }
.wck2-loc-copy strong b { font-weight: 800; }
.wck2-loc-copy span { display: block; margin-top: 3px; font-size: 11.5px; line-height: 1.5; color: #8791a5; }
.wck2-pill { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 4px; border-radius: 999px; padding: 5px 9px; font-size: 11px; font-weight: 800; white-space: nowrap; }
.wck2-pill.is-ok { background: var(--green-soft); color: #047857; }
.wck2-pill.is-bad { background: var(--red-soft); color: #b91c1c; }
.wck2-pill.is-warn { background: #fef3c7; color: #92400e; }
.wck2-loc-proj { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 11px; padding-top: 11px; border-top: 1px dashed #e8ebf3; font-size: 12px; line-height: 1.55; color: #64748b; }
.wck2-loc-proj b { color: #334155; }
.wck2-loc-proj > span { display: flex; align-items: center; gap: 7px; min-width: 0; }
.wck2-loc-proj b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wck2-tag { flex: 0 0 auto; font-style: normal; font-size: 10px; font-weight: 800; line-height: 1; padding: 4px 6px; border-radius: 6px; background: #eef2ff; color: #4338ca; }
.wck2-tag.is-manual { background: #ecfdf5; color: #047857; }
.wck2-tag.is-cur { background: #fef3c7; color: #92400e; }
.wck2-quick { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 8px; }
.wck2-chip { display: block; margin: 0; }
.wck2-chip > summary { list-style: none; display: inline-flex; align-items: center; gap: 5px; padding: 6px 10px; border-radius: 999px; background: #eef2ff; color: #4338ca; font-size: 12px; font-weight: 800; cursor: pointer; }
.wck2-chip > summary::-webkit-details-marker { display: none; }
.wck2-chip > summary i { font-style: normal; width: 15px; height: 15px; border-radius: 50%; display: grid; place-items: center; background: rgba(67, 56, 202, .12); font-size: 10px; }
.wck2-chip.is-warn > summary { background: #fef3c7; color: #92400e; }
.wck2-chip.is-warn > summary i { background: rgba(146, 64, 14, .12); }
.wck2-chip.is-bad > summary { background: var(--red-soft); color: #b91c1c; }
.wck2-chip.is-bad > summary i { background: rgba(185, 28, 28, .12); }
.wck2-chip-body { margin-top: 7px; padding: 9px 12px; border-radius: 12px; background: #f8fafc; border: 1px solid #eef1f6; color: #475569; font-size: 12px; line-height: 1.65; }
.wck2-link { flex: 0 0 auto; border: 0; background: transparent; color: var(--primary); font-size: 12px; font-weight: 800; padding: 4px 0; cursor: pointer; white-space: nowrap; }
.wck2-note { margin: 0 0 10px; padding: 9px 12px; border-radius: 12px; background: #f8fafc; border: 1px solid #eef1f6; color: #475569; font-size: 12px; line-height: 1.6; }
.wck2-note.is-warn { background: #fef3c7; border-color: #fde4b3; color: #92400e; }
.wck2-reloc { margin-top: 6px; padding: 6px 12px; border-radius: 9px; border: 1.5px solid var(--primary); background: #fff; color: var(--primary); font-size: 12px; font-weight: 700; cursor: pointer; }
.wck2 > .modal-actions { flex-direction: column; gap: 8px; }
.wck2-foot-hint { margin: 0; width: 100%; text-align: center; font-size: 10.5px; line-height: 1.5; color: #a0a8b8; }
/* 换项目弹窗 */
.wck-pick { width: min(430px, calc(100vw - 32px)); max-height: min(82vh, 640px); }
.wck-pick-list { display: flex; flex-direction: column; gap: 8px; }
.wck-pick-item { display: block; width: 100%; text-align: left; padding: 12px 14px; border: 1.5px solid var(--border); border-radius: 14px; background: #fff; cursor: pointer; }
.wck-pick-item b { display: block; font-size: 14px; line-height: 1.45; color: #1e293b; }
.wck-pick-item span { display: block; margin-top: 3px; font-size: 11.5px; line-height: 1.5; color: #8791a5; }
.wck-pick-item.is-current { border-color: var(--primary); background: #f5f4ff; }
.wck-pick-item.is-current b { color: var(--primary); }
.wck-pick-note { margin: 12px 0 0; font-size: 11.5px; line-height: 1.6; color: #8791a5; }

/* ===== D36h525（老板 2026-11-09）：聊天窗 / 业务卡 / 群内操作 / 入口弹窗
   统一到「展览管理」「财务端」的视觉：浅灰底 + 白卡 + 金色主色 + 大圆角 + 轻阴影。
   只做作用域换肤，不改 DOM / 流程；本块不写 !important。 ===== */
#view-timeline,
#drawer-panel,
.modal-mask,
.modal {
  --primary: #d99b16;
  --primary-soft: #fff6dd;
  --text: #172033;
  --text-2: #566072;
  --text-3: #8e97a8;
  --border: #e5e9f0;
  --border-soft: #eef1f6;
  --bg: #f4f6f9;
  --surface: #fff;
  --green: #0f9f6e;
  --green-soft: #e9f8f2;
  --red: #d94848;
  --red-soft: #fff0f0;
  --blue: #3568d4;
  --blue-soft: #eef4ff;
  --amber: #d99b16;
  --amber-soft: #fff6dd;
  --shadow-sm: 0 1px 2px rgba(16,24,40,.04);
  --shadow-md: 0 8px 26px rgba(20,35,60,.07);
  --shadow-lg: 0 24px 68px rgba(20,35,60,.16);
}

/* ---------- 聊天窗 ---------- */
#view-timeline { background: #f4f6f9; }
#view-timeline .chat-header {
  background: rgba(255,255,255,.94);
  border-bottom-color: #e5e9f0;
  box-shadow: 0 1px 2px rgba(16,24,40,.04);
  backdrop-filter: blur(10px);
}
#view-timeline .chat-project-name {
  color: #172033;
  font-size: 16px;
  font-weight: 800;
  letter-spacing: -.2px;
}
#view-timeline .chat-project-name::before {
  content: "";
  display: inline-block;
  width: 4px;
  height: 16px;
  margin-right: 8px;
  border-radius: 2px;
  background: #d99b16;
  vertical-align: -2px;
}
#view-timeline .overview-btn {
  border: 1px solid #e5e9f0;
  background: #fff;
  color: #566072;
  box-shadow: none;
  font-weight: 750;
}
#view-timeline .overview-btn:hover {
  border-color: #d99b16;
  background: #fffdf7;
  color: #b97c05;
}
#view-timeline .overview-btn.grad-ai-btn,
#view-timeline .overview-btn.grad-ai-btn:hover {
  border-color: transparent;
  color: #fff;
}
#view-timeline .chat-messages {
  background: #f4f6f9;
  padding: 16px 18px 24px;
}
#view-timeline .msg-row { margin-bottom: 12px; }
#view-timeline .msg-avatar {
  border-radius: 10px;
  background: linear-gradient(135deg, #f2b23a, #d99b16);
  box-shadow: 0 6px 16px -12px rgba(185,124,5,.7);
}
#view-timeline .msg-bubble {
  max-width: min(78%, 680px);
  padding: 10px 13px;
  border: 1px solid #e5e9f0;
  border-radius: 16px 16px 16px 6px;
  background: #fff;
  color: #172033;
  box-shadow: 0 8px 24px rgba(20,35,60,.06);
}
#view-timeline .msg-row.mine .msg-bubble {
  border-color: #f0d28d;
  border-radius: 16px 16px 6px 16px;
  background: linear-gradient(180deg, #fffdf7, #fff6dd);
}
#view-timeline .msg-time { color: #8e97a8; }
#view-timeline .msg-sys {
  width: fit-content;
  margin: 10px auto;
  border: 1px solid #e5e9f0;
  border-radius: 999px;
  background: #eef1f6;
  color: #8e97a8;
}
#view-timeline .fab-chat {
  border: 1px solid #e5e9f0;
  background: #fff;
  color: #8c6100;
  box-shadow: 0 8px 24px rgba(20,35,60,.08);
}
#view-timeline .fab-chat:hover {
  border-color: #f0d28d;
  background: #fffdf7;
  color: #b97c05;
}

/* ---------- 群内业务卡 ---------- */
#view-timeline .biz-card {
  max-width: min(92%, 760px);
  padding: 12px 14px;
  border: 1px solid #e5e9f0;
  border-left: 3px solid var(--ev-color, #d99b16);
  border-radius: 16px;
  background: #fff;
  box-shadow: 0 8px 26px rgba(20,35,60,.07);
  transition: box-shadow .16s, border-color .16s;
}
#view-timeline .biz-card:hover {
  border-color: #dbe1ea;
  box-shadow: 0 12px 34px rgba(20,35,60,.10);
}
#view-timeline .biz-card .event-head {
  gap: 10px;
  margin-bottom: 9px;
  padding-bottom: 8px;
  border-bottom: 1px solid #eef1f6;
}
#view-timeline .biz-card .event-icon {
  width: 30px;
  height: 30px;
  border-radius: 10px;
  background: var(--ev-bg, #fff6dd);
}
#view-timeline .biz-card .event-type-badge {
  border: 1px solid rgba(20,35,60,.04);
  border-radius: 999px;
  background: var(--ev-bg, #fff6dd);
  color: var(--ev-color, #b97c05);
  font-weight: 750;
}
#view-timeline .biz-card .event-body { font-size: 13.5px; line-height: 1.65; }
#view-timeline .biz-card .event-actions button {
  padding: 7px 14px;
  border: 1px solid #e5e9f0;
  border-radius: 999px;
  background: #fff;
  color: #566072;
  font-weight: 750;
}
#view-timeline .biz-card .event-actions button.confirm,
#view-timeline .biz-card .event-actions button.approve,
#view-timeline .biz-card .event-actions button.sign,
#view-timeline .biz-card .event-actions button.complete {
  border-color: #d99b16;
  background: #d99b16;
  color: #fff;
}
#view-timeline .biz-card .event-actions button.reject {
  border-color: #f6d3cf;
  background: #fff0f0;
  color: #d94848;
}
#view-timeline .flow-detail {
  border: 1px solid #f0d28d;
  border-radius: 999px;
  background: #fff6dd;
  color: #8c6100;
  font-weight: 750;
}
#view-timeline .flow-people {
  border: 1px solid #eef1f6;
  border-radius: 12px;
  background: #f8fafc;
}
#view-timeline .qb-ok { border-radius: 999px; }
#view-timeline .qb-no { border-radius: 999px; }

/* ---------- 底栏 ---------- */
#view-timeline .chat-dock { background: transparent; }
#view-timeline .chat-inputbar {
  padding: 8px 12px;
  border-top: 1px solid #e5e9f0;
  background: rgba(255,255,255,.96);
  box-shadow: 0 -8px 24px rgba(20,35,60,.05);
}
#view-timeline .chat-inputbar input {
  padding: 9px 15px;
  border: 1.5px solid #e5e9f0;
  border-radius: 999px;
  background: #f8fafc;
  color: #172033;
}
#view-timeline .chat-inputbar input:focus {
  border-color: #d99b16;
  background: #fff;
  box-shadow: 0 0 0 3px rgba(217,155,22,.12);
}
#view-timeline .quick-plus {
  width: auto;
  height: 36px;
  padding: 0 14px;
  border-radius: 999px;
  background: #d99b16;
  color: #fff;
  font-size: 13px;
  font-weight: 800;
}
#view-timeline .refresh-btn {
  height: 36px;
  border: 1px solid #e5e9f0;
  background: #fff;
  color: #566072;
  font-weight: 750;
}
#view-timeline .refresh-btn:hover {
  border-color: #d99b16;
  background: #fffdf7;
  color: #b97c05;
}
#view-timeline .send-btn {
  height: 36px;
  padding: 0 16px;
  border-radius: 999px;
  background: #d99b16;
  color: #fff;
  font-weight: 800;
}

/* ---------- 项目抽屉 ---------- */
#drawer-panel {
  border-right: 1px solid #e5e9f0;
  background: #fff;
  box-shadow: 12px 0 40px rgba(20,35,60,.10);
}
#drawer-panel .drawer-head { border-bottom-color: #eef1f6; }
#drawer-panel .drawer-head h3 { color: #172033; font-weight: 800; }
#drawer-panel .drawer-search {
  border: 1.5px solid #e5e9f0;
  border-radius: 12px;
  background: #f8fafc;
}
#drawer-panel .drawer-search:focus {
  border-color: #d99b16;
  background: #fff;
  box-shadow: 0 0 0 3px rgba(217,155,22,.12);
}
#drawer-panel .group-item:hover { background: #fffdf7; }
#drawer-panel .group-avatar {
  border-radius: 12px;
  background: linear-gradient(135deg, #f2b23a, #d99b16);
}

/* ---------- 入口弹窗 ---------- */
.modal-mask {
  background: rgba(16,24,40,.42);
  backdrop-filter: blur(6px);
}
.modal-mask .modal:not(.wck2) {
  border: 1px solid #e5e9f0;
  border-radius: 20px;
  box-shadow: 0 24px 68px rgba(20,35,60,.16);
}
.modal-mask .modal > h3,
.modal-mask .modal .list-head h3 {
  color: #172033;
  font-weight: 800;
  letter-spacing: -.2px;
}
.modal-mask .modal-x {
  border-radius: 10px;
  color: #8e97a8;
}
.modal-mask .modal-x:hover {
  background: #fff6dd;
  color: #b97c05;
}
.modal-mask .modal input:focus,
.modal-mask .modal select:focus,
.modal-mask .modal textarea:focus {
  box-shadow: 0 0 0 3px rgba(217,155,22,.12);
}
.modal-mask .modal-actions button {
  border-radius: 999px;
  font-weight: 750;
}
.modal-mask .modal-actions .cancel {
  background: #f1f4f9;
  color: #566072;
}
.modal-mask .modal-actions .ok {
  background: #d99b16;
  color: #fff;
}
.modal-mask .modal-actions .ok:hover { background: #b97c05; }

/* 群内操作：角色卡与操作按钮 */
#quick-menu-mask .modal.quick-menu { border-radius: 22px; }
#quick-menu-mask .modal > h3 {
  margin-bottom: 14px;
  padding-right: 42px;
  padding-bottom: 12px;
  border-bottom: 1px solid #eef1f6;
}
#quick-menu-mask .role-card {
  padding: 12px 14px;
  border: 1px solid #e5e9f0;
  border-radius: 14px;
  background: #fff;
  box-shadow: 0 8px 26px rgba(20,35,60,.05);
}
#quick-menu-mask .role-card-title { color: #566072; font-weight: 800; }
#quick-menu-mask .role-card-title > span:first-child::before {
  content: "";
  display: inline-block;
  width: 6px;
  height: 6px;
  margin-right: 7px;
  border-radius: 50%;
  background: #d99b16;
  vertical-align: 1px;
}
#quick-menu-mask .role-card-count {
  background: #fff6dd;
  color: #8c6100;
}
#quick-menu-mask .role-card-toggle {
  border: 1px solid #e5e9f0;
  background: #f7f9fc;
  color: #8c6100;
}
#quick-menu-mask .quick-btn {
  border: 1px solid #e5e9f0;
  background: #fff;
  color: #566072;
  font-weight: 750;
}
#quick-menu-mask .quick-btn:hover {
  border-color: #d99b16;
  background: #fffdf7;
  color: #b97c05;
}

@media (max-width: 700px) {
  #view-timeline .chat-messages { padding: 12px 10px 20px; }
  #view-timeline .msg-bubble { max-width: 84%; border-radius: 14px 14px 14px 5px; }
  #view-timeline .msg-row.mine .msg-bubble { border-radius: 14px 14px 5px 14px; }
  #view-timeline .biz-card { max-width: 100%; border-radius: 14px; }
  #view-timeline .chat-inputbar { gap: 6px; padding: 7px 8px; }
  #view-timeline .chat-inputbar .refresh-btn { min-width: 0; padding: 0 9px; }
  #view-timeline .quick-plus { padding: 0 11px; }
  #view-timeline .chat-dock { max-width: none; }
  #quick-menu-mask .modal.quick-menu { border-radius: 18px; }
}

@media (max-width: 820px) {
  .modal-mask .modal.wck2 { border: 0; border-radius: 0; }
}

@media (max-width: 420px) {
  #view-timeline .chat-project-name::before { display: none; }
  #view-timeline .chat-inputbar { gap: 4px; padding: 6px 7px; }
  #view-timeline .chat-inputbar .refresh-btn { padding: 0 7px; font-size: 12px; }
  #view-timeline .quick-plus { padding: 0 9px; font-size: 12px; }
  #view-timeline .send-btn { padding: 0 12px; font-size: 12px; }
}
