/* ============================================================================
   任务派工系统 · Design System
   ----------------------------------------------------------------------------
   v1.7 起视觉语言取自 Airtable 的 DESIGN.md（skills/design-md，slug: airtable）：
   白画布 + 近黑主按钮 + 有彩色的「签名色块」。

   为什么换掉上一版的 Linear 暗色：Linear 是「工程团队盯代码」的审美——近黑画布、
   单一淡紫、极度克制。它的问题不是不高级，而是**一整屏灰黑里分不出重点**：
   任务、看板列、卡片层级都靠 5% 的灰度差，扫视时非常费眼。
   Airtable 恰好解决这件事——它本身就是做结构化数据表格的，
   和本系统的表格 / 看板 / 日历是同构的，而且它的层级靠**色块对比**不靠灰度差。

   从 Airtable 只取三件事（其余都按内部工具的密度收敛）：
     1. 主按钮是**近黑**不是品牌蓝。CSS 里那个 --theme_button-background-primary
        其实是链接色，照抄会把「自信的一次行动」做成普通 SaaS 蓝按钮
     2. 有彩色只作**签名色块**（奶油/蜜桃/薄荷/芥末），绝不拿来刷小面积装饰
     3. 层级靠 color-block 而非阴影；阴影永远是「很浅的一层」

   原则：
   1. 一个主色（近黑）+ 一套有彩色标记；颜色用来分区分状态，不用来炫。
   2. 层次靠「白画布 vs 签名色块」的对比，其次才是边框和浅投影。
   3. 每个可交互的东西都有 4 个态：hover / active / focus-visible / disabled。
      没有 focus-visible 就等于键盘用户不存在，这条不让步。
   4. 动效只服务两件事：告诉用户「东西从哪来」（抽屉/弹层），
      和「操作成功了」（微光 + 轻位移）。时长 120–260ms，缓动是减速曲线。
   5. 数字用等宽 tabular-nums，时间列不错位。
   6. 不用外部字体 / 图标库：桌面软件要能离线跑，图标全部内联 SVG。
   ========================================================================== */

:root{
  /* 中性色阶（v1.7 亮色主题，取自 Airtable 的 white-canvas 体系）。
     方向又反回来了：数字越大越深，--n-0 是「卡片表面」= 白，
     --n-900 是「最深的文字」= 近黑 #181d26。
     这样 --ink:var(--n-900) 的语义在明暗两种主题下都成立，语义层不用改。 */
  --n-0:#ffffff;   /* surface：卡片 */
  --n-25:#f8fafc;  /* surface-soft 抬升 */
  --n-50:#f7f8fa;  /* 页面底 */
  --n-100:#f1f3f6; /* 轻填充：pill 底、seg 槽、表头 */
  --n-150:#e8eaee; /* 内部分隔线 */
  --n-200:#dcdcdc; /* hairline 卡片边框（Airtable 的 #dddddd） */
  --n-300:#c8ccd4; /* 滚动条、失效边框 */
  --n-400:#82878f; /* 占位符/禁用，已做到 3:1 以上 */
  --n-500:#676c75; /* 三级文字 4.97:1 */
  --n-600:#41454d; /* 二级文字（Airtable muted）9.05:1 */
  --n-700:#333840; /* 正文（Airtable body） */
  --n-800:#232833;
  --n-900:#181d26; /* 主文字（Airtable ink）15.9:1 */
  --n-950:#0d1218; /* 最深：按下态、登录页画布 */

  /* 语义 */
  --bg:var(--n-50);
  --canvas:#ffffff;
  --panel:var(--n-0);
  --ink:var(--n-900);
  --ink-2:var(--n-600);
  --ink-3:var(--n-500);
  --ink-4:var(--n-400);
  --line:var(--n-150);
  --line-ctl:#7c828c;      /* 输入框边界：3.87:1，装饰线不适用这个标准 */
  --line-strong:var(--n-200);

  /* Airtable 的招牌不是蓝按钮，而是**近黑**主按钮 + 白色描边次按钮这一对。
     --brand 保留近黑（填充分色），--brand-ink 给链接用真正的链接蓝。
     这是这份规范最容易读错的地方：CSS 里那个 --theme_button-background-primary
     变量其实是链接色，不是按钮色，照抄会把「自信的一次行动」做成普通 SaaS。 */
  --brand:#181d26;
  --brand-hover:#0d1218;
  --brand-active:#000000;
  --brand-ink:#1b61c9;   /* 链接蓝，Airtable 的 link */
  --link-hover:#1a3866;  /* link-active，按下更深 */
  --brand-soft:#eaf1fd;
  --brand-line:#bcd3f5;
  /* 有彩色只作「签名色块」用，绝不拿来刷小面积装饰（Airtable 的 do/don't） */
  --coral:#aa2d00;   --coral-soft:#fdeee8;
  --forest:#0a2e0e;  --forest-soft:#e8f2ea;
  --cream:#f5e9d4;   --peach:#fcab79;
  --mint:#a8d8c4;    --yellow:#f4d35e;  --mustard:#8a6100;
  --ok:#006400;   --ok-soft:#e8f5e9;   --ok-line:#a8d8b5;
  --warn:#8a4b00; --warn-soft:#fdf3e3; --warn-line:#f0dcb8;
  --danger:#b3261e; --danger-soft:#fdeceb; --danger-line:#f5c9c5;
  --violet:#5b3fd6; --violet-soft:#efeafd;

  /* 形状：Airtable 的 rounded 阶梯 2/6/10/12 + full */
  --r-xs:4px; --r-sm:6px; --r:8px; --r-lg:12px; --r-xl:16px;
  /* 亮色下投影重新变得廉价好用，但仍是「很浅的一层」，
     层级首选仍是白画布与签名色块的对比（Airtable: color-block first）。 */
  --sh-1:0 1px 2px rgba(24,29,38,.06);
  --sh-2:0 2px 4px -1px rgba(24,29,38,.07), 0 8px 18px -12px rgba(24,29,38,.16);
  --sh-3:0 12px 30px -12px rgba(24,29,38,.2), 0 2px 8px -2px rgba(24,29,38,.07);
  --sh-pop:0 24px 60px -24px rgba(24,29,38,.32);
  --edge-hi:inset 0 1px 0 rgba(255,255,255,.9);

  /* ==========================================================================
     毛玻璃材质（浅色版）
     --------------------------------------------------------------------------
     亮色玻璃比暗色难做：白底上再叠白，容易糊成一片没有边界。
     所以亮色玻璃靠「高透明度 + 更强边框 + 更明显的光斑」三件套：
     透明度提到 .55–.88（暗色是 .46–.78），边框降为深色半透明，
     光斑用奶油/薄荷/蜜桃这些 Airtable 签名色，压得很淡。
     ========================================================================== */
  --glass-1:rgba(255,255,255,.78);   /* 卡片：最实，正文都在这层 */
  --glass-2:rgba(255,255,255,.62);   /* 抬升块：子导航、表头 */
  --glass-3:rgba(255,255,255,.72);   /* 浮层：下拉、气泡 */
  --glass-pop:rgba(255,255,255,.92); /* 弹窗：要压住内容 */
  --glass-edge:rgba(24,29,38,.10);   /* 玻璃边缘：深色半透明细线 */
  --glass-hi:inset 0 1px 0 rgba(255,255,255,.95);
  --blur-sm:blur(10px) saturate(140%);
  --blur:blur(18px) saturate(150%);
  --blur-lg:blur(24px) saturate(160%);

  /* 动效 */
  --ease:cubic-bezier(.2,.8,.25,1);
  --ease-out:cubic-bezier(.16,1,.3,1);
  --t-fast:120ms; --t:180ms; --t-slow:260ms;

  --mono:ui-monospace,"SFMono-Regular","JetBrains Mono",Consolas,"Liberation Mono",monospace;
  --sidebar-w:224px;
  --topbar-h:56px;
}

*,*::before,*::after{box-sizing:border-box}
html,body{margin:0;padding:0}
/* 让浏览器自带的控件（滚动条、日期面板、自动填充）跟着暗色走。
   不加这一行，下拉展开的白色原生列表会在暗界面里像一块补丁。 */
:root{color-scheme:light}

/* 毛玻璃的底座：固定一层极低饱和的光斑。
   没有这个，玻璃后面就是一片纯色，blur 之后跟实色没有区别——那只是「半透明」，
   不是毛玻璃。光斑刻意压得很暗（8%–14% 透明度），保证不会干扰读字。
   position:fixed 让它不随滚动移动，玻璃划过时才有「擦过雾气」的相对位移。 */
body::before{
  content:"";position:fixed;inset:0;z-index:-1;pointer-events:none;
  background:
    radial-gradient(54vw 44vw at 10% -8%,rgba(27,97,201,.10),transparent 70%),
    radial-gradient(48vw 40vw at 96% 2%,rgba(168,216,196,.30),transparent 68%),
    radial-gradient(56vw 46vw at 80% 98%,rgba(252,171,121,.22),transparent 72%),
    radial-gradient(42vw 36vw at 2% 86%,rgba(244,211,94,.18),transparent 70%);
}

body{
  /* v1.6 起界面正文统一用微软雅黑（Windows 内置，离线可用）。
     雅黑放在最前面：它同时有中英文，中英混排时字重和字面高度更统一，
     不会再出现「英文像另一套字体」的割裂感。
     -apple-system / Segoe 留在后面，只在没有雅黑的机器（Mac/Linux）兜底。
     "Microsoft YaHei UI" 是雅黑在 UI 语境下的变体（字距略紧），优先用它。 */
  font-family:"Microsoft YaHei UI","Microsoft YaHei",-apple-system,
              BlinkMacSystemFont,"Segoe UI Variable Text","Segoe UI",
              "PingFang SC","Hiragino Sans GB",sans-serif;
  font-size:14px; line-height:1.6; color:var(--ink); background:var(--bg);
  -webkit-font-smoothing:antialiased; text-rendering:optimizeLegibility;
  font-feature-settings:"tnum" 0;
}
/* 表单控件不继承字体，必须显式声明，否则输入框会掉回 Times */
button,input,select,textarea{font-family:inherit}
::selection{background:var(--brand-soft);color:var(--brand-ink)}
a{color:var(--brand-ink);text-decoration:none;transition:color var(--t-fast) var(--ease)}
a:hover{color:var(--link-hover)}
h1,h2,h3,h4{margin:0;font-weight:650;letter-spacing:-.011em;line-height:1.3}
h1{font-size:20px} h2{font-size:15px} h3{font-size:13.5px}
p{margin:0}
small,.muted{color:var(--ink-3)}
.mono,.num{font-family:var(--mono);font-variant-numeric:tabular-nums}
.num{letter-spacing:-.02em}
.nowrap{white-space:nowrap}
.right{text-align:right}
.center{text-align:center}
.sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0)}

/* 键盘焦点：全局兜底，任何控件都不会「看不见焦点」 */
:focus-visible{outline:2px solid var(--brand);outline-offset:2px;border-radius:var(--r-xs)}

/* 细滚动条：桌面软件里粗滚动条特别廉价 */
*::-webkit-scrollbar{width:10px;height:10px}
*::-webkit-scrollbar-thumb{background:var(--n-300);border:3px solid transparent;
  background-clip:content-box;border-radius:99px}
*::-webkit-scrollbar-thumb:hover{background:var(--n-400);background-clip:content-box}
*::-webkit-scrollbar-track{background:transparent}

/* ============================================================================
   骨架
   ========================================================================== */
.shell{display:flex;min-height:100vh}

.sidebar{
  width:var(--sidebar-w);flex:0 0 var(--sidebar-w);
  /* 亮色下侧栏是「白玻璃」：靠右边一条细线跟内容分开，不再用深色压住左侧。
     深底侧栏在亮色主题里会像贴了一条黑边，跟 Airtable 的整页白画布冲突。 */
  background:var(--glass-1);backdrop-filter:var(--blur-lg);
  border-right:1px solid var(--glass-edge);
  color:var(--n-600);display:flex;flex-direction:column;
  position:sticky;top:0;height:100vh;z-index:30;
}
.brand{display:flex;gap:10px;align-items:center;padding:16px 16px 14px}
.brand .logo{
  width:30px;height:30px;border-radius:9px;display:grid;place-items:center;flex:0 0 auto;
  background:var(--brand);color:#fff;
  font-weight:750;font-size:14px;letter-spacing:-.5px;
  box-shadow:0 4px 12px -4px rgba(24,29,38,.45)
}
.brand b{display:block;color:var(--ink);font-size:13.5px;font-weight:650;line-height:1.25;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.brand span{font-size:11px;color:var(--ink-3);display:block;margin-top:1px}

.nav{padding:6px 8px;flex:1;overflow-y:auto;overflow-x:hidden}
.nav .group{
  font-size:10.5px;font-weight:600;letter-spacing:.08em;color:var(--ink-2);
  padding:14px 10px 6px;text-transform:uppercase
}
.nav a{
  display:flex;align-items:center;gap:9px;padding:8px 10px;margin-bottom:1px;
  border-radius:var(--r-sm);color:var(--n-800);font-size:13.5px;font-weight:500;
  position:relative;transition:background var(--t-fast) var(--ease),color var(--t-fast) var(--ease)
}
.nav a .ico{color:var(--ink-3);flex:0 0 auto;transition:color var(--t-fast) var(--ease)}
.nav a:hover{background:rgba(24,29,38,.045);color:var(--n-900)}
.nav a:hover .ico{color:var(--n-700)}
.nav a.active{background:var(--brand-soft);color:var(--brand-ink);font-weight:600}
.nav a.active .ico{color:var(--brand-ink)}
.nav a.active::before{
  content:"";position:absolute;left:-8px;top:50%;transform:translateY(-50%);
  width:3px;height:16px;border-radius:0 3px 3px 0;background:var(--brand)
}
.nav a .badge-dot{
  margin-left:auto;background:var(--danger);color:#fff;border-radius:99px;
  font-size:10px;font-weight:650;padding:1px 6px;min-width:17px;text-align:center;
  letter-spacing:0
}

.side-foot{padding:10px 12px 12px;border-top:1px solid rgba(255,255,255,.07)}
.side-foot .who{display:flex;align-items:center;gap:8px;padding:4px 2px 8px}
.side-foot .who .nm{color:var(--ink);font-size:12.5px;font-weight:600;line-height:1.25;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.side-foot .who .po{font-size:11px;color:var(--ink-3)}
.side-foot .row{gap:4px}
.foot-link{
  display:flex;align-items:center;gap:6px;padding:6px 8px;border-radius:var(--r-xs);
  color:var(--ink-3);font-size:12px;transition:background var(--t-fast),color var(--t-fast)
}
.foot-link:hover{background:rgba(24,29,38,.05);color:var(--n-900)}

.main{flex:1;min-width:0;display:flex;flex-direction:column}
.topbar{
  height:var(--topbar-h);display:flex;align-items:center;gap:12px;padding:0 22px;
  /* 毛玻璃顶栏：暗色下要用「深底 + 半透明」才有玻璃感。
     原来那层白 82% 是浅色主题的写法，留着会让面包屑的浅字落在白底上。 */
  background:rgba(255,255,255,.82);backdrop-filter:var(--blur);
  border-bottom:1px solid var(--line);position:sticky;top:0;z-index:20
}
.topbar .crumb{font-size:13px;color:var(--ink-3);display:flex;align-items:center;gap:7px;
  min-width:0;overflow:hidden;white-space:nowrap}
.topbar .crumb b{color:var(--ink);font-weight:650}
.topbar .spacer{flex:1}
.content{padding:20px 22px 72px;max-width:1440px;width:100%;margin:0 auto}

/* 页面标题区：每个页面一个，统一节奏 */
.page-head{display:flex;align-items:flex-start;gap:14px;margin-bottom:16px;flex-wrap:wrap}
.page-head .t{font-size:19px;font-weight:700;letter-spacing:-.02em;line-height:1.25}
.page-head .s{font-size:12.5px;color:var(--ink-3);margin-top:2px}
.page-head .acts{margin-left:auto;display:flex;gap:8px;align-items:center}

/* ============================================================================
   卡片与网格
   ========================================================================== */
.card{
  /* 卡片是玻璃的第一层：最实的一档，正文全落在这上面，
     所以透明度不能太低，否则字压不住背后的光斑。 */
  background:var(--glass-1);backdrop-filter:var(--blur);
  border:1px solid var(--glass-edge);border-radius:var(--r-lg);
  box-shadow:var(--sh-1),var(--glass-hi);overflow:hidden
}
.card .hd{
  display:flex;align-items:center;gap:9px;padding:13px 16px;
  border-bottom:1px solid var(--line);min-height:48px;flex-wrap:wrap
}
.card .hd h2{font-size:14px}
.card .hd .spacer{flex:1}
.card .bd{padding:14px 16px}
.card .bd.tight{padding:8px 10px}
.card .ft{padding:10px 16px;border-top:1px solid var(--line);
  background:var(--n-25);font-size:12px;color:var(--ink-3)}
.card.flush .bd{padding:0}
.card.interactive{transition:box-shadow var(--t) var(--ease),transform var(--t) var(--ease),
  border-color var(--t) var(--ease)}
.card.interactive:hover{box-shadow:var(--sh-2);border-color:var(--line-strong);
  transform:translateY(-1px)}

.grid{display:grid;gap:14px}
.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))}
.g-auto{grid-template-columns:repeat(auto-fill,minmax(232px,1fr))}
.row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.row.between{justify-content:space-between}
.col{display:flex;flex-direction:column;gap:8px}
.stack{display:flex;flex-direction:column;gap:10px}
.mt{margin-top:14px}.mt-s{margin-top:8px}.mb{margin-bottom:14px}.mb-s{margin-bottom:8px}
.panel{
  background:var(--n-50);border:1px solid var(--line);border-radius:var(--r);
  padding:12px 14px
}

/* ============================================================================
   按钮
   ========================================================================== */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:6px;
  border:1px solid var(--line-strong);background:var(--n-0);color:var(--ink);
  padding:0 12px;height:34px;border-radius:var(--r-sm);
  font-size:13px;font-weight:600;font-family:inherit;line-height:1;cursor:pointer;
  white-space:nowrap;user-select:none;
  transition:background var(--t-fast) var(--ease),border-color var(--t-fast) var(--ease),
             box-shadow var(--t-fast) var(--ease),transform var(--t-fast) var(--ease),
             color var(--t-fast) var(--ease);
  box-shadow:0 1px 1px rgba(0,0,0,.25)
}
.btn:hover{background:var(--n-50);border-color:var(--n-300);box-shadow:var(--sh-1)}
.btn:active{transform:translateY(1px);box-shadow:none}
.btn:disabled,.btn[aria-disabled="true"]{opacity:.45;cursor:not-allowed;transform:none;
  box-shadow:none;pointer-events:none}
.btn .ico{flex:0 0 auto;opacity:.72}

.btn.primary{background:var(--brand);border-color:var(--brand);color:#fff;
  box-shadow:0 1px 2px rgba(27,97,201,.4),0 4px 12px -6px rgba(27,97,201,.6)}
/* 悬停/按下是「更深」，不是变成链接蓝。主按钮一变蓝就退化成普通 SaaS，
   而 Airtable 的主按钮恰恰靠「近黑且更黑」表达「这是一次决定」。 */
.btn.primary:hover{background:var(--brand-hover);border-color:var(--brand-hover)}
.btn.primary:active{background:var(--brand-active);border-color:var(--brand-active)}
.btn.primary .ico{opacity:.9}
.btn.ghost{background:transparent;border-color:transparent;color:var(--ink-2);
  box-shadow:none}
.btn.ghost:hover{background:var(--n-100);color:var(--ink);border-color:transparent;
  box-shadow:none}
.btn.ok{color:var(--ok);border-color:var(--ok-line);background:var(--ok-soft)}
.btn.ok:hover{background:var(--ok-soft)}
.btn.danger{color:var(--danger);border-color:var(--danger-line);background:var(--danger-soft)}
.btn.danger:hover{background:var(--danger-soft)}
.btn.danger.solid{background:var(--danger);border-color:var(--danger);color:#fff}
.btn.danger.solid:hover{background:var(--danger)}
.btn.sm{height:28px;padding:0 9px;font-size:12.5px;border-radius:var(--r-xs);gap:5px}
.btn.lg{height:38px;padding:0 16px;font-size:13.5px}
.btn.block{width:100%}
.btn.icon{width:34px;padding:0}
.btn.icon.sm{width:28px}
.btn.loading{color:transparent!important;pointer-events:none;position:relative}
.btn.loading::after{
  content:"";position:absolute;width:14px;height:14px;border-radius:50%;
  border:2px solid currentColor;border-top-color:transparent;
  animation:spin .6s linear infinite;color:var(--n-900)
}
.btn.loading:not(.primary):not(.ok):not(.danger)::after{color:var(--ink-2)}

/* 分段控件：页面内切换视角的主力，滑动指示条 */
.seg{display:inline-flex;gap:2px;padding:3px;background:var(--n-100);
  border-radius:var(--r-sm);position:relative;border:1px solid var(--line)}
.seg a{
  position:relative;z-index:1;display:inline-flex;align-items:center;gap:6px;
  padding:0 11px;height:27px;border-radius:var(--r-xs);font-size:12.8px;
  font-weight:600;color:var(--ink-3);transition:color var(--t-fast) var(--ease)
}
.seg a:hover{color:var(--ink)}
.seg a.on{color:var(--ink)}
.seg .thumb{
  position:absolute;top:3px;left:0;height:calc(100% - 6px);border-radius:var(--r-xs);
  background:var(--n-0);box-shadow:0 1px 2px rgba(0,0,0,.45),0 1px 1px rgba(0,0,0,.3);
  transition:transform var(--t) var(--ease),width var(--t) var(--ease);z-index:0
}

/* 大 tabs（页面级） */
.tabs{display:flex;gap:2px;border-bottom:1px solid var(--line);margin-bottom:16px;
  overflow-x:auto;scrollbar-width:none}
.tabs::-webkit-scrollbar{display:none}
.tabs a{
  position:relative;padding:9px 12px;font-size:13.2px;font-weight:600;color:var(--ink-3);
  white-space:nowrap;transition:color var(--t-fast) var(--ease)
}
.tabs a:hover{color:var(--ink)}
.tabs a.on{color:var(--ink)}
.tabs a.on::after{
  content:"";position:absolute;left:8px;right:8px;bottom:-1px;height:2px;
  background:var(--brand);border-radius:2px 2px 0 0;
  animation:tabIn var(--t) var(--ease)
}
.tabs .count{font-size:11px;color:var(--ink-4);margin-left:4px;font-weight:600}

/* ============================================================================
   表单
   ========================================================================== */
label.f{display:block;margin-bottom:11px}
.drawer label.f{margin-bottom:8px}
.drawer .grid label.f:last-child{margin-bottom:0}
label.f > span,.fl{display:block;font-size:12px;font-weight:600;color:var(--ink-2);
  margin-bottom:5px;letter-spacing:.005em}
label.f > span .req{color:var(--danger);margin-left:2px}

input[type=text],input[type=password],input[type=email],input[type=tel],
input[type=date],input[type=time],input[type=number],input[type=search],
select,textarea{
  width:100%;height:36px;padding:0 11px;border:1px solid var(--line-ctl);
  border-radius:var(--r-sm);font-size:13.2px;font-family:inherit;color:var(--ink);
  background:var(--n-0);outline:none;appearance:none;
  transition:border-color var(--t-fast) var(--ease),box-shadow var(--t-fast) var(--ease),
             background var(--t-fast) var(--ease)
}
textarea{height:auto;min-height:76px;padding:9px 11px;resize:vertical;line-height:1.6}
select{
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23697180' stroke-width='2.4' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 10px center;padding-right:30px;cursor:pointer
}
select[multiple]{height:auto;min-height:96px;padding:6px;background-image:none;cursor:default}
/* 弹窗里的多选列表：3 行就够，96px 是给独立页面的，放在弹窗里会顶掉按钮 */
.drawer select[multiple]{min-height:78px}
select[multiple] option{padding:5px 8px;border-radius:var(--r-xs);font-size:13px}
select[multiple] option:checked{background:var(--brand-soft);color:var(--brand-ink)}
input:hover:not(:disabled),select:hover:not(:disabled),textarea:hover:not(:disabled){
  border-color:var(--n-500)}
input:focus,select:focus,textarea:focus{
  border-color:var(--brand);box-shadow:0 0 0 3px rgba(27,97,201,.16);background:var(--n-0)}
input::placeholder,textarea::placeholder{color:var(--n-400)}
input:disabled,select:disabled,textarea:disabled{
  background:var(--n-50);color:var(--ink-4);cursor:not-allowed}
input[type=date],input[type=time]{font-variant-numeric:tabular-nums}
input[type=number]{font-variant-numeric:tabular-nums}

/* 勾选 / 开关 */
.check{display:inline-flex;align-items:flex-start;gap:8px;font-size:12.8px;
  color:var(--ink-2);cursor:pointer;line-height:1.5;user-select:none}
.check input[type=checkbox]{appearance:none;width:16px;height:16px;flex:0 0 auto;
  margin:1px 0 0;border:1.5px solid var(--n-300);border-radius:5px;background:var(--n-0);
  cursor:pointer;position:relative;transition:all var(--t-fast) var(--ease)}
.check input[type=checkbox]:hover{border-color:var(--n-400)}
.check input[type=checkbox]:checked{background:var(--brand);border-color:var(--brand)}
.check input[type=checkbox]:checked::after{
  content:"";position:absolute;left:4.6px;top:1.2px;width:4px;height:8px;
  border:2px solid var(--n-900);border-top:0;border-left:0;transform:rotate(42deg)}
.check input[type=checkbox]:indeterminate{background:var(--brand);border-color:var(--brand)}
.check input[type=checkbox]:indeterminate::after{
  content:"";position:absolute;left:3px;top:6px;width:8px;height:2px;background:var(--n-0)}

.switch{position:relative;width:36px;height:20px;flex:0 0 auto;display:inline-block}
.switch input{position:absolute;opacity:0;width:100%;height:100%;margin:0;cursor:pointer;z-index:2}
.switch i{position:absolute;inset:0;background:var(--n-200);border-radius:99px;
  transition:background var(--t) var(--ease)}
.switch i::after{content:"";position:absolute;width:14px;height:14px;background:var(--n-0);
  border-radius:99px;top:3px;left:3px;transition:transform var(--t) var(--ease);
  box-shadow:0 1px 3px rgba(0,0,0,.22)}
.switch input:checked + i{background:var(--brand)}
.switch input:checked + i::after{transform:translateX(16px)}
.switch input:focus-visible + i{box-shadow:0 0 0 3px rgba(27,97,201,.25)}
.switch input:disabled + i{opacity:.5}

.hint{font-size:11.5px;color:var(--ink-3);line-height:1.6;margin-top:5px}
.err-text{font-size:11.5px;color:var(--danger);margin-top:4px;display:none}
.field.invalid input,.field.invalid select,.field.invalid textarea{
  border-color:var(--danger);box-shadow:0 0 0 3px rgba(239,83,80,.14)}
.field.invalid .err-text{display:block;animation:shakeX .3s var(--ease)}

/* 表单区段标题 */
.form-sec{border-top:1px solid var(--line);margin-top:14px;padding-top:13px}
.form-sec:first-of-type{border-top:0;margin-top:0;padding-top:0}
.form-sec .h{display:flex;align-items:center;gap:7px;font-size:12px;font-weight:700;
  color:var(--ink-3);letter-spacing:.04em;text-transform:uppercase;margin-bottom:10px}

/* ============================================================================
   分步表单（v1.6：新建 / 编辑任务）
   ----------------------------------------------------------------------------
   原来 5 个平铺区块 → 现在 3 步 + 折叠区。
   序号用实心圆点，让人一眼看出「一共几步、走到哪」；
   折叠区默认收起，只把大部分人必须填的露在外面。
   ========================================================================== */
.fstep{margin-top:13px}
.fstep:first-of-type{margin-top:0}
.fstep-h{display:flex;align-items:center;gap:9px;margin-bottom:7px;
  font-size:13px;font-weight:650;color:var(--ink)}
.fstep-n{
  width:20px;height:20px;flex:0 0 20px;border-radius:50%;
  display:grid;place-items:center;font-size:11.5px;font-weight:700;
  background:var(--brand);color:#fff;font-variant-numeric:tabular-nums
}
.fstep .req{color:var(--danger);font-style:normal;font-size:12px;margin-left:-4px}
/* 第一步的输入框做大：这是唯一必填、也是最该先填的字段 */
.fbig{height:40px;font-size:14.5px;font-weight:600}

/* 折叠区：默认收起，点标题展开。用 <button> 而不是 div，
   键盘 Tab 能到、回车能开，不用额外加 tabindex 和 keydown 监听。 */
.fold{margin-top:9px;border-top:1px solid var(--line);padding-top:7px}
.fold-h{
  display:flex;align-items:center;gap:7px;width:100%;padding:4px 0;
  background:none;border:0;cursor:pointer;text-align:left;
  font-size:12.5px;color:var(--ink-3);font-family:inherit;
  transition:color var(--t-fast) var(--ease)
}
.fold-h:hover{color:var(--ink)}
.fold-h .ar{display:inline-block;transition:transform var(--t) var(--ease);
  font-size:14px;line-height:1;color:var(--ink-4)}
.fold.open > .fold-h .ar{transform:rotate(90deg)}
.fold-b{display:none;padding-top:8px}
.fold.open > .fold-b{display:block;animation:slideUp var(--t) var(--ease-out)}
/* 三步之间只要一条淡分隔，别用五条横线把表单切碎 */
.fstep + .fstep{border-top:1px solid var(--line);padding-top:12px}

/* ============================================================================
   标签 / 徽标 / 头像
   ========================================================================== */
.pill{
  display:inline-flex;align-items:center;gap:4px;padding:2px 7px;border-radius:var(--r-xs);
  font-size:11.5px;font-weight:600;background:var(--n-100);color:var(--ink-2);
  white-space:nowrap;line-height:1.5;border:1px solid transparent
}
.pill.outline{background:transparent;border-color:var(--line-strong);color:var(--ink-2)}
.pill.gold{background:var(--warn-soft);color:var(--warn)}
.pill.violet{background:var(--violet-soft);color:var(--violet)}
.pill.blue{background:var(--brand-soft);color:var(--brand-ink)}
.pill.slate{background:var(--n-100);color:var(--ink-2)}
.pill.ok,.pill.done{background:var(--ok-soft);color:var(--ok)}
.pill.warn{background:var(--warn-soft);color:var(--warn)}
.pill.danger{background:var(--danger-soft);color:var(--danger)}
.pill.doing{background:var(--brand-soft);color:var(--brand-ink)}
.pill.pending{background:var(--n-100);color:var(--n-600)}
.pill.submitted{background:var(--warn-soft);color:var(--warn)}
.pill.skipped{background:var(--n-100);color:var(--ink-4)}
.pill .dot{width:5px;height:5px;border-radius:99px;background:currentColor;flex:0 0 auto}
.pill.lg{font-size:12px;padding:3px 9px}

.tag{font-family:var(--mono);background:var(--n-50);border:1px solid var(--line);
  border-radius:var(--r-xs);padding:1px 6px;font-size:11.5px;color:var(--ink-2)}

.avatar{
  width:30px;height:30px;border-radius:var(--r-sm);display:grid;place-items:center;
  font-weight:700;font-size:12.5px;flex:0 0 auto;color:var(--brand-ink);
  background:linear-gradient(150deg,var(--brand-soft),var(--brand-soft));border:1px solid var(--brand-line);
  letter-spacing:-.02em
}
.avatar.sm{width:24px;height:24px;border-radius:var(--r-xs);font-size:11px}
.avatar.xs{width:20px;height:20px;border-radius:5px;font-size:10px}
.avatar.gold{color:var(--warn);background:linear-gradient(150deg,var(--warn-soft),var(--warn-soft));border-color:var(--warn-line)}
.avatar.violet{color:var(--violet);background:linear-gradient(150deg,var(--violet-soft),var(--violet-soft));border-color:var(--violet-line)}
.avatar.slate{color:var(--ink-2);background:var(--n-100);border-color:var(--n-150)}
.person{display:flex;align-items:center;gap:8px;min-width:0}
.person .nm{font-weight:600;font-size:13px;line-height:1.3;color:var(--ink);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.person .po{font-size:11.5px;color:var(--ink-3);line-height:1.3;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* ============================================================================
   表格
   ========================================================================== */
.table{width:100%;border-collapse:separate;border-spacing:0;font-size:13px}
.table th{
  text-align:left;font-size:11px;letter-spacing:.05em;text-transform:uppercase;
  color:var(--ink-3);font-weight:700;padding:9px 14px;border-bottom:1px solid var(--line);
  background:var(--glass-2);backdrop-filter:var(--blur);
  white-space:nowrap;position:sticky;top:0;z-index:1
}
.table td{padding:10px 14px;border-bottom:1px solid var(--n-100);vertical-align:middle}
.table tbody tr{transition:background var(--t-fast) var(--ease)}
.table tbody tr:hover{background:var(--n-25)}
.table tbody tr:last-child td{border-bottom:0}
.table td.right,.table th.right{text-align:right}
.table td.num{font-family:var(--mono);font-variant-numeric:tabular-nums;font-size:12.5px}
.table-wrap{overflow:auto;max-height:560px}

/* ============================================================================
   KPI
   ========================================================================== */
.kpi{
  padding:14px 16px;border-radius:var(--r-lg);background:var(--panel);
  border:1px solid var(--line);box-shadow:var(--sh-1);position:relative;overflow:hidden
}
.kpi .lab{font-size:11.5px;color:var(--ink-3);display:flex;align-items:center;gap:5px;
  font-weight:600;letter-spacing:.02em}
.kpi .val{font-size:25px;font-weight:720;letter-spacing:-.03em;margin-top:5px;line-height:1.1;
  font-variant-numeric:tabular-nums}
.kpi .val small{font-size:13px;font-weight:600;color:var(--ink-4);margin-left:2px;
  letter-spacing:0}
.kpi .sub{font-size:11.5px;color:var(--ink-3);margin-top:5px;line-height:1.5}
/* v1.7：KPI 不再是一排白卡。Airtable 的层级逻辑是「用色块对比代替灰度差」，
   所以给每张 KPI 一个极淡的签名底色 + 顶部 3px 色条。
   扫视时先看到颜色分组，再读到数字，不用逐张比对灰度。 */
.kpi.accent{background:linear-gradient(180deg,var(--brand-soft),var(--panel));border-color:var(--brand-line)}
.kpi.accent .lab,.kpi.accent .val{color:var(--brand-ink)}
.kpi::before{
  content:"";position:absolute;left:0;right:0;top:0;height:3px;
  background:var(--n-300);opacity:.9
}
.kpi.accent::before{background:var(--brand-ink)}
.kpi.ok::before{background:var(--ok)}
.kpi.warn::before{background:var(--warn)}
.kpi.danger::before{background:var(--danger)}
.kpi.violet::before{background:var(--violet)}
/* 色条 + 极淡底色：只有色条会显得「加了根线」，底色带一点点才像一块有颜色的卡。

   透明度刻意压得很低（4%–7%），保证不抢数字，也不影响对比度。 */

.kpi.peach{background:linear-gradient(180deg,rgba(252,171,121,.14),var(--glass-1))}

.kpi.mint{background:linear-gradient(180deg,rgba(168,216,196,.20),var(--glass-1))}

.kpi.violet{background:linear-gradient(180deg,rgba(91,63,214,.07),var(--glass-1))}

.kpi.warn{background:linear-gradient(180deg,rgba(138,75,0,.07),var(--glass-1))}

.kpi.danger{background:linear-gradient(180deg,rgba(179,38,30,.07),var(--glass-1))}

.kpi.coral{background:linear-gradient(180deg,rgba(170,45,0,.07),var(--glass-1))}

.kpi.accent{background:linear-gradient(180deg,var(--brand-soft),var(--glass-1))}
.kpi.coral::before{background:var(--coral)}
.kpi.mint::before{background:var(--mint)}
.kpi.peach::before{background:var(--peach)}

.bar{height:5px;border-radius:99px;background:var(--n-150);overflow:hidden;position:relative}
.bar > i{display:block;height:100%;border-radius:99px;background:var(--brand);
  transition:width var(--t-slow) var(--ease)}
.bar.ok > i{background:var(--ok)}
.bar.warn > i{background:var(--warn)}
.bar.danger > i{background:var(--danger)}
.bar.thick{height:8px}

/* ============================================================================
   任务条目（时间轴 / 清单共用）
   ========================================================================== */
.task{
  display:flex;gap:12px;align-items:flex-start;padding:11px 13px;border-radius:var(--r);
  border:1px solid var(--glass-edge);background:var(--glass-1);
  backdrop-filter:var(--blur-sm);position:relative;
  transition:border-color var(--t-fast) var(--ease),box-shadow var(--t-fast) var(--ease),
             background var(--t-fast) var(--ease)
}
.task:hover{border-color:var(--line-strong);box-shadow:var(--sh-1)}
/* v1.7：任务卡左侧那条 2px 状态条原来只有「进行中」有，其余状态靠 opacity 区分——
   一屏十几条任务时全是灰白，分不出哪条在做、哪条超时。
   现在每种状态都有自己的颜色，扫一眼就能按颜色分堆，这是 Airtable 的色块分层法。 */
.task::before{
  content:"";position:absolute;left:0;top:9px;bottom:9px;width:3px;
  border-radius:0 3px 3px 0;background:var(--n-300)
}
.task.doing{border-color:var(--brand-line);background:linear-gradient(160deg,var(--brand-soft),var(--glass-1))}
.task.doing::before{background:var(--brand-ink)}
.task.todo::before,.task.pending::before{background:var(--n-400)}
.task.done::before{background:var(--ok)}
.task.late::before,.task.overdue::before{background:var(--danger)}
.task.blocked::before{background:var(--warn)}
.task.cancelled::before{background:var(--n-300)}
.task.done:hover{opacity:.85}
.task.cancelled{opacity:.5;text-decoration:line-through;text-decoration-color:var(--n-300)}
.task .time{
  font-family:var(--mono);font-variant-numeric:tabular-nums;font-size:12px;font-weight:650;
  color:var(--brand-ink);min-width:82px;line-height:1.45;letter-spacing:-.02em;
  border-right:1px solid var(--line);padding-right:9px;flex:0 0 auto
}
.task .time span{display:block;color:var(--ink-4);font-weight:500;font-size:11px}
/* 跨零点的班次（23:00–01:00）不标出来会被当成填错 */
.task .time .xday{font-size:9.5px;font-weight:700;color:var(--warn);margin-left:3px;
  border:1px solid currentColor;border-radius:3px;padding:0 2px;vertical-align:1px}
.task .body{flex:1;min-width:0}
.task .tt{font-weight:640;font-size:13.2px;display:flex;gap:6px;align-items:center;
  flex-wrap:wrap;line-height:1.45}
.task .dd{font-size:12.2px;color:var(--ink-2);margin-top:3px;line-height:1.55}
.task .acts{margin-left:auto;display:flex;gap:6px;align-items:center;flex:0 0 auto}

/* 一天分「上午 / 下午 / 晚上」三段。分段头要够轻——它是尺子，不是内容，
   抢了任务的注意力就本末倒置了：小字、灰、一条细线拉满剩余宽度。 */
.day-part{margin-top:12px}
.day-part:first-child{margin-top:4px}
.dp-h{display:flex;align-items:center;gap:8px;margin-bottom:7px}
.dp-name{font-size:12px;font-weight:680;color:var(--ink-2);letter-spacing:.02em}
.dp-meta{font-family:var(--mono);font-variant-numeric:tabular-nums;font-size:11px;
  color:var(--ink-4);font-weight:600}
.dp-line{flex:1;height:1px;background:var(--line)}
.dp-mins{font-family:var(--mono);font-variant-numeric:tabular-nums;font-size:11px;
  color:var(--ink-4);font-weight:600}
/* 全做完的那一段整段压暗一点，扫视时一眼能跳过 */
.day-part.all-done .dp-name{color:var(--ink-3)}
.day-part.all-done .dp-meta{color:var(--ok)}

/* 紧凑任务行（周看板列内） */
.tk{
  display:block;padding:6px 8px;border-radius:var(--r-xs);background:var(--n-50);
  border:1px solid transparent;font-size:11.8px;line-height:1.45;margin-bottom:4px;
  transition:all var(--t-fast) var(--ease);cursor:pointer;position:relative
}
.tk:hover{background:var(--n-0);border-color:var(--brand-line);box-shadow:var(--sh-1);
  transform:translateY(-1px)}
.tk .h{display:flex;gap:5px;align-items:center;justify-content:space-between;
  color:var(--brand-ink);font-family:var(--mono);font-size:10.5px;font-weight:700;
  font-variant-numeric:tabular-nums}
.tk .n{font-weight:600;color:var(--ink);margin-top:1px;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.tk .m{color:var(--ink-4);font-size:10.5px;margin-top:1px}
.tk.p-urgent{background:var(--danger-soft)}
.tk.p-high{background:var(--warn-soft)}
.tk.s-done{opacity:.55}
.tk.s-done .n{text-decoration:line-through}

/* ============================================================================
   抽屉（新建/编辑任务、成员、部门都用它：不打断当前页面上下文）
   ========================================================================== */
.drawer-mask{
  /* 遮罩本身也是玻璃：blur 掉底下的页面而不是压一层死黑。
     这样弹窗出现时背景还在，但被推远了，不会「世界消失」。 */
  position:fixed;inset:0;background:rgba(24,29,38,.28);backdrop-filter:blur(5px) saturate(120%);
  z-index:200;opacity:0;pointer-events:none;transition:opacity var(--t) var(--ease)
}
.drawer-mask.open{opacity:1;pointer-events:auto}
/* v1.6：新建/编辑任务的表单从「右侧抽屉」改成**屏幕居中的弹窗**。
   原因：这个表单有 5 组字段，右侧 480px 装不下，只能上下滚，
   用户滚到底才看得见保存按钮，流程是断的。居中弹窗一屏能看到全部字段 + 底部按钮。
   类名仍叫 .drawer，因为测试与 app.js 都按 .drawer 选择，改名没有收益。 */
.drawer{
  position:fixed;left:50%;top:50%;width:min(560px,94vw);max-height:min(90vh,900px);
  background:var(--glass-pop);backdrop-filter:var(--blur-lg);
  border:1px solid var(--glass-edge);border-radius:var(--r-xl);
  z-index:201;display:flex;flex-direction:column;
  box-shadow:var(--sh-pop),var(--glass-hi);
  /* 居中 + 入场：从下方轻微上浮，不是从右边滑入 */
  transform:translate(-50%,-46%) scale(.97);
  opacity:0;pointer-events:none;
  transition:transform var(--t-slow) var(--ease-out),opacity var(--t-slow) var(--ease-out);
  will-change:transform
}
.drawer.open{transform:translate(-50%,-50%) scale(1);opacity:1;pointer-events:auto}
.drawer .dh{
  display:flex;align-items:center;gap:10px;padding:14px 18px;
  border-bottom:1px solid var(--line);flex:0 0 auto
}
.drawer .dh h3{font-size:15px;font-weight:650}
.drawer .dh .sub{font-size:11.5px;color:var(--ink-3)}
.drawer .db{flex:1;overflow-y:auto;padding:14px 18px 16px}
.drawer .df{
  display:flex;gap:8px;align-items:center;padding:12px 18px;
  border-top:1px solid var(--glass-edge);background:rgba(255,255,255,.03);
  flex:0 0 auto
}
.drawer .df .spacer{flex:1}
.drawer .df .err{font-size:11.5px;color:var(--danger);display:none}

/* ============================================================================
   Toast
   ========================================================================== */
.toast-root{position:fixed;left:50%;bottom:22px;transform:translateX(-50%);
  z-index:300;display:flex;flex-direction:column-reverse;gap:8px;align-items:center;
  pointer-events:none;width:max-content;max-width:92vw}
.toast{
  display:flex;align-items:center;gap:9px;padding:9px 14px;border-radius:99px;
  /* toast 是「反相胶囊」：常规界面里底色最亮、字最深，才能在暗色层上跳出来。
     原来写的是深底白字，暗色主题下反相关系要跟着倒过来。 */
  /* toast 是「反相胶囊」：界面越浅，它越深，才能跳出来 */
  background:var(--n-900);color:#fff;font-size:13px;font-weight:550;
  box-shadow:var(--sh-3);pointer-events:auto;
  animation:toastIn var(--t-slow) var(--ease-out)
}
.toast.leaving{animation:toastOut var(--t) var(--ease) forwards}
.toast .ico{opacity:.85}
.toast.ok{background:var(--ok)}
.toast.error{background:var(--danger)}
.toast.warn{background:var(--warn)}

/* ============================================================================
   Flash（服务端一次性消息，做成可关闭的条）
   ========================================================================== */
.flash{
  display:flex;gap:9px;align-items:flex-start;padding:10px 13px;border-radius:var(--r);
  font-size:13px;margin-bottom:11px;border:1px solid;line-height:1.5;
  animation:flashIn var(--t) var(--ease)
}
.flash.success{background:var(--ok-soft);border-color:var(--ok-line);color:var(--ok)}
.flash.error{background:var(--danger-soft);border-color:var(--danger-line);color:var(--danger)}
.flash.info{background:var(--brand-soft);border-color:var(--brand-line);color:var(--brand-ink)}
.flash.warning{background:var(--warn-soft);border-color:var(--warn-line);color:var(--warn)}
.flash .x{margin-left:auto;cursor:pointer;opacity:.5;font-size:15px;line-height:1;
  padding:1px 3px;transition:opacity var(--t-fast)}
.flash .x:hover{opacity:1}

.empty{
  padding:40px 20px;text-align:center;color:var(--ink-3);font-size:13px;line-height:1.7
}
.empty .ico-lg{color:var(--n-300);margin-bottom:8px}
.empty b{color:var(--ink-2);font-weight:600;display:block;margin-bottom:3px}

/* 骨架屏 */
.sk{background:linear-gradient(90deg,var(--n-100) 25%,var(--n-50) 37%,var(--n-100) 63%);
  background-size:400% 100%;animation:shimmer 1.4s ease infinite;border-radius:var(--r-xs);
  height:12px}

/* ============================================================================
   时间轴（某天日程的左轨）
   ========================================================================== */
.tl{position:relative;padding-left:52px}
.tl::before{content:"";position:absolute;left:38px;top:6px;bottom:6px;width:1px;
  background:var(--line)}
.tl .slot{position:relative;padding-bottom:11px}
.tl .slot .hm{
  position:absolute;left:-52px;top:9px;width:34px;text-align:right;
  font-family:var(--mono);font-size:11px;color:var(--ink-4);font-variant-numeric:tabular-nums
}
.tl .slot::before{
  content:"";position:absolute;left:-15px;top:15px;width:7px;height:7px;border-radius:99px;
  background:var(--n-0);border:1.5px solid var(--n-300);z-index:1;
  transition:all var(--t) var(--ease)
}
.tl .slot.live::before{background:var(--brand);border-color:var(--brand);
  box-shadow:0 0 0 3px rgba(27,97,201,.18)}
.tl .slot.done::before{background:var(--ok);border-color:var(--ok)}
.tl .slot.past::before{background:var(--n-200);border-color:var(--n-200)}
/* 「现在」游标 */
.tl .nowline{position:relative;height:0;margin:2px 0 8px}
.tl .nowline::before{content:"";position:absolute;left:-16px;right:0;top:0;height:1px;
  background:linear-gradient(90deg,var(--danger),transparent 82%)}
.tl .nowline span{
  position:absolute;left:-52px;top:-7px;font-family:var(--mono);font-size:10px;
  font-weight:700;color:var(--danger);background:var(--danger-soft);
  border-radius:4px;padding:0 4px
}

/* ============================================================================
   周看板
   ========================================================================== */
.week{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:9px}
.wcol{
  background:var(--glass-2);backdrop-filter:var(--blur-sm);
  border:1px solid var(--glass-edge);border-radius:var(--r);
  padding:9px;min-height:148px;display:flex;flex-direction:column;
  transition:border-color var(--t-fast) var(--ease),background var(--t-fast) var(--ease)
}
.wcol.today{border-color:var(--brand-line);background:linear-gradient(180deg,var(--brand-soft),var(--n-0));
  box-shadow:0 0 0 1px var(--brand-line) inset}
.wcol.drop{border-color:var(--brand);background:var(--brand-soft)}
.wcol .wh{display:flex;align-items:baseline;gap:5px;margin-bottom:7px;
  padding-bottom:6px;border-bottom:1px solid var(--n-100)}
.wcol .wh .d{font-weight:700;font-size:12.5px;font-variant-numeric:tabular-nums}
.wcol .wh .w{font-size:11px;color:var(--ink-3)}
.wcol .wh .n{margin-left:auto;font-size:10.5px;color:var(--ink-4);font-weight:600;
  font-variant-numeric:tabular-nums}
.wcol .add{
  margin-top:auto;display:flex;align-items:center;justify-content:center;gap:4px;
  height:26px;border-radius:var(--r-xs);border:1px dashed var(--line-strong);
  color:var(--ink-4);font-size:11.5px;font-weight:600;background:transparent;
  cursor:pointer;font-family:inherit;width:100%;
  transition:all var(--t-fast) var(--ease);opacity:0
}
.wcol:hover .add{opacity:1}
.wcol .add:hover{color:var(--brand);border-color:var(--brand);background:var(--brand-soft)}

/* 固定排班周网格（可横向滚动，一格一天） */
.rgrid{display:grid;grid-template-columns:repeat(7,minmax(150px,1fr));gap:9px;
  overflow-x:auto;padding-bottom:4px}
.rcell{
  background:var(--n-50);border:1px solid var(--line);border-radius:var(--r);
  padding:8px;min-height:120px;display:flex;flex-direction:column;gap:5px
}
.rcell.wkend{background:var(--n-25)}
.rcell .rh{display:flex;align-items:center;gap:5px;font-size:11.5px;font-weight:700;
  color:var(--ink-2);margin-bottom:2px}
.rcell .rh .n{margin-left:auto;color:var(--ink-4);font-weight:600}
.rule{
  background:var(--glass-1);backdrop-filter:var(--blur-sm);
  border:1px solid var(--glass-edge);border-left:2.5px solid var(--brand);
  border-radius:var(--r-xs);padding:6px 8px;font-size:11.8px;line-height:1.45;
  cursor:pointer;transition:all var(--t-fast) var(--ease);position:relative
}
.rule:hover{box-shadow:var(--sh-1);transform:translateY(-1px);border-color:var(--line-strong);
  border-left-color:var(--brand)}
.rule .t{font-family:var(--mono);font-size:10.5px;font-weight:700;color:var(--brand-ink);
  font-variant-numeric:tabular-nums}
.rule .n{font-weight:600;margin-top:1px;color:var(--ink)}
.rule .m{color:var(--ink-4);font-size:10.5px;margin-top:2px;display:flex;gap:5px;
  align-items:center;flex-wrap:wrap}
.rule.off{opacity:.45;border-left-color:var(--n-300)}

/* ============================================================================
   提醒中心 / 弹窗
   ========================================================================== */
.bell{position:relative;width:34px;height:34px;border-radius:var(--r-sm);
  border:1px solid var(--line-strong);background:var(--n-0);display:grid;place-items:center;
  cursor:pointer;color:var(--ink-2);padding:0;
  transition:all var(--t-fast) var(--ease);font-family:inherit}
.bell:hover{background:var(--n-50);color:var(--ink);border-color:var(--n-300)}
.bell.on{color:var(--brand);border-color:var(--brand-line);background:var(--brand-soft)}
.bell .n{
  position:absolute;top:-4px;right:-4px;background:var(--danger);color:#fff;
  font-size:9.5px;font-weight:700;border-radius:99px;padding:0 4px;min-width:15px;
  height:15px;line-height:15px;text-align:center;border:1.5px solid #fff;
  font-variant-numeric:tabular-nums
}
.dropdown{
  position:absolute;right:0;top:42px;width:min(370px,90vw);max-height:460px;
  overflow-y:auto;background:var(--glass-3);backdrop-filter:var(--blur-lg);
  border:1px solid var(--glass-edge);
  border-radius:var(--r-lg);box-shadow:var(--sh-pop);padding:6px;
  display:none;z-index:60;transform-origin:top right
}
.dropdown.open{display:block;animation:popIn var(--t) var(--ease-out)}
.dropdown .it{
  padding:8px 9px;border-radius:var(--r-sm);font-size:12.8px;cursor:pointer;
  display:flex;gap:8px;transition:background var(--t-fast) var(--ease);position:relative
}
.dropdown .it:hover{background:var(--n-50)}
.dropdown .it.unread{background:var(--brand-soft)}
.dropdown .it.unread:hover{background:var(--brand-soft)}
.dropdown .it .ic{width:24px;height:24px;border-radius:var(--r-xs);display:grid;
  place-items:center;flex:0 0 auto;background:var(--n-100);color:var(--ink-3)}
.dropdown .it.unread .ic{background:var(--n-0);color:var(--brand)}
/* 昨天以前的未读不再计入角标，但仍在列表里——压暗 + 标「已过时」,
   让人一眼分清哪些是今天要处理的。 */
.dropdown .it.stale{opacity:.55}
.dropdown .it.stale .ff{color:var(--ink-4)}
.dropdown .it .tt{font-weight:600;line-height:1.4}
.dropdown .it .bb{color:var(--ink-2);font-size:11.8px;line-height:1.5;margin-top:1px}
.dropdown .it .ff{font-family:var(--mono);font-size:10.5px;color:var(--ink-4);margin-top:2px}
.dropdown .sep{height:1px;background:var(--line);margin:5px 4px}

/* 到点弹窗（右下角堆叠） */
.reminder-root{position:fixed;right:18px;bottom:18px;z-index:150;display:flex;
  flex-direction:column-reverse;gap:9px;width:min(360px,90vw);pointer-events:none}
.reminder{
  background:var(--glass-3);backdrop-filter:var(--blur-lg);
  border:1px solid var(--glass-edge);border-radius:var(--r-lg);
  box-shadow:var(--sh-3);padding:11px 13px;pointer-events:auto;position:relative;
  animation:slideUp var(--t-slow) var(--ease-out);overflow:hidden
}
.reminder::before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;
  background:var(--brand)}
.reminder.tone-warn::before{background:var(--warn)}
.reminder.tone-danger::before{background:var(--danger)}
.reminder.tone-ok::before{background:var(--ok)}
.reminder.tone-violet::before{background:var(--violet)}
.reminder .rh{display:flex;align-items:center;gap:7px}
.reminder .rh .ic{color:var(--brand)}
.reminder.tone-warn .rh .ic{color:var(--warn)}
.reminder.tone-danger .rh .ic{color:var(--danger)}
.reminder .rt{font-weight:650;font-size:13px;line-height:1.4;flex:1}
.reminder .rb{font-size:12px;color:var(--ink-2);margin-top:3px;line-height:1.55;
  padding-left:24px}
.reminder .rx{position:absolute;top:8px;right:8px;cursor:pointer;color:var(--ink-4);
  font-size:14px;line-height:1;padding:2px;border-radius:4px;
  transition:all var(--t-fast)}
.reminder .rx:hover{background:var(--n-100);color:var(--ink)}
.reminder.leaving{animation:slideDown var(--t) var(--ease) forwards}
.reminder .rbar{position:absolute;left:0;bottom:0;height:2px;background:var(--brand);
  opacity:.5;animation:drain 12s linear forwards}

/* ============================================================================
   登录 / 门禁

   设计取向：这是**软件登录界面**，不是产品落地页。
   所以左边只放可核对的事实（版本、数据位置、服务状态、账号体系），
   不放「几点做什么，到点提醒」这类宣传句，也不放带编号的卖点列表。
   参考的是 GitHub Primer 的登录页结构：左栏事实 + 右栏表单 + 底部入口切换，
   以及 DingTalk / 飞书 的「管理员 / 成员」双入口做法。
   ========================================================================== */
.gate{min-height:100vh;display:grid;grid-template-columns:296px 1fr;background:transparent}

/* 左栏：浅色侧板，不是深色渐变横幅。边界用 1px 线，不用阴影。 */
.gate-side{
  background:var(--n-0);border-right:1px solid var(--line);padding:26px 24px;
  display:flex;flex-direction:column;gap:26px
}
.gate-brand{display:flex;gap:9px;align-items:center}
.gate-brand .mark{
  width:28px;height:28px;border-radius:6px;background:var(--brand);color:#fff;
  display:grid;place-items:center;font-size:13px;font-weight:700;flex:0 0 auto
}
.gate-brand b{display:block;font-size:13.5px;font-weight:650;letter-spacing:-.01em;
  line-height:1.2}
.gate-brand i{display:block;font-style:normal;font-size:11px;color:var(--ink-4);
  letter-spacing:.03em;text-transform:uppercase;margin-top:2px}

.gate-facts{list-style:none;display:grid;gap:0;margin:0;padding:0}
.gate-facts li{
  display:flex;justify-content:space-between;gap:10px;align-items:baseline;
  padding:9px 0;border-bottom:1px solid var(--line);font-size:12px
}
.gate-facts li:first-child{border-top:1px solid var(--line)}
.gate-facts span{color:var(--ink-4);flex:0 0 auto}
.gate-facts b{color:var(--ink-2);font-weight:600;text-align:right;
  font-variant-numeric:tabular-nums}
.gate-facts b.ok{color:var(--ok)}
.gate-foot{margin-top:auto;font-size:11.5px;color:var(--ink-4);line-height:1.7}

/* 右栏：表单容器，垂直居中但不强行满屏居中 */
.gate-main{
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  padding:40px 24px;gap:14px
}
.gate-box{width:100%;max-width:376px}
.gate-hd{margin-bottom:20px}
.gate-hd h1{font-size:19px;font-weight:650;letter-spacing:-.015em;margin-bottom:6px}
.gate-hd p{font-size:12.5px;color:var(--ink-3);line-height:1.65}
.gate-hd code,.gate-hint code{
  font-family:var(--mono);font-size:11.5px;background:var(--n-100);border:1px solid var(--line);
  border-radius:4px;padding:0 4px;letter-spacing:.02em
}
.gate-hint{font-size:11.8px;color:var(--ink-3);line-height:1.7;margin-top:12px}
.gate-back{display:inline-flex;gap:4px;font-size:12px;color:var(--ink-3);
  font-weight:600;margin-bottom:14px}
.gate-back:hover{color:var(--brand-ink)}

/* 表单字段 */
.fl{display:block;margin-bottom:13px}
.fl > span{display:block;font-size:12px;font-weight:600;color:var(--ink-2);
  margin-bottom:5px}
.fl input,.fl select,.fl textarea{
  width:100%;height:38px;padding:0 11px;border:1px solid var(--line-strong);
  border-radius:var(--r-xs);font-size:13.5px;color:var(--ink);background:var(--n-0);
  transition:border-color var(--t-fast) var(--ease),box-shadow var(--t-fast) var(--ease)
}
.fl input:focus,.fl select:focus,.fl textarea:focus{
  outline:none;border-color:var(--brand);box-shadow:0 0 0 3px var(--brand-soft)
}
.fl input::placeholder{color:var(--ink-4)}
.fl-2{display:grid;grid-template-columns:1fr 1fr;gap:11px}

/* 卡密输入：等宽、大写字距，一眼看出是码 */
.lic-input{
  font-family:var(--mono)!important;font-size:15px!important;letter-spacing:.14em;
  text-transform:uppercase;text-align:center
}

/* 复选框 */
.ck{display:flex;align-items:center;gap:7px;font-size:12px;color:var(--ink-2);
  margin:2px 0 14px;cursor:pointer;user-select:none}
.ck input{
  width:14px;height:14px;margin:0;flex:0 0 auto;accent-color:var(--brand);cursor:pointer
}

/* 已记住凭证：一行卡片 + 一个「进入」 */
.remember{
  display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:11px 13px;border:1px solid var(--brand-line);background:var(--brand-soft);
  border-radius:var(--r-sm);margin-bottom:16px
}
.remember span{display:block;font-size:11px;color:var(--brand-ink);opacity:.75}
.remember b{display:block;font-size:13.5px;font-weight:650;color:var(--brand-ink);
  margin-top:1px}

/* 「或」分隔 */
.or{display:flex;align-items:center;gap:11px;margin:0 0 16px;font-size:11px;
  color:var(--ink-4)}
.or::before,.or::after{content:"";flex:1;height:1px;background:var(--line)}

/* 底部入口切换：常驻，样式比主按钮轻，避免和提交按钮抢焦点 */
.gate-nav{
  display:flex;gap:0;margin-top:22px;border-top:1px solid var(--line);padding-top:14px
}
.gate-nav a{
  flex:1;text-align:center;font-size:12px;font-weight:600;color:var(--ink-3);
  padding:6px 4px;border-radius:var(--r-xs);transition:all var(--t-fast) var(--ease)
}
.gate-nav a:hover{color:var(--ink);background:var(--n-100)}
.gate-nav a.on{color:var(--brand-ink);background:var(--brand-soft)}
.gate-alt{
  margin-top:14px;font-size:12px;color:var(--ink-3);display:flex;
  align-items:center;gap:8px;flex-wrap:wrap
}
.gate-alt a{font-weight:600;color:var(--brand-ink);display:inline-flex;align-items:center;gap:3px}
.gate-alt a:hover{text-decoration:underline}

/* 验证码通道切换：只两个选项，做成下划线标签，比大胶囊更省视觉重量 */
.gate-tabs2{display:flex;gap:18px;margin-bottom:16px;border-bottom:1px solid var(--line)}
.gate-tabs2 a{
  font-size:12.5px;font-weight:600;color:var(--ink-3);padding:0 0 8px;
  border-bottom:2px solid transparent;margin-bottom:-1px;
  transition:color var(--t-fast) var(--ease),border-color var(--t-fast) var(--ease)
}
.gate-tabs2 a:hover{color:var(--ink)}
.gate-tabs2 a.on{color:var(--brand-ink);border-bottom-color:var(--brand)}
.gate-resend{font-size:12px;font-weight:600;color:var(--brand-ink)}
.gate-resend:hover{text-decoration:underline}

/* 提示块 */
.note{padding:10px 12px;border-radius:var(--r-sm);font-size:12px;line-height:1.65;
  margin-bottom:14px}
.note.warn{background:var(--warn-soft);border:1px solid var(--warn-line);color:var(--warn)}

/* 键值行（套餐/席位/有效期） */
.kv{display:flex;gap:0;margin-bottom:16px;border:1px solid var(--line);
  border-radius:var(--r-sm);overflow:hidden}
.kv > div{flex:1;padding:8px 11px;border-right:1px solid var(--line);
  background:var(--n-25)}
.kv > div:last-child{border-right:0}
.kv span{display:block;font-size:10.5px;color:var(--ink-4)}
.kv b{display:block;font-size:13px;font-weight:650;margin-top:2px;
  font-variant-numeric:tabular-nums}

/* 6 位验证码：一格一位，支持整串粘贴 */
.otp{display:flex;gap:6px;margin:4px 0 2px}
.otp input{
  width:100%;height:44px;text-align:center;font-family:var(--mono);font-size:19px;
  font-weight:650;border:1px solid var(--line-strong);border-radius:var(--r-xs);
  padding:0;color:var(--ink);background:var(--n-0);letter-spacing:0;
  transition:all var(--t-fast) var(--ease)
}
.otp input:focus{border-color:var(--brand);box-shadow:0 0 0 3px var(--brand-soft)}
.otp input.filled{border-color:var(--brand-line);background:var(--brand-soft)}
.otp.error input{border-color:var(--danger);background:var(--danger-soft);
  animation:shakeX .32s var(--ease)}

.dev-note{
  margin-top:14px;padding:9px 11px;border-radius:var(--r-sm);font-size:11.5px;
  background:var(--warn-soft);border:1px dashed var(--warn-line);color:var(--warn);
  line-height:1.65
}
.dev-note code{font-family:var(--mono);background:var(--n-0);border:1px solid var(--warn-line);
  border-radius:4px;padding:0 4px;font-size:12px;letter-spacing:.1em;font-weight:700}

/* 演示信息：放在表单卡片外，等宽字体，视觉上明确是「测试数据」 */
.gate-demo{
  font-size:11px;color:var(--ink-4);line-height:1.9;text-align:center;
  max-width:376px;font-family:var(--mono)
}
.gate-demo code{color:var(--ink-2)}

@media (max-width:860px){
  .gate{grid-template-columns:1fr}
  .gate-side{display:none}
  .gate-main{padding:28px 16px}
}

/* ---- 兼容层：总后台注册 / 平台登录 / 错误页还在用旧的 gate-wrap 结构 ----
   这些页面是「网站侧」的，不是桌面客户端登录页，保留深色侧板反而合适：
   它们本来就要在一屏里讲清楚「网站管什么」。但把渐变收敛掉，
   改成纯色板 + 1px 线，避免整站都同一套 AI 落地页味道。 */
.gate-wrap{min-height:100vh;display:grid;grid-template-columns:1fr 1fr;
  background:var(--n-50)}
.gate-art{
  position:relative;color:#fff;padding:40px 42px;display:flex;flex-direction:column;
  justify-content:center;gap:22px;background:var(--n-900);overflow:hidden
}
.gate-art::after{
  content:"";position:absolute;inset:0;pointer-events:none;opacity:.4;
  background-image:linear-gradient(rgba(255,255,255,.02) 1px,transparent 1px),
                   linear-gradient(90deg,rgba(255,255,255,.02) 1px,transparent 1px);
  background-size:32px 32px
}
.gate-art > *{position:relative;z-index:1}
.gate-art h1{font-size:22px;line-height:1.35;color:#fff;letter-spacing:-.02em;
  font-weight:650}
.gate-art h1 em{font-style:normal;color:var(--brand-ink)}
.gate-art p{color:var(--ink-3);font-size:12.5px;max-width:420px;line-height:1.75}
.gate-feats{display:grid;gap:9px;margin-top:6px}
.gate-feat{display:flex;gap:9px;align-items:flex-start;font-size:12.5px;
  color:var(--ink-3);line-height:1.6}
.gate-feat .n{
  width:19px;height:19px;border-radius:4px;background:rgba(255,255,255,.06);
  border:1px solid rgba(255,255,255,.09);display:grid;place-items:center;
  font-size:10px;font-weight:650;color:var(--line);flex:0 0 auto;
  font-variant-numeric:tabular-nums
}
.gate-feat b{color:#fff;font-weight:600}

/* 左侧事实清单（网站注册页用）：跟 .gate-facts 同构，但配色适配深底 */
.gate-art .gate-facts li{border-color:rgba(255,255,255,.08)}
.gate-art .gate-facts li:first-child{border-top-color:rgba(255,255,255,.08)}
.gate-art .gate-facts span{color:var(--ink-2)}
.gate-art .gate-facts b{color:var(--line)}

.gate-form-wrap{background:var(--glass-pop);backdrop-filter:var(--blur-lg);
  display:flex;align-items:center;
  justify-content:center;padding:36px 28px;overflow-y:auto}
.gate-form{width:100%;max-width:380px}
.gate-form h2{font-size:18px;margin-bottom:5px;letter-spacing:-.015em;font-weight:650}
.gate-form .lead{font-size:12.5px;color:var(--ink-3);margin-bottom:18px;line-height:1.65}
@media (max-width:900px){
  .gate-wrap{grid-template-columns:1fr}
  .gate-art{display:none}
}

/* ============================================================================
   加密 / 杂项
   ========================================================================== */
.banner{
  background:linear-gradient(120deg,var(--n-25),var(--n-100) 60%,var(--n-150));color:var(--ink);
  border-radius:var(--r-lg);padding:16px 18px;display:flex;gap:14px;align-items:center;
  flex-wrap:wrap;position:relative;overflow:hidden
}
.banner::after{
  content:"";position:absolute;right:-60px;top:-60px;width:220px;height:220px;
  background:radial-gradient(circle,rgba(168,216,196,.55),transparent 70%);pointer-events:none
}
.banner .t{font-size:16px;font-weight:650;letter-spacing:-.01em}
.banner .s{color:var(--ink-3);font-size:12.5px;margin-top:2px}
.banner .spacer{flex:1}

.tree{font-size:13px}
.tree .node{display:flex;align-items:center;gap:7px;padding:6px 0}
.tree .branch{padding-left:20px;border-left:1.5px dashed var(--line-strong);margin-left:11px}

.perm-group{border:1px solid var(--line);border-radius:var(--r);overflow:hidden;
  background:var(--panel)}
.perm-group + .perm-group{margin-top:10px}
.perm-group .gh{background:var(--n-25);padding:8px 13px;font-size:11.5px;font-weight:700;
  color:var(--ink-3);border-bottom:1px solid var(--line);letter-spacing:.04em;
  text-transform:uppercase}
.perm-row{display:flex;align-items:center;gap:10px;padding:8px 13px;
  border-bottom:1px solid var(--n-100);transition:background var(--t-fast) var(--ease)}
.perm-row:last-child{border-bottom:0}
.perm-row:hover{background:var(--n-25)}
.perm-row .code{font-family:var(--mono);font-size:11px;color:var(--ink-4);
  margin-left:auto;letter-spacing:-.01em}
.perm-row .lb{font-size:12.8px;font-weight:550}

.heat{display:grid;grid-template-columns:repeat(auto-fill,minmax(92px,1fr));gap:7px}
.heat .d{border:1px solid var(--line);border-radius:var(--r-sm);padding:8px 9px;
  background:var(--glass-1);backdrop-filter:var(--blur-sm);
  transition:all var(--t-fast) var(--ease)}
.heat .d:hover{border-color:var(--line-strong);box-shadow:var(--sh-1)}
.heat .d .dd{font-size:11px;color:var(--ink-3);font-family:var(--mono);
  font-variant-numeric:tabular-nums}
.heat .d .nn{font-size:16px;font-weight:720;margin-top:2px;font-variant-numeric:tabular-nums}

.dept-card{border:1px solid var(--line);border-radius:var(--r);padding:13px 15px;
  background:var(--panel);transition:all var(--t-fast) var(--ease)}
.dept-card:hover{border-color:var(--line-strong);box-shadow:var(--sh-1)}
.dept-card .nm{font-size:14px;font-weight:650;display:flex;align-items:center;gap:6px}
.dept-card .mg{font-size:12px;color:var(--ink-2);margin-top:3px}
.dept-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(290px,1fr));gap:11px}

.readonly-badge{display:inline-flex;align-items:center;gap:4px;font-size:11px;
  color:var(--warn);background:var(--warn-soft);border:1px solid var(--warn-line);border-radius:99px;
  padding:1px 8px;font-weight:600}

.mod-line{display:flex;align-items:center;gap:8px;padding:8px 11px;
  border-bottom:1px solid var(--n-100);font-size:12.8px}
.mod-line:last-child{border-bottom:0}
.mod-line .key{font-family:var(--mono);font-size:10.5px;color:var(--ink-4)}

/* 平台后台 */
.plat-shell{min-height:100vh;background:var(--bg)}
.plat-bar{display:flex;align-items:center;gap:11px;padding:10px 20px;
  background:var(--glass-1);backdrop-filter:var(--blur);
  color:var(--ink);border-bottom:1px solid var(--line);position:sticky;top:0;z-index:20}
.plat-bar .spacer{flex:1}
.plat-bar .btn{background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.14);
  color:var(--line-strong)}
.plat-bar .btn:hover{background:rgba(24,29,38,.07);color:var(--ink)}
.plat-main{padding:20px;max-width:1440px;margin:0 auto}
.top-flash{padding:14px 20px 0;max-width:1440px;margin:0 auto}

/* 权限预览列表 */
.nav-preview{display:flex;flex-wrap:wrap;gap:5px}
.nav-preview .i{font-size:11.5px;padding:2px 8px;border-radius:99px;
  background:var(--n-100);color:var(--ink-4);text-decoration:line-through;
  text-decoration-color:var(--n-300)}
.nav-preview .i.on{background:var(--brand-soft);color:var(--brand-ink);
  text-decoration:none;font-weight:600}

/* 工作日选择器（一周七天圆点） */
.wd-pick{display:flex;gap:5px;flex-wrap:wrap}
.wd-pick label{cursor:pointer}
.wd-pick input{position:absolute;opacity:0;pointer-events:none}
.wd-pick span{
  display:grid;place-items:center;width:38px;height:32px;border-radius:var(--r-xs);
  border:1px solid var(--line-strong);background:var(--n-0);font-size:12px;
  font-weight:600;color:var(--ink-3);transition:all var(--t-fast) var(--ease)
}
.wd-pick label:hover span{border-color:var(--n-300);color:var(--ink)}
.wd-pick input:checked + span{background:var(--brand);border-color:var(--brand);
  color:var(--n-900);box-shadow:0 2px 6px -2px rgba(27,97,201,.6)}
.wd-pick input:focus-visible + span{outline:2px solid var(--brand);outline-offset:2px}

/* 提前量选择：一排胶囊 */
.lead-pick{display:flex;gap:5px;flex-wrap:wrap}
.lead-pick label{cursor:pointer}
.lead-pick input{position:absolute;opacity:0;pointer-events:none}
.lead-pick span{
  display:inline-flex;align-items:center;height:28px;padding:0 10px;
  border-radius:99px;border:1px solid var(--line-strong);background:var(--n-0);
  font-size:12px;font-weight:600;color:var(--ink-2);
  transition:all var(--t-fast) var(--ease);font-variant-numeric:tabular-nums
}
.lead-pick label:hover span{border-color:var(--n-300)}
.lead-pick input:checked + span{background:var(--brand);border-color:var(--brand);
  color:var(--n-900);box-shadow:0 2px 8px -3px rgba(27,97,201,.7)}
.lead-pick input:focus-visible + span{outline:2px solid var(--brand);outline-offset:2px}

/* 空态插图 */
.illo{width:54px;height:54px;border-radius:14px;display:grid;place-items:center;
  background:var(--n-100);color:var(--n-400);margin:0 auto 10px}

/* ============================================================================
   动效
   ========================================================================== */
@keyframes spin{to{transform:rotate(360deg)}}
@keyframes slideUp{from{opacity:0;transform:translateY(14px) scale(.985)}to{opacity:1;transform:none}}
@keyframes slideDown{to{opacity:0;transform:translateY(10px) scale(.98)}}
@keyframes popIn{from{opacity:0;transform:scale(.97) translateY(-4px)}to{opacity:1;transform:none}}
@keyframes toastIn{from{opacity:0;transform:translateY(12px) scale(.96)}to{opacity:1;transform:none}}
@keyframes toastOut{to{opacity:0;transform:translateY(8px) scale(.96)}}
@keyframes flashIn{from{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:none}}
@keyframes tabIn{from{transform:scaleX(.4);opacity:0}to{transform:none;opacity:1}}
@keyframes shakeX{0%,100%{transform:translateX(0)}25%{transform:translateX(-4px)}
  75%{transform:translateX(4px)}}
@keyframes shimmer{0%{background-position:100% 0}100%{background-position:-100% 0}}
@keyframes drain{from{width:100%}to{width:0}}
@keyframes pulse{0%,100%{opacity:1}50%{opacity:.4}}

/* 尊重系统「减少动态效果」 */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;
    transition-duration:.001ms!important;scroll-behavior:auto!important}
}

/* ============================================================================
   响应式
   ========================================================================== */
@media (max-width:1180px){
  .g4{grid-template-columns:repeat(2,minmax(0,1fr))}
  .week{grid-template-columns:repeat(4,minmax(0,1fr))}
}
@media (max-width:980px){
  .gate{grid-template-columns:1fr}
  .gate-art{display:none}
  .g3{grid-template-columns:repeat(2,minmax(0,1fr))}
  .week{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media (max-width:820px){
  /* 弹窗在窄屏占满，否则 3 列日期/时间在 94vw 里会挤成两行 */
  .drawer{width:100vw;max-height:92vh;border-radius:var(--r-lg) var(--r-lg) 0 0;
    top:auto;bottom:0;transform:translate(-50%,14%) scale(.99)}
  .drawer.open{transform:translate(-50%,0)}
  .fstep .grid.g3{grid-template-columns:1fr 1fr}
  .sidebar{position:fixed;left:calc(var(--sidebar-w) * -1);top:0;transition:left var(--t-slow) var(--ease-out)}
  .sidebar.open{left:0;box-shadow:var(--sh-pop)}
  .content{padding:14px 12px 80px}
  .topbar{padding:0 14px;gap:8px}
  .g2,.g3,.g4{grid-template-columns:1fr}
  .page-head .acts{margin-left:0;width:100%}
  .drawer{width:100vw}
}

/* 打印：只留内容 */
@media print{
  .sidebar,.topbar,.drawer,.drawer-mask,.toast-root,.reminder-root,.seg,.tabs{display:none!important}
  .content{padding:0;max-width:none}
  .card{box-shadow:none;break-inside:avoid}
}

/* ============================================================================
   旧页面兼容（logs / members / roles / settings / flow / platform / licenses
   还没重写成新组件，但用的还是这套 token，不能出现无样式元素）
   ========================================================================== */
.table th:first-child,.table td:first-child{padding-left:16px}
.dept-card,.wk-col,.wk-item{border-color:var(--line)}
.wk-col{background:var(--glass-2);backdrop-filter:var(--blur-sm);
  border:1px solid var(--glass-edge);border-radius:var(--r);
  padding:11px;min-height:120px}
.wk-col .hd2{font-weight:700;font-size:12.5px;margin-bottom:7px;display:flex;
  justify-content:space-between;align-items:center}
.wk-item{background:var(--n-50);border-radius:var(--r-xs);padding:7px 9px;
  margin-bottom:5px;font-size:12px}
.wk-item .tm{font-family:var(--mono);font-size:11px;color:var(--brand-ink);font-weight:700}
.week-grid{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:9px}
@media (max-width:1100px){.week-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:820px){.week-grid{grid-template-columns:1fr}}
.btn.xs{height:22px;padding:0 6px;font-size:11px;border-radius:5px}
