/* ============================================================
   17do事项跟踪
   配色取自用户手绘 UI 稿（2026-10-27 待办UI.png）：
   纯中性灰阶 —— 灰画布 #DCDCDC + 白卡 + 灰项目卡 #EDEDED + 深灰胶囊
   结构原则：扫读优先
   1. 无纹理、无渐变，页面内元素零投影
   2. 层级只靠三样：字重、明度、留白
   3. 彩色只表达状态：紧急度四色 + 逾期红/完成绿/挂着琥珀
   4. 一屏尽量多装信息
   所有文字色对比度已按 WCAG 校准
   ============================================================ */
:root{
  /* 面 —— 取自 UI 稿的中性灰 */
  --bg:#DCDCDC;        /* 页面画布（样机底色） */
  --surface:#FFFFFF;   /* 卡片 */
  --sunken:#EDEDED;    /* 项目卡灰（样机项目卡底） */
  --hover:#F2F3F4;

  /* 字 —— 中性灰阶（样机只画了灰，正文用深灰保对比） */
  --tx:#1F2226;      /* 主文 */
  --tx-2:#4C525A;    /* 次要 */
  --tx-3:#697077;    /* 弱化 */
  --tx-4:#9BA1A8;    /* 占位，仅装饰性内容 */

  /* 线 —— 样机边框 #CECECE 一族 */
  --line:#CFD2D5;
  --line-2:#BFC3C7;

  /* 强调：样机激活标签 #818181 加深到白字可读的炭灰 */
  --ac:#43484F;      /* 白字 9.2:1 */
  --ac-2:#5A6068;    /* 需要浅一档时用 */
  --ac-bg:#EBEDEF;

  /* 侧栏：样机里导航直接坐在灰画布上，选中项是深灰胶囊 */
  --side-bg:#D2D4D6;    /* 比画布深半档，和内容区分开 */
  --nav-tx:#22262B;
  --nav-tx-2:#4C525A;
  --nav-tx-3:#6E747B;
  --nav-pill:#43484F;   /* 选中胶囊 = 强调炭灰 */

  /* 项目页分组头：深灰（= 样机深胶囊），白字 */
  --lane-hd:#4A5058;
  --lane-hd-bd:#3E434A;

  /* 三级层次 —— 样机是「白卡浮在灰画布上」，深色交给胶囊与分组头 */
  --lvl1:#43484F;   /* 深胶囊 / 主强调 */
  --lvl2:#5A6068;   /* 选项卡条 */
  --lvl3:#DCDCDC;   /* 内容区 = 画布 */

  /* 区段签名色：灰阶由深到浅，挂着保留琥珀（功能色） */
  --z1:#43484F;        /* 今日概况 —— 最重 */
  --z2:#6E747B;        /* 条件已够 */
  --z3:#A9AEB4;        /* 后面还有 —— 最轻 */
  --z4:#9A6512;        /* 挂着 —— 琥珀 */

  /* 状态色 */
  --red:#C4362E;     /* 5.4:1 */
  --red-bg:#FCEDEC;
  --grn:#1A7A55;     /* 5.3:1 */
  --grn-bg:#E7F4EF;
  --amb:#9A6512;     /* 5.0:1 */
  --amb-bg:#FBF2E2;

  --r:4px;
  --r-sm:2px;
  /* 投影只给浮层用，页面内元素一律不投影 */
  --sh:0 12px 32px -8px rgba(20,24,28,.26), 0 0 0 1px rgba(20,24,28,.10);
}

[data-theme="dark"]{
  --bg:#141619;
  --surface:#1E2125;
  --sunken:#26292E;
  --hover:#232629;

  --tx:#E8EAED;
  --tx-2:#B4B9BF;
  --tx-3:#8B9198;
  --tx-4:#5F666D;

  --line:#2C3036;
  --line-2:#3A3F45;

  --ac:#A9AEB4;
  --ac-2:#C3C7CC;
  --ac-bg:#2A2D31;

  --side-bg:#191C1F;
  --nav-tx:#E8EAED;
  --nav-tx-2:#B4B9BF;
  --nav-tx-3:#8B9198;
  --nav-pill:#3A3F45;

  /* 深色下头部不能比内容还亮，否则会「发光」 */
  --lane-hd:#2A2E33;
  --lane-hd-bd:#34393F;

  --lvl1:#3A3F45;
  --lvl2:#2A2E33;
  --lvl3:#141619;

  /* 深色下反过来：越重要越亮 */
  --z1:#C6CAD0;
  --z2:#8B9198;
  --z3:#5F666D;
  --z4:#D3A44A;

  --red:#E58078;
  --red-bg:#331D1C;
  --grn:#4EB489;
  --grn-bg:#13291F;
  --amb:#D3A44A;
  --amb-bg:#2C2415;

  --sh:0 16px 40px -8px rgba(0,0,0,.7), 0 0 0 1px rgba(255,255,255,.08);
}

*{box-sizing:border-box}
html,body{height:100%}
body{
  margin:0;background:var(--bg);color:var(--tx);
  font:13px/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Microsoft YaHei",system-ui,sans-serif;
  -webkit-font-smoothing:antialiased;
  font-variant-numeric:tabular-nums;
}
button,input,select,textarea{font:inherit;color:inherit}
button{cursor:pointer}
h1,h2,h3{margin:0;font-weight:600}
p{margin:0}
::selection{background:var(--ac);color:#fff}

.app{display:flex;height:100vh;overflow:hidden;width:100%}
/* 收起侧边栏：侧栏退场，.main 本身就是 flex:1，自动铺满整行 */
.app.side-folded .side{display:none}

/* ============================================================
   侧栏：样机里导航坐在灰画布上 —— 浅灰底 + 深灰选中胶囊
   ============================================================ */
.side{
  width:198px;flex:0 0 198px;
  background:var(--side-bg);
  border-right:1px solid var(--line-2);
  display:flex;flex-direction:column;
}
.brand{display:flex;gap:8px;align-items:center;padding:0 14px;height:48px;border-bottom:1px solid rgba(0,0,0,.08)}
.mark{width:18px;height:18px;flex:0 0 18px;color:var(--nav-tx);display:block}
.brand-txt b{font-size:13px;font-weight:600;display:block;line-height:1.2;color:var(--nav-tx)}
.brand-txt small{font-size:10.5px;color:var(--nav-tx-3);display:block}

.nav{padding:8px;display:flex;flex-direction:column;gap:1px;overflow:auto;flex:1}
/* 主入口「今日」：单独一块，比其他项高一点、底色更亮。
   它是每天打开就停的那一页，用尺寸和底色把它和工具页区分开。 */
.nav .nv-main{
  margin-bottom:6px;padding-bottom:6px;
  border-bottom:1px solid rgba(0,0,0,.10);
}
.nav .nv-main .nv{
  padding:9px 9px;font-size:14px;
  color:var(--nav-tx);
  background:rgba(0,0,0,.05);
}
.nav .nv-main .nv:hover{background:rgba(0,0,0,.09);color:var(--nav-tx)}
.nav .nv-main .nv .lb{font-size:14px;font-weight:500}
.nav .nv-main .nv .ic{width:16px;height:16px;flex:0 0 16px}
.nav .nv-main .nv .ct{font-size:11px;min-width:20px}

/* 分组标题：功能页按"执行/跟进/回看"分三段，
   让人知道哪些是日常要做的、哪些是回头查的 */
.nav .nv-group{margin-bottom:4px}
.nav .nv-gt{
  font-size:10px;color:var(--nav-tx-3);letter-spacing:.10em;
  padding:6px 8px 3px;opacity:.75;
}

.nav .nv{
  display:flex;align-items:center;gap:8px;width:100%;
  padding:6px 8px;border:0;background:none;border-radius:var(--r);
  color:var(--nav-tx-2);text-align:left;transition:background .1s,color .1s;
}
.nav .nv:hover{background:rgba(0,0,0,.07);color:var(--nav-tx)}
/* 选中态：深灰胶囊白字 —— 样机里「今日待办」那颗深色标签 */
.nav .nv.on{background:var(--nav-pill);color:#FFFFFF;font-weight:600}
.nav .nv .ic{width:14px;height:14px;flex:0 0 14px;stroke-width:1.7}
.nav .nv .lb{flex:1;font-size:13px}
.nav .nv .ct{font-size:10.5px;color:var(--nav-tx-3);min-width:16px;text-align:right}
.nav .nv.on .ct{color:rgba(255,255,255,.75)}
.nav .nv.hot .ct{color:#B33730;font-weight:600}

.side-foot{padding:8px;border-top:1px solid rgba(0,0,0,.08);display:flex;flex-direction:column;gap:1px}
.sbtn{
  border:0;background:none;text-align:left;padding:5px 8px;border-radius:var(--r);
  color:var(--nav-tx-3);font-size:12px;transition:background .1s,color .1s;
}
.sbtn:hover{background:rgba(0,0,0,.07);color:var(--nav-tx)}
.sbtn.danger:hover{background:rgba(196,54,46,.12);color:#B33730}

/* ============================================================
   顶栏
   ============================================================ */
/* 主区改成 grid：顶栏跨整行，下面「左列表 | 右详情」两列。
   详情未选中时宽度为 0，不占地方也不挤左侧。 */
.main{
  flex:1;min-width:0;
  display:grid;
  grid-template-columns:minmax(0,1fr) 0px;
  grid-template-rows:auto minmax(0,1fr);
}
.main>.top{grid-column:1 / -1;grid-row:1}
.main>.view{grid-column:1;grid-row:2}
.main.has-detail{grid-template-columns:minmax(0,1fr) 320px}
.main>.detail{grid-column:2;grid-row:2}

.detail{
  overflow:hidden;background:var(--surface);
  border-left:0 solid var(--line);
}
.main.has-detail .detail{border-left-width:1px;overflow:auto}
.top{
  display:flex;align-items:center;gap:14px;
  height:48px;flex:0 0 48px;padding:0 20px;
  background:var(--surface);border-bottom:1px solid var(--line);
}
.top h1{font-size:15px;font-weight:600;white-space:nowrap}
/* 顶栏左侧的侧栏开关：方形图标钮，收起/展开都是它，永远可见 */
.btn.icon{
  width:30px;height:30px;flex:0 0 30px;padding:0;
  display:inline-flex;align-items:center;justify-content:center;
  background:transparent;border:1px solid var(--line-2);border-radius:var(--r);
  color:var(--tx-2);
}
.btn.icon:hover{background:var(--hover);color:var(--tx)}
.btn.icon svg{display:block}
.top-l{display:flex;align-items:baseline;gap:8px;min-width:130px}
.top-l p{font-size:11.5px;color:var(--tx-3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.qa{flex:1;display:flex;min-width:0;background:var(--surface);border:1px solid var(--line-2);border-radius:var(--r);overflow:hidden}
.qa input{
  flex:1;min-width:0;height:29px;padding:0 11px;
  border:0;background:var(--surface);outline:none;font-size:13px;
}
.qa input:focus{background:var(--surface)}
.qa input::placeholder{color:var(--tx-4)}
/* 输入框与按钮连成一体，取自参考图的登录框 */
.qa .btn{
  height:29px;border:0;border-left:1px solid var(--line-2);
  border-radius:0;background:var(--ac-2);color:#FFFFFF;font-weight:500;
}
.qa .btn:hover{background:var(--ac);color:#FFFFFF}

.view{padding:16px 20px 40px;overflow:auto;flex:1}
/* 内容随窗口铺满，不再限宽 —— 宽屏右侧不留大片空白 */

/* ============================================================
   控件
   ============================================================ */
.btn{
  height:29px;padding:0 11px;border:1px solid var(--line-2);border-radius:var(--r);
  background:var(--surface);color:var(--tx-2);font-size:12.5px;
  white-space:nowrap;transition:background .1s,border-color .1s,color .1s;
}
.btn:hover{background:var(--hover);border-color:var(--line-2);color:var(--tx)}
.btn.primary{background:var(--ac-2);border-color:var(--ac-2);color:#FFFFFF;font-weight:500}
.btn.primary:hover{background:var(--ac);border-color:var(--ac);color:#FFFFFF}
.btn.sm{height:23px;padding:0 7px;font-size:11.5px;border-radius:var(--r-sm)}
.btn.ghost{border-color:transparent;background:transparent;color:var(--tx-3)}
.btn.ghost:hover{background:var(--hover);border-color:transparent;color:var(--tx)}

.card{background:var(--surface);border:1px solid var(--line);border-radius:var(--r)}
/* 容器直接装行列表时，去掉内边距让行和边缘对齐 —— 
   行与行之间的分隔线才是分组依据，多一层内边距只会割裂 */
.card.flush{padding:2px 12px}
.card.over{border-color:var(--red);background:var(--red-bg)}

/* 区块头：标题 + 计数徽标，一行定住分组 */
.sec-h{display:flex;align-items:center;gap:7px;margin:0 0 7px;min-height:20px}
.sec-h h2{font-size:12.5px;font-weight:600;color:var(--tx)}
.sec-h .cnt{
  font-size:10.5px;font-weight:600;color:var(--tx-3);
  background:var(--sunken);border-radius:9px;padding:0 6px;line-height:16px;
}
.sec-h .cnt.red{color:var(--red);background:var(--red-bg)}
.sec-h.red .cnt{color:var(--red);background:var(--red-bg)}
.sec-h.blue .cnt{color:var(--ac);background:var(--ac-bg)}
.sec-h.amber .cnt{color:var(--amb);background:var(--amb-bg)}
.sec-h.green .cnt{color:var(--grn);background:var(--grn-bg)}
.sec-h .sp{flex:1}
.sec-h .hint{font-size:11px;color:var(--tx-3)}
.q-box{
  height:24px;padding:0 8px;border:1px solid var(--line-2);border-radius:var(--r-sm);
  background:var(--surface);font-size:12px;width:160px;outline:none;
}
.q-box:focus{border-color:var(--ac)}

.dot{width:5px;height:5px;border-radius:50%;flex:0 0 5px;background:var(--tx-4)}
.dot.red{background:var(--red)} .dot.amber{background:var(--amb)}
.dot.blue{background:var(--ac)} .dot.green{background:var(--grn)}
.dot.purple{background:var(--tx-3)} .dot.gray{background:var(--line-2)}

/* ============================================================
   今日清单：左侧竖色带标明类型
   逾期=红、今天到期=蓝、打卡=绿、待查进度=琥珀
   一列四种类型，靠色带就能扫出"哪条是例行、哪条真急"
   ============================================================ */
.act-row{padding-left:11px}
.k-band{position:absolute;left:0;top:5px;bottom:5px;width:3px;border-radius:2px}
.act-row.k-late .k-band{background:var(--red)}
/* 未到期但未完成：用中性灰，不抢眼但能看出"这不是今天必须做的" */
.act-row.k-soon .k-band{background:var(--line-2)}
.act-row.k-soon{opacity:.88}
.act-row.k-soon:hover{opacity:1}
.act-row.k-today .k-band{background:var(--ac-2)}
.act-row.k-check .k-band{background:var(--grn)}
.act-row.k-watch .k-band{background:var(--amb)}
.act-row.k-late .ttl{font-weight:500}
/* 打卡/查进度用的是圆形勾选框，flex 容器会把它压扁，
   固定宽高并取消外边距 */
.act-row .cb.round{margin-top:2px;min-width:15px}
/* 「后面还有」里的行更紧凑 —— 那是参考信息，不是必须现在做的 */
.row.compact{padding:5px 0;align-items:center}

/* ============================================================
   任务状态标签
   progress 决定它在哪；block 说明它为什么不动
   ============================================================ */
.tag.st{font-weight:500}
.tag.st.b-wait{color:var(--amb);background:var(--amb-bg)}
.tag.st.b-cond{color:var(--ac);background:var(--ac-bg)}
.tag.st.b-stuck{color:var(--red);background:var(--red-bg)}
.tag.st.p-drop{color:var(--tx-3);background:var(--sunken)}
/* 进展说明：斜体 + 无底色，和状态标签区分开 */
.tag.pn{
  color:var(--tx-2);background:transparent;border:1px dashed var(--line-2);
  font-style:italic;max-width:220px;overflow:hidden;text-overflow:ellipsis;display:inline-block;
  line-height:14px;
}
/* 已放弃：整行压暗 */
.row.dropped{opacity:.5}
.row.dropped .ttl{text-decoration:line-through}

/* 跟进记录列表 */
.logbox{
  border:1px solid var(--line);border-radius:var(--r-sm);
  background:var(--surface);padding:6px 9px;max-height:170px;overflow:auto;
}
.logrow{display:flex;gap:9px;font-size:12px;padding:2px 0;align-items:flex-start}
.logrow + .logrow{border-top:1px dashed var(--line)}
.logd{flex:0 0 42px;color:var(--faint);font-variant-numeric:tabular-nums}
.logn{flex:1;color:var(--tx-2);line-height:1.5}

/* 今日清单里「该跟进」行的色带：炭灰（样机里唯一允许的深灰信号，紫色已让位给中性方案） */
.act-row.k-follow .k-band{background:#33383E}

/* ============================================================
   区段（zone）—— 统一为「白卡 + 顶部细色条 + 彩色标题」
   以前 z1 用整块亮蓝填充，和全站「白底卡片 + 颜色只表状态」的
   语言冲突，孤零零一块蓝、没有整体感。现在所有区段同形同底，
   仅靠顶部 3px 色条与标题色区分轻重，颜色回到「点缀」位置：
   z1 今日概况 = 炭灰（与侧栏胶囊同族，最重）
   z2 条件已够 = 主蓝（可启动，是动作）
   z3 后面还有 = 中性灰（参考信息，不急）
   z4 挂着     = 琥珀（搁置/警示）
   ============================================================ */
.zone{
  background:var(--surface);
  border:1px solid var(--line);
  border-top:3px solid var(--zt,#C9D2DE);
  border-radius:8px;margin-bottom:14px;overflow:hidden;
}
.zone-h{
  display:flex;align-items:center;gap:8px;
  padding:9px 14px;
}
.zone-h h2{font-size:13.5px;font-weight:600}
.zone-h .cnt{
  font-size:10.5px;font-weight:600;padding:0 6px;line-height:16px;border-radius:9px;
}
.zone-h .sp{flex:1}
.zone-h .zhint{font-size:11px;color:var(--tx-3)}
.zone-b{padding:0 14px 14px}
/* 白卡内的内容区：用极浅底与白色区段底形成微弱层次（替代原来的白卡压色块） */
.zone-b>.card,.zone-b .zone-inner{
  background:var(--hover);border-radius:6px;border:1px solid var(--line);
  padding:2px 12px;
}
.zone-b .row:last-child{border-bottom:0}
.zone-b .empty{margin:0}

/* z1 今日概况：炭灰顶条 + 炭灰标题（与侧栏胶囊同族，最重） */
.zone.z1{--zt:var(--z1)}
.zone.z1 .zone-h h2{color:var(--z1)}
.zone.z1 .zone-h .cnt{background:var(--ac-bg);color:var(--ac)}
.zone.z1 .zone-h .zhint{color:var(--tx-3)}

/* z2 条件已够：主蓝顶条 + 主蓝标题（可启动，是动作） */
.zone.z2{--zt:var(--z2)}
.zone.z2 .zone-h h2{color:var(--z2)}
.zone.z2 .zone-h .cnt{background:var(--ac-bg);color:var(--z2)}
.zone.z2 .zone-h .zhint{color:var(--tx-3)}

/* z3 后面还有：中性灰顶条 + 灰标题（参考信息，不急） */
.zone.z3{--zt:var(--z3)}
.zone.z3 .zone-h h2{color:var(--tx)}
.zone.z3 .zone-h .cnt{background:var(--sunken);color:var(--tx-3)}
.zone.z3 .zone-h .zhint{color:var(--tx-3)}

/* z4 挂着：琥珀顶条 + 琥珀标题（搁置/警示，不是不做） */
.zone.z4{--zt:var(--z4)}
.zone.z4 .zone-h h2{color:var(--z4)}
.zone.z4 .zone-h .cnt{background:var(--amb-bg);color:var(--z4)}
.zone.z4 .zone-h .zhint{color:#8A6518}

/* ============================================================
   项目分组：同一项目的事项必须相邻且同色
   之前按优先级平铺，同一项目散落各处，看不出是一件事。
   组底色对比度均 >15:1（正文 #101318），分组明显但不牺牲可读性。
   ============================================================ */
.pgrp{
  margin:6px 0;border-radius:6px;overflow:hidden;
  border:1px solid var(--line-2);background:var(--sunken);
}
.pgrp:first-child{margin-top:2px}
.pgrp:last-child{margin-bottom:2px}
/* 组头：项目名直接坐在灰卡上（样机画法），深灰粗体即可分层 */
.pgrp-h{
  display:flex;align-items:center;gap:8px;
  padding:7px 12px;border-bottom:1px solid var(--line-2);
}
.pgrp-h::before{
  content:"";width:8px;height:8px;border-radius:2px;flex:0 0 8px;
}
.pgrp-name{font-size:12.5px;font-weight:600;color:var(--tx)}
.pgrp-sub{font-size:10.5px;color:var(--tx-3)}
/* 组内行 = 样机里的白色条目：白胶囊浮在灰卡上 */
.pgrp .row{
  background:var(--surface);
  border:1px solid var(--line);
  border-radius:5px;
  margin:0 6px 4px;
}
.pgrp .row:hover{background:var(--surface);border-color:var(--line-2)}
[data-theme="dark"] .pgrp .row:hover{background:var(--surface)}
.pgrp .act-row{padding-left:11px}

/* 分组配色已让位给紧急度：项目组统一中性灰（样机 #EDEDED）。
   g0~g7 的类名保留，JS 里的 PROJ_BG / colorOf 不用动。 */
.pgrp.g0,.pgrp.g1,.pgrp.g2,.pgrp.g3,
.pgrp.g4,.pgrp.g5,.pgrp.g6,.pgrp.g7{background:var(--sunken)}
/* 组头同灰卡融为一体：透明底 + 深灰标题（样机画法）。
   注意：卡片已不再挂 g0~g7 类名，选择器必须直接命中 .pgrp .pgrp-h。 */
.pgrp .pgrp-h{
  background:transparent;border-bottom-color:var(--line-2);
}
.pgrp .pgrp-h::before{
  background:var(--tx-3);
}
.pgrp .pgrp-name{color:var(--tx)}
.pgrp .pgrp-sub{color:var(--tx-3)}

[data-theme="dark"] .pgrp{background:var(--sunken)}

/* ============================================================
   三级层次（样机画法：白卡浮在灰画布上，深色只给胶囊与分组头）
   一级 深灰胶囊 #43484F —— 侧栏选中项 / 主按钮
   二级 选项卡条 #5A6068 —— 页内切换
   三级 内容区   #DCDCDC 灰画布 —— 白卡浮在上面

   之前的问题：侧栏深蓝、选项卡白、项目头深蓝、便签浅蓝，
   四个色块互相打架，看不出谁是谁。
   现在彩色只留给状态（紧急度/逾期/完成/挂着），框架全是灰阶。

   注意：选项卡条和选中胶囊不能同色，
   否则两者挤在一起反而分不开 —— 要有明确的深浅差。
   ============================================================ */
.ptabbar{
  display:flex;gap:2px;margin:0 0 16px;
  background:var(--lvl2);
  padding:2px;border-radius:var(--r);
}
.ptabbar button{
  border:0;background:none;padding:7px 16px;
  font-size:13px;color:rgba(255,255,255,.78);position:relative;
  border-radius:var(--r-sm);transition:background .1s,color .1s;
}
.ptabbar button:hover{background:rgba(255,255,255,.12);color:#FFFFFF}
/* 选中态用白底，和侧栏选中态是同一套语言 */
.ptabbar button.on{background:#FFFFFF;color:var(--lvl2);font-weight:500}
.ptabbar button.danger{color:rgba(255,205,200,.9)}
.ptabbar button.danger:hover{background:rgba(255,255,255,.12);color:#FFD4D1}
.ptabbar button.danger.on{background:#FFFFFF;color:var(--red)}
.ptabbar button b{
  font-size:10.5px;font-weight:500;color:rgba(255,255,255,.6);
  margin-left:5px;font-variant-numeric:tabular-nums;
}
.ptabbar button.on b{color:var(--lvl2);opacity:.75}
.ptabbar button.danger b{color:rgba(255,205,200,.85)}
.ptabbar button.danger.on b{color:var(--red);opacity:.8}
/* 回收站行：删除态整体压暗，还原按钮用蓝色（.keep 本身就常显） */
.row.tr-row{opacity:.72}
.row.tr-row:hover{opacity:1;background:var(--hover)}

/* ============================================================
   数据存储状态条
   侧栏是浅灰底，靠底色区分状态块效果很差，
   所以改用「左侧色条 + 高对比文字」来表达状态。
   ============================================================ */
.filestate{
  display:flex;align-items:center;gap:6px;
  padding:6px 8px;margin-bottom:5px;
  border-radius:var(--r-sm);
  background:rgba(0,0,0,.05);
  border-left:3px solid #58B98A;
  font-size:11px;color:var(--tx-2);
}
/* 未绑定文件时不显示。用 :empty 兜底 ——
   万一 JS 还没跑或渲染逻辑出岔，也不会留下一条空绿条 */
.filestate:empty{display:none}
.filestate[hidden]{display:none}
.filestate.warn{border-left-color:#D99A2B}
.filestate .fi{opacity:.7;font-size:10px;flex:0 0 auto}
.filestate .fn{
  flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  font-variant-numeric:tabular-nums;
}
.filestate .fs{flex:0 0 auto;font-size:10px;color:var(--tx-3)}
.filestate .fs-act{
  flex:0 0 auto;border:0;background:rgba(0,0,0,.08);color:var(--tx);
  font-size:10px;padding:1px 5px;border-radius:2px;
}
.filestate .fs-act:hover{background:rgba(0,0,0,.14)}
.filestate .fs-x{
  flex:0 0 auto;border:0;background:none;color:var(--tx-3);
  font-size:14px;line-height:1;padding:0 2px;
}
.filestate .fs-x:hover{color:var(--tx)}

.sbtn:disabled{opacity:.42;cursor:not-allowed}

/* ============================================================
   分组头（事项页）
   在三级内容区内，同样不用深底 —— 用左侧竖线 + 稍深底色表达层级，
   与项目页的项目头保持同一套语言。
   ============================================================ */
.sec-h.grp-h{
  background:var(--lane-hd);
  border:1px solid var(--lane-hd-bd);border-left:3px solid var(--lane-hd-bd);
  border-radius:var(--r) var(--r) 0 0;
  padding:7px 12px;margin:-1px -1px 0;padding-left:11px;
}
/* 分组头是"这一组的标题"，选中态是"这一行被选中了"，
   两者一个深底白字、一个白底蓝字，绝不能撞色。 */
.sec-h.grp-h h2{color:#FFFFFF}
.sec-h.grp-h .n{
  background:rgba(255,255,255,.22);color:#FFFFFF;
  font-size:10.5px;font-weight:600;padding:0 6px;line-height:16px;border-radius:9px;
}
.sec-h.grp-h .dot{background:rgba(255,255,255,.85)}
.sec-h.grp-h .btn{
  background:rgba(255,255,255,.16);border-color:rgba(255,255,255,.22);color:#FFFFFF;
}
.sec-h.grp-h .btn:hover{background:rgba(255,255,255,.28)}
/* 头和卡片拼成一个整体，不留缝 */
.sec-h.grp-h + .card{border-top-left-radius:0;border-top-right-radius:0;margin-top:0}

/* ============================================================
   右侧详情面板（主从布局的"从"）
   ============================================================ */
.det{padding:14px 15px 20px;min-width:0}
.det-h{display:flex;align-items:flex-start;gap:8px;margin-bottom:9px}
.det-title{font-size:14px;font-weight:600;line-height:1.45;flex:1;word-break:break-word}
.det-x{
  border:0;background:none;color:var(--tx-3);font-size:18px;line-height:1;
  padding:0 4px;flex:0 0 auto;border-radius:var(--r-sm);
}
.det-x:hover{background:var(--hover);color:var(--tx)}
.det-meta{display:flex;flex-wrap:wrap;gap:5px;margin-bottom:9px}
.det-proj{
  font-size:11.5px;color:var(--tx-2);background:var(--sunken);
  padding:5px 9px;border-radius:var(--r-sm);margin-bottom:12px;
}
.det-sec{
  display:flex;align-items:center;gap:6px;
  font-size:10.5px;font-weight:600;color:var(--tx-4);
  letter-spacing:.06em;margin-bottom:8px;
}
.det-n{
  font-size:10px;color:var(--tx-3);background:var(--sunken);
  padding:0 5px;border-radius:8px;letter-spacing:0;font-weight:500;
}

/* ---- 时间线 ---- */
.tl{position:relative;padding-left:3px}
.tl-i{display:flex;gap:10px;padding-bottom:12px;position:relative}
.tl-i:last-child{padding-bottom:2px}
/* 竖线连接各节点 */
.tl-i::before{
  content:"";position:absolute;left:4.5px;top:12px;bottom:0;width:1px;
  background:var(--line-2);
}
.tl-i:last-child::before{display:none}
.tl-dot{
  width:10px;height:10px;border-radius:50%;flex:0 0 10px;
  background:var(--line-2);margin-top:3px;z-index:1;
  box-shadow:0 0 0 2px var(--surface);
}
.tl-dot.k-done{background:var(--grn)}
.tl-dot.k-drop{background:var(--tx-4)}
.tl-dot.k-block{background:var(--amb)}
.tl-dot.k-new{background:var(--ac)}
.tl-dot.k-reopen{background:var(--amb)}
.tl-body{flex:1;min-width:0}
.tl-top{display:flex;align-items:baseline;gap:7px;margin-bottom:1px}
.tl-kind{font-size:10.5px;font-weight:600;color:var(--tx-3)}
.tl-kind.k-done{color:var(--grn)}
.tl-kind.k-drop{color:var(--tx-4)}
.tl-kind.k-block{color:var(--amb)}
.tl-kind.k-new{color:var(--ac)}
.tl-time{font-size:10.5px;color:var(--tx-4);font-variant-numeric:tabular-nums}
.tl-note{font-size:12.5px;color:var(--tx-2);line-height:1.55;word-break:break-word}
/* 最新一条：加底色标记，一眼看到"最近发生的是哪件" */
.tl-i.now .tl-note{color:var(--tx);font-weight:450}
.tl-i.now::after{
  content:"最新";position:absolute;right:0;top:0;
  font-size:9.5px;color:var(--ac);background:var(--ac-bg);
  padding:0 5px;border-radius:8px;letter-spacing:.02em;
}

.det-acts{display:flex;gap:6px;flex-wrap:wrap;margin-top:14px;
  padding-top:12px;border-top:1px solid var(--line)}

/* ---- 未选中时的引导 ---- */
.det-empty{
  padding:26px 18px;text-align:center;
}
.det-empty-t{font-size:13px;color:var(--tx-2);font-weight:500;margin-bottom:6px}
.det-empty-s{font-size:11.5px;color:var(--tx-4);line-height:1.7}
.det-empty-n{font-size:11px;color:var(--tx-3);margin-top:10px}

/* ---- 左侧行上的"最后更新"标签 ---- */
.tag.lu{
  background:var(--bg);color:var(--tx-2);
  border:1px solid var(--line);font-style:normal;
  max-width:260px;overflow:hidden;text-overflow:ellipsis;display:inline-block;
  line-height:15px;
}
.tag.lu.ok{background:var(--grn-bg);border-color:#C4E2D6;color:var(--grn)}
.tag.lu.warn{background:var(--amb-bg);border-color:#EAD6A8;color:var(--amb)}

/* 窄屏：详情改为浮层，不占两列 */
@media (max-width:960px){
  .main,.main.has-detail{grid-template-columns:minmax(0,1fr)}
  .main>.detail{
    grid-column:1;grid-row:2;position:absolute;
    left:0;right:0;top:48px;bottom:0;z-index:20;
    border-left:0;border-top:1px solid var(--line-2);
  }
  .main:not(.has-detail)>.detail{display:none}
}

.row.clickable{cursor:pointer}
/* 选中态：左侧一条实线 + 极浅底，和 hover 区分开（hover 一闪就没了） */
.row.picked{
  background:var(--ac-bg);
  box-shadow:inset 2px 0 0 var(--ac);
}
.row.picked:hover{background:var(--ac-bg)}
.pgrp .row.picked{background:var(--ac-bg)}

/* ============================================================
   data.json 种子文件相关
   data.json 和页面一起上传 → 任何静态托管、任何浏览器都能用
   ============================================================ */

/* 侧栏：显示 data.json 的条数和时间 */
.seedstate{
  display:flex;align-items:center;gap:6px;
  padding:6px 8px;margin-bottom:5px;
  border-radius:var(--r-sm);
  background:rgba(0,0,0,.05);
  border-left:3px solid #58B98A;
  font-size:11px;color:var(--tx-2);
}
.seedstate:empty{display:none}
.seedstate[hidden]{display:none}
.seedstate .fi{opacity:.7;font-size:10px;flex:0 0 auto}
.seedstate .fn{
  flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  font-weight:500;
}
.seedstate .fs{
  flex:0 0 auto;font-size:10px;color:var(--tx-3);
  font-variant-numeric:tabular-nums;
}

/* 顶部提示条：发现 data.json 更新了 */
.seedbar{
  position:fixed;left:50%;transform:translateX(-50%);top:12px;
  display:flex;align-items:center;gap:9px;
  padding:8px 12px;border-radius:var(--r);z-index:90;
  background:var(--surface);border:1px solid var(--line-2);
  box-shadow:var(--sh);font-size:12.5px;color:var(--tx);max-width:88vw;
}
.seedbar .sb-i{
  width:16px;height:16px;border-radius:50%;flex:0 0 16px;
  background:var(--ac);color:#FFFFFF;font-size:11px;font-weight:600;
  display:flex;align-items:center;justify-content:center;
}
.seedbar .sb-t{flex:1;min-width:0}
.seedbar .sb-b{
  border:0;background:var(--ac);color:#FFFFFF;font-size:12px;
  padding:3px 10px;border-radius:var(--r-sm);font-weight:500;
}
.seedbar .sb-b:hover{opacity:.88}
.seedbar .sb-x{
  border:0;background:none;color:var(--tx-3);font-size:12px;
  padding:3px 6px;border-radius:var(--r-sm);
}
.seedbar .sb-x:hover{background:var(--hover);color:var(--tx)}

/* ---- 项目分组拖动排序 ---- */
.pgrp.sortable{cursor:default}
/* 拖动手柄：只在 hover 组头时才明显，平时低调（组头是浅灰，用深色系） */
.pgrp-grip{
  font-size:13px;color:var(--tx-4);cursor:grab;
  flex:0 0 auto;padding:0 1px;letter-spacing:-1px;
  transition:color .1s;
}
.pgrp-h:hover .pgrp-grip{color:var(--tx-2)}
.pgrp-grip:active{cursor:grabbing}
/* 恢复自动排序：平时隐藏，hover 组头才出现 */
.pgrp-reset{
  font-size:10.5px;color:var(--tx-3);cursor:pointer;
  margin-left:auto;padding:1px 6px;border-radius:var(--r-sm);
  opacity:0;transition:opacity .1s;flex:0 0 auto;
}
.pgrp-h:hover .pgrp-reset{opacity:1}
.pgrp-reset:hover{background:rgba(0,0,0,.08);color:var(--tx)}

/* 拖动中的源：半透明，让用户看清是哪一块在动 */
.pgrp.dragging{opacity:.42}
/* 插入位置提示：上/下边缘一条粗线 */
.pgrp.over-top{box-shadow:inset 0 3px 0 var(--ac)}
.pgrp.over-bot{box-shadow:inset 0 -3px 0 var(--ac)}
.pgrp.over-top .pgrp-h{background:rgba(0,0,0,.07)}
.pgrp.over-bot .pgrp-h{background:rgba(0,0,0,.07)}
[data-theme="dark"] .pgrp-reset:hover{background:rgba(255,255,255,.10)}
[data-theme="dark"] .pgrp.over-top .pgrp-h,
[data-theme="dark"] .pgrp.over-bot .pgrp-h{background:rgba(255,255,255,.05)}

/* ---- 项目内子事项拖动排序 ---- */
.row.sortable-task{cursor:default}
.row-grip{
  font-size:12px;color:var(--tx-4);cursor:grab;
  flex:0 0 auto;align-self:center;padding:0 1px;letter-spacing:-1px;
  transition:color .1s;
}
.row:hover .row-grip{color:var(--tx-2)}
.row-grip:active{cursor:grabbing}
/* 行比分组窄，落点提示用背景色 + 上下边线，比粗 inset 阴影更清楚 */
.row.dragging{opacity:.4}
.row.over-top{box-shadow:inset 0 2px 0 var(--ac)}
.row.over-bot{box-shadow:inset 0 -2px 0 var(--ac)}
.row.over-top,.row.over-bot{background:var(--ac-bg)!important}
[data-theme="dark"] .row.over-top,[data-theme="dark"] .row.over-bot{background:#16283F!important}

/* ============================================================
   重复事项（打卡）
   事项填了「重复」就是打卡，所以视觉上和普通事项同源，
   只用一个专属标签区分频率。
   ============================================================ */
.tag.rp{
  background:var(--ac-bg);color:var(--ac);
  border:1px solid rgba(0,0,0,.06);font-weight:500;
}
/* 统计页里重复事项的频率副标 */
.stat-row .nm .sr2{
  font-size:10px;color:var(--tx-4);margin-left:6px;font-weight:400;
}

/* ============================================================
   列表行 —— 全站的密度基准
   ============================================================ */
.lane{background:var(--surface);border:1px solid var(--line);border-radius:var(--r);margin-bottom:10px;overflow:hidden}
/* 表头式分组条：沿用工作表格"色块表头即分组"的直觉 */
.lane-h{display:flex;align-items:center;gap:9px;padding:7px 12px;border-bottom:1px solid var(--line)}

/* 项目头 / 待处理事项头：深灰底 + 白字（= 样机的深灰胶囊）。
   分组头必须和「白底选中态」彻底分开 —— 之前用 --sunken（浅灰），
   和白底只差 1.1 倍，扫视时分不清哪行是标题、哪行被选中。 */
.lane.proj .lane-h,
.lane.free .lane-h{
  background:var(--lane-hd);
  border-bottom-color:var(--lane-hd-bd);
  border-left:3px solid var(--lane-hd-bd);
  padding-left:11px;
}
.lane.proj .lane-h h3,
.lane.free .lane-h h3{color:#FFFFFF}
.lane.proj .lane-h .sub,
.lane.free .lane-h .sub{color:rgba(255,255,255,.85)}
/* 深底上的按钮和标签要换成白字，否则看不清 */
.lane.proj .lane-h .btn.ghost,
.lane.free .lane-h .btn.ghost{color:rgba(255,255,255,.88);border-color:transparent}
.lane.proj .lane-h .btn.ghost:hover,
.lane.free .lane-h .btn.ghost:hover{background:rgba(255,255,255,.18);color:#FFFFFF}
.lane.proj .lane-h .btn,
.lane.free .lane-h .btn{
  background:rgba(255,255,255,.18);border-color:rgba(255,255,255,.24);color:#FFFFFF;
}
.lane.proj .lane-h .btn:hover,
.lane.free .lane-h .btn:hover{background:rgba(255,255,255,.30)}
.lane.proj .lane-h .tag,
.lane.free .lane-h .tag{background:rgba(255,255,255,.22);color:#FFFFFF}
.lane.proj .lane-h .tag.ok{background:rgba(255,255,255,.26);color:#EAF7F0}
.lane.proj .lane-h .tag.late{background:rgba(255,186,182,.30);color:#FFD9D6}
.lane.proj .lane-h .tag.warn{background:rgba(255,212,156,.28);color:#FFE9C9}
.lane-h h3{font-size:13px;font-weight:600;display:flex;align-items:baseline;gap:8px;flex-wrap:wrap;min-width:0}
.lane-h .sub{font-size:11.5px;color:var(--tx-2);font-weight:400;display:flex;align-items:baseline;gap:7px;flex-wrap:wrap}
.lane-h .sp{flex:1;min-width:8px}
.lane-b{padding:2px 12px 6px}
.lane.dn{opacity:.6}
/* 进度条放在白底事项区内部，顶部留白。
   放在深色头下方会被误读成头的一部分。 */
.lane .mini-bar{height:3px;background:var(--line-2);margin:8px 0 2px}
.lane .mini-bar i{display:block;height:100%;background:var(--ac-2);transition:width .18s}
.lane-more{
  text-align:center;font-size:11.5px;color:var(--tx-3);padding:6px;
  border-top:1px solid var(--line);cursor:pointer;
}
.lane-more:hover{background:var(--hover);color:var(--tx)}
.lane-empty{padding:14px;text-align:center;color:var(--tx-3);font-size:12px}

/* 逾期行：只在左侧打一条红标 + 日期标红，不铺满整行。
   铺满会让连续多条逾期连成一片红，反而看不出边界 —— 
   和工作表格里"红色只标单元格"是同一个克制原则 */
.row{
  position:relative;
  display:flex;align-items:flex-start;gap:9px;
  /* 右侧留 10px：操作按钮贴到容器边缘会看着像被截断 */
  padding:6px 10px 6px 8px;border-bottom:1px solid var(--line);
}
.row:last-child{border-bottom:0}
.row:hover{background:var(--hover)}
.row.late::before{
  content:"";position:absolute;left:0;top:4px;bottom:4px;width:2.5px;
  background:var(--red);border-radius:2px;
}
.row.done .ttl{text-decoration:line-through;color:var(--tx-4)}
.row.late .ttl{font-weight:500}
.row .ttl{font-size:13px;line-height:1.45}
.row .meta{display:flex;flex-wrap:wrap;gap:5px;align-items:center;margin-top:2px}
.row .body{flex:1;min-width:0}
/* 操作区整体不透明，逐个按钮自己控制显隐：
   .keep（主动作）常显，其余 hover 才现 */
.row .acts{display:flex;gap:2px;flex:0 0 auto;align-self:center}
.row .acts button{
  border:0;background:none;border-radius:var(--r-sm);opacity:0;
  padding:2px 6px;font-size:11px;color:var(--tx-3);transition:opacity .1s,background .1s;
  white-space:nowrap;
}
.row:hover .acts button,.row:focus-within .acts button{opacity:1}
.row .acts .keep{opacity:1;color:var(--ac)}
.row .acts button:hover{background:var(--sunken);color:var(--tx)}

/* 勾选框：加深边框，扫视时能一眼找到 */
.cb{
  width:15px;height:15px;flex:0 0 15px;margin-top:2px;position:relative;
  border:1.5px solid var(--tx-4);border-radius:var(--r-sm);background:var(--surface);
  transition:all .1s;
}
.cb:hover{border-color:var(--tx-2);background:var(--hover)}
.cb.on{background:var(--ac-2);border-color:var(--ac-2)}
.cb.on::after{
  content:"";position:absolute;left:3.5px;top:1px;width:4px;height:7px;
  border:solid #fff;border-width:0 1.6px 1.6px 0;transform:rotate(43deg);
}
.cb.round{border-radius:50%}
.cb.round.on::after{left:4px;top:2px;width:3.5px;height:6px}

/* 标签：无边框，只用底色。
   日期/数量这类可比的值靠右对齐 —— 与工作表格里数字列右对齐同一原理，
   扫读时能上下对齐，不用逐个数位数 */
.tag{
  display:inline-flex;align-items:center;font-size:10.5px;padding:0 5px;
  border-radius:var(--r-sm);color:var(--tx-2);background:var(--sunken);
  white-space:nowrap;line-height:16px;
}
.tag.num{font-variant-numeric:tabular-nums}
.tag.late{color:var(--red);background:#FBE0DD;font-weight:500}
.tag.p{color:var(--tx-2)}
.tag.r{color:var(--grn);background:var(--grn-bg)}
.tag.w{color:var(--amb);background:var(--amb-bg)}
.tag.b{color:var(--ac);background:var(--ac-bg)}
.tag.f{color:var(--tx-3);background:var(--sunken)}
.tag.warn{color:var(--amb);background:var(--amb-bg)}
.tag.ok{color:var(--grn);background:var(--grn-bg)}

/* 紧急度四档：暖色只给「紧急 / 优先」，因为这两档才是要抢的；
   正常 / 延后用中性色压住 —— 四档全上彩色，等于四档都看不出来。 */
.tag.ug{font-weight:500;border:1px solid transparent}
.tag.ug.u-urgent{color:#791F1F;background:#F7C1C1;border-color:#E9A3A3}
.tag.ug.u-high{color:#633806;background:#FAC775;border-color:#E5A63C}
.tag.ug.u-normal{color:#4C525A;background:#E9EBED;border-color:#D6D9DC}
.tag.ug.u-later{color:#85898E;background:#F2F3F4;border-color:#D6D9DC}

/* 行的底色叠加：用 background-image 而不是 background，
   这样既盖一层淡色，又不顶掉项目分组的底色和 .picked 的左边条。
   选择器用 .row —— 今日主清单、无日期区、项目页里的行为保持一致。 */
.row.u-urgent{background-image:linear-gradient(rgba(226,75,74,.10),rgba(226,75,74,.10))}
.row.u-high{background-image:linear-gradient(rgba(239,159,39,.12),rgba(239,159,39,.12))}
.row.u-later{opacity:.72}
.row.u-later:hover{opacity:1}
.row.u-urgent .ttl{font-weight:500}

/* ============================================================
   今日页头部：紧凑，不占地方
   ============================================================ */
.today-strip{display:flex;align-items:baseline;gap:12px;margin-bottom:16px;flex-wrap:wrap}
.ts-num{display:flex;align-items:baseline;gap:6px}
.ts-big{font-size:26px;font-weight:600;line-height:1;letter-spacing:-.02em}
.ts-mo{font-size:13px;color:var(--tx-3)}
.ts-info{min-width:0}
.ts-line{font-size:13px;color:var(--tx-2)}
.ts-line b{color:var(--tx);font-weight:600}
.ts-sub{display:flex;gap:6px;flex-wrap:wrap;font-size:11.5px;color:var(--tx-3);margin-top:2px}
.ts-warn{color:var(--red);font-weight:600}

/* ============================================================
   其他页面
   ============================================================ */
.pcard{padding:11px 13px}
.pcard h3{font-size:14px;display:flex;align-items:baseline;gap:8px;flex-wrap:wrap}
.pcard h3 .badge{font-size:11.5px;color:var(--tx-3);font-weight:400}
.bar{height:3px;background:var(--line);border-radius:2px;overflow:hidden;margin:9px 0 7px}
.bar i{display:block;height:100%;background:var(--ac);transition:width .18s}
/* 小进度条（今日页项目概览） */
.mini-tr{flex:0 0 90px;height:6px;background:var(--sunken);border-radius:3px;overflow:hidden}
.mini-tr i{display:block;height:100%;background:var(--ac-2);border-radius:3px;transition:width .18s}
.pmeta{display:flex;gap:10px;flex-wrap:wrap;font-size:11.5px;color:var(--tx-2);align-items:center}
.sublist{margin-top:7px;border-top:1px solid var(--line);padding-top:2px}

.loose-row{align-items:center}
.move-sel{
  display:none;height:22px;border:1px solid var(--line-2);border-radius:var(--r-sm);
  padding:0 4px;font-size:11px;background:var(--surface);max-width:120px;flex:0 0 auto;
}
.loose-row:hover .move-sel,.loose-row:focus-within .move-sel{display:block}

.hz{width:15px;height:15px;display:inline-block;border-radius:var(--r-sm);background:var(--line);border:1px solid var(--line-2)}
.hz.yes{background:var(--ac-2);border-color:var(--ac-2)}
.hz.miss{background:var(--surface);border-color:var(--line-2);border-style:dashed}
.hz.na{background:var(--line);opacity:.4;border-color:transparent}

.cond{display:flex;align-items:center;gap:7px;padding:2px 0;font-size:12.5px}
.cond .cbs{
  width:12px;height:12px;flex:0 0 12px;position:relative;cursor:pointer;
  border:1.5px solid var(--line-2);border-radius:var(--r-sm);background:var(--surface);
}
.cond .cbs:hover{border-color:var(--tx-3)}
.cond .cbs.on{background:var(--ac-2);border-color:var(--ac-2)}
.cond .cbs.on::after{content:"";position:absolute;left:3px;top:0;width:3px;height:6px;border:solid #fff;border-width:0 1.5px 1.5px 0;transform:rotate(43deg)}
.cond.ok{color:var(--tx-4);text-decoration:line-through}

.grid{display:grid;gap:9px;grid-template-columns:repeat(auto-fill,minmax(250px,1fr))}
.col-h{display:flex;align-items:center;gap:6px;margin-bottom:6px;font-size:12px;font-weight:600;color:var(--tx-2)}
.col-b{background:var(--bg);border:1px solid var(--line);border-radius:var(--r);padding:7px;min-height:56px}
.mini{
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r);
  padding:7px 9px;margin-bottom:6px;cursor:pointer;text-align:left;width:100%;
}
.mini:last-child{margin-bottom:0}
.mini:hover{border-color:var(--line-2)}
.mini .t{font-size:12.5px;line-height:1.4}
.mini .m{font-size:11px;color:var(--tx-3);margin-top:3px;display:flex;gap:5px;flex-wrap:wrap}

.cal{background:var(--surface);border:1px solid var(--line);border-radius:var(--r);padding:10px;margin-bottom:12px}
.cal-h{display:flex;align-items:center;gap:8px;margin-bottom:8px}
.cal-h h3{flex:1;font-size:13px;font-weight:600}
.cal-g{display:grid;grid-template-columns:repeat(7,1fr);gap:3px}
.cal-g .wd{text-align:center;font-size:10px;color:var(--tx-3);padding-bottom:3px}
.cal-d{
  min-height:62px;border:1px solid var(--line);border-radius:var(--r-sm);
  padding:3px 4px;background:var(--surface);cursor:pointer;overflow:hidden;
}
.cal-d:hover{border-color:var(--line-2);background:var(--hover)}
.cal-d.out{opacity:.32}
.cal-d.today{border-color:var(--ac);background:var(--ac-bg)}
.cal-d .dn{font-size:10.5px;color:var(--tx-3)}
.cal-d.today .dn{color:var(--ac);font-weight:700}
.cal-d .mini-row{display:flex;align-items:center;gap:3px;margin-top:1px;font-size:10px;color:var(--tx-2)}
.cal-d .mini-row span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cal-d .more{font-size:9.5px;color:var(--tx-3)}

.stat-row{display:flex;align-items:center;gap:11px;padding:5px 0;border-bottom:1px solid var(--line)}
.stat-row:last-child{border-bottom:0}
.stat-row .nm{width:170px;flex:0 0 170px;font-size:12.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* 轨道底色要能看见 —— 完成率往往很低（10%甚至 0%），否则整条像没渲染 */
.stat-row .tr{flex:1;height:6px;background:var(--sunken);border-radius:3px;overflow:hidden}
.stat-row .tr i{display:block;height:100%;background:var(--ac-2);border-radius:2px}
.stat-row .tr i.p{background:var(--line-2)}
.stat-row .tr i.o{background:var(--amb)}
.stat-row .vv{width:76px;flex:0 0 76px;text-align:right;font-size:11px;color:var(--tx-3)}

.spark{display:flex;gap:2px;align-items:flex-end;height:56px}
.spark i{flex:1;background:var(--ac);border-radius:1px 1px 0 0;min-height:2px}
.spark i.zero{background:var(--line)}
.spark-axis{display:flex;justify-content:space-between;font-size:10px;color:var(--tx-3);margin-top:6px;padding-top:6px;border-top:1px solid var(--line)}
.spark-empty{color:var(--tx-3);font-size:12px;text-align:center;padding:20px 0 6px}

.empty{
  text-align:center;color:var(--tx-3);padding:24px 12px;font-size:12.5px;
  border:1px dashed var(--line-2);border-radius:var(--r);background:var(--surface);
}
.empty b{display:block;color:var(--tx-2);font-size:13px;font-weight:500;margin-bottom:2px}
.list-t{list-style:none;margin:0;padding:0}
.tbl{width:100%;border-collapse:collapse;font-size:12.5px}
.tbl th{text-align:left;font-weight:500;color:var(--tx-3);font-size:10.5px;padding:4px 7px;border-bottom:1px solid var(--line)}
.tbl td{padding:5px 7px;border-bottom:1px solid var(--line)}
.tbl tr:last-child td{border-bottom:0}

/* ============================================================
   浮层：唯一使用投影的地方
   ============================================================ */
.modal{position:fixed;inset:0;background:rgba(20,24,30,.34);display:flex;align-items:flex-start;justify-content:center;padding:8vh 16px;z-index:50}
.modal[hidden]{display:none}
.sheet{background:var(--surface);border-radius:var(--r);width:100%;max-width:520px;box-shadow:var(--sh);max-height:84vh;display:flex;flex-direction:column}
.sheet-h{padding:12px 15px;border-bottom:1px solid var(--line);display:flex;align-items:center;gap:10px}
.sheet-h h3{font-size:14px;flex:1;font-weight:600}
.sheet-b{padding:14px 15px;overflow:auto}
.sheet-f{padding:10px 15px;border-top:1px solid var(--line);display:flex;gap:7px;justify-content:flex-end;align-items:center}
.x{border:0;background:none;font-size:19px;line-height:1;color:var(--tx-3);padding:0 5px}
.x:hover{background:var(--hover);color:var(--tx)}

.f{margin-bottom:11px}
.f:last-child{margin-bottom:0}
.f label{display:block;font-size:11px;color:var(--tx-3);margin-bottom:3px}
.f input[type=text],.f input[type=date],.f input[type=number],.f select,.f textarea{
  width:100%;padding:6px 9px;border:1px solid var(--line-2);border-radius:var(--r);
  background:var(--surface);outline:none;font-size:13px;
}
.f textarea{min-height:62px;resize:vertical}
/* 日期输入统一显示格式，不受浏览器 locale影响 */
.f input[type=date]{
  -webkit-appearance:none;appearance:none;
  font-variant-numeric:tabular-nums;
}
.f input[type=date]::-webkit-datetime-edit{font-variant-numeric:tabular-nums}
.f input:focus,.f select:focus,.f textarea:focus{border-color:var(--ac)}
.f .two{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.f .three{display:grid;grid-template-columns:1fr 1fr 1fr;gap:8px}

.seg{display:flex;gap:4px;flex-wrap:wrap}
.seg button{
  padding:5px 10px;border:1px solid var(--line-2);background:var(--surface);
  border-radius:var(--r);font-size:12.5px;color:var(--tx-2);
}
.seg button:hover{border-color:var(--tx-4)}
.seg button.on{background:var(--ac-2);border-color:var(--ac-2);color:#FFFFFF;font-weight:500}


.help{font-size:12.5px;line-height:1.75;color:var(--tx-2)}
.help h4{margin:15px 0 4px;font-size:12.5px;font-weight:600;color:var(--tx)}
.help h4:first-child{margin-top:0}
.help ul,.help ol{margin:0;padding-left:18px}
.help code{background:var(--sunken);padding:1px 4px;border-radius:var(--r-sm);font-size:11.5px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}
.help .kb{border:1px solid var(--line);border-radius:var(--r);padding:9px 11px;background:var(--bg)}

.toast{
  position:fixed;left:50%;bottom:22px;transform:translateX(-50%);
  background:var(--tx);color:var(--surface);padding:7px 14px;border-radius:var(--r);
  font-size:12.5px;z-index:80;box-shadow:var(--sh);
}
.toast[hidden]{display:none}

/* ============================================================
   访问门禁：未解锁时 body.locked，主界面完全不渲染
   ============================================================ */
body.locked .app{display:none}
.gate{
  position:fixed;inset:0;z-index:120;
  background:var(--bg);
  display:flex;align-items:center;justify-content:center;padding:16px;
}
.gate-box{
  width:100%;max-width:320px;background:var(--surface);
  border:1px solid var(--line);border-radius:8px;
  padding:24px 20px 20px;text-align:center;
}
.gate-ic{color:var(--tx-3);margin-bottom:8px}
.gate-box h2{font-size:15px;margin-bottom:4px}
.gate-box p{font-size:11.5px;color:var(--tx-3);margin-bottom:14px}
.gate-box input{
  width:100%;height:32px;padding:0 11px;box-sizing:border-box;
  border:1px solid var(--line-2);border-radius:var(--r);
  background:var(--surface);color:var(--tx);outline:none;margin-bottom:9px;
}
.gate-box input:focus{border-color:var(--ac)}
.gate-box .btn{width:100%;height:32px}
.gate-err{color:var(--red);font-size:11.5px;margin:9px 0 0}
.gate-err[hidden]{display:none}
.fab-bar{position:sticky;bottom:0;display:flex;gap:8px;flex-wrap:wrap;padding:9px 0 2px}

/* ============================================================
   手机 / 窄屏（≤860px）
   核心改动：放弃桌面的「100vh 锁死 + 内部滚动」——
   手机浏览器里 100vh 不可靠（地址栏伸缩），嵌套滚动经常拖不动，
   内容直接看不全。改为自然文档流：整页跟着手指滚。
   侧栏压成「吸顶导航条」：品牌行 + 横滑菜单，随时可切页。
   ============================================================ */
@media (max-width:860px){
  html,body{height:auto;overflow:visible}
  .app{display:block;height:auto;overflow:visible}

  /* 侧栏 → 吸顶条：品牌一行 + 菜单横滑 */
  .side{
    width:auto;flex:none;display:block;
    border-right:0;border-bottom:1px solid var(--line);
    position:sticky;top:0;z-index:30;
  }
  .brand{height:40px;padding:0 12px}
  .nav{
    flex-direction:row;flex-wrap:nowrap;overflow-x:auto;
    padding:5px 8px;gap:2px;-webkit-overflow-scrolling:touch;
  }
  .nav .nv{width:auto;white-space:nowrap;flex:0 0 auto;padding:6px 9px}
  .nav .nv-gt{display:none}          /* 分组标题在横条里没意义，隐藏 */
  .nav .nv-main .nv{padding:6px 9px}
  /* 数据导入导出等低频操作在手机上收起，避免挤成一团 */
  .side-foot{display:none}

  /* 主区回归文档流：顶栏折行、搜索框独占一行，内容随页滚 */
  .main{display:block}
  .top{height:auto;flex:0 0 auto;padding:8px 12px;flex-wrap:wrap;gap:8px}
  .top-l{flex:1;min-width:0}
  .top-l p{display:none}
  .qa{order:3;flex-basis:100%}
  .view{padding:12px;overflow:visible}
  .detail{border-top:1px solid var(--line)}

  /* 触屏没有 hover：平时藏起来的按钮改为常显 */
  .pgrp-reset{opacity:1}
  .pgrp-h:hover .pgrp-grip{color:rgba(255,255,255,.45)}

  .stat-row .nm{width:100px;flex:0 0 100px}
}

/* ============================================================
   横向项目卡片（今日概况）
   一卡 = 一项目，横向滚动；点卡片 → 下方「项目详情」展开全部事项。
   放在文件末尾，横向拖动指示才能盖过前面的纵向指示。
   ============================================================ */
.pgrid{
  display:flex;gap:10px;overflow-x:auto;padding:6px 2px 12px;
  align-items:stretch;scroll-snap-type:x proximity;
}
.pgrid .pgrp{
  flex:0 0 288px;margin:0;scroll-snap-align:start;
  display:flex;flex-direction:column;
}
.pgrid .pgrp.zero{opacity:.62}
.pgrp.pcard{cursor:pointer}
.pgrp.pcard.picked{outline:2px solid var(--ac);outline-offset:-2px}
.pcard-b{flex:1;overflow-y:auto;max-height:340px}
.pcard-empty{padding:20px 12px;color:var(--tx-3);font-size:12px;text-align:center}
.pcard-more{
  padding:5px 12px;font-size:10.5px;color:var(--tx-3);
  border-top:1px dashed var(--line);text-align:center;flex:0 0 auto;
}
/* 卡内行收窄：行尾按钮藏起来（动作都在下方详情面板里），勾选框仍可用 */
.pcard .act-row{padding:7px 10px 7px 11px}
.pcard .acts{display:none}
.pcard .ttl{font-size:12.5px;line-height:1.45;word-break:break-all}
.pcard .meta{display:flex;flex-wrap:wrap;gap:4px}

/* 项目详情面板（点卡片后出现在卡片行下方） */
.pdetail{border-left:3px solid var(--ac)}
.pdetail .zone-h .btn{margin-left:6px}
.pd-done-h{
  margin:12px 0 4px;padding-top:8px;border-top:1px solid var(--line);
  font-size:11px;color:var(--tx-3);font-weight:500;
}

/* 横向拖动的插入指示：竖线在左右边缘（盖过前面的上下横线版） */
.zone-b .pgrid .pgrp.over-top{box-shadow:inset 3px 0 0 var(--ac)}
.zone-b .pgrid .pgrp.over-bot{box-shadow:inset -3px 0 0 var(--ac)}
