/* ============================================================================
 * styles.css —— 鲸落书简 全部样式
 *
 * 依据 docs/TECH_DESIGN.md 2.6：本项目只有四个文件，样式全在这里，不引外部资源。
 * 约束（TECH_DESIGN 2.10）：不用 CSS 框架、不用 CDN 字体、不用图标库
 * —— 所以图标一律用文字符号（如 ← ），字体只用系统自带。
 * ========================================================================== */

:root {
  --paper:      #f6f4f1;   /* 页面底色，偏暖的纸感 */
  --card:       #ffffff;
  --ink:        #22262b;   /* 主文字 */
  --ink-soft:   #5c6672;   /* 次要文字 */
  --ink-faint:  #5f6a76;   /* 更弱的说明文字（加深后 ≥4.5:1，原先 #8b95a1 只有 2.77） */
  --line:       #e4dfd8;   /* 分隔线 */
  --accent:     #1f6f6b;   /* 主色：墨绿 */
  --accent-dk:  #175450;
  --accent-bg:  #e8f2f1;
  --danger:     #b3261e;
  --danger-bg:  #fdecea;
  --success:    #1d6b34;
  --success-bg: #e9f6ee;
  --radius:     10px;
  --shadow:     0 1px 2px rgba(34, 38, 43, .06);
}

* { box-sizing: border-box; }

/* 视图切换靠 hidden 属性；必须加这条，否则 display:flex 会把它盖掉 */
[hidden] { display: none !important; }

/*
 * 说明：HTML 里两个 <section> 都带 class="view"，但这里故意**不给它写样式**。
 * 它是给 app.js 用的钩子（切换视图时统一 document.querySelectorAll('.view')
 * 然后设 hidden），不是给 CSS 用的。看到它没有样式规则，不是漏写。
 */

body {
  margin: 0;
  padding: 28px 20px 64px;
  background: var(--paper);
  color: var(--ink);
  font: 15px/1.7 -apple-system, BlinkMacSystemFont, "Segoe UI",
        "Microsoft YaHei", "PingFang SC", "Hiragino Sans GB", sans-serif;
}

.wrap { max-width: 900px; margin: 0 auto; }

h1 { font-size: 24px; margin: 0; letter-spacing: .5px; }
h2 { font-size: 21px; margin: 0 0 6px; }
h3 { font-size: 15px; margin: 0; }

.muted { color: var(--ink-soft); margin: 0; }
.sub { font-size: 13px; margin-top: 2px; }

/* ---------------------------------------------------------------- 顶栏 */

.topbar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 14px; flex-wrap: wrap; margin-bottom: 18px;
}
.topbar-actions { display: flex; gap: 8px; }

/* ---------------------------------------------------------------- 按钮 */

.btn {
  font: inherit; font-size: 14px; cursor: pointer;
  padding: 7px 14px; border-radius: 8px;
  border: 1px solid var(--line); background: var(--card); color: var(--ink);
  transition: background .12s, border-color .12s;
}
.btn:hover { background: #f1efec; }

.btn-primary {
  background: var(--accent); border-color: var(--accent); color: #fff;
}
.btn-primary:hover { background: var(--accent-dk); border-color: var(--accent-dk); }

.btn-ghost { border-color: transparent; background: transparent; color: var(--ink-soft); }
.btn-ghost:hover { background: #ece9e5; color: var(--ink); }

.btn-danger { color: var(--danger); border-color: #eccac6; background: #fff; }
.btn-danger:hover { background: var(--danger-bg); }

/* 「已保存」的瞬时反馈（Day 14 用户测试）：
   原来点「保存进度」只有下面的百分比/进度条在变，按钮本身毫无反应，
   第一次用的人盯着按钮看，以为没保存上。这里让按钮自己回一句，1.5 秒后由 JS 恢复。 */
.btn.is-saved {
  background: var(--success); border-color: var(--success); color: #fff;
}

/* 键盘焦点可见（Tab 键导航时）：与 home.css 的重试按钮同一套规则 */
.btn:focus-visible,
.filter:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.btn-row { display: flex; gap: 8px; }

/* 小号按钮：用在笔记条目里 */
.btn-sm { padding: 3px 10px; font-size: 13px; border-radius: 6px; }

/* ---------------------------------------------------------------- 筛选项 */

.filters { display: flex; gap: 6px; margin-bottom: 18px; flex-wrap: wrap; }
.filter {
  font: inherit; font-size: 14px; cursor: pointer;
  padding: 5px 14px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--card); color: var(--ink-soft);
}
.filter:hover { background: #f1efec; }
.filter.is-active {
  background: var(--accent-bg); border-color: var(--accent); color: var(--accent-dk);
  font-weight: 600;
}

/* ---------------------------------------------------------------- 书单卡片列表 */

.book-list {
  display: grid; gap: 12px;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
}

.book-card {
  display: flex; gap: 14px; align-items: flex-start;
  padding: 14px; cursor: pointer;
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow);
  transition: border-color .12s, transform .12s;
}
.book-card:hover { border-color: #cfc8bf; transform: translateY(-1px); }

.book-card-body { min-width: 0; flex: 1; }

.book-title {
  font-size: 16px; font-weight: 600; margin: 0 0 2px;
  overflow-wrap: anywhere;
}
.book-author { font-size: 13px; color: var(--ink-soft); margin: 0 0 8px; }

/* ---------------------------------------------------------------- 封面与首字占位 */

.cover {
  flex: none; overflow: hidden;
  width: 72px; height: 100px; border-radius: 6px;
  display: flex; align-items: center; justify-content: center;
  font-size: 30px; font-weight: 600; color: #fff;
  background: linear-gradient(145deg, #3a7a76, #1f6f6b);   /* 浅端加深过：白字对比 3.76 → 4.97 */
  user-select: none;
}
.cover img { width: 100%; height: 100%; object-fit: cover; display: block; }

.cover-lg { width: 132px; height: 186px; font-size: 54px; border-radius: 8px; }

/* ------------------------------------------------------------ 悬停三件套（Day 11 Step 4） */

/* 封面 3D 翻转：外层给透视，内层负责转，背面预先反转到后面藏着 */
.flip-wrap { flex: none; perspective: 560px; }
.flip-inner {
  position: relative; width: 100%; height: 100%;
  transform-style: preserve-3d;
  transition: transform .45s cubic-bezier(.2, .7, .3, 1);
}
.flip-wrap .cover { backface-visibility: hidden; }

/* 触屏上 :hover 会「粘住」，所以只在真有鼠标的设备上启用悬停翻转 */
@media (hover: hover) {
  .flip-wrap:hover .flip-inner { transform: rotateY(180deg); }
}
.flip-wrap.is-flipped .flip-inner { transform: rotateY(180deg); }

@media (prefers-reduced-motion: reduce) {
  .flip-inner { transition: none; }
}

.cover-back {
  position: absolute; inset: 0;
  border-radius: 6px;                     /* 实际值由 JS 按原封面同步 */
  transform: rotateY(180deg); backface-visibility: hidden;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 3px; padding: 5px; overflow: hidden;
  background: #04342C;
}
.cover-back-label { font-size: 10px; line-height: 1; color: #9FE1CB; margin-bottom: 2px; }
.cover-back-chip {
  font-size: 10px; line-height: 1.25; color: #E1F5EE;
  background: rgba(225, 245, 238, .14);
  border-radius: 4px; padding: 1px 4px;
  max-width: 100%; word-break: break-all; text-align: center;
}
.cover-back-chip.is-none { color: #7FB3A4; background: none; }

/* 兜底：万一某处封面比 60px 还窄，放不下标题就只留关键词、字号再收一点 */
.flip-wrap.is-tiny .cover-back-label { display: none; }
.flip-wrap.is-tiny .cover-back-chip { font-size: 9px; padding: 1px 3px; }

/* 论坛帖子卡片：背面只放最热的那 1 条关键词，空间够，字号放大到看得清 */
.flip-wrap.is-single .cover-back-chip { font-size: 12px; padding: 3px 6px; }

/* 悬停资料浮层：固定定位挂在 body 上，不会被卡片的 overflow 切掉半截 */
.hover-tip {
  position: fixed; z-index: 45;          /* 高于导航栏(40)，低于弹窗(50) */
  min-width: 160px; max-width: 320px;    /* 简介从 20 来字扩到近百字，宽一点少折行 */
  padding: 10px 12px;
  background: var(--card); border: 1px solid var(--line);
  border-radius: 10px;
  box-shadow: 0 6px 20px rgba(30, 26, 22, .12);
}
.hover-tip-head { margin: 0 0 4px; font-size: 11px; color: var(--ink-soft); }
.hover-tip-body { margin: 0; font-size: 13px; line-height: 1.6; color: var(--ink); }
.hover-tip-works { margin: 6px 0 0; font-size: 12px; color: var(--ink-soft); }
.hover-tip-highlight { margin: 6px 0 0; font-size: 12px; color: var(--accent-dk); }
.hover-tip-none { margin: 0; font-size: 12px; color: var(--ink-soft); }

/* ---------------------------------------------------------------- 状态标签 */

.badge {
  display: inline-block; font-size: 12px; line-height: 1.6;
  padding: 1px 9px; border-radius: 999px; border: 1px solid;
}
.badge-want     { color: #7a6a4f; background: #f6f0e4; border-color: #e6dcc8; }
.badge-reading  { color: var(--accent-dk); background: var(--accent-bg); border-color: #cfe3e1; }
.badge-finished { color: #2f6b3a; background: #e9f4ea; border-color: #cfe4d2; }

/* ---------------------------------------------------------------- 进度条 */

.progress-line { font-size: 13px; color: var(--ink-soft); margin: 8px 0 0; }

.bar { height: 5px; border-radius: 999px; background: #eae6e1; margin-top: 6px; overflow: hidden; }
.bar-fill { height: 100%; background: var(--accent); border-radius: 999px; }

/* ---------------------------------------------------------------- 空状态 */

.empty {
  padding: 54px 24px; text-align: center;
  background: var(--card); border: 1px dashed #d9d3cb; border-radius: var(--radius);
}

/* ---------------------------------------------------------------- 加载态（Day 13）
   本机读数据是瞬时完成的，根本来不及「加载」。这里用一段约 300ms 的占位
   把「加载中」演出来，好在页面上真的看见这一态。
   接上后端后：换掉 app.js 里 showSkeleton 的调用即可，其余样式照用。 */
.skeleton-card {
  display: flex; gap: 14px; align-items: flex-start;
  padding: 14px;
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow);
}
.skeleton-block {
  background: linear-gradient(90deg, #ece8e2 25%, #f7f5f2 50%, #ece8e2 75%);
  background-size: 200% 100%;
  border-radius: 6px;
  animation: skeleton-sweep 1.2s ease-in-out infinite;
}
.skeleton-cover { width: 72px; height: 100px; flex: none; }
.skeleton-body { flex: 1; min-width: 0; padding-top: 8px; }
.skeleton-line { height: 14px; margin-bottom: 10px; }
.skeleton-line.is-wide { width: 62%; }
.skeleton-line.is-narrow { width: 38%; }
/* 说明小字：在网格容器里横跨整行，在普通容器里也占满一行 */
.skeleton-note {
  grid-column: 1 / -1; flex: 1 0 100%;
  margin: 0; padding: 4px 0;
  color: var(--ink-faint); font-size: 13px;
}
@keyframes skeleton-sweep {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .skeleton-block { animation: none; }
}
.empty-title { font-size: 17px; font-weight: 600; margin: 0 0 4px; }
.empty .btn { margin-top: 16px; }

/* ---------------------------------------------------------------- 出错提示条 */

.app-error {
  max-width: 900px; margin: 0 auto 16px;
  padding: 11px 16px; border-radius: var(--radius);
  background: var(--danger-bg); border: 1px solid #eccac6; color: #8c1d18;
  font-size: 14px;
}

/* 成功提示条（注册/登录成功等正向反馈） */
.app-success {
  max-width: 900px; margin: 0 auto 16px;
  padding: 11px 16px; border-radius: var(--radius);
  background: var(--success-bg); border: 1px solid #b8dcc4; color: var(--success);
  font-size: 14px;
}

/* ---------------------------------------------------------------- 卡片盒子（详情页用）*/

.box {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow);
  padding: 18px; margin-top: 16px;
}
.box-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap; margin-bottom: 12px;
}
.box-title { font-weight: 600; }

/* ---------------------------------------------------------------- 详情页头部 */

.detail-head { display: flex; gap: 20px; align-items: flex-start; flex-wrap: wrap; }
.detail-meta { min-width: 0; flex: 1; }
.detail-meta h2 { overflow-wrap: anywhere; }

.status-switch { display: flex; gap: 6px; margin-top: 12px; flex-wrap: wrap; }
.status-switch .btn.is-active {
  background: var(--accent-bg); border-color: var(--accent);
  color: var(--accent-dk); font-weight: 600;
}

/* ---------------------------------------------------------------- 进度录入 */

.progress-view { font-size: 15px; margin: 10px 0 14px; }
.progress-view strong { font-size: 21px; }
.progress-form { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.progress-form .bar { width: 100%; margin-top: 2px; }

.field-inline { display: inline-flex; align-items: center; gap: 6px; font-size: 14px; color: var(--ink-soft); }

input[type="text"], input[type="number"], textarea {
  font: inherit; font-size: 14px; color: var(--ink);
  padding: 6px 9px; border: 1px solid var(--line); border-radius: 7px;
  background: #fff;
}
input[type="number"] { width: 84px; }
input:focus, textarea:focus { outline: 2px solid #cfe3e1; outline-offset: 0; border-color: var(--accent); }
textarea { width: 100%; resize: vertical; }

/* ---------------------------------------------------------------- 笔记 */

.note-editor { margin-bottom: 16px; padding-bottom: 16px; border-bottom: 1px solid var(--line); }
.note-editor-foot {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin-top: 10px; flex-wrap: wrap;
}

.note-list { list-style: none; margin: 0; padding: 0; }
.note-item { padding: 13px 0; border-top: 1px solid var(--line); }
.note-item:first-child { border-top: none; }
.note-body { margin: 0 0 8px; white-space: pre-wrap; overflow-wrap: anywhere; }
.note-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.note-meta { font-size: 12px; color: var(--ink-faint); }

/* ---------------------------------------------------------------- 弹窗 */

.modal {
  position: fixed; inset: 0; z-index: 50;
  display: flex; align-items: center; justify-content: center;
  padding: 20px; background: rgba(34, 38, 43, .45);
}
.modal-card {
  width: 100%; max-width: 420px; max-height: 88vh; overflow: auto;
  background: var(--card); border-radius: 12px; padding: 22px;
  box-shadow: 0 10px 34px rgba(34, 38, 43, .22);
}
.modal-card h2 { margin-bottom: 16px; }

.field { display: block; margin-bottom: 14px; font-size: 14px; color: var(--ink-soft); }
.field input { display: block; width: 100%; margin-top: 6px; }
.field textarea { display: block; width: 100%; margin-top: 6px; }
.req { color: var(--danger); }

.form-error {
  margin: 0 0 14px; padding: 9px 12px; font-size: 13px;
  background: var(--danger-bg); border: 1px solid #eccac6;
  border-radius: 7px; color: #8c1d18;
}

.modal-foot { display: flex; justify-content: flex-end; gap: 8px; margin-top: 20px; }

/* ---------------------------------------------------------------- 窄屏 */

@media (max-width: 560px) {
  body { padding: 18px 14px 48px; }
  .book-list { grid-template-columns: 1fr; }
  .cover-lg { width: 96px; height: 136px; font-size: 40px; }
  h1 { font-size: 20px; }
}

/* home.css 的窄屏断点与这里保持一致（同为 560px），两个页面行为统一 */

/* ============================================================================
 * Day 11 新增：社区导航栏 + 论坛 / 私信 / 登录 / 我的（COMMUNITY_DESIGN.md）
 * ========================================================================== */

/* ---------------------------------------------------------------- 全局导航栏 */

.site-nav {
  position: sticky; top: 0; z-index: 40;
  background: var(--card);
  border-bottom: 1px solid var(--line);
  margin-bottom: 20px;
}
.site-nav-inner {
  max-width: 900px; margin: 0 auto;
  display: flex; align-items: center; gap: 18px;
  padding: 10px 20px; flex-wrap: wrap;
}
.site-brand {
  display: inline-flex; align-items: center; gap: 8px;
  text-decoration: none; color: var(--ink); font-weight: 600;
}
.site-brand-mark {
  width: 30px; height: 30px; border-radius: 8px;
  background: linear-gradient(145deg, #3a7a76, #1f6f6b);
  color: #fff; display: inline-flex; align-items: center; justify-content: center;
  font-size: 16px;
}
.site-brand-text { font-size: 16px; letter-spacing: .5px; }

.site-nav-links { display: flex; gap: 4px; flex: 1; }
.site-nav-link {
  font: inherit; font-size: 14px; cursor: pointer;
  padding: 6px 14px; border-radius: 8px;
  border: none; background: transparent; color: var(--ink-soft);
}
.site-nav-link:hover { background: #f1efec; color: var(--ink); }
.site-nav-link.is-active { background: var(--accent-bg); color: var(--accent-dk); font-weight: 600; }

/* 导航栏「私信」上的未读数字。没登录 / 没有未读时整颗隐藏 */
.nav-badge {
  display: inline-block; min-width: 16px; height: 16px; padding: 0 4px;
  margin-left: 4px; border-radius: 8px;
  background: var(--danger); color: #fff;
  font-size: 10px; font-weight: 600; line-height: 16px; text-align: center;
  vertical-align: 1px;
}
.nav-badge[hidden] { display: none; }

.site-nav-auth { display: flex; align-items: center; gap: 8px; }
/* nav-user 现在是 <button>，要重置按钮默认样式并加上可点击手感 */
.nav-user {
  display: flex; align-items: center; gap: 8px;
  font: inherit; cursor: pointer;
  padding: 4px 10px; border-radius: 8px;
  border: none; background: transparent;
}
.nav-user:hover { background: #f1efec; }
.nav-user-name { font-size: 14px; color: var(--ink-soft); }

/* ---------------------------------------------------------------- 头像 */

.avatar {
  display: inline-flex; align-items: center; justify-content: center;
  width: 36px; height: 36px; border-radius: 50%;
  background: var(--accent-bg); color: var(--accent-dk);
  font-weight: 600; font-size: 15px; flex: none;
}
.avatar-sm { width: 28px; height: 28px; font-size: 13px; }
.avatar-lg { width: 56px; height: 56px; font-size: 24px; }
.avatar img { width: 100%; height: 100%; object-fit: cover; border-radius: 50%; display: block; }

/* 头像选择器（注册页） */
.avatar-picker { margin: -6px 0 16px; }
.avatar-picker-row { display: flex; align-items: center; gap: 14px; margin-bottom: 10px; }
.avatar-picker-colors { display: flex; gap: 8px; flex-wrap: wrap; }
.avatar-swatch {
  width: 30px; height: 30px; border-radius: 50%; cursor: pointer;
  border: 2px solid transparent; padding: 0;
  transition: transform .1s, border-color .1s;
}
.avatar-swatch:hover { transform: scale(1.1); }
.avatar-swatch.is-active { border-color: var(--ink); }
.avatar-picker .btn { margin-right: 8px; }

/* ---------------------------------------------------------------- 热门排行 */

.hot-box { margin-top: 0; }
.hot-tabs { display: flex; gap: 6px; }
.hot-list { list-style: none; margin: 0; padding: 0; }
.hot-item {
  display: flex; align-items: center; gap: 14px;
  padding: 12px 0; border-top: 1px solid var(--line);
}
.hot-item:first-child { border-top: none; }
.hot-rank {
  width: 24px; text-align: center; font-size: 15px; font-weight: 600;
  color: var(--ink-soft); flex: none;
}
.hot-rank-top { color: var(--accent); }
/* Day 11 起与首页书卡统一成 72×100：原来的 44×60 放不下翻转关键词，字会挤成一团 */
.cover-sm { width: 72px; height: 100px; font-size: 30px; border-radius: 6px; }
.hot-body { min-width: 0; flex: 1; }
.hot-title { margin: 0; font-weight: 600; font-size: 15px; }
/* 作者名从「作者 · N 次讨论」里拆出来单独成元素，才有地方挂悬停资料 */
.hot-author { color: inherit; }
.hot-item:hover .hot-author { text-decoration: underline; }
.hot-go { flex: none; font-size: 13px; color: var(--accent); white-space: nowrap; }
.hot-item { cursor: pointer; }
.hot-item:hover .hot-go { text-decoration: underline; }

/* ---------------------------------------------------------------- 帖子流 */

.post-list { display: grid; gap: 12px; }
.post-card {
  display: flex; gap: 14px; align-items: flex-start;
  padding: 14px; cursor: pointer;
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow);
  transition: border-color .12s, transform .12s;
}
.post-card:hover { border-color: #cfc8bf; transform: translateY(-1px); }
.post-card-body { min-width: 0; flex: 1; }
.post-title { margin: 0 0 2px; font-size: 16px; font-weight: 600; }
.post-meta { margin: 0 0 8px; font-size: 13px; color: var(--ink-soft); }
.post-excerpt {
  margin: 0 0 8px; font-size: 14px; color: var(--ink-soft);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.post-foot { font-size: 13px; }

/* --------------------------------------------- 收藏按钮（Day 11 新增） */

/* 书名与收藏按钮同一行；窄屏挤不下时按钮换行，不撑破卡片 */
.post-title-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 2px; }
/* 热门榜的书名行：同款布局，榜单更紧凑 */
.hot-title-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 2px; }
.post-title-row .post-title { margin: 0; }

.fav-btn {
  display: inline-flex; align-items: center; gap: 5px; flex: none;
  padding: 3px 10px 3px 8px;
  font: inherit; font-size: 12px; line-height: 1.5;
  color: var(--ink-soft);
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 999px;
  cursor: pointer;
  transition: color .15s, border-color .15s, background-color .15s, transform .15s;
}
.fav-btn:hover:not(:disabled) {
  color: var(--ink); border-color: #cfc8bf; background: var(--paper);
  transform: translateY(-1px);
}
.fav-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.fav-btn:disabled { cursor: progress; opacity: .7; }

.fav-icon { width: 15px; height: 15px; flex: none; overflow: visible; }
.fav-star, .fav-orbit, .fav-dot { transform-box: fill-box; transform-origin: center; }
.fav-orbit { fill: none; stroke: currentColor; stroke-width: 1; stroke-dasharray: 2.6 3.2; opacity: .4; }
.fav-star  { fill: none; stroke: currentColor; stroke-width: 1.4; stroke-linejoin: round; }
.fav-dot   { fill: currentColor; opacity: 0; }

/* 悬停：星微微放大 —— 反馈落在鼠标所在的地方 */
.fav-btn:hover:not(:disabled) .fav-star { transform: scale(1.12); }

/* 处理中：轨道转起来、文字变「收藏中…」、按钮禁用（防重复点击） */
.fav-btn.is-busy .fav-orbit { animation: fav-spin .9s linear infinite; opacity: .7; }

/* 已收藏：星填金、轨道变实线并亮起轨道点 */
.fav-btn.is-on { color: #8a5a12; border-color: #e6c07a; background: #fdf6e8; }
.fav-btn.is-on .fav-star  { fill: #ef9f27; stroke: #9a6412; }
.fav-btn.is-on .fav-orbit { stroke-dasharray: none; opacity: .85; }
.fav-btn.is-on .fav-dot   { opacity: 1; }

/* 只在「刚收藏成功」那一次播弹一下；刷新列表不会再播（那会是假反馈） */
.fav-btn.is-just-on .fav-star { animation: fav-pop .34s ease-out; }

/* 已在书架但状态不是「想读」：虚线边、光标变问号，看着就不像能改的样子 */
.fav-btn.is-locked { border-style: dashed; cursor: help; }

@keyframes fav-spin { to { transform: rotate(360deg); } }
@keyframes fav-pop {
  0%   { transform: scale(.72); }
  62%  { transform: scale(1.2); }
  100% { transform: scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  .fav-btn, .fav-star, .fav-orbit, .fav-dot { transition: none; animation: none; }
}

/* ---------------------------------------------------------------- 评论 */

.comment-list { list-style: none; margin: 0; padding: 0; }
.comment-item { padding: 13px 0; border-top: 1px solid var(--line); }
.comment-item:first-child { border-top: none; }
.comment-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 4px; }
.comment-name { font-weight: 600; font-size: 14px; }
.comment-body { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; }
.comment-editor { display: flex; gap: 8px; margin-top: 16px; align-items: flex-end; }
.comment-editor textarea { flex: 1; }

/* 评论点赞心心：白色描边心 + 数字，放在评论头部右端 */
.like-btn {
  display: inline-flex; align-items: center; gap: 4px; flex: none;
  align-self: center;          /* 头部其他元素按基线对齐，心心这一颗单独居中 */
  margin-left: auto;           /* 推到这一行的右端（不另起一行） */
  padding: 2px 7px 2px 6px;
  font: inherit; font-size: 12px; line-height: 1.6;
  color: var(--ink-soft);
  background: transparent;
  border: 1px solid transparent;
  border-radius: 999px;
  cursor: pointer;
  transition: color .15s, background-color .15s;
}
.like-btn:hover:not(:disabled) { color: var(--danger); background: var(--danger-bg); }
.like-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.like-btn:disabled { cursor: progress; }

.like-icon { width: 14px; height: 14px; flex: none; overflow: visible; }
.like-heart {
  fill: #ffffff; stroke: #7c8792; stroke-width: 1.5; stroke-linejoin: round;
  transform-box: fill-box; transform-origin: center;
  transition: fill .18s, stroke .18s;
}

/* 悬停：心微微放大 + 描边转红 —— 反馈落在鼠标所在的地方 */
.like-btn:hover:not(:disabled) .like-heart { transform: scale(1.12); stroke: var(--danger); }

/* 处理中：心轻轻脉动 + 按钮禁用（防重复点击），数字不动 */
.like-btn.is-busy { opacity: .6; }
.like-btn.is-busy .like-heart { animation: like-pulse .9s ease-in-out infinite; }

/* 已点赞：心填红、数字加重 */
.like-btn.is-liked { color: var(--danger); }
.like-btn.is-liked .like-heart { fill: #e0453c; stroke: var(--danger); }
.like-btn.is-liked .like-count { font-weight: 600; }

/* 只在「刚点赞成功」那一次播弹一下；刷新列表不会再播（那会是假反馈） */
.like-btn.is-just-liked .like-heart { animation: like-pop .36s ease-out; }

@keyframes like-pulse {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(.82); }
}
@keyframes like-pop {
  0%   { transform: scale(.6); }
  45%  { transform: scale(1.32); }
  70%  { transform: scale(.94); }
  100% { transform: scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  .like-btn, .like-heart { transition: none; animation: none; }
}

/* ---------------------------------------------------------------- 私信 */

.conversation-list { display: flex; flex-direction: column; gap: 4px; }
.conversation-item {
  display: flex; align-items: center; gap: 12px;
  padding: 12px; cursor: pointer; border-radius: 8px;
}
.conversation-item:hover { background: #f1efec; }
.conversation-body { min-width: 0; flex: 1; }
.conversation-name { margin: 0; font-weight: 600; font-size: 15px; }
.conversation-body .muted { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 未读徽标：显示未读条数（不是纯红点，一眼看出有几条没读） */
.unread-dot {
  min-width: 18px; height: 18px; padding: 0 5px;
  border-radius: 9px; background: var(--danger); color: #fff;
  font-size: 11px; font-weight: 600; line-height: 18px; text-align: center;
  flex: none;
}
/* 点击处理中的那一行：不可再点，避免连点重复进同一个会话 */
.conversation-item.is-busy { opacity: .6; pointer-events: none; }

.chat-head { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; }
.chat-log {
  display: flex; flex-direction: column; gap: 8px;
  max-height: 50vh; overflow: auto; padding: 4px 0;
}
.chat-msg {
  max-width: 72%; padding: 9px 13px; border-radius: 12px;
  font-size: 14px; white-space: pre-wrap; overflow-wrap: anywhere;
}
.chat-msg-peer { align-self: flex-start; background: #efebe6; }
.chat-msg-me { align-self: flex-end; background: var(--accent); color: #fff; }
.chat-input { display: flex; gap: 8px; margin-top: 14px; }
.chat-input input { flex: 1; }

/* ---------------------------------------------------------------- 登录 / 注册 */

.auth-card {
  max-width: 420px; margin: 40px auto 0;
  background: var(--card); border: 1px solid var(--line);
  border-radius: 12px; box-shadow: var(--shadow);
  padding: 24px;
}
.auth-card h2 { margin-bottom: 12px; }
.auth-tabs { display: flex; gap: 6px; margin-bottom: 18px; }
.auth-hint { margin-top: 14px; }

/* ---------------------------------------------------------------- 我的 */

.me-card { display: flex; flex-direction: column; align-items: center; gap: 10px; text-align: center; }
.me-card h2 { margin: 0; }
.me-card .btn { margin-top: 8px; }

/* 可点击的用户名（进个人主页） */
.user-link {
  color: var(--accent-dk); text-decoration: none; cursor: pointer;
}
.user-link:hover { text-decoration: underline; }

/* 可点击的头像（进个人主页） */
.avatar-link { cursor: pointer; }
.avatar-link:hover { box-shadow: 0 0 0 2px var(--accent-bg); }

/* 会话名 / 聊天标题可点进主页 */
.conversation-name.user-link { cursor: pointer; }
.chat-head .user-link { cursor: pointer; font-size: 16px; }

/* 简介编辑 */
.bio-wrap { width: 100%; }
.bio-text { margin: 0 0 4px; }
.bio-editor { width: 100%; text-align: left; }
.bio-editor textarea {
  width: 100%; box-sizing: border-box; padding: 10px 12px;
  border: 1px solid var(--line); border-radius: var(--radius);
  font: inherit; font-size: 14px; resize: vertical; background: var(--card);
}
.bio-editor-actions { display: flex; gap: 8px; justify-content: flex-end; margin-top: 8px; }

/* 书单（个人主页 / 我的） */
.shelves { display: flex; flex-direction: column; gap: 0; }
.shelf-row {
  display: flex; gap: 12px; align-items: baseline;
  padding: 10px 0; border-top: 1px solid var(--line);
}
.shelf-row:first-child { border-top: none; }
.shelf-label {
  flex: none; width: 64px; font-weight: 600; font-size: 14px; color: var(--ink);
}
.shelf-books { min-width: 0; flex: 1; font-size: 14px; color: var(--ink-soft); overflow-wrap: anywhere; }

/* 个人主页活动区里的评论来源 */
.comment-source {
  display: block; margin-top: 4px; font-size: 12px; color: var(--accent-dk);
}

/* ---------------------------------------------------------------- 窄屏（社区） */

@media (max-width: 560px) {
  .site-nav-inner { padding: 10px 14px; }
  .site-nav-links { order: 3; width: 100%; justify-content: space-around; }
  .site-nav-auth { margin-left: auto; }
}

/* ============================================================
   Day 17 · 接口数据（只读演示视图）
   表格用真库返回的数据，样式保持和站内卡片一致的暖纸感
   ============================================================ */

#view-api-demo .topbar {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 14px;
}

#api-demo-status { min-height: 1.7em; }
#api-demo-status.is-error { color: var(--danger); }  /* 错误行实测 5.95:1，达标 ≥4.5（--danger #b3261e 对 --paper #f6f4f1） */

.api-table {
  width: 100%;
  border-collapse: collapse;
  background: var(--card);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow);
  font-size: 14px;
}

.api-table th,
.api-table td {
  border: 1px solid var(--line);
  padding: 9px 12px;
  text-align: left;
}

.api-table th {
  background: var(--success-bg);
  color: var(--ink);
  font-weight: 600;
  white-space: nowrap;
}

.api-table td { color: var(--ink-soft); }
.api-table td:first-child { color: var(--ink); font-weight: 500; }

@media (max-width: 560px) {
  .api-table th, .api-table td { padding: 7px 8px; font-size: 13px; }
}



/* ============================================================================
 * 星海鲸落主题（Day 20+ 视觉升级）
 * ----------------------------------------------------------------------------
 * 做法分三层，按顺序覆盖，不改动上面的原始规则：
 *   1) 重定义 :root 变量 —— 把「纸感浅色」翻成「星海深色」，全站自动跟随
 *   2) 定点补丁 —— 少数写死浅色 hex 的规则单独覆盖
 *   3) 新组件 —— 星海背景层 / 开场四幕 / 守护鲸面板 / 形态图鉴 / 数据卡 / 今日一句
 * 约束：零依赖、零图片（全 CSS + 内联 SVG）、双击 file:// 可用；
 *       尊重系统「减少动态效果」。
 * 对比度（WCAG 公式实算，正文阈 4.5:1）：
 *   主文字 15.77 / 次文字 10.24 / 弱文字 7.12 / 按钮深字 6.71（最差紫端）
 *   错误文字 10.43 / 成功文字 11.36 / 图鉴未解锁 5.93 / 已解锁 12.69 —— 全部达标
 * ========================================================================== */

:root {
  --paper:      #0a1134;                  /* 星海底色 */
  --card:       rgba(126, 140, 232, .09); /* 玻璃卡 */
  --ink:        #e9edff;                  /* 主文字：对 #0a1134 实测 15.77:1 */
  --ink-soft:   #b7c0e6;                  /* 次要文字：对底色 10.24:1、玻璃卡上 9.14:1 */
  --ink-faint:  #95a0c8;                  /* 弱文字：对底色 7.12:1、玻璃卡上 6.36:1 */
  --line:       rgba(152, 163, 255, .22);
  --accent:     #4fd8c9;                  /* 主色：青 */
  --accent-dk:  #9f8bff;                  /* 辅色：紫 */
  --accent-bg:  rgba(79, 216, 201, .15);
  --danger:     #ff9a8f;
  --danger-bg:  rgba(255, 122, 108, .14);
  --success:    #7ce8ae;
  --success-bg: rgba(110, 231, 168, .14);
  --radius:     12px;
  --shadow:     0 2px 16px rgba(2, 6, 24, .38);
  --star-1:     #4fd8c9;
  --star-2:     #55b8f5;
  --star-3:     #9f8bff;
  --gold:       #ffd166;                  /* 信笺的封蜡金 */
  --btn-ink:    #0d1030;                  /* 亮底按钮深字：对紫端 #9f8bff 6.71:1、对青端 #4fd8c9 10.58:1 */
}

body {
  background:
    radial-gradient(900px 500px at 12% 4%, rgba(124, 108, 240, .16), transparent 70%),
    radial-gradient(700px 420px at 88% 26%, rgba(80, 170, 235, .13), transparent 70%),
    linear-gradient(180deg, #0d1240 0%, #111c42 30%, #0a1330 62%, #05081c 100%);
  background-attachment: fixed;
  color: var(--ink);
}
.wrap { position: relative; z-index: 2; max-width: 960px; }

/* 标题渐变字 */
.topbar h1, h2 {
  background: linear-gradient(110deg, #eef2ff 10%, #8fd8ff 45%, #a08fff 80%);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}

/* ---------------------------------------------------------------- 2 定点补丁 */
.btn { background: rgba(140, 150, 255, .06); border-color: var(--line); color: var(--ink); }
.btn:hover { background: rgba(140, 150, 255, .14); }
.btn-primary {
  background: linear-gradient(135deg, var(--star-1) 0%, var(--star-2) 50%, var(--star-3) 100%);
  border-color: transparent; color: var(--btn-ink); font-weight: 700;
  box-shadow: 0 0 16px rgba(140, 150, 255, .35);
}
.btn-primary:hover { box-shadow: 0 0 26px rgba(150, 160, 255, .55); transform: translateY(-1px); }
.btn-ghost { color: #b9c2f5; background: rgba(140, 150, 255, .06); }
.btn-ghost:hover { background: rgba(140, 150, 255, .15); color: var(--ink); }
.btn-danger { color: var(--danger); border-color: rgba(255, 154, 143, .38); background: rgba(255, 122, 108, .08); }
.filter { color: #a8b2dd; background: rgba(150, 160, 255, .06); border-color: rgba(150, 160, 255, .28); }
.filter:hover { background: rgba(150, 160, 255, .14); color: var(--ink); }
.filter.is-active {
  color: var(--btn-ink); font-weight: 700; border-color: transparent;
  background: linear-gradient(135deg, var(--star-1), var(--star-3));
  box-shadow: 0 0 14px rgba(140, 150, 255, .4);
}
.book-card, .post-card, .conversation-item, .auth-card, .me-card, .api-table {
  background: var(--card); border-color: var(--line); backdrop-filter: blur(6px);
}
.book-card:hover, .post-card:hover { border-color: rgba(170, 180, 255, .5); }
.book-cover { background: linear-gradient(145deg, #4a58c8, #2b3585); color: #eef2ff; }
.badge-want     { color: #ffe1a8; background: rgba(255, 209, 102, .14); border-color: rgba(255, 209, 102, .35); }
.badge-reading  { color: #b6f4ec; background: rgba(79, 216, 201, .16); border-color: rgba(79, 216, 201, .38); }
.bar { background: rgba(150, 160, 255, .18); }
.bar-fill { background: linear-gradient(90deg, var(--star-1), var(--star-3)); }
.skeleton, .skeleton-line { background: linear-gradient(90deg, rgba(150,160,255,.10) 25%, rgba(150,160,255,.20) 50%, rgba(150,160,255,.10) 75%); }
.app-error { background: var(--danger-bg); border-color: rgba(255, 154, 143, .4); color: #ffc9c2; }
.app-success { background: var(--success-bg); border-color: rgba(124, 232, 174, .4); color: #c2f5da; }
.field input, .field textarea, input, textarea, select { background: rgba(8, 14, 40, .6); color: var(--ink); border-color: var(--line); }
input:focus, textarea:focus { outline: 2px solid rgba(79, 216, 201, .45); border-color: var(--accent); }
input::placeholder, textarea::placeholder { color: var(--ink-faint); }
.site-nav { background: rgba(10, 14, 40, .72); backdrop-filter: blur(10px); border-bottom: 1px solid var(--line); }
.site-nav-link { color: #a8b2dd; }
.site-nav-link:hover { background: rgba(140, 150, 255, .12); color: var(--ink); }
.site-nav-link.is-active {
  color: var(--btn-ink); font-weight: 700; border-color: transparent;
  background: linear-gradient(135deg, var(--star-1), var(--star-2));
  box-shadow: 0 0 12px rgba(140, 150, 255, .4);
}
.site-brand-mark {
  background: linear-gradient(135deg, var(--star-1), var(--star-2) 50%, var(--star-3));
  color: var(--btn-ink); box-shadow: 0 0 14px rgba(140, 150, 255, .5);
}
.nav-user:hover { background: rgba(140, 150, 255, .12); }
.fav-btn.is-on { color: #ffe1a8; border-color: rgba(255, 209, 102, .45); background: rgba(255, 209, 102, .12); }
.fav-btn.is-on .fav-star { fill: var(--gold); stroke: #b58a2e; }
.chat-msg-peer { background: rgba(150, 160, 255, .12); }
.chat-msg-me { background: linear-gradient(135deg, var(--star-1), var(--star-2)); color: var(--btn-ink); }
.avatar { background: linear-gradient(145deg, #4a58c8, #2b3585); color: #eef2ff; }
.api-table th { background: rgba(150, 160, 255, .1); }
.api-table td, .api-table th { border-color: var(--line); }
.tabs, .auth-tabs { border-color: var(--line); }

/* ---------------------------------------------------------------- 3 新组件 */

/* 3.1 星海背景层（装饰，不参与交互） */
.starfield, .opening { position: fixed; inset: 0; overflow: hidden; pointer-events: none; }
.starfield { z-index: 0; }
.opening { z-index: 5; }

.nebula { position: absolute; border-radius: 50%; filter: blur(40px); }
.n1 { width: 520px; height: 380px; left: -8%; top: 6%;
  background: radial-gradient(ellipse, rgba(124,108,240,.18), rgba(124,108,240,0) 70%);
  animation: nebulaDrift 26s ease-in-out infinite; }
.n2 { width: 460px; height: 340px; right: -6%; top: 30%;
  background: radial-gradient(ellipse, rgba(80,170,235,.15), rgba(80,170,235,0) 70%);
  animation: nebulaDrift 32s ease-in-out infinite reverse; }
.n3 { width: 620px; height: 420px; left: 24%; bottom: -10%;
  background: radial-gradient(ellipse, rgba(150,120,255,.11), rgba(150,120,255,0) 70%);
  animation: nebulaDrift 38s ease-in-out infinite; animation-delay: -12s; }
@keyframes nebulaDrift { 0%,100% { transform: translate(0,0); } 50% { transform: translate(36px,-22px); } }

.ray { position: absolute; top: -10%; width: 130px; height: 75%;
  background: linear-gradient(180deg, rgba(165,185,255,.15), rgba(165,185,255,0) 80%);
  transform: skewX(-14deg); filter: blur(6px); animation: shimmer 7s ease-in-out infinite; }
.ray.r1 { left: 16%; } .ray.r2 { left: 44%; animation-delay: 2.2s; width: 190px; }
.ray.r3 { left: 74%; animation-delay: 4s; width: 100px; }
@keyframes shimmer { 0%,100% { opacity: .45; } 50% { opacity: .9; } }

.dot { position: absolute; border-radius: 50%; background: #cdd6ff; animation: twinkle 5s ease-in-out infinite; }
.dot.d1{width:3px;height:3px;left:8%;top:30%;} .dot.d2{width:2px;height:2px;left:22%;top:52%;animation-delay:1s;}
.dot.d3{width:3px;height:3px;left:33%;top:22%;animation-delay:2s;} .dot.d4{width:2px;height:2px;left:55%;top:44%;animation-delay:.6s;}
.dot.d5{width:3px;height:3px;left:66%;top:18%;animation-delay:1.6s;} .dot.d6{width:2px;height:2px;left:81%;top:36%;animation-delay:2.6s;}
.dot.d7{width:3px;height:3px;left:90%;top:56%;animation-delay:3.1s;} .dot.d8{width:2px;height:2px;left:13%;top:70%;animation-delay:2s;}
.dot.d9{width:2px;height:2px;left:40%;top:64%;animation-delay:.9s;background:#b9a8ff;}
.dot.d10{width:3px;height:3px;left:72%;top:66%;animation-delay:1.8s;background:#b9a8ff;}
.dot.d11{width:2px;height:2px;left:5%;top:46%;animation-delay:2.7s;}
.dot.d12{width:2px;height:2px;left:95%;top:24%;animation-delay:1.2s;background:#b9a8ff;}
.dot.d13{width:2px;height:2px;left:28%;top:38%;animation-delay:3.2s;}
.dot.d14{width:2px;height:2px;left:60%;top:70%;animation-delay:2.1s;background:#b9a8ff;}
@keyframes twinkle { 0%,100% { opacity: .15; } 50% { opacity: .85; } }

.bubble { position: absolute; border-radius: 50%; border: 1px solid rgba(150,165,255,.35);
  background: radial-gradient(circle at 32% 30%, rgba(255,255,255,.3), rgba(110,130,230,.08));
  animation: rise 10s linear infinite; }
.bubble.bb1{width:18px;height:18px;left:12%;bottom:-30px;animation-delay:0s;}
.bubble.bb2{width:10px;height:10px;left:18%;bottom:-30px;animation-delay:3.5s;}
.bubble.bb3{width:14px;height:14px;right:16%;bottom:-30px;animation-delay:1.8s;}
.bubble.bb4{width:8px;height:8px;right:24%;bottom:-30px;animation-delay:5.2s;}
.bubble.bb5{width:22px;height:22px;left:48%;bottom:-30px;animation-delay:7s;}
@keyframes rise { 0% { transform: translateY(0); opacity: 0; } 12% { opacity: .7; } 100% { transform: translateY(-108vh); opacity: 0; } }

/* 3.2 两侧小鲸群：7 条梯度编队，藏在内容层后 */
.mini { position: absolute; left: 100%; will-change: transform; }
.mini .bob { animation: miniBob 5.5s ease-in-out infinite; }
.mini svg { display: block; filter: drop-shadow(0 0 9px rgba(130,145,255,.42)); }
.mini.m1 { top: 14%; animation: miniL 58s linear -12s infinite; } .mini.m1 svg { opacity: .55; }
.mini.m2 { top: 44%; animation: miniL 64s linear -38s infinite; } .mini.m2 svg { opacity: .4; }
.mini.m3 { top: 70%; animation: miniL 48s linear -30s infinite; } .mini.m3 svg { opacity: .5; }
.mini.m4 { top: 86%; animation: miniL 38s linear -8s infinite; }  .mini.m4 svg { opacity: .45; }
.mini.m7 { top: 8%;  animation: miniL 34s linear -17s infinite; }  .mini.m7 svg { opacity: .4; }
.mini.m5 { top: 30%; left: -360px; animation: miniR 56s linear -20s infinite; }
.mini.m5 svg { transform: scaleX(-1); opacity: .5; }
.mini.m6 { top: 58%; left: -360px; animation: miniR 44s linear -4s infinite; }
.mini.m6 svg { transform: scaleX(-1); opacity: .45; }
@keyframes miniL { 0% { transform: translateX(0); } 100% { transform: translateX(calc(-100vw - 420px)); } }
@keyframes miniR { 0% { transform: translateX(0); } 100% { transform: translateX(calc(100vw + 360px)); } }
@keyframes miniBob { 0%,100% { transform: translateY(0) rotate(0deg); } 50% { transform: translateY(-12px) rotate(-2deg); } }

/* 3.3 上浮的信笺 */
.letter { position: absolute; animation: drift 16s ease-in-out infinite; opacity: .85; }
.letter.lt1 { left: 9%; bottom: 6%; }
.letter.lt2 { right: 11%; bottom: 10%; animation-delay: 5s; }
.letter.lt3 { right: 26%; bottom: 3%; animation-delay: 9s; }
@keyframes drift { 0%,100% { transform: translateY(0) rotate(-4deg); } 50% { transform: translateY(-30px) rotate(4deg); } }

/* 3.4 守护鲸面板 */
.guard { position: relative; overflow: hidden; margin: 0 0 18px; padding: 16px 22px;
  display: flex; align-items: center; gap: 18px; text-align: left;
  background: var(--card); border: 1px solid var(--line); border-radius: 18px; backdrop-filter: blur(6px); }
.g-deco { position: absolute; z-index: 1; pointer-events: none; }
.g-deco svg { display: block; }
.g-deco.d1 { right: 26%; top: 14%; opacity: .3; animation: gDrift 24s ease-in-out infinite; }
.g-deco.d2 { right: 6%; bottom: 8%; opacity: .22; animation: gDrift 32s ease-in-out infinite reverse; }
@keyframes gDrift { 0%,100% { transform: translate(0,0); } 50% { transform: translate(-30px, 12px); } }
.g-whale, .guard-info { position: relative; z-index: 2; }
.g-whale { flex: none; width: 400px; display: flex; flex-direction: column; align-items: center; gap: 8px; }
.g-canvas { position: relative; width: 400px; height: 112px; }
.g-canvas > * { position: absolute; top: 50%; }
.whale-line { left: 150px; transform: translate(-50%, -50%); display: none; }
.guard.sleep .whale-line { display: block; }
.whale-stage { left: 108px; display: block; transition: transform .7s cubic-bezier(.2,.7,.3,1), left .7s ease;
  transform: translate(-50%, -50%) scale(var(--s, 1)); transform-origin: 50% 50%; }
.guard.sleep .whale-stage { display: none; }
.guard.dual .whale-stage { left: 280px; }
.whale-stage2 { left: 280px; display: none; transition: transform .7s cubic-bezier(.2,.7,.3,1);
  transform: translate(-50%, -50%) scale(var(--s2, .72)); transform-origin: 50% 50%; }
.guard.dual .whale-stage2 { display: block; animation: whaleWake 1.1s ease-out both; }
@keyframes whaleWake {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(.4); filter: blur(5px); }
  100% { opacity: 1; filter: blur(0); }
}
.stage-badge { display: inline-block; margin: 0 0 4px; padding: 4px 14px; border-radius: 999px;
  font-size: 12.5px; font-weight: 700; color: var(--btn-ink);
  background: linear-gradient(135deg, var(--star-1), var(--star-3));
  box-shadow: 0 0 14px rgba(140,150,255,.55); }
.guard-info h3 { font-size: 16px; color: var(--ink); margin-bottom: 5px; }
.guard-info p { font-size: 13.5px; color: var(--ink-soft); margin-bottom: 5px; }
.stage-count { font-size: 12.5px; color: var(--ink-faint); }

/* 鲸的游姿（面板内） */
.stage-svg .a-body { transform-box: fill-box; transform-origin: center; animation: aSwim 4s ease-in-out infinite; }
@keyframes aSwim { 0%,100% { transform: rotate(0deg) translateY(0); } 50% { transform: rotate(-2deg) translateY(-6px); } }
.stage-svg .a-tail { transform-box: fill-box; transform-origin: 0% 50%; animation: aTail 4s ease-in-out infinite; animation-delay: -.4s; }
@keyframes aTail { 0%,100% { transform: rotate(-8deg); } 50% { transform: rotate(9deg); } }
.a-star, .f-star, .w-star { animation: twinkle 3.2s ease-in-out infinite; }

/* 装备：默认隐藏，按形态显现 */
.gear, .gear2 { opacity: 0; transition: opacity .7s ease; }
.whale-stage.g-trail #g-trail, .whale-stage.g-armor #g-armor, .whale-stage.g-core #g-core,
.whale-stage.g-sats #g-sats, .whale-stage.g-flame #g-flame, .whale-stage.g-halo #g-halo { opacity: 1; }
.whale-stage2.g2-trail #g2-trail, .whale-stage2.g2-armor #g2-armor, .whale-stage2.g2-core #g2-core,
.whale-stage2.g2-sats #g2-sats, .whale-stage2.g2-flame #g2-flame, .whale-stage2.g2-halo #g2-halo,
.whale-stage2.g2-warp #g2-warp, .whale-stage2.g2-matrix #g2-matrix, .whale-stage2.g2-wings #g2-wings { opacity: 1; }
.core-pulse { transform-box: fill-box; transform-origin: center; animation: corePulse 1.6s ease-in-out infinite; }
@keyframes corePulse { 0%,100% { transform: scale(1); opacity: .95; } 50% { transform: scale(1.55); opacity: .45; } }
.sat-orbit { transform-box: view-box; transform-origin: 230px 100px; animation: orbitSpin 9s linear infinite; }
.halo-ring { transform-box: fill-box; transform-origin: center; animation: orbitSpin 22s linear infinite; }
.flame { transform-box: fill-box; transform-origin: 0% 50%; animation: flameFlick .35s ease-in-out infinite alternate; }
@keyframes flameFlick { from { transform: scaleX(.8); } to { transform: scaleX(1.3); } }
@keyframes orbitSpin { to { transform: rotate(360deg); } }

/* 3.5 数据小卡 + 今日一句 */
.stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin: 22px 0 0; }
.stat { padding: 16px 18px; display: flex; align-items: center; gap: 12px;
  background: var(--card); border: 1px solid var(--line); border-radius: 14px; }
.s-ic { flex: none; width: 38px; height: 38px; border-radius: 11px; display: flex; align-items: center; justify-content: center; }
.s-ic.s1 { background: rgba(79,216,201,.15); } .s-ic.s2 { background: rgba(122,160,255,.16); } .s-ic.s3 { background: rgba(255,209,102,.14); }
.stat b { font-size: 19px; color: var(--ink); }
.stat span { display: block; font-size: 12.5px; color: var(--ink-soft); margin-top: 1px; }

.quote { margin: 16px 0 0; padding: 18px 24px; display: flex; align-items: center; gap: 16px;
  background: var(--card); border: 1px solid var(--line); border-radius: 16px; }
.q-ic { flex: none; width: 42px; height: 42px; border-radius: 12px; display: flex; align-items: center; justify-content: center;
  background: linear-gradient(135deg, var(--star-1), var(--star-3)); box-shadow: 0 0 14px rgba(140,150,255,.45); }
.q-txt b { font-size: 15px; color: var(--ink); }
.q-txt span { display: block; margin-top: 3px; font-size: 13px; color: var(--ink-soft); }

/* 3.6 形态图鉴（我的页） */
.codex { margin-top: 18px; padding: 20px 22px; text-align: left;
  background: var(--card); border: 1px solid var(--line); border-radius: 18px; }
.codex h3 { font-size: 16px; color: var(--ink); margin-bottom: 4px; }
.cx-sub { font-size: 12.5px; color: var(--ink-faint); margin: 0 0 14px; }
.cx-sub2 { margin-top: 12px; }
.cx-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 10px; }
.cx-tile { border-radius: 12px; padding: 10px 6px; text-align: center; font-size: 12px; transition: .4s;
  background: rgba(140,150,255,.05); border: 1px solid rgba(150,160,255,.18); color: #8f9ac4; }
.cx-tile b { display: block; font-size: 14px; font-weight: 700; margin-bottom: 3px; }
.cx-tile.on { color: #e6eaff; background: rgba(140,150,255,.13); border-color: rgba(170,180,255,.45);
  box-shadow: 0 0 12px rgba(140,150,255,.22); }
.cx-tile.now { color: #fff; background: linear-gradient(135deg, rgba(79,216,201,.25), rgba(159,139,255,.32));
  border-color: rgba(205,215,255,.75); box-shadow: 0 0 18px rgba(150,160,255,.45); }

/* 3.7 开场四幕 */
.veil { position: absolute; inset: 0; opacity: 0;
  background: radial-gradient(circle at 50% 30%, rgba(200,205,255,.45), rgba(30,30,90,.26) 55%, rgba(5,8,28,0) 78%);
  animation: veilFlash .75s ease-out 3.55s both; }
@keyframes veilFlash { 0% { opacity: 0; } 28% { opacity: 1; } 100% { opacity: 0; } }
.shockwave { position: absolute; left: 50%; top: 34%; width: 120px; height: 120px; margin: -60px 0 0 -60px; border-radius: 50%;
  border: 3px solid rgba(205,210,255,.9);
  box-shadow: 0 0 40px rgba(150,160,255,.7), inset 0 0 30px rgba(150,160,255,.5);
  animation: shock .85s cubic-bezier(.16,.8,.3,1) 3.52s both; }
.shockwave.s2 { animation-delay: 3.64s; border-width: 2px; }
@keyframes shock { 0% { transform: scale(.15); opacity: 1; } 100% { transform: scale(6.5); opacity: 0; } }
.burst { position: absolute; left: 50%; top: 34%; width: 480px; height: 480px; margin: -240px 0 0 -240px; opacity: 0;
  background: repeating-conic-gradient(rgba(215,218,255,.5) 0deg 1.6deg, transparent 1.6deg 9deg);
  -webkit-mask-image: radial-gradient(circle, transparent 26%, #000 34%, transparent 72%);
  mask-image: radial-gradient(circle, transparent 26%, #000 34%, transparent 72%);
  animation: burstSpin .8s ease-out 3.52s both; }
@keyframes burstSpin { 0% { transform: rotate(-18deg) scale(.5); opacity: .85; } 100% { transform: rotate(14deg) scale(1.6); opacity: 0; } }
.spray i { position: absolute; display: block; border-radius: 50%; opacity: 0;
  background: radial-gradient(circle at 34% 30%, #ffffff, #b9c8ff 75%);
  box-shadow: 0 0 8px rgba(200,210,255,.9); animation: sprayFall 1.1s ease-in 3.55s both; }
.spray .sp1{ left:34%; top:12%; width:6px; height:6px; } .spray .sp2{ left:44%; top:6%; width:4px; height:4px; animation-delay:.12s; }
.spray .sp3{ left:56%; top:10%; width:7px; height:7px; animation-delay:.06s; } .spray .sp4{ left:64%; top:16%; width:4px; height:4px; animation-delay:.2s; }
.spray .sp5{ left:26%; top:18%; width:5px; height:5px; animation-delay:.28s; } .spray .sp6{ left:50%; top:20%; width:5px; height:5px; animation-delay:.34s; }
@keyframes sprayFall { 0% { transform: translateY(-30px); opacity: 0; } 18% { opacity: .95; } 100% { transform: translateY(46vh); opacity: 0; } }
.ripple { position: absolute; left: 50%; top: 16%; width: 60px; height: 18px; margin: -9px 0 0 -30px; border-radius: 50%;
  border: 2px solid rgba(185,195,255,.55); opacity: 0; animation: rippleOut 1.8s ease-out both; }
.ripple.rp1 { animation-delay: .35s; } .ripple.rp2 { animation-delay: 1.5s; } .ripple.rp3 { animation-delay: 2.6s; }
@keyframes rippleOut { 0% { transform: scale(.3); opacity: .85; } 100% { transform: scale(3.6); opacity: 0; } }
.arc-ring { position: absolute; left: 50%; top: 30%; width: 420px; height: 420px; margin: -210px 0 0 -210px; border-radius: 50%;
  animation: arcLife 4.8s linear .25s both; }
.arc-ring svg { animation: orbitSpin 14s linear infinite; }
.arc-ring.a2 { width: 560px; height: 560px; margin: -280px 0 0 -280px; top: 34%; }
.arc-ring.a2 svg { animation-direction: reverse; animation-duration: 22s; }
@keyframes arcLife { 0% { opacity: 0; } 25% { opacity: .5; } 75% { opacity: .35; } 100% { opacity: 0; } }
.whale-front { position: absolute; left: 50%; top: 16%; width: 300px; margin-left: -150px; margin-top: -190px;
  transform: scale(.03); animation: approach 4.2s linear .25s both; filter: drop-shadow(0 0 34px rgba(120,135,255,.4)); }
@keyframes approach {
  0% { transform: scale(.03) translateY(3.2vh); opacity: 0; filter: blur(2px) brightness(1.5); }
  7% { opacity: 1; }
  30% { transform: scale(.12) translateY(2.6vh); filter: blur(1.2px) brightness(1.3); }
  55% { transform: scale(.38) translateY(1.8vh); filter: blur(.5px) brightness(1.15); }
  75% { transform: scale(1.05) translateY(.8vh); filter: blur(0) brightness(1.05); }
  88% { transform: scale(2.3) translateY(-.5vh); filter: brightness(1.02); }
  100% { transform: scale(4.8) translateY(-9vh); opacity: 0; filter: blur(8px) brightness(1.3); }
}
.perf { position: absolute; inset: 0; }
.p-jump { position: absolute; left: var(--x); top: 82vh; margin-left: -46px; margin-top: -30px; opacity: 0;
  animation: perfArc 3.2s cubic-bezier(.3,.4,.5,1) var(--d) both; }
@keyframes perfArc {
  0% { transform: translate(0,0) scale(.5) rotate(26deg); opacity: 0; }
  8% { opacity: 1; }
  38% { transform: translate(3.5vw, calc(-1 * var(--h))) scale(.9) rotate(-6deg); }
  72% { transform: translate(7vw, calc(-.45 * var(--h))) scale(.85) rotate(-14deg); }
  94% { transform: translate(9vw, 0) scale(.78) rotate(-22deg); }
  100% { transform: translate(9.5vw, 0) scale(.78) rotate(-22deg); opacity: 0; }
}
.p-whale, .p-slip { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); }
.p-jump .p-whale svg { display: block; transform: scaleX(-1); }
.p-whale { animation: pWhaleFade 3.2s linear var(--d) both; }
@keyframes pWhaleFade { 0%, 38% { opacity: 1; } 50%, 100% { opacity: 0; } }
.p-slip { width: 54px; height: 98px; border-radius: 12px;
  background: repeating-linear-gradient(180deg, rgba(10,14,50,.35) 0 2px, transparent 2px 24px),
    linear-gradient(90deg, #2b2560 0%, #4a3fa0 40%, #7a6ce0 50%, #4a3fa0 60%, #2b2560 100%);
  border: 2px solid rgba(190,200,255,.55);
  box-shadow: 0 0 20px rgba(140,150,255,.6), inset 0 3px 6px rgba(255,255,255,.25);
  display: flex; align-items: center; justify-content: center;
  animation: pSlipFade 3.2s linear var(--d) both; }
.p-slip span { color: var(--gold); font-weight: 800; font-size: 30px;
  text-shadow: 0 0 14px rgba(255,209,102,.75), 0 0 4px rgba(0,0,0,.4); }
@keyframes pSlipFade { 0%, 40% { opacity: 0; } 52%, 90% { opacity: 1; } 97%, 100% { opacity: 0; } }
.p-splash { position: absolute; left: var(--x); top: 82vh; }
.p-splash i { position: absolute; border-radius: 50%; border: 2px solid rgba(185,195,255,.7); opacity: 0;
  animation: pRing .8s ease-out calc(var(--d) + 2.95s) both; }
.p-splash i:nth-child(1) { width: 76px; height: 24px; margin: -12px 0 0 -38px; }
.p-splash i:nth-child(2) { width: 46px; height: 15px; margin: -7px 0 0 -23px; animation-delay: calc(var(--d) + 3.08s); border-width: 1.5px; }
@keyframes pRing { 0% { transform: scale(.25); opacity: .9; } 100% { transform: scale(2.2); opacity: 0; } }
.p-swim { position: absolute; left: var(--x); top: 83vh; margin-left: -48px; opacity: 0;
  filter: drop-shadow(0 0 8px rgba(130,145,255,.4));
  animation: pSwim 3.4s ease-in-out calc(var(--d) + 3.1s) both; }
.p-swim svg { display: block; transform: scaleX(-1); }
.perf.swim-left .p-swim svg { transform: none; }
@keyframes pSwim {
  0% { transform: translateX(0); opacity: 0; filter: blur(2px); }
  12% { opacity: .95; filter: blur(0); }
  80% { opacity: .9; }
  100% { transform: translateX(calc(var(--sw) * 26vw)); opacity: 0; filter: blur(2px); }
}
.whale-cruise { position: absolute; top: 24%; left: calc(100% + 40px);
  animation: cruise 38s linear 6.2s infinite; filter: drop-shadow(0 0 20px rgba(130,140,255,.35)); }
@keyframes cruise {
  0% { transform: translateX(0); opacity: 0; filter: blur(3px) brightness(1.2); }
  4% { opacity: .95; filter: blur(0) brightness(1); }
  60% { transform: translateX(calc(-58vw - 260px)) translateY(-16px) rotate(-1.5deg); opacity: .95; }
  88% { transform: translateX(calc(-88vw - 460px)) translateY(6px) rotate(1deg); opacity: 0; filter: blur(5px) brightness(.9); }
  100% { transform: translateX(calc(-100vw - 560px)); opacity: 0; filter: blur(8px) brightness(.85); }
}
.w-body { transform-box: fill-box; transform-origin: center; animation: bodyFlex 5.2s ease-in-out infinite; }
@keyframes bodyFlex { 0%,100% { transform: rotate(0deg) translateY(0); } 25% { transform: rotate(-1.3deg) translateY(-3px); } 75% { transform: rotate(1.3deg) translateY(2px); } }
.w-tail { transform-box: fill-box; transform-origin: 0% 50%; animation: tailSwim 5.2s ease-in-out infinite; animation-delay: -.38s; }
@keyframes tailSwim { 0%,100% { transform: rotate(-9deg); } 50% { transform: rotate(11deg); } }
.w-fin { transform-box: fill-box; transform-origin: 15% 0%; animation: finSway 5.2s ease-in-out infinite; animation-delay: -.2s; }
@keyframes finSway { 0%,100% { transform: rotate(6deg); } 50% { transform: rotate(-7deg); } }

/* 开场时的整页轻震 */
body.opening-shake { animation: shake .45s ease-out 3.62s 1; }
@keyframes shake {
  0%,100% { transform: translate(0,0); }
  20% { transform: translate(-3px,2px); } 40% { transform: translate(3px,-2px); }
  60% { transform: translate(-2px,-2px); } 80% { transform: translate(2px,2px); }
}

/* ---------------------------------------------------------------- 4 减少动态效果 */
@media (prefers-reduced-motion: reduce) {
  .opening { display: none; }
  .mini, .nebula, .ray, .dot, .bubble, .letter, .g-deco { animation: none; }
  .stage-svg .a-body, .stage-svg .a-tail, .a-star, .f-star, .w-star,
  .core-pulse, .sat-orbit, .halo-ring, .flame, .w-body, .w-tail, .w-fin { animation: none; }
  body.opening-shake { animation: none; }
}

/* ---------------------------------------------------------------- 5 窄屏适配
   面板左栏是固定 400px 的鲸画布 + 右侧文字，窄屏放不下就改成上下堆叠。
   36em ≈ 576px，覆盖手机竖屏与预览面板的窄宽度。 */
@media (max-width: 36em) {
  .guard { flex-direction: column; align-items: stretch; gap: 10px; padding: 14px 16px; }
  .g-whale { width: 100%; }
  .g-canvas { width: 100%; max-width: 360px; margin: 0 auto; }
  .whale-line { left: 50%; }
  .whale-stage { left: 42%; }
  .guard.dual .whale-stage { left: 28%; }
  .whale-stage2 { left: 72%; }
  .guard .g-deco.d1 { right: 2%; }
  .guard .g-deco.d2 { display: none; }
  .stats { grid-template-columns: 1fr; gap: 10px; }
  .cx-grid { grid-template-columns: repeat(3, 1fr); }
  .quote { flex-direction: column; align-items: flex-start; gap: 10px; }
}

/* ------------------------------------------------- 6 深色主题下的表单控件
   Day 27 · 修「输入框白底浅字」（第三方试用反馈原话：「框里太淡了」）

   现象：阅读进度的数字输入框是白底、字是浅色 --ink，里面填的数字几乎看不见。

   真根因（跟设备无关，电脑上一样白 —— 起初误判成安卓深色模式，已更正）：
     第 328 行那条早期写的规则
         input[type="text"], input[type="number"], textarea { background: #fff; }
     权重是 (0,1,1)；
     而 Day 20 星海段想把它改成深底的规则用的是光秃秃的 input，权重只有 (0,0,1)，
     选择器竞争输了 —— 所以 background 一直保留着 #fff 白色。
     偏偏 color 两边算出来都是 var(--ink)（同一个浅色），看不出谁赢，
     于是最终呈现是「白底 + 浅字」，而不是「深底 + 浅字」。

   修法：把选择器写成与 328 行同等或更高的权重，深色底才覆盖得过去。
     这里不能只用 input 了事，必须写成 input[type="..."] 这种带属性的形式。

   附带保留 color-scheme: dark：它不是本 bug 的元凶，但能让浏览器把滚动条、
   下拉框等原生控件也按深色渲染，和整页统一。 */

:root { color-scheme: dark; }

input[type="text"],
input[type="number"],
input:not([type]),
textarea,
select {
  background-color: #0d1430;   /* 不透明深底，覆盖 328 行的 #fff */
  background-image: none;
  color: var(--ink);
}

/* ---------------------------------------------- 7 同步失败提示条（Day 29）
   为什么要有：sync.js 推送失败会把本地改动回滚。界面如果不说话，用户看到的是
   「我明明点了保存，一刷新就没了」——正是 AC-23 要防的那类事：出错可以，
   装作没出错不行。
   颜色用 --danger / --danger-bg：#b3261e 在 #fdecea 上按 WCAG 公式实算 5.71:1，
   过 AA（4.5:1）。深色主题在 814 行那段重新定义了 --danger-bg，这里不用再管。
   定位 fixed + 居中：不能挡住底部的导航栏，所以抬高到 18px 以上。 */
.sync-banner {
  position: fixed;
  left: 50%;
  bottom: 18px;
  transform: translateX(-50%);
  z-index: 90;
  display: flex;
  align-items: center;
  gap: 12px;
  max-width: min(94vw, 460px);
  padding: 9px 10px 9px 12px;
  border: 1px solid var(--danger);
  border-radius: var(--radius);
  background: var(--danger-bg);
  color: var(--ink);
  font-size: 12px;
  line-height: 1.5;
  box-shadow: var(--shadow);
}

.sync-banner[hidden] { display: none; }

.sync-banner-text { flex: 1; }

.sync-banner-close {
  flex: 0 0 auto;
  padding: 4px 10px;
  border: 1px solid var(--danger);
  border-radius: 6px;
  background: transparent;
  color: var(--danger);
  font: inherit;
  cursor: pointer;
}

.sync-banner-close:hover { background: rgba(179, 38, 30, .08); }

/* 键盘用户能看见焦点在哪（人工验收第 2 条就查这个） */
.sync-banner-close:focus-visible {
  outline: 2px solid var(--danger);
  outline-offset: 2px;
}

/* ============================================================
 * 论坛搜索（Day 31）
 * 放在「最新讨论」框里、帖子列表上方。样式跟着星海主题的变量走，
 * 不写死颜色 —— 否则换主题时会变成一块突兀的白。
 * ============================================================ */
.forum-search {
  display: flex;
  gap: 8px;
  align-items: center;
  margin: 0 0 12px;
}

.forum-search input {
  flex: 1 1 auto;
  min-width: 0;              /* 窄屏时能被压缩，否则会把按钮挤出容器 */
  padding: 8px 12px;
  font: inherit;
  color: var(--ink, #e8f1ff);
  background: var(--panel-soft, rgba(255, 255, 255, 0.06));
  border: 1px solid var(--line, rgba(255, 255, 255, 0.14));
  border-radius: 10px;
  outline: none;
  transition: border-color 0.15s, box-shadow 0.15s;
}

.forum-search input::placeholder {
  color: var(--ink-dim, rgba(232, 241, 255, 0.45));
}

/* 键盘用户必须能看见焦点在哪（preflight M2 那条人工检查就看这个） */
.forum-search input:focus-visible {
  border-color: var(--accent, #6fd6c8);
  box-shadow: 0 0 0 3px rgba(111, 214, 200, 0.18);
}

.forum-search-hint {
  margin: 0 0 10px;
  font-size: 13px;
}

/* ============================================================
 * 站内确认弹窗的正文（Day 30）
 * 容器直接用 .modal / .modal-card / .modal-foot，这里只补正文排版 ——
 * 不重新定义外观，才能保证跟"添加书籍"那些弹窗长得一模一样。
 * ============================================================ */
.dialog-text {
  margin: 0;
  font-size: 14px;
  line-height: 1.7;
  color: var(--ink-soft);
}

/* ============================================================
 * 键盘焦点统一可见（Day 30 修 M2）
 * ------------------------------------------------------------
 * 之前只有少数元素（添加书籍按钮、筛选档位）在 Tab 聚焦时有明显轮廓，
 * 帖子卡片、点赞、收藏、私信项走一遍基本看不出焦点在哪儿。
 *
 * 用 :focus-visible 而不是 :focus —— 前者**只在键盘操作时**生效，
 * 鼠标点按钮不会冒出一个多余的框。已有的更具体规则
 * （比如 .forum-search input:focus-visible）不会被这条覆盖。
 * ============================================================ */
a:focus-visible,
button:focus-visible,
input:focus-visible,
textarea:focus-visible,
select:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--accent, #6fd6c8);
  outline-offset: 2px;
}

/* ============================================================
 * 论坛「加载更多」（Day 32）
 * ------------------------------------------------------------
 * 位置：帖子流正下方、居中。它不是主操作（主操作是「发帖」），
 * 所以用 btn-ghost 而不是 btn-primary —— 一页一页翻是浏览时的次要动作，
 * 满屏突出的按钮会把它误导成"必须点"。
 *
 * 三种状态都要有明确落点：
 *   默认      —— 描边按钮，写「加载更多」
 *   加载中    —— 文字变「加载中…」且 disabled，点了没反应是预期行为
 *   没有下一页 —— 整块 hidden（不是变灰），灰按钮会让人反复去点
 * ============================================================ */
.post-more {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  margin: 18px 0 4px;
}

.post-more-hint {
  margin: 0;
  font-size: 13px;
}

.post-more .btn {
  min-width: 132px;
}

.post-more .btn[disabled] {
  cursor: default;
  opacity: 0.6;
}

/* ============================================================
 * 论坛搜索移到页面顶部（Day 32）
 * ------------------------------------------------------------
 * 它原来住在「最新讨论」那个 box 里，上下有 box 的内边距托着。
 * 现在直接站在 topbar 和热门榜之间，没人给它留白了，得自己撑开 ——
 * 否则输入框会贴着「热门书籍」的标题，看着像标题的一部分。
 *
 * ⚠️ 这条只作用于**论坛页的直属子元素**（#view-forum > …），
 *    不用 .forum-search 泛匹配：万一以后别处也放搜索框，不该被这里的间距连累。
 * ============================================================ */
#view-forum > .forum-search {
  margin: 2px 0 10px;
}

#view-forum > .forum-search-hint {
  margin: -4px 0 12px;
}

/* =============================================================
 * Day 32 封面 + 真简介补丁
 * - 真简介从豆瓣抓的多段文字（\n 分段），悬浮卡正文按换行分段
 * ============================================================= */
.hover-tip-body {
  white-space: pre-line;
}

/* =============================================================
 * Day 32 修：装饰鲸鱼压住正文（同学反馈「鱼会挡到字」）
 *   1. 整个开场装饰层从 z-index:5 降到 1 —— .wrap 是 2，鲸鱼从此只在
 *      卡片的缝隙里当背景花纹，不再盖在文字上；
 *   2. 窄屏（≤40em ≈ 640px）关掉跃水那批精灵：手机屏幕小，装饰和文字抢地方，
 *      留着只会打架。星空、渐变色、气泡仍然保留，气氛不散。
 * ============================================================= */
.opening { z-index: 1; }

@media (max-width: 40em) {
  /* 手机上整层关掉：鲸鱼退到文字后面也没用 —— 深底上一条浅蓝鲸鱼从字缝里透出来，
     字照样糊（第二次被反馈才想明白）。这层纯装饰、pointer-events:none，关掉零副作用。
     桌面宽屏保留：屏幕大、留白多，鲸鱼游在卡片缝隙里是加分项。 */
  .opening { display: none !important; }

  .perf,
  .whale-front,
  .whale-cruise,
  .spray { display: none !important; }
}
