* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

:root {
  --primary: #1890ff;
  --success: #52c41a;
  --warning: #faad14;
  --danger: #ff4d4f;
  --bg: #f5f5f5;
  --border: #e8e8e8;
  --text: #333;
  --text-secondary: #666;
}

body {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  background: var(--bg);
  color: var(--text);
  min-height: 100vh;
}

.hidden {
  display: none !important;
}

/* 登录页 */
#login-page {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}

.login-box {
  background: white;
  padding: 40px;
  border-radius: 8px;
  box-shadow: 0 4px 20px rgba(0,0,0,0.15);
  width: 100%;
  max-width: 400px;
}

.login-box h1 {
  text-align: center;
  margin-bottom: 30px;
  color: var(--text);
  font-size: 24px;
}

.login-box .tip {
  text-align: center;
  color: var(--text-secondary);
  font-size: 12px;
  margin-top: 15px;
}

/* 表单 */
.form-group {
  margin-bottom: 20px;
}

.form-group label {
  display: block;
  margin-bottom: 8px;
  font-weight: 500;
}

.form-group input,
.form-group select,
.form-group textarea {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 4px;
  font-size: 14px;
  transition: border-color 0.3s;
}

.form-group input:focus,
.form-group select:focus,
.form-group textarea:focus {
  outline: none;
  border-color: var(--primary);
}

.form-row {
  display: flex;
  gap: 15px;
  flex-wrap: wrap;
  align-items: flex-end;
}

.form-row .form-group {
  flex: 1;
  min-width: 150px;
}

/* 按钮 */
.btn {
  padding: 10px 20px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
  transition: all 0.3s;
}

.btn-primary {
  background: var(--primary);
  color: white;
}

.btn-primary:hover {
  background: #40a9ff;
}

.btn-secondary {
  background: #fff;
  color: var(--primary);
  border: 1px solid var(--primary);
}

.btn-secondary:hover {
  background: #e6f7ff;
}

.btn-sm {
  padding: 6px 12px;
  font-size: 12px;
}

.btn-block {
  width: 100%;
}

.btn:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

/* 头部 */
.header {
  background: white;
  padding: 15px 20px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  box-shadow: 0 2px 8px rgba(0,0,0,0.08);
}

.header h2 {
  font-size: 18px;
  color: var(--text);
}

.header-right {
  display: flex;
  align-items: center;
  gap: 15px;
}

/* 标签页 */
.tabs {
  background: white;
  display: flex;
  overflow-x: auto;
  border-bottom: 1px solid var(--border);
}

.tab {
  padding: 15px 20px;
  border: none;
  background: none;
  cursor: pointer;
  white-space: nowrap;
  color: var(--text-secondary);
  font-size: 14px;
  transition: all 0.3s;
}

.tab:hover {
  color: var(--primary);
}

.tab.active {
  color: var(--primary);
  border-bottom: 2px solid var(--primary);
}

/* 内容区域 */
.content {
  padding: 20px;
  max-width: 1400px;
  margin: 0 auto;
}

/* §443eq 2026-08-02: tab-content 默认 display:none, .active 时 block. 采购单需要占满视口 */
.tab-content {
  display: none;
}
.tab-content.active {
  display: flex;
  flex-direction: column;
  height: calc(100vh - 30px);  /* 视口高度 - 主内容 padding 边距 */
  margin: 0;
  padding: 0;
}
.tab-content.active > .card {
  flex: 1;
  min-height: 0;
}

/* 卡片 */
.card {
  background: white;
  border-radius: 8px;
  padding: 20px;
  margin-bottom: 20px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.06);
}

.card h3 {
  margin-bottom: 15px;
  font-size: 16px;
  color: var(--text);
}

/* 统计卡片 */
.stats-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 15px;
  margin-bottom: 20px;
}

.stat-card {
  background: white;
  border-radius: 8px;
  padding: 20px;
  text-align: center;
  box-shadow: 0 2px 8px rgba(0,0,0,0.06);
  /* §443snNEW1 2026-08-29: 老板原话 "KPI 卡片点击点不动" — dashboard 的 dash-* 5个 KPI
     现在是可点击的 (跳转到对应 status 过滤的工单列表), 所以卡片整体加 cursor + hover 阴影 */
  cursor: pointer;
  transition: box-shadow 0.2s, transform 0.2s;
  user-select: none;
}

.stat-card:hover {
  box-shadow: 0 6px 16px rgba(0,0,0,0.12);
  transform: translateY(-2px);
}

.stat-card:active {
  transform: translateY(0);
}

.stat-card .stat-value {
  font-size: 32px;
  font-weight: bold;
  color: var(--text);
  cursor: pointer;
  transition: color 0.2s;
}

.stat-card .stat-value:hover {
  color: var(--primary);
  text-decoration: underline;
}

.stat-card .stat-label {
  font-size: 14px;
  color: var(--text-secondary);
  margin-top: 5px;
}

.stat-card.pending .stat-value { color: var(--warning); }
.stat-card.processing .stat-value { color: var(--primary); }
.stat-card.completed .stat-value { color: var(--success); }
.stat-card.output .stat-value { color: #722ed1; }

/* 阶段统计 */
.stage-stats {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}

.stage-stat {
  background: var(--bg);
  padding: 10px 15px;
  border-radius: 4px;
  text-align: center;
  min-width: 80px;
}

.stage-stat .stage-name {
  font-size: 12px;
  color: var(--text-secondary);
}

.stage-stat .stage-count {
  font-size: 20px;
  font-weight: bold;
  color: var(--primary);
}

/* 工具栏 */
.toolbar {
  display: flex;
  gap: 10px;
  margin-bottom: 15px;
  flex-wrap: wrap;
  align-items: center;
}

.search-input {
  flex: 1;
  min-width: 200px;
  padding: 8px 12px;
  border: 1px solid var(--border);
  border-radius: 4px;
}

.filter-select {
  padding: 8px 12px;
  border: 1px solid var(--border);
  border-radius: 4px;
  min-width: 120px;
}

/* 表格 */
.table-container {
  overflow-x: scroll;
  width: 100%;
  scrollbar-width: thin;
}

.data-table {
  width: 2000px;
}

/* 冻结完整品名列(data-col="1",表头固定在左侧) — 仅对非商品档案的表格生效 */
.data-table:not(#products-data-table) th[data-col="1"],
.data-table:not(#products-data-table) td[data-col="1"] {
  position: sticky !important;
  left: 0 !important;
  z-index: 1;
  background: #fff !important;
  min-width: 240px;
}
.data-table:not(#products-data-table) th[data-col="1"] {
  z-index: 3;
  background: #f8f9fa !important;
}

.data-table {
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
}

/* 商品档案表格:列宽优先生效,不走 table-layout 平均分配 */
#products-data-table {
  table-layout: fixed;
  width: max-content;
  min-width: 100%;
}
#products-data-table th, #products-data-table td {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.data-table th,
.data-table td {
  padding: 8px;
  font-size: 12px;
  text-align: left;
  border-bottom: 1px solid var(--border);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 列宽可拖动 */
.data-table th {
  position: relative;
  user-select: none;
}

.data-table th .col-resize-handle {
  position: absolute;
  right: 0;
  top: 0;
  bottom: 0;
  width: 6px;
  cursor: col-resize;
  background: transparent;
  z-index: 2;
}

.data-table th .col-resize-handle:hover,
.data-table th .col-resize-handle.active {
  background: rgba(25, 118, 210, 0.3);
}

.data-table th {
  background: var(--bg);
  font-weight: 500;
  color: var(--text-secondary);
  font-size: 13px;
}

.data-table tr:hover {
  background: #fafafa;
}

/* 状态标签 */
.status-badge {
  display: inline-block;
  padding: 4px 8px;
  border-radius: 4px;
  font-size: 12px;
}

.status-pending {
  background: #fffbe6;
  color: var(--warning);
}

.status-processing {
  background: #e6f7ff;
  color: var(--primary);
}

.status-completed {
  background: #f6ffed;
  color: var(--success);
}

/* 优先级 */
.priority-badge {
  display: inline-block;
  padding: 2px 6px;
  border-radius: 2px;
  font-size: 11px;
}

.priority-1 {
  background: var(--bg);
  color: var(--text-secondary);
}

.priority-2 {
  background: #fffbe6;
  color: var(--warning);
}

.priority-3 {
  background: #fff2f0;
  color: var(--danger);
}

/* 分页 */
.pagination {
  display: flex;
  gap: 5px;
  justify-content: center;
  margin-top: 15px;
}

.pagination button {
  padding: 6px 12px;
  border: 1px solid var(--border);
  background: white;
  cursor: pointer;
  border-radius: 4px;
}

.pagination button.active {
  background: var(--primary);
  color: white;
  border-color: var(--primary);
}

/* 弹窗 */
.modal {
  position: fixed;
  top: 36px;   /* §443er 2026-08-03: 从 in-app tab 栏下方开始 (tab 栏 36px 高) */
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0,0,0,0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 998; /* 低于 sidebar 1500 (永远可点), 低于 in-app tabs 999 (永远可点) - 但 .modal 比 tab 栏 999 低... 修 */
}

.modal-content {
  background: white;
  border-radius: 8px;
  width: 90%;
  max-width: 500px;
  max-height: 90vh;
  overflow-y: auto;
}

.modal-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 15px 20px;
  border-bottom: 1px solid var(--border);
}

.modal-header h3 {
  margin: 0;
  font-size: 16px;
}

.modal-header .close {
  font-size: 24px;
  background: none;
  border: none;
  cursor: pointer;
  color: var(--text-secondary);
}

.modal-content form {
  padding: 20px;
}

.form-actions {
  display: flex;
  gap: 10px;
  justify-content: flex-end;
  margin-top: 20px;
}

/* 标签预览 */
.label-preview {
  background: white;
  border: 2px dashed var(--border);
  padding: 20px;
  margin: 15px 0;
  min-height: 200px;
}

.label-item {
  border: 1px solid #333;
  padding: 15px;
  margin-bottom: 10px;
  font-size: 12px;
}

.label-item table {
  width: 100%;
  border-collapse: collapse;
}

.label-item td {
  padding: 4px 8px;
}

.label-item .label-title {
  text-align: center;
  font-size: 16px;
  font-weight: bold;
  border-bottom: 1px solid #333;
  padding: 8px;
}

/* 快速操作 */
.quick-actions {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 15px;
}

/* 来源统计 */
.source-stats {
  display: flex;
  gap: 15px;
  flex-wrap: wrap;
}

.source-item {
  background: var(--bg);
  padding: 15px 25px;
  border-radius: 4px;
  text-align: center;
}

.source-item .source-name {
  font-size: 14px;
  color: var(--text-secondary);
}

.source-item .source-count {
  font-size: 24px;
  font-weight: bold;
  color: var(--primary);
}

/* 操作按钮 */
.action-btn {
  padding: 4px 8px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 12px;
  margin-right: 5px;
}

.action-btn.edit {
  background: #e6f7ff;
  color: var(--primary);
}

.action-btn.delete {
  background: #fff2f0;
  color: var(--danger);
}

.action-btn.print {
  background: #f6ffed;
  color: var(--success);
}

/* 手机端优化 */
@media (max-width: 768px) {
  body {
    font-size: 14px;
  }
  
  .header {
    flex-direction: column;
    gap: 8px;
    padding: 10px 15px;
  }
  
  .header h2 {
    font-size: 16px;
  }
  
  .tabs {
    flex-wrap: nowrap;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    justify-content: flex-start;
    padding-bottom: 5px;
  }
  
  .tab {
    padding: 10px 12px;
    font-size: 13px;
    white-space: nowrap;
  }
  
  .content {
    padding: 10px;
  }
  
  .card {
    padding: 12px;
    margin-bottom: 12px;
  }
  
  .card h3 {
    font-size: 15px;
    margin-bottom: 10px;
  }
  
  .toolbar {
    flex-wrap: wrap;
    gap: 8px;
  }
  
  .search-input,
  .filter-select {
    width: 100%;
    font-size: 14px;
    padding: 8px;
  }
  
  .btn {
    padding: 8px 12px;
    font-size: 13px;
  }
  
  .stats-grid {
    grid-template-columns: repeat(3, 1fr);
    gap: 8px;
  }
  
  .stat-card {
    padding: 12px 8px;
  }
  
  .stat-card .stat-value {
    font-size: 20px;
  }
  
  .stat-card .stat-label {
    font-size: 11px;
  }
  
  .form-row {
    flex-direction: column;
    gap: 10px;
  }
  
  .form-group {
    margin-bottom: 10px;
  }
  
  .form-group input,
  .form-group select,
  .form-group textarea {
    font-size: 14px;
    padding: 8px 10px;
  }
  
  /* 表格手机端优化 */
  .table-container {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }
  
  .data-table {
    font-size: 12px;
    min-width: 600px;
  }
  
  .data-table th,
  .data-table td {
    padding: 6px 8px;
    white-space: nowrap;
  }
  
  /* 弹窗手机端优化 */
  .modal-content {
    width: 95%;
    max-height: 85vh;
    margin: 10px auto;
  }
  
  .modal-header {
    padding: 10px 15px;
  }
  
  .modal-header h3 {
    font-size: 15px;
  }
  
  .modal-content form {
    padding: 15px;
  }
  
  .form-actions {
    flex-direction: column;
    gap: 8px;
  }
  
  .form-actions .btn {
    width: 100%;
  }
  
  /* 分页手机端 */
  .pagination button {
    padding: 6px 10px;
    font-size: 12px;
  }
  
  /* 操作按钮手机端 */
  .action-btn {
    padding: 6px 10px;
    font-size: 12px;
    margin: 2px;
  }
  
  /* 阶段统计手机端 */
  .stage-stats {
    overflow-x: auto;
    flex-wrap: nowrap;
    -webkit-overflow-scrolling: touch;
  }
  
  .stage-stat {
    min-width: 70px;
    flex-shrink: 0;
  }
  
  /* 快速操作手机端 */
  .quick-actions {
    overflow-x: auto;
    flex-wrap: nowrap;
    -webkit-overflow-scrolling: touch;
  }
  
  .quick-actions .btn {
    flex-shrink: 0;
    white-space: nowrap;
  }
  
  /* 标签预览手机端 */
  .label-preview {
    padding: 10px;
    font-size: 12px;
  }
  
  .label-item {
    padding: 10px;
    font-size: 11px;
  }
  
  /* 提示弹窗手机端 */
  .toast {
    left: 10px;
    right: 10px;
    transform: none;
    font-size: 13px;
    text-align: center;
  }
  
  @keyframes slideDown {
    from {
      top: -50px;
    }
    to {
      top: 10px;
    }
  }
}

/* 加载提示 */
.loading {
  text-align: center;
  padding: 20px;
  color: var(--text-secondary);
}

/* 空状态 */
.empty-state {
  text-align: center;
  padding: 40px;
  color: var(--text-secondary);
}

/* 成功/错误提示 */
.toast {
  position: fixed;
  top: 20px;
  left: 50%;
  transform: translateX(-50%);
  padding: 10px 20px;
  border-radius: 4px;
  z-index: 2000;
  animation: slideDown 0.3s ease;
}

.toast.success {
  background: var(--success);
  color: white;
}

.toast.error {
  background: var(--danger);
  color: white;
}

@keyframes slideDown {
  from {
    top: -50px;
  }
  to {
    top: 20px;
  }
}

/* 打印样式 */
@media print {
  body * {
    visibility: hidden;
  }
  
  #label-preview,
  #label-preview * {
    visibility: visible;
  }
  
  #label-preview {
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    background: white;
    padding: 20px;
  }
  
  .label-item {
    page-break-inside: avoid;
  }
}

/* §443snNEW585 2026-10-18 表格可读性优化 (修复中文按字竖排) */
table th, table td {
  white-space: nowrap !important;
  word-break: keep-all !important;
}
/* §443snNEW235 2026-10-25 老板拍板: 出入库记录「备注」列豁免全局 nowrap
   病根: 上面这条 `table th, table td { white-space: nowrap !important }` 是全局规则,
         优先级高于 td 的内联样式 → 备注列加再多 white-space:normal 都不生效
         → 长备注 (如 §443snNEW234 补录说明) 把整列撑到 1152px, 后面 6 列全被挤出屏幕
   修法: 用更具体的选择器 + !important 单独放开备注列 (只影响这一列, 不动其他表)
   ★ 选择器要同时匹配 th 和 td, 且优先级高于 `table th, table td` */
#rl-table-area table th,
#rl-table-area table td {
  /* 全局 nowrap 的兜底放开, 下面再逐列收紧 */
}
/* 备注列: 允许换行, 但限高 3 行 (老板拍板: 不能拉这么高) + 底部渐隐提示还有内容 */
#rl-table-area table th:nth-child(9),
#rl-table-area table td:nth-child(9) {
  white-space: normal !important;
  word-break: break-word !important;
  overflow-wrap: anywhere !important;
  line-height: 1.4;
  vertical-align: top;
}
/* §443snNEW236 2026-10-25 老板拍板: 备注列限高 (3 行) + 悬浮显示全部内容
   病根: 换行后长备注把行高拉到 8 行 (154px), 一屏放不了几行
   修法: 内层 div .rl-note-clamp 限 3 行 + overflow:hidden + 底部渐隐 (视觉提示"还有更多")
         + 自定义 tooltip 气泡 (data-tip 属性) 鼠标悬浮显示全文
   ★★ PITFALL: max-height 直接写在 td 上【不生效】(td 是 table-cell, 高度由内容撑开)
     → 必须套一层普通 div 才能限高 */
#rl-table-area table td:nth-child(9) {
  vertical-align: top;
  cursor: help;
}
.rl-note-clamp {
  max-height: 60px;
  overflow: hidden;
  white-space: normal !important;
  word-break: break-word !important;
  overflow-wrap: anywhere !important;
  line-height: 1.4;
  position: relative;
  /* 底部渐隐: 提示下面还有内容 */
  -webkit-mask-image: linear-gradient(to bottom, #000 42px, transparent 60px);
  mask-image: linear-gradient(to bottom, #000 42px, transparent 60px);
}
/* ★ 自定义 tooltip 气泡 (全局, 可复用): 给任意元素加 data-tip="全文" 即生效 */
.koz-tip {
  position: fixed;
  z-index: 99999;
  max-width: 460px;
  max-height: 320px;
  overflow-y: auto;
  padding: 8px 11px;
  background: #263238;
  color: #fff;
  font-size: 12px;
  line-height: 1.55;
  border-radius: 6px;
  box-shadow: 0 6px 20px rgba(0,0,0,0.28);
  white-space: pre-wrap;
  word-break: break-word;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.12s;
}
.koz-tip.show { opacity: 1; }
.koz-tip::after {
  content: '';
  position: absolute;
  border: 6px solid transparent;
}
/* 其余列保持 nowrap (不换行), 但允许省略号截断, 防止长文本撑破列宽 */
#rl-table-area table th:not(:nth-child(9)),
#rl-table-area table td:not(:nth-child(9)) {
  white-space: nowrap !important;
  overflow: hidden;
  text-overflow: ellipsis;
}
table thead th {
  white-space: nowrap;
  font-weight: 600;
}
/* 销售单/工单/库存等主表格容器加横向滚动, 防止列被切 */
#so-table-container,
#order-table-container,
#inventory-table-container,
#po-table-container,
table.data-table,
table.report-table {
  overflow-x: auto;
}
/* 主表格给个最小宽度, 触发横向滚动 */
#so-table,
#order-table,
#po-table,
table.data-table {
  min-width: 1400px;
}
#so-table th, #so-table td,
#order-table th, #order-table td {
  padding: 8px 10px;
  vertical-align: top;
}
#so-table th:nth-child(2), #so-table td:nth-child(2),
#order-table th:nth-child(2), #order-table td:nth-child(2) {
  min-width: 140px; /* 单号列 */
}
#so-table th:nth-child(3), #so-table td:nth-child(3),
#order-table th:nth-child(3), #order-table td:nth-child(3) {
  min-width: 200px; /* 客户/产品名列 */
}
#so-table th:nth-child(4), #so-table td:nth-child(4),
#order-table th:nth-child(4), #order-table td:nth-child(4) {
  min-width: 140px; /* 客户名/规格 */
}
#so-table th:nth-child(5), #so-table td:nth-child(5),
#order-table th:nth-child(5), #order-table td:nth-child(5),
#so-table th:nth-child(6), #so-table td:nth-child(6),
#order-table th:nth-child(6), #order-table td:nth-child(6) {
  min-width: 120px; /* 数量/价格/类型 */
}


/* §443snNEW585 2026-10-18 全局 loading spinner (P2-2) */
/* ★§443snNEW293 2026-10-28 老板拍 C: 遮罩从【全屏半透明黑底】改成【右上角小胶囊】
   病根: 全屏遮罩每闪一次 = 整页白闪一下, 批量操作(每个请求一次遮罩)最刺眼
   改法: 不再遮挡整页, 只在右上角显示一个小 spinner, 不挡老板看表格 */
.global-loading {
  position: fixed;
  top: 12px;
  right: 12px;
  background: rgba(0, 0, 0, 0.72);
  border-radius: 20px;
  z-index: 999999;
  display: none;
  align-items: center;
  justify-content: center;
  flex-direction: row;
  gap: 8px;
  padding: 8px 14px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.25);
  pointer-events: none;
}
.global-loading.active { display: flex; }
.global-loading .spinner {
  width: 20px;
  height: 20px;
  border: 3px solid rgba(255, 255, 255, 0.35);
  border-top-color: #64b5f6;
  border-radius: 50%;
  animation: global-spin 0.8s linear infinite;
  flex: 0 0 auto;
}
.global-loading .text {
  color: white;
  font-size: 13px;
  background: transparent;
  padding: 0;
  border-radius: 0;
  white-space: nowrap;
}
@keyframes global-spin {
  to { transform: rotate(360deg); }
}

/* §443snNEW585 骨架屏 (skeleton) */
.skeleton {
  background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
  background-size: 200% 100%;
  animation: skeleton-shimmer 1.5s infinite;
  border-radius: 4px;
  color: transparent !important;
}
.skeleton::after { content: " "; }
@keyframes skeleton-shimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

/* §443snNEW585 Toast 容器 (P2-6) */
.toast-container {
  position: fixed;
  top: 70px;
  right: 20px;
  z-index: 99999;
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-width: 360px;
}
.toast {
  padding: 12px 16px;
  border-radius: 6px;
  background: #323232;
  color: white;
  font-size: 14px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  animation: toast-slide 0.3s ease-out;
}
.toast.success { background: #2e7d32; }
.toast.error   { background: #c62828; }
.toast.warning { background: #ef6c00; }
.toast.info    { background: #1976d2; }
@keyframes toast-slide {
  from { transform: translateX(120%); opacity: 0; }
  to   { transform: translateX(0); opacity: 1; }
}


/* ★★ fix329 2026-10-29 老板报「外加工标签打印打不出来」
   病根: 上面那段 @media print (body * { visibility:hidden }) 是给【标签页】的老打印用的,
         可见白名单只有 #label-preview → 外加工标签 (#outsource-label-print-area) 不在白名单里
         → 打印预览整页空白
         而且 body * { visibility:hidden } 只隐藏【可见性】不改变【布局】
         → 侧边栏 + 整个 app 页面仍然占 2 页
   修法: 下面这段只针对外加工标签打印生效:
         ① 整体 display:none (真正不占版面 → 只剩 1 页)
         ② 把 #outsource-label-print-area 移到 body 下, position:static, 去掉圆角/边框
         ③ 打印完成后自动还原 (JS 在 printOutsourceLabel 里前后调 _osPrintMode)
   ★ 老标签页 (#label-preview) 的打印规则不动 */
@media print {
  /* 外加工标签打印模式 (由 body.os-print-mode 标记) */
  body.os-print-mode > *:not(#os-print-host) {
    display: none !important;
  }
  body.os-print-mode #os-print-host {
    display: block !important;
    position: static !important;
    margin: 0 !important;
    padding: 0 !important;
    background: #fff !important;
    /* ★ 老 @media print 的 body * { visibility:hidden } 也会命中这里 →
       必须显式把整棵子树 visibility 拉回来, 否则打印出来还是空白 */
    visibility: visible !important;
  }
  body.os-print-mode #os-print-host * {
    visibility: visible !important;
  }
  body.os-print-mode #os-print-host #outsource-label-print-area {
    border: none !important;
    border-radius: 0 !important;
    padding: 0 !important;
    margin: 0 !important;
    width: 100% !important;
    max-width: none !important;
    box-shadow: none !important;
  }
  body.os-print-mode #os-print-host table {
    page-break-inside: auto;
  }
  body.os-print-mode #os-print-host tr {
    page-break-inside: avoid;
  }
  @page {
    size: A4;
    margin: 10mm;
  }
}

/* ★ fix330 兜底: 即使 JS 没跑 (老板浏览器旧缓存), 只要外加工标签弹窗是打开的,
     打印也只输出标签。
   ★ 关键: #outsource-label-modal 是 #main-content 的【直接子元素】
     → 不能藏整个 #main-content (会把 modal 一起藏掉, 打印还是空白)
     → 改成只藏 #main-content 里除 modal 外的其他子元素 + 清掉 main-content 的边距
   ★ 老标签页 (#label-preview) 不受影响: 它不在 outsource-label-modal 里 */
@media print {
  body:has(#outsource-label-modal[style*="display: block"]) > *:not(#main-content),
  body:has(#outsource-label-modal[style*="display:block"]) > *:not(#main-content) {
    display: none !important;
  }
  body:has(#outsource-label-modal[style*="display: block"]) #main-content,
  body:has(#outsource-label-modal[style*="display:block"]) #main-content {
    margin: 0 !important;
    padding: 0 !important;
    min-height: 0 !important;
  }
  body:has(#outsource-label-modal[style*="display: block"]) #main-content > *:not(#outsource-label-modal),
  body:has(#outsource-label-modal[style*="display:block"]) #main-content > *:not(#outsource-label-modal) {
    display: none !important;
  }
  body:has(#outsource-label-modal[style*="display: block"]) #outsource-label-modal,
  body:has(#outsource-label-modal[style*="display:block"]) #outsource-label-modal {
    display: block !important;
    position: static !important;
    inset: auto !important;
    background: #fff !important;
    overflow: visible !important;
  }
  body:has(#outsource-label-modal[style*="display: block"]) #outsource-label-modal *,
  body:has(#outsource-label-modal[style*="display:block"]) #outsource-label-modal * {
    visibility: visible !important;
  }
  body:has(#outsource-label-modal[style*="display: block"]) #outsource-label-modal > div,
  body:has(#outsource-label-modal[style*="display:block"]) #outsource-label-modal > div {
    margin: 0 !important;
    padding: 0 !important;
    max-width: none !important;
  }
  body:has(#outsource-label-modal[style*="display: block"]) #outsource-label-print-area,
  body:has(#outsource-label-modal[style*="display:block"]) #outsource-label-print-area {
    border: none !important;
    border-radius: 0 !important;
    padding: 0 !important;
    margin: 0 !important;
    width: 100% !important;
    max-width: none !important;
    box-shadow: none !important;
    font-family: SimSun, serif !important;
  }
  /* ★ 打印时压缩字号/内边距, 保证 1 页 A4 塞得下 */
  body:has(#outsource-label-modal[style*="display: block"]) #outsource-label-print-area *,
  body:has(#outsource-label-modal[style*="display:block"]) #outsource-label-print-area * {
    font-size: 10px !important;
    line-height: 1.25 !important;
  }
  body:has(#outsource-label-modal[style*="display: block"]) #outsource-label-print-area table td,
  body:has(#outsource-label-modal[style*="display: block"]) #outsource-label-print-area table th,
  body:has(#outsource-label-modal[style*="display:block"]) #outsource-label-print-area table td,
  body:has(#outsource-label-modal[style*="display:block"]) #outsource-label-print-area table th {
    padding: 2px 3px !important;
  }
  body:has(#outsource-label-modal[style*="display: block"]) #outsource-label-print-area div[style*="letter-spacing"],
  body:has(#outsource-label-modal[style*="display:block"]) #outsource-label-print-area div[style*="letter-spacing"] {
    font-size: 16px !important;
    margin-bottom: 6px !important;
  }
  /* ★ 藏掉弹窗 UI 控件 (标题行「外加工标签」+ ×, 底部「打印」「关闭」按钮)
     只留真正的标签内容 (#outsource-label-preview-box) */
  body:has(#outsource-label-modal[style*="display: block"]) #outsource-label-modal > div > div:first-child,
  body:has(#outsource-label-modal[style*="display: block"]) #outsource-label-modal > div > div:last-child,
  body:has(#outsource-label-modal[style*="display:block"]) #outsource-label-modal > div > div:first-child,
  body:has(#outsource-label-modal[style*="display:block"]) #outsource-label-modal > div > div:last-child {
    display: none !important;
  }
}
