/* ============ 老树云阅读 - 全局样式 ============ */
:root {
  --primary: #4f46e5;
  --primary-2: #7c3aed;
  --grad: linear-gradient(135deg, #4f46e5 0%, #7c3aed 55%, #c026d3 100%);
  --bg: #f4f5fb;
  --card: #ffffff;
  --text: #1f2330;
  --muted: #8a90a3;
  --line: #eceef4;
  --danger: #e5484d;
  --ok: #16a34a;
  --radius: 16px;
  --shadow: 0 4px 20px rgba(31, 35, 48, .06);
  --shadow-lg: 0 12px 40px rgba(79, 70, 229, .16);
}
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
    "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Arial, sans-serif;
  background: var(--bg);
  color: var(--text);
  -webkit-font-smoothing: antialiased;
  font-size: 15px;
  line-height: 1.6;
}
.hidden { display: none !important; }
.muted { color: var(--muted); }
.center { text-align: center; }
a { color: var(--primary); }

/* ---------- 认证页（桌面分栏 / 移动居中；全屏覆盖，不与其后页面上下堆叠） ---------- */
.auth-page {
  position: fixed; inset: 0; z-index: 100;
  min-height: 100vh; min-height: 100dvh; display: flex; align-items: stretch;
  background: var(--bg); overflow-y: auto;
}
.auth-hero {
  flex: 1.15; background: var(--grad); color: #fff;
  display: flex; align-items: center; justify-content: center;
  padding: 48px; position: relative; overflow: hidden;
}
.auth-hero::before {
  content: ""; position: absolute; inset: 0;
  background:
    radial-gradient(circle at 20% 20%, rgba(255,255,255,.16), transparent 40%),
    radial-gradient(circle at 80% 75%, rgba(255,255,255,.12), transparent 45%);
}
.auth-brand { position: relative; max-width: 480px; }
.logo-badge {
  width: 72px; height: 72px; border-radius: 20px; background: rgba(255,255,255,.18);
  backdrop-filter: blur(6px); display: flex; align-items: center; justify-content: center;
  font-size: 38px; margin-bottom: 22px; box-shadow: 0 8px 30px rgba(0,0,0,.18);
}
.auth-brand h1 { font-size: 34px; margin: 0 0 8px; letter-spacing: 1px; }
.tagline { opacity: .9; font-size: 16px; margin: 0 0 28px; }
.auth-features { list-style: none; padding: 0; margin: 0; }
.auth-features li {
  display: flex; align-items: center; gap: 12px; margin: 14px 0;
  font-size: 15px; opacity: .95;
}
.auth-features li span {
  width: 34px; height: 34px; border-radius: 10px; background: rgba(255,255,255,.18);
  display: flex; align-items: center; justify-content: center; font-size: 17px; flex-shrink: 0;
}
.auth-panel {
  flex: 1; display: flex; align-items: center; justify-content: center; padding: 40px 24px;
}
.auth-card {
  width: 100%; max-width: 380px; background: var(--card); border-radius: 22px;
  padding: 38px 34px; box-shadow: var(--shadow-lg);
}
.auth-logo { display: none; text-align: center; margin-bottom: 22px; }
.auth-logo img { width: 68px; height: 68px; border-radius: 18px; box-shadow: 0 6px 18px rgba(0,0,0,.18); }
.auth-logo .name { font-size: 20px; font-weight: 700; margin-top: 10px; }
.tabs { display: flex; background: #f0f2f8; border-radius: 12px; padding: 4px; margin-bottom: 22px; }
.tabs .t {
  flex: 1; text-align: center; padding: 9px; border-radius: 9px; cursor: pointer;
  color: var(--muted); font-weight: 600; transition: all .2s;
}
.tabs .t.active { background: #fff; color: var(--primary); box-shadow: 0 2px 8px rgba(0,0,0,.08); }

/* ---------- 表单 ---------- */
.form-group { margin-bottom: 16px; }
.form-group label { display: block; font-size: 13px; color: var(--muted); margin-bottom: 6px; font-weight: 600; }
.form-group input, .form-group select, .form-group textarea {
  width: 100%; padding: 11px 13px; border: 1.5px solid var(--line); border-radius: 11px;
  font-size: 15px; font-family: inherit; background: #fbfbfe; color: var(--text);
  outline: none; transition: border-color .15s, box-shadow .15s;
}
.form-group input:focus, .form-group select:focus, .form-group textarea:focus {
  border-color: var(--primary); box-shadow: 0 0 0 3px rgba(79,70,229,.12); background: #fff;
}
.form-group textarea { min-height: 90px; resize: vertical; }

/* ---------- 上传弹窗：一次多本的文件清单 ---------- */
/* 一行一本：名字占满、体积靠右。超限/失败标红，成功标绿。
   ★ 名字必须 min-width:0 + ellipsis：书名普遍很长，而 flex 子项默认
     min-width:auto 会把整串文字的宽度顶出去，把弹窗撑破（§14.83 同款坑）。 */
.up-list { margin-top: 10px; max-height: 216px; overflow-y: auto; }
.up-list:empty { display: none; }
.up-row {
  display: flex; align-items: center; gap: 8px; min-width: 0;
  padding: 6px 9px; margin-bottom: 4px; border-radius: 8px;
  background: var(--bg); border: 1px solid var(--line); font-size: 13px;
}
.up-row .up-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.up-row .up-size { flex: 0 0 auto; color: var(--muted); }
.up-row.bad { border-color: #f6c9cb; background: #fdf2f2; }
.up-row.bad .up-name, .up-row.bad .up-size { color: var(--danger); }
.up-row.ok { border-color: #c7e9d2; background: #f1faf4; }
.up-row.ok .up-size { color: var(--ok); }

/* ---------- 按钮 ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  border: none; cursor: pointer; font-size: 15px; font-weight: 600; font-family: inherit;
  padding: 11px 20px; border-radius: 11px; background: var(--grad); color: #fff;
  transition: transform .1s, box-shadow .2s, opacity .2s;
  box-shadow: 0 4px 14px rgba(79,70,229,.28);
}
.btn:hover { box-shadow: 0 6px 20px rgba(79,70,229,.38); transform: translateY(-1px); }
.btn:active { transform: translateY(0); }
.btn:disabled { opacity: .55; cursor: not-allowed; }
.btn.block { width: 100%; }
.btn.sm { padding: 8px 14px; font-size: 13px; border-radius: 9px; }
.btn.ghost { background: #f0f2f8; color: var(--text); box-shadow: none; }
.btn.ghost:hover { background: #e6e9f2; }
.btn.danger { background: var(--danger); box-shadow: 0 4px 14px rgba(229,72,77,.28); }

/* ---------- 主界面 ---------- */
.main-shell { min-height: 100vh; display: flex; flex-direction: column; }
.navbar {
  position: sticky; top: 0; z-index: 40; height: 60px;
  background: rgba(255,255,255,.86); backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--line);
  display: flex; align-items: center; justify-content: space-between; padding: 0 24px;
}
.nav-left { display: flex; align-items: center; gap: 10px; font-weight: 700; font-size: 17px; }
.logo-mini { width: 26px; height: 26px; border-radius: 7px; object-fit: cover; vertical-align: middle; }
.nav-title { font-weight: 600; }
.nav-links { display: flex; gap: 4px; }
.nav-links a {
  padding: 8px 16px; border-radius: 9px; cursor: pointer; font-weight: 600;
  color: var(--muted); font-size: 15px; transition: all .15s;
}
.nav-links a:hover { color: var(--primary); }
.nav-links a.active { color: var(--primary); background: #eef0ff; }
.nav-right { display: flex; align-items: center; gap: 12px; }
.avatar {
  width: 36px; height: 36px; border-radius: 50%; background: var(--grad); color: #fff;
  display: flex; align-items: center; justify-content: center; font-weight: 700; cursor: pointer;
  background-size: cover; background-position: center;
}
.avatar.big { width: 64px; height: 64px; font-size: 26px; }
.back { background: none; border: none; font-size: 15px; color: var(--primary); cursor: pointer; font-weight: 600; }

.content { flex: 1; width: 100%; max-width: 1200px; margin: 0 auto; padding: 28px 24px 90px; }

/* ---------- 书库 hero ---------- */
.hero { display: flex; align-items: flex-end; justify-content: space-between; gap: 20px; flex-wrap: wrap; margin-bottom: 20px; }
.hero h2, .page-head h2 { font-size: 26px; margin: 0 0 4px; }
.page-head { margin-bottom: 22px; }
.searchbar {
  display: flex; align-items: center; gap: 8px; background: #fff; border-radius: 13px;
  padding: 6px 8px 6px 14px; box-shadow: var(--shadow); border: 1.5px solid transparent;
  min-width: 320px; flex: 1; max-width: 480px;
}
.searchbar:focus-within { border-color: var(--primary); }
.search-ico { opacity: .5; }
.searchbar input { flex: 1; border: none; outline: none; font-size: 15px; background: transparent; }
.searchbar button { padding: 8px 18px; border-radius: 9px; }

/* ---------- 分类 chips ---------- */
.chips { display: flex; gap: 10px; overflow-x: auto; padding-bottom: 8px; margin-bottom: 22px; scrollbar-width: none; }
.chips::-webkit-scrollbar { display: none; }
.chip {
  flex-shrink: 0; padding: 8px 16px; border-radius: 999px; background: #fff; color: #565b6e;
  cursor: pointer; font-size: 14px; font-weight: 600; border: 1.5px solid var(--line);
  transition: all .18s; white-space: nowrap;
}
.chip:hover { border-color: var(--primary); color: var(--primary); }
.chip.active { background: var(--grad); color: #fff; border-color: transparent; box-shadow: 0 4px 12px rgba(79,70,229,.3); }
.chip[draggable="true"] { cursor: grab; }
.chip[draggable="true"]:active { cursor: grabbing; opacity: .6; }

/* ---------- 书籍网格 ---------- */
.grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 20px;
}
/* “我的阅读”网格：宽屏 8 列，平板 4 列，窄手机 3 列 */
.reading-grid {
  display: grid; grid-template-columns: repeat(8, 1fr); gap: 12px;
}
@media (max-width: 900px) { .reading-grid { grid-template-columns: repeat(4, 1fr); } }
@media (max-width: 420px) { .reading-grid { grid-template-columns: repeat(3, 1fr); } }
.book-card {
  background: #fff; border-radius: 14px; overflow: hidden; cursor: pointer;
  box-shadow: var(--shadow); transition: transform .18s, box-shadow .18s;
  border: 1px solid var(--line);
  -webkit-touch-callout: none; -webkit-user-select: none; user-select: none;
  touch-action: manipulation; -webkit-tap-highlight-color: transparent;
  /* 热度推荐里有声版的角标叠在封面角上（绝对定位） */
  position: relative;
}
/* 首页「热度推荐」里带有声版的卡片：角标叠在封面左上角。
   ★ 必须绝对定位、不能塞进 .info —— .info .t 有 min-height，
     塞进去会把那一张卡片顶高，同一排卡片参差不齐。 */
.hot-audio {
  position: absolute; left: 6px; top: 6px; z-index: 2;
  padding: 2px 7px; border-radius: 999px; font-size: 11px; font-weight: 600;
  background: rgba(17, 24, 39, .72); color: #fff;
}
.book-card:hover { transform: translateY(-4px); box-shadow: 0 14px 32px rgba(31,35,48,.13); }
.book-card .cover {
  width: 100%; aspect-ratio: 3/4; object-fit: cover; display: block; background: #eef0f6;
}
.book-card .cover.placeholder {
  display: flex; align-items: center; justify-content: center; text-align: center;
  color: #fff; font-weight: 700; font-size: 15px; padding: 14px; aspect-ratio: 3/4;
  text-shadow: 0 1px 3px rgba(0,0,0,.25);
}
.book-card .info { padding: 10px 12px 13px; }
.book-card .info .t {
  font-weight: 600; font-size: 14px; line-height: 1.4; margin-bottom: 4px;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  min-height: 39px;
}
.book-card .info .a {
  font-size: 12px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ---------- 分类卡片 ---------- */
.cat-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 18px;
}
.cat-card {
  background: #fff; border-radius: 16px; padding: 20px 22px; cursor: pointer; position: relative;
  overflow: hidden; box-shadow: var(--shadow); border: 1px solid var(--line);
  transition: transform .18s, box-shadow .18s;
}
.cat-card:hover { transform: translateY(-4px); box-shadow: 0 14px 32px rgba(31,35,48,.13); }
.cat-card .bar { position: absolute; left: 0; top: 0; bottom: 0; width: 5px; }
.cat-card .cname { font-weight: 700; font-size: 16px; margin-bottom: 4px; line-height: 1.4; }
.cat-card .ccode { font-size: 12px; color: var(--muted); }
.cat-card .ccount { margin-top: 12px; font-size: 14px; color: var(--primary); font-weight: 700; }

/* ---------- 书架页布局：桌面端「书架收藏」左 2/3 + 「公共书库」右 1/3 ---------- */
.shelf-layout { display: flex; gap: 24px; align-items: flex-start; }
.shelf-main { flex: 1 1 0; min-width: 0; order: 1; }
#shelf-public { flex: 0 0 33.333%; min-width: 0; order: 2; }
/* 书架收藏：每行 4 本；有声阅读：每行 3 本（JS 限制最多 4 行 = 12 本，多出翻页）
   ★ 板块宽度与原来的「公共书库」完全一致（1/3），只是内容换成了有声电子书。
   ★ 用户明确要求：3 本一行时**只缩小封面**，1/3 的板块宽度一个字都不许动。 */
.shelf-main .grid { grid-template-columns: repeat(4, 1fr); gap: 14px; }
#shelf-public .au-cats { margin-bottom: 10px; gap: 6px; }
#shelf-public .au-cat { padding: 4px 10px; font-size: 12px; }
/* 3 列（原来 2 列）。容器宽度不变 → 每格从 ~1/6 变成 ~1/9，
   封面靠 .au-cover 的 width:100% 自动跟着缩，不需要也不该去改 aside 的宽度。 */
#shelf-public .au-shelf-grid { grid-template-columns: repeat(3, 1fr); gap: 8px; }
/* 格子窄了，卡片内边距与字号要跟着收，否则书名会被挤成竖排 */
#shelf-public .au-shelf-card { padding: 6px; border-radius: 11px; }
#shelf-public .au-shelf-card .au-title { font-size: 11px; margin: 4px 0 1px; }
#shelf-public .au-shelf-card .au-sub { font-size: 10px; }
/* ★ 提示行不覆盖字号：让它跟「书架收藏」那行「已收藏 N / M 本」用同一套
   （两者都是 .page-head 里的 p.muted，继承同样的 15px 与灰色）。
   之前写死 12px，比旁边那行小一圈，看着像两个层级的东西。 */
/* 「查看全部」自己占一行，紧贴分类上方；page-head 的下边距收窄，免得中间空一大块 */
#shelf-public .page-head { margin-bottom: 8px; }
#shelf-public .au-shelf-more { margin: 0 0 10px; }
#shelf-public .pagination { margin-top: 12px; }
/* 书架收藏的自定义分类：分两行显示，缩小文字与按钮 */
.shelf-main .chips { flex-wrap: wrap; overflow-x: visible; gap: 6px; margin-bottom: 14px; padding-bottom: 0; }
.shelf-main .chip { padding: 3px 10px; font-size: 12px; border-radius: 999px; line-height: 1.4; }

/* ---------- 书架 ---------- */
.shelf-item {
  background: #fff; border-radius: 14px; overflow: hidden; cursor: pointer;
  box-shadow: var(--shadow); border: 1px solid var(--line);
  transition: transform .18s, box-shadow .18s; position: relative;
}
.shelf-item:hover { transform: translateY(-4px); box-shadow: 0 14px 32px rgba(31,35,48,.13); }
.shelf-item .cover { width: 100%; aspect-ratio: 3/4; object-fit: cover; background: #eef0f6; }
.shelf-item .sinfo { padding: 11px 12px 13px; }
.shelf-item .sinfo .t {
  font-weight: 600; font-size: 14px; line-height: 1.4;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; min-height: 39px;
}
.shelf-item .sinfo .a { font-size: 12px; color: var(--muted); margin-top: 3px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.shelf-item .shelf-edit {
  position: absolute; top: 8px; right: 8px; width: 32px; height: 32px; border-radius: 50%;
  background: rgba(255,255,255,.92); border: 1px solid var(--line); cursor: pointer; font-size: 15px;
  box-shadow: 0 2px 6px rgba(0,0,0,.12); display: flex; align-items: center; justify-content: center;
}
.shelf-item .shelf-edit:hover { border-color: var(--primary); color: var(--primary); }
.chip.chip-add { border-style: dashed; color: var(--primary); font-weight: 600; }
.progress-bar { height: 4px; background: #eef0f6; border-radius: 2px; margin-top: 9px; overflow: hidden; }
.progress-bar > i { display: block; height: 100%; background: var(--grad); border-radius: 2px; }

/* ---------- 详情 ---------- */
.detail-head { display: flex; gap: 22px; margin-bottom: 20px; }
.detail-head .cover {
  width: 160px; aspect-ratio: 3/4; object-fit: cover; border-radius: 12px; background: #eef0f6;
  box-shadow: 0 10px 26px rgba(0,0,0,.14); flex-shrink: 0;
}
.detail-head .meta { flex: 1; }
.detail-head .meta h2 { margin: 6px 0 12px; font-size: 22px; line-height: 1.4; }
.detail-head .meta .line { margin: 6px 0; font-size: 14px; }
.tag {
  display: inline-block; padding: 3px 10px; border-radius: 999px; background: #eef0ff; color: var(--primary);
  font-size: 12px; font-weight: 600; margin-right: 6px;
}
.card { background: #fff; border-radius: 14px; padding: 18px; box-shadow: var(--shadow); border: 1px solid var(--line); margin-bottom: 16px; }
.card.actions { display: flex; gap: 10px; flex-wrap: wrap; }
/* “我的”页操作按钮。这排按钮现在在页面**顶部**（头像/昵称下面、消息上面）。
   ★ 用等宽网格，不用 flex 换行：按钮字数不一样（「修改密码」四个字 vs「下载APP」），
     flex 会让每个按钮按内容各宽各的、换行后还参差不齐。等宽格子整齐得多。
   ★ 桌面端用 auto-fit：按钮摊开撑满整行，好看。
   ★ **手机/App 端固定每行 2 个**（见下面的媒体查询）—— 原来是 auto-fit(minmax(96px))，
     窄屏上自己算成一行 3 个，「修改密码/后台管理/下载APP」挤在一行、下一条只剩 2 个，
     末行还孤零零。业主要求每行 2 个，那就把列数写死，别让它自己算。
   ★ 字号压到 13px、内边距收到 9px：这排在首屏，不该抢头像和消息的位置。 */
.me-actions { padding: 12px; margin-bottom: 14px; }
.me-btns {
  display: grid; gap: 8px;
  grid-template-columns: repeat(auto-fit, minmax(104px, 1fr));
}
.me-btns .btn {
  width: 100%; padding: 9px 8px; font-size: 13px; font-weight: 600;
  border-radius: 9px; line-height: 1.35;
}
/* 断点用 820px：和底部导航（.tabbar）**同一个** —— 那是本项目里「App/移动 Web」的
   唯一硬标志。用别的值会出现「底部导航已经出来了、按钮还是一行仨」这种半移动状态。
   固定 2 列（不是 auto-fit）：按钮个数依账号而变（管理员多一个「后台管理」、
   App 内是「检查更新」而不是「下载APP」），但**每行 2 个**是明确的。
   奇数个时最后一个占左半边、左对齐，不拉满整行。 */
@media (max-width: 820px) {
  .me-btns { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 520px) {
  .me-btns { gap: 7px; }
}

/* ---------- 我的 ---------- */
.me-head { display: flex; align-items: center; gap: 16px; margin-bottom: 22px; }
.me-info { min-width: 0; }
.me-info > p { margin: 3px 0 0; }
.me-leaves {
  display: inline-block; margin: 4px 0 1px; padding: 2px 12px;
  font-size: 14px; font-weight: 700; color: #3f7d32; line-height: 1.7;
  background: #eef7ec; border-radius: 999px;
}
/* ---------- 每日签到 ---------- */
.signin-box {
  margin: 4px 0 14px; padding: 18px 16px; text-align: center;
  background: linear-gradient(180deg, #f3f9f0, #e9f4e4); border-radius: 14px;
}
.signin-leaves { font-size: 38px; font-weight: 800; color: #3f7d32; line-height: 1.15; }
.signin-leaves span { font-size: 26px; margin-left: 4px; }
.signin-streak { margin: 8px 0 0; font-size: 14px; color: #4a6b41; line-height: 1.7; }
.signin-streak b { font-size: 16px; color: #3f7d32; }
.signin-tip { margin: 6px 0 0; font-size: 13px; color: #6b7a63; line-height: 1.7; }
.signin-status {
  min-height: 20px; margin-bottom: 10px; text-align: center;
  font-size: 13px; color: #d33; line-height: 1.6;
}
.signin-ok { color: #3f7d32; font-weight: 600; }
.perm-list { display: flex; flex-wrap: wrap; gap: 10px; }
.perm-item {
  display: flex; align-items: center; gap: 7px; padding: 8px 14px; border-radius: 10px;
  background: #f4f5fb; font-size: 13px; font-weight: 600;
}
.perm-item.on { background: #ecfdf3; color: var(--ok); }
.perm-item.off { background: #fef2f2; color: #d33; }
.hc-item {
  display: inline-flex; align-items: center; gap: 6px; padding: 7px 12px; border-radius: 9px;
  background: #f4f5fb; font-size: 13px; cursor: pointer; user-select: none;
}
.hc-item input { cursor: pointer; }

/* ---------- 列表 ---------- */
.list-item {
  display: flex; align-items: center; gap: 12px; padding: 12px 0; border-bottom: 1px solid var(--line);
}
.list-item:last-child { border-bottom: none; }
.list-item .txt { flex: 1; min-width: 0; }
.list-item .tt { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.list-item .aa { font-size: 13px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---------- 笔记条目 ---------- */
.note-item { padding: 12px 14px; border-bottom: 1px solid var(--line); cursor: pointer; }
.note-item:last-child { border-bottom: none; }
.note-item:hover { background: #f7f8fc; }
.note-item .ni-type { font-size: 12px; color: var(--primary); font-weight: 600; margin-bottom: 4px; }
.note-item .ni-text { font-size: 14px; color: var(--text); line-height: 1.6; margin-bottom: 4px; }
.note-item .ni-note { font-size: 13px; color: #8a6d1a; background: #fff8e1; border-radius: 6px; padding: 6px 8px; margin-bottom: 4px; }
.note-item .ni-meta { font-size: 12px; color: var(--muted); }

/* ---------- 后台管理标签页 ---------- */
.admin-tabs { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 18px; }
.admin-tabs .at {
  padding: 8px 16px; border-radius: 999px; border: 1.5px solid var(--line); background: #fff;
  cursor: pointer; font-size: 14px; font-weight: 600; color: var(--muted); position: relative;
}
.admin-tabs .at.active { background: var(--grad); color: #fff; border-color: transparent; }
.admin-tabs .at-badge {
  display: inline-block; min-width: 18px; height: 18px; line-height: 18px; border-radius: 9px;
  background: #e5484d; color: #fff; font-size: 11px; text-align: center; padding: 0 5px; margin-left: 4px;
}

/* ---------- 空状态 / 分页 ---------- */
.empty { text-align: center; color: var(--muted); padding: 60px 20px; font-size: 15px; }
.pagination { display: flex; align-items: center; justify-content: center; gap: 16px; margin: 30px 0 10px; }
.pagination button {
  padding: 8px 18px; border-radius: 10px; border: 1.5px solid var(--line); background: #fff;
  cursor: pointer; font-size: 15px; color: var(--text);
}
.pagination button:disabled { opacity: .4; cursor: not-allowed; }
/* 窄屏：分页器一行排下（输入框收窄、按钮缩小） */
@media (max-width: 520px) {
  .pagination { gap: 6px; flex-wrap: nowrap; }
  .pagination button { padding: 6px 9px; font-size: 13px; }
  .pagination span { gap: 3px !important; }
  .pagination input { width: 38px !important; padding: 5px 2px !important; font-size: 13px !important; }
  .pagination .btn.sm { padding: 6px 7px; font-size: 12px; }
}

/* ---------- 底部导航（移动端） ---------- */
.tabbar {
  position: fixed; bottom: 0; left: 0; right: 0; z-index: 40;
  display: none; background: rgba(255,255,255,.96); backdrop-filter: blur(12px);
  border-top: 1px solid var(--line);
}
.tabbar .tab {
  flex: 1; display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding: 9px 0 8px; background: none; border: none; color: var(--muted); font-size: 11px; cursor: pointer;
}
.tabbar .tab .ico { font-size: 20px; }
.tabbar .tab.active { color: var(--primary); font-weight: 700; }

/* ---------- 模态框 / toast ---------- */
.modal-mask {
  position: fixed; inset: 0; background: rgba(20,22,32,.5); z-index: 200;
  display: flex; align-items: center; justify-content: center; padding: 20px;
}
.modal {
  background: #fff; border-radius: 18px; padding: 24px; width: 100%; max-width: 420px;
  max-height: 85vh; overflow: auto; position: relative; box-shadow: var(--shadow-lg);
}
.modal.wide { max-width: 800px; }
.modal h3 { margin: 0 0 18px; font-size: 19px; }
.modal .close {
  position: absolute; top: 16px; right: 16px; background: #f0f2f8; border: none; width: 30px; height: 30px;
  border-radius: 50%; cursor: pointer; font-size: 15px; color: var(--muted);
}
#toast {
  position: fixed; left: 50%; bottom: 90px; transform: translateX(-50%) translateY(20px);
  background: rgba(20,22,32,.92); color: #fff; padding: 11px 22px; border-radius: 999px;
  font-size: 14px; z-index: 300; opacity: 0; pointer-events: none; transition: all .25s;
  max-width: 86vw; text-align: center;
}
#toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

/* ---------- 阅读进度 / 作者页 / 最近阅读 ---------- */
.prog-track { height: 10px; background: #eef0f6; border-radius: 999px; overflow: hidden; }
.prog-fill { height: 100%; background: var(--grad); border-radius: 999px; transition: width .4s; }
.row.between { display: flex; align-items: center; justify-content: space-between; }
.author-link { color: var(--primary); cursor: pointer; font-weight: 600; text-decoration: underline; text-underline-offset: 3px; }
/* 「我的」→「书库分类」：文本链接排布。分类名用主题色、数量用弱化色，
   靠色差把「名字」和「本数」分开，不需要额外的分隔符。 */
.me-cats { display: flex; flex-wrap: wrap; gap: 9px 20px; line-height: 1.5; }
.me-cat-link { display: inline-flex; align-items: baseline; gap: 5px; font-size: 13px;
  color: var(--primary); cursor: pointer; text-decoration: underline;
  text-underline-offset: 3px; text-decoration-color: transparent; transition: all .15s; }
.me-cat-link:hover { text-decoration-color: currentColor; }
.me-cat-n { color: var(--muted); font-size: 12px; text-decoration: none; }
.author-link:hover { color: #7c3aed; }
.author-banner {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  background: linear-gradient(135deg, rgba(79,70,229,.08), rgba(192,38,211,.08));
  border: 1px solid rgba(79,70,229,.25); border-radius: 12px; padding: 12px 16px; margin-bottom: 16px;
}
.recent-list { display: flex; gap: 14px; overflow-x: auto; padding-bottom: 8px; scrollbar-width: none; }
.recent-list::-webkit-scrollbar { display: none; }
.recent-item {
  flex: 0 0 auto; width: 190px; display: flex; gap: 10px; align-items: center;
  background: #fff; border: 1px solid var(--border); border-radius: 12px; padding: 10px;
  cursor: pointer; transition: all .18s; box-shadow: var(--shadow);
}
.recent-item:hover { transform: translateY(-2px); border-color: var(--primary); }
.recent-item img { width: 48px; height: 66px; object-fit: cover; border-radius: 6px; background: #eef0f6; flex: none; }
.recent-item .rinfo { flex: 1; min-width: 0; }
.recent-item .t { font-size: 14px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-bottom: 6px; }
.recent-item .bar { height: 5px; background: #eef0f6; border-radius: 999px; overflow: hidden; margin-bottom: 5px; }
.recent-item .bar .fill { height: 100%; background: var(--grad); border-radius: 999px; }
.recent-item .a { font-size: 12px; color: var(--muted); }
#recent-row .page-head, #home-shelf-row .page-head { display: flex; justify-content: space-between; align-items: center; }

/* 开关（注册审核） */
.switch { position: relative; display: inline-block; width: 52px; height: 28px; flex: none; }
.switch input { opacity: 0; width: 0; height: 0; }
.switch .slider { position: absolute; cursor: pointer; inset: 0; background: #cdd1dc; border-radius: 999px; transition: .25s; }
.switch .slider::before { content: ""; position: absolute; height: 22px; width: 22px; left: 3px; top: 3px; background: #fff; border-radius: 50%; transition: .25s; box-shadow: 0 1px 3px rgba(0,0,0,.2); }
.switch input:checked + .slider { background: var(--grad); }
.switch input:checked + .slider::before { transform: translateX(24px); }

/* ---------- 响应式 ---------- */
@media (max-width: 820px) {
  .auth-hero { display: none; }
  .auth-logo { display: block; }
  .auth-panel { padding: 24px 18px; }
  .navbar { padding: 0 16px; height: 56px; }
  .nav-title { display: none; }
  .nav-links { display: none; }
  .content { padding: 18px 14px 90px; }
  .hero { flex-direction: column; align-items: stretch; }
  .searchbar { min-width: 0; max-width: none; width: 100%; }
  .grid { grid-template-columns: repeat(3, 1fr); gap: 10px; }
  .book-card .info { padding: 8px 8px 10px; }
  .book-card .info .t { font-size: 12px; min-height: 34px; }
  .book-card .info .a { font-size: 11px; }
  .book-card .cover.placeholder { font-size: 12px; padding: 8px; }
  .shelf-item .sinfo { padding: 8px 8px 10px; }
  .shelf-item .sinfo .t { font-size: 12px; min-height: 34px; }
  .shelf-item .sinfo .a { font-size: 11px; }
  .shelf-item .shelf-edit { width: 26px; height: 26px; top: 6px; right: 6px; font-size: 12px; }
  .cat-grid { grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 12px; }
  /* 移动端：书架页恢复纵向（书架收藏在上、有声阅读在下），有声卡片每行 3 个
     （与桌面端一致，所以这里不用再覆盖列数） */
  .shelf-layout { flex-direction: column; gap: 0; }
  .shelf-main { flex: none; width: 100%; order: 1; }
  #shelf-public { flex: none; width: 100%; order: 2; margin-top: 30px; }
  /* 移动端：分类 chips 保持横向滚动一行（仍用缩小后的尺寸） */
  .shelf-main .chips { flex-wrap: nowrap; overflow-x: auto; margin-bottom: 18px; padding-bottom: 6px; }
  .shelf-main .grid { grid-template-columns: repeat(3, 1fr); gap: 10px; }
  .detail-head { flex-direction: column; }
  .detail-head .cover { width: 120px; margin: 0 auto; }
  .detail-head .meta h2 { text-align: center; font-size: 19px; }
  .detail-head .meta .line { text-align: center; }
  .tabbar { display: flex; }
  #toast { bottom: 84px; }
}

/* 后台用户管理表格 */
.user-table { width: 100%; border-collapse: collapse; font-size: 13px; min-width: 640px; }
.user-table th, .user-table td { padding: 8px 10px; text-align: left; border-bottom: 1px solid #eef0f6; white-space: nowrap; }
.user-table th { color: #8a90a0; font-weight: 600; background: #f7f8fb; }
.user-table tr:hover td { background: #fafbfe; }
.user-table .perm-cell { white-space: normal; max-width: 220px; }
.badge { display: inline-block; padding: 2px 9px; border-radius: 10px; font-size: 12px; }
.badge.ok { background: #e6f7ec; color: #1a9e54; }
.badge.no { background: #fdeaea; color: #e5484d; }
.badge.top { background: #fff4e0; color: #d97706; }
.badge.share { background: #e8efff; color: #2f6bdc; }
.badge.discuss { background: #e6f7ec; color: #1a9e54; }
.badge.find { background: #fff0e6; color: #e06a1f; }

/* 底部广告栏 */
.ad-row { display: flex; gap: 12px; padding: 14px 16px 90px; max-width: 1200px; margin: 0 auto; }
.ad-slot { flex: 1; min-height: 64px; background: #fff; border-radius: 12px; border: 1px solid var(--line); overflow: hidden; display: flex; align-items: center; justify-content: center; padding: 10px; text-align: center; }
.ad-slot:empty { display: none; }
.ad-slot img { max-width: 100%; height: auto; border-radius: 6px; }
@media (max-width: 640px) { .ad-row { flex-direction: column; padding-bottom: 84px; } }

/* ============ 书单讨论 ============ */
.badge.bad { background: #f0f1f5; color: #8a90a3; }
/* ★ 必须能换行：这一行是 4 个话题胶囊，nowrap 时它的 min-content 宽度
   （320px 小屏 / 系统大字体下约 330~362px）会顺着 grid 传给 .bl-main，
   把整页撑出手机边框 —— 实测 320px 下整页横向溢出 24px。
   flex 行默认 nowrap，窄屏上「能换行」比「挤在一行」重要得多。 */
.bl-tag-filter { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 14px; }
.bl-tag-filter .chip { padding: 4px 14px; font-size: 13px; border-radius: 999px; }
.bl-tag-row { display: flex; gap: 10px; flex-wrap: wrap; }
.bl-tag-opt { display: inline-flex; align-items: center; gap: 6px; padding: 6px 14px; border: 1.5px solid var(--line); border-radius: 10px; font-size: 14px; cursor: pointer; background: #fafbfe; color: #555; transition: all .15s; }
.bl-tag-opt:hover { border-color: var(--primary); color: var(--primary); }
.bl-tag-opt input { position: absolute; opacity: 0; pointer-events: none; }
.bl-tag-opt.on { background: var(--grad); color: #fff; border-color: transparent; box-shadow: 0 3px 10px rgba(79,70,229,.25); }
.write-form { max-width: 800px; margin: 0 auto; }
.write-form textarea { width: 100%; padding: 11px 13px; border: 1.5px solid var(--line); border-radius: 11px; font-size: 15px; font-family: inherit; background: #fbfbfe; color: var(--text); outline: none; transition: border-color .15s, box-shadow .15s; min-height: 320px; resize: vertical; }
.write-form textarea:focus { border-color: var(--primary); box-shadow: 0 0 0 3px rgba(79,70,229,.12); background: #fff; }
.intro-wrap { max-width: 800px; margin: 0 auto; }
.intro-wrap .card { margin-bottom: 14px; }
.intro-ul { margin: 0; padding-left: 20px; line-height: 1.9; }
.intro-ul li { font-size: 14px; margin-bottom: 4px; }
.bl-layout { display: grid; grid-template-columns: 1fr 300px; gap: 18px; align-items: start; }
/* ★ grid/flex 子项默认 min-width:auto —— 只要里面有一个不肯收缩的东西
   （不换行的胶囊行、长 URL、宽表格），整列就会被它顶宽、把页面撑出屏幕。
   这里显式允许列变窄，收缩的活儿交给里面各自的换行规则。 */
.bl-layout > * { min-width: 0; }
/* 侧栏（最新签到/最近回复/浏览排行/友情链接）内部也是 grid：卡片默认 min-width:auto，
   会被「最新签到」这张表格的 min-content 顶宽（实测 320px 屏下卡片 330px、整页溢出 24px）。
   表格自己是 table-layout:fixed + width:100%，只要容器允许变窄它就跟着收。 */
.bl-side > * { min-width: 0; }
/* 顶栏也一样：搜索框 + 「发表文章」在窄屏要能折行，否则同样是并排撑宽 */
.bl-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; margin: 2px 0 14px; }
.bl-item { padding: 16px 18px; cursor: pointer; transition: box-shadow .2s, transform .15s; }
.bl-item:hover { box-shadow: var(--shadow-lg); transform: translateY(-1px); }
.bl-item .t { font-size: 16px; font-weight: 700; margin-bottom: 4px; }
.bl-item .br { font-size: 13px; color: var(--muted); margin-bottom: 8px; line-height: 1.5;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.bl-item .m { font-size: 12px; color: var(--muted); }
.bl-side .bl-card { margin-bottom: 16px; padding: 16px 18px; }
.bl-side-ico { font-size: 15px; }
.bl-side-list .bl-ri { display: flex; flex-direction: column; gap: 2px; padding: 9px 0; border-bottom: 1px dashed var(--line); cursor: pointer; }
.bl-side-list .bl-ri:last-child { border-bottom: none; }
.bl-ri .t { font-size: 13px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bl-ri .c { font-size: 12px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bl-ri .ti { font-size: 11px; color: var(--muted); }
.bl-ri.top { flex-direction: row; align-items: center; gap: 8px; }
.bl-ri.top .no { min-width: 20px; height: 20px; border-radius: 6px; background: #eef0ff; color: var(--primary);
  font-size: 12px; font-weight: 700; display: inline-flex; align-items: center; justify-content: center; }
.bl-ri.top .t { flex: 1; font-weight: 500; }
/* 友情链接（后台可配，最多 5 条）：一行一条，长地址省略号截断，
   不换行 —— 侧栏只有 1/3 屏宽，让它换行会把下面整块顶下去。 */
.bl-links { display: flex; flex-direction: column; }
.bl-links .bl-link { display: block; padding: 7px 0; font-size: 13px; color: var(--primary);
  border-bottom: 1px dashed var(--line); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bl-links .bl-link:last-child { border-bottom: none; }
.bl-links .bl-link:hover { text-decoration: underline; }
.bl-ri.top .ti { font-size: 12px; }
/* 书单详情 */
.bl-article { padding: 22px 24px; }
.bl-article h2 { line-height: 1.4; }
.bl-meta { font-size: 13px; color: var(--muted); margin-bottom: 14px; }
.bl-content { line-height: 1.9; font-size: 15px; }
.bl-content h2, .bl-content h3, .bl-content h4 { margin: 18px 0 8px; }
.bl-content ul.bl-ul { padding-left: 22px; margin: 8px 0; }
.bl-content ul.bl-ul li { margin: 4px 0; }
/* 文章内嵌图片/视频：居中显示，按适合尺寸显示。
   max-width:100% + height:auto 的含意是「比容器小就按原始大小，比容器大才等比缩小」——
   这里刻意不写 width:100%，那样会把小图也拉大铺满整屏。
   display:block + margin:auto 才是居中的关键（img 默认是行内元素，text-align 管不到它）。*/
.bl-content .bl-media { display: block; margin: 14px auto; max-width: 100%; height: auto; border-radius: 8px; }
/* ★ 图片同样要限高（2026-10-14 站长反馈）：max-width:100% 只保证「不拉宽」，
   一张 900x2400 的手机截图按原始尺寸显示就有 2400px 高 —— 一屏根本放不下，
   正文里全是这一张图。跟视频一个规矩限到 70vh：高度封顶后浏览器会按原比例
   把宽度一起缩下来，所以既不变形、也一屏看得完。 */
.bl-content img.bl-media { max-height: 70vh; }
/* 视频再限一下高度：竖屏手机视频按宽度铺满会把一屏占满，画面反而看不全 */
.bl-content video.bl-media { max-height: 70vh; background: #000; }
.bl-comments { padding: 18px 22px; margin-top: 16px; }
.bl-cmt { padding: 10px 0; border-bottom: 1px dashed var(--line); }
.bl-cmt:last-child { border-bottom: none; }
.bl-cmt .c-head { font-size: 13px; color: var(--muted); margin-bottom: 3px; }
.bl-cmt .c-head b { color: var(--text); }
.bl-cmt .c-body { font-size: 14px; line-height: 1.7; word-break: break-word; }
.bl-comment-box { margin-top: 12px; }
.bl-comment-box textarea, #blf-content {
  width: 100%; border: 1.5px solid var(--line); border-radius: 12px; padding: 10px 12px;
  font-size: 14px; font-family: inherit; resize: vertical; outline: none; }
.bl-comment-box textarea:focus, #blf-content:focus { border-color: var(--primary); }
@media (max-width: 900px) {
  .bl-layout { grid-template-columns: 1fr; }
  .bl-side { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
}
@media (max-width: 640px) {
  .bl-side { grid-template-columns: 1fr; }
  .bl-article { padding: 16px; }
}
/* 书单搜索框（与「我的书单」按钮同高同风格） */
.bl-search-wrap { position: relative; display: inline-flex; align-items: center; }
.bl-search {
  width: 190px; padding: 8px 30px 8px 14px; font-size: 13px; color: var(--text);
  border: 1.5px solid var(--line); border-radius: 9px; outline: none; background: #fff;
  font-family: inherit; box-sizing: border-box;
}
.bl-search:focus { border-color: var(--primary); }
.bl-search-x {
  position: absolute; right: 8px; top: 50%; transform: translateY(-50%);
  border: none; background: none; color: var(--muted); font-size: 13px; cursor: pointer; padding: 2px;
}
.bl-search-x:hover { color: var(--text); }
@media (max-width: 640px) {
  .bl-search { width: 130px; padding-left: 10px; }
  .bl-toolbar { flex-wrap: wrap; gap: 8px; }
}

/* ---------- 站内消息（我的消息 / 导航红点） ---------- */
.msg-dot {
  position: absolute; top: 4px; right: -3px; width: 8px; height: 8px; border-radius: 50%;
  background: #e5484d; box-shadow: 0 0 0 2px #fff; display: inline-block; pointer-events: none;
}
.tabbar .tab { position: relative; }
.tabbar .tab .msg-dot { top: 5px; left: 50%; right: auto; margin-left: 6px; }

/* 每条消息只占**一行**：未读点 + 类型 + 标题 + 发送人 + 时间（+ 回复）。
   标题吃剩余宽度、超长省略号截断；其余元素一律 flex-shrink:0，
   这样在手机窄屏上也是稳稳一行，不会因为标题长就折成两行。 */
.msg-item {
  display: flex; align-items: center; gap: 8px;
  border: 1px solid var(--line); border-radius: 12px; padding: 8px 12px; margin-bottom: 6px;
  background: #fff; transition: background .15s;
}
.msg-item.unread { background: #fff8f8; border-color: #f6c9cb; }
.msg-item[onclick] { cursor: pointer; }
.msg-item[onclick]:hover { background: #f7f8fb; }
.msg-kind {
  display: inline-block; font-size: 11px; padding: 1px 7px; border-radius: 6px;
  background: #eef1f7; color: #555; flex-shrink: 0;
}
.msg-kind.pm { background: #e7f0ff; color: #1d63d2; }
.msg-kind.sent { background: #eef1f7; color: #7a8194; }
.msg-kind.share { background: #e6f7ec; color: #1a8f4c; }
.msg-kind.bl { background: #fff3e0; color: #b26a00; }
.msg-kind.review { background: #f0e9ff; color: #6b3fd4; }
.msg-kind.report { background: #ffe9e9; color: #c62828; }
.msg-title {
  font-weight: 600; font-size: 14px; flex: 1 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.msg-new { width: 7px; height: 7px; border-radius: 50%; background: #e5484d; flex-shrink: 0; }
/* 发送人：标题里已经写了同一个昵称时不重复显示（见 renderMessages），
   所以这一格是「有才有」。给个上限，长了也截断，别把标题挤没。 */
.msg-from {
  font-size: 12px; color: var(--muted); flex: 0 0 auto; max-width: 30%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.msg-time { font-size: 12px; color: var(--muted); flex-shrink: 0; }
/* 回复：一行布局里用文本链接，比按钮矮，整行高度不被撑开 */
.msg-reply {
  font-size: 12px; color: var(--primary); flex-shrink: 0; cursor: pointer;
  text-decoration: underline; text-underline-offset: 3px;
}
/* 消息详情弹窗 */
.msg-detail-meta {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  font-size: 12.5px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--line);
}
.msg-detail-body {
  margin: 12px 0 16px;
  font-size: 14.5px;
  line-height: 1.75;
  color: #333;
  white-space: pre-wrap;
  word-break: break-word;
  max-height: 46vh;
  overflow-y: auto;
}
.msg-detail-btns { display: flex; gap: 10px; flex-wrap: wrap; }
.msg-detail-btns .btn { flex: 1; min-width: 92px; }

/* ---------- 升级权限（树叶兑换分组） ---------- */
.upgrade-active {
  margin-top: 12px;
  padding: 9px 12px;
  border-radius: 9px;
  background: #eef7f0;
  border: 1px solid #cfe8d5;
  color: #2f6b3f;
  font-size: 13px;
  line-height: 1.6;
}
.upgrade-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 11px 13px;
  border: 1px solid var(--line);
  border-radius: 10px;
  margin-bottom: 9px;
}
.upgrade-item:last-child { margin-bottom: 0; }
.upgrade-item.current { background: #f7f9fb; border-color: #dbe4ec; }
.ug-info { min-width: 0; }
.ug-name { font-weight: 600; font-size: 14px; }
.ug-cost { color: #7b8794; font-size: 12.5px; margin-top: 3px; }
.upgrade-item .btn[disabled] { opacity: .45; cursor: not-allowed; }

/* 升级权限弹窗内的权限/限额说明 */
.upgrade-item { display: block; }
.ug-top { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.ug-perms { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 9px; }
.ug-perm {
  font-size: 12px;
  padding: 2px 7px;
  border-radius: 6px;
  background: #f2f4f7;
  color: #98a2b3;
  white-space: nowrap;
}
.ug-perm.on { background: #eef7f0; color: #2f6b3f; }
.ug-perm.gained { background: #e3f2e8; color: #1f7a3f; font-weight: 600; }
.ug-perm i { font-style: normal; font-size: 11px; margin-left: 3px; opacity: .85; }
.ug-limits { margin-top: 7px; font-size: 12.5px; color: #7b8794; line-height: 1.6; }

/* 审核页的树叶奖励设置条 */
.reward-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  padding: 10px 12px;
  background: #f6f8f5;
  border: 1px solid var(--line);
  border-radius: 10px;
  font-size: 13px;
}
.reward-bar .reward-label { color: #333; font-weight: 600; }
.reward-bar .reward-input {
  width: 84px;
  padding: 5px 8px;
  border: 1.5px solid var(--line);
  border-radius: 8px;
  font-size: 14px;
  text-align: center;
  font-family: inherit;
}
.reward-bar .reward-unit { color: #333; }
.reward-bar .reward-hint { margin-left: auto; font-size: 12px; }
@media (max-width: 640px) {
  .reward-bar .reward-hint { margin-left: 0; width: 100%; }
}

/* 发消息：昵称 + 群发勾选同一行 */
/* 发消息：「接收人昵称」+「群发」选框排在同一行。
   选择器统一加 .msg-to-row 前缀提高优先级，避免被 .form-group label / .form-group input 覆盖。 */
.msg-to-row { display: flex; align-items: stretch; gap: 10px; }
.msg-to-row #msg-to { flex: 1 1 0%; width: auto; min-width: 0; }
.msg-to-row .bc-check {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex: 0 0 auto;
  width: auto;
  margin: 0;
  padding: 0 12px;
  border: 1.5px solid var(--line);
  border-radius: 11px;
  background: #fbfbfe;
  color: var(--muted);
  font-size: 14px;
  font-weight: 600;
  line-height: 1.2;
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
  transition: border-color .15s, background .15s, color .15s;
}
.msg-to-row .bc-check input {
  appearance: auto;
  -webkit-appearance: auto;
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  accent-color: var(--primary);
  cursor: pointer;
}
.msg-to-row .bc-check input:focus { box-shadow: none; }
.msg-to-row .bc-check.on {
  border-color: var(--primary);
  background: #f2f7ff;
  color: var(--primary);
}

/* 消息正文里的超链接 */
.msg-detail-body a { color: var(--primary); text-decoration: underline; word-break: break-all; }
.msg-detail-body a:hover { color: var(--primary-2); }

/* 管理员书架「共享申请」系统分类 + 共享申请标记（非拖拽分类，高亮提示待处理） */
.chip.chip-req { border-color: #f59e0b; color: #b45309; background: #fffaf0; font-weight: 600; }
.chip.chip-req:hover { border-color: #d97706; color: #92400e; }
.chip.chip-req.active { background: #f59e0b; color: #fff; border-color: transparent; box-shadow: 0 4px 12px rgba(245,158,11,.32); }
.tag.tag-req { background: #fff4e0; color: #b45309; font-weight: 600; }

/* 后台「可申请共享的电子书格式」勾选格 */
.fmt-grid { display: flex; flex-wrap: wrap; gap: 8px; }
.fmt-check { display: inline-flex; align-items: center; gap: 7px; padding: 7px 13px;
  border: 1.5px solid var(--line); border-radius: 10px; background: #fbfbfe; color: #555;
  font-size: 13px; font-weight: 600; cursor: pointer; user-select: none;
  transition: border-color .15s, background .15s, color .15s; }
.fmt-check:hover { border-color: var(--primary); color: var(--primary); }
.fmt-check.on { border-color: var(--primary); background: #f2f7ff; color: var(--primary); }
.fmt-check input { flex: 0 0 auto; width: 15px; height: 15px; margin: 0; padding: 0;
  border: 0; background: none; accent-color: var(--primary); cursor: pointer; }

/* 用户管理：可点击排序的表头 */
.user-table th.sortable { cursor: pointer; user-select: none; white-space: nowrap; transition: color .15s, background .15s; }
.user-table th.sortable:hover { color: var(--primary); background: #eef3fd; }
.user-table th.sortable .sort-arrow { display: inline-block; margin-left: 5px; font-size: 11px; color: #b9bfcc; }
.user-table th.sortable:hover .sort-arrow { color: var(--primary); }
.user-table th.sortable.sorted { color: var(--primary); }
.user-table th.sortable.sorted .sort-arrow { color: var(--primary); }

/* ==================== 网站统计 ==================== */
.ss-topbar { display: flex; justify-content: space-between; align-items: center;
  gap: 14px; flex-wrap: wrap; margin: 2px 0 14px; }
.ss-range { display: inline-flex; background: #eceef4; border-radius: 9px; padding: 3px; gap: 2px; }
.ss-range button { border: 0; background: transparent; color: #6c7382; font-size: 13px;
  padding: 6px 14px; border-radius: 7px; cursor: pointer; font-family: inherit;
  transition: background .15s, color .15s; }
.ss-range button:hover { color: var(--text); }
.ss-range button.on { background: #fff; color: var(--text); font-weight: 600;
  box-shadow: 0 1px 3px rgba(31,35,48,.10); }

/* 概览卡 */
.ss-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(158px, 1fr));
  gap: 12px; margin-bottom: 16px; }
.ss-card { background: var(--card); border: 1px solid var(--line); border-radius: 12px;
  padding: 14px 16px 13px; box-shadow: 0 1px 2px rgba(31,35,48,.03); }
.ss-card-l { font-size: 12px; color: var(--muted); letter-spacing: .04em; }
.ss-card-v { font-size: 25px; font-weight: 650; color: var(--text); line-height: 1.25;
  margin-top: 5px; font-variant-numeric: tabular-nums; letter-spacing: -.01em; }
.ss-card-d { font-size: 11.5px; margin-top: 4px; display: flex; gap: 6px; align-items: baseline;
  color: #9aa1b0; font-variant-numeric: tabular-nums; }
.ss-card-d.up { color: #2f7d5f; }
.ss-card-d.down { color: #b4544f; }
.ss-card-d.flat { color: #9aa1b0; }
.ss-card-d span { color: #b3b9c6; }

/* 图表 */
.ss-chart { position: relative; }
.ss-chart-head { display: flex; justify-content: space-between; align-items: flex-end;
  gap: 12px; flex-wrap: wrap; margin-bottom: 4px; }
.ss-chart-head h3 { margin: 0; }
.ss-sub { margin: 3px 0 0; font-size: 12px; color: var(--muted); }
.ss-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
  gap: 16px; margin: 16px 0; }
.ss-legend { display: flex; gap: 16px; flex-wrap: wrap; margin: 0 0 2px 2px; }
.ss-legend span { display: inline-flex; align-items: center; gap: 6px;
  font-size: 12px; color: #6c7382; }
.ss-legend i { width: 9px; height: 9px; border-radius: 2px; display: inline-block; }

/* 悬停浮层 */
.ss-tip { position: absolute; z-index: 20; background: #fff; border: 1px solid #e4e7ee;
  border-radius: 9px; padding: 8px 11px; box-shadow: 0 6px 20px rgba(31,35,48,.13);
  pointer-events: none; min-width: 132px; transform: translateX(-50%); }
.ss-tip-d { font-size: 11.5px; color: var(--muted); margin-bottom: 5px;
  padding-bottom: 5px; border-bottom: 1px solid #f0f2f7; }
.ss-tip-r { display: flex; align-items: center; gap: 7px; font-size: 12.5px;
  color: #6c7382; line-height: 1.75; }
.ss-tip-r i { width: 8px; height: 8px; border-radius: 2px; flex: none; }
.ss-tip-r b { margin-left: auto; color: var(--text); font-variant-numeric: tabular-nums; }

/* 明细表 */
.ss-table { width: 100%; border-collapse: collapse; font-size: 12.5px; min-width: 900px;
  font-variant-numeric: tabular-nums; }
.ss-table th, .ss-table td { padding: 8px 10px; border-bottom: 1px solid #f1f3f8;
  white-space: nowrap; }
.ss-table th { color: var(--muted); font-weight: 600; font-size: 11.5px;
  background: #fafbfd; letter-spacing: .02em; }
.ss-table th.n, .ss-table td.n { text-align: right; }
.ss-table tbody tr:hover td { background: #fafbfe; }
.ss-table tfoot td { font-weight: 650; color: var(--text); background: #fafbfd;
  border-top: 1.5px solid #e6e9f0; border-bottom: 0; }
.ss-table td.ss-d { color: #5c6373; }
.ss-table tr.today td.ss-d { font-weight: 650; color: var(--text); }
.ss-table tr.today td.ss-d::after { content: '今天'; font-size: 10px; color: #fff;
  background: #8a90a3; border-radius: 4px; padding: 1px 5px; margin-left: 7px;
  font-weight: 500; vertical-align: 1px; }
.ss-table .ss-zero { color: #ccd1db; }
/* 环比小标：挂在数值下方，字号更小、不抢主数值 */
.ss-table .ss-tr { display: block; font-size: 10.5px; font-weight: 600;
  line-height: 1.5; letter-spacing: .01em; }
.ss-table .ss-tr.up { color: #1f8b4c; }
.ss-table .ss-tr.down { color: #c0392b; }
.ss-table .ss-tr.flat { color: #aab0bd; font-weight: 500; }
/* 表尾两条合计行：弱化第二条（前 10 天），只作对比基线 */
.ss-table tfoot tr.ss-sum:last-child td { font-weight: 500; color: var(--muted); }
#sec-sitestats.ss-loading { opacity: .55; transition: opacity .15s; pointer-events: none; }

/* ============ 后台「分组管理」：窄屏用卡片，宽屏用紧凑表格 ============
   .user-table 有 6 列且 min-width:640px，手机上会横向溢出 330px 左右，
   「编辑」按钮被挤出可视区，必须左右拖动才能看到。窄屏改成卡片，
   信息按「权限/限额/兑换」分行展示，编辑按钮固定在第一行右侧。

   ★ 宽屏原来直接复用 .user-table（权限 max-width:220px + white-space:normal），
     结果「权限」「限额」两列各自折成两三行：5 个分组占 455px 高，
     行高 79/79/59/59/59 参差不齐，一眼看过去很乱 —— 高度全花在换行上。
     现在一行一个分组：行高固定、长内容省略号 + title 悬浮看全文，
     权限改成小徽章（最多 3 个 + 「+N」），成员数并到分组名后面当小字。 */
.grp-tb { width: 100%; border-collapse: collapse; font-size: 13px; table-layout: fixed; }
.grp-tb th, .grp-tb td {
  padding: 5px 10px; text-align: left; border-bottom: 1px solid #eef0f6;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; vertical-align: middle;
}
.grp-tb th { color: #8a90a0; font-weight: 600; background: #f7f8fb; padding: 7px 10px; }
.grp-tb tr:hover td { background: #fafbfe; }
/* 行高由「编辑」按钮决定：按钮不缩小，单元格 padding 再小也白搭（实测 50px→37px 全靠这一行） */
.grp-tb .btn.sm { padding: 3px 11px; font-size: 12px; line-height: 18px; }
.grp-tb tr:hover td { background: #fafbfe; }
.grp-tb .g-mem { margin-left: 6px; font-size: 12px; color: var(--muted); font-weight: 400; }
.grp-tb .g-chip {
  display: inline-block; padding: 1px 7px; margin: 0 4px 0 0; border-radius: 999px;
  background: #eef3fd; color: var(--primary); font-size: 12px; line-height: 18px;
}
.grp-tb .g-chip.more { background: #f1f2f6; color: #8a90a0; }
.grp-tb .g-act { text-align: right; padding-right: 0; }
.grp-cards { display: none; }
.grp-card {
  border: 1px solid var(--line); border-radius: 12px; padding: 12px 13px;
  margin-bottom: 10px; background: #fff;
}
.grp-card .grp-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 8px; }
.grp-card .grp-head b { font-size: 15px; }
.grp-card .grp-members { margin-left: auto; font-size: 12px; color: var(--muted); }
.grp-card .grp-row { display: flex; gap: 8px; font-size: 13px; padding: 3px 0; line-height: 1.6; }
.grp-card .grp-k { flex: 0 0 40px; color: var(--muted); }
.grp-card .grp-v { flex: 1; min-width: 0; word-break: break-word; overflow-wrap: anywhere; }
@media (max-width: 700px) {
  .grp-table-wrap { display: none; }
  .grp-cards { display: block; }
}

/* ============ 后台「用户管理」：窄屏用卡片，宽屏用表格 ============
   表格 10 列、min-width:640px，手机（412px）上横向溢出 368px，
   「编辑」按钮被挤出可视区。窄屏改成卡片，并按行展示同一批信息。
   排序原本只能点表头触发，卡片没有表头，所以另配下拉选择器。 */
.usr-cards { display: none; }
.usr-sort {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 10px;
}
.usr-sort select {
  flex: 1; min-width: 120px; padding: 8px 10px; font-size: 13px; font-family: inherit;
  border: 1.5px solid var(--line); border-radius: 9px; background: #fff; color: var(--text);
}
.usr-sort .usr-sel-all { display: inline-flex; align-items: center; gap: 5px; font-size: 13px; color: var(--muted); }
.usr-card {
  border: 1px solid var(--line); border-radius: 12px; padding: 12px 13px;
  margin-bottom: 10px; background: #fff;
}
.usr-card .usr-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 8px; }
.usr-card .usr-head b { font-size: 15px; }
.usr-card .usr-leaves { margin-left: auto; font-size: 13px; font-weight: 600; }
.usr-card .usr-row { display: flex; gap: 8px; font-size: 13px; padding: 3px 0; line-height: 1.6; }
.usr-card .usr-k { flex: 0 0 34px; color: var(--muted); }
.usr-card .usr-v { flex: 1; min-width: 0; word-break: break-word; overflow-wrap: anywhere; }
@media (max-width: 700px) {
  .usr-table-wrap { display: none; }
  .usr-cards { display: block; }
}

/* ============ 后台 TTS 服务器行：结构信息一行、音色配置一行 ============
   每台服务器各自配默认音色与白名单（不同机器模型/音色集可能不同），
   挤在一行里手机上看不清，所以拆成上下两行。 */
.tts-srv {
  border: 1px solid var(--line); border-radius: 10px; padding: 10px 11px;
  margin-bottom: 9px; background: #fff;
}
.tts-srv .srv-line { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
.tts-srv .srv-line + .srv-line { margin-top: 7px; padding-top: 7px; border-top: 1px dashed var(--line); }
.tts-srv .srv-lb { font-size: 13px; color: var(--muted); white-space: nowrap; }
.tts-srv input {
  padding: 7px 9px; font-size: 13px; font-family: inherit; box-sizing: border-box;
  border: 1.5px solid var(--line); border-radius: 8px; background: #fff; color: var(--text);
}
@media (max-width: 700px) {
  .tts-srv .srv-line > input { min-width: 0; flex: 1 1 100%; width: auto !important; }
  .tts-srv .srv-line > .srv-lb { flex: 0 0 auto; }
}

/* ---------- 后台：用户收藏明细弹窗（点「收藏」数字打开） ---------- */
.link-num { color: #3b6ef5; cursor: pointer; border-bottom: 1px dashed #9db8f8; }
.link-num:hover { color: #1f4fd8; border-bottom-color: #1f4fd8; }
.ushelf-list { max-height: 56vh; overflow-y: auto; margin-top: 4px; }
.ushelf-item { display: flex; gap: 10px; padding: 8px 2px; border-bottom: 1px solid #f0f2f6; }
.ushelf-item:last-child { border-bottom: none; }
.ushelf-n { flex: 0 0 24px; color: #9aa1ad; font-size: 12px; line-height: 18px; text-align: right; }
.ushelf-t { flex: 1; min-width: 0; }
.ushelf-title { font-size: 14px; font-weight: 600; word-break: break-all; }
.ushelf-meta { font-size: 12px; color: #8a919c; margin-top: 2px; word-break: break-all; }

/* ==========================================================================
   有声电子书（「有声」页 / 详情 / 播放器）
   与听书（#l-* 前缀）分开命名，全部用 au- / ad- / ap- 前缀，避免相互覆盖。
   ========================================================================== */
.au-toolbar {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 14px;
}
.au-cats { display: flex; gap: 8px; flex-wrap: wrap; flex: 1; }
.au-cat {
  border: 1px solid var(--line); background: var(--card); color: var(--text);
  padding: 6px 12px; border-radius: 999px; font-size: 13px; cursor: pointer;
}
.au-cat.on { background: var(--primary); border-color: var(--primary); color: #fff; }
.au-cat-n { opacity: .7; font-size: 12px; }

.au-grid {
  display: grid; gap: 14px;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
}
.au-card {
  display: flex; gap: 12px; padding: 12px; background: var(--card);
  border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow);
  cursor: pointer; transition: transform .15s, box-shadow .15s;
  /* 右上角的「热度推荐」星标/角标是绝对定位的，卡片必须是定位祖先 */
  position: relative;
  /* ★★ min-width: 0 是**手机端不横向溢出**的关键，别删。
     卡片是 .au-grid 的 grid item，而 grid item 的 min-width 默认是 auto，
     即「不许比我内容的最小宽度还窄」。而下面 .au-sub 是 white-space: nowrap
     （为了长作者名一行截断），它的最小宽度 = **整行文字的实际宽度**，
     这个宽度经 .au-meta 一路顶到卡片 → 卡片最小宽度 ≈ 64(封面)+12+321(副标题)+24 ≈ 422px。
     于是 390px 的手机上：格子容器只有 362px，那一列却被撑到 422px，整页横向滚 47px。
     桌面端容器宽得多，一直没暴露；只有窄屏才现形。
     写成 min-width: 0 之后 grid item 可以比内容更窄，.au-sub 靠 ellipsis 截断，
     .au-meta 本来就 min-width: 0，整条链路都能收缩。 */
  min-width: 0;
}
.au-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); }
/* 管理员在卡片上直接「加入首页热度推荐」的星标。
   绝对定位 + 不参与 flex，所以不会把封面和标题挤动；点它要 stopPropagation，
   否则会连带触发整张卡片的 openAudio。 */
.au-star {
  position: absolute; top: 6px; right: 6px; z-index: 2;
  width: 26px; height: 26px; padding: 0; border-radius: 50%;
  border: 1px solid var(--line); background: #fff; color: var(--muted);
  font-size: 15px; line-height: 1; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.au-star:hover { border-color: #f59e0b; color: #f59e0b; }
.au-star.on { background: #fff7e6; border-color: #f59e0b; color: #f59e0b; }
/* 非管理员：已加入推荐的卡片给一个静态角标 */
.au-star-badge {
  position: absolute; top: 6px; right: 6px; z-index: 2;
  padding: 2px 8px; border-radius: 999px; font-size: 11px;
  background: #fff7e6; color: #b45309; border: 1px solid #fcd34d;
}
/* 角标占了右上角，标题让出那点宽度，免得长书名压到它下面。
   ★ 只在有角标时加，没有角标的卡片版面一点都不变。 */
.au-card.has-star .au-meta { padding-right: 30px; }
.au-card.has-badge .au-meta { padding-right: 52px; }
.au-cover {
  width: 64px; height: 88px; border-radius: 10px; object-fit: cover; flex: 0 0 auto;
  background: #eef0f7;
}
.au-cover-ph {
  /* 占位是文字「有声」，字号按文字调（原来是给 emoji 用的 26px） */
  display: flex; align-items: center; justify-content: center; font-size: 13px; color: var(--muted);
}
.au-meta { min-width: 0; flex: 1; }
.au-title {
  font-weight: 700; font-size: 15px; line-height: 1.3; margin-bottom: 4px;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
/* 卡片副标题一行封顶：作者名可能很长（「魔戒三部曲」的作者带上译者共 40 多字），
   放任换行会让这一张卡片比同排的高出一截、参差不齐。 */
.au-sub { font-size: 12px; color: var(--muted); line-height: 1.6;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.au-bar { height: 4px; background: var(--line); border-radius: 4px; margin: 6px 0 4px; overflow: hidden; }
.au-bar i { display: block; height: 100%; background: var(--primary); }
.au-tag {
  display: inline-block; margin-top: 6px; padding: 2px 8px; border-radius: 999px; font-size: 11px;
}
.au-tag.free { background: #e8f8ee; color: var(--ok); }
.au-tag.lock { background: #fdeaea; color: var(--danger); }
.au-tag.cur { background: #eef0ff; color: var(--primary); margin-left: 6px; }

/* 书架侧栏「有声阅读」：竖排小卡片（封面在上），每行 2 本时横排会挤成一团 */
.au-shelf-grid { display: grid; gap: 12px; }
.au-shelf-card {
  background: var(--card); border: 1px solid var(--line); border-radius: 14px;
  padding: 8px; cursor: pointer; box-shadow: var(--shadow);
  transition: transform .15s, box-shadow .15s; min-width: 0;
}
.au-shelf-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); }
.au-shelf-card .au-cover { width: 100%; height: auto; aspect-ratio: 3/4; }
.au-shelf-cov { position: relative; }
.au-shelf-card .au-title {
  font-weight: 600; font-size: 13px; line-height: 1.35; margin: 6px 0 2px;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.au-shelf-card .au-sub { font-size: 11px; }

/* 有声标识：首页最近阅读 / 书架卡片右上角的耳机 */
/* 书单页右栏「最新签到」：表格排版，数字列严格对齐。
   table-layout:fixed + colgroup 固定列宽，昵称再长也不会把数字列挤歪。 */
.bl-signin-tb {
  width: 100%; border-collapse: collapse; table-layout: fixed;
  font-size: 13px;
}
.bl-signin-tb col.c-u { width: auto; }
.bl-signin-tb col.c-l { width: 58px; }
.bl-signin-tb col.c-s { width: 52px; }
.bl-signin-tb thead th {
  font-size: 11.5px; font-weight: 600; color: var(--muted);
  text-align: left; padding: 0 0 6px; border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
.bl-signin-tb thead th.num { text-align: right; }
.bl-signin-tb tbody td {
  /* ★ 行高锁在 td 上、且不留上下 padding：
     靠 tr 高度或 padding 都压不住 🌿 那个 emoji —— 它的行盒比纯数字高 0.2px，
     一行行算下来就会有「有的行 46.0、有的行 46.2」的毛边。
     给 td 定死高度 + 垂直居中，每行就严格 46px。 */
  height: 46px; padding: 0; border-bottom: 1px solid var(--line); vertical-align: middle;
}
.bl-signin-tb tbody tr:last-child td { border-bottom: none; }
/* 固定行高：🌿 是 emoji，它所在行的行盒会比纯数字行高 0.5px，
   不锁死就会出现「每行高度差一点点」的毛边感。 */
.bl-signin-tb tbody td { line-height: 1.25; }
/* ★ 不要在 <td> 上直接 display:flex —— 那会让它不再是表格单元格，
   列宽与对齐随之失效。flex 放在内层 span 上，td 保持 table-cell。 */
.bl-signin-tb td.u { min-width: 0; }
.bl-signin-tb .u-in { display: flex; align-items: center; gap: 8px; min-width: 0; }
.bl-signin-tb .av {
  width: 26px; height: 26px; border-radius: 50%; flex: 0 0 auto;
  background: var(--grad); color: #fff; font-weight: 700; font-size: 12px;
  display: flex; align-items: center; justify-content: center;
}
.bl-signin-tb .nm-wrap { min-width: 0; display: flex; flex-direction: column; line-height: 1.3; }
.bl-signin-tb .nm {
  font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.bl-signin-tb .tm { font-size: 11px; color: var(--muted); white-space: nowrap; }
.bl-signin-tb td.num {
  text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums;
  color: var(--fg);
}
.bl-signin-tb td.num b { color: var(--primary); font-weight: 700; }
.bl-signin-tb td.num i {
  font-style: normal; font-size: 11px; margin-left: 1px;
  line-height: 1; vertical-align: -1px;
}

.au-badge {
  /* 放的是文字「有声」（用户明确要求不要再放 emoji），所以做成胶囊而不是圆点 */
  position: absolute; top: 6px; right: 6px; padding: 2px 6px;
  display: flex; align-items: center; justify-content: center;
  background: rgba(17, 20, 28, .62); color: #fff; border-radius: 999px;
  font-size: 10px; line-height: 1.25; letter-spacing: .3px;
  box-shadow: 0 1px 4px rgba(0, 0, 0, .28);
}
.au-recent { position: relative; }
.au-recent .au-badge { top: 8px; right: 8px; }

/* ---------- 详情 ---------- */
.ad-hero { display: flex; gap: 16px; align-items: flex-start; margin-bottom: 14px; }
.ad-cover { width: 108px; height: 148px; border-radius: 12px; object-fit: cover; background: #eef0f7; }
.ad-cover-ph {
  display: flex; align-items: center; justify-content: center; font-size: 18px; color: var(--muted);
}
.ad-info { min-width: 0; flex: 1; }
.ad-title { font-size: 19px; font-weight: 700; line-height: 1.3; margin-bottom: 6px; }
.ad-line { font-size: 13px; line-height: 1.8; color: var(--text); }
.ad-acts { display: flex; gap: 10px; flex-wrap: wrap; margin: 4px 0 10px; }
.ad-h { font-size: 15px; margin: 14px 0 8px; }
.ad-chaps { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }
.ad-chap {
  display: flex; align-items: center; gap: 10px; padding: 11px 14px; cursor: pointer;
  border-bottom: 1px solid var(--line); font-size: 14px;
}
.ad-chap:last-child { border-bottom: 0; }
.ad-chap:hover { background: #fafbff; }
.ad-chap.locked { color: var(--muted); }
.ad-chap-no { width: 34px; flex: 0 0 auto; color: var(--muted); font-size: 12px; text-align: right; }
.ad-chap-t { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ad-chap-d { font-size: 12px; flex: 0 0 auto; }

/* ---------- 播放器 ---------- */
.ap-head { display: flex; gap: 14px; align-items: center; margin-bottom: 12px; }
.ap-cover { width: 78px; height: 78px; border-radius: 12px; object-fit: cover; background: #eef0f7; }
.ap-cover-ph {
  display: flex; align-items: center; justify-content: center; font-size: 15px; color: var(--muted);
}
.ap-title { font-size: 17px; font-weight: 700; line-height: 1.35; }
.ap-sub { font-size: 12px; color: var(--muted); line-height: 1.7; }
.ap-player {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 12px; box-shadow: var(--shadow); margin-bottom: 12px;
}
.ap-player audio { width: 100%; margin-bottom: 10px; }
.ap-ctrl { display: flex; gap: 8px; flex-wrap: wrap; }
.ap-textwrap {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 8px 4px; height: 46vh; min-height: 220px; overflow-y: auto; scroll-behavior: smooth;
}
.ap-line {
  padding: 9px 14px; font-size: 16px; line-height: 1.65; color: var(--muted); cursor: pointer;
  border-radius: 10px;
}
.ap-line:hover { background: #fafbff; }
.ap-line.on { color: var(--text); font-weight: 700; background: #eef0ff; }
.ap-notext { padding: 40px 16px; text-align: center; color: var(--muted); font-size: 14px; }

@media (max-width: 620px) {
  .au-grid { grid-template-columns: 1fr; }
  .ad-cover { width: 88px; height: 120px; }
  .ad-chap { padding: 10px 12px; }
  .ap-textwrap { height: 40vh; }
  .ap-line { font-size: 15px; }
}

/* ---------- 手机端：有声播放页的文本区吃满剩余高度，底框一直拉到底 ---------- */
/* 原来文本区是固定高度（46vh，窄屏 40vh），手机上只占半屏，下面空一大片。
   这里把播放页改成一列定高布局：导航栏、封面、播放器按各自内容占位，
   文本区 flex:1 吃掉剩下的**全部**高度 —— 底框因此一直延伸到屏幕最底部。
   ★ 播放页本来就没有底部导航（showView 对 audioplay 调 setTabbar(false)），
     所以不必保留 .content 给 tabbar 预留的那 90px 底部内边距，改成只留一点点
     + 刘海屏安全区。
   ★ 手机 Web 和安卓 APP 用的是同一份 CSS，改这一处两端同时生效。
   ★ 屏幕很矮（横屏、小屏）时文本区不可能无限压缩，所以 .content 允许整体滚动，
     并给文本区留 140px 下限 —— 宁可整页滚，也不能把正文挤没。 */
@media (max-width: 820px) {
  #view-audioplay { height: 100vh; height: 100dvh; display: flex; flex-direction: column; }
  #view-audioplay .navbar { flex: 0 0 auto; }
  #view-audioplay .content {
    flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column;
    padding-bottom: max(10px, env(safe-area-inset-bottom));
    overflow-y: auto;
  }
  #aup-body > .ap-head, #aup-body > .ap-player { flex: 0 0 auto; }
  #aup-body > .ap-textwrap-wrap { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
  #aup-body .ap-textwrap { height: auto; flex: 1 1 auto; min-height: 140px; }
}

/* ---------- 悬浮播放条（离开播放页后的后台播放 + 一键恢复） ---------- */
.au-float {
  position: fixed; left: 50%; transform: translateX(-50%);
  bottom: 78px;                       /* 移动端：让开底部导航 */
  width: min(520px, calc(100% - 24px));
  display: flex; align-items: center; gap: 10px;
  padding: 8px 12px; z-index: 60;
  background: rgba(255, 255, 255, .97);
  border: 1px solid var(--line); border-radius: 14px;
  box-shadow: 0 10px 30px rgba(31, 35, 48, .18);
  cursor: pointer; backdrop-filter: blur(6px);
}
.au-float-cover {
  width: 38px; height: 38px; border-radius: 8px; flex: 0 0 auto;
  display: flex; align-items: center; justify-content: center;
  font-size: 12px; color: var(--muted); background: #eef0f7; overflow: hidden;
}
.au-float-cover img { width: 100%; height: 100%; object-fit: cover; }
.au-float-txt { flex: 1; min-width: 0; }
.au-float-t { font-size: 13.5px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.au-float-s { font-size: 11.5px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.au-float-btn {
  flex: 0 0 auto; width: 34px; height: 34px; border-radius: 50%;
  border: 1px solid var(--line); background: #fff; color: var(--text);
  font-size: 15px; cursor: pointer; line-height: 1;
}
.au-float-btn:hover { background: #f0f2f8; }
@media (min-width: 900px) { .au-float { bottom: 24px; } }

/* ---------- 文字同步：已读 / 当前句 ---------- */
.ap-textwrap-wrap { position: relative; }
.ap-line.done { color: #b6bacb; }
.ap-line.on {
  color: var(--text); font-weight: 700; background: #eef0ff;
  box-shadow: inset 3px 0 0 var(--primary);
}
.ap-follow { position: absolute; right: 10px; bottom: 10px; box-shadow: var(--shadow); }
.ap-follow.hidden { display: none; }

/* ---------- 有声播放器：自绘控制条（原生控件的「…」里有下载/播放速度，不用它） ---------- */
.ap-slot { display: none; }            /* 原生 audio 元素只用来出声，界面全部自绘 */
.ap-bar { padding: 4px 2px 0; }
.ap-bar input[type=range] {
  -webkit-appearance: none; appearance: none;
  width: 100%; height: 22px; background: transparent; cursor: pointer; margin: 0;
}
.ap-bar input[type=range]::-webkit-slider-runnable-track {
  height: 5px; border-radius: 4px; background: #e6e9f2;
}
.ap-bar input[type=range]::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 15px; height: 15px; border-radius: 50%; background: var(--primary);
  margin-top: -5px; box-shadow: 0 1px 4px rgba(79, 70, 229, .4);
}
.ap-bar input[type=range]::-moz-range-track { height: 5px; border-radius: 4px; background: #e6e9f2; }
.ap-bar input[type=range]::-moz-range-thumb {
  width: 15px; height: 15px; border: 0; border-radius: 50%; background: var(--primary);
}
.ap-times {
  display: flex; justify-content: space-between;
  font-size: 12px; color: var(--muted); margin: 0 2px 10px;
}
.ap-ctrl { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.btn.ap-play {
  width: 48px; height: 48px; border-radius: 50%; padding: 0;
  font-size: 18px; line-height: 1; box-shadow: 0 6px 18px rgba(79, 70, 229, .3);
}


/* ---------- 推广邀请（「我的」页） ---------- */
.promote-row {
  display: flex; align-items: center; gap: 8px; margin-bottom: 8px; flex-wrap: wrap;
}
.promote-k {
  flex: 0 0 60px; font-size: 13px; color: var(--muted);
}
.promote-code {
  flex: 1; min-width: 120px; font-size: 18px; font-weight: 700; letter-spacing: 2px;
  color: var(--accent); background: var(--card); border: 1.5px dashed var(--line);
  border-radius: 8px; padding: 7px 12px; text-align: center; font-family: ui-monospace, Menlo, monospace;
}
.promote-link {
  flex: 1; min-width: 160px; font-size: 13px; padding: 8px 10px;
  border: 1.5px solid var(--line); border-radius: 8px;
  background: var(--card); color: var(--fg);
}
/* 四项统计固定一行：min-width 必须是 0，否则窄屏会折成两行 */
.me-stats {
  display: flex; gap: 6px; margin: 0; flex-wrap: nowrap;
}
.me-stat {
  flex: 1 1 0; min-width: 0; text-align: center; padding: 9px 2px;
  border: 1px solid var(--line); border-radius: 10px;
}
.me-stat b { display: block; font-size: 18px; line-height: 1.25; color: var(--accent); }
.me-stat span { font-size: 11px; color: var(--muted); white-space: nowrap; }
.pi-tag.kind { background: rgba(120, 120, 140, .14); color: var(--muted); }
.promote-sub {
  font-size: 13px; font-weight: 600; margin: 14px 0 6px;
}
.promote-item {
  display: flex; align-items: center; gap: 8px; font-size: 13px;
  padding: 6px 0; border-bottom: 1px solid var(--line);
}
.promote-item:last-child { border-bottom: 0; }
.pi-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pi-time { color: var(--muted); font-size: 12px; }
.pi-tag { font-size: 12px; padding: 1px 7px; border-radius: 999px; white-space: nowrap; }
.pi-tag.ok { background: rgba(48, 164, 108, .15); color: #30a46c; }
.pi-tag.no { background: rgba(229, 72, 77, .13); color: #e5484d; }

/* 推广 / 邀请 两条独立渠道，各占一块，中间有线分开 */
.promote-block + .promote-block {
  margin-top: 16px; padding-top: 16px; border-top: 1px dashed var(--line);
}
.promote-head {
  display: flex; align-items: center; gap: 8px; margin-bottom: 10px; flex-wrap: wrap;
}
.promote-head b { font-size: 15px; }
