/* ==========================================================================
   desktop.css — 全局桌面层（登记簿式秩序感）
   加载顺序：tokens.css → 页面 <style> → mobile.css → desktop.css
   本文件零 !important：依靠「后加载 + html.app-shell body 前缀」两条取得层叠优势。
   如遇某页失效，优先检查该页 <link> 是否仍在本文件之后，而不是补 !important。
   ========================================================================== */

/* --------------------------------------------------------------------------
   0. 基础
   -------------------------------------------------------------------------- */
.bg-orb { display: none; }

html.app-shell body {
  display: block;
  margin: 0;
  min-height: 100vh;
  background-color: var(--canvas);
  background-image: none;
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: 14px;
  line-height: 1.5;
  letter-spacing: 0;
  -webkit-font-smoothing: antialiased;
}

/* --------------------------------------------------------------------------
   1. 侧栏（深色、去蓝、分组）
   -------------------------------------------------------------------------- */
.app-side {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  width: var(--rail-w);
  background-color: var(--rail);
  background-image: none;
  color: var(--rail-ink);
  display: flex;
  flex-direction: column;
  z-index: 40;
  padding: 16px 12px 16px;
  gap: 4px;
}

.app-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 2px 10px 18px;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0;
  color: var(--ink-invert);
  white-space: nowrap;
}

.app-brand-mark {
  width: 26px;
  height: 26px;
  border-radius: var(--r-sm);
  flex: none;
  display: block;
}

.app-side nav {
  display: flex;
  flex-direction: column;
  gap: 1px;
  overflow: auto;
  padding-bottom: 8px;
}

/* 分组标题：日常 / 业务 / 系统 */
.app-nav-group {
  padding: 14px 12px 6px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--rail-group);
  text-transform: uppercase;
}
.app-nav-group:first-child { padding-top: 2px; }

.app-nav-item {
  position: relative;
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 34px;
  padding: 7px 12px;
  border-radius: var(--r-sm);
  color: var(--rail-ink);
  text-decoration: none;
  font-size: var(--fs-base);
  font-weight: 400;
  line-height: 1.2;
  white-space: nowrap;
  letter-spacing: 0;
  transition: background-color 0.14s ease, color 0.14s ease;
}

.app-nav-item svg {
  width: 17px;
  height: 17px;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0.85;
}

.app-nav-item:hover {
  background: var(--rail-hover);
  color: var(--ink-invert);
}

/* 当前位置：强调色只在这里出现一次（左侧 2px 竖条） */
.app-nav-item.is-current {
  background: rgba(255, 255, 255, 0.08);
  color: var(--ink-invert);
  font-weight: 600;
}
.app-nav-item.is-current::before {
  content: "";
  position: absolute;
  left: 0;
  top: 8px;
  bottom: 8px;
  width: 2px;
  border-radius: 0 2px 2px 0;
  background: var(--brand-on-rail);
}
.app-nav-item.is-current svg { opacity: 1; }

.app-main {
  margin-left: var(--rail-w);
  min-width: 0;
  min-height: 100vh;
  overflow-x: hidden;
  /* 顶栏由 JS 注入前也预留高度，避免首屏文字被顶栏推下去 */
  padding-top: var(--app-chrome-h);
}

@media (min-width: 761px) {
  html.app-shell body:not(:has(.app-side))::before {
    content: "";
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    width: var(--rail-w);
    background-color: var(--rail);
    z-index: 40;
  }
  html.app-shell body:not(:has(.app-main)) > .container {
    margin-left: var(--rail-w);
    width: auto;
    max-width: calc(100% - var(--rail-w));
    padding-top: calc(20px + var(--app-chrome-h));
  }
}

/* --------------------------------------------------------------------------
   2. 页面容器与页头（压到一行标题 + 一行摘要）
   -------------------------------------------------------------------------- */
html.app-shell body .container {
  max-width: 100%;
  width: 100%;
  margin: 0;
  box-sizing: border-box;
  padding: 20px var(--page-pad-x) 56px;
}

html.app-shell body .header {
  background: transparent;
  border: 0;
  box-shadow: none;
  padding: 0 0 14px;
  margin-bottom: 14px;
  border-bottom: 1px solid var(--line);
}
html.app-shell body .header-top { align-items: flex-end; gap: var(--sp-4); }
html.app-shell body .header-right {
  display: flex;
  flex-direction: row;
  align-items: center;
  max-width: none;
  width: auto;
  margin-left: auto;
}
html.app-shell body .header-right > .toolbar { width: auto; }

html.app-shell body h1 {
  font-size: var(--fs-xl);
  font-weight: 600;
  letter-spacing: 0;
  color: var(--ink);
  margin: 0 0 4px;
  line-height: 1.3;
}

html.app-shell body .desc,
html.app-shell body .panel-sub,
html.app-shell body .panel-subtitle {
  color: var(--muted);
  font-size: 13px;
  margin: 0;
  line-height: 1.5;
}
html.app-shell body .panel-sub,
html.app-shell body .panel-subtitle { margin-bottom: var(--sp-3); }

html.app-shell body .panel-title,
html.app-shell body .section-title,
html.app-shell body h2 {
  font-size: 15px;
  font-weight: 600;
  color: var(--ink);
  letter-spacing: 0;
  margin: 0;
}
html.app-shell body .panel-head { align-items: center; gap: var(--sp-3); }

/* --------------------------------------------------------------------------
   3. 顶栏（用户 / 语言 / 退出）
   -------------------------------------------------------------------------- */
.app-chrome {
  z-index: 30;
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: var(--sp-2);
  height: var(--app-chrome-h);
  box-sizing: border-box;
  padding: 12px var(--page-pad-x) 0;
  background-color: var(--canvas);
  background-image: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

@media (min-width: 761px) {
  .app-chrome {
    position: fixed;
    top: 0;
    right: 0;
    left: var(--rail-w);
  }
}

@media (max-width: 760px) {
  .app-chrome {
    position: sticky;
    top: 0;
  }
}

.app-chrome .btn,
.app-chrome .lang-switch,
.app-chrome .lang-switch button,
.app-chrome .user-chip {
  font-family: var(--font-sans);
  font-size: 13px;
  font-weight: 500;
  line-height: 1;
}
.app-chrome .btn,
.app-chrome .lang-switch,
.app-chrome .user-chip {
  height: var(--ctl-h-sm);
  min-height: var(--ctl-h-sm);
  max-height: var(--ctl-h-sm);
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
}
.app-chrome .btn {
  min-width: 64px;
  justify-content: center;
  text-decoration: none;
  padding: 0 var(--sp-3);
  border: 1px solid var(--line-strong);
  background: var(--paper);
  color: var(--ink-2);
  border-radius: var(--r-sm);
  box-shadow: none;
  cursor: pointer;
}
.app-chrome .btn:hover { background: var(--wash); }
/* [hidden] 必须压过 .btn 的 display，否则工作台的「返回」会露出来 */
.app-chrome .btn[hidden],
.app-chrome [hidden] { display: none; }
.app-chrome .lang-switch {
  margin: 0;
  padding: 3px;
  gap: 2px;
  background: var(--wash);
  border: 0;
  border-radius: var(--r-md);
}
.app-chrome .lang-switch button {
  height: var(--ctl-h-xs);
  min-height: var(--ctl-h-xs);
  max-height: var(--ctl-h-xs);
  min-width: 36px;
  padding: 0 var(--sp-2);
  border: 0;
  background: transparent;
  color: var(--muted);
  border-radius: var(--r-sm);
  cursor: pointer;
  white-space: nowrap;
  transition: background-color 0.14s ease, color 0.14s ease;
}
.app-chrome .lang-switch button:hover { color: var(--ink-2); }
.app-chrome .lang-switch button.active {
  background: var(--brand);
  color: var(--ink-invert);
  font-weight: 600;
}
.app-chrome .user-chip {
  padding: 0 var(--sp-3);
  white-space: nowrap;
  background: var(--paper);
  color: var(--ink-2);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
}

/* 整栏隐藏：tokens.css 首屏已压掉；此处无 !important，与全站层叠策略一致 */
html.app-shell body .header .toolbar { display: none; }

html.app-shell body .toolbar { gap: var(--sp-2); }
html.app-shell body .user-chip,
html.app-shell body .lang-switch {
  background: var(--wash);
  color: var(--ink-2);
  border: 0;
  border-radius: var(--r-md);
  box-shadow: none;
}
html.app-shell body .lang-switch button { color: var(--muted); border-radius: var(--r-sm); }
html.app-shell body .lang-switch button.active { background: var(--brand); color: var(--ink-invert); font-weight: 600; }

/* --------------------------------------------------------------------------
   4. 卡片 / 面板
   -------------------------------------------------------------------------- */
html.app-shell body .glass,
html.app-shell body .panel,
html.app-shell body .dash-card,
html.app-shell body .login-box,
html.app-shell body .stat-card,
html.app-shell body .notice-box,
html.app-shell body .mini-item {
  background: var(--paper);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-1);
  transition: border-color 0.14s ease, box-shadow 0.14s ease;
}

html.app-shell body .glass:hover,
html.app-shell body .panel:hover,
html.app-shell body .dash-card:hover,
html.app-shell body .stat-card:hover {
  border-color: var(--brand-line);
}

html.app-shell body .panel { padding: var(--sp-5) var(--sp-5); }

/* 卡片等高：底部操作区自动沉底 */
html.app-shell body .dash-grid,
html.app-shell body .stat-grid,
html.app-shell body .grid-equal { align-items: stretch; }
html.app-shell body .dash-card {
  gap: var(--sp-4);
  height: 100%;
  padding: var(--sp-5);
  box-sizing: border-box;
}
html.app-shell body .dash-card-actions {
  margin-top: auto;
  padding-top: var(--sp-2);
}

/* 公告条 */
.dash-announcements { margin: 0 0 var(--sp-4); }
.dash-announcements:empty { display: none; }

html.app-shell body.page-dashboard .dash-card-actions .btn-primary {
  width: 100%;
}
html.app-shell body.page-dashboard .dash-kpi-row:has(.dash-kpi:only-child) {
  grid-template-columns: 1fr;
}
html.app-shell body.page-dashboard {
  --dash-body-min: 300px;
  --dash-list-min: 156px;
}
html.app-shell body.page-dashboard .dash-card-body {
  min-height: var(--dash-body-min);
}
html.app-shell body.page-dashboard .mini-list {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  min-height: var(--dash-list-min);
}
html.app-shell body.page-dashboard .mini-list > .empty {
  flex: 1;
  min-height: var(--dash-list-min);
  margin: 0;
}
html.app-shell body.page-dashboard .dash-pane-grow > .empty:only-child {
  flex: 1;
  min-height: var(--dash-list-min);
}
html.app-shell body.page-dashboard .section-label .dash-inline-meta {
  margin-left: auto;
  font-weight: 400;
}
html.app-shell body.page-dashboard .dash-leave-stack {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
}
html.app-shell body.page-dashboard .dash-leave-balance {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--line-soft);
  border-radius: var(--r-md);
  background: var(--sunken);
}
html.app-shell body.page-dashboard .dash-leave-balance .db-meter + .db-meter {
  margin-top: 0;
  padding-top: var(--sp-4);
  border-top: 1px solid var(--line-soft);
}
html.app-shell body.page-dashboard .dash-leave-balance .db-meter {
  gap: var(--sp-2);
}
html.app-shell body.page-dashboard .dash-leave-section .mini-list {
  min-height: 0;
}
html.app-shell body.page-dashboard .dash-leave-list {
  gap: var(--sp-2);
}
html.app-shell body.page-dashboard .dash-leave-item,
html.app-shell body.page-dashboard .dash-claim-item {
  padding: var(--sp-3) var(--sp-3);
  background: var(--paper);
}
html.app-shell body.page-dashboard .dash-leave-item-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--sp-2);
}
html.app-shell body.page-dashboard .dash-leave-item-tags {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 6px;
  flex-shrink: 0;
}
html.app-shell body.page-dashboard .dash-leave-doc {
  font-weight: 400;
  color: var(--muted);
}
html.app-shell body.page-dashboard .dash-leave-item .mini-item-meta {
  margin-top: 6px;
  font-size: 13px;
  line-height: 1.45;
}
html.app-shell body.page-dashboard .dash-leave-item-foot {
  color: var(--ink-2);
  font-size: 12px;
}
html.app-shell body.page-dashboard .dash-leave-section .notice-box {
  margin: 0;
}
html.app-shell body.page-dashboard .dash-leave-stack > .dash-alerts {
  margin: 0;
}
html.app-shell body.page-dashboard .dash-leave-stack .section-block + .section-block,
html.app-shell body.page-dashboard .dash-leave-stack .dash-alerts + .section-block,
html.app-shell body.page-dashboard .dash-leave-stack .dash-leave-balance + .dash-alerts,
html.app-shell body.page-dashboard .dash-leave-stack .dash-leave-balance + .section-block {
  margin-top: 0;
}

/* 审批操作区：与表单 field 同结构，不用额外套框 */
html.app-shell body .approval-section {
  margin-top: var(--sp-4);
  padding-top: var(--sp-4);
  border-top: 1px solid var(--line-soft);
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
}
html.app-shell body .approval-section .field {
  margin-bottom: 0;
}
html.app-shell body .approval-section .submit-row {
  margin-top: 0;
}
html.app-shell body .approval-choice-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
}
html.app-shell body .approval-choice {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: var(--ui-h-sm);
  padding: 0 var(--sp-3);
  margin: 0;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--paper);
  font-size: 14px;
  font-weight: 500;
  color: var(--ink-2);
  cursor: pointer;
  transition: border-color var(--dur) var(--ease), background-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
html.app-shell body .approval-choice:hover {
  border-color: var(--line-strong);
}
html.app-shell body .approval-choice:has(input:checked) {
  border-color: var(--brand-line);
  background: var(--brand-soft);
  color: var(--brand);
}
html.app-shell body .approval-choice input[type="checkbox"] {
  width: 16px;
  height: 16px;
  min-height: 16px;
  max-height: 16px;
  margin: 0;
  accent-color: var(--brand);
  cursor: pointer;
}
html.app-shell body .next-approvers-box,
html.app-shell body .revision-notice {
  margin-top: var(--sp-4);
  padding: var(--sp-3) var(--sp-4);
  font-size: 13px;
  line-height: 1.6;
}

html.app-shell body .global-ann-widget {
  width: 100%;
  max-width: none;
  margin: 0;
  padding: var(--sp-4) var(--sp-5);
  background: var(--paper);
  backdrop-filter: none;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-1);
}
html.app-shell body .global-ann-body {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--sp-2) var(--sp-4);
  max-height: 200px;
  overflow: auto;
}
@media (max-width: 760px) {
  html.app-shell body .global-ann-body { grid-template-columns: 1fr; }
}

html.app-shell body .tag,
html.app-shell body .quick-links,
html.app-shell body #moduleNavWrap,
html.app-shell body #homeBackBtn { display: none; }

/* --------------------------------------------------------------------------
   5. 按钮
   -------------------------------------------------------------------------- */
html.app-shell body .btn {
  box-sizing: border-box;
  border-radius: var(--r-md);
  box-shadow: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  height: var(--ctl-h);
  min-height: var(--ctl-h);
  max-height: var(--ctl-h);
  padding: 0 var(--sp-4);
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0;
  line-height: 1.2;
  vertical-align: middle;
  border: 1px solid transparent;
  cursor: pointer;
  transition: background-color 0.14s ease, border-color 0.14s ease;
}
html.app-shell body .btn-device-remove {
  white-space: nowrap;
}
html.app-shell body .btn-sm {
  height: var(--ctl-h-sm);
  min-height: var(--ctl-h-sm);
  max-height: var(--ctl-h-sm);
  padding: 0 var(--sp-3);
  font-size: 13px;
  border-radius: var(--r-sm);
}

/* 主操作：强调色第二个出处 */
html.app-shell body .btn-primary {
  background: var(--brand);
  color: var(--ink-invert);
  border-color: var(--brand);
}
html.app-shell body .btn-primary:hover { background: var(--brand-hover); border-color: var(--brand-hover); }

html.app-shell body .btn-outline {
  background: var(--paper);
  color: var(--ink-2);
  border-color: var(--line-strong);
}
html.app-shell body .btn-outline:hover { background: var(--wash); }

html.app-shell body .btn-danger {
  background: var(--paper);
  color: var(--danger-fg);
  border-color: var(--danger-line);
}
html.app-shell body .btn-danger:hover { background: var(--danger-bg); }

html.app-shell body .btn:disabled,
html.app-shell body .btn[disabled] { opacity: 0.45; cursor: not-allowed; }

html.app-shell body .app-chrome .btn {
  font-family: var(--font-sans);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0;
  line-height: 1;
  min-height: var(--ctl-h-sm);
  height: var(--ctl-h-sm);
  max-height: var(--ctl-h-sm);
  min-width: 64px;
  padding: 0 var(--sp-3);
  border-radius: var(--r-sm);
  text-decoration: none;
}

html.app-shell body .emp-link {
  background: transparent;
  border: 0;
  padding: 0;
  min-height: 0;
  box-shadow: none;
  font-weight: 500;
  color: var(--brand);
  cursor: pointer;
}

/* --------------------------------------------------------------------------
   6. 表单
   -------------------------------------------------------------------------- */
html.app-shell body .filters,
html.app-shell body .filter-bar,
html.app-shell body .records-filter-bar,
html.app-shell body .report-filters,
html.app-shell body .bonus-filters,
html.app-shell body .bonus-filters-2,
html.app-shell body .inline-form,
html.app-shell body .date-pair-row {
  align-items: end;
  gap: var(--sp-4);
}
html.app-shell body .two-col,
html.app-shell body .form-grid,
html.app-shell body .annual-grid,
html.app-shell body .attachment-remarks-row {
  gap: var(--sp-4);
  align-items: start;
}
html.app-shell body .field,
html.app-shell body .form-field,
html.app-shell body .form-group,
html.app-shell body .export-locale-field {
  margin-bottom: var(--sp-4);
}
html.app-shell body .two-col > .field,
html.app-shell body .form-grid > .field,
html.app-shell body .form-grid .field,
html.app-shell body .annual-grid .field,
html.app-shell body .date-pair-row .field,
html.app-shell body .date-summary-row .field,
html.app-shell body .attachment-remarks-row .field,
html.app-shell body .filters .field,
html.app-shell body .form-field { margin-bottom: 0; }
html.app-shell body .form-field { gap: 0; }
html.app-shell body label { letter-spacing: 0; text-transform: none; }

html.app-shell body .field > label,
html.app-shell body .form-field > label,
html.app-shell body .form-group > label,
html.app-shell body .filters label,
html.app-shell body .filter-bar label,
html.app-shell body .records-filter-bar label,
html.app-shell body .report-filters label,
html.app-shell body .bonus-filters label,
html.app-shell body .bonus-filters-2 label,
html.app-shell body .inline-form label,
html.app-shell body .annual-grid label,
html.app-shell body .behalf-emp-picker > label,
html.app-shell body .export-locale-field > label,
html.app-shell body .form-modal-box .field > label,
html.app-shell body .form-modal-box label,
html.app-shell body .leave-main .field > label,
html.app-shell body .claim-main .field > label,
html.app-shell body .attach-section > label,
html.app-shell body .remarks-section > label,
html.app-shell body .leave-main > label,
html.app-shell body .claim-main > label {
  display: block;
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--muted);
  letter-spacing: 0;
  text-transform: none;
  line-height: 1.4;
  margin: 0 0 var(--sp-1);
  padding: 0;
}

html.app-shell body input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not([type="hidden"]):not([type="range"]):not(.tag-input),
html.app-shell body select,
html.app-shell body textarea {
  box-sizing: border-box;
  height: var(--ctl-h);
  min-height: var(--ctl-h);
  max-height: var(--ctl-h);
  padding: 0 var(--sp-3);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  background-color: var(--paper);
  color: var(--ink);
  box-shadow: none;
  font-size: 14px;
  font-weight: 400;
  letter-spacing: 0;
  line-height: calc(var(--ctl-h) - 2px);
  font-family: var(--font-sans);
}
html.app-shell body textarea {
  height: auto;
  max-height: none;
  min-height: 96px;
  padding: var(--sp-2) var(--sp-3);
  line-height: 1.5;
}

html.app-shell body .readonly-field {
  box-sizing: border-box;
  min-height: var(--ctl-h);
  padding: 0 var(--sp-3);
  border-radius: var(--r-md);
  font-size: 14px;
  letter-spacing: 0;
  line-height: calc(var(--ctl-h) - 2px);
}
html.app-shell body .readonly-field.is-revised {
  color: var(--danger-fg);
  background: var(--danger-bg);
  box-shadow: inset 0 0 0 1px var(--danger-line);
}
html.app-shell body .upload-slots.is-revised {
  padding: var(--sp-2);
  border-radius: var(--r-md);
  box-shadow: inset 0 0 0 1px var(--danger-line);
  background: var(--danger-bg);
}
html.app-shell body .revised-original {
  margin-top: var(--sp-1);
  font-size: 12px;
  line-height: 1.4;
  color: var(--danger-fg);
}
html.app-shell body .readonly-field.hr-attachment-list {
  height: auto;
  line-height: 1.5;
  padding: var(--sp-2) var(--sp-3);
}

.doc-no { margin-top: 2px; font-size: 12px; line-height: 1.4; color: var(--muted); }
.upload-slots { display: flex; flex-direction: column; gap: var(--sp-2); min-width: 0; }
.expense-block .upload-slots { margin-top: var(--sp-4); }
.upload-slots-grid { display: flex; flex-direction: column; gap: var(--sp-2); min-width: 0; }
.upload-slots-grid.has-amount .upload-slots-head,
.upload-slots-grid.has-amount .upload-slot-row.has-amount {
  display: grid;
  grid-template-columns: minmax(0, 320px) 128px auto;
  column-gap: var(--sp-3);
  row-gap: var(--sp-2);
  align-items: center;
  min-width: 0;
  width: 100%;
}
.upload-slots-grid.has-amount .upload-slot-row.has-amount > .upload-slot {
  width: 100%;
  max-width: 320px;
  min-width: 0;
}
.upload-slots-grid.has-amount .upload-slot-row.has-amount > .upload-slot-row-tools {
  justify-self: start;
  white-space: nowrap;
}
.upload-slots-head-amount {
  font-size: 13px;
  font-weight: 500;
  color: var(--muted);
  margin-bottom: 0;
}
.upload-slots-grid:not(.has-amount) .upload-slot-row {
  display: grid;
  grid-template-columns: minmax(0, min(320px, 100%)) auto;
  column-gap: var(--sp-3);
  align-items: center;
  min-width: 0;
  width: 100%;
}
.upload-slots-grid:not(.has-amount) .upload-slot-row > .upload-slot {
  width: 100%;
  max-width: 320px;
  min-width: 0;
}
.upload-slots-grid:not(.has-amount) .upload-slot-row > .upload-slot-row-tools {
  justify-self: start;
  white-space: nowrap;
}
.upload-slot-row { min-width: 0; }
.upload-slot-amount input,
.upload-slot-readonly-amount {
  display: block;
  width: 100%;
  box-sizing: border-box;
  height: var(--ctl-h);
  font-family: inherit;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.upload-slots-add-btn { margin-top: var(--sp-3); }

html.app-shell body .upload-slot {
  flex: 0 0 320px;
  width: 320px;
  min-width: 0;
  max-width: 100%;
  box-sizing: border-box;
  height: var(--ctl-h);
  min-height: var(--ctl-h);
  max-height: var(--ctl-h);
  padding: 0 var(--sp-3);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  background: var(--paper);
}
html.app-shell body .upload-slot.has-file {
  border-style: solid;
  border-color: var(--line-strong);
  background: var(--paper);
  overflow: hidden;
}
html.app-shell body label.upload-slot.is-empty {
  cursor: pointer;
  margin: 0;
  font-weight: 500;
}
html.app-shell body .upload-slot-pick {
  position: relative;
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  margin: 0;
  cursor: pointer;
  font-weight: 500;
  overflow: hidden;
}
html.app-shell body .upload-slot-placeholder {
  font-size: 14px;
  line-height: 1.4;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
html.app-shell body .upload-slot-name {
  font-size: 14px;
  line-height: 1.4;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}
html.app-shell body .upload-slot.has-file .upload-slot-pick {
  min-width: 0;
}
html.app-shell body .upload-slot-clear {
  flex-shrink: 0;
  min-width: var(--ctl-h-sm);
  width: var(--ctl-h-sm);
  padding: 0;
  font-size: 16px;
  line-height: 1;
}
.upload-slot-file-actions,
.upload-slot-row-tools { display: flex; align-items: center; gap: var(--sp-2); flex-shrink: 0; }
html.app-shell body .upload-slot-file-actions .btn-sm {
  flex-shrink: 0;
  padding-left: var(--sp-2);
  padding-right: var(--sp-2);
}
.upload-file-btn { position: relative; cursor: pointer; margin: 0; }
html.app-shell body .upload-file-input {
  position: absolute;
  width: 1px;
  height: 1px;
  min-height: 0;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  border: 0;
  background: transparent;
}
.hr-attachment-line { display: flex; align-items: center; gap: var(--sp-2); min-height: var(--ctl-h-sm); }
.hr-attachment-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.hr-attachment-preview {
  position: fixed; inset: 0; z-index: 80;
  display: flex; align-items: center; justify-content: center; padding: var(--sp-5);
}
.hr-attachment-preview[hidden] { display: none; }
.hr-attachment-preview-backdrop { position: absolute; inset: 0; background: rgba(17, 24, 39, 0.45); }
.hr-attachment-preview-box {
  position: relative;
  width: min(920px, 100%);
  max-height: calc(100vh - 48px);
  background: var(--paper);
  border-radius: var(--r-lg);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  box-shadow: var(--shadow-3);
}
.hr-attachment-preview-bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-3); padding: var(--sp-3) var(--sp-4);
  border-bottom: 1px solid var(--line);
}
.hr-attachment-preview-bar strong { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hr-attachment-preview-body {
  padding: var(--sp-4);
  overflow: auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  min-height: 0;
  flex: 1;
}
.hr-attachment-preview-body img {
  display: block;
  max-width: 100%;
  width: auto;
  height: auto;
  max-height: calc(100vh - 160px);
  object-fit: contain;
  margin: 0 auto;
  border: 0;
  background: var(--sunken);
}
.hr-attachment-preview-body iframe {
  display: block;
  width: 100%;
  align-self: stretch;
  height: 70vh;
  max-height: calc(100vh - 160px);
  border: 0;
  background: var(--sunken);
}
.hr-attachment-preview-body pre,
.hr-attachment-preview-body p {
  align-self: stretch;
  width: 100%;
}
.hr-attachment-preview-body pre { margin: 0; white-space: pre-wrap; word-break: break-word; font-size: 13px; line-height: 1.5; }

html.app-shell body .date-section,
html.app-shell body .attach-section,
html.app-shell body .remarks-section { margin-top: var(--sp-4); }
html.app-shell body .leave-main > select,
html.app-shell body .leave-main > textarea { margin-bottom: 0; }

/* 输入焦点：强调色第三个出处 */
html.app-shell body input:focus,
html.app-shell body select:focus,
html.app-shell body textarea:focus {
  outline: none;
  border-color: var(--brand);
  box-shadow: 0 0 0 3px var(--focus-ring);
}

/* --------------------------------------------------------------------------
   7. 表格
   -------------------------------------------------------------------------- */
html.app-shell body .table-wrap {
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--paper);
  box-shadow: none;
}
html.app-shell body .table-header,
html.app-shell body .table-row {
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-radius: 0;
}
html.app-shell body .table-header {
  text-transform: none;
  letter-spacing: 0;
  background: var(--sunken);
  color: var(--muted);
  font-size: 12px;
  font-weight: 500;
  border: 0;
  border-bottom: 1px solid var(--line);
}
html.app-shell body .table-row {
  background: var(--paper);
  border-top: 1px solid var(--line-soft);
  box-shadow: none;
}
html.app-shell body .table-row:hover { background: var(--sunken); }
html.app-shell body .table-row { transition: background-color var(--dur) var(--ease); }

html.app-shell body .panel table,
html.app-shell body .glass table,
html.app-shell body table.data-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
  letter-spacing: 0;
}
html.app-shell body .panel th,
html.app-shell body .glass th,
html.app-shell body table.data-table th {
  text-align: left;
  text-transform: none;
  letter-spacing: 0;
  background: var(--sunken);
  color: var(--muted);
  font-size: 12px;
  font-weight: 500;
  padding: var(--sp-3) var(--sp-4);
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
html.app-shell body .panel td,
html.app-shell body .glass td,
html.app-shell body table.data-table td {
  padding: var(--sp-3) var(--sp-4);
  border-bottom: 1px solid var(--line-soft);
  color: var(--ink);
  vertical-align: middle;
}
html.app-shell body table.data-table td[colspan],
html.app-shell body .panel td[colspan],
html.app-shell body .glass td[colspan] {
  padding: var(--sp-3) var(--sp-4);
  text-align: left;
  color: var(--muted);
}
html.app-shell body table.data-table td.sort-col,
html.app-shell body .panel td.sort-col,
html.app-shell body .glass td.sort-col {
  width: 72px;
  padding: var(--sp-2) var(--sp-1) var(--sp-2) var(--sp-4);
  white-space: nowrap;
}
html.app-shell body table.data-table td.sort-col + td,
html.app-shell body .panel td.sort-col + td,
html.app-shell body .glass td.sort-col + td { padding-left: var(--sp-2); }

html.app-shell body td input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not([type="hidden"]):not([type="range"]):not(.tag-input),
html.app-shell body td select {
  height: var(--ctl-h-sm);
  min-height: var(--ctl-h-sm);
  max-height: var(--ctl-h-sm);
  line-height: calc(var(--ctl-h-sm) - 2px);
}
html.app-shell body .panel tbody tr:hover td,
html.app-shell body .glass tbody tr:hover td,
html.app-shell body table.data-table tbody tr:hover td { background: var(--sunken); }

html.app-shell body table.data-table { background: var(--paper); }

/* --------------------------------------------------------------------------
   8. 标签页
   -------------------------------------------------------------------------- */
html.app-shell body .tabs,
html.app-shell body .sub-tabs {
  display: flex;
  align-items: stretch;
  gap: var(--sp-1);
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--line);
  border-radius: 0;
  box-shadow: none;
  padding: 0;
  margin: 0 0 var(--sp-4);
  overflow-x: auto;
}
html.app-shell body .tabs::after,
html.app-shell body .sub-tabs::after { display: none; }

html.app-shell body .tab,
html.app-shell body .tabs .tab,
html.app-shell body .tabs button.tab,
html.app-shell body .sub-tab {
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 40px;
  min-height: 40px;
  margin: 0;
  background: transparent;
  color: var(--muted);
  border: 0;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  box-shadow: none;
  padding: 0 var(--sp-3);
  font-size: 14px;
  font-weight: 500;
  line-height: 1;
  cursor: pointer;
}
html.app-shell body .tab:hover,
html.app-shell body .sub-tab:hover { color: var(--ink); }
html.app-shell body .tab.active,
html.app-shell body .tabs .tab.active,
html.app-shell body .sub-tab.active {
  color: var(--ink);
  font-weight: 600;
  border-bottom-color: var(--brand);
  background: transparent;
}

/* --------------------------------------------------------------------------
   9. 徽章 / 状态 / 统计
   -------------------------------------------------------------------------- */
html.app-shell body .name-badge,
html.app-shell body .summary-avatar {
  width: var(--ctl-h);
  height: var(--ctl-h);
  border-radius: var(--r-md);
  background: var(--wash);
  color: var(--ink);
  border: 1px solid var(--line);
  font-size: 14px;
  font-weight: 500;
  box-shadow: none;
}

html.app-shell body .pill,
html.app-shell body .status-pill {
  display: inline-flex;
  align-items: center;
  border-radius: var(--r-pill);
  padding: 2px var(--sp-2);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0;
  line-height: 1.5;
  background: var(--pill-bg);
  color: var(--pill-fg);
  border: 1px solid var(--pill-line);
}
html.app-shell body .pill.pending { background: var(--warn-bg); color: var(--warn-fg); border-color: var(--warn-line); }
html.app-shell body .pill.generated { background: var(--ok-bg); color: var(--ok-fg); border-color: var(--ok-line); }
html.app-shell body .status-pill.approved { background: var(--ok-bg); color: var(--ok-fg); border-color: var(--ok-line); }
html.app-shell body .status-pill.rejected { background: var(--danger-bg); color: var(--danger-fg); border-color: var(--danger-line); }
html.app-shell body .status-pill.inProgress { background: var(--warn-bg); color: var(--warn-fg); border-color: var(--warn-line); }
html.app-shell body .status-pill.pendingConfirm { background: var(--info-bg); color: var(--info-fg); border-color: var(--info-line); }
html.app-shell body .status-pill.cancelled { background: var(--idle-bg); color: var(--idle-fg); border-color: var(--idle-line); }

html.app-shell body .empty::before {
  content: "";
  display: block;
  width: 24px;
  height: 24px;
  margin: 0 auto var(--sp-2);
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239ca3af' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='4' y='5' width='16' height='14' rx='2'/%3E%3Cpath d='M4 9.5h16M8 3.5v3M16 3.5v3'/%3E%3C/svg%3E") center / 24px 24px no-repeat;
}
html.app-shell body .empty,
html.app-shell body .flow-chart-empty {
  text-align: center;
  color: var(--muted);
  background: var(--sunken);
  border: 1px dashed var(--line);
  border-radius: var(--r-lg);
  padding: var(--sp-4);
  font-size: 13px;
  line-height: 1.5;
}

/* 数字统一等宽，避免跳动 */
html.app-shell body .stat-value,
html.app-shell body .stat-unit,
html.app-shell body .pay-net,
html.app-shell body .claim-total {
  font-variant-numeric: tabular-nums;
  font-family: var(--font-num);
  letter-spacing: 0;
  color: var(--ink);
}
html.app-shell body .stat-value { font-size: 24px; font-weight: 600; line-height: 1.15; }

html.app-shell body .section-label {
  letter-spacing: 0;
  text-transform: none;
  color: var(--muted);
  font-size: 12px;
  font-weight: 600;
  margin: 0;
}

html.app-shell body .error-box,
html.app-shell body .error-message {
  border-radius: var(--r-md);
  background: var(--danger-bg);
  border: 1px solid var(--danger-line);
  color: var(--danger-fg);
}

/* --------------------------------------------------------------------------
   10. 弹窗
   -------------------------------------------------------------------------- */
html.app-shell body .modal,
html.app-shell body .modal-box,
html.app-shell body .center-error-box,
html.app-shell body .form-modal-box {
  border-radius: var(--r-lg);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-3);
  background: var(--paper);
}
html.app-shell body .modal-backdrop,
html.app-shell body .center-error-modal,
html.app-shell body .modal-overlay {
  background: rgba(17, 24, 39, 0.45);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

/* --------------------------------------------------------------------------
   11. 工作台：1px 间隙数据条（账本格）
   -------------------------------------------------------------------------- */
html.app-shell body .stat-grid {
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  overflow: hidden;
}
html.app-shell body .stat-box,
html.app-shell body .notice-box,
html.app-shell body .mini-item {
  background: var(--paper);
  border: 0;
  border-radius: 0;
  padding: var(--sp-3) var(--sp-3);
  box-shadow: none;
}
html.app-shell body .stat-box:hover,
html.app-shell body .notice-box:hover,
html.app-shell body .mini-item:hover { border-color: transparent; }
html.app-shell body .stat-label { margin: 0 0 var(--sp-1); font-size: var(--fs-sm); color: var(--muted); font-weight: 400; }
html.app-shell body .pay-net { padding: var(--sp-3); background: var(--brand-soft); border: 1px solid var(--brand-line); border-radius: var(--r-md); color: var(--ink); font-weight: 600; }

html.app-shell body #leaveDashContent,
html.app-shell body #payDashContent,
html.app-shell body #claimDashContent,
html.app-shell body #leaveManagerContent,
html.app-shell body #payManagerContent,
html.app-shell body #claimManagerContent {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
}
html.app-shell body .section-block { gap: var(--sp-2); }
html.app-shell body .dash-manager-block { gap: var(--sp-4); }
html.app-shell body .panel-title:not(:first-child),
html.app-shell body .section-title:not(:first-child) { margin-top: var(--sp-6); }
html.app-shell body .stat-grid + .section-block,
html.app-shell body .notice-box + .section-block,
html.app-shell body .empty + .section-block,
html.app-shell body .mini-list + .section-block,
html.app-shell body .section-block + .section-block { margin-top: var(--sp-4); }
html.app-shell body .dash-manager-title { color: var(--ink); font-weight: 600; font-size: 14px; }
html.app-shell body .dash-card-sub { font-size: 13px; color: var(--muted); line-height: 1.5; }
html.app-shell body .mini-list { gap: var(--sp-2); }
html.app-shell body .mini-item { border: 1px solid var(--line); border-radius: var(--r-md); }
html.app-shell body .mini-item-title { font-weight: 500; color: var(--ink); }
html.app-shell body .mini-item-meta { color: var(--muted); margin-top: var(--sp-1); font-size: 12px; }
html.app-shell body .notice-box { border: 1px solid var(--line); border-radius: var(--r-md); line-height: 1.6; }
html.app-shell body .dash-pagination button {
  min-width: 32px; height: 32px; padding: 0 8px;
  font-size: 13px; font-weight: 500;
  border-radius: var(--r-sm);
  border: 1px solid var(--line-strong);
  background: var(--paper);
  color: var(--ink-2);
  cursor: pointer;
}
html.app-shell body .dash-pagination button.active {
  background: var(--brand);
  color: var(--ink-invert);
  border-color: var(--brand);
}

/* --------------------------------------------------------------------------
   12. 登录页
   两层结构：安静的浅灰台面（画布） → 居中一张「登录卡」 → 卡内左深右白
   台面刻意不加任何可见纹理：网格会读成「工程草稿纸」，抢卡片的主视觉。
   只留一层几乎察觉不到的柔光，让白卡看起来是浮在台面上、而不是贴上去。
   -------------------------------------------------------------------------- */
body:has(.login-box) {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  padding: 48px 32px;
  background-color: var(--canvas);
  /* 刻意不加任何纹理/渐变/网格：台面越安静，卡片越像「文件」。
     层次交给卡片自己的落影去表达。 */
  background-image: none;
  font-family: var(--font-sans);
  font-size: 14px;
  line-height: 1.5;
  letter-spacing: 0;
}
.login-container {
  position: relative;
  width: 100%;
  max-width: 880px;
  min-height: min(560px, calc(100vh - 80px));
  padding: 0;
  display: grid;
  /* 卡内：左品牌墙固定，右表单区自适应 */
  grid-template-columns: minmax(260px, 300px) minmax(0, 1fr);
  background: var(--paper);
  border-radius: var(--r-xl);
  overflow: hidden;
  /* 三层落影：贴地一层描边感 + 中层扩散 + 远层软化，纸面「浮」在平色台面上 */
  box-shadow:
    0 1px 2px rgba(17, 24, 39, 0.05),
    0 8px 20px -6px rgba(17, 24, 39, 0.10),
    0 30px 60px -22px rgba(17, 24, 39, 0.18);
  outline: 1px solid rgba(17, 24, 39, 0.06);
  outline-offset: -1px;
}
.login-side {
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  padding: 44px 40px 32px;
  /* 深色底换成公司官网 warpool.hk 的深海军蓝（--deep #102d4b → --deep-2）：
     侧边栏是「工作区」用墨黑 --rail，登录墙是「品牌区」用品牌深蓝——
     同一个系统里两种深色并存，但它们承担的角色不同，不会读成"没统一"。
     不提亮的纯渐变会发闷，所以下面第 26 节还叠了官网那种同心弧做层次。 */
  background-color: var(--deep);
  background-image: var(--grad-deep);
  color: var(--deep-ink);
}
/* 深色墙右缘 1px 高光：让「墙」与「纸面」的交界有工艺感 */
.login-side::before {
  content: "";
  display: block;
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 1px;
  background: var(--deep-line);
}
.login-side > * { position: relative; z-index: 1; }
/* 品牌组整体垂直居中：上下 auto 均分剩余空间，底部只留一行系统说明 */
.login-brand { margin: auto 0; }
.login-side-foot {
  flex: 0 0 auto;
  /* 两行：模块名（原 kicker）+ 使用范围声明。11px 是刻度外的档位，且中文在这个
     字号下发虚，全部归到 --fs-micro。 */
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding-top: var(--sp-3);
  border-top: 1px solid var(--deep-line);
  font-size: var(--fs-micro);
  color: var(--deep-ink-2);
}
.login-side-kicker { font-weight: 600; }
.login-side-note { color: var(--deep-ink-3); }
.login-side-mark {
  width: 46px;
  height: 46px;
  border-radius: var(--r-md);
  /* 深色底上用白色印章块，品牌字母用墨青——比深底深字清晰得多 */
  background: var(--paper);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 17px;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--brand);
  margin-bottom: var(--sp-5);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.28);
  overflow: hidden;
}
.login-side h2 { margin: 0; font-size: 30px; font-weight: 600; letter-spacing: 0; }
.login-side p { margin: var(--sp-2) 0 0; color: var(--deep-ink-2); font-size: var(--fs-base); line-height: var(--lh-base); }

.login-box {
  /* 卡片右半区就是「纸面」，表单直接排布，不再叠第二层白卡 */
  background: transparent;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  max-width: 380px;
  width: 100%;
  margin: auto;
  padding: 44px 36px 36px;
}
.login-box .logo { display: none; }
.login-box .login-header { text-align: left; margin-bottom: var(--sp-5); }
/* 品牌签名短线：给纯白表单区一个视觉锚点 */
.login-box .login-header::before {
  content: "";
  display: block;
  width: 28px;
  height: 3px;
  border-radius: 2px;
  background: var(--brand);
  margin-bottom: var(--sp-4);
}
.login-box .login-title { font-size: 24px; font-weight: 600; letter-spacing: 0; color: var(--ink); margin: 0 0 6px; }
.login-box .login-subtitle { font-size: var(--fs-base); color: var(--muted); margin: 0; }
.login-box .form-group { margin-bottom: 18px; }
.login-box .form-group label {
  text-transform: none;
  letter-spacing: 0;
  color: var(--muted);
  font-weight: 500;
  margin-bottom: 6px;
}
.login-box a { color: var(--brand); }
.login-box .form-group input {
  min-height: var(--ctl-h);
  height: var(--ctl-h);
  border-radius: var(--r-md);
  border: 1px solid var(--line-strong);
  background: var(--paper);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
.login-box .form-group input::placeholder { color: var(--faint); }
.login-box .form-group input:focus {
  border-color: var(--brand);
  box-shadow: 0 0 0 3px var(--focus-ring);
  background: var(--paper);
}
/* 语言切换是次要操作：挪到卡片右上角，不占表单主轴 */
.login-box .lang-selector {
  position: absolute;
  top: 20px;
  right: 20px;
  z-index: 3;
}
.lang-selector {
  position: static;
  display: inline-flex;
  align-items: center;
  /* 浅底无边框的分段控件，与侧栏 .lang-switch 同一套语言 */
  background: var(--wash);
  border: 0;
  border-radius: var(--r-md);
  margin: 0;
  width: fit-content;
  padding: 3px;
  gap: 2px;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
.lang-selector button {
  height: var(--ctl-h-xs);
  min-height: var(--ctl-h-xs);
  min-width: 48px;
  padding: 0 var(--sp-3);
  text-align: center;
  background: transparent;
  border: 0;
  color: var(--muted);
  border-radius: var(--r-sm);
  font-size: var(--fs-sm);
  font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
  transition: background-color 0.14s ease, color 0.14s ease;
}
.lang-selector button:hover { color: var(--ink-2); }
/* 激活态用全站强调色（墨青），不再用侧栏深灰蓝 */
.lang-selector button.active {
  background: var(--brand);
  color: var(--ink-invert);
  font-weight: 600;
  box-shadow: none;
}
.form-group { margin-bottom: var(--sp-4); }
/* 表单里的下拉与多行文本同样撑满容器 */
.form-group select,
.form-group textarea {
  box-sizing: border-box;
  width: 100%;
}
.form-group > label,
.login-box .form-group label {
  display: block;
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--muted);
  letter-spacing: 0;
  text-transform: none;
  line-height: 1.4;
  margin: 0 0 var(--sp-1);
  padding: 0;
}
.form-group input:not([type="checkbox"]):not([type="radio"]) {
  box-sizing: border-box;
  width: 100%;                 /* 表单控件撑满容器，缺这条会退回浏览器默认宽度 */
  height: var(--ctl-h);
  min-height: var(--ctl-h);
  max-height: var(--ctl-h);
  padding: 0 var(--sp-3);
  font-size: 14px;
  line-height: calc(var(--ctl-h) - 2px);
  letter-spacing: 0;
  border-radius: var(--r-md);
  border: 1px solid var(--line-strong);
  background: var(--paper);
  backdrop-filter: none;
}
.remember-me input[type="checkbox"] { accent-color: var(--brand); }
.forgot-password { color: var(--brand); font-weight: 500; }
.forgot-password:hover { color: var(--brand-hover); }
.logo { background: var(--rail); box-shadow: none; }
#btnLogin, .login-box .btn-primary, button[type="submit"] { border-radius: var(--r-md); }

@media (max-width: 800px) {
  /* 小屏：登录卡取消圆角与阴影，直接铺满，回到「上深下浅」单列 */
  body:has(.login-box) { padding: 0; align-items: stretch; }
  .login-container {
    max-width: none;
    min-height: 100vh;
    grid-template-columns: 1fr;
    /* 品牌条按内容高，表单区吃掉剩余高度（不加这行 auto 行会被均分拉伸） */
    grid-template-rows: auto minmax(0, 1fr);
    border-radius: 0;
    box-shadow: none;
  }
  /* 小屏把品牌墙压成一条：印章 + 名称横排，隐去说明，省出表单空间 */
  .login-side { padding: 20px 24px; }
  .login-side::before { display: none; }
  .login-brand { margin: 0; display: flex; align-items: center; gap: var(--sp-3); }
  .login-side-mark { width: 38px; height: 38px; font-size: 14px; margin-bottom: 0; border-radius: var(--r-sm); }
  .login-side h2 { font-size: 21px; }
  .login-side p { display: none; }
  .login-side-foot { display: none; }
  .login-box { margin: auto; padding: 32px var(--sp-5) 28px; }
  /* 小屏语言切换回到表单末尾、右下角对齐（与桌面版「右上角角落」位置呼应） */
  .login-box .lang-selector {
    position: static;
    display: flex;
    width: fit-content;
    margin: var(--sp-5) 0 0 auto;
  }
}

/* --------------------------------------------------------------------------
   13. 审批流程图
   -------------------------------------------------------------------------- */
.flow-chart {
  margin: 0 0 var(--sp-4);
  padding: var(--sp-3);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--sunken);
}
.flow-chart-title { margin-bottom: var(--sp-2); font-size: 13px; font-weight: 600; color: var(--ink-2); }
.flow-chart-empty { padding: var(--sp-2) 2px var(--sp-3); color: var(--muted); font-size: 13px; }
.flow-chart-track { display: flex; align-items: stretch; gap: 0; margin: 0; padding: 0 0 var(--sp-2); overflow-x: auto; list-style: none; }
.flow-step { flex: 1 0 190px; max-width: 250px; }
.flow-node { height: 100%; padding: var(--sp-2) var(--sp-3); border: 1px solid var(--line-strong); border-radius: var(--r-md); background: var(--paper); }
.flow-node-kicker { font-size: 12px; font-weight: 600; color: var(--ink-2); }
.flow-node-title { margin-top: var(--sp-1); font-size: var(--fs-base); font-weight: 600; color: var(--ink); }
.flow-node-rule { margin-top: var(--sp-1); font-size: 12px; line-height: 1.4; color: var(--muted); }
.flow-people { margin: var(--sp-2) 0 0; padding: 0; list-style: none; }
.flow-person { display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-2); align-items: baseline; padding: var(--sp-1) 0; border-top: 1px solid var(--line-soft); font-size: 13px; }
.flow-person-name { font-weight: 600; color: var(--ink); }
.flow-person-role, .flow-person-mark { color: var(--muted); font-size: 12px; }
.flow-arrow { position: relative; flex: 0 0 28px; }
.flow-arrow::before { content: ""; position: absolute; left: 0; right: 7px; top: 22px; border-top: 2px solid var(--faint); }
.flow-arrow::after { content: ""; position: absolute; right: 0; top: 17px; border: 5px solid transparent; border-left-color: var(--faint); }
.flow-step.is-edited .flow-node,
.flow-step.is-done .flow-node { border-color: var(--ok-line); background: var(--ok-bg); }
.flow-step.is-edited .flow-node-kicker,
.flow-step.is-done .flow-node-kicker { color: var(--ok-fg); }
.flow-step.is-current .flow-node,
.flow-step.is-supplement .flow-node,
.flow-step.is-confirm .flow-node { border-color: var(--brand); background: var(--brand-soft); box-shadow: none; }
.flow-step.is-current .flow-node-kicker,
.flow-step.is-supplement .flow-node-kicker,
.flow-step.is-confirm .flow-node-kicker { color: var(--brand); }
.flow-step.is-rejected .flow-node,
.flow-step.is-cancelled .flow-node { border-color: var(--danger-line); background: var(--danger-bg); }
.flow-step.is-rejected .flow-node-kicker,
.flow-step.is-cancelled .flow-node-kicker { color: var(--danger-fg); }
.flow-step.is-upcoming .flow-node { background: var(--sunken); }
.flow-person-mark { display: block; }
.flow-person-time { display: block; margin-top: var(--sp-1); font-size: 12px; line-height: 1.4; color: var(--muted); }
.flow-person.is-approved .flow-person-mark,
.flow-person.is-edited .flow-person-mark { color: var(--ok-fg); font-weight: 600; }
.flow-person.is-rejected .flow-person-mark { color: var(--danger-fg); font-weight: 600; }
.flow-person.is-waiting .flow-person-mark { color: var(--brand); font-weight: 600; }

/* --------------------------------------------------------------------------
   13b. 审批瀑布流（详情页右侧）
   -------------------------------------------------------------------------- */
html.app-shell body .app-detail-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(260px, 320px);
  gap: var(--sp-4);
  align-items: start;
}
html.app-shell body .app-detail-main { min-width: 0; }
html.app-shell body .app-detail-rail {
  position: sticky;
  top: calc(var(--app-chrome-h) + 16px);
  max-height: calc(100vh - var(--app-chrome-h) - 32px);
  overflow: auto;
  min-width: 0;
}
html.app-shell body .approval-timeline.glass.panel {
  margin-bottom: 0;
  padding: var(--sp-4);
}
html.app-shell body .approval-timeline-title,
html.app-shell body .approval-timeline-section-title {
  margin: 0 0 var(--sp-4);
  padding-bottom: var(--sp-3);
  border-bottom: 1px solid var(--line);
  font-size: var(--fs-body, 14px);
  font-weight: 600;
  color: var(--ink);
  letter-spacing: 0;
}
html.app-shell body .approval-timeline-section .approval-timeline.glass.panel {
  padding: 0;
  border: 0;
  background: transparent;
  box-shadow: none;
}
html.app-shell body .approval-timeline-section .approval-timeline-title { display: none; }
html.app-shell body .approval-timeline-empty {
  font-size: 13px;
  color: var(--muted);
  line-height: 1.5;
}
html.app-shell body .approval-timeline-track {
  list-style: none !important;
  margin: 0;
  padding: 0;
}
html.app-shell body .approval-timeline-item {
  position: relative;
  display: grid;
  grid-template-columns: 18px minmax(0, 1fr);
  gap: var(--sp-3);
  padding-bottom: var(--sp-4);
}
html.app-shell body .approval-timeline-item:last-child { padding-bottom: 0; }
html.app-shell body .approval-timeline-item:not(:last-child)::before {
  content: "";
  position: absolute;
  left: 8px;
  top: 18px;
  bottom: 0;
  width: 2px;
  background: linear-gradient(180deg, var(--line-strong) 0%, var(--line) 100%);
}
html.app-shell body .approval-timeline-marker {
  display: flex;
  justify-content: center;
  padding-top: 4px;
}
html.app-shell body .approval-timeline-dot {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  border: 2px solid var(--line-strong);
  background: var(--paper);
  box-sizing: border-box;
  flex-shrink: 0;
}
html.app-shell body .approval-timeline-item.is-success .approval-timeline-dot,
html.app-shell body .approval-timeline-item.is-neutral .approval-timeline-dot {
  border-color: var(--ok-line);
  background: var(--ok-bg);
}
html.app-shell body .approval-timeline-item.is-danger .approval-timeline-dot {
  border-color: var(--danger-line);
  background: var(--danger-bg);
}
html.app-shell body .approval-timeline-item.is-warn .approval-timeline-dot {
  border-color: var(--warn-line);
  background: var(--warn-bg);
}
html.app-shell body .approval-timeline-item.is-muted .approval-timeline-dot {
  border-color: var(--line-strong);
  background: var(--sunken);
}
html.app-shell body .approval-timeline-item.is-current .approval-timeline-dot {
  border-color: var(--brand);
  background: var(--brand);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--brand) 18%, transparent);
}
html.app-shell body .approval-timeline-item.is-upcoming .approval-timeline-dot {
  border-color: var(--line);
  background: var(--paper);
}
html.app-shell body .approval-timeline-item.is-upcoming .approval-timeline-card {
  border-style: dashed;
  background: var(--paper);
  opacity: 0.92;
}
html.app-shell body .approval-timeline-item.is-upcoming .approval-timeline-badge {
  border-color: var(--line);
  background: var(--sunken);
  color: var(--muted);
}
html.app-shell body .approval-timeline-item.is-upcoming .approval-timeline-actor {
  color: var(--ink-2);
  font-weight: 500;
}
html.app-shell body .approval-timeline-role {
  margin-left: 4px;
  font-size: 12px;
  font-weight: 500;
  color: var(--muted);
}
html.app-shell body .approval-timeline-card {
  padding: var(--sp-3);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--sunken);
}
html.app-shell body .approval-timeline-item.is-current .approval-timeline-card {
  border-color: color-mix(in srgb, var(--brand) 35%, var(--line));
  background: color-mix(in srgb, var(--brand) 6%, var(--paper));
}
html.app-shell body .approval-timeline-card-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--sp-2);
  flex-wrap: wrap;
}
html.app-shell body .approval-timeline-time {
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
  line-height: 1.4;
}
html.app-shell body .approval-timeline-badge {
  display: inline-flex;
  align-items: center;
  max-width: 100%;
  padding: 2px 8px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--paper);
  font-size: 11px;
  font-weight: 600;
  line-height: 1.45;
  color: var(--ink-2);
  word-break: break-word;
}
html.app-shell body .approval-timeline-item.is-success .approval-timeline-badge {
  border-color: var(--ok-line);
  background: var(--ok-bg);
  color: var(--ok-fg);
}
html.app-shell body .approval-timeline-item.is-danger .approval-timeline-badge {
  border-color: var(--danger-line);
  background: var(--danger-bg);
  color: var(--danger-fg);
}
html.app-shell body .approval-timeline-item.is-warn .approval-timeline-badge {
  border-color: var(--warn-line);
  background: var(--warn-bg);
  color: var(--warn-fg);
}
html.app-shell body .approval-timeline-item.is-current .approval-timeline-badge {
  border-color: color-mix(in srgb, var(--brand) 35%, var(--line));
  background: var(--brand-soft);
  color: var(--brand);
}
html.app-shell body .approval-timeline-item.is-muted .approval-timeline-badge {
  color: var(--muted);
}
html.app-shell body .approval-timeline-actor {
  margin-top: var(--sp-2);
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  line-height: 1.4;
}
html.app-shell body .approval-timeline-action {
  display: none;
}
html.app-shell body .approval-timeline-detail {
  margin-top: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--r-sm);
  border: 1px solid color-mix(in srgb, var(--line) 80%, transparent);
  background: var(--paper);
  font-size: 12px;
  line-height: 1.5;
  color: var(--ink-2);
  word-break: break-word;
}
html.app-shell body .approval-timeline-detail-label {
  display: block;
  margin-bottom: 2px;
  font-size: 11px;
  font-weight: 600;
  color: var(--muted);
}
html.app-shell body .approval-timeline-pending-meta {
  margin-top: var(--sp-2);
  display: flex;
  flex-direction: column;
  gap: 4px;
}
html.app-shell body .approval-timeline-actors {
  font-size: 12px;
  font-weight: 600;
  color: var(--ink);
  line-height: 1.45;
}
html.app-shell body .status-pill.pendingSupplement {
  background: var(--warn-bg);
  color: var(--warn-fg);
  border-color: var(--warn-line);
}
html.app-shell body a.mini-item.is-link {
  display: block;
  color: inherit;
  text-decoration: none;
}
html.app-shell body a.mini-item.is-link:hover {
  border-color: color-mix(in srgb, var(--brand) 35%, var(--line));
}
html.app-shell body .future-leave-tag {
  display: inline-flex;
  align-items: center;
  margin-left: 6px;
  padding: 1px 7px;
  border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--brand) 30%, var(--line));
  background: var(--brand-soft);
  font-size: 11px;
  font-weight: 600;
  line-height: 1.4;
  color: var(--brand);
  vertical-align: middle;
}

@media (max-width: 960px) {
  html.app-shell body .app-detail-layout { grid-template-columns: 1fr; }
  html.app-shell body .app-detail-rail {
    position: static;
    max-height: none;
    order: unset;
  }
}

/* --------------------------------------------------------------------------
   14. 杂项
   -------------------------------------------------------------------------- */
.toast { pointer-events: none; }
.toast.show { pointer-events: auto; }

html.app-shell body input[type="date"]:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not([type="hidden"]):not([type="range"]):not(.tag-input) {
  position: relative;
  cursor: pointer;
  min-width: 16rem;
  padding: 0 36px 0 var(--sp-3);
  color: transparent;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none' stroke='%236b7280' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='2' y='3' width='12' height='11' rx='1.5'/%3E%3Cpath d='M2 6.5h12M5 1.8v2.4M11 1.8v2.4'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--sp-3) center;
  background-size: 16px 16px;
}
html.app-shell body input[type="date"]::-webkit-calendar-picker-indicator {
  position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; padding: 0; cursor: pointer; opacity: 0;
}
html.app-shell body input[type="date"]::-webkit-datetime-edit,
html.app-shell body input[type="date"]::-webkit-datetime-edit-fields-wrapper { padding: 0; color: transparent; }
html.app-shell body input[type="date"]::-webkit-datetime-edit-year-field,
html.app-shell body input[type="date"]::-webkit-datetime-edit-month-field,
html.app-shell body input[type="date"]::-webkit-datetime-edit-day-field,
html.app-shell body input[type="date"]::-webkit-datetime-edit-text {
  padding: 0;
  color: transparent;
  background: transparent;
}
html.app-shell body .date-field {
  position: relative;
  display: block;
  width: 100%;
  min-width: 0;
}
html.app-shell body .date-field-face {
  position: absolute;
  left: var(--sp-3);
  top: 0;
  bottom: 0;
  display: inline-flex;
  align-items: center;
  width: max-content;
  max-width: calc(100% - var(--sp-3) - 36px);
  pointer-events: none;
  font-family: inherit;
  font-size: var(--fs-base);
  font-weight: 400;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
  line-height: 1;
  color: var(--placeholder);
}
html.app-shell body .date-field-face .date-sep {
  flex: none;
  width: 0.7em;
  text-align: center;
}
html.app-shell body .date-field.has-value .date-field-face { color: var(--ink); }
html.app-shell body .date-field.is-disabled .date-field-face { color: var(--faint); }

/* --------------------------------------------------------------------------
   15. 页头收口：即使元素带 .glass，也保持「标题行 + 1px 底线」的形态
   （必须写在卡片段之后，同特异性下后者胜）
   -------------------------------------------------------------------------- */
html.app-shell body .glass.header,
html.app-shell body .header {
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--line);
  border-radius: 0;
  box-shadow: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  padding: 0 0 14px;
  margin-bottom: 14px;
}
html.app-shell body .glass.header:hover { border-color: var(--line); }

/* --------------------------------------------------------------------------
   16. 响应式（窄屏）
   -------------------------------------------------------------------------- */
@media (max-width: 760px) {
  .app-side {
    position: sticky;
    top: 0;
    width: 100%;
    height: auto;
    flex-direction: row;
    align-items: center;
    padding: var(--sp-2);
    overflow: hidden;
    z-index: 50;
  }
  .app-brand { padding: 0 var(--sp-2) 0 var(--sp-1); white-space: nowrap; }
  .app-side nav { flex-direction: row; overflow-x: auto; }
  .app-nav-group { display: none; }
  .app-nav-item { white-space: nowrap; }
  .app-main { margin-left: 0; }
  .app-chrome {
    padding: var(--sp-2) var(--sp-3) 0;
    flex-wrap: wrap;
    justify-content: flex-start;
    row-gap: var(--sp-2);
  }
  .app-chrome .user-chip { max-width: 100%; overflow: visible; text-overflow: unset; white-space: nowrap; }
  html.app-shell body .container { padding: var(--sp-3) var(--sp-3) var(--sp-6); }
  html.app-shell body .stat-grid { grid-template-columns: 1fr; }
}

/* ==========================================================================
   17. 一致性收口（Consistency pass）
   --------------------------------------------------------------------------
   各页面 <style> 里仍留着一批 v1「玻璃拟态」皮肤：1.5px 半透明描边、
   14/16/18/22/24/28/32px 随意圆角、font-weight 700/800 满屏、硬编码
   slate 色值。它们与新皮肤（1px 实线 / 4·6·8·12 圆角 / 400·500·600 字重）
   混在一张屏上，是"新旧打架"观感的主要来源。

   本节只做覆盖：选择器带 html.app-shell body 前缀 + 文件末尾加载，
   同特异性下取胜，因此**不需要改任何 HTML**。新增组件皮肤请写在这里，
   不要再回头加 !important。
   ========================================================================== */

/* --- 17.1 数字：等宽对齐但不用 mono（SF Mono 的 0 带斜杠，读成空集） --- */
html.app-shell body .stat-value,
html.app-shell body .stat-unit,
html.app-shell body .pay-net,
html.app-shell body .claim-total,
html.app-shell body .list-meta strong,
html.app-shell body .balance-total,
html.app-shell body .net-highlight,
html.app-shell body .summary-avatar,
html.app-shell body .dash-pagination button {
  font-family: var(--font-sans);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}
/* 真正的"代号"仍用等宽：员工编号 / 单据号 / 设备序列号 */
html.app-shell body .doc-no,
html.app-shell body code,
html.app-shell body kbd {
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
}

/* --- 17.2 标题层级：卡片内标题一律 ≤ 页面 h1，字重封顶 600 --- */
html.app-shell body .emp-banner .name { font-size: 17px; font-weight: 600; line-height: 1.35; }
html.app-shell body .summary-name { font-size: 16px; font-weight: 600; }
html.app-shell body .modal-title,
html.app-shell body .form-modal-box .panel-title { font-size: 17px; font-weight: 600; line-height: 1.4; }
html.app-shell body .date-section-title,
html.app-shell body .annual-section-title,
html.app-shell body .limits-section-title,
html.app-shell body .report-preview-title,
html.app-shell body .approval-layer-title,
html.app-shell body .config-section-title {
  font-size: 15px;
  font-weight: 600;
  color: var(--ink);
  letter-spacing: 0;
}
html.app-shell body .center-success-box p { font-size: 18px; font-weight: 600; line-height: 1.5; }
html.app-shell body .center-error-box p { font-size: 16px; font-weight: 600; line-height: 1.6; }
html.app-shell body .ann-item-title { font-weight: 600; }
html.app-shell body .method-strong,
html.app-shell body .section-desc strong { font-weight: 600; }
/* 列表里"标签 + 大数字"混排：数字降一级，避免与标题抢注意力 */
html.app-shell body .list-meta { color: var(--muted); font-size: 13px; }
html.app-shell body .list-meta strong { font-size: 15px; font-weight: 600; color: var(--ink); }

/* --- 17.3 圆角：容器 12 / 控件 8 / 小件 6 / 徽章 pill。取消 14/16/18/20/22/24/28/32 --- */
html.app-shell body .panel,
html.app-shell body .glass,
html.app-shell body .dash-card,
html.app-shell body .modal,
html.app-shell body .modal-box,
html.app-shell body .form-modal-box,
html.app-shell body .center-error-box,
html.app-shell body .center-success-box,
html.app-shell body .table-wrap,
html.app-shell body .flow-chart,
html.app-shell body .summary-card,
html.app-shell body .slip-card,
html.app-shell body .device-row,
html.app-shell body .device-empty,
html.app-shell body .perm-pages {
  border-radius: var(--r-lg);
}
html.app-shell body .ann-item,
html.app-shell body .ann-cover-preview,
html.app-shell body .editor,
html.app-shell body .tag-input-wrap,
html.app-shell body .date-block,
html.app-shell body .policy-box,
html.app-shell body .projected-box,
html.app-shell body .balance-card,
html.app-shell body .next-approvers-box,
html.app-shell body .revision-notice,
html.app-shell body .claim-window-notice,
html.app-shell body .balance-advance-notice,
html.app-shell body .info-box,
html.app-shell body .approval-layer,
html.app-shell body .export-col-row,
html.app-shell body .summary-item,
html.app-shell body .perm-pages,
html.app-shell body .mini-item,
html.app-shell body .notice-box {
  border-radius: var(--r-md);
}
html.app-shell body .summary-avatar,
html.app-shell body .name-badge { border-radius: var(--r-md); }
/* 表格里的姓名徽章是行内件，不该比控件（40px）还高，否则整行被它撑开 */
html.app-shell body .name-badge {
  width: var(--ctl-h-sm);
  height: var(--ctl-h-sm);
  font-size: 13px;
  font-weight: 500;
  background: var(--wash);
  color: var(--ink-2);
  border: 1px solid var(--line);
}
html.app-shell body .name-main { font-size: 14px; font-weight: 500; color: var(--ink); }
html.app-shell body .name-sub { font-size: 12px; color: var(--muted); margin-top: 1px; }

/* --- 17.4 描边：全站只有两种线 —— 1px 实线（结构）与 1px 虚线（待填/空态） --- */
html.app-shell body .summary-card,
html.app-shell body .slip-card,
html.app-shell body .date-block,
html.app-shell body .balance-card,
html.app-shell body .approval-layer,
html.app-shell body .export-col-row,
html.app-shell body .summary-item,
html.app-shell body .device-row,
html.app-shell body .ann-item,
html.app-shell body .ann-cover-preview,
html.app-shell body .editor,
html.app-shell body .tag-input-wrap,
html.app-shell body .notice-box,
html.app-shell body .mini-item {
  border: 1px solid var(--line);
}
/* 说明性色块：原来的 dashed 会读成"待填"，改成实线 + 语义底色 */
html.app-shell body .policy-box,
html.app-shell body .perm-pages {
  border: 1px solid var(--line);
  background: var(--sunken);
  color: var(--muted);
}
html.app-shell body .projected-box,
html.app-shell body .balance-advance-notice,
html.app-shell body .claim-window-notice { border: 1px solid var(--warn-line); background: var(--warn-bg); color: var(--warn-fg); }
html.app-shell body .next-approvers-box,
html.app-shell body .annual-preview,
html.app-shell body .info-box { border: 1px solid var(--brand-line); background: var(--brand-soft); color: var(--ink-2); }
html.app-shell body .revision-notice { border: 1px solid var(--info-line); background: var(--info-bg); color: var(--info-fg); }
html.app-shell body .summary-avatar { border: 1px solid var(--line); background: var(--wash); color: var(--ink-2); }

/* --- 17.5 输入类：半径/描边/高度全部归位 --- */
html.app-shell body .config-item input,
html.app-shell body .field input,
html.app-shell body .filters input,
html.app-shell body .filter-bar input,
html.app-shell body .records-filter-bar input,
html.app-shell body .report-filters input,
html.app-shell body .annual-grid input,
html.app-shell body .inline-form input,
html.app-shell body .leave-main input,
html.app-shell body .claim-main input,
html.app-shell body .form-field input,
html.app-shell body .field-config-row input,
html.app-shell body .type-config-row input,
html.app-shell body .data-table input,
html.app-shell body .approver-row input,
html.app-shell body .upload-slot,
html.app-shell body .readonly-field,
html.app-shell body .form-modal-box input {
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  background-color: var(--paper);
}
html.app-shell body .readonly-field { background-color: var(--sunken); color: var(--ink-2); }
html.app-shell body .upload-slot.has-file { border-color: var(--line-strong); }
/* 关闭原生外观，避免 Safari/Chrome 回退到系统控件皮肤 */
html.app-shell body button,
html.app-shell body input,
html.app-shell body select,
html.app-shell body textarea { -webkit-appearance: none; appearance: none; }
html.app-shell body select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none' stroke='%236b7280' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4.5 6.5L8 10l3.5-3.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--sp-3) center;
  background-size: 16px 16px;
  padding-right: 34px;
}
html.app-shell body input[type="checkbox"],
html.app-shell body input[type="radio"] { -webkit-appearance: auto; appearance: auto; width: 16px; height: 16px; accent-color: var(--brand); }

/* --- 17.6 表单版面：给长表单一个阅读宽度上限，不要拉满 1160px --- */
html.app-shell body .form-layout > .panel,
html.app-shell body .claim-form-layout,
html.app-shell body .payment-form-layout,
html.app-shell body .leave-grid > .leave-main { max-width: var(--measure-form); }
html.app-shell body .filters,
html.app-shell body .filter-bar,
html.app-shell body .records-filter-bar,
html.app-shell body .report-filters,
html.app-shell body .bonus-filters,
html.app-shell body .bonus-filters-2 { max-width: 1100px; }
html.app-shell body .trip-card,
html.app-shell body .expense-block { max-width: calc(var(--measure-form) + 120px); }
/* 出差表单：输入框撑满单元格，消灭"出发地 140px / 日期 200px"的宽度跳变 */
html.app-shell body .form-grid input:not([type="checkbox"]):not([type="radio"]),
html.app-shell body .form-grid select,
html.app-shell body .form-grid textarea { width: 100%; }
/* 日报/区间表单：日期与时段等宽，避免一列里 520 / 110 的突变 */
html.app-shell body .date-pair-row { grid-template-columns: minmax(0, 1fr) 132px; }
html.app-shell body .date-summary-row { grid-template-columns: repeat(3, minmax(0, 1fr)); }

/* --- 17.7 表格：表头吸顶、金额列等宽、行高一致 --- */
html.app-shell body .table-wrap { position: relative; }
/* 说明：这里刻意不做 position:sticky 表头。
   本系统的 .table-wrap 只横向滚动（overflow-x），纵向跟随页面滚动，
   sticky 会让表头贴到视口顶部、被 .app-chrome 顶栏压住。
   若将来给表格容器加 max-height + overflow:auto，再打开下面两条：
   .table-header, table.data-table thead th { position: sticky; top: 0; z-index: 2; } */
html.app-shell body table.data-table th,
html.app-shell body table.data-table td { padding: 10px var(--sp-4); }
html.app-shell body table.data-table td { font-size: var(--fs-base); }
/* 任何表格里的数字都等宽，列才对得齐（中文不受影响） */
html.app-shell body .table-wrap td,
html.app-shell body .table-wrap th { font-variant-numeric: tabular-nums; }
/* 数字/金额列：右对齐 + 等宽（靠 data-num 标记，JS 只在需要时加） */
html.app-shell body .table-header > .num,
html.app-shell body table.data-table th.num,
html.app-shell body table.data-table td.num,
html.app-shell body .pay-row > :last-child {
  text-align: right;
  font-variant-numeric: tabular-nums;
}
html.app-shell body table.data-table td[colspan] { color: var(--muted); }
/* 空态：一行字变一个"空块"，与 dashboard 的 .empty 统一 */
html.app-shell body table.data-table td[colspan]:only-child { padding: var(--sp-5) var(--sp-4); }
html.app-shell body .records-filter-bar label,
html.app-shell body .report-filters label { margin-bottom: var(--sp-1); }

/* --- 17.8 标签页：一级是下划线，二级降一级（更矮更淡），避免两层长得一样 --- */
html.app-shell body .sub-tabs { border-bottom: 0; margin-bottom: var(--sp-4); }
html.app-shell body .sub-tab {
  height: 30px;
  min-height: 30px;
  padding: 0 var(--sp-3);
  font-size: 13px;
  font-weight: 500;
  color: var(--muted);
  background: var(--wash);
  border: 0;
  border-radius: var(--r-sm);
}
html.app-shell body .sub-tab:hover { color: var(--ink-2); background: var(--line-soft); }
html.app-shell body .sub-tab.active {
  color: var(--ink);
  font-weight: 600;
  background: var(--brand-soft);
  border-bottom-color: transparent;
  box-shadow: inset 0 0 0 1px var(--brand-line);
}

/* --- 17.9 状态徽章 / 标签 --- */
html.app-shell body .badge,
html.app-shell body .status-pill { border-radius: var(--r-pill); padding: 2px 10px; font-size: 12px; font-weight: 500; }
html.app-shell body .badge-inUse { background: var(--ok-bg); color: var(--ok-fg); }
html.app-shell body .badge-inStock { background: var(--warn-bg); color: var(--warn-fg); }
html.app-shell body .badge-retired { background: var(--idle-bg); color: var(--idle-fg); }
html.app-shell body .tag-chip { background: var(--brand-soft); border: 1px solid var(--brand-line); color: var(--brand); font-weight: 500; }
html.app-shell body .key-badge { background: var(--brand-soft); color: var(--brand); border-radius: var(--r-sm); font-weight: 500; }
html.app-shell body .dash-card-sub { font-size: 13px; }

/* --- 17.10 公告：去掉"卡片套卡片"的双层描边，条目退成纯文本块 --- */
html.app-shell body .global-ann-body { gap: var(--sp-4) var(--sp-6); }
html.app-shell body .global-ann-item {
  border: 0;
  border-radius: 0;
  padding: 0;
  background: transparent;
}
html.app-shell body .global-ann-item + .global-ann-item { padding-top: 0; }
html.app-shell body .global-ann-item-title { font-weight: 600; font-size: var(--fs-base); color: var(--ink); }
html.app-shell body .global-ann-item-date { font-size: var(--fs-micro); color: var(--faint); }
html.app-shell body .global-ann-item-content { font-size: 13px; color: var(--muted); line-height: 1.55; }
html.app-shell body .ann-item { border-radius: var(--r-md); padding: var(--sp-3) var(--sp-3) var(--sp-3) var(--sp-4); }
html.app-shell body .ann-item.active {
  background: var(--brand-soft);
  border-color: var(--brand-line);
  box-shadow: inset 2px 0 0 var(--brand);
}
/* 公告编辑器：与输入框同语言 */
html.app-shell body .editor { font-size: 14px; line-height: 1.7; padding: var(--sp-3); }
html.app-shell body .ann-cover-preview { border-style: dashed; border-color: var(--line-strong); background: var(--sunken); }
html.app-shell body .ann-cover-empty { color: var(--faint); font-size: 13px; }

/* --- 17.11 拖拽排序：把 10px 的 ▲▼ 放大到可点 --- */
html.app-shell body .sort-controls { align-items: center; gap: var(--sp-1); }
html.app-shell body .sortable-handle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 24px;
  margin-right: -2px;
  color: var(--faint);
  font-size: 15px;
  line-height: 1;
  border-radius: var(--r-xs);
}
html.app-shell body .sortable-handle:hover { color: var(--ink-2); background: var(--wash); }
html.app-shell body .sortable-handle:active { cursor: grabbing; }
html.app-shell body .sort-sort-btns { gap: 2px; }
html.app-shell body .btn-sort {
  width: 24px;
  height: 15px;
  padding: 0;
  font-size: 9px;
  line-height: 1;
  color: var(--muted);
  border: 0;
  border-radius: var(--r-xs);
  background: transparent;
}
html.app-shell body .btn-sort:hover { color: var(--brand); background: var(--brand-soft); }
html.app-shell body .btn-sort:disabled { opacity: 0.3; cursor: not-allowed; }

/* --- 17.12 交互态：键盘焦点 + 按下反馈 + 统一时长 --- */
html.app-shell body .btn,
html.app-shell body .tab,
html.app-shell body .sub-tab,
html.app-shell body .app-nav-item,
html.app-shell body .ann-item,
html.app-shell body .dash-card,
html.app-shell body .mini-item,
html.app-shell body .dash-pagination button,
html.app-shell body .lang-switch button,
html.app-shell body .lang-selector button {
  transition-duration: var(--dur);
  transition-timing-function: var(--ease);
}
html.app-shell body .btn:active:not(:disabled):not([disabled]),
html.app-shell body .tab:active,
html.app-shell body .sub-tab:active,
html.app-shell body .dash-pagination button:active:not(:disabled) {
  transform: translateY(1px);
  filter: brightness(0.97);
}
html.app-shell body .dash-card:hover { box-shadow: var(--shadow-2); }
html.app-shell body .btn-primary:active:not(:disabled) { filter: brightness(0.92); }
/* 键盘可见焦点：鼠标点击不显示，Tab 必须显示 */
html.app-shell body a:focus-visible,
html.app-shell body button:focus-visible,
html.app-shell body [tabindex]:focus-visible,
html.app-shell body summary:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
  /* 这里原来还写了 border-radius: var(--r-sm)。
     后果是：Tab 到按钮时，按钮的圆角会从自己的值（8px / 药丸）跳到 6px——
     一个只发生在键盘用户身上、鼠标用户永远看不到的形状变化。
     描边本来就跟随元素自身的圆角，不需要也不该覆盖它。 */
}
html.app-shell body input:focus-visible,
html.app-shell body select:focus-visible,
html.app-shell body textarea:focus-visible { outline: none; }
html.app-shell body .toast { border-radius: var(--r-md); box-shadow: var(--shadow-2); }

/* --- 17.13 滚动条：细、淡、圆，避免系统灰条割裂版面 --- */
html.app-shell body,
html.app-shell body .table-wrap,
html.app-shell body .app-side nav,
html.app-shell body .global-ann-body,
html.app-shell body .editor,
html.app-shell body .modal-box {
  scrollbar-width: thin;
  scrollbar-color: var(--scroll-thumb) transparent;
}
html.app-shell body ::-webkit-scrollbar { width: 10px; height: 10px; }
html.app-shell body ::-webkit-scrollbar-track { background: transparent; }
html.app-shell body ::-webkit-scrollbar-thumb {
  background: var(--scroll-thumb);
  border: 3px solid transparent;
  background-clip: padding-box;
  border-radius: var(--r-pill);
}
html.app-shell body ::-webkit-scrollbar-thumb:hover { background: var(--scroll-thumb-hover); background-clip: padding-box; }
html.app-shell body ::-webkit-scrollbar-corner { background: transparent; }

/* --- 17.14 窄屏：顶栏不许溢出，登录表单靠上 --- */
@media (max-width: 760px) {
  html.app-shell body .app-chrome { gap: var(--sp-2); flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; }
  html.app-shell body .app-chrome::-webkit-scrollbar { display: none; }
  html.app-shell body .app-chrome .user-chip {
    min-width: 0;
    max-width: 40vw;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  html.app-shell body .app-chrome .btn { flex: none; }
  html.app-shell body .app-side nav { mask-image: linear-gradient(90deg, #000 calc(100% - 28px), transparent); }
  html.app-shell body .table-header, html.app-shell body table.data-table thead th { position: static; }
}
@media (max-width: 800px) {
  body:has(.login-box) .login-box { margin: 0 auto; padding-top: var(--sp-6); }
  body:has(.login-box) .remember-me input[type="checkbox"] { width: 18px; height: 18px; }
}
/* 中文不用 letter-spacing：11px 的拉丁字距套在汉字上是散架 */
html.app-shell body .login-side-foot { letter-spacing: 0.02em; }
html.app-shell body .app-nav-group { letter-spacing: 0.02em; }

/* ==========================================================================
   18. 数值列：金额右对齐 + 等宽数字
   列判定由 numeric-align.js 在渲染后按列采样完成（列数/列序均为动态，
   CSS 的 :nth-child 无法定位）。这里只描述「命中之后长什么样」。
   ========================================================================== */
html.app-shell body th.num,
html.app-shell body td.num {
  text-align: right;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}
/* 单元格里的行内元素跟着右对齐，否则 Bradley/strong 仍按左浮动 */
html.app-shell body td.num > * { text-align: right; }
/* 表头右对齐后要留出和正文一致的内边距观感：单位紧跟尾声不断行 */
html.app-shell body th.num { padding-right: var(--sp-4); }

/* 非表格位置的金额：明细行、合计、只读值 —— 对齐由布局决定，这里补等宽 */
html.app-shell body .pay-row strong,
html.app-shell body .pay-net,
html.app-shell body .claim-total,
html.app-shell body .readonly-field,
html.app-shell body .stat-value {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}
html.app-shell body .pay-row { align-items: baseline; }

/* 实发工资：强调行用淡底即可，不要边框（带边框会被读成一个输入框） */
html.app-shell body .pay-net {
  margin-top: var(--sp-3);
  padding: 10px 12px;
  border: 0;
  border-radius: var(--r-md);
  background: var(--brand-soft);
  color: var(--brand-hover);
  font-size: 14px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* ==========================================================================
   19. 工作台仪表盘组件（进度 / 构成柱 / 角标）
   ========================================================================== */

/* --- 19.1 假期余额进度条：一眼看「用了多少 / 还剩多少」 --- */
html.app-shell body .db-meter { display: flex; flex-direction: column; gap: 6px; }
html.app-shell body .db-meter + .db-meter { margin-top: var(--sp-3); }
html.app-shell body .db-meter-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-3);
  font-size: var(--fs-sm);
}
html.app-shell body .db-meter-label { color: var(--muted); }
html.app-shell body .db-meter-value {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
html.app-shell body .db-meter-value .db-of { font-weight: 400; color: var(--faint); font-size: 12px; }
html.app-shell body .db-meter-foot {
  font-size: 12px;
  line-height: 1.45;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
html.app-shell body .db-meter-foot .db-of { font-weight: 400; }
html.app-shell body .db-track {
  position: relative;
  height: var(--bar-h);
  border-radius: var(--r-pill);
  background: var(--track);
  overflow: hidden;
}
html.app-shell body .db-track.is-lg { height: var(--bar-h-lg); }
html.app-shell body .db-fill {
  height: 100%;
  border-radius: var(--r-pill);
  background: var(--brand);
  transition: width var(--dur) var(--ease);
}
/* 额度吃紧（≤20%）改用琥珀色，超期 airborne danger */
html.app-shell body .db-fill.is-low { background: #d97706; }
html.app-shell body .db-fill.is-out { background: var(--danger-fg); }
html.app-shell body .db-fill.is-carry { background: #7c8ea3; }

/* --- 19.2 薪资构成迷你柱：把「9 行数字」压成一根占比条 --- */
html.app-shell body .db-comp { display: flex; flex-direction: column; gap: 10px; }
html.app-shell body .db-comp-bar {
  display: flex;
  height: var(--bar-h-lg);
  border-radius: var(--r-pill);
  overflow: hidden;
  background: var(--track);
}
html.app-shell body .db-comp-seg { height: 100%; }
html.app-shell body .db-comp-seg.is-base { background: var(--brand); }
html.app-shell body .db-comp-seg.is-bonus { background: #4a9aa1; }
html.app-shell body .db-comp-seg.is-cut { background: #c2685f; }
html.app-shell body .db-comp-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 4px var(--sp-4);
  font-size: 12px;
  color: var(--muted);
}
html.app-shell body .db-comp-item { display: inline-flex; align-items: center; gap: 6px; }
html.app-shell body .db-dot { width: 8px; height: 8px; border-radius: var(--r-xs); flex: none; }
html.app-shell body .db-dot.is-base { background: var(--brand); }
html.app-shell body .db-dot.is-bonus { background: #4a9aa1; }
html.app-shell body .db-dot.is-cut { background: #c2685f; }
html.app-shell body .db-comp-amount { color: var(--ink-2); font-variant-numeric: tabular-nums; }

/* --- 19.3 待办角标：数量即脸面，放在 section-label 右侧 --- */
html.app-shell body .db-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  height: 20px;
  padding: 0 6px;
  margin-left: 2px;
  border-radius: var(--r-pill);
  background: var(--wash);
  color: var(--ink-2);
  font-size: var(--fs-micro);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
html.app-shell body .db-count.is-hot { background: var(--warn-bg); color: var(--warn-fg); border: 1px solid var(--warn-line); }
html.app-shell body .db-count.is-zero { background: transparent; color: var(--faint); }
/* section-label 里放角标时保持基线对齐 */
html.app-shell body .section-label { display: flex; align-items: center; gap: 6px; }

/* ==========================================================================
   20. 组件规范（Design System v1）
   --------------------------------------------------------------------------
   为什么要集中到这一个文件
     实测（Chrome 计算样式，10 页 × 全部标签页）发现：`.tab` / `.sub-tab` /
     `.glass` / `.panel` / `h3` `h4` / 表单 label / input 系列的规则**完全不在
     desktop.css 里**，而是分散写在 5 个页面的 <style> 中各写各的。结果是：
       · 按钮 16 种取值（高 15/18/19/26/30/32/40，圆角 0/4/6/8/12，字重 400…700）
       · 标题 10 种取值（14/15/16/17/19/24px，字重混用 600 与 700）
       · 卡片 7 种取值（圆角 0/8/12，内距 0/12/20/24/40，描边混用灰与品牌色）
     规范散在页面里 = 看起来「没经过设计」。这里一次性收口：
     desktop.css 最后加载 + html.app-shell body 前缀，覆盖各页旧规则，
     全程不使用 !important，不改任何业务逻辑。
   ========================================================================== */

/* --------------------------------------------------------------------------
   20.1 唯一尺寸阶梯
   控件只允许 3 档高度、3 档圆角、1 档字重。新增控件必须从这几档里选。
   -------------------------------------------------------------------------- */
html.app-shell body {
  --ui-h: 40px;          /* 标准：主按钮、表单输入、一级标签 */
  --ui-h-sm: 32px;       /* 小：工具条内、表格行内、次级标签 */
  --ui-h-xs: 26px;       /* 微型：分段控件、排序控件 */
  --ui-r: var(--r-md);   /* 8px：标准圆角 */
  --ui-r-sm: var(--r-sm);/* 6px：小圆角 */
  --ui-fw: 500;          /* 控件字重：全站唯一，600 只留给标题与「当前项」 */
  --ui-line: var(--line);/* 卡片/分组描边 */
}

/* --------------------------------------------------------------------------
   20.2 卡片 / 面板
   一张卡 = 白底 + 1px 灰线 + 8px 阴影 + 12px 圆角 + 24px 内距。
   页面标题区（.header）不是卡片：透明底、只有一条下边框线。
   -------------------------------------------------------------------------- */
html.app-shell body .glass:not(.header),
html.app-shell body .panel:not(.editor-toolbar),
html.app-shell body .card {
  box-sizing: border-box;
  background: var(--paper);
  border: 1px solid var(--ui-line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-1);
  padding: var(--sp-5);
}
/* 卡片内的次级块：退成浅底、无描边、无阴影 */
html.app-shell body .stat-box,
html.app-shell body .glass.stat-box,
html.app-shell body .notice-box:not(.warn):not(.info) {
  border: 1px solid transparent;
  box-shadow: none;
}
html.app-shell body .stat-box {
  background: var(--sunken);
  border-radius: var(--r-md);
  padding: var(--sp-3) var(--sp-4);
}
/* --------------------------------------------------------------------------
   20.3 标题阶梯（4 级，不多不少）
   h1 页面标题 / h2 卡片标题 / h3 区块标题 / 统计数字
   -------------------------------------------------------------------------- */
html.app-shell body h1 {
  font-size: var(--fs-xl); font-weight: 600; line-height: 1.3;
  color: var(--ink); letter-spacing: 0; margin: 0 0 2px;
}
html.app-shell body h2,
html.app-shell body .panel-title,
html.app-shell body .section-title {
  font-size: 15px; font-weight: 600; line-height: 1.4;
  color: var(--ink); letter-spacing: 0; margin: 0;
}
html.app-shell body h3,
html.app-shell body h4,
html.app-shell body .panel-title-sm,
html.app-shell body .subsection-title {
  font-size: 14px; font-weight: 600; line-height: 1.45;
  color: var(--ink-2); letter-spacing: 0; margin: 0;
}
/* jssalary 的分区标题曾用 17px / 16px，收进 15px 档 */
html.app-shell body #monthlyTitle,
html.app-shell body #bonusRecordsTitle,
html.app-shell body #manualDeductionTitle,
html.app-shell body #nplTitle,
html.app-shell body #prorationTitle,
html.app-shell body #ir56eTitle,
html.app-shell body #customReportGroupFilterLabel {
  font-size: 15px; font-weight: 600; color: var(--ink); line-height: 1.4;
}
/* 统计数字：全站只允许 ink 一种颜色（devices 曾出现 brand / warn / muted 三色） */
html.app-shell body .stat-value {
  font-size: 24px; font-weight: 600; line-height: 1.15;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}
html.app-shell body .stat-unit {
  font-size: 13px; font-weight: 500; color: var(--muted); margin-left: 3px;
}

/* --------------------------------------------------------------------------
   20.4 表单：标签与输入
   标签 = 12.5px / 500 / muted（说明性文字，不与正文抢层级）
   输入 = 40px 高、8px 圆角、1px 灰线、聚焦时墨青线 + 3px 柔光环
   -------------------------------------------------------------------------- */
html.app-shell body .field > label,
html.app-shell body .field-label,
html.app-shell body .stat-label,
html.app-shell body .section-label {
  display: flex; align-items: center; gap: 6px;
  font-size: var(--fs-sm); font-weight: 500; color: var(--muted);
  letter-spacing: 0; line-height: 1.4; margin-bottom: 5px;
}
html.app-shell body .desc,
html.app-shell body .panel-sub,
html.app-shell body .panel-subtitle {
  font-size: 13px; font-weight: 400; color: var(--muted); line-height: 1.5;
}

html.app-shell body input:not([type="checkbox"]):not([type="radio"]):not([type="file"]),
html.app-shell body select,
html.app-shell body textarea {
  box-sizing: border-box;
  width: 100%;
  height: var(--ui-h);
  min-height: var(--ui-h);
  padding: 0 var(--sp-3);
  font-family: inherit;
  font-size: 14px;
  line-height: 1.4;
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--line-strong);
  border-radius: var(--ui-r);
  appearance: none;
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease), background-color var(--dur) var(--ease);
}
html.app-shell body select {
  padding-right: 30px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%236b7280' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 11px center;
  cursor: pointer;
}
html.app-shell body textarea {
  height: auto;
  min-height: 96px;
  padding: var(--sp-2) var(--sp-3);
  line-height: 1.55;
  resize: vertical;
}
html.app-shell body input::placeholder,
html.app-shell body textarea::placeholder { color: var(--faint); }
html.app-shell body input:hover:not(:disabled),
html.app-shell body select:hover:not(:disabled),
html.app-shell body textarea:hover:not(:disabled) { border-color: var(--muted); }
html.app-shell body input:focus,
html.app-shell body select:focus,
html.app-shell body textarea:focus {
  outline: none;
  border-color: var(--brand);
  box-shadow: 0 0 0 3px var(--focus-ring);
}
html.app-shell body input:disabled,
html.app-shell body select:disabled,
html.app-shell body textarea:disabled {
  background: var(--sunken); color: var(--faint); cursor: not-allowed;
}
/* 工具条 / 表格工具条里的输入降一档，避免撑破 40px 高的条 */
html.app-shell body .toolbar input:not([type="checkbox"]):not([type="radio"]),
html.app-shell body .table-toolbar input:not([type="checkbox"]):not([type="radio"]),
html.app-shell body .toolbar select,
html.app-shell body .table-toolbar select,
html.app-shell body .month-bar select,
html.app-shell body .month-bar input:not([type="checkbox"]):not([type="radio"]),
html.app-shell body .context-bar-group select {
  height: var(--ui-h-sm); min-height: var(--ui-h-sm);
  font-size: 13px;
}
/* 文件选择：系统原生控件无法完全同化，只统一高度与焦点环 */
html.app-shell body input[type="file"] {
  box-sizing: border-box;
  height: var(--ui-h);
  font-size: 13px;
  color: var(--muted);
  font-family: inherit;
}
html.app-shell body input[type="file"]::file-selector-button {
  height: calc(var(--ui-h) - 2px);
  margin-right: var(--sp-3);
  padding: 0 var(--sp-4);
  font: inherit; font-size: 13px; font-weight: var(--ui-fw);
  color: var(--ink-2); background: var(--wash);
  border: 0; border-right: 1px solid var(--line-strong);
  border-radius: 0; cursor: pointer;
}
html.app-shell body input[type="checkbox"],
html.app-shell body input[type="radio"] {
  width: 16px; height: 16px; margin: 0;
  accent-color: var(--brand);
  cursor: pointer;
  vertical-align: -2px;
}

/* --------------------------------------------------------------------------
   20.5 按钮
   三档高度 × 字重固定 500。0 圆角、透明底、9px 字号一律视为偏差。
   -------------------------------------------------------------------------- */
html.app-shell body .btn {
  box-sizing: border-box;
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--sp-2);
  height: var(--ui-h); min-height: var(--ui-h); max-height: var(--ui-h);
  padding: 0 var(--sp-4);
  font-family: inherit;
  font-size: 14px; font-weight: var(--ui-fw); line-height: 1.2; letter-spacing: 0;
  color: var(--ink-2);
  background: var(--paper);
  border: 1px solid var(--line-strong);
  border-radius: var(--ui-r);
  box-shadow: none;
  cursor: pointer;
  white-space: nowrap;
  transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
html.app-shell body .btn-sm {
  height: var(--ui-h-sm); min-height: var(--ui-h-sm); max-height: var(--ui-h-sm);
  padding: 0 var(--sp-3);
  font-size: 13px;
  border-radius: var(--ui-r-sm);
}
html.app-shell body .btn-primary {
  background: var(--brand); color: var(--ink-invert); border-color: var(--brand);
  box-shadow: 0 1px 2px rgba(14, 107, 115, 0.18);
  transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
html.app-shell body .btn-primary:hover {
  background: var(--brand-hover); border-color: var(--brand-hover);
  box-shadow: 0 2px 8px var(--brand-glow);
}
html.app-shell body .btn-primary:active {
  box-shadow: 0 1px 2px rgba(14, 107, 115, 0.18);
}
html.app-shell body .btn-outline { background: var(--paper); color: var(--ink-2); border-color: var(--line-strong); }
html.app-shell body .btn-outline:hover { background: var(--wash); border-color: var(--muted); }
html.app-shell body .btn-danger { background: var(--paper); color: var(--danger-fg); border-color: var(--danger-line); }
html.app-shell body .btn-danger:hover { background: var(--danger-bg); }
/* 幽灵按钮：只用于低频次要动作（取消、返回、清空） */
html.app-shell body .btn-ghost {
  background: transparent; color: var(--ink-2); border-color: transparent;
}
html.app-shell body .btn-ghost:hover { background: var(--wash); color: var(--ink); }
html.app-shell body .btn:disabled,
html.app-shell body .btn[disabled] { opacity: 0.45; cursor: not-allowed; }

/* 行内文字型动作（员工姓名链接、表头排序）—— 之前是 18~19px 高、0 圆角，点不中 */
html.app-shell body .emp-link,
html.app-shell body .sort-header-btn {
  display: inline-flex; align-items: center; gap: 4px;
  height: auto; min-height: 24px;
  padding: 2px 6px;
  font-family: inherit;
  font-size: 13px; font-weight: var(--ui-fw); line-height: 1.4;
  color: var(--brand);
  background: transparent;
  border: 0; border-radius: var(--r-xs);
  cursor: pointer;
  transition: background-color var(--dur) var(--ease);
}
html.app-shell body .emp-link:hover,
html.app-shell body .sort-header-btn:hover { background: var(--brand-soft); }
html.app-shell body .sort-header-btn .sort-caret { font-size: var(--fs-micro); color: var(--faint); }
html.app-shell body .sort-header-btn.is-active { color: var(--brand); }
html.app-shell body .sort-header-btn.is-active .sort-caret { color: var(--brand); }

/* 排序手柄 ▲▼ —— 之前 15×9px，指针根本点不准 */
html.app-shell body .sortable-handle {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 22px; height: 20px;
  font-size: 12px; color: var(--faint);
  background: transparent; border: 0; border-radius: var(--r-xs);
  cursor: grab;
}
html.app-shell body .sortable-handle:hover { color: var(--ink-2); background: var(--wash); }
html.app-shell body .sort-sort-btns { display: inline-flex; gap: 2px; }
html.app-shell body .btn-sort {
  width: 22px; height: 20px; min-height: 20px; max-height: 20px;
  padding: 0; font-size: var(--fs-micro); line-height: 1; font-weight: 500;
  color: var(--muted); background: transparent;
  border: 1px solid var(--line); border-radius: var(--r-xs);
  box-shadow: none; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
}
html.app-shell body .btn-sort:hover:not(:disabled) { color: var(--brand); background: var(--brand-soft); border-color: var(--brand-line); }
html.app-shell body .btn-sort:disabled { opacity: 0.3; cursor: not-allowed; }

/* --------------------------------------------------------------------------
   20.6 一级标签
   高度与正文节奏对齐（40px），底部 2px 指示线压住容器边框，
   选中态才升到 600 —— 之前 hover 会让字重跳动。
   -------------------------------------------------------------------------- */
html.app-shell body .tabs {
  display: flex;
  gap: var(--sp-1);
  border-bottom: 1px solid var(--ui-line);
  margin-bottom: var(--sp-5);
  overflow-x: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
}
html.app-shell body .tabs::-webkit-scrollbar { display: none; }
html.app-shell body .tabs > .tab,
html.app-shell body .tabs > button {
  appearance: none;
  flex: none;
  box-sizing: border-box;
  height: var(--ui-h);
  min-height: var(--ui-h);
  max-height: var(--ui-h);
  padding: 0 var(--sp-4);
  margin-bottom: -1px;
  font-family: inherit;
  font-size: 14px; font-weight: 500; line-height: 1.2; letter-spacing: 0;
  color: var(--muted);
  background: transparent;
  border: 0;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  box-shadow: none;
  cursor: pointer;
  white-space: nowrap;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease), background-color var(--dur) var(--ease);
}
html.app-shell body .tabs > .tab:hover,
html.app-shell body .tabs > button:hover { color: var(--ink-2); background: var(--wash); }
html.app-shell body .tabs > .tab.active,
html.app-shell body .tabs > button.active {
  color: var(--brand);
  font-weight: 600;
  border-bottom-color: var(--brand);
  background: transparent;
}

/* --------------------------------------------------------------------------
   20.7 二级标签 = 分段控件
   浅底槽 + 白色滑块。与一级标签在形态上彻底分层（高度、圆角、底色全不同），
   之前两者长得几乎一样，层级读不出来。
   -------------------------------------------------------------------------- */
html.app-shell body .sub-tabs {
  display: inline-flex;
  gap: 2px;
  padding: 3px;
  background: var(--wash);
  border: 1px solid var(--ui-line);
  border-radius: var(--r-md);
  max-width: 100%;
  overflow-x: auto;
  scrollbar-width: none;
}
html.app-shell body .sub-tabs::-webkit-scrollbar { display: none; }
html.app-shell body .sub-tabs > .sub-tab,
html.app-shell body .sub-tabs > button {
  appearance: none;
  flex: none;
  box-sizing: border-box;
  height: var(--ui-h-xs);
  min-height: var(--ui-h-xs);
  max-height: var(--ui-h-xs);
  padding: 0 var(--sp-4);
  font-family: inherit;
  font-size: 13px; font-weight: 500; line-height: 1.2; letter-spacing: 0;
  color: var(--muted);
  background: transparent;
  border: 0; border-bottom: 0; border-radius: var(--r-sm);
  box-shadow: none;
  cursor: pointer;
  white-space: nowrap;
  transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
html.app-shell body .sub-tabs > .sub-tab:hover,
html.app-shell body .sub-tabs > button:hover { color: var(--ink-2); }
html.app-shell body .sub-tabs > .sub-tab.active,
html.app-shell body .sub-tabs > button.active {
  background: var(--paper);
  color: var(--brand);
  font-weight: 600;
  box-shadow: var(--shadow-1);
}

/* 20.7b 二级标签 + 返回/操作按钮同排（高度与分段控件对齐） */
html.app-shell body .subtabs-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-bottom: var(--sp-4);
  flex-wrap: wrap;
}
html.app-shell body .subtabs-toolbar .sub-tabs {
  margin-bottom: 0;
}
html.app-shell body .subtabs-toolbar > .btn.btn-sm {
  height: calc(var(--ui-h-xs) + 6px);
  min-height: calc(var(--ui-h-xs) + 6px);
}
html.app-shell body .detail-back-btn {
  margin-bottom: var(--sp-4);
}

/* --------------------------------------------------------------------------
   20.8 状态标签 / 徽章
   高度 22px、pill 圆角、12px/500。背景一律取语义色变量，不写死 rgba。
   -------------------------------------------------------------------------- */
html.app-shell body .status-pill,
html.app-shell body .badge,
html.app-shell body .name-badge,
html.app-shell body .perm-pill {
  display: inline-flex; align-items: center; gap: 4px;
  height: 22px; padding: 0 9px;
  font-size: 12px; font-weight: 500; line-height: 1;
  border-radius: var(--r-pill);
  border: 1px solid transparent;
  white-space: nowrap;
}
html.app-shell body .user-chip {
  display: inline-flex; align-items: center;
  height: var(--ui-h-sm); padding: 0 var(--sp-3);
  font-size: 13px; font-weight: 500; color: var(--ink-2);
  background: var(--wash);
  border: 1px solid var(--ui-line);
  border-radius: var(--r-sm);
  white-space: nowrap;
}

/* --------------------------------------------------------------------------
   20.9 语言切换器：三个等宽分段，当前项用白底 + 墨青字
   -------------------------------------------------------------------------- */
html.app-shell body .lang-switch {
  display: inline-flex; gap: 2px; padding: 3px;
  background: var(--wash);
  border: 1px solid var(--ui-line);
  border-radius: var(--r-md);
}
html.app-shell body .lang-switch button {
  appearance: none;
  height: 26px; padding: 0 10px;
  font-family: inherit; font-size: var(--fs-sm); font-weight: 500; line-height: 1;
  color: var(--muted);
  background: transparent; border: 0; border-radius: var(--r-sm);
  cursor: pointer; white-space: nowrap;
  transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
html.app-shell body .lang-switch button:hover { color: var(--ink-2); }
html.app-shell body .lang-switch button.active {
  background: var(--paper); color: var(--brand); font-weight: 600;
  box-shadow: var(--shadow-1);
}

/* --------------------------------------------------------------------------
   20.10 空态：图标位 + 一句主因 + 一句去处
   -------------------------------------------------------------------------- */
html.app-shell body .empty,
html.app-shell body .empty-state {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 6px;
  padding: var(--sp-6) var(--sp-4);
  text-align: center;
  font-size: 13px; line-height: 1.6; color: var(--muted);
  background: transparent;
  border: 1px dashed var(--line-strong);
  border-radius: var(--r-md);
}
html.app-shell body .empty strong,
html.app-shell body .empty-title {
  display: block;
  font-size: 14px; font-weight: 600; color: var(--ink-2);
}

/* --------------------------------------------------------------------------
   21. 布局类统一
   这些容器（筛选条 / 统计行 / 工具条 / 表单网格）此前由各页自行定义列数与
   宽度，导致同一控件在不同页面被拉成完全不同的宽度。这里定死栅格。
   -------------------------------------------------------------------------- */

/* 筛选条：搜索框吃掉剩余空间，筛选项定宽，按钮贴右 */
html.app-shell body .filter-bar,
html.app-shell body .filters {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-3);
  margin-bottom: var(--sp-4);
}
html.app-shell body .filter-bar > input[type="text"],
html.app-shell body .filter-bar > input:not([type]),
html.app-shell body .filter-bar > .search-field {
  flex: 1 1 240px;
  min-width: 200px;
  max-width: 420px;
}
html.app-shell body .filter-bar > select,
html.app-shell body .filter-bar > .btn { flex: 0 0 auto; width: auto; min-width: 150px; }
html.app-shell body .filter-bar > .btn { min-width: 0; }

/* 月份/期间工具条：控件定宽，不再拉满整行 */
html.app-shell body .month-bar {
  display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap;
  min-height: 72px;
}
html.app-shell body .month-bar .context-bar-group {
  display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; width: 100%; min-height: 40px;
}
html.app-shell body .month-bar .context-bar-note { font-size: 13px; color: var(--muted); }
html.app-shell body .month-bar.is-month-disabled select,
html.app-shell body .month-bar.is-month-disabled .btn-sm { opacity: 0.45; pointer-events: none; }
html.app-shell body .month-bar select,
html.app-shell body .month-bar input { width: auto; min-width: 170px; max-width: 220px; }
html.app-shell body .month-bar > .btn { width: auto; }

/* 统计卡行：统一四列/三列，卡内留白一致 */
html.app-shell body .stats-grid,
html.app-shell body .stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--sp-3);
  margin-bottom: var(--sp-5);
}
html.app-shell body .stats-grid > *,
html.app-shell body .stat-grid > * { min-width: 0; }
@media (max-width: 760px) {
  html.app-shell body .stats-grid,
  html.app-shell body .stat-grid { grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); }
}

/* 表单网格：统一两列，控件不越出版心 */
html.app-shell body .form-grid,
html.app-shell body .two-col {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--sp-4);
  max-width: var(--measure-form);
}
html.app-shell body .form-field { min-width: 0; }
html.app-shell body .form-field.full,
html.app-shell body .field-full,
html.app-shell body .form-grid > .full { grid-column: 1 / -1; }
@media (max-width: 720px) {
  html.app-shell body .form-grid,
  html.app-shell body .two-col { grid-template-columns: 1fr; }
}

/* 表格行内输入/选择：定宽，绝不撑高行高 */
html.app-shell body table.data-table td input:not([type="checkbox"]):not([type="radio"]),
html.app-shell body table.data-table td select {
  width: 100%;
  min-width: 90px;
  max-width: 180px;
  height: var(--ui-h-sm);
  min-height: var(--ui-h-sm);
  font-size: 13px;
}

/* 排序手柄：⠿ 太淡看不见，加一层浅底让它在白纸上成立 */
html.app-shell body .sort-controls {
  display: inline-flex; align-items: center; gap: 4px;
}
html.app-shell body .sort-col { width: 1%; white-space: nowrap; }
html.app-shell body th .sortable-handle { color: var(--muted); background: var(--wash); }
html.app-shell body th .sortable-handle:hover { color: var(--ink-2); background: var(--wash); }

/* 二级标签底槽：wash 太淡，加深一档让「分段」这件事看得出来 */
html.app-shell body .sub-tabs { background: var(--track); }

/* ==========================================================================
   22. 登录页
   --------------------------------------------------------------------------
   沿用「左深墙 / 右白纸」的对切结构（已确认的骨架），此处只补完成度：
     · 错误提示从「裸文字」变成真正的告警条，并预留槽位避免顶动布局
     · 密码框加显示/隐藏切换
     · 按钮加 loading 指示，按钮高度与内页统一为 40px
     · 左墙加模块清单，让访客一眼知道这套系统管什么
     · 台面从死平色改为极淡双向渐变，让卡片浮起来（不画网格、不加纹理）
   ========================================================================== */

/* 台面：中心略亮、四角略沉，单一光源，脏不了 */
body:has(.login-box) {
  background-color: var(--canvas);
  background-image:
    radial-gradient(120% 90% at 50% 0%, rgba(255, 255, 255, 0.85) 0%, rgba(255, 255, 255, 0) 58%),
    radial-gradient(100% 80% at 50% 100%, rgba(17, 24, 39, 0.045) 0%, rgba(17, 24, 39, 0) 62%);
}

/* --- 22.1 左墙模块清单 --- */
/* 品牌组 + 模块清单作为一整块垂直居中，页脚贴底；
   之前两者各自 margin:auto，被空白割成两块。 */
.login-side-main { margin: auto 0; }
.login-modules {
  list-style: none;
  margin: var(--sp-6) 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}
/* 每条模块 = 一块图标 + 一句话。
   原来是 5px 的圆点，读起来像「未加载完的列表」，而且 4 行只有 106px，
   换来左墙 216px 的空白。换成 28px 图标块后，同样 4 条信息撑起 196px，
   空的那部分被信息吃掉，不是被装饰吃掉。 */
.login-module {
  display: flex; align-items: center; gap: 10px;
  font-size: var(--fs-base); line-height: 1.35;
  color: var(--deep-ink);
}
.login-module-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; flex: none;
  border: 1px solid var(--deep-line);
  border-radius: var(--r-sm);
  background: rgba(255, 255, 255, 0.06);
  color: var(--deep-accent);
}
/* 中文不能加 letter-spacing：0.06em 的拉丁字距套在汉字上是散架。
   仅英文语境用 uppercase + 字距。 */
:lang(en) .login-side-foot { letter-spacing: 0.06em; text-transform: uppercase; }

/* --- 22.2 品牌锚点：24×3 的墨青短线 --- */
.login-box .login-header::before {
  width: 24px; height: 3px; border-radius: 2px;
  background: var(--brand);
  margin-bottom: var(--sp-4);
}

/* --- 22.3 输入：文字用 --ink（原为系统纯黑），聚焦环与内页一致 --- */
.login-box .form-group input { color: var(--ink); }
.login-box .form-group input:-webkit-autofill {
  -webkit-text-fill-color: var(--ink);
  -webkit-box-shadow: 0 0 0 40px var(--paper) inset;
  caret-color: var(--ink);
}

/* --- 22.4 记住我：自绘勾选框 --- */
.remember-me input[type="checkbox"] {
  appearance: none;
  width: 16px; height: 16px; flex: none;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-xs);
  background: var(--paper);
  cursor: pointer;
  position: relative;
  transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.remember-me input[type="checkbox"]:hover { border-color: var(--muted); }
.remember-me input[type="checkbox"]:checked {
  background: var(--brand);
  border-color: var(--brand);
}
.remember-me input[type="checkbox"]:checked::after {
  content: "";
  position: absolute;
  left: 5px; top: 1.5px;
  width: 4px; height: 8px;
  border: solid #fff;
  border-width: 0 1.8px 1.8px 0;
  transform: rotate(43deg);
}
.remember-me input[type="checkbox"]:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--focus-ring);
}

/* --- 22.5 主按钮：40px 与内页同高，带 spinner --- */
.btn-login {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  width: 100%;
  height: 40px; min-height: 40px;
  padding: 0 var(--sp-4);
  font-family: inherit;
  font-size: 14px; font-weight: 500; line-height: 1.2; letter-spacing: 0;
  color: var(--ink-invert);
  background: var(--brand);
  border: 1px solid var(--brand);
  border-radius: var(--r-md);
  box-shadow: none;
  cursor: pointer;
  transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.btn-login:hover:not(:disabled) { background: var(--brand-hover); border-color: var(--brand-hover); }
.btn-login:active:not(:disabled) { background: var(--brand-hover); }
.btn-login:disabled { cursor: progress; opacity: 0.9; }
.btn-spinner {
  display: none;
  width: 13px; height: 13px; flex: none;
  border: 2px solid rgba(255, 255, 255, 0.35);
  border-top-color: #fff;
  border-radius: var(--r-pill);
  animation: ui-spin 0.6s linear infinite;
}
.btn-login.is-loading .btn-spinner { display: block; }
@keyframes ui-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .btn-spinner { animation-duration: 2s; }
}

/* --- 22.6 页脚注：把「演示账号」提示从顶部横幅降级到一行低调说明 --- */
.login-footnote {
  margin: var(--sp-5) 0 0;
  padding-top: var(--sp-4);
  border-top: 1px solid var(--line-soft);
  font-size: 12px;
  line-height: 1.6;
  color: var(--faint);
}

/* --- 22.7 移动端：左墙压成一条，模块清单收起 --- */
@media (max-width: 860px) {
  .login-modules { display: none; }
  .login-box .login-header::before { margin-bottom: var(--sp-3); }
  .login-footnote { margin-top: var(--sp-4); }
}

/* ==========================================================================
   24. 窄屏适配（≤760px）
   --------------------------------------------------------------------------
   实测 390px 下的三处硬伤：
     ① 顶栏一行塞不下「返回 / 语言 / 用户名 / 退出」，退出按钮被推出屏幕
        → 移动端隐藏用户名（侧边栏已有身份信息），只留三个可点动作
     ② 侧边栏变顶部横条后导航项溢出，视口外还有 4 项点不到
        → 给 nav 加横向滚动
     ③ 告警条里的长中文串在窄屏被裁掉
        → 允许任意位置断行
   ========================================================================== */
@media (max-width: 760px) {
  /* ① 顶栏 */
  html.app-shell body .app-chrome .user-chip { display: none; }
  html.app-shell body .app-chrome { justify-content: space-between; }

  /* ② 侧边栏横条 */
  html.app-shell body .app-side nav {
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  html.app-shell body .app-side nav::-webkit-scrollbar { display: none; }
  html.app-shell body .app-nav-item { flex: none; }

  /* ③ 长文本断行 */
  html.app-shell body .notice-box,
  html.app-shell body .mini-item,
  html.app-shell body .db-meter-head { overflow-wrap: anywhere; }

  /* 表格横向滚动兜底 */
  html.app-shell body .table-wrap,
  html.app-shell body .device-table { -webkit-overflow-scrolling: touch; }

  /* 原生日期选择器图标是深黑的，与整体墨青语言不搭：淡化 + 去色，hover 恢复 */
  html.app-shell body input[type="date"]::-webkit-calendar-picker-indicator,
  html.app-shell body input[type="datetime-local"]::-webkit-calendar-picker-indicator,
  html.app-shell body input[type="month"]::-webkit-calendar-picker-indicator {
    opacity: 0.4;
    filter: grayscale(1);
    cursor: pointer;
    transition: opacity var(--dur) var(--ease);
  }
  html.app-shell body input[type="date"]:hover::-webkit-calendar-picker-indicator,
  html.app-shell body input[type="datetime-local"]:hover::-webkit-calendar-picker-indicator,
  html.app-shell body input[type="month"]:hover::-webkit-calendar-picker-indicator { opacity: 0.75; }
}

/* ==========================================================================
   25. 审批流配置界面（按人配置）
   --------------------------------------------------------------------------
   组件类名统一 ap- 前缀；配色全部走令牌，与全站同一套语言。
   卡片 / 表格 / 分段标签沿用第 20 节的规范，这里只补新组件。
   ========================================================================== */
html.app-shell body .ap-wrap { display: flex; flex-direction: column; gap: var(--sp-5); }

html.app-shell body .ap-head { display: flex; flex-direction: column; gap: var(--sp-1); }
html.app-shell body .ap-head > .ap-tag { align-self: flex-start; }
html.app-shell body .ap-title { font-size: 17px; font-weight: 600; line-height: 1.3; margin: 0; color: var(--ink); }
html.app-shell body .ap-sub {
  font-size: var(--fs-sm); line-height: 1.6; color: var(--muted); margin: 0; max-width: 76ch;
}

/* --- 单据类型分段标签（只在多模块时出现） --- */
html.app-shell body .ap-mtabs {
  display: flex; gap: 2px; margin-top: var(--sp-3);
  padding: 3px; width: fit-content; max-width: 100%; overflow-x: auto;
  background: var(--track); border: 1px solid var(--line); border-radius: var(--r-md);
  scrollbar-width: none;
}
html.app-shell body .ap-mtabs::-webkit-scrollbar { display: none; }
html.app-shell body .ap-mtab {
  appearance: none; flex: none; box-sizing: border-box;
  height: var(--ctl-h-xs); padding: 0 var(--sp-4);
  font-family: inherit; font-size: 13px; font-weight: 500; line-height: 1;
  color: var(--muted); background: transparent; border: 0; border-radius: var(--r-sm);
  cursor: pointer; white-space: nowrap;
  transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease);
}
html.app-shell body .ap-mtab:hover { color: var(--ink-2); }
html.app-shell body .ap-mtab.active {
  background: var(--paper); color: var(--brand); font-weight: 600; box-shadow: var(--shadow-1);
}

/* --- 卡片 --- */
html.app-shell body .ap-card {
  padding: var(--sp-4) var(--sp-5);
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-1);
}
html.app-shell body .ap-card-title { font-size: 14px; font-weight: 600; line-height: 1.3; margin: 0; color: var(--ink); }
html.app-shell body .ap-card-sub { font-size: var(--fs-sm); color: var(--muted); margin: 4px 0 var(--sp-3); }

/* --- 审批流一览（流程图） --- */
html.app-shell body .ap-flow-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: var(--sp-4); flex-wrap: wrap;
}
html.app-shell body .ap-flow-head-main { min-width: 0; flex: 1 1 280px; }
html.app-shell body .ap-flow-head .ap-card-sub { margin-bottom: 0; }
html.app-shell body .ap-flow-pick {
  display: flex; align-items: center; gap: var(--sp-2); flex: 0 0 auto;
}
html.app-shell body .ap-flow-pick label { font-size: var(--fs-sm); color: var(--muted); }
html.app-shell body .ap-flow-pick select {
  box-sizing: border-box; flex: 0 0 auto; width: 214px; min-width: 214px;
  height: var(--ctl-h-sm); padding: 0 var(--sp-2);
  font-family: inherit; font-size: 13px; color: var(--ink);
  background: var(--paper); border: 1px solid var(--line-strong); border-radius: var(--r-sm);
}
html.app-shell body .ap-flow-pick select:focus {
  outline: none; border-color: var(--brand); box-shadow: 0 0 0 3px var(--focus-ring);
}

html.app-shell body .ap-flow-body {
  margin-top: var(--sp-3); padding: var(--sp-3) var(--sp-4);
  background: var(--sunken); border: 1px solid var(--line-soft); border-radius: var(--r-md);
}
/* 卡片已经提供了外框，流程图自身不再画第二层框 */
html.app-shell body .ap-flow-body .flow-chart,
html.app-shell body .ap-editor-preview .flow-chart {
  margin: 0; padding: 0; border: 0; background: transparent;
}
html.app-shell body .ap-flow-body .flow-chart-title,
html.app-shell body .ap-editor-preview .flow-chart-title { display: none; }
html.app-shell body .ap-flow-body .flow-chart-empty,
html.app-shell body .ap-editor-preview .flow-chart-empty {
  padding: 0; border: 0; background: transparent; text-align: left;
}

/* 流程图里的异常标记 */
html.app-shell body .flow-node-rule.ap-flow-bad { color: var(--danger-fg); font-weight: 600; }
html.app-shell body .flow-person-mark.ap-flow-missing { color: var(--danger-fg); }
html.app-shell body .flow-person.is-empty .flow-person-name { color: var(--faint); font-weight: 500; }

html.app-shell body .ap-flow-empty { padding: var(--sp-3) 0; text-align: center; }
html.app-shell body .ap-flow-empty-title { font-size: 13px; font-weight: 600; color: var(--ink-2); }
html.app-shell body .ap-flow-empty-hint { margin-top: 4px; font-size: var(--fs-sm); color: var(--muted); }

html.app-shell body .ap-flow-foot {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-3); flex-wrap: wrap; margin-top: var(--sp-3);
}
html.app-shell body .ap-flow-actions { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
html.app-shell body .ap-flow-actions > .btn { flex: 0 0 auto; width: auto; }

/* 编辑器里的实时预览 */
html.app-shell body .ap-editor-preview {
  padding: var(--sp-3) var(--sp-4);
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-md);
}

html.app-shell body .ap-chain-text { font-size: 13px; color: var(--ink-2); line-height: 1.5; }
html.app-shell body .ap-chain-default { font-size: var(--fs-sm); color: var(--muted); }
html.app-shell body .ap-chain-bad {
  font-size: var(--fs-sm); font-weight: 500; color: var(--danger-fg);
  padding: 2px 8px; background: var(--danger-bg);
  border: 1px solid var(--danger-line); border-radius: var(--r-pill);
}

/* --- 编辑器 --- */
html.app-shell body .ap-editor {
  padding: var(--sp-4) var(--sp-5);
  background: var(--sunken);
  border: 1px solid var(--brand-line); border-radius: var(--r-lg);
  display: flex; flex-direction: column; gap: var(--sp-3);
}
html.app-shell body .ap-editor-head { display: flex; align-items: baseline; gap: var(--sp-3); flex-wrap: wrap; }
html.app-shell body .ap-editor-head strong { font-size: 14px; font-weight: 600; color: var(--ink); }
html.app-shell body .ap-hint { font-size: 12px; color: var(--muted); }
html.app-shell body .ap-editor-foot { display: flex; gap: var(--sp-2); flex-wrap: wrap; }

html.app-shell body .ap-layer {
  padding: var(--sp-3) var(--sp-4);
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-md);
  display: flex; flex-direction: column; gap: var(--sp-2);
}
html.app-shell body .ap-layer-title {
  font-size: 12px; font-weight: 600; color: var(--muted);
  letter-spacing: 0.02em; text-transform: none;
}
html.app-shell body .ap-layer-foot { display: flex; gap: var(--sp-2); flex-wrap: wrap; }
/* 列向 flex 会把 inline-flex 的按钮拉满整行，逐个收回 */
html.app-shell body .ap-editor > .btn,
html.app-shell body .ap-layer-foot > .btn,
html.app-shell body .ap-editor-foot > .btn { align-self: flex-start; flex: 0 0 auto; width: auto; }
html.app-shell body .ap-editor .ap-check { flex: 0 0 auto; }

html.app-shell body .ap-approver {
  display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap;
}
html.app-shell body .ap-approver select {
  /* 页面里普遍有 `.leave-main select { width:100% }` 这类规则，这里必须显式收回宽度，
     否则编辑器里的下拉框会被拉满整行。 */
  box-sizing: border-box;
  flex: 0 0 auto;
  width: 178px; min-width: 178px;
  height: var(--ctl-h-sm); font-family: inherit; font-size: 13px;
  color: var(--ink); background: var(--paper);
  border: 1px solid var(--line-strong); border-radius: var(--r-sm);
  padding: 0 var(--sp-2);
}
html.app-shell body .ap-approver select:focus {
  outline: none; border-color: var(--brand); box-shadow: 0 0 0 3px var(--focus-ring);
}
html.app-shell body .ap-approver select[data-ap="role"] { width: 190px; min-width: 190px; }

html.app-shell body .ap-check {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: var(--fs-sm); color: var(--ink-2); cursor: pointer; user-select: none;
}
html.app-shell body .ap-check input[type="checkbox"] { width: 15px; height: 15px; margin: 0; accent-color: var(--brand); }
html.app-shell body .ap-check input:disabled { opacity: 0.45; cursor: not-allowed; }

html.app-shell body .ap-icon-btn {
  appearance: none; box-sizing: border-box;
  height: var(--ctl-h-sm); padding: 0 10px;
  font-family: inherit; font-size: var(--fs-sm); line-height: 1;
  color: var(--muted); background: transparent;
  border: 1px solid transparent; border-radius: var(--r-sm);
  cursor: pointer;
  transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}
html.app-shell body .ap-icon-btn:hover { background: var(--wash); color: var(--ink-2); border-color: var(--line); }

html.app-shell body .ap-empty {
  padding: var(--sp-4); text-align: center;
  font-size: var(--fs-sm); color: var(--faint);
  border: 1px dashed var(--line-strong); border-radius: var(--r-sm);
}
html.app-shell body .ap-error {
  padding: var(--sp-2) var(--sp-3);
  font-size: var(--fs-sm); color: var(--danger-fg);
  background: var(--danger-bg); border: 1px solid var(--danger-line); border-radius: var(--r-sm);
}
html.app-shell body .ap-notice {
  margin-top: var(--sp-3); padding: var(--sp-2) var(--sp-3);
  font-size: var(--fs-sm); color: var(--ok-fg);
  background: var(--ok-bg); border: 1px solid var(--ok-line); border-radius: var(--r-sm);
}

/* --- 工具条 --- */
html.app-shell body .ap-toolbar {
  display: flex; align-items: center; gap: var(--sp-2);
  flex-wrap: wrap; margin: var(--sp-3) 0;
}
html.app-shell body .ap-search {
  box-sizing: border-box; height: var(--ctl-h-sm); width: auto; min-width: 180px; flex: 0 1 240px;
  padding: 0 var(--sp-3);
  font-family: inherit; font-size: 13px; color: var(--ink);
  background: var(--paper); border: 1px solid var(--line-strong); border-radius: var(--r-sm);
}
html.app-shell body .ap-search:focus {
  outline: none; border-color: var(--brand); box-shadow: 0 0 0 3px var(--focus-ring);
}

/* --- 表格 --- */
html.app-shell body .ap-table {
  border: 1px solid var(--line); border-radius: var(--r-md);
  overflow: hidden; background: var(--paper);
}
html.app-shell body .ap-row {
  display: grid; grid-template-columns: 168px 128px 1fr 156px;
  align-items: center; gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-4);
  border-top: 1px solid var(--line-soft);
}
html.app-shell body .ap-row:first-child { border-top: 0; }
html.app-shell body .ap-row.is-inactive { opacity: 0.5; }
html.app-shell body .ap-row-head {
  background: var(--sunken);
  font-size: var(--fs-micro); font-weight: 600; color: var(--muted); letter-spacing: 0.02em;
}
html.app-shell body .ap-row[data-act] { cursor: pointer; }
html.app-shell body .ap-row:not(.ap-row-head):hover { background: var(--sunken); }
html.app-shell body .ap-row.is-selected {
  background: var(--brand-soft);
  box-shadow: inset 3px 0 0 var(--brand);
}
html.app-shell body .ap-cell { min-width: 0; font-size: 13px; color: var(--ink-2); }
html.app-shell body .ap-cell-emp { font-weight: 500; color: var(--ink); }
html.app-shell body .ap-cell-dept { color: var(--muted); font-size: var(--fs-sm); }
html.app-shell body .ap-cell-chain { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
html.app-shell body .ap-cell-act {
  display: flex; justify-content: flex-end; gap: 6px; flex-wrap: wrap;
}
html.app-shell body .ap-cell-act > .btn { flex: 0 0 auto; width: auto; }

/* 总览用的宽表：姓名 + 部门 + N 类单据 */
html.app-shell body .ap-table-wide { overflow-x: auto; }
html.app-shell body .ap-table-wide .ap-row { min-width: 720px; }
html.app-shell body .ap-grid-5 .ap-row { grid-template-columns: 150px 110px repeat(5, minmax(150px, 1fr)); }
html.app-shell body .ap-cell-mod { font-size: var(--fs-sm); line-height: 1.5; }

html.app-shell body .ap-tag {
  display: inline-block; padding: 1px 7px;
  font-size: 11px; font-weight: 500; line-height: 1.6;
  color: var(--pill-fg); background: var(--pill-bg);
  border: 1px solid var(--pill-line); border-radius: var(--r-pill);
  white-space: nowrap;
}
html.app-shell body .ap-flag {
  display: inline-block; padding: 1px 7px;
  font-size: 11px; line-height: 1.6; color: var(--warn-fg);
  background: var(--warn-bg); border: 1px solid var(--warn-line); border-radius: var(--r-pill);
}
html.app-shell body .ap-flag-bad {
  color: var(--danger-fg); background: var(--danger-bg); border-color: var(--danger-line);
}

/* --- 批量工具面板 --- */
html.app-shell body .ap-panel {
  margin-top: var(--sp-3); padding: var(--sp-3) var(--sp-4);
  background: var(--sunken); border: 1px solid var(--line); border-radius: var(--r-md);
}
html.app-shell body .ap-panel-head { font-size: var(--fs-sm); font-weight: 600; color: var(--ink-2); margin-bottom: var(--sp-2); }
html.app-shell body .ap-panel-row { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
html.app-shell body .ap-panel-row span { font-size: var(--fs-sm); color: var(--muted); }
html.app-shell body .ap-panel select {
  box-sizing: border-box; flex: 0 0 auto; width: 178px; min-width: 178px;
  height: var(--ctl-h-sm); padding: 0 var(--sp-2);
  font-family: inherit; font-size: 13px; color: var(--ink);
  background: var(--paper); border: 1px solid var(--line-strong); border-radius: var(--r-sm);
}
html.app-shell body .ap-panel > .btn { align-self: flex-start; width: auto; }
html.app-shell body .ap-copy-targets {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: var(--sp-2); margin: var(--sp-3) 0;
  max-height: 220px; overflow-y: auto;
  padding: var(--sp-3); background: var(--paper);
  border: 1px solid var(--line-soft); border-radius: var(--r-sm);
}

/* --- 自检结果 --- */
html.app-shell body .ap-audit-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
html.app-shell body .ap-audit-list li {
  padding: var(--sp-2) var(--sp-3);
  font-size: var(--fs-sm); line-height: 1.5;
  border: 1px solid var(--line-soft); border-radius: var(--r-sm);
  background: var(--paper); color: var(--ink-2);
}
html.app-shell body .ap-audit-list li b { font-weight: 600; color: var(--ink); }
html.app-shell body .ap-audit-error {
  background: var(--danger-bg); border-color: var(--danger-line); color: var(--danger-fg);
}
html.app-shell body .ap-audit-warn {
  background: var(--warn-bg); border-color: var(--warn-line); color: var(--warn-fg);
}

@media (max-width: 900px) {
  html.app-shell body .ap-row { grid-template-columns: 130px 1fr; grid-auto-rows: auto; }
  html.app-shell body .ap-cell-chain { grid-column: 1 / -1; }
  html.app-shell body .ap-cell-act { grid-column: 1 / -1; text-align: left; }
  html.app-shell body .ap-row-head { display: none; }
}

/* ==========================================================================
   23. 页面私有「第二套」组件收编
   --------------------------------------------------------------------------
   审计还剩 4 处页面自带的平行组件，它们绕过了第 20 节的规范：
     · devices 的 .stat-card 四色数字（inUse 墨青 / inStock 琥珀 / retired 灰）
     · jssalary 的 .tax-subtab（12px / 700 字重 / 12px 圆角 / 半透明底）
     · jssalary 的 file input（无描边、无圆角，裸系统控件）
     · jssalary 某面板 40px 内距
   这里把它们并回主规范。
   ========================================================================== */

/* --- 23.1 统计数字：全站只用 ink 一种颜色 ---
   四个数字用四种颜色是「彩虹统计卡」，看着热闹但没有信息量。
   状态区分改由标签前的状态点承担，数字本身保持中性。 */
html.app-shell body .stat-value,
html.app-shell body .stat-card .stat-value,
html.app-shell body .stat-card.inUse .stat-value,
html.app-shell body .stat-card.inStock .stat-value,
html.app-shell body .stat-card.retired .stat-value {
  font-size: 24px;
  font-weight: 600;
  line-height: 1.15;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}
html.app-shell body .stat-card { padding: var(--sp-4) var(--sp-5); }
html.app-shell body .stat-card .stat-label { position: relative; padding-left: 12px; }
html.app-shell body .stat-card .stat-label::before {
  content: "";
  position: absolute; left: 0; top: 50%;
  width: 6px; height: 6px; margin-top: -3px;
  border-radius: var(--r-pill);
  background: var(--faint);
}
html.app-shell body .stat-card.inUse .stat-label::before { background: var(--brand); }
html.app-shell body .stat-card.inStock .stat-label::before { background: #d97706; }
html.app-shell body .stat-card.retired .stat-label::before { background: var(--faint); }

/* --- 23.2 报税子标签：并入二级标签语言（分段控件） --- */
html.app-shell body .tax-subtabs {
  display: inline-flex;
  gap: 2px;
  padding: 3px;
  background: var(--track);
  border: 1px solid var(--ui-line);
  border-radius: var(--r-md);
  margin-bottom: var(--sp-4);
  max-width: 100%;
  overflow-x: auto;
  scrollbar-width: none;
}
html.app-shell body .tax-subtabs::-webkit-scrollbar { display: none; }
html.app-shell body .tax-subtab {
  appearance: none;
  flex: none;
  box-sizing: border-box;
  height: var(--ui-h-xs);
  min-height: var(--ui-h-xs);
  max-height: var(--ui-h-xs);
  padding: 0 var(--sp-4);
  font-family: inherit;
  font-size: 13px; font-weight: 500; line-height: 1.2; letter-spacing: 0;
  color: var(--muted);
  background: transparent;
  border: 0; border-radius: var(--r-sm);
  box-shadow: none;
  cursor: pointer;
  white-space: nowrap;
  transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
html.app-shell body .tax-subtab:hover { color: var(--ink-2); }
html.app-shell body .tax-subtab.active {
  background: var(--paper);
  color: var(--brand);
  font-weight: 600;
  box-shadow: var(--shadow-1);
}

/* --- 23.3 文件选择：给原生控件一个像样的壳（附件槽内用 .upload-file-input 视觉隐藏，不在此规则内） --- */
html.app-shell body input[type="file"]:not(.upload-file-input) {
  box-sizing: border-box;
  width: 100%;
  height: auto;
  min-height: 40px;
  padding: 8px 10px;
  font-family: inherit;
  font-size: 13px;
  color: var(--muted);
  background: var(--sunken);
  border: 1px dashed var(--line-strong);
  border-radius: var(--r-md);
  cursor: pointer;
}
html.app-shell body input[type="file"]:hover { border-color: var(--muted); }
html.app-shell body input[type="file"]::file-selector-button {
  height: 24px;
  margin-right: 10px;
  padding: 0 10px;
  font: inherit; font-size: var(--fs-sm); font-weight: 500;
  color: var(--ink-2);
  background: var(--paper);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-xs);
  cursor: pointer;
  transition: background-color var(--dur) var(--ease);
}
html.app-shell body input[type="file"]::file-selector-button:hover { background: var(--wash); }

/* --- 23.4 面板内距兜底：任何 .panel 都不允许出现第四种内距 --- */
html.app-shell body .panel:not(.editor-toolbar),
html.app-shell body .glass.panel {
  padding: var(--sp-5);
  border-radius: var(--r-lg);
  border: 1px solid var(--ui-line);
  background: var(--paper);
  box-shadow: var(--shadow-1);
}

/* ==========================================================================
   24. 细节打磨（第四轮 · 2026-10-04）
   --------------------------------------------------------------------------
   这一节只做收口，不引入新组件。目标是把「说不出哪里不对」的东西变成确定的规则：
     24.1  浏览器默认小字（<small> 的 0.8333em）回到刻度
     24.2  占位文字：2.5:1 → 3.4:1
     24.3  内容性弱文字一律补到 4.5:1 以上
     24.4  触控目标 ≥ 24px（WCAG 2.5.8 的下限，排序箭头原来只有 20px 高）
     24.5  表格：时间列不换行，行高不再被某一列撑开
     24.6  卡片里不要再套一层带描边的盒子
     24.7  筛选行：标签对齐了，按钮也要对齐
   ========================================================================== */

/* --- 24.1 <small> 的 0.8333em 会算出 11.6667px 这种数，直接归到 micro --- */
body small { font-size: var(--fs-micro); }

/* --- 24.2 占位文字 --- */
html.app-shell body input::placeholder,
html.app-shell body textarea::placeholder,
form input::placeholder { color: var(--placeholder); opacity: 1; }

/* --- 24.3 对比度：下面这些原来是 --faint（白底 2.5:1），读起来发虚 --- */
/* 顶栏语言切换：繁中 / EN 未激活时 4.39:1，差一点点，降一档颜色就够 */
.lang-selector button,
html.app-shell body .lang-switch button { color: var(--ink-2); }
.lang-selector button:not(.active):hover { color: var(--ink); }

/* 排序箭头与手柄：既是控件又是唯一的方向提示，不该用最淡的灰 */
html.app-shell body .btn-sort { color: var(--ink-2); }
html.app-shell body .btn-sort:disabled { color: var(--muted); opacity: 0.55; }
html.app-shell body .sortable-handle { color: var(--muted); }
html.app-shell body .sort-header-btn .sort-caret { color: var(--muted); }

/* 公告日期、统计角标、进度条分母、空态说明、未选人的位置 */
html.app-shell body .global-ann-item-date { color: var(--muted); }
html.app-shell body .db-count.is-zero { color: var(--muted); }
html.app-shell body .db-meter-value .db-of { color: var(--muted); }
html.app-shell body .flow-person.is-empty .flow-person-name { color: var(--muted); font-style: italic; }
html.app-shell body .ap-empty { color: var(--muted); }
html.app-shell body .ann-cover-empty { color: var(--muted); }

/* --- 24.4 触控目标 --- */
.lang-selector button { height: 30px; min-height: 30px; }
html.app-shell body .btn-sort { width: 24px; height: 24px; min-height: 24px; max-height: 24px; }
html.app-shell body .sortable-handle { min-width: 24px; height: 24px; }
/* 标签上的 × 只有 20×17，用伪元素把可点区域撑到 30×30，视觉尺寸不动 */
html.app-shell body .tag-remove,
html.app-shell body .tag-input-tag button { position: relative; }
html.app-shell body .tag-remove::after,
html.app-shell body .tag-input-tag button::after {
  content: ""; position: absolute; inset: -6px; border-radius: var(--r-sm);
}

/* --- 24.5 表格：时间列不换行 ---
   操作日志的时间是 "2026-10-04 15:45:01"，列宽不够就被拆成三行，
   一行被撑到 75px，整页信息密度掉一半。 */
html.app-shell body .data-table td.cell-time,
html.app-shell body table td.cell-time {
  white-space: nowrap;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
html.app-shell body table td.cell-time .cell-time-date { display: block; color: var(--ink-2); }
html.app-shell body table td.cell-time .cell-time-clock { display: block; color: var(--muted); }
/* 日志表整体压一档行高：这类表是"扫"的不是"读"的 */
html.app-shell body .panel > table > tbody > tr > td { vertical-align: middle; }

/* --- 24.6 面板里别再套一层带描边的盒子 ---
   .panel 本身已经是白纸 + 1px 描边，里面的 .table-wrap 再描一次就成了双线，
   层级反而看不出来。改成：内层不描边，只用一条表头顶线分隔。 */
html.app-shell body .panel .table-wrap {
  border: 0;
  border-radius: 0;
  background: transparent;
}
html.app-shell body .panel .table-wrap > table.data-table > thead > tr > th,
html.app-shell body .panel .table-wrap > table > thead > tr > th {
  border-bottom: 1px solid var(--line);
}

/* --- 24.7 筛选行：输入框/下拉上面有标签，重置按钮没有标签，默认会往上顶 --- */
html.app-shell body .filters { align-items: flex-end; }
html.app-shell body .filters-action {
  display: flex;
  align-items: flex-end;
  /* 与同级 .field 的输入框底边对齐（标签高度 + 标签下间距） */
  padding-bottom: 0;
  align-self: flex-end;
}
html.app-shell body .filters-action > .btn { height: var(--ctl-h); }

/* --- 24.8 提示横幅：原来写死在元素上的内联色值收进样式表 --- */
html.app-shell body .notice-banner {
  margin-bottom: var(--sp-4);
  padding: 14px var(--sp-4);
  border: 1px solid var(--warn-line);
  border-radius: var(--r-md);
  background: var(--warn-bg);
  color: var(--warn-fg);
  font-size: var(--fs-sm);
  line-height: var(--lh-base);
}
html.app-shell body .notice-banner strong { font-size: var(--fs-base); font-weight: 600; }
html.app-shell body .notice-banner-names { margin-top: 6px; font-weight: 600; }
html.app-shell body .notice-banner-hint { margin-top: 8px; opacity: 0.92; }
html.app-shell body .notice-banner[hidden],
html.app-shell body .notice-banner.hidden { display: none; }

/* --- 24.9 审批链缺口提示（表单内）：同样从内联样式收编 --- */
html.app-shell body .approval-gap-note {
  margin: 0 0 var(--sp-4);
  padding: 12px 14px;
  border: 1px solid var(--tint-line);
  border-radius: var(--r-md);
  background: var(--tint);
  color: var(--ink-3);
  font-size: var(--fs-sm);
  line-height: var(--lh-base);
}

/* ==========================================================================
   26. 登录页：从公司官网 warpool.hk 取元素（第五轮 · 2026-10-04）
   --------------------------------------------------------------------------
   用户原话：「登录首页大量的空白，是不是可以有些元素」。先量了空白，不靠眼睛：
     · 左墙 560px 高，品牌块上方空 130px、模块清单到页脚之间空 86px（合计 39%）
     · 右栏 580px 宽，表单只占 380px，左右各空 100px
     · 右栏高 493px、左墙 560px，卡片右下露出 67px 的白；两侧脚注也不在同一条基线上
   取的是官网的「做法」不是「配色」——本系统墨青 + 登记簿的秩序感是自洽的，
   整套换成海军蓝只会变成另一个网站。深蓝只在「品牌面」（登录墙）出现：
     26.1  深色面用同心弧 + 柔光分层（官网 about-us-bg.svg 的手法）
     26.2  展示级标题降到 300 字重（官网 40/32/24px 标题都是 Light）
     26.3  台面加两团极淡的品牌色晕（官网 --grey2 #f2f7fb 的蓝调浅面语言）
     26.4  左右脚注对齐到同一条基线，卡片才收得住
     26.5  表单控件补悬停/聚焦过渡，语言切换与表单右边缘对齐
   ========================================================================== */

/* --- 26.1 左墙装饰层：圆心落在左下角外侧，向外扫出四道同心弧 ---
   全部是 1px 级别的描边，透明度 0.06–0.18。放大看有工艺感，缩到 100% 只是一层
   「这堵墙不是平涂」的空气感。不加载任何图片，纯径向渐变，不产生额外请求。 */
.login-side::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image:
    /* 右上角一团柔光：把「光源」交代清楚，弧线才不像脏印 */
    radial-gradient(circle 260px at 330px -30px, rgba(127, 178, 229, 0.18) 0%, rgba(127, 178, 229, 0) 68%),
    radial-gradient(circle 150px at -30px 590px, rgba(127, 178, 229, 0) 0 148px, rgba(127, 178, 229, 0.16) 148px 150px, rgba(127, 178, 229, 0) 150px),
    radial-gradient(circle 206px at -30px 590px, rgba(127, 178, 229, 0) 0 204px, rgba(127, 178, 229, 0.12) 204px 206px, rgba(127, 178, 229, 0) 206px),
    radial-gradient(circle 262px at -30px 590px, rgba(127, 178, 229, 0) 0 260px, rgba(127, 178, 229, 0.09) 260px 262px, rgba(127, 178, 229, 0) 262px),
    radial-gradient(circle 318px at -30px 590px, rgba(127, 178, 229, 0) 0 316px, rgba(127, 178, 229, 0.06) 316px 318px, rgba(127, 178, 229, 0) 318px);
}

/* --- 26.2 展示级标题：300 字重 + 负字距 --- */
.login-side h2 { font-weight: 300; letter-spacing: -0.01em; color: #fff; }
/* 印章补一层柔和落影：原来只有 0 1px 3px 的硬边，在深蓝上像贴纸 */
.login-side-mark { box-shadow: 0 8px 18px -10px rgba(0, 0, 0, 0.6); }

/* --- 26.3 台面：两团品牌色晕（左上深蓝 / 右下墨青） ---
   顺序有讲究：先铺「打光」的两层（顶部提亮 + 底部压暗），再把品牌色晕压在最上层。
   反过来写的话，顶部那层 0.85 的白会把左上角的蓝晕整片冲掉，肉眼看就是「没生效」。 */
body:has(.login-box) {
  background-color: var(--canvas);
  background-image:
    radial-gradient(50% 46% at 4% 0%, rgba(16, 45, 75, 0.10) 0%, rgba(16, 45, 75, 0) 68%),
    radial-gradient(44% 42% at 102% 104%, rgba(14, 107, 115, 0.075) 0%, rgba(14, 107, 115, 0) 68%),
    radial-gradient(120% 90% at 50% 0%, rgba(255, 255, 255, 0.75) 0%, rgba(255, 255, 255, 0) 58%),
    radial-gradient(100% 80% at 50% 100%, rgba(17, 24, 39, 0.05) 0%, rgba(17, 24, 39, 0) 62%);
}

/* --- 26.4 右栏撑满 + 两侧脚注同基线 ---
   只在桌面生效：窄屏是单列，右栏本来就该占满，动了反而把脚注推到底部之外。 */
@media (min-width: 861px) {
  .login-box {
    /* 纵向撑满（脚注才沉得下去） */
    align-self: stretch;
    /* 横向仍居中：max-width 会把 item 拉成 stretch 的左对齐，
       必须显式给宽度 + justify-self，否则表单会贴住中线，右侧空出 200px */
    justify-self: center;
    width: 380px;
    max-width: 100%;
    margin: 0;
    display: flex;
    flex-direction: column;
    /* 上下不再用固定 padding，改由两个 auto 边距分配，
       余量才随卡片高度自动摊平 */
    padding: 0 36px;
    box-sizing: border-box;
  }
  .login-box .login-header { margin-top: auto; }
  /* 脚注沉到底：底边落在卡片内 32px 处，与左墙页脚（同样 32px）齐平 */
  .login-footnote {
    margin-top: auto;
    margin-bottom: 32px;
  }
}

/* --- 26.5 控件过渡与对齐 --- */
.login-box .form-group input {
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
/* 悬停只改描边：输入框在深色台面上已经很淡，再改底色会跳 */
.login-box .form-group input:hover:not(:focus) { border-color: var(--muted); }
/* 品牌短线改用品牌渐变，纯色 24×3 在深蓝卡片旁显得单薄 */
.login-box .login-header::before { background: var(--grad-brand); }
/* 语言切换原本贴卡片边 20px，比表单右边缘多出 16px，视觉上「没对齐」。
   无条件写：≤800px 时它是 static，top/right 不生效，不会打架。 */
.login-box .lang-selector { top: 24px; right: 36px; }

/* --- 26.6 窄屏：装饰层收起，左墙压成一条时不带弧线 --- */
@media (max-width: 860px) {
  .login-side::after { display: none; }
  /* 窄屏右栏本来就占满整屏，但内容只有 ~500px，余量全堆在底部，
     读起来像「页面没写完」。改成在剩余空间里居中，上下均分。 */
  .login-box { display: flex; flex-direction: column; justify-content: center; }
}

/* ==========================================================================
   27. 全站细节：把测量出来的「散落」收编（第五轮 · 2026-10-04）
   --------------------------------------------------------------------------
   这一节全部由客观测量驱动，没有一条是凭感觉加的：
     27.1  表格空态行：29 处内联 style="color:#94a3b8;padding:NNpx"，3 种内距、2.5:1
     27.2  公告列表的日期/标签行：--faint 在白底 2.5:1
     27.3  标签 chip 没有圆角，关闭按钮只有 20×17（WCAG 2.5.8 要求 24×24）
     27.4  分段控件（子标签）未激活态在 --track 上只有 4.11:1
     27.5  toast 用了体系外的 0.25s 时长
   ========================================================================== */

/* --- 27.1 表格空态行：一个类替掉 29 处内联样式 --- */
html.app-shell body .empty-row {
  padding: var(--sp-5);
  color: var(--muted);
  font-size: var(--fs-sm);
  text-align: center;
}
/* 空的 <td> 上下别顶太高：表格行本来就矮，24px 内距会在表体里开一个洞 */
html.app-shell body td.empty-row { padding: var(--sp-5) var(--sp-3); }

/* --- 27.2 公告列表日期 / 标签行 --- */
html.app-shell body .ann-item-meta { color: var(--muted); }

/* --- 27.3 标签 chip：补圆角，关闭按钮补到 24×24 --- */
html.app-shell body .tag-chip { border-radius: var(--r-pill); }
html.app-shell body .tag-chip button {
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px;
  /* 负外边距把「多出来的 6px」还给 chip：可点区域变大，chip 外形不变 */
  margin: -3px -4px -3px 0;
  padding: 0;
  border: 0; background: none;
  border-radius: var(--r-pill);
  color: var(--danger-fg);
  font-family: inherit; font-size: var(--fs-sm); line-height: 1;
  cursor: pointer;
  transition: background-color var(--dur) var(--ease);
}
html.app-shell body .tag-chip button:hover { background: color-mix(in srgb, var(--danger-fg) 12%, transparent); }
html.app-shell body .tag-chip button:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--focus-ring); }

/* --- 27.4 分段控件未激活态：--muted 落在 --track 上只有 4.11:1 --- */
html.app-shell body .sub-tab:not(.active),
html.app-shell body .ap-mtab:not(.active) { color: var(--ink-2); }
/* 悬停要跟未激活态拉开差别，不然 hover 时颜色反而变浅 */
html.app-shell body .sub-tab:not(.active):hover { color: var(--ink); }
html.app-shell body .ap-mtab:not(.active):hover { color: var(--ink); }

/* --- 27.5 toast：0.25s 是体系外时长 --- */
html.app-shell body .toast { transition: opacity var(--dur) var(--ease); }

/* --- 27.6 登录页：测量出来的三处小字/小控件 --- */
/* 印章里的 "JS" 原来是手写的 17px，是刻度外的档位 */
.login-side-mark { font-size: var(--fs-lg); }
/* 脚注原来是 --faint，白底 2.54:1 */
.login-footnote { color: var(--muted); }
/* 「忘记密码？」只有 20px 高：撑到 24px 的可点高度，文字位置不变 */
.login-box .forgot-password {
  display: inline-flex; align-items: center;
  min-height: 24px;
}
/* 「记住我」的勾选框原来是 16×16，达不到 WCAG 2.5.8 的 24×24。
   16px 的视觉框在触屏上本来也难点，直接做成 24px——比例不变（半径同步放大 1.5 倍）。 */
.remember-me { min-height: 24px; }
.remember-me input[type="checkbox"] {
  width: 24px; height: 24px;
  border-radius: var(--r-sm);
}
.remember-me input[type="checkbox"]:checked::after {
  left: 7.5px; top: 2.3px;
  width: 6px; height: 12px;
  border-width: 0 2.5px 2.5px 0;
}

/* --- 27.7 侧栏分组标题 / 审批配置徽标：11px 是刻度外的档位 ---
   写这份 CSS 的人（我）在 tokens 里立了「最小 12px」的规矩，
   结果自己在三处用了 11px。规矩要靠测量执行，不靠记性。 */
.app-nav-group {
  font-size: var(--fs-micro);
  /* 中文加字距是散架，大写对汉字也不生效——只在英文语境保留排版意图 */
  letter-spacing: 0;
  text-transform: none;
}
:lang(en) .app-nav-group { letter-spacing: 0.06em; text-transform: uppercase; }
html.app-shell body .ap-tag,
html.app-shell body .ap-flag { font-size: var(--fs-micro); }

/* --- 27.8 公告列表次级行：--muted 落在选中行的 --brand-soft 上只有 4.2:1 --- */
html.app-shell body .ann-item-meta { color: var(--ink-2); }

/* ==========================================================================
   28. 全站基础项（第五轮 · 2026-10-04）
   --------------------------------------------------------------------------
   28.1  选中文字改成品牌色调（默认的蓝跟全站墨青打架）
   28.2  减少动效：全站只此一处兜底，不逐个组件写
   ========================================================================== */

/* --- 28.1 ::selection --- */
::selection {
  /* 只给底色，不动文字色：同一条规则要同时活在浅底（表格）和深底（侧栏）上，
     写死 color 必然有一边读不清 */
  background: color-mix(in srgb, var(--brand) 26%, transparent);
}
::-moz-selection { background: color-mix(in srgb, var(--brand) 26%, transparent); }

/* --- 28.2 prefers-reduced-motion 兜底 --- */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  /* 例外：进度指示器表达的是「还在转」这个状态，不是装饰性动效。
     静止掉用户会以为卡死，所以放慢而不停。 */
  .btn-spinner {
    animation-duration: 2s !important;
    animation-iteration-count: infinite !important;
  }
}

/* --- 28.3 登录页的键盘焦点 ---
   全站那条焦点描边的选择器带 `html.app-shell body` 前缀，
   而登录页是独立页面（不注入侧栏，也就没有 .app-shell），
   于是它一直在用浏览器默认的蓝框 rgb(0,95,204) —— 只有键盘用户看得到。
   这里按同一套规范补一份，只针对登录页。 */
body:has(.login-box) a:focus-visible,
body:has(.login-box) button:focus-visible,
body:has(.login-box) summary:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}
/* 输入框与全站一致：不用描边，用 3px 的 focus-ring 外圈（见 22.3） */
body:has(.login-box) input:focus-visible,
body:has(.login-box) select:focus-visible,
body:has(.login-box) textarea:focus-visible { outline: none; }

/* --- 28.4 <strong>/<b> 的默认 700 ---
   和 24.1 的 <small>（默认 0.8333em → 11.6667px）是同一类问题：
   没有写进样式表的 HTML 默认值，会绕过整套刻度出现在页面上。
   全站的强调字重只有 600，这里把它压回刻度。 */
strong, b { font-weight: 600; }

/* --------------------------------------------------------------------------
   29. 配置行列表（假期配置、报销字段配置等）
   统一：圆角容器 + 表头 + 对齐列 + 40px 圆角输入
   -------------------------------------------------------------------------- */
html.app-shell body .settings-list,
html.app-shell body .config-rows {
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--paper);
  margin-bottom: var(--sp-4);
}

html.app-shell body .settings-list-head,
html.app-shell body .field-config-head {
  display: grid;
  gap: var(--sp-3);
  align-items: center;
  padding: 10px var(--sp-4);
  margin: 0;
  background: var(--sunken);
  border-bottom: 1px solid var(--line);
  font-size: var(--fs-micro);
  font-weight: 500;
  color: var(--muted);
  letter-spacing: 0;
  text-transform: none;
}

html.app-shell body .settings-list-head {
  grid-template-columns: 40px minmax(0, 1fr) minmax(140px, 220px);
}

html.app-shell body .settings-row,
html.app-shell body .type-config-row {
  display: grid;
  grid-template-columns: 40px minmax(0, 1fr) minmax(140px, 220px);
  gap: var(--sp-3);
  align-items: center;
  padding: var(--sp-3) var(--sp-4);
  margin: 0;
  min-height: 56px;
  border: 0;
  border-bottom: 1px solid var(--line-soft);
  background: transparent;
}

html.app-shell body .settings-row:last-child,
html.app-shell body .type-config-row:last-child {
  border-bottom: 0;
}

html.app-shell body .settings-row-check {
  display: flex;
  align-items: center;
  justify-content: center;
  align-self: center;
  height: var(--ui-h);
}

html.app-shell body .settings-row-label {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: var(--ui-h);
}

html.app-shell body .settings-row-label strong,
html.app-shell body .type-config-row > div:first-of-type strong {
  display: block;
  font-size: 14px;
  font-weight: 500;
  color: var(--ink);
  line-height: var(--lh-tight);
}

html.app-shell body .settings-row-sub,
html.app-shell body .settings-row-meta,
html.app-shell body .type-config-row .default-hint {
  font-size: var(--fs-micro);
  color: var(--muted);
  line-height: 1.45;
}

html.app-shell body .settings-row-sub {
  margin-top: 2px;
}

html.app-shell body .settings-row-field {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 6px;
  min-width: 0;
}

html.app-shell body .settings-row-meta {
  text-align: left;
  white-space: normal;
  word-break: break-word;
  line-height: 1.5;
  min-width: 0;
}

html.app-shell body .settings-row-field input:not([type="checkbox"]):not([type="radio"]),
html.app-shell body .type-config-row input:not([type="checkbox"]):not([type="radio"]) {
  width: 100%;
  height: var(--ui-h);
  min-height: var(--ui-h);
  padding: 0 var(--sp-3);
  border: 1px solid var(--line-strong);
  border-radius: var(--ui-r);
  background: var(--paper);
  font-size: 14px;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

html.app-shell body .field-config-head {
  grid-template-columns: minmax(120px, 1.1fr) minmax(120px, 1.1fr) minmax(110px, 0.9fr) 72px 72px 52px;
}

html.app-shell body .field-config-row {
  display: grid;
  grid-template-columns: minmax(120px, 1.1fr) minmax(120px, 1.1fr) minmax(110px, 0.9fr) 72px 72px 52px;
  gap: var(--sp-3);
  align-items: center;
  padding: var(--sp-3) var(--sp-4);
  margin: 0;
  border: 0;
  border-bottom: 1px solid var(--line-soft);
  background: transparent;
}

html.app-shell body .field-config-row:last-child {
  border-bottom: 0;
}

html.app-shell body .field-config-row input:not([type="checkbox"]):not([type="radio"]),
html.app-shell body .field-config-row select {
  width: 100%;
  height: var(--ui-h);
  min-height: var(--ui-h);
  border: 1px solid var(--line-strong);
  border-radius: var(--ui-r);
  background: var(--paper);
  font-variant-numeric: tabular-nums;
}

html.app-shell body .field-config-row input[type="checkbox"] {
  width: 16px;
  height: 16px;
  margin: 0 auto;
  display: block;
}

html.app-shell body .annual-section {
  margin-top: var(--sp-5);
  padding-top: var(--sp-4);
  border-top: 1px solid var(--line);
}

html.app-shell body .annual-section .annual-grid {
  margin-top: var(--sp-4);
}

html.app-shell body .annual-section .annual-grid > div {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

html.app-shell body .annual-section .annual-grid label {
  display: block;
  margin: 0;
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--muted);
}

html.app-shell body .annual-section .annual-grid input {
  width: 100%;
  height: var(--ui-h);
  border: 1px solid var(--line-strong);
  border-radius: var(--ui-r);
  background: var(--paper);
  font-variant-numeric: tabular-nums;
}

@media (max-width: 760px) {
  html.app-shell body .settings-list-head {
    display: none;
  }
  html.app-shell body .settings-row,
  html.app-shell body .type-config-row {
    grid-template-columns: 36px 1fr;
    grid-template-areas:
      "check label"
      ". field";
    row-gap: var(--sp-2);
    align-items: center;
  }
  html.app-shell body .settings-row-check,
  html.app-shell body .type-config-row > input[type="checkbox"] {
    grid-area: check;
    align-self: start;
    margin-top: 2px;
  }
  html.app-shell body .settings-row-label,
  html.app-shell body .type-config-row > div:first-of-type {
    grid-area: label;
  }
  html.app-shell body .settings-row-field,
  html.app-shell body .type-config-row > input:not([type="checkbox"]) {
    grid-area: field;
  }
  html.app-shell body .field-config-head {
    display: none;
  }
  html.app-shell body .field-config-row {
    grid-template-columns: 1fr;
    gap: var(--sp-2);
  }
}
