/* ============================================================
   通用组件层 —— 所有模块共用，禁止模块自造样式
   ============================================================ */

/* ---------- 卡片 ---------- */
.card{
  background:var(--surface); border:1px solid var(--border);
  border-radius:var(--r-lg); box-shadow:var(--sh-1); overflow:hidden;
}
.card + .card{ margin-top:var(--sp-4); }
.card-head{
  display:flex; align-items:center; gap:var(--sp-3);
  padding:var(--sp-4) var(--sp-5); border-bottom:1px solid var(--border);
}
.card-head .ch-title{ font-size:var(--fs-lg); font-weight:600; }
.card-head .ch-desc{ font-size:var(--fs-sm); color:var(--text-2); }
.card-head .ch-actions{ margin-left:auto; display:flex; gap:var(--sp-2); flex-wrap:wrap; }
.card-body{ padding:var(--sp-5); }
.card-body.tight{ padding:var(--sp-3); }
.card-foot{ padding:var(--sp-3) var(--sp-5); border-top:1px solid var(--border); background:var(--surface-2); }

/* 提示条 */
.note{
  background:var(--info-50); border:1px solid var(--brand-100); color:var(--gray-700);
  border-radius:var(--r-md); padding:var(--sp-3) var(--sp-4); font-size:var(--fs-sm); line-height:1.7;
}
.note.warn{ background:var(--warn-50); border-color:#f5dcae; }
.note.bad{ background:var(--bad-50); border-color:#f7c9c9; }
.note.ok{ background:var(--ok-50); border-color:#c2e7d1; }

/* ---------- 按钮 ---------- */
.btn{
  display:inline-flex; align-items:center; justify-content:center; gap:6px;
  height:32px; padding:0 14px; border-radius:var(--r-md);
  border:1px solid var(--border-strong); background:var(--surface); color:var(--text);
  font-size:var(--fs-md); cursor:pointer; white-space:nowrap;
  transition:all var(--dur) var(--ease); font-family:inherit;
}
.btn:hover{ border-color:var(--brand-400); color:var(--brand-700); background:var(--brand-50); }
.btn:active{ transform:translateY(1px); }
.btn:disabled{ opacity:.5; cursor:not-allowed; }
.btn.primary{ background:var(--brand-600); border-color:var(--brand-600); color:#fff; }
.btn.primary:hover{ background:var(--brand-700); border-color:var(--brand-700); color:#fff; }
.btn.danger{ background:var(--surface); border-color:var(--bad-400); color:var(--bad-600); }
.btn.danger:hover{ background:var(--bad-50); border-color:var(--bad-600); color:var(--bad-700); }
.btn.solid-danger{ background:var(--bad-600); border-color:var(--bad-600); color:#fff; }
.btn.solid-danger:hover{ background:var(--bad-700); color:#fff; }
.btn.ghost{ border-color:transparent; background:transparent; color:var(--text-2); }
.btn.ghost:hover{ background:var(--surface-3); color:var(--text); border-color:transparent; }
.btn.sm{ height:26px; padding:0 10px; font-size:var(--fs-sm); }
.btn.lg{ height:38px; padding:0 20px; font-size:var(--fs-lg); }
.btn.block{ width:100%; }

/* ---------- 表单 ---------- */
.form-grid{ display:grid; grid-template-columns:repeat(auto-fill,minmax(230px,1fr)); gap:var(--sp-4); }
.field{ display:flex; flex-direction:column; gap:6px; }
.field.wide{ grid-column:1 / -1; }
.field > label{ font-size:var(--fs-sm); color:var(--text-2); font-weight:500; }
.field .f-req{ color:var(--bad-600); margin-left:2px; }
.field .f-hint{ font-size:var(--fs-xs); color:var(--text-3); }
.field .f-err{ font-size:var(--fs-xs); color:var(--bad-600); display:none; }
.field.invalid .f-err{ display:block; }
.field.invalid .ipt,.field.invalid select,.field.invalid textarea{ border-color:var(--bad-600); }

.ipt,select,textarea{
  width:100%; height:32px; padding:0 10px; font-size:var(--fs-md); font-family:inherit;
  border:1px solid var(--border-strong); border-radius:var(--r-md);
  background:var(--surface); color:var(--text); outline:none;
  transition:border-color var(--dur) var(--ease),box-shadow var(--dur) var(--ease);
}
textarea{ height:auto; min-height:70px; padding:8px 10px; resize:vertical; line-height:1.6; }
.ipt:focus,select:focus,textarea:focus{ border-color:var(--brand-500); box-shadow:0 0 0 3px var(--brand-50); }
.ipt[readonly],.ipt:disabled{ background:var(--surface-3); color:var(--text-2); }
select{ cursor:pointer; }
.chk{ display:inline-flex; align-items:center; gap:6px; cursor:pointer; font-size:var(--fs-md); }
.chk input{ width:15px;height:15px;accent-color:var(--brand-600);cursor:pointer; }

/* 筛选工具条 */
.toolbar{
  display:flex; align-items:center; gap:var(--sp-2); flex-wrap:wrap;
  padding:var(--sp-3) var(--sp-5); background:var(--surface-2);
  border-bottom:1px solid var(--border);
}
.toolbar .tb-label{ font-size:var(--fs-sm); color:var(--text-2); }
.toolbar .tb-spacer{ flex:1 1 auto; }
.toolbar select,.toolbar .ipt{ height:28px; width:auto; min-width:110px; }

/* 分段控件 */
.seg{ display:inline-flex; background:var(--surface-3); border-radius:var(--r-md); padding:2px; }
.seg button{
  border:none; background:transparent; padding:0 12px; height:26px; border-radius:var(--r-sm);
  font-size:var(--fs-sm); color:var(--text-2); cursor:pointer; font-family:inherit;
}
.seg button.on{ background:var(--surface); color:var(--brand-700); font-weight:600; box-shadow:var(--sh-1); }

/* ---------- 徽章 / 标签 ---------- */
.badge{
  display:inline-flex; align-items:center; gap:4px; padding:1px 8px; border-radius:var(--r-full);
  font-size:var(--fs-xs); line-height:18px; border:1px solid transparent; white-space:nowrap;
}
.badge.ok{ background:var(--ok-50); color:var(--ok-700); border-color:#c2e7d1; }
.badge.warn{ background:var(--warn-50); color:var(--warn-700); border-color:#f5dcae; }
.badge.bad{ background:var(--bad-50); color:var(--bad-700); border-color:#f7c9c9; }
.badge.info{ background:var(--info-50); color:var(--brand-700); border-color:var(--brand-100); }
.badge.mute{ background:var(--surface-3); color:var(--text-2); border-color:var(--border); }
.dot{ width:8px;height:8px;border-radius:50%;display:inline-block; }
.dot.ok{ background:var(--ok-600); } .dot.warn{ background:var(--warn-600); }
.dot.bad{ background:var(--bad-600); } .dot.mute{ background:var(--gray-300); }

/* ---------- 表格 ---------- */
.table-wrap{ overflow-x:auto; }
table.tb{ width:100%; border-collapse:collapse; font-size:var(--fs-md); }
table.tb th{
  text-align:left; font-weight:600; color:var(--text-2); font-size:var(--fs-sm);
  background:var(--surface-2); padding:10px 12px; border-bottom:1px solid var(--border);
  white-space:nowrap; position:sticky; top:0; z-index:1;
}
table.tb td{ padding:9px 12px; border-bottom:1px solid var(--gray-100); vertical-align:middle; }
table.tb tbody tr:hover{ background:var(--surface-2); }
table.tb tbody tr.sel{ background:var(--brand-50); }
table.tb .ta-c{ text-align:center; } .ta-r{ text-align:right; }
table.tb .td-ops{ white-space:nowrap; }
table.tb .td-ops .btn{ margin-right:4px; }
table.tb .num{ font-variant-numeric:tabular-nums; }
.tb-foot{
  display:flex; align-items:center; gap:var(--sp-3); padding:var(--sp-3) var(--sp-5);
  border-top:1px solid var(--border); font-size:var(--fs-sm); color:var(--text-2); flex-wrap:wrap;
}
.tb-foot .tf-spacer{ flex:1 1 auto; }

/* 空状态 */
.empty{
  padding:var(--sp-10) var(--sp-5); text-align:center; color:var(--text-3);
}
.empty .em-ico{
  width:52px;height:52px;margin:0 auto var(--sp-3);border-radius:50%;
  background:var(--surface-3); display:flex;align-items:center;justify-content:center;
}
.empty .em-title{ color:var(--text-2); font-size:var(--fs-lg); margin-bottom:4px; }

/* ---------- 模态 / 抽屉 ---------- */
.modal-mask{
  position:fixed; inset:0; background:rgba(15,23,42,.45); z-index:100;
  display:flex; align-items:center; justify-content:center; padding:var(--sp-5);
  animation:fadeIn .15s var(--ease);
}
.modal{
  background:var(--surface); border-radius:var(--r-xl); box-shadow:var(--sh-3);
  width:640px; max-width:100%; max-height:88vh; display:flex; flex-direction:column;
  animation:popIn .18s var(--ease);
}
@keyframes popIn{ from{opacity:0;transform:scale(.97) translateY(6px);} to{opacity:1;transform:none;} }
.modal.wide{ width:900px; } .modal.narrow{ width:440px; }
.modal-head{
  padding:var(--sp-4) var(--sp-5); border-bottom:1px solid var(--border);
  display:flex; align-items:center; gap:var(--sp-3);
}
.modal-head .mh-title{ font-size:var(--fs-xl); font-weight:600; }
.modal-head .mh-x{ margin-left:auto; cursor:pointer; color:var(--text-3); font-size:18px; line-height:1; }
.modal-head .mh-x:hover{ color:var(--text); }
.modal-body{ padding:var(--sp-5); overflow-y:auto; flex:1 1 auto; }
.modal-foot{
  padding:var(--sp-3) var(--sp-5); border-top:1px solid var(--border);
  display:flex; justify-content:flex-end; gap:var(--sp-2); background:var(--surface-2);
  border-radius:0 0 var(--r-xl) var(--r-xl);
}

/* ---------- Toast ---------- */
#toast-box{
  position:fixed; top:16px; left:50%; transform:translateX(-50%);
  z-index:200; display:flex; flex-direction:column; gap:8px; align-items:center; pointer-events:none;
}
.toast{
  background:var(--gray-800); color:#fff; padding:8px 16px; border-radius:var(--r-md);
  font-size:var(--fs-md); box-shadow:var(--sh-3); animation:popIn .15s var(--ease);
}
.toast.ok{ background:var(--ok-600); } .toast.bad{ background:var(--bad-600); }
.toast.warn{ background:var(--warn-600); } .toast.info{ background:var(--brand-600); }

/* ---------- 标签页 ---------- */
.tabs{ display:flex; gap:var(--sp-1); border-bottom:1px solid var(--border); margin-bottom:var(--sp-4); }
.tabs .tab{
  padding:8px 14px; cursor:pointer; font-size:var(--fs-md); color:var(--text-2);
  border-bottom:2px solid transparent; margin-bottom:-1px;
}
.tabs .tab:hover{ color:var(--text); }
.tabs .tab.on{ color:var(--brand-700); border-bottom-color:var(--brand-600); font-weight:600; }

/* ---------- 图片网格 ---------- */
.img-grid{ display:grid; grid-template-columns:repeat(auto-fill,minmax(140px,1fr)); gap:var(--sp-3); }
.img-cell{
  position:relative; border:1px solid var(--border); border-radius:var(--r-md);
  overflow:hidden; background:var(--surface-3); aspect-ratio:4/3;
}
.img-cell img{ width:100%;height:100%;object-fit:cover; display:block; cursor:zoom-in; }
.img-cell .ic-cap{
  position:absolute; left:0; right:0; bottom:0; background:rgba(15,23,42,.6); color:#fff;
  font-size:var(--fs-xs); padding:3px 6px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.img-cell .ic-x{
  position:absolute; top:4px; right:4px; width:20px;height:20px;border-radius:50%;
  background:rgba(15,23,42,.6); color:#fff; display:flex;align-items:center;justify-content:center;
  cursor:pointer; font-size:12px;
}

/* ---------- 进度条 ---------- */
.bar{ height:6px; background:var(--surface-3); border-radius:var(--r-full); overflow:hidden; }
.bar > i{ display:block; height:100%; background:var(--brand-600); border-radius:var(--r-full); }
.bar.ok > i{ background:var(--ok-600); } .bar.warn > i{ background:var(--warn-600); }
.bar.bad > i{ background:var(--bad-600); }

/* ---------- 时间线 ---------- */
.timeline{ position:relative; padding-left:20px; }
.timeline::before{ content:""; position:absolute; left:5px; top:4px; bottom:4px; width:1px; background:var(--border); }
.timeline .tl-item{ position:relative; padding-bottom:var(--sp-4); }
.timeline .tl-item::before{
  content:""; position:absolute; left:-19px; top:6px; width:9px;height:9px;border-radius:50%;
  background:var(--brand-600); border:2px solid var(--surface);
}
.timeline .tl-time{ font-size:var(--fs-xs); color:var(--text-3); }

/* ---------- 键值对 ---------- */
.kv{ display:grid; grid-template-columns:auto 1fr; gap:6px var(--sp-4); font-size:var(--fs-md); }
.kv dt{ color:var(--text-2); } .kv dd{ margin:0; }

/* ---------- 载入中 ---------- */
.loading{ padding:var(--sp-10); text-align:center; color:var(--text-3); }
.spinner{
  width:22px;height:22px;border:2px solid var(--gray-200);border-top-color:var(--brand-600);
  border-radius:50%; display:inline-block; animation:spin .7s linear infinite;
}
@keyframes spin{ to{ transform:rotate(360deg); } }

/* ---------- 打印 ---------- */
@media print{
  .sidebar,.topbar,.no-print{ display:none !important; }
  .content{ padding:0; max-width:none; }
  .card{ box-shadow:none; border-color:#ddd; }
}
