/* 颜色 / 圆角 / 阴影 / 字重一律来自 store/ui.css。此处不再定义 :root。
   页面必须同时引 ui.css 与 proto.css；proto.css 只管结构与组件。 */

*{box-sizing:border-box;margin:0;padding:0}
body{font-family:var(--ui-font);font-size:var(--ui-fs-body);color:var(--t1);background:var(--bg);-webkit-font-smoothing:antialiased}
.app{display:flex;height:100vh;overflow:hidden}
.side{width:var(--ui-side-w);flex:0 0 var(--ui-side-w);background:var(--side);color:var(--side-t);display:flex;flex-direction:column;overflow:auto}
.brand{height:var(--ui-topbar-h);display:flex;align-items:center;gap:9px;padding:0 var(--ui-space-4);color:#fff;font-weight:600;font-size:14px;letter-spacing:-.01em;border-bottom:1px solid var(--side-line);flex:0 0 var(--ui-topbar-h)}
.brand i{width:19px;height:19px;border-radius:6px;background:var(--p);display:inline-block;box-shadow:0 0 0 3px rgba(83,58,253,.22)}
.brand small{font-weight:400;font-size:11px;color:rgba(255,255,255,.42);margin-left:auto}
.nav{padding:var(--ui-space-3) var(--ui-space-2) var(--ui-space-5)}
.nav-t{font-size:11px;font-weight:600;letter-spacing:.04em;color:rgba(255,255,255,.40);padding:var(--ui-space-3) var(--ui-space-3) 6px;text-transform:none}
.nav-item{position:relative;display:flex;align-items:center;gap:9px;height:38px;padding:0 var(--ui-space-3);border-radius:6px;color:var(--side-t);cursor:pointer;font-size:13px;text-decoration:none;margin-bottom:2px;transition:background var(--ui-dur) var(--ui-ease),color var(--ui-dur) var(--ui-ease)}
.nav-item:hover{background:var(--ui-side-hover);color:#fff}
.nav-item.active{background:var(--ui-side-on);color:#fff;font-weight:600}
/* 选中项左侧一道 3px 靛蓝短条：比整行填色更轻，多个高亮也不闹 */
.nav-item.active::before{content:"";position:absolute;left:0;top:50%;transform:translateY(-50%);width:3px;height:18px;background:var(--p);border-radius:0 3px 3px 0}
.nav-item .dot{width:6px;height:6px;border-radius:50%;background:currentColor;opacity:.45}
.nav-item.active .dot{opacity:1;background:#a9a2ff}
.nav-item .cnt{margin-left:auto;font-size:10.5px;font-weight:600;background:var(--ui-side-badge);color:rgba(255,255,255,.82);border-radius:9px;padding:1px 6px}
.nav-item.active .cnt{background:var(--p);color:#fff}
.nav-item.is-stub{opacity:.42;cursor:not-allowed}
.nav-item.is-stub:hover{background:transparent;color:var(--side-t)}
.nav-item .cnt-stub{background:rgba(224,160,42,.18);color:#f0c675}
.main{flex:1;display:flex;flex-direction:column;min-width:0;overflow:hidden}
.topbar{height:var(--ui-topbar-h);flex:0 0 var(--ui-topbar-h);background:var(--ui-surface);border-bottom:1px solid var(--ui-border);display:flex;align-items:center;padding:0 var(--ui-density-page-x);gap:var(--ui-space-4)}
.crumb{font-size:13px;color:var(--t2)}
.crumb b{color:var(--t1);font-weight:600}
.topbar .right{margin-left:auto;display:flex;align-items:center;gap:var(--ui-space-4);font-size:12px;color:var(--t2)}
.avatar{width:29px;height:29px;border-radius:50%;background:var(--p);color:#fff;display:flex;align-items:center;justify-content:center;font-weight:600;font-size:12px}
.page{flex:1;overflow:auto;padding:var(--ui-density-page-y) var(--ui-density-page-x) var(--ui-space-9)}
/* 页头定高 = 按钮高：页头里有没有按钮，h1 会差 8px。
   有 .act 的页（预算 34）和只有一句说明的页（26）并排翻，标题像是在跳。
   定一个下限按钮高，标题一律贴底对齐，翻页时头不动。 */
.pt{display:flex;align-items:flex-end;gap:var(--ui-space-3);min-height:var(--ui-btn-h);margin-bottom:var(--ui-space-5)}
.pt h1{font-size:var(--ui-fs-h1);font-weight:600;letter-spacing:-.015em;color:var(--ui-text-1);line-height:1.25}
.pt p{font-size:var(--ui-fs-small);color:var(--t3);padding-bottom:2px}
.pt .act{margin-left:auto;display:flex;gap:var(--ui-space-2)}
.btn{height:var(--ui-btn-h);padding:0 var(--ui-space-4);border-radius:6px;border:1px solid var(--ui-border-2);background:var(--ui-surface);color:var(--t1);font-size:13px;font-family:inherit;cursor:pointer;display:inline-flex;align-items:center;gap:6px;white-space:nowrap;transition:background var(--ui-dur) var(--ui-ease),border-color var(--ui-dur) var(--ui-ease),color var(--ui-dur) var(--ui-ease),box-shadow var(--ui-dur) var(--ui-ease)}
.btn:hover{border-color:var(--p);color:var(--p);background:var(--ui-surface)}
.btn.primary{background:var(--p);border-color:var(--p);color:#fff;box-shadow:var(--ui-shadow-sm)}
.btn.primary:hover{background:var(--ph);border-color:var(--ph);color:#fff}
.btn.primary:active{background:var(--ui-primary-active);border-color:var(--ui-primary-active);box-shadow:none}
.btn.danger{color:var(--danger);border-color:var(--danger-bd)}
.btn.danger:hover{background:var(--danger-bg);border-color:var(--danger)}
.btn.ghost{border-color:transparent;background:transparent;color:var(--t2)}
.btn.ghost:hover{background:var(--ui-primary-soft);color:var(--p);border-color:transparent}
.btn.sm{height:var(--ui-btn-h-sm);padding:0 var(--ui-space-2);font-size:12px;border-radius:var(--ui-r-xs)}
.btn:disabled{opacity:.45;cursor:not-allowed}
.btn:disabled:hover{border-color:var(--ui-border-2);color:var(--t1);background:var(--ui-surface)}
.tabs{display:flex;gap:2px;border-bottom:1px solid var(--bd);margin-bottom:14px}
.tab{padding:9px 14px;font-size:13px;color:var(--t2);cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-1px;display:flex;align-items:center;gap:6px}
.tab:hover{color:var(--p)}
.tab.active{color:var(--p);border-bottom-color:var(--p);font-weight:500}
.tab .n{background:var(--chip);color:var(--t2);border-radius:9px;padding:0 6px;font-size:11px;line-height:16px}
.tab.active .n{background:var(--soft);color:var(--p)}
.filters{background:var(--ui-surface);border:1px solid var(--ui-border);border-radius:var(--ui-r-lg);padding:var(--ui-space-3) var(--ui-space-4);display:flex;gap:var(--ui-space-3);align-items:center;flex-wrap:wrap;margin-bottom:var(--ui-space-3)}
.inp{height:var(--ui-input-h);border:1px solid var(--bd2);border-radius:6px;padding:0 var(--ui-space-3);font-size:13px;color:var(--t1);background:var(--ui-surface);outline:none;font-family:inherit;transition:border-color var(--ui-dur) var(--ui-ease),box-shadow var(--ui-dur) var(--ui-ease)}
.inp:focus{border-color:var(--p);box-shadow:0 0 0 3px var(--soft)}
.inp.w160{width:160px}.inp.w120{width:120px}.inp.w220{width:220px}
select.inp{padding-right:6px}
.card{background:var(--ui-surface);border:1px solid var(--ui-border);border-radius:var(--ui-r-xl);margin-bottom:var(--ui-density-gap);overflow:hidden;transition:box-shadow var(--ui-dur) var(--ui-ease),border-color var(--ui-dur) var(--ui-ease)}
.card-h{height:48px;display:flex;align-items:center;gap:var(--ui-space-3);padding:0 var(--ui-density-card-p);border-bottom:1px solid var(--bd)}
.card-h h3{font-size:var(--ui-fs-title);font-weight:600;letter-spacing:-.008em}
.card-h .sub{font-size:var(--ui-fs-small);color:var(--t3)}
.card-h .act{margin-left:auto;display:flex;gap:var(--ui-space-2);align-items:center}
.card-b{padding:var(--ui-density-card-p)}
.card-b.p0{padding:0}
/* 列宽一律 minmax(0,1fr)：裸 1fr 的最小值是 min-content，右边那张
   「应收未收 ¥48,320.00」一宽，整列就比邻列胖，四张 KPI 卡宽度不齐 —— 一排卡
   最刺眼的就是宽度不齐。minmax(0,…) 让四列严格等分，内容超了走省略号。 */
.grid{display:grid;gap:var(--ui-density-gap);align-items:stretch}
/* 网格里的卡片一律吃满行高：同排卡片底边对齐靠的是拉伸，不是内容刚好一样高。
   不写死这条，只要一张卡少一行字，它自己就矮一截，一排底边犬牙交错。
   卡片自带的 margin-bottom 会把拉伸抵消掉（height 被 margin 吃掉），这里清掉。 */
.grid > *{margin-bottom:0}
.g2{grid-template-columns:repeat(2,minmax(0,1fr))}
.g3{grid-template-columns:repeat(3,minmax(0,1fr))}
.g4{grid-template-columns:repeat(4,minmax(0,1fr))}
@media(max-width:1280px){.g4{grid-template-columns:repeat(2,minmax(0,1fr))}.g3{grid-template-columns:repeat(2,minmax(0,1fr))}}
table{width:100%;border-collapse:collapse;font-size:var(--ui-fs-body)}
th{background:var(--head);color:var(--t2);font-weight:500;text-align:left;padding:var(--ui-density-cell-y) var(--ui-density-cell-x);border-bottom:1px solid var(--bd);white-space:nowrap;font-size:var(--ui-fs-small);letter-spacing:.01em}
td{padding:var(--ui-density-cell-y) var(--ui-density-cell-x);border-bottom:1px solid var(--line2);color:var(--t1);vertical-align:middle;height:var(--ui-density-row-h)}
tbody tr{transition:background var(--ui-dur) var(--ui-ease)}
tbody tr:hover{background:var(--hover)}
tbody tr.clickable{cursor:pointer}
tbody tr.on{background:var(--soft)}
td.num,th.num{text-align:right;font-variant-numeric:tabular-nums}
td.mono{font-variant-numeric:tabular-nums}
.muted{color:var(--t3)}
.small{font-size:11.5px}
.tag{display:inline-flex;align-items:center;gap:4px;height:22px;padding:0 var(--ui-space-2);border-radius:var(--ui-r-sm);font-size:var(--ui-fs-caption);line-height:1;white-space:nowrap;font-weight:500}
.tag.ok{background:var(--ok-bg);color:var(--ok-t)}
.tag.warn{background:var(--warn-bg);color:var(--warn-t)}
.tag.danger{background:var(--danger-bg);color:var(--danger-t)}
.tag.info{background:var(--soft);color:var(--soft-t)}
.tag.mute{background:var(--line2);color:var(--t2)}
.tag.purple{background:var(--purple-bg);color:var(--purple-t)}
.money{font-variant-numeric:tabular-nums;font-weight:600}
.money.red{color:var(--danger)}
/* 列弹性：一排卡里文字行数不一样（有的两行、有的三行），靠列弹性把进度条压到底。
   不写的话四张卡一样高、内容却各悬在顶部，进度条位置参差。 */
.kpi{position:relative;display:flex;flex-direction:column;background:var(--ui-surface);border:1px solid var(--ui-border);border-radius:var(--ui-r-lg);padding:var(--ui-space-4) var(--ui-space-5);transition:box-shadow var(--ui-dur) var(--ui-ease),border-color var(--ui-dur) var(--ui-ease),transform var(--ui-dur) var(--ui-ease)}
.kpi:hover{box-shadow:var(--ui-shadow-md);border-color:var(--ui-border-2)}
.kpi .k{font-size:var(--ui-fs-caption);color:var(--t3);margin-bottom:var(--ui-space-2);display:flex;align-items:center;gap:6px;font-weight:500;letter-spacing:.01em}
.kpi .v{font-size:var(--ui-fs-stat-lg);font-weight:600;font-variant-numeric:tabular-nums;letter-spacing:-.025em;line-height:1.15;color:var(--ui-text-1)}
.kpi .v small{font-size:var(--ui-fs-h3);font-weight:500;color:var(--t3);letter-spacing:0;margin-left:2px}
/* 趋势行：数字下面先说「比什么变了」，再说这张卡怎么算的。
   以前只有一句「目标 2 万 · 完成 93%」，分不清是进度还是同比。 */
.kpi .tr{font-size:var(--ui-fs-caption);color:var(--t2);margin-top:var(--ui-space-2);display:flex;align-items:center;gap:5px;line-height:1.5}
.kpi .tr em{font-style:normal;font-weight:600;font-variant-numeric:tabular-nums}
.kpi .tr.up em{color:var(--ui-success-text)}
.kpi .tr.down em{color:var(--ui-danger-text)}
.kpi .s{font-size:var(--ui-fs-caption);color:var(--t3);margin-top:var(--ui-space-2);line-height:1.5}
.kpi .s b{color:var(--t2);font-weight:600}
/* 目标进度：贴着卡片底部的一条细槽，不占垂直空间 */
/* 进度条沉到卡片底部：margin-top:auto 吃掉上一行以下的剩余高度，
   四张卡的进度条落在同一条线上；卡片内文字越多，留给它的空隙越少，不会溢出。 */
.kpi .goal{height:3px;border-radius:2px;background:var(--ui-neutral-bg);margin-top:auto;overflow:hidden}
.kpi .goal i{display:block;height:100%;border-radius:2px;background:var(--p)}
.kpi.bad .goal i{background:var(--ui-danger)}
.kpi.warn .goal i{background:var(--ui-warning)}
/* KPI 顶部一道 2px 状态条：不用把整个卡片染色，也能一眼分出好坏。
   状态词用 ok / warn / bad，不用 alert —— .alert 是带 padding 与 12.5px 字号的
   提示框组件，`class="kpi alert"` 会把这套尺寸套到卡片上，卡片高度就和邻卡差一截。 */
.kpi.bad::before{content:"";position:absolute;left:0;top:0;right:0;height:2px;background:var(--ui-danger);border-radius:var(--ui-r-lg) var(--ui-r-lg) 0 0}
.kpi.warn::before{content:"";position:absolute;left:0;top:0;right:0;height:2px;background:var(--ui-warning);border-radius:var(--ui-r-lg) var(--ui-r-lg) 0 0}
.kpi.ok::before{content:"";position:absolute;left:0;top:0;right:0;height:2px;background:var(--ui-success);border-radius:var(--ui-r-lg) var(--ui-r-lg) 0 0}
/* 表单一行几列：列宽一律 minmax(0,1fr)。裸 1fr 的下限是 min-content，
   同一行里放两个输入框，带长占位文字的那个会把本列撑胖，另一列就窄 2px ——
   看不出来，但输入框右边缘一行对不齐一行。 */
.form-row{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px 16px}
/* ── 负荷条 ──────────────────────────────────────────────────────────────
   工位与班组原来是两列文字（「12.5h / 24h」），读者得自己算谁满谁闲。
   横条把比值画出来：一眼看见哪条最长、哪条已经压线。 */
.load{display:flex;flex-direction:column;gap:var(--ui-space-2)}
.load .li{display:flex;align-items:center;gap:var(--ui-space-2);font-size:var(--ui-fs-caption);color:var(--t2)}
.load .li .n{width:78px;flex:0 0 78px;white-space:nowrap;color:var(--t1)}
.load .li .bar{flex:1 1 40px;min-width:34px;height:6px;border-radius:3px;background:var(--ui-neutral-bg);overflow:hidden;position:relative}
.load .li .bar i{display:block;height:100%;border-radius:3px;background:var(--p);transition:width var(--ui-dur) var(--ui-ease)}
.load .li .bar i.full{background:var(--ui-warning)}
.load .li .bar i.stop{background:var(--ui-danger)}
.load .li .v{flex:0 0 auto;max-width:62%;text-align:right;font-variant-numeric:tabular-nums;color:var(--t3);line-height:1.45}
.load .li .v b{color:var(--t1);font-weight:600}
.load .li.hint-line{border-top:1px dashed var(--bd);margin-top:2px;padding-top:var(--ui-space-2)}
.form-row.c2{grid-template-columns:repeat(2,minmax(0,1fr))}
.form-row.c1{grid-template-columns:minmax(0,1fr)}
.field{display:flex;flex-direction:column;gap:5px}
.field label{font-size:12px;color:var(--t2)}
.field label em{color:var(--danger);font-style:normal;margin-left:2px}
.field .hint{font-size:11px;color:var(--t3)}
.ro{height:30px;border:1px solid var(--ui-border);background:var(--ui-surface-2);border-radius:var(--ui-r-sm);padding:0 10px;display:flex;align-items:center;font-size:13px;color:var(--t2)}
/* 多选一律用勾选组，不用 <select multiple>：手机上没法多选，选了几项也看不出来 */
.cb-row{display:flex;gap:14px;flex-wrap:wrap;padding-top:5px}
.cb{display:inline-flex;align-items:center;gap:5px;font-size:13px;cursor:pointer;color:var(--t1)}
.cb input{width:14px;height:14px;accent-color:var(--p)}
.stage{display:flex;flex-direction:column;gap:2px}
.stage a{display:flex;align-items:center;gap:8px;padding:8px 10px;border-radius:var(--ui-r-sm);color:var(--t2);text-decoration:none;font-size:13px;cursor:pointer}
.stage a:hover{background:var(--line2)}
.stage a.on{background:var(--soft);color:var(--p);font-weight:600}
.stage a .idx{width:18px;height:18px;border-radius:50%;background:var(--chip);color:var(--t3);font-size:11px;display:flex;align-items:center;justify-content:center}
.stage a.on .idx{background:var(--p);color:var(--ui-text-inverse)}
.stage a.done .idx{background:var(--ok-soft);color:var(--ok-t)}
.tl{position:relative;padding-left:14px}
.tl:before{content:"";position:absolute;left:4px;top:6px;bottom:6px;width:1px;background:var(--bd)}
.tl-i{position:relative;padding:0 0 12px 8px}
.tl-i:before{content:"";position:absolute;left:-14px;top:5px;width:7px;height:7px;border-radius:50%;background:var(--ui-border-2);border:1px solid var(--ui-surface)}
.tl-i.hi:before{background:var(--p);box-shadow:0 0 0 3px var(--ui-primary-soft)}
.tl-i .t{font-size:11.5px;color:var(--t3);margin-bottom:2px}
.tl-i .m{font-size:12.5px;line-height:1.5}
.tl-i .m b{font-weight:600}
.tl-i del{color:var(--t3);text-decoration:line-through}
.tl-i ins{color:var(--ok);text-decoration:none;font-weight:600}
.mask{position:fixed;inset:0;background:rgba(6,27,49,.42);backdrop-filter:blur(1.5px);display:none;align-items:center;justify-content:center;z-index:50}
.mask.on{display:flex}
.modal{background:var(--ui-surface);border-radius:var(--ui-r-xl);width:520px;max-width:calc(100vw - 40px);max-height:86vh;display:flex;flex-direction:column;box-shadow:var(--ui-shadow-lg)}
.modal.wide{width:760px}
.modal-h{padding:15px 18px;border-bottom:1px solid var(--ui-border);display:flex;align-items:center;gap:8px}
.modal-h h3{font-size:var(--ui-fs-h3);font-weight:600;letter-spacing:-.01em}
.modal-h .x{margin-left:auto;color:var(--t3);cursor:pointer;font-size:16px;line-height:1;width:26px;height:26px;display:flex;align-items:center;justify-content:center;border-radius:var(--ui-r-sm)}
.modal-h .x:hover{background:var(--line2);color:var(--t1)}
.modal-b{padding:18px;overflow:auto}
.modal-f{padding:13px 18px;border-top:1px solid var(--ui-border);display:flex;gap:8px;justify-content:flex-end;align-items:center}
.modal-f .l{margin-right:auto;font-size:12px;color:var(--t3)}
.toast{position:fixed;left:50%;top:74px;transform:translateX(-50%);background:var(--ui-text-1);color:#fff;padding:10px 18px;border-radius:var(--ui-r-md);font-size:13px;opacity:0;transition:opacity var(--ui-dur) var(--ui-ease),transform var(--ui-dur) var(--ui-ease);pointer-events:none;z-index:99;max-width:70vw;line-height:1.5;box-shadow:var(--ui-shadow-lg)}
.toast.on{opacity:1;transform:translateX(-50%) translateY(2px)}
.toast.err{background:var(--ui-danger-text)}
.alert{display:flex;gap:10px;align-items:flex-start;padding:11px 14px;border-radius:var(--ui-r-md);font-size:12.5px;line-height:1.6;margin-bottom:14px;border:1px solid transparent}
.alert.warn{background:var(--ui-warning-bg);border-color:var(--ui-warning-bd);color:var(--ui-warning-text)}
.alert.info{background:var(--ui-info-bg);border-color:var(--ui-info-bd);color:var(--ui-info-text)}
.alert.danger{background:var(--ui-danger-bg);border-color:var(--ui-danger-bd);color:var(--ui-danger-text)}
.alert b{font-weight:600}
.alert .l{margin-left:auto;white-space:nowrap}
.chk{display:flex;flex-direction:column;gap:8px}
.chk-i{display:flex;align-items:center;gap:8px;font-size:12.5px}
.chk-i .box{width:15px;height:15px;border-radius:var(--ui-r-xs);border:1.5px solid var(--ui-border-2);display:flex;align-items:center;justify-content:center;font-size:10px;color:var(--ui-text-inverse);flex:0 0 15px}
.chk-i.done .box{background:var(--ok);border-color:var(--ok)}
.chk-i.todo .box{border-color:var(--warn)}
.chk-i .r{margin-left:auto;font-size:11.5px;color:var(--t3)}
.photo-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px}
.photo{border:1px solid var(--ui-border);border-radius:var(--ui-r-md);overflow:hidden;background:var(--head)}
.photo .ph{height:78px;background:repeating-linear-gradient(45deg,#f4f6fa,#f4f6fa 8px,#eaeff6 8px,#eaeff6 16px);display:flex;align-items:center;justify-content:center;font-size:11px;color:var(--t3)}
.photo .cap{padding:6px 8px;font-size:11.5px;display:flex;align-items:center;gap:6px}
.photo .cap .badge{margin-left:auto}
.split{display:grid;grid-template-columns:150px minmax(0,1fr) 290px;gap:0;height:calc(100vh - 56px)}.split>.col{padding:16px;overflow:auto}
.split>.col.mid{border-left:1px solid var(--ui-border);border-right:1px solid var(--ui-border);background:var(--ui-surface-2)}
.bear{display:flex;flex-wrap:wrap;gap:4px}
.bear span{background:var(--line2);border-radius:var(--ui-r-xs);padding:1px 6px;font-size:11px}
.bear span.b1{background:var(--soft);color:var(--soft-t)}
.bear span.b2{background:var(--ok-bg);color:var(--ok-t)}
.bear span.b3{background:var(--warn-bg);color:var(--warn-t)}
.bear span.b4{background:var(--purple-bg);color:var(--purple-t)}
.hr{height:1px;background:var(--bd);margin:12px 0}

/* ── 待办清单 ────────────────────────────────────────────────────────────
   工作台第一块内容。左侧 3px 竖条就是紧急度，跟顶层 KPI 的 2px 状态条同语汇：
   红=今天不处理就出事，黄=这周内要动，蓝=知道就行。
   分组标题用等宽小字，不抢行内文字。 */
.todo-list{display:flex;flex-direction:column}
.todo-grp{font-size:var(--ui-fs-caption);font-weight:600;letter-spacing:.02em;color:var(--t3);padding:var(--ui-space-3) var(--ui-density-card-p) var(--ui-space-1);background:var(--ui-surface-2);border-bottom:1px solid var(--ui-divider)}
.todo-grp:first-child{padding-top:var(--ui-space-2)}
.todo-grp em{font-style:normal;font-weight:400;margin-left:6px;color:var(--t3)}
.todo{display:flex;align-items:center;gap:var(--ui-space-3);padding:var(--ui-space-3) var(--ui-density-card-p);border-bottom:1px solid var(--ui-divider);border-left:3px solid transparent;cursor:pointer;transition:background var(--ui-dur) var(--ui-ease),border-color var(--ui-dur) var(--ui-ease)}
.todo:last-child{border-bottom:none}
.todo:hover{background:var(--ui-surface-2)}
.todo.urgent{border-left-color:var(--ui-danger)}
.todo.soon{border-left-color:var(--ui-warning)}
.todo.notice{border-left-color:var(--ui-info)}
.todo .ic{width:26px;height:26px;border-radius:var(--ui-r-lg);display:flex;align-items:center;justify-content:center;font-size:12px;flex:0 0 26px;font-weight:600}
.todo.urgent .ic{background:var(--ui-danger-bg);color:var(--ui-danger-text)}
.todo.soon .ic{background:var(--ui-warning-bg);color:var(--ui-warning-text)}
.todo.notice .ic{background:var(--ui-info-bg);color:var(--ui-info-text)}
.todo .tx{flex:1;min-width:0;line-height:1.5}
.todo .tx b{font-size:var(--ui-fs-body);font-weight:600;color:var(--ui-text-1)}
.todo .tx span{display:block;font-size:var(--ui-fs-caption);color:var(--t3);margin-top:1px}
.todo .amt{font-size:var(--ui-fs-body);font-weight:600;font-variant-numeric:tabular-nums;white-space:nowrap;color:var(--ui-danger-text)}
.todo .amt.mute{color:var(--t3);font-weight:500}
.todo .go{font-size:var(--ui-fs-caption);color:var(--p);white-space:nowrap;display:flex;align-items:center;gap:3px}
.todo:hover .go{text-decoration:underline}
.row{display:flex;align-items:center;gap:10px}
.row.wrap{flex-wrap:wrap}
.grow{flex:1}
.right{margin-left:auto}
.big{font-size:16px;font-weight:600;font-variant-numeric:tabular-nums}
.pill{display:inline-flex;align-items:center;height:22px;padding:0 10px;border-radius:var(--ui-r-lg);font-size:12px;background:var(--line2);color:var(--t2);cursor:pointer;transition:background var(--ui-dur) var(--ui-ease),color var(--ui-dur) var(--ui-ease)}
.pill:hover{background:var(--ui-border-2)}
.pill.on{background:var(--p);color:var(--ui-text-inverse)}
.note{font-size:11.5px;color:var(--t3);line-height:1.6;margin-top:6px}
.link{color:var(--p);cursor:pointer}
.link:hover{text-decoration:underline}
.hide{display:none!important}

/* ---------- 列表增强 lz（搜索 / 状态筛选 / 空状态 / 分页） ---------- */
.lz{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:10px;padding:9px 12px;background:var(--ui-surface);border:1px solid var(--ui-border);border-radius:var(--ui-r-lg)}
/* 工具条在卡片里（通常紧贴标题条下沿）：不再自己描边成一张小卡，
   只留一条下分隔线。否则卡片里套卡片，一眼看不出哪层是内容。 */
.card > .lz{margin-bottom:0;border:0;border-bottom:1px solid var(--bd);border-radius:0;background:var(--ui-surface-2)}
.lz .lz-q{width:250px}
.lz-st{display:flex;gap:4px;flex-wrap:wrap}
.lz-st .chip{height:26px;display:inline-flex;align-items:center;padding:0 10px;border-radius:var(--ui-r-lg);font-size:12px;background:var(--chip);color:var(--t2);cursor:pointer;white-space:nowrap;transition:background var(--ui-dur) var(--ui-ease),color var(--ui-dur) var(--ui-ease)}
.lz-st .chip:hover{background:var(--ui-border-2)}
.lz-st .chip.on{background:var(--p);color:var(--ui-text-inverse)}
.lz-n{font-size:12px;color:var(--t3);white-space:nowrap}
.lz-pg{margin-left:auto;display:flex;align-items:center;gap:6px}
.lz-pn{font-size:12px;color:var(--t2);font-variant-numeric:tabular-nums}
tr.lz-hide{display:none}
tr.lz-empty td{border-bottom:0;padding:34px 12px}
.lz-empty-in{display:flex;flex-direction:column;align-items:center;gap:7px;color:var(--t3);font-size:12px;text-align:center}
.lz-empty-in b{color:var(--t1);font-size:13px;font-weight:500}

/* ---------- 打印 ---------- */
@media print{
  .side,.topbar,.tabs,.lz,.pt .act,.toast{display:none!important}
  body{background:#fff}
  .app,.main,.page{display:block!important;height:auto!important;overflow:visible!important}
  .page{padding:0!important}
}
