/* admin 的页面样式（从 templates/admin.html.html 的内联 <style> 外置而来）
 *
 * ⚠ 为什么要外置：内联 CSS 没法单独缓存 —— 每页访问都要重新下载、
 *   重新解析。一个达人主页原本 72KB，其中 31KB 就是这段。
 *   外置后浏览器缓存它，换页/回头再访都不再下载。
 * ⚠ 改样式请改**这个文件**，改 templates/admin.html.html 里的内联块无效
 *   （外置脚本已经把那段搬走了）。
 */
  /* ── 统计卡片 ───────────────────────────────────────── */
  .stat-grid {
    display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px;
    padding: 14px 16px 4px;
  }
  .stat {
    background: var(--surface); border-radius: var(--radius-sm);
    padding: 11px 10px; text-align: center; box-shadow: var(--shadow);
  }
  .stat .n { font-family: var(--serif); font-size: 22px; line-height: 1.15; font-weight: 600; }
  .stat .l { font-size: 11.5px; color: var(--text-3); margin-top: 3px; }
  .stat.accent .n { color: var(--accent); }
  .stat-sub {
    display: flex; flex-wrap: wrap; gap: 6px 12px; padding: 10px 18px 0;
    font-size: 12px; color: var(--text-3);
  }
  .stat-sub b { color: var(--text-2); font-weight: 600; }

  /* ── 筛选 ───────────────────────────────────────────── */
  .filter-bar { padding: 14px 16px 0; }
  .search {
    display: flex; align-items: center; gap: 8px; padding: 0 12px;
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    background: var(--surface); margin-bottom: 11px;
  }
  .search svg { width: 16px; height: 16px; color: var(--text-3); flex: none; }
  .search input {
    flex: 1; border: none; background: none; outline: none;
    /* 16px 是 iOS 不自动放大输入框的下限；内边距 11→10px 抵消长高的一行 */
    padding: 10px 0; font-size: 16px; color: var(--text); min-width: 0;
  }
  .chips { display: flex; gap: 7px; overflow-x: auto; padding-bottom: 3px; }
  .chips::-webkit-scrollbar { display: none; }
  .chip {
    flex: none; padding: 7px 14px; border-radius: 999px; font-size: 13px;
    border: 1px solid var(--border); background: var(--surface);
    color: var(--text-2); white-space: nowrap; cursor: pointer;
    transition: all .2s var(--ease);
    display: inline-flex; align-items: center; gap: 6px;
  }
  /* 主题 chip 上的色卡小圆点：一眼看出这个外观长什么样 */
  .chip .swatch {
    width: 12px; height: 12px; border-radius: 50%; flex: none;
    box-shadow: inset 0 0 0 1px rgba(0,0,0,.12);
  }
  .chip.on { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }

  /* ── 列表 ───────────────────────────────────────────── */
  .list { padding: 12px 16px 96px; }
  .row {
    display: flex; gap: 12px; align-items: flex-start;
    background: var(--surface); border-radius: var(--radius-sm);
    padding: 13px; margin-bottom: 9px; box-shadow: var(--shadow);
    position: relative;
  }
  .row .ava {
    width: 46px; height: 46px; border-radius: 13px; flex: none;
    object-fit: cover; background: var(--surface-2);
    display: grid; place-items: center; color: var(--text-3); font-size: 17px;
    font-family: var(--serif); overflow: hidden;
  }
  .row .ava svg { width: 20px; height: 20px; }
  /* 「我的」卡片里的头像图：铺满 .ava 那个方框（容器本身不变，图片坏了就消失） */
  .row .ava img { width: 100%; height: 100%; object-fit: cover; }
  .row .body { flex: 1; min-width: 0; }
  .row .nm { font-size: 15.5px; font-weight: 600; display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
  .row .nm .tg {
    font-size: 10.5px; font-weight: 500; padding: 1px 7px; border-radius: 999px;
    /* 浅底上的强调文字用更深一档（--accent 压在 accent-soft 上只有 4.8:1） */
    background: var(--accent-soft); color: var(--accent-2);
  }
  .row .nm .tg.off { background: var(--surface-2); color: var(--text-3); }
  .row .nm .tg.del { background: rgba(192,57,43,.12); color: #C0392B; }
  .row .nm .tg.ok { background: rgba(46,125,50,.13); color: #2E7D32; }
  .row .nm .tg.warn { background: rgba(214,158,46,.15); color: #B07818; }
  .row .mt {
    font-size: 12.5px; color: var(--text-2); margin-top: 3px; line-height: 1.5;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .row .mt .slug { color: var(--text-3); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11.5px; }
  .row .acts { display: flex; gap: 6px; margin-top: 9px; flex-wrap: wrap; }
  .mini {
    border: 1px solid var(--border); background: var(--surface);
    color: var(--text-2); font-size: 12px; padding: 5px 11px;
    border-radius: 999px; cursor: pointer; transition: all .18s var(--ease);
  }
  .mini:active { transform: scale(.96); }
  .mini.primary { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
  .mini.danger { color: #C0392B; border-color: rgba(192,57,43,.35); }
  /* 触摸设备上的小按钮要够大才点得中（P3-5）。
     .mini 桌面态只有 ~29px 高，低于移动端 44px 的触摸目标推荐值；
     手指点「重置密码」「停用」这种小药丸很容易点空、点错旁边的按钮。
     只在**粗指针**（真手指）下放大 —— 桌面鼠标 29px 完全够用，观感不变。
     ⚠ 靠 min-height + padding 真实撑高，而不是 ::after 撑热区：
        伪元素扩出来的热区会和相邻按钮的热区重叠，点在两个按钮之间会命中错的那个。 */
  @media (pointer: coarse) {
    .mini {
      padding: 12px 16px; font-size: 13.5px;
      min-height: 44px; display: inline-flex; align-items: center;
    }
    .row .acts { gap: 10px; }
  }
  /* 保存中：按钮要真的.disabled，同时给个看得出来的灰（对齐 app.css 的 .btn[disabled]） */
  .mini[disabled] { opacity: .45; pointer-events: none; }
  .empty { text-align: center; padding: 56px 20px; color: var(--text-3); font-size: 13.5px; line-height: 1.8; }
  .empty svg { width: 34px; height: 34px; margin-bottom: 10px; opacity: .5; }

  /* ── 页签 ───────────────────────────────────────────── */
  /* 四个页签在 390px 窄屏上刚好排得下，再窄的老机器（320px）会挤爆。
     跟 .chips 一个办法：允许横向滚动，但不显示滚动条。 */
  .tabs { display: flex; gap: 6px; padding: 14px 16px 0; overflow-x: auto; }
  .tabs::-webkit-scrollbar { display: none; }
  .tab {
    flex: none; padding: 7px 15px; border-radius: 999px; font-size: 13px;
    border: 1px solid var(--border); background: var(--surface);
    color: var(--text-2); cursor: pointer; transition: all .2s var(--ease);
  }
  .tab.on { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }

  /* ── 多选与批量操作 ─────────────────────────────────── */
  .row .pick {
    width: 20px; height: 20px; flex: none; margin-top: 13px;
    accent-color: var(--accent); cursor: pointer;
  }
  .row.sel { box-shadow: 0 0 0 2px var(--accent-soft), var(--shadow); }
  .batch-bar {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 80;
    display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
    padding: 10px 14px calc(10px + env(safe-area-inset-bottom));
    background: var(--surface); border-top: 1px solid var(--border);
    box-shadow: 0 -6px 24px rgba(0,0,0,.08);
  }
  .batch-bar .n { font-size: 12.5px; color: var(--text-2); font-weight: 600; }
  .batch-bar .acts { display: flex; gap: 6px; flex-wrap: wrap; margin-left: auto; }

  /* ── 操作记录 ───────────────────────────────────────── */
  .alog { padding: 11px 14px; border-bottom: 1px solid var(--border); }
  .alog:last-child { border-bottom: none; }
  .alog .h { display: flex; gap: 8px; align-items: baseline; flex-wrap: wrap; }
  .alog .act { font-size: 12px; font-weight: 600; color: var(--accent); }
  .alog .who { font-size: 12px; color: var(--text-2); }
  .alog .when { font-size: 11.5px; color: var(--text-3); margin-left: auto; }
  .alog .what { font-size: 12.5px; color: var(--text-2); margin-top: 4px; line-height: 1.65; word-break: break-word; }
  .alog .what code {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11.5px;
    background: var(--surface-2); padding: 1px 5px; border-radius: 5px;
  }

  /* ── 编辑抽屉 ───────────────────────────────────────── */
  /* 遮罩关闭态必须彻底退出交互层：只靠 opacity:0 的话，这个固定定位层
     仍然会吃掉页面中央的点击（老坑）。所以 opacity + visibility +
     pointer-events 三件套一起上。 */
  .mask {
    position: fixed; inset: 0; background: rgba(20,20,26,.42); z-index: 90;
    opacity: 0; visibility: hidden; pointer-events: none;
    transition: opacity .28s var(--ease), visibility 0s linear .28s;
  }
  .mask.on {
    opacity: 1; visibility: visible; pointer-events: auto;
    transition: opacity .28s var(--ease), visibility 0s;
  }
  .sheet {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 91;
    background: var(--surface); border-radius: 20px 20px 0 0;
    max-height: 92vh; display: flex; flex-direction: column;
    transform: translateY(100%); transition: transform .34s var(--ease), visibility 0s linear .34s;
    box-shadow: 0 -8px 40px rgba(0,0,0,.18);
    /* 关闭态彻底移出可聚焦序列：不写 visibility 的话，
       Tab 还能走进抽屉里的输入框（那是「碰巧」而不是焦点陷阱）。 */
    visibility: hidden;
  }
  .sheet.on {
    transform: translateY(0); visibility: visible;
    transition: transform .34s var(--ease), visibility 0s;
  }
  .sheet-head {
    display: flex; align-items: center; gap: 10px; padding: 14px 16px 10px;
    border-bottom: 1px solid var(--border); flex: none;
  }
  .sheet-head .t { font-size: 16px; font-weight: 600; flex: 1; }
  .sheet-body { overflow-y: auto; padding: 16px; -webkit-overflow-scrolling: touch; }
  .sheet-foot {
    padding: 12px 16px calc(12px + env(safe-area-inset-bottom));
    border-top: 1px solid var(--border); display: flex; gap: 10px; flex: none;
    background: var(--surface);
  }
  .sheet-foot .btn { flex: 1; justify-content: center; }
  @media (min-width: 860px) {
    .sheet {
      left: auto; right: 0; top: 0; bottom: 0; width: 460px;
      border-radius: 0; transform: translateX(100%); max-height: none;
    }
    .sheet.on { transform: translateX(0); }
  }

  /* 确认弹层：关闭时必须彻底退出交互层（否则隐形遮罩会吃掉页面中央的点击） */
  .confirm-sheet {
    position: fixed; left: 50%; top: 50%; z-index: 92;
    width: min(92vw, 340px);
    background: var(--surface); border-radius: 18px;
    box-shadow: 0 18px 60px rgba(0, 0, 0, .28);
    transform: translate(-50%, -50%) scale(.94);
    opacity: 0; visibility: hidden; pointer-events: none;
    transition: opacity .22s var(--ease), transform .22s var(--ease), visibility 0s linear .22s;
  }
  .confirm-sheet.on {
    transform: translate(-50%, -50%) scale(1);
    opacity: 1; visibility: visible; pointer-events: auto;
    transition: opacity .22s var(--ease), transform .22s var(--ease), visibility 0s;
  }

  /* 重置密码弹层：内容多（临时密码 + 8 个恢复码），所以比确认框宽、能滚。
     同样遵守「关闭态必须彻底退出交互层」——只设 opacity:0 的话，
     这个居中弹层会安静地吃掉页面中央的点击（老坑）。 */
  .pw-sheet {
    position: fixed; left: 50%; top: 50%; z-index: 92;
    width: min(92vw, 420px); max-height: 86vh; overflow-y: auto;
    background: var(--surface); border-radius: 18px;
    box-shadow: 0 18px 60px rgba(0, 0, 0, .28);
    transform: translate(-50%, -50%) scale(.94);
    opacity: 0; visibility: hidden; pointer-events: none;
    transition: opacity .22s var(--ease), transform .22s var(--ease), visibility 0s linear .22s;
  }
  .pw-sheet.on {
    transform: translate(-50%, -50%) scale(1);
    opacity: 1; visibility: visible; pointer-events: auto;
    transition: opacity .22s var(--ease), transform .22s var(--ease), visibility 0s;
  }
  .pw-secret {
    display: flex; align-items: center; gap: 10px; margin: 10px 0 16px;
    padding: 14px 16px; border-radius: var(--radius-sm);
    background: var(--surface-2); border: 1px dashed var(--border-2);
  }
  .pw-secret .v {
    flex: 1; font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 20px; font-weight: 600; letter-spacing: 1.5px; word-break: break-all;
  }
  .pw-codes {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; margin: 10px 0 14px;
  }
  .pw-codes .c {
    padding: 9px 10px; border-radius: 10px; background: var(--bg);
    border: 1px solid var(--border);
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 13.5px; letter-spacing: 1px; text-align: center;
  }

  /* ── 表单 ───────────────────────────────────────────── */
  .fld { margin-bottom: 14px; }
  .fld > label { display: block; font-size: 12.5px; color: var(--text-2); margin-bottom: 6px; font-weight: 500; }
  .fld .hint { font-size: 11.5px; color: var(--text-3); margin-top: 5px; }
  .fld textarea { min-height: 88px; resize: vertical; line-height: 1.6; }
  .row2 { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 10px; }

  /* 上传图片按钮行：输入框 + 按钮并排（窄屏按钮换行独占一行，不许溢出） */
  .up-row { display: flex; gap: 9px; align-items: stretch; }
  .up-row .input { flex: 1; min-width: 0; }
  .up-row .btn { flex: none; min-height: 40px; padding-left: 16px; padding-right: 16px; }
  .up-row .btn svg { width: 16px; height: 16px; }
  @media (max-width: 420px) {
    .up-row { flex-wrap: wrap; }
    .up-row .btn { width: 100%; }
  }
  .switch {
    display: flex; align-items: center; gap: 10px; padding: 12px 13px;
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    background: var(--surface-2); cursor: pointer;
  }
  .switch .track {
    width: 44px; height: 26px; border-radius: 999px; background: var(--border);
    position: relative; flex: none; transition: background .25s var(--ease);
  }
  .switch .track::after {
    content: ""; position: absolute; top: 3px; left: 3px; width: 20px; height: 20px;
    border-radius: 50%; background: #fff; transition: transform .25s var(--ease);
    box-shadow: 0 1px 3px rgba(0,0,0,.2);
  }
  .switch.on .track { background: var(--accent); }
  .switch.on .track::after { transform: translateX(18px); }
  .switch .sw-t { font-size: 14px; }
  .switch .sw-s { font-size: 11.5px; color: var(--text-3); margin-top: 2px; }

  .hl-row { display: flex; gap: 8px; margin-bottom: 8px; }
  .hl-row .input { flex: 1; }
  .hl-row .n {
    width: 26px; height: 26px; border-radius: 50%; background: var(--accent-soft);
    color: var(--accent-2); display: grid; place-items: center; font-size: 12px;
    font-family: var(--serif); flex: none; margin-top: 8px;
  }

  .tagbox {
    display: flex; flex-wrap: wrap; gap: 7px; padding: 9px; min-height: 44px;
    border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--bg);
    align-items: center; cursor: text;
    transition: border-color .22s var(--ease), box-shadow .22s var(--ease);
  }
  .tagbox:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
  .tagbox .tag {
    display: inline-flex; align-items: center; gap: 5px; background: var(--accent-soft);
    color: var(--accent-2); border-radius: 999px; padding: 4px 6px 4px 11px; font-size: 12.5px;
  }
  .tagbox .tag button { color: var(--accent-2); opacity: .6; display: grid; place-items: center; }
  .tagbox .tag button:hover { opacity: 1; }
  .tagbox .tag svg { width: 12px; height: 12px; }
  .tagbox input {
    flex: 1; min-width: 90px; border: none; background: none; outline: none;
    /* 16px 是 iOS 不自动放大输入框的下限 */
    padding: 3px 2px; font-size: 16px;
  }

  /* ── 无权限 / 登录态 ───────────────────────────────── */
  .gate { text-align: center; padding: 76px 28px 40px; }
  .gate .mark {
    width: 62px; height: 62px; border-radius: 19px; margin: 0 auto 18px;
    background: var(--accent-soft); color: var(--accent-2); display: grid; place-items: center;
  }
  .gate .mark svg { width: 28px; height: 28px; }
  .gate h2 { font-family: var(--serif); font-size: 21px; margin-bottom: 8px; }
  .gate p { font-size: 13.5px; color: var(--text-2); line-height: 1.75; margin-bottom: 22px; }

  /* ── 宽屏铺开（2026-10-28）────────────────────────────────────
     管理页**没有左侧说明栏**，不能落进 app.css 的两栏网格。
     那个网格是给「登录 / 建主页 / 编辑 / 找回密码」四页设计的：
     内容进第 2 列（宽 560px），侧栏进第 1 列。管理页没有侧栏，
     结果就是**左半屏整列空着** —— 实测 1440 宽时左边空 712px、
     右边内容只有 603px，看着像没做完。
     这里改成单栏铺开：容器放宽到 1240px，列表在宽屏下变双列，
     富余宽度真正被用上（而不是把一行拉长、右侧拖一大片空白）。
     实现说明：app.css 的 .app 在 960px 断点上是 display:grid，
     这里改回 display:block —— 网格列规则（grid-column）对非网格项
     直接失效，不用去跟 :not() 选择器比特异性。 */
  @media (min-width: 960px) {
    .app { display: block; max-width: 1240px; }
  }
  @media (min-width: 1080px) {
    /* 三张同构卡片列表变双列；「我的」和「操作记录」结构不同，保持单列 */
    #list, #reviewList, #userList {
      display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
      gap: 10px; align-content: start;
    }
    #list .row, #reviewList .row, #userList .row { margin-bottom: 0; }
  }
