/* ============================================================
   靴语 · 设计系统 v8 —— 时尚杂志 editorial
   版式：整版封面压字 / 卷首语 / 非对称封面故事 / 点线目录 /
         马赛克画廊（首图撑大，六格一循环）
   气质：克制、性感、纸质感。奶油底 + 炭黑 + 焦糖金
   修订：修掉 68ch 破坏栅格、目录死白、原价逻辑、撇号字距
   ============================================================ */
:root {
  /* 纸与墨 */
  --paper: #faf7f1;
  --paper-2: #f3eee4;
  --card: #ffffff;
  --ink: #17130f;          /* 主文 16:1 */
  --ink-soft: #4d443c;     /* 次级 8:1 */
  --muted: #7a6e62;        /* 辅助 4.8:1 */
  --faint: #9d9084;
  --night: #17130f;

  /* 品牌：焦糖 / 深焙 */
  --brand: #a9551f;
  --brand-deep: #7a3512;
  --gold: #c8994a;
  --gold-soft: #e8c98d;
  --brand-wash: #f6ece0;
  --brand-line: #e6d3ba;

  --line: #e7e0d4;
  --line-strong: #d6c9b6;

  --radius: 4px;
  --radius-sm: 3px;
  --radius-lg: 6px;

  --shadow-sm: 0 1px 2px rgba(30,22,14,.05), 0 3px 10px rgba(30,22,14,.04);
  --shadow-md: 0 10px 30px rgba(40,28,16,.09);
  --shadow-lg: 0 22px 60px rgba(40,28,16,.16);

  --ease: cubic-bezier(.22,.61,.36,1);
  --serif: "STZhongsong", "STSong", "Songti SC", "Source Han Serif SC", "Noto Serif CJK SC", "SimSun", Georgia, serif;
  --num: Georgia, "Times New Roman", serif;
  --sans: -apple-system, BlinkMacSystemFont, "PingFang SC", "HarmonyOS Sans SC", "Microsoft YaHei", sans-serif;
}

* { box-sizing: border-box; margin: 0; padding: 0; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; scroll-padding-top: 76px; }
body {
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.8;
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}
img { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { font: inherit; cursor: pointer; }
::selection { background: var(--brand); color: #fff; }
:focus-visible { outline: 2px solid var(--brand); outline-offset: 3px; }
p, .readable { max-width: 68ch; }
/* 栅格内的段落不能被 68ch 限宽，否则右对齐会失效、留出莫名空洞 */
.sec-lede, .end-fine { max-width: none; }

/* 小标签：杂志的呼吸感全靠它 */
.eyebrow {
  font-family: var(--sans);
  font-size: 11px; font-weight: 600;
  letter-spacing: .32em; text-transform: uppercase;
  color: var(--brand);
}

/* ---------- 导航：压在封面上时是透明的 ---------- */
.nav {
  position: fixed; top: 0; left: 0; right: 0; z-index: 80;
  background: rgba(250,247,241,.92);
  backdrop-filter: blur(14px) saturate(1.4);
  -webkit-backdrop-filter: blur(14px) saturate(1.4);
  border-bottom: 1px solid var(--line);
  transition: background .35s var(--ease), border-color .35s var(--ease), backdrop-filter .35s;
}
.nav-inner {
  max-width: 1280px; margin: 0 auto; padding: 16px 24px;
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
}
.nav .brand, .nav-links a { color: var(--ink); transition: color .35s var(--ease); }
/* 压在封面图上时才转为透明白字 */
.nav.over {
  background: transparent; border-bottom-color: transparent;
  backdrop-filter: none; -webkit-backdrop-filter: none;
}
.nav.over .brand, .nav.over .nav-links a { color: #fff; }
.brand { display: flex; align-items: baseline; gap: 10px; }
.brand .b-cn { font-family: var(--serif); font-size: 21px; font-weight: 700; letter-spacing: .16em; }
.brand .b-en { font-family: var(--num); font-size: 10px; letter-spacing: .3em; opacity: .7; }
.nav-links { display: flex; gap: 26px; font-size: 13px; letter-spacing: .18em; }
.nav-links a.active { color: var(--brand); }
.nav.over .nav-links a.active { color: var(--gold-soft); }
.nav-links a { position: relative; padding: 6px 0; }
.nav-links a::after {
  content: ""; position: absolute; left: 0; right: 100%; bottom: 2px; height: 1px;
  background: currentColor; transition: right .3s var(--ease);
}
.nav-links a:hover::after { right: 0; }

/* ---------- 封面 ---------- */
.cover {
  /* 首页只留这一屏：封面铺满视口，往下的内容都在「全部目录」页 */
  position: relative; min-height: 100vh; min-height: 100svh;
  display: flex; align-items: flex-end; overflow: hidden; isolation: isolate;
  background: linear-gradient(160deg, #2a211a, #17130f 60%);
}
.cover-media { position: absolute; inset: 0; z-index: -1; }
.cover-media img { width: 100%; height: 100%; object-fit: cover; object-position: center 30%; opacity: 0; transition: opacity 1.2s var(--ease); }
.cover-media img.loaded { opacity: 1; }
/* 压暗层：左边是文字区（标题/按钮），右边留给 3D 人物，两者不能一样压。
   🔴 2026-10-06 修遮挡：原来 90deg 只压到 55% 就基本放开了，
   可拼贴图上「原图保护中 PROTECTED ORIGINAL」那行大字横穿画面中部，
   正好压在主标题「先听见靴声再看见她」上 —— 字压字，读起来花。
   现在把文字区的暗度往右多铺 12 个百分点（55%→67%），并给文字块后面补一层
   柔和的椭圆暗晕（大字只被压淡、不消失，人物区仍清亮）。 */
.cover-shade {
  position: absolute; inset: 0;
  background:
    radial-gradient(115% 82% at 22% 74%, rgba(20,15,10,.62) 0%, rgba(20,15,10,.34) 42%, rgba(20,15,10,0) 74%),
    linear-gradient(180deg, rgba(23,19,15,.74) 0%, rgba(23,19,15,.3) 30%, rgba(23,19,15,.55) 62%, rgba(23,19,15,.95) 100%),
    linear-gradient(90deg, rgba(23,19,15,.76) 0%, rgba(23,19,15,.34) 44%, rgba(23,19,15,.08) 67%);
}
/* 手机上文字铺满整屏（没有右侧人物区了），压暗要更实才读得清 */
@media (max-width: 860px) {
  .cover-shade {
    background:
      linear-gradient(180deg, rgba(23,19,15,.82) 0%, rgba(23,19,15,.6) 34%, rgba(23,19,15,.8) 72%, rgba(23,19,15,.96) 100%),
      linear-gradient(90deg, rgba(23,19,15,.6) 0%, rgba(23,19,15,.3) 100%);
  }
}
.cover-inner {
  position: relative; z-index: 2; width: 100%;
  max-width: 1280px; margin: 0 auto;
  padding: 140px 24px clamp(52px, 8vh, 88px);
}
/* 🔴 2026-10-06 修遮挡：整块文字原来占满 1280px（.display 实测宽 1232px），
   标题字号跟着拉满，横着穿到右侧 3D 人物身上 —— 看着像字压在她前面，
   而且这块透明容器还会吃掉她那一区的鼠标（点她没反应）。
   现在把文字收成左栏：宽度取「到人物栏之前」，标题再大也到不了她那侧。
   min() 是关键：窄屏时左边本来就是满宽，自动退回原样。 */
.cover-inner > * { max-width: min(100%, 620px); }
.cover .display { font-size: clamp(42px, 6.6vw, 92px); }
.cover .eyebrow { color: var(--gold-soft); }
.cover .display { color: #fff; margin-top: 22px; }
.cover-lede {
  margin-top: 24px; max-width: 34em;
  color: rgba(255,255,255,.82); font-size: clamp(14px, 1.6vw, 16.5px);
  line-height: 2; letter-spacing: .06em; font-weight: 300;
}
.cover-actions { display: flex; gap: 14px; flex-wrap: wrap; margin-top: 34px; }
.cover-facts {
  margin-top: clamp(34px, 5vh, 56px); padding-top: 22px;
  border-top: 1px solid rgba(255,255,255,.18);
  display: flex; gap: clamp(28px, 5vw, 64px); flex-wrap: wrap;
}
.cover-facts dt { font-size: 10.5px; letter-spacing: .3em; color: rgba(255,255,255,.55); }
.cover-facts dd { margin-top: 2px; color: #fff; font-family: var(--serif); }
.cover-facts dd b { font-size: 26px; font-weight: 700; letter-spacing: .02em; }
.cover-facts dd { font-size: 12px; letter-spacing: .1em; }
/* 旧版右下角那枚竖排小标已换成下方 .cover-catalog（醒目大胶囊） */

/* 超大显示器级标题 */
.display {
  font-family: var(--serif);
  font-size: clamp(42px, 9.4vw, 104px);
  font-weight: 700; line-height: 1.02; letter-spacing: .04em;
}
.display span { display: block; }
.display em { font-style: normal; color: var(--gold-soft); }

/* ---------- 卷首语 ---------- */
.note { max-width: 880px; margin: 0 auto; padding: clamp(60px, 9.5vh, 112px) 24px; text-align: center; }
.note .n-tag { color: var(--faint); margin-bottom: 30px; }
/* 字距会把撇号后撑出一个空格，这里单独归零并收紧字宽 */
.note .n-tag .apos { letter-spacing: 0; margin-right: -.22em; }
.note blockquote { border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); padding: clamp(30px, 4.5vh, 46px) 0; }
.note blockquote p {
  font-family: var(--serif); font-weight: 700;
  font-size: clamp(20px, 3.5vw, 33px); line-height: 1.86; letter-spacing: .08em;
  color: var(--ink); max-width: none;
}
.note .n-sign {
  margin-top: 30px; font-family: var(--serif); font-size: 13px;
  letter-spacing: .28em; color: var(--brand);
}
.note .n-sign::before { content: "— "; }

/* ---------- 区块标题：通栏细线 + 编号 + 右对齐引语 ---------- */
.sec-head {
  max-width: 1280px; margin: 0 auto clamp(24px, 3vw, 38px);
  padding: 20px 24px 0;
  border-top: 1px solid var(--ink);
  display: grid; grid-template-columns: auto auto 1fr;
  align-items: baseline; gap: 4px 18px;
}
.sec-no {
  font-family: var(--num); font-size: 12px; letter-spacing: .26em;
  color: var(--brand); align-self: baseline;
}
.sec-head h2 {
  font-family: var(--serif); font-weight: 700;
  font-size: clamp(27px, 3.7vw, 42px);
  letter-spacing: .14em; line-height: 1.12;
}
.sec-lede {
  grid-column: 3; justify-self: end; text-align: right;
  font-size: 13px; color: var(--muted); letter-spacing: .09em; line-height: 1.9;
}
@media (max-width: 859px) {
  .sec-head { grid-template-columns: auto 1fr; }
  .sec-head h2 { grid-column: 2; }
  .sec-lede { grid-column: 1 / -1; justify-self: start; text-align: left; margin-top: 10px; }
}

/* ---------- 01 封面故事：非对称拼贴 ---------- */
.story { padding: clamp(10px, 3vh, 30px) 0 clamp(40px, 8vh, 80px); }
.story-grid {
  max-width: 1280px; margin: 0 auto; padding: 0 24px;
  display: grid; gap: 14px; grid-template-columns: 1fr;
}
@media (min-width: 760px) {
  .story-grid { grid-template-columns: 1.4fr 1fr; grid-template-rows: repeat(2, 1fr); gap: 18px; }
}
.s-item {
  position: relative; overflow: hidden; isolation: isolate;
  background: var(--paper-2); border-radius: var(--radius);
}
.s-item img { width: 100%; aspect-ratio: 4/3; object-fit: cover; transition: transform 1s var(--ease); }
.s-item:hover img { transform: scale(1.05); }
@media (min-width: 760px) {
  .s-lead { grid-row: span 2; }
  .s-lead img { aspect-ratio: auto; height: 100%; min-height: 100%; }
  .story-grid > .s-item:not(.s-lead) img { aspect-ratio: 16/11; }
}
.s-cap {
  position: absolute; inset: auto 0 0 0; padding: 44px 20px 18px;
  background: linear-gradient(transparent, rgba(18,14,10,.92));
  color: #fff; display: flex; flex-direction: column; gap: 5px;
}
.s-tag { font-size: 10.5px; letter-spacing: .26em; color: var(--gold-soft); text-transform: uppercase; }
.s-name { font-family: var(--serif); font-size: clamp(19px, 2.2vw, 27px); font-weight: 700; letter-spacing: .1em; line-height: 1.28; }
.s-line { font-size: 12.5px; color: rgba(255,255,255,.72); letter-spacing: .06em; }
.s-go {
  margin-top: 6px; font-size: 12px; letter-spacing: .18em; color: var(--gold-soft);
  display: inline-flex; align-items: center; gap: 8px;
}
/* 右侧两张副册图较矮，说明只留标签 + 名称，避免糊成一片 */
@media (min-width: 760px) {
  .story-grid > .s-item:not(.s-lead) .s-line { display: none; }
}
.s-go i { font-style: normal; transition: transform .3s var(--ease); }
.s-item:hover .s-go i { transform: translateX(6px); }

/* ---------- 02 目录 INDEX：点线目录（名称 …… 价格） ---------- */
.index { padding-bottom: clamp(34px, 6vh, 68px); }
.index-list {
  max-width: 1280px; margin: 0 auto; padding: 0 24px;
  list-style: none; border-top: 1px solid var(--line);
}
.entry { border-bottom: 1px solid var(--line); }
.entry > a {
  display: flex; align-items: center; gap: 20px;
  padding: 20px 6px; transition: background .3s var(--ease), padding .3s var(--ease);
}
.entry > a:hover { background: var(--paper-2); padding-left: 16px; }

.e-no {
  flex: none; width: 30px;
  font-family: var(--num); font-size: 13px; letter-spacing: .14em; color: var(--brand);
  align-self: flex-start; padding-top: 6px;
}
.e-thumb {
  flex: none; width: 74px; height: 96px; overflow: hidden;
  background: var(--paper-2); border-radius: var(--radius-sm);
}
.e-thumb img { width: 100%; height: 100%; object-fit: cover; transition: transform .55s var(--ease); }
.entry > a:hover .e-thumb img { transform: scale(1.07); }
.e-thumb.no-img { background: linear-gradient(150deg, var(--paper-2), var(--brand-wash)); }

.e-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 7px; }
.e-row1 { display: flex; align-items: baseline; gap: 14px; }
.e-name {
  font-family: var(--serif); font-weight: 700;
  font-size: clamp(19px, 2.1vw, 24px); letter-spacing: .1em; white-space: nowrap;
}
.e-dots {
  flex: 1; min-width: 26px; height: 0;
  border-bottom: 1px dotted var(--faint); transform: translateY(-6px);
}
.e-price { flex: none; white-space: nowrap; }
.e-price b {
  font-family: var(--serif); font-size: 21px; font-weight: 700;
  color: var(--brand); letter-spacing: .02em;
}
.e-price s { margin-left: 8px; font-size: 12.5px; color: var(--faint); }
.e-price .plain {
  font-family: var(--sans); font-size: 12.5px; color: var(--muted); letter-spacing: .1em;
}
.e-go { flex: none; font-size: 17px; color: var(--brand); transition: transform .3s var(--ease); }
.entry > a:hover .e-go { transform: translateX(6px); }

.e-row2 { display: flex; align-items: baseline; gap: 16px; }
.e-sub { flex: 1; min-width: 0; font-size: 13px; color: var(--ink-soft); letter-spacing: .05em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.e-meta { flex: none; font-size: 12px; color: var(--muted); letter-spacing: .12em; white-space: nowrap; }
.e-meta i { font-style: normal; color: var(--brand-line); padding: 0 4px; }

@media (max-width: 719px) {
  /* 横向可滑动时给右缘一个渐隐，明确提示还有内容 */
  .scene-bar {
    -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 34px), transparent);
    mask-image: linear-gradient(90deg, #000 calc(100% - 34px), transparent);
  }
  .entry > a { gap: 13px; padding: 16px 4px; }
  .e-no { width: 22px; padding-top: 4px; }
  .e-thumb { width: 58px; height: 76px; }
  .e-dots { display: none; }
  .e-row1 { flex-wrap: wrap; gap: 4px 10px; }
  .e-price { margin-left: auto; }   /* 名称贴左、价格贴右，中间留白，避免读串 */
  .e-row2 { flex-direction: column; gap: 3px; }
  .e-sub { white-space: normal; }
}

/* ---------- 筛选条 ---------- */
.scene-bar {
  max-width: 1280px; margin: 0 auto 22px; padding: 0 24px;
  display: flex; gap: 8px; overflow-x: auto; scrollbar-width: none;
}
.scene-bar::-webkit-scrollbar { display: none; }
.scene-chip {
  flex-shrink: 0; min-height: 38px; padding: 7px 18px; border-radius: 999px;
  background: transparent; border: 1px solid var(--line-strong);
  font-size: 13.5px; letter-spacing: .1em; color: var(--ink-soft);
  transition: all .22s var(--ease);
}
.scene-chip:hover { border-color: var(--brand); color: var(--brand-deep); }
.scene-chip.active { background: var(--ink); color: #fff; border-color: var(--ink); }

/* ---------- 03 套系画廊：马赛克（首图撑大，六格一循环） ---------- */
.gallery { padding-bottom: clamp(50px, 9vh, 96px); }
.grid {
  max-width: 1280px; margin: 0 auto; padding: 0 24px;
  display: grid; grid-template-columns: repeat(2, 1fr); gap: 14px;
}
@media (min-width: 768px) { .grid { grid-template-columns: repeat(3, 1fr); gap: 20px; } }

/* ≥1080px 且套数足够多时：4 列 × 定高行，靠 span 排出节奏 */
@media (min-width: 1080px) {
  .grid.is-mosaic {
    grid-template-columns: repeat(4, 1fr);
    grid-auto-rows: clamp(150px, 13.2vw, 224px);
    grid-auto-flow: dense; gap: 20px;
  }
  .grid.is-mosaic .album-card { display: flex; flex-direction: column; grid-row: span 2; }
  .grid.is-mosaic .album-card .thumb { aspect-ratio: auto; height: auto; flex: 1; min-height: 0; }
  /* 每 6 个一循环，正好铺满 4 列 × 5 行（6+4+6+4=20 格），不留空洞 */
  .grid.is-mosaic .album-card:nth-child(6n + 1) { grid-column: span 2; grid-row: span 3; }
  .grid.is-mosaic .album-card:nth-child(6n + 4) { grid-column: span 2; grid-row: span 3; }
  .grid.is-mosaic .album-card:nth-child(6n + 1) .a-title { font-size: 21px; letter-spacing: .08em; }
  .grid.is-mosaic .album-card:nth-child(6n + 1) .a-price { font-size: 21px; }
  .grid.is-mosaic .album-card:nth-child(6n + 1) .a-foot { padding: 76px 20px 20px; }
  .grid.is-mosaic .album-card:nth-child(6n + 1) .a-frame { top: 14px; left: 14px; padding: 5px 13px; font-size: 11.5px; }
}

.album-card { position: relative; display: block; }
.album-card .thumb {
  position: relative; display: block; overflow: hidden;
  aspect-ratio: 3/4; border-radius: var(--radius); background: var(--paper-2);
}
.album-card .thumb img { width: 100%; height: 100%; object-fit: cover; transition: transform .8s var(--ease); }
.album-card:hover .thumb img { transform: scale(1.06); }
.a-frame {
  position: absolute; top: 10px; left: 10px; z-index: 2;
  padding: 4px 11px; border-radius: 999px;
  background: rgba(250,247,241,.88); backdrop-filter: blur(6px);
  color: var(--brand-deep); font-size: 11px; letter-spacing: .12em; font-weight: 600;
}
.a-foot {
  position: absolute; inset: auto 0 0 0; z-index: 2; padding: 54px 14px 14px;
  background: linear-gradient(transparent, rgba(18,14,10,.88));
  color: #fff; display: flex; align-items: flex-end; justify-content: space-between; gap: 10px;
}
.a-title {
  font-family: var(--serif); font-size: 15.5px; font-weight: 700; letter-spacing: .06em; line-height: 1.45;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.a-price { font-family: var(--num); font-size: 17px; font-weight: 700; color: var(--gold-soft); white-space: nowrap; }

/* ---------- 收尾 / 封底 ---------- */
.end {
  background: var(--night); color: #fff;
  padding: clamp(56px, 9vh, 100px) 24px clamp(48px, 7vh, 80px);
}
.end > * { max-width: 1280px; margin-left: auto; margin-right: auto; }
.end .eyebrow.dark { color: var(--gold-soft); }
.end-h { font-family: var(--serif); font-size: clamp(26px, 4.4vw, 52px); line-height: 1.25; letter-spacing: .06em; margin-top: 18px; }
.end-h em { font-style: normal; color: var(--gold-soft); }
.end-steps {
  margin-top: clamp(34px, 5vh, 56px);
  display: grid; grid-template-columns: 1fr; gap: 22px 30px;
  border-top: 1px solid rgba(255,255,255,.16); padding-top: 28px;
}
@media (min-width: 760px) { .end-steps { grid-template-columns: repeat(3, 1fr); } }
.end-steps > div { display: flex; flex-direction: column; gap: 6px; }
.end-steps span { font-family: var(--num); font-style: italic; font-size: 18px; color: var(--gold-soft); }
.end-steps b { font-family: var(--serif); font-size: 17px; letter-spacing: .14em; }
.end-steps p { font-size: 13.5px; color: rgba(255,255,255,.66); letter-spacing: .04em; line-height: 1.75; max-width: 32ch; }
.end-fine {
  margin-top: clamp(30px, 5vh, 48px); padding-top: 20px;
  border-top: 1px solid rgba(255,255,255,.12);
  font-size: 12.5px; color: rgba(255,255,255,.62); letter-spacing: .06em; line-height: 1.9;
}
.end-fine b { color: var(--gold-soft); font-weight: 600; }

/* ---------- 页脚 ---------- */
footer { background: var(--night); color: rgba(255,255,255,.55); padding: 0 24px calc(40px + env(safe-area-inset-bottom)); }
.footer-inner {
  max-width: 1280px; margin: 0 auto; padding-top: 26px;
  border-top: 1px solid rgba(255,255,255,.12);
  display: flex; flex-wrap: wrap; gap: 16px; align-items: flex-end; justify-content: space-between;
}
.f-brand { display: flex; align-items: baseline; gap: 10px; color: #fff; }
.f-brand .b-cn { font-family: var(--serif); font-size: 19px; font-weight: 700; letter-spacing: .16em; }
.f-brand .b-en { font-family: var(--num); font-size: 10px; letter-spacing: .3em; opacity: .65; }
.f-line { font-size: 12.5px; letter-spacing: .06em; margin-top: 6px; }
.f-links { display: flex; gap: 22px; flex-wrap: wrap; font-size: 13px; letter-spacing: .1em; }
.f-links a { color: rgba(255,255,255,.72); }
.f-links a:hover { color: var(--gold-soft); }

/* ---------- 按钮 ---------- */
.btn {
  border: none; border-radius: 999px; padding: 13px 32px; min-height: 46px;
  background: var(--ink); color: #fff; font-weight: 600; font-size: 14.5px; letter-spacing: .16em;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  transition: all .25s var(--ease);
}
.btn:hover { transform: translateY(-2px); filter: brightness(1.12); }
.btn:active { transform: translateY(0); }
.btn.solid { background: #fff; color: var(--ink); }
.btn.solid:hover { box-shadow: 0 12px 30px rgba(255,255,255,.18); }
.btn.ghost { background: transparent; color: #fff; border: 1px solid rgba(255,255,255,.5); }
.btn.ghost:hover { background: rgba(255,255,255,.1); border-color: #fff; }
.btn.accent { background: var(--brand); color: #fff; box-shadow: 0 8px 24px rgba(169,85,31,.3); }
.btn.outline { background: #fff; color: var(--ink); border: 1px solid var(--ink); }
.btn.outline:hover { background: var(--ink); color: #fff; }
.btn:disabled { opacity: .5; cursor: not-allowed; transform: none; }
.btn.small { padding: 9px 18px; font-size: 13.5px; min-height: 38px; letter-spacing: .1em; }
.btn.block { width: 100%; }
.btn.danger { background: #b91c3a; color: #fff; }

/* ---------- 详情页 ---------- */
.detail { max-width: 1100px; margin: 0 auto; padding: 118px 24px 70px; }
.crumb { font-size: 12.5px; letter-spacing: .12em; color: var(--muted); margin-bottom: 20px; }
.crumb a { color: var(--brand); }
.crumb a:hover { text-decoration: underline; }
.detail-head h1 {
  font-family: var(--serif); font-size: clamp(26px, 4.6vw, 46px);
  font-weight: 700; letter-spacing: .1em; line-height: 1.35;
}
.detail-head .meta {
  margin: 16px 0 26px; font-size: 13px; letter-spacing: .14em; color: var(--muted);
  display: flex; flex-wrap: wrap; gap: 8px 22px;
}
.detail-head .meta span::before { content: "— "; color: var(--brand-line); }
.detail-head .desc { color: var(--ink-soft); font-size: 15.5px; line-height: 1.9; max-width: 60ch; }

.buy-bar {
  display: flex; flex-wrap: wrap; align-items: center; gap: 16px;
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
  padding: 22px 0; margin-bottom: 32px;
}
.buy-bar .price { font-family: var(--serif); font-size: 34px; font-weight: 700; color: var(--brand); letter-spacing: .02em; }
.buy-bar .hint { color: var(--ink-soft); font-size: 13.5px; flex: 1 1 240px; line-height: 1.8; letter-spacing: .04em; }
.buy-bar .btn { margin-left: auto; }

.preview-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 12px; flex-wrap: wrap; margin: 0 0 14px;
}
.preview-head h2 { font-family: var(--serif); font-size: 18px; font-weight: 700; letter-spacing: .22em; }
.preview-head .tip { font-size: 12.5px; color: var(--muted); letter-spacing: .08em; }

.preview-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
@media (min-width: 640px) { .preview-grid { grid-template-columns: repeat(4, 1fr); gap: 12px; } }
.preview-grid .cell {
  position: relative; cursor: zoom-in; overflow: hidden; isolation: isolate;
  background: var(--paper-2); border-radius: var(--radius-sm);
}
.preview-grid .cell::after {
  content: "⌕"; position: absolute; inset: 0; font-size: 24px; color: #fff;
  display: flex; align-items: center; justify-content: center;
  background: rgba(18,14,10,0); opacity: 0; transition: all .25s var(--ease);
}
.preview-grid .cell:hover::after { opacity: 1; background: rgba(18,14,10,.34); }
.preview-grid img { width: 100%; aspect-ratio: 1; object-fit: cover; transition: transform .6s var(--ease); }
.preview-grid .cell:hover img { transform: scale(1.08); }
.lock-tip {
  margin-top: 24px; text-align: center; color: var(--ink-soft); font-size: 14px; line-height: 1.9;
  letter-spacing: .06em; padding: 20px; border-top: 1px solid var(--line);
}

/* ---------- 表单卡片 ---------- */
.form-card {
  max-width: 520px; margin: clamp(100px, 14vh, 140px) auto 60px; padding: 30px 26px;
  background: var(--card); border: 1px solid var(--line);
}
.form-card h2 { font-family: var(--serif); margin-bottom: 6px; font-size: 21px; font-weight: 700; letter-spacing: .14em; }
.form-card .sub { color: var(--muted); font-size: 13.5px; margin-bottom: 18px; letter-spacing: .04em; }
.form-card label {
  display: block; font-size: 12.5px; letter-spacing: .16em; color: var(--ink-soft);
  font-weight: 600; margin: 18px 0 6px;
}
.form-card input, .form-card textarea, .form-card select {
  width: 100%; padding: 12px 14px; min-height: 46px; border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm); font: inherit; font-size: 15.5px; background: #fff; color: var(--ink);
  transition: border-color .2s, box-shadow .2s;
}
.form-card input::placeholder, .form-card textarea::placeholder { color: var(--faint); }
.form-card input:focus, .form-card textarea:focus, .form-card select:focus {
  outline: none; border-color: var(--brand); box-shadow: 0 0 0 3px rgba(169,85,31,.12);
}
.hint-text { font-size: 12.5px; color: var(--muted); margin-top: 6px; line-height: 1.75; }

/* ---------- 付款 / 订单 ---------- */
.flow { display: flex; align-items: center; justify-content: center; gap: 8px; margin-bottom: 22px; flex-wrap: wrap; }
.flow .f-item { display: flex; align-items: center; gap: 8px; font-size: 13px; letter-spacing: .1em; color: var(--muted); }
.flow .f-dot {
  width: 24px; height: 24px; border-radius: 50%; display: grid; place-items: center;
  background: var(--paper-2); border: 1px solid var(--line-strong); font-size: 12px; color: var(--muted);
}
.flow .f-item.on { color: var(--brand-deep); font-weight: 600; }
.flow .f-item.on .f-dot { background: var(--ink); color: #fff; border-color: transparent; }
.flow .f-line { width: 26px; height: 1px; background: var(--line-strong); }
.amount-box {
  text-align: center; padding: 20px; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
  margin: 6px 0 20px;
}
.amount-box .a-lab { font-size: 11.5px; letter-spacing: .28em; color: var(--muted); text-transform: uppercase; }
.amount-box .a-num { font-family: var(--serif); font-size: 40px; font-weight: 700; color: var(--brand); line-height: 1.25; }
.qr-panel { margin-top: 18px; }
.qr-panel .qr-title { font-size: 13px; color: var(--ink-soft); letter-spacing: .14em; margin-bottom: 8px; }
.qr-panel img { width: 200px; margin: 0 auto; border: 1px solid var(--line); }
.order-no-box {
  display: flex; align-items: center; justify-content: center; gap: 12px;
  background: var(--paper-2); border: 1px dashed var(--brand-line);
  padding: 14px; margin-top: 18px; flex-wrap: wrap;
}
.order-no-box code { font-weight: 700; letter-spacing: .14em; font-size: 15px; color: var(--brand-deep); word-break: break-all; }
.link-box {
  margin-top: 16px; padding: 18px; background: var(--brand-wash);
  border: 1px solid var(--brand-line); word-break: break-all; font-size: 15px; line-height: 1.9;
}
.link-box b { color: var(--ink); }
.result-card { margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--line); }
.result-card .r-head { display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap; }
.result-card .r-title { font-size: 16.5px; font-weight: 700; letter-spacing: .08em; }
.result-card .r-meta { font-size: 13.5px; color: var(--muted); margin-top: 6px; line-height: 1.85; }
.empty { text-align: center; color: var(--muted); padding: 56px 20px; font-size: 14.5px; letter-spacing: .1em; }
.empty::before { content: "❋"; display: block; font-size: 30px; color: var(--brand-line); margin-bottom: 10px; }

/* ---------- 灯箱 ---------- */
.lightbox {
  position: fixed; inset: 0; z-index: 200; background: rgba(12,9,6,.97);
  display: none; flex-direction: column; animation: fadeIn .22s ease;
}
.lightbox.open { display: flex; }
.lightbox img { flex: 1; min-height: 0; width: auto; max-width: 100%; object-fit: contain; margin: 0 auto; }
.lightbox .bar {
  display: flex; justify-content: center; align-items: center; gap: 18px;
  padding: 16px 14px calc(16px + env(safe-area-inset-bottom));
  color: rgba(255,255,255,.9); font-size: 14px; letter-spacing: .1em;
}
.lightbox .bar button, .lightbox .close {
  background: rgba(255,255,255,.1); color: #fff; border: 1px solid rgba(255,255,255,.18);
  border-radius: 999px; padding: 10px 20px; min-height: 42px; transition: background .2s;
}
.lightbox .bar button:hover, .lightbox .close:hover { background: rgba(255,255,255,.24); }
.lightbox .close { position: absolute; top: 14px; right: 14px; }
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }

/* ---------- toast ---------- */
.toast {
  position: fixed; left: 50%; bottom: calc(36px + env(safe-area-inset-bottom));
  transform: translateX(-50%) translateY(8px);
  background: rgba(23,19,15,.95); color: #fff; padding: 12px 26px; max-width: 88vw;
  font-size: 14.5px; letter-spacing: .06em; z-index: 300;
  opacity: 0; pointer-events: none; text-align: center;
  transition: opacity .25s, transform .25s;
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

/* ---------- 后台 ---------- */
.admin-wrap { max-width: 1080px; margin: 0 auto; padding: 100px 20px 80px; }
.admin-tabs { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 24px; }
.admin-tabs button {
  border: 1px solid var(--line-strong); background: var(--card); color: var(--ink-soft);
  border-radius: 999px; padding: 9px 20px; font-size: 14.5px; min-height: 40px; transition: all .2s var(--ease);
}
.admin-tabs button:hover { border-color: var(--brand); color: var(--brand-deep); }
.admin-tabs button.active { background: var(--ink); color: #fff; border-color: transparent; }
.panel { display: none; }
.panel.active { display: block; animation: rise .3s var(--ease); }
@keyframes rise { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
.admin-list { display: flex; flex-direction: column; gap: 14px; }
.admin-item {
  background: var(--card); border: 1px solid var(--line);
  padding: 18px; display: flex; flex-direction: column; gap: 12px;
}
.admin-item .head { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 10px; }
.admin-item .head .t { font-weight: 700; font-size: 16px; letter-spacing: .06em; }
.admin-item input, .admin-item select, .admin-item textarea {
  padding: 11px 13px; border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  font: inherit; font-size: 15px; background: #fff; color: var(--ink);
}
.admin-item input:focus, .admin-item select:focus, .admin-item textarea:focus {
  outline: none; border-color: var(--brand); box-shadow: 0 0 0 3px rgba(169,85,31,.12);
}
.tag { font-size: 12px; padding: 4px 12px; border-radius: 999px; letter-spacing: .08em; }
.tag.ok { background: #eaf5ec; color: #1a6b42; }
.tag.no { background: #fdf1e3; color: var(--brand-deep); }
.tag.paid { background: var(--brand-wash); color: var(--brand-deep); }
/* 会员徽标：跟「已付款」区分开，用品牌色实底 + 白字，一眼区别于普通标签 */
.tag.vip { background: var(--brand); color: #17130f; font-weight: 700; }
.mini-grid { display: flex; gap: 8px; overflow-x: auto; padding: 4px 0 6px; scrollbar-width: none; }
.mini-grid::-webkit-scrollbar { display: none; }
.mini-grid img { width: 74px; height: 74px; object-fit: cover; border-radius: var(--radius-sm); flex-shrink: 0; cursor: zoom-in; }
.mini-grid .del {
  position: absolute; top: -6px; right: -6px; width: 22px; height: 22px; border-radius: 50%;
  background: #b91c3a; color: #fff; border: none; font-size: 12px; line-height: 22px;
}
.row2 { display: flex; gap: 10px; flex-wrap: wrap; }
.row2 > * { flex: 1; min-width: 140px; }
/* 后台系列卡上的「自动拼合封面」预览（2026-10-08 取消上传封面后新增） */
.hero-tiles { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.hero-tiles .ht-thumbs { display: grid; grid-template-columns: repeat(5, 1fr); gap: 3px; width: 235px; flex-shrink: 0; }
.hero-tiles .ht-thumbs img { width: 100%; aspect-ratio: 1; object-fit: cover; border-radius: 4px; display: block; }
.hero-tiles .ht-note { font-size: 12px; color: var(--muted); line-height: 1.7; }

/* ---------- 骨架屏 / 渐显 ---------- */
.skel { background: var(--card); border: 1px solid var(--line); overflow: hidden; }
.skel .s-thumb, .skel .s-line {
  background: linear-gradient(90deg, #f0ebe1 25%, #f8f5ef 37%, #f0ebe1 63%);
  background-size: 400% 100%; animation: shimmer 1.3s ease infinite;
}
.skel .s-thumb { aspect-ratio: 3/4; }
.skel .s-body { padding: 12px 14px 14px; display: flex; flex-direction: column; gap: 9px; }
.skel .s-line { height: 12px; border-radius: 6px; }
.skel .s-line.w60 { width: 60%; }
.skel .s-line.w40 { width: 40%; height: 16px; }
@keyframes shimmer { 0% { background-position: 100% 0; } 100% { background-position: 0 0; } }

.fade-img { opacity: 0; transition: opacity .6s var(--ease); }
.fade-img.loaded { opacity: 1; }

/* v31：图还没下下来时，卡片先给一层暖灰纸色 + 一道极淡的光扫过。
   翻页时看到的不是空洞洞的白框，而是"这页正在来"的提示。 */
.c-thumb, .r-thumb, .album-card .thumb, .pick-card .pc-thumb { background: var(--paper-3); }
.c-thumb img:not(.loaded), .r-thumb img:not(.loaded) { opacity: 0; }
.c-thumb, .r-thumb { position: relative; overflow: hidden; }
.c-thumb::before, .r-thumb::before {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(105deg, transparent 32%, rgba(255,255,255,.55) 50%, transparent 68%);
  background-size: 260% 100%;
  animation: shimmer 1.7s var(--ease) infinite;
}
/* 图一落地就撤掉光扫。用 JS 打标记（比 :has() 兼容老手机浏览器），
   同时保留 :has() 作为双保险 —— 任意一条生效光扫都会停。 */
.c-thumb.done::before, .r-thumb.done::before,
.c-thumb.no-img::before, .r-thumb.no-img::before { display: none; }
@keyframes shimmer {
  from { background-position: 150% 0; }
  to   { background-position: -60% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .c-thumb::before, .r-thumb::before { animation: none; }
}
.reveal { opacity: 0; transform: translateY(20px); }
.reveal.in { opacity: 1; transform: none; transition: opacity .7s var(--ease), transform .7s var(--ease); }

/* ---------- 系列详情页 ---------- */
.scene-hero {
  position: relative; overflow: hidden; isolation: isolate;
  min-height: min(62vh, 520px); display: flex; align-items: flex-end;
  background: linear-gradient(160deg, #2a211a, #17130f);
}
.scene-hero > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: -1; }
/* 自动拼贴封面（2026-10-08）：左一张大图 + 右侧四张小的，
   把「这个系列有很多套」在第一屏就说清楚。取消上传封面后由服务端下发 coverTiles。 */
.scene-hero .hero-mosaic {
  position: absolute; inset: 0; z-index: -1; overflow: hidden;
  display: grid; gap: 3px;
  /* 🔴 行高必须写 minmax(0, 1fr)，不能写 1fr（2026-10-08 本地实测踩到）：
     裸的 1fr 等于 minmax(auto, 1fr)，那个 auto 最小值取的是**图片按固有比例
     撑出来的高度** —— 图 320×400、列宽 262 时最小行高就是 327，
     两行 657，而 hero 只有 446，于是拼图整体溢出、被 overflow 裁掉半张脸。
     minmax(0, …) 把这个自动最小尺寸摁掉，行高才真正听容器的。
     同理给图片加 min-width/min-height: 0。 */
  grid-template-columns: minmax(0, 2fr) minmax(0, 1fr) minmax(0, 1fr);
  grid-template-rows: minmax(0, 1fr) minmax(0, 1fr);
}
.scene-hero .hero-mosaic img {
  width: 100%; height: 100%; min-width: 0; min-height: 0;
  object-fit: cover; display: block;
}
.scene-hero .hero-mosaic img:first-child { grid-row: span 2; }
@media (max-width: 640px) {
  .scene-hero .hero-mosaic {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-rows: minmax(0, 1fr) minmax(0, 1fr);
  }
  .scene-hero .hero-mosaic img:first-child { grid-row: auto; }
  .scene-hero .hero-mosaic img:nth-child(n+5) { display: none; }
}
.scene-hero .shade {
  position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(rgba(23,19,15,.2) 20%, rgba(23,19,15,.92));
}
.scene-hero .inner { padding: 120px 24px 34px; color: #fff; width: 100%; max-width: 1280px; margin: 0 auto; }
.scene-hero .kicker {
  display: inline-block; padding: 5px 14px; border: 1px solid rgba(255,255,255,.35);
  font-size: 10px; letter-spacing: .34em; text-transform: uppercase; color: var(--gold-soft);
}
.scene-hero h1 {
  font-family: var(--serif); font-size: clamp(30px, 6vw, 62px);
  letter-spacing: .12em; margin-top: 14px; line-height: 1.2;
}
.scene-hero .meta { margin-top: 10px; font-size: 13px; letter-spacing: .16em; color: rgba(255,255,255,.72); }

.bundle-card { max-width: 1280px; margin: 0 auto; padding: 0 24px; position: relative; z-index: 2; }
.bundle-card .inner {
  background: var(--card); border: 1px solid var(--line);
  padding: 26px 26px 24px; display: flex; gap: 20px; align-items: center; flex-wrap: wrap;
  transform: translateY(-28px);
}
.bundle-card .b-info { flex: 1 1 300px; }
.bundle-card .b-title { font-family: var(--serif); font-weight: 700; font-size: 21px; letter-spacing: .14em; }
.bundle-card .b-desc { margin-top: 8px; font-size: 13.5px; color: var(--ink-soft); line-height: 1.85; letter-spacing: .04em; }
.bundle-card .b-price { text-align: right; }
.bundle-card .b-price .now { font-family: var(--serif); font-size: 38px; font-weight: 700; color: var(--brand); line-height: 1.1; }
.bundle-card .b-price .now small { font-size: .5em; }
.bundle-card .b-price .was { display: block; font-size: 12.5px; color: var(--faint); text-decoration: line-through; }
.bundle-card .b-price .save {
  display: inline-block; margin-bottom: 5px; padding: 4px 12px;
  background: var(--brand); color: #fff; font-size: 13px; font-weight: 700; letter-spacing: .14em;
  box-shadow: 0 6px 16px rgba(169,85,31,.26);
}
.bundle-card .b-price .per {
  display: block; margin-top: 7px; font-size: 12px; color: var(--muted); letter-spacing: .08em;
}
@media (max-width: 680px) { .bundle-card .b-price { text-align: left; } }

.bundle-hint {
  max-width: 1280px; margin: 18px auto 0; padding: 16px 20px;
  background: var(--brand-wash); border-left: 3px solid var(--brand);
  font-size: 13.5px; color: var(--ink-soft); line-height: 1.85; letter-spacing: .04em;
}

/* ---------- 动效降级 ---------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
  .reveal { opacity: 1; transform: none; }
  html { scroll-behavior: auto; }
}

/* ---------- 移动端 ---------- */
@media (max-width: 480px) {
  body { font-size: 15.5px; }
  .cover-inner { padding-top: 120px; }
  .grid { grid-template-columns: repeat(2, 1fr); gap: 12px; }
  .form-card { padding: 24px 20px; border: none; border-top: 1px solid var(--line); }
  .buy-bar { padding: 18px 0; }
  .buy-bar .btn { margin-left: 0; width: 100%; }
  .nav-links { gap: 16px; font-size: 12px; }
}

/* ---------- 后台：未加固提醒条 + 加固进度 ---------- */
.alert-bar {
  display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap;
  margin: 0 0 18px; padding: 13px 16px;
  background: #fdf4e8; border: 1px solid #e9d2ad; border-left: 3px solid var(--brand);
  color: #7a4a1d; font-size: 13.5px; letter-spacing: .02em; line-height: 1.7;
}
.alert-bar .btn { flex: 0 0 auto; }
.meter {
  margin-top: 14px; height: 6px; overflow: hidden;
  background: var(--paper-2); border: 1px solid var(--line);
}
.meter i { display: block; height: 100%; width: 0; background: var(--brand); transition: width .3s var(--ease); }

/* ---------- 前台：原图与预览分离后的浏览保护 ----------
   下发的本来就只是带水印的预览图，这里再收一层：
   不可选中、不可拖拽、移动端长按不弹"存储图像"。 */
img, .preview-grid .cell, .album-card .thumb {
  -webkit-user-select: none; -moz-user-select: none; user-select: none;
  -webkit-user-drag: none; -webkit-touch-callout: none;
}
.album-card, .preview-grid .cell, .scene-card { -webkit-tap-highlight-color: transparent; }

/* ============================================================
   首页改版 v11 —— 一场景一卷
   砍掉卷首语 / 封面故事 / 点线目录 / 筛选画廊四块重复展示，
   改为：封面 → 场景卷（卷头 + 横向卷轴）→ 封底
   ============================================================ */

/* 封面：规模压成一行小字，不再占三个统计块 */
.cover-scale {
  margin-top: 26px;
  font-size: 11.5px;
  letter-spacing: .26em;
  color: rgba(255, 255, 255, .62);
}

/* ---------- 场景卷 ---------- */
.vols { padding-top: clamp(26px, 5vh, 52px); }
.vol { padding: clamp(30px, 5.5vh, 58px) 0; border-top: 1px solid var(--line); }
.vol:first-child { border-top: 0; }
.vol-inner { max-width: 1280px; margin: 0 auto; }

.vol-head {
  display: flex; align-items: flex-end; gap: 16px;
  padding: 0 24px clamp(16px, 2.6vh, 28px);
}
.vol-no {
  flex: 0 0 auto; padding-bottom: 8px;
  font-family: var(--num); font-size: 12px; letter-spacing: .22em; color: var(--faint);
}
.vol-title { flex: 1 1 auto; min-width: 0; }
.vol-title h2 {
  font-family: var(--serif); font-weight: 700;
  font-size: clamp(23px, 3.2vw, 36px); line-height: 1.24; letter-spacing: .01em;
}
.vol-meta {
  display: block; margin-top: 4px;
  font-size: 12.5px; letter-spacing: .1em; color: var(--muted);
}
.vol-go {
  flex: 0 0 auto; padding-bottom: 7px; white-space: nowrap;
  font-size: 13px; letter-spacing: .16em; color: var(--brand);
}
.vol-go i {
  display: inline-block; margin-left: 6px; font-style: normal;
  transition: transform .3s var(--ease);
}
.vol-go:hover i { transform: translateX(5px); }

/* ---------- 横向卷轴 ---------- */
.reel-wrap { position: relative; }
.reel {
  display: flex; gap: 14px;
  overflow-x: auto; overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
  padding: 4px 24px 14px;
  scrollbar-width: thin; scrollbar-color: var(--line-strong) transparent;
}
.reel::-webkit-scrollbar { height: 6px; }
.reel::-webkit-scrollbar-thumb { background: var(--line-strong); border-radius: 3px; }
.reel::-webkit-scrollbar-track { background: transparent; }

.reel-card, .reel-more { flex: 0 0 auto; width: 216px; scroll-snap-align: start; }
.reel-card { position: relative; display: block; }
.r-thumb {
  display: block; position: relative; overflow: hidden;
  aspect-ratio: 4 / 5; background: var(--paper-2);
}
.r-thumb img {
  width: 100%; height: 100%; object-fit: cover;
  transition: transform .6s var(--ease);
}
.reel-card:hover .r-thumb img { transform: scale(1.045); }
.r-title {
  display: block; margin-top: 10px;
  font-family: var(--serif); font-size: 14.5px; line-height: 1.5;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.r-frame {
  display: block; margin-top: 2px;
  font-size: 11.5px; letter-spacing: .12em; color: var(--faint);
}

/* 卷尾：进场景看全部 */
.reel-more {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  aspect-ratio: 4 / 5;
  border: 1px solid var(--line-strong); color: var(--muted);
  font-family: var(--serif); font-size: 14px; letter-spacing: .1em; line-height: 1.9;
  transition: border-color .3s var(--ease), color .3s var(--ease), background .3s var(--ease);
}
.reel-more:hover { border-color: var(--brand); color: var(--brand); background: var(--brand-wash); }

/* 翻页箭头：只在悬停且还有得滚时出现，滚到头自动收起 */
.reel-nav {
  position: absolute; top: 50%; z-index: 2;
  width: 38px; height: 38px; margin-top: -19px;
  display: none; align-items: center; justify-content: center;
  border: 1px solid var(--line); border-radius: 50%;
  background: rgba(255, 255, 255, .95); color: var(--ink);
  font-size: 20px; line-height: 1; box-shadow: var(--shadow-sm);
  transition: color .3s var(--ease), border-color .3s var(--ease);
}
.reel-wrap:hover .reel-nav { display: flex; }
.reel-nav.prev { left: 4px; }
.reel-nav.next { right: 4px; }
.reel-nav:hover { border-color: var(--brand); color: var(--brand); }
@media (hover: none) { .reel-nav { display: none !important; } }

@media (max-width: 640px) {
  .reel-card, .reel-more { width: 146px; }
  .reel { gap: 10px; padding: 4px 16px 12px; }
  .vol-head { padding: 0 16px 14px; gap: 12px; }
  .vol-go { font-size: 12px; padding-bottom: 5px; }
  .vol-meta { font-size: 11.5px; }
}

/* ============================================================
   后台 v11 —— 套系库按场景分组（面向「几十场景 × 每场景几十套」）
   ============================================================ */

/* 工具条：筛选 / 搜索 / 展开收起 */
.album-tools {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin: 18px 0 14px; padding-bottom: 14px; border-bottom: 1px solid var(--line);
}
.album-tools select { flex: 0 0 auto; width: auto; min-width: 130px; }
.album-tools input { flex: 1 1 140px; min-width: 140px; }
.album-tools .btn { flex: 0 0 auto; min-width: auto; }
.at-count { flex: 0 0 auto; font-size: 12.5px; letter-spacing: .08em; color: var(--muted); }

/* 场景分组 */
.scene-group { border: 1px solid var(--line); border-radius: var(--radius); background: #fff; }
.scene-group + .scene-group { margin-top: 10px; }
.sg-head {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 13px 16px; cursor: pointer; user-select: none;
  background: none; border: 0; font: inherit; color: inherit; text-align: left;
}
.sg-head:hover .sg-name { color: var(--brand); }
.sg-caret { font-size: 11px; color: var(--faint); transition: transform .25s var(--ease); }
.scene-group.open .sg-caret { transform: rotate(0deg); }
.sg-name { font-family: var(--serif); font-weight: 700; font-size: 16px; letter-spacing: .06em; transition: color .25s var(--ease); }
.sg-count { margin-left: auto; font-size: 12px; letter-spacing: .1em; color: var(--muted); }
.sg-body { padding: 0 14px 14px; display: flex; flex-direction: column; gap: 10px; }

/* 套系卡片：一行说清状态，图片与编辑按需展开 */
.a-card { padding: 12px 14px; }
.a-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.a-thumb {
  flex: 0 0 auto; width: 52px; height: 65px; overflow: hidden;
  background: var(--paper-2); border-radius: var(--radius-sm);
}
.a-thumb img { width: 100%; height: 100%; object-fit: cover; }
.a-main { flex: 1 1 200px; min-width: 0; }
.a-name { display: block; font-size: 15px; font-weight: 700; letter-spacing: .04em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.a-tags { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 5px; }
.a-tags .tag { padding: 3px 10px; font-size: 11.5px; }
.a-tags .tag:not(.ok):not(.no) { background: var(--paper-2); color: var(--muted); }
.a-ops { flex: 0 0 auto; display: flex; gap: 8px; flex-wrap: wrap; }
.a-ops .btn { padding: 7px 14px; min-height: 34px; font-size: 12.5px; letter-spacing: .06em; }
.a-card .row2, .a-card input[type="text"], .a-card input:not([type]) { margin-top: 10px; }

@media (max-width: 700px) {
  .a-ops { width: 100%; }
  .a-thumb { width: 44px; height: 55px; }
  .album-tools select { min-width: 110px; }
}

/* hidden 属性必须真的隐藏：本表里多处用 display:flex 的组件会给它盖掉 */
[hidden] { display: none !important; }

/* ---------- 批量上料 ---------- */
.intake-bar { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
.intake-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); gap: 12px; margin-top: 12px; }
.intake-card {
  position: relative; display: flex; flex-direction: column; gap: 5px;
  border: 1px solid var(--line); border-radius: var(--radius); padding: 8px;
  background: var(--card); cursor: pointer;
  transition: border-color .18s var(--ease), box-shadow .18s var(--ease);
}
.intake-card:hover { border-color: var(--line-strong); }
.intake-card.on { border-color: var(--brand); box-shadow: 0 0 0 1px var(--brand); }
.intake-card img { width: 100%; aspect-ratio: 3 / 4; object-fit: cover; border-radius: var(--radius-sm); background: var(--paper-2); }
.intake-card .pick { position: absolute; top: 14px; left: 14px; width: 17px; height: 17px; }
.intake-card .ic-name { font-size: 13.5px; font-weight: 700; letter-spacing: .04em; }
.intake-card .ic-meta { font-size: 11.5px; color: var(--muted); line-height: 1.5; word-break: break-all; }
.intake-card .tag { align-self: flex-start; font-size: 11px; padding: 3px 9px; }

/* ============================================================
   转化增强 v12 —— 把「浏览」推向「下单」
   三处着力：首屏给理由、网格留悬念、按钮随手可及
   ============================================================ */

/* ---------- 封面：第一屏就把"怎么买"讲明白 ---------- */
.cover-note {
  margin-top: 20px; padding-left: 14px; border-left: 2px solid var(--gold);
  font-size: 12.5px; letter-spacing: .18em; color: rgba(255,255,255,.68);
}
.cover-note:empty { display: none; }
@media (max-width: 560px) { .cover-note { letter-spacing: .1em; font-size: 12px; } }

/* ---------- 首页套系卡：补上价格与"看这一套" ---------- */
.reel-card .r-foot {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 10px; margin-top: 2px;
}
.reel-card .r-foot .r-frame { margin-top: 0; }
.reel-card .r-price {
  font-family: var(--serif); font-size: 15.5px; font-weight: 700;
  color: var(--brand); white-space: nowrap; letter-spacing: .02em;
}
.reel-card .r-buy {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 24px 12px 11px; text-align: center;
  background: linear-gradient(to top, rgba(23,19,15,.88), rgba(23,19,15,0));
  color: #fff; font-size: 12.5px; letter-spacing: .18em;
  opacity: 0; transform: translateY(10px);
  transition: opacity .3s var(--ease), transform .3s var(--ease);
  pointer-events: none;
}
.reel-card .r-buy i { font-style: normal; margin-left: 4px; }
.reel-card:hover .r-buy { opacity: 1; transform: translateY(0); }
@media (hover: none) { .reel-card .r-buy { display: none; } }

/* ---------- 详情页：价格条里的"值不值" ---------- */
.buy-bar .hint b { color: var(--ink); font-weight: 700; }

/* ---------- 详情页：预览门槛线（前段敞开 / 门后渐隐） ---------- */
.preview-grid .pv-gate {
  grid-column: 1 / -1;
  display: flex; align-items: center; gap: 14px;
  padding: 18px 0 12px;
}
.pv-gate .pg-line { flex: 1; height: 1px; background: var(--line-strong); }
.pv-gate .pg-txt {
  font-size: 12px; letter-spacing: .24em; color: var(--brand); white-space: nowrap;
}
.pv-gate .pg-txt b { font-family: var(--num); font-size: 18px; font-weight: 700; letter-spacing: .02em; }
.preview-grid .cell.behind img { opacity: .5; filter: saturate(.7); }
.preview-grid .cell.behind.far img { opacity: .28; }
.preview-grid .cell.behind:hover img { opacity: 1; filter: none; }

/* ---------- 详情页：门后解锁卡 ---------- */
.unlock {
  display: flex; flex-wrap: wrap; align-items: center; gap: 22px;
  margin-top: 26px; padding: 26px 28px;
  background: linear-gradient(135deg, #fff 0%, var(--brand-wash) 100%);
  border: 1px solid var(--brand-line); border-radius: var(--radius);
  box-shadow: var(--shadow-md);
}
.unlock .u-l { flex: 1 1 280px; }
.unlock .u-k { font-size: 10px; letter-spacing: .36em; color: var(--gold); }
.unlock .u-n {
  margin-top: 6px; display: flex; align-items: baseline; gap: 6px;
  font-family: var(--serif); font-size: 21px; font-weight: 700;
  line-height: 1.15; letter-spacing: .08em; color: var(--ink-soft);
}
.unlock .u-n b { font-family: var(--num); font-size: 52px; color: var(--brand); line-height: 1; }
.unlock .u-n span { font-size: 15px; letter-spacing: .12em; }
.unlock .u-s { margin-top: 10px; font-size: 13px; color: var(--muted); letter-spacing: .04em; line-height: 1.7; }
.unlock .u-r { margin-left: auto; display: flex; flex-direction: column; align-items: flex-end; gap: 5px; }
.unlock .u-price { font-family: var(--serif); font-size: 32px; font-weight: 700; color: var(--brand); line-height: 1; }
.unlock .u-price span { font-size: .55em; }
.unlock .u-per { font-size: 12px; color: var(--muted); letter-spacing: .06em; }
.unlock .u-r .btn { margin-top: 10px; min-width: 156px; }
@media (max-width: 620px) {
  .unlock { padding: 22px 20px; gap: 16px; }
  .unlock .u-r { margin-left: 0; align-items: flex-start; width: 100%; }
  .unlock .u-r .btn { width: 100%; }
}

/* ---------- 详情页：已敞开（会员 / 积分换过）（2026-10-07） ---------- */
/* 这一条不是广告，是「你已经进来了」的确认 ——
   所以做得安静：淡草绿底 + 一行小字。它不该跟他抢注意力，
   真正要他做的事（想要原片）在赞赏条里，这里只是告诉他「门已经开了」。 */
.unlocked-band {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
  margin-top: 26px; padding: 16px 20px;
  background: linear-gradient(135deg, rgba(111,125,99,.11), rgba(111,125,99,.035));
  border: 1px solid rgba(111,125,99,.28); border-radius: var(--radius);
  font-size: 13.5px; color: var(--ink-soft); line-height: 1.85;
}
.unlocked-band .ub-k {
  font-size: 10px; letter-spacing: .32em; font-weight: 700; color: var(--sage);
  padding: 3px 9px; border-radius: 99px; background: rgba(111,125,99,.13);
}
.unlocked-band b { font-family: var(--serif); font-size: 15px; letter-spacing: .06em; color: var(--ink); }
.unlocked-band > span:last-child { flex: 1 1 260px; min-width: 0; }
.unlocked-band > span:last-child b { font-size: inherit; letter-spacing: inherit; }

/* ---------- 详情页：积分兑换入口（2026-10-07） ---------- */
/* 摆在赞赏条下面，**故意做得比它轻**：虚框、无渐变、按钮是描边的。
   积分是「另一条路」，不是主推 —— 视觉上要是抢过赞赏条，等于自己拆自己的台。
   （收入那条线靠的是原片网盘链接，积分只换站内翻阅权，本来就不该更响。） */
.pts-get {
  display: flex; flex-wrap: wrap; align-items: center; gap: 16px;
  margin-top: 14px; padding: 16px 20px;
  border: 1px dashed var(--line-strong); border-radius: var(--radius);
  background: var(--paper-3);
}
.pts-get .pg-l { flex: 1 1 240px; min-width: 0; }
.pts-get .pg-t {
  font-family: var(--serif); font-size: 15px; letter-spacing: .05em;
  color: var(--ink-soft); margin-bottom: 3px;
}
.pts-get .pg-s { font-size: 12.5px; color: var(--muted); line-height: 1.8; }
/* 两个按钮并排（2026-10-07 第二轮加体验档后）。
   主按钮（永久）与次按钮（7 天体验）之间留 8px，窄屏都撑满一行、
   但顺序保持「永久在前」—— 让他先看到那个更大的选择。 */
.pts-get .pg-r { display: flex; flex-wrap: wrap; gap: 8px; flex: 0 0 auto; }
.pts-get .btn { flex: 0 0 auto; }
.pts-get .btn.ok { border-color: var(--brand); color: var(--brand); font-weight: 700; }
.pts-get .btn:disabled { opacity: .55; cursor: not-allowed; }
@media (max-width: 620px) {
  .pts-get { padding: 14px 16px; gap: 12px; }
  .pts-get .pg-r { flex: 1 1 100%; }
  .pts-get .btn { width: 100%; }
}

/* ---------- 详情页：限时敞开的说明条（2026-10-07） ---------- */
/* 体验档（200 分 / 7 天）在手时才出现。语气要比「永久敞开」的 .unlocked-band
   更**轻**、更带一点「它快到期了」的意味 —— 但不能像警报（那是催债的味道）。
   所以用虚线框 + 琥珀色字，不上红色。 */
.pts-temp {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
  margin-top: 14px; padding: 13px 18px;
  border: 1px dashed rgba(186,117,23,.42); border-radius: var(--radius);
  background: rgba(250,238,218,.5);
  font-size: 13px; color: var(--ink-soft); line-height: 1.8;
}
.pts-temp .pt-k {
  font-size: 10px; letter-spacing: .3em; font-weight: 700; color: #854f0b;
  padding: 3px 9px; border-radius: 99px; background: rgba(186,117,23,.14);
}
.pts-temp b { font-family: var(--serif); font-size: 15px; color: #854f0b; letter-spacing: .04em; }

/* 连续签到日历（2026-10-07 第四轮「继续优化」）：把「已连续 N 天」画成小格子。
   已签亮、今天描金、未签灰 —— 断在哪一眼可见。 */
.pts-cal { display: flex; flex-wrap: wrap; gap: 4px; margin: 10px 0 2px; }
.pts-cal .cal-d { font-size: 11px; line-height: 1; padding: 4px 5px; border-radius: 6px; background: #efe9df; color: #9b8f7d; font-variant-numeric: tabular-nums; }
.pts-cal .cal-d.on { background: #f1e6d2; color: #9a6a2f; font-weight: 700; }
.pts-cal .cal-d.today { box-shadow: 0 0 0 2px #c9a24a; }
.pts-cal .cal-d.off { opacity: .5; }
.pts-makeup { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin: 6px 0 2px; }
.pts-makeup .mk-t { font-size: 12px; color: var(--muted); }
.pts-makeup .mk-btn { font-size: 12px; padding: 4px 8px; }
/* 会员连续天数小标（2026-10-07 第四轮） */
.vip-days { font-style: normal; font-size: 12px; color: var(--gold); margin-left: 6px; }

/* 积分任务中心（2026-10-07 第四轮「继续优化」）：签到/邀请/兑换三件事带进度 */
.pts-tasks { margin: 10px 0; display: flex; flex-direction: column; gap: 6px; }
.pts-task { display: flex; align-items: center; gap: 10px; padding: 8px 10px; background: #f6efe6; border-radius: 9px; }
.pts-task .pt-ico { font-size: 15px; color: #b4632c; width: 18px; text-align: center; }
.pts-task .pt-body { display: flex; flex-direction: column; min-width: 0; }
.pts-task b { font-size: 13px; color: #3a2c20; }
.pts-task .pt-sub { font-size: 12px; color: #9b8f7d; }

/* ---------- 2026-10-08 新增：等级 / 徽章 / 皮肤 / 浏览 / 抽奖 / 回顾 ---------- */
.pts-level { margin: 10px 0; padding: 10px 12px; background: #f6efe6; border-radius: 9px; }
.pl-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.pl-badge { font-size: 11px; font-weight: 700; padding: 3px 8px; border-radius: 999px; background: var(--brand); color: #fff; letter-spacing: .04em; }
.pl-head b { font-size: 13px; color: #3a2c20; }
.pl-perk { font-size: 12px; color: #9b8f7d; }
.pl-bar { height: 6px; background: #e7ddcd; border-radius: 999px; margin: 8px 0 6px; overflow: hidden; }
.pl-bar i { display: block; height: 100%; width: 0; background: var(--gold); border-radius: 999px; transition: width .4s ease; }
.pl-sub { font-size: 12px; color: #9b8f7d; line-height: 1.6; }

.pts-badges, .pts-skins { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: 8px 0; }
.bdg-t { font-size: 12px; color: #9b8f7d; }
.bdg { font-size: 12px; padding: 3px 10px; border-radius: 999px; background: #f1e6d2; color: #9a6a2f; }
.skin { font-size: 12px; padding: 3px 10px; border-radius: 999px; border: 1px solid var(--line); background: #fff; color: #6b5c4a; cursor: pointer; }
.skin.on { background: var(--brand); border-color: var(--brand); color: #fff; }
.skin.lock { opacity: .45; cursor: default; }

.pts-browse { margin: 10px 0; padding: 10px 12px; background: #f6efe6; border-radius: 9px; display: flex; flex-direction: column; gap: 4px; }
.pts-browse b { font-size: 13px; color: #3a2c20; }
.br-sub { font-size: 12px; color: #9b8f7d; line-height: 1.7; }
/* 🔴🔴 相邻数字必须留 ≥6px 间隔并给胶囊底 ——
   「还能攒 5 套，每套 2 分」挤在一起会被读成「52 分」（血泪教训）。 */
.pts-browse i, .lt-sub i {
  font-style: normal; font-weight: 700; color: #9a6a2f;
  background: #f1e6d2; border-radius: 5px; padding: 1px 5px; margin: 0 4px;
  font-variant-numeric: tabular-nums;
}

.pts-lotto { display: flex; align-items: center; gap: 10px; margin: 10px 0 0; padding: 9px 12px; background: #f6efe6; border-radius: 9px; }
.lt-l { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.lt-l b { font-size: 13px; color: #3a2c20; }
.lt-sub { font-size: 12px; color: #9b8f7d; }
.pts-lotto-res { margin: 6px 0 0; font-size: 12.5px; color: #9a6a2f; }

.pts-review { margin: 12px 0 0; padding: 10px 12px; background: #f6efe6; border-radius: 9px; }
.rv-t { font-size: 12px; color: #9b8f7d; }
.rv-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(72px, 1fr)); gap: 8px; margin-top: 8px; }
.rv-cell { display: flex; flex-direction: column; align-items: center; gap: 3px; padding: 6px 4px; background: #fff; border-radius: 8px; }
.rv-cell b { font-size: 16px; color: #3a2c20; font-variant-numeric: tabular-nums; }
.rv-cell i { font-style: normal; font-size: 11px; color: #9b8f7d; }

/* ---------- 首页积分条（P0-1 · 2026-10-08）----------
   行业原话：积分的价值只有在**被看见**的时候才存在。
   压在封面上，半透明胶囊，不抢封面那张图。 */
.pts-strip {
  margin-top: 14px; display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 13px; border-radius: 999px;
  background: rgba(28, 22, 17, .42); border: 1px solid rgba(255, 255, 255, .2);
  font-size: 12.5px; color: #f3ece2; letter-spacing: .02em;
}
.pts-strip b { font-weight: 700; color: var(--gold); font-variant-numeric: tabular-nums; margin: 0 3px; }
.pts-strip .sp-a { color: #f3ece2; text-decoration: none; border-bottom: 1px solid rgba(243, 236, 226, .45); }
.pts-strip .sp-dot { opacity: .45; }
@media (max-width: 640px) { .pts-strip { font-size: 12px; padding: 6px 11px; } }

/* ---------- 详情页：积分价小标（P0-2 · 2026-10-08）---------- */
.pts-chip {
  display: inline-flex; align-items: center; gap: 5px; margin-left: 8px;
  padding: 3px 9px; border-radius: 999px; background: #f6efe6;
  font-size: 12px; color: #9a6a2f; white-space: nowrap;
}
.pts-chip b { font-variant-numeric: tabular-nums; margin: 0 4px; }

/* ---------- 详情页：幕后花絮（P2-10 · 2026-10-08）---------- */
.pts-behind {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin: 18px 0 0; padding: 12px 16px;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius-sm);
}
.pts-behind .pb-l { display: flex; flex-direction: column; gap: 3px; flex: 1; min-width: 0; }
.pts-behind .pb-l b { font-size: 13.5px; color: var(--ink); letter-spacing: .04em; }
.pts-behind .pb-sub { font-size: 12.5px; color: var(--muted); }
.pts-behind-body { margin-top: 10px; padding: 14px 16px; background: #faf6ef; border-radius: var(--radius-sm); }
.pts-behind-body .pb-txt { font-size: 13.5px; line-height: 1.9; color: #4a3c2c; white-space: pre-wrap; }
.pts-behind-body .pb-img { display: block; width: 100%; margin-top: 10px; border-radius: 8px; }

/* ---------- 详情页：三个安心点 ---------- */
.assure {
  list-style: none; display: grid; gap: 12px; margin-top: 26px;
  grid-template-columns: repeat(3, 1fr);
}
.assure li {
  padding: 15px 18px; background: var(--card);
  border: 1px solid var(--line); border-radius: var(--radius-sm);
}
.assure li b { display: block; font-size: 14px; letter-spacing: .06em; color: var(--ink); }
.assure li b::before { content: "✓ "; color: var(--brand); font-weight: 700; }
.assure li span { display: block; margin-top: 5px; font-size: 12.5px; color: var(--muted); letter-spacing: .03em; line-height: 1.6; }
@media (max-width: 640px) { .assure { grid-template-columns: 1fr; } }

/* ---------- 详情页：套系留言（2026-10-06）----------
   注册用户能在每套下面留言并显示。放在「三件安心」之后、赞赏提示之前 ——
   看过图、觉得不错、想说两句，再决定要不要赞赏，这个顺序才顺。 */
.notes { margin-top: 34px; padding-top: 26px; border-top: 1px solid var(--line); }
.notes-h {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  margin-bottom: 4px;
}
.notes-h h2 { font-family: var(--serif); font-size: 20px; font-weight: 400; letter-spacing: .12em; }
.notes-h .n-count { font-size: 12px; color: var(--faint); letter-spacing: .1em; }
.notes-h .n-tip { margin-left: auto; font-size: 12px; color: var(--faint); letter-spacing: .04em; }
.notes-lede { font-size: 13px; color: var(--muted); line-height: 1.8; margin: 0 0 16px; }

/* 留留言的框 */
.note-form { display: flex; gap: 10px; align-items: flex-start; }
.note-form textarea {
  flex: 1; min-height: 62px; max-height: 160px; resize: vertical;
  padding: 11px 14px; font-family: var(--sans); font-size: 14px; line-height: 1.7;
  color: var(--ink); background: var(--card);
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  outline: none; transition: border-color .25s var(--ease);
}
.note-form textarea::placeholder { color: var(--faint); }
.note-form textarea:focus { border-color: var(--brand); }
.note-form .btn { flex: none; min-height: 62px; padding: 0 24px; }
.note-form .btn[disabled] { opacity: .55; cursor: not-allowed; }

/* 未登录：不给输入框（门槛在服务端，前端也不假装能发），换一句引导 */
.note-gate {
  padding: 18px 20px; border-radius: var(--radius-sm);
  background: var(--card); border: 1px dashed var(--line-strong);
  font-size: 13.5px; color: var(--muted); line-height: 1.9;
}
.note-gate a { color: var(--brand); font-weight: 700; text-decoration: none; }
.note-gate a:hover { text-decoration: underline; }

/* 留言列表 */
.note-list { list-style: none; margin: 20px 0 0; padding: 0; }
.note-list li {
  padding: 14px 0; border-top: 1px solid var(--line);
  display: flex; gap: 12px; align-items: flex-start;
}
.note-list li:first-child { border-top: 0; }
.note-av {
  flex: none; width: 34px; height: 34px; border-radius: 50%;
  display: grid; place-items: center;
  background: rgba(200,153,74,.16); border: 1px solid rgba(200,153,74,.4);
  color: var(--brand); font-family: var(--serif); font-size: 14px;
}
.note-b { flex: 1; min-width: 0; }
.note-m { display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap; margin-bottom: 4px; }
.note-m b { font-size: 13.5px; font-weight: 700; color: var(--ink); letter-spacing: .04em; }
.note-m time { font-size: 11.5px; color: var(--faint); letter-spacing: .06em; }
.note-list li.mine .note-av { background: var(--brand); color: #fff; border-color: var(--brand); }
.note-m .n-mine {
  font-size: 10.5px; letter-spacing: .12em; color: var(--brand);
  border: 1px solid var(--brand); border-radius: 999px; padding: 1px 7px;
}
.note-x {
  flex: none; align-self: flex-start; background: none; border: 0; cursor: pointer;
  color: var(--faint); font-size: 12px; font-family: var(--sans); padding: 2px 4px;
}
.note-x:hover { color: #c96a5a; }
.note-b p {
  margin: 0; font-size: 14px; line-height: 1.8; color: var(--ink);
  /* 留言是访客写的，长度不定，但不能让一条长留言把整页撑变形 */
  word-break: break-word; overflow-wrap: anywhere; white-space: pre-wrap;
}
.notes-empty { padding: 22px 0 4px; font-size: 13.5px; color: var(--faint); line-height: 1.9; }

@media (max-width: 640px) {
  .note-form { flex-direction: column; }
  .note-form .btn { width: 100%; min-height: 46px; }
  .notes-h .n-tip { margin-left: 0; width: 100%; }
}

/* ---------- 详情页：手机吸底购买条 ---------- */
.buy-dock {
  display: none; position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
  align-items: center; gap: 14px;
  padding: 10px 16px calc(10px + env(safe-area-inset-bottom, 0px));
  background: rgba(250,247,241,.95);
  -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px);
  border-top: 1px solid var(--line-strong);
  box-shadow: 0 -8px 26px rgba(40,28,16,.1);
  transform: translateY(110%); transition: transform .32s var(--ease);
}
.buy-dock.show { transform: translateY(0); }
.buy-dock .bd-l { display: flex; flex-direction: column; line-height: 1.25; }
.buy-dock .bd-l b { font-family: var(--num); font-size: 22px; font-weight: 700; color: var(--brand); }
.buy-dock .bd-l small { font-size: 11.5px; color: var(--muted); letter-spacing: .08em; }
.buy-dock .btn { margin-left: auto; padding: 11px 26px; min-height: 42px; }
@media (max-width: 820px) { .buy-dock { display: flex; } }

/* ============================================================
   目录页 · 一卷一块，纵向滚动
   首页收成纯封面后，原来那一长条内容整体搬到这里
   ============================================================ */
.cat-head {
  background: linear-gradient(160deg, #241c15, #17130f 72%);
  color: #fff;
  padding: clamp(78px, 13vh, 132px) 24px clamp(32px, 5vh, 52px);
}
.cat-head-inner { max-width: 1280px; margin: 0 auto; }
.cat-head .kicker {
  display: block; font-size: 10.5px; letter-spacing: .32em;
  color: var(--gold-soft); text-transform: uppercase;
}
.cat-title {
  font-family: var(--serif); font-weight: 700; letter-spacing: .05em;
  font-size: clamp(30px, 5.4vw, 58px); line-height: 1.1; margin-top: 14px;
}
.cat-sub { margin-top: 12px; font-size: 12.5px; letter-spacing: .18em; color: rgba(255,255,255,.72); }
.cat-note { margin-top: 6px; font-size: 11.5px; letter-spacing: .08em; color: rgba(255,255,255,.5); }

/* 吸顶快跳条 */
.cat-jump {
  position: sticky; top: 57px; z-index: 40;
  background: rgba(250,247,241,.94);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
}
.cat-jump-inner {
  max-width: 1280px; margin: 0 auto; padding: 10px 24px;
  display: flex; gap: 8px; overflow-x: auto; scrollbar-width: none;
}
.cat-jump-inner::-webkit-scrollbar { display: none; }
.cat-jump a {
  flex: 0 0 auto; white-space: nowrap;
  font-size: 12.5px; letter-spacing: .06em; color: var(--ink-soft);
  background: var(--card); border: 1px solid var(--line-strong);
  border-radius: 999px; padding: 5px 14px;
  transition: background .25s var(--ease), color .25s var(--ease), border-color .25s var(--ease);
}
.cat-jump a:hover { border-color: var(--brand-line); color: var(--brand); }
.cat-jump a.active { background: var(--ink); border-color: var(--ink); color: #fff; }

.catalog { max-width: 1280px; margin: 0 auto; padding: 0 24px clamp(48px, 8vh, 88px); }
.cat-sec { padding: clamp(34px, 5.5vh, 60px) 0; border-bottom: 1px solid var(--line); }
.cat-sec:last-child { border-bottom: 0; }
.cat-sec-head { display: flex; align-items: flex-end; gap: 16px; flex-wrap: wrap; }
.cat-no { font-family: var(--num); font-size: 30px; line-height: 1; color: var(--faint); }
.cat-sec-title h2 { font-family: var(--serif); font-weight: 700; letter-spacing: .04em; font-size: clamp(21px, 2.8vw, 30px); }
.cat-sec-title h2 a { color: var(--ink); }
.cat-sec-title h2 a:hover { color: var(--brand); }
.cat-meta { display: block; margin-top: 4px; font-size: 12px; letter-spacing: .14em; color: var(--muted); }
.cat-sec-buy { margin-left: auto; display: flex; align-items: center; gap: 16px; }
.cat-pkg { font-family: var(--num); font-size: 18px; font-weight: 700; color: var(--brand); }
.cat-pkg em { font-style: normal; font-size: 11px; letter-spacing: .08em; color: var(--muted); margin-left: 7px; }
.cat-go { font-size: 12.5px; letter-spacing: .14em; color: var(--ink-soft); border-bottom: 1px solid var(--line-strong); padding-bottom: 2px; }
.cat-go i, .c-buy i { font-style: normal; margin-left: 5px; }
.cat-go:hover { color: var(--brand); border-color: var(--brand-line); }

.cat-grid {
  margin-top: 22px; display: grid; gap: 18px;
  /* v30：卡面从 150px 放大到 200px，图看得清、标题也读得舒服 */
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}
.cat-card {
  display: block; background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius); overflow: hidden;
  transition: transform .35s var(--ease), box-shadow .35s var(--ease), border-color .35s var(--ease);
}
.cat-card:hover { transform: translateY(-5px); box-shadow: var(--shadow-md); border-color: var(--brand-line); }
.c-thumb { position: relative; display: block; aspect-ratio: 3 / 4; background: var(--paper-2); overflow: hidden; }
.c-thumb img { width: 100%; height: 100%; object-fit: cover; opacity: 0; transition: opacity .5s var(--ease), transform .7s var(--ease); }
.c-thumb img.loaded { opacity: 1; }
.cat-card:hover .c-thumb img { transform: scale(1.06); }
.c-buy {
  position: absolute; left: 0; right: 0; bottom: 0;
  display: flex; justify-content: space-between; align-items: center;
  padding: 16px 10px 8px; font-size: 11.5px; letter-spacing: .1em; color: #fff;
  background: linear-gradient(transparent, rgba(23,19,15,.82));
  opacity: 0; transition: opacity .28s var(--ease);
}
.cat-card:hover .c-buy { opacity: 1; }
.c-title {
  display: block; padding: 11px 12px 1px; font-size: 13.5px; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* 🔴 2026-10-07 手机小屏套系标题不再截成省略号：
   320px 两列时每格只有 129px，而「第 2 套 · 长椅与旧书」要 146px ——
   一屏 12 个全成了「第 N 套 · 长椅与旧…」，第一眼就是坏的。窄屏放成最多两行。 */
@media (max-width: 480px) {
  .c-title {
    white-space: normal; display: -webkit-box; -webkit-box-orient: vertical;
    -webkit-line-clamp: 2; line-height: 1.45; padding-bottom: 3px;
  }
}
.c-foot { display: flex; justify-content: space-between; align-items: baseline; padding: 0 12px 12px; font-size: 11.5px; color: var(--muted); }
/* 🔴 2026-10-07 窄屏卡片脚部拆字：320px 两列时卡片净宽只有 105px，
   「每套 100 张」+「暂未开放」横着放不下 ⇒ 逼出「暂未开 / 放」这种竖排断词。
   窄屏改成上下两行、各自不换行。 */
@media (max-width: 480px) {
  .c-foot { flex-direction: column; align-items: flex-start; gap: 3px; }
  .c-foot > span { white-space: nowrap; }
}
.c-price { font-family: var(--num); font-size: 13px; color: var(--brand); }
.cat-more {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  aspect-ratio: 3 / 4; border: 1px dashed var(--line-strong); border-radius: var(--radius);
  background: var(--paper-2); color: var(--muted);
  font-size: 12.5px; letter-spacing: .1em; text-align: center; line-height: 1.9;
  transition: color .25s var(--ease), border-color .25s var(--ease), background .25s var(--ease);
}
.cat-more:hover { color: var(--brand); border-color: var(--brand-line); background: var(--paper-3); }
@media (max-width: 640px) {
  /* v30：卡面下限从 104px 抬到 128px —— 原来一屏挤六列，图小到看不清长相 */
  .cat-grid { grid-template-columns: repeat(auto-fill, minmax(128px, 1fr)); gap: 10px; }
  .cat-sec-buy { margin-left: 0; width: 100%; }
  .cat-no { font-size: 24px; }
  /* 工具条折行时，计数和「随手翻一套」各占一行，按钮拉通好点 */
  .cat-count { margin-left: 0; width: 100%; order: 9; }
  .cat-dice { order: 10; width: 100%; padding: 10px 16px; }
  .cat-search { max-width: none; }
}

/* ============================================================
   目录入口放大 v13 —— 「目录」必须一眼撞见
   原来只有两处 10~13px 的小字，手机上还整块隐藏了，
   等于把唯一的入口藏了起来。改成：金色胶囊导航 + 封面右下大胶囊，
   手机端不再隐藏，直接拉成底部通栏。
   ============================================================ */

/* ---------- 顶部导航：进目录的金色胶囊 ---------- */
.nav-links a.nav-cta {
  padding: 8px 18px; border-radius: 999px;
  border: 1px solid var(--gold);
  background: rgba(200, 153, 74, .14);
  color: var(--brand-deep);
  font-size: 12.5px; letter-spacing: .16em; font-weight: 600; white-space: nowrap;
  transition: background .3s var(--ease), color .3s var(--ease), border-color .3s var(--ease);
}
.nav-links a.nav-cta::after { display: none; }
.nav-links a.nav-cta i { font-style: normal; margin-left: 2px; transition: transform .3s var(--ease); }
.nav-links a.nav-cta:hover { background: var(--gold); border-color: var(--gold); color: #fff; }
.nav-links a.nav-cta:hover i { transform: translateX(3px); }
/* 压在封面大图上时：磨砂玻璃 + 金边，暗底也照样抢眼 */
.nav.over .nav-links a.nav-cta {
  background: rgba(23, 19, 15, .45); border-color: var(--gold-soft); color: var(--gold-soft);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
}
.nav.over .nav-links a.nav-cta:hover { background: var(--gold); border-color: var(--gold); color: #17130f; }
.nav-links a.nav-cta.active { background: var(--gold); border-color: var(--gold); color: #fff; }

/* ---------- 封面右列三块的垂直栈：用同一个变量算，天然不会互相压住 ----------
   右侧从上到下：3D 迎宾员 → 今日宜翻阅小卡 → 全部目录胶囊。
   🔴 以前小卡的 bottom 是自己写的 clamp(72px,11vh,110px)，胶囊是 clamp(52px,8vh,88px)，
   两条各写各的 ⇒ 实测小卡底 805px、胶囊顶 765px，**重叠 40px**，
   小卡把胶囊左半边压住了，两个按钮叠在一起既看不清也不好点。
   现在改成：胶囊的 bottom 是唯一的真值，小卡的 bottom 由它反推（胶囊高 + 间隙），
   以后改胶囊位置，小卡自动跟着让位，永远不会再撞。 */
/* 🔴 2026-10-06：人物宽度抽成变量，给字幕当定位锚。
   起因：人物宽度在主规则和 @media(max-height:780px) 里各写一份 clamp()，
   字幕要按「人物中心线」定位就得把同一份 clamp 再抄一遍 ——
   实测抄错两回（1366×768 偏 11px、1180×820 偏 10px，都是媒体查询档位对不上）。
   现在宽度只在这里定义一次，人物和字幕都读它，两边永远同宽同位。 */
.cover { --cat-b: clamp(52px, 8vh, 88px); --cat-h: 63px; --rail-gap: 22px; --host-w: clamp(188px, 14.5vw, 238px); }

.cover-catalog {
  position: absolute; right: clamp(18px, 4vw, 44px); bottom: var(--cat-b); z-index: 4;
  display: inline-flex; align-items: center; gap: 14px;
  padding: 15px 24px; max-width: calc(100% - 36px);
  border: 1px solid rgba(232, 201, 141, .55); border-radius: 999px;
  background: rgba(23, 19, 15, .46);
  backdrop-filter: blur(10px) saturate(1.1); -webkit-backdrop-filter: blur(10px) saturate(1.1);
  color: #fff;
  animation: catGlow 3.4s var(--ease) infinite;
  transition: transform .35s var(--ease), background .35s var(--ease), border-color .35s var(--ease);
}
.cover-catalog:hover { transform: translateY(-3px); background: rgba(200, 153, 74, .93); border-color: var(--gold-soft); }
.cover-catalog .cc-label { font-family: var(--serif); font-size: 17px; font-weight: 700; letter-spacing: .14em; color: var(--gold-soft); white-space: nowrap; }
.cover-catalog .cc-meta { font-size: 11.5px; letter-spacing: .14em; color: rgba(255, 255, 255, .74); white-space: nowrap; }
.cover-catalog .cc-meta:empty { display: none; }
.cover-catalog .cc-arrow { font-style: normal; font-size: 22px; line-height: 1; color: var(--gold-soft); transition: transform .3s var(--ease), color .3s var(--ease); }
.cover-catalog:hover .cc-label,
.cover-catalog:hover .cc-arrow { color: #17130f; }
.cover-catalog:hover .cc-meta { color: rgba(23, 19, 15, .72); }
.cover-catalog:hover .cc-arrow { transform: translateX(5px); }
@keyframes catGlow {
  0%, 100% { box-shadow: 0 10px 34px rgba(0, 0, 0, .34), 0 0 0 0 rgba(200, 153, 74, .34); }
  55%      { box-shadow: 0 10px 34px rgba(0, 0, 0, .34), 0 0 0 12px rgba(200, 153, 74, 0); }
}

/* 手机：不再隐藏，拉成底部一条通栏，拇指一伸就点得到 */
@media (max-width: 640px) {
  /* 🔴 2026-10-07 修手机端首屏顶部那条死白（实测 390px：导航底 61，正文却从 y222 才开始 ⇒ 空了 161px）。
     病根不在 padding，而在 .cover 的 align-items:flex-end ——
     桌面端正文比视口高，这一条不起作用；手机正文比视口矮，flex 就把整块顶到底部，顶上白出一条。
     手机改成顶部对齐 + 竖排（.daily 哪天不再隐藏，也不会横着和正文挤成两栏）。 */
  .cover { flex-direction: column; align-items: flex-start; }
  /* 74 = 导航底 58~61 + 一点呼吸；底部留 132 给「滚动字幕(顶 724) + 目录胶囊(顶 769)」让位 */
  .cover-inner { padding: 74px 24px 132px; }
  .cover-catalog {
    left: 16px; right: 16px; bottom: 18px; max-width: none;
    justify-content: center; gap: 10px; padding: 13px 18px; border-radius: 999px;
  }
  .cover-catalog .cc-label { font-size: 16px; letter-spacing: .1em; }
  .cover-catalog .cc-meta { font-size: 11px; letter-spacing: .08em; overflow: hidden; text-overflow: ellipsis; }
}
@media (max-width: 380px) {
  .cover-catalog .cc-meta { display: none; }
}

/* 手机上导航别把「查订单」挤换行：整体不许折行，胶囊略收窄 */
.nav-links a { white-space: nowrap; }
@media (max-width: 640px) {
  .nav-links a.nav-cta { padding: 7px 13px; letter-spacing: .1em; }
}
/* 🔴 2026-10-07 修手机端导航破版（实测 iPhone 390px）：
   上面那条「链接不许折行」只管住了链接，宽度不够时被压缩的只剩品牌区 ——
   结果「靴语」被挤成上下两行、英文副标也竖排成两行，导航栏撑到 150px 高，
   右边「留个名字」还被裁掉一半，第一眼就是坏的。
   现在把手机端重新配平：
     · 品牌取 0 0 auto，谁都别想压扁它；英文副标收起来（竖着排没法看）
     · 链接让出弹性、空间不够时可以横向滑，绝不裁字
   按最坏情况「封面 目录 会员 领取记录 会员·我的」（已登录的会员）算过：
   390px 需 348px、380px 需 310px，都留了余量。 */
@media (max-width: 640px) {
  .nav-inner { padding: 13px 16px; gap: 12px; }
  .brand { flex: 0 0 auto; }
  .brand .b-cn { font-size: 19px; white-space: nowrap; }
  .brand .b-en { display: none; }
  .nav-links {
    flex: 1 1 auto; min-width: 0; justify-content: flex-end;
    gap: 13px; font-size: 12px; letter-spacing: .08em;
    overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch;
  }
  .nav-links::-webkit-scrollbar { display: none; }
}
@media (max-width: 380px) {
  .nav-inner { padding: 12px 14px; gap: 10px; }
  .brand .b-cn { font-size: 17px; }
  .nav-links { gap: 10px; font-size: 11.5px; letter-spacing: .04em; }
}

/* ============================================================
   活封面 v14 —— 拼贴图改为「随时在变」
   以前是一张固定的大拼图，看久了就是张死海报。
   现在改成：从全部套系封面里随机抽几张拼成一屏，每次进首页都不一样，
   停留时每 9 秒悄悄换掉其中两格 —— 像橱窗在不停换陈列。
   兜底：底图（轻量版）还在下面，脚本没跑起来也不会开天窗。
   ============================================================ */
.cover-mosaic {
  position: absolute; inset: 0; z-index: 0;
  display: grid; grid-template-columns: .92fr .8fr 1.02fr .86fr 1.4fr;
  gap: 3px; background: #0e0c0a;
  opacity: 0; transition: opacity 1.2s var(--ease);
}
.cover-mosaic.on { opacity: 1; }
.cm-cell { overflow: hidden; background: #17130f; }
.cm-cell img {
  width: 100%; height: 100%;
  object-fit: cover; object-position: center 26%;   /* 偏上裁，保住头脸 */
  opacity: 0; transform: scale(1.04);
  transition: opacity .55s var(--ease), transform 7s linear;
}
/* v30：每格自己慢速推近，像橱窗里的胶片在轻微呼吸。
   原来是整层静止，右侧大片区域看着发空、发闷；现在有生命感了。 */
.cm-cell img.on { opacity: 1; transform: scale(1); animation: cmBreathe var(--dur, 15s) ease-in-out infinite alternate; }
@keyframes cmBreathe {
  from { transform: scale(1); }
  to   { transform: scale(1.07); }
}
@media (max-width: 640px) {
  .cover-mosaic { grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr; }
}
/* 需要减少动效的机器：只拼一次，不再轮换 */
@media (prefers-reduced-motion: reduce) {
  .cm-cell img { transition: opacity .2s linear; transform: none; }
  .cover-mosaic { transition: none; }
}

/* ============================================================
   后台改版 v15 —— 先看见「还差什么」，再干活
   原来的后台一进去就是一堆表单，链接空着、收款码空着没人提醒。
   现在第一屏是总览：五个数字 + 待办清单（点一下直达），
   系列页能批量贴链接，订单页能按状态筛。
   ============================================================ */

/* ---------- 总览：数字卡 ---------- */
.ov-stats {
  display: grid; gap: 12px; margin-bottom: 18px;
  grid-template-columns: repeat(auto-fit, minmax(132px, 1fr));
}
.ov-card {
  padding: 16px 18px; border: 1px solid var(--line); border-radius: 14px;
  background: linear-gradient(180deg, rgba(255,255,255,.86), rgba(255,255,255,.62));
  box-shadow: 0 6px 18px rgba(23,19,15,.05);
}
.ov-k { font-size: 12px; letter-spacing: .18em; color: var(--muted); }
.ov-v { font-family: var(--serif); font-size: 27px; font-weight: 700; line-height: 1.25; color: var(--ink); }
.ov-s { font-size: 11.5px; letter-spacing: .06em; color: var(--faint); margin-top: 2px; }

/* ---------- 总览：待办清单 ---------- */
/* 「还差什么没办」是活的：这一条放「已更新 xx:xx:xx」+ 手动刷新，
   让人一眼看出数字会自己动，而不是打开后台时的一张快照。 */
.ov-live { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 10px; }
.ov-updated { font-size: 12.5px; color: var(--muted); letter-spacing: .03em; }
.todo-list { display: flex; flex-direction: column; gap: 10px; margin-top: 12px; }
.todo {
  display: flex; align-items: center; gap: 12px;
  padding: 13px 16px; border: 1px solid var(--line); border-radius: 12px;
  background: rgba(255,255,255,.7);
}
.todo .dot { flex: 0 0 auto; width: 9px; height: 9px; border-radius: 50%; background: var(--brand); }
.todo.bad { border-color: rgba(179,38,30,.34); background: rgba(179,38,30,.05); }
.todo.bad .dot { background: #b3261e; }
.todo.warn { border-color: rgba(200,153,74,.42); background: rgba(200,153,74,.07); }
.todo.warn .dot { background: var(--gold); }
.todo.ok { border-color: rgba(56,142,90,.34); background: rgba(56,142,90,.06); }
.todo.ok .dot { background: #388e5a; }
.todo .tt { flex: 1; min-width: 0; }
.todo .tt b { font-size: 14.5px; letter-spacing: .04em; }
.todo .tt .hint-text { margin-top: 2px; }
.todo .btn { flex: 0 0 auto; }

.ov-order {
  padding: 12px 0; border-bottom: 1px dashed var(--line);
}
.ov-order:last-child { border-bottom: none; }
.ov-order b { font-size: 14px; }
.ov-order .hint-text { margin-top: 3px; }

/* ---------- 系列页：筛选条 ---------- */
.scene-tools { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin-top: 18px; }
.scene-tools input[type="text"], .scene-tools input:not([type]) { flex: 1; min-width: 150px; }
.chk { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; color: var(--muted); flex: 0 0 auto; }
.chk input { width: auto; }

/* ---------- 订单页：状态筛选 ---------- */
.order-tools { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-top: 12px; }
.order-tools .obtn {
  padding: 7px 14px; border-radius: 999px; border: 1px solid var(--line);
  background: transparent; color: var(--muted); font-size: 12.5px; letter-spacing: .08em;
  cursor: pointer; transition: all .25s var(--ease);
}
.order-tools .obtn:hover { border-color: var(--brand); color: var(--brand-deep); }
.order-tools .obtn.active { background: var(--ink); border-color: var(--ink); color: #fff; }
.order-tools input { flex: 1; min-width: 150px; }

/* ---------- 后台常见控件收口 ---------- */
.admin-item code {
  padding: 2px 6px; border-radius: 5px; background: rgba(23,19,15,.06);
  font-size: 12px; letter-spacing: 0;
}
.admin-tabs { gap: 6px; }
.admin-tabs button { font-size: 13px; letter-spacing: .06em; padding: 9px 16px; border-radius: 999px; }

/* ---------- 手机上后台也能用 ---------- */
@media (max-width: 720px) {
  .admin-wrap { padding: 88px 14px 70px; }
  .admin-tabs {
    flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch;
    padding-bottom: 6px; margin-bottom: 16px;
  }
  .admin-tabs button { flex: 0 0 auto; padding: 8px 14px; font-size: 12.5px; }
  .ov-stats { grid-template-columns: repeat(2, 1fr); }
  .ov-v { font-size: 23px; }
  .todo { flex-wrap: wrap; }
  .todo .btn { width: 100%; margin-top: 4px; }
}

/* ============================================================
   缺网盘链接的套系：前台标「暂未开放」 v16
   单套靠「这套自己的网盘链接」发货，链接空着就会出现"收了钱发不出货"。
   现在这类套系在列表上直接写「暂未开放」、详情页按钮变灰不可点，
   服务端下单接口也按同一口径拦截 —— 前后台一致，绕不过去。
   ============================================================ */
.c-price.off, .a-price.off {
  color: var(--muted); font-size: 12px; letter-spacing: .1em; font-weight: 500;
}
.a-price.off { opacity: .8; }
.cat-card .c-buy { transition: opacity .3s var(--ease); }

/* ============================================================
   v27 · 后台可操作性 + 打赏口吻（2026-10-02）
   ============================================================ */
/* 订单汇总：每一块都是能点的筛子 */
.sum-chips { display: inline-flex; gap: 6px; flex-wrap: wrap; }
.sum-chip {
  border: 1px solid var(--line, #e5ded4); background: var(--card, #fff);
  border-radius: 999px; padding: 5px 12px; font-size: 12px; color: var(--muted);
  cursor: pointer; letter-spacing: .02em;
}
.sum-chip b { color: var(--ink, #2b2724); }
.sum-chip.on { background: #2b2724; color: #fff; border-color: #2b2724; }
.sum-chip.on b { color: #fff; }
.sum-chip.static { cursor: default; }
/* 订单卡片：单号 / 联系方式 / 邮箱一键复制 */
.o-meta { font-size: 12px; color: var(--muted); line-height: 1.9; }
.copy-btn {
  border: none; background: transparent; color: var(--brand, #8a5a2b);
  font-size: 11px; cursor: pointer; padding: 1px 6px; border-radius: 6px;
  border: 1px dashed rgba(138, 90, 43, .45);
}
.copy-btn:hover { background: rgba(138, 90, 43, .08); }
.no-mail { color: #b3261e; font-size: 11px; }
/* 套系与图片：折叠条上的状态徽章（不展开也能看出这卷缺什么） */
.sg-badges { display: inline-flex; gap: 6px; margin-left: auto; margin-right: 12px; }
.sg-badge {
  font-size: 11px; padding: 3px 10px; border-radius: 999px; letter-spacing: .03em;
  background: #f1efe8; color: #5f5e5a;
}
.sg-badge.warn { background: #faeeda; color: #854f0b; }
.sg-badge.ok { background: #eaf3de; color: #3b6d11; }
/* 批量上料：底部浮动操作条 —— 选中套系后滚到哪都能操作 */
.intake-dock {
  position: fixed; left: 50%; transform: translateX(-50%);
  bottom: 18px; z-index: 60;
  display: flex; align-items: center; gap: 10px;
  background: #2b2724; color: #fff;
  padding: 10px 16px; border-radius: 14px;
  box-shadow: 0 8px 28px rgba(0, 0, 0, .25);
}
.intake-dock .id-n { font-size: 13px; letter-spacing: .04em; white-space: nowrap; }
.intake-dock input {
  width: 130px; padding: 7px 10px; border-radius: 8px; border: none;
  font-size: 13px; background: rgba(255, 255, 255, .12); color: #fff;
}
.intake-dock input::placeholder { color: rgba(255, 255, 255, .55); }
.intake-dock .btn.small { background: #fff; color: #2b2724; }
.intake-dock .btn.small.outline { background: transparent; color: #fff; border: 1px solid rgba(255, 255, 255, .5); }
@media (max-width: 640px) { .intake-dock { width: calc(100% - 24px); flex-wrap: wrap; justify-content: center; } }
/* 总览数字卡：可点，悬停轻轻抬一下 */
.ov-card.link { cursor: pointer; transition: transform .18s var(--ease), box-shadow .18s var(--ease); }
.ov-card.link:hover { transform: translateY(-2px); box-shadow: 0 6px 18px rgba(43, 39, 36, .1); }
/* 详情页打赏条 */
.tip-jar {
  margin-top: 18px; padding: 14px 18px; border-radius: 12px;
  background: #fbf7f2; border: 1px dashed rgba(138, 90, 43, .4);
  font-size: 14px; color: #5c707c; text-align: center;
}
.tip-jar a { color: var(--brand, #8a5a2b); font-weight: 700; }
/* 免费/暂未开放 标签 */
.c-price.free, .a-price.free { color: #3b6d11; font-weight: 700; }

/* ============================================================
   v28 · 赞赏页明细（2026-10-02）
   ============================================================ */
.pay-amount {
  margin: 18px 0 4px; border: 1px solid var(--line, #e5ded4);
  border-radius: 12px; overflow: hidden; background: var(--card, #fff);
}
.pa-row {
  display: flex; align-items: center; gap: 12px;
  padding: 11px 16px; font-size: 14px; border-bottom: 1px solid var(--line, #ece5db);
}
.pa-row:last-child { border-bottom: none; }
.pa-k { width: 76px; flex: none; color: var(--muted); font-size: 13px; }
.pa-v { color: var(--ink, #2b2724); word-break: break-all; }
.pa-money { font-size: 20px; font-weight: 700; color: var(--brand, #8a5a2b); }
.pa-money .copy-btn, .pa-v .copy-btn { margin-left: 8px; vertical-align: middle; }

/* ============================================================
   v29 · 文艺清新：纸感、悬停、交互、视频位（2026-10-03）
   ============================================================ */
:root {
  --paper-3: #fbf9f5;
  --sage: #6f7d63;          /* 一抹清冷的草绿，给"清新"用 */
  --glow: rgba(169, 85, 31, .09);
  --film: rgba(23, 19, 15, .06);
}

/* ---------- 底子：更细腻的纸与字 ---------- */
body {
  background-image:
    radial-gradient(circle at 18% 12%, rgba(200, 153, 74, .05), transparent 42%),
    radial-gradient(circle at 84% 78%, rgba(111, 125, 99, .05), transparent 46%);
  background-attachment: fixed;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* 章节小标：一条细金线 + 一个词，文艺又不喧哗 */
.sec-mark {
  display: flex; align-items: center; gap: 14px;
  margin: 0 0 22px; color: var(--muted);
  font-size: 12px; letter-spacing: .28em; text-transform: uppercase;
}
.sec-mark::after { content: ""; flex: 1; height: 1px; background: linear-gradient(90deg, var(--brand-line), transparent); }
.sec-mark b { color: var(--brand); font-weight: 700; letter-spacing: .18em; }

/* ---------- 卡片：悬停会轻轻浮起来，图缓慢推近 ---------- */
.cat-card, .reel-card, .album-card { will-change: transform; }
.cat-card, .reel-card, .album-card, .pick-card {
  transition: transform .55s var(--ease), box-shadow .55s var(--ease), border-color .55s var(--ease);
}
.cat-card:hover, .reel-card:hover, .album-card:hover, .pick-card:hover {
  transform: translateY(-5px);
  box-shadow: 0 18px 44px rgba(40, 28, 16, .14);
  border-color: var(--brand-line);
}
.cat-card .c-thumb img, .reel-card .r-thumb img, .album-card .thumb img, .pick-card img {
  transition: transform 1.4s var(--ease), filter .8s var(--ease);
}
.cat-card:hover .c-thumb img, .reel-card:hover .r-thumb img, .album-card:hover .thumb img, .pick-card:hover img {
  transform: scale(1.07); filter: saturate(1.06);
}
/* 悬停时"看这一套"轻轻浮现 */
.c-buy, .r-buy {
  opacity: 0; transform: translateY(6px);
  transition: opacity .45s var(--ease), transform .45s var(--ease);
}
.cat-card:hover .c-buy, .reel-card:hover .r-buy,
.cat-card:focus-visible .c-buy, .reel-card:focus-visible .r-buy { opacity: 1; transform: none; }

/* ---------- 播放角标：这一套将来挂了视频就亮这个 ---------- */
.play-badge {
  position: absolute; top: 10px; left: 10px; z-index: 3;
  display: inline-flex; align-items: center; gap: 5px;
  padding: 4px 10px 4px 8px; border-radius: 999px;
  background: rgba(23, 19, 15, .58); color: #fff;
  font-size: 11px; letter-spacing: .06em; backdrop-filter: blur(6px);
  border: 1px solid rgba(255, 255, 255, .22);
  transition: background .3s var(--ease), transform .3s var(--ease);
}
/* v30：镜头前的短片会呼吸，红点亮一下；有短片的套系在一排图里自己会跳出来 */
.play-badge::before {
  content: ""; width: 0; height: 0;
  border-left: 8px solid currentColor; border-top: 5px solid transparent; border-bottom: 5px solid transparent;
  filter: drop-shadow(0 0 3px rgba(255, 255, 255, .5));
}
.play-badge::after {
  content: ""; position: absolute; inset: -1px; border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, .55);
  animation: pbPulse 2.4s var(--ease) infinite;
}
@keyframes pbPulse {
  0%   { opacity: .7; transform: scale(1); }
  60%  { opacity: 0;  transform: scale(1.28); }
  100% { opacity: 0;  transform: scale(1.28); }
}
.cat-card:hover .play-badge { background: rgba(23, 19, 15, .78); transform: scale(1.06); }
.c-thumb, .r-thumb, .thumb, .pick-card .pc-thumb { position: relative; }
.c-thumb > img, .r-thumb > img { display: block; }

/* ---------- 首页「今日宜翻阅」：一张斜靠在封面上的拍立得 ---------- */
.daily {
  position: absolute; left: clamp(18px, 5vw, 64px); bottom: clamp(26px, 6vh, 64px);
  z-index: 6; width: min(276px, 46vw);
  transform: rotate(-2.2deg);
  transition: transform .6s var(--ease), box-shadow .6s var(--ease);
}
.daily:hover { transform: rotate(0deg) translateY(-4px); box-shadow: 0 26px 60px rgba(20, 14, 8, .45); }
.daily-in {
  display: block; padding: 10px 10px 14px; border-radius: 10px;
  background: #fffdf9; color: var(--ink); text-decoration: none;
  box-shadow: 0 18px 44px rgba(20, 14, 8, .38);
  border: 1px solid rgba(255, 255, 255, .6);
}
.daily .pc-thumb {
  display: block; aspect-ratio: 4 / 5; overflow: hidden; border-radius: 6px;
  background: var(--paper-2);
}
.daily .pc-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.daily .pc-k {
  display: flex; align-items: center; justify-content: space-between;
  margin: 10px 2px 4px; font-size: 10px; letter-spacing: .24em;
  color: var(--brand); text-transform: uppercase;
}
.daily .pc-t {
  display: block; margin: 0 2px; font-family: var(--serif);
  font-size: 15px; line-height: 1.5; color: var(--ink);
}
.daily .pc-s { display: block; margin: 4px 2px 0; font-size: 12px; color: var(--muted); }
.daily .pc-swap {
  display: block; width: 100%; margin-top: 10px; padding: 7px 0;
  border: 1px solid var(--line); border-radius: 8px; background: transparent;
  font-size: 12px; color: var(--muted); cursor: pointer; letter-spacing: .08em;
  transition: background .3s var(--ease), color .3s var(--ease);
}
.daily .pc-swap:hover { background: var(--brand-wash); color: var(--brand-deep); }
/* 手机上别挡住封面文字，缩成一条小卡 */
@media (max-width: 860px) {
  .daily { position: static; width: 100%; transform: none; margin: 14px 0 0; }
  .daily-in { display: flex; gap: 12px; align-items: center; padding: 8px; }
  .daily .pc-thumb { width: 62px; flex: none; aspect-ratio: 1 / 1; }
  .daily .pc-body { flex: 1; min-width: 0; }
  .daily .pc-swap { margin-top: 6px; }
}

/* ---------- 目录工具条：搜索 + 筛选 + 计数 ---------- */
.cat-tools {
  position: sticky; top: 58px; z-index: 30;
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 12px 0; margin-bottom: 6px;
  /* 🔴 2026-10-07 改实色（原为「72% 处渐变到透明」）：吸顶时底部 28% 会透出下面的卡片 ——
     实测手机上「随手翻一套」按钮像被削掉下半截。吸顶条必须整条不透明。 */
  background: var(--paper);
}
.cat-search {
  flex: 1; min-width: 190px; max-width: 320px;
  padding: 9px 14px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--card); color: var(--ink);
  font-size: 13px; letter-spacing: .02em; outline: none;
  transition: border-color .3s var(--ease), box-shadow .3s var(--ease);
}
.cat-search:focus { border-color: var(--brand-line); box-shadow: 0 0 0 3px var(--glow); }
.cat-search::placeholder { color: var(--faint); }
.cat-chips { display: inline-flex; gap: 6px; flex-wrap: wrap; }
.cat-chip {
  padding: 7px 13px; border-radius: 999px; cursor: pointer;
  border: 1px solid var(--line); background: var(--card);
  font-size: 12px; color: var(--muted); letter-spacing: .04em;
  transition: all .3s var(--ease);
}
.cat-chip:hover { border-color: var(--brand-line); color: var(--brand-deep); }
.cat-chip.on { background: var(--ink); border-color: var(--ink); color: #fff; }
.cat-count { margin-left: auto; font-size: 12px; color: var(--muted); letter-spacing: .06em; }
.cat-count b { color: var(--brand); font-size: 15px; font-family: var(--num); margin: 0 3px; }

/* v30 新增：「随手翻一套」——不知道从哪看起时，让它替你挑一套。
   放在计数右边、贴着右边缘，跟筛选按钮明显分开，不抢主操作的位。 */
.cat-dice {
  padding: 8px 16px; border-radius: 999px; cursor: pointer;
  border: 1px solid var(--brand-line); background: transparent;
  color: var(--brand-deep); font-size: 12.5px; letter-spacing: .06em; white-space: nowrap;
  transition: all .3s var(--ease);
}
.cat-dice:hover { background: var(--brand); border-color: var(--brand); color: #fff; box-shadow: var(--shadow-sm); }
.cat-dice:disabled { opacity: .6; cursor: default; transform: none; }

/* 🔴 2026-10-07 手机端吸顶条瘦身：实测高 194px，占掉近三分之一屏幕 ——
   往下翻时几乎看不到几套。压成三行：搜索 → 筛选(横滑不换行) → 计数与「随手翻一套」并排。
   ⚠️ 必须写在上面的 .cat-search/.cat-chips/.cat-count/.cat-dice 定义之后，否则同优先级被后面的覆盖。 */
@media (max-width: 640px) {
  .cat-tools { gap: 8px; padding: 10px 0; }
  .cat-search { flex: 1 1 100%; min-width: 0; max-width: none; }
  .cat-chips {
    flex: 1 1 100%; flex-wrap: nowrap;
    overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch;
  }
  .cat-chips::-webkit-scrollbar { display: none; }
  /* 覆盖 1269/1270 那条「计数与按钮各占一行」：搜索已经独占一行了，
     这两条再各占一行就是白占 35px 屏高。并排后按钮仍有 ~120×41，拇指点得到。 */
  .cat-count { margin-left: 0; white-space: nowrap; width: auto; order: 0; }
  .cat-dice { margin-left: auto; width: auto; order: 0; padding: 9px 18px; }
}

.cat-sec.hidden, .cat-card.hidden { display: none; }
.cat-none { display: none; padding: 48px 20px; text-align: center; color: var(--muted); }
/* 一套都没翻到时，快跳条没有意义，收起来 */
.cat-jump.hidden { display: none; }

/* ---------- 详情页：阅读进度条 ---------- */
.read-bar {
  position: fixed; top: 0; left: 0; z-index: 70; height: 2px; width: 0;
  background: linear-gradient(90deg, var(--brand), var(--gold));
  transition: width .12s linear;
}

/* ---------- 详情页：胶片条（快速回看每一格） ---------- */
.filmstrip {
  display: flex; gap: 8px; overflow-x: auto; padding: 4px 2px 10px;
  scrollbar-width: thin; scroll-snap-type: x proximity;
}
.filmstrip::-webkit-scrollbar { height: 5px; }
.filmstrip::-webkit-scrollbar-thumb { background: var(--line-strong); border-radius: 3px; }
.filmstrip button {
  flex: none; width: 62px; aspect-ratio: 1 / 1; padding: 0; cursor: pointer;
  border: 1px solid var(--line); border-radius: 6px; overflow: hidden;
  background: var(--paper-2); scroll-snap-align: start;
  transition: transform .35s var(--ease), border-color .35s var(--ease), box-shadow .35s var(--ease);
}
.filmstrip button img { width: 100%; height: 100%; object-fit: cover; display: block; }
.filmstrip button:hover { transform: translateY(-3px); border-color: var(--brand-line); }
.filmstrip button.on { border-color: var(--brand); box-shadow: 0 0 0 2px var(--glow); }

/* ---------- 详情页：视频位 ---------- */
.video-box {
  position: relative; margin: 0 0 26px; border-radius: 12px; overflow: hidden;
  background: #14100c; box-shadow: var(--shadow-md); border: 1px solid var(--line);
}
.video-box video { display: block; width: 100%; max-height: 68vh; background: #14100c; }
.video-cap {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 12px 16px; background: var(--paper-2);
  font-size: 12px; color: var(--muted); letter-spacing: .06em;
}
.video-cap b { color: var(--ink); font-weight: 700; letter-spacing: .04em; }
.video-cap .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--brand); }

/* ---------- 返回顶部 ---------- */
.to-top {
  position: fixed; right: 20px; bottom: 22px; z-index: 55;
  width: 42px; height: 42px; border-radius: 50%; cursor: pointer;
  border: 1px solid var(--line); background: rgba(255, 253, 249, .92);
  color: var(--ink); font-size: 15px; line-height: 1;
  box-shadow: var(--shadow-md); backdrop-filter: blur(6px);
  opacity: 0; pointer-events: none; transform: translateY(8px);
  transition: all .4s var(--ease);
}
.to-top.show { opacity: 1; pointer-events: auto; transform: none; }
.to-top:hover { border-color: var(--brand-line); color: var(--brand); }
@media (max-width: 820px) { .to-top { display: none; } }   /* 手机上有吸底条，别打架 */

/* ---------- 悬停微光：卡片上的一层柔光 ---------- */
.cat-card::after, .reel-card::after, .album-card::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background: radial-gradient(420px circle at var(--mx, 50%) var(--my, 0%), rgba(255, 255, 255, .5), transparent 62%);
  opacity: 0; transition: opacity .5s var(--ease);
}
.cat-card:hover::after, .reel-card:hover::after, .album-card:hover::after { opacity: 1; }

/* ---------- 后台：视频行 ---------- */
.vid-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.vid-row input { flex: 1; min-width: 200px; }
.vid-pick { cursor: pointer; white-space: nowrap; }

/* 胶片条末尾那格：门后的张数 */
.fs-more {
  flex: none; align-self: stretch; display: inline-flex; align-items: center;
  padding: 0 16px; border: 1px dashed var(--brand-line); border-radius: 6px;
  font-size: 12px; color: var(--muted); letter-spacing: .06em; white-space: nowrap;
  background: var(--brand-wash);
}

/* v35 重排：右侧竖列从上到下 = 3D 迎宾员 → 今日宜翻阅 → 全部目录胶囊。
   原先两者都挂在"右侧垂直居中"上，迎宾员会被今日卡整个盖住（都是 absolute + 右侧）。
   现在迎宾员占上段，今日卡压扁（缩略图 4:5 改 4:3）挪到胶囊上方；
   高度不足 860px 的屏装不下两个，只留迎宾员（今日推荐在目录页照样有）。

   🔴 2026-10-06 修遮挡：小卡的 bottom 由「胶囊占位」反推 —— 胶囊高 --cat-h + 间隙 --rail-gap。
   原来小卡自己写 bottom: clamp(72px,11vh,110px)，胶囊写 clamp(52px,8vh,88px)，
   两条互不知情 ⇒ 1440×900 实测重叠 40px，小卡压住胶囊左半边（两个按钮叠一起点不准）。
   现在两条共用 .cover 上的 --cat-b/--cat-h，改一处就整体让位，不可能再撞。

   ⚠️ 右列纵向就那么点空间（900px 屏：迎宾员底 ~470，胶囊顶 ~749，中间只有 279px），
   所以小卡本身也得压扁：缩略图改 16:9、卡片缩到 190px，整卡高 ~213 才塞得下，
   剩下的空隙当呼吸位 —— 不然「让开胶囊」就变成「压住人物」，只是把遮挡换了个方向。 */
.daily {
  left: auto; right: clamp(20px, 4.5vw, 72px); top: auto;
  bottom: calc(var(--cat-b) + var(--cat-h) + var(--rail-gap));
  width: min(258px, 26vw);
  transform: rotate(2.4deg);
}
.daily:hover { transform: rotate(0deg) translateY(-6px); }
/* 横向紧凑条：缩略图缩成小方块放左边，标题/副题放右边。
   竖排那张卡光缩略图就吃掉 100 多 px（4:5/4:3/16:9 都一样），
   900px 屏右列只剩 294px，竖排怎么压都塞不下 ⇒ 直接改成一行，整卡矮到 ~150px，
   空出来的就还给迎宾员和胶囊当呼吸位。 */
.daily-in { display: flex; gap: 12px; align-items: center; padding: 9px; }
.daily .pc-thumb { width: 84px; flex: none; aspect-ratio: 1 / 1; }
.daily .pc-body { flex: 1; min-width: 0; }
.daily .pc-k { margin: 0 0 3px; }
.daily .pc-t {
  font-size: 13.5px; line-height: 1.4;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.daily .pc-s { margin-top: 3px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.daily .pc-swap { margin-top: 7px; padding: 5px 0; }
/* 够高的屏（≥980）才显示：实测 900px 屏右列只剩 294px，
   这条横向条约 150px，加上胶囊和迎宾员才不挤。矮屏宁可不显示，
   今日推荐在目录页照样有。 */
@media (max-width: 1180px), (max-height: 980px) { .daily { display: none; } }

/* ============================================================
   v32 诗意文案排版
   句子本身在 poems.js，这里只管"怎么摆"：
   文艺感全靠字距、斜体、颜色深浅 —— 字号绝不动，正文可读性优先。
   ============================================================ */

/* ---------- 卷引：目录页每一卷、系列页、详情页标题下共用 ----------
   位置都是"客人视线第一落点"，所以统一：斜体 + 品牌色 + 略小字号。 */
.cat-epi, .epi {
  display: block; margin-top: 7px;
  font-family: var(--serif, Georgia, "Times New Roman", serif);
  font-style: italic;
  font-size: 13.5px; line-height: 1.7; letter-spacing: .04em;
  color: var(--brand); opacity: .88;
}
.epi { font-size: 14.5px; margin-top: 10px; }

/* 系列页卷引压在暗底大图上，要更亮一点才读得清 */
.scene-hero .epi { color: rgba(255,255,255,.9); text-shadow: 0 1px 12px rgba(0,0,0,.4); }

/* 详情页标题下的引言：比标题小、比正文大，作为过渡 */
.detail-head .epi { color: var(--brand); }

/* ---------- 门后那句：临门一脚 ---------- */
.u-poem {
  margin-top: 9px; font-family: var(--serif, Georgia, serif); font-style: italic;
  font-size: 12.5px; letter-spacing: .05em; color: var(--muted); opacity: .9;
}

/* ---------- 页脚收尾语 ---------- */
.f-poem {
  margin-top: 7px; font-family: var(--serif, Georgia, serif); font-style: italic;
  font-size: 12.5px; letter-spacing: .05em; color: var(--faint);
}

/* ---------- 备案号（2026-10-15 域名备案通过）----------
   工信部要求：网站底部必须标明备案号，且链到官方查询页。
   刻意做得安静 —— 它是合规标识，不是装饰，不去抢上面那句诗。
   颜色压低、字号最小，但保证对比度够看（不是靠"看不见"来藏拙）。 */
.f-legal { margin-top: 9px; font-size: 11.5px; letter-spacing: .04em; }
.f-legal a { color: rgba(255,255,255,.42); text-decoration: none; border-bottom: 1px solid rgba(255,255,255,.16); padding-bottom: 1px; }
.f-legal a:hover { color: var(--gold-soft); border-bottom-color: var(--gold-soft); }

/* 页脚永远贴底（2026-10-15）：赞赏页、领取记录这类"内容不满一屏"的页面，
   页脚原本会浮在半空、后面还露一截底色，像没做完。
   让 body 竖着排，富余的空间自动落在页脚上方 —— 页脚就被顶到底了。
   （fixed 定位的浮层不受影响；后台没页脚，多一条 flex 也不碍事。） */
body { min-height: 100vh; display: flex; flex-direction: column; }
#footer { margin-top: auto; flex-shrink: 0; }

/* ---------- 移动端：诗句独立成行，别和署名挤在一行 ---------- */
@media (max-width: 640px) {
  .cat-epi, .epi { font-size: 12.5px; margin-top: 5px; }
  .f-poem { font-size: 12px; }
  .f-legal { font-size: 11px; }
}

/* ============================================================
   v33 非首页重做 —— 让每一页都有"坐下来看"的质感
   诊断出来的三处真问题：
     · 领取记录整页只有 423px，一个表单框孤零零飘在空白里
     · 打赏页被直接打开时是个死胡同（没金额、没单号）
     · 详情页底部本来就好，不动它
   ============================================================ */

/* ---------- 取件台：左氛围 / 右动作 ---------- */
.desk {
  display: grid; grid-template-columns: 1fr minmax(340px, 440px);
  gap: clamp(32px, 6vw, 88px); align-items: center;
  max-width: 1080px; margin: 0 auto; padding: clamp(48px, 9vh, 110px) 28px 90px;
}
.desk-l { max-width: 420px; }
.desk-t {
  font-size: clamp(38px, 6vw, 62px); line-height: 1.08; margin: 12px 0 18px;
  letter-spacing: .04em;
}
.desk-lede {
  font-family: var(--serif, Georgia, serif); font-style: italic;
  font-size: 17px; line-height: 1.95; color: var(--ink-2, var(--ink)); opacity: .9;
}
.desk-l .u-poem { margin-top: 16px; font-size: 13.5px; }
.desk-back {
  display: inline-block; margin-top: 26px; text-decoration: none;
  font-size: 13px; letter-spacing: .06em; color: var(--brand-deep);
  border-bottom: 1px solid var(--brand-line); padding-bottom: 3px;
  transition: border-color .3s var(--ease), color .3s var(--ease);
}
.desk-back:hover { color: var(--brand); border-color: var(--brand); }
.desk-r { box-shadow: var(--shadow-md); }

/* 手机上：氛围在上、动作在下，顺序不能反（先有情绪，再有按钮） */
@media (max-width: 860px) {
  .desk {
    grid-template-columns: 1fr; gap: 28px;
    /* 原来上下 padding 一百多，手机上中间空出一大片，看着像缺了内容 */
    padding: 40px 22px 64px; align-items: start;
  }
  .desk-l { max-width: none; }
  .desk-t { font-size: clamp(32px, 10vw, 44px); }
  .desk-lede { font-size: 15.5px; line-height: 1.85; }
  .desk-back { margin-top: 18px; }
  .desk-r { margin-top: 4px; }
}

/* ---------- 打赏页走错门时的兜底引导 ---------- */
.lost-box {
  margin-top: 22px; padding: 22px 18px; text-align: center;
  border: 1px dashed var(--line-strong); border-radius: var(--radius);
  background: var(--paper-2);
}
.lost-box .u-poem { margin: 0 0 16px; font-size: 13.5px; }

/* ---------- v33 目录页呼吸句：卷与卷之间的空白页 ----------
   14772px 的长页要靠节奏救，光靠卡片只会让人一路划到底。
   斜体大字、极淡，像翻书时遇到的章间留白，不抢图也不抢按钮。 */
.cat-breather {
  margin: clamp(28px, 4.5vh, 56px) 0;
  padding: clamp(18px, 3vh, 30px) 0;
  text-align: center;
  font-family: var(--serif, Georgia, serif); font-style: italic;
  font-size: clamp(15px, 2.1vw, 20px); line-height: 1.9;
  letter-spacing: .1em; color: var(--ink); opacity: .3;
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
  transition: opacity .3s var(--ease);
}
.cat-breather:hover { opacity: .55; }
.cat-breather.hidden { display: none; }
@media (max-width: 640px) {
  .cat-breather { font-size: 14px; letter-spacing: .06em; opacity: .34; }
}

/* ============================================================
   后台 v34 —— 三件事：
   ① 页签上的小红点：不用点进去就知道哪儿有事
   ② 页内分段：套系页 / 系列页原来三块平铺，常看的那块被压在一千多像素以下
   ③ 页签记忆的可见化：进后台直接回到上次的活儿，不用手点
   ============================================================ */

/* ① 页签待办角标 */
.admin-tabs button { position: relative; padding-right: 20px; }
.tab-dot {
  position: absolute; top: 6px; right: 8px;
  width: 7px; height: 7px; border-radius: 50%;
  background: #d0453b; box-shadow: 0 0 0 2px var(--card);
}
.admin-tabs button.active .tab-dot { background: #ff8a7a; box-shadow: 0 0 0 2px #fff; }
.tab-dot.warn { background: #d8a13a; }
.admin-tabs button.active .tab-dot.warn { background: #ffd08a; }

/* 进后台时的「接着上回干」条 */
.tab-resume {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin: -6px 0 18px; padding: 9px 14px;
  font-size: 13px; color: var(--muted); letter-spacing: .04em;
  background: var(--paper-2); border: 1px solid var(--line); border-radius: var(--radius-sm);
}
.tab-resume b { color: var(--ink); font-weight: 700; }
.tab-resume button {
  border: 0; background: none; padding: 0; font: inherit; cursor: pointer;
  color: var(--brand); text-decoration: underline; text-underline-offset: 3px;
}
.tab-resume button:hover { color: var(--brand-deep); }

/* ② 页内分段 */
.sub-tabs {
  display: flex; gap: 6px; flex-wrap: wrap;
  margin-bottom: 18px; padding-bottom: 14px; border-bottom: 1px solid var(--line);
}
.sub-tabs button {
  display: inline-flex; align-items: center; gap: 7px;
  border: 1px solid var(--line-strong); background: var(--card); color: var(--ink-soft);
  border-radius: 999px; padding: 8px 18px; min-height: 38px; font-size: 14px;
  letter-spacing: .05em; transition: all .2s var(--ease);
}
.sub-tabs button:hover { border-color: var(--brand); color: var(--brand-deep); }
.sub-tabs button.on { background: var(--ink); color: #fff; border-color: transparent; }
/* 段上带个数（几套缺链接、几个系列没链接），切之前就知道该去哪个段 */
.sub-tabs .sub-n {
  font-size: 11.5px; letter-spacing: .04em; padding: 2px 8px; border-radius: 999px;
  background: var(--paper-2); color: var(--muted); font-style: normal;
}
.sub-tabs button.on .sub-n { background: rgba(255,255,255,.18); color: #fff; }
.sub-tabs .sub-n.alert { background: #fbe9e7; color: #b3261e; }
.sub-tabs button.on .sub-n.alert { background: rgba(255,255,255,.2); color: #ffd9d3; }

.sub-pane { display: none; }
.sub-pane.on { display: block; animation: rise .26s var(--ease); }
/* 第一段别再顶一条多余分隔线：分段条已经画过了 */
.sub-pane.on > .album-tools:first-child,
.sub-pane.on > .scene-tools:first-child { margin-top: 0; padding-top: 0; border-top: 0; }

@media (max-width: 700px) {
  .sub-tabs button { padding: 7px 14px; font-size: 13px; }
}

/* ============================================================
   首页 3D 迎宾员 v37
   站在封面右侧亮区，会自己走来走去。
   三层分工（各管各的，别互相打架）：
     .host3d        外层：位置平移（走到哪儿）
     .host-stage    中层：转身（左右镜像）
     model-viewer   内层：呼吸 / 走路颠簸
   左下是「今日宜翻阅」卡、右下是「全部目录」胶囊，这块正好空着。
   ============================================================ */
.host3d {
  position: absolute;
  right: clamp(22px, 4.5vw, 76px);
  /* 🔴 2026-10-06 修遮挡：原来 top 是 clamp(84px,9.4vh,108px)，
     可 1366×768 实测导航底 70px、她（含气泡）顶只有 60px —— 气泡往上顶进导航 10px，
     「你来啦」那句话就压在「目录/会员」那一排下面。
     病根是 9.4vh：768×0.094 = 72px，比导航的 70px 还小，屏一矮就压上去。
     现在下限抬到 96px（= 导航 70 + 26 呼吸位），更高的屏仍按 9.4vh 往上走。

     🔴 2026-10-06 再改：下限从 96 抬到 124。
     滚动字幕搬到她头顶正上方了（.cover-ticker top:76 / 高 36 ⇒ 底 112），
     96 会让字幕直接坐她脑袋上。下限 124 = 字幕底 112 + 12 呼吸位。
     ⚠️ 改这里之前先确认 .cover-ticker 的 top/高度，别只顾一边。
     ⚠️ 上面 @media (max-height:780px) 里那条 max(96px,7.6vh) 也要跟着抬。 */
  top: max(clamp(96px, 9.4vh, 112px), 124px);
  z-index: 5;
  /* 窄而高的取景框 —— 她是「细高」型，容器接近正方形会把人缩得很小。
     这个比例（≈1:1.8）刚好贴合全身比例，人物能占满高度又不切到发顶和靴尖。
     🔴 宽度读 .cover 上的 --host-w，不自己写 clamp —— 字幕按同一定位锚，
     两边一旦各写一份就会在不同屏宽下偏开（已踩过 10~11px）。 */
  width: var(--host-w, clamp(188px, 14.5vw, 238px));
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  /* 位置由 --hx/--hy 决定，JS 改这两个值她就走到新地方 */
  opacity: 0; --hx: 0px; --hy: 0px; --lean: 1;
  transform: translate3d(var(--hx), calc(var(--hy) + 18px), 0);
  /* 位移的时长由 JS 每一步单独给（--move，= 一步的移动相）。
     默认这条给的是"出场滑入"；.walking 下换成**先快后慢**的曲线 ——
     匀速看着像滑行；起步快、临近落脚慢下来，那一下"沉"才是踩地感。 */
  transition: opacity .9s var(--ease), transform 2.4s cubic-bezier(.42,.02,.32,1);
  pointer-events: none;
  will-change: transform;
}
.host3d.walking {
  /* --move 走完这一格后，剩下 22% 刻意不再改 --hx：人已经站定了。
     这一段"停住"是整个手感的核心 —— 之前是匀速一路滑到底，所以像贴地平移。 */
  transition: opacity .9s var(--ease), transform var(--move, 235ms) cubic-bezier(.28,.62,.36,1);
}
.host3d.on {
  opacity: 1; pointer-events: auto;
  transform: translate3d(var(--hx), var(--hy), 0);
}
/* 走动途中被人打断：立刻刹住。
   0.1s 而不是 0.28s —— 迈步位移是"这一小格 440ms 走完"，被打断时若还留 0.28s 的滑行，
   眼睛会看到"叫人拦下之后又往前溜了一小段"，那就不是刹住而是滑了。 */
.host3d.still { transition: opacity .9s var(--ease), transform .06s linear; }

/* 舞台：模型站的地方。
   高度是算过的：她底下不能压到「今日宜翻阅」那张卡（1440×900 这类中等屏最挤），
   再加上气泡两行的高度，正好留出安全边。宁可人略小一点，也不能缺一块、压一块。 */
.host-stage {
  position: relative; width: 100%; height: clamp(300px, 34vh, 420px);
  transition: transform .34s var(--ease);
}
/* 落影：她脚下的影子。走动时淡一点、摊开一点（真影子在移动时会散） */
.host-stage::before {
  content: ''; position: absolute; left: 50%; bottom: 2px;
  width: 62%; height: 26px; z-index: 0;
  transform: translateX(-50%) scale(1);
  background: radial-gradient(ellipse at center, rgba(24,16,9,.58), rgba(24,16,9,.18) 52%, transparent 72%);
  filter: blur(1.5px);
  transition: opacity .7s var(--ease), transform .7s var(--ease), width .7s var(--ease);
}
.host3d.walking .host-stage::before { opacity: .58; width: 70%; transform: translateX(-50%) scale(.88); }
/* 转身：左右镜像。放中层，不跟内层的走路动画抢 transform。
   .34s 是站定时慢慢转；走起来要转得快一点（人转身是跟着第一步一起完成的，
   慢慢翻会看成"原地转圈再走"）。 */
.host3d.turned .host-stage { transform: scaleX(-1); }
.host3d.walking.turned .host-stage { transition-duration: .18s; }
/* 脚边那道落地光晕。落地那一下要跟着"踩实"亮一下 —— 影子一聚、光晕一闪，
   眼睛就会读成"脚落地了"，这是走路细节里最省力也最有效的一条。 */
.host-stage::after {
  content: ''; position: absolute; left: 8%; right: 8%; bottom: 2%;
  height: 46px; border-radius: 50%; z-index: 2;
  background: radial-gradient(ellipse at center, rgba(232,201,141,.20), transparent 72%);
  pointer-events: none;
  transition: opacity .7s var(--ease);
}
.host3d.walking .host-stage::after { animation: hostStamp var(--step, 378ms) linear both; }
@keyframes hostStamp {
  0%   { opacity: .55; transform: scaleX(1); }
  40%  { opacity: .3;  transform: scaleX(1.12); }   /* 抬起：光晕散开变淡 */
  78%  { opacity: .85; transform: scaleX(.9); }    /* 踩实：光晕聚拢最亮 */
  100% { opacity: .55; transform: scaleX(1); }
}

.host3d model-viewer {
  position: relative; z-index: 1;
  --progress-bar-color: var(--gold-soft);
}
/* 站着的时候轻轻起伏一下，像有呼吸 —— 站着不动的模型最像假的 */
.host3d.breathe model-viewer { animation: hostBreathe 4.4s ease-in-out infinite; }
@keyframes hostBreathe {
  0%, 100% { transform: translateY(0) scaleY(1); }
  50%      { transform: translateY(-1.4px) scaleY(1.004); }
}
/* 迈步：**一步一个完整循环**，不是连续颠簸。
   真人走一步的顺序是 —— 蹬地（重心换到支撑腿）→ 摆动（身体抬起、微前倾、胯往迈腿那侧倒）
   → 落地（脚踩实、身子最沉）→ 双支撑（站定一小下）。
   ① 时长 = JS 给的一整步（--step），其中前 78% 是「移动相」（对应外层那 78% 的位移），
      后 22% 是「落地顿」—— 脚已经踩实、人却不动，就是这一下把滑行变成了迈步。
   ② --lean 是这一脚迈的是哪条腿：JS 每步取反，胯就左右倒一次。
      之前只靠 .turned 镜像，看着像同一条腿来回蹬；加上胯的交替才有两条腿的感觉。
   ③ 关键帧 0% 和 100% 都是「踩实」姿态，所以每步重新触发时不会跳。 */
/* 🔴 选择器必须写成后代（.host-stage model-viewer）：model-viewer 是 .host-stage 的**子元素**，
   不是 .host3d 自己。原来写的 `.host3d.walking.model-viewer` 要求同一个元素
   同时具备这两个身份 ⇒ 永远匹配不上 ⇒ 这条走路动画其实**一次都没生效过**。
   她全程只有外层整体平移，没有起伏、没有胯的交替 —— 「像滑行」就是这么来的。 */
.host3d.walking .host-stage model-viewer { animation: hostStride var(--step, 378ms) linear both; }
@keyframes hostStride {
  /* 0% = 刚踩实 */
  0%   { transform: translate(0, 2.4px) rotate(0deg) scale(1, .990); }
  /* 蹬地：重心沉、胯往支撑腿那边压 —— 压得最深的一下 */
  14%  { transform: translate(calc(var(--lean, 1) * -2.2px), 3.4px) rotate(calc(var(--lean, 1) * .7deg)) scale(1.006, .983); }
  /* 摆动最高点：身体抬起、前倾、胯往迈出的腿那边倒 —— 抬得最高 */
  40%  { transform: translate(calc(var(--lean, 1) * 4.2px), -4.6px) rotate(calc(var(--lean, 1) * -1.7deg)) scale(.994, 1.022); }
  /* 下落 */
  66%  { transform: translate(calc(var(--lean, 1) * 1.8px), -1px) rotate(calc(var(--lean, 1) * -.6deg)) scale(.999, 1.006); }
  /* 78% = 落地，此刻位移刚好走完这一小格 */
  78%  { transform: translate(0, 3px) rotate(0deg) scale(1, .987); }
  /* 落地顿：脚踩实了，剩下 22% 只把身子从最沉处缓缓回正 —— 这一段人是不平移的 */
  89%  { transform: translate(0, .7px) rotate(0deg) scale(1, .998); }
  100% { transform: translate(0, 2.4px) rotate(0deg) scale(1, .990); }
}
/* 走的时候影子跟着一步一收一张：落地时聚拢、摆动时摊开，跟真实影子一个脾气。
   之前是一条 .7s 匀变，走完整程只变一次，等于没跟。 */
.host3d.walking .host-stage::before { animation: hostShadow var(--step, 378ms) linear both; }
@keyframes hostShadow {
  0%   { opacity: .62; width: 66%; transform: translateX(-50%) scale(.9); }
  40%  { opacity: .5;  width: 74%; transform: translateX(-50%) scale(1.02); }
  78%  { opacity: .68; width: 62%; transform: translateX(-50%) scale(.84); }
  100% { opacity: .62; width: 66%; transform: translateX(-50%) scale(.9); }
}

.host-loading {
  position: absolute; inset: 0; margin: 0; z-index: 3;
  display: flex; align-items: flex-end; justify-content: center; padding-bottom: 12px;
  font-size: 12px; letter-spacing: .18em; color: rgba(255,255,255,.5);
}

/* 气泡：她说的话。不点也在那儿，自己来自己走 */
.host-bubble {
  max-width: 268px; padding: 11px 16px;
  border-radius: 14px 14px 14px 4px;
  background: rgba(255,253,249,.95); color: var(--ink);
  font-size: 13.5px; line-height: 1.85; letter-spacing: .04em;
  box-shadow: 0 14px 34px rgba(20,14,8,.34);
  opacity: 0; transform: translateY(8px) scale(.97); transform-origin: bottom left;
  transition: opacity .45s var(--ease), transform .45s var(--ease);
  pointer-events: none;
}
.host-bubble.on { opacity: 1; transform: none; }
/* 走路时别说话：说话配走路太滑稽，气泡先收起来 */
.host3d.walking .host-bubble { opacity: 0; }

/* 手机：右侧那块被文案占满了，她就不出场了（也就不会走路）。
   「怎么拿到照片？」已经挪进封面那一排按钮里（见 index.html），
   所以藏掉她不会丢功能 —— 别再把按钮挂回她身上。 */
@media (max-width: 820px) {
  .host3d { display: none; }
}
/* 有人嫌晃就别晃：她站定不动，只是安静地在那儿 */
@media (prefers-reduced-motion: reduce) {
  /* 这两条必须和 .host3d.walking 同等特异性，否则迈步那条的 transition 会盖掉"不位移" */
  .host3d, .host3d.on, .host3d.walking, .host3d.walking.on { transition: opacity .9s var(--ease); }
  .host3d.breathe model-viewer,
  .host3d.walking model-viewer { animation: none; }
}


/* ---------- 聊天窗：问「小靴」任何事 ---------- */
.host-chat {
  position: fixed; inset: 0; z-index: 260;
  display: flex; align-items: center; justify-content: center; padding: 22px;
  background: rgba(16,12,9,.62);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  opacity: 0; transition: opacity .26s var(--ease);
}
.host-chat.on { opacity: 1; }
.hc-card {
  position: relative; width: min(420px, 100%);
  max-height: min(600px, 86vh); display: flex; flex-direction: column;
  padding: 0; border-radius: var(--radius); overflow: hidden;
  background: var(--card); border: 1px solid var(--line);
  box-shadow: 0 30px 70px rgba(20,14,8,.5);
  transform: translateY(12px) scale(.985); transition: transform .3s var(--ease);
}
.host-chat.on .hc-card { transform: none; }

.hc-head {
  display: flex; align-items: center; gap: 11px;
  padding: 15px 16px; border-bottom: 1px solid var(--line);
  background: linear-gradient(180deg, var(--paper-2), var(--card));
}
.hc-avatar {
  width: 36px; height: 36px; flex: none; border-radius: 50%;
  background: linear-gradient(145deg, var(--brand-deep), var(--brand));
  color: #fff; font-family: var(--serif); font-size: 17px; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 4px 12px rgba(160,100,50,.28);
}
.hc-avatar::after { content: "靴"; }
.hc-who { flex: 1; min-width: 0; line-height: 1.35; }
.hc-who b { display: block; font-size: 14.5px; letter-spacing: .08em; color: var(--ink); }
.hc-who span { display: block; font-size: 11px; letter-spacing: .06em; color: var(--faint); }
/* 「重新聊」：清空对话记忆，从头来。跟关闭按钮并排，样式刻意做轻，不抢关闭的视觉权重。 */
.hc-reset {
  flex: none; height: 30px; padding: 0 11px; border: 1px solid var(--line, rgba(0,0,0,.08));
  border-radius: 15px; background: transparent; color: var(--muted);
  font-size: 11.5px; letter-spacing: .06em; cursor: pointer; white-space: nowrap;
  transition: background .25s var(--ease), color .25s var(--ease), border-color .25s var(--ease);
}
.hc-reset:hover { background: var(--paper-2); color: var(--ink); border-color: transparent; }
.hc-close {
  flex: none; width: 30px; height: 30px; border: 0; border-radius: 50%;
  background: transparent; color: var(--muted); font-size: 14px; cursor: pointer;
  transition: background .25s var(--ease), color .25s var(--ease);
}
.hc-close:hover { background: var(--paper-2); color: var(--ink); }

.hc-msgs {
  flex: 1; min-height: 168px; overflow-y: auto; overscroll-behavior: contain;
  padding: 18px 16px 8px; display: flex; flex-direction: column; gap: 10px;
  scrollbar-width: thin;
}
.hc-msgs::-webkit-scrollbar { width: 5px; }
.hc-msgs::-webkit-scrollbar-thumb { background: var(--line); border-radius: 4px; }
.hc-msg {
  max-width: 82%; padding: 9px 13px; border-radius: 14px;
  font-size: 13.5px; line-height: 1.85; letter-spacing: .02em;
  word-break: break-word; white-space: pre-wrap;
  animation: hcIn .28s var(--ease) both;
}
@keyframes hcIn { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
.hc-msg.her {
  align-self: flex-start; border-top-left-radius: 4px;
  background: var(--brand-wash); color: var(--ink);
  border: 1px solid rgba(190,150,100,.22);
}
.hc-msg.me {
  align-self: flex-end; border-top-right-radius: 4px;
  background: var(--ink); color: var(--paper);
}
.hc-typing { align-self: flex-start; display: flex; gap: 4px; padding: 13px 15px; }
.hc-typing i {
  width: 5px; height: 5px; border-radius: 50%; background: var(--muted);
  animation: hcDot 1.1s infinite ease-in-out;
}
.hc-typing i:nth-child(2) { animation-delay: .16s; }
.hc-typing i:nth-child(3) { animation-delay: .32s; }
@keyframes hcDot { 0%, 60%, 100% { opacity: .28; transform: translateY(0); } 30% { opacity: 1; transform: translateY(-3px); } }

/* ---- 访客档案（2026-10-05）：左边人、右边他跟小语的一整本对话 ---- */
.guest-wrap { display: grid; grid-template-columns: 330px 1fr; gap: 16px; align-items: start; }
.guest-list { max-height: 64vh; overflow: auto; }
.guest-row { padding: 12px 14px; border-bottom: 1px solid var(--line); cursor: pointer; transition: background .25s var(--ease); }
.guest-row:hover { background: var(--paper-2); }
.guest-row.on { background: var(--brand-wash); }
.g-top { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; font-size: 13.5px; word-break: break-all; }
.g-meta { color: var(--muted); font-size: 12px; margin-top: 5px; }
.g-words { color: var(--faint); font-size: 12px; margin-top: 6px; }

/* 账户管理按钮组（2026-05 加）：开通/取消会员、改称呼、删聊天、删账号 */
.g-manage { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.g-manage .btn.small { padding: 5px 12px; font-size: 12px; border-radius: 999px; }
.g-manage .btn[disabled] { opacity: .45; cursor: not-allowed; }
/* 🔴 必须显式改 background：`.btn.danger` 在上面定义了 background:#b91c3a，
   只覆盖 color 会变成「红底白字」，而我原来的意图是「白底红字」的次级危险按钮。 */
.g-manage .btn.danger { background: transparent; color: #b3402f; border-color: rgba(179,64,47,.4); }
.g-manage .btn.danger:hover { background: rgba(179,64,47,.08); }
.g-manage-msg { font-size: 12px; margin-top: 8px; min-height: 16px; }
.g-manage-msg.ok { color: #2f7a4d; }
.g-manage-msg.bad { color: #b3402f; }
/* 后台 · 积分流水（2026-10-07）
   站方在给一个人调积分之前，先要看得见他这些分是怎么来的 ——
   只看一个余额，没法判断「-500 那笔是他自己换的，还是被人误扣了」。 */
.g-pts-log {
  margin-top: 8px; border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--paper-3); padding: 6px 10px;
}
.g-pts-row {
  display: flex; align-items: baseline; gap: 10px;
  font-size: 12px; padding: 4px 0; border-bottom: 1px solid var(--line);
}
.g-pts-row:last-child { border-bottom: 0; }
.g-pts-note { flex: 1; min-width: 0; color: var(--ink-soft); }
.g-pts-at { flex: 0 0 auto; color: var(--faint); font-size: 11px; }
.g-pts-d { flex: 0 0 auto; font-family: var(--num); font-weight: 700; color: var(--ink-soft); }
.g-pts-d.plus { color: #2f7a4d; }
.g-pts-bal { flex: 0 0 auto; color: var(--faint); font-size: 11px; }
.g-pts-more { font-size: 11px; color: var(--faint); padding-top: 5px; }
/* 详情页的标签要按内容宽度显示，不能被父容器拉成整条横幅 */
.gd-user-tags { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 8px 0 2px; }
.gd-user-tags .tag { display: inline-block; width: auto; }

/* ---------- 会员面板（v54）---------- */
.mem-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 10px; margin: 14px 0 4px; }
.ms-card {
  background: var(--panel-2, rgba(127,127,127,.06));
  border: 1px solid var(--line, rgba(127,127,127,.18));
  border-radius: 12px; padding: 12px 14px;
}
.ms-v { font-size: 22px; font-weight: 800; line-height: 1.1; color: var(--text); }
.ms-l { font-size: 12px; color: var(--muted); margin-top: 4px; font-weight: 600; }
.ms-t { font-size: 11px; color: var(--faint); margin-top: 3px; line-height: 1.4; }
.ms-card.ms-main { border-color: rgba(47,122,77,.45); }
.ms-card.ms-main .ms-v { color: #2f7a4d; }
.ms-card.ms-money .ms-v { color: #b3402f; }
.ms-card.ms-gift { border-color: rgba(127,127,127,.3); }
/* 待开通是最该先处理的，给它一个显眼的底色 */
.ms-card.ms-warn { border-color: rgba(185,28,58,.5); background: rgba(185,28,58,.07); }
.ms-card.ms-warn .ms-v { color: #b91c3a; }

.mem-filter { display: flex; flex-wrap: wrap; gap: 8px; margin: 14px 0 2px; }
.mem-filter .mf {
  padding: 6px 14px; border-radius: 999px; font-size: 12px; font-weight: 600;
  border: 1px solid var(--line, rgba(127,127,127,.25));
  background: transparent; color: var(--muted); cursor: pointer; transition: .18s;
}
.mem-filter .mf:hover { color: var(--text); border-color: var(--brand); }
.mem-filter .mf.on { background: var(--brand); color: #fff; border-color: var(--brand); }

.mem-row { padding: 12px 14px; border-bottom: 1px solid var(--line, rgba(127,127,127,.14)); }
.mem-row:last-child { border-bottom: 0; }
.mem-row.ms-row-off { opacity: .68; }
.mem-row.ms-row-wait { background: rgba(185,28,58,.05); }
.m-top { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.m-top b { font-size: 14px; }
.m-top .tag { display: inline-block; width: auto; }
.m-meta { color: var(--muted); font-size: 12px; margin-top: 6px; }
.m-note { color: var(--faint); font-size: 12px; margin-top: 5px; font-style: italic; }
.m-act { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.m-act .btn.small { padding: 5px 12px; font-size: 12px; border-radius: 999px; }
/* 🔴 .btn.danger 已被定义成红底白字，次级危险按钮要显式把背景透明掉 */
.m-act .btn.danger { background: transparent; color: #b3402f; border-color: rgba(179,64,47,.4); }
.m-act .btn.danger:hover { background: rgba(179,64,47,.08); }
.m-sub { padding: 14px 14px 6px; font-size: 12px; font-weight: 700; color: var(--muted); }
.gd-cols { display: grid; grid-template-columns: 1.15fr .85fr; gap: 16px; align-items: start; }
.gd-cols h4 { font-size: 13px; letter-spacing: .12em; color: var(--muted); margin: 0 0 8px; font-weight: 600; }
.gt-log {
  max-height: 56vh; overflow: auto; padding: 12px; background: var(--paper-2);
  border-radius: 12px; display: flex; flex-direction: column; gap: 8px;
}
.gt-msg {
  max-width: 86%; padding: 8px 11px; border-radius: 12px;
  font-size: 13px; line-height: 1.8; white-space: pre-wrap; word-break: break-word;
}
.gt-msg.her { align-self: flex-start; background: var(--brand-wash); border: 1px solid rgba(190,150,100,.22); }
.gt-msg.me { align-self: flex-end; background: var(--ink); color: var(--paper); }
.gt-msg i { display: block; font-style: normal; font-size: 10.5px; opacity: .5; margin-top: 3px; }
.gt-orders { font-size: 13px; }
.gt-orders .g-item { padding: 10px 0; border-bottom: 1px dashed var(--line); }
.gt-orders .g-item:last-child { border-bottom: 0; }
@media (max-width: 900px) {
  .guest-wrap, .gd-cols { grid-template-columns: 1fr; }
  .guest-list, .gt-log { max-height: none; }
}

/* 没留名字时，她在窗里摆的那张引导条 + 一枚去留名字的按钮。
   用她自己的口气请，不用弹窗、不用红字报错。 */
.hc-msg.hc-gate { background: var(--paper-2); border-style: dashed; }
.hc-gate-btn {
  align-self: flex-start; margin: 6px 0 4px;
  display: inline-block; padding: 9px 18px; border-radius: 999px;
  background: var(--brand); color: #fff; text-decoration: none;
  font-size: 13px; letter-spacing: .12em;
  box-shadow: 0 8px 22px rgba(169,85,31,.24);
  transition: transform .3s var(--ease), filter .3s var(--ease);
}
.hc-gate-btn:hover { transform: translateY(-2px); filter: brightness(1.1); }

/* 称呼栏（2026-10-05）：她当面叫他什么 + 「她记不记得住」。
   会员才记事，所以这行同时也是会员权益的提示位，登录后才出现。 */
.hc-namebar {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin: 6px 16px 0; padding: 8px 12px;
  border: 1px solid var(--line); border-radius: 12px;
  background: var(--paper-2);
  font-size: 12px; letter-spacing: .04em; color: var(--muted);
}
.hc-name-l { opacity: .75; }
.hc-namebar b { color: var(--brand); font-size: 13px; letter-spacing: .08em; }
.hc-rename {
  border: 1px solid var(--line); background: transparent; color: var(--muted);
  border-radius: 999px; padding: 3px 10px; font-size: 11px; cursor: pointer;
  font-family: inherit; transition: all .24s var(--ease);
}
.hc-rename:hover { color: var(--brand); border-color: var(--brand); }
.hc-mem { margin-left: auto; opacity: .8; }
.hc-mem.on { color: var(--brand); opacity: 1; }

.hc-chips { display: flex; flex-wrap: wrap; gap: 7px; padding: 10px 16px 4px; }
.hc-chips button {
  border: 1px solid var(--line); background: var(--paper-2); color: var(--muted);
  border-radius: 999px; padding: 6px 12px; font-size: 12px; letter-spacing: .04em;
  cursor: pointer; font-family: inherit;
  transition: all .24s var(--ease);
}
.hc-chips button:hover { border-color: var(--brand); color: var(--brand-deep); background: var(--brand-wash); }

.hc-input {
  display: flex; gap: 8px; padding: 12px 16px 15px;
  border-top: 1px solid var(--line); background: var(--card);
}
.hc-input input {
  flex: 1; min-width: 0; height: 38px; padding: 0 13px;
  border: 1px solid var(--line); border-radius: 999px;
  background: var(--paper-2); color: var(--ink);
  font-size: 13.5px; font-family: inherit; outline: none;
  transition: border-color .24s var(--ease), background .24s var(--ease);
}
.hc-input input::placeholder { color: var(--faint); }
.hc-input input:focus { border-color: var(--brand); background: var(--card); }
.hc-send {
  flex: none; width: 38px; height: 38px; border: 0; border-radius: 50%;
  background: var(--brand-deep); color: #fff; font-size: 15px; cursor: pointer;
  transition: transform .22s var(--ease), opacity .22s var(--ease);
}
.hc-send:hover { transform: scale(1.06); }
.hc-send:disabled { opacity: .45; cursor: default; transform: none; }

/* 手机：改成从底部升起的抽屉，不挡住整屏 */
@media (max-width: 560px) {
  .host-chat { align-items: flex-end; padding: 0; }
  .hc-card {
    width: 100%; max-height: 82vh; border-radius: 18px 18px 0 0;
    border-bottom: 0; transform: translateY(100%);
  }
  .host-chat.on .hc-card { transform: none; }
  .hc-msgs { min-height: 210px; }
}

/* 矮屏（笔记本合盖、老显示器）：舞台压扁一档，保证她从头到脚还在画面里。
   ⚠️ 只能压高度不能压宽度——压窄了她就会被切掉两侧，完整性优先。
   🔴 2026-10-06 修遮挡：原来 top 写 clamp(60px,7.6vh,80px)，可 1366×768 实测导航底 70px，
   她的气泡顶只有 60px —— 往上顶进导航 10px，「你来啦」压在「目录/会员」那一排下面。
   压高度是对的，压 top 是压错了地方（省下的高度已经从 height 里出了）。
   现在 top 只做「不低于导航 + 呼吸位」，高度照旧压扁。
   🔴 下限 96 → 124：字幕搬到她头顶后，得再给她留出字幕那条的高度。 */
@media (max-height: 780px) and (min-width: 821px) {
  /* 改宽度 = 改 --host-w（别直接写 width，字幕会跟着偏） */
  .cover { --host-w: clamp(168px, 13vw, 208px); }
  .host3d { top: max(124px, 7.6vh); }
  .host-stage { height: clamp(272px, 38vh, 320px); }
}

/* 🔴 2026-10-06 修遮挡（矮屏）：封面 min-height:100vh，可内容装不下时封面会比视口高 ——
   实测 1366×660 封面高 778px、超出视口 118px，锚在封面底部的「全部目录」胶囊
   就整颗掉到首屏外面去了（顶 662 > 视口 660），要往下滚才看得见。
   根因是竖排文字块太高（实测占 725px），把整屏顶满了。
   矮屏上把文字收紧一档：上下留白、标题字号、导语行距一起收，
   让内容装进一屏，胶囊自然回到屏内 —— 不是去改胶囊位置糊弄过去。 */
@media (max-height: 820px) and (min-width: 821px) {
  .cover-inner { padding: 104px 24px clamp(30px, 5vh, 46px); }
  .cover .display { font-size: clamp(38px, 5.4vw, 68px); }
  .cover-lede { margin-top: 18px; line-height: 1.75; }
  .cover-actions { margin-top: 24px; }
  .cover-scale { margin-top: 14px; }
  .cover { --cat-b: clamp(30px, 5vh, 52px); }
}


/* ---------------- 会员徽标（2026-10-05）----------------
   会员的价值原来只在后台结算时体现，前台一点痕迹都没有 ——
   付了 100 开通，页面上看到的还是原价，等于白付。
   现在价格旁边挂一枚小徽标，并让原价带删除线，形成「省到了」的直观感受。
   铁律照旧：这里只出现「半价」两个字，绝不出现「价格/购买/付款/下单」。 */
.vip-tag {
  display: inline-block; vertical-align: middle; margin-left: 10px;
  padding: 3px 10px; border-radius: 999px;
  font-family: var(--sans); font-size: 11px; letter-spacing: .16em;
  color: var(--brand); border: 1px solid var(--brand); opacity: .85;
  white-space: nowrap;
}
/* 价格里的删除线原价：小一号、淡一点，不抢主价 */
.price s, .u-price s, .bd-l s, .b-price s, .a-price s { text-decoration-thickness: 1px; }
/* 会员价本体：跟原价同一个字号，靠颜色区分，不靠加大字号（文案铁律：不加大字号） */
.price b, .u-price b, .bd-l b { font-weight: 700; }

/* ---------------- 导航里的「我的」（2026-10-06）----------------
   注册之后的所有东西（会员、小语的记忆、领取记录）都挂在"我是谁"上，
   可原来导航里没有入口 —— 登录了也找不着自己去哪看。
   会员那颗金点是从导航栏就能看见的身份，不是藏在某个页面里。 */
.nav-links .nav-me.vip { color: var(--gold); font-weight: 700; }
.nav-links .nav-me.vip::before {
  content: ''; display: inline-block; width: 5px; height: 5px; border-radius: 50%;
  background: var(--gold); margin-right: 6px; vertical-align: middle;
}
/* 导航上那枚积分小标（2026-10-07）。
   「我的」两个字里藏着一个能攒能换的东西，谁也不会点进去发现 ——
   摆一枚「120 分」在导航上，人才知道有这回事。 */
.nav-links .nav-me .nav-pts {
  font-style: normal; font-size: 11px; letter-spacing: .04em;
  padding: 1px 7px; border-radius: 99px; margin-left: 6px;
  background: rgba(198,161,91,.14); color: var(--brand); white-space: nowrap;
}
/* 窄屏导航本来就挤，积分小标先让位（身份还在，只是不在这条小字上重复一遍） */
@media (max-width: 640px) {
  .nav-links .nav-me .nav-pts { display: none; }
}

/* ---------------- 「我的」页 · 会员卡 / 代建提示 ---------------- */
.me-vip {
  margin-top: 14px; padding: 14px 16px; border-radius: var(--radius-lg);
  border: 1px solid var(--line-strong); background: var(--brand-wash);
  display: flex; flex-direction: column; gap: 4px;
  font-size: 13.5px; line-height: 1.8; color: var(--ink-soft);
}
.me-vip b { font-family: var(--serif); font-size: 15px; letter-spacing: .06em; color: var(--ink); }
.me-vip.on { border-color: var(--gold); }
.me-vip.off { background: var(--paper-2); }
.me-vip .btn { align-self: flex-start; margin-top: 8px; }
.me-warn {
  margin-top: 12px; padding: 12px 14px; border-radius: var(--radius);
  border: 1px solid #e2b7a6; background: #fdf1ec; color: #7a3512;
  font-size: 13px; line-height: 1.75;
}
.me-warn b { display: block; margin-bottom: 2px; font-size: 13.5px; }

/* ---------------- 系列页付费墙提示（2026-10-06）----------------
   非会员在一卷里只翻得到前几套，剩下的不能一声不吭地藏掉 ——
   要明说"还有多少套"、怎么才能翻，不然看起来像这一卷本来就只有几套。 */
.scene-lock {
  display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
  margin: 6px 0 34px; padding: 18px 20px;
  border: 1px dashed var(--brand-line); border-radius: var(--radius-lg);
  background: var(--brand-wash);
}
.scene-lock .sl-l { flex: 1 1 260px; display: flex; flex-direction: column; gap: 4px; }
.scene-lock b { font-family: var(--serif); font-size: 16px; letter-spacing: .06em; color: var(--ink); }
.scene-lock span { font-size: 13px; color: var(--muted); line-height: 1.8; }

/* ---------------- 封面人物头顶：滚动字幕（2026-10-06）----------------
   一条竖着往上滚的「刚刚 ××开通了会员」。
   🔴 2026-10-06 按要求挪位置：从**左上空白**改到**3D 迎宾员头顶正上方**，
   跟她站成一列（头像 + 头顶字幕），不再孤零零扔在左上角。

   位置是算出来的，不是拍的：
   - 人物 .host3d 原来 top 96px（= 导航底 70 + 26 呼吸位），
     而导航底 70 到 96 之间只有 26px —— 塞不下 36px 高的字幕。
     所以顺序必须反过来：**先把她下移 28px 让出头顶，再把字幕放进这条 28px 的口子里**。
   - 字幕水平以「人物中心线」对齐，不是贴右边。用 left:100% - right - width/2
     再 translateX(-50%)，因为 .cover-ticker 宽度随文案变（nowrap+省略号），
     只有锚人物中心才不会宽窄不一地飘。同理 .swap 那条也要补上 translateX(-50%)，
     否则换句时整条会往左跳 100 多像素。
   - 宽度上限 340px：她头顶那片除了字幕没别的，宽一点不压任何东西；
     但也别太宽，否则在 1920 上左缘会伸到主标题那一带去。 */
.cover-ticker {
  position: absolute; z-index: 6;
  /* 按「人物中心线」对齐，而不是贴右边。--host-w 是 .cover 上的变量，
     人物和这条字幕共用同一个宽度 ⇒ 任何屏宽下都严丝合缝，不用再抄一遍 clamp。
     之所以用 left + translateX(-50%) 而不用 right：字幕宽度随文案变（nowrap+省略号），
     只有锚中心才不会宽窄不一地飘。 */
  left: calc(100% - clamp(22px, 4.5vw, 76px) - var(--host-w, clamp(188px, 14.5vw, 238px)) / 2);
  top: 76px;                       /* 导航底 70 + 6 */
  transform: translateX(-50%);
  display: flex; align-items: center; gap: 9px;
  /* 宽度上限 —— 必须**按可用空间算**，不能拍脑袋写死。
   字幕是 translateX(-50%) 居中于「人物中心线」，而人物中心离右边缘只剩
   「人物右边距 + 半个身位」。1180 宽时实测人物中心在 x1033，右边缘 1180，
   只剩 147px ⇒ 宽度上限 294 就顶出去了（公网实测右缘 1183，超 3px）。
   推导：中心到右边缘 = right + --host-w/2，两边对称 ⇒ 上限 = 2×(right + w/2) − 两侧留白。
   🔴 随文案长度变的是实际宽度，上限管的是**最坏情况** ⇒ 这一条必须算，不能靠截断碰运气。
   ⚠️ 写成含 clamp/var 的算式后，矮屏那档改 --host-w 就自动跟着收窄，不必再手抄一份。 */
  max-width: min(340px, calc(clamp(22px, 4.5vw, 76px) * 2 + var(--host-w, clamp(188px, 14.5vw, 238px)) - 16px));
  padding: 7px 15px 7px 13px;
  border: 1px solid rgba(232, 201, 141, .28); border-radius: 999px;
  background: rgba(23, 19, 15, .38);
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  color: rgba(255, 255, 255, .9);
  font-size: 12.5px; letter-spacing: .04em; line-height: 1.5;
  overflow: hidden;
  transition: opacity .5s var(--ease), transform .5s var(--ease);
}
/* 换句的那一下：淡出并微微上移，像从底下顶上来一条。
   🔴 translateX(-50%) 必须跟 .cover-ticker 主规则那条一模一样 ——
   少了它，换句瞬间整条字幕会往左跳半个身位（实测约 170px），看着像闪了一下。 */
.cover-ticker.swap { opacity: 0; transform: translateX(-50%) translateY(-9px); }
.cover-ticker .tk-label {
  flex: none; padding: 2px 8px; border-radius: 999px;
  background: rgba(200, 153, 74, .9); color: #17130f;
  font-size: 10.5px; font-weight: 700; letter-spacing: .16em;
}
.cover-ticker .tk-view {
  display: block; min-width: 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cover-ticker .tk-dot {
  flex: none; width: 5px; height: 5px; border-radius: 50%;
  background: var(--gold-soft); animation: tkBlink 2.6s var(--ease) infinite;
}
@keyframes tkBlink { 0%, 100% { opacity: .28; } 50% { opacity: 1; } }

/* 矮屏：人物下移到 124，字幕那条也跟着收到 74，别让她俩在矮屏上贴太紧 */
@media (max-height: 820px) and (min-width: 821px) {
  /* 🔴 这里只调字号和 top，**不再写 max-width**。
     宽度上限由主规则那条算式统一管（它读 --host-w，矮屏改过 --host-w 会自动跟着收窄）。
     原来这条写死 300px，正是公网 1180×820 右缘超 3px 的原因：
     主规则的 42vw 在 1180 宽下算出 495，min() 取 300 —— 300 比可用 294 大，超了。 */
  .cover-ticker { top: 74px; font-size: 12px; }
  /* 矮屏上文字块整体上移（实测 1366×660 标题顶 188），字幕别压到标题上去 */
  @media (max-height: 720px) { .cover-ticker { display: none; } }
}
/* 手机：右上角归导航和胶囊了，字幕改到标题上方当一条窄条。
   不显示也不影响页面，但这里保留是因为它在矮机上是唯一还在动的提示。 */
@media (max-width: 860px) {
  .cover-ticker {
    top: auto; right: auto; left: 16px;
    bottom: calc(18px + 57px + 12px);       /* 让开底部那条目录胶囊通栏 */
    max-width: min(340px, calc(100% - 32px));
    font-size: 12px; padding: 6px 13px;
    /* 🔴 2026-10-07 修手机端字幕整条跑出屏幕（实测 390px 左缘 x=-80，文案被裁掉半截）。
       主规则那条 transform: translateX(-50%) 是给桌面「锚人物中心线」用的；
       这条媒体查询只改了 left/top/right/bottom，没把它撤掉 —— left:16 再左移半个宽度就出屏了。 */
    transform: none;
  }
  /* 换句动画那条也必须同步去掉 -50%，否则每次换句整条要往右跳半个身位 */
  .cover-ticker.swap { transform: translateY(-9px); }
  .cover-ticker .tk-label { font-size: 10px; padding: 2px 7px; }
}
/* 极窄屏：文案长，省略号比换行把布局撑破好 */
@media (max-width: 380px) {
  .cover-ticker { font-size: 11.5px; }
}

/* ================= 全站 3D 迎宾员浮层（2026-10-06）================
   以前她只在首页封面右下角，进了别的页面就没了。现在她每个页面都在。

   三个位置讲究：
   ① **fixed 跟视口**，不跟文档 —— 往下滚相册时她一直站在屏幕右下角，
      不用追着页面跑（absolute 的话她会被滚出画面，等于白做）。
   ② **压角不压内容**：右下角 + 缩到 0.72 倍。相册网格是通栏的，
      她只占一小块，且页面底部本来就有一圈留白。
   ③ **可一键收起**：小圆钮永远在，她缩起来只留一颗「问问她」，
      不喜欢的人点一下就没，不挡任何东西。
   ⚠️ 手机上她不出场（display:none）：屏本来就窄，一个 3D 模型
      加一个「问问她」钮会把商品图挤到没地方摆；首页那句「怎么拿到照片？」
      按钮在手机上照样点得到（index.html:v35 的设计），不丢入口。 */
.host-float {
  position: fixed; right: clamp(10px, 2.2vw, 26px); bottom: clamp(10px, 2.4vh, 26px);
  z-index: 120;                 /* 比页面内容高，比聊天模态(260)低 */
  opacity: 0; transition: opacity .7s var(--ease);
  pointer-events: none;         /* 整块默认不吃事件，只有她和按钮吃 */
}
.host-float.on { opacity: 1; }
.host-float > * { pointer-events: auto; }

/* 缩到 0.72：她在首页是主角，在别的页面该是背景。
   🔴 margin 的负值原来给错了方向（-42px 右、-104px 下），
   把她往视口外推 ⇒ 实测 x 到 1456 > 视口 1440，人物被切掉一截。
   现在按「缩放后仍要完整落在容器内」来算：
   原宽 158 × 0.72 = 114，收掉的差值 = 44（右侧）/ 74（下方），
   负 margin 就等于这部分差值 —— 她完整可见，且不留空白。 */
.host-float .host3d {
  position: static;             /* 覆盖 .host3d 的绝对定位，交给浮层排版 */
  width: 158px;
  transform-origin: bottom right;
  transform: scale(.72);
  /* 负 margin 必须等于「原宽 × (1 - scale)」：
     158 × 0.28 ≈ 44。之前写 -42 实测还超出 18px —— 差值算少了，
     而且 transform-origin 在右下时缩放是**贴着右边缘**缩的，
     右边那 44px 才是真正省出来的，左边本来就没占。
     这里直接按算式写死，别拍脑袋。 */
  margin: 0 -44px -74px 0;
}
/* 悬停时放大一点，像她察觉到你来了（不移动位置，只放大，不惊动布局） */
.host-float .host3d:hover { transform: scale(.76); transition: transform .4s var(--ease); }
.host-float .host-stage { height: 260px; }
.host-float .host-bubble { font-size: 12px; }

/* 收起态：一颗小圆钮。她不在了，入口还在。 */
.host-float-btn {
  position: relative; display: block;
  margin-left: auto;                    /* 靠右下角 */
  width: 46px; height: 46px; padding: 0;
  border-radius: 50%; cursor: pointer;
  border: 1px solid rgba(232, 201, 141, .5);
  background: rgba(23, 19, 15, .82);
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  color: var(--gold-soft);
  font-family: var(--serif); font-size: 12.5px; letter-spacing: .08em; line-height: 1.1;
  text-align: center;
  box-shadow: 0 10px 30px rgba(20, 14, 8, .4);
  transition: transform .35s var(--ease), background .35s var(--ease), border-color .35s var(--ease);
}
.host-float-btn:hover { transform: translateY(-3px) scale(1.05); background: rgba(200, 153, 74, .92); border-color: var(--gold-soft); color: #17130f; }
/* 她在的时候，这颗钮变成"叫她/收起"的意思 —— 两种状态一句话说清 */
.host-float-btn::after {
  content: attr(data-label);
  position: absolute; right: 54px; top: 50%; transform: translateY(-50%);
  padding: 5px 10px; border-radius: 999px; white-space: nowrap;
  background: rgba(23, 19, 15, .86); color: rgba(255, 255, 255, .88);
  border: 1px solid rgba(232, 201, 141, .28);
  font-family: var(--sans, inherit); font-size: 11.5px; letter-spacing: .06em;
  opacity: 0; pointer-events: none;
  transition: opacity .28s var(--ease);
}
.host-float-btn:hover::after { opacity: 1; }

/* 展开态把钮挪到她**旁边**（不是压在人物身上）。
   🔴 原来用 margin-top:-46px 想把钮藏进人物那块，结果钮的命中区
   被 model-viewer 整个盖住（实测 Playwright 报
   "model-viewer ... intercepts pointer events"，点第二下永远点不到）。
   现在：收起时钮在右下角；展开时钮上移到人物头顶左侧 —— 两个形态不重叠，
   点得着、也看得清「让她先走」这个动作在哪儿。 */
.host-float:not(.show) .host-float-btn { opacity: 1; }
.host-float.show .host-float-btn {
  margin: 0 0 8px auto;          /* 挪到人物上方，仍靠右 */
  opacity: .92;
}

/* 聊天窗从浮层里搬到了 body，这两条要跟着改回原来的居中定位 */
.host-float ~ .host-chat, body > .host-chat { inset: 0; }

/* 页脚收尾语 + 回到顶部那颗别和浮层叠着 */
@media (max-width: 860px), (max-height: 560px) {
  .host-float { display: none; }        /* 手机与横屏矮机不挂她 */
}

/* ============================================================================
   留言自动补充 · 后台面板（2026-10-06）
   ----------------------------------------------------------------------------
   这是「无人值守自动写库」的唯一可视化出口。站方不用碰服务器就能：
   看清现在是开是关、补了多少、每套分布成什么样，一键停下。
   数字要能对上才敢放着不管 —— 所以计数、分布、最近一轮都摆在明面上。
   ========================================================================== */
#noteFillBox .nf-top { display: flex; gap: 8px; flex-wrap: wrap; margin: 10px 0 12px; }
#noteFillBox .nf-nums {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(88px, 1fr));
  gap: 10px; margin-bottom: 12px;
}
#noteFillBox .nf-nums > div {
  padding: 10px 12px; border-radius: 12px;
  background: rgba(255,255,255,.05); border: 1px solid rgba(255,255,255,.10);
}
#noteFillBox .nf-nums b { display: block; font-size: 22px; line-height: 1.15; font-weight: 700; }
#noteFillBox .nf-nums span { display: block; margin-top: 3px; font-size: 12px; opacity: .68; }
#noteFillBox .nf-meta { font-size: 13px; line-height: 1.7; opacity: .82; }
#noteFillBox .nf-dist {
  margin-top: 8px; font-size: 12px; opacity: .7; line-height: 1.8;
  word-break: break-all;
}
#noteFillBox .nf-btns { display: flex; gap: 8px; flex-wrap: wrap; margin: 14px 0 4px; }
#noteFillBox .nf-out {
  margin-top: 10px; font-size: 13px; line-height: 1.8;
  max-height: 320px; overflow: auto;
}
#noteFillBox .nf-item {
  padding: 7px 0; border-top: 1px dashed rgba(255,255,255,.12);
  display: flex; gap: 8px; flex-wrap: wrap; align-items: baseline;
}
#noteFillBox .nf-tt { font-weight: 600; opacity: .9; }
#noteFillBox .nf-nn {
  padding: 1px 7px; border-radius: 999px; font-size: 12px;
  background: rgba(255,255,255,.09);
}
#noteFillBox .nf-at { font-size: 12px; opacity: .55; margin-left: auto; }
@media (max-width: 640px) {
  #noteFillBox .nf-at { margin-left: 0; width: 100%; }
}
/* 计数与实有数对不上时的提示条 —— 数据可信度问题必须自己说出来，不能装作没事 */
#noteFillBox .nf-warn {
  margin: 10px 0; padding: 9px 12px; border-radius: 10px; font-size: 13px; line-height: 1.7;
  background: rgba(255, 190, 90, .12); border: 1px solid rgba(255, 190, 90, .34);
}
