/* ============================================================
   ui.css — 平台/引擎共用的基础交互组件层
   ------------------------------------------------------------
   设计原则：
   1) 只依赖 CSS 变量，不写死颜色。平台(style.css)定义 --brand/--ink/--line…
      引擎(admin.css)定义 --primary/--text-primary/--card-border…
      本文件开头把两套变量映射成统一别名，因此同一份组件代码两侧都能用。
   2) 不改任何已有类名的行为，纯新增。出问题删掉本文件引用即可回退。
   3) 图标一律用字符/内联 SVG，不依赖 FontAwesome（离线内网可用）。
   ============================================================ */

/* ---------- 变量别名：兼容平台(blue) 与引擎(indigo) 两套体系 ---------- */
:root {
  /* 若宿主页没定义 --brand，就退回引擎侧变量，最后兜底一个蓝色 */
  --ui-accent:      var(--brand, var(--primary, #2563eb));
  --ui-accent-dark: var(--brand-dark, var(--primary-hover, #1d4ed8));
  --ui-accent-soft: var(--brand-soft, var(--primary-light, #eff6ff));
  --ui-ink:         var(--ink, var(--text-primary, #0f172a));
  --ui-muted:       var(--muted, var(--text-muted, #64748b));
  --ui-line:        var(--line, var(--card-border, #e2e8f0));
  --ui-card:        var(--card, var(--card-bg, #fff));
  --ui-danger:      var(--danger, #dc2626);
  --ui-ok:          var(--ok, var(--success, #16a34a));
  --ui-warn:        var(--warn, var(--warning, #d97706));
  --ui-radius:      var(--radius, 12px);
  --ui-shadow:      0 10px 30px rgba(15, 23, 42, .14);
}

/* ============================================================
   1) 表格横向滚动兜底
   43 个后台表格在 375px 手机上会横向撑破页面。给所有 table 加一层
   滚动容器最稳，但逐个包 HTML 改动面太大 —— 这里用「给 table 的
   直接父元素上滚动」不可行（父元素还装标题等）。
   折中：给 table 自身设 display:block + overflow-x:auto（窄屏才启用），
   宽屏恢复 table 布局，桌面视觉零变化。
   ============================================================ */
@media (max-width: 900px) {
  /* 显式包裹的容器（推荐做法，优先用这个） */
  .table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .table-wrap > table { min-width: 560px; }

  /* 没包裹的表格兜底：窄屏转为可横向滚动的块 */
  main table:not(.compare):not(.no-scroll),
  .main table:not(.compare):not(.no-scroll),
  .content table:not(.compare):not(.no-scroll) {
    display: block;
    width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    white-space: nowrap;
  }
  /* display:block 会让 table 失去自动列宽，手动补回来 */
  main table:not(.compare):not(.no-scroll) tbody,
  .main table:not(.compare):not(.no-scroll) tbody {
    display: table;
    width: 100%;
    min-width: 560px;
  }
}

/* ============================================================
   2) Toast 轻提示
   替代散落各页的内联提示。JS 侧调用 UI.toast('已保存')。
   ============================================================ */
#ui-toast-host {
  position: fixed; top: 16px; right: 16px; z-index: 9999;
  display: flex; flex-direction: column; gap: 10px;
  max-width: min(360px, calc(100vw - 32px));
  pointer-events: none;
}
.ui-toast {
  pointer-events: auto;
  display: flex; align-items: flex-start; gap: 10px;
  background: #111827; color: #fff;
  padding: 12px 14px; border-radius: 10px;
  box-shadow: var(--ui-shadow);
  font-size: 16px; line-height: 1.6;
  animation: ui-toast-in .22s ease-out;
}
.ui-toast.is-out { animation: ui-toast-out .18s ease-in forwards; }
.ui-toast .ui-toast-body { flex: 1; min-width: 0; word-break: break-word; }
.ui-toast .ui-toast-close {
  background: none; border: 0; color: inherit; opacity: .6;
  cursor: pointer; font-size: 20.7px; line-height: 1; padding: 0 2px;
}
.ui-toast .ui-toast-close:hover { opacity: 1; }
.ui-toast.ok   { background: #065f46; }
.ui-toast.err  { background: #991b1b; }
.ui-toast.warn { background: #92400e; }
@keyframes ui-toast-in  { from { opacity: 0; transform: translateY(-8px); } to { opacity: 1; transform: none; } }
@keyframes ui-toast-out { to { opacity: 0; transform: translateY(-8px); } }

/* ============================================================
   3) 通用确认/表单弹窗（替代原生 confirm）
   ============================================================ */
.ui-modal-mask {
  position: fixed; inset: 0; z-index: 9998;
  background: rgba(15, 23, 42, .5);
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
  animation: ui-fade-in .16s ease-out;
}
.ui-modal {
  background: var(--ui-card); color: var(--ui-ink);
  border-radius: var(--ui-radius);
  box-shadow: var(--ui-shadow);
  width: 100%; max-width: 420px;
  max-height: calc(100vh - 40px); overflow: auto;
  animation: ui-modal-in .18s ease-out;
}
.ui-modal-hd { padding: 18px 20px 0; font-size: 20.7px; font-weight: 600; }
.ui-modal-bd { padding: 10px 20px 4px; color: var(--ui-muted); font-size: 16px; line-height: 1.7; }
.ui-modal-bd p { margin: 0 0 10px; }
.ui-modal-ft {
  padding: 16px 20px 18px; display: flex; gap: 10px;
  justify-content: flex-end; flex-wrap: wrap;
}
.ui-modal-ft .btn { min-width: 84px; text-align: center; }
/* 危险操作：按钮红色强调 */
.ui-modal.is-danger .ui-modal-hd { color: var(--ui-danger); }
.ui-modal .btn.ui-danger { background: var(--ui-danger); border-color: var(--ui-danger); color: #fff; }
.ui-modal .btn.ui-danger:hover { filter: brightness(.92); }
@keyframes ui-fade-in  { from { opacity: 0; } to { opacity: 1; } }
@keyframes ui-modal-in { from { opacity: 0; transform: translateY(10px) scale(.98); } to { opacity: 1; transform: none; } }

@media (max-width: 480px) {
  .ui-modal-mask { align-items: flex-end; padding: 0; }
  .ui-modal { max-width: none; border-radius: var(--ui-radius) var(--ui-radius) 0 0; }
  .ui-modal-ft { position: sticky; bottom: 0; background: var(--ui-card); }
  .ui-modal-ft .btn { flex: 1; }
}

/* ============================================================
   4) 加载态：按钮忙碌 + 页面遮罩 + 骨架屏
   ============================================================ */
.btn.is-busy { position: relative; color: transparent !important; pointer-events: none; }
.btn.is-busy::after {
  content: ""; position: absolute; top: 50%; left: 50%;
  width: 16px; height: 16px; margin: -8px 0 0 -8px;
  border: 2px solid rgba(255, 255, 255, .45);
  border-top-color: #fff; border-radius: 50%;
  animation: ui-spin .7s linear infinite;
}
.btn.ghost.is-busy::after, .btn.gray.is-busy::after {
  border-color: rgba(37, 99, 235, .3); border-top-color: var(--ui-accent);
}
@keyframes ui-spin { to { transform: rotate(360deg); } }

.ui-busy-mask {
  position: fixed; inset: 0; z-index: 9997;
  background: rgba(255, 255, 255, .72);
  display: flex; align-items: center; justify-content: center;
  flex-direction: column; gap: 12px; color: var(--ui-muted); font-size: 16px;
}
.ui-busy-mask::before {
  content: ""; width: 30px; height: 30px;
  border: 3px solid var(--ui-line); border-top-color: var(--ui-accent);
  border-radius: 50%; animation: ui-spin .8s linear infinite;
}

/* 骨架屏：用于列表/卡片首屏占位 */
.ui-skeleton {
  background: linear-gradient(90deg, #eef2f7 25%, #f6f8fb 37%, #eef2f7 63%);
  background-size: 400% 100%;
  animation: ui-shimmer 1.4s ease-in-out infinite;
  border-radius: 6px; display: block; height: 14px;
}
.ui-skeleton.line  { margin-bottom: 8px; }
.ui-skeleton.title { height: 20px; width: 40%; margin-bottom: 14px; }
@keyframes ui-shimmer { from { background-position: 100% 50%; } to { background-position: 0 50%; } }

/* ============================================================
   5) 统一分页器
   ============================================================ */
.ui-pager {
  display: flex; align-items: center; justify-content: center;
  gap: 6px; flex-wrap: wrap; margin: 22px 0 6px;
}
.ui-pager a, .ui-pager span.pg {
  min-width: 38px; height: 38px; padding: 0 12px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--ui-line); border-radius: 8px;
  background: var(--ui-card); color: var(--ui-ink);
  font-size: 16px; text-decoration: none;
}
.ui-pager a:hover { border-color: var(--ui-accent); color: var(--ui-accent); }
.ui-pager .is-current {
  background: var(--ui-accent); border-color: var(--ui-accent);
  color: #fff; font-weight: 600;
}
.ui-pager .is-disabled { opacity: .45; pointer-events: none; }
.ui-pager .pg-info { border: 0; background: none; color: var(--ui-muted); }

/* ============================================================
   6) 空状态（统一外观）
   ============================================================ */
.ui-empty {
  text-align: center; padding: 44px 20px;
  color: var(--ui-muted); font-size: 16px;
}
.ui-empty .ui-empty-ico { font-size: 39.1px; line-height: 1; opacity: .35; margin-bottom: 12px; }
.ui-empty .ui-empty-ttl { color: var(--ui-ink); font-size: 18.4px; font-weight: 600; margin-bottom: 6px; }
.ui-empty .btn { margin-top: 14px; }

/* ============================================================
   7) 无障碍：跳转到主内容（键盘用户不必 Tab 穿过整个导航）
   ============================================================ */
.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 10000;
  background: var(--ui-accent); color: #fff;
  padding: 10px 16px; border-radius: 0 0 8px 0; font-size: 16px;
}
.skip-link:focus { left: 0; color: #fff; }

/* ============================================================
   8) 危险按钮的 hover 态补齐（.btn.danger 已有，这里补 gh 态）
   ============================================================ */
.btn.danger:active { background: #fee2e2; }

/* ============================================================
   9) 表单防重复提交的视觉反馈
   ============================================================ */
form.is-submitting { pointer-events: none; opacity: .72; }
form.is-submitting .btn[type=submit] { cursor: wait; }
