@font-face {
  font-family: 'Smiley Sans';
  src: url('../assets/fonts/smiley-sans-subset.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'ZCOOL GDH';
  src: url('../assets/fonts/zcool-gdh-subset.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
:root {
  /* 2026-09-26 换色：全站改用 StyleKit「Natural Organic」调色板（暖米白 / 深棕 / 鼠尾草）。
     原琥珀色系（#D97706 族）保留在阅读页 #readingPage 等局部。 */
  --c-primary: #5C4033;
  --c-primary-light: #8A7A6B;   /* 注意：它被用作**答题卡方框描边**（.q-box 的 2px border），
                                   属于"识别 UI 组件所必需的图形"，需 >= 3:1 —— #B9A899 只有
                                   2.14:1（旧值 #A8A29E 更差，2.4:1，是既存缺陷），故取 #8A7A6B = 3.77:1 */
  --c-primary-dark: #3F2D24;
  --c-accent: #5A6E45;
  --c-accent-deep: #5C4033;
  --c-accent-hover: #4A5C38;
  --c-accent-light: #E9E0D4;
  --c-bg: #FAF6F1;
  --c-bg-card: #FFFCF8;
  --c-bg-reading: #FDFAF6;
  --c-text: #292524;
  --c-text-secondary: #57534E;
  --c-text-muted: #6B5D52;
  --c-border: #E7E5E4;
  --c-success: #4F6B36;
  --c-danger: #A63D2A;
  --c-white: #FFFDFA;
  /* 顶栏下方那条浮动提示（.toast）：2026-09-28 用户要求 → 蓝色系 + 白色加粗字。
     ⚠️ 字改成白色后底色不能再用很浅的蓝：#DCEAF7 上白字只有 1.22:1（等于看不见）。
     取 #3F739F = 白字 5.04:1（达标里最浅的那个蓝），与顶栏那几颗按钮的分量也接近。 */
  --c-toast-bg: #3F739F;
  --c-toast-fg: #FFFFFF;
  --c-toast-bd: rgba(255,255,255,.18);
  --shadow-sm: 0 1px 2px rgba(0,0,0,.05);
  --shadow-md: 0 4px 16px rgba(0,0,0,.06), 0 1px 3px rgba(0,0,0,.04);
  --shadow-lg: 0 12px 32px rgba(0,0,0,.08), 0 2px 8px rgba(0,0,0,.04);
  --radius-sm: 10px;
  --radius-md: 18px;
  --radius-lg: 28px;
  --transition-fast: 120ms ease;
  --transition-normal: 200ms ease;
  /* 动效令牌（速记生词按钮层）：微交互统一走指数缓出，替代各处零散的 ease */
  --ease-out-quart: cubic-bezier(.25, 1, .5, 1);
  --ease-out-expo: cubic-bezier(.16, 1, .3, 1);
  --ease-in-quart: cubic-bezier(.7, 0, .84, 0);
  --t-press: 110ms;
  --t-state: 200ms;
  --t-swap: 240ms;
}
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: system-ui, -apple-system, 'Segoe UI', 'Microsoft YaHei', sans-serif; background: var(--c-bg); color: var(--c-text); min-height: 100vh; line-height: 1.6; -webkit-font-smoothing: antialiased; -webkit-tap-highlight-color: transparent; }
button { cursor: pointer; border: none; outline: none; font: inherit; transition: all var(--transition-fast); }
button:focus-visible { outline: 2px solid var(--c-accent); outline-offset: 2px; }
a { color: var(--c-accent); }

/* Home Page */
.home { display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: 100vh; padding: 80px 20px 60px; background: #F9F4EF; position: relative; overflow: hidden; }
.home::before { content: ''; position: absolute; inset: 0; z-index: 0; opacity: .9; pointer-events: none; background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 400 400' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.04'/%3E%3C/svg%3E"); }
.home::after { content: ''; position: absolute; top: -140px; left: 50%; transform: translateX(-50%); width: 760px; height: 480px; background: radial-gradient(closest-side, rgba(139,157,119,.10), transparent 70%); pointer-events: none; }
.home h1 { font-family: inherit; font-size: 3.4em; font-weight: 700; color: #5C4033; letter-spacing: .03em; margin-bottom: 10px; line-height: 1.15; }
.home-online { display: flex; align-items: center; justify-content: center; gap: 7px; margin: 0 0 12px; color: var(--c-success); font-size: .92em; letter-spacing: .03em; }
.ho-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--c-success); box-shadow: 0 0 0 0 rgba(79,107,54,.45); animation: hoPulse 2.2s infinite; flex-shrink: 0; }
@keyframes hoPulse { 0% { box-shadow: 0 0 0 0 rgba(79,107,54,.45); } 70% { box-shadow: 0 0 0 9px rgba(79,107,54,0); } 100% { box-shadow: 0 0 0 0 rgba(79,107,54,0); } }
@keyframes hoBreath { 0%,100% { transform: scale(1); } 50% { transform: scale(1.2); } }
.home-online .ho-num { font-weight: 700; color: var(--c-success); font-family: system-ui, -apple-system, 'Segoe UI', 'Microsoft YaHei', sans-serif; font-size: 1.05em; }
.cards { display: grid; grid-template-columns: repeat(2, 1fr); gap: 24px; max-width: 640px; width: 100%; margin-bottom: 34px; }
.cards.cards-exam { grid-template-columns: repeat(3, 1fr); max-width: 960px; gap: 22px; }
.cards-exam .card { padding: 28px 24px 26px; }
.cards-exam h2 { font-size: 1.1em; }
.cards-exam .card-badge { top: 10px; right: 12px; }
/* 导入题目的二级入口（2026-10-07 用户要求）：只有一张卡 → 单列、限宽、**居中** */
.cards.cards-import { grid-template-columns: 1fr; max-width: 420px; margin: 0 auto 34px; gap: 0; }
.cards-import .card { padding: 28px 24px 26px; }
.cards-import h2 { font-size: 1.1em; }
.cards-import .card-badge { top: 10px; right: 12px; }
/* ⚠️ 那三档「预览模式」的通用 .cards 规则带 !important（force-desktop 是 2 列 640）——
   不按同一优先级写一遍的话，强制电脑模式下这张卡会被塞进第 1 列、宽 320、偏左 160px（实测）。 */
@media (max-width: 768px) { .cards.cards-import { max-width: 340px; } }
html.force-desktop .cards.cards-import { grid-template-columns: 1fr !important; max-width: 420px !important; }
html.force-tablet .cards.cards-import { grid-template-columns: 1fr; max-width: 420px; }
html.force-phone .cards.cards-import { grid-template-columns: 1fr; max-width: 340px; }
html.force-tablet .cards.cards-import, html.force-phone .cards.cards-import { gap: 0; }
.card { width: 100%; padding: 30px 26px 28px; border-radius: var(--radius-lg); background: #FFFCF8; box-shadow: 0 1px 3px rgba(0,0,0,.04), 0 4px 12px rgba(0,0,0,.04); border: 1px solid rgba(120,113,108,.08); transition: all .35s cubic-bezier(.25,.8,.25,1); cursor: pointer; position: relative; overflow: hidden; }
.card::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px; transition: height .35s ease; }
.card.kaoyan::before { background: #72785E; }
.card.cet::before { background: #76928A; }
.card.gaokao::before { background: #7788B0; }
.card.basic::before { background: #B2AAA1; }
.card.story::before { background: #AF827A; }
.card:hover { transform: translateY(-4px); box-shadow: 0 8px 30px rgba(0,0,0,.08), 0 2px 8px rgba(0,0,0,.04); }
.card:hover::before { height: 5px; }
.card:hover.kaoyan { border-color: rgba(120,113,108,.25); }
.card:hover.cet { border-color: rgba(74,110,102,.25); }
.card:hover.gaokao { border-color: rgba(90,110,150,.25); }
.card:hover.basic { border-color: rgba(122,114,106,.25); }
.card:hover.story { border-color: rgba(140,95,88,.25); }
.card:hover.train { border-color: rgba(74,97,127,.25); }
.card .card-icon { width: 46px; height: 46px; border-radius: 18px; display: flex; align-items: center; justify-content: center; margin-bottom: 15px; transition: transform .35s ease; }
.card:hover .card-icon { transform: scale(1.08); }
.card.kaoyan .card-icon { background: #E9E0D4; color: #5C4033; }
.card.cet .card-icon { background: #E6ECEA; color: #4A6E66; }
.card.gaokao .card-icon { background: #E5EAF4; color: #5A6E96; }
.card.basic .card-icon { background: #EEEBE7; color: #7A726A; }
.card.story .card-icon { background: #F1E6E4; color: #8C5F58; }
.card h2 { font-family: 'Noto Serif SC', serif; font-size: 1.18em; font-weight: 700; color: var(--c-text); margin-bottom: 2px; letter-spacing: .02em; }
.card p { font-size: .8em; color: var(--c-text-muted); letter-spacing: .01em; }
.card .card-badge { position: absolute; top: 12px; right: 14px; font-size: .65em; font-weight: 600; padding: 2px 10px; border-radius: 100px; letter-spacing: .04em; }
.card.kaoyan .card-badge { background: #E9E0D4; color: #5C4033; }
.card.cet .card-badge { background: #E2EBE8; color: #4A6E66; }
.card.gaokao .card-badge { background: #E3E8F4; color: #5A6E96; }
.card.basic .card-badge { background: #EDEAE5; color: #7A726A; }
.card.story .card-badge { background: #F0E4E1; color: #8C5F58; }
.card.card-split { cursor: default; }
.card.card-split:hover { transform: translateY(-4px); }
.card .card-top { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; }
.card .card-top .card-icon { margin-bottom: 0; }
.card .card-title-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 2px; }
.card .card-title-row h2 { margin-bottom: 0; }
.csm-btn { border: none; background: transparent; padding: 6px 14px; border-radius: 100px; font-size: .72em; font-weight: 600; color: var(--c-text-muted); cursor: pointer; transition: all .25s ease; letter-spacing: .03em; line-height: 1.4; }
.csm-btn:hover { color: var(--c-text); }
.csm-btn.active { background: #fff; color: var(--c-accent-deep); box-shadow: 0 1px 4px rgba(0,0,0,.14), 0 2px 8px rgba(0,0,0,.06); }
.card.cet .csm-btn.active { color: #4A6E66; }
.card.gaokao .csm-btn.active { color: #5A6E96; }

@keyframes cardReveal { from { opacity: 0; transform: translateY(24px); } to { opacity: 1; transform: translateY(0); } }
.card:nth-child(1) { animation: cardReveal .5s .05s both; }
.card:nth-child(2) { animation: cardReveal .5s .15s both; }
.card:nth-child(3) { animation: cardReveal .5s .25s both; }
.card:nth-child(4) { animation: cardReveal .5s .35s both; }
/* 2026-10-17：原来只写到第 4 张，而「我的」页后来加到了 6 张（登录设备 / 账号安全 / 管理后台），
   第 5、6 张**没有动画** → 切到「我的」时前四张淡入错峰、后两张直接瞬现，看着"不对齐"。
   补齐 5、6，并给 n+7 兜底：以后再加卡也不会漏。 */
.card:nth-child(5) { animation: cardReveal .5s .45s both; }
.card:nth-child(6) { animation: cardReveal .5s .55s both; }
.card:nth-child(n+7) { animation: cardReveal .5s .65s both; }
@keyframes lbUtilIn { from { opacity: 0; translate: 0 16px; } to { opacity: 1; translate: 0 0; } }
/* 2026-09-24（用户要求把「选择宠物」入口挪到排行榜旁边）：排行榜卡从"通栏"改成**占两列**，
   第三列留给宠物卡。只在 3 列布局（>1024 / force-desktop）下这样排；2 列时它整行、宠物卡落到下一行，
   手机 1 列时两张都整行。⚠️ 别在 1 列布局里写 span 2 —— 会造出隐式列，把手机撑出横向滚动。 */

/* 工具区（首页「工具」区）的排布，2026-09-24 按用户要求调整过两次，结论如下：
   · 手机 ≤768px（1 列）：5 张卡各占整行。
   · 平板 769–1024px（**6 栏**）：上行三张工具卡（各 span 2）＋下行排行榜/宠物（各 span 3）= **两行**。
   · 桌面 ≥1025px（3 列）：三张工具卡一行，第二行排行榜（2 列）+ 宠物（1 列）。
   ⚠️ 为什么平板用 6 栏而不是 2 或 3 列：6 = 2×3，于是「span 2」在 1 列手机端就等于整行、「span 3」在 3 列桌面端就是半行，
   同一组跨列值三种布局都自洽，**不会造出隐式列**（1 列布局里写 span 2 会横向溢出，踩过）。
   ⚠️ 站内 .utility-row 的列数规则共 4 处（159 基础 / 手机断点 / 平板断点 / force-tablet），
   靠「源码顺序」决胜负太脆 —— 这里一律用 `.utility-row.utility-row` 提高特异性，加在哪都不会被盖掉。 */

/* 平板：6 栏两行 */
@media (min-width: 769px) and (max-width: 1024px) {          /* 排行榜 / 宠物：一行两张 */
}
.icp-footer { margin-top: 34px; text-align: center; display: flex; flex-direction: column; align-items: center; gap: 6px; }
.icp-footer a { font-size: .78em; color: var(--c-text-muted); text-decoration: none; transition: color var(--transition-fast); }
.icp-footer a:hover { color: var(--c-accent); }
.icp-footer .gongan { display: inline-flex; align-items: center; gap: 6px; }
.icp-footer .gongan img { width: 14px; height: 14px; vertical-align: middle; }
@media (prefers-reduced-motion: reduce) {
  .card{ animation: none !important; }
}

/* Top Bar */
.topbar { display: flex; align-items: center; justify-content: center; margin: 16px auto 0; padding: 8px 20px; background: rgba(255,255,255,.35); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px); box-shadow: 0 8px 32px rgba(0,0,0,.08); position: sticky; top: 12px; z-index: 10; gap: 8px; border: none; border-radius: 9999px; width: fit-content; max-width: calc(100% - 24px); }
.topbar .back svg, .topbar .info { filter: drop-shadow(0 1px 2px rgba(255,255,255,.8)); }
.topbar .info { text-shadow: 0 1px 2px rgba(255,255,255,.8); }
.topbar .back { background: none; font-size: 1.3em; padding: 6px 10px; color: var(--c-text-secondary); border-radius: var(--radius-sm); display: flex; align-items: center; }
.topbar .back:hover { background: #F5F5F4; color: var(--c-text); }
.topbar .back svg { width: 20px; height: 20px; }
.topbar .info { flex: 0 0 auto; font-weight: 600; color: var(--c-text); font-size: .95em; }
.topbar .btn { padding: 7px 16px; border-radius: var(--radius-sm); font-size: .82em; font-weight: 500; display: flex; align-items: center; gap: 5px; }
.topbar .btn-outline { background: var(--c-white); color: var(--c-primary); border: 1px solid var(--c-border); }
.topbar .btn-outline:hover { background: #F5F5F4; border-color: var(--c-primary-light); }
.topbar .btn-primary { background: var(--c-accent-deep); color: var(--c-white); }
.topbar .btn-primary:hover { background: var(--c-accent-hover); }
/* ── 顶栏头像旁：未登录显示绿色「登录」，登录后显示账号名 + 「退出」──────────────
   用户要求（2026-09-25）：未登录时头像旁要有绿色登录键。
   配色依据站内设计令牌 --c-success（绿）：
     亮色 #4F6B36 + 白字 = 4.99:1（过 AA 4.5:1）
     深色 #A3B98C + 深字 = 9.04:1
   （--c-success 原值 #4F6B36 白字只有 3.09:1，达不到正文标准，故用加深变体。）

   尺寸刻意对齐顶栏邻居（`.btn-donate` = 32px 高 / 圆角 100px / 0.78em / gap 6px），
   这样和「打赏 / 全屏 / 电脑」排在一起是同一套体系，而不是一个突兀的小方块。 */
.auth-login-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  height: 32px; min-height: 32px; padding: 0 14px; border-radius: 9999px;
  border: none !important; cursor: pointer; white-space: nowrap;
  font-size: .78em !important; font-weight: 600; letter-spacing: .02em; line-height: 1;
  color: #fff !important;
  background-image: none; background-color: #476624 !important;
  box-shadow: 0 1px 2px rgba(79,107,54,.22), 0 3px 10px -2px rgba(79,107,54,.32) !important;
  transition: transform .2s var(--ease-out-quart, cubic-bezier(.25,1,.5,1)),
              box-shadow .2s var(--ease-out-quart, cubic-bezier(.25,1,.5,1)),
              filter .2s var(--ease-out-quart, cubic-bezier(.25,1,.5,1));
}
.auth-login-btn svg { flex: none; width: 13px; height: 13px; }
.auth-login-btn:hover {
  transform: translateY(-1px); filter: brightness(1.07);
  box-shadow: 0 2px 4px rgba(79,107,54,.24), 0 8px 20px -4px rgba(79,107,54,.42) !important;
}
.auth-login-btn:active { transform: translateY(0) scale(.98); filter: brightness(1); }
.auth-login-btn:focus-visible { outline: 2px solid #4F6B36; outline-offset: 3px; }
html.dark .auth-login-btn {
  color: #12240A !important;
  background-image: none; background-color: #AEC296 !important;
  box-shadow: 0 1px 2px rgba(0,0,0,.3), 0 3px 12px -2px rgba(163,185,140,.35) !important;
}
html.dark .auth-login-btn:hover {
  box-shadow: 0 2px 4px rgba(0,0,0,.3), 0 8px 22px -4px rgba(163,185,140,.45) !important;
}
html.dark .auth-login-btn:focus-visible { outline-color: #B9CBA0; }
@media (prefers-reduced-motion: reduce) {
  .auth-login-btn, .auth-login-btn:hover, .auth-login-btn:active { transition: none; transform: none; }
}
/* 未登录态：头像 + 登录键（账号名与退出键藏起来） */
.auth-info.auth-guest .auth-username { display: none !important; }
/* 已登录态：隐藏登录键 */
.auth-info.auth-in .auth-login-btn { display: none !important; }
/* 账号名做成可点的胶囊，和「登录」的体量对齐（不然一进一出会跳一下） */
.auth-info .auth-username { padding: 0 2px; }
/* 头像 / 账号名 → 个人中心（2026-10-23 用户要求）：点击委托在 JS 侧，这里只给手型 */
.auth-info .auth-username, .auth-info > img { cursor: pointer; }
.topbar .btn-hot {
  transition: all .3s ease-in-out;
  border-radius: 100px;   /* 椭圆形（2026-09-27 用户要求；原 8px 圆角矩形） */
  /* 2026-09-27：暖黄渐变改为主题色令牌（用户要求阅读页跟随主题）。暗色由主题令牌自动跟随。 */
  background-image: linear-gradient(135deg, var(--c-accent) 0%, var(--c-accent-hover) 100%);
  background-color: transparent;
  box-shadow: 0 10px 20px -6px color-mix(in srgb, var(--c-accent) 50%, transparent);
  outline: none;
  cursor: pointer;
  border: none;
  color: var(--c-white);
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 34px;
  padding: 0 18px;
  font-size: .82em;
  font-weight: 600;
  letter-spacing: .01em;
}
.topbar .btn-hot:hover { transform: translateY(3px); box-shadow: none; background-image: linear-gradient(135deg, var(--c-accent) 0%, var(--c-accent-hover) 100%); }
.topbar .btn-hot:active { opacity: .5; }
.topbar .btn-hot svg { width: 15px; height: 15px; }

/* ── Username tooltip (Uiverse hover popup) ── */
.auth-username {
  position: relative;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 4px;
  text-decoration-color: #333;
  z-index: 1;
}
.auth-username::after {
  content: '点击查看个人信息';
  position: absolute;
  top: calc(100% + 10px);
  left: 50%;
  transform: translateX(-50%);
  background: #ffffff;
  color: #666;
  font-weight: 500;
  font-size: .75em;
  padding: .4em .9em;
  border-radius: 16px;
  box-shadow: 0 0 10px rgba(0,0,0,.1);
  white-space: nowrap;
  opacity: 0;
  visibility: hidden;
  transition: opacity .3s ease-in-out;
  z-index: 300;
  pointer-events: none;
}
.auth-username::before {
  content: '';
  position: absolute;
  top: calc(100% + 2px);
  left: 50%;
  transform: translateX(-50%);
  border: 7px solid transparent;
  border-bottom-color: #ffffff;
  opacity: 0;
  visibility: hidden;
  transition: opacity .3s ease-in-out;
  z-index: 300;
  pointer-events: none;
}
.auth-username:hover::after,
.auth-username:hover::before {
  opacity: 1;
  visibility: visible;
}

/* Main Layout */
.main-layout { display: flex; max-width: 1440px; margin: 0 auto; padding: 24px; gap: 24px; }
.reading-area { flex: 1; min-width: 0; background: var(--c-bg-reading); border-radius: var(--radius-md); padding: 30px 0 40px; box-shadow: 0 4px 20px rgba(0,0,0,.06), 0 12px 40px rgba(0,0,0,.08); border: 1px solid var(--c-border); }
.reading-area .title { font-size: 1.15em; font-weight: 700; margin-bottom: 20px; color: var(--c-primary-dark); padding: 0 40px 14px; border-bottom: 1px solid var(--c-border); letter-spacing: -.01em; display: flex; align-items: center; gap: 10px; }
.reading-area .title .rt-title-text { flex: 1; min-width: 0; }
.rt-btn { flex-shrink: 0; width: 34px; height: 34px; border-radius: 14px; border: none; padding: 0; background: #BBF7D0; cursor: pointer; position: relative; box-shadow: inset -1px 1px 4px 0px #F0FDF4, inset 1px -1px 4px 0px #4ADE80, -1px 2px 4px 0px #22C55E; }
.reading-area .title .rt-side { flex: 1; min-width: 0; position: relative; display: flex; justify-content: flex-end; }
/* ⚠️ 2026-10-09 修（用户报「Aa 点开后的窗口透明不可见」）：
   `.title` 自己是一个 `position:relative; z-index:1` 的**层叠上下文**，而正文容器 `#annotateWrap`
   同样是 `position:relative; z-index:1`，两者平级、按文档顺序**正文在后 → 正文压住标题这一层**。
   于是 `#rtPanel` 虽然写了 `z-index:60`，也只能在 `.title` 这层内部排序，**整个排版面板被正文盖住**：
   实测点面板正中，`elementFromPoint` 抓到的是正文的 `<p>` / `word`，面板收不到任何点击
   —— 用户看到的就是"透明的窗口、点不动"。把 `.title` 提到 20（高于正文的 1）即可让面板浮到最上层。
   实测：提层前 hitTest=`word`、hitInPanel=false；提层后 hitTest=`rt-dd-btn`、hitInPanel=true。 */
.reading-area .title { position: relative; z-index: 20; }
.rt-btn .rt-inner { position: absolute; left: 50%; top: 50%; width: 22px; height: 22px; transform: translate(-50%,-50%); border-radius: 9px; background: #DCFCE7; display: flex; align-items: center; justify-content: center; box-shadow: inset -1px 1px 4px 0px #F0FDF4, inset 1px -1px 4px 0px #4ADE80, -1px 1px 2px 0px #22C55E; transition: box-shadow 200ms; }
.rt-btn.open .rt-inner { box-shadow: inset 1px -1px 4px 0px #F0FDF4, inset -1px 1px 4px 0px #4ADE80; }
.rt-btn .rt-aa { font-family: 'Noto Serif SC', serif; font-size: 10px; font-weight: 700; color: #15803D; letter-spacing: .01em; transition: opacity 200ms; }
/* ⚠️ 2026-10-09 修：原来这里是 `.rt-btn.open .rt-aa { opacity:.35 }` —— 一点开排版面板，
   按钮里唯一的可视内容（Aa）就被压到 35% 不透明，用户看到的就是"**按钮变透明、像坏了**"。
   这条在 2.8.4 就存在（不是本轮加的），但确实是个坏设计：拿"变淡"表达"已打开"等于把可点目标抹掉。
   改成**明确的已打开反馈**：外圈实心描边 + 内层按下凹陷 + 底色提亮，**文字始终保持 100% 不透明**。
   两个排版按钮（文章页 #rtBtn、精读训练页 #trainRtBtn）共用这条，一处修两端好。 */
.rt-btn.open { background: #A7F3C8; box-shadow: inset -1px 1px 4px 0px #F0FDF4, inset 1px -1px 4px 0px #4ADE80, -1px 2px 4px 0px #22C55E; }
.rt-btn.open .rt-aa { opacity: 1; color: #14532D; }
.rt-btn:active { transform: translateY(1px); }
.rt-panel { position: absolute; top: calc(100% + 8px); right: 0; z-index: 60; width: 280px; background: var(--c-white); border: 1px solid var(--c-border); border-radius: 14px; box-shadow: 0 8px 30px rgba(0,0,0,.12), 0 2px 8px rgba(0,0,0,.06); padding: 16px; font-size: .82em; display: none; }
.rt-panel.show { display: block; }
.rt-row { margin-bottom: 14px; }
.rt-row:last-child { margin-bottom: 0; }
.rt-label { font-size: .78em; font-weight: 600; color: var(--c-text-muted); margin-bottom: 7px; letter-spacing: .06em; }
.rt-stepper { display: flex; align-items: center; gap: 8px; }
.rt-stepper button { width: 34px; height: 34px; border-radius: 12px; border: none; padding: 4px; cursor: pointer; background: linear-gradient(to bottom, #fff, rgba(231,229,228,.4)); box-shadow: 0 1px 3px rgba(0,0,0,.5); color: var(--c-text); font-size: .88em; font-weight: 600; transition: box-shadow .15s, transform .15s; }
.rt-stepper button .rt-step-inner { display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; border-radius: 8px; background: linear-gradient(to bottom, rgba(231,229,228,.4), rgba(255,255,255,.8)); }
.rt-stepper button:hover:not(:disabled) { color: var(--c-accent-deep, #A34909); }
.rt-stepper button:active:not(:disabled) { box-shadow: 0 0 1px rgba(0,0,0,.5); transform: scale(.995); }
.rt-stepper button:disabled { opacity: .35; cursor: not-allowed; }
.rt-stepper .rt-val { flex: 1; text-align: center; font-weight: 600; color: var(--c-text); font-variant-numeric: tabular-nums; }
.rt-opt { padding: 5px 11px; border-radius: 999px; border: 1px solid var(--c-border); background: var(--c-white); color: var(--c-text-secondary); font-size: .92em; cursor: pointer; transition: all var(--transition-fast); }
.rt-opt:hover { border-color: var(--c-accent); }
.rt-opt.sel { background: var(--c-accent); border-color: var(--c-accent); color: #fff; font-weight: 600; }
.rt-opt.mono { font-family: Consolas, Menlo, monospace; font-size: .86em; }
.rt-dd { position: relative; }
.rt-dd-btn { width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 7px 12px; border-radius: 8px; border: 1px solid var(--c-border); background: var(--c-white); color: var(--c-text); font-size: .95em; cursor: pointer; transition: all var(--transition-fast); }
.rt-dd-btn:hover { border-color: var(--c-accent); }
.rt-dd-btn .rt-dd-cur { font-family: inherit; }
.rt-dd-btn svg { width: 13px; height: 13px; flex-shrink: 0; transition: transform var(--transition-fast); color: var(--c-text-muted); }
.rt-dd.open .rt-dd-btn svg { transform: rotate(180deg); }
.rt-dd-menu { display: none; position: absolute; top: calc(100% + 6px); left: 0; right: 0; z-index: 70; border: 1px solid var(--c-border); border-radius: 10px; background: var(--c-white); box-shadow: 0 8px 28px rgba(0,0,0,.14), 0 2px 6px rgba(0,0,0,.06); overflow: hidden; max-height: 400px; overflow-y: auto; }
.rt-dd.open .rt-dd-menu { display: block; animation: rtDdIn .16s ease; }
@keyframes rtDdIn { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: translateY(0); } }
.rt-dd-item { display: block; width: 100%; text-align: left; padding: 8px 12px; border: none; background: none; color: var(--c-text); font-size: .95em; cursor: pointer; transition: background var(--transition-fast); }
.rt-dd-item:hover { background: var(--c-accent-light); }
.rt-dd-item.sel { color: var(--c-accent-deep); font-weight: 600; background: color-mix(in srgb, var(--c-accent) 12%, transparent); }
.rt-align-row { display: flex; gap: 6px; }
.rt-align-row .rt-opt { flex: 1; display: inline-flex; align-items: center; justify-content: center; padding: 5px 0; }
.rt-align-row .rt-opt svg { width: 15px; height: 15px; }
.rt-reset { margin-top: 14px; width: 100%; padding: 9px 0; border: none; border-radius: 100px; background-color: var(--c-accent); color: #ffffff; font-weight: 700; font-size: .9em; cursor: pointer; transition: all .5s; -webkit-transition: all .5s; }
.rt-reset:hover { background-color: var(--c-accent-hover); box-shadow: 0 0 20px color-mix(in srgb, var(--c-accent) 45%, transparent); transform: scale(1.1); }
.rt-reset:active { background-color: var(--c-accent-deep); transition: all .25s; -webkit-transition: all .25s; box-shadow: none; transform: scale(.98); }
.reading-area .instruction { color: var(--c-text-muted); font-size: .85em; margin: 0 40px 24px; padding: 10px 16px; background: var(--c-bg-card); border-left: 3px solid var(--c-accent); border-radius: 0 var(--radius-sm) var(--radius-sm) 0; }
.passage-body { padding: 0 40px; }
/* 完形填空空位（2026-09-27）：正文里的 \n(N)\n 渲染成可点的下划线空位。
   只用 --c-* 变量，暗夜模式自动跟随；不用硬编码颜色。 */
.cloze-blank { display: inline-block; min-width: 2.6em; margin: 0 .18em; padding: 0 .2em; text-align: center;
  /* text-indent: 0 必须有：.passage-body p 有 text-indent:2em（中文首行缩进），
     空位是 inline-block 会把它继承到自己的第一行 → 数字被推进去 ~33px、格子也被撑大，
     看起来就是「数字不在中间」（2026-09-27 用户提问后定位到的原因）。 */
  text-indent: 0;
  font-size: .82em; font-weight: 700; line-height: 1.5; color: var(--c-accent); cursor: pointer;
  border-bottom: 2px solid var(--c-accent); border-radius: 2px 2px 0 0;
  background: color-mix(in srgb, var(--c-accent) 10%, transparent); vertical-align: baseline;
  transition: background var(--transition-fast), transform var(--transition-fast); user-select: none; }
.cloze-blank:hover { background: color-mix(in srgb, var(--c-accent) 22%, transparent); }
.cloze-blank:active { transform: scale(.94); }
.cloze-flash { animation: clozeFlash 1.2s ease-out; }
@keyframes clozeFlash {
  0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--c-accent) 55%, transparent); }
  100% { box-shadow: 0 0 0 12px transparent; }
}
/* 已作答 / 看答案后的空位状态（2026-09-27） */
.cloze-blank.done { background: color-mix(in srgb, var(--c-accent) 20%, transparent); }
.cloze-blank.right { color: #15803D; border-bottom-color: #15803D; background: color-mix(in srgb, #15803D 14%, transparent); }
.cloze-blank.wrong { color: #B91C1C; border-bottom-color: #B91C1C; background: color-mix(in srgb, #B91C1C 14%, transparent); }
.cloze-blank .cb-ans { font-weight: 700; margin-left: .1em; }
.cloze-blank .cb-n { font-size: .68em; font-weight: 700; vertical-align: super; opacity: .75; margin-right: .1em; }
.cloze-blank .cb-ans.ok { color: #15803D; }
.cloze-blank .cb-ans.bad { color: #B91C1C; text-decoration: line-through; }
.cloze-blank .cb-arrow { color: var(--c-text-muted); font-size: .8em; margin: 0 .15em; }
/* 完形栏（进度 + 查看答案 / 重做）：吸在视口底部，滚正文时一直在 */
/* ── 四六级 Section A 选词填空（2026-10-02）：词库框 + 正文空位 + 弹层 ── */
.cb-bank { margin: 0 0 16px; padding: 12px 14px; background: var(--c-bg-card); border: 1px solid var(--c-border);
  border-radius: var(--radius-sm); }
.cb-bank-h { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-bottom: 8px; }
.cb-bank-t { font-size: .8em; font-weight: 700; color: #fff; background: var(--c-accent-deep);
  padding: 2px 10px; border-radius: 9999px; }
.cb-bank-n { font-size: .76em; color: var(--c-text-muted); }
.cb-bank-list { display: flex; flex-wrap: wrap; gap: 6px 10px; }
.cb-bank-item { font-size: .86em; color: var(--c-text-secondary); white-space: nowrap; }
.cb-bank-item b { display: inline-block; min-width: 15px; margin-right: 3px; color: var(--c-accent-deep); }
.cb-bank-item.used { opacity: .38; text-decoration: line-through; }
/* 正文段落：**首行缩进 2em + 双边对齐（两端对齐）**（2026-10-02 用户要求两次：先要首行缩进，再要两边对齐） */
.cb-body p.cb-p { margin: 0 0 12px; font-size: 1.02em; line-height: 1.85; text-align: justify; text-indent: 2em; color: var(--c-text); }
/* 空位（复用 .nt-blank 的三态样式，这里只补选词填空特有的宽度感） */
.cb-blank { min-width: 3.2em; }
.cb-blank .cb-n { font-size: .7em; font-weight: 700; color: var(--c-text-muted); margin-right: 3px; }
/* 词库弹层（自绘，避免依赖别处的浮层样式） */
.cb-pop { position: fixed; z-index: 300; width: 300px; max-width: calc(100vw - 16px); max-height: 62vh; overflow: auto;
  background: var(--c-white); border: 1px solid var(--c-border); border-radius: var(--radius-md);
  box-shadow: 0 10px 34px rgba(0,0,0,.16); padding: 10px; }
.cb-pop-h { font-size: .82em; font-weight: 700; color: var(--c-accent-deep); margin-bottom: 8px; }
.cb-pop-ana { font-size: .82em; line-height: 1.7; color: var(--c-text-secondary); background: #FBF8F3;
  border-radius: 10px; padding: 8px 10px; margin-bottom: 8px; }
.cb-pop-ana b { color: var(--c-accent-deep); margin-right: 4px; }
/* 卡片上只有字母 → 排成整齐的字母键盘（5 列），比一串长短不一的胶囊干净 */
.cb-pop-grid { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 6px; }
.cb-pop-item { font: inherit; font-size: .9em; font-weight: 700; padding: 6px 0; border-radius: 10px; cursor: pointer;
  border: 1px solid var(--c-border); background: #FFFCF8; color: #6B5D52; text-align: center;
  text-transform: uppercase; }
.cb-pop-item:hover { border-color: var(--c-accent); color: var(--c-accent-deep); }
.cb-pop-item.on { background: var(--c-accent-deep); border-color: var(--c-accent-deep); color: #fff; }
.cb-pop-item.right { background: #15803D; border-color: #15803D; color: #fff; }
.cb-pop-item.bad { background: #B91C1C; border-color: #B91C1C; color: #fff; }
.cb-pop-l { font-weight: 700; text-transform: uppercase; }
.cb-pop-foot { display: flex; gap: 8px; margin-top: 10px; }
.cb-pop-clear { font: inherit; font-size: .8em; padding: 5px 12px; border-radius: 100px; cursor: pointer;
  border: 1px solid var(--c-border); background: transparent; color: var(--c-text-muted); }
/* 没做完时「解析」置灰不可点（2026-10-02 用户要求） */
.cb-pop-clear:disabled { opacity: .4; cursor: not-allowed; }
html.dark .cb-pop-clear:disabled { opacity: .35; }
html.dark .cb-pop { background: #26221F; border-color: #3F3A37; }
html.dark .cb-pop-item { background: #2A2521; border-color: #3F3A37; color: #B5A797; }
html.dark .cb-pop-ana { background: #1E1B19; }
/* 揭示后的逐空答案与解析 */
.cb-ana { margin: 14px 0 0; padding: 12px 14px; background: color-mix(in srgb, var(--c-accent) 5%, var(--c-white));
  border-left: 3px solid color-mix(in srgb, var(--c-accent) 50%, transparent); border-radius: 0 var(--radius-sm) var(--radius-sm) 0; }
.cb-ana-h { margin: 0 0 8px; font-size: .84em; font-weight: 700; color: var(--c-accent-deep); }
.cb-ana-row { margin: 0 0 8px; font-size: .86em; line-height: 1.75; color: var(--c-text-secondary);
  text-indent: 0; text-align: left; }
.cb-ana-row:last-child { margin-bottom: 0; }
.cb-ana-row b { color: var(--c-accent-deep); margin-right: 4px; }
.cb-ana-w { display: inline-block; min-width: 90px; font-weight: 600; color: #15803D; }
.cb-ana-mine { color: #B91C1C; margin-right: 8px; }
.cb-ana-t { display: block; margin-top: 2px; }
html.dark .cb-ana { background: #221F1D; }
html.dark .cb-ana-w { color: #6EE7B7; }
html.dark .cb-ana-mine { color: #FCA5A5; }
/* 长篇阅读（Section B）：文章分段 + 字母槽 + 题项列表 */
.cm-title { margin: 0 0 12px; font-size: 1.06em; font-weight: 700; color: var(--c-text); text-indent: 0; text-align: left; }
.cm-article { margin: 0 0 18px; }
.cm-para { display: flex; gap: 10px; margin: 0 0 12px; }
.cm-letter { flex-shrink: 0; width: 22px; height: 22px; margin-top: 3px; text-align: center; line-height: 22px;
  font-size: .76em; font-weight: 700; color: #fff; background: var(--c-accent-deep); border-radius: 6px; }
.cm-para-body { flex: 1; min-width: 0; font-size: 1.02em; line-height: 1.85; color: var(--c-text);
  text-align: justify; text-indent: 2em; }   /* 双边对齐 + 首行缩进（2026-10-02 用户要求） */
.cm-qs { margin: 18px 0 0; padding: 14px 16px; background: var(--c-bg-card); border: 1px solid var(--c-border);
  border-radius: var(--radius-sm); }
.cm-qs-h { margin: 0 0 10px; font-size: .82em; font-weight: 600; color: var(--c-text-muted); text-indent: 0; text-align: left; }
.cm-item { display: flex; align-items: flex-start; gap: 8px; padding: 6px 0; border-top: 1px dashed var(--c-border); }
.cm-item:first-of-type { border-top: 0; }
.cm-num { flex-shrink: 0; min-width: 26px; padding-top: 2px; font-size: .84em; font-weight: 700; color: var(--c-accent-deep); }
.cm-slot { flex-shrink: 0; min-width: 2.2em; }
.cm-txt { flex: 1; min-width: 0; font-size: .94em; line-height: 1.7; color: var(--c-text); text-indent: 0; text-align: left; }
html.dark .cm-qs { background: #221F1D; border-color: #3A322C; }
html.force-phone .cm-para { gap: 8px; }
/* ── 四六级听力（2026-10-02）：整卷连做（8 组音频 + 25 题 + 可点跳转原文）── */
.ls-group { margin: 0 0 18px; padding: 14px 16px; background: var(--c-white); border: 1px solid var(--c-border); border-radius: var(--radius-sm); }
.ls-head { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin-bottom: 10px; }
.ls-sec { font-size: .76em; font-weight: 700; color: #fff; background: var(--c-accent-deep); padding: 2px 9px; border-radius: 9999px; }
.ls-kind { font-size: .94em; font-weight: 600; color: var(--c-text); }
.ls-nums { font-size: .78em; color: var(--c-text-muted); }
.ls-audio { width: 100%; height: 38px; margin: 2px 0 10px; }
.ls-acts { display: flex; align-items: center; gap: 10px; margin: 8px 0 2px; }
/* 「原文对照」在标题行里（接在「Section A · 短篇新闻 · 1–2 题」后面）：
   比标题文字小一号、淡一点，别抢标题；手机上允许换行到第二行。 */
.ls-head .ls-btn-head { margin-left: 2px; }
html.force-phone .ls-head .ls-btn-head { margin-left: 0; }
.ls-btn { font: inherit; font-size: .8em; font-weight: 600; padding: 6px 13px; border-radius: 9999px;
  border: 1px solid var(--c-border); background: #FFFCF8; color: #6B5D52; cursor: pointer; transition: all .15s ease; }
.ls-btn:hover { border-color: var(--c-accent); color: var(--c-accent-deep); }
.ls-btn.on { background: var(--c-accent-deep); border-color: var(--c-accent-deep); color: #fff; }
.ls-hint { font-size: .76em; color: var(--c-text-muted); }
.ls-trans { margin: 8px 0 2px; padding: 10px 12px; background: #FBF8F3; border-radius: 12px; max-height: 340px; overflow: auto; }
.ls-line { display: grid; grid-template-columns: 52px 1fr; gap: 4px 10px; padding: 4px 6px; border-radius: 8px; cursor: pointer; }
.ls-line:hover { background: rgba(217,119,6,.08); }
.ls-line.cur { background: color-mix(in srgb, var(--c-accent) 16%, transparent); }
.ls-t { font-size: .74em; color: var(--c-text-muted); font-variant-numeric: tabular-nums; padding-top: 2px; }
.ls-en { font-size: .9em; color: var(--c-text); line-height: 1.6; }
.ls-zh { grid-column: 2; font-size: .82em; color: var(--c-text-secondary); line-height: 1.6; }
.ls-qs { margin-top: 4px; }
/* ★ 听力题块是渲染在 `.passage-body` **里面**的（阅读页的题目区在它外面），
   于是正文那套排版会漏进来：`.passage-body p { text-indent:2em; text-align:justify;
   font-size:calc(1.02em*scale) }` → 题干/选项被**两端对齐**（英文单词之间被拉出大片空白）
   且首行缩进 2em（2026-10-02 用户报「题目的格式有问题」）。
   这里按题面该有的样子还原：左对齐、不缩进。字号由下面 .ls-qs 的规则接管。 */
.ls-qs p, .ls-group .q-stem, .ls-group .q-option { text-indent: 0; text-align: left; }
/* `.questions-section` 自带 `margin-top:36px + padding-top:24px + 1px 分隔线`（阅读页的规格），
   听力页 8 组连排时这 60px 纯属浪费 —— 组内压掉（播放器与题目贴紧、去掉那条线）。 */
.ls-group .questions-section { margin-top: 10px; padding-top: 0; border-top: 0; padding-left: 0; padding-right: 0; }
html.force-phone .ls-group .questions-section { margin-top: 8px; padding-top: 0; padding-left: 0; padding-right: 0; }
.ls-qs .question-block:last-child { margin-bottom: 0; }
/* 听力题目**做小一档**（2026-10-02 用户要求）：一组 2~4 题、整卷 8 组，按阅读页那套尺寸太占屏。
   只改听力（.ls-qs 作用域内），阅读页的题目块尺寸不受影响。 */
.ls-qs .question-block { padding: 10px 12px; margin-bottom: 10px; }
.ls-qs .q-stem { font-size: .92em; line-height: 1.6; margin-bottom: 4px; padding-left: 12px; padding-right: 40px; }
.ls-qs .q-stem .q-num { width: 20px; margin-top: 1px; }
.ls-qs .q-option { padding: 3px 8px; margin: 1px 0; font-size: .92em; line-height: 1.5; gap: 6px; }
.ls-qs .q-box { width: 19px; height: 19px; border-width: 1.5px; border-radius: 5px; margin-top: 1px; font-size: .68em; }
.ls-qs .q-my-ans { margin-top: 4px; font-size: .82em; }
.ls-qs .q-analyze-row { margin-top: 5px; padding-left: 12px; gap: 6px; }
.ls-qs .q-analyze-result { font-size: .9em; }
.ls-qs .ui-bookmark { transform: scale(.82); transform-origin: top right; }
/* 「答案 / 解析」**这一组的题做完才出现**（2026-10-23 用户要求：听一段就能对这一段答案，
   不再等整套 25 题）。未做完时整行 display:none，做完后由 lsGateRefresh() 给该组 .ls-group 加 .ls-done。 */
.ls-qs .q-analyze-row { display: none; }
.ls-group.ls-done .ls-qs .q-analyze-row { display: flex; }
.ls-btn:disabled { opacity: .45; cursor: default; }
.ls-btn:disabled:hover { border-color: var(--c-border); color: #6B5D52; }
.ls-gate { display: block; margin-top: 6px; font-size: .82em; color: var(--c-accent-deep); font-weight: 600; }
/* 听力吸底栏：`.cloze-bar / .cloze-tip` 自带 40px 左右外边距（完形是全宽正文版面），
   听力页在 `.passage-body` 内已有 40px 内边距 → 这里归零，否则会double缩进。 */
#lsBar { margin-left: 0; margin-right: 0; }
#lsTip { margin-left: 0; margin-right: 0; }
html.force-phone #lsBar { margin-top: 14px; padding: 9px 12px; gap: 10px; }
.ls-gate.ok { color: #036B4B; }
html.dark .ls-gate { color: #FBBF24; }
html.dark .ls-gate.ok { color: #6EE7B7; }
html.force-phone .ls-qs .question-block { padding: 9px 10px; margin-bottom: 9px; }
html.force-phone .ls-qs .q-stem { font-size: .9em; padding-right: 34px; }
html.dark .ls-group { background: #221F1C; border-color: #3A322C; }
html.dark .ls-btn { background: #2A2521; border-color: #3F3A37; color: #B5A797; }
html.dark .ls-btn.on { background: var(--c-accent-deep); border-color: var(--c-accent-deep); color: #fff; }
html.dark .ls-trans { background: #1E1B19; }
html.dark .ls-zh { color: #A8A29E; }
html.force-phone .ls-group { padding: 12px 12px; margin-bottom: 14px; }
html.force-phone .ls-line { grid-template-columns: 44px 1fr; gap: 2px 8px; }
@media (max-width: 768px) {
  .ls-group { padding: 12px 12px; }
  .ls-line { grid-template-columns: 44px 1fr; gap: 2px 8px; }
}
/* ── 听力「遮住题干」（2026-10-08 用户要求：默认遮住、点击显示；**每组 + 每题** 两级开关）──
   口径（同日用户两次澄清）：遮的是**题干**，**选项一直显示**（真实考试就是「选项印在卷面、
   问题靠听」）；遮法用**毛玻璃**——题干文字 blur 掉 + 罩一层半透明磨砂（backdrop-filter），
   罩子本身就是点击目标（写着「第 N 题 · 题干已遮住，点击显示」）；显示后题干行右侧出现「遮住」小钮。
   ⚠️ 文字 blur 与 backdrop-filter **两条都写**：前者保证任何浏览器都看不清，后者出毛玻璃质感。
   状态见 lsApplyQsUi()（内存、按套分记，刷新回默认遮住）。 */
.ls-stem-wrap { position: relative; }
.ls-stem-wrap.frost .q-stem { filter: blur(6px); opacity: .5; user-select: none; pointer-events: none; }
/* 显示态：题干本身可点（再点一下就重新遮住，2026-10-08 用户要求）——给个手型 + 淡底，点得明白 */
.ls-stem-wrap:not(.frost) .q-stem { cursor: pointer; }
.ls-stem-wrap:not(.frost) .q-stem:hover { background: rgba(217, 119, 6, .07); border-radius: 8px; }
.ls-frost { display: none; }
.ls-stem-wrap.frost .ls-frost {
  display: flex; align-items: center; position: absolute; inset: 0; z-index: 2; cursor: pointer;
  padding: 0 12px; border-radius: 10px; transition: background .15s ease;
  background: rgba(255, 252, 246, .42);
  backdrop-filter: blur(7px) saturate(1.2); -webkit-backdrop-filter: blur(7px) saturate(1.2);
  border: 1px solid rgba(255, 255, 255, .55); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .6);
}
.ls-stem-wrap.frost .ls-frost:hover { background: rgba(255, 243, 224, .72); border-color: var(--c-accent); }
.ls-frost-tip { font-size: .84em; font-weight: 600; color: #6B5D52; }
.ls-stem-hide { display: none; position: absolute; right: 44px; top: 0; z-index: 3; font: inherit; font-size: .74em;
  padding: 2px 9px; border-radius: 9999px; border: 1px solid var(--c-border); background: #FFFCF8;
  color: #6B5D52; cursor: pointer; }
.ls-stem-wrap:not(.frost) .ls-stem-hide { display: inline-block; }
.ls-stem-hide:hover { border-color: var(--c-accent); color: var(--c-accent-deep); }
html.dark .ls-stem-wrap.frost .ls-frost { background: rgba(30, 27, 25, .5); border-color: rgba(255, 255, 255, .12);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .06); }
html.dark .ls-stem-wrap.frost .ls-frost:hover { background: rgba(48, 42, 37, .72); }
html.dark .ls-frost-tip { color: #C9BFB2; }
html.dark .ls-stem-hide { background: #2A2521; border-color: #3F3A37; color: #B5A797; }
html.force-phone .ls-frost-tip { font-size: .8em; }
/* 手机档：「遮住」钮移到题干下方右对齐，不再压在题干第一行末尾（2026-10-11 用户报） */
@media (max-width: 768px) {
  .ls-stem-wrap:not(.frost) .ls-stem-hide { display: block; position: static; width: max-content; margin: 2px 0 4px auto; }
}
html.force-phone .ls-stem-wrap:not(.frost) .ls-stem-hide { display: block; position: static; width: max-content; margin: 2px 0 4px auto; }
/* ── 新题型（2026-09-27）：空位/段落/两栏/判断题 ── */
.nt-dir { margin: 0 0 16px; padding: 10px 14px; border-left: 3px solid var(--c-accent);
  background: color-mix(in srgb, var(--c-accent) 8%, transparent); border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  font-size: .88em; line-height: 1.6; color: var(--c-text-secondary); }
.nt-dir b { color: var(--c-accent-deep); margin-right: 6px; }
.nt-p { margin-bottom: 10px; }
.nt-blank { display: inline-block; min-width: 2.6em; margin: 0 .18em; padding: 0 .25em; text-align: center;
  text-indent: 0; font-size: .82em; font-weight: 700; line-height: 1.5; color: var(--c-accent); cursor: pointer;
  border-bottom: 1.5px solid var(--c-accent); border-radius: 3px 3px 0 0;
  background: color-mix(in srgb, var(--c-accent) 10%, transparent); transition: background .15s, transform .12s; }
.nt-blank:hover { background: color-mix(in srgb, var(--c-accent) 24%, transparent); }
.nt-blank:active { transform: scale(.95); }
.nt-blank.done { background: color-mix(in srgb, var(--c-accent) 20%, transparent); }
.nt-blank.right { color: #15803D; border-bottom-color: #15803D; background: color-mix(in srgb, #15803D 14%, transparent); }
.nt-blank.wrong { color: #B91C1C; border-bottom-color: #B91C1C; background: color-mix(in srgb, #B91C1C 14%, transparent); }
.nt-blank .cb-n { font-size: .68em; font-weight: 700; vertical-align: super; opacity: .75; margin-right: .1em; }
.nt-blank .cb-ans { font-weight: 700; margin-left: .1em; }
.nt-blank .cb-ans.ok { color: #15803D; }
.nt-blank .cb-ans.bad { color: #B91C1C; text-decoration: line-through; }
.nt-blank .cb-arrow { color: var(--c-text-muted); font-size: .8em; margin: 0 .15em; }

/* 小作文：字数统计 + 范文排印 */
.wr-count { margin-left: auto; font-size: .78em; font-weight: 700; color: var(--c-text-muted); }
.wr-essay { white-space: pre-wrap; }
.wr-input { font-family: inherit; }
/* ── 大作文（Part B 图画/图表作文）：真题配图 + 点图放大 + 答题卡（2026-09-28）── */
.bg-fig { margin: 0 0 16px; text-align: center; }
.bg-img { display: block; margin: 0 auto; max-width: 100%; max-height: 460px; width: auto; height: auto;
  border: 1px solid var(--c-border); border-radius: var(--radius-md); background: var(--c-white);
  cursor: zoom-in; }
.bg-cap { margin: 8px 0 0; font-size: .82em; color: var(--c-text-secondary); line-height: 1.95;
  text-align: justify; text-justify: inter-ideograph; text-indent: 2em; }
.bg-cap-tip { margin: 6px 0 0; font-size: .74em; color: var(--c-text-muted); text-align: center; text-indent: 0; }
.bg-noimg .bg-cap { display: block; margin: 0; }
/* 源卷没抓到配图时的文字兜底（不给用户看空框） */
.bg-noimg { margin: 0 0 16px; padding: 12px 14px; font-size: .9em; line-height: 1.8;
  background: color-mix(in srgb, var(--c-accent) 5%, transparent);
  border-left: 3px solid color-mix(in srgb, var(--c-accent) 35%, transparent);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0; }
.bg-noimg b { display: block; margin-bottom: 4px; font-size: .82em; color: var(--c-text-muted); }
.bg-card { padding: 14px 16px; }
.bg-input { font-family: inherit; }
html.dark .bg-img { background: #2A2623; }
/* 点图放大：全屏遮罩；body.bg-zoom-lock 锁背景滚动 */
.bg-zoom { position: fixed; inset: 0; z-index: 9999; display: none; align-items: center; justify-content: center;
  padding: 24px; background: rgba(0,0,0,.78); cursor: zoom-out; }
.bg-zoom.show { display: flex; }
.bg-zoom img { max-width: 96vw; max-height: 92vh; width: auto; height: auto; border-radius: var(--radius-md);
  background: #fff; box-shadow: 0 18px 60px rgba(0,0,0,.5); }
body.bg-zoom-lock { overflow: hidden; }
/* ── 翻译（Part C）：原文划线句 + 答题卡（2026-09-28）──────────────────── */
.tr-mark { background: color-mix(in srgb, var(--c-accent) 15%, transparent);
  border-bottom: 1.5px solid color-mix(in srgb, var(--c-accent) 60%, transparent); border-radius: 3px 3px 0 0; }
.tr-cards { margin-top: 20px; }
.tr-cards-head { display: flex; justify-content: space-between; align-items: center; gap: 10px;
  font-size: .84em; color: var(--c-text-muted); margin: 0 0 10px; }
.tr-prog { font-weight: 700; color: var(--c-accent-deep); }
.tr-card { border: 1px solid var(--c-border); border-radius: var(--radius-md); background: var(--c-bg-card);
  padding: 14px 16px; margin-bottom: 14px; }
.tr-head { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.tr-num { font-weight: 800; color: var(--c-accent-deep); }
.tr-score { font-size: .74em; color: var(--c-text-muted); border: 1px solid var(--c-border);
  border-radius: 100px; padding: 1px 8px; }
.tr-en { font-size: .94em; line-height: 1.75; color: var(--c-text-secondary); margin: 0 0 10px;
  background: color-mix(in srgb, var(--c-accent) 6%, transparent); padding: 8px 12px;
  border-left: 3px solid color-mix(in srgb, var(--c-accent) 45%, transparent);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0; }
.tr-input { width: 100%; box-sizing: border-box; font: inherit; font-size: .94em; line-height: 1.7;
  color: var(--c-text); background: var(--c-white); border: 1px solid var(--c-border);
  border-radius: var(--radius-sm); padding: 10px 12px; resize: vertical; }
textarea.tr-input[readonly] { background: #F7F4ED; color: #A8A29E; cursor: pointer; }
textarea.tr-input[readonly]:focus { border-color: #DED2BB; box-shadow: none; }
html.dark textarea.tr-input[readonly] { background: #2A2623; color: #78716C; }
.tr-input:focus { outline: none; border-color: var(--c-accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--c-accent) 14%, transparent); }
.tr-acts { display: flex; align-items: center; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
.tr-btn { font: inherit; font-size: .8em; padding: 6px 14px; border-radius: 100px; cursor: pointer;
  border: 1px solid color-mix(in srgb, var(--c-accent) 45%, transparent);
  background: color-mix(in srgb, var(--c-accent) 8%, transparent); color: var(--c-accent-deep); }
.tr-btn:hover { background: color-mix(in srgb, var(--c-accent) 16%, transparent); }
.ocr-acts { margin-left: auto; display: flex; gap: 8px; }
.ocr-ico { width: 14px; height: 14px; display: inline-block; vertical-align: -2px; margin-right: 5px; }
.tr-btn-ai { border-color: color-mix(in srgb, #65A30D 50%, transparent); color: #3F6212;
  background: color-mix(in srgb, #65A30D 10%, transparent); }
.tr-hint { font-size: .76em; color: var(--c-text-muted); }
.tr-box { margin-top: 10px; padding: 12px 14px; font-size: .9em; line-height: 1.8;
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0; }
.tr-ref { background: color-mix(in srgb, #15803D 7%, var(--c-white));
  border-left: 3px solid color-mix(in srgb, #15803D 55%, transparent); }
.tr-ana { background: color-mix(in srgb, var(--c-accent) 6%, var(--c-white));
  border-left: 3px solid color-mix(in srgb, var(--c-accent) 50%, transparent); }
.tr-ref-note { margin: 0 0 6px; font-size: .78em; font-weight: 700; color: var(--c-text-muted); }
.tr-foot { text-align: center; margin: 6px 0 2px; }
.tr-reset { font: inherit; font-size: .8em; padding: 6px 16px; border-radius: 100px; cursor: pointer;
  border: 1px solid var(--c-border); background: transparent; color: var(--c-text-muted); }
html.dark .tr-input { background: #2A2623; }
html.dark .tr-card { background: #221F1D; }
/* ── 四六级汉译英（2026-10-02）：中文原文区 + 解锁提示 + 解析块 ── */
.cz-zh { margin: 0 0 18px; padding: 14px 16px; background: var(--c-bg-card); border: 1px solid var(--c-border);
  border-radius: var(--radius-sm); }
.cz-zh-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-bottom: 8px; }
.cz-zh-head > span:first-child { font-size: .8em; font-weight: 700; color: #fff; background: var(--c-accent-deep);
  padding: 2px 10px; border-radius: 9999px; }
.cz-zh-n { font-size: .76em; color: var(--c-text-muted); }
/* 中文原文整段连排、首行缩进 2em —— 与真实卷面一致（考卷上就是一段连排，没有题号）。
   注意：它也在 `.passage-body` 里，`.passage-body p` 的 `text-align:justify + text-indent:2em`
   会生效 —— **对中文正好是对的**（中文两端对齐好看），所以这里不跟它抢。 */
.cz-zh-body { margin: 0; text-indent: 2em; font-size: 1.02em; line-height: 1.9; color: var(--c-text); }
/* ── 四六级汉译英：解析块直接上屏用的样式（内容仍在按钮后面，面板样式走 .tr-ref/.tr-ana）── */
.cz-sec { margin: 0 0 12px; }
.cz-sec-h { margin: 0 0 6px; font-size: .84em; font-weight: 700; color: var(--c-accent-deep);
  padding-left: 8px; border-left: 3px solid var(--c-accent); }
/* ★ 解析里的**英文**必须左对齐、不缩进：`.passage-body p`（0,1,1）会把 justify 漏进来，
   英文被拉开字距就一眼不对（听力题那次同样的坑）。选择器写到 (0,2,1) 才压得住。 */
.cz-sec .cz-p { margin: 0; font-size: .9em; line-height: 1.85; color: var(--c-text-secondary); text-align: justify; }
.cz-ul { margin: 0; padding-left: 20px; }
.cz-ul li { font-size: .88em; line-height: 1.8; color: var(--c-text-secondary); margin-bottom: 4px; }
.cz-item { margin: 0 0 12px; padding: 10px 12px; background: color-mix(in srgb, var(--c-accent) 4%, var(--c-white));
  border-radius: var(--radius-sm); }
.cz-item:last-child { margin-bottom: 0; }
.cz-item .cz-zh { margin: 0 0 4px; font-size: .9em; font-weight: 600; color: var(--c-text); line-height: 1.7;
  text-indent: 0; text-align: left; }
.cz-n { display: inline-block; min-width: 18px; height: 18px; margin-right: 6px; text-align: center; line-height: 18px;
  font-size: .74em; font-weight: 700; color: #fff; background: var(--c-accent-deep); border-radius: 50%; }
.cz-item .cz-en { margin: 0 0 6px; font-size: .9em; line-height: 1.7; color: #0F5132;
  text-align: left; text-indent: 0; }
.cz-item .cz-note { margin: 0 0 4px; font-size: .84em; line-height: 1.75; color: var(--c-text-secondary);
  text-indent: 0; text-align: justify; }
.cz-note b { display: inline-block; min-width: 34px; margin-right: 4px; color: var(--c-accent-deep); }
html.dark .cz-zh, html.dark .cz-item { background: #221F1D; border-color: #3A322C; }
html.dark .cz-en { color: #6EE7B7; }
html.force-phone .cz-zh { padding: 12px; }
html.force-phone .cz-zh-body { font-size: .98em; }
/* 选句填空：整句填进去以后（.long）不再用居中小胶囊 —— 换成规范化引文：
   题号小徽标 + 与正文同字号同对齐的高亮句；多行时左边竖线逐行重复，行距/字号跟正文一致。
   短内容（字母、True/False、几个字的标题）继续用上面那套小胶囊。 */
.nt-blank.long { display: inline; min-width: 0; margin: 0; padding: 0; text-align: inherit;
  font-size: 1em; font-weight: inherit; line-height: inherit; color: inherit;
  border-bottom: 0; border-radius: 0; background: transparent; }
.nt-blank.long .cb-n { display: inline-block; vertical-align: 1px; margin: 0 .4em 0 0; padding: 0 5px;
  border-radius: 4px; font-size: .72em; font-weight: 700; opacity: 1;
  color: var(--c-accent-deep); background: color-mix(in srgb, var(--c-accent) 16%, transparent); }
.nt-blank.long .cb-ans { display: inline; margin: 0; padding: 1px 3px 1px 6px; font-weight: inherit;
  background: color-mix(in srgb, var(--c-accent) 13%, transparent); border-radius: 2px;
  border-left: 2px solid color-mix(in srgb, var(--c-accent) 55%, transparent);
  -webkit-box-decoration-break: clone; box-decoration-break: clone; }
.nt-blank.long .cb-ans.ok { background: color-mix(in srgb, #15803D 13%, transparent);
  border-left-color: color-mix(in srgb, #15803D 60%, transparent); color: inherit; }
.nt-blank.long .cb-ans.bad { background: color-mix(in srgb, #B91C1C 12%, transparent);
  border-left-color: color-mix(in srgb, #B91C1C 55%, transparent); }
.nt-blank.long .cb-arrow { margin: 0 .35em; font-size: .9em; }
/* 左栏字母 + 右栏正文；译文独占下一行；「译文」按钮固定在右上角 */
.nt-para { position: relative; display: grid; grid-template-columns: 52px 1fr;
  column-gap: 12px; row-gap: 8px; margin: 0 0 14px; padding: 12px 74px 12px 14px;
  border: 1px solid var(--c-border); border-radius: var(--radius-md); }
.nt-para::before { content: ''; position: absolute; inset: 0; z-index: -2; border-radius: inherit; background: var(--c-bg-card); }
.nt-para-label { grid-column: 1; text-align: center; }
.nt-letter { display: inline-block; min-width: 30px; height: 30px; line-height: 30px; border-radius: 50%;
  font-weight: 800; font-size: .95em; color: var(--c-white); background: var(--c-accent); }
.nt-given { display: block; margin-top: 6px; font-size: .68em; font-weight: 700; color: var(--c-accent-deep);
  background: color-mix(in srgb, var(--c-accent) 16%, transparent); border-radius: 100px; padding: 1px 6px; }
.nt-used { display: block; margin-top: 6px; font-size: .68em; font-weight: 700; color: #B45309;
  background: color-mix(in srgb, #B45309 16%, transparent); border-radius: 100px; padding: 1px 6px; }
.nt-para-body { grid-column: 2; min-width: 0; font-size: .98em; line-height: 1.65; }
.nt-para > .nt-zh-text { grid-column: 2; width: 100%; box-sizing: border-box; margin: 0; }
.nt-para > .nt-zh-btn { position: absolute; top: 10px; right: 12px; }
.nt-pwrap { position: relative; margin-bottom: 12px; }
.nt-pwrap > .nt-zh-btn { position: absolute; top: 0; right: 0; }
.nt-pwrap > .nt-p { padding-right: 74px; margin-bottom: 0; }
.nt-zh-ai-note { margin: 0 0 4px; font-size: .78em; font-weight: 700; color: #B45309; }
.nt-order-row { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin: 18px 0 6px; padding: 12px 14px;
  border: 1px dashed var(--c-border); border-radius: var(--radius-md); background: var(--c-bg-card); }
.nt-chip { display: inline-flex; align-items: center; gap: 6px; }
.nt-chip-n { font-weight: 800; color: var(--c-accent-deep); font-size: .9em; }
.nt-chip-fixed { display: inline-flex; align-items: center; gap: 6px; padding: 0 8px;
  border: 1px dashed color-mix(in srgb, var(--c-accent) 55%, transparent); border-radius: 100px;
  background: color-mix(in srgb, var(--c-accent) 8%, transparent); }
.nt-chip-fixed-tag { font-weight: 700; font-size: .74em; color: var(--c-text-muted); }
.nt-chip-sep { width: 1px; height: 22px; margin: 0 4px;
  background: var(--c-border); display: inline-block; }
.nt-blank-done { display: inline-block; min-width: 2.4em; text-align: center; font-weight: 800;
  color: var(--c-accent-deep); }
.nt-prog-note { font-weight: 500; color: var(--c-text-muted); font-size: .92em; }
.nt-opt.given { opacity: .6; }
.nt-opt.given .nt-opt-tag { color: var(--c-accent-deep); }
.nt-hint { margin: 6px 0 0; font-size: .8em; color: var(--c-text-muted); }
.nt-zh-btn { min-width: 62px; text-align: center; white-space: nowrap;
  font-size: .74em; padding: 2px 8px; border-radius: 100px; cursor: pointer; color: var(--c-accent-deep);
  border: 1px solid color-mix(in srgb, var(--c-accent) 45%, transparent);
  background: color-mix(in srgb, var(--c-accent) 8%, transparent); }
.nt-zh-btn:hover { background: color-mix(in srgb, var(--c-accent) 18%, transparent); }
.nt-zh-text { margin-top: 8px; padding: 10px 12px; border-radius: var(--radius-sm); font-size: .9em; line-height: 1.7;
  color: var(--c-text-secondary); background: color-mix(in srgb, var(--c-accent) 6%, transparent); }
.nt-opts { position: relative; margin: 18px 0 0; padding: 12px 14px; border: 1px solid var(--c-border); border-radius: var(--radius-md); }
.nt-opts::before { content: ''; position: absolute; inset: 0; z-index: -2; border-radius: inherit; background: var(--c-bg-card); }
.nt-opts-head { font-size: .76em; font-weight: 700; letter-spacing: .04em; color: var(--c-text-muted); margin-bottom: 8px; }
/* 选项的「译」开关（2026-10-01 用户要求）：选项本身保持纯英文（与阅读/完形一致），
   中文译文存在 newtype_bank 的 optionZh 里，点「译」才显示 —— 不再把中文挂在选项文字后面。 */
.nt-opt-zh-btn { min-width: 38px; text-align: center; white-space: nowrap; margin-left: 8px; vertical-align: middle;
  font-size: .74em; padding: 1px 8px; border-radius: 100px; cursor: pointer; color: var(--c-accent-deep);
  border: 1px solid color-mix(in srgb, var(--c-accent) 45%, transparent);
  background: color-mix(in srgb, var(--c-accent) 8%, transparent); }
.nt-opt-zh-btn:hover { background: color-mix(in srgb, var(--c-accent) 18%, transparent); }
.nt-opt-zh { display: block; margin-top: 2px; font-size: .92em; line-height: 1.6; color: var(--c-text-secondary); }
.nt-opt { display: flex; gap: 10px; padding: 6px 2px; font-size: .92em; line-height: 1.6; }
.nt-opt-l { flex: 0 0 22px; height: 22px; line-height: 22px; text-align: center; border-radius: 50%;
  border: 1.5px solid var(--c-border); font-weight: 700; font-size: .8em; color: var(--c-accent-deep); }
.nt-match { display: flex; gap: 14px; margin: 18px 0 0; align-items: flex-start; }
.nt-match-col { position: relative; flex: 1; min-width: 0; border: 1px solid var(--c-border); border-radius: var(--radius-md);
  padding: 10px 12px; }
.nt-match-col::before { content: ''; position: absolute; inset: 0; z-index: -2; border-radius: inherit; background: var(--c-bg-card); }
.nt-match-head { font-size: .76em; font-weight: 700; color: var(--c-text-muted); margin-bottom: 8px; }
.nt-match-item { display: flex; gap: 8px; align-items: flex-start; width: 100%; text-align: left; padding: 8px 6px;
  border: 0; border-bottom: 1px dashed var(--c-border); background: transparent; cursor: pointer; font-size: .92em; line-height: 1.55; }
.nt-match-item:hover { background: color-mix(in srgb, var(--c-accent) 8%, transparent); }
.nt-match-item.sel { background: color-mix(in srgb, var(--c-accent) 12%, transparent); }
.nt-match-num { flex: 0 0 26px; font-weight: 800; color: var(--c-accent-deep); }
.nt-match-txt { flex: 1; }
.nt-match-ans { flex: 0 0 30px; text-align: center; font-weight: 800; color: var(--c-accent-deep);
  border: 1.5px solid var(--c-border); border-radius: 6px; }
.nt-match-row { display: flex; gap: 8px; align-items: flex-start; padding: 6px 4px; font-size: .9em; line-height: 1.55;
  border-radius: var(--radius-sm); }
.nt-match-row.sel { background: color-mix(in srgb, var(--c-accent) 14%, transparent); }
.nt-match-tag { flex: 0 0 24px; font-size: .72em; font-weight: 800; color: #B45309; }
.nt-match-l { flex: 0 0 22px; font-weight: 800; color: var(--c-accent-deep); }
.nt-tf { position: relative; margin: 16px 0 0; border: 1px solid var(--c-border); border-radius: var(--radius-md); padding: 10px 12px; }
.nt-tf::before { content: ''; position: absolute; inset: 0; z-index: -2; border-radius: inherit; background: var(--c-bg-card); }
.nt-tf-row { display: flex; gap: 10px; align-items: flex-start; padding: 9px 4px; border-bottom: 1px dashed var(--c-border); }
.nt-tf-row:last-child { border-bottom: 0; }
.nt-tf-txt { flex: 1; font-size: .94em; line-height: 1.6; }
/* 判断题（2026-10-01）：整行可点（作答/看解析），行尾多一个「解析」按钮 —— 原来这页没有任何解析入口。 */
.nt-tf-row[data-ntq] { cursor: pointer; }
.nt-tf-row[data-ntq]:hover { background: color-mix(in srgb, var(--c-accent) 7%, transparent); }
.nt-tf-ana { flex: 0 0 auto; height: 30px; padding: 0 10px; border-radius: 8px; cursor: pointer;
  font-size: .78em; font-weight: 700; border: 1px solid var(--c-border); background: var(--c-bg-card);
  color: var(--c-text-secondary); }
.nt-tf-ana:hover { border-color: var(--c-accent); color: var(--c-accent-deep); }
.nt-tf-ana:focus-visible { outline: 2px solid var(--c-accent); outline-offset: 2px; }
.nt-tf-btns { flex: 0 0 auto; display: inline-flex; gap: 6px; }
.nt-tf-btns button { width: 36px; height: 30px; border-radius: 8px; cursor: pointer; font-weight: 800; font-size: .86em;
  border: 1.5px solid var(--c-border); background: transparent; color: var(--c-text-secondary); }
.nt-tf-btns button:hover { border-color: var(--c-accent); color: var(--c-accent-deep); }
.nt-tf-btns button.sel { background: var(--c-accent); border-color: var(--c-accent); color: var(--c-white); }
.nt-tf-btns button.right { background: #15803D; border-color: #15803D; color: #fff; }
.nt-tf-btns button.wrong { background: #B91C1C; border-color: #B91C1C; color: #fff; }
.nt-bar { margin-top: 20px; }
.cloze-opt.used { opacity: .45; }
.popover.cloze-pop.nt-letter-pop { display: flex !important; flex-direction: column !important;
  min-width: 0 !important; width: fit-content !important; max-width: calc(100vw - 24px) !important;
  gap: 6px !important; padding: 9px 10px; }
.nt-letter-row { display: flex; flex-direction: row; flex-wrap: nowrap; gap: 3px; align-items: center; }
/* 段落排序：卡片里只有大写字母 */
.nt-letter-opt { flex: 0 0 38px !important; display: inline-flex; align-items: center; justify-content: center;
  width: 38px !important; max-width: 38px !important; height: 38px; padding: 0 !important; margin: 0;
  border-radius: 50%; }
.nt-letter-opt .nt-big-letter { font-size: 1em; font-weight: 800; color: var(--c-accent-deep); }
.nt-letter-opt.sel { border-color: var(--c-accent); background: color-mix(in srgb, var(--c-accent) 18%, transparent); }
.nt-letter-opt.right { border-color: #15803D; background: color-mix(in srgb, #15803D 14%, transparent); }
.nt-letter-opt.right .nt-big-letter { color: #15803D; }
.nt-letter-opt.wrong { border-color: #B91C1C; background: color-mix(in srgb, #B91C1C 14%, transparent); }
.nt-letter-opt.wrong .nt-big-letter { color: #B91C1C; }
/* 段落排序：候选卡只显示段落首句摘要（完整原文在正文 A–G 段里） */
.popover.cloze-pop.nt-pop-compact { min-width: 260px; max-width: min(420px, calc(100vw - 24px)); }
.nt-opt-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.nt-opt-txt { display: block; }
.nt-opt-used { font-size: .74em; font-weight: 700; color: #B45309; }
.cloze-opt .nt-opt-txt { white-space: normal; }

.cloze-opt.nt-clear { color: var(--c-text-muted); }
.nt-match-ans.right { color: #15803D; border-color: #15803D; }
.nt-match-ans.wrong { color: #B91C1C; border-color: #B91C1C; }
@media (max-width: 720px) {
  .nt-match { flex-direction: column; }
  .nt-para { grid-template-columns: 40px 1fr; column-gap: 8px; padding: 10px 64px 10px 10px; }
  .nt-para > .nt-zh-btn { top: 8px; right: 10px; }
  .nt-para-label { flex: 0 0 40px; }
}

.cloze-bar { position: sticky; bottom: 0; z-index: 60; margin: 18px 40px 0; padding: 10px 16px;
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  background: color-mix(in srgb, var(--c-bg-reading) 92%, transparent); backdrop-filter: blur(6px);
  border: 1px solid var(--c-border); border-radius: var(--radius-md); box-shadow: 0 -2px 14px rgba(0,0,0,.06); }
.cloze-prog { font-size: .86em; font-weight: 600; color: var(--c-text-secondary); white-space: nowrap; }
.cloze-prog b { color: var(--c-accent-deep); font-size: 1.06em; }
.cloze-track { flex: 1; min-width: 90px; height: 6px; border-radius: 100px; background: var(--c-border); overflow: hidden; }
.cloze-track i { display: block; height: 100%; width: 0; border-radius: 100px; background: var(--c-accent); transition: width .2s ease; }
.cloze-bar .cbtn { padding: 7px 16px; border-radius: 100px; font-size: .84em; font-weight: 600; cursor: pointer;
  border: 1px solid var(--c-border); background: var(--c-white); color: var(--c-text-secondary); transition: all .15s; }
.cloze-bar .cbtn:hover { border-color: var(--c-accent); color: var(--c-accent-deep); }
.cloze-bar .cbtn.primary { background: var(--c-accent); border-color: var(--c-accent); color: var(--c-white); }
.cloze-bar .cbtn.primary:hover { background: var(--c-accent-hover); }
.cloze-bar .cbtn:disabled { opacity: .45; cursor: not-allowed; }
.cloze-tip { margin: 8px 40px 0; font-size: .8em; color: var(--c-text-muted); }
/* 空位选项卡（复用 .popover 视觉；用 .popover.cloze-pop 提高优先级，
   否则会被后面定义的 .popover { min-width:180px } 压回去，长选项会挤成两行） */
.popover.cloze-pop { padding: 10px 10px 8px; min-width: 240px; max-width: min(360px, calc(100vw - 24px)); }
.cloze-pop .cp-head { font-size: .74em; font-weight: 700; letter-spacing: .06em; color: var(--c-text-muted); padding: 2px 8px 8px; }
.cloze-opt { display: flex; align-items: flex-start; gap: 9px; width: 100%; text-align: left; padding: 8px 10px;
  border: 1px solid transparent; border-radius: 10px; background: none; cursor: pointer; font-size: .88em;
  color: var(--c-text); line-height: 1.5; transition: background .13s, border-color .13s; }
.cloze-opt:hover { background: color-mix(in srgb, var(--c-accent) 10%, transparent); }
/* 2026-10-31 用户要求：每个选项旁边加一个「译」，点一下直接查这个词（卡片贴在按钮旁）。
   单独一行 flex，避免把「译」套在选项 <button> 里面（button 里再放 button 不合法）。 */
.cp-opt-row { display: flex; align-items: stretch; gap: 6px; }
.cp-opt-row .cloze-opt { flex: 1 1 auto; min-width: 0; width: auto; }
.cp-tr { flex: 0 0 30px; align-self: center; height: 30px; padding: 0; border-radius: 9px;
  border: 1px solid var(--c-border); background: transparent; color: var(--c-text-muted);
  font: inherit; font-size: .72em; cursor: pointer; transition: color .13s, border-color .13s, background .13s; }
.cp-tr:hover { color: var(--c-accent); border-color: var(--c-accent);
  background: color-mix(in srgb, var(--c-accent) 10%, transparent); }
html.dark .cp-tr { border-color: rgba(199,169,104,.35); }
.cloze-opt .cp-l { flex: 0 0 20px; height: 20px; border-radius: 50%; border: 1.5px solid var(--c-border);
  display: inline-flex; align-items: center; justify-content: center; font-size: .74em; font-weight: 700; color: var(--c-text-muted); }
.cloze-opt.sel { border-color: var(--c-accent); background: color-mix(in srgb, var(--c-accent) 14%, transparent); }
.cloze-opt.sel .cp-l { background: var(--c-accent); border-color: var(--c-accent); color: var(--c-white); }
.cloze-opt.right { border-color: #15803D; background: color-mix(in srgb, #15803D 12%, transparent); }
.cloze-opt.right .cp-l { background: #15803D; border-color: #15803D; color: #fff; }
.cloze-opt.wrong { border-color: #B91C1C; background: color-mix(in srgb, #B91C1C 12%, transparent); }
.cloze-opt.wrong .cp-l { background: #B91C1C; border-color: #B91C1C; color: #fff; }
.cloze-opt:disabled { cursor: default; }
/* 解析区（2026-09-27）：看完答案后卡片底部多一行「解析」 */
.cloze-pop .cp-ana-row { display: flex; align-items: center; gap: 8px; margin: 6px 4px 0; padding-top: 8px; border-top: 1px dashed var(--c-border); }
.cloze-pop .cp-ana-btn { padding: 5px 14px; border-radius: 100px; font-size: .8em; font-weight: 600; cursor: pointer;
  border: 1px solid var(--c-accent); background: transparent; color: var(--c-accent-deep); transition: all .15s; }
.cloze-pop .cp-ana-btn:hover { background: color-mix(in srgb, var(--c-accent) 12%, transparent); }
.cloze-pop .cp-ana-btn:disabled { opacity: .45; cursor: not-allowed; border-color: var(--c-border); color: var(--c-text-muted); }
.cloze-pop .cp-ana-btn:disabled:hover { background: transparent; }
.cloze-pop .cp-ana-note { font-size: .72em; color: var(--c-text-muted); }
.cloze-pop .cp-ana { display: none; }
.cloze-pop .cp-ana.show { display: block; }
.cloze-pop .cp-ana-text { max-height: 40vh; overflow-y: auto; margin-top: 8px; padding: 10px 12px;
  background: color-mix(in srgb, var(--c-accent) 5%, var(--c-white)); border: 1px solid var(--c-border);
  border-radius: 10px; font-size: .84em; line-height: 1.75; color: var(--c-text-secondary); white-space: pre-wrap; word-break: break-word; }
.cloze-pop .cp-ana-loading { margin-top: 8px; padding: 8px 12px; font-size: .8em; color: var(--c-text-muted); }
/* 防误触开关（标题行中间） */
.guard-title-toggle { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.guard-title-toggle .switch { position: relative; width: 72px; height: 30px; border-radius: 15px; background: #ddd; display: flex; align-items: center; padding: 3px; cursor: pointer; transition: background .4s cubic-bezier(.4,0,.2,1), box-shadow .3s ease; box-shadow: 0 3px 6px rgba(0,0,0,.2); box-sizing: border-box; }
.guard-title-toggle .switch .toggle { position: absolute; top: 3px; left: 3px; width: 24px; height: 24px; border-radius: 50%; background: #fff; box-shadow: 0 2px 5px rgba(0,0,0,.3); display: flex; justify-content: center; align-items: center; transition: transform .4s cubic-bezier(.4,0,.2,1), background .3s ease; }
.guard-title-toggle .switch .toggle svg { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 14px; height: 14px; fill: black; opacity: .5; transition: opacity .3s ease; }
.passage-body p { text-indent: 2em; margin-bottom: 2px; font-size: calc(1.02em * var(--rt-scale, 1)); letter-spacing: .005em; text-align: var(--rt-align, justify); line-height: var(--rt-line, 1.6); font-family: var(--rt-font, system-ui, -apple-system, 'Segoe UI', 'Microsoft YaHei', sans-serif); }
/* ── 正文文字颜色（2026-09-27 用户要求「文章字体一定要是黑色，不然看不清」）──
   亮色下一律**纯黑**：主题的 --c-text 是深暖灰 #292524，在高频词高亮/荧光笔叠加时观感发灰。
   覆盖文章正文与它里面的每个词（.word 会带 hf 高亮 class，必须一起钉，否则深灰字压浅色底更糊）。
   暗色**不跟**：纯黑在深底上等于看不见，仍用主题的浅色 #EDE9E6。 */
html:not(.dark) .passage-body,
html:not(.dark) .passage-body p,
html:not(.dark) .passage-body .word { color: #000; }
/* 小说/文章阅读器同理 */
html:not(.dark) .story-read-body,
html:not(.dark) .story-read-body p,
html:not(.dark) .story-read-body .word,
html:not(.dark) .story-read-area .word { color: #000; }
.questions-section { padding: 36px 40px 0; }
.reading-area ::selection { background: #C6D3B6; color: var(--c-text); }
.reading-area .word { cursor: pointer; transition: all .1s; border-radius: 3px; padding: 0 1px; }
.reading-area .word.ul { text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 3px; }
.reading-area .word:hover { background: var(--c-accent-light); }
.questions-section { margin-top: 36px; padding-top: 24px; border-top: 1px solid var(--c-border); }
.questions-section h3 { font-size: 1em; font-weight: 600; color: var(--c-primary-dark); margin-bottom: 18px; }
.question-block { position: relative; margin-bottom: 22px; padding: 16px 20px; background: var(--c-white); border-radius: var(--radius-sm); border: 1px solid var(--c-border); transition: border-color var(--transition-fast); }
.q-float-btn { margin: 0.25rem; padding: 0.25rem 0.5rem; border-radius: 0.4rem; border: none; font-weight: 600; cursor: pointer; display: inline-flex; align-items: center; gap: 0.35rem; font-family: inherit; font-size: 11px; background: linear-gradient(#fbbf24, #f59e0b); color: #7c2d12; box-shadow: inset 0pt 4pt 3pt -2pt #fcd34d, 0pt 4pt 5pt -3pt #0009; border-bottom: 2pt solid #b45309; transition: none; vertical-align: middle; }
.q-float-btn:hover { border-bottom: 2pt solid #b45309; translate: 0pt 0pt; }
.q-float-btn:active { box-shadow: inset 0pt 4pt 3pt -2pt #fcd34d, 0pt 4pt 5pt -3pt #0000; border-bottom: 1pt solid #b45309; translate: 0pt 0pt; }
.q-float-btn svg { background-color: #fbbf24; box-shadow: inset 0pt -3pt 3pt -2pt #f59e0b, inset 0pt 3pt 3pt -2pt #fde68a, 0pt 2pt 2pt -2pt #0005, 0pt 0pt 0pt 2pt #d97706; border-radius: 0.2rem; padding: 1px; width: 13px; height: 13px; flex-shrink: 0; }
.float-q-card { position: fixed; z-index: 200; width: 540px; max-width: 92vw; max-height: 75vh; display: none; background: var(--c-white); border-radius: 18px; box-shadow: 0 12px 40px rgba(0,0,0,.18), 0 4px 12px rgba(0,0,0,.08); border: 1px solid rgba(120,113,108,.16); overflow: hidden; }
.float-q-card.show { display: block; }
.float-q-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 6px 10px; background: transparent; border-bottom: 1px solid rgba(120,113,108,.14); cursor: move; user-select: none; touch-action: none; }
body.float-q-dragging { overflow: hidden; }
body.float-q-dragging, body.float-q-dragging * { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
.float-q-title { font-size: .72em; font-weight: 700; color: var(--c-primary-dark); letter-spacing: .02em; }
.float-q-nav { display: flex; align-items: center; gap: 5px; }
.float-q-nav-btn, .float-q-close { width: 22px; height: 22px; border-radius: 7px; border: 1px solid rgba(120,113,108,.18); background: rgba(255,255,255,.6); color: var(--c-text-secondary); cursor: pointer; display: flex; align-items: center; justify-content: center; transition: all .2s ease; }
.float-q-nav-btn svg, .float-q-close svg { width: 12px; height: 12px; }
.float-q-nav-btn:hover { border-color: var(--c-accent); color: var(--c-accent-deep); }
.float-q-close:hover { border-color: var(--c-danger); color: var(--c-danger); }
.float-q-body { max-height: calc(75vh - 36px); overflow-y: auto; padding: 8px 10px 10px; }
.float-q-body .question-block { margin-bottom: 0; padding: 10px 12px; border-radius: 16px; border-color: rgba(120,113,108,.12); }
.float-q-body .word { cursor: pointer; transition: all .1s; border-radius: 3px; padding: 0 1px; }
.float-q-body .word:hover, .float-q-body .word:active { background: #FDE68A; }
.float-q-body ::selection { background: #C6D3B6; color: var(--c-text); }
.float-q-body .q-stem { font-size: .82em; }
.float-q-body .q-option { font-size: .8em; padding: 4px 10px; }
.float-q-body .q-my-ans { font-size: .78em; }
.float-q-body .q-analyze-row { padding-left: 10px; }
.float-q-body .q-toggle-switch .ts-label { font-size: .7em; }
.float-q-body .q-analyze-result { font-size: .78em; padding: 10px 12px; }
.question-block:hover { border-color: var(--c-primary-light); }
.q-stem { padding-right: 56px; }
.q-stem { font-weight: 600; margin-bottom: 8px; line-height: 1.7; color: var(--c-text); display: flex; align-items: flex-start; gap: 8px; padding-left: 15px; }
.q-stem .q-num { flex-shrink: 0; width: 24px; margin-top: 2px; text-align: center; font-weight: 700; color: var(--c-primary-dark); }
.q-stem .q-stem-text { flex: 1; min-width: 0; }
.q-option { padding: 6px 14px; margin: 3px 0; color: #444; line-height: 1.6; cursor: pointer; border-radius: var(--radius-sm); border: 1px solid transparent; transition: all var(--transition-fast); display: flex; align-items: flex-start; gap: 8px; width: 100%; position: relative; }
.q-option::before { content: ''; position: absolute; inset: 0; z-index: -2; border-radius: inherit; transition: background var(--transition-fast); }
.q-option:hover { border-color: transparent; }
.q-option:hover::before { background: #F4FCF7; }
.q-option.selected { border-color: transparent; }
.q-option.selected::before { background: #E6F9EF; }
.q-box { flex-shrink: 0; width: 24px; height: 24px; margin-top: 2px; border: 2px solid var(--c-primary-light); border-radius: 6px; display: inline-flex; align-items: center; justify-content: center; font-size: .72em; font-weight: 700; color: var(--c-text-muted); line-height: 1; transition: all .3s cubic-bezier(.4,0,.2,1); user-select: none; position: relative; overflow: visible; background: var(--c-white); }
.q-box .checkbox-fill { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: #0AA875; transform: scale(0); transition: all .4s cubic-bezier(.68,-.55,.265,1.55); border-radius: 4px; opacity: 0; }
.q-box .q-box-letter { position: relative; z-index: 2; transition: all .3s ease; }
.q-box .success-ripple { position: absolute; top: 50%; left: 50%; width: 0; height: 0; background: rgba(79,107,54,.4); border-radius: 50%; transform: translate(-50%,-50%); opacity: 0; pointer-events: none; }
.q-option:hover .q-box { border-color: #10b981; box-shadow: 0 0 0 2px rgba(79,107,54,.1); }
.q-option.selected .q-box { border-color: #10b981; background: #10b981; box-shadow: 0 4px 12px rgba(79,107,54,.3), 0 0 0 2px rgba(79,107,54,.2); }
.q-option.selected .q-box .checkbox-fill { transform: scale(1); opacity: 1; }
.q-option.selected .q-box .q-box-letter { color: #fff; }
.q-option.selected .q-box .success-ripple { animation: rippleSuccess .6s ease-out; }
.q-option:active .q-box { transform: scale(.95); }
@keyframes rippleSuccess { 0% { width: 0; height: 0; opacity: .6; } 70% { width: 50px; height: 50px; opacity: .3; } 100% { width: 60px; height: 60px; opacity: 0; } }
.q-opt-text { flex: 1; min-width: 0; }
.train-opt-trans { display: inline-flex; align-items: center; gap: 3px; flex-shrink: 0; background: #F0F7FF; color: #2E6DB4; border: 1px solid #C9E1F7; border-radius: 16px; padding: 2px 8px; font-size: .68em; font-weight: 600; cursor: pointer; margin-top: 2px; transition: all var(--transition-fast); line-height: 1.6; }
.train-opt-trans:hover { background: #2E6DB4; color: #fff; border-color: #2E6DB4; }
html.force-phone .train-opt-trans { padding: 1px 6px; font-size: .64em; }
.q-my-ans { margin-top: 6px; font-size: .88em; color: var(--c-accent); display: none; font-weight: 500; }
.q-my-ans.show { display: block; }
.q-my-ans svg { vertical-align: -3px; margin-right: 2px; }
.q-analyze-row { display: flex; align-items: center; gap: 8px; margin-top: 8px; padding-left: 15px; }
.q-analyze-btn { display: inline-flex; align-items: center; justify-content: center; gap: 4px; height: 28px; padding: 0 14px; border-radius: var(--radius-sm); font-size: .78em; font-weight: 500; background: var(--c-accent-light); color: var(--c-accent); border: 1px solid var(--c-accent-light); transition: all var(--transition-fast); }
.q-analyze-btn:hover { background: color-mix(in srgb, var(--c-accent) 20%, var(--c-white)); border-color: var(--c-accent); }
.q-analyze-btn:disabled { opacity: .55; cursor: not-allowed; }
.q-analyze-btn svg { width: 14px; height: 14px; }
.q-toggle-switch {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  font: inherit;
}
.q-toggle-switch .switch {
  font-size: .7rem;
  position: relative;
  display: inline-block;
  width: 4em;
  height: 2em;
  flex-shrink: 0;
}
.q-toggle-switch .slider {
  position: absolute;
  cursor: pointer;
  inset: 0;
  background-color: #eee;
  transition: 0.4s;
  border-radius: 0.5em;
  box-shadow: 0 0.2em #dfd9d9;
}
.q-toggle-switch .slider::before {
  position: absolute;
  content: "";
  height: 1.5em;
  width: 1.4em;
  border-radius: 0.3em;
  left: 0.3em;
  bottom: 0.7em;
  background-color: lightsalmon;
  transition: 0.4s;
  box-shadow: 0 0.4em #bcb4b4;
}
.q-toggle-switch .slider:hover::before {
  box-shadow: 0 0.2em #bcb4b4;
  bottom: 0.5em;
}
.q-toggle-switch.on .slider::before {
  transform: translateX(2em);
  background: lightgreen;
}
.q-toggle-switch .ts-label { font-size: .78em; font-weight: 500; color: var(--c-text-secondary); white-space: nowrap; }
.q-toggle-switch.disabled { opacity: .55; cursor: not-allowed; }
/* 亮色底 #FFFCF8（相对亮度 0.9905、黄相 4.5）：比原 #F5EFE4（0.9816 / 8.0）更亮且去掉奶油黄感，
   原值比页面底 --c-bg(#F5EFE4, 0.9625) 更亮却更黄，观感发闷。暗夜由 html.dark 覆盖。 */
.q-analyze-result { margin-top: 8px; padding: 12px 14px; background: color-mix(in srgb, var(--c-accent) 5%, var(--c-white)); border: 1px solid var(--c-border); border: 1px solid var(--c-accent); border-radius: 0 var(--radius-sm) var(--radius-sm) 0; font-size: .88em; line-height: 1.8; color: var(--c-text-secondary); text-align: justify; }
.q-analyze-result:empty { display: none; }
.q-analyze-result p { margin-bottom: 6px; }
.q-analyze-result h4 { font-size: .95em; color: var(--c-primary-dark); margin: 10px 0 4px; }
.qa-reanalyze-row { margin-bottom: 6px; }
/* 题目解析题库标准格式渲染（renderAnalysis）：答案徽章 + A/B/C/D 选项块，正确项琥珀强调 */
.qa-ans { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 0 0 10px; }
/* 答案徽章：浅底 + 深琥珀字 + 细描边（原为实心饱和琥珀 + 深棕小字，文字对比度仅 4.86:1
   且 10.4px 小字被饱和底压得发闷）→ 现文字对比度 9.04:1、字号提至 11px，靠描边维持徽章感 */
.qa-ans-badge { display: inline-flex; align-items: center; height: 22px; padding: 0 10px; border-radius: 11px;
  background: #FDE9C0; color: #4A3229; border: 1px solid rgba(92,64,51,.45);
  font-size: .78em; font-weight: 700; letter-spacing: .02em; white-space: nowrap; }
.qa-ans-num { font-size: .76em; font-weight: 600; color: var(--c-primary-dark); }
.qa-ans .qa-reanalyze-btn { margin-left: auto; }
.qa-opt { display: flex; align-items: flex-start; gap: 8px; margin: 0 0 7px; padding: 7px 10px; border-radius: var(--radius-sm);
  border: 1px solid transparent; background: rgba(120,113,108,.028); line-height: 1.75; }
.qa-opt:last-child { margin-bottom: 0; }
.qa-key { flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px;
  margin-top: 1px; border-radius: 6px; border: 2px solid var(--c-primary-light); background: var(--c-white);
  font-size: .7em; font-weight: 700; color: var(--c-primary-dark); }
.qa-text { flex: 1; min-width: 0; text-align: justify; }
.qa-opt.correct { border-left-color: var(--c-accent); background: rgba(90,110,69,.05); }
.qa-opt.correct .qa-key { border-color: var(--c-accent-deep); background: var(--c-accent-deep); color: #fff; }
.qa-note { margin: 6px 0 0; text-align: justify; }

/* ── 阅读计时（正计时 / 倒计时）：左上角悬浮卡 ──
   #timerFloat 为 JS 注入到 body 的 fixed 浮层，滚动时常驻；top 值随三端顶栏高度调整
   （实测顶栏底：桌面/平板 66px、手机 60px），故取 70 / 64 留 4px 余量。 */
/* 顶栏计时按钮：放大为 36px 圆形图标按钮（顶栏同级按钮为 34px 高），
   计时进行中显示绕圈旋转的环形指示器——用"时钟走时"的表意承载运行状态，
   而非通用悬浮/淡入。低于 prefers-reduced-motion 时改为静态颜色状态。 */
.topbar .timer-btn { position: relative; flex: none; width: 36px; height: 36px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--c-border); border-radius: 50%; background: var(--c-white);
  color: var(--c-primary); cursor: pointer;
  box-shadow: 0 1px 3px rgba(40,30,10,.08);
  transition: color .2s cubic-bezier(.16,1,.3,1), background .2s cubic-bezier(.16,1,.3,1),
              border-color .2s cubic-bezier(.16,1,.3,1), box-shadow .2s cubic-bezier(.16,1,.3,1),
              transform .15s cubic-bezier(.16,1,.3,1); }
.topbar .timer-btn svg { width: 22px; height: 22px; display: block; }
.topbar .timer-btn:hover { color: var(--c-accent-deep); border-color: #4D7AE6; background: #F7FAFF;
  box-shadow: 0 4px 12px rgba(77,122,230,.22); transform: translateY(-1.5px); }
.topbar .timer-btn:focus-visible { outline: 2px solid var(--c-accent); outline-offset: 2px; }
.topbar .timer-btn:active { transform: scale(.94); box-shadow: 0 1px 2px rgba(40,30,10,.1); }
/* 运行中：琥珀着色 + 旋转圆环（环形用遮罩只留最外 2px） */
.topbar .timer-btn.running { color: var(--c-accent-deep); border-color: rgba(217,119,6,.35); background: #FFFDF6; }
.topbar .timer-btn.running::after {
  content: ''; position: absolute; inset: -1px; border-radius: 50%; pointer-events: none;
  background: conic-gradient(from 0deg, rgba(217,119,6,.9) 0deg, rgba(217,119,6,.9) 90deg, rgba(217,119,6,0) 230deg, rgba(217,119,6,0) 360deg);
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 2px), #000 calc(100% - 1px));
  mask: radial-gradient(farthest-side, transparent calc(100% - 2px), #000 calc(100% - 1px));
  animation: timerRingSpin 2.4s linear infinite;
}
/* 运行态 + 悬停：边框按 hover 要求转蓝，但保留琥珀着色与环形指示
   （.running 的 border-color 与 :hover 同特异性且声明更晚，必须用更高特异性的组合选择器才能生效） */
.topbar .timer-btn.running:hover { border-color: #4D7AE6; background: #F7FAFF;
  box-shadow: 0 4px 12px rgba(77,122,230,.22); }
@keyframes timerRingSpin { to { transform: rotate(360deg); } }
html.dark .topbar .timer-btn { background: #2A2623; border-color: #3F3A37; color: #A8A29E; }
html.dark .topbar .timer-btn:hover { color: #86A6F2; border-color: #4D7AE6; background: #26303F; box-shadow: 0 4px 12px rgba(77,122,230,.28); }
html.dark .topbar .timer-btn.running { color: #FBBF24; border-color: rgba(245,158,11,.4); background: #332B23; }
html.dark .topbar .timer-btn.running:hover { border-color: #4D7AE6; background: #26303F; box-shadow: 0 4px 12px rgba(77,122,230,.28); }
html.dark .topbar .timer-btn.running::after {
  background: conic-gradient(from 0deg, rgba(245,158,11,.95) 0deg, rgba(245,158,11,.95) 90deg, rgba(245,158,11,0) 230deg, rgba(245,158,11,0) 360deg);
}
@media (prefers-reduced-motion: reduce) {
  .topbar .timer-btn, .topbar .timer-btn:hover, .topbar .timer-btn:active { transform: none; }
  .topbar .timer-btn.running::after { animation: none; opacity: .85; }
}
/* 手机顶栏整体隐藏 chrome，计时入口由「更多」面板承担 */
html.force-phone .topbar .timer-btn { display: none; }
.timer-float { position: fixed; top: 70px; left: 12px; z-index: 90; display: none; align-items: center; gap: 10px;
  padding: 7px 12px 7px 9px;   /* 左内边距少 3px 以抵消 3px 左边框占位，使内容左右间隙均为 12px
                                  （改前实测左 15 / 右 13：边框占 padding 盒内部空间把内容又推右了 3px） */
  border-radius: 18px; background: rgba(255,254,250,.93);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  border: 1px solid var(--c-border); border: 1px solid #4D7AE6;   /* 左侧线条：与计时图标同色系蓝 */
  box-shadow: 0 6px 20px rgba(40,30,10,.13), 0 1px 3px rgba(40,30,10,.08);
  cursor: grab; touch-action: none; user-select: none; -webkit-user-select: none; }
.timer-float.dragging { cursor: grabbing; box-shadow: 0 14px 34px rgba(40,30,10,.22), 0 2px 6px rgba(40,30,10,.12); }
.timer-float.dragging .tf-acts { pointer-events: none; }   /* 拖动中屏蔽按钮，避免松手误触 */
.timer-float.show { display: flex; }
.timer-float .tm-label { font-size: .72em; font-weight: 600; color: var(--c-text-secondary); white-space: nowrap; }
.timer-float .tm-clock { font-size: 1.34em; font-weight: 700; letter-spacing: .03em; color: var(--c-text);
  font-variant-numeric: tabular-nums; -moz-font-feature-settings: "tnum"; line-height: 1.1; }
.timer-float.warn { border-left-color: #2F5FD0; }
.timer-float.warn .tm-clock { color: #2F5FD0; }
html.dark .timer-float.warn { border-left-color: #86A6F2; }
html.dark .timer-float.warn .tm-clock { color: #86A6F2; }
.timer-float.over { border-left-color: var(--c-danger); }
.timer-float.over .tm-clock { color: var(--c-danger); }
.timer-float.blurred .tm-clock { filter: blur(6px); opacity: .5; user-select: none; pointer-events: none; }
.timer-float.blurred .tm-label { opacity: .5; }
.tm-done { display: none; font-size: .74em; font-weight: 600; color: var(--c-danger); white-space: nowrap; }
.timer-float.over .tm-done { display: inline; }
/* 按钮组：Uiverse by eirikvold（青→蓝渐变胶囊 + 圆形图标底座），按卡片尺寸等比缩小 */
.tf-acts { display: flex; align-items: center; gap: 4px; }
.tf-acts button {
  font-family: inherit;
  font-size: .56em;
  font-weight: 600;
  background: #5AB6EC;
  color: #fff;
  padding: .4em .58em;
  margin: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: 25px;
  box-shadow: 0 .2em .45em rgba(0, 0, 0, .2);
  cursor: pointer;
  white-space: nowrap;
  /* 内容视觉偏置：整体向左上挪一点（布局不变，与悬停/按压的 transform 叠加） */
  transform: translate(-1.5px, -1.5px);
  transition: all .3s;
}
.tf-acts button:hover { transform: translate(-1.5px, -3px); box-shadow: 0 .34em .7em rgba(0, 0, 0, .28); }
.tf-acts button:active { transform: translate(-1.5px, -1.5px) scale(.95); box-shadow: 0 .1em .24em rgba(0, 0, 0, .2); }
.tf-acts button span { display: block; margin-left: .34em; transition: all .3s; }
.tf-acts .svg-wrapper {
  display: flex; align-items: center; justify-content: center;
  width: 1.4em; height: 1.4em; border-radius: 50%;
  background-color: rgba(255, 255, 255, .25); margin-right: .34em; transition: all .3s;
}
.tf-acts button:hover .svg-wrapper { background-color: rgba(255, 255, 255, .5); }
.tf-acts svg { width: .95em; height: .95em; flex: none; fill: #fff; transition: all .3s; }
.tf-acts button:hover svg { transform: rotate(-25deg); }   /* 原版 45°，此处用小幅摆动更贴合计时语义 */
/* 结束：暖红渐变区分危险操作 */
.tf-acts .tf-stop { background: #E8593C; }
/* 开关型按钮（遮住）开启态：白色描边加高亮 */
.tf-acts .tf-toggle.on { box-shadow: 0 0 0 2px #fff, 0 0 0 3.5px rgba(77, 122, 230, .55), 0 .25em .55em rgba(0, 0, 0, .2); }
.tf-acts .tf-toggle.on .svg-wrapper { background-color: rgba(255, 255, 255, .55); }
/* 悬停强调：暂停/继续 用琥珀描边（与卡片警示色一致） */
.tf-acts .tf-pause:hover, .tf-acts .tf-resume:hover { box-shadow: 0 0 0 2px #fff, 0 0 0 3.5px #6B7F58, 0 .4em .8em rgba(0, 0, 0, .28); }
/* 精读训练页顶栏按钮形状不一致，这里只调形状不改配色。加时钟图标 + 运行态着色。 */
.train-type-switch.train-timer-btn { position: relative; display: inline-flex; align-items: center; gap: 4px; }
.train-type-switch.train-timer-btn::before {
  content: ''; width: 11px; height: 11px; flex: none;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 3a9 9 0 1 0 9 9 9 9 0 0 0-9-9zm0 16a7 7 0 1 1 7-7 7 7 0 0 1-7 7zm1-11h-2v6l5 3 1-1.7-4-2.3z'/%3E%3C/svg%3E") center/contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 3a9 9 0 1 0 9 9 9 9 0 0 0-9-9zm0 16a7 7 0 1 1 7-7 7 7 0 0 1-7 7zm1-11h-2v6l5 3 1-1.7-4-2.3z'/%3E%3C/svg%3E") center/contain no-repeat;
}
.train-type-switch.train-timer-btn.running { color: var(--c-accent-deep); border-color: rgba(90,110,69,.45); }
html.dark .train-type-switch.train-timer-btn.running { color: #D4A373; border-color: rgba(163,185,140,.5); }
/* 计时配置弹窗 */
.tm-modes { display: flex; gap: 8px; margin: 0 0 16px; }
.tm-mode { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 5px; padding: 13px 8px;
  border-radius: 18px; border: 1.5px solid var(--c-border); background: #fff; color: var(--c-text-secondary);
  font-size: .84em; font-weight: 600; cursor: pointer; transition: all var(--transition-normal); }
.tm-mode:hover { border-color: var(--c-primary-light); }
.tm-mode.on { border-color: var(--c-accent); background: #F2EDE4; color: var(--c-accent-deep); box-shadow: 0 0 0 3px rgba(90,110,69,.1); }
.tm-mode small { font-size: .82em; font-weight: 500; color: var(--c-text-muted); }
.tm-mode.on small { color: var(--c-accent-deep); opacity: .8; }
.tm-dur { display: none; margin: 0 0 16px; }
.tm-dur.on { display: block; }
.tm-dur-label { font-size: .8em; font-weight: 600; color: var(--c-text-secondary); margin-bottom: 8px; }
.tm-presets { display: grid; grid-template-columns: repeat(4, 1fr); gap: 7px; }
.tm-presets button { height: 36px; border-radius: 16px; border: 1.5px solid var(--c-border); background: #fff;
  color: var(--c-text-secondary); font-size: .84em; font-weight: 600; cursor: pointer; transition: all var(--transition-normal); }
.tm-presets button:hover { border-color: var(--c-primary-light); }
.tm-presets button.on { border-color: var(--c-accent); background: var(--c-accent); color: #262019; }
.tm-custom { display: flex; align-items: center; gap: 8px; margin-top: 9px; font-size: .82em; color: var(--c-text-muted); }
.tm-custom input { width: 88px; height: 34px; padding: 0 10px; border-radius: 9px; border: 1.5px solid var(--c-border);
  background: #fff; font-size: 1em; color: var(--c-text); outline: none; }
.tm-custom input:focus { border-color: var(--c-accent); box-shadow: 0 0 0 3px rgba(90,110,69,.12); }
.add-modal-overlay.mode-timer .add-modal-icon { background: #426CD5; box-shadow: 0 8px 20px rgba(77,122,230,.3); }
/* 暗夜配色 */
html.dark .timer-float { background: rgba(42,38,35,.94); border-color: #3F3A37; border-left-color: #4D7AE6; }
/* 暗夜下 .over 需再次覆盖左边条（上面的 border-left-color 会盖掉 .over 的红） */
html.dark .timer-float.over { border-left-color: var(--c-danger); }
html.dark .tf-acts .tf-toggle.on { box-shadow: 0 0 0 2px #2A2623, 0 0 0 3.5px rgba(134,166,242,.7), 0 .25em .55em rgba(0,0,0,.4); }
/* 手机/平板：顶栏更低、屏更窄，卡片缩小并下移一点 */
@media (max-width: 768px) {
  .timer-float { top: 64px; left: 8px; padding: 5px 8px; gap: 6px; border-radius: 16px; }
  .timer-float .tm-clock { font-size: 1.18em; }
  .timer-float .tm-label { display: none; }
  .tf-acts { gap: 3px; }
  /* 手机只留图标：更紧凑且触摸目标仍达标 */
  .tf-acts button { height: auto; min-height: 24px; padding: .3em; font-size: .62em; }
  .tf-acts button span { display: none; }
  .tf-acts .svg-wrapper { width: 1.32em; height: 1.32em; margin-right: 0; }
  .tf-acts svg { width: .9em; height: .9em; }
}
html.force-phone .timer-float { top: 64px; left: 8px; padding: 5px 8px; gap: 6px; border-radius: 16px; }
html.force-phone .timer-float .tm-clock { font-size: 1.18em; }
html.force-phone .timer-float .tm-label { display: none; }
html.force-phone .tf-acts { gap: 3px; }
html.force-phone .tf-acts button { height: auto; min-height: 24px; padding: .3em; font-size: .62em; }
html.force-phone .tf-acts button span { display: none; }
html.force-phone .tf-acts .svg-wrapper { width: 1.32em; height: 1.32em; margin-right: 0; }
html.force-phone .tf-acts svg { width: .9em; height: .9em; }
.qa-reanalyze-btn { margin-left: 8px; height: auto; padding: 2px 10px; font-size: .72em; white-space: nowrap; }
.qa-reanalyze-btn svg { width: 12px; height: 12px; }

/* Annotation Canvas */
.annotate-wrap { position: relative; pointer-events: auto; }
.annotate-wrap canvas.annotate-canvas, .annotate-wrap svg.annotate-canvas { position: absolute; top: 0; left: 0; z-index: 2; cursor: none; display: none; }
.annotate-cursor { position: fixed; border-radius: 50%; pointer-events: none; z-index: 3; display: none; transform: translate(-50%, -50%); }
.annotate-cursor.show { display: block; }

/* Toast */
.toast { position: fixed; z-index: 500; padding: 10px 28px; border-radius: 100px; background: var(--c-toast-bg); color: var(--c-toast-fg); border: 1px solid var(--c-toast-bd, transparent); font-size: .88em; font-weight: 700; opacity: 0; transition: opacity .3s; pointer-events: none; box-shadow: var(--shadow-md); }
/* 换色后 --c-success 暗色是亮鼠尾草 #A3B98C，白字压上去只有 2.2:1 —— 暗色下改深字 */
html.dark .toast { color: var(--c-toast-fg); }
.toast.show { opacity: 1; }
.toast-center { position: fixed !important; top: 50% !important; left: 50% !important; transform: translate(-50%, -50%); padding: 12px 32px !important; font-size: 1.15em !important; font-weight: 700 !important; background: rgba(0,0,0,.55) !important; color: #fff !important; text-shadow: none !important; box-shadow: 0 4px 16px rgba(0,0,0,.2) !important; letter-spacing: .06em; white-space: nowrap; border-radius: 100px !important; }
.annotate-wrap canvas.annotate-canvas.active, .annotate-wrap svg.annotate-canvas.active { display: block; }
.annotate-wrap.pen-mode .word { pointer-events: none; }
.annotate-wrap.pen-mode .q-option, .annotate-wrap.pen-mode .questions-section button { pointer-events: none; }
.annotate-toolbar { display: none; align-items: center; gap: 4px; background: var(--c-white); padding: 4px 12px; border: 1px solid var(--c-border); border-radius: var(--radius-sm); position: sticky; top: 48px; z-index: 5; margin: 0 40px 12px; }
.annotate-toolbar.show { display: flex; }
.annotate-toolbar button { width: 26px; height: 26px; border-radius: 50%; border: 2px solid transparent; padding: 0; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: all var(--transition-fast); }
.annotate-toolbar button:hover { transform: scale(1.1); }
.annotate-toolbar button.sel { border-color: var(--c-primary-dark); }
.annotate-toolbar .color-red { background: #EF4444; }
.annotate-toolbar .color-yellow { background: #F59E0B; }
.annotate-toolbar .color-blue { background: #3B82F6; }
.annotate-toolbar .color-green { background: #22C55E; }
/* ── 色板（2026-10-17 用户要求：「点开标注时候颜色是收着的，点一次才展开」）──
   收起态 = 一颗显示当前色的小圆钮；展开 = 8 色浮层（紫/粉/青/黑 是这轮新增，棕色换成黑色）。
   外层 .cp-wrap 是 position:relative 的锚点；浮层绝对定位 → 不占工具条宽度、不加高。 */
.cp-wrap { position: relative; display: flex; align-items: center; flex: none; }
.cp-trigger { position: relative; }
.cp-trigger::after {                       /* 右下角小三角：一眼看出这里能展开 */
  content: ''; position: absolute; right: -1px; bottom: -1px; width: 0; height: 0;
  border-left: 5px solid transparent; border-bottom: 5px solid var(--c-text-muted);
  border-radius: 1px; opacity: .75;
}
.cp-panel { display: none; }
.cp-wrap.open .cp-panel {
  display: grid; grid-template-columns: repeat(4, 24px); gap: 7px;
  position: absolute; top: calc(100% + 7px); left: 0; z-index: 40;
  padding: 9px; background: var(--c-white); border: 1px solid var(--c-border);
  border-radius: var(--radius-md); box-shadow: 0 8px 24px rgba(41,37,36,.16);
}
.cp-wrap.open.cp-up .cp-panel { top: auto; bottom: calc(100% + 7px); }
.cp-wrap.open.cp-fixed .cp-panel {
  /* 用 absolute 而不是 fixed：底部动作表的祖先带 transform/animation（slideUp），
     会成为 fixed 的包含块，把面板压成 20px 高（实测：offsetHeight 20 / scrollHeight 68）。
     absolute 的包含块是最近的定位祖先，配合 JS 按包含块算的 top/left 才稳。 */
  position: absolute; top: auto; bottom: auto; left: auto; right: auto;
  grid-template-columns: repeat(4, 26px); z-index: 210;
}
.cp-wrap.open.cp-fixed .cp-panel button { width: 26px; height: 26px; }
.cp-panel button { width: 24px; height: 24px; border-radius: 50%; border: 2px solid transparent; padding: 0; cursor: pointer; transition: transform var(--transition-fast); }
.cp-panel button:hover { transform: scale(1.12); }
.cp-panel .sel { border-color: var(--c-primary-dark); }
/* 色值定义两处共用：面板里的色块 + 收起态那颗圆钮（圆钮在 .cp-wrap 里，不在 .cp-panel 里，
   所以不能只写 .cp-panel 那条 —— 漏了就会"选黑后圆钮不变色"，看着像透明）。 */
.cp-panel .color-purple, .cp-trigger.color-purple { background: #7C3AED; }
.cp-panel .color-pink,   .cp-trigger.color-pink   { background: #DB2777; }
.cp-panel .color-teal,   .cp-trigger.color-teal   { background: #0D9488; }
.cp-panel .color-black,  .cp-trigger.color-black  { background: #111827; }
html.dark .cp-trigger::after { border-bottom-color: #D6D3D1; }
html.dark .cp-panel { background: #2A2623; border-color: #3F3A37; box-shadow: 0 10px 26px rgba(0,0,0,.5); }
html.dark .cp-panel .sel { border-color: #E7E5E4; }
/* 暗底上"黑色"看不出来 → 反相显示（两者语义一致：仍是"黑"这个选择） */
html.dark .cp-panel .color-black, html.dark .cp-trigger.color-black { background: #E7E5E4; }
.annotate-toolbar .tool-eraser { background: #FFF; border: 1px solid var(--c-border); color: var(--c-text-secondary); font-size: .75em; }
.annotate-toolbar .tool-clear { background: #FEE2E2; color: var(--c-danger); font-size: .75em; }
.annotate-toolbar .tool-undo { background: #FFF; border: 1px solid var(--c-border); color: var(--c-text-secondary); font-size: .72em; }
.annotate-toolbar .tool-hl { background: transparent; border: 1px solid var(--c-border); color: var(--c-text-secondary); font-size: .8em; border-radius: var(--radius-sm); width: 26px; height: 26px; }
.annotate-toolbar .tool-hl.sel { background: color-mix(in srgb, var(--c-accent) 18%, transparent); border-color: var(--c-accent); color: var(--c-accent); }
.annotate-toolbar .sep { width: 1px; height: 18px; background: var(--c-border); margin: 0 4px; }
.annotate-toolbar .tool-size { border-radius: var(--radius-sm); width: auto; min-width: 22px; height: 22px; padding: 0 4px; font-size: .7em; font-weight: 500; background: #F5F5F4; border: 1px solid var(--c-border); color: var(--c-text-muted); }
.annotate-toolbar .tool-size.sel-pen { border-color: var(--c-accent); background: color-mix(in srgb, var(--c-accent) 14%, transparent); color: var(--c-accent); }
.annotate-toolbar .tool-size.sel-eraser { border-color: var(--c-danger); background: #FEF2F2; color: var(--c-danger); }
.annotate-toolbar .tool-label { background: transparent; border: none; width: auto; min-width: 14px; padding: 0 2px; font-size: .72em; font-weight: 600; color: var(--c-text-muted); letter-spacing: .02em; cursor: default; display: inline-flex; align-items: center; justify-content: center; }
.annotate-toolbar .tool-label.active { color: var(--c-accent); }
.annotate-toolbar .tool-label-eraser.active { color: var(--c-danger); }

/* Tablet: annotation button dropdown */
.annotate-btn-dropdown { position: fixed; background: var(--c-white); border-radius: var(--radius-md); box-shadow: 0 8px 28px rgba(0,0,0,.12); border: 1px solid var(--c-border); padding: 8px 12px; z-index: 99; gap: 4px; white-space: nowrap; display: none; }
.annotate-btn-dropdown.show { display: flex; align-items: center; }
.annotate-btn-dropdown button { width: 28px; height: 28px; border-radius: 6px; border: 2px solid transparent; padding: 0; display: flex; align-items: center; justify-content: center; cursor: pointer; background: transparent; color: var(--c-text-secondary); transition: all .15s; }
.annotate-btn-dropdown button:hover { transform: scale(1.1); }
.annotate-btn-dropdown button.sel { border-color: var(--c-primary-dark); }
.annotate-btn-dropdown .color-red { background: #EF4444; }
.annotate-btn-dropdown .color-yellow { background: #F59E0B; }
.annotate-btn-dropdown .color-blue { background: #3B82F6; }
.annotate-btn-dropdown .color-green { background: #22C55E; }
.annotate-btn-dropdown .cp-trigger { width: 28px; height: 28px; border-radius: 50%; }
.annotate-btn-dropdown .cp-panel { grid-template-columns: repeat(4, 26px); }
.annotate-btn-dropdown .cp-panel button { width: 26px; height: 26px; }
.annotate-btn-dropdown .tool-eraser { background: #FFF; border: 1px solid var(--c-border); }
.annotate-btn-dropdown .tool-size { border-radius: var(--radius-sm); width: auto; min-width: 24px; height: 22px; padding: 0 5px; font-size: .68em; font-weight: 500; border: 1px solid var(--c-border); background: #F5F5F4; }
.annotate-btn-dropdown .tool-size.sel-pen { border-color: var(--c-accent); background: color-mix(in srgb, var(--c-accent) 14%, transparent); color: var(--c-accent); }
.annotate-btn-dropdown .tool-size.sel-eraser { border-color: var(--c-danger); background: #FEF2F2; color: var(--c-danger); }
.annotate-btn-dropdown .tool-clear { color: var(--c-danger); font-size: .72em; font-weight: 500; border: 1px solid #FECACA; background: #FEF2F2; width: auto; padding: 0 8px; }
.annotate-btn-dropdown .tool-undo { font-size: .7em; border: 1px solid var(--c-border); width: auto; padding: 0 8px; }
.annotate-btn-dropdown .tool-hl { font-size: .75em; border: 1px solid var(--c-border); }
.annotate-btn-dropdown .tool-hl.sel { background: color-mix(in srgb, var(--c-accent) 18%, transparent); border-color: var(--c-accent); }
.annotate-btn-dropdown .sep { width: 1px; height: 16px; background: var(--c-border); margin: 0 3px; }
.annotate-btn-dropdown .tool-label { background: transparent; border: none; width: auto; min-width: 14px; padding: 0 2px; font-size: .72em; font-weight: 600; color: var(--c-text-muted); letter-spacing: .02em; cursor: default; display: inline-flex; align-items: center; justify-content: center; }
.annotate-btn-dropdown .tool-label.active { color: var(--c-accent); }
.annotate-btn-dropdown .tool-label-eraser.active { color: var(--c-danger); }

/* Phone: bottom sheet */
.annotate-bottomsheet { position: fixed; inset: 0; z-index: 200; display: none; pointer-events: none; }
.annotate-bottomsheet.show { display: block; }
.annotate-bottomsheet .ab-backdrop { position: absolute; inset: 0; background: transparent; pointer-events: none; }
.annotate-bottomsheet .ab-panel { position: absolute; bottom: 0; left: 0; right: 0; background: var(--c-white); border-radius: 16px 16px 0 0; padding: 4px 10px 12px; box-shadow: 0 -4px 20px rgba(0,0,0,.08); animation: slideUp .25s cubic-bezier(.32,.72,0,1); pointer-events: auto; }
@keyframes slideUp { from { transform: translateY(100%); } to { transform: translateY(0); } }
.annotate-bottomsheet .ab-head { display: flex; align-items: center; justify-content: center; margin-bottom: 6px; }
.annotate-bottomsheet .ab-handle { width: 32px; height: 20px; border-radius: 0 0 4px 4px; border: none; background: transparent; color: var(--c-text-muted); font-size: .65em; display: flex; align-items: center; justify-content: center; cursor: pointer; padding: 0; line-height: 1; }
.annotate-bottomsheet .ab-handle svg { display: block; }
.annotate-bottomsheet .ab-tools { display: flex; align-items: center; justify-content: center; gap: 5px; flex-wrap: wrap; }
.annotate-bottomsheet .ab-tools button { width: 28px; height: 28px; border-radius: 6px; border: 2px solid transparent; padding: 0; display: flex; align-items: center; justify-content: center; cursor: pointer; background: transparent; color: var(--c-text-secondary); transition: all .15s; font-size: .75em; }
.annotate-bottomsheet .ab-tools button:hover { transform: scale(1.1); }
.annotate-bottomsheet .ab-tools button.sel { border-color: var(--c-primary-dark); }
.annotate-bottomsheet .ab-tools .color-red { background: #EF4444; }
.annotate-bottomsheet .ab-tools .color-yellow { background: #F59E0B; }
.annotate-bottomsheet .ab-tools .color-blue { background: #3B82F6; }
.annotate-bottomsheet .ab-tools .color-green { background: #22C55E; }
/* 手机底部动作表：色板展开在触发器上方（下面是屏幕边），2 行 × 4 列 */
.annotate-bottomsheet .ab-tools .cp-wrap.open .cp-panel { bottom: calc(100% + 7px); top: auto; left: 0; }
.annotate-bottomsheet .ab-tools .tool-eraser { background: #FFF; border: 1px solid var(--c-border); }
.annotate-bottomsheet .ab-tools .tool-size { border-radius: var(--radius-sm); width: auto; min-width: 26px; height: 24px; padding: 0 5px; font-size: .7em; font-weight: 500; border: 1px solid var(--c-border); background: #F5F5F4; }
.annotate-bottomsheet .ab-tools .tool-size.sel-pen { border-color: var(--c-accent); background: color-mix(in srgb, var(--c-accent) 14%, transparent); color: var(--c-accent); }
.annotate-bottomsheet .ab-tools .tool-size.sel-eraser { border-color: var(--c-danger); background: #FEF2F2; color: var(--c-danger); }
.annotate-bottomsheet .ab-tools .tool-clear { color: var(--c-danger); font-size: .75em; font-weight: 500; border: 1px solid #FECACA; background: #FEF2F2; width: auto; padding: 0 8px; }
.annotate-bottomsheet .ab-tools .tool-undo { font-size: .75em; border: 1px solid var(--c-border); width: auto; padding: 0 8px; }
.annotate-bottomsheet .ab-tools .tool-hl { font-size: .8em; border: 1px solid var(--c-border); width: auto; padding: 0 6px; }
.annotate-bottomsheet .ab-tools .tool-hl.sel { background: color-mix(in srgb, var(--c-accent) 18%, transparent); border-color: var(--c-accent); }
.annotate-bottomsheet .ab-tools .sep { width: 1px; height: 16px; background: var(--c-border); margin: 0 2px; }
.annotate-bottomsheet .ab-tools .tool-label { background: transparent; border: none; width: auto; min-width: 16px; padding: 0 2px; font-size: .75em; font-weight: 600; color: var(--c-text-muted); letter-spacing: .02em; cursor: default; display: inline-flex; align-items: center; justify-content: center; }
.annotate-bottomsheet .ab-tools .tool-label.active { color: var(--c-accent); }
.annotate-bottomsheet .ab-tools .tool-label-eraser.active { color: var(--c-danger); }

/* Phone: floating triangle to re-open toolbar */
.ab-float-handle { position: fixed; bottom: 0; left: 50%; transform: translateX(-50%); z-index: 199; width: 44px; height: 18px; background: var(--c-white); border-radius: 16px 8px 0 0; box-shadow: 0 -2px 8px rgba(0,0,0,.08); display: none; align-items: center; justify-content: center; cursor: pointer; border: none; color: var(--c-text-muted); padding: 0; }
.ab-float-handle svg { display: block; }
.ab-float-handle.show { display: flex; }

/* Vocab Sidebar */
.vocab-sidebar { width: 240px; flex-shrink: 0; position: sticky; top: 80px; align-self: flex-start; max-height: calc(100vh - 100px); overflow-y: auto; scrollbar-width: thin; }
.vocab-panel { background: var(--c-white); border-radius: var(--radius-md); padding: 20px; box-shadow: 0 4px 20px rgba(0,0,0,.06), 0 12px 40px rgba(0,0,0,.08); border: 1px solid var(--c-border); }
.vocab-panel h3 { font-size: .9em; font-weight: 600; margin-bottom: 14px; color: var(--c-text); display: flex; align-items: center; gap: 8px; }
.vocab-panel h3 .count { background: var(--c-accent); color: var(--c-white); border-radius: 50%; min-width: 22px; height: 22px; display: flex; align-items: center; justify-content: center; font-size: .75em; font-weight: 600; }
.vocab-panel h3 .vt-title { white-space: nowrap; flex-shrink: 0; }
.vocab-list { max-height: 45vh; overflow-y: auto; }
.vocab-item { position: relative; padding: 9px 0; border-bottom: 1px solid #F5F5F4; font-size: .85em; }
.vocab-item:last-child { border-bottom: none; }
.vocab-item .w { font-weight: 600; color: var(--c-text); display: block; margin-bottom: 2px; }
.vocab-item .m { color: var(--c-text-muted); font-size: .82em; line-height: 1.6; display: block; }
.vocab-item .del { background: none; color: var(--c-border); font-size: 1.1em; padding: 0 2px; position: absolute; top: 9px; right: 0; border-radius: 3px; }
.vocab-item .del:hover { color: var(--c-danger); background: #FBEDE8; }
.vocab-empty { color: var(--c-text-muted); text-align: center; padding: 28px 0; font-size: .85em; }
.vocab-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }
/* 「查词」按钮（2026-10-01 用户要求）：单独占一行，排在「清空生词本 / 添加单词」下面。
   ⚠️ 侧栏里 .vocab-add-action 的规则带 ID 选择器（#readingPage .vocab-sidebar … / #trainPage .train-rail …）
   特异性更高，会盖掉这两条 —— 所以这里对**我自己的两个选择器**提权（不影响站内其它任何元素）。 */
.vocab-actions { flex-wrap: wrap !important; }
.vocab-actions .vocab-lookup-action { flex: 1 0 100% !important; }
.vocab-actions button { flex: 1; padding: 6px 0; border-radius: var(--radius-sm); font-size: .78em; font-weight: 500; border: 1px solid var(--c-border); background: var(--c-white); color: var(--c-text-secondary); cursor: pointer; transition: all var(--transition-fast); }
.vocab-actions button:hover { background: #F5F5F4; }
.vocab-actions .vocab-merge-btn:hover { color: #4F6B36; border-color: #C6D3B6; background: #F7FEE7; }
.vocab-actions .vocab-clear:hover { color: var(--c-danger); border-color: #FECACA; background: #FEF2F2; }
.vocab-clear-all { color: var(--c-danger) !important; border-color: #FECACA !important; }
.vocab-clear-all:hover { background: #FBEDE8 !important; }

/* Vocab panel header highlight switch */
.vocab-hl { margin-left: auto; flex-shrink: 0; display: inline-flex; align-items: center; }
.vocab-hl input { display: none; }
.vocab-hl .vocab-hl-bar { height: 24px; padding: 0 9px; border-radius: 100px; font-size: .66em; font-weight: 600; color: var(--c-text-muted); background: #F5F5F4; border: 1px solid #E7E5E4; display: inline-flex; align-items: center; gap: 4px; cursor: pointer; user-select: none; white-space: nowrap; transition: all .15s; box-sizing: border-box; }
.vocab-hl .vocab-hl-bar svg { width: 11px; height: 11px; opacity: .8; }
.vocab-hl input:checked + .vocab-hl-bar { background: color-mix(in srgb, var(--c-accent) 16%, transparent); border-color: color-mix(in srgb, var(--c-accent) 55%, transparent); color: var(--c-accent-deep); box-shadow: 0 1px 4px color-mix(in srgb, var(--c-accent) 20%, transparent); }
.vocab-hl input:checked + .vocab-hl-bar svg { opacity: 1; }
html.dark .vocab-hl .vocab-hl-bar { background: #332E2A; border-color: #3F3A37; color: var(--c-text-muted); }
html.dark .vocab-hl input:checked + .vocab-hl-bar { background: color-mix(in srgb, var(--c-accent) 22%, transparent); border-color: var(--c-accent); color: var(--c-accent); box-shadow: 0 1px 4px rgba(0,0,0,.4); }

/* Vocab sidebar action row: green "add" at right slot */
.vocab-actions .vocab-add-action { display: inline-flex; align-items: center; justify-content: center; gap: 4px; color: #047857; border-color: #A7F3D0; background: #ECFDF5; }
.vocab-actions .vocab-add-action:hover { color: #065F46; border-color: #34D399; background: #D1FAE5; }
.vocab-actions .vocab-add-action svg { flex-shrink: 0; }
html.dark .vocab-actions .vocab-add-action { color: #6EE7B7; border-color: rgba(16,185,129,.45); background: rgba(16,185,129,.12); }
html.dark .vocab-actions .vocab-add-action:hover { color: #A7F3D0; background: rgba(16,185,129,.22); }

/* Right sidebar: obvious delete button */
.vocab-item .del { top: 50%; transform: translateY(-50%); width: 24px; height: 24px; display: inline-flex; align-items: center; justify-content: center; background: #F5F5F4; border: 1px solid #E7E5E4; color: #A8A29E; border-radius: 50%; font-size: 15px; line-height: 1; padding: 0; }
.vocab-item .del:hover { color: var(--c-danger); background: #FBEDE8; border-color: #FECACA; }
.vocab-item { padding-right: 30px; }
html.dark .vocab-item .del { background: #332E2A; border-color: #3F3A37; color: #A8A29E; }
html.dark .vocab-item .del:hover { color: #E08B76; background: rgba(166,61,42,.15); border-color: rgba(224,139,118,.45); }

/* Body highlight for user-added words/phrases (same amber family as HF; independent control) */
#readingContent .word.svhl, #trainSentence .word.svhl, #trainStem .word.svhl, #trainOptions .word.svhl { background: linear-gradient(transparent 58%, rgba(245,158,11,.38) 58%); border-radius: 2px; }
html.dark #readingContent .word.svhl, html.dark #trainSentence .word.svhl, html.dark #trainStem .word.svhl, html.dark #trainOptions .word.svhl { background: linear-gradient(transparent 42%, rgba(217,119,6,.55) 42%); }
/* 词组高亮（2026-10-17）：整条词组包成一个 span，底色连成一段；跨行时按行断开但样式连续 */
#readingContent .svhl-phrase, #trainSentence .svhl-phrase, #trainStem .svhl-phrase, #trainOptions .svhl-phrase { background: linear-gradient(transparent 58%, rgba(245,158,11,.38) 58%); border-radius: 3px; -webkit-box-decoration-break: clone; box-decoration-break: clone; }
html.dark #readingContent .svhl-phrase, html.dark #trainSentence .svhl-phrase, html.dark #trainStem .svhl-phrase, html.dark #trainOptions .svhl-phrase { background: linear-gradient(transparent 42%, rgba(217,119,6,.55) 42%); }
#readingContent .svhl-phrase .word, #trainSentence .svhl-phrase .word, #trainStem .svhl-phrase .word, #trainOptions .svhl-phrase .word { background: none; }

/* Reading title toolbar cluster: make HF switch / lock / lookup obvious */
#readingPage .reading-area .title .guard-title-toggle { background: linear-gradient(180deg, var(--c-white), color-mix(in srgb, var(--c-accent) 8%, var(--c-white))); border: 1px solid color-mix(in srgb, var(--c-accent) 22%, transparent); border-radius: 12px; padding: 4px 6px; box-shadow: 0 1px 4px color-mix(in srgb, var(--c-accent) 10%, transparent); }
#readingPage .reading-area .title .hf-switch { font-size: 13px; }
#readingPage .reading-area .title .switch { transform: scale(.9); transform-origin: center; }
html.dark #readingPage .reading-area .title .guard-title-toggle { background: linear-gradient(180deg, rgba(61,48,24,.42), rgba(61,48,24,.22)); border-color: rgba(217,119,6,.3); box-shadow: 0 1px 4px rgba(0,0,0,.3); }
@media (max-width: 768px), html.force-phone {
  #readingPage .reading-area .title .guard-title-toggle { padding: 3px 5px; border-radius: 16px; }
}

/* Clear Vocab Modal */
.clear-modal-overlay { position: fixed; inset: 0; background: rgba(41,37,36,.45); z-index: 500; display: none; align-items: center; justify-content: center; backdrop-filter: blur(4px); }
.clear-modal-overlay.show { display: flex; }
.clear-modal { background: var(--c-white); border-radius: var(--radius-lg); padding: 36px; max-width: 400px; width: 90%; text-align: center; box-shadow: var(--shadow-lg); animation: popIn .15s ease; }
.clear-modal h3 { font-size: 1.1em; font-weight: 600; color: var(--c-text); margin-bottom: 12px; }
.clear-modal p { color: var(--c-text-secondary); font-size: .9em; margin-bottom: 24px; line-height: 1.7; }
.clear-modal .btn-row { display: flex; gap: 10px; justify-content: center; }
.clear-modal .btn-row button { padding: 10px 28px; border-radius: var(--radius-sm); font-size: .88em; font-weight: 500; }
.clear-modal .btn-cancel-confirm { background: #F5F5F4; color: var(--c-text-secondary); border: 1px solid var(--c-border); }
.clear-modal .btn-cancel-confirm:hover { background: #E7E5E4; }
.clear-modal .btn-danger { background: var(--c-danger); color: #fff; transition: all var(--transition-normal); }
.clear-modal .btn-danger:disabled { background: #FECACA; color: #FDA4AF; cursor: not-allowed; }
.clear-modal .btn-danger:not(:disabled):hover { background: #8E3323; }
.clear-modal .countdown { color: var(--c-danger); font-weight: 600; font-size: 1.1em; }
/* 「这一篇你做过 → 继续做 / 重做」浮层（2026-10-08）：它是在**选题面板**（.reading-picker-overlay,
   z-index 600）之上打开的，所以必须高于 600 —— 否则面板会把这里按钮的点击全拦走（实测点不到）。 */
#redoAskModal { z-index: 620; }
/* ── 「这一篇你做过」浮层的卡片皮肤（2026-10-09 视觉重做）─────────────────────────
   原来它直接套 .clear-modal（跟「确认清除生词本」同一张脸、三颗同级灰按钮），
   而这是一次"继续学习"的邀请：继续做 = 实心橄榄绿主按钮（站内主色 --c-accent），
   重做 = 白底描边次按钮，取消 = 底部灰字逃生口。三条信息各归各位，不再挤在一段 <p> 里。 */
.redo-ask-card { width: min(430px, calc(100vw - 40px)); position: relative; overflow: hidden;
  background: var(--c-bg-card); border: 1px solid #E9E0D4; border-radius: 20px;
  /* 内边距按 2pt 网格收敛（原 26/24/18 与 4pt 体系对不齐）：
     左右 22px 给「取消」的焦点环留出呼吸位（原 18px 时 outline-offset 2 + ring 2 会被卡片边缘裁掉）；
     上 24 贴齐 4pt 尺度；下 22 与左右同值，视觉上真正对称。
     宽度 424 → 430：换算出内容列 386 > 两条最长说明 366，精确到不换行。 */
  padding: 24px 22px 22px; --way-px: 16px;
  box-shadow: 0 28px 64px -16px rgba(41,37,36,.28), 0 2px 8px rgba(41,37,36,.06);
  animation: redoAskIn .22s var(--ease-out-quart); }
@keyframes redoAskIn { from { opacity: 0; transform: translateY(8px) scale(.98); } to { opacity: 1; transform: none; } }
.redo-ask-card::before { content: ''; position: absolute; inset: 0 0 auto; height: 2px;
  background: linear-gradient(90deg, var(--c-accent), color-mix(in srgb, var(--c-accent) 25%, transparent)); }
.redo-ask-top { text-align: center; margin-bottom: 16px; }
/* 标题行高 1.6 → 1.35：1.6 是正文的行高，用在单行标题上会在字上下各留约 5px 幽灵空白，
   看起来"标题离徽章远、离时间也远"。font-size 16.96/1.19em 实测，保持不动。 */
.redo-ask-card h3 { margin: 9px 0 0; font-family: 'Noto Serif SC', serif; font-size: 1.06em;
  font-weight: 700; color: #5C4033; letter-spacing: .01em; line-height: 1.35; }
/* 成绩徽章：与题目训练长条上的 .sh-done 同一套语义色，扫描时是同一个记号。
   slop 修：圆标左内边距 4 → 3（右侧 11 与 15px 圆标之间原留 4px 才对齐），
   无分（score-none）时右侧也不需要 11px 的余量 → 收紧成 9。 */
.redo-ask-badge { display: inline-flex; align-items: center; gap: 6px; padding: 3px 11px 3px 3px;
  border-radius: 9999px; font-size: .74em; font-weight: 700; letter-spacing: .01em;
  font-variant-numeric: tabular-nums; background: #EFE8DC; color: #6B5D52; }
.redo-ask-badge[hidden] { display: none; }
.redo-ask-badge.score-none { padding-right: 9px; }
.redo-ask-badge .ic { flex: none; width: 15px; height: 15px; border-radius: 50%; background: #8C857B;
  color: #fff; display: inline-flex; align-items: center; justify-content: center; }
.redo-ask-badge .ic svg { width: 9px; height: 9px; display: block; }
.redo-ask-badge.score-good { background: rgba(79,107,54,.11); color: #3F5530; }
.redo-ask-badge.score-good .ic { background: #4F6B36; }
.redo-ask-badge.score-mid { background: rgba(138,106,47,.11); color: #7A5A24; }
.redo-ask-badge.score-mid .ic { background: #8A6A2F; }
.redo-ask-badge.score-low { background: rgba(155,59,46,.10); color: #9B3B2E; }
.redo-ask-badge.score-low .ic { background: #9B3B2E; }
.redo-ask-time { margin: 6px 0 0; font-size: .78em; color: var(--c-text-muted);
  font-variant-numeric: tabular-nums; }
.redo-ask-time[hidden] { display: none; }
.redo-ask-ways { display: flex; flex-direction: column; gap: 10px; }
/* 两条路 = 两张可点整块的卡（不是并排小按钮）：说明文字跟着路走，不再堆在正文里。
   边框 1.5 → 1（1.5px 在 1x 屏上被量化成 1 或 2、两边会不一样粗；站内其它卡也都是 1px）；
   底边框色由 #E7E5E4 改为 #E3DED7，与卡片的暖纸底同色系，不再发灰。 */
.redo-way { display: flex; align-items: center; gap: 12px; width: 100%; padding: 12px var(--way-px);
  font-family: inherit; font-size: .9em; text-align: left; border-radius: 14px; cursor: pointer;
  background: #fff; border: 1px solid #E3DED7; color: var(--c-text-secondary);
  transition: border-color .18s var(--ease-out-quart), background-color .18s var(--ease-out-quart),
              box-shadow .18s var(--ease-out-quart), transform .12s var(--ease-out-quart); }
.redo-way > svg { flex: none; width: 20px; height: 20px; }
.redo-way-tx { min-width: 0; display: flex; flex-direction: column; gap: 3px; }
/* 主次层级：主路径的动词更大（1.14em vs 1.06em），次路径的动词更实（#44403C 而不是灰），
   这样"哪条是推荐的""哪个词是动作"都不用靠颜色去猜。 */
.redo-way-tx b { font-size: 1.06em; font-weight: 700; color: #44403C; }
.redo-way-tx i { font-style: normal; font-size: .8em; line-height: 1.5; color: var(--c-text-muted); }
.redo-way:hover { border-color: #C6B8A6; background: #FDFAF6; }
.redo-way:active { transform: scale(.985); }
.redo-way:focus-visible { outline: 2px solid var(--c-accent); outline-offset: 2px; }
/* 主路径：继续做 */
.redo-way.primary { background: color-mix(in srgb, var(--c-accent) 9%, var(--c-bg-card));
  border-color: color-mix(in srgb, var(--c-accent) 42%, transparent); color: var(--c-accent-deep);
  box-shadow: 0 1px 3px rgba(90,110,69,.1); }
.redo-way.primary .redo-way-tx b { font-size: 1.14em; color: #3F5530; }
.redo-way.primary > svg { color: var(--c-accent); }
.redo-way.primary:hover { background: color-mix(in srgb, var(--c-accent) 15%, var(--c-bg-card));
  border-color: color-mix(in srgb, var(--c-accent) 62%, transparent); }
/* 逃生口：取消是一行灰字，不再是一颗与主操作同重量的按钮 */
.redo-ask-cancel { display: block; margin: 10px auto 0; padding: 7px 16px; border: 0;
  background: none; font-family: inherit; font-size: .82em; color: var(--c-text-muted);
  border-radius: 9999px; cursor: pointer;
  transition: color .18s var(--ease-out-quart), background-color .18s var(--ease-out-quart); }
.redo-ask-cancel:hover { color: var(--c-accent); background: color-mix(in srgb, var(--c-accent) 10%, transparent); }
.redo-ask-cancel:focus-visible { outline: 2px solid var(--c-accent); outline-offset: 2px; }
/* 暗色一套（站内暗色块也都按需重写，不靠继承） */
html.dark .redo-ask-card { background: #262220; border-color: #3A322C;
  box-shadow: 0 28px 64px -16px rgba(0,0,0,.6), 0 2px 8px rgba(0,0,0,.3); }
html.dark .redo-ask-card h3 { color: #F0EAE2; }
html.dark .redo-ask-badge { background: #2A2521; color: #B5A797; }
html.dark .redo-ask-badge .ic { background: #7E776D; color: #1C1917; }
html.dark .redo-ask-badge.score-good { background: rgba(163,185,140,.15); color: #CEDFB2; }
html.dark .redo-ask-badge.score-good .ic { background: #A3B98C; color: #21260F; }
html.dark .redo-ask-badge.score-mid { background: rgba(232,209,155,.14); color: #E8D19B; }
html.dark .redo-ask-badge.score-mid .ic { background: #E8D19B; color: #3A2D12; }
html.dark .redo-ask-badge.score-low { background: rgba(240,169,155,.13); color: #FFC4B8; }
html.dark .redo-ask-badge.score-low .ic { background: #F0A99B; color: #3A1F1A; }
/* 暗色下"白底卡"换成比卡片亮一档的表面色（暗色深度靠亮度差，不靠阴影），
   与主路径的暗绿底形成有方向的层次；次路径动词提到 #E9E3DB，明确比它的说明文字更重。 */
html.dark .redo-way { background: #2E2925; border-color: #423A33; }
html.dark .redo-way-tx b { color: #E9E3DB; }
html.dark .redo-way-tx i { color: #A99F94; }
html.dark .redo-way:hover { background: #352F2A; border-color: #55493F; }
html.dark .redo-way.primary { background: #2A3123;
  border-color: rgba(163,185,140,.45); box-shadow: 0 1px 3px rgba(0,0,0,.35); }
html.dark .redo-way.primary .redo-way-tx b { color: #CEDFB2; }
html.dark .redo-way.primary > svg { color: #A3B98C; }
html.dark .redo-way.primary:hover { background: #333C29; border-color: rgba(163,185,140,.7); }
html.dark .redo-ask-cancel { color: #A99F94; }
html.dark .redo-ask-cancel:hover { color: #CEDFB2; background: rgba(163,185,140,.12); }
@media (prefers-reduced-motion: reduce) {
  .redo-ask-card { animation: none; }
  .redo-way, .redo-ask-cancel { transition: color .01ms, border-color .01ms, background-color .01ms; }
  .redo-way:active { transform: none; }
}
@media (max-width: 480px) {
  .redo-ask-card { padding: 20px 16px 16px; --way-px: 14px; }
  .redo-way { gap: 10px; }
  .redo-way-tx i { font-size: .76em; }
}
/* ── 手动添加弹窗 ── */
.add-modal-overlay { position: fixed; inset: 0; background: rgba(41,37,36,.5); z-index: 500; display: none; align-items: center; justify-content: center; backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); }
.add-modal-overlay.show { display: flex; }
.add-modal { position: relative; width: min(370px, calc(100vw - 40px)); background: #F8F4EE; border: 1px solid rgba(90,110,69,.14); border-radius: 20px; padding: 28px 26px 24px; box-shadow: 0 24px 64px rgba(0,0,0,.18), 0 2px 8px rgba(0,0,0,.06); animation: addModalIn .24s cubic-bezier(.2,.8,.2,1); }
@keyframes addModalIn { from { opacity: 0; transform: translateY(16px) scale(.96); } to { opacity: 1; transform: none; } }
/* ── 「添加单词」改成可拖动的浮窗（2026-10-23 用户要求）──────────────────────
   只有 #addItemModal 去掉遮罩 + 允许拖动；拍照 / 报错 / 计时 / 导入进度同样复用 .add-modal，
   它们保持原来的居中弹窗（别一起改了）。
   遮罩去掉后页面照常能点（pointer-events:none），所以必须能拖开，否则挡着正文。 */
#addItemModal.add-float { background: transparent; backdrop-filter: none; -webkit-backdrop-filter: none; pointer-events: none; }
#addItemModal.add-float .add-modal { position: fixed; pointer-events: auto; }
#addItemModal.add-float .add-modal-head { cursor: move; touch-action: none; user-select: none; -webkit-user-select: none; }
#addItemModal.add-float .add-modal.dragging { cursor: grabbing; box-shadow: 0 30px 72px rgba(0,0,0,.24), 0 3px 10px rgba(0,0,0,.08); }
html.dark #addItemModal.add-float .add-modal.dragging { box-shadow: 0 30px 72px rgba(0,0,0,.62); }
/* 联想列表默认挂在卡片**下方**（绝对定位）；卡片被拖到屏幕下半部时它会跑出视口 →
   没地方就翻到卡片上方（见 addFloatSuggestFit），列表始终可见可点。 */
#addItemModal.add-float .add-modal.suggest-up .suggest-list { top: auto; bottom: calc(100% + 6px); }
.add-modal-close { position: absolute; top: 14px; right: 14px; width: 30px; height: 30px; border-radius: 50%; border: none; background: transparent; color: var(--c-text-muted); font-size: .95em; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: all var(--transition-fast); }
.add-modal-close:hover { background: #F5F0E6; color: var(--c-text); }
.add-modal-head { display: flex; align-items: center; gap: 14px; margin-bottom: 20px; }
.add-modal-icon { width: 50px; height: 50px; border-radius: 14px; background: #62764E; color: #fff; display: flex; align-items: center; justify-content: center; flex-shrink: 0; box-shadow: 0 8px 20px rgba(90,110,69,.28); }
.add-modal-icon svg { width: 25px; height: 25px; }
.add-modal-icon .ico-phrase { display: none; }
.add-modal-overlay.mode-phrase .add-modal-icon .ico-word { display: none; }
.add-modal-overlay.mode-phrase .add-modal-icon .ico-phrase { display: block; }
.add-modal h3 { font-size: 1.28em; font-weight: 700; color: var(--c-text); margin: 0 0 2px; }
.add-modal .add-item-sub { margin: 0; font-size: .82em; color: var(--c-text-muted); }
.add-modal input#addItemInput { width: 100%; padding: 13px 16px; border-radius: 18px; border: 1.5px solid var(--c-border); background: #fff; font-size: 1em; color: var(--c-text); outline: none; transition: border-color var(--transition-normal), box-shadow var(--transition-normal); }
.add-modal input#addItemInput:focus { border-color: var(--c-accent); box-shadow: 0 0 0 3px rgba(90,110,69,.14); }
.suggest-list { position: absolute; top: calc(100% + 6px); left: 0; right: 0; z-index: 60; display: flex; flex-direction: column; max-height: 220px; overflow-y: auto; border: 1px solid var(--c-border); border-radius: 18px; background: #fff; box-shadow: 0 12px 32px rgba(0,0,0,.14); opacity: 0; transform: translateY(-6px); pointer-events: none; visibility: hidden; transition: opacity .18s ease, transform .18s ease, visibility .18s; }
.suggest-list.show { opacity: 1; transform: translateY(0); pointer-events: auto; visibility: visible; }
.suggest-item { display: flex; align-items: center; gap: 10px; padding: 8px 14px; border: none; background: transparent; cursor: pointer; text-align: left; font-size: .86em; border-radius: 16px; width: 100%; }
.suggest-item:hover, .suggest-item.sel { background: #FFFBEB; }
.suggest-item .si-word { font-weight: 600; color: var(--c-text); flex-shrink: 0; }
.suggest-item .si-mean { font-size: .78em; color: var(--c-text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
html.dark .suggest-list { background: #292524; border-color: #3F3A37; }
html.dark .suggest-item:hover, html.dark .suggest-item.sel { background: #332E2A; }
html.dark .suggest-item .si-word { color: #EDE9E6; }
.add-modal-btns { display: flex; gap: 10px; }
.add-modal-btns button { flex: 1; height: 44px; border-radius: 18px; font-size: .92em; font-weight: 600; cursor: pointer; transition: all var(--transition-normal); }
.add-btn-cancel { background: #F5F0E6; color: var(--c-text-secondary); border: 1px solid transparent; }
.add-btn-cancel:hover { background: #EFE7DA; color: var(--c-text); }
.add-btn-confirm { background: #62764E; color: #fff; border: none; box-shadow: 0 6px 16px rgba(90,110,69,.28); }
.add-btn-confirm:hover { transform: translateY(-1px); box-shadow: 0 10px 22px rgba(90,110,69,.34); }
.add-btn-confirm:active { transform: translateY(0) scale(.98); }

/* ── 「添加单词」紧凑版（2026-10-23 用户要求：卡片做小、去掉没用的装饰和文字）────
   只作用于 #addItemModal；拍照 / 报错 / 计时 / 导入进度同样复用 .add-modal，保持原尺寸。
   砍掉：左侧 50px 图标块、副标题、底部提示行；标题与 ✕ 并成一行，按钮右对齐做小。 */
#addItemModal .add-modal { width: min(320px, calc(100vw - 32px)); padding: 14px 16px 12px; border-radius: 14px;
  box-shadow: 0 16px 40px rgba(0,0,0,.16), 0 2px 6px rgba(0,0,0,.05); }
#addItemModal .add-modal-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin: 0 0 8px; padding: 1px 0 7px; }   /* 这一条是拖动把手，留够高度才好抓 */
#addItemModal .add-modal h3 { font-size: .95em; font-weight: 700; margin: 0; line-height: 1.3; }
#addItemModal .add-modal-close { position: static; width: 24px; height: 24px; flex-shrink: 0; margin: -2px -6px -2px 0; }
#addItemModal .add-modal input#addItemInput { padding: 9px 12px; border-radius: 9px; font-size: .92em; }
#addItemModal .add-modal-btns { display: flex; justify-content: flex-end; gap: 8px; margin-top: 10px; }
#addItemModal .add-modal-btns button { flex: 0 0 auto; height: 32px; padding: 0 16px; border-radius: 10px; font-size: .82em; }
#addItemModal .add-btn-cancel { background: transparent; padding: 0 10px; color: var(--c-text-muted); }
#addItemModal .add-btn-cancel:hover { background: #EFE7DA; color: var(--c-text); }
#addItemModal .add-btn-confirm { box-shadow: none; }
#addItemModal .add-btn-confirm:hover { transform: none; box-shadow: none; }
#addItemModal .add-btn-confirm:active { transform: scale(.98); }
html.dark #addItemModal .add-btn-cancel { background: transparent; }
html.dark #addItemModal .add-btn-cancel:hover { background: #332E2A; color: #E7E5E4; }
html.dark #addItemModal input#addItemInput { background: #332E2A; border-color: #3F3A37; color: #EDE9E6; }

@keyframes panelReveal { from { opacity: 0; transform: translateY(12px) scale(.96); } to { opacity: 1; transform: translateY(0) scale(1); } }
.ai-greet { position: fixed; right: 88px; bottom: 34px; background: var(--c-white); border-radius: var(--radius-md); box-shadow: 0 8px 24px rgba(0,0,0,.08); padding: 16px 36px 16px 20px; z-index: 92; max-width: 280px; display: none; border: 1px solid rgba(120,113,108,.06); animation: msgReveal .3s ease both; }
.ai-greet.show { display: block; }
.ai-greet p { font-size: .88em; color: var(--c-text-secondary); line-height: 1.7; margin: 0; }
.ai-greet .greet-close { position: absolute; top: 6px; right: 8px; background: none; color: var(--c-text-muted); font-size: .95em; padding: 2px 6px; border-radius: 3px; }
.ai-greet .greet-close:hover { background: #F5F5F4; color: var(--c-text); }
.ai-greet::after { content: ''; position: absolute; right: -7px; bottom: 16px; width: 0; height: 0; border: 1px solid var(--c-white); border-top: 7px solid transparent; border-bottom: 7px solid transparent; }

/* ── Feedback Float ── */
.fb-float-btn { position: fixed; right: 24px; bottom: 88px; width: 52px; height: 52px; border-radius: 50%; background: var(--c-accent); color: #fff; box-shadow: 0 4px 14px rgba(90,110,69,.32), 0 1px 3px rgba(92,64,51,.12); display: flex; align-items: center; justify-content: center; cursor: pointer; z-index: 88; border: none; overflow: visible; transition: all .5s ease; }
.fb-float-btn:hover { transform: scale(1.06); background: var(--c-accent-hover); box-shadow: 0 10px 26px rgba(74,92,56,.34), 0 2px 6px rgba(92,64,51,.14); }
.fb-float-btn svg { width: 24px; height: 24px; transition: all .5s ease; z-index: 2; border-radius: 50%; }
.fb-float-btn:hover svg { transform: scale(1.05); }
.fb-float-btn:active { background: #3F5230; transform: scale(.94); transition: all 100ms ease; }
.fb-float-btn .now { position: absolute; left: 0; transform: translateX(-120%); transition: all .5s ease; z-index: 2; white-space: nowrap; color: #fff; background: var(--c-accent); border-radius: 9999px; padding: 4px 10px; font-size: 13px; font-weight: 400; line-height: 1.4; opacity: 0; pointer-events: none; }
.fb-float-btn:hover .now { transform: translateX(4px); transition-delay: 300ms; opacity: 1; }
.fb-float-btn:hover .play { transform: translateX(200%); transition-delay: 300ms; opacity: 0; }
.fb-float-btn .play { display: flex; transition: all .5s ease; transition-delay: 300ms; }
.fb-float-btn .fb-unread-dot { position: absolute; top: -4px; right: -4px; width: 12px; height: 12px; border-radius: 50%; background: var(--c-danger); border: 2px solid #fff; z-index: 3; box-shadow: 0 1px 3px rgba(0,0,0,.25); }
.fb-unread-dot { position: absolute; top: 0; right: 0; width: 10px; height: 10px; border-radius: 50%; background: var(--c-danger); border: 2px solid #fff; }
.fb-tab { background: none; border: 1px solid transparent; color: var(--c-text-muted); padding: 3px 12px; border-radius: 100px; font-size: .78em; font-weight: 500; transition: all .15s; }
.fb-tab.active { background: var(--c-accent); color: #fff; border-color: var(--c-accent); }
.fb-tab:hover:not(.active) { color: var(--c-accent); }
.fb-float-panel { position: fixed; right: 24px; bottom: 148px; width: 380px; height: 440px; background: var(--c-white); border-radius: var(--radius-lg); box-shadow: 0 12px 40px rgba(0,0,0,.1), 0 4px 12px rgba(0,0,0,.06), 0 1px 3px rgba(0,0,0,.04); border: 1px solid rgba(120,113,108,.08); display: none; flex-direction: column; z-index: 87; animation: panelReveal .2s cubic-bezier(.34,1.2,.64,1) both; }
.fb-float-panel.show { display: flex; }
.fb-float-panel .fb-float-head { display: flex; align-items: center; justify-content: space-between; padding: 14px 18px; border-bottom: 1px solid rgba(120,113,108,.06); flex-shrink: 0; background: linear-gradient(180deg, #F5EFE4, var(--c-white)); border-radius: var(--radius-lg) var(--radius-lg) 0 0; }
.fb-float-panel .fb-float-head span { font-family: 'Noto Serif SC', serif; font-weight: 600; font-size: .9em; color: var(--c-text); letter-spacing: .01em; display: flex; align-items: center; gap: 8px; }
.fb-float-panel .fb-float-head span svg { color: var(--c-accent); width: 16px; height: 16px; }
.fb-float-panel .fb-float-head button { background: none; color: var(--c-text-muted); padding: 4px 10px; border-radius: var(--radius-sm); font-size: .85em; transition: all .1s; }
.fb-float-panel .fb-float-head button:hover { background: #FBEDE8; color: var(--c-danger); }
.fb-float-panel .fb-float-list { flex: 1; overflow-y: auto; padding: 12px 16px; }
.fb-float-card { padding: 10px 14px; border-radius: var(--radius-sm); margin-bottom: 8px; background: #FAFAF9; border: 1px solid #F0EFED; transition: border-color .15s; }
.fb-float-card:hover { border-color: #E0DED9; }
.fb-float-card .fb-float-msg { font-size: .84em; line-height: 1.65; color: var(--c-text); margin-bottom: 5px; }
.fb-float-card .fb-float-meta { font-size: .72em; color: var(--c-text-muted); display: flex; align-items: center; gap: 8px; }
.fb-float-del, .fb-float-edit { margin-left: 2px; background: none; border: 1px solid transparent; color: var(--c-text-muted); cursor: pointer; padding: 3px 5px; border-radius: 4px; transition: all .1s; line-height: 1; display: inline-flex; align-items: center; }
.fb-float-del svg, .fb-float-edit svg { width: 12px; height: 12px; }
.fb-float-edit:hover { color: var(--c-accent); background: #F5EFE4; border-color: var(--c-accent-light); }
.fb-float-del:hover { color: var(--c-danger); background: #FBEDE8; border-color: #FECACA; }
.fb-float-card .fb-float-cat { font-size: .7em; padding: 1px 7px; border-radius: 100px; font-weight: 500; }
.fb-float-card.cat-func .fb-float-cat { background: #F5EFE4; color: #5C4033; }
.fb-float-card.cat-ux .fb-float-cat, .fb-float-card.cat-data .fb-float-cat { background: #FBEDE8; color: #8E3323; }
.fb-float-card.cat-idea .fb-float-cat { background: #EEF2E9; color: #3F5530; }
.fb-float-panel .fb-float-input { padding: 10px 16px 14px; border-top: 1px solid rgba(120,113,108,.06); flex-shrink: 0; display: flex; gap: 6px; align-items: flex-end; background: var(--c-bg); border-radius: 0 0 var(--radius-lg) var(--radius-lg); }
.fb-float-panel .fb-float-input select { padding: 6px 8px; border: 1px solid rgba(120,113,108,.1); border-radius: var(--radius-sm); font-size: .76em; background: var(--c-white); color: var(--c-text-secondary); outline: none; cursor: pointer; transition: border-color .15s; }
.fb-float-panel .fb-float-input select:focus { border-color: var(--c-accent); }
.fb-float-panel .fb-float-input textarea { flex: 1; padding: 7px 10px; border: 1px solid rgba(120,113,108,.1); border-radius: var(--radius-sm); font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; font-size: .82em; line-height: 1.5; resize: none; outline: none; min-height: 32px; max-height: 60px; background: var(--c-white); color: var(--c-text); transition: border-color .15s, box-shadow .15s; }
.fb-float-panel .fb-float-input textarea:focus { border-color: var(--c-accent); box-shadow: 0 0 0 3px rgba(90,110,69,.06); }
.fb-float-panel .fb-float-input button { padding: 7px 16px; background: var(--c-accent); color: #fff; border-radius: var(--radius-sm); font-size: .8em; font-weight: 600; white-space: nowrap; box-shadow: 0 2px 4px rgba(90,110,69,.15); transition: all .15s; }
.fb-float-panel .fb-float-input button:hover { background: var(--c-accent-hover); box-shadow: 0 4px 8px rgba(90,110,69,.2); transform: translateY(-1px); }
.fb-float-panel .fb-float-input button:active { transform: translateY(0); box-shadow: 0 1px 2px rgba(90,110,69,.1); }
.fb-float-panel .fb-float-input button:disabled { opacity: .45; cursor: not-allowed; transform: none; box-shadow: none; }
.fb-service-line { padding: 6px 12px; font-size: .72em; color: var(--c-text-muted); text-align: center; border-top: 1px solid rgba(120,113,108,.08); background: var(--c-bg); border-radius: 0 0 var(--radius-lg) var(--radius-lg); letter-spacing: .02em; flex-shrink: 0; }
html.dark .fb-service-line { border-top-color: #3F3A37; }
.fb-float-empty { text-align: center; padding: 48px 20px; color: var(--c-text-muted); font-size: .85em; line-height: 1.8; }
.fb-float-empty svg { display: block; margin: 0 auto 10px; opacity: .2; }
@media (max-width: 768px), html.force-tablet {
  .fb-float-panel { width: 340px; height: 380px; right: 12px; bottom: 128px; }
  .fb-float-btn { right: 12px; bottom: 72px; }
}
html.force-phone .fb-float-btn { right: 12px; bottom: 128px; width: 42px; height: 42px; }
html.force-phone .fb-float-btn svg { width: 21px; height: 21px; }
html.force-phone .fb-float-panel { width: calc(100vw - 24px); height: 50vh; right: 12px; bottom: 180px; left: 12px; }

/* ── Admin Page ── */
#adminPage .topbar { top: 4px; }
.admin-page { max-width: 680px; margin: 0 auto; padding: 56px 24px 48px; display: none; }
.admin-page.show { display: block; }

/* 指标卡：**一张统一网格**（手机 3 列 / 桌面 4 列），组标签 `grid-column: 1/-1` 横跨整行做分隔。
   试过三种排法，记录一下取舍：
     ① 每组一行、行内 auto-fill → 短的那组（系统 2 张）右边空一半；
     ② 每组一行、行内 1fr 平分 → 行填满了，但 2 张卡各拉 570px（里面只有一个 0），别扭；
     ③ 每行按张数封顶 → 卡片宽 183~262 不等，**列左缘出现 8~20px 台阶**，比留白更难看。
   现在这版：卡片尺寸统一、列严格对齐，不满的行末尾是空白（格网里这是正常留白，不刺眼）。 */
.admin-stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin-bottom: 24px; }
.admin-stat-card { background: var(--c-white); border-radius: var(--radius-md); padding: 18px 16px; box-shadow: var(--shadow-sm); border: 1px solid var(--c-border); text-align: center; position: relative; overflow: hidden; }
.admin-stat-card::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px; }
.admin-stat-card.s-today::before { background: var(--c-accent); }
.admin-stat-card.s-yesterday::before { background: var(--c-primary-light); }
.admin-stat-card.s-total::before { background: var(--c-primary-dark); }
.admin-stat-card.s-users::before { background: #8B9D77; }
.admin-stat-card.s-new::before { background: #4F6B36; }
.admin-stat-card.s-active::before { background: #A8804E; }
.admin-stat-card.s-today-online::before { background: #0EA5E9; }
.admin-stat-card.s-online30::before { background: #D946EF; }
.admin-stat-card .stat-num { font-family: 'Noto Serif SC', serif; font-size: 2.2em; font-weight: 700; color: var(--c-text); line-height: 1; margin-bottom: 2px; }
.admin-stat-card .stat-label { font-size: .75em; color: var(--c-text-muted); letter-spacing: .03em; }

.admin-chart { background: var(--c-white); border-radius: var(--radius-md); padding: 20px 22px; box-shadow: var(--shadow-sm); border: 1px solid var(--c-border); margin-bottom: 24px; }
.admin-chart h3 { font-family: 'Noto Serif SC', serif; font-size: .88em; font-weight: 600; color: var(--c-text); margin-bottom: 16px; letter-spacing: .01em; }
.admin-bars { display: flex; align-items: flex-end; gap: 12px; height: 72px; padding: 0 4px; }
.admin-bar-wrap { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 4px; }
.admin-bar { width: 100%; border-radius: 4px 4px 0 0; background: linear-gradient(180deg, var(--c-accent), #E9E0D4); min-height: 4px; transition: height .4s ease; }
.admin-bar-label { font-size: .62em; color: var(--c-text-muted); }
/* ── 在线人数折线（2026-10-13）：纯内联 SVG，不引图表库。
      宽度 100%、高度按 viewBox 等比 → 手机/平板都不用另写一套尺寸。 ── */
.admin-line { display: block; max-width: 100%; height: auto; }
.admin-line .ln-gl { stroke: var(--c-border); stroke-width: 1; }
.admin-line .ln-tx { fill: var(--c-text-muted); font-size: 10px; }
.admin-line .ln-ar { fill: color-mix(in srgb, var(--c-accent) 14%, transparent); }
.admin-line .ln-ln { fill: none; stroke: var(--c-accent-deep); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.admin-line .ln-pt { fill: var(--c-accent-deep); }

.admin-section { margin-bottom: 24px; }
.admin-section-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.admin-section-head.clickable { cursor: pointer; }
.admin-section-head.clickable:hover h3 { color: var(--c-accent); }
.admin-section-head h3 { font-family: 'Noto Serif SC', serif; font-size: .88em; font-weight: 600; color: var(--c-text); letter-spacing: .01em; transition: color .15s; }
.admin-section-head span { font-size: .78em; color: var(--c-text-muted); }

.admin-item-card { background: var(--c-white); border-radius: var(--radius-md); padding: 14px 16px; box-shadow: var(--shadow-sm); border: 1px solid var(--c-border); margin-bottom: 8px; transition: box-shadow .15s; }
.admin-item-card:hover { box-shadow: var(--shadow-md); }
.admin-item-card .ai-msg { font-size: .86em; line-height: 1.65; color: var(--c-text); margin-bottom: 6px; }
.admin-item-card .ai-meta { font-size: .74em; color: var(--c-text-muted); display: flex; align-items: center; gap: 8px; }

@media (max-width: 768px), html.force-tablet { 
  .admin-page { padding: 52px 16px 36px; } 
  .admin-stat-card { padding: 14px 12px; } 
  .admin-stat-card .stat-num { font-size: 1.6em; } 
}
html.force-phone .admin-page { padding: 68px 10px 28px; }
html.force-phone .admin-stat-card { padding: 12px 8px; }
html.force-phone .admin-stat-card .stat-num { font-size: 1.3em; }
/* 手机端组间距收紧（组标签在窄屏也保留，它承担"这组是什么"的信息） */
html.force-phone .admin-stat-group { margin: 12px 0 6px; }

/* ── 桌面管理台外壳（2026-09-20）──
   原来整页是一个 `max-width: 680px` 的窄单列（手机布局放大）。宽屏下拆成
   「贴屏幕最左边的固定侧栏 + 右侧内容区 + 通栏顶栏」——用户明确要求侧栏要在最左边，
   所以它是 `position: fixed; left: 0`，不再跟着居中列飘。
   ⚠️ 形态由 `#adminPage.admin-desktop` 一个类驱动（JS: adminSyncShell），不用媒体查询 ——
      媒体查询会跟 html.force-desktop / force-tablet 打架（速记页那次实测出过组合漏洞）。
      不加这个类时下面全部规则不生效，窄屏保持原来的单列堆叠。
   尺寸约定：--admin-nav-w = 侧栏宽；--admin-top-h = 顶栏高。 */
#adminPage { --admin-nav-w: 216px; --admin-top-h: 56px; }
.admin-shell-wrap { min-width: 0; }
.admin-nav { display: none; }
.admin-view { min-width: 0; }
.admin-updated, .admin-refresh, .admin-crumb { display: none; }

#adminPage.admin-desktop { max-width: none; padding: 0; }
/* 侧栏：贴屏幕最左边、整列固定 */
#adminPage.admin-desktop .admin-nav {
  display: flex; flex-direction: column; gap: 2px;
  position: fixed; left: 0; top: 0; bottom: 0; width: var(--admin-nav-w); z-index: 50;
  padding: 14px 12px 14px; overflow-y: auto;
  background: #FFFCF8;                    /* 比页面暖底更实一层（product 登记册里说的"第二层中性色"） */
  border-right: 1px solid var(--c-border);
}
html.dark #adminPage.admin-desktop .admin-nav { background: #232019; border-right-color: #3F3A37; }
.admin-nav-brand { display: flex; align-items: center; gap: 8px; padding: 4px 10px 14px;
  font-size: .95em; font-weight: 800; color: var(--c-text); letter-spacing: .01em; }
.admin-nav-logo { display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 26px;
  border-radius: 16px; background: #62764E; color: #fff; font-size: .9em;
  box-shadow: 0 4px 10px rgba(90,110,69,.3); }
.admin-nav-item { display: flex; align-items: center; gap: 10px; text-align: left;
  min-height: 40px; padding: 9px 10px; border: 0; border-radius: 16px; background: transparent;
  color: var(--c-text-secondary); font: inherit; font-size: .88em; font-weight: 600; cursor: pointer;
  transition: background var(--transition-fast), color var(--transition-fast); }
.admin-nav-item svg { width: 16px; height: 16px; flex: none; opacity: .8; }
.admin-nav-item:hover { background: #F4EEE2; color: var(--c-text); }
.admin-nav-item.sel { background: var(--c-accent); color: #fff; box-shadow: 0 4px 12px rgba(217,119,6,.25); }
.admin-nav-item.sel svg { opacity: 1; }
.admin-nav-item em { font-style: normal; margin-left: auto; font-size: .8em; font-weight: 700;
  color: var(--c-accent-deep); background: rgba(90,110,69,.12); border-radius: 999px; padding: 1px 7px; }
.admin-nav-item.sel em { color: #fff; background: rgba(255,255,255,.22); }
.admin-nav-item em:empty { display: none; }
html.dark .admin-nav-item:hover { background: rgba(255,255,255,.07); }
html.dark .admin-nav-item.sel { color: #1C1917; }
html.dark .admin-nav-item em { color: #E9E0D4; background: rgba(163,185,140,.16); }
.admin-nav-back { margin-top: auto; display: flex; align-items: center; gap: 10px; min-height: 38px; padding: 8px 10px;
  border: 0; border-top: 1px solid var(--c-border); background: none; color: var(--c-text-muted);
  font: inherit; font-size: .84em; font-weight: 600; cursor: pointer; }
.admin-nav-back:hover { color: var(--c-text); }
.admin-nav-back svg { width: 15px; height: 15px; }

/* 顶栏：桌面外壳里变成**贴内容区顶部的通栏**（不再居中漂浮，和侧栏/内容对齐） */
#adminPage.admin-desktop .topbar {
  position: fixed; top: 0; left: var(--admin-nav-w); right: 0; height: var(--admin-top-h);
  width: auto; max-width: none; margin: 0; padding: 0 24px; border-radius: 0; border-bottom: 1px solid var(--c-border);
  justify-content: flex-start; gap: 12px; background: rgba(255,252,246,.86); backdrop-filter: blur(16px);
  box-shadow: none;
}
#adminPage.admin-desktop .topbar .back { display: none; }   /* 返回首页挪到侧栏底部 */
/* 顶栏**不再重复品牌名**：侧栏顶部已经有「⚙ 管理中心」，这里只显示当前分区（面包屑即页面标题） */
#adminPage.admin-desktop .topbar .info { display: none; }
#adminPage.admin-desktop .admin-crumb { display: inline-flex; align-items: center; font-size: 1.02em; font-weight: 800; color: var(--c-text); }
#adminPage.admin-desktop .admin-crumb::before { content: none; }

/* 内容区：让开侧栏与顶栏；内容自身限宽并居中在剩余区域里 */
#adminPage.admin-desktop .admin-shell-wrap { margin-left: var(--admin-nav-w); padding-top: var(--admin-top-h); }
#adminPage.admin-desktop .admin-views { max-width: 1220px; margin: 0 auto; padding: 20px 28px 28px; }
#adminPage.admin-desktop .admin-view { display: none; }
#adminPage.admin-desktop .admin-view.on { display: block; }
/* ── 手机端底部导航（2026-09-20）──
   手机管理页原来是"五个分区全堆在一列往下滚"，现在给一条底部栏、一次只看一个分区
   （与桌面外壳同一套视图切换逻辑，只是导航从侧栏换成底部栏）。
   底部栏复用 .phone-tab-bar 的视觉，所以不加外壳时才有意义 —— 选择器带上 :not(.admin-desktop)。 */
#adminPage:not(.admin-desktop) .admin-tab-bar { display: flex; }
#adminPage:not(.admin-desktop) .admin-view { display: none; }
#adminPage:not(.admin-desktop) .admin-view.on { display: block; }
/* 角标要相对"按钮"定位，所以给按钮加 relative（共享的 .phone-tab-bar button 有 position:relative，
   但这里不依赖它：作用域收在管理页底部栏内，避免动到阅读页那条栏） */
#adminPage .admin-tab-bar button { position: relative; }
#adminPage .admin-tab-badge { position: absolute; top: 2px; left: 50%; margin-left: 6px; min-width: 15px; height: 15px;
  padding: 0 4px; border-radius: 999px; background: var(--c-danger); color: #fff;
  font-size: .58em; font-weight: 800; font-style: normal; line-height: 15px; text-align: center; }
#adminPage .admin-tab-badge:empty { display: none; }
/* 手机形态：内容区给底部栏留位（force-phone 下 body 已有 64px，这只兜住"窄窗口但没加 force-phone"的情况）；
   顶栏也开始显示当前分区名 —— 底部栏一眼能看出在哪，文字是第二重确认 */
#adminPage:not(.admin-desktop) .admin-views { padding-bottom: 76px; }
#adminPage:not(.admin-desktop) .admin-crumb { display: inline-flex; align-items: center; }
#adminPage:not(.admin-desktop) .admin-crumb::before { content: '·'; color: var(--c-border); margin-right: 6px; }

#adminPage.admin-desktop .admin-updated { display: inline; margin-left: auto; font-size: .76em; color: var(--c-text-muted); white-space: nowrap; }
#adminPage.admin-desktop .admin-refresh { display: inline-flex; align-items: center; gap: 6px; padding: 7px 14px;
  border: 1px solid var(--c-border); border-radius: 999px; background: var(--c-white); color: var(--c-text-secondary);
  font: inherit; font-size: .8em; font-weight: 600; cursor: pointer; transition: all var(--transition-fast); }
#adminPage.admin-desktop .admin-refresh:hover { border-color: var(--c-accent); color: var(--c-accent-deep); background: #FFFCF8; }
#adminPage.admin-desktop .admin-refresh:active { transform: scale(.97); }
#adminPage.admin-desktop .admin-refresh svg { width: 13px; height: 13px; opacity: .7; }

/* 指标卡：去掉 10 种无语义的顶部色条（impeccable 把"卡片彩色条纹"列为装饰性反模式），
   改成**每组一个小圆点**（3 个颜色、只标记分组，不做装饰）；
   数字从展示衬线体换成全站 UI 字体（product 登记册禁止"数据用展示字体"）。 */
#adminPage .admin-stat-card::before { display: none; }
.admin-stat-group { display: flex; align-items: center; gap: 7px; grid-column: 1 / -1;
  font-size: .74em; font-weight: 700; letter-spacing: .08em; color: var(--c-text-muted); margin: 14px 0 7px; }
.admin-stat-group:first-child { margin-top: 0; }
.admin-dot { width: 7px; height: 7px; border-radius: 50%; flex: none; }
.admin-dot.g-visit { background: var(--c-accent); }
.admin-dot.g-user { background: #8B9D77; }
.admin-dot.g-sys { background: #0EA5E9; }
.admin-stat-card { position: relative; text-align: left;
  background: var(--c-white); border-radius: 18px; padding: 14px 16px;
  box-shadow: 0 1px 2px rgba(90,60,20,.05); border: 1px solid var(--c-border); }
.admin-stat-card .stat-num { font-family: inherit; font-size: 1.6em; font-weight: 700; color: var(--c-text);
  line-height: 1.1; margin-bottom: 2px; font-variant-numeric: tabular-nums; letter-spacing: -.01em; }
.admin-stat-card .stat-label { font-size: .74em; color: var(--c-text-muted); }
.admin-stat-card[onclick] { transition: border-color var(--transition-fast), box-shadow var(--transition-fast), transform var(--transition-fast); }
.admin-stat-card[onclick]:hover { border-color: rgba(90,110,69,.45); box-shadow: 0 6px 16px rgba(120,80,30,.12); transform: translateY(-1px); }
.admin-stat-card[onclick]:active { transform: translateY(0); }
/* 桌面：4 列（手机 3 列）——卡片尺寸统一、列严格对齐 */
#adminPage.admin-desktop .admin-stats { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px; }
/* 桌面：4 列（手机 3 列），间距略松 */
#adminPage.admin-desktop .admin-stats { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px; }
#adminPage.admin-desktop .admin-stat-card { padding: 14px 16px; }
#adminPage.admin-desktop .admin-stat-card .stat-num { font-size: 1.8em; }

/* 趋势图：柱子限宽并居中，数值在上、日期在下；容器高度桌面 160px */
.admin-bar-val { display: none; font-size: .68em; font-weight: 700; color: var(--c-text-secondary);
  font-variant-numeric: tabular-nums; margin-bottom: 3px; }
#adminPage.admin-desktop .admin-bar-val { display: block; }
#adminPage.admin-desktop .admin-chart { padding: 20px 24px 16px; border-radius: 14px; }
#adminPage.admin-desktop .admin-bars { height: 140px; gap: 10px; align-items: flex-end; }
#adminPage.admin-desktop .admin-bar-wrap { max-width: 120px; margin: 0 auto; }
#adminPage.admin-desktop .admin-bar { border-radius: 6px 6px 2px 2px;
  background: #AAB096; }
#adminPage.admin-desktop .admin-bar-label { font-size: .68em; }
@keyframes clRing { 0%,100% { transform: scale(.94); opacity: .75; } 50% { transform: scale(1.06); opacity: .28; } }
@keyframes clBadgeIn { 0% { transform: scale(.4) rotate(-12deg); opacity: 0; } 60% { transform: scale(1.1) rotate(4deg); opacity: 1; } 100% { transform: none; } }

/* ── 积分制（2026-09-23）：得分提示 + 排行榜页 ── */
/* 得分提示：右下角独立小卡（站内 .toast 在顶部居中，会挡住阅读页顶栏按钮，故不复用） */
.points-toast-wrap { position: fixed; right: 18px; bottom: 24px; z-index: 320; display: flex; flex-direction: column; gap: 8px; pointer-events: none; }
.points-toast { display: flex; align-items: center; gap: 10px; padding: 9px 15px 9px 11px; border-radius: 100px;
  background: var(--c-bg-card); border: 1px solid var(--c-border); box-shadow: 0 4px 16px rgba(41,37,36,.10), 0 1px 3px rgba(41,37,36,.06);
  animation: ptIn 260ms var(--ease-out-quart) both; }
.points-toast.out { animation: ptOut 400ms var(--ease-out-quart) both; }
.points-toast .pt-gain { min-width: 32px; height: 32px; padding: 0 9px; border-radius: 100px; display: inline-flex;
  align-items: center; justify-content: center; background: var(--c-accent-light); color: #3F2D24; font-weight: 800; font-size: .92em; }
.points-toast .pt-txt { font-size: .78em; color: var(--c-text-muted); line-height: 1.25; }
.points-toast .pt-txt em { display: block; font-style: normal; color: var(--c-text-secondary); font-weight: 600; }
@keyframes ptIn { from { opacity: 0; transform: translateY(10px) scale(.9); } 60% { opacity: 1; transform: translateY(-2px) scale(1.04); } to { opacity: 1; transform: none; } }
@keyframes ptOut { to { opacity: 0; transform: translateY(-6px); } }
html.dark .points-toast { background: #292524; border-color: #3F3A37; box-shadow: 0 4px 16px rgba(0,0,0,.5); }
html.dark .points-toast .pt-gain { background: #3A322C; color: #E9E0D4; }
@media (max-width: 480px) {
  .points-toast-wrap { right: 10px; left: 10px; bottom: 74px; align-items: center; }
}
@media (prefers-reduced-motion: reduce) { .points-toast, .points-toast.out { animation: none; } }

/* ── 排行榜页（2026-09-24 换版式，设计来自 学习排行榜/ 设计包）──
   外壳沿用站内 .topbar + .vocab-page；下面只写它自己的部件。
   口径：三档榜单（总榜/本周/日榜）＋ 5 个积分分项（真题/文章/精读题/生词新增/生词复习）。
   ⚠️ 动效红线：入场动画只动 opacity / translate（独立属性），**不能动 transform** ——
      animation-fill-mode: both 会把 transform 钉死，之后 hover 的 translateY 永远不生效。 */
:root {
  --lb-gold: #D99A1F;    /* 领奖台 1/2/3 名金属箔 */
  --lb-silver: #A9AEB5;
  --lb-bronze: #B9763F;
}
#pointsPage { min-height: 100vh; }
#pointsPage .lb-page { max-width: 880px; }
#pointsPage .lb-hero { align-items: center; }

/* ── 头像：按用户名哈希取 6 组暖色渐变之一（同一人永远同色） ── */
.lb-ava { display: flex; align-items: center; justify-content: center; width: 40px; height: 40px; border-radius: 50%; flex: none; color: #fff;
  font-family: 'Noto Serif SC', serif; font-weight: 700; font-size: .95em; line-height: 1; letter-spacing: .02em; user-select: none;
  box-shadow: inset 0 -3px 8px rgba(0,0,0,.13), 0 1px 2px rgba(0,0,0,.06); }
.lb-a0 { background: #BE9260; }
.lb-a1 { background: #8AA594; }
.lb-a2 { background: #AF8E6F; }
.lb-a3 { background: #8E9CB9; }
.lb-a4 { background: #B28EA8; }
.lb-a5 { background: #A2967E; }

/* ── 标题行右侧：总榜 / 本周 / 日榜 胶囊分段器 ── */
.lb-seg { display: inline-flex; padding: 3px; gap: 2px; border-radius: 9999px; background: rgba(120,113,108,.075); border: 1px solid rgba(120,113,108,.1); flex: none; }
.lb-seg-btn { border: none; background: none; font: inherit; font-family: system-ui, -apple-system, 'Segoe UI', 'Microsoft YaHei', sans-serif; font-size: .78em; font-weight: 500; color: var(--c-text-secondary);
  padding: 8px 16px; border-radius: 9999px; cursor: pointer;
  transition: color .2s var(--ease-out-quart), background-color .2s var(--ease-out-quart), box-shadow .2s var(--ease-out-quart); }
.lb-seg-btn:hover { color: var(--c-text); }
.lb-seg-btn:focus-visible { outline: 2px solid var(--c-accent); outline-offset: 2px; }
.lb-seg-btn.active { background: var(--c-white); color: var(--c-accent-deep); font-weight: 600; box-shadow: 0 1px 3px rgba(0,0,0,.08); }
html.dark .lb-seg { background: rgba(255,255,255,.06); border-color: rgba(255,255,255,.08); }
html.dark .lb-seg-btn.active { background: #3A332E; color: var(--c-accent); }

/* ── 标题旁边的「规则」按钮 + 规则弹窗（2026-09-24：计分口径从副标题挪进来） ── */
.lb-rule-btn { margin-left: 10px; width: auto; padding: 3px 11px; border-radius: 9999px; border: 1px solid rgba(90,110,69,.32);
  background: rgba(233,224,212,.55); color: var(--c-accent-deep); font-family: system-ui, -apple-system, 'Segoe UI', 'Microsoft YaHei', sans-serif; font-size: .46em;
  font-weight: 600; letter-spacing: .02em; cursor: pointer; white-space: nowrap; align-self: center;
  transition: background-color var(--t-state) var(--ease-out-quart), border-color var(--t-state) var(--ease-out-quart); }
.lb-rule-btn:hover { background: var(--c-accent-light); border-color: var(--c-accent); }
.lb-rule-btn:focus-visible { outline: 2px solid var(--c-accent); outline-offset: 2px; }
html.dark .lb-rule-btn { background: rgba(163,185,140,.14); color: #D4A373; border-color: rgba(163,185,140,.3); }
html.dark .lb-rule-btn:hover { background: rgba(163,185,140,.24); }
/* 弹窗外壳复用站内 update-notice 那套皮肤 */
.lb-rule-overlay { position: fixed; inset: 0; background: rgba(41,37,36,.5); backdrop-filter: blur(4px);
  z-index: 600; display: flex; align-items: center; justify-content: center; padding: 16px; }
.lb-rule-card { position: relative; width: min(420px, 92vw); max-height: 84vh; overflow-y: auto; text-align: left;
  background: var(--c-white); border-radius: 20px; border-top: 3px solid var(--c-accent); padding: 26px 24px 20px;
  box-shadow: var(--shadow-lg); animation: donateIn .3s cubic-bezier(.34,1.56,.64,1); }
.lb-rule-close { position: absolute; top: 10px; right: 12px; background: none; border: none; font-size: 1.2em; line-height: 1;
  color: var(--c-text-muted); cursor: pointer; padding: 4px 8px; border-radius: 16px; }
.lb-rule-close:hover { background: rgba(120,113,108,.12); color: var(--c-text); }
.lb-rule-card h3 { font-family: 'Noto Serif SC', serif; font-size: 1.08em; font-weight: 700; color: #5C4033; margin: 0 0 14px; }
html.dark .lb-rule-card h3 { color: var(--c-text); }
.lb-rule-group { margin-bottom: 14px; }
.lb-rule-t { font-size: .7em; font-weight: 700; letter-spacing: .1em; color: var(--c-text-muted); margin-bottom: 7px; }
.lb-rule-row { display: flex; align-items: baseline; gap: 10px; padding: 7px 0; border-bottom: 1px dashed rgba(120,113,108,.16); font-size: .84em; }
.lb-rule-row:last-child { border-bottom: none; }
.lb-rule-row .n { flex: 1; min-width: 0; color: var(--c-text); }
.lb-rule-row .n em { display: block; font-style: normal; font-size: .8em; color: var(--c-text-muted); margin-top: 2px; }
.lb-rule-row .v { flex: none; font-family: 'Noto Serif SC', serif; font-weight: 700; color: var(--c-accent-deep); font-variant-numeric: tabular-nums; }
.lb-rule-note { margin: 4px 0 0; font-size: .74em; line-height: 1.75; color: var(--c-text-secondary); }
.lb-rule-note b { color: var(--c-accent-deep); }
html.dark .lb-rule-card { background: #292524; }
html.dark .lb-rule-row { border-bottom-color: rgba(255,255,255,.1); }
html.dark .lb-rule-row .v, html.dark .lb-rule-note b { color: var(--c-accent); }
@media (max-width: 768px) {
  .lb-rule-card { padding: 22px 18px 16px; max-height: 80vh; }
  .lb-rule-row { font-size: .8em; }
  .lb-rule-btn { font-size: .5em; padding: 2px 9px; }
}

/* ── 第一名福利横幅（2026-10-11）：领奖台上方通栏 ──
   配色口径（用户：不要刺眼的橙色）→ 哑光茶金 #8A6A2F / #C7A968，底走暖纸 #FBF6EC，不用金色渐变铺满。
   ⚠️ 文案与「规则」弹窗里那组「福利」是同一件事，改一处必须跟着改另一处（showPointsRules()）。 */
.lb-perk { display: flex; align-items: center; gap: 12px; margin: -16px 0 22px; padding: 9px 16px 9px 12px;
  border-radius: 14px; border: 1px solid rgba(138,106,47,.22); background: #FBF6EC;
  box-shadow: 0 1px 2px rgba(92,64,51,.05), inset 0 1px 0 rgba(255,255,255,.7);
  font-size: .84em; font-weight: 600; color: var(--c-text); letter-spacing: .01em; }
.lb-perk-ico { flex: none; width: 28px; height: 28px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
  color: #8A6A2F; background: linear-gradient(140deg, #F7EEDA, #EDE0C2);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.85), 0 1px 2px rgba(138,106,47,.16); }
.lb-perk-ico svg { width: 17px; height: 17px; }
/* 「第一名」用细描边小胶囊承载重点：比加粗变色克制，也不会把整条染成金色 */
.lb-perk em { font-style: normal; margin: 0 2px; padding: 1px 8px 2px; border-radius: 100px;
  border: 1px solid rgba(138,106,47,.3); background: rgba(199,169,104,.16); color: #7A5C22; font-weight: 700; }
html.dark .lb-perk { border-color: rgba(199,169,104,.24); background: rgba(199,169,104,.08);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.04); color: #E8E1D6; }
html.dark .lb-perk-ico { color: #E0C68C; background: linear-gradient(140deg, #3A3226, #2E2A24);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.05); }
html.dark .lb-perk em { border-color: rgba(199,169,104,.36); background: rgba(199,169,104,.14); color: #E7CE96; }
@media (max-width: 768px) { .lb-perk { margin: -10px 0 18px; padding: 8px 13px 8px 10px; font-size: .78em; gap: 9px; } .lb-perk-ico { width: 24px; height: 24px; } .lb-perk-ico svg { width: 14px; height: 14px; } }

/* ══ 登录 / 注册：紧凑化 + 换风格（2026-09-24 用户要求「不要太长」+「顺便换个新风格」）══
   旧版实测高度：登录 621 / 注册 787（手机视口 844 —— 注册页几乎顶满，键盘一弹就看不见按钮）。
   这一块是**覆盖式新增**（放在原 `.login-*` 样式之后生效），旧规则先留着，出问题好对照回退。
   新风格：暖白毛玻璃卡 + 圆形品牌徽标；去掉顶部彩条、底部装饰线、56px 图标块、斜体英文副标题、
   每个字段的独立 label（文案收进 placeholder）。字段改「下划线式」描边，聚焦时琥珀色渐显。
   目标高度：登录 ≈400、注册 ≈540。 */
.login-overlay { background: rgba(41,37,36,.42); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); }

.login-card {
  width: min(384px, 92vw);
  max-width: 384px;
  max-height: calc(100vh - 32px); max-height: calc(100dvh - 32px);
  overflow-y: auto; -webkit-overflow-scrolling: touch;
  padding: 24px 22px 18px;
  border-radius: 18px;
  background: linear-gradient(180deg, rgba(255,253,247,.97), rgba(253,246,235,.94));
  backdrop-filter: blur(18px) saturate(1.1); -webkit-backdrop-filter: blur(18px) saturate(1.1);
  border: 1px solid rgba(90,110,69,.16);
  box-shadow: 0 18px 50px rgba(120,113,108,.24), inset 0 1px 0 rgba(255,255,255,.85);
  text-align: left;
}
.login-card::before, .login-card::after { display: none; }     /* 顶彩条 + 底装饰线：去掉 */
.login-card h2 { margin: 0; }                                   /* 标题已挪进品牌头（保留 h2 只为兜底） */

/* 品牌头：一行装完徽标 + 标题 + 一行说明 */
.lg-brand { display: flex; align-items: center; gap: 11px; margin-bottom: 18px; }
.lg-brand-logo { flex: none; width: 44px; height: 44px; border-radius: 14px; display: flex; align-items: center; justify-content: center;
  background: #F8EBD6; color: var(--c-accent);
  box-shadow: inset 0 0 0 1px rgba(90,110,69,.16); }
.lg-brand-logo svg { width: 22px; height: 22px; }
.lg-brand-text { min-width: 0; }
.lg-brand-text b { display: block; font-family: 'Noto Serif SC', serif; font-size: 1.1em; font-weight: 700; color: #5C4033; letter-spacing: .04em; }
.lg-brand-text i { display: block; font-style: normal; font-size: .74em; color: var(--c-text-muted); margin-top: 2px; }

/* 字段：无 label、下划线式描边、间距收到 12px */
.login-card .field { margin-bottom: 12px; }
.login-card .field:last-of-type { margin-bottom: 16px; }
.login-card .field label { display: none; }
/* 邮箱那一行：输入框 + 「发送验证码」按钮并排（按钮占右侧，输入框自适应） */
.login-card .field { position: relative; }
.login-card .field .lg-send { position: absolute; right: 0; top: 50%; transform: translateY(-50%);
  padding: 5px 9px; border-radius: 16px; border: 1px solid rgba(90,110,69,.35); background: rgba(233,224,212,.5);
  color: var(--c-accent-deep); font: inherit; font-size: .74em; font-weight: 600; white-space: nowrap; cursor: pointer;
  transition: background-color .2s var(--ease-out-quart), border-color .2s var(--ease-out-quart); }
.login-card .field .lg-send:hover:not(:disabled) { background: var(--c-accent-light); border-color: var(--c-accent); }
.login-card .field .lg-send:disabled { opacity: .55; cursor: default; }
.login-card .field:has(.lg-send) input { padding-right: 92px; }
html.dark .login-card .field .lg-send { background: rgba(163,185,140,.16); color: #D4A373; border-color: rgba(163,185,140,.3); }
/* 强制绑定层：说清「为什么必须绑」 */
.bind-card .bind-why { margin: 0 0 14px; font-size: .82em; line-height: 1.75; color: var(--c-text-secondary); }
.bind-card .bind-why b { color: var(--c-accent-deep); font-weight: 600; }
html.dark .bind-card .bind-why b { color: var(--c-accent); }
/* 登录页底部的管理员兜底提示（2026-09-24）：比正文更弱，不与「忘记密码？」抢注意力 */
.login-admin-hint { margin-top: 10px; padding-top: 10px; border-top: 1px dashed rgba(120,113,108,.18);
  font-size: .72em; line-height: 1.6; color: var(--c-text-muted); text-align: center; }
.login-admin-hint b { color: var(--c-accent-deep); font-weight: 600; letter-spacing: .02em; }
html.dark .login-admin-hint { border-top-color: rgba(255,255,255,.1); }
html.dark .login-admin-hint b { color: #D4A373; }
@keyframes glPop { from { transform: scale(.8); opacity: 0; } to { transform: scale(1); opacity: 1; } }

.login-card .field input {
  width: 100% !important; padding: 10px 2px !important;
  border: none !important; border-bottom: 1.5px solid rgba(120,113,108,.22) !important;
  border-radius: 0 !important; background: transparent !important; box-shadow: none !important;
  font: inherit; font-size: .95em; outline: none; color: var(--c-text);
  transition: border-color .2s var(--ease-out-quart), box-shadow .2s var(--ease-out-quart);
}
.login-card .field input::placeholder { color: var(--c-text-muted); }
/* ⚠️ 这几条用 !important：旧 `.login-card .field input` 系列规则散在文件各处（含 html.dark 变体），
   同特异性下「谁生效」取决于源码顺序 —— 实测过旧规则仍然胜出（输入框还是完整圆角描边）。
   与其跟层叠猜拳，不如把目标值直接钉死；改版式时记得这一组要一起看。 */
.login-card .field input:focus {
  border-bottom-color: var(--c-accent) !important;
  box-shadow: 0 2px 0 -0.5px var(--c-accent) !important;
  background: transparent !important;
}
.login-card .btn-login { width: 100%; padding: 11px; margin-top: 4px; border-radius: 11px; font-size: .94em; font-weight: 600;
  letter-spacing: .1em; animation: none; }
/* 错误区不占位：有错才出现 */
.login-card .login-error { margin-top: 10px; min-height: 0; font-size: .8em; color: var(--c-danger); text-align: left; }
.login-card .login-error:empty { display: none; }

/* 底部一行：切模式 + 忘记密码 */
.login-foot { margin-top: 14px; display: flex; align-items: center; justify-content: space-between; gap: 10px; font-size: .78em; }
.login-foot .lg-switch { color: var(--c-text-muted); display: inline-flex; align-items: center; gap: 4px; }
.login-foot .lg-switch button { background: none; color: var(--c-accent); font-size: 1em; font-weight: 600; padding: 2px 4px; border-radius: 6px; transition: background-color .2s; }
.login-foot .lg-switch button:hover { background: rgba(90,110,69,.08); }
.login-foot a { color: var(--c-text-muted); text-decoration: none; }
.login-foot a:hover { color: var(--c-accent); }
/* 只有「以后再说」一项时居中，否则会被 justify-content:space-between 推到左边孤零零的 */
.login-foot:has(> .lg-switch:only-child) { justify-content: center; }

/* ── 登录方式页签 + 微信扫码页（2026-10-14）────────────────────────────────── */
.lg-tabs { display: flex; gap: 6px; margin: 2px 0 14px; background: rgba(120,113,108,.07); padding: 3px; border-radius: 11px; }
.lg-tab { flex: 1; padding: 7px 8px; border-radius: 9px; font-size: .84em; font-weight: 600; color: var(--c-text-muted);
  background: none; border: 0; cursor: pointer; transition: background-color .18s, color .18s; font-family: inherit; }
.lg-tab.sel { background: var(--c-bg-card); color: var(--c-accent-deep); box-shadow: var(--shadow-sm); }
/* 微信扫码：官方 SDK 在站内渲染二维码。
   ⚠️⚠️ 2026-10-14 的坑：这页**不止一种版式** ——
   电脑上装了微信客户端时，微信会改成「微信快捷登录」（绿色按钮 + 一行说明），内容垂直位置完全不同。
   我原先把整页**往上挪 43px** 去裁顶部空白，结果把快捷登录版式**从中间截断**。
   ⚠️ 2026-10-16 最终口径：**不再用位移**。位移会让两个版式互相打架（二维码要上移才均匀，
   快捷登录被上移就顶掉头像）—— 改成①用官方 `href` 参数往那张页面里注入 CSS，从内部把上方空白归零
   （见 wxQrHref()）、②把 iframe 略微**放大**（scale 1.1）把二维码补回原大小（注入后它会缩小到 ~159px）。
   ⚠️ 别用 `align-items: center`：iframe 的盒子仍是 400px 高，居中等于把上面切掉（实测二维码被裁）。
   若注入被微信忽略（那些类名非官方文档，改版可能变），回落到默认样式也能扫、能用，只是不再完美居中。 */
.wx-box { position: relative; width: 260px; height: 215px; margin: 0 auto;
  display: flex; align-items: flex-start; justify-content: center;
  border: 1px solid var(--c-border); border-radius: 16px;
  background: #fff; box-shadow: var(--shadow-sm); overflow: hidden; }
/* 二维码那张页面自带白底，直接贴在暖色卡上像"白块贴上去"；一道内圈细描边把它框成有意为之的一块 */
.wx-box::after { content: ''; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  box-shadow: inset 0 0 0 1px rgba(120,113,108,.10); }
.wx-box iframe { width: 300px !important; height: 400px !important; border: 0; display: block;
  transform: scale(.84); transform-origin: top center; }
.wx-tip { margin-top: 10px; font-size: .74em; line-height: 1.65; color: var(--c-text-muted); text-align: center; }
.wx-tip-tight { margin: 10px 0 0; }
/* 提示 + 刷新按钮，居中排在二维码下面（2026-10-16：提示收成一枚"标签"，不再和按钮挤成一团） */
.wx-foot { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 8px; margin-top: 14px; }
.wx-hint { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap;
  font-size: .74em; line-height: 1.5; color: var(--c-text-muted);
  background: rgba(120,113,108,.06); border: 1px solid var(--c-border);
  border-radius: 999px; padding: 5px 12px; }
.wx-hint::before { content: ''; width: 5px; height: 5px; border-radius: 50%;
  background: var(--c-accent); flex: none; }
.wx-refresh { display: inline-flex; align-items: center; gap: 5px; padding: 7px 14px; border-radius: 999px;
  border: 1px solid var(--c-accent); background: var(--c-accent-light); color: var(--c-accent-deep);
  font-family: inherit; font-size: .78em; font-weight: 600; cursor: pointer; white-space: nowrap;
  transition: background-color .18s, color .18s, transform .18s, box-shadow .18s; }
.wx-refresh:hover { background: var(--c-accent); color: #fff; transform: translateY(-1px); box-shadow: var(--shadow-sm); }
.wx-refresh:active { transform: none; }
.wx-refresh:disabled { opacity: .55; cursor: default; transform: none; box-shadow: none; }
.wx-acts { display: flex; align-items: center; justify-content: center; gap: 8px; margin-top: 4px; }
.wx-mini { background: none; border: 0; padding: 3px 8px; font-family: inherit; font-size: .74em;
  color: var(--c-accent); cursor: pointer; border-radius: 7px; }
.wx-mini:hover { background: var(--c-accent-light); }
/* 两个绑定闸门之间的"换一条路"入口（2026-10-16：邮箱或微信二选一，手机默认走邮箱） */
.bind-swap { margin: 12px 0 0; font-size: .74em; color: var(--c-text-muted); text-align: center; }
.bind-swap button { background: none; border: 0; padding: 3px 6px; margin-left: 2px; border-radius: 7px;
  font-family: inherit; font-size: 1em; font-weight: 600; color: var(--c-accent-deep); cursor: pointer; }
.bind-swap button:hover { background: var(--c-accent-light); }
html.dark .bind-swap button { color: #D4C4A8; }
html.dark .bind-swap button:hover { background: rgba(163,185,140,.16); }
/* 暗色：二维码那张页面自带白底，这里只调"框"与提示标签（2026-10-16） */
/* 暗色：这块刻意保持**白底**（二维码要扫），只把描边调柔，免得白块在暗色卡上太扎眼 */
html.dark .wx-box { background: #fff; border-color: rgba(255,255,255,.16); box-shadow: 0 6px 20px rgba(0,0,0,.35); }
html.dark .wx-box::after { box-shadow: inset 0 0 0 1px rgba(255,255,255,.07); }
html.dark .wx-hint { background: rgba(255,255,255,.05); border-color: rgba(255,255,255,.12); color: var(--c-text-muted); }
html.dark .wx-hint::before { background: #A3B98C; }
html.dark .wx-refresh { background: rgba(163,185,140,.14); border-color: rgba(163,185,140,.42); color: #D4C4A8; }
html.dark .wx-refresh:hover { background: var(--c-accent); color: #fff; }
/* 微信首次进入：一键开号为主，「绑定已有账号」为次（2026-10-14） */
.wx-or { display: flex; align-items: center; gap: 10px; margin: 14px 0 10px; color: var(--c-text-muted); font-size: .74em; }
.wx-or::before, .wx-or::after { content: ''; flex: 1; height: 1px; background: var(--c-border); }
.wx-link { display: block; width: 100%; padding: 9px; border-radius: 10px; border: 1px solid var(--c-border);
  background: var(--c-bg-card); color: var(--c-accent-deep); font-size: .86em; font-weight: 600; cursor: pointer; font-family: inherit; }
.wx-link:hover { background: var(--c-accent-light); border-color: var(--c-accent); }
/* 「完善资料」弹窗（2026-10-14 美化）：带框输入 + 分组标签 + 信息条，层次清楚、不再是一大段灰字。
   ⚠️ 基类 `.login-card .field input` 的样式**全是 `!important`**（见那段注释），
   这里要覆盖必须同样 `!important`（好在 ID 选择器特异性更高，暗色变体也压得住）。
   只作用于 #wxMailTip —— 登录 / 绑定邮箱 / 找回密码那几层一点都不受影响。 */
#wxMailTip .login-card { max-width: 386px; }
#wxMailTip .wx-label { display: block; font-size: .78em; font-weight: 600; color: var(--c-text); margin: 15px 0 7px; }
#wxMailTip .wx-opt { margin-left: 6px; font-weight: 500; font-size: .92em; color: var(--c-text-muted); }
#wxMailTip .field { margin-bottom: 8px; }
#wxMailTip .field input {
  border: 1px solid var(--c-border) !important; background: var(--c-bg-card) !important;
  border-radius: 10px !important; padding: 11px 13px !important;
}
#wxMailTip .field input:focus {
  border-color: var(--c-accent) !important; background: var(--c-bg-card) !important;
  box-shadow: 0 0 0 3px rgba(90,110,69,.13) !important;
}
#wxMailTip .field:has(.lg-send) input { padding-right: 98px !important; }
#wxMailTip .field .lg-send { right: 6px; }
#wxMailTip .wx-note { font-size: .72em; color: var(--c-text-muted); margin: 7px 0 0 2px; }
#wxMailTip .wx-callout { display: flex; align-items: flex-start; gap: 8px; margin: 17px 0 3px; padding: 11px 13px;
  border-radius: 12px; background: var(--c-accent-light); color: var(--c-accent-deep);
  font-size: .76em; line-height: 1.68; }
#wxMailTip .wx-callout svg { flex: none; margin-top: 2px; opacity: .75; }
#wxMailTip .wx-callout b { font-weight: 600; }
.lg-legal { margin-top: 12px; padding-top: 10px; border-top: 1px dashed rgba(120,113,108,.18);
  font-size: .74em; color: var(--c-text-muted); text-align: center; }
.lg-legal a { color: var(--c-text-muted); text-decoration: none; margin: 0 4px; }
.lg-legal a:hover { color: var(--c-accent); text-decoration: underline; }
.acct-sec { font-size: .84em; }   /* 2026-10-23：弹窗删了，这三行现在画在个人中心的展开块里，类名保留 */
.acct-row { display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 11px 14px; border: 1px solid var(--c-border); border-radius: 10px; margin-bottom: 9px; background: var(--c-bg-card); }
.acct-row .acct-k { font-weight: 600; color: var(--c-text); }
.acct-row .acct-v { font-size: .82em; color: var(--c-text-muted); margin-top: 3px; }
.acct-row button { font-size: .92em; padding: 6px 12px; border-radius: 8px; border: 1px solid var(--c-border);
  background: var(--c-bg); color: var(--c-accent-deep); font-weight: 600; cursor: pointer; font-family: inherit; }
.acct-row button:hover { background: var(--c-accent-light); border-color: var(--c-accent); }
.acct-row button.danger { color: var(--c-danger); }
.login-card .login-close { position: absolute; top: 9px; right: 9px; width: 28px; height: 28px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center; font-size: 1.05em; line-height: 1; color: var(--c-text-muted);
  background: rgba(120,113,108,.08); }
.login-card .login-close:hover { background: rgba(120,113,108,.16); color: var(--c-text); }

/* 暗色：同一套玻璃，换深色底 */
html.dark .login-card { background: linear-gradient(180deg, rgba(42,38,35,.97), rgba(36,32,29,.95)); border-color: rgba(163,185,140,.22);
  box-shadow: 0 18px 50px rgba(0,0,0,.55), inset 0 1px 0 rgba(255,255,255,.06); }
html.dark .lg-brand-logo { background: #342C26; color: #D4A373; box-shadow: inset 0 0 0 1px rgba(163,185,140,.25); }
html.dark .lg-brand-text b { color: var(--c-text); }
html.dark .login-card .field input { color: var(--c-text) !important; border-bottom-color: rgba(255,255,255,.18) !important; background: transparent !important; }
html.dark .login-card .field input:focus { border-bottom-color: var(--c-accent) !important; box-shadow: 0 2px 0 -0.5px var(--c-accent) !important; }
html.dark .login-card .login-close { background: rgba(255,255,255,.08); }

/* 手机：再压一档，并给 iOS 键盘留空间（卡片自身可滚） */
@media (max-width: 768px) {
  .login-card { width: min(360px, 94vw); padding: 20px 16px 16px; border-radius: 16px;
    max-height: calc(100vh - 24px); max-height: calc(100dvh - 24px); }
  .lg-brand { margin-bottom: 14px; gap: 10px; }
  .lg-brand-logo { width: 40px; height: 40px; border-radius: 18px; }
  .login-card .field { margin-bottom: 10px; }
}

/* ── 领奖台（前三名，DOM 顺序 2-1-3） ── */
.lb-podium { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; align-items: end; margin: 2px 0 14px; }
.lb-pod { position: relative; display: flex; flex-direction: column; align-items: center; gap: 5px; padding: 20px 8px 15px; border-radius: var(--radius-lg);
  background: var(--c-white); border: 1px solid var(--c-border); box-shadow: var(--shadow-sm);
  transition: transform .38s var(--ease-out-quart), box-shadow .38s var(--ease-out-quart), border-color .38s var(--ease-out-quart); }
.lb-pod::after { content: ''; position: absolute; left: 24%; right: 24%; bottom: 0; height: 3px; border-radius: 3px 3px 0 0;
  background: linear-gradient(90deg, transparent, var(--lb-metal, transparent), transparent); }
.lb-pod:hover, .lb-pod.focus { transform: translateY(-6px); box-shadow: var(--shadow-lg); }
.lb-pod-1 { padding-top: 28px; --lb-metal: var(--lb-gold); border-color: rgba(212,163,115,.3); }
.lb-pod-1:hover, .lb-pod-1.focus { border-color: rgba(212,163,115,.65); }
.lb-pod-2 { --lb-metal: var(--lb-silver); }
.lb-pod-3 { --lb-metal: var(--lb-bronze); }
.lb-pod-1 .lb-ava { width: 62px; height: 62px; font-size: 1.5em; box-shadow: 0 0 0 3px rgba(212,163,115,.2), 0 6px 16px rgba(212,163,115,.26); }
.lb-pod-2 .lb-ava, .lb-pod-3 .lb-ava { width: 50px; height: 50px; font-size: 1.2em; }
.lb-crown { position: absolute; top: -13px; left: 50%; width: 28px; height: 21px; color: var(--lb-gold); filter: drop-shadow(0 3px 6px rgba(212,163,115,.42)); animation: lbCrown 3.4s ease-in-out infinite; }
@keyframes lbCrown { 0%, 100% { transform: translateX(-50%) translateY(0); } 50% { transform: translateX(-50%) translateY(-3px); } }
.lb-pod-place { position: absolute; top: 9px; left: 50%; transform: translateX(-50%); font-family: 'Noto Serif SC', serif; font-size: .72em; font-weight: 700; color: var(--lb-metal, var(--c-text-muted)); letter-spacing: .04em; }
.lb-pod-name { max-width: 100%; font-family: 'Noto Serif SC', serif; font-size: .86em; font-weight: 600; color: var(--c-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lb-pod-score { display: flex; align-items: baseline; gap: 3px; }
.lb-pod-score b { font-family: 'Noto Serif SC', serif; font-size: 1.22em; font-weight: 700; color: var(--c-accent-deep); line-height: 1; font-variant-numeric: tabular-nums; }
.lb-pod-score span { font-size: .62em; color: var(--c-text-muted); }
.lb-pod-1 .lb-pod-score b { font-size: 1.5em; }
.lb-pod.is-me { box-shadow: 0 0 0 1px rgba(90,110,69,.5), var(--shadow-md); }
html.dark .lb-pod { background: #292524; border-color: rgba(255,255,255,.07); box-shadow: 0 1px 3px rgba(0,0,0,.3); }
html.dark .lb-pod:hover { border-color: rgba(255,255,255,.16); }
html.dark .lb-pod-score b { color: var(--c-accent); }

/* ── 领奖台共用明细条（悬停/点击谁就显示谁的，默认第一名） ── */
.lb-pod-detail { margin: 0 0 20px; padding: 13px 16px; border-radius: var(--radius-md);
  background: linear-gradient(180deg, rgba(255,253,246,.92), rgba(255,255,255,.62)); border: 1px dashed rgba(120,113,108,.22); }
.lb-pod-detail-head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 9px; font-size: .74em; color: var(--c-text-muted); flex-wrap: wrap; }
.lb-pod-detail-head b { font-family: 'Noto Serif SC', serif; font-size: 1.15em; color: var(--c-text); font-weight: 600; }
.lb-pod-detail-head .lb-pd-tip { margin-left: auto; font-size: .92em; }
html.dark .lb-pod-detail { background: linear-gradient(180deg, rgba(41,37,36,.72), rgba(38,33,29,.5)); border-color: rgba(255,255,255,.1); }

/* ── 积分分项：一条堆叠比例条（2026-09-24 用户要求：底下的图例整块去掉） ── */
.lb-stack { display: flex; height: 7px; border-radius: 9999px; overflow: hidden; background: rgba(120,113,108,.1); }
.lb-stack i { flex: none; height: 100%; transition: width .5s var(--ease-out-quart); }
.lb-stack i + i { box-shadow: inset 1px 0 0 rgba(255,255,255,.32); }

/* ── 榜单列表（第 4 名起；悬浮或点击展开分项） ── */
.lb-list { display: flex; flex-direction: column; gap: 8px; }
.lb-row { position: relative; border-radius: var(--radius-md); background: var(--c-white); border: 1px solid var(--c-border); box-shadow: var(--shadow-sm);
  overflow: hidden; cursor: pointer; animation: lbRowIn .45s both; animation-delay: calc(var(--i, 0) * 45ms);
  transition: transform .3s var(--ease-out-quart), box-shadow .3s var(--ease-out-quart), border-color .3s var(--ease-out-quart), background-color .3s var(--ease-out-quart); }
@keyframes lbRowIn { from { opacity: 0; translate: 8px 0; } to { opacity: 1; translate: 0 0; } }
.lb-row::before { content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 2px; background: var(--c-accent); transform: scaleY(0); transition: transform .3s var(--ease-out-quart); }
.lb-row:hover, .lb-row.expanded, .lb-row:focus-visible { transform: translateY(-3px); box-shadow: var(--shadow-lg); border-color: rgba(90,110,69,.45); outline: none; }
.lb-row:hover::before, .lb-row.expanded::before, .lb-row:focus-visible::before { transform: scaleY(1); }
.lb-row.is-me { border-color: rgba(90,110,69,.4); background-image: none; background-color: linear-gradient(90deg, rgba(233,224,212,.3), rgba(255,255,255,0) 42%); }
.lb-row.is-me::before { transform: scaleY(1); }
.lb-row-main { display: flex; align-items: center; gap: 12px; padding: 11px 14px; }
.lb-rank { flex: none; width: 30px; text-align: center; font-family: 'Noto Serif SC', serif; font-size: .98em; font-weight: 700; color: var(--c-text-muted); font-variant-numeric: tabular-nums; }
.lb-name { flex: 1; min-width: 0; font-family: 'Noto Serif SC', serif; font-size: .88em; font-weight: 500; color: var(--c-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lb-name-tag { display: inline-block; margin-left: 6px; padding: 0 6px; border-radius: 9999px; font-family: system-ui, -apple-system, 'Segoe UI', 'Microsoft YaHei', sans-serif; font-size: .62em; font-weight: 600;
  color: var(--c-accent-deep); background: var(--c-accent-light); vertical-align: 1px; }
html.dark .lb-name-tag { background: rgba(163,185,140,.16); color: #D4A373; }
.lb-score { flex: none; display: flex; align-items: baseline; gap: 3px; }
.lb-score b { font-family: 'Noto Serif SC', serif; font-size: 1.06em; font-weight: 700; color: var(--c-accent-deep); font-variant-numeric: tabular-nums; }
.lb-score i { font-style: normal; font-size: .64em; color: var(--c-text-muted); }
.lb-chev { flex: none; width: 14px; height: 14px; color: var(--c-border); transition: transform .3s var(--ease-out-quart), color .3s var(--ease-out-quart); }
.lb-row:hover .lb-chev, .lb-row.expanded .lb-chev, .lb-row:focus-visible .lb-chev { color: var(--c-accent); transform: rotate(180deg); }
.lb-detail { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .38s var(--ease-out-quart); }
.lb-row:hover .lb-detail, .lb-row.expanded .lb-detail { grid-template-rows: 1fr; }
.lb-detail > div { overflow: hidden; }
.lb-detail-inner { padding: 0 14px 13px 56px; }
html.dark .lb-row { background: #292524; border-color: rgba(255,255,255,.07); }
html.dark .lb-row:hover, html.dark .lb-row.expanded, html.dark .lb-row:focus-visible { border-color: rgba(163,185,140,.5); }
html.dark .lb-row.is-me { background-image: none; background-color: linear-gradient(90deg, rgba(120,77,15,.32), rgba(41,37,36,0) 42%); }
html.dark .lb-score b { color: var(--c-accent); }
.lb-empty { padding: 40px 16px; text-align: center; font-size: .86em; color: var(--c-text-muted); line-height: 1.9; }

/* ── 「我的排名」吸底条 ── */
.lb-me { position: sticky; bottom: 14px; z-index: 5; display: flex; align-items: center; gap: 12px; margin-top: 18px; padding: 11px 16px; border-radius: var(--radius-md);
  background: rgba(255,255,255,.82); backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
  border: 1px solid rgba(90,110,69,.35); box-shadow: 0 10px 28px rgba(120,113,108,.18); }
.lb-me:empty { display: none; }
.lb-me-label { flex: none; font-family: system-ui, -apple-system, 'Segoe UI', 'Microsoft YaHei', sans-serif; font-size: .68em; font-weight: 600; letter-spacing: .1em; color: var(--c-accent-deep); }
.lb-me .lb-rank { width: auto; min-width: 30px; color: var(--c-accent-deep); font-size: 1.06em; }
/* 名次超出展示范围（>20）时不写数字，改写「暂未上榜」：字多，字号收一点、不换行、别把整条挤变形 */
.lb-me .lb-rank-no { width: auto; min-width: 0; flex: none; font-family: 'Noto Serif SC', serif; font-size: .82em; font-weight: 600; white-space: nowrap; }
.lb-me .lb-ava { width: 34px; height: 34px; font-size: .84em; }
html.dark .lb-me { background: rgba(41,37,36,.86); }
html.dark .lb-me-label, html.dark .lb-me .lb-rank { color: var(--c-accent); }

/* ── 手机端：三档胶囊收起来，切到下方那三条（与速记生词/文章阅读同一套形态驱动） ── */
#pointsPage .pt-tab-bar { display: none; }
#pointsPage.pt-nav-mobile .pt-tab-bar { display: flex; }
#pointsPage.pt-nav-mobile .lb-seg { display: none; }
#pointsPage.pt-nav-mobile .vocab-page { padding-bottom: 76px; }
/* ⚠️ 手机上「我的排名」的吸底落点必须让开底部导航：
   底部导航是 fixed + z-index 80，吸底条只有 5 —— 之前吸底条停在视口底部时整条被导航盖住，看不见。
   这里把它的吸底位置抬到导航上方（导航高 56px）。
   左边还要再让开宠物入口圆钮（fixed、left 12/宽 42、z-index 更高）——
   滚到页面底部时它正好压在「我的排名」标签上，实测把「我的」两个字盖住了。 */
#pointsPage.pt-nav-mobile .lb-me { bottom: calc(56px + 10px + env(safe-area-inset-bottom, 0px)); margin-bottom: 8px; padding-left: 50px; }
/* ⚠️ 手机端排行榜页原来**只给底部栏留了位，没给顶部那条 fixed 顶栏留位** ——
   其它页都有「.topbar ~ .vocab-page { padding-top: 68px }」这一条，排行榜页漏了，
   于是顶栏会盖住标题行（「学习排行榜」+ 规则按钮 + 副标题）。
   高度不写死：由 pointsSyncNav() 每次进页面/缩放时量真实顶栏高度写进 --lb-topbar-h（兜底 56px）。
   只在「顶栏确实是 fixed」的两档生效 —— ≤768px 与 force-phone；窄桌面窗口（force-tablet）顶栏还在文档流里，不能加。 */
@media (max-width: 768px) {
  #pointsPage .vocab-page.vocab-page { padding-top: calc(var(--lb-topbar-h, 56px) + 12px); }
}
html.force-phone #pointsPage .vocab-page.vocab-page { padding-top: calc(var(--lb-topbar-h, 56px) + 12px); }

@media (max-width: 768px) {
  #pointsPage .lb-seg-btn { padding: 8px 12px; font-size: .72em; }
  #pointsPage .lb-podium { gap: 7px; }
  #pointsPage .lb-pod { padding: 16px 5px 12px; border-radius: var(--radius-md); }
  #pointsPage .lb-pod-1 { padding-top: 23px; }
  #pointsPage .lb-pod-1 .lb-ava { width: 46px; height: 46px; font-size: 1.1em; }
  #pointsPage .lb-pod-2 .lb-ava, #pointsPage .lb-pod-3 .lb-ava { width: 38px; height: 38px; font-size: .95em; }
  #pointsPage .lb-crown { width: 22px; height: 17px; top: -11px; }
  #pointsPage .lb-pod-place { top: 6px; font-size: .64em; }
  #pointsPage .lb-pod-name { font-size: .74em; }
  #pointsPage .lb-pod-score b { font-size: 1em; }
  #pointsPage .lb-pod-1 .lb-pod-score b { font-size: 1.18em; }
  #pointsPage .lb-pod-detail { padding: 11px 12px 10px; }
  #pointsPage .lb-detail-inner { padding-left: 14px; }
  #pointsPage .lb-me { gap: 8px; padding: 10px 12px; }
  #pointsPage .lb-me-label { letter-spacing: .04em; }
}
@media (prefers-reduced-motion: reduce) {
  #pointsPage .lb-row { animation: none !important; }
  #pointsPage .lb-pod, #pointsPage .lb-row, #pointsPage .lb-stack i, #pointsPage .lb-chev,
  #pointsPage .lb-detail, #pointsPage .lb-seg-btn { transition: none !important; }
  #pointsPage .lb-crown { animation: none !important; }
  #pointsPage .lb-pod:hover, #pointsPage .lb-pod.focus,
  #pointsPage .lb-row:hover, #pointsPage .lb-row.expanded { transform: none; }
}

/* Update Notice (broadcast to online users) */
.update-notice-overlay { position: fixed; inset: 0; background: rgba(41,37,36,.5); backdrop-filter: blur(4px); z-index: 600; display: none; align-items: center; justify-content: center; }
.update-notice-overlay.show { display: flex; }
.update-notice-card { background: var(--c-white); border-radius: 20px; padding: 36px 40px 30px; max-width: 340px; width: 90%; text-align: center; box-shadow: var(--shadow-lg); animation: donateIn .3s cubic-bezier(.34,1.56,.64,1); border-top: 3px solid var(--c-accent); }
.update-notice-card .un-icon { color: var(--c-accent); margin-bottom: 14px; }
.update-notice-card .un-title { font-family: 'Noto Serif SC', serif; font-size: 1.15em; font-weight: 700; color: var(--c-text); margin-bottom: 10px; }
.update-notice-card .un-msg { color: var(--c-text-secondary); font-size: .92em; line-height: 1.8; margin-bottom: 24px; }
.update-notice-card #updateCountdown { display: inline-block; min-width: 3em; font-weight: 700; color: var(--c-accent-deep); font-family: system-ui, -apple-system, 'Segoe UI', 'Microsoft YaHei', sans-serif; font-variant-numeric: tabular-nums; letter-spacing: .02em; }
.update-notice-card button { padding: 10px 40px; background: var(--c-accent); color: #fff; border: none; border-radius: 100px; font-size: .9em; font-weight: 600; cursor: pointer; transition: all .15s ease; box-shadow: 0 2px 8px rgba(90,110,69,.25); }
.update-notice-card button:hover { background: var(--c-accent-hover); box-shadow: 0 4px 14px rgba(90,110,69,.35); transform: translateY(-1px); }
.update-notice-card button:active { transform: translateY(0) scale(.97); }

/* Popover */
.popover { position: fixed; background: #FFFFFF; border-radius: 16px; box-shadow: 6px 6px 12px #E8DFCE, -6px -6px 12px #FBF7EF; padding: 16px 20px; z-index: 300; max-width: 340px; min-width: 180px; max-height: 86vh; overflow-y: auto; display: none; border: none; animation: popIn .15s ease; }
.popover.show { display: block; }
/* 叠加在「添加单词」弹窗（.add-modal-overlay，z-index 500）之上：
   生词本里点搜索结果时要在弹窗上方弹出单词卡，否则会被半透明遮罩盖住。 */
.popover.above-modal { z-index: 600; }
/* 词典面板浮窗（z-index 500）开着时点正文单词：单词卡要压在它上面（2026-10-31） */
.popover.above-lk { z-index: 620; }
@keyframes popIn { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: translateY(0); } }
/* ── 查词卡片拖动把手（2026-10-31 用户要求「做成悬浮可拖动」）──
   卡片本身就是 position:fixed，拖动只改 left/top。把手做成 sticky：内容滚很长时它仍贴在卡顶。 */
.pop-grip { position: sticky; top: -16px; z-index: 1; height: 26px; margin: -16px -20px 8px;
  display: grid; place-items: center; cursor: grab; touch-action: none; user-select: none;
  background: inherit; border-radius: 16px 16px 0 0; }
.pop-grip span { width: 34px; height: 4px; border-radius: 2px; background: rgba(61,50,38,.22); transition: background .15s; }
html.dark .pop-grip span { background: rgba(240,226,196,.26); }
.pop-grip:hover span { background: rgba(61,50,38,.4); }
html.dark .pop-grip:hover span { background: rgba(240,226,196,.45); }
.popover.dragging { animation: none; user-select: none; }
.popover.dragging .pop-grip { cursor: grabbing; }
.popover.dragging .pop-grip span { background: rgba(61,50,38,.5); }
.popover .dict-word { font-size: 1.1em; font-weight: 700; color: var(--c-text); }
.popover .dict-word-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.popover .dict-sound { display: inline-flex; align-items: center; gap: 4px; padding: 3px 9px; border-radius: 100px; border: 1px solid #3D3226; background: transparent; color: #3D3226; cursor: pointer; line-height: 0; transition: all .15s; flex-shrink: 0; }
.popover .dict-sound:hover { background: rgba(61,50,38,.06); transform: scale(1.05); }
.popover .dict-sound:active { transform: scale(.94); }
.popover .dict-sound-tag { font-size: .66em; font-weight: 600; line-height: 1; }
.popover .dict-ph-row { margin-top: 3px; }
.popover .dict-ph { font-size: .86em; color: var(--c-text-muted); font-family: system-ui, -apple-system, 'Segoe UI', 'Microsoft YaHei', sans-serif; }
.popover .dict-phonetic { color: var(--c-text-muted); font-size: .82em; margin: 2px 0; }
.popover .dict-meaning { color: var(--c-text-secondary); margin: 8px 0; font-size: .9em; line-height: 1.8; }
.popover .dict-meaning div { padding: 1px 0; }
.popover .dict-actions { margin-top: 12px; display: flex; gap: 8px; }
.popover .dict-actions button { padding: 6px 14px; border-radius: var(--radius-sm); font-size: .82em; font-weight: 500; }
.popover .btn-add { background: var(--c-accent); color: var(--c-white); }
.popover .btn-add:hover { background: var(--c-accent-hover); }
.popover .btn-close { background: #FFFFFF; color: var(--c-text-secondary); border: 1px solid #EDE4D0; }
.popover .btn-close:hover { background: #F5F0E6; }
.popover .dict-folds { margin-top: 4px; }
.popover .fold-item { border-top: 1px dashed rgba(120,113,108,.18); }
.popover .fold-head { width: 100%; display: flex; align-items: center; justify-content: space-between; padding: 7px 2px; background: none; border: none; font-size: .78em; font-weight: 600; color: var(--c-text-muted); cursor: pointer; letter-spacing: .04em; }
.popover .fold-head:hover { color: var(--c-accent); }
.popover .fold-arrow { transition: transform .2s ease; font-size: 1em; }
.popover .fold-item.open .fold-arrow { transform: rotate(90deg); }
.popover .fold-body { display: none; padding: 0 2px 10px; }
.popover .fold-item.open .fold-body { display: block; }
.popover .fold-phrase { font-size: .8em; margin: 4px 0; color: var(--c-text-secondary); line-height: 1.6; }
.popover .fold-phrase b { color: var(--c-accent-deep); font-weight: 600; }
.popover .fold-syn { font-size: .8em; margin: 4px 0; color: var(--c-text-secondary); line-height: 1.6; }
.popover .fold-syn b { color: var(--c-accent-deep); font-weight: 600; }
.popover .fold-etym { font-size: .78em; color: var(--c-text-secondary); line-height: 1.75; margin: 4px 0; }
.popover.phrase-popover { max-width: 420px; }
.popover.phrase-popover .dict-word { word-break: break-word; }
.popover.phrase-popover .dict-meaning.loading { color: var(--c-text-muted); }
.popover .phrase-syn { margin-top: 8px; font-size: .84em; color: var(--c-text-secondary); line-height: 1.8; }
.popover .phrase-syn .syn-label { color: var(--c-text-muted); }
.popover .phrase-syn .syn-item { display: inline-block; background: var(--c-accent-light); border-radius: 4px; padding: 1px 8px; margin: 2px 4px 2px 0; color: var(--c-accent-deep); }
.popover.phrase-popover .dict-word.not-phrase { color: var(--c-text-muted); }

/* Translation Overlay */
/* 2026-10-23：浮窗跟着选中的句子走（见 transPlace）。卡片限高 + 自己滚：
   长译文以前用 fixed 定位又没限高，超出视口的部分永远看不到。 */
.trans-overlay { position: fixed; background: var(--c-white); border-radius: var(--radius-md); box-shadow: var(--shadow-lg); padding: 18px 22px; z-index: 300; max-width: 460px; max-height: calc(100vh - 160px); overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; display: none; border: 1px solid var(--c-border); animation: popIn .15s ease; }
.trans-overlay.compact { padding: 8px; }
.trans-overlay.show { display: block; }
.trans-overlay .loading { color: var(--c-text-muted); font-size: .9em; }
.trans-overlay .trans-text { line-height: 1.8; margin-top: 8px; font-size: .92em; color: var(--c-text-secondary); }
.trans-actions { display: flex; gap: 6px; }
.trans-actions button { display: inline-flex; align-items: center; justify-content: center; background-color: #FFFFFF; border: 1px solid rgba(0,0,0,.1); border-radius: 6px; box-shadow: rgba(0,0,0,.02) 0 1px 3px 0; box-sizing: border-box; color: rgba(0,0,0,.8); cursor: pointer; font-family: system-ui,-apple-system,system-ui,"Helvetica Neue",Helvetica,Arial,sans-serif; font-size: .78em; font-weight: 400; justify-content: center; line-height: 1; padding: 7px 14px; text-decoration: none; transition: all 250ms; user-select: none; -webkit-user-select: none; touch-action: manipulation; vertical-align: baseline; width: auto; }
.trans-actions button:hover, .trans-actions button:focus { border-color: rgba(0,0,0,.15); box-shadow: rgba(0,0,0,.1) 0 4px 12px; color: rgba(0,0,0,.62); }
.trans-actions button:hover { transform: translateY(-1px); }
.trans-actions button:active { background-color: #F0F0F1; border-color: rgba(0,0,0,.15); box-shadow: rgba(0,0,0,.06) 0 2px 4px; color: rgba(0,0,0,.62); transform: translateY(0); }

/* Bottom Section */
.bottom-section { max-width: 1440px; margin: 0 auto; padding: 0 24px 48px; }
.bottom-section h3 { font-size: 1em; font-weight: 600; margin: 28px 0 14px; color: var(--c-primary-dark); }
.loading-dots { color: var(--c-text-muted); font-size: .9em; }
.full-trans { background: var(--c-white); border-radius: var(--radius-md); padding: 28px 32px; box-shadow: 0 4px 20px rgba(0,0,0,.06), 0 12px 40px rgba(0,0,0,.08); border: 1px solid var(--c-border); line-height: 1.9; color: var(--c-text-secondary); margin-top: 20px; font-size: .95em; text-align: justify; }
.full-trans p { text-indent: 2em; }

/* Settings Modal */
.modal-overlay { position: fixed; inset: 0; background: rgba(41,37,36,.4); z-index: 400; display: none; align-items: center; justify-content: center; backdrop-filter: blur(4px); }
.modal-overlay.show { display: flex; }
.modal { background: var(--c-white); border-radius: var(--radius-lg); padding: 32px; max-width: 420px; width: 90%; box-shadow: var(--shadow-lg); }
.modal h3 { margin-bottom: 20px; color: var(--c-text); font-size: 1.1em; font-weight: 600; }
.modal label { display: block; font-size: .82em; color: var(--c-text-secondary); margin-bottom: 6px; font-weight: 500; }
.modal input { width: 100%; padding: 10px 14px; border: 1px solid var(--c-border); border-radius: var(--radius-sm); font-size: .9em; margin-bottom: 16px; outline: none; font: inherit; transition: border-color var(--transition-fast); }
.modal input:focus { border-color: var(--c-accent); }
.modal .btn-row { display: flex; gap: 10px; justify-content: flex-end; }
.modal .btn-row button { padding: 8px 20px; border-radius: var(--radius-sm); font-size: .85em; font-weight: 500; }
.modal .btn-save { background: var(--c-accent); color: var(--c-white); }
.modal .btn-save:hover { background: var(--c-accent-hover); }
@media (max-width: 768px) {
  #parseResult { font-size: .8em; }
  #parseResult p { margin-bottom: 4px; }
  #parseResult li { margin-bottom: 2px; }
  #parseOriginal { font-size: .85em !important; }
}
html.force-phone #parseResult { font-size: .8em; }
html.force-phone #parseResult p { margin-bottom: 4px; }
html.force-phone #parseResult li { margin-bottom: 2px; }
html.force-phone #parseOriginal { font-size: .85em !important; }
.modal .hint { font-size: .78em; color: var(--c-text-muted); margin-bottom: 16px; line-height: 1.6; }

.hidden { display: none !important; }

/* Donate Modal */
.donate-overlay { position: fixed; inset: 0; background: rgba(41,37,36,.45); z-index: 400; display: none; align-items: center; justify-content: center; backdrop-filter: blur(6px); }
.donate-overlay.show { display: flex; }
.donate-card {
  background: #F4EEE5;
  border-radius: 24px;
  padding: 28px 32px 24px;
  max-width: 420px; width: 90%;
  text-align: center;
  box-shadow: 0 20px 60px rgba(120,113,108,.15), 0 2px 8px rgba(0,0,0,.04);
  border: 1px solid rgba(90,110,69,.12);
  position: relative;
  overflow: hidden;
}
.donate-card::before {
  content: '';
  position: absolute; top: 0; left: 0; right: 0;
  height: 3px;
  background: #8A856F;
}
.donate-card.show-anim { animation: donateIn .4s cubic-bezier(.34,1.56,.64,1); }
@keyframes donateIn { from { opacity: 0; transform: translateY(20px) scale(.96); } to { opacity: 1; transform: translateY(0) scale(1); } }

.donate-card .donate-icon-svg { display: block; margin: 0 auto 10px; opacity: .85; }

.donate-card h3 {
  font-size: 1.4em; font-weight: 600; letter-spacing: .4em;
  color: var(--c-primary-dark); margin-bottom: 12px;
}
.donate-card .donate-text {
  font-size: .88em; color: var(--c-text-secondary); line-height: 1.72;
  margin-bottom: 12px; text-align: justify;
  padding: 0 4px; text-indent: 2em;
}
.donate-card .donate-qq {
  font-size: .84em; color: var(--c-text-muted); margin-bottom: 16px;
  letter-spacing: .02em;
}
.donate-card .donate-qq strong {
  color: var(--c-accent); font-size: 1.05em; font-weight: 600;
  letter-spacing: .05em;
}
.donate-card .btn-row { display: flex; gap: 14px; justify-content: center; }
.donate-card .btn-row button {
  padding: 11px 32px; border-radius: 100px;
  font-size: .88em; font-weight: 500;
  letter-spacing: .04em;
  transition: all .2s ease;
}
.donate-card .btn-skip {
  background: transparent; color: var(--c-text-muted);
  border: 1px solid var(--c-border);
}
.donate-card .btn-skip:hover { background: rgba(0,0,0,.03); color: var(--c-text-secondary); border-color: var(--c-primary-light); }

/* ── 打赏卡片上的彩蛋入口：「暂不打赏 / 施舍一下」那一排下面 ── */
.gift-entry {
  display: flex; align-items: center; justify-content: center; gap: 6px;
  width: 100%; margin-top: 16px; padding: 9px 14px;
  border: 1px dashed rgba(90,110,69,.45); border-radius: 100px;
  background: rgba(255,248,238,.75); color: #4A3229;
  font-size: .84em; font-weight: 600; letter-spacing: .02em; cursor: pointer;
  transition: background .18s ease, border-color .18s ease, transform .18s ease, box-shadow .18s ease;
}
.gift-entry:hover {
  background: #E9E0D4; border-color: var(--c-accent); border-style: solid;
  transform: translateY(-1px); box-shadow: 0 3px 12px rgba(90,110,69,.18);
}
.gift-entry:active { transform: translateY(0) scale(.99); }
.gift-entry-emoji { font-size: 1.15em; line-height: 1; }
html.dark .gift-entry { background: rgba(58,45,27,.6); border-color: rgba(90,110,69,.5); color: #D4A373; }

/* ── 「一份神秘礼物」卡片 ──
   设计依据（ui-ux-pro-max）：
     · Glassmorphism 明确适用于 modal overlay → 遮罩毛玻璃加强到 blur(14px) + saturate(120%)
     · Bento 卡片规范 → 选项 16px 圆角、1px 发丝边、内高光、hover scale(1.02)
     · UX「Focus States」是 High 严重度项 → 补齐 :focus-visible 焦点环（原来这张卡片完全没有）
   配色沿用站内暖纸体系（--c-accent #5A6E45），不引入新色相；四个选项各给一个主题色圆底做辨识度。 */
.gift-overlay {
  z-index: 410;   /* 比打赏卡（400）高一层 */
  background: rgba(41,37,36,.38);
  backdrop-filter: blur(14px) saturate(120%);
  -webkit-backdrop-filter: blur(14px) saturate(120%);
}
/* 选择器写成 .gift-overlay .gift-card（而非裸 .gift-card）：
   站点在 3742 行有一条 `html.dark .modal { background:#2A2623; box-shadow:... }`，
   与 `html.dark .gift-card` 权重相同但位置更靠后 —— 实测把暗色的渐变底和四层阴影盖掉了
   （computed 里 backgroundImage 变成 none、阴影只剩 1 层）。这里提高一级权重，与顺序解耦。
   媒体查询里的 .gift-card 也必须同步提高，否则它会被上面这条基础规则压住、失去响应式内边距。 */
.gift-overlay .gift-card {
  position: relative; max-width: 396px; padding: 38px 30px 26px; text-align: center;
  border-radius: 24px; border: 1px solid rgba(90,110,69,.16);
  background: #F6F2EB;
  box-shadow: 0 1px 0 rgba(255,255,255,.9) inset,
              0 2px 6px rgba(120,80,20,.06),
              0 18px 48px -12px rgba(120,80,20,.28),
              0 40px 80px -30px rgba(120,80,20,.22);
  overflow: hidden;
}
/* 顶部一条金色发丝线，左右淡出 */
.gift-card::before {
  content: ''; position: absolute; top: 0; left: 12%; right: 12%; height: 1.5px;
  background: linear-gradient(90deg, transparent, rgba(90,110,69,.55), transparent);
}
.gift-overlay.show .gift-card { animation: giftCardIn .42s cubic-bezier(.22,1.2,.4,1) both; }
@keyframes giftCardIn { from { opacity: 0; transform: translateY(16px) scale(.94); } to { opacity: 1; transform: none; } }

/* 右上角细 × */
.gift-x {
  position: absolute; top: 12px; right: 12px; width: 30px; height: 30px;
  display: flex; align-items: center; justify-content: center;
  border: none; border-radius: 50%; background: transparent; color: #B9A899;
  cursor: pointer; transition: background .18s ease, color .18s ease;
}
.gift-x:hover { background: rgba(185,168,153,.14); color: #4A3229; }
.gift-x svg { width: 15px; height: 15px; }

/* 会呼吸的光环 + 圆形金底徽章 + 四颗小星点 */
.gift-badge { position: relative; width: 84px; height: 84px; margin: 0 auto 16px; display: flex; align-items: center; justify-content: center; }
.gift-badge::before {
  content: ''; position: absolute; inset: 0; border-radius: 50%;
  background: radial-gradient(circle at 50% 38%, #F2EDE4, #E9E0D4 60%, #E9E0D4);
  box-shadow: 0 6px 18px -4px rgba(90,110,69,.35), 0 0 0 1px rgba(90,110,69,.14) inset;
}
.gift-badge-ring {
  position: absolute; inset: -7px; border-radius: 50%;
  border: 1.5px solid rgba(90,110,69,.32);
  animation: giftRing 2.6s ease-in-out infinite;
}
@keyframes giftRing { 0%,100% { transform: scale(.94); opacity: .75; } 50% { transform: scale(1.06); opacity: .28; } }
.gift-badge-emoji {
  position: relative; z-index: 2; font-size: 2.5em; line-height: 1;
  filter: drop-shadow(0 4px 8px rgba(92,64,51,.28));
  animation: giftPop .62s cubic-bezier(.34,1.56,.64,1) both;
}
@keyframes giftPop {
  0% { transform: scale(.4) rotate(-12deg); opacity: 0; }
  60% { transform: scale(1.1) rotate(4deg); opacity: 1; }
  100% { transform: scale(1) rotate(0deg); }
}
.gift-spark { position: absolute; border-radius: 50%; background: #D4A373; opacity: .8; }
.gift-spark.s1 { top: 6px; left: -14px; width: 4px; height: 4px; }
.gift-spark.s2 { top: 24px; right: -16px; width: 3px; height: 3px; background: #D4A373; }
.gift-spark.s3 { bottom: 12px; left: -10px; width: 3px; height: 3px; background: #DFA0C8; }
.gift-spark.s4 { bottom: 2px; right: -12px; width: 5px; height: 5px; background: #86C7A8; opacity: .65; }

/* 标题与「分隔式」副标题（两侧各一条短细线） */
.gift-card h3 { margin: 0 0 10px; font-size: 1.24em; font-weight: 700; letter-spacing: .14em; color: #4A3229; }
.gift-card-sub { display: flex; align-items: center; justify-content: center; gap: 10px; margin: 0 0 24px; font-size: .84em; color: #A8804E; }
.gift-card-sub::before, .gift-card-sub::after { content: ''; width: 26px; height: 1px; background: linear-gradient(90deg, transparent, rgba(168,128,78,.5)); }
.gift-card-sub::after { transform: scaleX(-1); }

/* Bento 选项：发丝边 + 内高光 + hover 微抬 + 主题色 emoji 圆底 */
.gift-options { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 20px; }
.gift-opt {
  position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px;
  padding: 18px 8px 15px; border: 1px solid rgba(185,168,153,.22); border-radius: 16px;
  background: #FFFEFC;
  color: #3A322C; text-decoration: none; font-weight: 600;
  box-shadow: 0 1px 0 rgba(255,255,255,.9) inset, 0 1px 3px rgba(120,80,20,.06);
  transition: transform .18s cubic-bezier(.34,1.4,.64,1), box-shadow .18s ease, border-color .18s ease;
}
.gift-opt:hover { transform: translateY(-3px) scale(1.02); box-shadow: 0 1px 0 rgba(255,255,255,.9) inset, 0 10px 22px -8px rgba(120,80,20,.3); }
.gift-opt:active { transform: translateY(-1px) scale(.995); }
.gift-opt-emoji { display: flex; align-items: center; justify-content: center; width: 42px; height: 42px; border-radius: 13px; font-size: 1.42em; line-height: 1; }
.gift-opt-name { font-size: .9em; letter-spacing: .04em; }
.gift-opt[data-theme="gaokao"] .gift-opt-emoji { background: #E9E0D4; box-shadow: 0 2px 6px -2px rgba(90,110,69,.4); }
.gift-opt[data-theme="cet4"]   .gift-opt-emoji { background: #C0E8D6; box-shadow: 0 2px 6px -2px rgba(79,107,54,.35); }
.gift-opt[data-theme="cet6"]   .gift-opt-emoji { background: #CAD6F6; box-shadow: 0 2px 6px -2px rgba(50,80,170,.35); }
.gift-opt[data-theme="kaoyan"] .gift-opt-emoji { background: #DFCEF4; box-shadow: 0 2px 6px -2px rgba(110,60,160,.35); }
.gift-opt[data-theme="gaokao"]:hover { border-color: rgba(90,110,69,.5); }
.gift-opt[data-theme="cet4"]:hover   { border-color: rgba(79,107,54,.45); }
.gift-opt[data-theme="cet6"]:hover   { border-color: rgba(50,80,170,.45); }
.gift-opt[data-theme="kaoyan"]:hover { border-color: rgba(110,60,160,.45); }
/* 键盘焦点环（ui-ux-pro-max: Focus States, High 严重度） */
.gift-opt:focus-visible, .gift-x:focus-visible, .gift-card-close:focus-visible { outline: 2px solid var(--c-accent); outline-offset: 3px; }
/* 打开时焦点落在卡片**容器**上（a11y 标准做法），Tab 再进第一个选项。
   容器自己不画环 —— 它不可交互，且这样能避免"默认选中了高考"的误读。 */
.gift-overlay .gift-card:focus { outline: none; }

/* 关闭：轻量 ghost 胶囊 */
.gift-card-close {
  display: block; margin: 0 auto; padding: 9px 26px; border-radius: 100px;
  background: transparent; border: 1px solid rgba(185,168,153,.28);
  color: #8A7A6B; font-size: .82em; cursor: pointer;
  transition: background .18s ease, color .18s ease, border-color .18s ease;
}
.gift-card-close:hover { background: rgba(185,168,153,.1); border-color: rgba(185,168,153,.45); color: #4A3229; }

/* 暗色模式 */
html.dark .gift-overlay { background: rgba(12,10,9,.55); }
html.dark .gift-overlay .gift-card {
  border-color: rgba(90,110,69,.22);
  background: #2A241E;
  box-shadow: 0 1px 0 rgba(255,255,255,.06) inset, 0 18px 48px -12px rgba(0,0,0,.6);
}
html.dark .gift-card h3 { color: #D4A373; }
html.dark .gift-card-sub { color: #A89478; }
html.dark .gift-card-sub::before, html.dark .gift-card-sub::after { background: linear-gradient(90deg, transparent, rgba(185,168,153,.4)); }
html.dark .gift-opt { background: #302923; border-color: rgba(90,110,69,.18); color: #EADFCE; box-shadow: 0 1px 0 rgba(255,255,255,.05) inset; }
html.dark .gift-opt:hover { box-shadow: 0 1px 0 rgba(255,255,255,.05) inset, 0 10px 22px -8px rgba(0,0,0,.55); }
html.dark .gift-x { color: #8A7A66; }
html.dark .gift-x:hover { background: rgba(90,110,69,.14); color: #D4A373; }
html.dark .gift-card-close { color: #B9A899; border-color: rgba(90,110,69,.24); }
html.dark .gift-card-close:hover { background: rgba(90,110,69,.12); color: #D4A373; }

@media (max-width: 480px) {
  .gift-overlay .gift-card { padding: 32px 20px 22px; border-radius: 20px; }
  .gift-badge { width: 72px; height: 72px; margin-bottom: 14px; }
  .gift-badge-emoji { font-size: 2.1em; }
  .gift-card h3 { font-size: 1.14em; }
  .gift-options { gap: 10px; }
  .gift-opt { padding: 14px 6px 12px; }
  .gift-opt-emoji { width: 38px; height: 38px; border-radius: 18px; }
}
@media (prefers-reduced-motion: reduce) {
  .gift-overlay.show .gift-card, .gift-badge-emoji, .gift-badge-ring { animation: none; }
}
@keyframes shake {
  0% { left: 45%; }
  25% { left: 54%; }
  50% { left: 48%; }
  75% { left: 52%; }
  100% { left: 50%; }
}

.donate-card .qr-img {
  max-width: 200px; width: 100%;
  margin: 4px auto 14px; display: block;
  border-radius: 16px;
  box-shadow: 0 4px 20px rgba(0,0,0,.08);
}

/* Vocab Page */
.vocab-page { max-width: 800px; margin: 0 auto; padding: 40px 24px; }
.vocab-page h2 { font-size: 1.5em; font-weight: 700; color: var(--c-primary-dark); margin-bottom: 8px; }
.vocab-page .vp-sub { color: var(--c-text-muted); font-size: .9em; margin-bottom: 28px; }
.vp-toolbar { display: flex; gap: 10px; margin-bottom: 20px; flex-wrap: wrap; }
/* 生词本 / 词组本的计数（2026-10-04 用户要求）：从标题下面挪到这一栏**最右**，与下面单词框的右缘对齐，
   并换一种字体（等宽，数字更整齐，和正文的衬线/无衬线都区分得开）。窄屏整行靠右，不挤按钮。 */
.vp-count { margin-left: auto; align-self: center; white-space: nowrap;
  font-family: ui-monospace, 'SFMono-Regular', Menlo, Monaco, Consolas, 'Courier New', monospace;
  font-size: .8em; letter-spacing: .02em; color: var(--c-text-muted); }
@media (max-width: 768px) { .vp-count { flex: 1 1 100%; margin-left: 0; text-align: right; } }
html.force-phone .vp-count { flex: 1 1 100%; margin-left: 0; text-align: right; }
/* 标题去掉后 .ws-vocab-head 只剩「全部加入学习」一个孩子 → 保持靠右（原来靠 space-between 顶到右边） */
#wordStudyPage .ws-vocab-head { justify-content: flex-end; }
.vp-toolbar button { padding: 8px 18px; border-radius: var(--radius-sm); font-size: .82em; font-weight: 500; display: flex; align-items: center; gap: 6px; }
.vp-btn-study { background: var(--c-accent-deep); color: #fff; }
.vp-btn-study:hover { background: var(--c-accent-hover); }
.vp-btn-outline { background: #fff; color: var(--c-text-secondary); border: 1px solid var(--c-border); }
.vp-btn-outline:hover { background: #F5F5F4; }

/* ── 生词本 / 词组本：右上角那排工具收进一颗毛玻璃胶囊（179.291 用户要求「连在一起」）──
   原来是一排各自白底 + 描边的小胶囊，视觉是散的；正上方那条 `.ws-tools-bar`（UK/音效/查词）
   本来就是毛玻璃胶囊，这里做成同一套语言：**整排共用一层玻璃底，按钮自身去掉描边与白底，
   靠 hover 时"该格升起浅底"区分**。计数与「不再提示 ?」一并收进玻璃底（不再嵌套第二层小胶囊）。
   口径：生词本与词组本两栏共用这套（结构完全一致）；手机档按钮照旧换行、胶囊底随内容。 */
.vp-toolbar { gap: 2px; align-items: center; padding: 4px 6px; border-radius: 9999px;
  background: linear-gradient(180deg, rgba(255,253,248,.62), rgba(247,240,229,.5));
  border: 1px solid rgba(92,64,51,.12);
  -webkit-backdrop-filter: blur(14px) saturate(1.2); backdrop-filter: blur(14px) saturate(1.2);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.5); }
/* ⚠️ 原来写的是 `rgba(255,255,255,.55)`：白 55% 叠在暖纸底（#FBF6EC）上≈纯白，
   测出来"玻璃面"和页面底色几乎没差别（对照实验：加浓色偏才看得出 blur 在生效）——
   所以改成**带透明度更高的暖色顶光**，玻璃面才读得出来。 */
html.dark .vp-toolbar { background: linear-gradient(180deg, rgba(255,255,255,.08), rgba(255,255,255,.04));
  border-color: rgba(255,255,255,.12); box-shadow: inset 0 1px 0 rgba(255,255,255,.05); }

.vp-empty { text-align: center; padding: 60px 20px; color: var(--c-text-muted); }
.vp-empty svg { width: 48px; height: 48px; margin-bottom: 16px; color: var(--c-border); }

/* Vocab/Phrase Tab Radio Group (topbar) */
.radio-group {
  display: flex;
  gap: 0;
  background: rgba(255, 255, 255, 0.55);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  padding: 4px;
  border-radius: 25px;
  box-shadow: 0 2px 10px rgba(120, 113, 108, 0.12), inset 0 1px 0 rgba(255, 255, 255, 0.7);
  border: 1px solid rgba(217, 119, 6, 0.16);
  position: relative;
  width: 210px;
  height: 36px;
  animation: rg-slide-in 0.5s ease-out;
}
@keyframes rg-slide-in {
  from { opacity: 0; transform: scale(0.9); }
  to { opacity: 1; transform: scale(1); }
}
.radio-group .rg-slider {
  position: absolute;
  top: 4px;
  bottom: 4px;
  left: 4px;
  width: calc(50% - 4px);
  background: #fff;
  border-radius: 20px;
  transition: all 0.4s cubic-bezier(0.68, -0.55, 0.265, 1.55);
  box-shadow: 0 2px 8px rgba(90,110,69,0.2), 0 1px 3px rgba(0, 0, 0, 0.08);
  z-index: 0;
}
.radio-option {
  position: relative;
  z-index: 1;
  flex: 1;
}
.radio-option input[type="radio"] {
  position: absolute;
  opacity: 0;
  cursor: pointer;
  margin: 0;
  width: 100%;
  height: 100%;
}
.radio-label {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  padding: 0 14px;
  color: var(--c-text-secondary);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: color 0.3s ease;
  user-select: none;
  border-radius: 20px;
  position: relative;
  white-space: nowrap;
}
.radio-option input[type="radio"]:checked + .radio-label {
  color: var(--c-accent-deep);
}
.radio-label:hover {
  color: var(--c-accent);
}
.radio-group:has(#basicGenRadio:checked) .rg-slider {
  left: calc(50%);
}
.radio-group:has(#storyHubRadio) { width: 290px; }
.radio-group:has(#storyHubRadio) .rg-slider {
  width: calc(33.333% - 3px);
}
.radio-group:has(#storyGenRadio:checked) .rg-slider {
  left: calc(33.333%);
}
.radio-group:has(#storyImportRadio:checked) .rg-slider {
  left: calc(66.666%);
}

/* Basic Reading Generate Entry */
.gen-entry { display: flex; align-items: center; justify-content: center; height: calc(100vh - 100px); padding: 24px; }
.flip-card {
  background-color: transparent;
  width: 240px;
  height: 320px;
  perspective: 1000px;
  font-family: 'Noto Serif SC', serif;
  cursor: pointer;
}
.flip-card-inner {
  position: relative;
  width: 100%;
  height: 100%;
  text-align: center;
  transition: transform 0.8s;
  transform-style: preserve-3d;
}
.flip-card:hover .flip-card-inner {
  transform: rotateY(180deg);
}
.flip-card-front, .flip-card-back {
  box-shadow: 0 8px 14px 0 rgba(0,0,0,0.2);
  position: absolute;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 100%;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
  border: 1px solid coral;
  border-radius: 1rem;
  padding: 20px;
  box-sizing: border-box;
}
.flip-card-front {
  background: linear-gradient(120deg, bisque 60%, rgb(255, 231, 222) 88%,
     rgb(255, 211, 195) 40%, rgba(168,128,78,0.603) 48%);
  color: coral;
}
.flip-card-back {
  background: linear-gradient(120deg, rgb(255, 174, 145) 30%, coral 88%,
     bisque 40%, rgb(255, 185, 160) 78%);
  color: white;
  transform: rotateY(180deg);
}
.gen-entry-icon { width: 64px; height: 64px; border-radius: 50%; background: #A8804E; color: #fff; display: flex; align-items: center; justify-content: center; margin: 0 auto 18px; box-shadow: 0 4px 16px rgba(168,128,78,.3); }
.flip-card h3 { font-family: 'Noto Serif SC', serif; font-size: 1.4em; font-weight: 700; margin: 0 0 10px; letter-spacing: .03em; }
.flip-card-front h3 { color: coral; }
.flip-card p { font-size: .85em; line-height: 1.7; margin: 0; max-width: 200px; }
.flip-card-back p { color: rgba(255,255,255,.92); }
.topbar .chat-search { width: 180px; height: 32px; padding: 0 14px; border: 1px solid var(--c-border); border-radius: 9999px; font-size: .82em; color: var(--c-text); background: #fff; outline: none; transition: border-color .2s ease; }
.topbar .chat-search:focus { border-color: var(--c-accent); }
.topbar .chat-search::placeholder { color: var(--c-text-muted); }
/* 深色：白色透镜与发丝线相应减淡。
   注：这一段原先是「速记生词页通栏玻璃条」的覆盖规则（#wordStudyPage .topbar / .ws-topbar-title
   与它那条手机媒体查询）—— 老玻璃条已于 2026-10-03 整条删除，那些规则（连同基础 .ws-topbar-title）
   一并清掉，只留下面两条工具条暗色规则。 */
html.dark .ws-tool-item:hover { background: rgba(255,255,255,.10); }
html.dark .ws-tool-sep { background: rgba(255,255,255,.14); }
#wordStudyPage { display: flow-root; }
/* 本页 --c-text-muted 原为 #A8A29E，在暖底 #F5EFE4 上仅 2.43:1（正文需 4.5:1），
   落在未选中侧栏项、块标题、「加载中／暂无释义」等处。限定到本页且只在白天生效
   （暗夜由 html.dark 自己的调色板接管；自定义属性按继承就近取值，故加 :not(.dark) 兜底）。 */
html:not(.dark) #wordStudyPage { --c-text-muted: #78716C; }

/* 左侧全高竖导航 + 内容 */
.ws-shell { display: flex; }
.ws-side-brand { display: flex; align-items: center; gap: var(--ws-brand-gap, 8px); padding: var(--ws-brand-pad, 4px 6px 16px); font-size: var(--ws-brand-fs, .95em); font-weight: 700; color: var(--c-text); }
.ws-side-brand svg { width: var(--ws-brand-icon, 20px); height: var(--ws-brand-icon, 20px); color: var(--c-accent); flex-shrink: 0; }
.ws-side-item { display: flex; align-items: center; gap: var(--ws-item-gap, 10px); min-height: var(--ws-item-minh, 44px); padding: var(--ws-item-pad, 10px 12px); border: none; border-radius: 16px; background: transparent; color: var(--c-text-secondary); font-size: var(--ws-item-fs, .86em); font-weight: 600; text-align: left; cursor: pointer; transition: var(--transition-fast); }
.ws-side-item svg { width: var(--ws-item-icon, 18px); height: var(--ws-item-icon, 18px); flex-shrink: 0; }
.ws-side-item:hover { background: var(--c-bg); color: var(--c-text); }
.ws-side-item.sel { background: var(--c-accent); color: #fff; }
html.dark .ws-side-item.sel { color: #1C1917; }
.ws-content { flex: 1; min-width: 0; margin-left: var(--ws-side-w, 150px); padding: var(--ws-content-pad, 24px 28px 48px); }

.ws-stage { position: relative; flex: 1; min-height: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; overflow: hidden; }
.ws-card { position: relative; width: 100%; max-height: 100%; display: flex; flex-direction: column; background: transparent; border: none; border-radius: var(--radius-lg); padding: 12px 26px 0; text-align: center; box-shadow: none; overflow: hidden; }
.ws-card.revealed { height: 100%; justify-content: flex-start; }
/* 键盘提示（2026-10-10）：放在「不认识 / 认识」下面一行（居中），且**随阶段换文案** ——
   只写"两阶段都列出来"会误导：按下 ↓ 之后这张卡回到未评分态，那次 → 是评分、不是前进。
   ⚠️ 一开始是绝对定位挂在评分行**右侧**，920 宽的卡片里它从 1426px 起算、被视口切掉 ——
   所以改成同一列里的第二行，只多 21px 高度，不占左右空间。
   显隐与 wsKeyPhase() 的判定对齐：只有电脑/桌面档能看到（手机/平板/窄屏不显示）。 */
.ws-keyhint { display: flex; align-items: center; justify-content: center; flex-wrap: wrap;
  gap: 8px; margin-top: 10px; font-size: .7em; color: var(--c-text-muted); }
.ws-keyhint i { font-style: normal; opacity: .45; }
.ws-keyhint kbd { font-family: 'Noto Serif SC', serif; font-size: .92em; line-height: 1;
  padding: 3px 7px 4px; margin-right: 4px; border-radius: 6px;
  border: 1px solid rgba(120,113,108,.28); background: rgba(120,113,108,.06); color: var(--c-text-secondary); }
html.dark .ws-keyhint kbd { border-color: rgba(255,255,255,.16); background: rgba(255,255,255,.05); }
@media (max-width: 1024px) { .ws-keyhint { display: none; } }
html.force-tablet .ws-keyhint, html.force-phone .ws-keyhint { display: none; }
.ws-word { font-family: var(--ws-word-ff, ui-monospace, 'SFMono-Regular', Menlo, Monaco, Consolas, 'Courier New', monospace); font-size: calc(var(--ws-word-fs, clamp(2.8em, 9vw, 5em)) * var(--ws-word-scale, 1)); font-weight: 700; letter-spacing: .01em; line-height: 1.15; color: var(--c-text); word-break: break-word; transition: color .25s ease; }
/* 注：此处原有 .ws-quick-meaning（词下琥珀色首义大字）。它与揭示面板内的首义**完全重复**
   （评审 A 早已指出"揭示态重复首义"），也是页面上最大的一块黄，故整体移除 ——
   首义的强调改由面板内的 .ws-mean-line.first 承担（见下）。 */
.ws-card.forget .ws-word { color: var(--c-accent); }
.ws-phon-row { display: flex; justify-content: center; align-items: center; gap: 20px; flex-wrap: wrap; margin-top: 14px; min-height: 22px; }
.ws-phon-item { display: inline-flex; align-items: center; gap: 5px; font-size: .86em; color: var(--c-text-secondary); }
.ws-phon-label { font-size: .8em; font-weight: 700; color: var(--c-text-muted); }
.ws-spk { position: relative; display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; padding: 0; border: none; border-radius: 50%; background: transparent; color: #8A8177; cursor: pointer; transition: color .18s ease, background .18s ease; }
/* 视觉尺寸保持 22px，用不可见覆盖层把热区扩到 44×44（触摸目标下限） */
.ws-spk::after { content: ''; position: absolute; inset: -11px; }
/* 悬停由绿色底（rgba(79,107,54,.14)，游离的冷色）改为中性铅笔灰 —— 与 E-Ink 单色方向一致 */
.ws-spk:hover { color: var(--c-text); background: rgba(120,113,108,.12); }
.ws-spk svg { width: 15px; height: 15px; }
.ws-bottom { flex-shrink: 0; min-height: 108px; display: flex; flex-direction: column; justify-content: center; }
.ws-actions { display: flex; flex-direction: row; gap: 18px; width: 100%; max-width: var(--ws-actions-w, 480px); margin: 0 auto; }
/* flex-basis 必须给显式长度（而非 0）：本站 box-sizing:border-box，flex-basis:0 会被各自折叠成
   「padding+border」——认识(28×2+2×2=60) 与 不认识(3×2+0=6) 基准不同，导致两枚宽度不均(348/294)。
   取 100px（大于两者的 padding+border）使基准一致，两枚各得 321px。 */
/* 尺寸：容器 max-width 决定宽度，padding/font-size 决定「认识」高度（它撑起整行），
   「不认识」的内层 span padding 必须同比缩，否则渐变环上下会露出白边。 */
.ws-act { flex: 1 1 100px; display: flex; align-items: center; justify-content: center; gap: 10px; padding: 16px; border: 1.5px solid var(--c-border); border-radius: 20px; background: var(--c-bg-card); color: var(--c-text); font-size: 1.2em; font-weight: 700; cursor: pointer; transition: var(--transition-fast); }
.ws-act-yes { background: var(--c-accent); border-color: var(--c-accent); color: #fff; }
.ws-act-yes:hover { background: var(--c-accent-hover); border-color: var(--c-accent-hover); }
/* 注：「不认识」的 hover 规则已移除 —— 其新皮肤是渐变+内层 span，旧的 background/color 覆写会把渐变抹掉 */
html.dark .ws-act-yes { color: #1C1917; }

/* 进度条 */
.ws-progress-bar { margin: 24px auto 0; max-width: 300px; padding: 0; border-top: none; }
.ws-progress-track { position: relative; height: 6px; border-radius: 99px; background: var(--c-border); }
.ws-progress-fill { height: 100%; width: 0; border-radius: 99px; background: var(--c-accent); transition: width var(--t-state) var(--ease-out-quart); }

/* 主页：居中舞台 + 左侧可收起词表 */
.ws-home { display: block; }
.ws-stage-col { min-width: 0; display: flex; flex-direction: column; justify-content: center; height: var(--ws-stage-h, calc(100vh - 168px)); overflow: hidden; }
/* 未揭示时让舞台收拢到卡面自身高度，使「卡面 + 决策区」作为一个整体垂直居中，
   消掉卡面与按钮之间约 245px 的死区。用 :has() 做渐进增强：揭示态不匹配该规则，
   舞台保持 flex:1，`.ws-card.revealed{height:100%}` 的滚动容纳契约不受影响；
   不支持 :has() 的浏览器整条规则被忽略，回退到改动前的表现，不会坏。 */
.ws-stage:has(> .ws-card:not(.revealed)) { flex: 0 1 auto; }

/* ── 右上角工具条：白卡容器 + 三个文字项（词典 / 发音 / 音效）──
   排版借鉴 qwertylearner.cn 顶栏（实测：白卡 / border-radius 12px / 8px 项圆角 / 文字项而非纯图标）。
   项级：词典=显示当前所背词库，点击跳「词库」tab；发音=显示当前口音，点击出下拉切换；
   音效=点击出小卡片，内含「自动发音」与「答题音效」两个开关。
   注意：站内**已有** `.ws-seg` 组件（设置页口音选择 / 生词本分段，规则见下方），
   上一版曾复用该类名导致级联互相污染（我的滑块组继承了旧组件的 border/radius/padding），
   本版不再使用 `.ws-seg`，全部限定在 `.ws-tool-*` 之下。
   偏离参考站之处：容器保留 1px 描边 —— 站内 --c-bg-card #FFFCF8 在页面暖底 #F5EFE4 上只有
   1.03:1（等于看不见），参考站"白卡浮在白背景上"的前提在这里不成立。 */
/* 工具条住在生词本页**顶部那条通栏玻璃条**（`.topbar`）的右端 —— 对标原网站（2026-10-07）。
   下面这条 `margin-left: auto` 就是把它顶到顶栏最右（= 页面右上角）用的；
   控件组自身不承载材质/定位，材质与圆角由 `.topbar` 统一给。
   显隐由 JS `wsSyncTools()` 管：只在「记单词主界面」「打字记词练习界面」出现。 */
.ws-toolbar { display: flex; align-items: center; gap: 3px; margin-left: auto; flex: none; }
@media (max-width: 768px) {
  /* 手机端一行放不下 15.2px 的项：压到 12.2px / 34px 高，并收紧内边距与分组线间距，
     把宽度让给标题（否则标题会被挤成两行）。热区仍靠 ::after 补到 44px。 */
  .ws-toolbar { gap: 0; }
  .ws-tool-item { min-height: 34px; padding: 6px 8px; font-size: .76em; gap: 2px; }
  .ws-tool-item::after { inset: -5px 0; }
  .ws-tool-item svg { width: 9px; height: 9px; }
  .ws-tool-sep { height: 13px; margin: 0; }
  /* 顶栏在手机上已经很挤：模式切换只留那个双向箭头图标，省出约 30px，避免标题被挤掉 */
  #wsModeBtn .ws-mode-emoji, #wsModeBtn #wsModeLabel { display: none; }
}

.ws-tool-item { position: relative; display: inline-flex; align-items: center; gap: 5px; min-height: 40px; padding: 8px 14px; border: 0; border-radius: 9999px; background: transparent; color: var(--c-text); font-size: .95em; font-weight: 600; letter-spacing: .01em; white-space: nowrap; cursor: pointer; transition: background .18s ease, color .18s ease, transform .12s ease; }
/* 热区纵向扩到 44px（横向不外扩，避免相邻项互相误触）；视觉高度仍是 40px */
.ws-tool-item::after { content: ''; position: absolute; inset: -2px 0; }
/* 悬停给一层"白色透镜"，压在玻璃上仍读作玻璃，而不是换成一块实色 */
.ws-tool-item:hover { background: rgba(255,255,255,.62); color: var(--c-text); }
.ws-tool-item.on { background: rgba(233,224,212,.72); color: var(--c-accent-deep); }
.ws-tool-item:active { transform: scale(.96); }
.ws-tool-item svg { width: 12px; height: 12px; opacity: .45; flex-shrink: 0; }
/* ── 手机模式重塑 · 第 1 步（2026-09-20）：底部导航 + 顶栏瘦身 ──
   形态由 `#wordStudyPage.ws-nav-mobile` **一个类**统一驱动（JS: wsSyncNav）。
   为什么不直接用媒体查询：媒体查询会跟 html.force-desktop / force-tablet 打架 ——
   实测 700px 窄窗口下会出现"侧栏被媒体查询隐藏、底部栏又因为不是 force-phone 而不显示"，
   结果是**完全没有导航**。用一个类驱动就不会有这种组合漏洞。
   桌面/平板不加这个类 → 下面全部规则不生效 → 桌面侧栏与平铺工具条一行不动。 */
/* 「速记生词」的手机底部栏（#wsTabBar，2026-09-20 那版加的）**已停用** ——
   2026-10-03 用户要求「去掉最底部那条横条，记单词时很明显」：
   栏目导航现在都在**上方那一排**里（手机端也放出来了，见下面的 `.ws-nav-mobile #wsRail`），底部不需要第二条。
   元素保留在 DOM 里（wsTab() 仍同步它的高亮，无副作用），只是不再显示。 */
/* 2026-10-07：手机档底部栏恢复启用（对标原网站：手机 = 侧栏收掉 + 底部栏导航） */
#wordStudyPage.ws-nav-mobile .ws-content { margin-left: 0; padding-bottom: 16px; }
/* ⚠️ 底部间距只加 16px：`html.force-phone body { padding-bottom: 64px }`（全局，给固定底部栏留位）
   已经把 56px 的 Tab 栏让开了。第 1 步一开始这里写的是 84px，等于算了两遍，
   手机端因此多出 41~105px 的无谓滚动（实测 390 下 41px、360 下 105px）。 */
/* ⋯ 按钮：手机才出现 */
#wordStudyPage .ws-tool-more { display: none; }
#wordStudyPage.ws-nav-mobile .ws-tool-more { display: inline-flex; }
/* 工具条：手机上从"平铺一排"变成"挂在顶栏下方的面板" */
#wordStudyPage.ws-nav-mobile .ws-toolbar { display: none; position: absolute; top: calc(100% + 8px); right: 8px; left: 8px;
  flex-direction: column; align-items: stretch; gap: 2px; padding: 8px; margin-left: 0; z-index: 60;
  background: rgba(255,255,255,.96); backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
  border: 1px solid var(--c-border); border-radius: 16px; box-shadow: 0 18px 44px rgba(41,37,36,.18); }
#wordStudyPage.ws-nav-mobile .ws-toolbar.open { display: flex; animation: wsToolIn .16s var(--ease-out-expo) both; }
#wordStudyPage.ws-nav-mobile .ws-toolbar .ws-tool-item { justify-content: flex-start; min-height: 44px; padding: 8px 12px; border-radius: 16px; font-size: .92em; }
#wordStudyPage.ws-nav-mobile .ws-toolbar .ws-tool-item svg { width: 13px; height: 13px; }
#wordStudyPage.ws-nav-mobile .ws-toolbar .ws-tool-sep { display: none; }
/* 面板里的下拉改成内联手风琴（position:static、无阴影）：小屏上"下拉里再套下拉"容易跑出屏幕 */
#wordStudyPage.ws-nav-mobile .ws-toolbar .ws-tool-menu { position: static; min-width: 0; padding: 2px 0 6px 10px;
  background: transparent; border: 0; box-shadow: none; }
html.dark #wordStudyPage.ws-nav-mobile .ws-toolbar { background: rgba(41,37,36,.96); }

/* ── 手机模式重塑 · 第 2 步已**按用户要求回退**（2026-09-20）──
   曾把「新学 / 复习」两张大卡压成两行紧凑任务行；用户看过之后明确要求保持原来的两张大卡，
   所以这里那一整套 `.ws-pick*` 的 grid 覆盖、以及为"垂直居中"加的弹性列（`#wordStudyPage.ws-nav-mobile`
   的 flex 链）全部删除，主页回到原样。**第 1 步（底部导航 + 顶栏瘦身）保留。**
   教训记下来：两张大卡虽然占屏，但它是这个页面的"门面"，改之前应当先问，而不是先做后看。 */

/* ── 用户列表：桌面表格 / 窄屏卡片（2026-09-20 第 2 步）──
   原来每行是一张 79px 的卡片、一行里堆三行文字，6 个用户吃掉 618px；
   桌面这本来就是**表格**的活：7 列（勾选 / 用户名 / 注册时间 / 今日在线 / 内容 / 今日访问 / 操作）。
   ⚠️ 同一个 DOM 两套排版：桌面 grid 7 列 + 表头；窄屏 `:not(.admin-desktop)` 变成卡片式换行，
      列名用 data-col 由 ::before 显示 —— 这样 JS 不用按模式分叉渲染。 */
/* 列宽要能在**最窄的外壳下**（平板 1024：内容区约 756px）也放得下 ——
   之前 操作列 96px 时合计 840px 就溢出了 74px（实测）。这里的合计 ≈ 664 + 6×10 间距 = 724 ≤ 756。
   末列放两个按钮：详情 + 重置密码；用户名列 1fr，宽屏下自动吃掉剩余宽度。 */
#adminPage { --user-cols: 34px minmax(110px, 1fr) 92px 84px 108px 72px 164px; }
.admin-table-head { display: none; }
.admin-row { border-bottom: 1px solid var(--c-border); }
.admin-row:last-child { border-bottom: 0; }
.admin-row:hover { background: #F5EFE4; }
html.dark .admin-row:hover { background: rgba(255,255,255,.04); }
.admin-row-check { display: flex; align-items: center; cursor: pointer; }
.admin-row-check input { cursor: pointer; accent-color: var(--c-accent); }
.admin-row-name { font-size: .9em; font-weight: 700; color: var(--c-text); }
.admin-row-status { display: block; font-size: .72em; font-weight: 600; margin-top: 1px; }
.admin-row-status.on { color: #4F6B36; }
.admin-row-status.off { color: var(--c-text-muted); }
.admin-row-cell { font-size: .82em; color: var(--c-text-secondary); font-variant-numeric: tabular-nums; }
.admin-row-act { padding: 5px 10px; border: 1px solid var(--c-border); border-radius: 999px; background: var(--c-white);
  color: var(--c-text-secondary); font: inherit; font-size: .76em; font-weight: 600; cursor: pointer; white-space: nowrap;
  transition: all var(--transition-fast); }
.admin-row-act:hover { border-color: var(--c-accent); color: var(--c-accent-deep); background: #FFFCF8; }
.admin-row-act:active { transform: scale(.97); }

/* 桌面：表头 + 7 列网格 */
#adminPage.admin-desktop .admin-table-head {
  display: grid; grid-template-columns: var(--user-cols); gap: 10px; align-items: center;
  padding: 0 14px 8px; font-size: .72em; font-weight: 700; letter-spacing: .06em; color: var(--c-text-muted);
  border-bottom: 1px solid var(--c-border);
}
#adminPage.admin-desktop .admin-row {
  display: grid; grid-template-columns: var(--user-cols); gap: 10px; align-items: center; padding: 9px 14px;
}
/* 窄屏：卡片式换行 —— 勾选 + 用户名一行，五个字段换行成一行小字（带列名） */
#adminPage:not(.admin-desktop) .admin-row {
  display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; padding: 11px 4px;
}
#adminPage:not(.admin-desktop) .admin-row-check { order: 0; }
#adminPage:not(.admin-desktop) .admin-row-main { order: 1; flex: 1 1 55%; min-width: 0; }
#adminPage:not(.admin-desktop) .admin-row-cell { order: 2; font-size: .76em; }
#adminPage:not(.admin-desktop) .admin-row-cell::before { content: attr(data-col) ' '; color: var(--c-text-muted); }
#adminPage:not(.admin-desktop) .admin-row-act { order: 3; margin-left: auto; }

/* 用户视图的工具条：搜索框限宽（原来拉满 1160px）、全选紧跟其后 */
.admin-toolbar { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-bottom: 10px; }
.admin-toolbar input { flex: 1 1 200px; max-width: 280px; padding: 8px 12px; border: 1px solid var(--c-border);
  border-radius: 16px; font: inherit; font-size: .84em; outline: none; background: var(--c-white);
  transition: border-color .15s; }
.admin-checkall { display: inline-flex; align-items: center; gap: 6px; font-size: .8em; color: var(--c-text-secondary);
  cursor: pointer; flex: none; white-space: nowrap; }
.admin-checkall input { accent-color: var(--c-accent); cursor: pointer; }
/* 与左侧导航 / 手机底部栏**重复**的分区标题行不再显示（导航项 + 顶栏分区名已经说明"你在哪"）；
   但保留在 DOM 里 —— 导航角标是从这些标题的计数里读的。
   手机端同样隐藏：底部栏已经标明当前分区，标题行只剩噪音（内容由 adminTab 自动展开，不受影响）。 */
#adminPage .admin-section-head.admin-dup { display: none; }

/* ── 留言 / 报错视图（2026-09-20 第 3 步）──
   改造前：留言卡在宽屏下铺满 1160px，正文 .84em 一行 100+ 字（远超可读行宽），
   分类/用户/时间/回复/删除全挤在正文下面同一行；筛选下拉也是 width:100% 铺满。
   现在：卡片限宽到可读长度、元信息与操作分列（操作靠右）、待回复排最前并给出摘要。 */
.admin-fb-sum { font-size: .8em; color: var(--c-text-muted); }
.admin-fb-sum.warn { color: var(--c-accent-deep); font-weight: 600; }
.admin-fb-sum b { font-weight: 800; }
.admin-toolbar select { padding: 8px 10px; border: 1px solid var(--c-border); border-radius: 16px; font: inherit;
  font-size: .84em; background: var(--c-white); color: var(--c-text); cursor: pointer; outline: none; max-width: 200px; }
.admin-toolbar select:focus { border-color: var(--c-accent); }
/* 操作组靠右：回复/编辑 + 删除 */
.fb-float-actions { margin-left: auto; display: inline-flex; align-items: center; gap: 4px; }
.fb-fb-time { color: var(--c-text-muted); }
#adminPage.admin-desktop .admin-fb-list { max-width: 720px; }       /* 可读行宽（约 70 字符） */
#adminPage.admin-desktop .admin-fb-list .fb-float-card { padding: 14px 16px; margin-bottom: 10px; border-radius: 18px; }
#adminPage.admin-desktop .admin-fb-list .fb-float-msg { font-size: .92em; margin-bottom: 10px; }
#adminPage.admin-desktop .admin-fb-list .fb-float-meta { font-size: .76em; gap: 10px; }
/* 报错行：类型 + 标题 + 第 N 题 一行，用户·时间一行，删除靠右（原来是 10px 内边距的紧凑块）
   宽度与留言卡统一成同一条阅读栏，避免"标签在左、删除在 1100px 之外" */
#adminPage.admin-desktop #adminRepList { max-width: 720px; }
#adminPage.admin-desktop .admin-rep-item { padding: 12px 14px; border-radius: 16px; }
#adminPage.admin-desktop .admin-rep-label { font-size: .88em; }
#adminPage.admin-desktop .admin-rep-sub { font-size: .76em; margin-top: 5px; }

/* ── 通知视图 ──
   2026-09-27：站内「公告 / 更新内容」功能整体下线（前端展示链路与后台发布端一并删除），
   这个分区只留「更新通知」（给所有在线用户广播维护倒计时）。卡片宽度收到 560px，
   免得单个通栏按钮铺满整个内容区。 */
#adminPage.admin-desktop .admin-announce { display: grid; grid-template-columns: minmax(0, 560px); gap: 24px; align-items: start; }
/* 更新通知：广播动作单独一张卡（琥珀底 = 提醒"这会打到所有在线用户"） */
.admin-notice-card { background: #F5EFE4; border: 1px solid #E9E0D4; border-radius: 18px; padding: 16px; }
.admin-notice-head { display: flex; align-items: center; gap: 8px; font-size: .95em; font-weight: 800; color: #4A3229; }
.admin-notice-head svg { width: 17px; height: 17px; }
.admin-notice-desc { margin: 8px 0 14px; font-size: .8em; line-height: 1.7; color: #4A3229; opacity: .85; }
.admin-notice-desc b { font-weight: 800; }
.admin-notice-btn { width: 100%; padding: 11px; border: 0; border-radius: 16px; background: var(--c-accent); color: #fff;
  font: inherit; font-size: .86em; font-weight: 700; cursor: pointer; box-shadow: 0 2px 8px rgba(90,110,69,.22);
  transition: all var(--transition-fast); }
.admin-notice-btn:hover { background: var(--c-accent-hover); }
.admin-notice-btn:active { transform: scale(.98); }
html.dark .admin-notice-card { background: #2E2620; border-color: #7A5A2F; }
html.dark .admin-notice-head, html.dark .admin-notice-desc { color: #D4A373; }
/* 趋势图每天日期下挂一行「峰 N」；只在桌面显示 —— 手机上 7 列每列才 45px，塞不下 */
.admin-peak { display: none; }
#adminPage.admin-desktop .admin-peak { display: block; font-style: normal; font-weight: 700; color: var(--c-accent-deep); margin-top: 1px; }
/* 用户表格操作列要放两个按钮：详情 / 重置密码（列宽在上面的 --user-cols 里） */
.admin-row-actions { display: inline-flex; align-items: center; gap: 6px; }
#adminPage:not(.admin-desktop) .admin-row-actions { order: 3; margin-left: auto; }
/* 单人 7 天在线弹窗里的迷你柱状图 */
.uo-chart { display: flex; align-items: flex-end; gap: 8px; height: 150px; padding: 0 2px; }
.uo-col { flex: 1; height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; gap: 4px; }
.uo-h { font-size: .68em; color: var(--c-text-muted); white-space: nowrap; }
.uo-bar { width: 100%; max-width: 34px; border-radius: 4px 4px 2px 2px;
  background: #AAB096; }
.uo-d { font-size: .68em; color: var(--c-text-muted); }
.uo-total { margin-top: 14px; font-size: .84em; color: var(--c-text-secondary); text-align: center; }
.uo-total b { color: var(--c-text); font-weight: 800; }

/* 组间发丝线：词典 ｜ 发音·音效 ｜ 简单 —— 四项等重排成一排才像"纯文字列表"，分组后才有结构 */
.ws-tool-sep { width: 1px; height: 18px; margin: 0 2px; background: rgba(120,113,108,.18); flex: none; }

/* ── 手机模式重塑 · 第 1 步：顶栏瘦身（2026-09-20）──
   手机上顶栏原本平铺 6 个控件（模式/词库/查词/发音/音效/简单），390px 里右侧必然被裁。
   现在手机上整条工具条**收进「⋯」面板**（同一批元素，只是换布局），桌面端照旧平铺、一行不动。
   面板用绝对定位挂在 .topbar 下方，右侧对齐；发音/音效的下拉在面板里改成**内联展开**（手风琴），
   避免"下拉里再套下拉"在小屏上跑出屏幕。 */
.ws-tool-more { display: none; align-items: center; justify-content: center; width: 36px; height: 36px; padding: 0;
  border: 0; border-radius: 9999px; background: transparent; color: var(--c-text); cursor: pointer;
  transition: background .18s ease, color .18s ease, transform .12s ease; flex: none; }
.ws-tool-more:hover { background: rgba(255,255,255,.62); }
.ws-tool-more.on { background: rgba(233,224,212,.72); color: var(--c-accent-deep); }
.ws-tool-more:active { transform: scale(.94); }
.ws-tool-more svg { width: 20px; height: 20px; }

.ws-tool-dd { position: relative; }
.ws-tool-menu { position: absolute; top: calc(100% + 10px); right: 0; z-index: 60; min-width: 208px; padding: 6px; background: rgba(255,255,255,.72); backdrop-filter: blur(24px) saturate(160%); -webkit-backdrop-filter: blur(24px) saturate(160%); border-radius: 16px; box-shadow: 0 0 0 1px rgba(92,64,51,.08), 0 16px 40px rgba(90,60,20,.16); display: none; }
.ws-tool-menu.open { display: block; animation: wsToolIn .16s var(--ease-out-expo) both; }
@keyframes wsToolIn { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
.ws-tool-opt { display: flex; align-items: center; justify-content: space-between; gap: 14px; width: 100%; padding: 9px 12px; border: 0; border-radius: 16px; background: transparent; color: var(--c-text); font-size: .86em; font-weight: 500; text-align: left; cursor: pointer; transition: var(--transition-fast); }
.ws-tool-opt:hover { background: var(--c-bg); }
.ws-tool-opt.sel { background: var(--c-accent-light); color: var(--c-accent-deep); font-weight: 700; }
.ws-tool-opt small { color: var(--c-text-muted); font-weight: 400; }
.ws-tool-opt.sel small { color: var(--c-accent-deep); }
/* 「字号」卡片（2026-10-22 用户要求）：两行分段钮 —— 字号 4 档 / 字体 3 档。
   沿用 .ws-tool-opt 的选中语言（浅棕底 + 深棕字），只是排成等宽一格一格 */
.ws-tool-menu-font { min-width: 244px; }
/* 这个弹层在**两种主题下都是浅色玻璃**（.ws-tool-menu 背景写死 rgba(255,255,255,.72)），
   所以按钮和标签一律用浅色面板那套固定色，不跟 --c-text / --c-bg-card 走（暗色下会变成白底浅字）。 */
.ws-tool-label { padding: 7px 12px 5px; font-size: .72em; font-weight: 600; letter-spacing: .08em; color: #57534E; }
.ws-tool-seg { display: flex; gap: 4px; padding: 0 6px 8px; }
.ws-seg-btn { flex: 1 1 0; min-width: 0; padding: 8px 0; border: 1px solid #E7E5E4; border-radius: 12px; background: #FFFCF8; color: #292524; font-size: .8em; font-weight: 600; line-height: 1.1; white-space: nowrap; cursor: pointer; transition: background .16s ease, color .16s ease, border-color .16s ease; }
.ws-seg-btn:hover { border-color: #A34909; color: #A34909; }
.ws-seg-btn.sel { background: #E9E0D4; border-color: transparent; color: #5C4033; font-weight: 700; }
.ws-seg-btn:focus-visible { outline: 2px solid #A34909; outline-offset: 2px; }
/* 字体那一行：「Aa」字形预览 + 一行小字名字（只写名字看不出衬线/无衬线的差别，只放字形又认不出是哪个） */
.ws-seg-btn.ws-seg-font { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px; padding: 6px 0 5px; font-size: 1em; }
.ws-seg-btn.ws-seg-font b { font-size: 1em; font-weight: 700; line-height: 1.1; }
.ws-seg-btn.ws-seg-font small { font-size: .66em; font-weight: 500; color: #78716C; letter-spacing: .02em; }
.ws-seg-btn.ws-seg-font.sel small { color: #5C4033; }
.ws-seg-btn[data-font="mono"] b { font-family: ui-monospace, 'SFMono-Regular', Menlo, Consolas, monospace; }
.ws-seg-btn[data-font="serif"] b { font-family: Georgia, 'Times New Roman', 'Songti SC', serif; }
.ws-seg-btn[data-font="sans"] b { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', sans-serif; }
/* 手机档：⋯ 面板只有 ~190px 宽，4 个字号档排一行会把"标准/特大"挤成竖排 → 两列两行 */
#wordStudyPage.ws-nav-mobile .ws-tool-seg#wsFontSizeSeg { display: grid; grid-template-columns: 1fr 1fr; }
#wordStudyPage.ws-nav-mobile .ws-seg-btn { padding: 10px 0; font-size: .84em; }
/* 字体那行在窄面板里同样放不下三列（"无衬线"会被挤出去）→ 竖排三行，像「音效」面板那样一行一项 */
#wordStudyPage.ws-nav-mobile .ws-tool-seg#wsFontFamSeg { display: grid; grid-template-columns: 1fr; gap: 5px; }
#wordStudyPage.ws-nav-mobile .ws-seg-btn.ws-seg-font { flex-direction: row; justify-content: flex-start; gap: 9px; padding: 9px 12px; }
#wordStudyPage.ws-nav-mobile .ws-seg-btn.ws-seg-font b { width: 20px; text-align: left; }
#wordStudyPage.ws-nav-mobile .ws-seg-btn.ws-seg-font small { font-size: .72em; }
.ws-tool-row { display: flex; align-items: center; justify-content: space-between; gap: 14px; padding: 9px 12px; border-radius: 16px; font-size: .86em; color: var(--c-text); cursor: pointer; transition: var(--transition-fast); }
.ws-tool-row:hover { background: var(--c-bg); }
.ws-tool-row input { width: 17px; height: 17px; margin: 0; accent-color: var(--c-accent); flex-shrink: 0; }
/* 注：原先还有 .ws-tool-note（音效卡里"认识=上行音…"那句说明），按要求移除，样式一并删除 */

/* 「标记为简单词」—— 从顶栏移到揭示态，再移到 ‹ › 导航行**上面**。
   原来在卡片里只写了 margin-top，现在在 .ws-bottom 里要与导航行对齐 → 居中对齐。 */
.ws-simple-wrap { margin: 0 0 10px; text-align: center; }
.ws-simple-btn { display: inline-flex; align-items: center; gap: 6px; padding: 9px 14px; border: 1px solid #D6D3D1; border-radius: 16px; background: transparent; color: #292524; font-size: .82em; font-weight: 600; cursor: pointer; transition: var(--transition-fast); }
.ws-simple-btn:hover { border-color: var(--c-accent); color: var(--c-accent-deep); background: var(--c-bg); }

@media (prefers-reduced-motion: reduce) { .ws-tool-menu.open { animation: none; } }
/* 「要学的单词」侧边栏（2026-10-03 第四轮用户要求：「做成竖着的长方形放到最左边，点开看到要学的单词」）。
   原来它是 `left: 150px` 的一小条（老左侧竖栏还在时的位置，栏已在 179.184 撤掉 → 那条 150px 是悬空的旧值），
   而且高度由内容决定（收起时只有图标那 52px 高，看着像个小方块）。现在：
     · 贴最左边 `left: 0`（移动端本来就是 0，两轨一致）；右边圆角、左无边框 = 挂在左缘的一片；
     · **竖着的长方形**：收起时 `height: 40vh`（下限 180px）—— 高 ≫ 宽；2026-10-03 用户反馈 62vh 太长了，收到 40vh；
     · `.ws-wl-toggle` 改成 `flex: 1` 撑满整块 → 整片长方形都可点，图标垂直居中；
     · 展开仍是右侧滑出词表（`.open` → width 280px / 手机上 min(82vw,320px)），词表内部自己滚。 */
.ws-wl-panel { position: fixed; left: 0; top: 50%; transform: translateY(-50%); z-index: 35; width: 48px; height: 40vh; min-height: 180px; max-height: 76vh; display: flex; flex-direction: column; background: var(--c-bg-card); border: 1px solid var(--c-border); border-left: none; border-radius: 0 16px 16px 0; overflow: hidden; transition: width .24s ease, left .22s ease; }
.ws-wl-panel.open { width: 280px; }
/* ⚠️ 展开后**不许**「☰」再吃富余高度（2026-10-03 用户反馈「词表点开后上方空白太大，单词往上挪一些」）：
   收起时 `.ws-wl-toggle` 是 `flex:1`（整片长方形都可点），但展开时若它继续 flex-grow，
   词条少的时候富余高度全归按钮 → 单词被顶到底部，上方留一大片空白（实测短队列下空白 209px）。
   展开态：按钮回到自然高度，词表区吃掉剩余高度并从顶部开始排。 */
.ws-wl-panel.open .ws-wl-toggle { flex: 0 0 auto; }
.ws-wl-panel.open .ws-wordlist { flex: 1 1 auto; min-height: 0; }
.ws-wl-toggle { display: flex; align-items: center; justify-content: center; flex: 1 1 auto; min-height: 0; padding: 16px 12px; border: none; background: transparent; color: var(--c-text-secondary); cursor: pointer; }
.ws-wl-toggle:hover { color: var(--c-accent-deep); }
.ws-wl-toggle svg { width: 20px; height: 20px; }
.ws-wordlist { display: none; flex-direction: column; gap: 2px; padding: 0 10px 12px; overflow-y: auto; }
.ws-wl-panel.open .ws-wordlist { display: flex; }
.ws-wl-item { display: block; padding: 8px 10px; border-radius: 16px; }
.ws-wl-item + .ws-wl-item { border-top: 1px solid var(--c-border); }
.ws-wl-item.cur { background: rgba(90,110,69,.10); }
.ws-wl-row { display: flex; align-items: center; justify-content: flex-start; gap: 12px; }
.ws-wl-text { flex: 0 1 auto; min-width: 0; font-size: 1.1em; color: var(--c-text); cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ws-wl-text:hover { color: var(--c-accent-deep); }
.ws-wl-item.cur .ws-wl-text { color: var(--c-accent-deep); font-weight: 700; }
.ws-wl-item.done .ws-wl-text { opacity: .5; text-decoration: line-through; }
.ws-wl-spk { position: relative; flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 26px; border-radius: 50%; border: none; background: transparent; color: var(--c-accent); cursor: pointer; }
.ws-wl-spk::after { content: ''; position: absolute; inset: -9px; }
.ws-wl-spk:hover { background: var(--c-accent-light); }
.ws-wl-spk svg { width: 15px; height: 15px; }
.ws-wl-mean { margin-top: 6px; padding: 8px 10px; border-radius: 16px; background: var(--c-bg); font-size: .85em; color: var(--c-text-secondary); line-height: 1.6; }

/* ── 展开详情（单词意思显示界面）· E-Ink / Paper（经 ui-ux-pro-max 的 E-Ink 风格定稿）──
   skill 给的配方：纸底 #FFFCF8 / 墨色 #1A1A1A / 铅笔灰 #4A4A4A / 描边 #E0E0E0，**单色**、无渐变、阅读优先、WCAG AAA。
   据此把原来偏黄的几处换掉：词根词胶囊的琥珀、例句块的琥珀标题、学习提示的琥珀底，
   并把「词性缩写」提成小标签、例句加左侧细引线（编辑部排版）——层级靠排版而非颜色建立。
   面板由 flex:1 改为贴合内容（flex:0 1 auto + max-height:100%），消掉正文下方的大片空框。 */
.ws-phonetic { display: none; }
/* ══════════════════════════════════════════════════════════════════════════════
   记单词「揭示面板」重做（2026-10-09）
   上一版的问题（都是实测到的）：
     ① **暗色下它是一块白板** —— `.ws-reveal` 与里面所有文字都是硬编码浅色
        （`#FFFCF8` / `#262322` / `#8A8177` / `#1A1A1A`），而站内其它记单词组件（.ws-pick / .ws-stat /
        .ws-type-* / .ws-level / .ws-pick-card）都有暗色覆盖 —— 这一块是**唯一漏掉的**。
     ② 释义是一堵墙：一条 61 字的释义全塞进一个 `.ws-mean-line`，词性标签数量为 0
        （`正式` 这种中文语域标记正则不认），5 个义项用 `;` 连成一串。
     ③ 右侧小节标题（11.84px + 通栏发丝线）比它下面的胶囊（32.5px）还轻。
     ④ 节奏挤：块间 16 / 列间 26 / 内边距 18-22 / 圆角 14 / 无阴影。
     ⑤ 两列失衡：左 219px vs 右 134.8px。
   做法：**颜色全部令牌化**（一处定义、暗色只改这一处），释义按中文语义分条 + 语域标签，
   小节标题提级，间距按 4pt 网格重排，两列比例 1.35:1 并把右列块间距单独收紧。
   ⚠️ 不动 DOM 结构、id 与任何 onclick 契约（#wsForms/#wsRoots/#wsSynonyms 的渲染路径照旧）。
   ══════════════════════════════════════════════════════════════════════════════ */
.ws-reveal {
  --ws-paper: #FFFCF8;          /* 面板底 */
  --ws-ink: #262322;            /* 英文/释义正文 */
  --ws-ink-strong: #1A1A1A;     /* 首义 */
  --ws-sub: #6B5D52;            /* 中文译文、元信息 */
  --ws-label: #6F655B;          /* 小节标题、词性标签 */
  --ws-chip-bg: #F7F4ED;        /* 胶囊底 */
  --ws-chip-bd: #E5DED2;        /* 胶囊描边 */
  --ws-chip-tx: #3A3733;        /* 胶囊文字 */
  --ws-chip-bg-hover: #F1ECE2;
  --ws-chip-bd-hover: #B8AE9E;
  --ws-rule: #EDE8DE;           /* 发丝分隔线 */
  --ws-cur-rule: #B8AE9E;       /* 目标词下划线 */
  display: block;
  margin-top: 18px; padding: 20px 24px; border: 1px solid var(--ws-chip-bd); border-radius: 16px;
  background: var(--ws-paper); text-align: left; flex: 0 1 auto; max-height: 100%; min-height: 0;
  overflow-y: auto; box-shadow: 0 1px 2px rgba(41,37,36,.04);
}
html.dark .ws-reveal {
  --ws-paper: #262220; --ws-ink: #E7E5E4; --ws-ink-strong: #FAFAF9; --ws-sub: #A8A29E; --ws-label: #9A9086;
  --ws-chip-bg: #2E2925; --ws-chip-bd: #423A33; --ws-chip-tx: #D6D3D1;
  --ws-chip-bg-hover: #352F2A; --ws-chip-bd-hover: #57534E; --ws-rule: #3A322C; --ws-cur-rule: #7E776D;
  box-shadow: 0 1px 2px rgba(0,0,0,.3);
}
/* 两列比例 1.25:1 → 1.35:1 并把列间距放大（实测右列比左列矮 84px） */
.ws-reveal-cols { display: flex; gap: 32px; align-items: flex-start; }
.ws-col-left { flex: 1.35; min-width: 0; }
.ws-col-right { flex: 1; min-width: 0; }
.ws-col-right .ws-block { margin-top: 18px; }        /* 右列各块之间单独收紧（原来和左列一样是 22） */
/* 右列第一块（现在是「例句」）贴着列顶；它自带 margin-top:18 会白推 18px 下去 */
.ws-col-right .ws-block:first-child { margin-top: 0; }
.ws-meaning { font-size: .96em; color: var(--ws-ink); line-height: 1.7; }
/* 释义渲染（2026-10-11 用户要求改版）：
   ① **同一词性的多个义项用「，」连成一行**（原来是"一行一个义项"，义项一多就是一堵墙）；
   ② **每个词性默认只显示前 3 条**，第 4 条起带 `.ws-mean-extra`，折叠时隐藏，点「展开全部释义」再看。
   词性标签（n./v./a.…）仍各自成行、悬挂对齐；首义的加重改挂到 `.ws-mean-first`（段落级，不再要求它是第一个子元素）。 */
.ws-mean-line { display: block; padding: 3px 0; }
.ws-mean-line > .ws-pos + .ws-mean-entry { margin-left: 6px; }
.ws-pos { display: inline-block; min-width: 2.6em; text-align: center; padding: 1px 7px;
  border-radius: 6px; background: var(--ws-chip-bg); border: 1px solid var(--ws-chip-bd);
  font-size: .76em; font-weight: 700; font-style: normal; color: var(--ws-label); letter-spacing: .02em;
  vertical-align: .08em; }
.ws-mean-first { font-size: 1.05em; font-weight: 600; color: var(--ws-ink-strong); }
/* 折叠态：每组只留前 3 条。分隔符是**每条义项自带的尾随符**，所以整条一起 display:none 就不会
   在末条后面留下"孤零零的逗号"（第 4 条起即 `.ws-mean-extra`）。
   有词性标签时它占第 1 个子元素 → 义项从第 2 个起，故 `nth-child(n+5)`；没有标签时即是 `n+4`。 */
.ws-meaning:not(.ws-mean-open) .ws-mean-line > .ws-mean-extra { display: none; }
.ws-mean-more { display: inline-block; margin-top: 6px; padding: 3px 12px; border-radius: 9999px;
  font-size: .82em; font-weight: 600; color: var(--ws-label); background: var(--ws-chip-bg);
  border: 1px solid var(--ws-chip-bd); cursor: pointer; user-select: none; transition: all .15s ease; }
.ws-mean-more:hover { background: #F5EFE4; color: var(--ws-ink-strong); border-color: var(--c-accent-light); }
html.dark .ws-mean-more { background: rgba(255,255,255,.06); color: #D6D3D1; border-color: rgba(255,255,255,.14); }
html.dark .ws-mean-more:hover { background: rgba(255,255,255,.12); }
.ws-loading, .ws-muted { color: var(--c-text-muted); font-size: .88em; }
/* 学习提示：琥珀底 → 中性纸色 + 左引线（信息条而非警告条） */
.ws-learn-note { text-align: left; font-size: .84em; color: #57534E; background: #F7F4ED; border: 1px solid #C9C0B2; border-radius: 0 8px 8px 0; padding: 9px 13px; margin-bottom: 14px; line-height: 1.6; }
html.dark .ws-learn-note { color: #D6D3D1; background: rgba(255,255,255,.05); border-left-color: #57534E; }
/* 小节：块间距 16 → 22（4pt 网格），标题提级 —— 上一版标题只有 11.84px + 一条通栏发丝线，
   比它下面的胶囊（32.5px）还轻，读不出"这是一个小节"。现在改用站内标题那套语言：
   **琥珀小方钉 + 12.5px 加粗 + 短横线**（不再让发丝线横贯整行去抢注意力）。 */
.ws-block { margin-top: 22px; }
.ws-block-title { display: flex; align-items: center; gap: 9px; font-size: .82em; font-weight: 700;
  color: var(--ws-label); margin-bottom: 10px; letter-spacing: .06em; }
.ws-block-title::before { content: ''; flex: none; width: 3px; height: 12px; border-radius: 2px;
  background: linear-gradient(180deg, var(--c-accent), color-mix(in srgb, var(--c-accent) 35%, transparent)); }
.ws-block-title::after { content: ''; flex: 0 1 26px; height: 1px; background: var(--ws-rule); }
/* 例句（2026-10-07 第二十五轮：**去掉外框**，只有「当前正在背的那个词」下面才有下划线）：
   本轮给例句之间加一条发丝分隔线 —— 上一版两条例句只靠 11px 外边距，读起来是连着的。 */
.ws-ex + .ws-ex { margin-top: 13px; padding-top: 13px; border-top: 1px solid var(--ws-rule); }
.ws-ex:not(:last-child) { margin-bottom: 0; }
.ws-ex-en { font-size: .92em; color: var(--ws-ink); line-height: 1.6; }
.ws-ex-zh { font-size: .82em; color: var(--ws-sub); line-height: 1.6; margin-top: 3px; }
.ws-link { color: var(--ws-ink); cursor: pointer; }
.ws-link:hover { background: var(--ws-chip-bg-hover); }
.ws-link-cur { border-bottom: 1px solid var(--ws-cur-rule); }
.ws-link-cur:hover { border-bottom-color: var(--c-accent); }
/* 胶囊：min-height 统一 + 居中，换行时不再参差（实测高度本来都是 32.5px，主要修换行参差与间距节奏） */
.ws-syns { display: flex; flex-wrap: wrap; gap: 8px; }
.ws-syn { display: inline-flex; align-items: center; min-height: 30px; padding: 4px 12px; border-radius: 15px;
  border: 1px solid var(--ws-chip-bd); background: var(--ws-chip-bg); color: var(--ws-chip-tx);
  font-size: .82em; font-family: inherit; cursor: pointer;
  transition: var(--transition-fast); }
.ws-syn:hover { border-color: var(--ws-chip-bd-hover); background: var(--ws-chip-bg-hover); color: var(--ws-ink-strong); }
.ws-syn:active { transform: scale(.97); }
.ws-loading, .ws-muted { color: var(--c-text-muted); font-size: .88em; }

/* 底部导航 */
.ws-nav-row { display: flex; gap: 14px; width: 100%; max-width: var(--ws-actions-w, 480px); margin: 0 auto; }
.ws-nav-btn { flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 8px; padding: 16px; border-radius: 14px; border: 1px solid #E7E5E4; background: #F5F0EB; color: #292524; font-size: .92em; font-weight: 600; cursor: pointer; transition: var(--transition-fast); }
.ws-nav-btn:hover { border-color: var(--c-accent); color: var(--c-accent-deep); }
.ws-nav-btn svg { width: 20px; height: 20px; }
.ws-nav-btn span { display: none; }
/* 「记错了」：夹在 ‹ › 中间，只有它带文字（左右两个是图标），所以单独排一下字号与着重点。
   2026-09-23 用户要求加。 */
.ws-nav-btn.ws-nav-wrong { font-size: .9em; letter-spacing: .02em; color: #5C4033; border-color: #DCD2C4; background: #F2EDE4; }
.ws-nav-btn.ws-nav-wrong:hover { background: #E9E0D4; border-color: var(--c-accent); color: #4A3229; }
.ws-nav-next { background: var(--c-accent); border-color: var(--c-accent); color: #fff; }
.ws-nav-next:hover { background: var(--c-accent-hover); border-color: var(--c-accent-hover); color: #fff; }
html.dark .ws-nav-next { color: #1C1917; }

/* 简单词后移除按钮 */
.ws-remove-wrap { margin-top: 12px; }
.ws-remove-btn { width: 100%; padding: 11px; border-radius: var(--radius-md); border: 1.5px solid var(--c-danger); background: transparent; color: var(--c-danger); font-size: .9em; font-weight: 600; cursor: pointer; transition: var(--transition-fast); }
.ws-remove-btn:hover { background: var(--c-danger); color: #fff; }

/* 完成 / 空态 */
.ws-done-mark { width: 64px; height: 64px; margin: 30px auto 18px; border-radius: 50%; background: var(--c-success); color: #fff; font-size: 2em; display: flex; align-items: center; justify-content: center; }
#wsDoneView, #wsEmptyView { text-align: center; padding: 30px 0; }
/* 「本轮学习完成」在内容区内垂直居中（原来贴顶，下方留一大片空）。
   .hidden 是 `display: none !important`，所以这里设 display:flex 不会破坏隐藏逻辑。
   高度基准用 min-height 而不是 flex:1 —— 内容区从 .ws-shell 到 #wordStudyPage 都没有确定高度，
   flex:1 无法解析；具体数值由实测校准。 */
#wsDoneView { display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: calc(100vh - 136px); padding: 8px 0 40px; }
#wsDoneView h2, #wsEmptyView h2 { color: var(--c-text); margin-bottom: 8px; }
.ws-done-text, .ws-empty-text { color: var(--c-text-secondary); font-size: .9em; margin-bottom: 24px; line-height: 1.7; }

/* ── 入口选择屏：新学 / 复习 两张卡片（沿用 E-Ink / Paper 材质）──
   卡片用大号 emoji 作视觉锚点（用户明确允许 emoji），其余仍保持纸底 + 发丝边 + 墨字。 */
.ws-pick-wrap { display: flex; flex-direction: column; justify-content: center; min-height: calc(100vh - 245px); padding: 8px 0 40px; }
.ws-pick { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; width: 100%; max-width: 760px; margin: 0 auto; }
.ws-pick-card { position: relative; display: flex; flex-direction: column; align-items: center; text-align: center; gap: 7px; padding: 34px 22px 26px; border-radius: 20px; border: 1px solid #E8E2D6; background: #FFFCF8; cursor: pointer; box-shadow: 0 1px 2px rgba(90,60,20,.04); transition: transform .24s var(--ease-out-quart), box-shadow .24s ease, border-color .24s ease, background .24s ease; }
.ws-pick-card:hover { transform: translateY(-4px); border-color: #B8AE9E; box-shadow: 0 16px 34px rgba(120,80,30,.15); }
.ws-pick-card:active { transform: translateY(-1px); }
.ws-pick-card.off { opacity: .5; }
.ws-pick-card.off:hover { transform: none; box-shadow: 0 1px 2px rgba(90,60,20,.04); border-color: #E8E2D6; }
.ws-pick-emoji { font-size: 2.7em; line-height: 1.1; }
.ws-pick-name { font-size: 1.5em; font-weight: 800; color: #1A1A1A; letter-spacing: .02em; }
.ws-pick-desc { font-size: .84em; color: #8A8177; }
.ws-pick-count { margin-top: 8px; font-size: .78em; color: #8A8177; }
.ws-pick-count b { font-size: 2.1em; font-weight: 800; color: #1A1A1A; margin-right: 3px; font-variant-numeric: tabular-nums; }
.ws-pick-extra { font-size: .74em; color: #A8A29E; }
.ws-pick-go { margin-top: 16px; display: inline-flex; align-items: center; gap: 6px; padding: 10px 22px; border-radius: 999px; background: #F1ECE2; color: #57534E; font-size: .84em; font-weight: 700; transition: background .2s ease, color .2s ease; }
.ws-pick-card:hover .ws-pick-go { background: #57534E; color: #FFFCF8; }
.ws-pick-go svg { width: 15px; height: 15px; transition: transform .22s var(--ease-out-quart); }
.ws-pick-card:hover .ws-pick-go svg { transform: translateX(3px); }
html.dark .ws-pick-card { background: #2A2623; border-color: #3F3A37; }
html.dark .ws-pick-card:hover { border-color: #57534E; }
html.dark .ws-pick-name { color: #FAFAF9; }
html.dark .ws-pick-desc { color: #A8A29E; }
html.dark .ws-pick-count { color: #A8A29E; }
html.dark .ws-pick-count b { color: #FAFAF9; }
html.dark .ws-pick-extra { color: #78716C; }
html.dark .ws-pick-go { background: #322C28; color: #D6D3D1; }
html.dark .ws-pick-card:hover .ws-pick-go { background: #A8A29E; color: #1C1917; }

/* ── 本轮学习完成的庆祝：🥳 先弹出，随后撒花 ──
   .ws-done-emoji 覆盖 .ws-done-mark 的绿底圆盘（那条规则给「空态」的 · 用）。
   两层用声明式 CSS 动画，JS 只负责生成粒子与重放，避免维护两套时序。 */
/* width 必须 fit-content：这是块级 div，若保持整宽，弹入时的 scale(1.14) 会把整宽外扩，
   实测造成 49px 横向溢出（transform 会参与可滚动溢出区域的计算）。 */
.ws-done-mark.ws-done-emoji { width: fit-content; height: auto; margin: 26px auto 10px; background: none; font-size: 3.6em; line-height: 1; animation: wsPopIn .62s var(--ease-out-expo) both; }
@keyframes wsPopIn {
  0%   { opacity: 0; transform: scale(.35) rotate(-14deg); }
  55%  { opacity: 1; transform: scale(1.14) rotate(5deg); }
  78%  { transform: scale(.97) rotate(-2deg); }
  100% { opacity: 1; transform: scale(1) rotate(0deg); }
}
/* 撒花层 */
.ws-confetti { position: fixed; inset: 0; z-index: 90; pointer-events: none; overflow: hidden; }
.ws-confetti i { position: absolute; top: -16px; left: var(--x, 50%); width: 8px; height: var(--h, 13px); border-radius: 2px; background: var(--c, #5A6E45); opacity: 0; will-change: transform, opacity; animation: wsConfettiFall var(--dur, 2.6s) cubic-bezier(.3,.5,.5,1) var(--delay, .6s) forwards; }
.ws-confetti i.e { width: auto; height: auto; background: none; border-radius: 0; font-size: var(--fs, 15px); line-height: 1; }
@keyframes wsConfettiFall {
  0%   { opacity: 0; transform: translate3d(0, -6px, 0) rotate(0deg) scale(.6); }
  10%  { opacity: 1; }
  82%  { opacity: 1; }
  100% { opacity: 0; transform: translate3d(var(--dx, 0px), 88vh, 0) rotate(var(--rot, 540deg)) scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  .ws-done-mark.ws-done-emoji { animation: none; }
  .ws-confetti { display: none; }
}

/* ── 打字记词（模仿 qwerty learner：待机大字 → 逐字符高亮 → 底部五格统计条）──
   材质沿用 E-Ink / Paper：纸底 + 墨字 + 铅笔灰，单色。 */
/* 打字入口直接用 .ws-pick-* 那套卡片样式（与新学/复习的选择屏完全一致），
   所以这里不再需要 .ws-type-idle-big / .ws-type-idle-sub / .ws-type-go —— 已删除。 */
/* 打字自己的词库 chip 行（入口屏上方）——独立于主页的「选择词库」 */
.ws-type-boards { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; margin: 0 0 22px; }
.ws-type-chip { padding: 7px 15px; border: 1.5px solid #E8E2D6; border-radius: 999px; background: #FFFCF8;
  color: #57534E; font-size: .82em; font-weight: 600; cursor: pointer; transition: border-color .18s ease, background .18s ease, color .18s ease; }
.ws-type-chip:hover { background: #F1ECE2; border-color: #B8AE9E; color: #1A1A1A; }
.ws-type-chip.sel { background: #F1ECE2; border-color: #57534E; color: #1A1A1A; }
/* 完成屏上的熟练度三格（复用 .ws-stat，只是窄一点、居中） */
.ws-type-prog { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; width: 100%; max-width: 380px; margin: 18px auto 22px; }
html.dark .ws-type-chip { background: #2A2623; border-color: #3F3A37; color: #D6D3D1; }
html.dark .ws-type-chip:hover, html.dark .ws-type-chip.sel { background: #322C28; border-color: #78716C; color: #FAFAF9; }
.ws-type-center { display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: calc(100vh - 136px); padding: 8px 0 40px; text-align: center; }

#wsTypingPlay { display: flex; flex-direction: column; min-height: calc(100vh - 136px); padding: 4px 0 24px; }
.ws-type-head { display: flex; align-items: center; justify-content: flex-end; gap: 12px; }
/* 注：原先此处有页内的「给中文打英文 / 照着打」分段控件（.ws-type-seg / .ws-type-segbtn），
   按要求把切换移到顶栏（复用顶栏那个模式按钮，按页面上下文切「新学 / 默写」），样式一并删除。 */
.ws-type-progress { font-size: .8em; color: #A8A29E; font-variant-numeric: tabular-nums; white-space: nowrap; }
.ws-type-stage { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 16px; text-align: center; min-height: 0; }
.ws-type-prompt { font-size: 1.12em; font-weight: 600; color: #262322; line-height: 1.6; max-width: 780px; }
/* 新学模式下提示区是空的（意思改放到单词下面），空元素不能占掉 flex 的 gap */
.ws-type-prompt:empty { display: none; }
/* 默写模式的提示行：汉字 + 喇叭。喇叭由 JS 按模式在「提示行 / 单词行」之间搬家
   （默写 → 汉字旁边；新学 → 单词旁边），只有这一个按钮，不复制 DOM。 */
.ws-type-promptrow { display: flex; align-items: center; justify-content: center; gap: 8px; max-width: 100%; flex-wrap: wrap; }
.ws-type-promptrow .ws-type-prompt { min-width: 0; }
/* 单词下方的音标（只在新学模式出现：默写模式单词是藏着的，给音标等于泄题） */
.ws-type-phon { font-family: ui-monospace, 'SFMono-Regular', Menlo, Monaco, Consolas, monospace; font-size: 1.04em; color: #8A8177; letter-spacing: .02em; }
.ws-type-phon:empty { display: none; }
html.dark .ws-type-phon { color: #A8A29E; }
/* 单词行：目标串 + 喇叭（按钮复用站内 .ws-spk，含 44px 热区）。
   窄屏下长单词/词组会换行，把按钮挤到下一行 —— 用 flex-wrap 让它体面地折下去。 */
.ws-type-wordrow { display: flex; align-items: center; justify-content: center; gap: 8px; max-width: 100%; flex-wrap: wrap; }
/* 目标串：未打=浅灰、已打对=墨色、当前位=铅笔灰加下划线、打错=红 */
.ws-type-target { min-width: 0; font-family: ui-monospace, 'SFMono-Regular', Menlo, Monaco, Consolas, monospace; font-size: clamp(1.9em, 6.5vw, 3.2em); font-weight: 700; letter-spacing: .04em; color: #D6D3D1; word-break: break-word; line-height: 1.2; }
.ws-type-target .ok { color: #1A1A1A; }
.ws-type-target .cur { color: #8A8177; box-shadow: inset 0 -3px 0 #57534E; }
.ws-type-target .bad { color: #A63D2A; }
/* 打错时下划线也变红 —— .bad.cur 权重(0,2,0) 高于 .cur(0,1,0)，无需 !important */
.ws-type-target .bad.cur { box-shadow: inset 0 -3px 0 #A63D2A; }
.ws-type-target.shake { animation: wsTypeShake .18s ease; }
@keyframes wsTypeShake { 0%,100% { transform: translateX(0); } 25% { transform: translateX(-4px); } 75% { transform: translateX(4px); } }
/* 单词下方的释义（新学模式）：这是关键信息，比一般 hint 更实 */
.ws-type-hint { font-size: .98em; font-weight: 500; color: #57534E; line-height: 1.6; max-width: 780px; }
.ws-type-hint:empty { display: none; }
/* 真实输入框：只为唤起软键盘，视觉上完全不可见。
   ⚠ 移动端两个坑（实测确认）：
     ① font-size 必须 ≥ 16px —— iOS Safari 聚焦 font-size < 16px 的输入框会**自动缩放整页**，
        一 zoom 布局就错位、看起来像"卡住"（原实现继承到 13.33px）。
     ② 不能用 left:-9999px 挪到屏外 —— iOS 会**拒绝为屏外元素弹出软键盘**，
        改成 1×1 留在视口左上角 + opacity:0，配合 caret 透明，同样不可见但可聚焦。 */
.ws-type-input { position: fixed; top: 0; left: 0; width: 1px; height: 1px; padding: 0; border: 0; opacity: 0; font-size: 16px; caret-color: transparent; }
/* 底部五格统计条（qwerty 的那条卡） */
.ws-type-stats { display: grid; grid-template-columns: repeat(5, 1fr); gap: 8px; width: 100%; max-width: 640px; margin: 18px auto 0; padding: 14px 10px; border: 1px solid #E8E2D6; border-radius: 14px; background: #FFFCF8; }
.ws-type-stat { display: flex; flex-direction: column; align-items: center; gap: 3px; }
.ws-type-stat b { font-size: 1.14em; font-weight: 800; color: #1A1A1A; font-variant-numeric: tabular-nums; }
.ws-type-stat span { font-size: .7em; color: #8A8177; letter-spacing: .06em; }
html.dark .ws-type-progress { color: #78716C; }
html.dark .ws-type-hint { color: #A8A29E; }
html.dark .ws-type-stats { background: #2A2623; border-color: #3F3A37; color: #D6D3D1; }
html.dark .ws-type-prompt { color: #E7E5E4; }
html.dark .ws-type-target { color: #57534E; }
html.dark .ws-type-target .ok { color: #FAFAF9; }
html.dark .ws-type-target .cur { color: #A8A29E; box-shadow: inset 0 -3px 0 #A8A29E; }
html.dark .ws-type-stat b { color: #FAFAF9; }
html.dark .ws-type-stat span { color: #A8A29E; }
@media (max-width: 768px) {
  .ws-type-stats { gap: 4px; padding: 12px 6px; }
  .ws-type-stat b { font-size: 1em; }
  .ws-type-stat span { font-size: .64em; }
  #wsTypingPlay, .ws-type-center { min-height: calc(100vh - 245px); }
}
html.force-phone #wsTypingPlay, html.force-phone .ws-type-center { min-height: calc(100vh - 245px) !important; }
/* ── 「去选择词库」CTA：移植 Uiverse.io by Itskrish01 ──
   原稿是 Tailwind + group-hover：两个角上的"缺口"向外滑走 + 一层色块从左扫入（delay 200ms）+ 文字保持白。
   照搬结构与配色，类名全部改为站内命名 —— 原稿是裸 <button>，站内有 101+ 处引用，必须限定。
   两处适配：① 标签居中（原稿 `w-full text-left` 是因为它的按钮是内容宽；我们是固定 320px 宽，左对齐会明显失衡）；
             ② `rounded-md`(6px) → 8px，与站内 CTA 的圆角一致。 */
.ws-start { position: relative; display: flex; align-items: center; justify-content: center; width: 100%; max-width: 320px; margin: 0 auto; padding: 12px 24px; overflow: hidden; border: none; border-radius: 16px; background: #6366F1; color: #fff; font-size: 1em; font-weight: 600; cursor: pointer; transition: all .3s ease; }
/* 角上的两个缺口：静止贴角，悬停时向外滑出 */
.wss-notch { position: absolute; display: inline-block; width: 16px; height: 16px; background: #4338CA; border-radius: 4px; transition: all .5s ease-in-out; }
.wss-tr { top: 0; right: 0; }
.wss-bl { bottom: 0; left: 0; transform: rotate(180deg); }
.ws-start:hover .wss-tr { margin-right: -16px; margin-top: -16px; }
.ws-start:hover .wss-bl { margin-left: -16px; margin-bottom: -16px; }
/* 缺口里的白色斜切，做出"纸角被剪掉"的效果 */
.wss-cut { position: absolute; top: 0; right: 0; width: 20px; height: 20px; background: #fff; transform: rotate(45deg) translate(50%, -50%); }
/* 从左扫入的色块（delay 200ms，与缺口滑出错开） */
.wss-sweep { position: absolute; bottom: 0; left: 0; width: 100%; height: 100%; background: #4F46E5; border-radius: 16px; transform: translateX(-100%); transition: all .5s ease-in-out .2s; }
.ws-start:hover .wss-sweep { transform: translateX(0); }
.wss-label { position: relative; width: 100%; text-align: center; color: #fff; transition: color .2s ease-in-out; }
@media (prefers-reduced-motion: reduce) { .wss-notch, .wss-sweep, .wss-label { transition: none; } }
/* 统一的最简禁用态（skill 规范：muted + opacity + not-allowed）。全站按钮此前一个 disabled 样式都没有。 */
#wordStudyPage button:disabled { opacity: .55; cursor: not-allowed; color: #57534E; box-shadow: none; transform: none; }
html.dark .ws-done-mark { color: #1C1917; }

/* 选择词库 */
.ws-hero { text-align: center; margin: 6px 0 22px; }
.ws-hero h2 { font-size: 1.4em; color: var(--c-text); margin-bottom: 6px; }
.ws-hero p { font-size: .86em; color: var(--c-text-secondary); }
/* 词库卡片：去掉「勾选圆圈」（已改为点谁背谁），改为
   名称 + 词数胶囊 / 一行说明 / 底部「开始学习 →」，选中态用左缘琥珀标记 + 琥珀渐变底。 */
.ws-lib-list { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
.ws-lib-card { position: relative; display: flex; flex-direction: column; gap: 7px; text-align: left; min-height: 138px; padding: 20px; border-radius: 18px; border: 1px solid var(--c-border); background: var(--c-bg-card); cursor: pointer; box-shadow: 0 1px 2px rgba(90,60,20,.04); transition: transform .22s var(--ease-out-quart), box-shadow .22s ease, border-color .22s ease, background .22s ease; }
.ws-lib-card:hover { transform: translateY(-3px); border-color: var(--c-accent); box-shadow: 0 12px 26px rgba(120,80,30,.14); }
.ws-lib-card:active { transform: translateY(-1px); }
.ws-lib-card.sel { border-color: var(--c-accent); background-image: linear-gradient(180deg, #FFFDF6 0%, #FDF2DF 100%); box-shadow: 0 6px 18px rgba(217,119,6,.14); }
.ws-lib-card.sel::before { content: ''; position: absolute; left: -1px; top: 18px; bottom: 18px; width: 3px; border-radius: 0 3px 3px 0; background: var(--c-accent); }
.ws-lib-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.ws-lib-name { font-size: 1.34em; font-weight: 800; letter-spacing: .01em; color: var(--c-text); min-width: 0; }
/* chip：已背/掌握 的数字用它自己的强调色，"/ 总数" 压淡一档 —— 一个 pill 里分清主次（2026-10-10） */
.ws-lib-count { font-size: .72em; font-weight: 700; color: var(--c-accent-deep); background: var(--c-accent-light); padding: 3px 9px; border-radius: 999px; white-space: nowrap; flex: none; }
.ws-lib-count em { font-style: normal; font-weight: 600; opacity: .62; }
.ws-lib-sub { font-size: .82em; color: var(--c-text-muted); line-height: 1.5; }
.ws-lib-go { margin-top: auto; display: inline-flex; align-items: center; gap: 5px; font-size: .82em; font-weight: 700; color: var(--c-accent-deep); }
.ws-lib-go svg { width: 14px; height: 14px; transition: transform .22s var(--ease-out-quart); }
.ws-lib-card:hover .ws-lib-go svg { transform: translateX(4px); }
/* ── 暗色：选中态整块原本看不清 ──
   .ws-lib-card.sel 的底色写死了近白渐变（#F5EFE4 → #F2EDE4），而暗色下卡片文字是浅色
   （--c-text = #EDE9E6、.ws-lib-go 用 --c-accent-deep = #D4A373）→ 近白字压近白底，
   对比度只有约 1.05:1，选中哪个词库完全看不出来。全站 html.dark 里原本**没有一条** ws-lib 规则。
   这里换成暖深棕渐变（与 --c-bg-card #292524 同色系、略亮一档），保留琥珀色选中标记
   （左边条 + 边框都走 --c-accent，无需另写）。
   顺带量了同卡片另两层文字在暗色下的对比度，一并对齐到 AA：
     · 副标题 --c-text-muted #8A8582 on #292524 只有 3.98:1（.82em 正文级不达标）→ 提到 --c-text-secondary 的 5.76:1
     · 词数药丸 #D4A373 on #5C4033 只有 3.01:1 → 改成 #E9E0D4 on #3A322C 的 9.7:1 */
html.dark .ws-lib-card.sel { background-image: none; background-color: #362D23; box-shadow: 0 6px 18px rgba(90,110,69,.2); }
html.dark .ws-lib-sub { color: var(--c-text-secondary); }
html.dark .ws-lib-count { background: #3A322C; color: #E9E0D4; }
.ws-lib-hint { text-align: center; font-size: .8em; color: var(--c-text-muted); margin-top: 18px; min-height: 1.2em; }

/* 生词本 / 词组本 */
.ws-vocab-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 16px; flex-wrap: wrap; }
.ws-master { display: inline-flex; align-items: center; gap: 8px; font-size: .82em; font-weight: 600; color: var(--c-text-secondary); cursor: pointer; user-select: none; }
.ws-master input { display: none; }
.ws-master-track { width: 40px; height: 22px; border-radius: 99px; background: var(--c-border); position: relative; transition: var(--transition-fast); flex-shrink: 0; }
.ws-master-track::after { content: ''; position: absolute; top: 2px; left: 2px; width: 18px; height: 18px; border-radius: 50%; background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,.2); transform: translateX(0); transition: transform var(--t-state) var(--ease-out-quart); }
.ws-master input:checked + .ws-master-track { background: var(--c-accent); }
.ws-master input:checked + .ws-master-track::after { transform: translateX(18px); }
.ws-master input:checked ~ .ws-master-text { color: var(--c-accent-deep); }

/* ── 学习计划（设置）· 与「单词意思」面板同一套 E-Ink / Paper 材质 ──
   少用黄色：① 分节改为纸卡（纸底 #FFFCF8 + 发丝边 #E8E2D6）
             ② 档位选中态由「琥珀底 + 琥珀字」改为**墨色**（深边 + 纸灰底 + 墨字）
             ③ 开关由原生琥珀勾选框改为自绘开关（关 = 纸灰轨，开 = 墨色轨）
             ④ 小节标题由正文黑改为铅笔灰字距标签，与释义面板的块标题统一 */
/* ── 「单词状态」统计块：六个数字（全新/学习中/待复习/已掌握/难词/今日已学）──
   状态判定见 wsState()：每个词唯一状态，「难词」（累计答错≥5）是横跨各状态的优先级标记，故单列。
   材质沿用 E-Ink / Paper：纸底 + 发丝线 + 铅笔灰标签，数字用墨色等宽数字对齐。 */
.ws-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
.ws-stat { display: flex; flex-direction: column; align-items: center; gap: 3px; padding: 12px 4px;
  border: 1px solid #E8E2D6; border-radius: 16px; background: #FFFCF8; }
.ws-stat b { font-size: 1.34em; font-weight: 800; color: #1A1A1A; font-variant-numeric: tabular-nums; line-height: 1.1; }
.ws-stat span { font-size: .72em; color: #8A8177; letter-spacing: .04em; white-space: nowrap; }
/* 难词是"要注意"的那一格，用一条左侧色条提示，不用红（避免报警感） */
.ws-stat.is-hard b { color: #4A3229; }
.ws-stat.is-hard { border-color: #DCD2C4; }
.ws-stats-note { margin: 12px 0 0; font-size: .74em; color: #A8A29E; line-height: 1.6; }
html.dark .ws-stat { background: #2A2623; border-color: #3F3A37; }
html.dark .ws-stat b { color: #FAFAF9; }
html.dark .ws-stat span { color: #A8A29E; }
html.dark .ws-stat.is-hard b { color: #D4A373; }
html.dark .ws-stat.is-hard { border-color: #6B5D52; }
html.dark .ws-stats-note { color: #78716C; }
@media (max-width: 768px) {
  .ws-stat b { font-size: 1.15em; }
  .ws-stat { padding: 10px 2px; }
}
.ws-set-block { background: #FFFCF8; border: 1px solid #E8E2D6; border-radius: 14px; padding: 18px 20px; margin-bottom: 16px; }
.ws-label { font-size: .74em; font-weight: 700; color: #8A8177; letter-spacing: .1em; margin: 0 0 12px; }
.ws-levels { display: grid; grid-template-columns: repeat(5, 1fr); gap: 8px; }
.ws-level { padding: 12px 2px; border-radius: 16px; border: 1.5px solid #E8E2D6; background: #FFFCF8; color: #3A3733; cursor: pointer; transition: border-color .18s ease, background .18s ease, color .18s ease; display: flex; flex-direction: column; align-items: center; gap: 4px; }
.ws-level:hover { border-color: #B8AE9E; background: #F7F4ED; }
.ws-level b { font-size: .92em; font-weight: 600; }
.ws-level small { font-size: .68em; color: #8A8177; white-space: nowrap; }
.ws-level.sel { border-color: #57534E; background: #F1ECE2; color: #1A1A1A; }
.ws-level.sel b { font-weight: 800; }
.ws-level.sel small { color: #57534E; }
/* 自绘开关（无需改 HTML：直接改原生 checkbox 外观）—— 本页「发音」区块已移除，
   该开关样式随之删除；「音效」卡片里仍用 .ws-tool-row 的原生勾选框。 */
/* ── 每日额度卡片：两行（新词 / 复习），各由 − 数值 + 滑杆组成 ── */
.ws-quota-row { padding: 12px 0; }
.ws-quota-row + .ws-quota-row { border-top: 1px solid #F0EBE1; }
.ws-quota-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 12px; }
.ws-quota-name { font-size: .9em; font-weight: 600; color: #262322; }
.ws-quota-val { font-size: .76em; color: #8A8177; }
.ws-quota-val b { font-size: 1.7em; font-weight: 800; color: #1A1A1A; margin-right: 3px; font-variant-numeric: tabular-nums; }
.ws-quota-ctl { display: flex; align-items: center; gap: 12px; }
.ws-step { position: relative; flex: none; width: 34px; height: 34px; display: inline-flex; align-items: center; justify-content: center; border: 1px solid #E8E2D6; border-radius: 9px; background: #FFFCF8; color: #57534E; font-size: 1.05em; line-height: 1; cursor: pointer; transition: background .18s ease, border-color .18s ease, color .18s ease, transform .12s ease; }
/* 热区扩到 44×44（34 + 5×2），触摸目标下限 */
.ws-step::after { content: ''; position: absolute; inset: -5px; }
.ws-step:hover { background: #F1ECE2; border-color: #B8AE9E; color: #1A1A1A; }
.ws-step:active { transform: scale(.94); }
/* 滑杆：细纸轨 + 墨色圆钮（webkit / firefox 两套伪元素） */
.ws-quota-ctl input[type=range] { -webkit-appearance: none; appearance: none; flex: 1; min-width: 0; height: 22px; background: transparent; cursor: pointer; }
.ws-quota-ctl input[type=range]::-webkit-slider-runnable-track { height: 4px; border-radius: 999px; background: #E8E2D6; }
.ws-quota-ctl input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 18px; height: 18px; margin-top: -7px; border-radius: 50%; background: #57534E; border: 2px solid #FFFCF8; box-shadow: 0 1px 3px rgba(60,50,35,.3); }
.ws-quota-ctl input[type=range]::-moz-range-track { height: 4px; border-radius: 999px; background: #E8E2D6; }
.ws-quota-ctl input[type=range]::-moz-range-thumb { width: 16px; height: 16px; border-radius: 50%; background: #57534E; border: 2px solid #FFFCF8; box-shadow: 0 1px 3px rgba(60,50,35,.3); }
.ws-quota-ctl input[type=range]:focus-visible { outline: 2px solid #57534E; outline-offset: 2px; border-radius: 999px; }
html.dark .ws-quota-row + .ws-quota-row { border-top-color: #3F3A37; }
html.dark .ws-quota-name { color: #E7E5E4; }
html.dark .ws-quota-val b { color: #FAFAF9; }
html.dark .ws-step { background: #262220; border-color: #3F3A37; color: #D6D3D1; }
html.dark .ws-step:hover { background: #322C28; border-color: #57534E; color: #FAFAF9; }
html.dark .ws-quota-ctl input[type=range]::-webkit-slider-runnable-track { background: #3F3A37; }
html.dark .ws-quota-ctl input[type=range]::-moz-range-track { background: #3F3A37; }
html.dark .ws-quota-ctl input[type=range]::-webkit-slider-thumb { background: #D6D3D1; border-color: #262220; }
html.dark .ws-quota-ctl input[type=range]::-moz-range-thumb { background: #D6D3D1; border-color: #262220; }
html.dark .ws-set-block { background: #2A2623; border-color: #3F3A37; }
html.dark .ws-label { color: #A8A29E; }
html.dark .ws-level { background: #262220; border-color: #3F3A37; color: #D6D3D1; }
html.dark .ws-level small { color: #A8A29E; }
html.dark .ws-level:hover { border-color: #57534E; background: #322C28; }
html.dark .ws-level.sel { background: #3A342F; border-color: #A8A29E; color: #FAFAF9; }
html.dark .ws-level.sel small { color: #D6D3D1; }

.ws-side-item, .ws-syn, .ws-level, .ws-lib-card, .ws-start, .ws-act, .ws-nav-btn, .ws-remove-btn, .ws-wl-toggle, .ws-wl-text, .ws-spk, .ws-wl-spk{
  transition: color var(--t-state) var(--ease-out-quart),
              background-color var(--t-state) var(--ease-out-quart),
              border-color var(--t-state) var(--ease-out-quart),
              box-shadow var(--t-state) var(--ease-out-quart),
              transform var(--t-press) var(--ease-out-quart);
}
.ws-syn:active, .ws-level:active, .ws-side-item:active, .ws-nav-btn:active, .ws-start:active, .ws-remove-btn:active, .ws-wl-text:active{
  transform: scale(.97);
}
/* 大块按钮与卡片：缩放幅度收小，整块缩放过大反而显得弹 */
.ws-act:active, .ws-lib-card:active { transform: scale(.985); }
.ws-spk:active, .ws-wl-spk:active, .ws-wl-toggle:active{ transform: scale(.9); }
/* 认识 / 不认识 的按压反馈现由其自身皮肤承担（见下），动效层不再覆写这两枚 */
/* 槽位交接：评分后 nav 按钮才被取消 .hidden，此时交叉淡入交代"这一步记下了" */
@keyframes wsSwapIn { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
.ws-actions.swap-in, .ws-nav-btn.swap-in { animation: wsSwapIn var(--t-swap) var(--ease-out-expo) both; }

/* 注：此处原有 Uiverse.io by Mike11jr 的「硬偏移阴影 + 斜切扫光」皮肤说明（含 ::before 的 left:0 与
   500% 行程两条修正）。该皮肤已按用户要求整体替换为下方的「白底柔和上浮」皮肤，扫光与硬阴影不再存在，
   故相关说明与 `.ws-act-yes::before` / `.ws-act-no::before` 规则一并移除。 */
/* ── 两枚主按钮：用户给定的「白底柔和上浮」皮肤（原稿为裸 `button` 选择器）──
   原稿：白底 / 无描边 / 45px 圆角 / `0 8px 15px rgba(0,0,0,.1)` / hover 变绿 + 上浮 7px + 绿色辉光 / active 回落 1px。
   **必需的四处修正（均实测）**：
   1. 选择器：原稿是裸 `button`，站内 `button` / `.btn` 共 101+ 处引用，裸用会波及全站 → 限定到这两枚。
   2. 悬停对比度：原稿白字 on `#23c483` 实测仅 **2.26:1**；`font-size: 12px` 属正文级、门槛 4.5:1，不可读。
      绿色加深到 `#0F7A50` 得 **5.36:1**，保留"变绿 + 白字"的原意。（辉光色仍用原稿的 rgba(163,185,140,.4)，属装饰）
   3. `outline: none`：站内全局有 `:focus-visible` 键盘焦点环，此处不覆盖它（原稿的裸 `outline:none` 会削弱可达性）。
   4. 减少动态：原稿 hover 有 -7px 位移，已在下方 `prefers-reduced-motion` 块里一并关掉。
   另：`text-transform: uppercase` 对中文无效果（无拉丁字母）；`letter-spacing: 2.5px` 对中文生效。
   原「方向 A 主次分明」的焦糖橙渐变 + 斜切扫光皮肤已整体移除。 */
.ws-act-yes, .ws-act-no {
  padding: 1.3em 3em;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 2.5px;
  font-weight: 500;
  color: #231C15;
  background-color: #fff;
  border: none;
  border-radius: 45px;
  box-shadow: 0px 8px 15px rgba(0, 0, 0, 0.1);
  transition: all 0.3s ease 0s;
  cursor: pointer;
}
.ws-act-yes:hover, .ws-act-no:hover {
  background-color: #0F7A50;
  box-shadow: 0px 15px 16px rgba(163,185,140,0.4);
  color: #fff;
  transform: translateY(-7px);
}
.ws-act-yes:active, .ws-act-no:active {
  transform: translateY(-1px);
}

/* 减少动态：去掉位移，保留颜色与不透明度的状态反馈（确认动作仍要看得见） */
@media (prefers-reduced-motion: reduce) {
  .ws-syn:active, .ws-level:active, .ws-side-item:active, .ws-nav-btn:active, .ws-start:active, .ws-remove-btn:active, .ws-wl-text:active, .ws-act:active, .ws-lib-card:active, .ws-spk:active, .ws-wl-spk:active, .ws-wl-toggle:active, .ws-act-yes:active, .ws-act-no:active{ transform: none; opacity: .88; }
  /* 新皮肤 hover 带 -7px 上浮位移，减少动态下一并关掉；底色/文字色/辉光变化保留（仍能确认状态） */
  .ws-act-yes:hover, .ws-act-no:hover { transform: none; }
  .ws-actions.swap-in, .ws-nav-btn.swap-in { animation: none; }
}

/* ── 速记生词页：平板适配 ──
   ⚠ 坑（本轮实测踩到）：不能写 `@media (min-width:769px), html.force-tablet` 把媒体查询和类选择器 OR 在一起 ——
   @media 的前导只能是媒体查询，混了选择器**整块会被浏览器丢弃**（实测：那样写的 12 条规则一条都没生效，
   force-tablet 下侧栏仍是 150px、字号仍是 80px）。站内其它 `@media …, html.force-phone/tablet` 写法同样可疑。
   所以这里走**自定义属性**：真平板用媒体查询覆盖变量、平板预览用 html.force-tablet 覆盖同一组变量，
   下面消费变量的规则只写一遍。
   取值依据（实测）：平板原本完全沿用桌面布局；底部那片空档**不是**平板 bug —— 内容组本来就垂直居中
   （实测中心 576 vs 容器 590，桌面同样留 335px），属于"卡片只有 170px 高"的既定设计，不动它。 */
:root {
  --ws-side-w: 150px;
  --ws-side-gap: 4px;
  --ws-side-pad: 14px 12px;
  --ws-brand-gap: 8px;
  --ws-brand-pad: 4px 6px 16px;
  --ws-brand-fs: .95em;
  --ws-brand-icon: 20px;
  --ws-item-gap: 10px;
  --ws-item-minh: 44px;
  --ws-item-pad: 10px 12px;
  --ws-item-fs: .86em;
  --ws-item-icon: 18px;
  --ws-content-pad: 24px 28px 48px;
  --ws-topbar-m: 16px 16px 0 calc(150px + 16px);
  --ws-word-fs: clamp(2.8em, 9vw, 5em);
  --ws-actions-w: 480px;
  --ws-stage-h: calc(100vh - 168px);
}
/* 平板取值（769–1180px）：侧栏收窄到 116px（图标+文字仍放得下，内容区多出 34px），
   保留**竖向侧栏**而不改成手机那种顶部横条 —— 横向空间够，横条反而白费竖向空间。
   单词上限 5em→5.6em 并引入视口高度约束（22vh），横屏矮屏（768 高）下不会把卡片撑爆。 */
@media (min-width: 769px) and (max-width: 1180px) {
  :root {
    --ws-side-w: 116px;
    --ws-side-pad: 12px 8px;
    --ws-brand-gap: 6px;
    --ws-brand-pad: 4px 4px 12px;
    --ws-brand-fs: .88em;
    --ws-brand-icon: 17px;
    --ws-item-gap: 8px;
    --ws-item-minh: 42px;
    --ws-item-pad: 9px 9px;
    --ws-item-icon: 16px;
    --ws-content-pad: 18px 22px 32px;
    --ws-topbar-m: 14px 14px 0 calc(116px + 14px);
    --ws-word-fs: min(11vw, 22vh, 5.6em);
    --ws-actions-w: 440px;
    --ws-stage-h: calc(100vh - 148px);
  }
  .ws-lib-list { grid-template-columns: repeat(2, 1fr); }
  .ws-nav-btn { padding: 14px; }
  .ws-type-boards { gap: 10px; margin-bottom: 24px; }
  .ws-type-stats { max-width: 560px; }
}
/* 平板预览：覆盖同一组变量 → 预览与真机一致（这正是原来缺的那一块） */
html.force-tablet {
  --ws-side-w: 116px;
  --ws-side-pad: 12px 8px;
  --ws-brand-gap: 6px;
  --ws-brand-pad: 4px 4px 12px;
  --ws-brand-fs: .88em;
  --ws-brand-icon: 17px;
  --ws-item-gap: 8px;
  --ws-item-minh: 42px;
  --ws-item-pad: 9px 9px;
  --ws-item-icon: 16px;
  --ws-content-pad: 18px 22px 32px;
  --ws-topbar-m: 14px 14px 0 calc(116px + 14px);
  --ws-word-fs: min(11vw, 22vh, 5.6em);
  --ws-actions-w: 440px;
  --ws-stage-h: calc(100vh - 148px);
}
html.force-tablet .ws-lib-list { grid-template-columns: repeat(2, 1fr); }
html.force-tablet .ws-nav-btn { padding: 14px; }
html.force-tablet .ws-type-boards { gap: 10px; margin-bottom: 24px; }
html.force-tablet .ws-type-stats { max-width: 560px; }
/* 注：顶栏定位那两条覆盖必须写在下面通用 force-tablet 规则**之后** ——
   选择器权重完全相同（1,3,1），只能靠源序取胜；写在前面会输，实测 padding-top 仍是 60px。 */
@media (max-width: 768px) {
  .ws-shell { display: block; min-height: 0; }
  /* ⚠️ 这里**不能**写 `margin-left: 0`：那句原本是配合"侧栏被压成横向条"的，
     而侧栏现在只在 `#wordStudyPage.ws-nav-mobile` 时才不渲染 ——
     强制平板 + 768px 这种组合下侧栏仍是 fixed 116px，内容清零就会滑到侧栏底下（改完实测踩到过）。 */
  .ws-content { padding: 16px 14px 32px; }
  /* 手机端：决策区必须落到拇指区。舞台重新撑高，底部槽位用 margin-top:auto 顶到底。
     `.ws-stage-col > .ws-stage` 权重 (0,2,0) 与上面那条 :has() 规则相同，靠「后来居上」覆盖它。
     245px 是手机端固定 chrome 的实测标定值（侧栏横条 + 内容上下内边距 + 舞台头/进度条等），
     使页面恰好占满视口、不产生尾随滚动；手机端 chrome 尺寸若有变动需重新标定。 */
  .ws-stage-col { height: auto; overflow: visible; min-height: calc(100vh - 245px); min-height: calc(100dvh - 245px); }
  .ws-stage-col > .ws-stage { flex: 1; }
  .ws-bottom { margin-top: auto; }
  .ws-wl-panel { left: 0; width: 42px; max-height: 70vh; }
  .ws-wl-panel.open { width: min(82vw, 320px); }
  .ws-lib-list { grid-template-columns: 1fr; }
  .ws-levels { grid-template-columns: repeat(3, 1fr); }
  /* 手机上「新学 / 复习」两张卡片改为上下排（左右并排会太窄） */
  .ws-pick { grid-template-columns: 1fr; gap: 14px; }
  .ws-pick-wrap { min-height: 0; padding: 4px 0 24px; }
  .ws-pick-card { padding: 26px 20px 20px; }
  .ws-pick-emoji { font-size: 2.2em; }
  .ws-pick-name { font-size: 1.32em; }
  .ws-card { padding: 16px 12px 0; }
  .ws-word { font-size: calc(2.4em * var(--ws-word-scale, 1)); }
  .ws-actions { width: 100%; margin: 20px auto 8px; }
  /* 注：这里原有 `.ws-act { padding: 14px; font-size: 1.1em }`。
     新皮肤（padding 1.3em 3em / font-size 12px）本身就是紧凑的 ~45px 高，再压会破坏其 em 比例，故移除。 */
  .ws-reveal-cols { flex-direction: column; flex-wrap: wrap; row-gap: 20px; }
  .ws-col-left, .ws-col-right { flex: none; width: 100%; }
  .ws-col-right .ws-block:first-child { margin-top: 20px; }
  .ws-reveal { margin-top: 12px; padding: 16px; }
  .ws-meaning { font-size: .9em; line-height: 1.65; }
  .ws-ex-en { font-size: .86em; }
  .ws-ex-zh { font-size: .8em; }
  .ws-ex + .ws-ex { margin-top: 11px; padding-top: 11px; }
  .ws-block { margin-top: 18px; }
  .ws-col-right .ws-block { margin-top: 16px; }
  .ws-block-title { margin-bottom: 8px; }
  .ws-mean-line { gap: 7px; }
  .ws-syns { gap: 7px; }
}
/* 第 2 步回退（2026-09-20）：这条原本被删掉过，现在按原样恢复 —— 主页保持"块状 + 两张大卡"的原设计。 */
html.force-phone .ws-shell { display: block !important; min-height: 0 !important; }
/* 手机导航形态统一由 #wordStudyPage.ws-nav-mobile 驱动（见上方 CSS 注释），
   这里不再单独覆盖 .ws-sidebar / .ws-content —— 否则会和 force-tablet / 窄窗口组合打架。 */
/* ⚠️ 这一条是**手机档「单词垂直居中」的总开关**，而且带 `html` 前缀 + `!important`，
   特异性高于后面 `@media (max-width:400px)` 那类写法 —— 所以手机分档只能改这里（改别处都会被它压掉，
   实测为此外白折腾了两轮）。原值 245 是"一屏固定高度"时代的预算；2026-10-09 按实测改成 109：
   小屏手机（360×640）单词中心与视口中心差从 -36px 收敛到 ±10px 内。 */
html.force-phone .ws-stage-col { height: auto !important; overflow: visible !important; min-height: calc(100vh - 111px) !important; min-height: calc(100dvh - 111px) !important; }
html.force-phone .ws-stage-col > .ws-stage { flex: 1 !important; }
html.force-phone .ws-bottom { margin-top: auto !important; }
html.force-phone .ws-wl-panel { left: 0 !important; width: 42px !important; max-height: 70vh !important; }
html.force-phone .ws-wl-panel.open { width: min(82vw, 320px) !important; }
html.force-phone .ws-lib-list { grid-template-columns: 1fr !important; }
html.force-phone .ws-levels { grid-template-columns: repeat(3, 1fr) !important; }
/* 第 2 步回退（2026-09-20）：这两条也按原样恢复（主页两张大卡在手机端仍是单列、紧凑内边距）。 */
html.force-phone .ws-pick { grid-template-columns: 1fr !important; gap: 14px !important; }
html.force-phone .ws-pick-wrap { min-height: 0 !important; padding: 4px 0 24px !important; }
html.force-phone #wsModeBtn .ws-mode-emoji, html.force-phone #wsModeBtn #wsModeLabel { display: none !important; }
html.force-phone .ws-card { padding: 16px 12px 0 !important; }
html.force-phone .ws-word { font-size: calc(2.4em * var(--ws-word-scale, 1)) !important; }
html.force-phone .ws-actions { width: 100% !important; }
/* 同上：移除 `.ws-act { padding: 14px !important; font-size: 1.1em !important }` —— 新皮肤已是紧凑尺寸，
   且 `!important` 会无视权重直接覆盖新皮肤的 padding/font-size，破坏 1.3em×3em 的比例。 */
html.force-phone .ws-reveal-cols { flex-direction: column !important; gap: 0 !important; }
html.force-phone .ws-col-left, html.force-phone .ws-col-right { flex: none !important; width: 100% !important; }
html.force-phone .ws-col-right .ws-block:first-child { margin-top: 12px !important; }
html.force-phone .ws-nav-btn { padding: 14px !important; }
html.force-desktop .ws-levels { grid-template-columns: repeat(5, 1fr) !important; }
html.force-desktop .ws-shell { display: flex !important; }
html.force-desktop .ws-content { margin-left: 150px !important; }

@media (max-width: 768px) {
  .home h1 { font-size: 2em; }
  .cards { grid-template-columns: 1fr; max-width: 340px; }
  .cards.cards-exam { grid-template-columns: 1fr; max-width: 340px; gap: 16px; }
  .card { padding: 24px 20px; }
  .topbar { position: fixed; top: 0; left: 0; right: 0; z-index: 100; }
  #readingPage { padding-top: 48px; }
  #donePage .topbar ~ .vocab-page { padding-top: 48px; }
  #trainDonePage .topbar ~ .vocab-page { padding-top: 48px; }
  #basicLibraryPage .topbar ~ .vocab-page { padding-top: 48px; }
  #petPage .topbar ~ .vocab-page { padding-top: 56px; }
  .chat-layout { top: 52px; height: calc(100vh - 52px); }
  .annotate-toolbar { top: 48px !important; }
  .main-layout { flex-direction: column; padding: 16px; }
  .reading-area { padding: 20px 0 24px; }
  .reading-area .title, .passage-body, .questions-section { padding-left: 16px; padding-right: 16px; }
  .reading-area .instruction { margin: 0 16px 24px; padding-left: 16px; }
  .vocab-sidebar { width: 100%; position: static; max-height: none; overflow: visible; }
  .vocab-panel { position: static; }
  .radio-group { width: 170px; height: 32px; }
  .radio-group:has(#storyHubRadio) { width: 190px; }
  .radio-group .rg-slider { top: 3px; bottom: 3px; border-radius: 17px; }
  .radio-label { font-size: 12px; padding: 0 10px; }
}

@media (min-width: 769px) and (max-width: 1024px) {
  /* Home */
  .home { padding: 60px 20px 40px; }
  .home h1 { font-size: 2.4em; }
  .home-online { margin: 0 0 10px; font-size: .86em; }
  .cards { max-width: 560px; gap: 16px; }
.cards.cards-exam { max-width: 900px; gap: 16px; }
  .cards-exam .card { padding: 22px 14px 20px; }
  .cards-exam h2 { font-size: .95em; }
  .card { padding: 24px 20px; }

  /* Top Bar */
  .topbar { padding: 8px 12px; gap: 6px; }
  .topbar .btn { padding: 5px 10px; font-size: .74em; }
  .topbar .back { padding: 4px 8px; font-size: 1.1em; }
  .topbar .info { font-size: .85em; }
  .topbar .btn svg { width: 13px; height: 13px; }
  .topbar .btn-outline { padding: 5px 10px; }
  .topbar .btn-primary { padding: 5px 12px; }

  /* Reading Page */
  .main-layout { padding: 16px; gap: 14px; }
  .reading-area { padding: 20px 0 24px; }
  .reading-area .title { padding: 0 24px 12px; font-size: 1.05em; }
  .reading-area .instruction { margin: 0 24px 18px; font-size: .78em; }
  .passage-body { padding: 0 24px; }
  .passage-body p { font-size: calc(.96em * var(--rt-scale, 1)); }
  .questions-section { padding: 20px 24px 0; margin-top: 28px; padding-top: 18px; }
  .question-block { padding: 14px 16px; margin-bottom: 16px; }
  .q-option { padding: 5px 12px; font-size: .9em; }
  .q-stem { padding-left: 13px; }
  .q-analyze-row { padding-left: 13px; }
.vocab-sidebar { width: 205px; top: 72px; max-height: calc(100vh - 90px); }
  .vocab-panel { padding: 16px; }
.vocab-panel h3 { font-size: .82em; gap: 6px; }
  .vocab-item { font-size: .78em; }
  .vocab-item .del { font-size: 1em; }
  .vocab-actions button { font-size: .74em; }
  .bottom-section { padding: 0 16px 32px; }
  .bottom-section h3 { font-size: .9em; margin: 22px 0 12px; }
  .full-trans { padding: 22px 24px; font-size: .9em; }

  /* Chat Pages */
  .chat-layout { top: 52px; height: calc(100vh - 52px); }
  .chat-sidebar { width: 195px; }
  .chat-main .chat-container { padding: 0 16px; max-width: none; }
  .chat-msg .bubble { max-width: 88%; font-size: .88em; }
  .chat-input-area input { font-size: .85em; padding: 10px 16px; }
  .chat-input-area .btn-send { font-size: .84em; padding: 8px 20px; }
  .session-item { padding: 9px 28px 9px 12px; }
  .session-item .sess-title { font-size: .8em; }
  .sidebar-head button { font-size: .8em; padding: 8px; }
  .chat-hint { font-size: .82em; padding: 14px 18px; }

  /* Story Hub */
  .story-hub-layout { flex-direction: column; height: auto; gap: 20px; padding: 24px 20px; max-width: none; }
  .story-hub-right { width: 100%; }
  .story-hub-right .story-list-body { max-height: 300px; }
  .story-hub-right .story-list-head { font-size: .8em; padding-bottom: 10px; }

  /* Story Reading */
  #storyReadLayout { padding: 16px; gap: 14px; }
  .story-read-area { padding: 28px 32px; }
  .story-vocab-sidebar { width: 230px; }
  .story-vocab-panel { padding: 16px; }
  .story-vocab-item { font-size: .8em; }

  /* Vocab Page / Done Page */
  .vocab-page { max-width: none; padding: 28px 20px; }
  .vp-toolbar button { font-size: .78em; padding: 7px 14px; }

  .ai-greet { right: 66px; bottom: 22px; max-width: 210px; font-size: .82em; padding: 14px 28px 14px 16px; }

  /* Popovers / Overlays */
  .popover { max-width: min(60vw, 340px); }
  .trans-overlay { max-width: 80vw; }
  .popover .dict-word { font-size: 1em; }
  .popover .dict-meaning { font-size: .85em; }
  .trans-overlay .trans-text { font-size: .88em; }
  .reading-picker { padding: 28px 32px; }
  .login-card { padding: 36px 30px; }
  .donate-card { padding: 24px 22px 20px; }
  .clear-modal { padding: 28px; }

  /* Annotate Toolbar */
  .annotate-toolbar { padding: 3px 8px; gap: 2px; }
  .annotate-toolbar button { width: 22px; height: 22px; }
  .annotate-toolbar .tool-size { height: 20px; min-width: 20px; font-size: .65em; }
  .annotate-toolbar .sep { margin: 0 2px; height: 14px; }

  /* Annotate Canvas */
  .annotate-cursor.show { display: none; }
}

/* Floating annotate trigger (mobile pinch-to-reveal) */
.fab-container { position: fixed; right: 16px; top: 50%; z-index: 95; display: flex; align-items: center; flex-direction: row-reverse; gap: 0; pointer-events: none; opacity: 0; transition: opacity .3s; }
.fab-container.show { opacity: 1; pointer-events: auto; }

.floating-annotate-btn { width: 52px; height: 52px; border-radius: 50%; background: linear-gradient(135deg, var(--c-accent), #B45309); color: #fff; box-shadow: 0 4px 20px rgba(217,119,6,.4); display: flex; align-items: center; justify-content: center; border: none; cursor: pointer; flex-shrink: 0; transition: transform .2s ease; touch-action: manipulation; }
.floating-annotate-btn:active { transform: scale(.9); }
.floating-annotate-btn svg { width: 20px; height: 20px; }
.fab-container.show .floating-annotate-btn { pointer-events: auto; }

.fab-label { position: absolute; right: 64px; top: 50%; transform: translateY(-50%); white-space: nowrap; font-size: .78em; background: rgba(0,0,0,.7); color: #fff; padding: 4px 12px; border-radius: 100px; opacity: 0; transition: opacity .3s; pointer-events: none; }
.fab-label.visible { opacity: 1; }

.fab-toolbar { position: absolute; right: 60px; top: 50%; display: flex; flex-wrap: wrap; justify-content: center; max-width: 300px; align-items: center; gap: 4px; background: var(--c-white); border-radius: 18px; padding: 5px 10px; box-shadow: 0 4px 16px rgba(0,0,0,.1); border: 1px solid var(--c-border); transform-origin: right center; transform: translateY(-50%) scaleX(0); opacity: 0; transition: transform .35s cubic-bezier(.32,.72,0,1), opacity .25s; }
.fab-toolbar .sep { width: 1px; height: 16px; background: var(--c-border); margin: 0 2px; flex-shrink: 0; }
.fab-toolbar.expanded { transform: translateY(-50%) scaleX(1); opacity: 1; }

.fab-toolbar button { width: 32px; height: 32px; border-radius: 6px; border: 2px solid transparent; padding: 0; display: flex; align-items: center; justify-content: center; cursor: pointer; flex-shrink: 0; font-size: .7em; font-weight: 500; background: transparent; color: var(--c-text-secondary); transition: all .15s; }
.fab-toolbar button:hover { transform: scale(1.1); }
.fab-toolbar button.sel { border-color: var(--c-primary-dark); }
.fab-toolbar .color-red { background: #EF4444; }
.fab-toolbar .color-yellow { background: #F59E0B; }
.fab-toolbar .color-blue { background: #3B82F6; }
.fab-toolbar .color-green { background: #22C55E; }
/* 悬浮笔上的色板：同样收起，展开在触发器右侧（它是竖排小工具条） */
.fab-toolbar .cp-panel { top: 0; left: calc(100% + 7px); }
.fab-toolbar .tool-eraser { background: #FFF; border: 1px solid var(--c-border); color: var(--c-text-secondary); }
.fab-toolbar .tool-undo { background: transparent; border: 1px solid var(--c-border); color: var(--c-text-secondary); }
.fab-toolbar .tool-size { border-radius: var(--radius-sm); width: auto; min-width: 22px; height: 22px; padding: 0 5px; border: 1px solid var(--c-border); background: #F5F5F4; }
.fab-toolbar .tool-size.sel-pen { border-color: var(--c-accent); background: #FFFBEB; color: var(--c-accent); }
.fab-toolbar .sep { width: 1px; height: 16px; background: var(--c-border); margin: 0 2px; flex-shrink: 0; }
.fab-toolbar .tool-label { background: transparent; border: none; width: auto; min-width: 14px; padding: 0 2px; font-size: .72em; font-weight: 600; color: var(--c-text-muted); letter-spacing: .02em; cursor: default; display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; }
.fab-toolbar .tool-label.active { color: var(--c-accent); }
.fab-toolbar .tool-label-eraser.active { color: var(--c-danger); }
.fab-toolbar .fab-collapse { background: #F5F5F4; border: 1px solid var(--c-border); border-radius: var(--radius-sm); width: 28px; height: 28px; font-size: .65em; }
.fab-toolbar .fab-hl-btn { background: transparent; border: 1px solid var(--c-border); color: var(--c-text-secondary); border-radius: var(--radius-sm); font-size: .8em; }
.fab-toolbar .fab-hl-btn.sel { background: #FEF3C7; border-color: var(--c-accent); color: var(--c-accent); }

/* ── Force Mode: Tablet (no media query - class driven) ── */
/* Force Desktop: override responsive media queries */
html.force-desktop .main-layout { flex-direction: row !important; }
html.force-desktop .vocab-sidebar { width: 240px !important; top: 80px !important; }
html.force-desktop .vocab-panel { position: static !important; }
html.force-desktop .cards { grid-template-columns: repeat(2, 1fr) !important; max-width: 640px !important; }
html.force-desktop .cards.cards-exam { grid-template-columns: repeat(3, 1fr) !important; max-width: 980px !important; }
html.force-desktop .cards-exam .card { padding: 26px 20px 24px !important; }
html.force-desktop .cards-exam h2 { font-size: 1.05em !important; }
html.force-desktop .card { padding: 30px 26px 28px !important; }
/* ⚠️ 这里必须排除「上一篇 / 下一篇」这两个按钮（用 :not() 提特异性，比再加一条 !important 干净得多）：
   否则这条 !important 会压过下面的 #readingPage #btnPrevArticle{display:none}，
   后果是「视图模式 → 电脑」下原题训练顶栏又冒出上下篇 —— 2026-09-24 用户实测踩到过。
   :not() 的权重按里面最重的算（#id），所以这条依然稳稳压过上面的基础 .topbar .btn。
   ⚠️ 2026-10-04 又踩了同一个坑：新加的「小说 / 生成题目」那两组「修改 · 再来一篇」没进排除表，
   于是**电脑视图模式下，任何阅读页（含真题训练所有题型）顶栏都会冒出这四颗按钮**
   （用户截图式描述：「上一篇、下一篇、修改、再来一篇、修改、再来一篇、标注…」）。
   凡是"只在某个阅读模式下才显示"的顶栏按钮，都必须加进这个 :not() 名单。 */
html.force-desktop .topbar .btn:not(.back):not(#btnPrevArticle):not(#btnNextArticle):not(#btnRefresh):not(#btnStoryEdit):not(#btnStoryAgain):not(#btnGenEdit):not(#btnGenAgain):not(#btnFavQuiz):not(#btnSaveArticle) { display: flex !important; }
html.force-desktop .auth-info { display: flex !important; }
html.force-desktop .phone-tab-bar { display: none !important; }

/* Force Tablet */
html.force-tablet .home { padding: 60px 20px 40px; }
html.force-tablet .home h1 { font-size: 2.4em; }
html.force-tablet .home-online { margin: 0 0 14px; font-size: .86em; }
html.force-tablet .cards { max-width: 560px; gap: 16px; }
html.force-tablet .cards.cards-exam { max-width: 900px; gap: 16px; }
html.force-tablet .cards-exam .card { padding: 22px 14px 20px; }
html.force-tablet .cards-exam h2 { font-size: .95em; }
html.force-tablet .card { padding: 24px 20px; }
html.force-tablet .csm-btn { padding: 3px 9px; font-size: .64em; }
html.force-tablet .topbar { padding: 8px 12px; gap: 6px; position: fixed; top: 0; left: 0; right: 0; z-index: 100; }
html.force-tablet .topbar .btn { padding: 5px 10px; font-size: .74em; }
html.force-tablet .topbar .back { padding: 4px 8px; font-size: 1.1em; }
html.force-tablet .topbar .info { font-size: .85em; }
html.force-tablet .topbar .btn svg { width: 13px; height: 13px; }
html.force-tablet .topbar .btn-outline { padding: 5px 10px; }
html.force-tablet .topbar .btn-primary { padding: 5px 12px; }
html.force-tablet #readingPage { padding-top: 46px; }
html.force-tablet .annotate-toolbar { top: 46px !important; }
html.force-tablet .chat-layout { top: 52px; height: calc(100vh - 52px); padding-top: 0; }
html.force-tablet .main-layout { padding: 26px 16px 16px; gap: 14px; }
html.force-tablet .reading-area { padding: 20px 0 24px; }
html.force-tablet .reading-area .title { padding: 0 24px 12px; font-size: 1.05em; }
html.force-tablet .reading-area .instruction { margin: 0 24px 18px; font-size: .78em; }
html.force-tablet .passage-body { padding: 0 24px; }
html.force-tablet .passage-body p { font-size: calc(.96em * var(--rt-scale, 1)); }
html.force-tablet .questions-section { padding: 20px 24px 0; margin-top: 28px; padding-top: 18px; }
html.force-tablet .question-block { padding: 14px 16px; margin-bottom: 16px; }
html.force-tablet .q-option { padding: 5px 12px; font-size: .9em; }
html.force-tablet .q-stem { padding-left: 13px; }
html.force-tablet .q-analyze-row { padding-left: 13px; }
html.force-tablet .vocab-sidebar { width: 205px; top: 72px; max-height: calc(100vh - 90px); }
html.force-tablet .vocab-panel { padding: 16px; }
html.force-tablet .vocab-panel h3 { font-size: .82em; gap: 6px; }
html.force-tablet .vocab-item { font-size: .78em; }
html.force-tablet .vocab-item .del { font-size: 1em; }
html.force-tablet .vocab-actions button { font-size: .74em; }
html.force-tablet .bottom-section { padding: 0 16px 32px; }
html.force-tablet .bottom-section h3 { font-size: .9em; margin: 22px 0 12px; }
html.force-tablet .full-trans { padding: 22px 24px; font-size: .9em; }
html.force-tablet .annotate-toolbar { display: none !important; }
html.force-tablet .chat-layout { top: 52px; height: calc(100vh - 52px); padding-top: 0; }
html.force-tablet .chat-sidebar { width: 195px; }
html.force-tablet .chat-main .chat-container { padding: 0 16px; max-width: none; }
html.force-tablet .chat-msg .bubble { max-width: 88%; font-size: .88em; }
html.force-tablet .chat-input-area { position: fixed; bottom: 0; left: 195px; right: 0; background: var(--c-white); padding: 10px 16px; border-top: 1px solid rgba(120,113,108,.08); z-index: 10; margin-top: 0; }
html.force-tablet .chat-input-area input { font-size: .85em; padding: 10px 16px; }
html.force-tablet .chat-messages { padding-bottom: 60px; }
html.force-tablet .chat-input-area .btn-send { font-size: .84em; padding: 8px 20px; }
html.force-tablet .session-item { padding: 9px 28px 9px 12px; }
html.force-tablet .session-item .sess-title { font-size: .8em; }
html.force-tablet .sidebar-head button { font-size: .8em; padding: 8px; }
html.force-tablet .chat-hint { font-size: .82em; padding: 14px 18px; }
html.force-tablet .story-hub-layout { flex-direction: column; height: auto; gap: 20px; padding: 24px 20px; padding-top: 56px; max-width: none; }
html.force-tablet .story-hub-right { width: 100%; }
html.force-tablet .story-hub-right .story-list-body { max-height: 300px; }
html.force-tablet .story-hub-right .story-list-head { font-size: .8em; padding-bottom: 10px; }
html.force-tablet #storyReadLayout { padding: 16px; padding-top: 62px; gap: 14px; }
html.force-tablet .story-read-area { padding: 28px 32px; }
html.force-tablet .story-vocab-sidebar { width: 230px; }
html.force-tablet .story-vocab-panel { padding: 16px; }
html.force-tablet .story-vocab-item { font-size: .8em; }
html.force-tablet #donePage .vocab-page, html.force-tablet #trainDonePage .vocab-page, html.force-tablet #basicLibraryPage .vocab-page{ padding-top: 52px; }
html.force-tablet #donePage, html.force-tablet #trainDonePage, html.force-tablet #basicLibraryPage, html.force-tablet #petPage{ padding-top: 52px; }
html.force-tablet #petPage { padding-top: 62px; }   html.force-tablet #donePage .vocab-page, html.force-tablet #trainDonePage .vocab-page, html.force-tablet #basicLibraryPage .vocab-page, html.force-tablet #petPage .vocab-page{ padding-top: 0; }
html.force-tablet .vocab-page { max-width: none; padding: 28px 20px; }
html.force-tablet .vp-toolbar button { font-size: .78em; padding: 7px 14px; }
html.force-tablet .ai-greet { right: 66px; bottom: 22px; max-width: 210px; font-size: .82em; padding: 14px 28px 14px 16px; }
html.force-tablet .popover { max-width: min(60vw, 340px); }
html.force-tablet .trans-overlay { max-width: 80vw; }
html.force-tablet .popover .dict-word { font-size: 1em; }
html.force-tablet .popover .dict-meaning { font-size: .85em; }
html.force-tablet .trans-overlay .trans-text { font-size: .88em; }
html.force-tablet .reading-picker { padding: 28px 32px; }
html.force-tablet .login-card { padding: 36px 30px; }
html.force-tablet .donate-card { padding: 24px 22px 20px; }
html.force-tablet .clear-modal { padding: 28px; }
html.force-tablet .annotate-toolbar { padding: 3px 8px; gap: 2px; }
html.force-tablet .annotate-toolbar button { width: 22px; height: 22px; }
html.force-tablet .annotate-toolbar .tool-size { height: 20px; min-width: 20px; font-size: .65em; }
html.force-tablet .annotate-toolbar .sep { margin: 0 2px; height: 14px; }
html.force-tablet .annotate-cursor.show { display: none; }

/* ── Force Mode: Phone (no media query - class driven) ── */
html.force-phone .home { padding: 60px 12px 94px; margin-bottom: -64px; }
html.force-phone .home h1 { font-size: 2em; }
html.force-phone .home-online { margin: 0 0 8px; font-size: .82em; gap: 6px; }
html.force-phone .cards { grid-template-columns: 1fr; max-width: 340px; gap: 14px; }
html.force-phone .cards.cards-exam { grid-template-columns: 1fr; max-width: 340px; gap: 14px; }
html.force-phone .card { padding: 24px 20px; }
html.force-phone .topbar { padding: 6px 10px; gap: 6px; overflow: visible; position: fixed; top: 0; left: 0; right: 0; z-index: 100; }
html.force-phone .topbar .info { font-size: .82em; max-width: 140px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
html.force-phone .topbar .btn:not(.back) { display: none !important; }
html.force-phone .topbar .auth-info { display: none !important; }
html.force-phone .radio-group { width: 170px; height: 32px; }
html.force-phone .radio-group:has(#storyHubRadio) { width: 190px; }
html.force-phone .radio-group .rg-slider { top: 3px; bottom: 3px; border-radius: 17px; }
html.force-phone .radio-label { font-size: 12px; padding: 0 10px; }
/* Phone: FAB compact */
html.force-phone .floating-annotate-btn { width: 44px; height: 44px; }
html.force-phone .floating-annotate-btn svg { width: 20px; height: 20px; }
/* 悬浮笔在手机上：4 列网格（原来 3 列）。色板浮层要跨满整行，否则会被挤成单列窄条。 */
html.force-phone .fab-toolbar { display: grid; grid-template-columns: repeat(4, 32px); gap: 2px; padding: 4px; right: 52px; top: 0; border-radius: 16px; }
html.force-phone .fab-toolbar .cp-wrap { grid-column: 1 / -1; }
html.force-phone .fab-toolbar .cp-panel { grid-template-columns: repeat(4, 32px); left: 0; }
html.force-phone .fab-toolbar .sep { display: none; }
html.force-phone .fab-toolbar .tool-size { border-radius: 6px; width: 32px; height: 32px; padding: 0; text-align: center; border: 1px solid var(--c-border); background: #F5F5F4; }
html.force-phone .fab-container { top: 80px; }

/* Phone: bottom tab bar */
.phone-tab-bar { display: none; position: fixed; bottom: 0; left: 0; right: 0; height: 56px; background: rgba(255,253,246,.94); backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px); border-top: 1px solid rgba(120,113,108,.08); z-index: 80; padding: 0 8px; justify-content: space-around; align-items: center; }
html.force-phone .phone-tab-bar { display: flex; }
.phone-tab-bar button { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; padding: 4px 10px; border-radius: 16px; font-size: .64em; font-weight: 500; background: transparent; color: var(--c-text-muted); transition: all .2s ease; border: none; min-width: 48px; }
.phone-tab-bar button svg { width: 20px; height: 20px; }
.phone-tab-bar button.active { color: var(--c-accent); }
.phone-tab-bar button.active::after { content: ''; position: absolute; bottom: 2px; width: 16px; height: 2px; background: var(--c-accent); border-radius: 1px; }
.phone-tab-bar button:active { transform: scale(.92); }

/* Phone: more sheet */
.phone-more-sheet { display: none; position: fixed; inset: 0; z-index: 200; }
.phone-more-sheet.show { display: block; }
.phone-more-backdrop { position: absolute; inset: 0; background: rgba(41,37,36,.35); animation: fadeIn .2s ease; }
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
.phone-more-panel { position: absolute; bottom: 0; left: 0; right: 0; background: var(--c-white); border-radius: 20px 20px 0 0; padding: 28px 20px 44px; box-shadow: 0 -4px 24px rgba(0,0,0,.08); animation: sheetUp .3s cubic-bezier(.32,.72,0,1); }
@keyframes sheetUp { from { transform: translateY(100%); } to { transform: translateY(0); } }
.phone-more-panel button { display: flex; align-items: center; gap: 12px; width: 100%; padding: 14px 16px; border-radius: var(--radius-md); font-size: .92em; font-weight: 500; background: transparent; color: var(--c-text); border: none; transition: all .15s ease; }
.phone-more-panel button:hover { background: #F5F0EB; }
.phone-more-panel button:active { background: #EDE5DC; }
html.force-phone .main-layout { flex-direction: column; padding: 12px; }
html.force-phone .reading-area { padding: 8px 0 20px; }
html.force-phone .reading-area .title { padding: 0 16px 10px; font-size: .95em; flex-wrap: wrap; row-gap: 8px; }
  html.force-phone .reading-area .title .rt-title-text { flex: 0 0 100%; }
  html.force-phone .guard-title-toggle .switch { transform: scale(.6); transform-origin: center; }
html.force-phone .reading-area .instruction { margin: 0 16px 16px; padding-left: 16px; font-size: .74em; }
html.force-phone .passage-body { padding: 0 16px; }
html.force-phone .passage-body p { font-size: calc(.92em * var(--rt-scale, 1)); }
html.force-phone .questions-section { padding: 16px 16px 0; padding-left: 16px; padding-right: 16px; }
html.force-phone .question-block { padding: 12px 14px; margin-bottom: 12px; }
html.force-phone .q-option { padding: 4px 10px; font-size: .85em; }
html.force-phone .q-stem { padding-left: 11px; }
html.force-phone .q-analyze-row { padding-left: 11px; }
html.force-phone .q-box { width: 22px; height: 22px; margin-top: 1px; }
html.force-phone .q-num { width: 22px; }
html.force-phone .vocab-sidebar { width: 100%; position: static; max-height: none; overflow: visible; }
html.force-phone .vocab-panel { position: static; padding: 14px; }
html.force-phone .vocab-panel h3 { font-size: .8em; }
html.force-phone .vocab-item { font-size: .76em; }
html.force-phone .bottom-section { padding: 0 12px 24px; }
html.force-phone .bottom-section h3 { font-size: .84em; }
html.force-phone .full-trans { padding: 16px 18px; font-size: .85em; }
html.force-phone .chat-layout { flex-direction: column; top: 52px; height: calc(100dvh - 52px); padding-top: 0; display: flex; }
html.force-phone .chat-sidebar { display: none; }
html.force-phone .chat-main { flex: 1; display: flex; flex-direction: column; min-height: 0; }
html.force-phone .chat-main .chat-container { flex: 1; min-height: 0; padding: 0 12px; max-width: none; height: 100%; display: flex; flex-direction: column; }
html.force-phone .chat-input-area { position: fixed; bottom: 0; left: 0; right: 0; background: var(--c-white); padding: 10px 12px; border-top: 1px solid rgba(120,113,108,.08); z-index: 10; margin-top: 0; }
html.force-phone .chat-input-area input { font-size: .85em; padding: 10px 14px; }
html.force-phone .chat-messages { padding-bottom: 60px; }
html.force-phone .chat-container { padding-bottom: 0; }
html.force-phone .chat-msg .bubble { max-width: 90%; font-size: .84em; }
html.force-phone .chat-quick { flex-wrap: nowrap; overflow-x: auto; padding-bottom: 4px; }
html.force-phone .chat-back-btn { bottom: 64px; }
html.force-phone .chat-suggests { padding-bottom: 6px; }
html.force-phone .sg-btn { padding: 6px 14px; font-size: .76em; }

/* Chat History Bottom Sheet (phone) */
.topbar .btn.chat-history-btn { display: none; }
html.force-desktop .topbar .btn.chat-history-btn { display: none !important; }
html.force-phone .topbar .btn.chat-history-btn { display: inline-flex !important; align-items: center; gap: 3px; padding: 3px 8px; font-size: .66em; height: 26px; }
html.force-phone .topbar .btn.chat-history-btn svg { width: 11px; height: 11px; }
.chat-sheet { position: fixed; inset: 0; z-index: 300; display: none; pointer-events: none; }
.chat-sheet.show { display: block; }
.chat-sheet .chat-sheet-backdrop { position: absolute; inset: 0; background: rgba(41,37,36,.35); pointer-events: auto; }
.chat-sheet .chat-sheet-panel { position: absolute; bottom: 0; left: 0; right: 0; background: var(--c-white); border-radius: 16px 16px 0 0; padding: 6px 12px 18px; box-shadow: 0 -4px 20px rgba(0,0,0,.08); animation: slideUp .25s cubic-bezier(.32,.72,0,1); pointer-events: auto; max-height: 65vh; display: flex; flex-direction: column; }
.chat-sheet .chat-sheet-handle { display: flex; justify-content: center; margin-bottom: 4px; }
.chat-sheet .chat-sheet-handle button { width: 32px; height: 20px; border: none; background: transparent; color: var(--c-text-muted); cursor: pointer; padding: 0; }
.chat-sheet .chat-sheet-head { font-family: 'Noto Serif SC', serif; font-size: .95em; font-weight: 700; color: var(--c-text); text-align: center; padding: 4px 0 12px; letter-spacing: .02em; }
.chat-sheet .chat-sheet-body { flex: 1; overflow-y: auto; }
.chat-sheet .chat-sheet-body .sidebar-head { padding: 0 0 10px; }
.chat-sheet .chat-sheet-body .sidebar-head button { width: 100%; padding: 9px; border-radius: 100px; font-size: .84em; font-weight: 600; background: var(--c-accent); color: var(--c-white); letter-spacing: .02em; }
.chat-sheet .chat-sheet-body .session-list { padding: 0; }
.chat-sheet .chat-sheet-body .session-item { padding: 11px 32px 11px 14px; }
html.force-phone .session-item { padding: 8px 24px 8px 10px; }
html.force-phone .story-hub-layout { flex-direction: column; height: auto; gap: 16px; padding: 20px 12px; padding-top: 68px; max-width: none; }
html.force-phone .story-hub-right { width: 100%; }
html.force-phone #storyReadLayout { flex-direction: column; padding: 12px; padding-top: 58px; }
html.force-phone .story-read-area { padding: 20px 16px; }
html.force-phone .story-bm-btn { left: -24px; top: 8px; }
html.force-phone .story-vocab-sidebar { width: 100%; position: static; max-height: none; overflow: visible; }
html.force-phone .story-vocab-panel { position: static; }
html.force-phone #donePage, html.force-phone #trainDonePage{ padding-top: 68px; }
html.force-phone #basicLibraryPage { padding-top: 68px; }
html.force-phone #petPage { padding-top: 68px; }
html.force-phone .vocab-page { max-width: none; padding: 20px 14px; }
html.force-phone #donePage .vocab-page, html.force-phone #trainDonePage .vocab-page, html.force-phone #basicLibraryPage .vocab-page, html.force-phone #petPage .vocab-page{ padding-top: 0; }
html.force-phone .vp-toolbar { gap: 6px; }
html.force-phone .vp-toolbar button { font-size: .74em; padding: 6px 10px; }
html.force-phone .ai-greet { right: 58px; bottom: 58px; max-width: 200px; font-size: .78em; }
html.force-phone .ai-greet::after { right: -7px; bottom: 35px; }
html.force-phone .ai-greet p { text-align: justify; }
html.force-phone #fbGreet { right: 58px !important; bottom: 123px !important; max-width: 200px; }
html.force-phone #fbGreet::after { right: -7px; bottom: 26px; }
html.force-phone .popover { max-width: min(80vw, 300px); }
html.force-phone .trans-overlay { max-width: 90vw; }
html.force-phone .trans-actions button { min-height: 44px; }
html.force-phone .annotate-toolbar { display: none !important; }
html.force-phone .annotate-cursor.show { display: none; }
.train-annotate-toolbar { position: sticky; top: 8px; margin: 0 0 12px; z-index: 6; }
html.force-tablet .train-annotate-toolbar, html.force-phone .train-annotate-toolbar { display: none !important; }
html.force-tablet .train-annotate-toolbar.show, html.force-phone .train-annotate-toolbar.show { display: flex !important; }
html.force-phone .train-annotate-toolbar { flex-wrap: wrap; justify-content: center; padding: 5px 10px; gap: 3px; }
html.dark .train-annotate-toolbar { background: #2A2623; border-color: #3F3A37; }

/* bottom spacing */
html.force-phone body { padding-bottom: 64px; }

/* 平板+手机模式：禁用原生复制菜单 */
html.force-tablet .reading-area, html.force-phone .reading-area,
html.force-tablet .story-read-area, html.force-phone .story-read-area,
html.force-tablet .train-sentence-text, html.force-phone .train-sentence-text { -webkit-touch-callout: none; }
#readingContent, #storyReadContent, .train-sentence-text { -webkit-user-select: text; user-select: text; -webkit-touch-callout: none; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* Basic Library */
.lib-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 16px; }
.lib-card { background: var(--c-white); border-radius: var(--radius-md); padding: 20px 24px; box-shadow: var(--shadow-sm); border: 1px solid var(--c-border); cursor: pointer; transition: all var(--transition-fast); position: relative; }
.lib-card:hover { box-shadow: var(--shadow-md); border-color: var(--c-accent); }
.lib-card h4 { font-size: .95em; font-weight: 600; color: var(--c-text); margin-bottom: 6px; }
.lib-card .diff { display: inline-block; padding: 2px 10px; border-radius: 100px; font-size: .72em; margin-top: 6px; font-weight: 500; }
.lib-card .lib-del { position: absolute; top: 8px; right: 10px; background: none; color: var(--c-border); font-size: 1.2em; padding: 2px 6px; border-radius: 4px; line-height: 1; }
.lib-card .lib-del:hover { color: var(--c-danger); background: #FBEDE8; }
.diff-easy { background: #DCE4D2; color: #3F5530; }
.diff-medium { background: #E9E0D4; color: #4A3229; }
.diff-hard { background: #F7DED6; color: #991B1B; }
.lib-empty { text-align: center; padding: 60px 20px; color: var(--c-text-muted); }

/* ── Enhanced Vocab / Library / Done Pages (paper editorial) ── */
.vocab-page { padding-top: 32px; }
.vocab-page h2 { font-family: 'Noto Serif SC', serif; font-size: 1.6em; font-weight: 700; color: #5C4033; letter-spacing: .02em; display: flex; align-items: center; gap: 10px; }
.vocab-page h2::before { content: ''; width: 4px; height: 22px; border-radius: 2px; background: linear-gradient(180deg, var(--c-accent), #E9E0D4); }
.vocab-page .vp-sub { font-family: 'Crimson Text', 'Noto Serif SC', serif; font-style: italic; color: var(--c-text-muted); font-size: .92em; margin: 4px 0 24px; padding-left: 14px; }
.vp-toolbar { gap: 10px; margin-bottom: 22px; }
.vp-toolbar button { padding: 9px 18px; border-radius: 100px; font-size: .82em; font-weight: 500; box-shadow: 0 1px 3px rgba(0,0,0,.03); transition: all .2s ease; }
.vp-btn-study { background: linear-gradient(135deg, var(--c-accent-deep), var(--c-accent-hover)); color: #fff; box-shadow: 0 2px 8px rgba(90,110,69,.25) !important; }
.vp-btn-study:hover { background: var(--c-accent-hover); transform: translateY(-1px); box-shadow: 0 4px 14px rgba(90,110,69,.35) !important; }
.vp-btn-outline { background: var(--c-bg-card); color: var(--c-text-secondary); border: 1px solid var(--c-border); }
.vp-btn-outline:hover { background: #F5EFE4; border-color: var(--c-accent-light); color: var(--c-accent); transform: translateY(-1px); }
/* ⚠️ 这一组必须写在上面那两行**之后**：`.vp-toolbar button{padding/border-radius}`（0,1,1）
   与 `.vp-btn-outline`（0,1,0）都在这里，写在前面会被它们盖掉（本文件里同权重后写者赢）。 */
.vp-toolbar button { padding: 8px 14px; border-radius: 9999px; }
.vp-toolbar .vp-btn-outline { background: none; border: 0; color: var(--c-text-secondary); }   /* 去掉"各自一块" */
.vp-toolbar .vp-btn-outline:hover { background: rgba(92,64,51,.08); border: 0; color: var(--c-text); transform: none; }
.vp-toolbar .vp-btn-outline:active { background: rgba(92,64,51,.14); }
html.dark .vp-toolbar .vp-btn-outline:hover { background: rgba(255,255,255,.1); color: #F5F5F4; }
html.dark .vp-toolbar .vp-btn-outline:active { background: rgba(255,255,255,.16); }
/* 计数（靠 margin-left:auto 顶到最右）与「不再提示 ?」留在同一条玻璃里，不另加底色 */
.vp-toolbar .vp-count { padding: 0 4px; }
.vp-toolbar .vp-noconfirm { margin-left: 2px; }
.vp-toolbar .vp-help { margin-left: 2px; }
@media (max-width: 768px) {
  .vp-toolbar { gap: 2px; width: fit-content; margin-left: auto; max-width: 100%; }
}
html.force-phone .vp-toolbar { gap: 2px; width: fit-content; margin-left: auto; max-width: 100%; }
/* ⚠️ 再压一次 gap：文件里 `.vp-toolbar{gap:10px}` 出现在上面这组之前，但**也在**我那句
   `gap:2px` 之后（L4052）——同权重后写者赢，所以这里必须再声明一次，否则组内间距还是 10px。 */
.vp-toolbar { gap: 2px; }
/* ⚠️ 2026-10-11 修（用户报「手机版生词本：+添加单词/导出 TXT/导入 TXT/遮挡所有释义/清除生词本 会重合」）：
   原因是这排的**胶囊造型**（`border-radius:9999px` + 玻璃底）是照**单行**设计的，而手机屏窄 → `flex-wrap:wrap`
   换行成 3 行，行间只有 2px、每行又被巨大圆角切着，几行按钮的字就贴在一起，看着像重合（实测几何不叠，
   但观感糊成一团）。手机档改成**单行横向滑动**：保持一行胶囊（造型回到设计意图），换行问题消失；
   `-webkit-overflow-scrolling:touch` 让 iOS 上滑动顺手；右侧留一点内边距，滚到底不贴边。
   ⚠️ 只改手机档（`html.force-phone` 与 ≤560px 的窄视口），平板/电脑一行放得下，一个像素不动。 */
html.force-phone .vp-toolbar { flex-wrap: nowrap; overflow-x: auto; overflow-y: hidden; max-width: 100%; width: 100%;
  margin-left: 0; scrollbar-width: none; -webkit-overflow-scrolling: touch; padding-right: 10px; }
html.force-phone .vp-toolbar::-webkit-scrollbar { height: 0; }
html.force-phone .vp-toolbar > * { flex: 0 0 auto; }
/* 「共 N 个单词」在单行里不再独占整行，而是跟在按钮后面（滑到最右能看到） */
html.force-phone .vp-toolbar .vp-count { flex: 0 0 auto; margin-left: 8px; text-align: left; }
@media (max-width: 560px) {
  .vp-toolbar { flex-wrap: nowrap; overflow-x: auto; overflow-y: hidden; max-width: 100%; width: 100%;
    margin-left: 0; scrollbar-width: none; -webkit-overflow-scrolling: touch; padding-right: 10px; }
  .vp-toolbar::-webkit-scrollbar { height: 0; }
  .vp-toolbar > * { flex: 0 0 auto; }
  .vp-toolbar .vp-count { flex: 0 0 auto; margin-left: 8px; text-align: left; }
}
/* ⚠️ 2026-10-11 用户要求「清除生词本挪到下面来」：
   横向滑动那排（`.vp-toolbar`）在手机档只保留 4 个常用动作，
   「清除生词本 / 共 N 个单词 / 不再提示 / ?」落到**下面一行**（这两个空的 `.vp-foot` 容器里）。
   实现方式是 **JS 搬迁**（`vpFootSync()`，见生词本那段脚本）：HTML 结构与改动前逐一相同，
   电脑/平板档容器恒空且 `display:none` → 大屏零影响。
   （试过用 CSS `display:contents` 让它们"浮回"那一行，实测电脑档会掉到第二行，已弃用。） */
.vp-foot { display: none; }
/* ⚠️ 阈值 768 必须与 CSS/JS 其余各处一致（`wsIsMobileNav()`、底部栏、顶栏吸附都用 768）。
   写成 560 会漏掉 561~768 宽的手机 → 表现就是"手机模式下这条没生效"（实测踩过）。 */
@media (max-width: 768px) {
  .vp-foot { display: flex; flex-direction: column; align-items: stretch; gap: 8px; }
  .vp-foot > * { flex: 0 0 auto; }
  .vp-foot .vocab-clear-all { width: 100%; justify-content: center; background: var(--c-bg-card);
    border: 1px solid #FECACA; border-radius: 9999px; color: var(--c-danger); }
  .vp-foot .vp-count { margin-left: 0; }
  /* 「不再提示 + ?」成组靠右并排：脚注是**纵向** flex，不包这一层它俩会各占一行，
     而且 `?` 的负边距会把它拉到左边（实测 `?` 跑到 x=184、而勾选框在 x=291）。 */
  .vp-foot .vp-right { display: flex; align-items: center; justify-content: flex-end; gap: 6px; margin-left: auto; }
  .vp-foot .vp-right .vp-noconfirm { margin-left: 0; }
  .vp-foot .vp-right .vp-help { margin-left: 0; }
}
/* 站内「手机档」按钮（与宽度判定可能不一致，例如宽屏强制手机预览）→ 同款规则兜一层 */
html.force-phone .vp-foot { display: flex; flex-direction: column; align-items: stretch; gap: 8px; }
html.force-phone .vp-foot > * { flex: 0 0 auto; }
html.force-phone .vp-foot .vocab-clear-all { width: 100%; justify-content: center; background: var(--c-bg-card);
  border: 1px solid #FECACA; border-radius: 9999px; color: var(--c-danger); }
html.force-phone .vp-foot .vp-count { margin-left: 0; }
html.force-phone .vp-foot .vp-right { display: flex; align-items: center; justify-content: flex-end; gap: 6px; margin-left: auto; }
html.force-phone .vp-foot .vp-right .vp-noconfirm { margin-left: 0; }
html.force-phone .vp-foot .vp-right .vp-help { margin-left: 0; }
.vp-btn-outline:active, .vp-btn-study:active { transform: translateY(0) scale(.97); }

/* Vocab list */
.vl-list { display: flex; flex-direction: column; border: 1px solid var(--c-border); border-radius: var(--radius-md); background: var(--c-bg-card); overflow: hidden; box-shadow: var(--shadow-sm); }
.vl-item { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 16px 20px; border-bottom: 1px solid #F0EFED; transition: background .15s ease; }
.vl-item:last-child { border-bottom: none; }
.vl-item:hover { background: #F5EFE4; }
.vl-item .vl-main { display: flex; align-items: baseline; gap: 12px; min-width: 0; flex: 1; flex-wrap: wrap; }
.vl-item .vl-word { font-family: 'Noto Serif SC', serif; font-size: 0.82em; font-weight: 600; color: var(--c-text); letter-spacing: .01em; flex-shrink: 0; }
.vl-sound { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; border-radius: 50%; border: 1px solid #5C4033; background: transparent; color: #5C4033; cursor: pointer; line-height: 0; flex-shrink: 0; transition: all .15s; vertical-align: middle; }
.vl-sound:hover { background: rgba(61,50,38,.06); }
.vl-sound:active { transform: scale(.9); }
.vl-item .vl-phonetic { font-size: .8em; color: var(--c-text-muted); font-family: system-ui, -apple-system, 'Segoe UI', 'Microsoft YaHei', sans-serif; flex-shrink: 0; }
.vl-item .vl-meaning { font-size: .88em; color: var(--c-text-secondary); line-height: 1.55; min-width: 0; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.vl-item .vl-del { background: none; border: none; color: var(--c-border); padding: 6px; border-radius: 6px; cursor: pointer; line-height: 0; flex-shrink: 0; opacity: 0; transition: all .15s ease; }
.vl-item:hover .vl-del { opacity: 1; }
.vl-item .vl-del svg { width: 16px; height: 16px; }
.vl-item .vl-del:hover { color: var(--c-danger); background: #FBEDE8; }
.vl-item .vl-del { opacity: 1; background: #F5F5F4; border: 1px solid #E7E5E4; border-radius: 50%; color: #A8A29E; padding: 5px; }
.vl-item .vl-del:hover { color: var(--c-danger); background: #FBEDE8; border-color: #FECACA; }
html.dark .vl-item .vl-del { opacity: 1; background: #332E2A; border-color: #3F3A37; color: #A8A29E; }
html.dark .vl-item .vl-del:hover { color: #E08B76; background: rgba(166,61,42,.15); border-color: rgba(224,139,118,.45); }

/* ── 已背词（2026-10-22 用户要求）：**一排词库切换** + 该词库的只读词表 ──
   切换条直接复用打字页那套 .ws-type-chip（同一套选中语言，暗色也已适配），只是左对齐并带计数 */
.ws-learned-sub { margin: 0 0 18px; font-size: .8em; color: var(--c-text-muted); }
.ws-learned-loading { padding: 48px 0; text-align: center; color: var(--c-text-muted); font-size: .86em; }
.ws-learned-tabs { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 18px; }
.ws-learned-tabs .ws-type-chip i { font-style: normal; margin-left: 7px; color: var(--c-text-muted); font-variant-numeric: tabular-nums; }
.ws-learned-tabs .ws-type-chip.sel i { color: inherit; opacity: .7; }
.ws-learned-extra { margin: 0 0 12px; font-size: .78em; color: var(--c-text-muted); }
.ws-learned-group { margin: 0 0 26px; }

/* ── Phrase Book ── */
/* ── Phrase Book (second floating card) ── */
.phrase-panel { margin-top: 20px; }
.phrase-sidebar-title { display: flex; align-items: center; gap: 8px; margin-bottom: 14px !important; }
.phrase-panel .vocab-list { max-height: 26vh; overflow-y: auto; }
.phrase-sidebar-item .w { color: var(--c-accent-deep); }
/* ── 右侧「生词本 / 词组本」合并面板（2026-09-28）────────────────────────────
   两块面板并成一块：顶部一个下拉切当前看哪一本（收起态 = 书名 + 数量），
   下面只保留一个列表区 + 一组操作键，「高亮」开关跟着当前那一栏换。
   ▸ 阴影（2026-09-28 重做）：卡片是 .vocab-sidebar（overflow-y:auto）的唯一子元素，
     原来那种「大范围外放大阴影」会被滚动容器裁掉，在卡片上方两角留下硬边（暗角）。
     现在只保留**一层**：向下偏移 + 负扩散（0 5px 14px -8px），阴影矩形内缩、
     不越出卡片左右边界，顶部更是完全不投影 —— 观感是「纸片压在桌面上」，不会再有暗角。
   ▸ 下拉配色：不用黄色（2026-09-28 用户要求），改走站内一贯的墨色纸感
     （纸白底 + 发丝边 + 墨字；展开态 = 纸灰底 + 墨色描边；选中项 = 纸灰底 + 勾）。 */
#readingPage .vocab-sidebar .vocab-panel.vt-merged {
  padding: 14px 12px 15px; min-height: 400px; display: flex; flex-direction: column;
  border: 1px solid #EAE4DA;
  box-shadow: 0 5px 14px -8px rgba(41,37,36,.18); }
@media (max-height: 720px) { #readingPage .vocab-sidebar .vocab-panel.vt-merged { min-height: 300px; } }
@media (max-width: 768px) { #readingPage .vocab-sidebar .vocab-panel.vt-merged { min-height: 320px; } }
html.dark #readingPage .vocab-sidebar .vocab-panel.vt-merged {
  border-color: #3A3532; box-shadow: 0 5px 14px -8px rgba(0,0,0,.6); }

/* 顶部：下拉 + 高亮开关 */
.vt-top { display: flex; align-items: center; gap: 6px; margin-bottom: 12px; flex-shrink: 0; }
.vt-dd { position: relative; flex: 1 1 auto; min-width: 0; }
.vt-dd-btn { width: 100%; height: 30px; padding: 0 8px 0 10px; cursor: pointer; box-sizing: border-box;
  display: flex; align-items: center; gap: 6px; font: inherit; font-size: .82em; font-weight: 700;
  color: #3F3A37; background: #FFFFFF; border: 1px solid #E4DDD1; border-radius: 10px;
  box-shadow: 0 1px 2px rgba(41,37,36,.04);
  transition: background .16s ease, border-color .16s ease, color .16s ease, box-shadow .16s ease; }
.vt-dd-btn:hover { background: #F8F5EF; border-color: #D8CFC0; }
.vt-dd .vt-dd-cur { flex: 1 1 auto; text-align: left; white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis; letter-spacing: .02em; }
.vt-dd .vt-dd-num { flex-shrink: 0; font-weight: 800; color: #8A8177; font-variant-numeric: tabular-nums; }
.vt-dd-btn svg { width: 13px; height: 13px; flex-shrink: 0; color: #A8A29E; transition: transform .18s ease; }
.vt-dd.open .vt-dd-btn { background: #F1ECE2; border-color: #57534E; color: #1A1A1A;
  box-shadow: 0 1px 2px rgba(41,37,36,.06); }
.vt-dd.open .vt-dd-btn svg { transform: rotate(180deg); color: #57534E; }
.vt-dd.open .vt-dd-num { color: #57534E; }
.vt-dd-menu { display: none; position: absolute; top: calc(100% + 6px); left: 0; right: 0; z-index: 70;
  padding: 4px; border: 1px solid #E4DDD1; border-radius: 11px; background: #FFFFFF;
  box-shadow: 0 6px 16px -8px rgba(41,37,36,.35), 0 2px 6px -2px rgba(41,37,36,.08); }
.vt-dd.open .vt-dd-menu { display: block; animation: rtDdIn .16s ease; }
.vt-dd-item { display: flex; align-items: center; gap: 6px; width: 100%; box-sizing: border-box;
  padding: 8px 9px; border: none; border-radius: 8px; background: none; cursor: pointer;
  font: inherit; font-size: .82em; font-weight: 600; color: #57534E; text-align: left;
  transition: background .14s ease, color .14s ease; }
.vt-dd-item:hover { background: #F8F5EF; color: #292524; }
.vt-dd-item.sel { background: #F1ECE2; color: #1A1A1A; font-weight: 800; }
.vt-dd-item .count { margin-left: auto; min-width: 0; height: auto; padding: 0; background: transparent;
  border: none; font-size: .95em; font-weight: 700; color: #A8A29E; font-variant-numeric: tabular-nums; }
.vt-dd-item.sel .count { color: #57534E; }
.vt-dd-item.sel::after { content: '\2713'; margin-left: 1px; font-size: .92em; font-weight: 800; color: #57534E; }
.vt-top .vocab-hl { flex-shrink: 0; }
.vt-top .vocab-hl .vocab-hl-bar { height: 22px; padding: 0 8px; font-size: .64em; font-weight: 600;
  gap: 4px; background: transparent; border: 1px solid #E7E5E4; color: #78716C; }
.vt-top .vocab-hl .vocab-hl-bar svg { width: 10px; height: 10px; }
.vt-top .vocab-hl:hover .vocab-hl-bar { background: #F7F1E4; }
.vt-top .vocab-hl input:checked + .vocab-hl-bar { background: #FEF3C7; border-color: rgba(217,119,6,.5);
  color: #A34909; box-shadow: 0 1px 3px rgba(217,119,6,.15); }
@media (max-width: 559px) {
  .vt-top { flex-wrap: wrap; }
  .vt-top .vocab-hl { flex: 1 1 100%; justify-content: flex-end; }
}

/* 列表区：撑满面板剩余高度（卡片因此"变长"，内容溢出时内部滚动） */
.vt-pane { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
.vt-pane.hidden { display: none; }
.vt-pane .vocab-list { flex: 1 1 auto; min-height: 0; max-height: none; overflow-y: auto; }
.vt-pane .vocab-actions { flex-shrink: 0; }
html.dark .vt-dd-btn { background: #2A2623; border-color: #3F3A37; color: #E7E5E4; box-shadow: none; }
html.dark .vt-dd-btn:hover { background: #332E2A; border-color: #4A443F; }
html.dark .vt-dd .vt-dd-num { color: #A8A29E; }
html.dark .vt-dd.open .vt-dd-btn { background: #332E2A; border-color: #6B6157; color: #FAFAF9; }
html.dark .vt-dd.open .vt-dd-num { color: #D6D3D1; }
html.dark .vt-dd-menu { background: #262220; border-color: #3F3A37;
  box-shadow: 0 8px 20px -8px rgba(0,0,0,.7); }
html.dark .vt-dd-item { color: #D6D3D1; }
html.dark .vt-dd-item:hover { background: #332E2A; color: #FAFAF9; }
html.dark .vt-dd-item.sel { background: #332E2A; color: #FAFAF9; }
html.dark .vt-dd-item .count { color: #78716C; }
html.dark .vt-dd-item.sel .count, html.dark .vt-dd-item.sel::after { color: #E7E5E4; }
html.dark .vt-top .vocab-hl .vocab-hl-bar { background: transparent; border-color: #3F3A37; color: #A8A29E; }
html.dark .vt-top .vocab-hl:hover .vocab-hl-bar { background: #332E2A; }
html.dark .vt-top .vocab-hl input:checked + .vocab-hl-bar { background: #443018; color: #FCD9A8;
  border-color: var(--c-accent); box-shadow: 0 1px 3px rgba(0,0,0,.35); }
/* ── 题目 / 训练两页的「页面内返回键」在桌面档收掉（2026-10-07）────────────────
   这两页的 `.topbar` 只装了一颗返回键，`position: sticky; top: 12px` → 实际落在 y≈16，
   而全站一级导航是 **fixed、高 65px**（z-50 > topbar 的 z-10）→ 桌面上这颗键被压在导航下面，
   elementFromPoint 命中的是导航项「题目训练」（实测：点了等于跳题目训练，看起来像"返回跳错页"）。
   做法：宽屏（且非强制手机/平板）与强制桌面档 收掉这颗**重复**的键 ——
   一级导航左上角本来就有一颗同款返回键（可点，走 backStop()/backOneLevel() 只退一级），
   同时用 padding-top 补回它原来占的 64px，页面内容位置一个像素都不动。
   手机/平板档保持原样（那边它是可点的，且是主要返回入口）。 */
@media (min-width: 769px) {
  html:not(.force-phone):not(.force-tablet) #donePage .topbar,
  html:not(.force-phone):not(.force-tablet) #trainDonePage .topbar { display: none; }
  html:not(.force-phone):not(.force-tablet) #donePage,
  html:not(.force-phone):not(.force-tablet) #trainDonePage { padding-top: 64px; }
}
html.force-desktop #donePage .topbar, html.force-desktop #trainDonePage .topbar { display: none; }
html.force-desktop #donePage, html.force-desktop #trainDonePage { padding-top: 64px; }

/* ── 已做题目页：两级分类（科目 → 题型）2026-09-28 用户要求 ──────────────────
   一级「考研英语 / 高考英语 / 大学英语 / 其它」用纸感大标题 + 右侧计数胶囊，
   二级「传统阅读 / 完形填空 / …」用铅笔灰字距小标题 + 左侧短竖条；
   组与组之间一条发丝分隔线，题型之间靠留白区分。 */
.done-sections { display: block; }
.done-sec + .done-sec { margin-top: 30px; padding-top: 24px; border-top: 1px solid var(--c-border); }
.done-exam { display: flex; align-items: center; gap: 9px; margin: 0 0 16px;
  font-family: 'Noto Serif SC', serif; font-size: 1.06em; font-weight: 700; color: var(--c-text); letter-spacing: .02em; }
.done-sec-n { display: inline-flex; align-items: center; justify-content: center; min-width: 22px;
  height: 20px; padding: 0 7px; border-radius: 99px; font-family: inherit;
  font-size: .66em; font-weight: 700; letter-spacing: 0;
  color: #8A8177; background: #F5F1E8; border: 1px solid #E8E2D6; }
.done-qtype { display: flex; align-items: center; gap: 7px; margin: 20px 0 10px;
  font-size: .82em; font-weight: 800; letter-spacing: .08em; color: #8A8177; }
.done-qtype::before { content: ''; width: 3px; height: 12px; border-radius: 2px; background: #D8CFC0; }
.done-sec .done-qtype:first-of-type { margin-top: 0; }
.done-sec .lib-grid { margin-bottom: 4px; }
/* ── 已做题目：横条（2026-10-01 用户要求「卡片改成横条」）────────────────────────
   只作用于 #donePage 的这一列，站内共用的 .lib-grid / .lib-card 一点没碰；
   配色沿用站内 token 与 .lib-score 的三档色（≥80 绿 / ≥60 黄 / 其余红）。 */
.done-rows { display: flex; flex-direction: column; gap: 8px; }
.done-row { display: flex; align-items: center; gap: 12px; padding: 11px 14px;
  border: 1px solid var(--c-border); border-radius: var(--radius-md); background: var(--c-bg-card);
  cursor: pointer; transition: border-color .18s, translate .18s, box-shadow .18s; }
.done-row:hover { border-color: var(--c-accent); translate: 0 -1px; box-shadow: 0 4px 14px rgba(0,0,0,.06); }
.done-row:focus-visible { outline: 2px solid var(--c-accent); outline-offset: 2px; }
.done-row-ic { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; border-radius: 8px; color: var(--c-accent-deep);
  background: color-mix(in srgb, var(--c-accent) 12%, transparent); }
.done-row-ic svg { width: 15px; height: 15px; }
.done-row-title { flex: 1 1 auto; min-width: 0; font-size: .94em; font-weight: 600; color: var(--c-text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.done-row .lib-score { flex: 0 0 auto; }
.done-row-date { flex: 0 0 auto; font-size: .76em; color: var(--c-text-muted); }
.done-row-del { flex: 0 0 auto; width: 24px; height: 24px; padding: 0; border: 0; border-radius: 50%;
  background: transparent; color: var(--c-text-muted); font-size: 1.05em; line-height: 1; cursor: pointer; }
.done-row-del:hover { background: color-mix(in srgb, #B91C1C 12%, transparent); color: #B91C1C; }
@media (max-width: 600px) {
  /* 窄屏：图标 + 标题占第一行，正确率/时间/删除落到第二行（别让图标独占一行白白多出一行） */
  .done-row { flex-wrap: wrap; gap: 6px 10px; padding: 10px 12px; }
  .done-row-title { flex: 1 1 auto; white-space: normal; }
  .done-row .lib-score { order: 3; }
  .done-row-date { order: 4; margin-left: auto; }
  .done-row-del { order: 5; }
}
html.dark .done-sec-n { background: #2A2623; border-color: #3F3A37; color: #A8A29E; }

/* ── 「保存题目」的查找工具 + 行样式重排（2026-11-02）───────────────────────── */
.done-tools { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 0 0 16px;
  padding: 10px 12px; border-radius: 16px; border: 1px solid var(--c-border);
  background: color-mix(in srgb, var(--c-accent) 4%, var(--c-bg-card)); }
html.dark .done-tools { background: color-mix(in srgb, #E0C07C 5%, #221F1B); }
/* 顶上的总览行（📚 共 N 条 · 🎯 平均 x%） */
#doneCount b { font-family: 'Noto Serif SC', serif; font-size: 1.06em; color: var(--c-text); }
#doneCount { font-size: .8em; }
.done-search { position: relative; flex: 1 1 240px; min-width: 0; }
.done-search-ic { position: absolute; left: 11px; top: 50%; width: 15px; height: 15px; translate: 0 -50%;
  color: var(--c-text-muted); pointer-events: none; }
.done-search input { width: 100%; height: 36px; padding: 0 32px 0 33px; border-radius: 999px;
  border: 1px solid var(--c-border); background: var(--c-bg-card); color: var(--c-text);
  font: inherit; font-size: .84em; }
.done-search input::placeholder { color: var(--c-text-muted); }
.done-search input:focus { outline: none; border-color: var(--c-accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--c-accent) 16%, transparent); }
.done-search input::-webkit-search-cancel-button { display: none; }
.done-search-x { position: absolute; right: 6px; top: 50%; translate: 0 -50%; width: 22px; height: 22px;
  border: 0; border-radius: 50%; background: transparent; color: var(--c-text-muted); font-size: 1em;
  line-height: 1; cursor: pointer; }
.done-search-x:hover { background: color-mix(in srgb, var(--c-text) 8%, transparent); color: var(--c-text); }
.done-chips { display: flex; flex-wrap: wrap; gap: 6px; min-width: 0; }
.done-filter-toggle { display: none; }
.done-chips-lab { align-self: center; margin-right: 2px; font-size: .68em; letter-spacing: .04em; color: var(--c-text-muted); }
.done-chip { display: inline-flex; align-items: center; gap: 5px; height: 28px; padding: 0 10px;
  border-radius: 999px; border: 1px solid var(--c-border); background: transparent; color: var(--c-text-secondary);
  font: inherit; font-size: .74em; cursor: pointer; white-space: nowrap; }
.done-chip i { font-style: normal; font-size: 1.02em; line-height: 1; }
.done-chip span { font-size: .92em; color: var(--c-text-muted); font-variant-numeric: tabular-nums; }
.done-chip:hover { border-color: var(--c-accent); color: var(--c-text); }
.done-chip.on { background: color-mix(in srgb, var(--c-accent) 16%, transparent); border-color: var(--c-accent);
  color: var(--c-accent-deep); font-weight: 600; }
.done-chip.on span { color: var(--c-accent-deep); }
.done-sort { margin-left: auto; display: inline-flex; align-items: center; gap: 6px; font-size: .74em; color: var(--c-text-muted); }
.done-sort select { height: 30px; padding: 0 6px; border-radius: 9px; border: 1px solid var(--c-border);
  background: var(--c-bg-card); color: var(--c-text); font: inherit; font-size: 1em; cursor: pointer; }
html.dark .done-chip.on { background: color-mix(in srgb, #E0C07C 18%, transparent); color: #F0E2C4; border-color: #C9A968; }

/* 行内重排：标题 + 副标题两行，右侧分数/日期/删除 */
.done-row { border-radius: 15px; padding: 12px 15px; }
.done-row-ic { width: 34px; height: 34px; border-radius: 11px; font-size: 17px; line-height: 1;
  background: linear-gradient(145deg, color-mix(in srgb, var(--c-accent) 14%, transparent),
              color-mix(in srgb, var(--c-accent) 6%, transparent)); }
.done-row-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.done-row-main .done-row-title { display: block; font-size: .96em; }
.done-row-sub { display: flex; align-items: center; gap: 8px; font-size: .72em; color: var(--c-text-muted);
  white-space: nowrap; overflow: hidden; }
.done-score { flex: 0 0 auto; display: inline-flex; align-items: baseline; gap: 4px; padding: 3px 10px;
  border-radius: 999px; font-size: .74em; font-weight: 600; font-variant-numeric: tabular-nums; }
.done-score i { font-style: normal; font-size: .95em; line-height: 1; }
.done-score em { font-style: normal; font-size: .92em; opacity: .8; }
.done-row-del { opacity: .45; transition: opacity .15s, background .15s, color .15s; }
.done-row:hover .done-row-del, .done-row-del:focus-visible { opacity: 1; }
/* 分组标题的表情（真题 / 科目 / 题型） */
.done-exam i, .done-qtype i { font-style: normal; font-size: 1.06em; line-height: 1; }
.done-nomatch { padding: 44px 16px; text-align: center; border: 1px dashed var(--c-border); border-radius: var(--radius-md); }
.done-nomatch-em { display: block; font-size: 30px; line-height: 1; margin-bottom: 8px; }
.done-nomatch b { display: block; font-size: .94em; color: var(--c-text); }
.done-nomatch span { display: block; margin: 6px 0 14px; font-size: .78em; color: var(--c-text-muted); }
.done-nomatch-btn { height: 34px; padding: 0 16px; border-radius: 10px; cursor: pointer; font: inherit;
  font-size: .8em; font-weight: 600; color: var(--c-accent-deep); background: color-mix(in srgb, var(--c-accent) 12%, transparent);
  border: 1px solid var(--c-accent); }
.done-nomatch-btn:hover { background: color-mix(in srgb, var(--c-accent) 20%, transparent); }

@media (max-width: 600px) {
  .done-tools { gap: 8px; }
  .done-search { flex: 1 1 100%; }
  /* 手机档：筛选默认收起（两排 chips 太占首屏），点「筛选」再展开；生效条数写在按钮上 */
  .done-filter-toggle { display: inline-flex; align-items: center; height: 30px; padding: 0 12px;
    border-radius: 999px; border: 1px solid var(--c-border); background: transparent;
    font: inherit; font-size: .74em; color: var(--c-text-secondary); cursor: pointer; }
  .done-filter-toggle.on { border-color: var(--c-accent); color: var(--c-accent-deep);
    background: color-mix(in srgb, var(--c-accent) 14%, transparent); font-weight: 600; }
  .done-tools .done-chips { display: none; }
  .done-tools.filters-open .done-chips { display: flex; }
  .done-sort { margin-left: auto; flex: 0 0 auto; }
  .done-row-main { flex: 1 1 calc(100% - 50px); }   /* 图标 34 + gap 10 之后还剩的宽度：够标题一行，分数/日期自然落到第二行 */
  .done-row-sub { white-space: normal; }
  .done-score { order: 3; }
  .done-row-date { order: 4; }
  .done-row-del { order: 5; }
}
html.dark .done-qtype { color: #A8A29E; }
html.dark .done-qtype::before { background: #4A443F; }
/* ── 「题目训练 → 我的」已做真题 / 已做精读：横栏（2026-10-06 用户要求）──────────────
   复用上面那套 .done-row（横向长条，一条一条），只是栏目换成新的一排字段格：
   考试+年份 / 题型（或 篇号 / 题号 / 题型）/ 正确率或状态 / 最右作答日期。 */
.tr-rows { display: flex; flex-direction: column; gap: 8px; }
.tr-cell { flex: 0 0 auto; font-size: .82em; color: var(--c-text-secondary); white-space: nowrap; }
.tr-cell-a { font-weight: 600; color: var(--c-text); }
.tr-cell-b { padding: 2px 9px; border-radius: 100px; font-size: .74em; font-weight: 600; color: var(--c-accent-deep);
  background: color-mix(in srgb, var(--c-accent) 12%, transparent); }
.tr-cell-c { padding: 2px 9px; border: 1px dashed var(--c-border); border-radius: 100px; font-size: .74em; color: var(--c-text-muted); }
.tr-row-spacer { flex: 1 1 auto; min-width: 0; }
@media (max-width: 600px) {
  /* 窄屏：字段换到第二行，日期仍靠右（与 .done-row 的窄屏规则配套） */
  .tr-rows .done-row { flex-wrap: wrap; gap: 6px 10px; }
  .tr-rows .done-row-date { order: 9; margin-left: auto; }
  .tr-rows .done-row-del { order: 10; }
}
html.dark .tr-cell-b { background: color-mix(in srgb, var(--c-accent) 20%, transparent); color: #D6D3D1; }
/* ── 完整试卷：长卷（七大题竖向连排）+ 右栏「题目」面板（2026-09-28）────────── */
.pp-hint { margin-left: auto; font-size: .74em; color: var(--c-text-muted); }
.pp-sec { margin: 0; padding: 0 0 20px; }
.pp-sec + .pp-sec { margin-top: 30px; padding-top: 26px; border-top: 1px dashed var(--c-border); }
.pp-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin: 0 0 18px;
  font-family: 'Noto Serif SC', serif; }
.pp-no { font-size: .72em; font-weight: 700; letter-spacing: .1em; color: #A8A29E; white-space: nowrap; }
.pp-name { font-size: 1.1em; font-weight: 800; color: var(--c-text); }
.pp-range { font-size: .72em; font-weight: 600; color: #8A8177; border: 1px solid #E8E2D6;
  border-radius: 99px; padding: 1px 9px; white-space: nowrap; }
.pp-sec .questions-section { margin-top: 22px; }
/* 右栏「题目」面板 */
.pp-panel { padding: 14px 12px 15px; min-height: 400px; display: flex; flex-direction: column;
  border-color: #EDE8DF; box-shadow: 0 5px 14px -8px rgba(41,37,36,.18); }
.pp-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 12px; }
.pp-title { font-size: .86em; font-weight: 800; color: #3F3A37; letter-spacing: .02em; }
.pp-prog { font-size: .74em; font-weight: 700; color: #8A8177; font-variant-numeric: tabular-nums; }
/* 答题卡上的「AI 批改并算分」（2026-10-13）：窄栏里整行铺满、够大好点；
   配色与站内 .cloze-bar .cbtn.primary 同族（强调色填充 + 白字）。 */
.pp-grade { margin: 12px 0 0; }
.pp-grade-btn { box-sizing: border-box; width: 100%; padding: 9px 10px; font: inherit; font-size: .8em;
  font-weight: 700; cursor: pointer; border: 1px solid var(--c-accent); border-radius: 99px;
  background: var(--c-accent); color: var(--c-white); transition: background .18s, translate .18s; }
.pp-grade-btn:hover { background: var(--c-accent-hover); translate: 0 -1px; }
.pp-grade-btn:disabled { opacity: .55; cursor: default; translate: 0; }
html.dark .pp-grade-btn { color: #1C1917; }
.pp-biglist { display: flex; flex-direction: column; gap: 2px; margin-bottom: 12px;
  padding-bottom: 12px; border-bottom: 1px solid #F0EBE1; }
.pp-big { display: flex; align-items: center; gap: 6px; width: 100%; box-sizing: border-box;
  padding: 6px 7px; border: none; border-radius: 8px; background: none; cursor: pointer;
  font: inherit; font-size: .78em; font-weight: 600; color: #57534E; text-align: left;
  transition: background .14s ease, color .14s ease; }
.pp-big:hover { background: #F8F5EF; color: #292524; }
.pp-big.cur { background: #F1ECE2; color: #1A1A1A; font-weight: 800; }
.pp-bi { flex-shrink: 0; width: 15px; font-size: .9em; font-weight: 800; color: #C4BAA8; text-align: center; }
.pp-big.cur .pp-bi { color: #8A8177; }
.pp-bname { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pp-bn { flex-shrink: 0; font-size: .92em; font-weight: 700; color: #A8A29E; font-variant-numeric: tabular-nums; }
.pp-big.done .pp-bn { color: #15803D; }
.pp-card { display: flex; flex-direction: column; gap: 8px; overflow-y: auto; }
/* ⑩ 答题卡改 5 列网格（2026-09-28 用户要求「好看规整」）：
   整卷题号刚好都能被 5 整除（1–20 / 21–25 / 26–30 / 31–35 / 36–40 / 41–45 / 46–50），
   所以每行固定 5 格 → 行右边缘齐平，不再出现"最后一行只剩一两格"的参差。 */
.pp-cardrow { display: grid; grid-template-columns: 15px repeat(5, 1fr); gap: 5px; align-items: center; }
.pp-cardlab { width: auto; text-align: left; padding-left: 1px; }
.pp-cardrow { display: flex; align-items: center; gap: 5px; flex-wrap: wrap; }
.pp-cardlab { flex-shrink: 0; width: 15px; font-size: .7em; font-weight: 800; color: #C4BAA8; text-align: center; }
.pp-chip { width: 100%; box-sizing: border-box; height: 24px; padding: 0; border-radius: 6px; cursor: pointer;
  border: 1px solid #E7E5E4; background: #FFFFFF; color: #78716C;
  font: inherit; font-size: .72em; font-weight: 700; font-variant-numeric: tabular-nums;
  display: inline-flex; align-items: center; justify-content: center;
  transition: background .14s ease, border-color .14s ease, color .14s ease; }
.pp-chip:hover { border-color: #D8CFC0; background: #F8F5EF; }
.pp-chip.done { background: #F1ECE2; border-color: #C9BFAC; color: #1A1A1A; }
.pp-chip.right { background: #E9F5EC; border-color: #A7D7B0; color: #15803D; }
.pp-chip.wrong { background: #FDECEC; border-color: #F3B9B9; color: #B91C1C; }
.pp-chip.wide { grid-column: span 5; padding: 0 9px; }
html.dark .pp-no, html.dark .pp-range, html.dark .pp-prog, html.dark .pp-bn { color: #A8A29E; }
html.dark .pp-range { border-color: #3F3A37; }
html.dark .pp-panel { border-color: #3A3532; box-shadow: 0 5px 14px -8px rgba(0,0,0,.6); }
html.dark .pp-title { color: #E7E5E4; }
html.dark .pp-biglist { border-bottom-color: #332E2A; }
html.dark .pp-big { color: #D6D3D1; }
html.dark .pp-big:hover { background: #332E2A; color: #FAFAF9; }
html.dark .pp-big.cur { background: #332E2A; color: #FAFAF9; }
html.dark .pp-chip { background: #2A2623; border-color: #3F3A37; color: #A8A29E; }
html.dark .pp-chip:hover { background: #332E2A; border-color: #4A443F; }
html.dark .pp-chip.done { background: #332E2A; border-color: #57534E; color: #FAFAF9; }
html.dark .pp-chip.right { background: #17301E; border-color: #2F5D3C; color: #86EFAC; }
html.dark .pp-chip.wrong { background: #351D1D; border-color: #6B3333; color: #FCA5A5; }
/* ── 完整试卷：对齐与节奏（2026-09-28 用户确认的 5 条）────────────────────────
   只修「两套左边界 / 三套圆角 / 缺呼吸」，**不动**栏宽、字号、字体、配色、段头排版。
   基线实测：正文与卡片 x=65 w=1046；题目区与完形进度条原来内缩到 x=105（差 40px）；
   段头原来在 x=25（比正文外凸 40px）；圆角 10 / 18 / 0-10 三套。 */
/* ① 段头已挪进 .passage-body（跟随正文内边距），这里只定它与内容的间距 */
.pp-sec .pp-head { margin: 0 0 20px; }
/* ⑧ 段头字号对调（2026-09-28 用户要求）：英文（Section I / Section II · Part A）大、汉字（完形填空…）小 */
.pp-sec .pp-no { font-size: .96em; font-weight: 800; letter-spacing: .12em; color: var(--c-accent-deep); }
.pp-sec .pp-name { font-size: .88em; font-weight: 600; letter-spacing: .04em; color: #8A8178; }
html.dark .pp-sec .pp-name { color: #A8A29E; }
/* ② 题目区与完形进度条取消额外内缩 → 与正文同一条左/右边界 */
.pp-sec .questions-section { padding-left: 0; padding-right: 0; }
/* ⑨ 阅读理解题目区收小（2026-09-28 用户要求）：块内边距/题距/字号整体降一档 */
.pp-sec .questions-section { padding-top: 18px; }
.pp-sec .questions-section h3 { font-size: .78em; }
.pp-sec .question-block { padding: 12px 14px; margin-bottom: 10px; }
.pp-sec .q-stem, .pp-sec .q-option { font-size: .95em; }
.pp-sec .q-option { padding: 4px 10px; gap: 7px; }
.pp-sec .q-option .q-box { width: 21px; height: 21px; }
.pp-sec .q-my-ans { font-size: .82em; margin-top: 6px; }
.pp-sec .q-analyze-row { margin-top: 8px; }
.pp-sec .cloze-bar, .pp-sec .cloze-tip { margin-left: 0; margin-right: 0; }
/* ⑥ 题目区/卡片现在也在 .passage-body 里 → 站内 .passage-body p 的首行缩进与两端对齐会漏进来
   （选项里那个字母 span 会继承 text-indent:2em 被撑宽、挤出方格）。这里按题面该有的样子还原：
   题干与选项左对齐、不缩进；译文/范文/提示同理（与各自的单页版式一致）。 */
.pp-sec .questions-section p, .pp-sec .cloze-tip, .pp-sec .tr-card p,
.pp-sec .tr-box p, .pp-sec .bg-cap-tip { text-indent: 0; text-align: left; }
/* ③ 卡片圆角统一 12px（输入框保持 10px） */
.pp-sec .question-block, .pp-sec .cloze-bar, .pp-sec .tr-card, .pp-sec .bg-fig { border-radius: 12px; }
/* ④ 段落呼吸：正文段间距 12px；正文与进度条之间 32px */
.pp-sec .passage-body > p { margin: 0 0 12px; }
.pp-sec .cloze-bar { margin-top: 32px; }
/* ⑦ 完形进度条原本是 sticky 吸底（z-index 60 > 顶栏 10），在长卷里会飘上来盖住顶栏；
   整卷是一路往下读的，吸底没意义 → 回到「完形正文末尾」的静态位置（2026-09-28 用户反馈）。 */
.pp-sec .cloze-bar { position: static; top: auto; bottom: auto; z-index: auto; }
/* ⑤ 段与段固定留白 48px（保留原虚线分隔）；跳转锚点让开悬浮工具条 */
.pp-sec .questions-section .question-block:last-child { margin-bottom: 0; }  /* 末题的下外边距不再算进段间留白 */
.pp-sec + .pp-sec { margin-top: 22px; padding-top: 14px; }   /* 段间留白收小（2026-09-28 用户反馈：原来 48+22 太空） */
.pp-sec { scroll-margin-top: 92px; }
.pp-sec .question-block { scroll-margin-top: 116px; }

/* ⑩-2 答题卡网格：必须带 .pp-panel 前缀 —— 原块里的 `.pp-cardrow{display:flex;flex-wrap:wrap}` 在它后面，
   同级选择器会压过它（上次就是被这条吃掉了，量到 chipW 仍 9/16px）。 */
.pp-panel .pp-cardrow { display: flex; gap: 5px; align-items: flex-start; }
/* 题号区固定 5 列网格：1–20 四行、21–25/41–45/46–50 各一行，每行右边缘齐平；
   标签在网格**外面**（固定 15px 左列），所以不会把首行挤宽、也不会被题号占用格子。 */
.pp-panel .pp-chips { flex: 1 1 auto; min-width: 0; display: grid; grid-template-columns: repeat(5, 1fr); gap: 5px; }
.pp-panel .pp-chips .pp-chip { width: 100%; flex: none; }
.pp-panel .pp-chips .pp-chip.wide { grid-column: 1 / -1; }
/* ⑪ 汇总区段头与锁提示的版式（2026-09-28 用户反馈「格式很差」）：
   段头与正文段头**同格式**（Answers ｜ 答案与解析 ｜ 1–45 题），
   不再单独改字号/颜色；锁提示收成 560px 居中的两行小卡，不拉满整行。 */
.pp-ans .pa-lock { max-width: 560px; margin: 0 auto; padding: 18px 20px; text-align: center;
  border: 1px solid var(--c-border); border-radius: 12px; background: #FBF8F2; font-size: .9em; line-height: 1.8; }
.pp-ans .pa-lock .pa-lock-h { display: block; font-weight: 800; color: var(--c-text); font-size: 1.04em; margin-bottom: 3px; }
.pp-ans .pa-lock .pa-lock-s { display: block; color: #8A8177; font-size: .94em; }
.pp-ans .pa-lock .pa-lock-s b { color: #A34909; font-weight: 800; }
html.dark .pp-ans .pa-lock .pa-lock-h { color: #FAFAF9; }

/* ── 完整试卷：答案与解析汇总区（2026-09-28 用户要求）────────────────────── */
.pp-ans .pa-group + .pa-group { margin-top: 26px; }
.pp-ans .pa-ghead { display: flex; align-items: baseline; gap: 10px; margin: 0 0 8px;
  font-family: 'Noto Serif SC', serif; font-size: .98em; font-weight: 800; color: var(--c-text); }
.pp-ans .pa-grange { font-size: .72em; font-weight: 600; color: #8A8178; }
.pp-ans .pa-gscore { margin-left: auto; font-size: .78em; font-weight: 700; color: #8A8177; font-variant-numeric: tabular-nums; }
.pp-ans .pa-row { display: flex; align-items: center; gap: 10px; padding: 7px 10px; border-radius: 8px; }
.pp-ans .pa-row:nth-of-type(odd) { background: #FCFAF6; }
.pp-ans .pa-num { width: 26px; text-align: right; font-weight: 800; color: #8A8177; font-variant-numeric: tabular-nums; }
.pp-ans .pa-mine, .pp-ans .pa-corr { min-width: 44px; font-weight: 700; }
.pp-ans .pa-corr { color: #15803D; }
.pp-ans .pa-flag { width: 14px; font-weight: 800; }
.pp-ans .pa-row.ok .pa-flag { color: #15803D; }
.pp-ans .pa-row.bad .pa-flag { color: #B91C1C; }
.pp-ans .pa-ana-btn { margin-left: auto; font: inherit; font-size: .78em; font-weight: 600; cursor: pointer;
  padding: 3px 12px; border-radius: 99px; border: 1px solid #E7E5E4; background: #FFFFFF; color: #57534E;
  transition: background .14s ease, border-color .14s ease; }
.pp-ans .pa-ana-btn:hover { background: #F8F5EF; border-color: #D8CFC0; }
.pp-ans .pa-res:not(:empty) { margin: 4px 0 12px 36px; padding: 12px 14px; border-radius: 10px;
  background: color-mix(in srgb, var(--c-accent) 5%, var(--c-white));
  border-left: 3px solid color-mix(in srgb, var(--c-accent) 40%, transparent); font-size: .92em; line-height: 1.8; }
.pp-ans .pa-loading { color: #8A8177; font-size: .86em; }
/* 三段各自的答案入口在完整试卷里隐藏（答案只从这个汇总区看） */
/* ⑬ 完整试卷：删掉完形段自己那条「已答 N / 20 · 重做 · 查看答案」与下方提示
   （2026-09-28 用户要求）——整卷进度与「查看答案」已统一在最下方的 Answers 区，
   这里再放一条重复且会诱导提前看答案。元素保留在 DOM 里（只是不显示），
   clozeSyncBlanks() 仍能正常更新它，不会报错。 */
.pp-sec #clozeBar, .pp-sec #clozeTip,
.pp-sec #ntBar, .pp-sec .nt-tip { display: none; }
.pp-sec #clozeBar .cbtn.primary { display: none; }   /* 只藏完形段自己那条；汇总区的 #ppAnsBar 要留着 */
/* ⑫ 阅读选项的对错标记（只在「查看答案」后出现，2026-09-28 用户要求） */
.pp-sec .q-option.opt-right { border-color: #A7D7B0; }
.pp-sec .q-option.opt-right::before { background: #EDF7F0; }
.pp-sec .q-option.opt-right .q-box { border-color: #15803D; color: #15803D; background: #E9F5EC; }
.pp-sec .q-option.opt-right .q-opt-text { color: #15803D; }
.pp-sec .q-option.opt-wrong { border-color: #F0B4B4; }
.pp-sec .q-option.opt-wrong::before { background: #FDECEC; }
.pp-sec .q-option.opt-wrong .q-box { border-color: #B91C1C; color: #B91C1C; background: #FBE7E7; }
.pp-sec .q-option.opt-wrong .q-opt-text { color: #B91C1C; }
html.dark .pp-sec .q-option.opt-right { border-color: #2F5D3C; }
html.dark .pp-sec .q-option.opt-right::before { background: #17301E; }
html.dark .pp-sec .q-option.opt-right .q-box { border-color: #4ADE80; color: #86EFAC; background: #17301E; }
html.dark .pp-sec .q-option.opt-right .q-opt-text { color: #86EFAC; }
html.dark .pp-sec .q-option.opt-wrong { border-color: #6B3333; }
html.dark .pp-sec .q-option.opt-wrong::before { background: #351D1D; }
html.dark .pp-sec .q-option.opt-wrong .q-box { border-color: #F87171; color: #FCA5A5; background: #351D1D; }
html.dark .pp-sec .q-option.opt-wrong .q-opt-text { color: #FCA5A5; }
/* ── 退出前的保存询问弹窗（2026-09-28）────────────────────────────────────── */
#saveAskModal { position: fixed; inset: 0; z-index: 600; display: none; align-items: center;
  justify-content: center; padding: 20px; background: rgba(41,37,36,.34); }
#saveAskModal.show { display: flex; }
#saveAskModal .sa-card { width: min(430px, 92vw); background: var(--c-white); border: 1px solid var(--c-border);
  border-radius: 16px; padding: 22px 22px 18px; box-shadow: 0 18px 50px rgba(0,0,0,.22); }
#saveAskModal h3 { margin: 0 0 8px; font-family: 'Noto Serif SC', serif; font-size: 1.06em; color: var(--c-text); }
#saveAskModal p { margin: 0 0 18px; font-size: .86em; line-height: 1.75; color: var(--c-text-muted); }
#saveAskModal .sa-btns { display: flex; gap: 8px; justify-content: flex-end; flex-wrap: wrap; }
#saveAskModal button { font: inherit; font-size: .82em; font-weight: 600; padding: 8px 16px; border-radius: 10px;
  cursor: pointer; border: 1px solid var(--c-border); background: var(--c-white); color: var(--c-text-secondary);
  transition: background .14s ease, border-color .14s ease, color .14s ease; }
#saveAskModal button:hover { background: #F8F5EF; border-color: #D8CFC0; }
#saveAskModal button.primary { background: var(--c-accent-deep); border-color: var(--c-accent-deep); color: #fff; }
#saveAskModal button.primary:hover { filter: brightness(1.06); }
#saveAskModal button.sa-discard:hover { color: #B91C1C; border-color: #FECACA; background: #FEF2F2; }
html.dark #saveAskModal .sa-card { background: #262220; border-color: #3F3A37; }
html.dark #saveAskModal button { background: #2A2623; border-color: #3F3A37; color: #D6D3D1; }
html.dark #saveAskModal button.primary { background: var(--c-accent-deep); color: #fff; }


.pp-sec .q-analyze-row { display: none; }
.pp-sec .q-analyze-row .q-answer-toggle { display: none; }        /* 答案开关一直藏：答案由汇总区揭示 */
.pa-revealed .pp-sec .q-analyze-row { display: flex; }            /* 点过「查看答案」后，解析按钮出现 */
/* 四六级整卷（2026-10-02）：**没有**考研那套「答案与解析汇总区」（它只认完形/阅读/新题型的 1–45 题），
   所以各段直接用自己的答案机制：阅读段落把每题那对开关放出来（听力/选词填空/长篇阅读/翻译本来就自带）。 */
.pp-sec.cet-sec .q-analyze-row { display: flex; }
.pp-sec.cet-sec .q-analyze-row .q-answer-toggle { display: flex; }
html.dark .pp-ans .pa-lock { background: #2A2623; border-color: #3F3A37; color: #A8A29E; }
html.dark .pp-ans .pa-row:nth-of-type(odd) { background: #262220; }
html.dark .pp-ans .pa-ana-btn { background: #2A2623; border-color: #3F3A37; color: #D6D3D1; }
html.dark .pp-ans .pa-ana-btn:hover { background: #332E2A; border-color: #4A443F; }
html.dark .pp-ans .pa-corr { color: #86EFAC; }

.pp-panel .pp-cardlab { flex: 0 0 15px; width: auto; text-align: left; padding-left: 1px; }
/* 每行恒定 5 格：格子宽度 = (整宽 − 标签 15 − 5 个间隙) / 5 → 等宽且右边缘齐平；
   20 个题号正好 4 行、5 个题号正好 1 行，不会出现"末行只剩一两格"的参差。
   用 flex 定宽而不是 grid：grid 的 6 列会让第 6 个题号落进标签那一列（量到 15px 的怪格子）。 */
.pp-panel .pp-chip { box-sizing: border-box; }
/* Enhanced library / done cards *//* Enhanced library / done cards */
.lib-grid { gap: 14px; }
.lib-card { background: var(--c-bg-card); border-radius: var(--radius-md); padding: 18px 20px; box-shadow: var(--shadow-sm); border: 1px solid var(--c-border); cursor: pointer; transition: all .22s cubic-bezier(.25,.8,.25,1); position: relative; overflow: hidden; }
.lib-card::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px; background: linear-gradient(90deg, var(--c-accent), #E9E0D4); opacity: .55; transition: opacity .2s ease; }
.lib-card:hover { box-shadow: var(--shadow-md); border-color: var(--c-accent-light); transform: translateY(-3px); }
.lib-card:hover::before { opacity: 1; }
.lib-card .lib-card-top { display: none; }
.lib-card .lib-card-icon { width: 36px; height: 36px; border-radius: 9px; background: #EFE8DC; color: var(--c-accent); display: flex; align-items: center; justify-content: center; margin-bottom: 10px; }
.lib-card .lib-card-icon svg { width: 20px; height: 20px; }
.lib-card h4 { font-family: 'Noto Serif SC', serif; font-size: .98em; font-weight: 600; color: var(--c-text); margin-bottom: 8px; line-height: 1.5; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.lib-card .lib-meta { display: flex; align-items: center; justify-content: space-between; gap: 8px; flex-wrap: wrap; }
.lib-card .lib-date { font-size: .75em; color: var(--c-text-muted); }
.lib-card .lib-del { position: absolute; top: 10px; right: 12px; background: none; color: var(--c-border); font-size: 1.2em; padding: 2px 7px; border-radius: 5px; line-height: 1; opacity: 0; transition: all .18s ease; }
.lib-card:hover .lib-del { opacity: 1; }
.lib-card .lib-del:hover { color: var(--c-danger); background: #FBEDE8; }
.lib-card .diff { padding: 3px 11px; border-radius: 100px; font-size: .72em; font-weight: 600; letter-spacing: .02em; }
.diff-easy { background: #DCE4D2; color: #3F5530; }
.diff-medium { background: #E9E0D4; color: #4A3229; }
.diff-hard { background: #F7DED6; color: #991B1B; }
.lib-score { padding: 3px 11px; border-radius: 100px; font-size: .72em; font-weight: 600; letter-spacing: .02em; }
.score-good { background: #DCE4D2; color: #3F5530; }
.score-mid { background: #E9E0D4; color: #4A3229; }
.score-low { background: #F7DED6; color: #991B1B; }
/* 算不出正确率（听力/写作/翻译这类记录没有可判分的题目）→ 中性色，绝不用红色假装 0 分 */
.score-none { background: #EFE8DC; color: #6B5D52; }
/* 「已做 N/M · P%」徽章（2026-10-08）：题目训练的长条(.sh-done)与选题面板(.rp-done)共用，
   复用上面这套三档色；窄屏把「已做」两个字藏掉（只留分数），免得把标题挤没/横向溢出。 */
.reading-picker .rp-done { margin-right: 6px; }

/* ── 「已做」状态徽章专属皮肤（2026-10-09 改版，**只作用于题目训练的长条**）──
   改版原因：原来它直接套 .lib-score，而 .lib-score 的 score-good 绿底 #DCE4D2 与旁边
   「难度=简单」用的 .diff-easy 是**同一个色值**、score-mid 又等于 diff-medium —— 形状/字号/圆角全一样，
   并排时分不清哪片是状态、哪片是元数据；而且排名语义（正确率）被推到标签组最左，视线落点不对。
   现在：实心勾号圆标 + 大数字分数 + 淡底百分比片 —— 站内没有任何元素用「实心圆 + 白勾」，
   一眼就能与难度片/月份片分开。⚠️ 不动 .lib-score 本身：「已做题目」页的 .done-row 与保存题目横条还在用它。 */
.sh-done { display: inline-flex; align-items: center; gap: 6px; padding: 3px 9px 3px 4px; border-radius: 9999px;
  font-size: .74em; font-weight: 600; letter-spacing: .01em; white-space: nowrap; }
.sh-done-ic { flex: none; width: 15px; height: 15px; border-radius: 50%; display: inline-flex;
  align-items: center; justify-content: center; color: #fff; }
.sh-done-ic svg { width: 9px; height: 9px; display: block; }
/* 分数与百分比**不许被压扁**（宁可整组换行，也不让数字折断） */
.sh-done-n { font-weight: 700; font-size: 1.14em; font-variant-numeric: tabular-nums; white-space: nowrap; }
.sh-done-p { flex: none; padding: 1px 7px; border-radius: 9999px; font-size: .92em; font-weight: 700;
  font-variant-numeric: tabular-nums; white-space: nowrap; }
.sh-done-a { font-weight: 700; }
.sh-done.score-none .sh-done-a { display: none; }   /* 无分时「已做」由勾号承担，不再显示多余的字 */
/* 三档状态色：≥80 绿 / ≥60 琥珀 / 其余红（沿用站内三档语义，没有引入新色相）。
   每条先写一层**静态降级底色**，紧跟一条 color-mix —— 不支持 color-mix 的浏览器至少还有底色，
   不会退化成"只有字、没有胶囊"（站内别处也在用 color-mix，这里只是加一道保险）。 */
.sh-done.score-good { color: #3F5530; background: rgba(79,107,54,.11); background: color-mix(in srgb, #4F6B36 11%, transparent); }
.sh-done.score-good .sh-done-ic { background: #4F6B36; }
.sh-done.score-good .sh-done-p { color: #3F5530; background: #E4EBD9; background: color-mix(in srgb, #4F6B36 17%, transparent); }
.sh-done.score-mid { color: #7A5A24; background: rgba(138,106,47,.11); background: color-mix(in srgb, #8A6A2F 11%, transparent); }
.sh-done.score-mid .sh-done-ic { background: #8A6A2F; }
.sh-done.score-mid .sh-done-p { color: #7A5A24; background: #F2E8D6; background: color-mix(in srgb, #8A6A2F 18%, transparent); }
.sh-done.score-low { color: #9B3B2E; background: rgba(155,59,46,.10); background: color-mix(in srgb, #9B3B2E 10%, transparent); }
.sh-done.score-low .sh-done-ic { background: #9B3B2E; }
.sh-done.score-low .sh-done-p { color: #9B3B2E; background: #F6E2DD; background: color-mix(in srgb, #9B3B2E 16%, transparent); }
/* 算不出正确率（听力 / 写作 / 翻译这类没有可判分题目的记录）：中性灰，绝不用红色假装「考了 0 分」 */
.sh-done.score-none { color: #5F5952; background: #F1ECE4; }
.sh-done.score-none .sh-done-ic { background: #8C857B; }
@media (max-width: 480px) { .done-badge-n { display: none; } }
html.force-phone .done-badge-n { display: none; }
.lib-empty, .vp-empty { padding: 72px 20px; }
.lib-empty svg, .vp-empty svg { width: 56px; height: 56px; color: var(--c-border); opacity: .7; }

/* ── Basic Library Page (hero + tabs) ── */
.lib-hero { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; margin-bottom: 18px; flex-wrap: wrap; }
.lib-hero-text h2 { font-family: 'Noto Serif SC', serif; font-size: 1.7em; font-weight: 700; color: #5C4033; letter-spacing: .02em; display: flex; align-items: center; gap: 10px; }
.lib-hero-text h2::before { content: ''; width: 4px; height: 24px; border-radius: 2px; background: linear-gradient(180deg, var(--c-accent), #E9E0D4); }
.lib-hero-text .vp-sub { margin: 4px 0 10px; padding-left: 14px; }
.lib-tabs { display: flex; gap: 8px; margin-bottom: 20px; flex-wrap: wrap; }
.lib-tab { display: inline-flex; align-items: center; gap: 6px; padding: 7px 16px; border-radius: 100px; font-size: .82em; font-weight: 500; background: var(--c-bg-card); color: var(--c-text-secondary); border: 1px solid var(--c-border); cursor: pointer; transition: all .2s ease; }
.lib-tab:hover { border-color: var(--c-accent-light); color: var(--c-accent); }
.lib-tab.active { background: linear-gradient(135deg, var(--c-accent-deep), var(--c-accent-hover)); color: #fff; border-color: transparent; box-shadow: 0 2px 8px rgba(90,110,69,.25); }
.lib-tab-count { min-width: 18px; height: 18px; padding: 0 5px; border-radius: 100px; font-size: .7em; font-weight: 600; background: rgba(0,0,0,.08); display: inline-flex; align-items: center; justify-content: center; }
.lib-tab.active .lib-tab-count { background: rgba(255,255,255,.25); }
.lib-filter-empty { text-align: center; padding: 60px 20px; color: var(--c-text-muted); font-size: .88em; }
.lib-card .lib-go { position: absolute; right: 14px; bottom: 10px; font-size: .74em; font-weight: 600; color: var(--c-accent); opacity: 0; transform: translateX(-6px); transition: all .2s ease; }
.lib-card:hover .lib-go { opacity: 1; transform: translateX(0); }
.lib-card .lib-meta { padding-right: 64px; }
@media (max-width: 768px), html.force-phone {
  .lib-hero { flex-direction: column; }
  .lib-tabs { flex-wrap: nowrap; overflow-x: auto; padding-bottom: 4px; -webkit-overflow-scrolling: touch; }
  .lib-tab { flex-shrink: 0; }
}

/* Chat Page */
.chat-container { max-width: 720px; margin: 0 auto; display: flex; flex-direction: column; height: calc(100vh - 120px); }
.chat-messages { flex: 1; min-height: 0; overflow-y: auto; padding: 24px 0; scroll-behavior: smooth; }
.chat-msg { margin-bottom: 20px; display: flex; flex-direction: column; animation: msgReveal .35s ease both; }
@keyframes msgReveal { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }
.chat-msg.user { align-items: flex-end; }
.chat-msg.ai { align-items: flex-start; }
.chat-msg .bubble { max-width: 82%; padding: 14px 20px; border-radius: 18px; line-height: 1.75; font-size: .92em; position: relative; }
.chat-msg.user .bubble { background: linear-gradient(135deg, var(--c-accent-deep), var(--c-accent-hover)); color: var(--c-white); border-bottom-right-radius: 6px; box-shadow: 0 2px 8px rgba(90,110,69,.15); }
.chat-msg.ai .bubble { background: #FFFCF8; color: var(--c-text); border-bottom-left-radius: 6px; border: 1px solid rgba(120,113,108,.08); box-shadow: 0 1px 3px rgba(0,0,0,.03); font-family: 'Crimson Text', 'Noto Serif SC', serif; text-align: justify; }
.chat-msg.ai .bubble p { margin: 4px 0; line-height: 1.8; text-indent: 2em; }
.chat-msg.user .bubble p { margin: 0; }
.chat-input-area { display: flex; gap: 10px; padding: 16px 0; border-top: 1px solid rgba(120,113,108,.08); margin-top: auto; }
.ci-wrap { position: relative; flex: 1; }
.ci-deco { position: absolute; left: -2px; top: 8px; bottom: 8px; width: 5px; border-radius: 3px; background: #62764E; opacity: .7; transition: opacity .3s ease; z-index: 1; }
.ci-wrap:focus-within .ci-deco { opacity: 1; }
.ci-wrap input { width: 100%; padding: 16px 14px 6px 18px; font-size: .85rem; color: #1f2937; background: #fff; border: 1px solid #e5e7eb; border-radius: 7px; box-shadow: 0 1px 3px rgba(0,0,0,.08); outline: none; font: inherit; transition: border-color .2s ease, box-shadow .2s ease; }
.ci-wrap input:focus { border-color: transparent; box-shadow: 0 0 0 2px rgba(90,110,69,.3); }
.ci-wrap label { position: absolute; left: 18px; top: 11px; font-size: .85rem; color: #6b7280; transition: top .2s ease, color .2s ease; cursor: text; pointer-events: none; }
.ci-wrap input:placeholder-shown + label { top: 11px; font-size: .9rem; color: #9ca3af; }
.ci-wrap input:focus + label, .ci-wrap input:not(:placeholder-shown) + label { top: 3px; font-size: .7rem; color: #5A6E45; font-weight: 600; }
.chat-input-area .btn-send { position: relative; top: -2px; padding: 10px 20px; background: #5A6E45; color: #fff; border-radius: 6px; font-weight: 700; font-size: .85em; letter-spacing: 1px; opacity: .85; transition: opacity .2s ease, top .2s ease, box-shadow .2s ease; box-shadow: #5C4033 0 5px 0, rgba(0,0,0,.35) 0 7px 5px; }
.chat-input-area .btn-send:hover { opacity: 1; }
.chat-input-area .btn-send:active { top: 1px; box-shadow: #5C4033 0 1px 0, rgba(0,0,0,.35) 0 3px 5px; }
.chat-input-area .btn-send:disabled { opacity: .4; top: 0; box-shadow: none; cursor: not-allowed; }
.chat-save-area { text-align: center; padding: 14px 0; animation: msgReveal .35s ease both; }
.chat-save-area .btn-save { padding: 12px 36px; background: #4F6B36; color: #fff; border-radius: 100px; font-size: .92em; font-weight: 600; letter-spacing: .04em; box-shadow: 0 2px 12px rgba(79,107,54,.25); transition: all .25s ease; }
.chat-save-area .btn-save:hover { transform: translateY(-2px); box-shadow: 0 6px 20px rgba(79,107,54,.35); }
.chat-hint { background: #F5EFE4; border: 1px solid rgba(90,110,69,.12); border-radius: var(--radius-md); padding: 18px 22px; font-size: .88em; color: var(--c-text-secondary); margin-bottom: 16px; line-height: 1.8; box-shadow: 0 1px 3px rgba(0,0,0,.02); }
.chat-hint .chat-hint-icon { width: 1.35em; height: 1.35em; margin-right: 9px; vertical-align: -0.28em; flex-shrink: 0; }
.bubble.thinking { color: var(--c-text-muted); font-style: italic; animation: thinkPulse 1.5s infinite; }
@keyframes thinkPulse { 0%, 100% { opacity: .4; } 50% { opacity: .8; } }

.chat-layout { display: flex; height: calc(100vh - 52px); position: fixed; top: 52px; left: 0; right: 0; background: var(--c-bg); }
#basicChatTopbar, #storyChatTopbar { position: fixed; top: 0; left: 0; right: 0; z-index: 130; width: 100%; max-width: none; border-radius: 0; margin: 0; }
.chat-sidebar { width: 260px; flex-shrink: 0; background: rgba(255,254,249,.6); border-right: 1px solid rgba(120,113,108,.06); display: flex; flex-direction: column; overflow: hidden; backdrop-filter: blur(8px); }
.chat-sidebar .sidebar-head { padding: 16px 14px 12px; }
.chat-sidebar .sidebar-head button { width: 100%; padding: 9px; border-radius: 100px; font-size: .84em; font-weight: 600; background: var(--c-accent); color: var(--c-white); letter-spacing: .02em; box-shadow: 0 2px 8px rgba(90,110,69,.15); transition: all .25s ease; }
.chat-sidebar .sidebar-head button:hover { background: var(--c-accent-hover); transform: translateY(-1px); box-shadow: 0 4px 14px rgba(90,110,69,.25); }
.session-list { flex: 1; overflow-y: auto; padding: 0 10px 10px; }
.session-item { position: relative; padding: 11px 42px 11px 14px; border-radius: var(--radius-md); cursor: pointer; margin-bottom: 4px; transition: all .2s ease; border: 1px solid transparent; }
.session-item:hover { background: var(--c-white); border-color: rgba(120,113,108,.06); }
.session-item.active { background: var(--c-white); border-color: rgba(90,110,69,.15); box-shadow: 0 2px 8px rgba(0,0,0,.04); }
.session-item.active::before { content: ''; position: absolute; left: 0; top: 10px; bottom: 10px; width: 3px; background: var(--c-accent); border-radius: 0 2px 2px 0; }
.session-item .sess-title { font-size: .85em; font-weight: 500; color: var(--c-text); margin-bottom: 3px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.session-item .sess-date { font-size: .72em; color: var(--c-text-muted); }
.story-session-source { display: inline-flex; align-items: center; min-height: 18px; margin-right: 6px; padding: 0 6px; border: 1px solid rgba(92,64,51,.22); border-radius: 999px; color: #5C4033; background: rgba(254,243,199,.72); font-size: .9em; font-weight: 700; line-height: 1; }
/* 「删除这条对话」（2026-10-04 用户要求：**做得明显一些**）——
   原来是无底色的浅灰 × 且 `opacity:0`，不 hover 根本看不见。现在改成**常显的红色圆钮**：
   淡红底 + 红 × + 细描边，hover 变实心红底白 ×；两种聊天侧栏（阅读 AI 对话 / 生成小说）共用这一份。 */
.session-item .sess-del { position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; padding: 0; border-radius: 50%; cursor: pointer;
  background: #FBEDE8; color: var(--c-danger); border: 1px solid rgba(166,61,42,.24);
  font-size: 1.15em; line-height: 1; opacity: 1;
  transition: background-color .18s ease, color .18s ease, border-color .18s ease, transform .18s ease; }
.session-item .sess-del:hover { background: var(--c-danger); color: #fff; border-color: var(--c-danger); transform: translateY(-50%) scale(1.06); }
.chat-main { flex: 1; min-width: 0; display: flex; background: var(--c-bg); }
.chat-main .chat-container { height: 100%; padding: 0 24px; max-width: 760px; }
.session-empty { text-align: center; padding: 48px 16px; color: var(--c-text-muted); font-size: .82em; line-height: 1.8; }
.session-empty::before { content: '\1F4AD'; display: block; font-size: 2em; margin-bottom: 8px; }

/* Chat Enhance */
.chat-quick { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 14px; }
.chat-suggests { display: flex; gap: 8px; justify-content: center; padding: 8px 0 4px; }
.sg-btn { padding: 7px 20px; border-radius: 100px; font-size: .8em; font-weight: 500; background: var(--c-white); color: var(--c-text-secondary); border: 1px solid var(--c-border); cursor: pointer; transition: all .18s ease; }
.sg-btn:hover { background: #F5EFE4; border-color: var(--c-accent); color: var(--c-accent); }
.chat-back-btn { position: fixed; bottom: 84px; left: 50%; transform: translateX(-50%); z-index: 90; padding: 8px 18px; border-radius: 100px; font-size: .8em; font-weight: 500; background: rgba(41,37,36,.75); color: #fff; border: none; cursor: pointer; opacity: 0; pointer-events: none; transition: all .25s ease; }
.chat-back-btn.show { opacity: 1; pointer-events: auto; }
.chat-msg .bubble.thinking { display: flex; align-items: center; gap: 6px; }
.chat-msg .bubble.thinking .tdot { width: 7px; height: 7px; border-radius: 50%; background: var(--c-accent); opacity: .4; animation: tdot 1.2s infinite ease-in-out; }
.chat-msg .bubble.thinking .tdot:nth-child(2) { animation-delay: .2s; }
.chat-msg .bubble.thinking .tdot:nth-child(3) { animation-delay: .4s; }
@keyframes tdot { 0%, 100% { opacity: .3; transform: translateY(0); } 50% { opacity: 1; transform: translateY(-3px); } }
.btn-send.loading { opacity: .6; pointer-events: none; }
.btn-send.loading::after { content: ''; display: inline-block; width: 12px; height: 12px; margin-left: 8px; border: 2px solid rgba(255,255,255,.4); border-top-color: #fff; border-radius: 50%; animation: spin .7s linear infinite; vertical-align: -1px; }
@keyframes spin { to { transform: rotate(360deg); } }
.chat-hint { font-size: .86em; }
/* 会话栏暖黄纸张风 */
.chat-sidebar { background: #F4EEE4; border-right: 1px solid rgba(90,110,69,.08); }
.session-item:hover { background: #F5EFE4; border-color: rgba(90,110,69,.1); }
.session-item.active { background: #F2EDE4; border-color: rgba(90,110,69,.18); }
/* 消息气泡纸张质感 */
.chat-msg.ai .bubble { background: #FFFCF8; border: 1px solid var(--c-accent); box-shadow: 0 1px 3px rgba(0,0,0,.03), 0 0 0 1px rgba(120,113,108,.04); }
.chat-msg.ai .bubble ul, .chat-msg.ai .bubble ol { margin: 4px 0 4px 18px; padding: 0; }
.chat-msg.ai .bubble li { text-indent: 0; margin: 2px 0; }
.chat-msg.ai .bubble h5 { font-size: .95em; margin: 8px 0 4px; color: var(--c-primary-dark); }

/* Reading Picker */
.reading-picker-overlay { position: fixed; inset: 0; background: rgba(41,37,36,.4); z-index: 600; display: none; align-items: center; justify-content: center; backdrop-filter: blur(3px); }
.reading-picker-overlay.show { display: flex; }
.reading-picker { background: #FFFCF8; border-radius: 18px; padding: 26px 30px 24px; max-width: 520px; width: 92%; max-height: 88vh; overflow-y: auto; text-align: center; box-shadow: 0 2px 6px rgba(0,0,0,.04), 0 16px 40px rgba(120,113,108,.14), 0 30px 80px rgba(120,113,108,.16); border: 2px solid #CEC9C0; animation: popIn .18s ease; }
.reading-picker .rp-head { display: flex; align-items: baseline; gap: 12px; margin-bottom: 18px; padding-bottom: 14px; border-bottom: 1px solid #F0EAE0; position: relative; }
.reading-picker .rp-head::after { content: ''; position: absolute; left: 0; bottom: -1px; width: 72px; height: 2px; border-radius: 2px; background: #5A6E45; }
.reading-picker .rp-head h3 { font-family: 'Noto Serif SC', serif; font-size: 1.12em; font-weight: 700; color: #5C4033; letter-spacing: .06em; margin: 0; }
.reading-picker .rp-count { font-family: 'Crimson Text', serif; font-size: .85em; color: #A8A29E; font-style: italic; }
.reading-picker .rp-close { margin-left: auto; background: none; border: none; color: #A8A29E; padding: 6px; border-radius: 16px; cursor: pointer; line-height: 0; transition: all .15s; }
.reading-picker .rp-close:hover { background: #F5F0E8; color: #5C4033; }
.reading-picker .rp-groups { display: flex; flex-direction: column; gap: 8px; margin-bottom: 12px; text-align: left; }
.reading-picker .rp-dd { position: relative; }
.reading-picker .rp-dd-btn { width: 100%; display: flex; align-items: center; gap: 8px; padding: 9px 12px; border-radius: 16px; border: 1px solid #F0E9DC; background: #FAF7F0; cursor: pointer; transition: border-color .15s; text-align: left; }
.reading-picker .rp-dd-btn:hover { border-color: #E2D6BE; }
.reading-picker .rp-dd-lab { display: inline-flex; align-items: center; gap: 6px; font-family: 'Noto Serif SC', serif; font-size: .74em; font-weight: 600; color: #9C8B6E; letter-spacing: .14em; flex-shrink: 0; }
.reading-picker .rp-dd-lab svg { color: #5C4033; flex-shrink: 0; }
.reading-picker .rp-dd-lab .rp-gbar { width: 3px; height: 12px; border-radius: 2px; background: #A2A78C; flex-shrink: 0; }
.reading-picker .rp-dd-cur { flex: 1; min-width: 0; text-align: right; font-size: .85em; color: #5C4033; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.reading-picker .rp-dd-cur.on { color: #5C4033; font-weight: 700; }
.reading-picker .rp-dd-caret { width: 13px; height: 13px; flex-shrink: 0; color: #A8A29E; transition: transform .15s; }
.reading-picker .rp-dd.open .rp-dd-caret { transform: rotate(180deg); color: #5C4033; }
.reading-picker .rp-dd-menu { display: none; position: absolute; top: calc(100% + 6px); left: 0; right: 0; z-index: 70; border: 1px solid #E5DDCC; border-radius: 16px; background: #FFFCF8; box-shadow: 0 8px 28px rgba(120,113,108,.16), 0 2px 6px rgba(0,0,0,.06); overflow: hidden; max-height: 240px; overflow-y: auto; }
.reading-picker .rp-dd.open .rp-dd-menu { display: block; animation: rtDdIn .16s ease; }
.reading-picker .rp-dd-item { display: block; width: 100%; text-align: left; padding: 8px 14px; border: none; background: none; color: #57534E; font-size: .85em; cursor: pointer; transition: background .15s; }
.reading-picker .rp-dd-item:hover { background: #F5F0E8; color: #5C4033; }
.reading-picker .rp-dd-item.sel { color: #B45309; font-weight: 700; background: #FFF7E8; }
.reading-picker .rp-random { width: 100%; padding: 14px; border-radius: 16px; font-size: .92em; font-weight: 600; background: #5B573C; color: #fff; border: none; cursor: pointer; margin-bottom: 16px; box-shadow: 0 3px 10px rgba(90,110,69,.2); transition: opacity .15s ease; letter-spacing: .02em; }
.reading-picker .rp-random:hover { opacity: .92; }
.reading-picker .rp-results-head { font-size: .8em; color: #A8A29E; text-align: left; margin-bottom: 8px; }
.reading-picker .rp-results { max-height: 264px; overflow-y: auto; text-align: left; }
.reading-picker .rp-item { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 11px 14px; border-radius: 16px; border: 1px solid transparent; cursor: pointer; transition: background .15s, border-color .15s; }
.reading-picker .rp-item:hover { background: #F5F0E8; border-left-color: #5A6E45; }
.reading-picker .rp-item-title { font-size: .9em; color: #5C4033; font-weight: 500; }
.reading-picker .rp-tag { font-size: .72em; padding: 2px 9px; border-radius: 100px; border: 1px solid #E5DDCC; color: #78716C; margin-left: 6px; white-space: nowrap; }
.reading-picker .rp-tag.diff-简单 { background: #ECFDF5; color: #047857; border-color: #C6D3B6; }
.reading-picker .rp-tag.diff-中等 { background: #F5EFE4; color: #5C4033; border-color: #E9E0D4; }
.reading-picker .rp-tag.diff-困难 { background: #FBEDE8; color: #8E3323; border-color: #FECACA; }
.reading-picker .rp-empty { text-align: center; padding: 30px; color: #A8A29E; font-size: .85em; }

/* Story Card */
.card.story::before { background: #AF827A; }
.card.story .card-icon { background: #F1E6E4; color: #8C5F58; }
.card:hover.story { border-color: rgba(140,95,88,.25); }

/* ===== 精读训练模块 ===== */
.train-page { max-width: 760px; margin: 0 auto; padding: 26px 20px 60px; }
.train-tip { text-align: center; font-size: .78em; color: var(--c-text-muted); margin-bottom: 22px; letter-spacing: .02em; }
.train-card { animation: cardReveal .4s ease both; }
.train-sentence { position: relative; background: #F2F5FA; border: 1px solid rgba(74,97,127,.16); border: 1px solid #5B6E8C; border-radius: var(--radius-md); padding: 14px 20px 20px; margin-bottom: 12px; box-shadow: var(--shadow-sm); }
.train-sentence-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 10px; }
.train-sentence-label { font-size: .68em; font-weight: 700; color: #4A617F; letter-spacing: .12em; display: flex; align-items: center; gap: 6px; }
.train-sentence-text { font-size: calc(1.06em * var(--rt-scale, 1)); line-height: var(--rt-line, 1.9); font-family: var(--rt-font, 'Crimson Text', 'Inter', serif); text-align: var(--rt-align, justify); color: var(--c-text); }
.train-page .word { cursor: pointer; transition: all .1s; border-radius: 3px; padding: 0 1px; }
.train-page .word:hover, .train-page .word:active { background: var(--c-accent-light); }
.train-sentence-text b, .train-sentence-text .kw { color: #5C4033; font-weight: 700; background: rgba(90,110,69,.08); padding: 0 3px; border-radius: 3px; }
.train-instruction { margin: 0 0 14px; }
.train-source { font-size: .7em; font-weight: 600; color: #5C4033; background: rgba(92,64,51,.09); border: 1px solid rgba(92,64,51,.2); padding: 2px 10px; border-radius: 100px; white-space: nowrap; letter-spacing: .02em; margin-left: -40px; }
.train-stem { display: flex; gap: 8px; align-items: flex-start; font-weight: 600; margin-bottom: 10px; padding-left: 15px; line-height: 1.7; }
.train-stem-text { flex: 1; min-width: 0; }
.train-qtag { flex-shrink: 0; background: #EDF1F7; color: #4A617F; font-size: .66em; font-weight: 700; padding: 2px 9px; border-radius: 6px; letter-spacing: .08em; margin-top: 5px; }
.train-options { margin-bottom: 4px; }
.train-actions { display: flex; justify-content: center; gap: 12px; margin-top: 8px; }
.train-actions .vp-btn-study { min-width: 170px; }
.train-actions .vp-btn-study.train-prev { min-width: 140px; }
.train-actions .vp-btn-study:disabled { opacity: .5; cursor: not-allowed; transform: none; box-shadow: none; }
.train-loading { text-align: center; padding: 70px 0; color: var(--c-text-muted); font-size: .88em; }
.train-spinner { width: 34px; height: 34px; margin: 0 auto 16px; border: 3px solid rgba(74,97,127,.15); border-top-color: #4A617F; border-radius: 50%; animation: fcSpin 1s linear infinite; }
@keyframes fcSpin { to { transform: rotate(360deg); } }
.train-options .q-option.right-opt { border-color: #10b981; }
.train-options .q-option.right-opt::before { background: #E6F9EF; }
.train-options .q-option.wrong-opt { border-color: #A63D2A; }
.train-options .q-option.wrong-opt::before { background: #FBEDE8; }
.train-options .q-option.locked { cursor: default; }
.train-options .q-option.locked:hover::before { background: none; }
.train-options .q-option.locked.right-opt:hover::before { background: #E6F9EF; }
.train-options .q-option.locked.wrong-opt:hover::before { background: #FBEDE8; }
.train-options .q-option.locked .word { cursor: pointer; }
.train-ans-key { color: var(--c-accent-deep); font-weight: 700; }
.train-type-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
.train-type-card { position: relative; display: flex; flex-direction: column; align-items: flex-start; gap: 6px; background: var(--c-white); border: 1px solid var(--c-border); border-radius: var(--radius-md); padding: 18px 16px; text-align: left; cursor: pointer; transition: all var(--transition-normal); box-shadow: var(--shadow-sm); }
.train-type-card:hover { border-color: rgba(74,97,127,.4); transform: translateY(-2px); box-shadow: 0 8px 20px rgba(74,97,127,.12); }
.train-type-icon { display: flex; align-items: center; justify-content: center; width: 38px; height: 38px; border-radius: 16px; background: #E4EAF4; color: #4A617F; }
.train-type-name { font-size: .98em; font-weight: 700; color: var(--c-text); }
.train-type-desc { font-size: .72em; color: var(--c-text-muted); line-height: 1.6; }
.train-type-tag { font-size: .66em; font-weight: 600; color: #4A617F; background: #EDF1F7; padding: 2px 9px; border-radius: 100px; margin-top: 2px; }
.train-type-card.disabled { cursor: not-allowed; opacity: .55; filter: grayscale(.35); }
.train-type-card.disabled:hover { transform: none; box-shadow: var(--shadow-sm); }
.train-type-chip { display: flex; align-items: center; gap: 8px; justify-content: center; margin-bottom: 14px; font-size: .82em; font-weight: 600; color: #4A617F; }
.train-type-chip-dot { width: 8px; height: 8px; border-radius: 50%; background: #10b981; box-shadow: 0 0 0 3px rgba(79,107,54,.18); }
.train-type-switch { background: none; border: 1px solid var(--c-border); border-radius: 100px; padding: 3px 12px; font-size: .72em; color: var(--c-text-secondary); cursor: pointer; transition: all .2s; }
.train-type-switch:hover { border-color: rgba(74,97,127,.4); color: #4A617F; }
@media (max-width: 768px) {
  .train-type-grid { grid-template-columns: repeat(2, 1fr); gap: 10px; }
  .train-type-card { padding: 14px 12px; }
}
html.force-phone .train-type-grid { grid-template-columns: repeat(2, 1fr); gap: 10px; }
html.force-phone .train-type-card { padding: 14px 12px; }
@media (max-width: 768px) {
  .train-page { padding: 72px 14px 50px; }
  .train-sentence { padding: 13px 14px 17px; }
  .train-sentence-text { font-size: calc(.92em * var(--rt-scale, 1)); }
  .train-stem { padding-left: 12px; }
  .train-stem-text { font-size: .88em; }
  .train-options .q-option { font-size: .82em; }
  .train-tip { font-size: .72em; }
}
html.force-phone .train-page { padding: 72px 14px 50px; }
html.force-phone .train-sentence { padding: 13px 14px 17px; }
html.force-phone .train-sentence-text { font-size: calc(.92em * var(--rt-scale, 1)); }
html.force-phone .train-stem { padding-left: 12px; }
html.force-phone .train-stem-text { font-size: .88em; }
html.force-phone .train-options .q-option { font-size: .82em; }
html.force-phone .train-tip { font-size: .72em; }
/* ⚠️ 2026-10-11 修（用户报「手机版『定位答案句』和 2019年12月 六级 第2套 Passage 2·第4题 挤在一起」）：
   `.train-sentence-head` 是一行 flex，里面三样：图标+「定位答案句」的文字、中间那枚来源胶囊（`white-space:nowrap`）、
   右侧「Aa」按钮。胶囊本身就有 ~320px（`2019年12月 六级 第2套 Passage 2 · 第4题`），
   加上标签与按钮 > 手机可用宽度 → 标签被压成两行、和胶囊挤在一起（截图实测）。
   修法（只动手机档）：① 胶囊允许收缩 + 省略号（不再硬撑）；② 胶囊去掉 `margin-left:-40px`
   （那是给电脑档拉近标签用的，手机上正是它把胶囊推去压标签）；③ 极窄屏（≤430px）只留「定位答案句」的图标，
   文字省掉 —— 三个都保留时宽度根本不够。平板/电脑档一个像素不动。 */
html.force-phone .train-sentence-head { gap: 8px; }
html.force-phone .train-sentence-label { flex: 0 0 auto; }
html.force-phone .train-source { margin-left: 0; flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
@media (max-width: 430px) {
  .train-sentence-head { gap: 8px; }
  .train-sentence-label { flex: 0 0 auto; font-size: 0; letter-spacing: 0; }
  .train-sentence-label svg { width: 15px; height: 15px; }
  .train-source { margin-left: 0; flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; font-size: .66em; padding: 2px 8px; }
}
html.force-tablet .train-page { padding-top: 72px; }

/* 精读训练题型选择弹框 */
.train-type-overlay { position: fixed; inset: 0; background: rgba(41,37,36,.45); z-index: 700; display: none; align-items: center; justify-content: center; backdrop-filter: blur(4px); }
.train-type-overlay.show { display: flex; }
.train-type-modal { background: #FFFCF8; border-radius: 18px; padding: 26px 30px 24px; max-width: 560px; width: 92%; max-height: 88vh; overflow-y: auto; text-align: center; box-shadow: 0 2px 6px rgba(0,0,0,.04), 0 16px 40px rgba(120,113,108,.14), 0 30px 80px rgba(120,113,108,.16); border: 2px solid #CEC9C0; animation: popIn .18s ease; }
.train-type-modal .ttm-head { display: flex; align-items: baseline; gap: 12px; margin-bottom: 18px; padding-bottom: 14px; border-bottom: 1px solid #F0EAE0; position: relative; }
.train-type-modal .ttm-head::after { content: ''; position: absolute; left: 0; bottom: -1px; width: 72px; height: 2px; border-radius: 2px; background: #5A6E45; }
.train-type-modal .ttm-head h3 { font-family: 'Noto Serif SC', serif; font-size: 1.12em; font-weight: 700; color: #5C4033; letter-spacing: .06em; margin: 0; }
.train-type-modal .ttm-head p { margin: 0; font-size: .72em; color: #A8A29E; }
.train-type-modal .ttm-close { margin-left: auto; background: none; border: none; color: #A8A29E; padding: 6px; border-radius: 16px; cursor: pointer; line-height: 0; transition: all .15s; }
.train-type-modal .ttm-close:hover { background: #F5F0E8; color: #5C4033; }
.train-type-modal .train-type-grid { grid-template-columns: repeat(3, 1fr); gap: 12px; }
.train-type-modal .train-type-card { padding: 16px 14px; }
@media (max-width: 768px), html.force-phone {
  .train-type-modal { padding: 22px 18px 20px; }
  .train-type-modal .train-type-grid { grid-template-columns: repeat(2, 1fr); gap: 10px; }
  .train-type-modal .train-type-card { padding: 14px 12px; }
}

/* 精读训练三栏布局：左生词本 / 中题目卡 / 右词组本 */
.train-page { max-width: 1320px; }
.train-layout { display: grid; grid-template-columns: minmax(0, 240px) minmax(0, 760px) minmax(0, 240px); gap: 20px; align-items: start; justify-content: center; max-width: 1300px; margin: 0 auto; }
.train-rail { position: sticky; top: 92px; align-self: start; max-height: calc(100vh - 120px); overflow-y: auto; scrollbar-width: thin; }
.train-rail .vocab-panel { padding: 14px 16px; }
.train-rail .vocab-panel h3 { margin-bottom: 10px; }
.train-rail .vocab-list { max-height: 40vh; }
.train-rail .phrase-panel { margin-top: 0; }
.train-center { min-width: 0; }
@media (min-width: 769px) and (max-width: 1024px) {
  .train-layout { grid-template-columns: minmax(0, 196px) minmax(0, 1fr) minmax(0, 196px); gap: 14px; }
  .train-rail { top: 82px; max-height: calc(100vh - 100px); }
}
@media (max-width: 768px), html.force-phone {
  .train-layout { display: flex; flex-direction: column; gap: 14px; max-width: 720px; }
  .train-center { order: 1; width: 100%; }
  .train-rail { order: 2; position: static; max-height: none; overflow: visible; width: 100%; }
  .train-rail-right { order: 3; }
}
html.force-tablet .train-type-modal { padding: 22px 18px 20px; }
html.force-tablet .train-type-modal .train-type-grid { grid-template-columns: repeat(2, 1fr); gap: 10px; }

/* Story Hub Page */
.story-hub-layout { display: flex; height: calc(100vh - 50px); max-width: 960px; margin: 0 auto; padding: 32px 24px; gap: 28px; }
.story-hub-right { width: 300px; flex-shrink: 0; display: flex; flex-direction: column; }
.story-hub-right .story-list-head { font-family: 'Noto Serif SC', serif; font-weight: 600; font-size: .84em; color: var(--c-text); letter-spacing: .04em; padding-bottom: 14px; border-bottom: 1px solid rgba(120,113,108,.08); margin-bottom: 8px; }
.story-hub-right .story-list-body { flex: 1; overflow-y: auto; }
.story-hub-right .story-item { position: relative; padding: 14px 32px 14px 16px; border-radius: var(--radius-md); cursor: pointer; margin-bottom: 4px; transition: all .2s ease; border: 1px solid transparent; }
.story-hub-right .story-item:hover { background: var(--c-white); border-color: rgba(120,113,108,.08); box-shadow: 0 2px 8px rgba(0,0,0,.03); }
.story-hub-right .story-item .story-title { font-size: .88em; font-weight: 600; color: var(--c-text); margin-bottom: 3px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.story-hub-right .story-item .story-meta { font-size: .74em; color: var(--c-text-muted); }
.story-hub-right .story-item .story-del { position: absolute; right: 8px; top: 50%; transform: translateY(-50%); background: none; color: var(--c-border); font-size: 1em; padding: 3px 7px; border-radius: 4px; line-height: 1; opacity: 0; transition: all .2s ease; }
.story-hub-right .story-item:hover .story-del { opacity: 1; }
.story-hub-right .story-item .story-del:hover { color: var(--c-danger); background: #FBEDE8; }
.story-hub-right .story-empty { text-align: center; padding: 48px 16px; color: var(--c-text-muted); font-size: .82em; line-height: 1.8; }
.story-hub-right .story-empty::before { content: '\1F4D6'; display: block; font-size: 2em; margin-bottom: 8px; }

.import-preview-overlay { position: fixed; inset: 0; background: rgba(41,37,36,.5); z-index: 300; display: none; align-items: center; justify-content: center; backdrop-filter: blur(4px); }
.import-preview-overlay.show { display: flex; }
.import-preview-card { background: var(--c-white); border-radius: var(--radius-lg); width: min(900px, 92vw); max-height: 86vh; display: flex; flex-direction: column; box-shadow: var(--shadow-lg); overflow: hidden; }
.import-preview-head { display: flex; align-items: center; justify-content: space-between; padding: 14px 20px; border-bottom: 1px solid var(--c-border); background: linear-gradient(180deg, #F5F3FF, var(--c-white)); }
.import-preview-head span { font-family: 'Noto Serif SC', serif; font-weight: 700; font-size: .95em; color: var(--c-text); }
.import-preview-head button { background: none; color: var(--c-text-muted); font-size: 1.2em; padding: 4px 10px; border-radius: var(--radius-sm); }
.import-preview-head button:hover { background: #FBEDE8; color: var(--c-danger); }
.import-preview-body { display: flex; flex: 1; min-height: 0; }
.import-preview-left { flex: 1; min-width: 0; padding: 16px 20px; border-right: 1px solid var(--c-border); overflow-y: auto; background: var(--c-bg-reading); }
.import-preview-right { width: 320px; flex-shrink: 0; padding: 16px 20px; overflow-y: auto; }
.ip-label { font-size: .78em; font-weight: 600; color: var(--c-text-muted); letter-spacing: .05em; margin-bottom: 10px; text-transform: uppercase; }
.ip-label .count { background: #7C3AED; color: #fff; border-radius: 50%; min-width: 20px; height: 20px; display: inline-flex; align-items: center; justify-content: center; font-size: .75em; margin-left: 4px; }
.ip-content { font-size: .95em; line-height: 1.9; text-align: justify; }
.ip-content p { text-indent: 2em; margin-bottom: 6px; }
.ip-content p:last-child { margin-bottom: 0; }
.ip-content mark { background: #E9E0D4; border-bottom: 2px solid var(--c-accent); padding: 0 1px; }
.ip-list { display: flex; flex-direction: column; gap: 6px; }
/* ── 导入阅读：解析结果预览（2026-09-20）──
   解析完先给人看，确认了才入库（与上面小说词汇预览是两个独立弹窗）。 */
.imp-prev-overlay { position: fixed; inset: 0; background: rgba(41,37,36,.5); z-index: 320;
  display: none; align-items: center; justify-content: center; backdrop-filter: blur(4px); }
.imp-prev-overlay.show { display: flex; }
.imp-prev-card { background: var(--c-bg-card); border-radius: var(--radius-lg); box-shadow: var(--shadow-lg);
  width: min(720px, calc(100vw - 32px)); max-height: calc(100vh - 32px);
  display: flex; flex-direction: column; overflow: hidden; }
.imp-prev-head { display: flex; align-items: center; gap: 10px; padding: 13px 18px;
  border-bottom: 1px solid var(--c-border); background: linear-gradient(180deg, #F5EFE4, var(--c-bg-card)); }
.imp-prev-kicker { font-weight: 700; color: var(--c-accent-deep); font-size: .88em; letter-spacing: .04em; }
.imp-prev-stat { flex: 1; text-align: right; font-size: .78em; color: var(--c-text-muted); }
.imp-prev-x { background: none; border: none; color: var(--c-text-muted); font-size: 1.3em; line-height: 1;
  cursor: pointer; padding: 2px 8px; border-radius: var(--radius-sm); }
.imp-prev-x:hover { background: #FBEDE8; color: var(--c-danger); }
.imp-prev-title { margin: 16px 18px 6px; font-size: 1.1em; font-weight: 700; color: var(--c-text); line-height: 1.5; }
.imp-prev-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 0 18px 8px; }
.imp-prev-lab { font-size: .74em; font-weight: 700; color: var(--c-text-muted); letter-spacing: .08em;
  margin: 14px 0 8px; display: flex; align-items: center; gap: 8px; }
.imp-prev-lab::after { content: ''; flex: 1; height: 1px; background: var(--c-border); }
.imp-prev-p { font-size: .93em; line-height: 1.85; color: var(--c-text-secondary); margin: 0 0 9px; text-align: justify; }
.imp-prev-q { border: 1px solid var(--c-border); border-radius: 16px; padding: 11px 13px; margin-bottom: 10px; background: #FFFCF8; }
html.dark .imp-prev-q { background: #2E2924; }
.imp-prev-qn { display: inline-block; min-width: 20px; font-weight: 700; color: var(--c-accent-deep); margin-right: 5px; }
.imp-prev-stem { font-size: .93em; font-weight: 600; color: var(--c-text); margin: 0 0 7px; line-height: 1.6; }
.imp-prev-opt { font-size: .9em; color: var(--c-text-secondary); line-height: 1.7; margin: 2px 0; padding-left: 3px; }
.imp-prev-opt em { font-style: normal; font-weight: 700; color: var(--c-accent-deep); margin-right: 5px; }
/* 答案点选（2026-09-20）：照片里一般不会有答案，预览时让用户自己点字母补上。
   识别到答案的（txt/docx）会预选中，也能顺手改。
   （原来的 `.imp-prev-ans` / `.imp-prev-ans.none` 两行静态文字已随手删掉 —— 答案行现在一律是可点选的按钮） */
.imp-prev-ansbar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 9px;
  padding-top: 8px; border-top: 1px dashed var(--c-border); }
.imp-prev-anslab { font-size: .8em; font-weight: 700; color: var(--c-text-muted); flex-shrink: 0; }
.imp-prev-chips { display: flex; gap: 6px; flex-wrap: wrap; }
.imp-chip { min-width: 34px; height: 30px; padding: 0 9px; border-radius: 9px; cursor: pointer;
  border: 1px solid var(--c-border); background: #fff; color: var(--c-text-secondary);
  font: inherit; font-size: .84em; font-weight: 700; line-height: 1;
  transition: all var(--transition-fast); }
.imp-chip:hover { border-color: var(--c-accent); color: var(--c-accent-deep); background: #FFFCF8; }
.imp-chip.on { background: #62764E; border-color: transparent; color: #fff;
  box-shadow: 0 3px 10px rgba(90,110,69,.28); }
.imp-chip-clear { font-weight: 600; color: var(--c-text-muted); min-width: 0; }
.imp-chip-clear:hover { color: var(--c-danger); border-color: #E8B3A3; background: #FBEDE8; }
.imp-prev-ansraw { font-size: .78em; color: var(--c-text-muted); }
html.dark .imp-chip { background: #332E2A; border-color: #4A4034; color: var(--c-text-secondary); }
html.dark .imp-chip:hover { background: #2E2620; color: #E9E0D4; border-color: #7A5A2F; }
html.dark .imp-chip.on { background: #646046; color: #3F2D24; }
.imp-prev-tips:empty { display: none; }
.imp-prev-tips { padding: 0 18px; }
.imp-prev-tip { font-size: .82em; color: #4A3229; background: #F5EFE4; border: 1px solid #E9E0D4;
  border-radius: 16px; padding: 8px 11px; margin: 0 0 8px; line-height: 1.6; }
html.dark .imp-prev-tip { background: #262019; border-color: #3A322C; color: #D4A373; }
.imp-prev-btns { display: flex; gap: 10px; padding: 14px 18px 16px; border-top: 1px solid var(--c-border); }
.imp-prev-btns button { flex: 1; height: 44px; border-radius: 18px; font-size: .92em; font-weight: 600; cursor: pointer;
  transition: all var(--transition-normal); }
.imp-prev-cancel { background: #F5F0E6; color: var(--c-text-secondary); border: 1px solid transparent; }
.imp-prev-cancel:hover { background: #EFE7DA; color: var(--c-text); }
.imp-prev-ok { background: #62764E; color: #fff; border: none;
  box-shadow: 0 6px 16px rgba(90,110,69,.28); }
.imp-prev-ok:hover { transform: translateY(-1px); box-shadow: 0 10px 22px rgba(90,110,69,.34); }
.imp-prev-ok:active { transform: translateY(0) scale(.98); }
@media (max-width: 420px) {
  .imp-prev-title { font-size: 1rem; margin: 12px 14px 4px; }
  .imp-prev-body { padding: 0 14px 6px; }
  .imp-prev-tips { padding: 0 14px; }
  .imp-prev-btns { padding: 12px 14px 14px; gap: 8px; }
  /* 手机竖向本来就紧张：提示条占的是"题目可滚动区"的高度，收紧一点把空间还给题目（2026-09-20） */
  .imp-prev-tip { font-size: .78em; padding: 7px 10px; margin-bottom: 6px; line-height: 1.5; }
}
.ip-item { display: flex; align-items: center; gap: 8px; padding: 7px 10px; border-radius: var(--radius-sm); border: 1px solid var(--c-border); background: #FAFAF9; font-size: .84em; }
.ip-item input { accent-color: #8B9D77; }
.ip-item .iw { font-weight: 600; color: var(--c-text); flex-shrink: 0; min-width: 110px; }
.ip-item .im { color: var(--c-text-muted); font-size: .8em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ip-empty { text-align: center; padding: 40px 16px; color: var(--c-text-muted); font-size: .85em; }
.ip-loading { text-align: center; padding: 40px 16px; color: var(--c-text-muted); font-size: .85em; }
@media (max-width: 768px), html.force-phone {
  .import-preview-body { flex-direction: column; }
  .import-preview-left { border-right: none; border-bottom: 1px solid var(--c-border); max-height: 40vh; }
  .import-preview-right { width: 100%; }
}

/* Story Read Page */
.story-read-area { flex: 1; min-width: 0; background: var(--c-bg-reading); border-radius: var(--radius-md); padding: 40px 48px; box-shadow: var(--shadow-sm); border: 1px solid var(--c-border); }
.story-read-area .story-read-title { font-size: 1.25em; font-weight: 700; margin-bottom: 20px; color: var(--c-primary-dark); padding-bottom: 14px; border-bottom: 1px solid var(--c-border); letter-spacing: -.01em; }
.story-read-area .story-read-body { line-height: 2; text-align: justify; }
.story-read-area .story-read-body p { text-indent: 2em; margin-bottom: 2px; font-size: 1.02em; letter-spacing: .005em; }
.story-read-area .word { cursor: pointer; transition: all .1s; border-radius: 3px; padding: 0 1px; }
.story-read-area .word:hover { background: var(--c-accent-light); }
.story-read-area .word.story-vocab { background: #E9E0D4; border-bottom: 2px solid var(--c-accent); }
.story-read-area .word.story-vocab:hover { background: #E9E0D4; }
.story-vocab-sidebar { width: 280px; flex-shrink: 0; position: sticky; top: 80px; align-self: flex-start; max-height: calc(100vh - 96px); overflow-y: auto; }
.story-vocab-panel { background: var(--c-white); border-radius: var(--radius-md); padding: 20px; box-shadow: var(--shadow-sm); border: 1px solid var(--c-border); }
.story-source-overlay { position: fixed; inset: 0; z-index: 620; display: none; align-items: center; justify-content: center; padding: 20px; background: rgba(41,37,36,.48); backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); }
.story-source-overlay.show { display: flex; }
.story-source-dialog { position: relative; width: min(520px, 100%); padding: 28px; border: 1px solid rgba(90,110,69,.15); border-radius: 22px; background: #F8F4EE; box-shadow: 0 24px 64px rgba(120,113,108,.22), 0 4px 16px rgba(0,0,0,.08); animation: storySourceIn .22s cubic-bezier(.22,.8,.32,1) both; }
@keyframes storySourceIn { from { opacity: 0; transform: translateY(10px) scale(.98); } to { opacity: 1; transform: translateY(0) scale(1); } }
.story-source-close { position: absolute; top: 14px; right: 14px; width: 36px; height: 36px; display: inline-flex; align-items: center; justify-content: center; border: 1px solid transparent; border-radius: 16px; background: transparent; color: var(--c-text-muted); cursor: pointer; }
.story-source-close:hover, .story-source-close:focus-visible { border-color: var(--c-border); background: rgba(255,255,255,.7); color: var(--c-text); outline: none; }
.story-source-close svg { width: 17px; height: 17px; }
.story-source-heading { display: flex; align-items: center; gap: 13px; padding-right: 30px; margin-bottom: 22px; }
.story-source-mark { width: 44px; height: 44px; flex: 0 0 44px; display: inline-flex; align-items: center; justify-content: center; border-radius: 14px; background: #E9E0D4; color: #5C4033; }
.story-source-mark svg { width: 25px; height: 25px; }
.story-source-heading h3 { margin: 0 0 5px; color: var(--c-text); font-family: 'Noto Serif SC', serif; font-size: 1.15em; font-weight: 700; letter-spacing: .03em; }
.story-source-heading p { margin: 0; color: var(--c-text-muted); font-size: .78em; line-height: 1.55; }
.story-source-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.story-source-option { min-height: 76px; display: flex; align-items: center; gap: 10px; padding: 12px; border: 1px solid var(--c-border); border-radius: 14px; background: rgba(255,255,255,.7); color: var(--c-text); text-align: left; cursor: pointer; transition: transform .18s ease, border-color .18s ease, box-shadow .18s ease, background .18s ease; }
.story-source-option:hover, .story-source-option:focus-visible { transform: translateY(-2px); border-color: currentColor; box-shadow: 0 8px 18px rgba(120,113,108,.1); outline: none; }
.story-source-icon { width: 34px; height: 34px; flex: 0 0 34px; display: inline-flex; align-items: center; justify-content: center; border-radius: 16px; background: currentColor; color: #fff; }
.story-source-icon svg { width: 19px; height: 19px; }
.story-source-copy { min-width: 0; display: flex; flex: 1; flex-direction: column; gap: 3px; }
.story-source-copy strong { font-size: .9em; font-weight: 700; }
.story-source-copy small { overflow: hidden; color: var(--c-text-muted); font-size: .68em; text-overflow: ellipsis; white-space: nowrap; }
.story-source-arrow { font-size: .7em; font-weight: 700; opacity: .75; }
.source-kaoyan { color: #5C4033; }
.source-gaokao { color: #5A6E96; }
.source-cet4 { color: #12725B; }
.source-cet6 { color: #8B9D77; }
.story-source-cancel { width: 100%; min-height: 42px; margin-top: 16px; border: 1px solid var(--c-border); border-radius: 11px; background: transparent; color: var(--c-text-muted); cursor: pointer; font-size: .82em; }
.story-source-cancel:hover, .story-source-cancel:focus-visible { background: rgba(255,255,255,.7); color: var(--c-text); outline: none; }
html.dark .story-source-dialog { background: #2C2622; border-color: rgba(163,185,140,.2); box-shadow: 0 24px 64px rgba(0,0,0,.45); }
html.dark .story-source-option { background: rgba(51,46,42,.72); }
html.dark .story-source-close:hover, html.dark .story-source-close:focus-visible, html.dark .story-source-cancel:hover, html.dark .story-source-cancel:focus-visible { background: rgba(255,255,255,.06); }
@media (max-width: 480px) { .story-source-dialog { padding: 22px 16px 16px; border-radius: 18px; } .story-source-heading { gap: 10px; margin-bottom: 16px; } .story-source-mark { width: 38px; height: 38px; flex-basis: 38px; border-radius: 18px; } .story-source-grid { gap: 8px; } .story-source-option { min-height: 70px; padding: 9px; gap: 7px; } .story-source-icon { width: 30px; height: 30px; flex-basis: 30px; } .story-source-icon svg { width: 17px; height: 17px; } .story-source-copy small { font-size: .62em; } }
.story-word-source-native { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.story-import-source-panel { margin: 14px 0 12px; padding: 14px; border: 1px solid rgba(90,110,69,.13); border-radius: 16px; background: rgba(255,253,247,.72); }
.story-import-source-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 11px; }
.story-import-source-head > div { display: flex; align-items: baseline; gap: 9px; }
.story-import-source-head strong { color: var(--c-text); font-size: .86em; }
.story-import-source-head span { color: var(--c-text-muted); font-size: .72em; }
.story-import-current { padding: 4px 8px; border-radius: 999px; background: #E9E0D4; color: #5C4033 !important; font-size: .68em !important; font-weight: 700; white-space: nowrap; }
.story-import-source-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 7px; }
.story-import-source-option { position: relative; min-height: 52px; display: flex; flex-direction: column; align-items: flex-start; justify-content: center; gap: 2px; padding: 8px 10px; border: 1px solid var(--c-border); border-radius: 11px; background: rgba(255,255,255,.74); color: var(--c-text-secondary); cursor: pointer; text-align: left; transition: border-color .18s ease, background .18s ease, transform .18s ease, box-shadow .18s ease; }
.story-import-source-option:hover, .story-import-source-option:focus-visible { transform: translateY(-1px); border-color: currentColor; box-shadow: 0 5px 12px rgba(120,113,108,.1); outline: none; }
.story-import-source-option strong { font-size: .8em; color: currentColor; }
.story-import-source-option small { color: var(--c-text-muted); font-size: .62em; }
.story-import-source-option .story-import-check { position: absolute; top: 6px; right: 7px; display: none; color: currentColor; font-size: .72em; font-weight: 800; }
.story-import-source-option.selected { border-color: currentColor; background: color-mix(in srgb, currentColor 9%, white); box-shadow: inset 0 0 0 1px currentColor; }
.story-import-source-option.selected .story-import-check { display: block; }
.story-import-source-option.source-kaoyan { color: #5C4033; }
.story-import-source-option.source-gaokao { color: #5A6E96; }
.story-import-source-option.source-cet4 { color: #12725B; }
.story-import-source-option.source-cet6 { color: #8B9D77; }
html.dark .story-import-source-panel { border-color: rgba(163,185,140,.18); background: rgba(47,40,34,.7); }
html.dark .story-import-source-option { background: rgba(51,46,42,.72); }
html.dark .story-import-source-option.selected { background: color-mix(in srgb, currentColor 17%, #332E2A); }
@media (max-width: 520px) { .story-import-source-panel { padding: 12px 10px; } .story-import-source-head { align-items: flex-start; flex-direction: column; gap: 6px; } .story-import-source-head > div { gap: 7px; } .story-import-current { align-self: flex-start; } .story-import-source-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 7px; } .story-import-source-option { min-height: 48px; } }
.story-vocab-panel h3 { font-size: .9em; font-weight: 600; margin-bottom: 14px; color: var(--c-text); display: flex; align-items: center; gap: 8px; }
.story-vocab-panel h3 .count { background: #7C3AED; color: var(--c-white); border-radius: 50%; min-width: 22px; height: 22px; display: flex; align-items: center; justify-content: center; font-size: .75em; font-weight: 600; }
.story-vocab-list { max-height: 55vh; overflow-y: auto; }
.story-vocab-item { position: relative; padding: 9px 0; border-bottom: 1px solid #F5F5F4; font-size: .85em; }
.story-vocab-item:last-child { border-bottom: none; }
.story-vocab-item .sw { font-weight: 600; color: var(--c-text); display: block; margin-bottom: 2px; }
.story-vocab-item .sm { color: var(--c-text-muted); font-size: .82em; line-height: 1.6; display: block; }
.story-vocab-item .sbtn { background: none; color: var(--c-accent); font-size: .78em; padding: 2px 8px; border-radius: var(--radius-sm); border: 1px solid var(--c-accent-light); position: absolute; top: 9px; right: 0; cursor: pointer; }
.story-vocab-item .sbtn:hover { background: var(--c-accent-light); }
.story-vocab-item .sbtn.done { color: var(--c-text-muted); border-color: var(--c-border); pointer-events: none; }

/* Story Bookmarks */
.story-read-body .story-para { position: relative; }
.story-read-body .story-para p { text-indent: 2em; margin-bottom: 2px; font-size: 1.02em; letter-spacing: .005em; }
.story-bm-btn { position: absolute; left: -30px; top: 6px; background: none; border: none; color: var(--c-text-muted); opacity: 0; cursor: pointer; padding: 4px; border-radius: 4px; display: flex; align-items: center; transition: all .15s ease; line-height: 0; }
.story-para:hover .story-bm-btn { opacity: .55; }
.story-bm-btn:hover { opacity: 1; color: var(--c-accent); }
.story-bm-btn.on { opacity: 1; color: var(--c-accent); }
.story-bm-btn svg { width: 15px; height: 15px; }
.story-para.bm-flash { animation: bmFlash 1.6s ease; border-radius: var(--radius-sm); }
@keyframes bmFlash { 0% { background: rgba(90,110,69,.22); } 100% { background: transparent; } }
.story-bm-panel { margin-top: 16px; }
.story-bm-list { max-height: 40vh; overflow-y: auto; }
.story-bm-item { position: relative; display: flex; align-items: center; gap: 8px; padding: 7px 22px 7px 8px; border-radius: var(--radius-sm); font-size: .82em; cursor: pointer; transition: background .15s; margin-bottom: 2px; }
.story-bm-item:hover { background: #F5EFE4; }
.story-bm-item .bm-pi { width: 22px; height: 22px; border-radius: 50%; background: #E9E0D4; color: #5C4033; font-size: .72em; font-weight: 600; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.story-bm-item .bm-text { color: var(--c-text-secondary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.story-bm-item .bm-del { position: absolute; right: 4px; top: 50%; transform: translateY(-50%); background: none; border: none; color: var(--c-border); font-size: 1em; cursor: pointer; padding: 2px 6px; border-radius: 3px; opacity: 0; line-height: 1; transition: all .15s; }
.story-bm-item:hover .bm-del { opacity: 1; }
.story-bm-item .bm-del:hover { color: var(--c-danger); background: #FBEDE8; }

/* Login Modal */
.login-overlay { position: fixed; inset: 0; background: rgba(41,37,36,.55); z-index: 500; display: none; align-items: center; justify-content: center; backdrop-filter: blur(8px); }
.login-overlay.show { display: flex; }
.login-card {
  background: #F6F2EB;
  border-radius: 24px;
  padding: 48px 42px 38px;
  max-width: 400px; width: 90%;
  box-shadow: 0 20px 60px rgba(120,113,108,.18), 0 2px 12px rgba(0,0,0,.04), inset 0 1px 0 rgba(255,255,255,.8);
  border: 1px solid rgba(90,110,69,.1);
  position: relative;
  overflow: hidden;
  animation: loginCardIn .5s cubic-bezier(.25,.8,.25,1) both;
}
.login-card::before {
  content: ''; position: absolute; top: 0; left: 0; right: 0; height: 4px;
  background: #828F6E;
  border-radius: 24px 24px 0 0;
}
.login-card::after {
  content: ''; position: absolute; bottom: 32px; left: 50%; transform: translateX(-50%);
  width: 60px; height: 2px;
  background: linear-gradient(90deg, transparent, rgba(90,110,69,.2), transparent);
}
@keyframes loginCardIn { from { opacity: 0; transform: translateY(24px) scale(.96); } to { opacity: 1; transform: translateY(0) scale(1); } }
.login-card h2 {
  font-family: 'Noto Serif SC', serif; font-size: 1.4em; font-weight: 700;
  color: #5C4033; margin-bottom: 4px; letter-spacing: .06em;
}
.login-card .field { margin-bottom: 18px; text-align: left; animation: loginFieldIn .4s ease both; }
.login-card .field:nth-child(3) { animation-delay: .08s; }
.login-card .field:nth-child(4) { animation-delay: .14s; }
.login-card .field:nth-child(5) { animation-delay: .2s; }
@keyframes loginFieldIn { from { opacity: 0; transform: translateX(-8px); } to { opacity: 1; transform: translateX(0); } }

/* ── Slim Scrollbars ── */
* { scrollbar-width: thin; scrollbar-color: #C9BFB0 transparent; }
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: #C9BFB0; border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: #B3A793; }
/* 阅读选择面板滚动条更细 */
.reading-picker { scrollbar-gutter: stable; }
.reading-picker::-webkit-scrollbar, .reading-picker .rp-results::-webkit-scrollbar { width: 6px; }
.reading-picker::-webkit-scrollbar-track, .reading-picker .rp-results::-webkit-scrollbar-track { background: transparent; }
.reading-picker::-webkit-scrollbar-thumb, .reading-picker .rp-results::-webkit-scrollbar-thumb { background: #D8CFBE; border-radius: 4px; border: 2px solid #FFFCF8; background-clip: padding-box; min-height: 36px; }
.reading-picker::-webkit-scrollbar-thumb:hover, .reading-picker .rp-results::-webkit-scrollbar-thumb:hover { background: #C9BFB0; border: 2px solid #FFFCF8; background-clip: padding-box; }
.login-card .field label {
  display: block; font-size: .78em; color: var(--c-text-secondary);
  margin-bottom: 6px; font-weight: 500; letter-spacing: .03em;
}
.login-card .field input {
  width: 100%; padding: 13px 16px;
  border: 1.5px solid rgba(120,113,108,.12);
  border-radius: 18px; font-size: .92em; outline: none; font: inherit;
  background: rgba(255,253,245,.6);
  transition: all .25s ease;
  box-shadow: inset 0 1px 3px rgba(0,0,0,.03);
}
.login-card .field input:focus {
  border-color: var(--c-accent);
  box-shadow: 0 0 0 4px rgba(90,110,69,.06), inset 0 1px 3px rgba(0,0,0,.03);
  background: var(--c-white);
}
.login-card .btn-login {
  width: 100%; padding: 13px; border-radius: 14px; font-size: .95em; font-weight: 600;
  background: #5B573C;
  color: #fff; margin-top: 10px; letter-spacing: .08em;
  box-shadow: 0 4px 16px rgba(90,110,69,.22);
  transition: all .3s cubic-bezier(.25,.8,.25,1);
  animation: loginFieldIn .4s .26s ease both;
  position: relative;
  overflow: hidden;
}
.login-card .btn-login::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(135deg, transparent 40%, rgba(255,255,255,.15) 50%, transparent 60%);
  transform: translateX(-100%); transition: transform .6s ease;
}
.login-card .btn-login:hover::after { transform: translateX(100%); }
.login-card .btn-login:hover { transform: translateY(-2px); box-shadow: 0 8px 24px rgba(90,110,69,.32); }
.login-card .btn-login:disabled { opacity: .5; cursor: not-allowed; transform: none; box-shadow: none; }
.login-card .btn-login:disabled::after { display: none; }
.login-card .login-error { color: var(--c-danger); font-size: .8em; margin-top: 14px; min-height: 1.2em; text-align: center; }
.login-card .login-close {
  position: absolute; top: 14px; right: 16px;
  background: none; color: var(--c-text-muted); font-size: 1.15em;
  padding: 4px 10px; border-radius: 16px; transition: all .2s;
}
.login-card .login-close:hover { background: rgba(0,0,0,.04); color: var(--c-text); }
.theme-toggle-label { font-size: .82em; color: var(--c-text-muted); letter-spacing: .06em; }

/* ── 暗夜模式 ── */
html.dark {
  --c-primary: #A8A29E;
  --c-primary-light: #78716C;
  --c-primary-dark: #E7E5E4;
  /* 2026-09-26 换色：暗色下的强调色从琥珀 #F59E0B 改鼠尾草族。
     ⚠ 这里必须是**亮**鼠尾草 #A3B98C 而不是浅色模式那个深鼠尾草 #5A6E45 ——
       暗底上它主要当**文字色**用（激活态文字/链接），#5A6E45 在 #1C1917 上只有 3.6:1，
       不达正文 4.5:1；#A3B98C = 7.4:1。 */
  --c-accent: #A3B98C;
  --c-accent-deep: #D4A373;
  --c-accent-hover: #8B9D77;
  --c-accent-light: #5C4033;
  --c-bg: #1C1917;
  --c-bg-card: #292524;
  --c-bg-reading: #26211E;
  --c-text: #EDE9E6;
  --c-text-secondary: #A8A29E;
  --c-text-muted: #9A9086;   /* 原 #8A8582 在 #1C1917 上只有 ~4.4:1，提亮到 5.0:1 */
  --c-border: #3F3A37;
  --c-success: #A3B98C;
  --c-danger: #E08B76;
  --c-white: #292524;
  --c-toast-bg: #3F739F;   /* 暗色下同一个蓝：#1C1917 上足够跳出来，白字 5.04:1 */
  --c-toast-fg: #FFFFFF;
  --c-toast-bd: rgba(255,255,255,.18);
}
html.dark .home { background: #0C1225; }
html.dark .home h1 { color: #EDE9E6; }
html.dark .card { background: #282422; border-color: rgba(255,255,255,.07); box-shadow: 0 1px 3px rgba(0,0,0,.3), 0 4px 12px rgba(0,0,0,.3); }
html.dark .card:hover { border-color: rgba(255,255,255,.18); box-shadow: 0 8px 30px rgba(0,0,0,.4); }
html.dark .csm-btn.active { background: #3D3833; color: var(--c-accent); box-shadow: 0 1px 4px rgba(0,0,0,.4); }
html.dark .card.cet .csm-btn.active { color: #9FBFB6; }
html.dark .card.gaokao .csm-btn.active { color: #A8B8D8; }
html.dark .card.kaoyan .card-icon { background: #342C26; color: #D4A373; }
html.dark .card.cet .card-icon { background: #293531; color: #9FBFB6; }
html.dark .card.gaokao .card-icon { background: #29303C; color: #A8B8D8; }
html.dark .card.basic .card-icon { background: #332F2B; color: #C9C1B8; }
html.dark .card.story .card-icon { background: #382926; color: #D3A99E; }
html.dark .card.kaoyan .card-badge { background: #2E2620; color: #D4A373; }
html.dark .card.cet .card-badge { background: #24302C; color: #9FBFB6; }
html.dark .card.gaokao .card-badge { background: #242A35; color: #A8B8D8; }
html.dark .card.basic .card-badge { background: #383430; color: #C9C1B8; }
html.dark .card.story .card-badge { background: #3D2E2B; color: #D3A99E; }
html.dark .icp-footer a { color: var(--c-text-muted); }
html.dark .topbar { background: rgba(41,37,36,.55); box-shadow: 0 8px 32px rgba(0,0,0,.4); }
html.dark .topbar .back:hover, html.dark .topbar .btn:hover { background: rgba(255,255,255,.08); }
html.dark .topbar .info, html.dark .topbar .back svg { text-shadow: none; filter: none; }
/* 2026-09-27：暗色下的暖黄渐变覆盖已删 —— .topbar .btn-hot 现在全走主题令牌，两个主题自动跟随 */
html.dark .reading-area { box-shadow: 0 4px 20px rgba(0,0,0,.35); }
html.dark .q-option { color: var(--c-text-secondary); }
html.dark .q-option:hover::before { background: rgba(79,107,54,.12); }
html.dark .q-option.selected::before { background: rgba(79,107,54,.2); }
html.dark .q-box { background: #2A2623; }
html.dark .q-my-ans, html.dark .bottom-section, html.dark .full-trans { color: var(--c-text-secondary); }
html.dark .reading-area ::selection, html.dark .float-q-body ::selection, html.dark #trainPage ::selection { background: rgba(16,185,129,.42); color: #FFF; }
html.dark .vocab-panel { background: #292524; border-color: #3F3A37; box-shadow: 0 4px 20px rgba(0,0,0,.3); }
html.dark .vocab-item { border-bottom-color: #3F3A37; }
html.dark .vocab-item .w { color: var(--c-text); }
html.dark .vocab-item .m { color: var(--c-text-muted); }
html.dark .vocab-actions button { background: #332E2A; border-color: #3F3A37; color: var(--c-text-secondary); }
html.dark .vocab-actions button:hover { background: #3D3833; }
html.dark .vocab-actions .vocab-merge-btn:hover { color: #BEF264; border-color: #4D7C0F; background: rgba(101,163,13,.14); }
html.dark .vocab-actions .vocab-clear:hover { color: var(--c-danger); border-color: rgba(248,113,113,.4); background: rgba(220,38,38,.12); }
html.dark .vl-item { border-bottom-color: #3F3A37; }
html.dark .vl-item .vl-word { color: var(--c-text); }
html.dark .vl-item .vl-meaning { color: var(--c-text-muted); }
html.dark .vl-del { color: var(--c-text-muted); }
html.dark .vl-del:hover { color: var(--c-danger); background: rgba(166,61,42,.12); }
html.dark .reading-area .instruction { background: #292524; color: #EDE9E6; border-left-color: var(--c-accent); }
html.dark .reading-area .instruction[style*="F0FDF4"] { background: #292524 !important; border-left-color: #65A30D !important; color: #EDE9E6; }
html.dark .popover { background: #2A2623; box-shadow: 0 24px 60px rgba(0,0,0,.5); }
html.dark .modal, html.dark .clear-modal { background: #2A2623; box-shadow: 0 24px 64px rgba(0,0,0,.5); }
html.dark .add-modal { background: #282422; border-color: rgba(90,110,69,.2); box-shadow: 0 24px 64px rgba(0,0,0,.5); }
html.dark .add-btn-cancel { background: #332E2A; color: var(--c-text-secondary); }
html.dark .add-btn-cancel:hover { background: #3D3833; color: var(--c-text); }
html.dark .clear-modal .btn-cancel-confirm { background: #332E2A; color: var(--c-text-secondary); border-color: #3F3A37; }
html.dark .clear-modal .btn-cancel-confirm:hover { background: #3D3833; }
html.dark .modal .btn-row button, html.dark .donate-card .btn-row button { border-color: #3F3A37; }
html.dark .login-card { background: #26221F; box-shadow: 0 20px 60px rgba(0,0,0,.55); border-color: rgba(90,110,69,.16); }
html.dark .login-card .field input { background: rgba(255,255,255,.05); border-color: #3F3A37; color: var(--c-text); }
html.dark .login-card .field input:focus { border-color: var(--c-accent); box-shadow: 0 0 0 3px rgba(90,110,69,.16); }
html.dark .login-card .login-close:hover { background: rgba(255,255,255,.08); color: var(--c-text); }
html.dark .btn-outline { background: #2A2623; color: var(--c-text-secondary); border-color: #3F3A37; }
html.dark .btn-outline:hover { background: #332E2A; color: var(--c-text); }
html.dark .vp-btn-outline { background: #2A2623; color: var(--c-text-secondary); border-color: #3F3A37; }
html.dark .vp-btn-outline:hover { background: #332E2A; border-color: var(--c-accent); color: var(--c-accent); }
html.dark .radio-group { background: #332E2A; }
html.dark .radio-group .rg-slider { background: #4B4642; }
html.dark .radio-option input:checked + .radio-label { color: var(--c-text); }
html.dark .train-options .q-option:hover::before { background: rgba(79,107,54,.12); }
html.dark .train-options .q-option.selected::before { background: rgba(79,107,54,.2); }
html.dark .train-type-modal { background: #2A2623; border-color: #3F3A37; box-shadow: 0 16px 40px rgba(0,0,0,.5), 0 30px 80px rgba(0,0,0,.55); }
html.dark .train-type-modal .ttm-head { border-bottom-color: #3F3A37; }
html.dark .train-type-modal .ttm-head h3 { color: #EDE9E6; }
html.dark .train-type-modal .ttm-close:hover { background: #3D3833; color: #EDE9E6; }
html.dark .train-type-tag { background: #2F3546; color: #A9BFE0; }
html.dark .train-type-card:hover { border-color: rgba(130,160,200,.5); box-shadow: 0 8px 20px rgba(0,0,0,.4); }
html.dark .train-sentence { background: #202832; border-color: rgba(120,150,190,.2); box-shadow: 0 1px 2px rgba(0,0,0,.3); }
html.dark .train-sentence-label { color: #8FA8C8; }
html.dark .train-sentence-text b, html.dark .train-sentence-text .kw { color: #D4A373; background: rgba(90,110,69,.12); }
html.dark .train-qtag { background: #2F3546; color: #A9BFE0; }
html.dark .train-type-chip { color: #A9BFE0; }
html.dark .train-type-chip-dot { box-shadow: 0 0 0 3px rgba(79,107,54,.28); }
html.dark .train-opt-trans { background: #1F2B3D; color: #7FB2E8; border-color: #2E4664; }
html.dark .train-opt-trans:hover { background: #2E6DB4; color: #fff; border-color: #2E6DB4; }
html.dark .rt-btn { background: #14532D; box-shadow: inset -1px 1px 4px 0px rgba(240,253,244,.08), inset 1px -1px 4px 0px #166534, -1px 2px 4px 0px rgba(34,197,94,.25); }
html.dark .rt-btn .rt-aa { color: #BBF7D0; }
html.dark .rt-btn .rt-inner { background: #166534; box-shadow: inset -1px 1px 4px 0px rgba(240,253,244,.1), inset 1px -1px 4px 0px #22C55E, -1px 1px 2px 0px rgba(34,197,94,.3); }
/* 暗色下的「已打开」态：与浅色同一套表达（实心描边 + 不透明文字），只是换成暗色的绿 */
html.dark .rt-btn.open { background: #166534; box-shadow: inset -1px 1px 4px 0px rgba(240,253,244,.1), inset 1px -1px 4px 0px #22C55E, -1px 2px 4px 0px rgba(34,197,94,.3); }
html.dark .rt-btn.open .rt-aa { opacity: 1; color: #DCFCE7; }
html.dark .train-type-icon { background: #29303F; color: #A9BFE0; }
html.dark .q-toggle-switch .slider { background-color: #3F3A37; box-shadow: 0 0.2em #332E2A; }
html.dark .q-toggle-switch .slider::before { background-color: #5A6E45; box-shadow: 0 0.4em #3F2D24; }
html.dark .q-toggle-switch .slider:hover::before { box-shadow: 0 0.2em #3F2D24; }
html.dark .trans-overlay{ background: #2A2623; }
html.dark .annotate-toolbar { background: #2A2623; border-color: #3F3A37; }
html.dark .annotate-btn-dropdown { background: #2A2623; border-color: #3F3A37; box-shadow: 0 20px 50px rgba(0,0,0,.5); }
html.dark .annotate-btn-dropdown .tool-size, html.dark .annotate-btn-dropdown .tool-eraser { background: #332E2A; border-color: #3F3A37; color: var(--c-text-muted); }
html.dark .annotate-btn-dropdown .tool-clear { background: rgba(220,38,38,.15); color: var(--c-danger); }
html.dark .annotate-btn-dropdown .tool-undo { background: #332E2A; border-color: #3F3A37; color: var(--c-text-secondary); }
html.dark .annotate-toolbar .tool-size, html.dark .train-annotate-toolbar .tool-size, html.dark .annotate-btn-dropdown .tool-size, html.dark .ab-tools .tool-size, html.dark .fab-toolbar .tool-size { background: #332E2A; border-color: #3F3A37; color: var(--c-text-muted); }
html.dark .annotate-toolbar .tool-size.sel-pen, html.dark .train-annotate-toolbar .tool-size.sel-pen, html.dark .annotate-btn-dropdown .tool-size.sel-pen, html.dark .ab-tools .tool-size.sel-pen, html.dark .fab-toolbar .tool-size.sel-pen { background: #4A3417; border-color: var(--c-accent); color: #FDE68A; box-shadow: 0 0 0 1px rgba(217,119,6,.3); }
html.dark .annotate-toolbar .tool-size.sel-eraser, html.dark .train-annotate-toolbar .tool-size.sel-eraser, html.dark .annotate-btn-dropdown .tool-size.sel-eraser, html.dark .ab-tools .tool-size.sel-eraser, html.dark .fab-toolbar .tool-size.sel-eraser { background: #3D2020; border-color: #F87171; color: #FCA5A5; box-shadow: 0 0 0 1px rgba(248,113,113,.3); }
html.dark .annotate-toolbar .tool-label.active, html.dark .train-annotate-toolbar .tool-label.active, html.dark .annotate-btn-dropdown .tool-label.active, html.dark .ab-tools .tool-label.active, html.dark .fab-toolbar .tool-label.active { color: #FDE68A; }
html.dark .annotate-toolbar .tool-label-eraser.active, html.dark .train-annotate-toolbar .tool-label-eraser.active, html.dark .annotate-btn-dropdown .tool-label-eraser.active, html.dark .ab-tools .tool-label-eraser.active, html.dark .fab-toolbar .tool-label-eraser.active { color: #FCA5A5; }
html.dark .annotate-toolbar button.sel, html.dark .train-annotate-toolbar button.sel, html.dark .annotate-btn-dropdown button.sel, html.dark .ab-tools button.sel, html.dark .fab-toolbar button.sel { border-color: #FDE68A; }
/* ── 2026-09-27：标注工具条（吸顶在正文里）在暗色下跟随主题色；悬浮的 .fab-toolbar 仍走琥珀（已钉住）── */
html.dark .annotate-toolbar .tool-size.sel-pen, html.dark .annotate-btn-dropdown .tool-size.sel-pen, html.dark .ab-tools .tool-size.sel-pen {
  background: color-mix(in srgb, var(--c-accent) 22%, transparent); border-color: var(--c-accent); color: var(--c-accent); box-shadow: 0 0 0 1px color-mix(in srgb, var(--c-accent) 30%, transparent); }
html.dark .annotate-toolbar .tool-label.active, html.dark .annotate-btn-dropdown .tool-label.active, html.dark .ab-tools .tool-label.active { color: var(--c-accent); }
html.dark .annotate-toolbar button.sel, html.dark .annotate-btn-dropdown button.sel, html.dark .ab-tools button.sel { border-color: var(--c-accent); }
html.dark .annotate-bottomsheet .ab-panel { background: #2A2623; border-color: #3F3A37; box-shadow: 0 -4px 24px rgba(0,0,0,.5); }
html.dark .annotate-bottomsheet .ab-handle { color: var(--c-text-muted); }
html.dark .fab-toolbar { background: #2A2623; border-color: #3F3A37; box-shadow: 0 8px 24px rgba(0,0,0,.4); }
html.dark .float-q-card { background: #2A2623; border-color: #3F3A37; box-shadow: 0 24px 60px rgba(0,0,0,.5); }
html.dark .float-q-head { border-bottom-color: #3F3A37; }
html.dark .float-q-nav-btn { color: var(--c-text-muted); }
html.dark .float-q-nav-btn:hover { background: rgba(255,255,255,.07); }
html.dark .chat-layout { background: var(--c-bg); }
html.dark .ci-wrap input { background: #2A2623; border-color: #3F3A37; color: var(--c-text); }
html.dark .chat-msg.ai .bubble { background: #332E2A; color: var(--c-text); }
html.dark .topbar .btn-primary, html.dark .chat-msg.user .bubble, html.dark .chat-sidebar .sidebar-head button, html.dark .vocab-panel h3 .count, html.dark .popover .btn-add, html.dark .modal .btn-save, html.dark .story-vocab-panel h3 .count{ color: #fff; }
html.dark .chat-msg.user .bubble { background: #53392E; box-shadow: 0 2px 8px rgba(0,0,0,.3); }
/* 暗夜：留言浮层 面板头与留言卡片浅底修正 */
html.dark .fb-float-panel .fb-float-head { background: #2E2824; }
html.dark .fb-float-panel .fb-float-head button:hover { background: rgba(166,61,42,.14); color: #E8B3A3; }
html.dark .fb-float-card { background: #322D27; border-color: #3F3A37; }
html.dark .fb-float-card:hover { border-color: #57504A; }
html.dark .fb-float-card .fb-float-msg { color: #EDE9E6; }
html.dark .fb-float-card.cat-func .fb-float-cat { background: #3A322C; color: #D4A373; }
html.dark .fb-float-card.cat-ux .fb-float-cat, html.dark .fb-float-card.cat-data .fb-float-cat { background: #4A1F1F; color: #F2A5A5; }
html.dark .fb-float-card.cat-idea .fb-float-cat { background: #173A2A; color: #A7E3C1; }
html.dark .chat-sidebar { background: #1F1B18; border-right-color: rgba(90,110,69,.15); }
html.dark .session-item:hover { background: #332E2A; border-color: rgba(90,110,69,.12); }
html.dark .session-item.active { background: #332E2A; border-color: rgba(90,110,69,.22); box-shadow: 0 2px 8px rgba(0,0,0,.3); }
html.dark .session-item .sess-del { background: rgba(166,61,42,.20); color: var(--c-danger); border-color: rgba(224,139,118,.32); }
html.dark .session-item .sess-del:hover { background: var(--c-danger); color: #1C1917; border-color: var(--c-danger); }
html.dark .story-session-source { border-color: rgba(163,185,140,.28); color: #D4A373; background: rgba(120,72,18,.28); }
html.dark .chat-hint { background: #282422; border-color: rgba(90,110,69,.18); color: var(--c-text-secondary); }
html.dark .sg-btn:hover { background: #332E2A; border-color: var(--c-accent); color: var(--c-accent); }
html.dark .ci-wrap label { color: #A8A29E; }
html.dark .ci-wrap input:placeholder-shown + label { color: #78716C; }
html.dark .reading-picker { background: #292524; border-color: #3F3A37; box-shadow: 0 16px 40px rgba(0,0,0,.5), 0 30px 80px rgba(0,0,0,.55); }
html.dark .reading-picker .rp-head { border-bottom-color: #3F3A37; }
html.dark .reading-picker .rp-head h3 { color: #EDE9E6; }
html.dark .reading-picker .rp-count, html.dark .reading-picker .rp-close, html.dark .reading-picker .rp-empty, html.dark .reading-picker .rp-results-head, html.dark .reading-picker .rp-dd-caret { color: #A8A29E; }
html.dark .reading-picker .rp-close:hover { background: rgba(255,255,255,.08); color: #EDE9E6; }
html.dark .reading-picker .rp-dd-btn { border-color: #3F3A37; background: #262220; }
html.dark .reading-picker .rp-dd-btn:hover { border-color: #57534E; }
html.dark .reading-picker .rp-dd-lab { color: #A8A29E; }
html.dark .reading-picker .rp-dd-cur { color: #EDE9E6; }
html.dark .reading-picker .rp-dd-cur.on { color: #D4A373; }
html.dark .reading-picker .rp-dd-menu { border-color: #3F3A37; background: #292524; box-shadow: 0 8px 28px rgba(0,0,0,.5); }
html.dark .reading-picker .rp-dd-item { color: #D6D3D1; }
html.dark .reading-picker .rp-dd-item:hover { background: rgba(255,255,255,.07); color: #D4A373; }
html.dark .reading-picker .rp-dd-item.sel { color: #FBBF24; background: rgba(217,119,6,.18); }
html.dark .reading-picker .rp-random { background: #53392E; box-shadow: 0 3px 10px rgba(0,0,0,.35); }
html.dark .reading-picker .rp-item:hover { background: rgba(255,255,255,.06); }
html.dark .reading-picker .rp-item-title { color: #EDE9E6; }
html.dark .reading-picker .rp-tag { border-color: #3F3A37; color: #A8A29E; }
html.dark .reading-picker .rp-tag.diff-简单 { background: rgba(79,107,54,.14); color: #A8BC90; border-color: rgba(79,107,54,.3); }
html.dark .reading-picker .rp-tag.diff-中等 { background: rgba(90,110,69,.16); color: #D4A373; border-color: rgba(90,110,69,.32); }
html.dark .reading-picker .rp-tag.diff-困难 { background: rgba(166,61,42,.16); color: #E8B3A3; border-color: rgba(166,61,42,.32); }
html.dark .donate-card { background: #28241F; border-color: rgba(90,110,69,.18); box-shadow: 0 20px 60px rgba(0,0,0,.55); }
html.dark .donate-card .btn-row button { border-color: #3F3A37; }
html.dark .donate-card .btn-skip { background: #2A2623; color: var(--c-text-secondary); border-color: #3F3A37; }
html.dark .donate-card .btn-skip:hover { background: rgba(255,255,255,.06); color: var(--c-text); border-color: #57534E; }

/* ── 高频词高亮 ── */
.hf-switch {
  --icon-size: 1.3em;
  --anim-time: 0.2s;
  --base-radius: 9999px;
  display: flex; align-items: center; position: relative; cursor: pointer;
  font-size: 12px; font-weight: 500; user-select: none; height: 32px;
}
.hf-switch input { display: none; }
.hf-switch{ transition: all var(--anim-time); }
#readingContent .word.hf { background: linear-gradient(transparent 58%, rgba(163,185,140,.38) 58%); border-radius: 2px; }
.dict-freq { margin-top: 8px; font-size: .78em; color: var(--c-accent-deep); font-weight: 600; display: flex; align-items: center; gap: 5px; }
html.force-phone .hf-switch { font-size: 11px; }
.hf-group-modal { position: fixed; z-index: 400; display: none; }
.hf-group-modal.show { display: block; animation: hfModalIn .15s ease; }
.hf-group-panel { background: var(--c-bg-card); border-radius: 18px; padding: 8px; min-width: 190px; border: 1px solid var(--c-border); box-shadow: 0 12px 32px rgba(0,0,0,.14); }
@keyframes hfModalIn { from { transform: translateY(-6px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
.hf-group-title { font-size: .8em; font-weight: 600; color: var(--c-text-muted); margin-bottom: 6px; padding: 4px 10px 6px; text-align: left; letter-spacing: .04em; border-bottom: 1px solid var(--c-border); }
.hf-group-opts { display: flex; flex-direction: column; gap: 2px; }
.hf-group-opt { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 7px 10px; border-radius: 16px; border: none; background: transparent; color: var(--c-text); font-size: .84em; cursor: pointer; transition: all .12s; }
.hf-group-opt:hover { background: #F5EFE4; }
.hf-group-opt.sel { background: #FEF3C7; color: var(--c-accent-deep); font-weight: 600; }
.hf-group-opt span { font-size: .72em; color: var(--c-text-muted); font-weight: 400; }
.hf-group-opt.sel span { color: var(--c-accent); }
html.dark .hf-group-panel { background: #292524; border-color: #3F3A37; }
html.dark .hf-group-opt { background: transparent; color: #EDE9E6; }
html.dark .hf-group-opt:hover { background: #332E2A; }
html.dark .hf-group-opt.sel { background: #443018; color: #FCD9A8; }
html.dark .hf-group-title { border-bottom-color: #3F3A37; }

/* Uiverse 00Kubi radio-inputs 分段控件改版：阅读页标题行 防误触/高频词/锁/查词 (2026-09-03) */
/* v2: 融入阅读区暖纸环境 —— 暖米浅刻痕容器 + 石墨墨激活态 */
#readingPage .reading-area .title .guard-title-toggle {
  position: relative; display: inline-flex; align-items: center; gap: 5px; flex-shrink: 0;
  box-sizing: border-box; padding: 5px;
  border-radius: 16px;
  border: 1px solid rgba(120,113,108,.13);
  background: linear-gradient(145deg, #F0EBE0, #FCF9F1);
  box-shadow: inset 0 1px 3px rgba(99,88,66,.10), 0 1px 0 rgba(255,255,255,.65);
  font-size: 13px;
}
#readingPage .reading-area .title .guard-title-toggle .seg {
  position: relative; flex: 0 0 auto; display: flex; align-items: center; justify-content: center;
  border: none; background: transparent; margin: 0; padding: 0; cursor: pointer; font-family: inherit; color: inherit;
  box-shadow: none;
}
#readingPage .reading-area .title .guard-title-toggle .seg input { display: none; }
html.dark #readingPage .reading-area .title .guard-title-toggle {
  border-color: rgba(237,233,230,.07);
  background: linear-gradient(145deg, #221E19, #2C2721);
  box-shadow: inset 0 1px 3px rgba(0,0,0,.5), 0 1px 0 rgba(255,255,255,.04);
}
@media (max-width: 768px), html.force-phone {
  #readingPage .reading-area .title .guard-title-toggle { padding: 4px; gap: 4px; border-radius: 14px; font-size: 12px; }
}
@keyframes segPop { 0% { transform: scale(.9); } 45% { transform: scale(1.06); } 100% { transform: scale(1); } }
@keyframes segDotsUp {
  0% { opacity: 1; transform: translateX(-50%) translateY(0) scale(1); box-shadow: 0 0 6px rgba(212,163,115,.8), 11px -11px 0 rgba(212,163,115,.9), -11px -11px 0 rgba(212,163,115,.75); }
  45% { opacity: .85; }
  100% { opacity: 0; transform: translateX(-50%) translateY(-26px) scale(.12); box-shadow: 0 0 6px rgba(212,163,115,0), 23px -26px 0 rgba(212,163,115,0), -23px -26px 0 rgba(212,163,115,0); }
}
@keyframes segDotsDown {
  0% { opacity: 1; transform: translateX(-50%) translateY(0) scale(1); box-shadow: 0 0 7px rgba(212,163,115,.85), 11px 11px 0 rgba(212,163,115,.9), -11px 11px 0 rgba(212,163,115,.75); }
  45% { opacity: .85; }
  100% { opacity: 0; transform: translateX(-50%) translateY(26px) scale(.12); box-shadow: 0 0 7px rgba(212,163,115,0), 23px 26px 0 rgba(212,163,115,0), -23px 26px 0 rgba(212,163,115,0); }
}
@keyframes segRing { 0% { opacity: 0; transform: scale(.96); } 18% { opacity: .7; } 60% { opacity: .35; } 100% { opacity: 0; transform: scale(1.05); } }

/* 阅读页顶部按钮组：Uiverse elijahgummer btn-group（忠实版）(2026-09-03) */
#readingPage .reading-area .title .guard-title-toggle {
  display: inline-flex; align-items: center; flex-shrink: 0; box-sizing: border-box;
  padding: 0; margin: 0; border: none; background: transparent; box-shadow: none; gap: 0;
}
#readingPage .reading-area .title .guard-title-toggle .seg {
  position: relative; display: inline-flex; align-items: center; justify-content: center;
  font: inherit; background-color: #ffffff; border: 0; color: #292524;
  font-size: .92rem; font-weight: bold; line-height: 1.25;
  padding: 0.26em 0.85em;
  text-shadow: 0 0.0625em 0 #fff;
  box-shadow: inset 0 0.0625em 0 0 #f4f4f4, 0 0.0625em 0 0 #efefef, 0 0.125em 0 0 #ececec,
    0 0.25em 0 0 #e0e0e0, 0 0.3125em 0 0 #dedede, 0 0.375em 0 0 #dcdcdc, 0 0.425em 0 0 #cacaca,
    0 0.425em 0.5em 0 #cecece;
  transition: color 0.23s ease, background-color 0.23s ease, box-shadow 0.23s ease,
    letter-spacing 0.23s ease, translate 0.23s ease;
  cursor: pointer; margin: 0; white-space: nowrap; user-select: none; -webkit-user-select: none;
}
#readingPage .reading-area .title .guard-title-toggle .seg + .seg { margin-left: -1px; }
#readingPage .reading-area .title .guard-title-toggle .seg input { display: none; }
#readingPage .reading-area .title .guard-title-toggle .seg:first-child {
  border-top-left-radius: 0.5em; border-bottom-left-radius: 0.5em;
}
#readingPage .reading-area .title .guard-title-toggle .seg:last-child {
  border-top-right-radius: 0.5em; border-bottom-right-radius: 0.5em;
}
#readingPage .reading-area .title .guard-title-toggle .seg:hover { background-color: #f7f7f7; }
#readingPage .reading-area .title .guard-title-toggle .seg:active {
  translate: 0 0.225em;
  box-shadow: inset 0 0.03em 0 0 #f4f4f4, 0 0.03em 0 0 #efefef, 0 0.0625em 0 0 #ececec,
    0 0.125em 0 0 #e0e0e0, 0 0.125em 0 0 #dedede, 0 0.2em 0 0 #dcdcdc, 0 0.225em 0 0 #cacaca,
    0 0.225em 0.375em 0 #cecece;
  letter-spacing: 0.1em; color: #16a34a;
}
#readingPage .reading-area .title .guard-title-toggle .seg:focus { color: #16a34a; }
#readingPage .reading-area .title .guard-title-toggle .seg:focus-visible { outline: 2px solid #34d399; outline-offset: 2px; }
#readingPage .reading-area .title .guard-title-toggle .seg b { font-weight: bold; }
/* 开启态持久提示：防误触 checked / 高频词 is-on -> 同 :focus 的 skyblue 文字 */
#readingPage .reading-area .title .guard-title-toggle .seg:has(input:checked),
#readingPage .reading-area .title .guard-title-toggle .seg.is-on { color: #16a34a; }
html.dark #readingPage .reading-area .title .guard-title-toggle .seg {
  background-color: #3b3833; color: #EDE7DC; text-shadow: 0 0.0625em 0 rgba(0,0,0,.25);
  box-shadow: inset 0 0.0625em 0 0 rgba(255,255,255,.06), 0 0.0625em 0 0 rgba(0,0,0,.5),
    0 0.125em 0 0 rgba(0,0,0,.45), 0 0.25em 0 0 rgba(0,0,0,.4), 0 0.3125em 0 0 rgba(0,0,0,.36),
    0 0.375em 0 0 rgba(0,0,0,.32), 0 0.425em 0 0 rgba(0,0,0,.3), 0 0.425em 0.5em 0 rgba(0,0,0,.35);
}
html.dark #readingPage .reading-area .title .guard-title-toggle .seg:hover { background-color: #45413b; color: #fff; }
html.dark #readingPage .reading-area .title .guard-title-toggle .seg:active {
  translate: 0 0.225em; color: #86efac; letter-spacing: 0.1em;
  box-shadow: inset 0 0.03em 0 0 rgba(255,255,255,.06), 0 0.03em 0 0 rgba(0,0,0,.5),
    0 0.0625em 0 0 rgba(0,0,0,.45), 0 0.125em 0 0 rgba(0,0,0,.4), 0 0.125em 0 0 rgba(0,0,0,.36),
    0 0.2em 0 0 rgba(0,0,0,.32), 0 0.225em 0 0 rgba(0,0,0,.3), 0 0.225em 0.375em 0 rgba(0,0,0,.35);
}
html.dark #readingPage .reading-area .title .guard-title-toggle .seg:focus { color: #86efac; }
html.dark #readingPage .reading-area .title .guard-title-toggle .seg:has(input:checked),
html.dark #readingPage .reading-area .title .guard-title-toggle .seg.is-on { color: #86efac; }
@media (max-width: 768px), html.force-phone {
  #readingPage .reading-area .title .guard-title-toggle .seg { font-size: .82rem; padding: 0.22em 0.7em; }
}
/* 高频词设置菜单（方案乙） */
#hfGroupModal .hf-group-panel { min-width: 220px; padding: 12px 10px; }
#hfGroupModal .hf-mrow { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin: 6px 4px 4px; }
#hfGroupModal .hf-mlabel { font-size: .82em; color: #4b463d; font-weight: 600; }
#hfGroupModal .hf-menu-toggle {
  font: inherit; font-size: .78em; font-weight: 700; cursor: pointer;
  background-color: #ffffff; border: 0; color: #292524;
  padding: .35em .9em; border-radius: .5em;
  box-shadow: inset 0 .0625em 0 0 #f4f4f4, 0 .0625em 0 0 #efefef, 0 .125em 0 0 #ececec,
    0 .25em 0 0 #e0e0e0, 0 .25em .35em 0 #cecece;
  transition: box-shadow .2s ease, translate .2s ease, color .2s ease;
}
#hfGroupModal .hf-menu-toggle:active { translate: 0 .15em; box-shadow: inset 0 .03em 0 0 #f4f4f4, 0 .03em 0 0 #efefef, 0 .0625em 0 0 #ececec, 0 .125em 0 0 #e0e0e0; color: #4F6B36; }
#hfGroupModal .hf-menu-toggle.on { color: #4F6B36; }
#hfGroupModal .hf-group-current { font-size: .8em; color: #8a8582; margin: 2px 4px 8px; }
#hfGroupModal .hf-group-opt.sel { background: #ecfdf5; color: #15803d; }
html.dark #hfGroupModal .hf-mlabel { color: #E7E1D6; }
html.dark #hfGroupModal .hf-menu-toggle { background-color: #3b3833; color: #EDE7DC; box-shadow: inset 0 .0625em 0 0 rgba(255,255,255,.06), 0 .0625em 0 0 rgba(0,0,0,.5), 0 .125em 0 0 rgba(0,0,0,.45), 0 .25em 0 0 rgba(0,0,0,.4), 0 .25em .35em 0 rgba(0,0,0,.4); }
html.dark #hfGroupModal .hf-menu-toggle.on, html.dark #hfGroupModal .hf-menu-toggle:active { color: #A8BC90; }
html.dark #hfGroupModal .hf-group-opt.sel { background: #14371f; color: #86efac; }
@media (prefers-reduced-motion: reduce) {
  #readingPage .reading-area .title .guard-title-toggle .seg, #hfGroupModal .hf-menu-toggle { transition: none; }
}

/* 中文查英文 候选条 (2026-09-03) */
#popAlt { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: 8px 2px 2px; }
#popAlt .alt-label { font-size: .72em; color: #A8A29E; margin-right: 2px; flex-shrink: 0; }
#popAlt .alt-chip { font: inherit; font-size: .78em; font-weight: 600; color: #57534E; background: #F5F1E7; border: 1px solid #E7E0D2; border-radius: 999px; padding: 3px 10px; cursor: pointer; display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; line-height: 1.3; }
#popAlt .alt-chip em { font-style: normal; color: #A8A29E; font-weight: 500; }
#popAlt .alt-chip:hover { background: #EFE9DB; }
#popAlt .alt-chip.sel { color: #15803D; border-color: rgba(21,128,61,.4); background: #F0FDF4; }
html.dark #popAlt .alt-chip { background: #37312B; border-color: #4A433B; color: #E5DFD3; }
html.dark #popAlt .alt-chip em { color: #A8A29E; }
html.dark #popAlt .alt-chip.sel { background: #123526; border-color: rgba(110,231,183,.4); color: #86EFAC; }

/* 有道词典风查词卡 · 暖纸精致 (2026-09-03) */
/* v2 紧凑版：体积收敛 + 动效 + focus 细节 (2026-09-03) */
.lk-overlay { position: fixed; inset: 0; z-index: 500; display: flex; align-items: center; justify-content: center; padding-right: 0; background: rgba(28,25,23,.34); opacity: 0; pointer-events: none; transition: opacity .16s ease; }
.lk-overlay.show { opacity: 1; pointer-events: auto; }
/* 卡片高度分两种（用户要求）：
   ① **默认（未输入单词 / 联想列表态）**：固定大小，保持原来的观感；
   ② **点开某个单词后的详情态**（.lk-card.word-view，由 lkShowWord() 加类）：高度随释义多少自适应，
      释义少的词不再留一大片空白；内容多时由 max-height 封顶、.lk-body 内部滚动。 */
/* 高度（2026-10-31 用户要求「做短一点」）：原来 640px / 86vh 太高，列表态大半是空白；
   现在 520px / 74vh，手机上 70vh。详情态仍按内容自适应，超过就内部滚动。 */
.lk-card { width: min(432px, calc(100vw - 32px)); height: min(460px, 68vh); display: flex; flex-direction: column; background: #FFFCF6; border: 1px solid #E7E0D2; border-radius: 16px; box-shadow: 0 18px 46px rgba(40,30,10,.18), 0 3px 10px rgba(40,30,10,.08); overflow: hidden; }
@media (max-width: 768px) {
  .lk-overlay { justify-content: center; padding-right: 0; }
  .lk-card { height: min(460px, 66vh); }
}
html.force-phone .lk-overlay { justify-content: center !important; padding-right: 0 !important; }
html.force-phone .lk-card { height: min(460px, 66vh) !important; }
/* 详情态：高度自适应 */
.lk-card.word-view { height: auto; max-height: min(460px, 68vh); }
@media (max-width: 768px) { .lk-card.word-view { height: auto; max-height: min(460px, 66vh); } }
html.force-phone .lk-card.word-view { height: auto !important; max-height: min(460px, 66vh) !important; }
.lk-overlay.show .lk-card { animation: lkCardIn .2s cubic-bezier(.22,.8,.32,1); }
@keyframes lkCardIn { from { transform: translateY(8px) scale(.97); opacity: 0; } to { transform: translateY(0) scale(1); opacity: 1; } }
/* ── 词典面板 = 「添加单词」那种浮窗（2026-10-31 用户要求）──
   遮罩去掉、页面照常能点能滚（pointer-events:none），卡片自身 fixed + pointer-events:auto；
   位置记在 _lkFloatPos（会话内记住）。**拖动靠顶栏那一条**，不再额外加抓握条（用户不喜欢那个胶囊）。 */
#lkOverlay.lk-float .lk-head { cursor: grab; touch-action: none; user-select: none; -webkit-user-select: none; }
#lkOverlay.lk-float .lk-head .lk-back,
#lkOverlay.lk-float .lk-head .lk-x,
#lkOverlay.lk-float .lk-head #lkInput { cursor: auto; }
#lkOverlay.lk-float .lk-card.dragging .lk-head { cursor: grabbing; }
/* 底部的拖动条（2026-10-31 用户要求「在底部弄一个可以拖动的地方」）：上下拖 = 调高度 */
.lk-foot-grip { height: 16px; flex: none; display: grid; place-items: center; cursor: ns-resize;
  touch-action: none; user-select: none; -webkit-user-select: none; }
.lk-foot-grip span { width: 56px; height: 5px; border-radius: 3px; background: rgba(61,50,38,.45); transition: background .15s; }
html.dark .lk-foot-grip span { background: rgba(240,226,196,.34); }
.lk-foot-grip:hover span { background: rgba(61,50,38,.55); }
html.dark .lk-foot-grip:hover span { background: rgba(240,226,196,.55); }
.lk-card.resizing .lk-foot-grip { cursor: ns-resize; }
.lk-card.resizing .lk-foot-grip span { background: rgba(61,50,38,.45); }
.lk-card.dragging { animation: none !important; }
/* ── 词典面板改成「添加单词」那种浮窗（2026-10-31 用户要求）──
   遮罩去掉、页面照常能点能滚（pointer-events:none），面板自己是 fixed + pointer-events:auto；
   位置记在 _lkFloatPos（会话内记住），拖开就是为了不挡住正文。 */
#lkOverlay.lk-float { background: transparent; -webkit-backdrop-filter: none; backdrop-filter: none; pointer-events: none; }
#lkOverlay.lk-float.show { pointer-events: none; }
#lkOverlay.lk-float .lk-card { position: fixed; pointer-events: auto; }
#lkOverlay.lk-float .lk-card.dragging { animation: none !important; }
/* 关掉（没有 .show）时卡片必须彻底不接事件。
   否则它只是 opacity:0 —— 看不见，却仍然吃点击：查词卡关掉后那块矩形变成"死区"，
   点单词、画标注都点不中（2026-11-02 冒烟测试抓到：关掉查词卡后标注画不上笔迹）。 */
#lkOverlay:not(.show) .lk-card { pointer-events: none; }
html.dark .lk-card { background: #2A2520; border-color: #423A33; box-shadow: 0 18px 46px rgba(0,0,0,.5); }
.lk-head { display: flex; align-items: center; gap: 6px; padding: 9px 11px 8px; border-bottom: 1px solid #EFE9DC; }
html.dark .lk-head { border-bottom-color: #3B352D; }
.lk-back { width: 26px; height: 26px; border: none; background: transparent; color: #A8A29E; font-size: 22px; line-height: 1; cursor: pointer; border-radius: 16px; flex-shrink: 0; }
.lk-back:hover { background: #F3EDE0; color: #57534E; }
html.dark .lk-back:hover { background: #383129; }
.lk-searchbox { flex: 1; display: flex; align-items: center; gap: 6px; background: #F5F1E7; border: 1px solid #EAE3D4; border-radius: 16px; padding: 5px 10px; transition: border-color .15s, box-shadow .15s; }
.lk-searchbox:focus-within { border-color: rgba(217,119,6,.5); box-shadow: 0 0 0 2.5px rgba(217,119,6,.12); }
html.dark .lk-searchbox { background: #332D27; border-color: #463E35; }
.lk-sicon { width: 14px; height: 14px; color: #A8A29E; flex-shrink: 0; }
#lkInput { flex: 1; min-width: 0; border: none; outline: none; background: transparent; color: #292524; font: inherit; font-size: 14px; }
#lkInput::placeholder { color: #B7B0A4; }
html.dark #lkInput { color: #EDE7DC; }
.lk-x { width: 26px; height: 26px; border: none; background: transparent; color: #A8A29E; font-size: 18px; line-height: 1; cursor: pointer; border-radius: 16px; flex-shrink: 0; }
.lk-x:hover { background: #F3EDE0; color: #57534E; }
html.dark .lk-x:hover { background: #383129; }
.lk-body { flex: 1; min-height: 0; overflow-y: auto; padding: 6px; scrollbar-width: thin;
  /* 2026-10-17：用户反馈"卡片滚到最底看不到结尾"（我这边 6 档屏高都复现不出：滚到底 .lk-acts 可见）。
     按他选的做两处防守：① 手势交给浏览器原生纵向滚动，免得被站内全局 touch 监听搅掉；
     ② 底部留一段余量，最后一行不再贴着卡片下沿（视觉上"像被切了"）。 */
  touch-action: pan-y; overscroll-behavior: contain; -webkit-overflow-scrolling: touch;
  padding-bottom: 14px; }
.lk-hint { text-align: center; color: #B7B0A4; font-size: .84em; padding: 22px 14px; line-height: 1.7; }
.lk-row { display: block; width: 100%; text-align: left; border: none; background: transparent; border-radius: 16px; padding: 7px 11px; cursor: pointer; font: inherit; }
.lk-row:hover, .lk-row.sel { background: #F6F1E4; }
html.dark .lk-row:hover, html.dark .lk-row.sel { background: #37302A; }
.lk-row .lk-w { display: block; font-size: 15px; font-weight: 700; color: #292524; line-height: 1.35; }
.lk-row .lk-m { display: block; margin-top: 1px; font-size: 11.5px; color: #A8A29E; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
html.dark .lk-row .lk-w { color: #F3EEE6; }
.lk-word .lk-wcard { padding: 6px 13px 12px; }
.lk-whint { text-align: center; color: #A8A29E; padding: 30px 10px; font-size: .88em; }
.lk-wtop { display: flex; align-items: baseline; flex-wrap: wrap; gap: 8px; margin: 3px 0 1px; }
.lk-wb { font-size: 23px; font-weight: 800; color: #292524; font-family: "Crimson Text", Georgia, serif; line-height: 1.2; }
html.dark .lk-wb { color: #F6F1E8; }
.lk-ph { font-size: 13px; color: #A8A29E; }
.lk-snds { display: inline-flex; gap: 5px; margin-left: auto; align-items: center; }
.lk-snds button { width: 24px; height: 24px; border-radius: 999px; border: 1.5px solid #57534E; background: transparent; color: #57534E; font-size: 11px; font-weight: 700; cursor: pointer; line-height: 1; }
.lk-snds button:hover { background: #57534E; color: #fff; }
.lk-mean { margin: 7px 0 3px; font-size: 14px; line-height: 1.8; color: #44403C; }
html.dark .lk-mean { color: #E5DFD4; }
.lk-fold { border-top: 1px solid #EFE9DC; margin-top: 6px; padding-top: 4px; }
html.dark .lk-fold { border-top-color: #3B352D; }
.lk-fold-h { display: flex; align-items: center; justify-content: space-between; width: 100%; background: none; border: none; color: #A8A29E; font-size: 12px; font-weight: 600; padding: 6px 2px; cursor: pointer; }
.lk-fold-h .lk-fa { transition: transform .15s; font-size: 15px; }
.lk-fold-h.open .lk-fa { transform: rotate(90deg); }
.lk-ex { padding: 4px 2px; }
.lk-ex-en { font-size: 13px; color: #57534E; line-height: 1.6; }
.lk-ex-zh { font-size: 12px; color: #A8A29E; line-height: 1.6; margin-top: 1px; }
html.dark .lk-ex-en { color: #E5DFD4; }
.lk-acts { display: flex; justify-content: flex-end; margin-top: 10px; }
.lk-add { font: inherit; font-size: 12px; font-weight: 700; color: #fff; background: #476033; border: none; border-radius: 999px; padding: 7px 15px; cursor: pointer; box-shadow: 0 2px 5px rgba(79,107,54,.28); }
.lk-add:hover { filter: brightness(1.05); }
@media (max-width: 420px) { .lk-card { width: calc(100vw - 20px); max-height: 84vh; } .lk-word .lk-wb { font-size: 21px; } }
@media (prefers-reduced-motion: reduce) { .lk-overlay, .lk-overlay.show .lk-card, .lk-fold-h .lk-fa { transition: none !important; animation: none !important; } }

/* 精读训练 选题按钮 + 题号选择面板 (2026-09-14) */
#trainPage .train-pick-btn { color: var(--c-accent-deep); border-color: rgba(90,110,69,.4); background: #E9E0D4; white-space: nowrap; }
#trainPage .train-pick-btn:hover { color: #4A3229; border-color: rgba(90,110,69,.55); background: #E9E0D4; }
#trainPage .train-pick-btn:disabled { opacity: .5; cursor: default; }
html.dark #trainPage .train-pick-btn { color: #D4A373; border-color: #7A5A2F; background: #2E2620; }
html.dark #trainPage .train-pick-btn:hover { color: #E9E0D4; border-color: #8A7A6B; background: #463522; }
.train-pick-overlay { position: fixed; inset: 0; z-index: 520; display: none; align-items: center; justify-content: center; background: rgba(28,25,23,.42); padding: 20px; }
.train-pick-overlay.show { display: flex; }
.train-pick-modal { width: min(680px, 100%); max-height: 82vh; display: flex; flex-direction: column; background: var(--c-bg-card); border: 1px solid var(--c-border); border-radius: var(--radius-lg); box-shadow: 0 24px 60px rgba(0,0,0,.28); overflow: hidden; }
.train-pick-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 18px; border-bottom: 1px solid var(--c-border); }
.train-pick-head h3 { margin: 0; font-size: 1em; color: var(--c-text); }
.train-pick-close { width: 30px; height: 30px; border: none; border-radius: 16px; background: transparent; color: var(--c-text-muted); font-size: 20px; line-height: 1; cursor: pointer; }
.train-pick-close:hover { background: var(--c-bg); color: var(--c-text); }
.train-pick-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(46px, 1fr)); gap: 8px; padding: 16px 18px 20px; overflow-y: auto; }
.train-pick-num { height: 42px; border-radius: 16px; border: 1px solid var(--c-border); background: var(--c-bg); color: var(--c-text-secondary); font-size: .9em; font-weight: 600; cursor: pointer; transition: var(--transition-fast); }
.train-pick-num:hover { border-color: var(--c-accent); color: var(--c-accent-deep); }
.train-pick-num.done { background: var(--c-accent-light); border-color: var(--c-accent-light); color: var(--c-accent-deep); }
.train-pick-num.cur { border-color: var(--c-accent); color: #fff; background: var(--c-accent); box-shadow: 0 3px 10px rgba(90,110,69,.3); }
html.dark .train-pick-num.done { background: #443018; border-color: #3A322C; color: #E9E0D4; }
html.dark .train-pick-num.cur { color: #1C1917; }
@media (max-width: 768px) { #trainTopInfo { max-width: 40vw; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } }

/* 生词本/词组本 面板按钮 · 暖纸柔和 (2026-09-03) */
#readingPage .vocab-sidebar .vocab-panel h3 .count,
#trainPage .train-rail .vocab-panel h3 .count {
  background: #FEF3C7; color: #A34909; min-width: 20px; height: 20px;
  border: 1px solid rgba(217,119,6,.28); font-size: .72em; font-weight: 700;
}
#readingPage .vocab-sidebar .vocab-panel h3 .vocab-hl-bar,
#trainPage .train-rail .vocab-panel h3 .vocab-hl-bar {
  height: 22px; padding: 0 8px; font-size: .64em; font-weight: 600; gap: 4px;
  background: transparent; border: 1px solid #E7E5E4; color: #78716C;
}
#readingPage .vocab-sidebar .vocab-panel h3 .vocab-hl-bar svg,
#trainPage .train-rail .vocab-panel h3 .vocab-hl-bar svg { width: 10px; height: 10px; }
#readingPage .vocab-sidebar .vocab-panel h3 .vocab-hl:hover .vocab-hl-bar,
#trainPage .train-rail .vocab-panel h3 .vocab-hl:hover .vocab-hl-bar { background: #F7F1E4; }
#readingPage .vocab-sidebar .vocab-panel h3 .vocab-hl input:checked + .vocab-hl-bar,
#trainPage .train-rail .vocab-panel h3 .vocab-hl input:checked + .vocab-hl-bar {
  background: #FEF3C7; border-color: rgba(217,119,6,.5); color: #A34909; box-shadow: 0 1px 3px rgba(217,119,6,.15);
}
#readingPage .vocab-sidebar .vocab-actions, #trainPage .train-rail .vocab-actions { gap: 6px; margin-top: 12px; }
#readingPage .vocab-sidebar .vocab-actions button, #trainPage .train-rail .vocab-actions button {
  height: 30px; border-radius: 9px; font-size: .74em; font-weight: 600;
  padding: 0 8px; display: inline-flex; align-items: center; justify-content: center; gap: 4px;
}
#readingPage .vocab-sidebar .vocab-actions .vocab-clear, #trainPage .train-rail .vocab-actions .vocab-clear {
  background: #FFFFFF; border: 1px solid #E7E5E4; color: #78716C;
}
#readingPage .vocab-sidebar .vocab-actions .vocab-clear:hover, #trainPage .train-rail .vocab-actions .vocab-clear:hover {
  color: #B91C1C; border-color: #FECACA; background: #FEF2F2;
}
#readingPage .vocab-sidebar .vocab-actions .vocab-add-action, #trainPage .train-rail .vocab-actions .vocab-add-action {
  border: none; color: #fff; background: linear-gradient(135deg, #34D399, #059669);
  box-shadow: 0 2px 5px rgba(16,185,129,.28);
}
#readingPage .vocab-sidebar .vocab-actions .vocab-add-action:hover, #trainPage .train-rail .vocab-actions .vocab-add-action:hover {
  filter: brightness(1.05); box-shadow: 0 3px 8px rgba(16,185,129,.34);
}
html.dark #readingPage .vocab-sidebar .vocab-panel h3 .count,
html.dark #trainPage .train-rail .vocab-panel h3 .count {
  background: #443018; color: #FCD9A8; border-color: rgba(217,119,6,.5);
}
html.dark #readingPage .vocab-sidebar .vocab-panel h3 .vocab-hl-bar,
html.dark #trainPage .train-rail .vocab-panel h3 .vocab-hl-bar {
  background: transparent; border-color: #3F3A37; color: #A8A29E;
}
html.dark #readingPage .vocab-sidebar .vocab-panel h3 .vocab-hl:hover .vocab-hl-bar,
html.dark #trainPage .train-rail .vocab-panel h3 .vocab-hl:hover .vocab-hl-bar { background: #332E2A; }
html.dark #readingPage .vocab-sidebar .vocab-panel h3 .vocab-hl input:checked + .vocab-hl-bar,
html.dark #trainPage .train-rail .vocab-panel h3 .vocab-hl input:checked + .vocab-hl-bar {
  background: #443018; color: #FCD9A8; border-color: var(--c-accent); box-shadow: 0 1px 3px rgba(0,0,0,.35);
}
html.dark #readingPage .vocab-sidebar .vocab-actions .vocab-clear,
html.dark #trainPage .train-rail .vocab-actions .vocab-clear { background: #332E2A; border-color: #3F3A37; color: #A8A29E; }
html.dark #readingPage .vocab-sidebar .vocab-actions .vocab-clear:hover,
html.dark #trainPage .train-rail .vocab-actions .vocab-clear:hover { color: #FCA5A5; border-color: rgba(248,113,113,.4); background: rgba(220,38,38,.14); }
html.dark #readingPage .vocab-sidebar .vocab-actions .vocab-add-action,
html.dark #trainPage .train-rail .vocab-actions .vocab-add-action { background: linear-gradient(135deg, #10B981, #047857); color: #fff; box-shadow: 0 2px 5px rgba(0,0,0,.3); }

/* 清空/清除按钮：静默危险钮（垃圾桶图标）(2026-09-03) */
#readingPage .vocab-sidebar .vocab-actions .vocab-clear svg,
#trainPage .train-rail .vocab-actions .vocab-clear svg { width: 12px; height: 12px; flex-shrink: 0; opacity: .75; }
#readingPage .vocab-sidebar .vocab-actions .vocab-clear:hover svg,
#trainPage .train-rail .vocab-actions .vocab-clear:hover svg { opacity: 1; }

/* 题目标记 · Uiverse Galahhad 书签 (2026-09-03) */
.ui-bookmark {
  position: absolute; top: 6px; right: 8px; z-index: 3;
  --icon-size: 22px;
  --icon-secondary-color: rgb(120, 113, 108);
  --icon-hover-color: rgb(163, 73, 9);
  --icon-primary-color: gold;
  --icon-circle-border: 1px solid gold;
  --icon-circle-size: 34px;
  --icon-anmt-duration: 0.3s;
}
.ui-bookmark input {
  -webkit-appearance: none; -moz-appearance: none; appearance: none; display: none;
}
.ui-bookmark .bookmark {
  width: var(--icon-size); height: var(--icon-size);
  fill: var(--icon-secondary-color); cursor: pointer;
  -webkit-transition: 0.2s; -o-transition: 0.2s; transition: 0.2s;
  display: -webkit-box; display: -ms-flexbox; display: flex;
  -webkit-box-pack: center; -ms-flex-pack: center; justify-content: center;
  -webkit-box-align: center; -ms-flex-align: center; align-items: center;
  position: relative;
  -webkit-transform-origin: top; -ms-transform-origin: top; transform-origin: top;
}
.ui-bookmark .bookmark svg { width: 100%; height: 100%; display: block; }
.ui-bookmark .bookmark::after {
  content: ""; position: absolute; width: 10px; height: 10px;
  -webkit-box-shadow: 0 30px 0 -4px var(--icon-primary-color), 30px 0 0 -4px var(--icon-primary-color),
    0 -30px 0 -4px var(--icon-primary-color), -30px 0 0 -4px var(--icon-primary-color),
    -22px 22px 0 -4px var(--icon-primary-color), -22px -22px 0 -4px var(--icon-primary-color),
    22px -22px 0 -4px var(--icon-primary-color), 22px 22px 0 -4px var(--icon-primary-color);
  box-shadow: 0 30px 0 -4px var(--icon-primary-color), 30px 0 0 -4px var(--icon-primary-color),
    0 -30px 0 -4px var(--icon-primary-color), -30px 0 0 -4px var(--icon-primary-color),
    -22px 22px 0 -4px var(--icon-primary-color), -22px -22px 0 -4px var(--icon-primary-color),
    22px -22px 0 -4px var(--icon-primary-color), 22px 22px 0 -4px var(--icon-primary-color);
  border-radius: 50%;
  -webkit-transform: scale(0); -ms-transform: scale(0); transform: scale(0);
}
.ui-bookmark .bookmark::before {
  content: ""; position: absolute; border-radius: 50%;
  border: var(--icon-circle-border); opacity: 0;
}
.ui-bookmark:hover .bookmark { fill: var(--icon-hover-color); }
.ui-bookmark:active .bookmark { -webkit-transform: scale(.92); -ms-transform: scale(.92); transform: scale(.92); }
.ui-bookmark:has(input:focus-visible) .bookmark::before { outline: 2px solid rgba(120,113,108,.4); outline-offset: 2px; }
.ui-bookmark input:checked + .bookmark::after {
  -webkit-animation: gcircles var(--icon-anmt-duration) cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards;
  animation: gcircles var(--icon-anmt-duration) cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards;
  -webkit-animation-delay: var(--icon-anmt-duration); animation-delay: var(--icon-anmt-duration);
}
.ui-bookmark input:checked + .bookmark {
  fill: var(--icon-primary-color);
  -webkit-animation: gbookmark var(--icon-anmt-duration) forwards; animation: gbookmark var(--icon-anmt-duration) forwards;
  -webkit-transition-delay: 0.3s; -o-transition-delay: 0.3s; transition-delay: 0.3s;
}
.ui-bookmark input:checked + .bookmark::before {
  -webkit-animation: gcircle var(--icon-anmt-duration) cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards;
  animation: gcircle var(--icon-anmt-duration) cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards;
  -webkit-animation-delay: var(--icon-anmt-duration); animation-delay: var(--icon-anmt-duration);
}
@keyframes gbookmark { 50% { -webkit-transform: scaleY(0.6); transform: scaleY(0.6); } 100% { -webkit-transform: scaleY(1); transform: scaleY(1); } }
@keyframes gcircle { from { width: 0; height: 0; opacity: 0; } 90% { width: var(--icon-circle-size); height: var(--icon-circle-size); opacity: 1; } to { opacity: 0; } }
@keyframes gcircles { from { -webkit-transform: scale(0); transform: scale(0); } 40% { opacity: 1; } to { -webkit-transform: scale(0.8); transform: scale(0.8); opacity: 0; } }
html.dark .ui-bookmark { --icon-secondary-color: rgb(168, 162, 158); --icon-hover-color: #CDC5BA; }
@media (prefers-reduced-motion: reduce) { .ui-bookmark input:checked + .bookmark, .ui-bookmark input:checked + .bookmark::after, .ui-bookmark input:checked + .bookmark::before { animation: none !important; } }

/* 悬浮题目卡 · 暖纸精致 (2026-09-03) */
.float-q-card {
  border-radius: 16px; background: linear-gradient(180deg, #FFFDF8, #FFF9EF);
  border: 1px solid #E7E0D2;
  box-shadow: 0 20px 48px rgba(40,30,10,.16), 0 5px 14px rgba(40,30,10,.08);
}
.float-q-card.show { -webkit-animation: fqIn .2s cubic-bezier(.22,.8,.32,1); animation: fqIn .2s cubic-bezier(.22,.8,.32,1); }
@keyframes fqIn { from { opacity: 0; transform: translateY(10px) scale(.98); } to { opacity: 1; transform: translateY(0) scale(1); } }
.float-q-head { gap: 8px; padding: 8px 12px 8px 10px; background: rgba(252,247,238,.9); border-bottom: 1px solid #EFE9DC; }
.fq-grip { display: inline-flex; color: #C9C0B0; flex-shrink: 0; }
.fq-grip svg { width: 16px; height: 16px; }
.float-q-title { font-size: .78em; font-weight: 700; color: #57534E; letter-spacing: .03em; flex: 1; min-width: 0; }
.float-q-nav { gap: 5px; flex-shrink: 0; }
.float-q-nav-btn, .float-q-close {
  width: 24px; height: 24px; border-radius: 16px;
  border: 1px solid #E7E0D2; background: #FFFCF8; color: #78716C;
  box-shadow: 0 1px 2px rgba(40,30,10,.05);
}
.float-q-nav-btn svg, .float-q-close svg { width: 12px; height: 12px; }
.float-q-nav-btn:hover:not(:disabled) { border-color: rgba(217,119,6,.5); color: #A34909; background: #FFFBEB; transform: translateY(-1px); }
.float-q-nav-btn:disabled { opacity: .35; cursor: default; }
.float-q-close:hover { border-color: #FECACA; color: #B91C1C; background: #FEF2F2; }
.float-q-body { max-height: calc(75vh - 40px); padding: 12px; background: rgba(250,246,237,.4); scrollbar-width: thin; }
.float-q-body .question-block {
  margin: 0; padding: 14px 16px; border-radius: 18px;
  background: #FFFFFF; border: 1px solid #EFE9DC;
  box-shadow: 0 1px 3px rgba(40,30,10,.05);
}
.float-q-body ::selection { background: #E9E0D4; color: #292524; }
html.dark .float-q-card { background: linear-gradient(180deg, #2A2520, #26211C); border-color: #3F3A37; box-shadow: 0 20px 48px rgba(0,0,0,.5); }
html.dark .float-q-head { background: rgba(45,39,33,.9); border-bottom-color: #3B352D; }
html.dark .fq-grip { color: #57524B; }
html.dark .float-q-title { color: #E5DFD4; }
html.dark .float-q-nav-btn, html.dark .float-q-close { background: #332E28; border-color: #3F3A37; color: #A8A29E; }
html.dark .float-q-nav-btn:hover:not(:disabled) { background: #443018; color: #FCD9A8; border-color: var(--c-accent); }
html.dark .float-q-close:hover { background: rgba(220,38,38,.14); color: #FCA5A5; border-color: rgba(248,113,113,.4); }
html.dark .float-q-body { background: rgba(35,30,26,.4); }
html.dark .float-q-body .question-block { background: #2E2924; border-color: #3F3A37; box-shadow: 0 1px 3px rgba(0,0,0,.2); }
@media (prefers-reduced-motion: reduce) { .float-q-card.show { animation: none !important; } }

/* 悬浮题目卡 · 更紧凑 (2026-09-03) */
.float-q-card { width: 400px; max-width: 88vw; max-height: 62vh; }
.float-q-body { max-height: calc(62vh - 36px); padding: 8px; }
.float-q-body .question-block { padding: 10px 12px; border-radius: 16px; }
.float-q-head { padding: 6px 10px 6px 8px; }
.fq-grip svg { width: 14px; height: 14px; }
.float-q-title { font-size: .72em; }
.float-q-nav-btn, .float-q-close { width: 22px; height: 22px; border-radius: 7px; }
.float-q-nav-btn svg, .float-q-close svg { width: 11px; height: 11px; }
.float-q-body .q-stem { font-size: .76em; }
.float-q-body .q-option { font-size: .74em; padding: 3px 9px; }
.float-q-body .q-my-ans { font-size: .72em; }
.float-q-body .q-analyze-row { padding-left: 8px; }
.float-q-body .q-analyze-result { font-size: .72em; padding: 8px 10px; }

/* ── 全文翻译浮窗（2026-10-23 用户要求：译文可悬浮）──────────────────────────
   视觉沿用上面「悬浮题目卡」那一套（同渐变底 / 同描边 / 同头部），只把正文换成译文。
   手机与手机预览不浮：贴底、让开 56px 的底部导航，位置全交给 CSS（不参与拖动）。 */
.float-t-card {
  position: fixed; z-index: 200; width: 460px; max-width: calc(100vw - 24px);
  display: none; flex-direction: column; overflow: hidden;
  background: linear-gradient(180deg, #FFFDF8, #FFF9EF);
  border: 1px solid #E7E0D2; border-radius: 16px;
  box-shadow: 0 20px 48px rgba(40,30,10,.16), 0 5px 14px rgba(40,30,10,.08);
}
.float-t-card.show { display: flex; -webkit-animation: fqIn .2s cubic-bezier(.22,.8,.32,1); animation: fqIn .2s cubic-bezier(.22,.8,.32,1); }
.float-t-card.dragging { box-shadow: 0 26px 60px rgba(40,30,10,.24), 0 8px 18px rgba(40,30,10,.12); }
.float-t-head {
  display: flex; align-items: center; gap: 8px; flex-shrink: 0;
  padding: 8px 12px 8px 10px; background: rgba(252,247,238,.9);
  border-bottom: 1px solid #EFE9DC; cursor: move;
  touch-action: none; user-select: none; -webkit-user-select: none;
}
.float-t-card.dragging .float-t-head { cursor: grabbing; }
.float-t-title { flex: 1; min-width: 0; font-size: .78em; font-weight: 700; color: #57534E; letter-spacing: .03em; }
.float-t-body { overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; max-height: calc(64vh - 42px); }
.float-t-body .full-trans {
  margin: 0; padding: 4px 18px 18px; background: transparent;
  border: none; box-shadow: none; border-radius: 0; font-size: .92em; line-height: 1.95;
}
.float-t-body .full-trans p { text-indent: 2em; margin: 0 0 2px; }
.float-t-body ::selection { background: #E9E0D4; color: #292524; }
html.dark .float-t-card { background: linear-gradient(180deg, #2A2520, #26211C); border-color: #3F3A37; box-shadow: 0 20px 48px rgba(0,0,0,.5); }
html.dark .float-t-head { background: rgba(45,39,33,.9); border-bottom-color: #3B352D; }
html.dark .float-t-title { color: #E5DFD4; }
html.dark .float-t-card .fq-grip { color: #6B6258; }
html.dark .float-t-body .full-trans { color: var(--c-text-secondary); }
html.dark .float-t-body ::selection { background: rgba(16,185,129,.42); color: #FFF; }
@media (prefers-reduced-motion: reduce) { .float-t-card.show { animation: none !important; } }
html.force-phone .float-t-card {
  left: 10px !important; right: 10px !important; top: auto !important; bottom: 66px !important;
  width: auto; max-width: none;
}
html.force-phone .float-t-head { cursor: default; }
html.force-phone .float-t-card .fq-grip { display: none; }   /* 手机上不能拖，就别给拖动的把手 */
html.force-phone .float-t-body { max-height: 58vh; }
html.force-phone .float-t-body .full-trans { font-size: .88em; padding: 4px 16px 16px; }

/* 平板窄侧栏：生词本/词组本 操作行纵向堆叠 (2026-09-03) */
@media (min-width: 769px) and (max-width: 1024px), html.force-tablet {
  #readingPage .vocab-sidebar .vocab-actions,
  #trainPage .train-rail .vocab-actions { flex-direction: column; gap: 6px; margin-top: 10px; }
  #readingPage .vocab-sidebar .vocab-actions button,
  #trainPage .train-rail .vocab-actions button { width: 100%; height: 28px; font-size: .74em; padding: 0 6px; }
  #readingPage .vocab-sidebar .vocab-actions .vocab-clear svg,
  #trainPage .train-rail .vocab-actions .vocab-clear svg { width: 11px; height: 11px; }
}

/* 生词本/词组本操作行：文案不折行，窄处自动独占一行 (2026-09-03) */
#readingPage .vocab-sidebar .vocab-actions,
#trainPage .train-rail .vocab-actions { flex-wrap: wrap; }
#readingPage .vocab-sidebar .vocab-actions button,
#trainPage .train-rail .vocab-actions button {
  flex: 1 1 0; min-width: max-content; max-width: 100%;
  white-space: nowrap; overflow: hidden;
}

/* 生词本/词组本操作行：两键恒定同一行、不折字 (2026-09-03) */
#readingPage .vocab-sidebar .vocab-actions,
#trainPage .train-rail .vocab-actions { flex-direction: row; flex-wrap: nowrap; }
#readingPage .vocab-sidebar .vocab-actions button,
#trainPage .train-rail .vocab-actions button { flex: 1 1 0; min-width: 0; white-space: nowrap; }
@media (min-width: 769px) and (max-width: 1024px), html.force-tablet {
  #readingPage .vocab-sidebar .vocab-actions,
  #trainPage .train-rail .vocab-actions { gap: 5px; }
  #readingPage .vocab-sidebar .vocab-actions button,
  #trainPage .train-rail .vocab-actions button { padding: 0 2px; gap: 3px; font-size: .66em; }
  #readingPage .vocab-sidebar .vocab-actions .vocab-clear svg,
  #trainPage .train-rail .vocab-actions .vocab-clear svg { width: 11px; height: 11px; }
  #readingPage .vocab-sidebar .vocab-actions .vocab-add-action svg,
  #trainPage .train-rail .vocab-actions .vocab-add-action svg { width: 11px; height: 11px; }
}

/* 导入阅读卡片色（user）(2026-09-03) */
.card.user .card-icon { background: #D0E4DC; color: #1E5B52; }
.card.user .card-badge { background: #DCE9E3; color: #1E5B52; }
html.dark .card.user .card-icon { background: #1E3A33; color: #8FC8B6; }
html.dark .card.user .card-badge { background: #22443A; color: #9FD9C4; }
/* 导入阅读页 (2026-09-03) */
/* 顶栏对齐基础性阅读：桌面不加页内距（sticky 顶栏自然），移动端按固定顶栏补高 */
@media (min-width: 769px) and (max-width: 1024px) { #importReadingPage { padding-top: 52px; } }
html.force-tablet #importReadingPage { padding-top: 52px; }
@media (max-width: 768px) { #importReadingPage { padding-top: 68px; } }
html.force-phone #importReadingPage { padding-top: 68px; }
.imp-scope .imp-upload { border: 2px dashed rgba(90,110,69,.45); border-radius: 16px; padding: 40px 16px; text-align: center; color: #A8A29E; cursor: copy; background: rgba(255,253,248,.6); transition: all .18s ease; }
.imp-scope .imp-upload:hover { border-color: var(--c-accent); background: #F5EFE4; color: #5C4033; }
.imp-scope .imp-upload h3 { margin: 12px 0 6px; font-size: 1.05em; color: var(--c-text); }
.imp-scope .imp-upload p { margin: 0; font-size: .8em; }
.imp-scope .imp-upload svg { color: var(--c-accent-deep); }
html.dark .imp-scope .imp-upload { background: rgba(38,33,29,.4); }
/* 上传区两个按钮：文件上传（暖黄主钮）/ 拍照上传（白底次钮）；拖动上传依旧直接生效 */
.imp-scope .imp-actions { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; margin-top: 18px; }
.imp-scope .imp-btn {
  display: inline-flex; align-items: center; gap: 7px; padding: 9px 20px;
  border: 0; border-radius: 100px; background: #6B7F58; color: #fff;
  font: inherit; font-size: .84em; font-weight: 700; cursor: pointer;
  box-shadow: 0 2px 8px rgba(90,110,69,.25); transition: all .2s;
}
.imp-scope .imp-btn:hover { background: #D4A373; box-shadow: 0 6px 16px rgba(90,110,69,.3); transform: translateY(-1px); }
.imp-scope .imp-btn:active { background: #A8804E; box-shadow: none; transform: scale(.97); }
.imp-scope .imp-btn svg { width: 15px; height: 15px; flex-shrink: 0; color: currentColor; }
.imp-scope .imp-btn-cam { background: #fff; color: #4A3229; border: 1px solid rgba(90,110,69,.35); box-shadow: 0 1px 3px rgba(120,113,108,.12); }
.imp-scope .imp-btn-cam:hover { background: #FFFCF8; color: #5C4033; border-color: rgba(90,110,69,.55); }
.imp-scope .imp-btn-cam:active { background: #F5EFE3; }
html.dark .imp-scope .imp-btn { background: #6B7F58; color: #3F2D24; box-shadow: none; }
html.dark .imp-scope .imp-btn:hover { background: #D4A373; color: #3F2D24; }
html.dark .imp-scope .imp-btn:active { background: #A8804E; color: #3F2D24; }
html.dark .imp-scope .imp-btn-cam { background: #2A2623; color: #D4A373; border-color: #4A4034; }
html.dark .imp-scope .imp-btn-cam:hover { background: #2E2620; color: #E9E0D4; border-color: #7A5A2F; }
.imp-scope .imp-actions-tip { margin: 10px 0 0 !important; font-size: .74em !important; color: #A8A29E; }
@media (prefers-reduced-motion: reduce) { .imp-scope .imp-btn:hover, .imp-scope .imp-btn:active { transform: none; } }
@media (max-width: 480px) {
  .imp-scope .imp-upload { padding: 28px 12px; }
  .imp-scope .imp-actions { gap: 8px; }
  .imp-scope .imp-btn { padding: 9px 16px; font-size: .8em; }
}
/* 拍照上传页（2026-09-20 新增第三栏）：复用 .imp-upload 的虚线卡外观，
   但它不是拖拽区，所以把 cursor: copy 和 hover 高亮收掉（拖拽只绑在 #impUploadZone 上）。 */
#importCamView .imp-cam-hero { cursor: default; }
#importCamView .imp-cam-hero:hover { border-color: rgba(90,110,69,.45); background: rgba(255,253,248,.6); color: #A8A29E; }
html.dark #importCamView .imp-cam-hero:hover { background: rgba(38,33,29,.4); }
#importCamView .imp-cam-hero h3 { font-size: 1.15em; }
/* ── 拍照弹窗（2026-09-20 第 5 步 + 修订：取景尽可能大）──
   背景：拍照复用 .add-modal，而它是 min(370px, 100vw-40px) —— 取景框原本只有 ~330px 宽。
   所以只把**拍照**这一个弹窗放大（语义类名隔离，不影响其它弹窗）。
   修订要点（用户反馈"拍摄界面尽可能的大"）：
     · 取景框改成**按高度撑满**：原来是 max-height:60vh，对窄而竖的元素无效 ——
       手机上宽度 282 决定高度只有 212（仅占视口高的 25%），几乎没法构图。
     · 头部在取景态**收起图标与说明行**，只留紧凑标题，把空间让给取景框。 */
/* 关键：必须给**确定的 height**（只写 max-height 的话，flex 容器会按内容收缩到 453px，
   里面的 flex:1 就没有可分配空间 —— 实测这样取景框只有 min-height 那么高）。
   2026-09-20 第 8 步（用户要求"拍照窗口改成全屏"）：改成**真全屏** —— 贴满覆盖层、
   无圆角无边框，省下的边距全部给取景框。覆盖层 `.add-modal-overlay` 本来就是 inset:0 无内边距，
   所以 100vw/100vh 正好铺满。
   ⚠️ 高度写 `100dvh` 兜底 `100vh`：手机浏览器地址栏收起/展开时 vh 是不变的，
   dvh 才会跟着实际可视高度走（老浏览器不认 dvh，会退回上一行的 100vh）。
   取景框尺寸仍由 JS 按真实相机流比例算死（见 _camUpdateAspect），弹窗变大 → 框跟着变大。 */
#cameraModal .add-modal.cam-modal { width: 100vw;
  height: 100vh; height: 100dvh;
  max-width: none; max-height: none; border: none; border-radius: 0;
  padding: 12px;
  display: flex; flex-direction: column; overflow: hidden;
  animation: none; }
#cameraModal .cam-stage { position: relative; margin: 4px 0 8px; flex: 1 1 auto; min-height: 0;
  display: flex; align-items: center; justify-content: center; }
/* 取景框尺寸由 JS 按**真实相机流比例**算死（inline width/height，见 _camUpdateAspect），
   所以这里的 height:100%/min-height 都去掉 —— 它们会和 inline 尺寸打架。
   浅色描边 + 底部"页"标记：提示把纸的底边对进来，减少切边。 */
#cameraModal .cam-frame { position: relative; border-radius: 18px; overflow: hidden; background: #0B0A09;
  border: 1px solid rgba(90,110,69,.22); margin: 0 auto; }
#cameraModal .cam-frame::after { content: '页'; position: absolute; left: 50%; bottom: 8px; transform: translateX(-50%);
  font-size: .68em; letter-spacing: .18em; color: rgba(255,255,255,.72); text-shadow: 0 1px 3px rgba(0,0,0,.65); pointer-events: none; }
/* 预览态：看的是已拍的成片，去掉"对准"提示 */
#cameraModal .cam-frame.preview::after { display: none; }
#cameraModal .cam-frame.preview { border-color: rgba(41,37,36,.16); }
/* 暗色下取景框描边换成半透明白：原来那条浅色边在深底上会显出一圈发白（2026-09-20） */
html.dark #cameraModal .cam-frame { border-color: rgba(255,255,255,.14); }
html.dark #cameraModal .cam-frame.preview { border-color: rgba(255,255,255,.10); }
/* 视频/预览图填满取景框（object-fit:contain 保证不变形、不裁切） */
#cameraModal .cam-video { width: 100%; height: 100%; background: #231C15; object-fit: contain; display: block; }
#cameraModal .cam-stage img#camPreview { width: 100%; height: 100%; background: #231C15; object-fit: contain; display: block; }
#cameraModal .cam-hidden { display: none !important; }
/* 2026-09-20：相机弹窗的头部（相机图标 + 拍摄说明）已按用户要求整体删除，
   原来那几条"取景态把头部收起来"的规则连同横屏里的头部间距也一并删掉了 ——
   头部元素已经不存在，留着就是死样式。 */
/* 多张缩略图 */
#cameraModal .cam-shots { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin: 0 0 8px; min-height: 0; }
#cameraModal .cam-shots:empty { display: none; }
#cameraModal .cam-shot { position: relative; width: 64px; height: 64px; border-radius: 16px; overflow: hidden; border: 2px solid transparent; cursor: pointer; flex: none; background: #F3EFE6; }
#cameraModal .cam-shot img { width: 100%; height: 100%; object-fit: cover; display: block; }
#cameraModal .cam-shot.sel { border-color: #B45309; }
/* 删除钮：视觉 22px、热区够点（原来只有 20px，手机上点不中） */
#cameraModal .cam-shot-x { position: absolute; top: 2px; right: 2px; width: 22px; height: 22px; border-radius: 50%; border: none;
  background: rgba(41,37,36,.88); color: #fff; font-size: 13px; line-height: 20px; text-align: center; cursor: pointer; padding: 0; }
#cameraModal .cam-shot-x:hover { background: #8E3323; }
#cameraModal .cam-shot-idx { position: absolute; left: 4px; bottom: 3px; font-size: .62em; font-weight: 700; color: #fff; text-shadow: 0 1px 2px rgba(0,0,0,.7); }
html.dark #cameraModal .cam-shot { background: #3F3A37; }
/* 「继续拍」比主按钮弱一档：可选动作，不与「导入」抢视觉重心 */
#cameraModal .add-btn-more { background: #FFFFFF; color: #292524; border: 1px solid #E9E2D6; }
#cameraModal .add-btn-more:hover { background: #F5F0E6; }
html.dark #cameraModal .add-btn-more { background: #2A2623; color: #E7E5E4; border-color: #3F3A37; }
html.dark #cameraModal .add-btn-more:hover { background: #332E2A; }
#cameraModal .cam-importmode { color: var(--c-text-muted); }
#cameraModal .cam-importmode input { accent-color: #5C4033; }
/* 关闭钮（2026-09-20 第 8 步）：标题删掉之后，它是取景区里唯一的可视出口 ——
   原来是无底色灰色图标，压在深色取景画面上几乎看不见，这里给它一个半透明底 + 阴影。 */
#cameraModal .add-modal-close { z-index: 5; background: rgba(255,255,255,.86); color: #44403C;
  box-shadow: 0 2px 8px rgba(0,0,0,.2); }
#cameraModal .add-modal-close:hover { background: #fff; color: var(--c-text); }
html.dark #cameraModal .add-modal-close { background: rgba(41,37,36,.86); color: #E7E5E4; }
html.dark #cameraModal .add-modal-close:hover { background: #292524; color: #fff; }
/* ── 横屏（2026-09-20 A 方案）──
   真实约束：手机横过来视口高度只有约 360~390px，竖布局必溢出，所以要压缩留白。
   （2026-09-20 第 8 步起弹窗已经**真全屏**，这里不再需要 98vw/98vh 那两行。）
   ⚠️ `orientation` 指**视口**方向、不是设备方向：桌面窗口天生宽>高，
   单写 `orientation: landscape` 会把桌面也套上这套样式（实测桌面弹窗被撑到 882px、
   还覆盖掉它原本的 min(820px,…)）。所以必须同时限定"视口矮"，才真正只打到手机横屏。 */
@media (orientation: landscape) and (max-height: 560px) {
  /* 尺寸已经是全屏（上面那条规则），这里只压留白 —— 横屏视口高度只有 360~390px */
  #cameraModal .add-modal.cam-modal { padding: 6px 8px 8px; }
  #cameraModal .cam-stage { margin: 2px 0 6px; }
  /* 取景框尺寸**交给 JS**（inline width/height，按真实剩余空间与相机流比例算死）。
     这里刻意不再写 max-height/max-width —— 写了会 clamp 掉 inline 尺寸：
     实测 46vh 把 JS 算好的 232px 压到 179px，比例就失真了。 */
  #cameraModal .cam-shots { margin-bottom: 6px; gap: 6px; }
  #cameraModal .cam-shot { width: 48px; height: 48px; }
  #cameraModal #camHint { font-size: .78em; margin: 0 0 4px !important; }
  #cameraModal .add-modal-btns { flex-direction: row; gap: 8px; }
  #cameraModal .add-modal-btns button { flex: 1 1 0; min-width: 0; height: 38px; font-size: .86em; padding: 0 8px; }
}
/* 手机竖屏：三按钮横排会把「继续拍」挤成 60px，改成纵向堆叠、主按钮在上；同时压缩留白。
   注意用 orientation:portrait 限定 —— 否则它会给横屏（窄高视口）也加上 min-height:200px，
   把横屏刚压下去的高度又顶起来（横屏空间本来就紧张）。 */
@media (max-width: 420px) and (orientation: portrait) {
  #cameraModal .add-modal-btns { flex-direction: column-reverse; gap: 8px; }
  #cameraModal .add-modal-btns button { flex: 0 0 auto; width: 100%; }
  #cameraModal .add-modal.cam-modal { padding: 18px 16px 16px; }
  #cameraModal .cam-frame { min-height: 120px; }
  #cameraModal .cam-shot { width: 56px; height: 56px; }
}
@media (prefers-reduced-motion: reduce) {
  #cameraModal .cam-frame::after { animation: none; }
}
.imp-scope .imp-format { margin-top: 18px; background: #FFFCF8; border: 1px solid #EFE9DC; border-radius: 14px; padding: 14px 16px; }
html.dark .imp-scope .imp-format { background: #2E2924; border-color: #3F3A37; }
.imp-scope .imp-format h4 { margin: 0 0 10px; font-size: .86em; color: var(--c-primary-dark); }
.imp-scope .imp-format pre { margin: 0; font-size: .78em; line-height: 1.7; color: var(--c-text-secondary); background: #F7F3EA; border-radius: 16px; padding: 12px; overflow-x: auto; white-space: pre; }
html.dark .imp-scope .imp-format pre { background: #221E1A; }
.imp-scope .imp-format h4 { margin-bottom: 6px; }
.imp-scope .imp-dl-row { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 10px; }
.imp-scope .imp-dl { display: inline-flex; align-items: center; gap: 6px; padding: 5px 12px; border-radius: 100px; border: 1px solid rgba(90,110,69,.35); background: #F2EDE4; color: #4A3229; font-size: .74em; font-weight: 600; text-decoration: none; transition: all var(--transition-fast); }
.imp-scope .imp-dl:hover { background: #E9E0D4; border-color: var(--c-accent); box-shadow: 0 1px 5px rgba(90,110,69,.18); }
.imp-scope .imp-dl svg { width: 13px; height: 13px; flex-shrink: 0; }
html.dark .imp-scope .imp-dl { background: #2E2620; border-color: #7A5A2F; color: #D4A373; }
html.dark .imp-scope .imp-dl:hover { background: #443018; border-color: var(--c-accent); }
/* ── 批量导入：进度 / 结果面板（一次可导入多篇）──
   作用域限定在 #importReadingPage —— 小说导入复用了同名 .imp-* 类，不能外溢。
   2026-09-20 第 9 步：由「拖拽区内嵌条」改成**居中弹窗**（用户要求"进度条用弹窗显示在拍照上传页面"）。
   ⚠️ z-index 310 是刻意的：必须**低于**逐篇确认用的 #impPrevOverlay（320），
   否则进度弹窗会盖在预览上面，用户点不到「确认导入 / 不导入」。
   （其它 .add-modal-overlay 都是 500：相机弹窗这时已经关了，不受影响。） */
#impProg { z-index: 310; }
.imp-scope .imp-prog-modal { width: min(440px, calc(100vw - 40px)); padding: 22px 22px 18px;
  max-height: min(560px, calc(100vh - 32px)); overflow-y: auto;
  /* 不要滚动条（用户要求）：兜底滚动仍然留着，但把滚动条的视觉藏掉（Firefox / 老 Edge / WebKit 三套写法） */
  scrollbar-width: none; -ms-overflow-style: none; }
.imp-scope .imp-prog-modal::-webkit-scrollbar { display: none; }
/* 右上角的进度胶囊：导入中是「2/3」，结束即隐藏（那时状态由标题与清单表达，别重复说同一件事）。
   用 tabular-nums 让数字跳动时不左右抖。 */
.imp-scope .imp-prog-count { margin-left: auto; flex-shrink: 0; align-self: flex-start;
  font-style: normal; font-family: system-ui, -apple-system, 'Segoe UI', 'Microsoft YaHei', sans-serif; font-variant-numeric: tabular-nums;
  font-size: .76em; font-weight: 700; color: var(--c-accent-deep);
  background: rgba(90,110,69,.10); border: 1px solid rgba(90,110,69,.20);
  border-radius: 999px; padding: 4px 10px; }
html.dark .imp-scope .imp-prog-count { color: #E9E0D4; background: rgba(163,185,140,.14); border-color: rgba(163,185,140,.28); }
/* ── 导入中的「点手指」等待动画（2026-09-20 第 10 步，用户提供的 CSS）──
   取代了原来那根 `imp-prog-track/fill` 进度条（条数已经由右上角的「3/10」表达）。
   两点工程处理：
   1. **作用域**：类名是 emoji（🤚 / 👉 / 🌴 / 👍），不限定范围会污染全局样式，
      所以每条选择器都加上 `#impProg` 前缀；类名本身保持用户给的写法不改名
      （CSS 标识符允许非 ASCII 字符，`class="🤚"` 与 `document.querySelector('.🤚')` 在现代浏览器都正常）。
   2. **结束后收掉**：`.imp-prog-done` 时隐藏动画 —— 那时要看的是失败清单，不是"正在忙"。
   `margin-left: 80px` 是原作者用来补偿"手指往左伸出去"的偏移，配合 flex 居中刚好把整只手摆正。 */
#impProg .imp-prog-hand { display: flex; justify-content: center; margin: 10px 0 18px; }
#impProg.imp-prog-done .imp-prog-hand { display: none; }
#impProg .🤚 {
  --skin-color: #D4A373;
  --tap-speed: 0.6s;
  --tap-stagger: 0.1s;
  position: relative;
  width: 80px;
  height: 60px;
  margin-left: 80px;
}
#impProg .🤚:before {
  content: '';
  display: block;
  width: 180%;
  height: 75%;
  position: absolute;
  top: 70%;
  right: 20%;
  background-color: #231C15;
  border-radius: 40px 10px;
  filter: blur(10px);
  opacity: 0.3;
}
#impProg .🌴 {
  display: block;
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  background-color: var(--skin-color);
  border-radius: 16px 40px;
}
#impProg .👍 {
  position: absolute;
  width: 120%;
  height: 38px;
  background-color: var(--skin-color);
  bottom: -18%;
  right: 1%;
  transform-origin: calc(100% - 20px) 20px;
  transform: rotate(-20deg);
  border-radius: 30px 20px 20px 10px;
  border-bottom: 2px solid rgba(0, 0, 0, 0.1);
  border: 1px solid rgba(0, 0, 0, 0.1);
}
#impProg .👍:after {
  width: 20%;
  height: 60%;
  content: '';
  background-color: rgba(255, 255, 255, 0.3);
  position: absolute;
  bottom: -8%;
  left: 5px;
  border-radius: 60% 10% 10% 30%;
  border: 1px solid rgba(0, 0, 0, 0.05);
}
#impProg .👉 {
  position: absolute;
  width: 80%;
  height: 35px;
  background-color: var(--skin-color);
  bottom: 32%;
  right: 64%;
  transform-origin: 100% 20px;
  animation-duration: calc(var(--tap-speed) * 2);
  animation-timing-function: ease-in-out;
  animation-iteration-count: infinite;
  transform: rotate(10deg);
}
#impProg .👉:before {
  content: '';
  position: absolute;
  width: 140%;
  height: 30px;
  background-color: var(--skin-color);
  bottom: 8%;
  right: 65%;
  transform-origin: calc(100% - 20px) 20px;
  transform: rotate(-60deg);
  border-radius: 20px;
}
#impProg .👉:nth-child(1) { animation-delay: 0; filter: brightness(70%); animation-name: tap-upper-1; }
#impProg .👉:nth-child(2) { animation-delay: var(--tap-stagger); filter: brightness(80%); animation-name: tap-upper-2; }
#impProg .👉:nth-child(3) { animation-delay: calc(var(--tap-stagger) * 2); filter: brightness(90%); animation-name: tap-upper-3; }
#impProg .👉:nth-child(4) { animation-delay: calc(var(--tap-stagger) * 3); filter: brightness(100%); animation-name: tap-upper-4; }
@keyframes tap-upper-1 { 0%, 50%, 100% { transform: rotate(10deg) scale(0.4); } 40% { transform: rotate(50deg) scale(0.4); } }
@keyframes tap-upper-2 { 0%, 50%, 100% { transform: rotate(10deg) scale(0.6); } 40% { transform: rotate(50deg) scale(0.6); } }
@keyframes tap-upper-3 { 0%, 50%, 100% { transform: rotate(10deg) scale(0.8); } 40% { transform: rotate(50deg) scale(0.8); } }
@keyframes tap-upper-4 { 0%, 50%, 100% { transform: rotate(10deg) scale(1); } 40% { transform: rotate(50deg) scale(1); } }
/* 尊重"减少动态效果"：这组动画是纯装饰，关掉不影响任何信息 */
@media (prefers-reduced-motion: reduce) {
  #impProg .👉 { animation: none; }
}
/* 失败/提示逐条列出。左边那列是固定的「失败 / 提示」短标签，所以给它一个固定宽度让右侧文字对齐成一条竖线。
   2026-09-20（用户要求「不要滚动条」）：这里**不再自己滚**、按内容长高 —— 平时就几条，撑不出滚动条。
   弹窗整体仍保留"不超出视口"的兜底（见 .imp-prog-modal），但把滚动条本身藏掉，
   真到极端情况（矮横屏 + 10 条失败）还能用滚轮 / 触摸滚到按钮，不至于够不着。 */
.imp-scope .imp-prog-list { margin: 4px 0 0; padding: 0; list-style: none; font-size: .82em; line-height: 1.7; color: var(--c-text-secondary); }
.imp-scope .imp-prog-list li { display: flex; gap: 8px; padding: 3px 0; }
.imp-scope .imp-prog-list li + li { border-top: 1px solid var(--c-border); }
.imp-scope .imp-prog-list b { color: var(--c-danger); font-weight: 700; flex-shrink: 0; width: 2.4em; }
.imp-scope .imp-prog-list b.imp-note { color: #5C4033; }
html.dark .imp-scope .imp-prog-list b.imp-note { color: #D4A373; }
html.dark .imp-scope .imp-prog-list b { color: #E08B76; }
/* 「知道了」只在导入结束（且有失败/提示）时出现 —— 见 impProgressDone；
   按钮本身用全站共用的 .add-btn-confirm，这里只管它上面那点间距。 */
.imp-scope .imp-prog-modal .add-modal-btns { margin-top: 16px; }
/* 焦点环：全站那条 `button:focus-visible { outline: 2px solid var(--c-accent) }` 是琥珀色，
   压在琥珀填充的确认按钮上几乎等于没有 —— 换成中性深灰（同站内 .ws-quota-ctl 的先例），
   保证键盘用户在任何状态下都看得见焦点在哪。 */
.imp-scope .imp-prog-modal .add-btn-confirm:focus-visible { outline: 2px solid #57534E; outline-offset: 2px; }
html.dark .imp-scope .imp-prog-modal .add-btn-confirm:focus-visible { outline-color: #D6D3D1; }
/* 导入中锁住上传区，避免重复触发 */
.imp-scope .imp-upload.busy { opacity: .5; pointer-events: none; }
/* ── 导入规则：把限制与格式约定写在页面上（用户要求"写清楚上限"）──
   标签/取值两列，窄屏折成一列。所有条目都与代码实际行为逐条对齐，不是泛泛而谈。 */
.imp-scope .imp-rules { margin-top: 16px; background: #FFFCF8; border: 1px solid #EFE9DC; border-radius: 14px; padding: 14px 16px; }
html.dark .imp-scope .imp-rules { background: #2E2924; border-color: #3F3A37; }
.imp-scope .imp-rules h4 { margin: 0 0 10px; font-size: .86em; color: var(--c-primary-dark); }
.imp-scope .imp-rules-list { margin: 0; display: grid; gap: 7px; }
.imp-scope .imp-rules-list > div { display: grid; grid-template-columns: 78px 1fr; gap: 10px; align-items: baseline; font-size: .78em; line-height: 1.65; }
/* 标签用 --c-text + 加粗来建立层级，而不是用更浅的颜色：
   原写法用 --c-text-muted，实测对比度只有 2.5:1（暗色 3.95:1），
   低于正文 4.5:1 的要求 —— 把限制条件写得"看不清"就失去意义了。 */
.imp-scope .imp-rules-list dt { color: var(--c-text); font-weight: 600; white-space: nowrap; }
.imp-scope .imp-rules-list dd { margin: 0; color: var(--c-text-secondary); }
.imp-scope .imp-rules-list b { color: var(--c-text); font-weight: 700; }
.imp-scope .imp-rules-list code { font-family: ui-monospace, 'SFMono-Regular', Menlo, Consolas, monospace; font-size: .94em; background: #F7F3EA; border: 1px solid #EFE9DC; border-radius: 5px; padding: 0 4px; color: #4A3229; }
html.dark .imp-scope .imp-rules-list code { background: #221E1A; border-color: #3F3A37; color: #D4A373; }
@media (max-width: 480px) {
  .imp-scope .imp-rules-list > div { grid-template-columns: 1fr; gap: 1px; }
}

/* AI 导入阅读卡：顶部彩色线条 (2026-09-03) */
.card.user::before { background: #4C887C; }

/* 导入阅读页 radio-group 滑动指示器 (2026-09-03)
   2026-09-20：加「拍照上传」当第三栏，由两段式 translateX(100%) 改成三段式 left 定位
   （同「已做阅读」三栏的写法）。 */
.radio-group:has(#impCameraRadio) { width: 252px; }
.radio-group:has(#impCameraRadio) .rg-slider { width: calc(33.333% - 3px); }
/* 滑块位置跟着新顺序走（上传文件 0 / 拍照上传 1 / 我导入的 2；第一格用基础 left，无需单独写） */
.radio-group:has(#impCameraRadio:checked) .rg-slider { left: calc(33.333%); }
.radio-group:has(#impLibRadio:checked) .rg-slider { left: calc(66.666%); }
@media (max-width: 768px), html.force-phone {
  .radio-group:has(#impCameraRadio) { width: 216px; }
}

/* 精读训练页排版（rhythm pass, 2026-09-03）*/
#trainPage .train-page { padding: 16px 22px 72px; }
#trainPage .train-layout { gap: 18px; align-items: start; }
#trainPage .train-rail { top: 88px; max-height: calc(100vh - 116px); padding: 0 2px 6px; }
#trainPage .train-rail .vocab-panel { margin-bottom: 10px; padding: 13px 12px 14px; border-radius: 14px; box-shadow: 0 1px 2px rgba(0,0,0,.03), 0 6px 18px rgba(0,0,0,.04); }
#trainPage .train-rail .vocab-list { max-height: 40vh; }
#trainPage .train-rail .vocab-panel h3 { margin-bottom: 10px; }
#trainPage .train-center { min-width: 0; }
#trainPage .train-type-chip { flex-wrap: wrap; row-gap: 6px; margin: 2px 0 10px; }
#trainPage .train-tip { margin: 0 auto 12px; font-size: .8em; color: var(--c-text-muted); text-align: center; line-height: 1.7; }
#trainPage .train-card { padding: 2px 0 0; }
#trainPage .train-sentence { padding: 16px 20px 20px; margin-bottom: 12px; }
#trainPage .train-stem { margin: 12px 0 8px; }
#trainPage .train-options { margin-bottom: 6px; }
#trainPage .train-actions { margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--c-border); }
@media (min-width: 769px) and (max-width: 1024px) {
  #trainPage .train-page { padding: 12px 16px 60px; }
  #trainPage .train-rail { top: 84px; max-height: calc(100vh - 108px); }
  #trainPage .train-sentence { padding: 13px 16px 17px; }
}
html.force-tablet #trainPage .train-page { padding: 12px 16px 60px; }
html.force-tablet #trainPage .train-rail { top: 84px; }
@media (max-width: 768px) {
  /* ⚠️ 第四十八轮（2026-10-06 用户：手机版精读训练做题界面，最上方的导航栏遮住了上方的按钮）：
     手机档那条 `.topbar` 是 `position: fixed` 的**悬浮胶囊**（第 3631 行 top:0 + 基础那条 margin-top 16
     → 实测 y 16~72，高 56，z-index 100），而这一页原来只留了 64px 上内边距
     → 内容第一排（`.train-type-chip` 的「切换题型 / 保存训练 / 全文翻译」）落在 y 66~88，
     顶上 6px 被那颗胶囊盖住（`elementFromPoint(66/68/70)` 命中的是 `DIV.topbar`，点不到也看不全）。
     改成 80px（= 胶囊底 72 + 8px 呼吸位）后第一排从 82 开始，整排都在胶囊下面。 */
  #trainPage .train-page { padding: 80px 12px 110px; }
  #trainPage .train-rail { order: 2; position: static; }
  #trainPage .train-layout { max-width: 560px; }
}
html.force-phone #trainPage .train-page { padding: 80px 12px 110px; }

/* 精读训练：词卡栏与答案句卡底边平齐 (2026-09-03) */
#trainPage .train-rail .vocab-panel { display: flex; flex-direction: column; min-height: 0; }
#trainPage .train-rail .vocab-list { flex: 1 1 auto; min-height: 0; overflow-y: auto; }

/* ===== 精读训练工作台重设计（暖纸学习台 · 2.7.7）===== */
/* —— 栏距与三列对齐：词卡栏顶部与中央题目卡对齐 —— */
#trainPage .train-layout { column-gap: 24px; align-items: start; }
#trainPage ::selection { background: #E9E0D4; color: #292524; }
@media (min-width: 1025px) {
  #trainPage .train-page { padding: 18px 24px 72px; }
  #trainPage .train-rail { margin-top: 70px; }
}

/* —— 两侧词卡栏卡片体系 —— */
#trainPage .train-rail .vocab-panel {
  position: relative;
  border-radius: 16px;
  border: 1px solid rgba(120,113,108,.18);
  background: #FFFEFB;
  box-shadow: 0 1px 2px rgba(0,0,0,.02), 0 10px 22px rgba(120,113,108,.07);
  padding: 14px 15px 15px;
}
#trainPage .train-rail .vocab-panel h3 { gap: 8px; align-items: center; margin-bottom: 12px; }
#trainPage .train-rail .vocab-panel h3 > svg {
  width: 26px; height: 26px; box-sizing: border-box; padding: 5px;
  border-radius: 16px; flex-shrink: 0; transition: transform var(--transition-fast);
}
#trainPage .train-rail .vocab-panel h3:hover > svg { transform: translateY(-1px); }
#trainPage .train-rail .vocab-panel:not(.phrase-panel) h3 > svg { background: #FBE6C4; color: #B45309; }
#trainPage .train-rail .vocab-panel.phrase-panel h3 > svg { background: #DCEFE5; color: #12725B; }
#trainPage .train-rail .vocab-panel h3 .vt-title { font-size: 1em; font-weight: 700; letter-spacing: .01em; color: #3E3830; }
#trainPage .train-rail .vocab-panel h3 .count {
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 999px; min-width: 25px; height: 20px; padding: 0 8px;
  font-size: .7em; font-weight: 700; letter-spacing: .02em;
}
#trainPage .train-rail .vocab-panel:not(.phrase-panel) h3 .count { background: #F9E4BF; color: #8C3F08; }
#trainPage .train-rail .vocab-panel.phrase-panel h3 .count { background: #DAECE2; color: #0F5C49; }
#trainPage .train-rail .vocab-panel h3 .vocab-hl-bar {
  height: 22px; padding: 0 8px; border-radius: 100px;
  font-size: .64em; font-weight: 700; letter-spacing: .02em;
  color: #84755C; background: #F6F1E6; border: 1px solid #E9E0CE;
  transition: all var(--transition-fast);
}
#trainPage .train-rail .vocab-panel h3 .vocab-hl-bar svg { width: 11px; height: 11px; }
#trainPage .train-rail .vocab-panel h3 .vocab-hl:hover .vocab-hl-bar { background: #F0E7D6; border-color: #DED2BB; }
#trainPage .train-rail .vocab-panel h3 .vocab-hl input:checked + .vocab-hl-bar {
  background: #FCE9BD; border-color: rgba(217,119,6,.6); color: #92400E;
  box-shadow: 0 1px 5px rgba(217,119,6,.18);
}

/* —— 词条行 —— */
#trainPage .train-rail .vocab-list { scrollbar-width: thin; }
#trainPage .train-rail .vocab-item { padding: 8px 24px 8px 2px; border-bottom-color: #F1EBDF; }
#trainPage .train-rail .vocab-item .w {
  display: block; font-size: .86em; font-weight: 700; letter-spacing: .004em;
  color: #2A2622; margin-bottom: 1px;
}
#trainPage .train-rail .vocab-item .m {
  color: #85786A; font-size: .78em; line-height: 1.55;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
#trainPage .train-rail .vocab-item .del {
  width: 22px; height: 22px; display: inline-flex; align-items: center; justify-content: center;
  top: 50%; transform: translateY(-50%); right: 0; font-size: 15px; line-height: 1; padding: 0;
  background: #F5F0E6; border: 1px solid #E7DCC8; color: #B3A489; border-radius: 50%;
  transition: all var(--transition-fast);
}
#trainPage .train-rail .vocab-item .del:hover { color: #B03420; background: #FBE8E6; border-color: #F0B9B5; }

/* —— 空状态 —— */
#trainPage .train-rail .vocab-empty {
  color: #8A7B64; padding: 22px 6px 24px; font-size: .8em; line-height: 1.7; text-align: center;
}
#trainPage .train-rail .vocab-empty::before {
  content: ''; display: block; width: 26px; height: 26px; margin: 0 auto 10px; opacity: .85;
  border-radius: 50%; border: 1.5px dashed #D9C7A3; box-sizing: border-box;
  background: radial-gradient(circle, rgba(217,119,6,0) 42%, rgba(217,119,6,.14) 43%, rgba(217,119,6,.14) 45%, rgba(217,119,6,0) 46%);
}

/* —— 底部操作 —— */
#trainPage .train-rail .vocab-actions { gap: 7px; margin-top: 13px; }
#trainPage .train-rail .vocab-actions button {
  height: 30px; padding: 0 6px; border-radius: 16px;
  font-size: .75em; font-weight: 600; letter-spacing: .01em;
  display: inline-flex; align-items: center; justify-content: center; gap: 4px;
}
#trainPage .train-rail .vocab-actions button svg { width: 12px; height: 12px; flex-shrink: 0; }
#trainPage .train-rail .vocab-actions .vocab-clear { background: #FAF6EE; border: 1px solid #E9E1D1; color: #99896F; }
#trainPage .train-rail .vocab-actions .vocab-clear:hover { color: #B03420; border-color: #ECB7AE; background: #FBEDE9; }
#trainPage .train-rail .vocab-actions .vocab-add-action {
  color: #FFFDF7; border: 1px solid transparent;
  background: linear-gradient(135deg, #F6A73B, #E08A0E);
  box-shadow: 0 2px 6px rgba(217,119,6,.22);
}
#trainPage .train-rail .vocab-actions .vocab-add-action:hover { filter: brightness(1.05); box-shadow: 0 3px 9px rgba(217,119,6,.3); }

/* —— 顶部题型 chip / 提示 —— */
#trainPage .train-type-chip { justify-content: center; margin: 2px 0 12px; color: #8A7A6B; letter-spacing: .02em; }
#trainPage .train-type-switch {
  color: #8A7355; border-color: #EDE4D4; border-radius: 100px; padding: 3px 11px;
  background: transparent; font-size: .7em; font-weight: 600;
}
#trainPage .train-type-switch:hover { color: #4A3229; border-color: rgba(90,110,69,.45); background: #E9E0D4; }
#trainPage .train-tip { color: #9B8B73; letter-spacing: .02em; }

/* —— 中央答案句卡 —— */
#trainPage .train-sentence { border-radius: 16px; }
/* 底色挪到 ::before 且 z-index:-2：不透明底色会盖住划词色块（-1 层），这里让它退到色块之下 */
#trainPage .train-sentence { background: transparent; }
#trainPage .train-sentence::before { content: ''; position: absolute; inset: -1px; z-index: -2; border-radius: inherit; background: #F2F5FA; }
html.dark #trainPage .train-sentence::before { background: #202832; }
#trainPage .train-sentence-text { letter-spacing: .001em; }

/* —— 手机/小屏：生词本+词组本并排于中卡之下 —— */
@media (max-width: 768px), html.force-phone {
  #trainPage .train-layout { display: flex; flex-direction: row; flex-wrap: wrap; column-gap: 12px; row-gap: 12px; max-width: 640px; margin: 0 auto; }
  #trainPage .train-center { order: 1; flex: 0 0 100%; }
  #trainPage .train-rail { order: 2; position: static; max-height: none; overflow: visible; width: auto; margin-top: 0; }
  #trainPage .train-rail-left, #trainPage .train-rail-right { flex: 1 1 calc(50% - 6px); min-width: 0; }
  #trainPage .train-rail .vocab-panel { padding: 12px 13px 13px; }
  #trainPage .train-rail .vocab-panel h3 > svg { width: 24px; height: 24px; padding: 4px; }
  #trainPage .train-rail .vocab-panel h3 .vocab-hl-bar { padding: 0 7px; font-size: .6em; }
}
@media (max-width: 559px), html.force-phone {
  #trainPage .train-layout { column-gap: 8px; row-gap: 10px; }
  #trainPage .train-rail .vocab-panel { padding: 11px 10px 12px; }
  #trainPage .train-rail .vocab-panel h3 { gap: 6px; row-gap: 5px; flex-wrap: wrap; }
  #trainPage .train-rail .vocab-panel h3 .vt-title { font-size: .95em; letter-spacing: 0; }
  #trainPage .train-rail .vocab-panel h3 > svg { width: 20px; height: 20px; padding: 4px; }
  #trainPage .train-rail .vocab-panel h3 .count { min-width: 20px; height: 18px; padding: 0 5px; font-size: .66em; }
  #trainPage .train-rail .vocab-panel h3 .vocab-hl { flex: 1 1 100%; justify-content: flex-end; margin-left: 0; }
  #trainPage .train-rail .vocab-panel h3 .vocab-hl-bar { height: 20px; padding: 0 7px; font-size: .6em; gap: 3px; }
  #trainPage .train-rail .vocab-actions { flex-direction: column; align-items: stretch; gap: 5px; }
  #trainPage .train-rail .vocab-actions button { width: 100%; height: 28px; }
  #trainPage .train-rail .vocab-item { padding: 7px 20px 7px 2px; }
}

/* —— 暗夜模式（暖纸->夜读纸）—— */
html.dark #trainPage ::selection { background: rgba(90,110,69,.55); color: #F2EDE4; }
html.dark #trainPage .train-rail .vocab-panel {
  background: #2A2621; border-color: rgba(255,255,255,.06);
  box-shadow: 0 1px 2px rgba(0,0,0,.25), 0 10px 24px rgba(0,0,0,.38);
}
html.dark #trainPage .train-rail .vocab-panel h3 .vt-title { color: #EEE7DC; }
html.dark #trainPage .train-rail .vocab-panel:not(.phrase-panel) h3 > svg { background: #4A3417; color: #F3CB83; }
html.dark #trainPage .train-rail .vocab-panel.phrase-panel h3 > svg { background: #17392E; color: #93D8BC; }
html.dark #trainPage .train-rail .vocab-panel:not(.phrase-panel) h3 .count { background: #3E2F15; color: #F0C674; }
html.dark #trainPage .train-rail .vocab-panel.phrase-panel h3 .count { background: #16352B; color: #9AD7BC; }
html.dark #trainPage .train-rail .vocab-panel h3 .vocab-hl-bar {
  background: #37312A; border-color: #494037; color: #9D8F7A;
}
html.dark #trainPage .train-rail .vocab-panel h3 .vocab-hl:hover .vocab-hl-bar { background: #40382F; border-color: #574A3C; }
html.dark #trainPage .train-rail .vocab-panel h3 .vocab-hl input:checked + .vocab-hl-bar {
  background: #4A3417; border-color: rgba(245,158,11,.6); color: #FCE3AE; box-shadow: 0 1px 5px rgba(0,0,0,.4);
}
html.dark #trainPage .train-rail .vocab-item { border-bottom-color: #3A342C; }
html.dark #trainPage .train-rail .vocab-item .w { color: #ECE5DA; }
html.dark #trainPage .train-rail .vocab-item .m { color: #A79B88; }
html.dark #trainPage .train-rail .vocab-item .del { background: #3A332C; border-color: #4C433A; color: #948774; }
html.dark #trainPage .train-rail .vocab-item .del:hover { color: #FAA0A0; border-color: #A23D3D; background: #4A2020; }
html.dark #trainPage .train-rail .vocab-empty { color: #A89A84; }
html.dark #trainPage .train-rail .vocab-empty::before { border-color: #5A4B36; background: radial-gradient(circle, rgba(217,119,6,0) 42%, rgba(217,119,6,.12) 43%, rgba(217,119,6,.12) 45%, rgba(217,119,6,0) 46%); }
html.dark #trainPage .train-rail .vocab-actions .vocab-clear { background: transparent; border-color: #4A4036; color: #A0937C; }
html.dark #trainPage .train-rail .vocab-actions .vocab-clear:hover { color: #FCA5A5; border-color: #8F3F3F; background: #3C1F1F; }
html.dark #trainPage .train-rail .vocab-actions .vocab-add-action {
  color: #FFF9EF; background: linear-gradient(135deg, #B45309, #92400E); box-shadow: 0 2px 6px rgba(0,0,0,.35);
}
html.dark #trainPage .train-type-chip { color: #B9A899; }
html.dark #trainPage .train-type-switch { color: #A79A83; border-color: #494035; background: transparent; }
html.dark #trainPage .train-type-switch:hover { color: #D4A373; border-color: #7A5A2F; background: #2E2620; }
html.dark #trainPage .train-tip { color: #A49A8A; }

/* ===== 精读训练顶部按钮：Uiverse(suda-code) 胶囊皮肤 · 纯白 =====
   底色/悬停/按下都保持纯白（#fff），边框与阴影改用**中性灰**、字色改中性深灰 ——
   之前用暖色边框+暖字，叠在米黄纸底上会整体发米，看着"不够白"。
   ⚠ 作用域限定 #trainPage .train-type-switch —— 站内裸 button 有 100+ 处，绝不能全局生效。 */
#trainPage .train-type-switch {
  border: 1px solid #E9E2D6; border-radius: 100px; padding: 8px 18px;
  background: #FFFFFF; color: #44403C; font-weight: 700; font-size: .74em; letter-spacing: .01em;
  cursor: pointer; white-space: nowrap; box-shadow: 0 1px 2px rgba(0,0,0,.06);
  transition: all .5s ease; -webkit-transition: all .5s ease;
}
#trainPage .train-type-switch:hover {
  background: #FFFFFF; color: #292524; border-color: #D8CFC0;
  box-shadow: 0 6px 18px rgba(0,0,0,.14);
  transform: scale(1.06);
}
#trainPage .train-type-switch:active {
  background: #F2F2F2; color: #292524; border-color: #D8CFC0; box-shadow: none; transform: scale(.98);
  transition: all .25s ease; -webkit-transition: all .25s ease;
}
/* 暗夜同样保持纯白（用户要求"就是要白"） */
html.dark #trainPage .train-type-switch { background: #FFFFFF; color: #292524; border-color: #FFFFFF; box-shadow: 0 1px 2px rgba(0,0,0,.3); }
html.dark #trainPage .train-type-switch:hover { background: #FFFFFF; color: #1C1917; border-color: #FFFFFF; box-shadow: 0 6px 18px rgba(0,0,0,.5); }
html.dark #trainPage .train-type-switch:active { background: #EDEDED; color: #1C1917; border-color: #EDEDED; }
/* 报错按钮与旁边按钮**完全同款**（用户要求），只是多做一件事：点它提交报错 */
@media (prefers-reduced-motion: reduce) {
  #trainPage .train-type-switch:hover, #trainPage .train-type-switch:active { transform: none; }
}
/* 原题训练：正文标题（文章信息）旁的报错按钮 —— 与精读训练同款纯白胶囊，无图标 */
.report-entry {
  display: inline-flex; align-items: center; margin-left: 8px; vertical-align: middle;
  padding: 3px 12px; border: 1px solid #E9E2D6; border-radius: 100px;
  background: #FFFFFF; color: #44403C; font: inherit; font-size: .62em; font-weight: 700; letter-spacing: .01em;
  cursor: pointer; white-space: nowrap; box-shadow: 0 1px 2px rgba(0,0,0,.06); transition: all .25s;
}
.report-entry:hover { background: #FFFFFF; color: #292524; border-color: #D8CFC0; box-shadow: 0 5px 14px rgba(0,0,0,.14); transform: scale(1.05); }
.report-entry:active { background: #F2F2F2; color: #292524; border-color: #D8CFC0; box-shadow: none; transform: scale(.97); }
html.dark .report-entry { background: #FFFFFF; color: #292524; border-color: #FFFFFF; box-shadow: 0 1px 2px rgba(0,0,0,.3); }
html.dark .report-entry:hover { background: #FFFFFF; color: #1C1917; border-color: #FFFFFF; box-shadow: 0 5px 14px rgba(0,0,0,.5); }
html.dark .report-entry:active { background: #EDEDED; color: #1C1917; border-color: #EDEDED; }
@media (prefers-reduced-motion: reduce) { .report-entry:hover, .report-entry:active { transform: none; } }
@media (max-width: 768px) { .report-entry { padding: 3px 10px; margin-left: 6px; } }
/* 正文/训练/题目点词：词典卡按释义多少自适应（比速记生词更宽，长释义更少折行） */
.popover.article-pop { max-width: 480px; }
/* 报错：题号选择面板 */
.report-q-list { display: grid; gap: 6px; max-height: 46vh; overflow-y: auto; margin: 10px 0 4px; }
.report-q-item {
  display: flex; align-items: baseline; gap: 8px; width: 100%; text-align: left;
  padding: 9px 12px; border-radius: 16px; border: 1px solid var(--c-border); background: #FFFCF8;
  font: inherit; font-size: .8em; color: var(--c-text); cursor: pointer; transition: all .15s;
}
.report-q-item:hover { border-color: #6B7F58; background: #F2EDE4; }
.report-q-item b { color: #5C4033; flex-shrink: 0; }
.report-q-item span { color: var(--c-text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
html.dark .report-q-item { background: #2A2623; border-color: #3F3A37; }
html.dark .report-q-item:hover { background: #2E2620; border-color: #7A5A2F; }
html.dark .report-q-item b { color: #D4A373; }
/* 管理中心：报错列表条目 */
.admin-rep-item { padding: 10px 12px; border: 1px solid var(--c-border); border-radius: var(--radius-sm); margin-bottom: 8px; cursor: pointer; background: var(--c-white); transition: all .15s; }
.admin-rep-item:hover { border-color: #6B7F58; background: #F2EDE4; }
.admin-rep-top { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.admin-rep-kind { font-size: .7em; font-weight: 700; color: #fff; background: #6B7F58; border-radius: 100px; padding: 1px 8px; flex-shrink: 0; }
/* 报错分类（2026-10-31 用户要求）：筛选条 + 分类小标（考研英语 / 四六级 / 高考） */
.admin-rep-filter { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 10px; }
.admin-rep-filter button { padding: 3px 12px; border-radius: 99px; border: 1px solid var(--c-border);
  background: var(--c-white); color: var(--c-text-secondary); font: inherit; font-size: .76em; cursor: pointer; }
.admin-rep-filter button:hover { border-color: #6B7F58; }
.admin-rep-filter button.on { background: #6B7F58; border-color: #6B7F58; color: #fff; font-weight: 700; }
.admin-rep-cat { font-size: .68em; font-weight: 700; border-radius: 99px; padding: 1px 7px; flex-shrink: 0;
  border: 1px dashed currentColor; }
.admin-rep-cat.c-kaoyan { color: #8A6A2F; }
.admin-rep-cat.c-cet { color: #4F6B36; }
.admin-rep-cat.c-gaokao { color: #B45309; }
html.dark .admin-rep-filter button { background: #2A2623; border-color: #3F3A37; color: #C9C2B8; }
html.dark .admin-rep-filter button.on { background: #6B7F58; border-color: #6B7F58; color: #fff; }
html.dark .admin-rep-cat.c-kaoyan { color: #E7CE96; }
html.dark .admin-rep-cat.c-cet { color: #A8C48A; }
html.dark .admin-rep-cat.c-gaokao { color: #E8A06A; }
.admin-rep-label { font-size: .82em; font-weight: 600; color: var(--c-text); }
.admin-rep-q { font-size: .72em; color: #5C4033; border: 1px solid rgba(90,110,69,.4); border-radius: 100px; padding: 0 7px; flex-shrink: 0; }
/* 用户所选答案（2026-09-22 用户要求：报错卡片要能看出「他当时选了什么」） */
.admin-rep-choice { font-size: .72em; color: #1D4ED8; background: rgba(37,99,235,.1); border-radius: 100px; padding: 0 7px; flex-shrink: 0; }
html.dark .admin-rep-choice { color: #93B4FF; background: rgba(96,165,250,.16); }
/* 从管理中心点报错跳过来后，给报错所指那道题闪一下（2026-09-22：用户反馈「点击无法跳转」——
   实际是跳到了整篇、看不出落在哪一题） */
.question-block.ar-report-flash { animation: arRepFlash 1.8s ease-out 1; border-radius: 16px; }
@keyframes arRepFlash {
  0%   { background: rgba(212,163,115,.30); box-shadow: 0 0 0 3px rgba(212,163,115,.35); }
  100% { background: transparent; box-shadow: none; }
}
.admin-rep-del { margin-left: auto; flex-shrink: 0; padding: 2px 8px; border: 0; border-radius: 100px; background: none;
  color: var(--c-danger); font: inherit; font-size: .72em; font-weight: 600; cursor: pointer; transition: background .15s; }
.admin-rep-del:hover { background: rgba(166,61,42,.1); }
.admin-rep-sub { font-size: .72em; color: var(--c-text-muted); margin-top: 4px; }
.admin-fb-empty { font-size: .8em; color: var(--c-text-muted); padding: 10px 2px; }
html.dark .admin-rep-item { background: #2A2623; border-color: #3F3A37; }
html.dark .admin-rep-item:hover { background: #2E2620; border-color: #7A5A2F; }
html.dark .admin-rep-q { color: #D4A373; border-color: rgba(244,181,100,.4); }
@media (min-width: 769px) and (max-width: 1024px) {
  #trainPage .train-page { padding: 78px 18px 60px; }
  html.force-tablet #trainPage .train-page { padding: 78px 18px 60px; }
  #trainPage .train-layout { column-gap: 16px; }
  #trainPage .train-rail { top: 84px; margin-top: 70px; }
  #trainPage .train-rail .vocab-panel { padding: 12px 12px 13px; }
  #trainPage .train-rail .vocab-panel h3 { gap: 4px; }
  #trainPage .train-rail .vocab-panel h3 > svg { width: 22px; height: 22px; padding: 4px; }
  #trainPage .train-rail .vocab-panel h3 .vt-title { font-size: .95em; letter-spacing: 0; }
  #trainPage .train-rail .vocab-panel h3 .count { min-width: 21px; height: 19px; padding: 0 5px; }
  #trainPage .train-rail .vocab-panel h3 .vocab-hl-bar { height: 20px; padding: 0 6px; font-size: .58em; gap: 3px; }
  #trainPage .train-rail .vocab-panel h3 .vocab-hl-bar svg { width: 9px; height: 9px; }
  #trainPage .train-rail .vocab-item { padding: 7px 22px 7px 2px; }
  #trainPage .train-rail .vocab-item .m { font-size: .76em; }
}
html.force-tablet #trainPage .train-page { padding-top: 78px; }
/* 导入小说视图（对齐导入阅读样式，2026-09-04）*/
#storyHub #storyImportView .imp-upload { cursor: pointer; border: 2px dashed rgba(90,110,69,.45); border-radius: 16px; padding: 36px 16px; text-align: center; color: #A8A29E; background: rgba(255,253,248,.6); transition: all .18s ease; outline: none; }
#storyHub #storyImportView .imp-upload:hover, #storyHub #storyImportView .imp-upload:focus-visible { border-color: var(--c-accent); background: #F5EFE4; color: #5C4033; }
#storyHub #storyImportView .imp-upload h3 { margin: 12px 0 6px; font-size: 1.05em; color: var(--c-text); }
#storyHub #storyImportView .imp-upload p { margin: 0; font-size: .8em; }
#storyHub #storyImportView .imp-upload svg { color: var(--c-accent-deep); }
html.dark #storyHub #storyImportView .imp-upload { background: rgba(38,33,29,.4); }
#storyHub #storyImportView .imp-format { margin-top: 6px; background: #FFFCF8; border: 1px solid #EFE9DC; border-radius: 14px; padding: 14px 16px; }
html.dark #storyHub #storyImportView .imp-format { background: #2E2924; border-color: #3F3A37; }
#storyHub #storyImportView .imp-format h4 { margin: 0 0 6px; font-size: .86em; color: var(--c-primary-dark); }
#storyHub #storyImportView .imp-format pre { margin: 0; font-size: .78em; line-height: 1.7; color: var(--c-text-secondary); background: #F7F3EA; border-radius: 16px; padding: 12px; overflow-x: auto; white-space: pre; }
html.dark #storyHub #storyImportView .imp-format pre { background: #221E1A; }
#storyHub #storyImportView .imp-dl-row { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 10px; }
#storyHub #storyImportView .imp-dl { display: inline-flex; align-items: center; gap: 6px; padding: 5px 12px; border-radius: 100px; border: 1px solid rgba(90,110,69,.35); background: #F2EDE4; color: #4A3229; font-size: .74em; font-weight: 600; text-decoration: none; transition: all var(--transition-fast); }
#storyHub #storyImportView .imp-dl:hover { background: #E9E0D4; border-color: var(--c-accent); box-shadow: 0 1px 5px rgba(90,110,69,.18); }
#storyHub #storyImportView .imp-dl svg { width: 13px; height: 13px; flex-shrink: 0; }
html.dark #storyHub #storyImportView .imp-dl { background: #2E2620; border-color: #7A5A2F; color: #D4A373; }
html.dark #storyHub #storyImportView .imp-dl:hover { background: #443018; border-color: var(--c-accent); }
#storyHub #storyImportView .si-grid-head { display: flex; align-items: baseline; justify-content: space-between; margin: 24px 0 10px; }
#storyHub #storyImportView .si-grid-head h3 { font-size: .95em; font-weight: 700; color: var(--c-text); }
#storyHub #storyImportView .si-grid-head span { font-size: .78em; color: var(--c-text-muted); }
/* 拖拽上传高亮（导入阅读 / 导入小说）(2026-09-04) */
.imp-scope .imp-upload.dragover,
#storyHub #storyImportView .imp-upload.dragover {
  border-color: var(--c-accent);
  background: #F5EFE4;
  color: #5C4033;
  box-shadow: 0 0 0 4px rgba(90,110,69,.12);
}
html.dark .imp-scope .imp-upload.dragover,
html.dark #storyHub #storyImportView .imp-upload.dragover {
  background: rgba(90,110,69,.14);
}
/* 暗夜：小说阅读单词高亮可读性 (2026-09-04) */
html.dark .story-read-area .word:hover { background: rgba(163,185,140,.22); }
html.dark .story-read-area .word.story-vocab { background: rgba(90,110,69,.30); border-bottom-color: #D4A373; }
html.dark .story-read-area .word.story-vocab:hover { background: rgba(163,185,140,.42); }

/* ── 暗夜：题目解析区（.q-analyze-result 背景原为硬编码 #F5EFE4 亮暖底，两模式不变，
      导致暗夜下浅字叠浅底：正文仅 2.48:1、重解析按钮 2.11:1，远低于 WCAG AA 4.5:1）── */
html.dark .q-analyze-result { background: #2A2623; color: #E7E5E4; border-left-color: #6B7F58; }
html.dark .q-analyze-result h4, html.dark .q-analyze-result h5 { color: #D4A373; }
html.dark .q-analyze-btn { background: #2E2620; border-color: #7A5A2F; color: #D4A373; }
html.dark .q-analyze-btn:hover { background: #443018; border-color: var(--c-accent); }
/* 暗夜：题库标准格式渲染（.qa-*） */
html.dark .qa-ans-badge { background: #2E2620; color: #E9E0D4; border-color: rgba(163,185,140,.5); }
html.dark .qa-ans-num { color: #A8A29E; }
html.dark .qa-opt { background: rgba(255,255,255,.045); }
html.dark .qa-key { border-color: #57534E; background: #332E2A; color: #D6CFC7; }
html.dark .qa-opt.correct { border-left-color: #6B7F58; background: rgba(163,185,140,.15); }
html.dark .qa-opt.correct .qa-key { border-color: #6B7F58; background: #6B7F58; color: #262019; }

/* ── 亮色：题目解析「色块感」减半 ──
   面板底色已并入上方 .q-analyze-result 基准（#FFFCF8）。
   选项底色 .055→.028 / 正确项 .10→.05：淡化块面，层次改由左侧琥珀竖条 + 字母徽章承担。
   注意：此处是亮色基准值，位于 html.dark 覆盖之后，暗夜由上方 html.dark 规则接管。── */
.qa-opt { background: rgba(120,113,108,.028); }
.qa-opt.correct { background: rgba(90,110,69,.05); }
/* ── 统一「立体白底分段按钮」外观（2026-09-16）─────────────────────────────
   参照物：阅读页标题行的 .seg（防误触 / 高频词·档位 / 查词，Uiverse elijahgummer btn-group 忠实版）。
   套用对象：① 精读训练顶部功能按钮 ② 原题训练顶部功能按钮 ③ 原题训练标题行「报错」。
   与参照物的唯一差别：这些按钮彼此是不同功能、数量多且会换行，所以**各自独立**、
   四个角统一 0.5em 圆角（不做连体分组，也不做 -1px 重叠）。
   放在样式表最后，用同特异性覆盖前面几轮的纯白胶囊版本。 */
#trainPage .train-type-switch,
#readingPage .topbar .btn-hot,
#readingPage .report-entry {
  position: relative; display: inline-flex; align-items: center; justify-content: center;
  font: inherit; background-color: #ffffff; border: 0; color: #292524;
  font-size: .92rem; font-weight: bold; line-height: 1.25;
  padding: 0.26em 0.85em; border-radius: 0.5em; gap: 4px;
  text-shadow: 0 0.0625em 0 #fff;
  box-shadow: inset 0 0.0625em 0 0 #f4f4f4, 0 0.0625em 0 0 #efefef, 0 0.125em 0 0 #ececec,
    0 0.25em 0 0 #e0e0e0, 0 0.3125em 0 0 #dedede, 0 0.375em 0 0 #dcdcdc, 0 0.425em 0 0 #cacaca,
    0 0.425em 0.5em 0 #cecece;
  transition: color 0.23s ease, background-color 0.23s ease, box-shadow 0.23s ease,
    letter-spacing 0.23s ease, translate 0.23s ease;
  cursor: pointer; margin: 0; white-space: nowrap; user-select: none; -webkit-user-select: none;
}
#trainPage .train-type-switch:hover,
#readingPage .topbar .btn-hot:hover,
#readingPage .report-entry:hover {
  background-color: #f7f7f7; color: #292524; border-color: transparent;
  transform: none; box-shadow: inset 0 0.0625em 0 0 #f4f4f4, 0 0.0625em 0 0 #efefef,
    0 0.125em 0 0 #ececec, 0 0.25em 0 0 #e0e0e0, 0 0.3125em 0 0 #dedede, 0 0.375em 0 0 #dcdcdc,
    0 0.425em 0 0 #cacaca, 0 0.425em 0.5em 0 #cecece;
}
#trainPage .train-type-switch:active,
#readingPage .topbar .btn-hot:active,
#readingPage .report-entry:active {
  translate: 0 0.225em; letter-spacing: 0.1em; color: #16a34a; transform: none;
  box-shadow: inset 0 0.03em 0 0 #f4f4f4, 0 0.03em 0 0 #efefef, 0 0.0625em 0 0 #ececec,
    0 0.125em 0 0 #e0e0e0, 0 0.125em 0 0 #dedede, 0 0.2em 0 0 #dcdcdc, 0 0.225em 0 0 #cacaca,
    0 0.225em 0.375em 0 #cecece;
}
#trainPage .train-type-switch:focus-visible,
#readingPage .topbar .btn-hot:focus-visible,
#readingPage .report-entry:focus-visible { outline: 2px solid #34d399; outline-offset: 2px; }
/* 开启 / 进行中状态沿用参照物的绿色文字（计时器在跑、题型已选、标注已开） */
#trainPage .train-type-switch.is-on,
#trainPage .train-type-switch.train-timer-btn.running,
#trainPage .train-type-switch.train-annotate-btn.is-on,
#trainPage .train-type-switch.train-pick-btn.is-on { color: #4F6B36; }
#trainPage .train-type-switch:disabled { opacity: .5; cursor: default; }
html.dark #trainPage .train-type-switch,
html.dark #readingPage .topbar .btn-hot,
html.dark #readingPage .report-entry {
  background-color: #3b3833; color: #EDE7DC; border-color: transparent;
  text-shadow: 0 0.0625em 0 rgba(0,0,0,.25);
  box-shadow: inset 0 0.0625em 0 0 rgba(255,255,255,.06), 0 0.0625em 0 0 rgba(0,0,0,.5),
    0 0.125em 0 0 rgba(0,0,0,.45), 0 0.25em 0 0 rgba(0,0,0,.4), 0 0.3125em 0 0 rgba(0,0,0,.36),
    0 0.375em 0 0 rgba(0,0,0,.32), 0 0.425em 0 0 rgba(0,0,0,.3), 0 0.425em 0.5em 0 rgba(0,0,0,.35);
}
html.dark #trainPage .train-type-switch:hover,
html.dark #readingPage .topbar .btn-hot:hover,
html.dark #readingPage .report-entry:hover { background-color: #45413b; color: #fff; }
html.dark #trainPage .train-type-switch:active,
html.dark #readingPage .topbar .btn-hot:active,
html.dark #readingPage .report-entry:active {
  translate: 0 0.225em; color: #86efac; letter-spacing: 0.1em;
  box-shadow: inset 0 0.03em 0 0 rgba(255,255,255,.06), 0 0.03em 0 0 rgba(0,0,0,.5),
    0 0.0625em 0 0 rgba(0,0,0,.45), 0 0.125em 0 0 rgba(0,0,0,.4), 0 0.125em 0 0 rgba(0,0,0,.36),
    0 0.2em 0 0 rgba(0,0,0,.32), 0 0.225em 0 0 rgba(0,0,0,.3), 0 0.225em 0.375em 0 rgba(0,0,0,.35);
}
html.dark #trainPage .train-type-switch.is-on,
html.dark #trainPage .train-type-switch.train-timer-btn.running,
html.dark #trainPage .train-type-switch.train-annotate-btn.is-on,
html.dark #trainPage .train-type-switch.train-pick-btn.is-on { color: #A8BC90; }
@media (prefers-reduced-motion: reduce) {
  #trainPage .train-type-switch, #readingPage .topbar .btn-hot, #readingPage .report-entry { transition: none; }
}
@media (max-width: 768px), html.force-phone {
  #trainPage .train-type-switch, #readingPage .report-entry { font-size: .82rem; padding: 0.22em 0.7em; }
}
html.force-tablet #trainPage .train-type-switch,
html.force-tablet #readingPage .report-entry { font-size: .86rem; padding: 0.24em 0.78em; }
/* ── 2026-09-18 修正：上面这套「白底立体按钮」皮肤只声明了 background-color，而旧的
   .topbar .btn-hot 用的是 background-image: none; background-color: linear-gradient(...)（亮色 #D4A373→#5C4033 /
   暗色 #4A3229→#4A3229），background-image 优先级高于 background-color →
   白底从未真正生效，橙底 + 深灰字 #57534E + text-shadow 白色下影造成「文字底部白色边缘」
   （实测真实绘制像素：亮色 216,149,66 / 暗色 140,64,15）。下面统一清掉渐变，白底才真正生效。 ── */
#readingPage .topbar .btn-hot, #readingPage .topbar .btn-hot:hover, #readingPage .topbar .btn-hot:active,
#trainPage .train-type-switch, #trainPage .train-type-switch:hover, #trainPage .train-type-switch:active,
#readingPage .report-entry, #readingPage .report-entry:hover, #readingPage .report-entry:active { background-image: none; }
html.dark #readingPage .topbar .btn-hot, html.dark #readingPage .topbar .btn-hot:hover, html.dark #readingPage .topbar .btn-hot:active,
html.dark #trainPage .train-type-switch, html.dark #trainPage .train-type-switch:hover, html.dark #trainPage .train-type-switch:active,
html.dark #readingPage .report-entry, html.dark #readingPage .report-entry:hover, html.dark #readingPage .report-entry:active { background-image: none; }
/* ── 阅读页顶栏那排（换一篇 / 上一篇 / 下一篇 / 标注 / 保存阅读 / 全文翻译）──
   沿革：2026-09-19 用户要求恢复暖黄渐变 → 2026-09-27 用户要求跟随主题色、并改成椭圆形，
   于是这里改成主题令牌渐变（亮 鼠尾草→深鼠尾草 / 暗 浅鼠尾草→中鼠尾草）+ border-radius: 100px。
   文字色用 var(--c-white)：亮色下是奶白、暗色下是 #292524 —— 深色字压浅色底，和站内
   「强调色填充 + --c-white 文字」的做法一致（见 .cloze-bar .cbtn.primary）。
   ⚠️ 仍要清掉 text-shadow：深色字 + 白色下影会再现「文字底部白色边缘」。
   精读训练那排按钮（#trainPage .train-type-switch）本就是纯白胶囊，不受本段影响。 ── */
#readingPage .topbar .btn-hot,
html.dark #readingPage .topbar .btn-hot {
  background-color: transparent;
  background-image: linear-gradient(135deg, var(--c-accent) 0%, var(--c-accent-hover) 100%);
  color: var(--c-white); text-shadow: none; border: 0; border-radius: 100px;   /* 椭圆形（2026-09-27 用户要求） */
  font-size: .82em; font-weight: 600; letter-spacing: .01em;
  padding: 0 18px; height: 34px; gap: 5px;
  box-shadow: 0 10px 20px -6px rgba(163,73,9,.5);
  translate: none; transform: none; opacity: 1;
  transition: all .3s ease-in-out;
}
#readingPage .topbar .btn-hot:hover,
html.dark #readingPage .topbar .btn-hot:hover {
  background-color: transparent;
  background-image: linear-gradient(135deg, var(--c-accent) 0%, var(--c-accent-hover) 100%);
  color: var(--c-white); text-shadow: none; opacity: 1;
  box-shadow: none; translate: none; transform: translateY(3px); letter-spacing: .01em;
}
#readingPage .topbar .btn-hot:active,
html.dark #readingPage .topbar .btn-hot:active {
  background-color: transparent;
  background-image: linear-gradient(135deg, var(--c-accent) 0%, var(--c-accent-hover) 100%);
  color: var(--c-white); text-shadow: none; opacity: .5; translate: none;
  letter-spacing: .01em; box-shadow: 0 10px 20px -6px rgba(163,73,9,.5);
}
/* 2026-09-27：阅读页顶栏三态在暗色下也不再压暖黄 —— 上面那三条已改成主题令牌，这里整段删除 */
/* ── 2026-09-19 ① 按钮文字加深：#57534E 太浅（用户要求"搞黑一些"），
   上面三处皮肤（阅读页标题行 .seg / 高频词菜单按钮 / 精读·原题训练按钮与报错）已统一改 #292524；
   暗色仍保持 #EDE7DC·#A8BC90 不变。
   ② 「报错」从标题文字流里挪到「防误触 / 高频词·档位 / 查词」那组左侧（见 renderReading），
   原来它跟在文章标题后面，桌面与那组隔 181px 空档、平板还被挤到第二行；
   挪位后字号需与那组对齐（平板下原来 .86rem vs 那组 .92rem）。 ── */
@media (min-width: 769px) {
  html.force-tablet #readingPage .reading-area .title .report-entry { font-size: .92rem; padding: 0.26em 0.85em; }
}

/* ══════════════════════════════════════════════════════════════════════════
   文章阅读 Article Reading（2026-09-21 新增；取代首页「小说记单词」入口）
   外壳完全沿用「速记生词」那一套：桌面/平板 = 左侧固定侧栏（复用 .ws-sidebar /
   .ws-side-item / .ws-content 全局类，保证两页视觉一模一样），手机 = 底部固定栏
   （复用 .phone-tab-bar）。形态由 `#articlePage.ar-nav-mobile` **一个类**驱动
   （JS: arSyncNav()，判定复用 wsIsMobileNav()）——与速记生词同样不用媒体查询，
   避免与 html.force-desktop / force-tablet 组合出「两边都没有导航」。
   ══════════════════════════════════════════════════════════════════════════ */
#articlePage { display: flow-root; }
/* 本页 --c-text-muted 在暖底上只有 2.43:1（与速记生词同一个问题），白天换成 #78716C */
html:not(.dark) #articlePage { --c-text-muted: #78716C; }
/* ══ 文章页：去顶栏 + 首页居中 + 分类/入口按钮改紧凑小横栏（2026-10-07 用户要求 B）══════
   ① 顶部那条「← 文章阅读」玻璃导航整条删掉（返回键 + 标题），所以页面顶部空隙从 96 收到 80
      （全站导航栏是 fixed、高 65px，80 = 65 + 15 的呼吸位），不留大片空白；
   ② 文章阅读首页（#arViewHome）内容**水平 + 垂直居中**：让内容列撑到视口底部，
      首页那一屏用 flex 居中（其它栏目仍是普通块流，不受影响）；
   ③ 文章库的分类按钮（#arCats）与导入文章的三个入口（#arImportCats）改成**紧凑小横栏**：
      `width: fit-content` 只包住按钮、圆角胶囊 + 浅底毛玻璃，靠内容区左上角；栏内按钮去掉自身的胶囊描边，
      选中态用琥珀色底，避免"胶囊套胶囊"。 */
#articlePage .ws-content { display: flex; flex-direction: column; min-height: calc(100vh - 80px); }
#arViewHome { flex: 1 1 auto; display: flex; align-items: center; justify-content: center; }
#articlePage .ar-home { min-height: 0; }
/* 紧凑小横栏（两处共用同一套：文章库分类 / 导入文章入口） */
#arCats, #arImportCats { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; width: fit-content;
  max-width: 100%; margin: 0 0 14px; padding: 4px 6px; border-radius: 9999px;
  background: rgba(255, 255, 255, .55); border: 1px solid var(--c-border);
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px); }
html.dark #arCats, html.dark #arImportCats { background: rgba(41, 37, 36, .55); }
#arCats .ar-cat, #arImportCats .ar-cat { padding: 6px 14px; border: 0; border-radius: 9999px;
  background: transparent; color: var(--c-text-secondary); font-size: .82em; font-weight: 600; }
#arCats .ar-cat:hover, #arImportCats .ar-cat:hover { background: rgba(233, 224, 212, .6); color: var(--c-accent-deep); }
#arCats .ar-cat.sel, #arImportCats .ar-cat.sel { background: var(--c-accent); border-color: var(--c-accent); color: #fff; }
html.dark #arCats .ar-cat.sel, html.dark #arImportCats .ar-cat.sel { color: #1C1917; }

/* 注：本页那条「[←] 文章阅读 · Tab 名」通栏玻璃条已于 2026-10-03 删除（返回统一走全站顶栏），
   它的 .topbar / .ws-topbar-title 覆盖规则（含手机媒体查询）一并清掉。 */
/* 手机形态：侧栏整个不渲染，改用底部栏（底部间距由 html.force-phone body padding-bottom 让开） */
/* 文章页的手机底部栏目栏（.ar-tab-bar）：**2026-10-07 起恢复启用** ——
   原网站的手机档就是「侧栏收掉 + 底部栏导航」，本轮按用户「对标原网站」的口径还原
   （显示规则见下面 .ar-nav-mobile 那段）。 */
/* 注：`.ws-sidebar`（老左侧固定竖栏组件）已随两页的竖栏并入顶部导航排（2026-10-04）彻底退役，
   原本 4 条规则（基础定位 / 两页手机隐藏 / force-desktop 覆盖）一并删除；子项 `.ws-side-item` 仍在使用。 */

   /* 上内边距归 0：与 #wordStudyPage 同口径（间距由 .ws-navrow 的下边距给） */
/* 文章库 / 小说 / 我的那几屏：容器 .vocab-page 自带 32px 上内边距，会把标题推低 ——
   标题那排下面已经有 36px 的呼吸位了，这里收掉（2026-10-04 用户要求「文章库的界面往上挪一下」） */
#articlePage .vocab-page { padding-top: 0; }

/* ── 文章页 / 生词本页**常驻全站顶栏**（2026-10-03 用户要求）────────────────────────
   这两页不是 .wl-page（那条外壳的让位规则挂在 .wl-page 上），而顶栏 `.wl-topbar` 是**永远 fixed**
   （z-50），所以让位得自己写：页面容器给 padding-top，文档流里的东西跟着一起下移。
   · 文章页：左侧固定侧栏 `.ws-sidebar`（position:fixed，从屏顶拉到屏底）会被顶栏压住 → 单独下移；
   · 生词本页：2026-10-03 第二轮起左侧竖栏已并入页内那条居中导航排（见下面 .ws-navrow 一段），
     页面里不再有固定侧栏，所以只需要容器让位。
   高度口径与顶栏自身一致：桌面/平板 64px + 1px 下边框 = 65；手机档（≤768 与强制手机）60 + 1 = 61。
   JS 进**文章页**时量实际高度写进 `--wl-nav-h`（wlSyncNavSpace），量不到就用这里的兜底值
   （生词本页走「题目训练同款」容器，用固定 96/88/84，见下面 .ws-navrow 一段）。
   ▸ 历史：这里原来是**文章页老横条**（`[←] 文章阅读 · Tab 名`）的让位块（`--ar-topbar-h`，
     2026-09-22 为「手机版标题被顶栏压住」而加）。老横条已于 2026-10-03 删除（返回键交给全站顶栏，
     栏目名各 Tab 内容里本来就有），那条机制连同 `arSyncTopbarSpace()` 一起去掉。
   ▸ 生词本页的老玻璃条（`[←] 速记生词 + 工具条`）也在同日删除，工具条并进 .ws-navrow。 */
/* 2026-10-07：顶栏那条「← 文章阅读」玻璃导航已删（用户 B1），顶部让位从 96 收到 **80**
   （全站导航固定 65px + 15px 呼吸位），免得删完留一截空白。与 #wordStudyPage 仍是同口径。 */
#articlePage { padding: 80px 0 24px; }
@media (max-width: 768px) { #articlePage { padding: 84px 0 16px; } }
html.force-tablet #articlePage { padding: 88px 0 24px; }
html.force-phone #articlePage { padding: 84px 0 16px; }
/* 生词本页改走「题目训练同款」容器（.th-main = 96/80，平板 88/64，手机 84/56）——
   96px 已经把固定的全站顶栏（65px）让开，所以本页不再叠加 --wl-nav-h。
   ⚠️ 下内边距 80 → 24（手机 56 → 16）：2026-10-03 第三轮用户要求「记单词 / 打字记词 一屏完全显示」，
   底部那 80px 是**看不见的空白**，留着它就意味着卡面少 80px（矮窗口下揭示面板会被压到几十像素高）。
   这一段只在页面最底部留白，收掉它不影响任何一屏的视觉对齐。 */
#wordStudyPage { padding: 96px 0 24px; }
@media (max-width: 768px) { #wordStudyPage { padding: 84px 0 16px; } }
html.force-tablet #wordStudyPage { padding: 88px 0 24px; }
html.force-phone #wordStudyPage { padding: 84px 0 16px; }
/* 内容区下内边距同理：48 → 16（列表类 tab 的底部留白随之略紧，属可接受） */

/* 文章页的左侧竖栏已在 2026-10-04 并入顶部导航排（.ws-navrail）：页面里不再有 position:fixed 的侧栏，
   所以原来那两条「固定侧栏让位」规则（#articlePage .ws-sidebar / force-desktop 覆盖）一并删除。 */

/* ── 「记单词 / 打字记词」一屏放下、不出现上下滚动（2026-10-03 用户要求）──────────────
   用户的抱怨是"背单词那屏和打字那屏要往上/收一点，一个界面内完全显示、不能上下滑动"。
   根因：本页顶部现在有「96px 上内边距 + 居中大标题 + 导航排 + 36px 下边距」，
   而这两屏的高度公式还是老的固定值（`.ws-stage-col: calc(100vh - 168px)`、
   `.ws-pick-wrap: min-height calc(100vh - 245px)`）—— 预算没跟上，于是页面被撑出滚动条。
   做法（与站内 `--ar-topbar-h` / `--lb-topbar-h` 同一口径：**不写死数字，实测**）：
     JS `wsFitViews()` 量出"这个面板上方还有多高 + 下方还留多少内边距"，把剩下的高度直接写成
     面板的 height（`--ws-fit-h` 只作记录/调试），面板内部再用 flex 分配：
       · 学习卡：`.ws-stage-col` 吃掉剩余（reveal 面板自己内部滚，契约不变），`.ws-bottom` 固定沉底；
       · 入口选框 / 打字待机：整块居中，卡片不够高也不会撑破；
       · 打字中：`.ws-type-stage`（flex:1）吃掉剩余，输入框与统计条沉底。
   注意：**只给这两个面板定高**，页面本身仍是普通文档流 —— 词库 / 生词本 / 词组本 / 学习计划
   那些长列表照旧正常滚动，不受影响。 */
/* ⚠️ 这两个面板**不能加 `overflow:hidden`**（2026-10-03 第五轮踩到）：面板高度是实测写死的，
   而 `.ws-bottom` 里的「不认识 / 认识」正好贴着面板底边 —— overflow:hidden 会把**按钮的阴影在底边切成一条直边**，
   看起来就像"底部有根横栏把阴影挡住了"（用户原话）。去掉后阴影照常画到面板外：
   `box-shadow` 不参与滚动尺寸计算，所以"一屏放下"（页面 scrollHeight）不受影响。 */
#wsTabStudy, #wsTabTyping { display: flex; flex-direction: column; }
#wsStudyView.ws-home { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
#wsStudyView.ws-home .ws-stage-col { flex: 1 1 auto; min-height: 0; height: auto; overflow: visible; }
/* ⚠️ 这里**必须 overflow: visible**（2026-10-03 第五轮用户反馈「按钮的阴影延伸不下去，像被横栏挡住」）：
   标注为 `.ws-bottom` 的那一行其实**嵌在 `.ws-stage-col` 里面**（见 #wsStudyView 的层级），
   而基础规则 `.ws-stage-col{overflow:hidden}` 会把贴着它底边的「不认识 / 认识」按钮阴影**切成一条直边**。
   卡面自己的滚动契约不受影响 —— `.ws-card` 自己有 `overflow:hidden`、揭示面板 `.ws-reveal` 自己 `overflow:auto`；
   手机两轨本来就写着 `overflow: visible`，这里只是让桌面跟它们一致。
   `box-shadow` 不参与滚动尺寸计算，所以「一屏放下」不受影响（实测页面溢出仍 0）。 */
#wsStudyView.ws-home .ws-bottom { flex: 0 0 auto; min-height: 0; margin-top: 0; }
#wsStudyView.ws-home .ws-stage { flex: 1 1 auto; min-height: 0; }
/* ⚠️ 2026-10-09：这两条把基础规则的 `min-height: calc(100vh - 245px)` 归零过
   （当初是为了"整块居中，卡片不够高也不撑破"）—— 结果 #wsPickView 只剩内容高（实测 354.8px），
   `justify-content:center` 没有剩余空间可居中，**新学/复习两张大卡在桌面/平板就贴到页面下半部**
   （实测偏 +209 / +385px；手机档结构不同、本来就是居中的）。
   真正的修法在下面「入口屏撑满一屏」那一段：光给这一层 min-height 没用（外层高度仍是内容高）。 */
#wsPickView.ws-pick-wrap { flex: 1 1 auto; padding: 8px 0 16px; }
#wsTypingIdle.ws-pick-wrap { flex: 1 1 auto; padding: 4px 0 16px; }
/* 入口屏（新学/复习 两张卡）撑满一屏：外层 #wsTabStudy 占「视口 − 顶栏/工具条」，
   里面 #wsPickView 用 flex:1 吃掉全部，再用 justify-content:center 把两张大卡放在正中。 */
#wsTabStudy { display: flex; flex-direction: column; min-height: calc(100vh - 180px); min-height: calc(100dvh - 180px); }
#wsTabStudy > .ws-pick-wrap { flex: 1 1 auto; }
@media (min-width: 769px) and (max-width: 1180px) {
  #wsTabStudy { min-height: calc(100dvh - 154px); }   /* 平板档页面内边距更高（实测 66 vs 68 但工具条更靠下） */
}
html.force-phone #wsTabStudy { min-height: calc(100dvh - 100px); }
#wsTypingPlay { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
#wsTypingDone.ws-type-center { flex: 1 1 auto; min-height: 0; }
/* ⚠️ 手机两轨里那几条 `!important` 的固定高度（3309 / 2982）必须压掉，否则手机上仍按老预算撑高 */
@media (max-width: 768px) {
  #wsStudyView.ws-home .ws-stage-col { min-height: 0 !important; height: auto !important; }
  #wsStudyView.ws-home .ws-stage-col > .ws-stage { flex: 1 1 auto !important; }
}
html.force-phone #wsStudyView.ws-home .ws-stage-col { min-height: 0 !important; height: auto !important; }
html.force-phone #wsStudyView.ws-home .ws-stage-col > .ws-stage { flex: 1 1 auto !important; }
html.force-phone #wsTypingPlay, html.force-phone #wsTypingDone { min-height: 0 !important; }

/* ══ 生词本：紧凑控件小横栏 + 正方形词表钮（2026-10-07 用户要求）════════════════════
   ① 原来这里是通栏玻璃条（`#wordStudyPage .topbar`，左「← 速记生词」+ 右控件组）——
      按用户口径整条删掉（返回键、标题一起删），只把控件组留下；
   ② 控件组做成**紧凑小横栏**：`width: fit-content` 只包住按钮，右对齐在内容列右上角，
      圆角胶囊 + 浅底毛玻璃（与站内其它小横栏同风格）；
   ③ 词表收起钮原来是 `flex:1 1 auto` 撑成一条**长竖条** → 改成 38×38 的**正方形**按钮
      （功能不变，仍走 wsToggleWordList）；收起态面板宽度收到 50px 刚好包住方钮。 */
.ws-tools-bar { display: flex; align-items: center; gap: 6px; width: fit-content; max-width: calc(100% - 32px);
  margin: 16px 24px 12px auto; padding: 4px 6px; border-radius: 9999px; position: relative; z-index: 20;
  background: rgba(255, 255, 255, .55); border: 1px solid var(--c-border);
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px); }
html.dark .ws-tools-bar { background: rgba(41, 37, 36, .55); }
.ws-tools-bar .ws-toolbar { margin-left: 0; }
#wsToolsBar.hidden { display: none !important; }
/* 手机档：控件组收进「⋯」面板 —— 面板锚在这条小横栏上（原来锚在通栏玻璃条上） */
#wordStudyPage.ws-nav-mobile .ws-tools-bar { margin: 12px 14px 10px auto; }
/* ⚠️ 这两条要**多带一个 .ws-tools-bar**：文件末尾那块「对标原网站外壳」里有一条同权重的
   `#wordStudyPage.ws-nav-mobile .ws-toolbar{left:8px;right:8px}`，同权重时后写者赢 ——
   不多带一层的话面板会按"贴着通栏玻璃条"算宽度，在手机上直接冲出屏幕（实测 right=575 > 390）。 */
#wordStudyPage.ws-nav-mobile .ws-tools-bar .ws-toolbar {
  right: 0; left: auto; min-width: 240px; max-width: calc(100vw - 28px);
  max-height: 60vh; overflow-y: auto; }
/* 词表抽屉的收起/展开钮：正方形 */
.ws-wl-toggle { flex: 0 0 auto; width: 38px; height: 38px; min-height: 38px; padding: 0; margin: 6px auto;
  border: 1px solid var(--c-border); border-radius: 12px; background: var(--c-bg); color: var(--c-text-secondary); }
.ws-wl-toggle:hover { background: var(--c-accent-light); border-color: var(--c-accent); color: var(--c-accent-deep); }
.ws-wl-toggle:active { transform: scale(.94); }
.ws-wl-toggle svg { width: 18px; height: 18px; }
.ws-wl-panel { width: 50px; }
.ws-wl-panel.open .ws-wl-toggle { margin: 8px auto; }

/* ── 首页：状态判断式跳转，只有两个按钮 ──
   两枚按钮直接复用速记生词的「白底柔和上浮」皮肤（.ws-act + .ws-act-yes/no），
   连 hover 上浮 7px + 绿色辉光、active 回落都一并继承（用户要求动效与速记生词一致）。 */
#articlePage .ar-home { display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: calc(100vh - 220px); text-align: center; }
#articlePage .ar-home-mark { width: 54px; height: 54px; border-radius: 16px; display: flex; align-items: center; justify-content: center; background: #EFE8DC; color: var(--c-accent); margin-bottom: 14px; }
html.dark #articlePage .ar-home-mark { background: #3A3023; color: #D4A373; }
#articlePage .ar-home h2 { font-family: 'Noto Serif SC', serif; font-size: 1.5em; font-weight: 700; color: #5C4033; margin: 0 0 8px; }
html.dark #articlePage .ar-home h2 { color: var(--c-text); }
#articlePage .ar-home-now { font-size: .84em; color: var(--c-text-secondary); margin: 0 0 26px; min-height: 1.4em; }
#articlePage .ar-home-acts { display: flex; flex-direction: row; gap: 18px; width: 100%; max-width: 480px; }
/* 未选过文章 →「开始阅读」置灰不可点（规格 1.3）。必须压过 .ws-act-yes:hover */
#articlePage .ar-start[disabled], #articlePage .ar-start[disabled]:hover {
  background-color: #F5F5F4; color: #A8A29E; box-shadow: none; transform: none; cursor: not-allowed;
}
html.dark #articlePage .ar-start[disabled], html.dark #articlePage .ar-start[disabled]:hover {
  background-color: #322C28; color: #78716C;
}
#articlePage .ar-home-tip { margin: 16px 0 0; font-size: .74em; color: var(--c-text-muted); }

/* ── 文章库：顶部横向分类标签 + 卡片列表 ── */
#articlePage .ar-cats,
/* ── 文章库：顶部横向分类标签 + 卡片列表 ── */
#trainHubPage .ar-cats,
#impQuizPage .ar-cats{ display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 18px; }
#articlePage .ar-cat,
#trainHubPage .ar-cat,
#impQuizPage .ar-cat{ position: relative; padding: 7px 16px; border-radius: 999px; border: 1px solid var(--c-border); background: var(--c-bg-card); color: var(--c-text-secondary); font: inherit; font-size: .82em; font-weight: 600; white-space: nowrap; cursor: pointer;
  transition: color var(--t-state) var(--ease-out-quart), background-color var(--t-state) var(--ease-out-quart),
              border-color var(--t-state) var(--ease-out-quart), box-shadow var(--t-state) var(--ease-out-quart),
              transform var(--t-press) var(--ease-out-quart); }
#articlePage .ar-cat:hover,
#trainHubPage .ar-cat:hover,
#impQuizPage .ar-cat:hover{ border-color: var(--c-accent); color: var(--c-accent-deep); background: var(--c-bg); }
#articlePage .ar-cat.sel,
#trainHubPage .ar-cat.sel,
#impQuizPage .ar-cat.sel{ background: var(--c-accent); border-color: var(--c-accent); color: #fff; }
html.dark #articlePage .ar-cat.sel,
html.dark #trainHubPage .ar-cat.sel,
html.dark #impQuizPage .ar-cat.sel{ color: #1C1917; }
.pg-bar{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:10px;margin:28px 0 8px}
.pg-bar.hidden{display:none}
.pg-btn{padding:7px 16px;border-radius:999px;border:1px solid var(--c-border);background:var(--c-bg-card);color:var(--c-text-secondary);font:inherit;font-size:.82em;font-weight:600;cursor:pointer}
.pg-btn:hover:not(:disabled){border-color:var(--c-accent);color:var(--c-accent-deep)}
.pg-btn:disabled{opacity:.4;cursor:default}
.pg-info{font-size:.85em;color:var(--c-text-secondary);min-width:6.5em;text-align:center}
.pg-jump{width:4.2em;padding:6px 8px;border:1px solid var(--c-border);border-radius:8px;background:var(--c-bg-card);color:inherit;font:inherit;font-size:.85em;text-align:center}
#articlePage .ar-cat:active,
#trainHubPage .ar-cat:active,
#impQuizPage .ar-cat:active{ transform: scale(.97); }
/* ── 小标题（按钮行）切换的过渡（2026-09-21，用户反馈「切换太突兀」）──
   两件事：
   ① 高亮不再靠重建 DOM：按钮行只在分类列表变化时构建一次，之后**只切 .sel**，
      让 `.ar-cat` 自己那条 background-color/color transition（--t-state 200ms）真正跑起来 ——
      原来每次切换都 innerHTML 重建，等于把 transition 抹掉了，高亮是"瞬间跳"的。
   ② 内容区换内容时淡入 + 轻微上浮（.ar-swap-in），主栏目整体切换更轻（.ar-view-in）。
   同一元素连着切也要能重放：JS 里先摘类、强制回流、再加类（见 arSwapIn）。 */
@keyframes arSwapIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
#articlePage .ar-swap-in { animation: arSwapIn .24s var(--ease-out-quart) both; }
@keyframes arViewIn { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
#articlePage .ar-view-in { animation: arViewIn .18s var(--ease-out-quart) both; }
@media (prefers-reduced-motion: reduce) {
  #articlePage .ar-swap-in, #articlePage .ar-view-in { animation: none; }
}
/* 卡片复用全站 .lib-grid / .lib-card（与「我的阅读」同一套，规格要求卡片样式一致）
   2026-09-22 用户要求：卡片上**只留中文题头 + 标签** → 原来的 `.ar-sum`（摘要）与
   `.ar-meta-chip.src`（来源署名）两条样式随之删除；来源署名改只出现在阅读页正文上方那一行。 */
#articlePage .ar-meta-chip,
#trainHubPage .ar-meta-chip,
#minePage .ar-meta-chip { display: inline-block; padding: 3px 10px; border-radius: 100px; font-size: .72em; font-weight: 600; }
#articlePage .ar-meta-chip.cat,
#trainHubPage .ar-meta-chip.cat,
#minePage .ar-meta-chip.cat { background: var(--c-accent-light); color: var(--c-accent-deep); }
html.dark #articlePage .ar-meta-chip.cat,
html.dark #trainHubPage .ar-meta-chip.cat,
html.dark #minePage .ar-meta-chip.cat { background: #443018; color: #E9E0D4; }
#articlePage .ar-meta-chip.read,
#trainHubPage .ar-meta-chip.read,
#minePage .ar-meta-chip.read { background: #ECFDF5; color: #047857; }
html.dark #articlePage .ar-meta-chip.read,
html.dark #trainHubPage .ar-meta-chip.read,
html.dark #minePage .ar-meta-chip.read { background: #14321F; color: #A8BC90; }
/* 词数片（2026-09-22 追加）：中性描边，和分类/已读片同一排 */
#articlePage .ar-meta-chip.words,
/* 词数片（2026-09-22 追加）：中性描边，和分类/已读片同一排 */
#trainHubPage .ar-meta-chip.words,
/* 词数片（2026-09-22 追加）：中性描边，和分类/已读片同一排 */
#minePage .ar-meta-chip.words { background: var(--c-bg); color: var(--c-text-secondary); border: 1px solid var(--c-border); font-variant-numeric: tabular-nums; }
html.dark #articlePage .ar-meta-chip.words { background: #322C28; color: #D6D3D1; border-color: #44403C; }
/* 阅读页正文上方的出处行：2026-09-22 用户要求去掉，样式一并删除（数据里的 source 仍保留） */
/* 卡片右上角：收藏星标（「我的 → 收藏文章」里点它取消收藏） */
#articlePage .ar-fav { position: absolute; top: 8px; right: 10px; background: none; border: none; padding: 4px 6px; border-radius: 6px; color: var(--c-border); cursor: pointer; line-height: 1; opacity: 0; transition: all .18s ease; }
#articlePage .lib-card:hover .ar-fav, #articlePage .ar-fav.on { opacity: 1; }
#articlePage .ar-fav svg { width: 17px; height: 17px; }
#articlePage .ar-fav.on { color: var(--c-accent); }
#articlePage .ar-fav:hover { background: #F5EFE4; color: var(--c-accent-deep); }
html.dark #articlePage .ar-fav:hover { background: #2E2620; }
/* 「我的 → 收藏文章」卡片上的**删除**钮（2026-10-04 用户要求）：原来它与收藏星并存、被挤到 right:40px
   且 `opacity:0`（不 hover 看不见）；用户要求「去掉五角星、只留删除钮，且和小说里的一样」→
   现在这一颗**不再特殊定位**（星标从收藏文章里撤了），回车到右上角，和上面那条 `.ar-cards .lib-del` 完全同款。
   （`.ar-del-fav` 这个类保留在按钮上只作语义标记，没有任何样式依赖它。） */
/* 卡片底部：「开始阅读」小字（hover 出现，与 .lib-go 同一处） */
#articlePage .ar-go { position: absolute; right: 14px; bottom: 10px; font-size: .74em; font-weight: 600; color: var(--c-accent); opacity: 0; transform: translateX(-6px); transition: all .2s ease; }
#articlePage .lib-card:hover .ar-go { opacity: 1; transform: translateX(0); }

/* ══════════════════════════════════════════════════════════════════════════
   文章卡片 · 2026-09-23 第 4 版（用 impeccable 的 **product register** 重做，用户已同意结构可动）
   结构：.arc-cover（类别色封面，内含中文题头 + 英文原标题；收藏/删除按钮压在右上角）
        ＋ .arc-info（主题标签〔只在我的〕/ 词数）
        ＋ .arc-footer（左：1/N 编号 + 已读标记；右：圆形按钮里的**书**图标）
   历史：第 3 版按 jztheme 设计稿把题头放进「会悬浮的橙色块」(.arc-img，hover 上浮 -10%)；
        本版按规范去掉了嵌套卡片与封面位移，详见下方逐条依据。
   只作用于 [文章库 / 我的 / 我导入的] 三个网格（.ar-cards），生词本等其它页仍用老卡片皮肤。
   ══════════════════════════════════════════════════════════════════════════
   文章卡片 · 2026-09-23 第 4 版（用 impeccable 的 **product register** 重做，用户已同意结构可动）
   改动依据（每条都对应规范里的一条）：
   ① **去掉卡片套卡片**：旧版是「外层灰卡壳（#f5f5f5 + 14px 圆角 + 阴影）里再套一块橙色圆角块」，
      而「nested cards are always wrong」是绝对禁令 → 现在橙色封面就是卡片本身的一段，
      整个卡片**只有一个圆角、只用一层高度（阴影）**，不再同时叠 border + 双阴影（ghost card 禁令）。
   ② **封面从纯装饰变成有信息的封面**：旧版 48 张卡的封面是同一块橙色渐变，等于占位图。
      现在按**类别**给色（7 大类各一色，见下），色是语义而非装饰。
   ③ **题头仍是主角，英文原标题降为第二行小字**（本地库每篇都有 title_en —— 对英语学习者是真实有效信息）。
   ④ 去掉那行看不见的 `text-shadow`（浅底上的白高光，实测无意义）；层级改用留白 + 字阶表达。
   ⑤ 补全交互态：`:focus-visible` 焦点环 + `:active` 按压；悬停位移交给**卡片容器**，
      **不再动封面本身**（规范：不要把图像/封面块当作 hover 位移的目标）。
   ⑥ 底栏「书」按钮改成真正的圆钮热区（原来 padding .3em，手机上难点中）。
   只作用于 [文章库 / 我的 / 我导入的] 三个网格（.ar-cards），生词本等其它页仍用老卡片皮肤。
   ══════════════════════════════════════════════════════════════════════════ */
/* 卡片墙用 **flex 铺满**而不是 grid：grid 的轨道数是按容器算的，遇上篇数少的分类
   （政治 4 篇、国际 1 篇）最后一行右边会空一大块 —— 2026-09-23 用户指出「这样右边的空就太大了」。
   flex 让同一行的卡片等分增长，**每一行都铺满**；只有行内卡片被 max-width 卡住时才用居中收尾，
   两侧留白对称（不会出现只在右边空）。 */
#articlePage .ar-cards , #trainHubPage .ar-cards,
/* ══════════════════════════════════════════════════════════════════════════
   文章卡片 · 2026-09-23 第 4 版（用 impeccable 的 **product register** 重做，用户已同意结构可动）
   结构：.arc-cover（类别色封面，内含中文题头 + 英文原标题；收藏/删除按钮压在右上角）
        ＋ .arc-info（主题标签〔只在我的〕/ 词数）
        ＋ .arc-footer（左：1/N 编号 + 已读标记；右：圆形按钮里的**书**图标）
   历史：第 3 版按 jztheme 设计稿把题头放进「会悬浮的橙色块」(.arc-img，hover 上浮 -10%)；
        本版按规范去掉了嵌套卡片与封面位移，详见下方逐条依据。
   只作用于 [文章库 / 我的 / 我导入的] 三个网格（.ar-cards），生词本等其它页仍用老卡片皮肤。
   ══════════════════════════════════════════════════════════════════════════
   文章卡片 · 2026-09-23 第 4 版（用 impeccable 的 **product register** 重做，用户已同意结构可动）
   改动依据（每条都对应规范里的一条）：
   ① **去掉卡片套卡片**：旧版是「外层灰卡壳（#f5f5f5 + 14px 圆角 + 阴影）里再套一块橙色圆角块」，
      而「nested cards are always wrong」是绝对禁令 → 现在橙色封面就是卡片本身的一段，
      整个卡片**只有一个圆角、只用一层高度（阴影）**，不再同时叠 border + 双阴影（ghost card 禁令）。
   ② **封面从纯装饰变成有信息的封面**：旧版 48 张卡的封面是同一块橙色渐变，等于占位图。
      现在按**类别**给色（7 大类各一色，见下），色是语义而非装饰。
   ③ **题头仍是主角，英文原标题降为第二行小字**（本地库每篇都有 title_en —— 对英语学习者是真实有效信息）。
   ④ 去掉那行看不见的 `text-shadow`（浅底上的白高光，实测无意义）；层级改用留白 + 字阶表达。
   ⑤ 补全交互态：`:focus-visible` 焦点环 + `:active` 按压；悬停位移交给**卡片容器**，
      **不再动封面本身**（规范：不要把图像/封面块当作 hover 位移的目标）。
   ⑥ 底栏「书」按钮改成真正的圆钮热区（原来 padding .3em，手机上难点中）。
   只作用于 [文章库 / 我的 / 我导入的] 三个网格（.ar-cards），生词本等其它页仍用老卡片皮肤。
   ══════════════════════════════════════════════════════════════════════════ */
/* 卡片墙用 **flex 铺满**而不是 grid：grid 的轨道数是按容器算的，遇上篇数少的分类
   （政治 4 篇、国际 1 篇）最后一行右边会空一大块 —— 2026-09-23 用户指出「这样右边的空就太大了」。
   flex 让同一行的卡片等分增长，**每一行都铺满**；只有行内卡片被 max-width 卡住时才用居中收尾，
   两侧留白对称（不会出现只在右边空）。 */
#minePage .ar-cards,
#donePage .ar-cards,#trainDonePage .ar-cards,#impQuizPage .ar-cards{ display: flex; flex-wrap: wrap; align-content: flex-start; justify-content: center; gap: 16px; }
#articlePage .ar-cards .lib-card , #trainHubPage .ar-cards .lib-card,
#minePage .ar-cards .lib-card,
#donePage .ar-cards .lib-card,#trainDonePage .ar-cards .lib-card,#impQuizPage .ar-cards .lib-card{ flex: 1 1 176px; min-width: 150px; max-width: 400px; }
/* ── 类别色：7 大类各一色，全部落在暖色区间内（与站内琥珀主色同族），低饱和。
      封面用「有存在感的浅纸底」，标题用「很深的墨水」；亮暗各一套变量，卡片规则只消费变量。
      ⚠️ 实测过对比度（脚本算的，不是目测）：亮色下封面 vs 页面 ≥1.14:1（第一版取 #FCEFF0 只有 1.08:1、
      几乎看不出是一块，故加深一档）、题头 ≥11.6:1、英文行 ≥4.95:1；
      暗色下封面 vs 页面 ≥1.21:1、题头 ≥11.5:1、英文行 ≥6.6:1。改色时请按同样口径复算。 ── */
#articlePage .ar-cards , #trainHubPage .ar-cards,
/* ── 类别色：7 大类各一色，全部落在暖色区间内（与站内琥珀主色同族），低饱和。
      封面用「有存在感的浅纸底」，标题用「很深的墨水」；亮暗各一套变量，卡片规则只消费变量。
      ⚠️ 实测过对比度（脚本算的，不是目测）：亮色下封面 vs 页面 ≥1.14:1（第一版取 #FCEFF0 只有 1.08:1、
      几乎看不出是一块，故加深一档）、题头 ≥11.6:1、英文行 ≥4.95:1；
      暗色下封面 vs 页面 ≥1.21:1、题头 ≥11.5:1、英文行 ≥6.6:1。改色时请按同样口径复算。 ── */
#minePage .ar-cards,
#donePage .ar-cards,#trainDonePage .ar-cards,#impQuizPage .ar-cards{
  --arcBg: #F5EBE1; --arcInk: #231C15; --arcInk2: #6A5748; --arcRule: rgba(43,22,8,.12);
}
html.dark #articlePage .ar-cards , html.dark #trainHubPage .ar-cards,
html.dark #minePage .ar-cards,
html.dark #donePage .ar-cards,html.dark #trainDonePage .ar-cards,html.dark #impQuizPage .ar-cards{
  --arcBg: #322820; --arcInk: #E9E0D4; --arcInk2: #B9A899; --arcRule: rgba(255,255,255,.12);
}
/* ── 卡片本体：一个圆角、一层高度（只用阴影，不用边框）、纵向三段 ── */
#articlePage .ar-cards .lib-card , #trainHubPage .ar-cards .lib-card,
/* ── 卡片本体：一个圆角、一层高度（只用阴影，不用边框）、纵向三段 ── */
#minePage .ar-cards .lib-card,
#donePage .ar-cards .lib-card,#trainDonePage .ar-cards .lib-card,#impQuizPage .ar-cards .lib-card{
  display: flex; flex-direction: column; min-height: 232px; padding: 0; overflow: hidden;
  border: none; border-radius: 14px;                            /* 规范给的卡片圆角区间 12–16px */
  box-shadow: 0 1px 2px rgba(41,37,36,.06), 0 4px 14px rgba(41,37,36,.07);
  transition: transform 220ms var(--ease-out-quart), box-shadow 220ms var(--ease-out-quart);
  outline: none;
}
html.dark #articlePage .ar-cards .lib-card , html.dark #trainHubPage .ar-cards .lib-card,
html.dark #minePage .ar-cards .lib-card,
html.dark #donePage .ar-cards .lib-card,html.dark #trainDonePage .ar-cards .lib-card,html.dark #impQuizPage .ar-cards .lib-card{ box-shadow: 0 1px 2px rgba(0,0,0,.5), 0 4px 16px rgba(0,0,0,.42); }
/* 悬停：抬的是**卡片**（不是封面）；按压回沉一档 —— 反馈层级清楚，且不动图像块 */
#articlePage .ar-cards .lib-card:hover , #trainHubPage .ar-cards .lib-card:hover,
/* 悬停：抬的是**卡片**（不是封面）；按压回沉一档 —— 反馈层级清楚，且不动图像块 */
#minePage .ar-cards .lib-card:hover,
#donePage .ar-cards .lib-card:hover,#trainDonePage .ar-cards .lib-card:hover,#impQuizPage .ar-cards .lib-card:hover{ transform: translateY(-2px); box-shadow: 0 2px 4px rgba(41,37,36,.07), 0 12px 28px rgba(41,37,36,.12); }
#articlePage .ar-cards .lib-card:active , #trainHubPage .ar-cards .lib-card:active,
#minePage .ar-cards .lib-card:active,
#donePage .ar-cards .lib-card:active,#trainDonePage .ar-cards .lib-card:active,#impQuizPage .ar-cards .lib-card:active{ transform: translateY(0); box-shadow: 0 1px 2px rgba(41,37,36,.08), 0 4px 12px rgba(41,37,36,.08); }
/* 键盘焦点环：改用 **outline** 而不是 box-shadow。
   ⚠️ 踩坑记录：最初用 box-shadow 写焦点环（`0 0 0 2px …, 0 0 0 4px …`），
   规则确实进了 CSSOM（能 dump 出来）、`:focus-visible` 也匹配为 true、真实键盘 Tab 聚焦也确认焦点在卡片上，
   但 getComputedStyle 里始终只有卡片的基础阴影，我的三层被整条丢弃 —— 与同样声明 box-shadow 的
   `:hover`/`:active` 同权重抢占，且规则位置在前。改用 outline 后与高度层（box-shadow）**互不干扰**。 */
#articlePage .ar-cards .lib-card:focus-visible , #trainHubPage .ar-cards .lib-card:focus-visible,
0 0 0 4px …`），
   规则确实进了 CSSOM（能 dump 出来）、`:focus-visible` 也匹配为 true、真实键盘 Tab 聚焦也确认焦点在卡片上，
   但 getComputedStyle 里始终只有卡片的基础阴影，我的三层被整条丢弃 —— 与同样声明 box-shadow 的
   `:hover`/`:active` 同权重抢占，且规则位置在前。改用 outline 后与高度层（box-shadow）**互不干扰**。 */
#minePage .ar-cards .lib-card:focus-visible,
#donePage .ar-cards .lib-card:focus-visible,#trainDonePage .ar-cards .lib-card:focus-visible,#impQuizPage .ar-cards .lib-card:focus-visible{ outline: 2px solid #5A6E45; outline-offset: 3px; }
html.dark #articlePage .ar-cards .lib-card:focus-visible , html.dark #trainHubPage .ar-cards .lib-card:focus-visible,
html.dark #minePage .ar-cards .lib-card:focus-visible,
html.dark #donePage .ar-cards .lib-card:focus-visible,html.dark #trainDonePage .ar-cards .lib-card:focus-visible,html.dark #impQuizPage .ar-cards .lib-card:focus-visible{ outline-color: #6B7F58; }
/* 已读：封面压一点存在感（左侧 3px 竖线是规范禁令，故用整块色调 + 底栏标记表达） */
#articlePage .ar-cards .lib-card.is-read .arc-cover , #trainHubPage .ar-cards .lib-card.is-read .arc-cover,
/* 已读：封面压一点存在感（左侧 3px 竖线是规范禁令，故用整块色调 + 底栏标记表达） */
#minePage .ar-cards .lib-card.is-read .arc-cover,
#donePage .ar-cards .lib-card.is-read .arc-cover,#trainDonePage .ar-cards .lib-card.is-read .arc-cover,#impQuizPage .ar-cards .lib-card.is-read .arc-cover{ filter: saturate(.72) brightness(.985); }
/* ── 封面段：类别色纸底 + 中文题头（主角）+ 英文原标题（次行） ── */
#articlePage .ar-cards .arc-cover , #trainHubPage .ar-cards .arc-cover,
/* ── 封面段：类别色纸底 + 中文题头（主角）+ 英文原标题（次行） ── */
#minePage .ar-cards .arc-cover,
#donePage .ar-cards .arc-cover,#trainDonePage .ar-cards .arc-cover,#impQuizPage .ar-cards .arc-cover{
  position: relative; flex: none; min-height: 118px; padding: 1em .9em .95em;
  background: var(--arcBg); color: var(--arcInk);
  display: flex; flex-direction: column; justify-content: center;
  border-bottom: 1px solid var(--arcRule);
}
#articlePage .ar-cards .arc-title , #trainHubPage .ar-cards .arc-title,
#minePage .ar-cards .arc-title,
#donePage .ar-cards .arc-title,#trainDonePage .ar-cards .arc-title,#impQuizPage .ar-cards .arc-title{
  font-family: 'Noto Serif SC', serif; font-size: 1em; font-weight: 800; line-height: 1.42;
  color: inherit; margin: 0; letter-spacing: .01em; text-align: left;
  overflow: hidden; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
}
#articlePage .ar-cards .arc-title-en , #trainHubPage .ar-cards .arc-title-en,
#minePage .ar-cards .arc-title-en,
#donePage .ar-cards .arc-title-en,#trainDonePage .ar-cards .arc-title-en,#impQuizPage .ar-cards .arc-title-en{
  margin-top: .45em; font-size: .74em; line-height: 1.35; font-weight: 500; color: var(--arcInk2);
  overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}
/* ── 信息行：标签 / 词数 ── */
#articlePage .ar-cards .arc-info , #trainHubPage .ar-cards .arc-info,
/* ── 信息行：标签 / 词数 ── */
#minePage .ar-cards .arc-info,
#donePage .ar-cards .arc-info,#trainDonePage .ar-cards .arc-info,#impQuizPage .ar-cards .arc-info{ padding: .7em .9em .2em; }
#articlePage .ar-cards .arc-meta , #trainHubPage .ar-cards .arc-meta,
#minePage .ar-cards .arc-meta,
#donePage .ar-cards .arc-meta,#trainDonePage .ar-cards .arc-meta,#impQuizPage .ar-cards .arc-meta{ display: flex; flex-wrap: wrap; gap: 6px; margin: 0; }
/* ── 底栏：左 1/N 编号 + 已读；右 书按钮（热区放大到 34px） ── */
#articlePage .ar-cards .arc-footer , #trainHubPage .ar-cards .arc-footer,
/* ── 底栏：左 1/N 编号 + 已读；右 书按钮（热区放大到 34px） ── */
#minePage .ar-cards .arc-footer,
#donePage .ar-cards .arc-footer,#trainDonePage .ar-cards .arc-footer,#impQuizPage .ar-cards .arc-footer{
  margin-top: auto; padding: .55em .75em .7em .9em;
  display: flex; align-items: center; gap: 8px;
}
#articlePage .ar-cards .arc-idx , #trainHubPage .ar-cards .arc-idx,
#minePage .ar-cards .arc-idx,
#donePage .ar-cards .arc-idx,#trainDonePage .ar-cards .arc-idx,#impQuizPage .ar-cards .arc-idx{
  padding: 2px 9px; border-radius: 100px; font-size: .7em; font-weight: 700;
  color: #3F2D24; background: #E9E0D4; font-variant-numeric: tabular-nums;
}
html.dark #articlePage .ar-cards .arc-idx , html.dark #trainHubPage .ar-cards .arc-idx,
html.dark #minePage .ar-cards .arc-idx,
html.dark #donePage .ar-cards .arc-idx,html.dark #trainDonePage .ar-cards .arc-idx,html.dark #impQuizPage .ar-cards .arc-idx{ color: #E9E0D4; background: #3A322C; }
#articlePage .ar-cards .arc-read , #trainHubPage .ar-cards .arc-read,
#minePage .ar-cards .arc-read,
#donePage .ar-cards .arc-read,#trainDonePage .ar-cards .arc-read,#impQuizPage .ar-cards .arc-read{ font-size: .72em; font-weight: 700; color: #036B4B; }
html.dark #articlePage .ar-cards .arc-read , html.dark #trainHubPage .ar-cards .arc-read,
html.dark #minePage .ar-cards .arc-read,
html.dark #donePage .ar-cards .arc-read,html.dark #trainDonePage .ar-cards .arc-read,html.dark #impQuizPage .ar-cards .arc-read{ color: #A8BC90; }
/* 词数片 / 分类片在卡片上要看得清：本站默认是浅灰小字，这里换正文色并加粗 */
#articlePage .ar-cards .ar-meta-chip.words , #trainHubPage .ar-cards .ar-meta-chip.words,
/* 词数片 / 分类片在卡片上要看得清：本站默认是浅灰小字，这里换正文色并加粗 */
#minePage .ar-cards .ar-meta-chip.words,
#donePage .ar-cards .ar-meta-chip.words,#trainDonePage .ar-cards .ar-meta-chip.words,#impQuizPage .ar-cards .ar-meta-chip.words{ color: #3A332E; font-weight: 700; }
html.dark #articlePage .ar-cards .ar-meta-chip.words , html.dark #trainHubPage .ar-cards .ar-meta-chip.words,
html.dark #minePage .ar-cards .ar-meta-chip.words,
html.dark #donePage .ar-cards .ar-meta-chip.words,html.dark #trainDonePage .ar-cards .ar-meta-chip.words,html.dark #impQuizPage .ar-cards .ar-meta-chip.words{ color: #EDE9E4; }
#articlePage .ar-cards .ar-meta-chip.cat , #trainHubPage .ar-cards .ar-meta-chip.cat,
#minePage .ar-cards .ar-meta-chip.cat,
#donePage .ar-cards .ar-meta-chip.cat,#trainDonePage .ar-cards .ar-meta-chip.cat,#impQuizPage .ar-cards .ar-meta-chip.cat{ color: #4A3229; font-weight: 700; }
html.dark #articlePage .ar-cards .ar-meta-chip.cat , html.dark #trainHubPage .ar-cards .ar-meta-chip.cat,
html.dark #minePage .ar-cards .ar-meta-chip.cat,
html.dark #donePage .ar-cards .ar-meta-chip.cat,html.dark #trainDonePage .ar-cards .ar-meta-chip.cat,html.dark #impQuizPage .ar-cards .ar-meta-chip.cat{ color: #E9E0D4; }
#articlePage .ar-cards .arc-spacer , #trainHubPage .ar-cards .arc-spacer,
#minePage .ar-cards .arc-spacer,
#donePage .ar-cards .arc-spacer,#trainDonePage .ar-cards .arc-spacer,#impQuizPage .ar-cards .arc-spacer{ display: none; }
/* ── 底栏圆钮（书图标）：视觉 34px、热区 40px；hover 用有偏移的暖色阴影，不用零偏移光晕 ── */
#articlePage .ar-cards .arc-btn , #trainHubPage .ar-cards .arc-btn,
/* ── 底栏圆钮（书图标）：视觉 34px、热区 40px；hover 用有偏移的暖色阴影，不用零偏移光晕 ── */
#minePage .ar-cards .arc-btn,
#donePage .ar-cards .arc-btn,#trainDonePage .ar-cards .arc-btn,#impQuizPage .ar-cards .arc-btn{
  display: flex; align-items: center; justify-content: center; flex: none;
  width: 34px; height: 34px; margin-left: auto;
  border: 1px solid var(--c-border); border-radius: 50px; background: var(--c-bg-card);
  color: var(--c-accent-deep); cursor: pointer; position: relative;
  transition: background-color 180ms var(--ease-out-quart), color 180ms var(--ease-out-quart), border-color 180ms var(--ease-out-quart), box-shadow 180ms var(--ease-out-quart);
}
#articlePage .ar-cards .arc-btn::after , #trainHubPage .ar-cards .arc-btn::after,
#minePage .ar-cards .arc-btn::after,
#donePage .ar-cards .arc-btn::after,#trainDonePage .ar-cards .arc-btn::after,#impQuizPage .ar-cards .arc-btn::after{ content: ''; position: absolute; inset: -3px; border-radius: 50px; }
#articlePage .ar-cards .arc-btn svg , #trainHubPage .ar-cards .arc-btn svg,
#minePage .ar-cards .arc-btn svg,
#donePage .ar-cards .arc-btn svg,#trainDonePage .ar-cards .arc-btn svg,#impQuizPage .ar-cards .arc-btn svg{ width: 17px; height: 17px; }
#articlePage .ar-cards .arc-btn:hover , #trainHubPage .ar-cards .arc-btn:hover,
#minePage .ar-cards .arc-btn:hover,
#donePage .ar-cards .arc-btn:hover,#trainDonePage .ar-cards .arc-btn:hover,#impQuizPage .ar-cards .arc-btn:hover{ background: var(--c-accent-light); border-color: var(--c-accent-light); color: #4A3229; box-shadow: 0 3px 10px rgba(90,110,69,.22); }
#articlePage .ar-cards .arc-btn:active , #trainHubPage .ar-cards .arc-btn:active,
#minePage .ar-cards .arc-btn:active,
#donePage .ar-cards .arc-btn:active,#trainDonePage .ar-cards .arc-btn:active,#impQuizPage .ar-cards .arc-btn:active{ background: var(--c-accent); border-color: var(--c-accent); color: #fff; }
#articlePage .ar-cards .arc-btn:focus-visible , #trainHubPage .ar-cards .arc-btn:focus-visible,
#minePage .ar-cards .arc-btn:focus-visible,
#donePage .ar-cards .arc-btn:focus-visible,#trainDonePage .ar-cards .arc-btn:focus-visible,#impQuizPage .ar-cards .arc-btn:focus-visible{ outline: 2px solid var(--c-accent); outline-offset: 2px; }
html.dark #articlePage .ar-cards .arc-btn , html.dark #trainHubPage .ar-cards .arc-btn,
html.dark #minePage .ar-cards .arc-btn,
html.dark #donePage .ar-cards .arc-btn,html.dark #trainDonePage .ar-cards .arc-btn,html.dark #impQuizPage .ar-cards .arc-btn{ background: #292524; border-color: #57534E; color: #E9E0D4; }
html.dark #articlePage .ar-cards .arc-btn:hover , html.dark #trainHubPage .ar-cards .arc-btn:hover,
html.dark #minePage .ar-cards .arc-btn:hover,
html.dark #donePage .ar-cards .arc-btn:hover,html.dark #trainDonePage .ar-cards .arc-btn:hover,html.dark #impQuizPage .ar-cards .arc-btn:hover{ background: #3A322C; border-color: #D4A373; color: #E9E0D4; }
/* ── 封面上的收藏星标 / 删除按钮：压在纸底上，给半透明底保证可辨；触屏常显 ── */
#articlePage .ar-cards .ar-fav , #trainHubPage .ar-cards .ar-fav,
/* ── 封面上的收藏星标 / 删除按钮：压在纸底上，给半透明底保证可辨；触屏常显 ── */
#minePage .ar-cards .ar-fav,
#donePage .ar-cards .ar-fav,#trainDonePage .ar-cards .ar-fav,#impQuizPage .ar-cards .ar-fav{ top: 6px; right: 6px; z-index: 2; background: rgba(255,255,255,.7); color: #4A3229; }
html.dark #articlePage .ar-cards .ar-fav , html.dark #trainHubPage .ar-cards .ar-fav,
html.dark #minePage .ar-cards .ar-fav,
html.dark #donePage .ar-cards .ar-fav,html.dark #trainDonePage .ar-cards .ar-fav,html.dark #impQuizPage .ar-cards .ar-fav{ background: rgba(28,25,23,.6); color: #E9E0D4; }
/* 「删除这张卡片」（2026-10-04 用户要求：**做得明显一些**，且收藏文章与小说里那个要一模一样）——
   原来只是浅灰 × 压在白色半透明底上（`--c-border:#E7E5E4`，几乎看不见）。现在统一成**红色圆钮**：
   白半透明圆底 + 红 × + 细描边 + 一点阴影；hover/按下变实心红。
   注意：这一条对**文章库 / 我的导入 / 我的已读 / 我的收藏 / 我的小说**一视同仁 —— 它们是同一批
   `.lib-card.arc`，所以「收藏文章」和「小说」里的删除钮天然长得一样（用户要的就是这个）。 */
#articlePage .ar-cards .lib-del , #trainHubPage .ar-cards .lib-del,
/* 「删除这张卡片」（2026-10-04 用户要求：**做得明显一些**，且收藏文章与小说里那个要一模一样）——
   原来只是浅灰 × 压在白色半透明底上（`--c-border:#E7E5E4`，几乎看不见）。现在统一成**红色圆钮**：
   白半透明圆底 + 红 × + 细描边 + 一点阴影；hover/按下变实心红。
   注意：这一条对**文章库 / 我的导入 / 我的已读 / 我的收藏 / 我的小说**一视同仁 —— 它们是同一批
   `.lib-card.arc`，所以「收藏文章」和「小说」里的删除钮天然长得一样（用户要的就是这个）。 */
#minePage .ar-cards .lib-del,
#donePage .ar-cards .lib-del,#trainDonePage .ar-cards .lib-del,#impQuizPage .ar-cards .lib-del{ top: 6px; right: 6px; z-index: 2; display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; padding: 0; border-radius: 50%; background: rgba(255,255,255,.88); color: var(--c-danger);
  border: 1px solid rgba(166,61,42,.26); font-size: 1.1em; line-height: 1; opacity: 1;
  box-shadow: 0 1px 4px rgba(28,25,23,.10); transition: background-color .18s ease, color .18s ease, border-color .18s ease, transform .18s ease; }
#articlePage .ar-cards .lib-del:hover , #trainHubPage .ar-cards .lib-del:hover,
#minePage .ar-cards .lib-del:hover,
#donePage .ar-cards .lib-del:hover,#trainDonePage .ar-cards .lib-del:hover,#impQuizPage .ar-cards .lib-del:hover{ background: var(--c-danger); color: #fff; border-color: var(--c-danger); transform: scale(1.06); }
html.dark #articlePage .ar-cards .lib-del , html.dark #trainHubPage .ar-cards .lib-del,
html.dark #minePage .ar-cards .lib-del,
html.dark #donePage .ar-cards .lib-del,html.dark #trainDonePage .ar-cards .lib-del,html.dark #impQuizPage .ar-cards .lib-del{ background: rgba(28,25,23,.72); color: var(--c-danger); border-color: rgba(224,139,118,.32); }
html.dark #articlePage .ar-cards .lib-del:hover , html.dark #trainHubPage .ar-cards .lib-del:hover,
html.dark #minePage .ar-cards .lib-del:hover,
html.dark #donePage .ar-cards .lib-del:hover,html.dark #trainDonePage .ar-cards .lib-del:hover,html.dark #impQuizPage .ar-cards .lib-del:hover{ background: var(--c-danger); color: #1C1917; border-color: var(--c-danger); }
/* 同一颗删除钮也用在「题目训练 → 我的」那两张列表上（2026-10-04）——那边不是 #articlePage，
   所以把上面那份规则的选择器补上 #trainHubPage，保证两处长得一模一样。 */
#trainHubPage .ar-cards .lib-del,
#donePage .ar-cards .lib-del,#trainDonePage .ar-cards .lib-del,#impQuizPage .ar-cards .lib-del{ top: 6px; right: 6px; z-index: 2; display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; padding: 0; border-radius: 50%; background: rgba(255,255,255,.88); color: var(--c-danger);
  border: 1px solid rgba(166,61,42,.26); font-size: 1.1em; line-height: 1; opacity: 1;
  box-shadow: 0 1px 4px rgba(28,25,23,.10); transition: background-color .18s ease, color .18s ease, border-color .18s ease, transform .18s ease; }
#trainHubPage .ar-cards .lib-del:hover,
#donePage .ar-cards .lib-del:hover,#trainDonePage .ar-cards .lib-del:hover,#impQuizPage .ar-cards .lib-del:hover{ background: var(--c-danger); color: #fff; border-color: var(--c-danger); transform: scale(1.06); }
html.dark #trainHubPage .ar-cards .lib-del,
html.dark #donePage .ar-cards .lib-del,html.dark #trainDonePage .ar-cards .lib-del,html.dark #impQuizPage .ar-cards .lib-del{ background: rgba(28,25,23,.72); color: var(--c-danger); border-color: rgba(224,139,118,.32); }
html.dark #trainHubPage .ar-cards .lib-del:hover,
html.dark #donePage .ar-cards .lib-del:hover,html.dark #trainDonePage .ar-cards .lib-del:hover,html.dark #impQuizPage .ar-cards .lib-del:hover{ background: var(--c-danger); color: #1C1917; border-color: var(--c-danger); }
@media (hover: none) {
  #articlePage .ar-cards .ar-fav ,   #trainHubPage .ar-cards .ar-fav,
#minePage .ar-cards .ar-fav,
#donePage .ar-cards .ar-fav,#trainDonePage .ar-cards .ar-fav,#impQuizPage .ar-cards .ar-fav{ opacity: 1; }
}
/* 手机上两列（卡片保持竖向比例；390 宽可用约 306px） */
@media (max-width: 480px) {
  #articlePage .ar-cards ,   #trainHubPage .ar-cards,
#minePage .ar-cards,
#donePage .ar-cards,#trainDonePage .ar-cards,#impQuizPage .ar-cards{ gap: 12px; }
  #articlePage .ar-cards .lib-card ,   #trainHubPage .ar-cards .lib-card,
#minePage .ar-cards .lib-card,
#donePage .ar-cards .lib-card,#trainDonePage .ar-cards .lib-card,#impQuizPage .ar-cards .lib-card{ flex-basis: 130px; min-width: 130px; min-height: 206px; }
  #articlePage .ar-cards .arc-cover ,   #trainHubPage .ar-cards .arc-cover,
#minePage .ar-cards .arc-cover,
#donePage .ar-cards .arc-cover,#trainDonePage .ar-cards .arc-cover,#impQuizPage .ar-cards .arc-cover{ min-height: 100px; padding: .8em .7em; }
  #articlePage .ar-cards .arc-title ,   #trainHubPage .ar-cards .arc-title,
#minePage .ar-cards .arc-title,
#donePage .ar-cards .arc-title,#trainDonePage .ar-cards .arc-title,#impQuizPage .ar-cards .arc-title{ font-size: .92em; }
  #articlePage .ar-cards .arc-title-en ,   #trainHubPage .ar-cards .arc-title-en,
#minePage .ar-cards .arc-title-en,
#donePage .ar-cards .arc-title-en,#trainDonePage .ar-cards .arc-title-en,#impQuizPage .ar-cards .arc-title-en{ font-size: .7em; }
}
@media (prefers-reduced-motion: reduce) {
  #articlePage .ar-cards .lib-card,   #trainHubPage .ar-cards .lib-card,
  #articlePage .ar-cards .arc-btn ,   #trainHubPage .ar-cards .arc-btn,
#minePage .ar-cards .lib-card,
#minePage .ar-cards .arc-btn,
#donePage .ar-cards .lib-card,#trainDonePage .ar-cards .lib-card,#impQuizPage .ar-cards .lib-card,#donePage .ar-cards .arc-btn,#trainDonePage .ar-cards .arc-btn,#impQuizPage .ar-cards .arc-btn{ transition: none; }
  #articlePage .ar-cards .lib-card:hover,   #trainHubPage .ar-cards .lib-card:hover,
  #articlePage .ar-cards .lib-card:active ,   #trainHubPage .ar-cards .lib-card:active,
#minePage .ar-cards .lib-card:hover,
#minePage .ar-cards .lib-card:active,
#donePage .ar-cards .lib-card:hover,#trainDonePage .ar-cards .lib-card:hover,#impQuizPage .ar-cards .lib-card:hover,#donePage .ar-cards .lib-card:active,#trainDonePage .ar-cards .lib-card:active,#impQuizPage .ar-cards .lib-card:active{ transform: none; }
}

/* ── 我的：保存文章 / 收藏文章 ──
   2026-09-21 用户要求「我的」整页版式与文章库一致 → 原来的「上下两块（.ar-sec）」改成
   **顶部一行按钮（保存文章 / 收藏文章）+ 一个卡片网格**，按钮直接复用文章库的 .ar-cats/.ar-cat
   （同一位置、同一外观），故此处原有的 .ar-sec / .ar-sec-head / .ar-sec-empty 一组样式整体删除。 */

/* ── 导入文章（文章阅读第 4 栏）**与导入阅读（独立整页）是两件事**（2026-09-22 用户指出后拆开）──
   原先的做法是「把 #importReadingPage 整块搬进本视图」，已撤销：导入阅读回到它自己的整页。
   现在两者各有各的 DOM 与数据流（导入阅读 → 我的阅读 / 已做题目；导入文章 → 我的导入文章 → 文章库），
   但**共用同一套 `.imp-*` 视觉** —— 组件样式的作用域已从 `#importReadingPage` 改为 `.imp-scope` 类，
   两个页面的一层容器都带这个类即可（见 #importReadingPage 与本视图的 .imp-scope）。 */
/* 导入文章的外壳头部：与文章库同一个内容栏（.vocab-page），按钮行位置一致 */
#articlePage .ar-imp-head { padding-bottom: 0; }

/* ── 内容栏宽度（2026-09-23 用户反馈：「我的 / 文章库」左右空白太大）──
   原因：`.vocab-page { max-width: 800px; margin: 0 auto }` 是全站给"阅读类"栏目定的窄栏
   （生词本、已做阅读那种一行行的列表正合适），但文章库/我的 是**卡片墙**，被 800px 一卡再居中，
   1440 宽下左右各空 245px、1920 下各空 485px。
   改法：文章页里的 .vocab-page 取消 800px 上限、改成**左对齐铺满**内容区（与顶栏返回按钮同一左边界），
   卡片墙就能把空间用起来（1440 → 6 列、1920 → 9 列）。阅读页的正文栏不受影响（不是这个类）。 */
#articlePage .vocab-page { max-width: none; margin: 0; }
/* 「导入文章」的三个子视图是表单式内容（上传区/拍照区/我的导入），别拉成超宽，给个舒服的上限；
   头部标题行仍与文章库/我的 同宽左对齐（保持三个板块标题位置一致）。 */
#articlePage #arViewImport .vocab-page:not(.ar-imp-head) { max-width: 880px; }
/* 「文章 → 我的」那一屏也走同一套：三级按钮 + 内容大框作为 880 一块整体居中（2026-10-05）——
   上面 `#articlePage .vocab-page { max-width:none }` 会把 `.mine-block` 的 880 顶掉，所以这里更具体地写一条。 */
#articlePage #arViewMine .vocab-page.mine-block { max-width: 880px; margin: 0 auto; }
/* 导入题目的导入界面（同一套组件搬到题目训练页）沿用同样的宽度预算 —— 2026-10-05 */
#thImpMount .vocab-page:not(.ar-imp-head) { max-width: 880px; margin-left: auto; margin-right: auto; }
/* ── 导入界面统一排版（2026-10-05 用户要求，导入文章 / 导入题目 共用这一套）──────────
   ① 内容块 = 三个入口按钮 + 拖拽框 + 导入规则，统一 880 宽并**整体水平居中**；
   ② 按钮组左边缘与拖拽框左边缘严格对齐（同在 880 块里，padding 一致 → 左边都是块左 + 24）；
   ③ 按钮组底部贴紧拖拽框顶部（行 margin-bottom 收到 8px、内容块 padding-top 归零）；
   ④ 整块向上提 14px，减少顶部空白。 */
#arViewImport .ar-imp-head,
#impQuizPage .ar-imp-head {
  max-width: 880px; margin: 0 auto; padding: 0 24px; }
#arViewImport .ar-imp-head .ar-cats,
#impQuizPage .ar-imp-head .ar-cats { margin: 0 0 8px; }
#arViewImport .vocab-page:not(.ar-imp-head),
#thImpMount .vocab-page:not(.ar-imp-head),
#impQuizPage > .vocab-page:not(.ar-imp-head) {
  max-width: 880px; margin-left: auto; margin-right: auto; padding: 0 24px 24px; }
/* 窄屏：两个页面容器的左右内边距不一样（文章页 28 / 题目训练页 20），
   会让同一块内容在两个入口差 12px —— 这里给导入题目面板补 8px，两边落点完全一致（2026-10-05）。 */
@media (max-width: 768px) { #impQuizPage { padding-left: 12px; padding-right: 12px; } }
html.force-phone #impQuizPage { padding-left: 12px; padding-right: 12px; }
/* 导入文章的三个子视图沿用导入阅读那套 .vocab-page 内边距；页级 padding-top 不需要（外壳顶栏不是固定的）。
   2026-09-22：`头部`（.ar-imp-head，含「导入文章」标题行）要**保留** .vocab-page 自己的 padding-top，
   否则它的标题比「文章库 / 我的」高一截（桌面实测 76 vs 108、手机 20 vs 40），
   三个板块标题位置就不同了（用户要求位置一致）。 */
#arViewImport .vocab-page:not(.ar-imp-head) { padding-top: 0; }
#arViewImport .lib-del { opacity: 1; }

/* ── 「保存这篇」（2026-10-07 用户要求）──────────────────────────────────────────────
   原来挂在右栏生词本下面（#arFinishWrap，已删）；现在**统一收到顶栏**，位置就在
   「标注」和「收藏」中间。显隐同「上一篇 / 下一篇」那套：默认不显示，只有文章阅读
   （#readingPage.reading-article）才出现 —— CSS 说了算，JS 只切类。 */
#readingPage #btnSaveArticle { display: none; }
#readingPage.reading-article #btnSaveArticle { display: flex; }
#readingPage #pmFinishBtn { display: none; }
#readingPage.reading-article #pmFinishBtn { display: inline-flex; }
/* 顶栏「上一篇 / 下一篇」：**默认不显示**，只有文章阅读模式才出现（与「选一篇」同款 .btn-hot 皮肤）。
   用户要求：「文章阅读里面的上下篇要，原题训练顶栏的上下篇不要」。
   所以显隐做成 **CSS 说了算、JS 只负责加/去 `reading-article` 类** ——
   反过来写（默认显示、再由 arSyncReadingChrome() 用 style.display 去藏）的话，
   一旦某条入口漏调同步函数、或页面在 JS 跑之前先绘制，真题页就可能冒出这两个按钮。
   现在结构上不可能：没有这个类就没有显示规则。 */
#readingPage #btnPrevArticle, #readingPage #btnNextArticle { display: none; }
#readingPage.reading-article #btnPrevArticle,
#readingPage.reading-article #btnNextArticle { display: flex; }
/* 手机「更多」面板里那对同理（顶栏按钮在 force-phone 下被整体隐藏，动作在面板里也有一份） */
#readingPage #pmPrevBtn, #readingPage #pmNextBtn { display: none; }
#readingPage.reading-article #pmPrevBtn,
#readingPage.reading-article #pmNextBtn { display: inline-flex; }
/* 文章阅读顶栏**不要**那个「换一篇 / 选一篇」按钮（2026-09-24 用户要求）：
   文章阅读要换篇就回文章库；原题训练里它才显示「换一篇」，那里留着。
   顶栏那个按钮与手机「更多」面板里那份一起处理，靠 reading-article 类切换，不用 JS 抢 display。 */
#readingPage.reading-article #btnRefresh,
#readingPage.reading-article .phone-more-panel .pm-refresh { display: none !important; }
/* ── 小说阅读页（2026-10-04 用户要求）─────────────────────────────
   从「生成小说」生成完成点「查看」进来的，走的是**和阅读文章完全同一个界面**（#readingPage），
   只是顶栏不要「上一篇 / 下一篇 / 收藏文章」，换成「修改 / 再来一篇」；「标注 / 全文翻译」保持。
   和上面两套一样：显隐只认 `reading-story` 这个类，JS 不抢行内 display。 */
#readingPage #btnStoryEdit, #readingPage #btnStoryAgain { display: none; }
#readingPage.reading-story #btnStoryEdit,
#readingPage.reading-story #btnStoryAgain { display: flex; }
/* ── 「生成题目」的查看页（2026-10-04 用户要求）：修改 / 再来一篇 **只在这个界面出现** ──
   走的是同一个 #readingPage（state.reading.type='基础阅读' 且记录带 from='gen'，见 arIsGenQuizMode），
   所以要有一组**独立**的按钮与类，别和小说那两颗混用。 */
/* 「收藏」★（P2 2026-10-04）：只在题目类阅读页出现 */
#readingPage #btnFavQuiz { display: none; }
#readingPage.reading-quiz #btnFavQuiz { display: flex; }
#readingPage #pmFavQuizBtn { display: none; }
#readingPage.reading-quiz #pmFavQuizBtn { display: inline-flex; }
#readingPage #btnGenEdit, #readingPage #btnGenAgain { display: none; }
#readingPage.reading-aigen #btnGenEdit,
#readingPage.reading-aigen #btnGenAgain { display: flex; }
#readingPage #pmGenEditBtn, #readingPage #pmGenAgainBtn { display: none; }
#readingPage.reading-aigen #pmGenEditBtn,
#readingPage.reading-aigen #pmGenAgainBtn { display: inline-flex; }
#readingPage #pmStoryEditBtn, #readingPage #pmStoryAgainBtn { display: none; }
#readingPage.reading-story #pmStoryEditBtn,
#readingPage.reading-story #pmStoryAgainBtn { display: inline-flex; }
#readingPage.reading-story #btnRefresh,
#readingPage.reading-story .phone-more-panel .pm-refresh { display: none !important; }
#readingPage.reading-story #btnSaveReading,
#readingPage.reading-story .phone-more-panel .pm-save { display: none !important; }
/* ── 分支A（暂不新建）：底部输入区整块换成这颗「创建新对话」（2026-10-05 用户定稿）──
   题目与小说共用同一套外观；按钮皮肤沿用上面那颗「保存/查看」的绿色胶囊。 */
.chat-new-area { text-align: center; padding: 6px 0 12px; }
.chat-new-area .btn-save { padding: 12px 36px; background: #4F6B36; color: #fff; border-radius: 100px; font-size: .92em;
  font-weight: 600; letter-spacing: .04em; box-shadow: 0 2px 12px rgba(79,107,54,.25); transition: all .25s ease; }
.chat-new-area .btn-save:hover { transform: translateY(-2px); box-shadow: 0 6px 20px rgba(79,107,54,.35); }
html.dark .chat-new-area .btn-save { color: #fff; }
/* ── 生成完成后的三颗按钮：查看 / 修改 / 再来一篇（对话区底部）── */
.chat-save-area .story-done-btns { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; }
.chat-save-area .story-done-btns .btn-save.ghost { background: var(--c-white); color: var(--c-text-secondary); border: 1px solid var(--c-border); box-shadow: none; }
.chat-save-area .story-done-btns .btn-save.ghost:hover { background: #F5EFE4; border-color: var(--c-accent); color: var(--c-accent); box-shadow: 0 4px 14px rgba(217,119,6,.18); }
html.dark .chat-save-area .story-done-btns .btn-save.ghost { background: #2A2724; color: var(--c-text-secondary); border-color: var(--c-border); }
html.dark .chat-save-area .story-done-btns .btn-save.ghost:hover { background: #332E2A; border-color: var(--c-accent); color: var(--c-accent); }
/* ── 生成对话里那排「可点选项」（#storyChatQuick，2026-10-04 挪到输入框正上方）──
   一行胶囊按钮、紧贴输入框；手机上横向滑动（沿用 html.force-phone .chat-quick 那条规则）。 */
#storyChatQuick { margin: 0 0 10px; padding: 0 2px; }
#storyChatQuick .sg-btn { flex: 0 0 auto; }
/* ── 真题阅读页（完形 / 阅读 / 新题型 / 翻译…）：顶栏把「换一篇」整块换成「上一篇 / 下一篇」──
   2026-09-27 用户要求：点一下就到「下一年」的那一篇（同科目、同题型、同卷别，按 年份→篇号 排序）。
   和上面文章模式一样，显隐只靠这个类，JS 不抢行内 display。 */
#readingPage.reading-exam #btnPrevArticle,
#readingPage.reading-exam #btnNextArticle { display: flex; }
#readingPage.reading-exam #btnRefresh,
#readingPage.reading-exam .phone-more-panel .pm-refresh { display: none !important; }
#readingPage.reading-exam #pmPrevBtn,
#readingPage.reading-exam #pmNextBtn { display: inline-flex; }
/* ── 新题型页（2026-09-28）───────────────────────────────────────
   顶栏「换一篇」整块换成「上一篇 / 下一篇」——新题型同样按 年份→卷别 排序翻篇，
   走的还是上面那套 reading-exam 规则，这里只是让 isExamReading() 认得新题型卷。
   ⚠️ 「全文翻译」在这页**保留**（用户 2026-09-28 明确要求「还是要有的」），
   不再按 reading-newtype 隐藏；新题型卷没有 content 字段，translateFull() 里已按段落拼正文。 */
/* 到头了：置灰但仍在（用户能看到"没有更早/更晚的年份了"） */
#readingPage #btnPrevArticle[disabled], #readingPage #btnNextArticle[disabled] { opacity: .4; cursor: not-allowed; }
/* 「保存文章」已收藏态：绿色实心，与橙色「全文翻译」明确区分 */
#readingPage #btnSaveReading.faved, #readingPage #btnSaveReading.faved:hover, #readingPage #btnSaveReading.faved:active {
  background-image: linear-gradient(135deg, #0F7A50 0%, #0B5C3C 100%); color: #fff;
}
html.dark #readingPage #btnSaveReading.faved, html.dark #readingPage #btnSaveReading.faved:hover, html.dark #readingPage #btnSaveReading.faved:active {
  background-image: linear-gradient(135deg, #0F7A50 0%, #0A4C31 100%); color: #F0FDF4;
}
/* ── 悬浮小恐龙宠物（2026-09-23 新增）──────────────────────────────
   全站常驻的固定层，默认贴**左下角**（右下角已被 AI 客服 bottom:24 / 反馈 bottom:88 占用）。
   容器自身 pointer-events:none，只有宠物本体和收起按钮吃事件 —— 绝不挡住页面内容与文字选择。
   左侧出现固定侧栏（速记生词 #wsRail / 文章 #arRail / 管理 #adminNav）时，
   由 JS 读实际布局把 left 让开：侧栏有 display 和 .hidden 两种隐藏方式，
   写死 :has() 判不准，getBoundingClientRect().width === 0 才可靠。 */
.dino-pet { position: fixed; left: 16px; bottom: 16px; z-index: 86; --dino-size: 122px;
  width: var(--dino-size); height: var(--dino-size); pointer-events: none;
  transition: left .24s var(--ease-out-quart), bottom .24s var(--ease-out-quart); }
.dino-pet.dino-dragging { transition: none; }
.dino-pet.dino-off, .dino-pet-restore.dino-off, .pet-ask-btn.dino-off { display: none; }   /* ⚠ 新加的浮动件要记得加进这条，否则只切类、人还杵在那儿 */
/* stage 负责裁剪 + 呼吸/动作位移，strip 负责逐帧播放；两层各管一套动画就不打架。
   drop-shadow 挂在 stage 上（不是 strip）：strip 有 N 帧那么宽，挂在它身上会被 stage 裁掉，
   而挂在 stage 上时滤镜作用在「裁完之后」的结果上，影子能正常落到框外。 */
/* 待机是**一张图**，所以"活着"的感觉全在这条动画上。
   ⚠ 关键：**脚不能动** —— 所以不用 translateY（整体上下平移会把脚抬起来），
   改成**绕脚底那个点**做两件事：
     · 上下 = `scaleY` 拉伸（缩放中心在脚上 ⇒ 脚不动、身体拔高/回落，就是呼吸）
     · 左右 = `rotate`（同样绕脚 ⇒ 脚基本不动，上半身左右晃 = 重心在两脚间挪）
   `transform-origin: 50% 88%`：角色脚底在帧框 95.5% 处，取 88% 做支点 ——
   脚离支点只有 7.5%，缩放时脚几乎不位移（0.2px 级），同时给 scale 留出头顶余量（帧框上下各留 4.5%）。 */
.dino-pet-stage { position: relative; width: 100%; height: 100%; overflow: hidden; transform-origin: 50% 88%;
  filter: drop-shadow(0 4px 7px rgba(41,37,36,.18));
  animation: dinoBreath 3.8s ease-in-out infinite; }
.dino-pet.acting .dino-pet-stage { animation: none; }
html.dark .dino-pet-stage { filter: drop-shadow(0 4px 8px rgba(0,0,0,.55)); }
/* 雪碧图一行 N 帧，帧等宽等高。**不加任何 opacity 过渡**：
   曾经用两层交叉溶解去"补中间帧"，但两层同时半透明时合成不透明度会掉到 ~0.75，
   每切一帧闪一次（走路 180ms 一帧 = 每秒闪 5 次），而且两层姿势错开还会闪出一只"更宽更淡"的恐龙。
   现在就是硬切 + 更快的帧速，靠速度出流畅感。两层 img 交替只是为了换帧时不必重新给 src（只改 transform）。 */
.dino-pet-strip { position: absolute; left: 0; top: 0; height: 100%; width: auto; display: block;
  opacity: 0; pointer-events: auto; cursor: grab;
  touch-action: none; -webkit-user-drag: none; user-select: none; -webkit-user-select: none; }
.dino-pet-strip.on { opacity: 1; }
.dino-pet-strip:active { cursor: grabbing; }
@keyframes dinoBreath {
  0%,100% { transform: rotate(0deg)    scaleY(1); }
  28%     { transform: rotate(-2deg)   scaleY(1.02); }
  62%     { transform: rotate(1.8deg)  scaleY(1.006); }
}
.dino-pet.act-pop   .dino-pet-stage { animation: dinoPop .62s var(--ease-out-quart) 2; }
.dino-pet.act-shake .dino-pet-stage { animation: dinoShake .7s ease-in-out 2; }
/* 缩放同样绕 88% 的支点，1.05 刚好在头顶余量内（再大就会顶到帧框上沿） */
@keyframes dinoPop { 0%,100% { transform: scale(1); } 45% { transform: scale(1.05) rotate(-2.5deg); } }
@keyframes dinoShake { 0%,100% { transform: translateX(0); } 25% { transform: translateX(-5px) rotate(-2deg); } 75% { transform: translateX(5px) rotate(2deg); } }
/* 英文台词气泡：贴在宠物右上方，尖角朝宠物。
   ⚠️ 这里的百分比不是拍脑袋的：宠物立绘只占帧框中间一块（实测四只一致 —— 右边 ~74%~78%、上边 10.3%），
   原来写 `calc(100% + 12px)` 是从**帧框**右沿起算，看着就离宠物老远。现在从立绘右沿（79%）起算、只留 3px。
   尖角（4px 那个角）在左下、指向宠物。 */
.dino-pet-bubble { position: relative;
  min-width: 104px; max-width: 220px; padding: 11px 17px 11px 19px;
  /* ⚠️ 这里**不能**声明 --bub：自定义属性一旦在本元素上声明，就盖住从 .dino-pet 继承下来的那只宠物的颜色
     （踩过：四只气泡底色全变成兜底色）。只留 var() 的兜底值。 */
  background: var(--bub, #FFFCF8); color: var(--c-text);
  border: none; border-radius: 0;
  font-size: .82em; line-height: 1.45; opacity: 0; transform: translateY(4px) scale(.96);
  transform-origin: left bottom; transition: opacity .18s ease, transform .22s var(--ease-out-quart);
  pointer-events: none;
  /* 思考云蒙版：**只取云**（viewBox 收到云的包围盒 192 125 756 455 → 云撑满整个盒子，文字区域不被侵占）；
     两个小圆点在蒙版外，由下面的 .pbub-dots 画 —— 放进蒙版会挤掉文字（踩过） */
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='192 125 756 455' preserveAspectRatio='none'%3E%3Cpath d='M265 405 C145 350 185 210 315 220 C350 105 520 95 585 190 C690 105 875 165 860 285 C1000 315 960 485 830 500 C760 615 560 590 505 520 C360 590 205 520 265 405 Z' fill='%23fff'/%3E%3C/svg%3E") no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='192 125 756 455' preserveAspectRatio='none'%3E%3Cpath d='M265 405 C145 350 185 210 315 220 C350 105 520 95 585 190 C690 105 875 165 860 285 C1000 315 960 485 830 500 C760 615 560 590 505 520 C360 590 205 520 265 405 Z' fill='%23fff'/%3E%3C/svg%3E") no-repeat;
  -webkit-mask-size: 100% 100%; mask-size: 100% 100%;
  /* 描边与软投影都挪到**壳**（.dino-pet-bubwrap）上了：
     filter 与 mask 放在同一个元素上时，浏览器先滤镜后蒙版 → 影子会被裁掉，画不出描边（见壳那条规则） */
  }
/* 气泡的**壳**：只负责定位与描边。
   ⚠️ 为什么必须有这一层：`filter` 与 `mask` 放在**同一个元素**上时，浏览器先滤镜后蒙版 ——
   drop-shadow 投出来的描边落在蒙版之外，会被裁掉（用户反馈"圆圈有描边、云朵没有"就是这个；
   实测盒子外侧像素是页面底色而不是描边色）。
   把描边（那串 drop-shadow）放到**壳**上、mask 留在里面的气泡上：壳的 drop-shadow 作用于
   "子元素渲染完（含蒙版）之后的轮廓"，于是描边跟着云形走、又不会被裁。 */
.dino-pet-bubwrap { position: absolute; left: calc(79% + 3px); bottom: 58%; pointer-events: none;
  filter:
    drop-shadow(1.7px 0 0 var(--bub-edge, #B9CFF0)) drop-shadow(-1.7px 0 0 var(--bub-edge, #B9CFF0))
    drop-shadow(0 1.7px 0 var(--bub-edge, #B9CFF0)) drop-shadow(0 -1.7px 0 var(--bub-edge, #B9CFF0))
    drop-shadow(1.2px 1.2px 0 var(--bub-edge, #B9CFF0)) drop-shadow(-1.2px 1.2px 0 var(--bub-edge, #B9CFF0))
    drop-shadow(1.2px -1.2px 0 var(--bub-edge, #B9CFF0)) drop-shadow(-1.2px -1.2px 0 var(--bub-edge, #B9CFF0))
    drop-shadow(0 6px 14px rgba(41,37,36,.16)); }
.dino-pet-bubble.show { opacity: 1; transform: translateY(0) scale(1); }
.dino-pet-bubble b { display: block; font-weight: 600; color: var(--c-accent-deep); letter-spacing: .01em; }
.dino-pet-bubble span { display: block; margin-top: 2px; font-size: .88em; color: var(--c-text-muted); }
html.dark .dino-pet { --bub: #2A2724; }
/* 描边色 = 该宠物主题色（--pc）与底色的混色。比例给到 78%：第一版只给 42% 太淡，1x 屏上看不出来 */
.dino-pet { --bub-edge: color-mix(in srgb, var(--pc, #4A7FE0) 78%, #FFFFFF); }
html.dark .dino-pet { --bub-edge: color-mix(in srgb, var(--pc, #4A7FE0) 88%, #1C1917); }
html.dark .dino-pet-bubble { color: #F5F5F4; }
html.dark .dino-pet-bubble b { color: var(--c-accent-light); }
html.dark .dino-pet-bubble span { color: #A8A29E; }
/* 宠物被拖到屏幕右边、右侧放不下气泡时，翻到宠物**左边**（JS 按剩余宽度加 .bub-left）。
   镜像的只有"贴哪边"和尖角方向，配色/字体不变。 */
.dino-pet.bub-left .dino-pet-bubwrap { left: auto; right: calc(79% + 3px); }
.dino-pet.bub-left .dino-pet-bubble { transform-origin: right bottom; }

/* ── 四只宠物：同一个思考云形状，**靠颜色区分**（2026-09-24 用户要求）──────────────
   形状（含两个小圆点）来自用户给的 thought-cloud.svg，写在上面基础规则里；
   这里只给每只一套 --bub 底色 + 英文行颜色（中英对比度保持）。 */
.dino-pet[data-pet="dino"]   { --bub: #F2EDE4; }
.dino-pet[data-pet="rabbit"] { --bub: #FFF1F7; }
.dino-pet[data-pet="bear"]   { --bub: #F2EDE4; }
.dino-pet[data-pet="wolf"]   { --bub: #F3F7FC; }
.dino-pet[data-pet="dino"]   .dino-pet-bubble b { color: #3C6FD0; }
.dino-pet[data-pet="rabbit"] .dino-pet-bubble b { color: #D4708F; }
.dino-pet[data-pet="bear"]   .dino-pet-bubble b { color: #A9743A; }
.dino-pet[data-pet="wolf"]   .dino-pet-bubble b { color: #55606E; }
html.dark .dino-pet[data-pet="dino"]   { --bub: #2A2724; }
html.dark .dino-pet[data-pet="rabbit"] { --bub: #2E2629; }
html.dark .dino-pet[data-pet="bear"]   { --bub: #2E2822; }
html.dark .dino-pet[data-pet="wolf"]   { --bub: #24282D; }
.dino-pet[data-pet="cat"]   { --bub: #FFF6EC; }
.dino-pet[data-pet="cat"]   .dino-pet-bubble b { color: #C2762A; }
html.dark .dino-pet[data-pet="cat"]   { --bub: #2E2620; }
html.dark .dino-pet[data-pet="cat"]   .dino-pet-bubble b { color: #F0B473; }
.dino-pet[data-pet="pig"]   { --bub: #FFF1F4; }
.dino-pet[data-pet="pig"]   .dino-pet-bubble b { color: #D9647A; }
html.dark .dino-pet[data-pet="pig"]   { --bub: #2E2326; }
html.dark .dino-pet[data-pet="pig"]   .dino-pet-bubble b { color: #F0A0AF; }
html.dark .dino-pet[data-pet="dino"]   .dino-pet-bubble b { color: #8FB4F0; }
html.dark .dino-pet[data-pet="rabbit"] .dino-pet-bubble b { color: #EEA6C0; }
html.dark .dino-pet[data-pet="bear"]   .dino-pet-bubble b { color: #D4A373; }
html.dark .dino-pet[data-pet="wolf"]   .dino-pet-bubble b { color: #AEBAC8; }

/* 思考云的两个小圆点：挂在气泡左下角外侧，跟气泡一起显隐（气泡在前，用 ~ 选到），
   颜色跟气泡底一样（--bub 从 .dino-pet 容器继承）。翻到左边时整体镜像到右下。 */
.pbub-dots { position: absolute; left: calc(79% + 1px); bottom: calc(58% - 16px); width: 11px; height: 11px;
  border-radius: 50%; background: var(--bub, #F2EDE4); pointer-events: none; opacity: 0;
  transition: opacity .18s ease;
  /* 两个小圆点也跟上描边色，和云是一套（圈给到 2px，跟气泡的描边同粗细） */
  box-shadow: 0 0 0 2px var(--bub-edge, #B9CFF0);
  filter: drop-shadow(0 3px 6px rgba(41,37,36,.12)); }
.pbub-dots::after { content: ''; position: absolute; left: -15px; top: 13px; width: 7px; height: 7px;
  border-radius: 50%; background: inherit; box-shadow: 0 0 0 2px var(--bub-edge, #B9CFF0); }
.dino-pet-bubwrap:has(.dino-pet-bubble.show) ~ .pbub-dots { opacity: 1; }
.dino-pet.bub-left .pbub-dots { left: auto; right: calc(79% + 1px); }
.dino-pet.bub-left .pbub-dots::after { left: auto; right: -15px; }
/* 收起按钮：放**宠物右下角**（2026-09-24 用户要求）。
   沿革：帧框右上角 → 贴近头的右上角（5%/5%）—— 但那个位置和台词气泡撞了：
   气泡从 `bottom:58%` 往上长、左沿在 79%，两行以上就会盖住头右侧那块。
   现在放到底部偏右（`bottom:12%; right:3%`），既躲开气泡，也躲开脚下那颗「答疑」钮
   （答疑钮是水平居中、只占底部中间那一小段）。 */
.dino-pet-close { position: absolute; bottom: 12%; right: 3%; width: 20px; height: 20px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center; padding: 0; z-index: 2;
  background: var(--c-white); color: var(--c-text-muted); border: 1px solid rgba(120,113,108,.18);
  box-shadow: var(--shadow-sm); font-size: 13px; line-height: 1; opacity: 0;
  transition: opacity .16s ease, background .16s ease, color .16s ease; pointer-events: auto; }
/* ✕ 的显隐：**点过宠物才出现**（2026-09-24 用户要求），跟「答疑」钮同一时机。
   原来靠 `.dino-pet:hover` 露出来 —— 鼠标一划过就冒出来，用户觉得吵。
   现在由 JS 在 syncAsk() 里一起切 `.dino-pet.tapped`（点宠物 → 两个都出来；点别处 → 两个都收）。 */
.dino-pet.tapped .dino-pet-close { opacity: 1; }
.dino-pet-close:hover { background: var(--c-danger); color: #fff; border-color: var(--c-danger); }
html.dark .dino-pet-close { background: #2A2724; color: #A8A29E; border-color: rgba(255,255,255,.12); }
/* 收起后留下的召回小圆点（不然宠物被收掉就再也找不回来） */
.dino-pet-restore { position: fixed; left: 16px; bottom: 16px; z-index: 86; width: 34px; height: 34px;
  border-radius: 50%; padding: 0; display: flex; align-items: center; justify-content: center;
  background: var(--c-white); border: 1px solid rgba(120,113,108,.18); box-shadow: var(--shadow-md);
  color: var(--c-accent-deep); font-size: 15px; line-height: 1; opacity: .5;
  transition: opacity .2s ease, transform .2s var(--ease-out-quart); }
.dino-pet-restore:hover { opacity: 1; transform: translateY(-2px); }
html.dark .dino-pet-restore { background: #2A2724; color: var(--c-accent-light); }
/* ── 宠物答疑（2026-09-24 新增，取代原来的「AI 答疑助手」浮标）──────────────
   ① 「答疑」钮：点宠物后出现在宠物**右下角**；② 对话框：贴在宠物**旁边**。
   位置都由 JS（syncPetTalkPos）按宠物实际矩形算 —— 宠物可拖拽、还要给左侧固定侧栏让位，
   写死 left/bottom 会跟宠物脱节；右边放不下就翻到宠物左边。
   四只宠物各一套：主题色 --pc（取自 PETS.color）、头像 emoji、招呼语与快捷问题（PET Talk），
   连气泡圆角都不同（下面 [data-pet] 那几条）。
   手机：改成贴底抽屉（!important 接管定位，JS 在手机上不写内联 left/bottom）。 */
.pet-ask-btn { position: fixed; z-index: 91; height: 24px; padding: 0 10px; border-radius: 9999px;
  display: inline-flex; align-items: center; gap: 5px; cursor: pointer; border: none; white-space: nowrap;
  background: var(--pc, #4A7FE0); color: #fff; font-size: 12px; font-weight: 600; letter-spacing: .02em;
  box-shadow: 0 5px 16px color-mix(in srgb, var(--pc, #4A7FE0) 38%, transparent), 0 1px 3px rgba(0,0,0,.08);
  transition: left .24s var(--ease-out-quart), bottom .24s var(--ease-out-quart), transform .2s var(--ease-out-quart); }
.pet-ask-btn:hover { transform: translateY(-2px) scale(1.03); }
.pet-ask-btn:active { transform: scale(.95); }
.pet-ask-btn.on { box-shadow: 0 0 0 3px color-mix(in srgb, var(--pc, #4A7FE0) 25%, transparent), 0 5px 16px rgba(41,37,36,.18); }
.pet-ask-btn .pa-star { font-size: 12px; opacity: .9; }
html.dark .pet-ask-btn { color: #1C1917; }

.pet-chat { position: fixed; z-index: 92; width: 340px; height: min(460px, calc(100vh - 130px));
  display: none; flex-direction: column; overflow: hidden; background: var(--c-white);
  border: 1px solid rgba(120,113,108,.12); border-radius: 18px;
  box-shadow: 0 18px 48px rgba(41,37,36,.16), 0 2px 8px rgba(0,0,0,.05);
  transition: left .24s var(--ease-out-quart), bottom .24s var(--ease-out-quart); }
.pet-chat.show { display: flex; animation: petChatIn .26s var(--ease-out-quart); }
@keyframes petChatIn { from { opacity: 0; transform: translateY(10px) scale(.97); } to { opacity: 1; transform: none; } }
.pc-head { display: flex; align-items: center; gap: 10px; padding: 11px 14px; flex-shrink: 0;
  background: linear-gradient(135deg, color-mix(in srgb, var(--pc, #4A7FE0) 18%, #fff), color-mix(in srgb, var(--pc, #4A7FE0) 5%, #fff));
  border-bottom: 1px solid rgba(120,113,108,.08); }
.pc-ava { width: 34px; height: 34px; border-radius: 50%; flex-shrink: 0; display: flex; align-items: center;
  justify-content: center; font-size: 19px; line-height: 1; background: var(--c-white);
  box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--pc, #4A7FE0) 32%, transparent); }
.pc-title { flex: 1; min-width: 0; }
.pc-title b { display: block; font-family: 'Noto Serif SC', serif; font-size: .88em; font-weight: 700; color: var(--c-text); }
.pc-title i { display: block; font-style: normal; font-size: .68em; color: var(--c-text-muted); margin-top: 1px; }
.pc-close { flex-shrink: 0; background: none; border: none; color: var(--c-text-muted); font-size: .95em;
  padding: 4px 8px; border-radius: 16px; cursor: pointer; transition: background .16s, color .16s; }
.pc-close:hover { background: #FBEDE8; color: var(--c-danger); }
.pc-msgs { flex: 1; overflow-y: auto; padding: 12px 12px 6px; display: flex; flex-direction: column; gap: 9px;
  overscroll-behavior: contain; }
.pc-msg { display: flex; gap: 7px; align-items: flex-end; }
.pc-msg.user { flex-direction: row-reverse; }
.pc-mini { width: 22px; height: 22px; border-radius: 50%; flex-shrink: 0; display: flex; align-items: center;
  justify-content: center; font-size: 12px; line-height: 1; background: color-mix(in srgb, var(--pc, #4A7FE0) 13%, #fff); }
.pc-msg.user .pc-mini { display: none; }
.pc-bub { max-width: 78%; padding: 8px 12px; font-size: .84em; line-height: 1.7; word-break: break-word;
  background: #F7F4EF; color: var(--c-text); border-radius: 14px 14px 14px 4px; }
.pc-msg.user .pc-bub { background: var(--pc, #4A7FE0); color: #fff; border-radius: 14px 14px 4px 14px; }
.pc-bub p { margin: 0 0 6px; }
.pc-bub p:last-child { margin-bottom: 0; }
.pc-bub code { padding: 1px 5px; border-radius: 5px; background: rgba(120,113,108,.1); font-size: .94em; }
.pc-thinking { color: var(--c-text-muted); font-style: italic; }
.pc-quick { display: flex; flex-wrap: wrap; gap: 6px; padding: 2px 12px 9px; flex-shrink: 0; }
.pc-chip { padding: 5px 11px; border-radius: 100px; border: none; cursor: pointer; white-space: nowrap;
  font-size: .72em; background: color-mix(in srgb, var(--pc, #4A7FE0) 10%, transparent);
  color: color-mix(in srgb, var(--pc, #4A7FE0) 78%, #292524); transition: background .16s; }
.pc-chip:hover { background: color-mix(in srgb, var(--pc, #4A7FE0) 19%, transparent); }
.pc-input { display: flex; gap: 8px; padding: 10px 12px; border-top: 1px solid rgba(120,113,108,.08); flex-shrink: 0; }
.pc-input input { flex: 1; min-width: 0; padding: 9px 13px; border-radius: 100px; font-size: .84em; outline: none;
  border: 1px solid rgba(120,113,108,.15); background: var(--c-white); color: var(--c-text); transition: border-color .16s; }
.pc-input input:focus { border-color: var(--pc, #4A7FE0); }
.pc-input button { padding: 8px 16px; border-radius: 100px; border: none; cursor: pointer; font-size: .82em;
  font-weight: 600; color: #fff; background: var(--pc, #4A7FE0); transition: opacity .16s; }
.pc-input button:disabled { opacity: .45; cursor: not-allowed; }
/* 四只宠物各自的"长相"：气泡圆角（配色走 --pc，头像走 PETS.emoji） */
.pet-chat[data-pet="dino"]   .pc-bub { border-radius: 15px 15px 15px 3px; }
.pet-chat[data-pet="rabbit"] .pc-bub { border-radius: 17px 17px 17px 6px; }
.pet-chat[data-pet="bear"]   .pc-bub { border-radius: 19px 19px 19px 9px; }
.pet-chat[data-pet="wolf"]   .pc-bub { border-radius: 9px 9px 9px 1px; }
.pet-chat[data-pet="wolf"]   .pc-head { background: linear-gradient(135deg, color-mix(in srgb, var(--pc, #6E7B8B) 24%, #fff), #fff); }
.pet-chat[data-pet="cat"] .pc-bub { border-radius: 16px 16px 16px 5px; }
.pet-chat[data-pet="cat"]   .pc-head { background: linear-gradient(135deg, color-mix(in srgb, var(--pc, #E08A3C) 22%, #fff), #fff); }
.pet-chat[data-pet="pig"] .pc-bub { border-radius: 18px 18px 18px 7px; }
.pet-chat[data-pet="pig"]   .pc-head { background: linear-gradient(135deg, color-mix(in srgb, var(--pc, #E4737F) 22%, #fff), #fff); }
html.dark .pet-chat { background: #2A2724; border-color: rgba(255,255,255,.1); }
html.dark .pc-bub { background: #332E2A; color: #F5F5F4; }
html.dark .pc-input input { background: #262220; border-color: rgba(255,255,255,.12); }
html.dark .pc-input input:focus { border-color: var(--pc, #4A7FE0); }
html.dark .pc-close:hover { background: rgba(166,61,42,.16); color: #E8B3A3; }
@media (max-width: 768px) {
  .pet-chat { left: 12px !important; right: 12px; bottom: 60px !important; width: auto; height: 55vh; }
}
html.force-phone .pet-chat { left: 12px !important; right: 12px; bottom: 60px !important; width: auto; height: 55vh; }
/* ── 选择宠物页（2026-09-23 新增；同日重做视觉）──
   设计语言跟站内其它栏目对齐：奶油底 + 顶部 3px 渐变条（首页卡片就是这个语汇）+ 柔和阴影，
   另外给每只宠物一个**自己的主题色**（--pa），用于顶部色条、聚光底、选中环和动作标签，
   这样四张卡一眼能区分、又不至于花。 */
.pet-page { max-width: 980px; }
/* 标题区整体左对齐 —— 跟站内其它栏目页（h2 带左侧色条）一致；
   混着"徽章居中、h2 靠左"会很乱。 */
.pet-head { margin: 2px 0 28px; }
.pet-head-badge { display: inline-flex; align-items: center; gap: 6px; padding: 4px 14px; border-radius: 100px;
  background: #E9E0D4; color: #5C4033; font-size: .72em; font-weight: 600;
  letter-spacing: .14em; border: 1px solid rgba(90,110,69,.12); margin-bottom: 12px; }
.pet-head h2 { font-family: 'Noto Serif SC', serif; font-size: 1.7em; font-weight: 700; color: #5C4033;
  letter-spacing: .04em; margin: 0 0 8px; }
.pet-head-sub { color: var(--c-text-secondary); font-size: .84em; letter-spacing: .02em; line-height: 1.9; margin: 0; }
/* 体验规则那行：跟介绍语同段但视觉上分层（2026-10-11） */
.pet-rule-note { display: block; margin-top: 2px; font-size: .94em; color: var(--c-text-muted); }
.pet-rule-note b { color: #B45309; font-weight: 700; }
html.dark .pet-rule-note b { color: #E7CE96; }
html.dark .pet-head h2 { color: #F5F5F4; }
html.dark .pet-head-badge { background: #342C26; color: #E9E0D4; border-color: rgba(163,185,140,.2); }

/* 桌面 5 列（2026-10-31：宠物加到 9 只，5+4 比 6+3 匀；末尾「定制宠物」通栏卡另占一行） */
.pet-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 14px; margin: 0; }
.pet-card { position: relative; display: flex; flex-direction: column; align-items: center; gap: 11px;
  padding: 22px 16px 18px; border-radius: var(--radius-lg); cursor: pointer; text-align: center; overflow: hidden;
  background: #FFFCF8;
  border: 1px solid rgba(120,113,108,.10);
  box-shadow: 0 1px 3px rgba(0,0,0,.04), 0 4px 12px rgba(0,0,0,.04);
  transition: transform .35s cubic-bezier(.25,.8,.25,1), box-shadow .35s, border-color .35s; }
/* 顶部色条：和首页卡片同一套语汇 */
.pet-card::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px;
  background: linear-gradient(90deg, transparent, var(--pa, #78716C) 22%, var(--pa, #78716C) 78%, transparent);
  opacity: .55; transition: opacity .35s, height .35s; }
.pet-card:hover { transform: translateY(-6px); border-color: color-mix(in srgb, var(--pa, #78716C) 45%, transparent);
  box-shadow: 0 14px 34px rgba(0,0,0,.10), 0 3px 8px rgba(0,0,0,.05); }
.pet-card:hover::before { opacity: 1; height: 4px; }
/* 聚光底：把抠好的透明立绘放在一圈很淡的主题色光晕上，白底立绘也不会显得"贴"在卡上 */
.pet-stage { position: relative; width: 100%; aspect-ratio: 1 / 1; max-width: 148px;
  display: flex; align-items: flex-end; justify-content: center; border-radius: 50%;
  background: radial-gradient(circle at 50% 62%, color-mix(in srgb, var(--pa, #78716C) 16%, transparent) 0%,
              color-mix(in srgb, var(--pa, #78716C) 6%, transparent) 48%, transparent 72%);
  transition: transform .35s cubic-bezier(.25,.8,.25,1); }
.pet-card:hover .pet-stage { transform: scale(1.04); }
.pet-stage img { width: 88%; height: 88%; object-fit: contain; display: block;
  filter: drop-shadow(0 6px 10px rgba(41,37,36,.10)); }
.pet-name { font-family: 'Noto Serif SC', serif; font-size: 1.02em; font-weight: 700; color: var(--c-text);
  letter-spacing: .04em; }
/* 副标：中文小名 · 物种（大字英文名在 .pet-name） */
.pet-nick { font-size: .78em; color: var(--c-text-muted); letter-spacing: .04em; margin-top: -5px; }
html.dark .pet-nick { color: #A8A29E; }
.pet-chips { display: flex; flex-wrap: wrap; gap: 5px; justify-content: center; }
.pet-chip { padding: 2px 9px; border-radius: 100px; font-size: .68em; letter-spacing: .02em;
  background: color-mix(in srgb, var(--pa, #78716C) 11%, transparent);
  color: color-mix(in srgb, var(--pa, #78716C) 82%, #292524); white-space: nowrap; }
.pet-chip.muted { background: rgba(120,113,108,.09); color: var(--c-text-muted); }
/* 选中态：主题色描边环 + 左上角"当前"飘带 + 右上角勾 */
.pet-card.on { border-color: color-mix(in srgb, var(--pa, #78716C) 55%, transparent);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--pa, #78716C) 22%, transparent), 0 10px 28px rgba(0,0,0,.07); }
.pet-card.on::before { opacity: 1; height: 4px; }
.pet-card.on .pet-stage { transform: scale(1.02); }
.pet-tick { position: absolute; top: 12px; right: 12px; width: 24px; height: 24px; border-radius: 50%;
  display: none; align-items: center; justify-content: center; color: #fff; font-size: 12px; line-height: 1;
  background: var(--pa, #78716C); box-shadow: 0 2px 8px color-mix(in srgb, var(--pa, #78716C) 45%, transparent); }
.pet-card.on .pet-tick { display: flex; animation: petTick .32s cubic-bezier(.34,1.56,.64,1); }
@keyframes petTick { 0% { transform: scale(.2); opacity: 0; } 100% { transform: scale(1); opacity: 1; } }
.pet-flag { position: absolute; top: 0; left: 0; padding: 4px 11px 5px; border-radius: 0 0 12px 0;
  font-size: .66em; font-weight: 600; letter-spacing: .1em; color: #fff; display: none;
  background: var(--pa, #78716C); }
.pet-card.on .pet-flag { display: block; }
html.dark .pet-card { background: #24211E; border-color: rgba(255,255,255,.08); }
/* 我的积分数（钱包胶囊）：跟首页"学习排行榜"卡同一套暖金色 —— 解锁宠物要花分，得让人看得见余额 */
/* 「我的积分」与「邀请奖励」并排一行（2026-09-24）：间距挪到外层 .pet-metabar 上 */
.pet-metabar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 12px; }
.pet-metabar .pet-wallet { margin-top: 0; }
/* 宠物页的「充值积分」入口（2026-10-31）：和积分页那颗同一件事，这里做成一枚实心胶囊，
   紧挨着余额 —— 用户看到"积分不够"时第一个会找的就是充值。 */
.pet-buy-points { padding: 5px 15px; border-radius: 100px; border: 1px solid rgba(138,106,47,.5);
  background: #8A6A2F; color: #FFFCF8; font: inherit; font-size: .78em; font-weight: 600;
  letter-spacing: .02em; white-space: nowrap; cursor: pointer;
  transition: background-color .2s var(--ease-out-quart), border-color .2s; }
.pet-buy-points:hover { background: #6B4E32; border-color: #6B4E32; }
.pet-buy-points:active { transform: translateY(1px); }
html.dark .pet-buy-points { background: #C9A227; border-color: #C9A227; color: #1C1917; }
html.dark .pet-buy-points:hover { background: #DDB63A; border-color: #DDB63A; }
/* 邀请奖励：样式对齐个人信息里那张邀请码卡（虚线边 + 米底），一眼能认成「同一件事」 */
.pet-invite { display: inline-block; padding: 5px 14px; border-radius: 100px;
  border: 1px dashed rgba(92,64,51,.35); background: #F5EFE4; color: #5C4033;
  font-size: .78em; font-weight: 600; letter-spacing: .02em; white-space: nowrap; }
.pet-invite b { color: #5C4033; font-weight: 700; }
.pet-invite button { background: none; border: none; margin-left: 6px; padding: 0; font: inherit; font-weight: 600;
  color: #5C4033; cursor: pointer; text-decoration: underline; text-underline-offset: 3px; }
.pet-invite button:hover { color: #4A3229; }
html.dark .pet-invite { background: #2A2419; border-color: rgba(242,192,107,.35); color: #B9A899; }
html.dark .pet-invite b, html.dark .pet-invite button { color: #D4A373; }
.pet-wallet { display: inline-flex; align-items: baseline; gap: 8px; margin-top: 12px; padding: 5px 14px;
  border-radius: 100px; background: #E9E0D4; color: #5C4033;
  font-size: .78em; font-weight: 600; letter-spacing: .02em; }
.pet-wallet b { font-family: 'Noto Serif SC', serif; font-size: 1.25em; font-variant-numeric: tabular-nums; }
.pet-wallet span { font-weight: 400; opacity: .8; }
html.dark .pet-wallet { background: #342C26; color: #D4A373; }

/* 锁住的宠物卡：立绘与文字压暗，盖一层磨砂，中间一颗「N 积分解锁」胶囊。
   胶囊本身就是"去解锁"的按钮语义 —— 点整张卡（= 点胶囊）就走 buyPet。 */
.pet-card.locked .pet-stage img { filter: grayscale(.6) opacity(.45); }
.pet-card.locked .pet-name, .pet-card.locked .pet-nick, .pet-card.locked .pet-chips { opacity: .45; }
/* 锁着的卡：英文名会被锁标/价签压掉一半（390 竖排尤其明显），直接不显示；中文名仍在，浮层里也有英文 */
.pet-card.locked .pet-name { visibility: hidden; }
.pet-card.locked:hover { transform: translateY(-6px); }
.pet-lock { position: absolute; inset: 0; display: none; flex-direction: column; align-items: center;
  justify-content: center; gap: 8px; background: rgba(255,253,248,.5); border-radius: inherit; }
.pet-card.locked .pet-lock { display: flex; }
.pet-lock b { font-size: 1.6em; line-height: 1; filter: drop-shadow(0 2px 4px rgba(41,37,36,.18)); }
.pet-lock span { padding: 5px 13px 6px; border-radius: 100px; font-size: .74em; font-weight: 600;
  color: #5C4033; background: #E9E0D4;
  box-shadow: 0 2px 8px rgba(90,110,69,.22); white-space: nowrap; }
html.dark .pet-lock { background: rgba(38,35,31,.55); }
html.dark .pet-lock span { color: #2E2620; }
/* 现金直购价签（2026-10-31 用户选定「奶油票券」版）：奶油实底 + 一道虚线把价格和「现金直购」分隔开。
   高度刚好盖住卡片上的英文名 —— 早先虚线浅底那版会让底下的字透出来，看着脏。 */
.pet-lock .pet-price { display: inline-flex; flex-direction: column; align-items: center; gap: 0;
  padding: 9px 20px 10px; border-radius: 12px; font-size: 1em; white-space: nowrap;
  margin-bottom: 16px;   /* 往上让一点：正好压住宠物图，别切到卡片上的英文名 */
  background: #FFFCF8; border: 1px solid rgba(138,106,47,.32);
  box-shadow: 0 12px 24px rgba(90,64,51,.16), inset 0 1px 0 rgba(255,255,255,.6);
  transition: transform .2s var(--ease-out-quart); }
.pet-lock .pet-price b { font-family: 'Noto Serif SC', serif; font-size: 1.5em; line-height: 1.05;
  font-weight: 700; color: #5C4033; font-variant-numeric: tabular-nums; filter: none; }
.pet-lock .pet-price i { font-style: normal; font-size: .68em; font-weight: 600; letter-spacing: .1em;
  color: #8A6A2F; width: 100%; text-align: center; padding-top: 6px; margin-top: 6px;
  border-top: 1px dashed rgba(138,106,47,.45); }
.pet-card.locked:hover .pet-lock .pet-price { transform: translateY(-2px); }
html.dark .pet-lock .pet-price { background: #2E2A24; border-color: rgba(199,169,104,.42);
  box-shadow: 0 12px 24px rgba(0,0,0,.4), inset 0 1px 0 rgba(255,255,255,.06); }
html.dark .pet-lock .pet-price b { color: #F0E2C4; }
html.dark .pet-lock .pet-price i { color: #C7A968; border-top-color: rgba(199,169,104,.4); }
html.dark .pet-card:hover { border-color: color-mix(in srgb, var(--pa, #78716C) 55%, transparent); }
html.dark .pet-name { color: #F5F5F4; }
html.dark .pet-chip { background: color-mix(in srgb, var(--pa, #78716C) 22%, transparent);
  color: color-mix(in srgb, var(--pa, #78716C) 40%, #F5F5F4); }
html.dark .pet-chip.muted { background: rgba(255,255,255,.07); color: #A8A29E; }

/* 底部"当前宠物"条：把选中结果和同步说明收在一处，不用一行小字挂在下面 */
.pet-current { display: flex; align-items: center; gap: 16px; max-width: 980px; margin: 30px auto 0;
  padding: 16px 22px; border-radius: var(--radius-lg); background: var(--c-bg-card);
  border: 1px solid var(--c-border); box-shadow: var(--shadow-sm); }
.pet-current img { width: 62px; height: 62px; object-fit: contain; flex-shrink: 0;
  filter: drop-shadow(0 4px 8px rgba(41,37,36,.10)); }
.pet-current-main { flex: 1; min-width: 0; }
.pet-current-name { font-family: 'Noto Serif SC', serif; font-size: .98em; font-weight: 700; color: var(--c-text);
  display: flex; align-items: center; gap: 8px; }
.pet-current-name em { font-style: normal; font-size: .78em; font-weight: 600; color: var(--c-text-muted); letter-spacing: .03em; }
html.dark .pet-current-name em { color: #A8A29E; }
.pet-current-name i { font-style: normal; font-size: .68em; font-weight: 600; letter-spacing: .06em;
  padding: 2px 8px; border-radius: 100px; background: rgba(79,107,54,.12); color: var(--c-success); }
.pet-current-desc { font-size: .78em; color: var(--c-text-muted); margin-top: 4px; line-height: 1.8; }
html.dark .pet-current { background: #26231F; border-color: rgba(255,255,255,.08); }
html.dark .pet-current-name { color: #F5F5F4; }
/* 进场：轻微上浮 + 逐个延迟。用 `backwards` 而不是 `both` ——
   both 会让 keyframes 的 `transform: none` 在动画结束后继续生效，把 :hover 的抬起盖掉。 */
@keyframes petIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
.pet-card { animation: petIn .42s cubic-bezier(.16,1,.3,1) backwards; }
.pet-card:nth-child(2) { animation-delay: .06s; }
.pet-card:nth-child(3) { animation-delay: .12s; }
.pet-card:nth-child(4) { animation-delay: .18s; }
.pet-current { animation: petIn .46s cubic-bezier(.16,1,.3,1) .2s backwards; }
@media (prefers-reduced-motion: reduce) {
  .pet-card, .pet-current { animation: none; }
}

@media (max-width: 780px) {
  .pet-grid { grid-template-columns: repeat(2, 1fr); gap: 16px; }
  .pet-head { margin-bottom: 22px; }
  .pet-current { flex-wrap: wrap; gap: 12px; padding: 14px 16px; }
}
@media (max-width: 520px) {
  .pet-grid { gap: 12px; }
  .pet-card { padding: 16px 12px 14px; gap: 8px; }
  .pet-name { font-size: .92em; }
  .pet-chip { font-size: .64em; padding: 2px 7px; }
  .pet-tick { width: 20px; height: 20px; top: 9px; right: 9px; font-size: 11px; }
  .pet-head h2 { font-size: 1.4em; }
  .pet-current img { width: 48px; height: 48px; }
}

/* ── 「定制宠物」通栏卡（2026-10-11）：排在 4 张宠物卡下方、占满整行 ──
   ⚠️ 它**不能**带 .pet-card 类：renderPetGrid/syncPetLocks 按 .pet-card 遍历，
   混进去会被当成第 5 只宠物去判 data-pet、画解锁锁。样式独立走 .pet-cust。 */
.pet-cust { grid-column: 1 / -1; display: flex; align-items: center; gap: 16px; width: 100%;
  margin: 0; padding: 15px 20px; text-align: left; font: inherit; cursor: pointer;
  border: 1px solid rgba(138,106,47,.26); border-radius: var(--radius-lg);
  background: linear-gradient(100deg, rgba(199,169,104,.14), #FFFCF8 60%);
  box-shadow: 0 1px 2px rgba(92,64,51,.05), inset 0 1px 0 rgba(255,255,255,.75);
  animation: petIn .42s cubic-bezier(.16,1,.3,1) .24s backwards;
  transition: transform .25s var(--ease-out-quart), box-shadow .25s var(--ease-out-quart), border-color .25s; }
.pet-cust:hover { transform: translateY(-2px); border-color: rgba(138,106,47,.42);
  box-shadow: 0 6px 18px rgba(92,64,51,.1), inset 0 1px 0 rgba(255,255,255,.75); }
.pet-cust:focus-visible { outline: 2px solid var(--c-accent); outline-offset: 3px; }
.pet-cust-ico { flex: none; width: 56px; height: 56px; border-radius: 18px; display: flex; align-items: center; justify-content: center;
  color: #7A5C22; background: linear-gradient(140deg, #E4D0A0, #C7A968);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.5), 0 2px 6px rgba(138,106,47,.2); }
.pet-cust-ico svg { width: 26px; height: 26px; }
.pet-cust:hover .pet-cust-ico svg { animation: petCustSpark .5s var(--ease-out-quart); }
@keyframes petCustSpark { 0% { transform: scale(1); } 55% { transform: scale(1.12); } 100% { transform: scale(1); } }
.pet-cust-main { flex: 1; min-width: 0; }
.pet-cust-main b { display: block; font-family: 'Noto Serif SC', serif; font-size: 1.02em; font-weight: 700; color: var(--c-text); }
.pet-cust-main span { display: block; margin-top: 3px; font-size: .78em; line-height: 1.7; color: var(--c-text-muted); }
/* 按钮走「浅茶金底 + 细描边 + 茶金字」（原来实底橙 #A8630A 太促销），hover 才压深一档 */
.pet-cust-go { flex: none; display: inline-flex; align-items: center; gap: 4px; padding: 8px 15px; border-radius: 100px;
  font-size: .78em; font-weight: 600; white-space: nowrap; color: #7A5C22;
  background: rgba(199,169,104,.2); border: 1px solid rgba(138,106,47,.3);
  transition: background-color .2s var(--ease-out-quart), border-color .2s var(--ease-out-quart), color .2s; }
.pet-cust-go svg { width: 12px; height: 12px; transition: transform .2s var(--ease-out-quart); }
.pet-cust:hover .pet-cust-go { background: #7A5C22; border-color: #7A5C22; color: #FFFCF8; }
.pet-cust:hover .pet-cust-go svg { transform: translateX(2px); }
html.dark .pet-cust { border-color: rgba(199,169,104,.26);
  background: linear-gradient(100deg, rgba(199,169,104,.12), rgba(41,37,36,.94) 60%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.04); }
html.dark .pet-cust-ico { color: #2A2418; background: linear-gradient(140deg, #E0C68C, #C7A968);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.12), 0 2px 8px rgba(0,0,0,.35); }
html.dark .pet-cust-go { color: #E7CE96; background: rgba(199,169,104,.14); border-color: rgba(199,169,104,.34); }
html.dark .pet-cust:hover .pet-cust-go { color: #2A2418; background: #E0C68C; border-color: #E0C68C; }
/* 窄屏（平板/手机）：图标与按钮一行，文案换行占满整宽 —— 否则 390px 下文案被挤成三行、右缘参差 */
@media (max-width: 780px) {
  .pet-cust { flex-wrap: wrap; gap: 12px; padding: 14px 16px; }
  .pet-cust-main { flex: 1 1 100%; order: 3; margin-top: -2px; }
  .pet-cust-main span { font-size: .76em; line-height: 1.65; }
  .pet-cust-go { margin-left: auto; }
}

/* 定制宠物：联系管理员弹层（外壳复用 .lb-rule-overlay 那套皮肤）。
   ⚠️ 开关必须用 .show 而不是 `.hidden`：本元素是 ID 选择器 + display:flex，
   特异性高过 `.hidden{display:none!important}`，用 hidden 会变成**一进页面就常驻显示**。 */
/* 免费体验浮层与「定制宠物」浮层共用外壳（2026-10-11） */
#petContactOverlay, #petTrialOverlay { position: fixed; inset: 0; z-index: 700; display: none; align-items: center; justify-content: center;
  padding: 16px; background: rgba(41,37,36,.55); backdrop-filter: blur(4px); }
#petContactOverlay.show, #petTrialOverlay.show { display: flex; }
.pet-contact-card { position: relative; width: min(400px, 92vw); padding: 26px 26px 22px; text-align: center;
  background: linear-gradient(180deg, #FDF9F1, var(--c-white) 46%); border-radius: 22px;
  border: 1px solid rgba(138,106,47,.18);
  box-shadow: 0 18px 46px rgba(92,64,51,.2), 0 2px 6px rgba(92,64,51,.06);
  animation: donateIn .3s cubic-bezier(.34,1.56,.64,1); }
html.dark .pet-contact-card { background: linear-gradient(180deg, #2E2A24, #292524 46%); border-color: rgba(199,169,104,.2); }
.pet-contact-close { position: absolute; top: 12px; right: 12px; width: 28px; height: 28px; display: flex; align-items: center; justify-content: center;
  padding: 0; border: none; border-radius: 50%; background: none; font-size: 1.1em; line-height: 1; color: var(--c-text-muted); cursor: pointer;
  transition: background-color .18s var(--ease-out-quart), color .18s; }
.pet-contact-close:hover { background: rgba(120,113,108,.12); color: var(--c-text); }
.pet-contact-close:focus-visible { outline: 2px solid var(--c-accent); outline-offset: 1px; }
.pet-contact-ico { width: 52px; height: 52px; margin: 4px auto 14px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
  color: #7A5C22; background: linear-gradient(140deg, #E4D0A0, #C7A968);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.5), 0 3px 10px rgba(138,106,47,.22); }
.pet-contact-ico svg { width: 25px; height: 25px; }
.pet-contact-card h3 { font-family: 'Noto Serif SC', serif; font-size: 1.1em; font-weight: 700; color: #5C4033; margin: 0 0 7px; }
html.dark .pet-contact-card h3 { color: var(--c-text); }
.pet-contact-card > p { margin: 0 auto 15px; max-width: 18em; font-size: .82em; line-height: 1.7; color: var(--c-text-secondary); }
/* QQ 号单独一块「茶金浅底」小卡：数字看得清，又不靠橙色抢眼 */
.pet-contact-qq { padding: 13px 14px 15px; border-radius: 16px; border: 1px solid rgba(138,106,47,.18);
  background: rgba(199,169,104,.11); font-size: .78em; color: var(--c-text-muted); letter-spacing: .02em; }
.pet-contact-qq b { display: block; margin-top: 5px; font-family: 'Noto Serif SC', serif; font-size: 1.72em;
  letter-spacing: .05em; color: #7A5C22; font-variant-numeric: tabular-nums; }
html.dark .pet-contact-qq { border-color: rgba(199,169,104,.2); background: rgba(199,169,104,.09); }
html.dark .pet-contact-qq b { color: #E7CE96; }
/* 两个动作是"二选一"：左=先体验（主），右=直接拿下（次）。
   2026-10-31 重做：原来是一行 flex + 长文案，左键在 320px 卡片里折成两行、两块高度不齐。
   现在用 grid 等分（自动等高）+ 单行短文案 + "名额"移到上面的 meta 行。 */
.pet-contact-btns { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 14px; }
.pet-contact-btns > button { display: inline-flex; align-items: center; justify-content: center;
  min-height: 46px; padding: 10px 12px; border-radius: 14px; font: inherit; font-size: .86em;
  font-weight: 600; letter-spacing: .01em; line-height: 1.2; white-space: nowrap; cursor: pointer;
  transition: background-color .18s var(--ease-out-quart), border-color .18s, box-shadow .2s, transform .18s; }
.pet-contact-copy { color: #FFFCF8; border: 1px solid #6E5322;
  background: linear-gradient(180deg, #8A6A2F, #6E5322);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.14), 0 2px 0 rgba(92,64,51,.16), 0 6px 16px rgba(122,92,34,.18); }
.pet-contact-copy:hover { background: linear-gradient(180deg, #97763A, #765A26); border-color: #765A26;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.16), 0 2px 0 rgba(92,64,51,.18), 0 8px 20px rgba(122,92,34,.22); }
.pet-contact-copy:active { transform: translateY(1px); }
.pet-contact-copy:focus-visible { outline: 2px solid var(--c-accent); outline-offset: 2px; }
/* 次操作用站内那套「茶金浅底 + 虚线边」（和邀请码胶囊同一族），不用纯白描边 */
.pet-contact-done { color: #5C4033; background: #F5EFE4; border: 1px dashed rgba(138,106,47,.42); }
.pet-contact-done b { font-family: 'Noto Serif SC', serif; font-size: 1.16em; font-weight: 700;
  color: #7A5C22; margin-right: 3px; font-variant-numeric: tabular-nums; }
.pet-contact-done:hover { background: #EFE4D2; border-color: rgba(138,106,47,.62); }
.pet-contact-done:active { transform: translateY(1px); }
.pet-contact-done:focus-visible { outline: 2px solid var(--c-accent); outline-offset: 2px; }
html.dark .pet-contact-copy { color: #1C1917; border-color: #C9A227;
  background: linear-gradient(180deg, #DDB63A, #C9A227); }
html.dark .pet-contact-copy:hover { background: linear-gradient(180deg, #E6C24F, #D3AC32); border-color: #D3AC32; }
html.dark .pet-contact-done { color: #E7CE96; background: #2E2A24; border-color: rgba(199,169,104,.42); }
html.dark .pet-contact-done b { color: #E7CE96; }
html.dark .pet-contact-done:hover { background: #363028; border-color: rgba(199,169,104,.62); }
/* 手机：两列会更挤，改成上下两行；主操作永远在上 */
@media (max-width: 420px) {
  .pet-contact-btns { grid-template-columns: 1fr; gap: 8px; }
  .pet-contact-btns > button { min-height: 48px; font-size: .9em; }
}
/* ── 免费体验浮层（2026-10-11）：宠物图 + 说明 + 卡片上的「体验中」倒计时角标 ── */
.pet-trial-art { display: block; width: 112px; height: 112px; margin: 2px auto 10px; }
.pet-trial-art img { width: 100%; height: 100%; object-fit: contain; }
.pet-trial-card h3 { font-size: 1.22em; margin-bottom: 4px; }
.pet-trial-meta { margin: 0 auto 2px; font-size: .76em; line-height: 1.7; color: var(--c-text-muted); }
.pet-trial-meta b { color: #B45309; font-weight: 700; }
html.dark .pet-trial-meta b { color: #E7CE96; }
.pet-contact-copy[disabled] { opacity: .55; cursor: default; }
.pet-trial-tag { position: absolute; left: 9px; top: 9px; z-index: 3; display: none;
  padding: 3px 9px; border-radius: 9999px; background: #E08A3C; color: #fff;
  font-size: .68em; font-weight: 700; letter-spacing: .02em;
  box-shadow: 0 3px 10px rgba(224,138,60,.35); }
html.dark .pet-trial-tag { color: #2A2418; }
/* 手机：让开底部 56px 的 .phone-tab-bar，并整体缩小 */
@media (max-width: 768px) {
  .dino-pet { --dino-size: 98px; left: 12px; bottom: 68px; }
  .dino-pet-restore { left: 12px; bottom: 68px; }
  .dino-pet-bubble { max-width: 168px; font-size: .78em; }
}
html.force-phone .dino-pet { --dino-size: 92px; left: 12px; bottom: 68px; }
html.force-phone .dino-pet-restore { left: 12px; bottom: 68px; }
html.force-tablet .dino-pet { --dino-size: 108px; }
@media (prefers-reduced-motion: reduce) {
  .dino-pet-stage, .dino-pet.acting .dino-pet-stage { animation: none !important; }
}
/* ── 三只新宠物（2026-10-31 从同事版移植：奶虫糯糯 / 水豚噜噜 / 布偶猫臭臭）──────
   只搬了它们实际用到的那几条：换色交叉淡入、朝向翻转、蓄力跳、设置面板；换装配件那套没搬。 */
/* 换衣服：只有换色那一下给两层加过渡做交叉淡入，平时仍然硬切（逐帧播放不能有过渡） */
.dino-pet.nono-fade .dino-pet-strip { transition: opacity .24s ease; }
/* 朝向：素材本身是"面朝右"的，选「左」就整只水平翻转（连伸缩的左右方向一起翻）。
   ⚠️ 不能直接给 img 写 transform 类 —— place() 会用内联 transform 摆帧，把类覆盖掉；
   所以翻转走 CSS 变量，由 place() 拼进内联 transform 里。 */
.dino-pet.face-left { --pet-face: -1; }
/* 跳动：整体上移 + 起跳拉伸 / 落地压扁，支点仍在脚底（88%），像从地面弹起而不是整张图平移。
   ⚠️ 这条必须写在 `.dino-pet.acting .dino-pet-stage{animation:none}` 之后，否则会被它压掉。
   高度/时长用 CSS 变量 —— 长按蓄力时由 JS 写 --hop-h / --hop-ms，蓄得越久跳得越高。 */
.dino-pet.act-hop   .dino-pet-stage { animation: petHop var(--hop-ms, .95s) cubic-bezier(.3,.8,.4,1) 1; will-change: transform; }
/* 顶点只出现**一次**（以前两个关键帧都是最高点，等于在空中"挂"了 18% 的时长） */
@keyframes petHop {
  0%   { transform: translateY(0)    scaleY(1)    scaleX(1); }
  24%  { transform: translateY(var(--hop-h, -20%)) scaleY(1.06) scaleX(.97);
         animation-timing-function: cubic-bezier(.45,0,.8,.45); }   /* 下落段加速 */
  48%  { transform: translateY(0)    scaleY(.90)  scaleX(1.06); }
  60%  { transform: translateY(calc(var(--hop-h, -20%) * .28)) scaleY(1.03) scaleX(.98); }
  74%  { transform: translateY(0)    scaleY(.97)  scaleX(1.02); }
  88%  { transform: translateY(-2%)  scaleY(1.01); }
  100% { transform: translateY(0)    scaleY(1); }
}
/* 长按蓄力：按住时越蹲越低、越横，松手才起跳。用 linear（匀速）而不是 ease：
   1.2s 的贝塞尔前 30% 就把蹲伏做完了，看着"顿一下"；0.9s 匀速正好对上蓄力 900ms 的满格。 */
.dino-pet.charging .dino-pet-stage { animation: petCharge .9s linear forwards; will-change: transform; }
@keyframes petCharge {
  0%   { transform: translateY(0)   scaleY(1)    scaleX(1)    rotate(0); }
  100% { transform: translateY(7%)  scaleY(.82)  scaleX(1.18) rotate(1.2deg); }
}
/* 糯糯：8 套衣服，气泡底色/描边由 CSS 从 --pc（JS 按当前颜色写的内联变量）推导，
   浅色/深色各一套 —— 不逐色写 8 条规则，也不会被内联值盖掉暗色。 */
.dino-pet[data-pet="nono"] { --bub: color-mix(in srgb, var(--pc, #F2C230) 9%, #FFFCF8);
                            --bub-edge: color-mix(in srgb, var(--pc, #F2C230) 62%, #FFFFFF); }
html.dark .dino-pet[data-pet="nono"] { --bub: color-mix(in srgb, var(--pc, #F2C230) 16%, #26221F);
                                      --bub-edge: color-mix(in srgb, var(--pc, #F2C230) 52%, #1C1917); }
.dino-pet[data-pet="nono"] .dino-pet-bubble b { color: var(--pc, #C99A18); }
/* 糯糯的台词偏长：气泡按内容撑开（上限仍是 220）。不写的话会被 122px 容器压到 min-width 104，
   一句话折成四五行的窄条。只对糯糯生效，不动其它宠物的观感。 */
.dino-pet[data-pet="nono"] .dino-pet-bubble { width: max-content; }
/* 暗色下 --pc 直接当文字色偏暗（比如苔绿 #5FA83F），往白色提一档保证可读 */
html.dark .dino-pet[data-pet="nono"] .dino-pet-bubble b { color: color-mix(in srgb, var(--pc, #F2C230) 72%, #FFFFFF); }
/* 糯糯的立绘比较窄，卡片两侧容易显得空：聚光调亮一档、范围放大 */
.pet-card[data-pet="nono"] .pet-stage {
  background: radial-gradient(circle at 50% 60%,
              color-mix(in srgb, var(--pa, #E87722) 26%, transparent) 0%,
              color-mix(in srgb, var(--pa, #E87722) 11%, transparent) 50%, transparent 76%); }
.pet-card[data-pet="nono"] .pet-stage img { width: 94%; height: 94%; }
/* 页面里的糯糯图一律朝左（朝向开关只管左下角那只浮动宠物）。
   ⚠️ 只翻糯糯：老六只的卡片原图本来就是朝右的，整排翻会改掉它们的观感。 */
.pet-card[data-pet="nono"] .pet-stage img,
.pet-current img[src*="/nono"],
#petSetArt,
.pet-dot-art { transform: scaleX(-1); }
/* 「使用中」那条的「设置」按钮（只有带设置面板的宠物有） */
.pet-current-set { flex: none; margin-left: auto; padding: 7px 15px; border: 1px solid rgba(138,106,47,.32);
  border-radius: 999px; background: #FFFCF8; font: inherit; font-size: .78em; color: #6B4E32; cursor: pointer;
  transition: background-color .2s var(--ease-out-quart), border-color .2s; }
.pet-current-set:hover { background: #F6EEE2; border-color: rgba(138,106,47,.52); }
html.dark .pet-current-set { background: #2E2A24; border-color: rgba(199,169,104,.32); color: #E7CE96; }
html.dark .pet-current-set:hover { background: #363028; }
/* ── 宠物设置面板 ──
   桌面：居中卡片；手机：底部抽屉（同答疑面板的形态）。只对带 prefs 的宠物出现入口。 */
#petSettingsOverlay { position: fixed; inset: 0; z-index: 750; display: none; align-items: center; justify-content: center;
  background: rgba(28,25,23,.30); -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px); }
#petSettingsOverlay.show { display: flex; }
.pet-set-card { width: min(400px, 92vw); max-height: 86vh; overflow: auto; padding: 18px 18px 14px;
  background: linear-gradient(180deg, #FFFCF8, #FAF5EE); border: 1px solid rgba(138,106,47,.18);
  border-radius: 20px; box-shadow: 0 24px 60px rgba(41,37,36,.24); }
html.dark .pet-set-card { background: linear-gradient(180deg, #2E2A24, #292524); border-color: rgba(199,169,104,.22); }
.pet-set-head { display: flex; align-items: center; gap: 10px; padding-bottom: 12px; border-bottom: 1px dashed rgba(120,113,108,.18); }
.pet-set-head img { width: 38px; height: 38px; object-fit: contain; flex: none; }
.pet-set-name b { display: block; font-family: 'Noto Serif SC', serif; font-size: 1.02em; color: var(--c-text); }
.pet-set-name i { display: block; font-style: normal; font-size: .72em; color: var(--c-text-muted); margin-top: 2px; }
.pet-set-close { margin-left: auto; width: 28px; height: 28px; display: flex; align-items: center; justify-content: center;
  border: none; background: none; border-radius: 50%; color: var(--c-text-muted); font-size: 15px; cursor: pointer; }
.pet-set-close:hover { background: rgba(120,113,108,.12); color: var(--c-text); }
.pet-set-sec { padding: 12px 0; border-bottom: 1px dashed rgba(120,113,108,.18); }
.pet-set-sec:last-of-type { border-bottom: none; }
.pet-set-row { display: flex; align-items: center; gap: 10px; }
.pet-set-t { flex: 1; min-width: 0; font-size: .86em; color: var(--c-text); line-height: 1.4; }
.pet-set-t small { display: block; font-size: .72em; color: var(--c-text-muted); margin-top: 2px; }
.pet-sw { width: 38px; height: 22px; flex: none; padding: 0; border: none; border-radius: 999px; background: #D6D3D1;
  position: relative; cursor: pointer; transition: background-color .2s; }
.pet-sw span { position: absolute; top: 2px; left: 2px; width: 18px; height: 18px; border-radius: 50%; background: #fff;
  box-shadow: 0 1px 3px rgba(0,0,0,.22); transition: transform .2s var(--ease-out-quart); }
.pet-sw[aria-pressed="true"] { background: #8A6A2F; }
.pet-sw[aria-pressed="true"] span { transform: translateX(16px); }
.pet-sw[disabled] { opacity: .45; cursor: default; }
html.dark .pet-sw { background: rgba(255,255,255,.18); }
html.dark .pet-sw[aria-pressed="true"] { background: #C9A227; }
html.dark .pet-sw span { background: #F5F5F4; }
.pet-set-slider { display: flex; align-items: center; gap: 10px; margin-top: 9px; font-size: .76em; color: var(--c-text-muted); }
.pet-set-slider input { flex: 1; accent-color: #8A6A2F; }
html.dark .pet-set-slider input { accent-color: #C9A227; }
.pet-set-slider b { font-variant-numeric: tabular-nums; color: var(--c-text); min-width: 34px; text-align: right; }
.pet-set-sec.disabled .pet-set-slider { opacity: .45; pointer-events: none; }
.pet-set-colors { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 11px; }
.pet-set-dot { width: 26px; height: 26px; padding: 0; border-radius: 50%; border: 2px solid transparent; cursor: pointer;
  position: relative; box-shadow: inset 0 0 0 1px rgba(41,37,36,.08); }
/* 未解锁的颜色：变灰 + 锁标，点它走解锁流程 */
.pet-set-dot.locked { opacity: .5; }
.pet-set-dot.locked::after { content: '🔒'; position: absolute; right: -3px; bottom: -3px; font-size: 9px;
  line-height: 1; filter: drop-shadow(0 1px 1px rgba(0,0,0,.25)); }
/* 设置面板里不显示解释小字（用户要求去掉） */
#petSettingsOverlay .pet-set-t small { display: none; }
.pet-set-tip { margin-top: 8px; font-size: 12px; color: var(--c-text-muted); }
.pet-set-actions { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.pet-set-act { padding: 6px 12px; border-radius: 100px; border: 1px solid rgba(41,37,36,.12);
  background: #fff; font-size: 13px; color: var(--c-text-secondary); cursor: pointer; }
.pet-set-act:hover { border-color: #C99A6E; color: #8B5E3C; }
.pet-set-act:active { transform: scale(.96); }
.pet-set-dot[aria-pressed="true"] { border-color: #292524; box-shadow: 0 0 0 3px rgba(41,37,36,.10); }
html.dark .pet-set-dot[aria-pressed="true"] { border-color: #F5F5F4; box-shadow: 0 0 0 3px rgba(255,255,255,.12); }
.pet-set-dot.auto { background: conic-gradient(#F2C230, #3B9BD8, #35C3C8, #5FA83F, #E87722, #E98FA6, #C9A227, #A9A9A9, #F2C230); }
/* 衣服色块用宠物形象：26px 不变，待机图铺满露出脸和身子 */
.pet-set-dot.pet-dot-art { background-size: 100% 100%; background-position: center; background-repeat: no-repeat;
  background-color: #F7F3EC; }
.pet-set-seg { display: flex; flex: none; border: 1px solid var(--c-border); border-radius: 999px; overflow: hidden; }
.pet-set-seg button { padding: 6px 14px; border: none; background: none; font: inherit; font-size: .76em;
  color: var(--c-text-muted); cursor: pointer; }
.pet-set-seg button + button { border-left: 1px solid var(--c-border); }
.pet-set-seg button[aria-pressed="true"] { background: #8A6A2F; color: #fff; }
html.dark .pet-set-seg button[aria-pressed="true"] { background: #C9A227; color: #1C1917; }
.pet-set-foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 14px; }
.pet-set-mini { padding: 7px 13px; border: 1px solid var(--c-border); border-radius: 999px; background: none;
  font: inherit; font-size: .76em; color: var(--c-text-secondary); cursor: pointer; }
.pet-set-mini:hover { background: rgba(120,113,108,.08); }
.pet-set-link { border: none; background: none; padding: 0; font: inherit; font-size: .76em; color: var(--c-text-muted);
  cursor: pointer; border-bottom: 1px dashed currentColor; }
.pet-set-link:hover { color: var(--c-text); }
@media (max-width: 768px) {
  #petSettingsOverlay { align-items: flex-end; }
  .pet-set-card { width: 100%; max-height: 78vh; border-radius: 20px 20px 0 0;
    padding-bottom: max(16px, env(safe-area-inset-bottom)); }
}
html.force-phone #petSettingsOverlay { align-items: flex-end; }
html.force-phone .pet-set-card { width: 100%; max-height: 78vh; border-radius: 20px 20px 0 0; }
/* ══ 门厅 #welcomePage（2026-09-25 新增 · 09-26 换色）════════════════════════════
   新主页 = 门厅（介绍站内功能，Persuade 型），原主页 #homePage 降为二级页（工作台）。
   配色 = StyleKit「Natural Organic」：暖米白底 #FAF6F1 + 深棕主 #5C4033 + 鼠尾草绿副 #8B9D77
   （+ 暖褐 #D4A373 / 浅沙 #E9E0D4）。全站 `:root` 的 17 个颜色 token 已同步换成这套，
   所以工作台与其它页面也会跟着变 —— 那 342 处**硬编码**琥珀色这轮**没动**（已知混色，待下一轮）。

   这个风格的硬规矩（照它 showcase + 规格文档）：
     · 禁渐变（`bg-gradient-*`）、禁冷色（蓝/紫）、禁纯黑、禁高饱和/霓虹、禁重投影、禁几何硬角
     · hover 要"往下沉 + 加深底色"（Soft Earth Press），**不要浮起来**；动效 300ms+ ease-in-out
     · 圆形按钮/胶囊 = rounded-full 可以；方块要圆角 24px+（它写 rounded-[2rem]=32px，
       3 列小卡上 32px 太圆，取 24px）
     · 正文对比度必须 >= 4.5:1 —— 所以 `--c-accent` 用的是**深**鼠尾草 #5A6E45，
       亮鼠尾草 #8B9D77 只当图形色（色块/图标底/细线，3:1 即可）

   ⚠ 三条硬约束（后面改这个页面请一起守）：
     ① **必须自带 html.dark 覆盖**：工作台的暗色规则全挂在 `#homePage > .xxx` / `.home .xxx`
        作用域下，门厅**一点都继承不到** —— 不写就是亮底黑字糊在暗色页面上；
     ② 三端**同时**写媒体查询与 html.force-phone / html.force-tablet（站内双轨制，缺一边就会
        在预览模式下与真机不一致，179.66 那次 !important 打架就是双轨漏了一边）；
     ③ 入场动画只动 opacity / translate（**不动 transform**），且只用 `backwards` 不用 `both`
        —— `fill-mode: both` 会把 translate 钉死，之后 hover 的位移永久失效（179 章红线）。
   ══════════════════════════════════════════════════════════════════════════ */
@keyframes wlIn { from { opacity: 0; translate: 0 14px; } to { opacity: 1; translate: 0 0; } }
@keyframes wlBob { 0%, 100% { translate: 0 0; } 50% { translate: 0 4px; } }

/* ⚠ .wl-page 的 overflow:hidden 会让**内部所有 position:sticky 失效**（hidden 会把 .wl-page 变成滚动容器，
   而它自己并不滚动，后代 sticky 就无从吸附）。改用 overflow-x: clip —— 同样裁掉几何块/纸页溢出的部分，
   但 clip 不创建滚动容器，sticky 照常工作。老 Safari（<16）不支持 clip：下面有 @supports 兜底，
   那时退化成"图片不切换"，版面仍然是好的。 */
.wl-page { position: relative; display: flex; flex-direction: column; align-items: center; min-height: 100vh; padding: 0 20px; overflow-x: clip; background: #FAF6F1; }
@supports not (overflow: clip) { .wl-page { overflow-x: hidden; overflow-y: hidden; } }
/* 纸纹：改用 Natural Organic 自己给的那层 feTurbulence 噪点 —— 原来那层是几何点阵，
   而这个风格明令"避免几何/工业感"，噪点更像纸 */
/* 性能：原来这层噪点铺在整页（近 2000px 高）上，每次滚动都要重绘整张；改成 position: fixed 的视口层（图层只有一屏），滚动零重绘。
   噪点图案是均匀的，肉眼看不出区别；numOctaves 3→2 让 feTurbulence 光栅化也便宜一档。 */
.wl-page::before { content: ''; position: fixed; inset: 0; z-index: 0; opacity: .9; pointer-events: none; background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 400 400' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.04'/%3E%3C/svg%3E"); }
.wl-page > * { position: relative; z-index: 1; }
/* 有机色块：Natural Organic 的招牌装饰（大块柔和 blob，纯色 + 不规则圆角，慢慢形变）。
   鼠尾草绿 / 暖褐 / 浅沙三块 —— 替代原来那层"琥珀灯光晕"（琥珀是旧配色，且渐变被这个风格禁用）。 */
/* 性能：不要用动画改 border-radius —— 它每帧触发样式重算 + 重绘（实测这是滚动卡顿的主因）。改用 transform 系的 scale/translate：走合成器线程，零重绘。
   形状照旧是不规则 blob（border-radius 静态不变），只是「呼吸 / 漂移」用 transform 表达。 */
.wl-blob { position: absolute; z-index: 0; pointer-events: none; animation: wlDrift 26s ease-in-out infinite; }
/* 四块的圆角都取「四角差 30~40 个百分点」（showcase 是 30 vs 70），这才是它的形状语言；
   上一版只差 8~16 个百分点，所以看着就是圆。 */
.wl-blob.b1 { top: 26px; right: -140px; width: 430px; height: 430px; border-radius: 60% 40% 30% 70% / 60% 30% 70% 40%; background: rgba(212,163,115,.26); }
.wl-blob.b2 { top: 46%; left: -140px; width: 360px; height: 360px; border-radius: 40% 60% 70% 30% / 50% 60% 40% 50%; background: rgba(139,157,119,.20); animation-duration: 15s; }
/* 第三块照 showcase：放在首屏偏中上的位置（它在那 0.33 / 0.21），浅沙几乎实心，
   压在标题后面做一层"纸的光影"，而不是当色块用。 */
.wl-blob.b3 { top: 400px; left: calc(50% - 560px); width: 250px; height: 250px; border-radius: 70% 30% 50% 50% / 30% 70% 50% 60%; background: rgba(233,224,212,.85); animation: wlBreathe 9s ease-in-out infinite; }
/* 第 4 块：补左上空档（与右上的鼠尾草块配平）。圆角取「接近圆、仍略有起伏」—— 风格禁完美圆形，所以不是 border-radius:50%。
   颜色用 NO 调色板的 Accent 4 灰绿 #75A191，给背景多一个层次；时长与其它三块错开。 */
/* 第四块：补下半页（数据带 / 收尾 CTA 那一段）的右下空档，灰绿是 NO 的 Accent 4。 */
.wl-blob.b4 { bottom: 40px; right: -110px; width: 340px; height: 340px; border-radius: 44% 56% 68% 32% / 62% 38% 56% 44%; background: rgba(117,161,145,.18); animation-duration: 19s; }
/* 形变节奏照 showcase：漂移带 ±1° 旋转（它的是 organic-drift / organic-breathe），
   全部走 transform 系（translate/rotate/scale），合成器处理、不触发重绘。 */
@keyframes wlDrift { 0%, 100% { translate: 0 0; rotate: 0deg; } 50% { translate: 0 -20px; rotate: 1.3deg; } }
@keyframes wlBreathe { 0%, 100% { scale: 1; } 50% { scale: 1.07; } }

/* ── 纸页：门厅背景的第三层，由用户 2026-09-26 要求加入（"背景飘着一些纸张，数量要少"，只在门厅页）。
   三条硬约束，改之前先读：
   ① 只动 translate / rotate —— 上一轮滚动卡顿就是 border-radius / filter 这种每帧重算的属性造成的；
   ② 纸不能压到任何文字 —— 所以三张的 x 全部落在文字列之外，任何视口高度都压不到（矩形相交验收）；
   ③ 暗色下白纸刺眼（html.dark .wl-page 是 #1C1917），必须换成深色纸。
   厚度只给一点点：offset 6px + blur 18px + 6% 暖棕（NO 禁重投影）。 */
.wl-paper { position: absolute; z-index: 0; pointer-events: none; background: rgba(255,253,250,.72);
  border: 1px solid rgba(233,224,212,.9);
  box-shadow: 0 6px 18px rgba(92,64,51,.06);
  /* 纸的不规则边：沿用 showcase"四角极差"的语言，幅度按纸收（不规整 ≠ 圆） */
  border-radius: 10px 14px 8px 12px / 12px 9px 14px 10px;
  rotate: var(--pbase, 0deg);
  /* 入场只做 opacity：translate 交给循环动画，两个动画抢同一属性时后者会覆盖前者 */
  animation: wlPaperIn .8s var(--ease-out-quart) 240ms backwards,
             wlFloat var(--pdur,26s) ease-in-out var(--pdelay,0s) infinite; }
/* 纸上的"字"：1 条标题行（暖褐）+ 2 条正文行（浅沙），全部 % 定位，随纸缩放 */
.wl-paper::before, .wl-paper::after { content: ''; }
.wl-paper::before, .wl-paper::after, .wl-paper i { position: absolute; left: 16%; height: 2px; border-radius: 2px; background: rgba(233,224,212,.95); }
.wl-paper::before { top: 26%; width: var(--w1,64%); height: 3px; background: rgba(212,163,115,.5); }
.wl-paper::after { top: 41%; width: var(--w2,70%); }
.wl-paper i { top: 53%; width: var(--w3,54%); }
/* 三张各不相同：角度、周期、相位（负 delay = 一上来就在循环中段，三张永不同步）、字线宽度 */
.wl-paper.p1 { top: 168px; left: 130px; width: 104px; height: 140px; --pbase: -11deg; --pdur: 27s; --pdelay: -3s; }
.wl-paper.p2 { top: 486px; right: 168px; width: 128px; height: 96px; --pbase: 7deg; --pdur: 33s; --pdelay: -11s; --w1: 46%; --w2: 58%; --w3: 40%; }
.wl-paper.p3 { top: 742px; left: 300px; width: 92px; height: 126px; --pbase: 13deg; --pdur: 23s; --pdelay: -7s; --w1: 56%; --w2: 64%; --w3: 46%; }
@keyframes wlPaperIn { from { opacity: 0; } }
@keyframes wlFloat {
  0%, 100% { translate: 0 0; rotate: var(--pbase, 0deg); }
  50% { translate: 0 var(--pdy,-14px); rotate: calc(var(--pbase, 0deg) + var(--prz,1.5deg)); }
}

/* ── 顶栏：只放 品牌 / 暗夜 / 账号（打赏·全屏·模式切换 留在工作台）── */
.wl-topbar { position: fixed; top: 0; left: 0; right: 0; z-index: 50; background: rgba(250,246,241,.92); -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px); border-bottom: 1px solid #E9E0D4; will-change: backdrop-filter; transform: translateZ(0); }
.wl-nav-inner { max-width: 1152px; margin: 0 auto; padding: 0 40px; height: 64px; display: flex; align-items: center; justify-content: space-between; gap: 16px; }
/* 品牌：浅沙有机胶囊（数值取自 showcase，含它那个不规则圆角）*/
.wl-brand-pill { display: flex; align-items: center; gap: 10px; padding: 8px 16px; background: #E9E0D4; border-radius: 28px 32px 24px 30px / 28px 30px 32px 26px; text-decoration: none; transition: all .5s ease-in-out; flex: none; }
.wl-brand-pill:hover { translate: 0 2px; }
.wl-brand-pill img { display: block; width: 16px; height: 16px; object-fit: contain; }
.wl-brand-text { font-size: 14px; font-weight: 600; letter-spacing: .35px; color: #5C4033; line-height: 20px; white-space: nowrap; }
.wl-brand-text em { font-style: normal; color: #8B9D77; }
.wl-nav-links { display: flex; align-items: center; gap: 4px; margin-left: auto; }
/* 文字链接：与 showcase 同款（14px/400 · padding 6px 12px · .5s · hover 下沉 2px）*/
.wl-nav-link { padding: 6px 12px; font-family: inherit; font-size: 14px; font-weight: 400; line-height: 20px; color: #5C4033; background: none; border: none; border-radius: 0; cursor: pointer; transition: all .5s ease-in-out; }
.wl-nav-link:hover { translate: 0 2px; }
.wl-nav-link:focus-visible { outline: 2px solid #8B9D77; outline-offset: 2px; }
.wl-nav-right { display: flex; align-items: center; gap: 6px; }
.wl-icon-btn { display: flex; align-items: center; justify-content: center; padding: 6px 12px; line-height: 20px; background: none; border: none; border-radius: 0; color: #5C4033; cursor: pointer; transition: all .5s ease-in-out; }
.wl-icon-btn:hover { translate: 0 2px; }
.wl-icon-btn:active { scale: .95; }
.wl-icon-btn:focus-visible { outline: 2px solid #8B9D77; outline-offset: 2px; }
.wl-icon-btn svg { display: block; width: 18px; height: 18px; transition: opacity .45s var(--ease-out-quart), transform .55s var(--ease-out-quart); }
/* 暗夜键：亮色显示**月亮**（点一下变暗），暗色显示太阳 —— 状态全由 html.dark 驱动，不需要 JS 同步。
   ⚠ 这里**不能**用 display 切换：.wl-icon-btn svg{display:block}（0,1,1）优先级高于 .wl-ico-sun{display:none}（0,1,0），
   所以原来那样写在亮色下**两个图标会同时显示**（按钮也被撑宽）。改成两个图标绝对定位叠在按钮正中、
   用 opacity + transform 交叉过渡 —— 既有了动画，也不再有优先级打架。 */
.wl-theme-btn { position: relative; width: 36px; height: 34px; padding: 0; }
/* 返回键（题目训练页 / 科目页顶栏最左，2026-09-26）：与全屏/暗夜键同规格。
   手机端顶栏的导航链接是隐藏的，返回键是唯二的退路之一（另一个是 logo），所以不隐藏。 */
.wl-back-btn { position: relative; width: 36px; height: 34px; padding: 0; }
/* 返回键现在跟「题目训练」并排（2026-09-26 用户要求），所以用一个 .wl-nav-lead 同时包住两者：
   手机端那条 `.wl-nav-links{display:none}` 只会藏掉链接，**返回键留着** —— 否则手机就没有退路了。
   外层 margin-left:auto 顶替原来写在 .wl-nav-links 上的那份，保证这一组仍靠右。 */
.wl-nav-lead { display: flex; align-items: center; gap: 4px; margin-left: auto; }
.wl-back-btn:hover { color: #5A6E45; }
html.dark .wl-back-btn:hover { color: #A8BC90; }
.wl-ico-moon, .wl-ico-sun { position: absolute; inset: 0; margin: auto; }
.wl-ico-moon { opacity: 1; transform: rotate(0deg) scale(1); }
.wl-ico-sun { opacity: 0; transform: rotate(-90deg) scale(.45); }
html.dark .wl-ico-moon { opacity: 0; transform: rotate(90deg) scale(.45); }
html.dark .wl-ico-sun { opacity: 1; transform: rotate(0deg) scale(1); }
/* 全屏键：与暗夜键完全同一套做法（两个图标叠放、状态写进 html.fs-on 由 CSS 驱动）。
   iPhone Safari 不支持元素全屏，那种情况下由 JS 给 html 加 .no-fs 把整颗按钮藏掉 —— 不留点不动的死按钮。 */
.wl-fs-btn { position: relative; width: 36px; height: 34px; padding: 0; }
.wl-ico-expand, .wl-ico-compress { position: absolute; inset: 0; margin: auto; }
.wl-ico-compress { opacity: 0; transform: rotate(-90deg) scale(.45); }
html.fs-on .wl-ico-expand { opacity: 0; transform: rotate(90deg) scale(.45); }
html.fs-on .wl-ico-compress { opacity: 1; transform: rotate(0deg) scale(1); }
html.no-fs .wl-fs-btn { display: none; }
.wl-topbar .auth-info { display: flex; align-items: center; gap: 8px; }
/* 未登录时藏掉那颗头像：站内既有设计是「头像 + 绿色登录键」（179.111），
   但 showcase 顶栏没有头像，在门厅这块会挤 —— 只作用于门厅，工作台那边照旧。 */
.wl-topbar .auth-info.auth-guest > img { display: none; }
/* 登录键：形状用 showcase 的有机圆角，颜色仍是你定的鼠尾草族（只作用于门厅这一处）*/
.wl-topbar .auth-login-btn { display: inline-flex; align-items: center; gap: 6px; padding: 8px 16px; height: auto; font-size: 14px; font-weight: 500; color: #4F6B36; background: #DCE4D2; border: none; line-height: 20px; border-radius: 30px 24px 28px 22px / 24px 28px 22px 30px; cursor: pointer; transition: all .5s ease-in-out; }
.wl-topbar .auth-login-btn:hover { translate: 0 2px; background: #D2DDC5; }
.wl-topbar .auth-login-btn:active { scale: .95; }
.wl-topbar .auth-login-btn svg { width: 15px; height: 15px; }
.wl-topbar .auth-username { color: #5C4033 !important; }

/* ── 首屏（自带 CTA，不依赖滚动）── */
.wl-hero { width: 100%; min-height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; padding: 88px 0 48px; }
.wl-hero > * { animation: wlIn .52s var(--ease-out-quart) backwards; }
.wl-hero > *:nth-child(1) { animation-delay: 30ms; }
.wl-hero > *:nth-child(2) { animation-delay: 110ms; }
.wl-hero > *:nth-child(3) { animation-delay: 190ms; }
.wl-hero > *:nth-child(4) { animation-delay: 260ms; }
.wl-hero > *:nth-child(5) { animation-delay: 330ms; }
.wl-hero > *:nth-child(6) { animation-delay: 380ms; }
.wl-hero > *:nth-child(7) { animation-delay: 440ms; }
/* 品牌锁定：与工作台 .brand-head 同一套（logo + 衬线字），保证两页是一家 */
/* 2026-09-26 按用户要求删掉标题下那条横线（原 .wl-brand-head::after，148×3 鼠尾草）。
   工作台 .home .brand-head::after（64×2）**未动**，用户只说过门厅。 */
/* 实测：整组（logo+文字）居中时，「百分百英语」这几个字的中心在 +44px（桌面）/ +28px（手机）。
   改成「文字本身居中、logo 悬挂到左边」—— 这样标题与下面的副标/定位句/CTA 同一条中线。 */
/* 品牌锁定：**整组居中**（对齐工作台 .home .brand-head 的做法）。
   ⚠ 别再用「给文字加右侧 padding 配平」那一招：那只会让盒子对称，
     看得见的 logo + 文字会整体左偏 (logo宽+间距)/2 —— 实测偏 33px，看着就别扭。 */
/* 首屏文字块的**墨迹间距**分四档（像素实测值，不是 CSS margin —— margin 之间还夹着各自的行高留白）：
   标题→副标 24 / 副标→定位句 31 / 定位句→副行 21 / 副行→按钮 39（桌面）。
   分层的道理：副标与标题是**同一个品牌锁定**（要贴紧），定位句是另一个信息组（前面要留更大的断口）。
   2026-09-26 用户要求收紧；改前这四档是 43 / 45 / 24 / 51 —— 标题→副标居然是最大的一档，层级是反的。 */
.wl-brand-head { position: relative; display: flex; align-items: center; justify-content: center; margin-bottom: 8px; }
/* logo 尺寸 = 「可见高度 ≈ 0.88em」反推，不是直接按 CSS 尺寸定：
   ① 这张 PNG 自带透明边（864×864 里可见部分只占高 74.7%），给 58px 时可见高只有 43px，所以才要放大；
   ② 但也不能与文字**几何等高**（0.97em / 56px）—— logo 是实心块、文字是笔画加空隙，
      等高的实心块看着更大更重；给实心标记补 ~10% 光学缩量取 0.88em 才视觉等高。
   桌面：0.88 × 57.6 = 50.7px 可见高 → CSS = 50.7 ÷ 0.747 ≈ 68px。 */
/* 垂直微调：用截图逐行扫像素实测，logo 墨迹中心比文字墨迹中心**偏上 2.8px**（桌面）/ 2.2px（手机），
   所以往下挪一点点（translate 是纯视觉位移，不动布局、不影响整组居中）。 */
.wl-brand-head img { display: block; flex: none; width: 78px; height: 78px; margin-right: 16px; translate: 0 2.5px; object-fit: contain; }
.wl-brand-head h1 { margin: 0; font-family: 'Noto Serif SC', serif; font-size: 4.125em; font-weight: 700; color: #5C4033; line-height: 1.1; letter-spacing: .04em; }
.wl-sub { margin: 0 0 16px; font-family: 'Crimson Text', serif; font-style: italic; font-size: 1.375em; color: #6B5D52; letter-spacing: .02em; }
.wl-lead { margin: 0 0 5px; font-size: 1.75em; font-weight: 600; color: #3F2D24; letter-spacing: .04em; }
/* 双色衬线：第二行进鼠尾草绿 —— Natural Organic 最标志性的一招（深棕 + 鼠尾草同屏） */
.wl-lead-sub { margin: 0 0 32px; font-size: 1.25em; color: #5A6E45; letter-spacing: .03em; }
.wl-hero-actions { display: flex; align-items: center; justify-content: center; gap: 18px; flex-wrap: wrap; }
/* 次按钮：与主 CTA 同高同形（胶囊），但走描边式 secondary 语言，不抢主按钮；hover 仍是「下沉 2px」 */
.wl-donate { display: inline-flex; align-items: center; justify-content: center; gap: 8px; height: 56px; padding: 0 28px; font-family: inherit; font-size: 1.1875em; font-weight: 500; line-height: 20px; color: #5C4033; background: transparent; border: 1px solid #D8CCBC; border-radius: 9999px; cursor: pointer; transition: all .5s ease-in-out; }
.wl-donate svg { width: 19px; height: 19px; }
/* 次按钮的图标用 emoji（用户 2026-09-26 指定）：字号略大于文字，站内本来就用 emoji（🎁 礼物入口 / 🦕 宠物）*/
.wl-donate-emoji { position: relative; z-index: 2; font-size: 1em; line-height: 1; margin-right: -4px; }
.wl-donate:hover { translate: 0 2px; background: #F2EDE4; border-color: #C6B8A6; }
.wl-donate:active { scale: .98; }
.wl-donate:focus-visible { outline: 3px solid rgba(90,110,69,.5); outline-offset: 3px; }

/* ── 次按钮改造成打赏卡里那颗「施舍一下」3D 键的样式（用户 2026-09-26 要求）──
   机制照搬：6 个象限热点浮在按钮上，鼠标落在哪一格就朝那个方向做 3D 倾斜（perspective 800px、rotateX/Y ±15°），
   配硬投影 + 文字抖动；悬停时填充转描边、正下方浮出「感谢支持」。
   三处**有意偏离**原版：
   ① 配色按用户要求改成黄色：填充 #FDDF6D + **墨字** #5C4033（7.1:1）。原版是白字压 #D4A373，只有 2.26:1，
      AA 要 4.5:1 —— 白字压亮黄更糟（1.8:1），所以黄底必须配墨字。
   ② 悬停把填充收掉（原版那颗 3D 键的手势）、只留描边，但**文字保持墨色**：墨字压米白底 8.46:1 ✔
       —— 要避的坑只是"黄字压米白底"（<2:1），不是"透明"本身。暗色下反过来：透明底 + 黄字（13.28:1）。
   ③ 硬投影用站内墨色 rgba(58,50,44,.45)，不引 #181818（Natural Organic 禁纯黑系）。
   尺寸没动：内层按钮留在正常流里当网格内容，所以桌面 56px / 手机 54px 满宽这些既有规则照旧生效。
   点击挂在**外层**：热点浮在按钮之上（鼠标点击落在热点上），键盘仍走内层 <button> 冒泡上来 —— 各只触发一次。 */
.wl-give { position: relative; display: inline-grid; grid-template-columns: repeat(3, minmax(0, 1fr)); grid-template-rows: repeat(2, minmax(0, 1fr)); perspective: 800px; }
.wl-give > .wl-hot { z-index: 3; cursor: pointer; }
.wl-give > .bt-1 { grid-area: 1 / 1; } .wl-give > .bt-2 { grid-area: 1 / 2; } .wl-give > .bt-3 { grid-area: 1 / 3; }
.wl-give > .bt-4 { grid-area: 2 / 1; } .wl-give > .bt-5 { grid-area: 2 / 2; } .wl-give > .bt-6 { grid-area: 2 / 3; }
.wl-give > .wl-donate { grid-area: 1 / 1 / 3 / 4; z-index: 2; translate: none; background: #FDDF6D; border: 3px solid #E5B93C; color: #5C4033; font-weight: 700;
  transition: transform .3s ease-in-out, background-color .3s ease-in-out, border-color .3s ease-in-out, color .3s ease-in-out, box-shadow .3s ease-in-out; }
.wl-give > .wl-donate > svg, .wl-give > .wl-donate > span { position: relative; z-index: 2; }
.wl-give > .bt-1:hover ~ .wl-donate { --dx: -2px; --dy: -2px; transform: rotateX(15deg) rotateY(-15deg); }
.wl-give > .bt-3:hover ~ .wl-donate { --dx: 2px; --dy: -2px; transform: rotateX(15deg) rotateY(15deg); }
.wl-give > .bt-4:hover ~ .wl-donate { --dx: -2px; --dy: 2px; transform: rotateX(-15deg) rotateY(-15deg); }
.wl-give > .bt-6:hover ~ .wl-donate { --dx: 2px; --dy: 2px; transform: rotateX(-15deg) rotateY(15deg); }
.wl-give > .wl-hot:hover ~ .wl-donate { box-shadow: var(--dx, 0) var(--dy, 0) rgba(58,50,44,.45); background: transparent; border-color: #DCAF33; color: #5C4033; }
.wl-give > .wl-hot:hover ~ .wl-donate > span { text-shadow: var(--dx, 0) var(--dy, 0) rgba(58,50,44,.35); animation: wlGiveShake .5s ease-in-out .15s; }
@keyframes wlGiveShake { 0% { left: 0; } 25% { left: 3px; } 50% { left: -1px; } 75% { left: 2px; } 100% { left: 0; } }
/* 「感谢支持」：字号按原版那颗（20px），emoji 用打赏卡里同一颗（原样搬过来）。
   位置改成贴按钮**右侧**：原版放在按钮正下方，但首屏下面 32px 就是「N 人正在学习」，
   实测会压掉那行字的一半（垫胶囊底也救不了观感），右侧是空的，放这儿零遮挡。
   emoji 悬停时弹一下（只动 transform），reduced-motion 下关掉。 */
.wl-give-thanks { position: absolute; top: 50%; left: 100%; translate: 0 -50%; display: inline-flex; align-items: center; gap: 8px; margin-left: 2px;
  font-size: 1.25em; font-weight: 700; color: #5C4033; white-space: nowrap; z-index: 4; pointer-events: none; opacity: 0; transition: opacity .3s ease, transform .3s ease; }
.wl-give-thanks svg { display: block; width: 30px; height: 30px; }
.wl-give:hover .wl-give-thanks { opacity: 1; transform: translateX(10px); }
.wl-give:hover .wl-give-thanks svg { animation: wlEmojiPop .6s var(--ease-out-quart) .2s; }
@keyframes wlEmojiPop { 0% { transform: scale(.6) rotate(-12deg); } 60% { transform: scale(1.14) rotate(6deg); } 100% { transform: scale(1) rotate(0deg); } }
/* 在线人数：从「与 CTA 并排」改成独立一行，放在两颗按钮下面 */
.wl-hero > .home-online { margin: 26px 0 0; font-size: 1.125em; }
/* 百分百政治入口（2026-10-31 用户要求）：安静的一行胶囊文字链接，放在在线人数下面。
   底色按用户给的色值 #F0E0D0（rgb(240,224,208)）—— 比门厅底 #FAF6F1 暖一档，像一张小纸片。 */
.wl-xsite { display: inline-flex; align-items: center; gap: 6px; margin: 12px auto 0; padding: 7px 16px;
  border-radius: 9999px; border: 1px solid rgba(122,90,52,.38); color: #6B4F3A; background: #F0E0D0;
  font-size: .92em; letter-spacing: .02em; text-decoration: none;
  transition: color .2s, border-color .2s, background-color .2s, translate .2s; }
.wl-xsite:hover { color: #5C4033; border-color: #5C4033; background: #E9D5C1; translate: 0 -1px; }
.wl-xsite svg { width: 13px; height: 13px; opacity: .75; }
/* 暗夜：同一色相压成半透明，避免一块亮色糊在黑底上 */
html.dark .wl-xsite { color: #EAD9BE; border-color: rgba(234,217,190,.4); background: rgba(240,224,208,.16); }
html.dark .wl-xsite:hover { color: #F5EBD8; border-color: #F5EBD8; background: rgba(240,224,208,.24); }
/* 主 CTA：**纯色深棕 + 米白字**（Natural Organic 的 primary button = stone-800 底 / stone-50 字，禁渐变）。
   实测 #FAF6F1 on #5C4033 = 8.42:1，比上一版橙渐变（5.0:1）更稳。
   hover 按它的 "Soft Earth Press"：**下沉 2px + 底色加深** —— 不浮起、不弹跳（风格里明确禁止悬浮感）。 */
.wl-cta { display: inline-flex; align-items: center; justify-content: center; gap: 10px; height: 56px; padding: 0 40px; border: none; border-radius: 9999px; font-family: inherit; font-size: 1.25em; font-weight: 700; letter-spacing: .05em; color: #FAF6F1; background: #5C4033; box-shadow: 0 4px 14px -6px rgba(92,64,51,.45); transition: translate 300ms var(--ease-out-quart), background-color 300ms var(--ease-out-quart), box-shadow 300ms var(--ease-out-quart); }
.wl-cta svg { width: 19px; height: 19px; }
.wl-cta:hover { translate: 0 2px; background: #4A3229; box-shadow: 0 2px 8px -6px rgba(92,64,51,.5); }
.wl-cta:active { translate: 0 2px; background: #3F2D24; }
.wl-cta:focus-visible { outline: 3px solid rgba(90,110,69,.55); outline-offset: 3px; }
.wl-scroll { display: flex; align-items: center; gap: 6px; margin-top: 44px; font-size: .8em; color: var(--c-text-secondary); letter-spacing: .1em; }
.wl-scroll svg { width: 14px; height: 14px; animation: wlBob 1.9s ease-in-out infinite; }

/* ── 功能简介（"简介"的全部内容）── */
.wl-section { width: 100%; max-width: 1152px; padding: 72px 0 8px; }
/** 分区标题：规范自检清单点名禁止「tiny uppercase tracked eyebrow 放在每个 section 标题上面」，
    所以门厅不再用站内那套 .section-label（11px + .14em 字距 + 两侧发丝线），改成真衬线 H2。 */
.wl-h2 { margin: 0 0 36px; font-family: 'Noto Serif SC', serif; font-size: 1.75em; font-weight: 700; color: #5C4033; text-align: center; letter-spacing: .06em; }
.wl-feats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 26px;
  /* 规范要 max-w-6xl(1152) 的容器；但 3 列 × 366px 配 1~2 行文案右侧会发空，
     所以容器保持 1152（合规），网格自身收到 980px 居中 —— 每张卡约 310px，文案占满。 */
  width: 100%; max-width: 980px; margin: 0 auto; }
/* 卡片：Natural Organic 的规格是 rounded-[2rem]（32px）+ 1px 暖边框 + 极浅投影。
   这里取 24px —— 32px 在 3 列小卡上会显得过于圆润，24px 更稳，仍明显比全站 12px 更"有机"。 */
.wl-feat { display: flex; flex-direction: row; flex-wrap: wrap; align-items: center; gap: 14px 12px; padding: 26px 26px 28px; border-radius: 32px; background: #FFFCF8; border: 1px solid #E9E0D4; box-shadow: 0 1px 2px rgba(92,64,51,.05); transition: background-color var(--t-state) var(--ease-out-quart), border-color var(--t-state) var(--ease-out-quart), box-shadow var(--t-state) var(--ease-out-quart); }
/* hover：加深底色与边框；上浮 4px + 加深阴影 + 图标歪头在文件末尾「动效层」⑦（2026-10-17 用户要求，取代原来的"不抬升"） */
.wl-feat:hover { background: #FBF6EF; border-color: #D8CCBC; box-shadow: 0 4px 14px -8px rgba(92,64,51,.28); }
/* Verdant Tint（规范交互项）：hover 时标题向深绿缓慢过渡，像植物被光唤醒 */
.wl-feat:hover h3 { color: #5A6E45; }
.wl-feat-ico { display: flex; align-items: center; justify-content: center; flex: none; width: 44px; height: 44px; border-radius: 15px; background: #E9E0D4; color: #5C4033; }
/* 6 块里挑 2 块用鼠尾草绿，做出"深棕主 + 绿副"的节奏 */
.wl-feat:nth-child(2) .wl-feat-ico, .wl-feat:nth-child(5) .wl-feat-ico { background: #DCE4D2; color: #4F6B36; }
.wl-feat-ico svg { width: 22px; height: 22px; }
.wl-feat h3 { flex: 1 1 auto; min-width: 0; margin: 0; font-family: 'Noto Serif SC', serif; font-size: 1.25em; font-weight: 600; color: #3F2D24; letter-spacing: .04em; transition: color 300ms var(--ease-out-quart); }
.wl-feat p { flex: 1 1 100%; margin: 0; font-size: .9375em; color: var(--c-text-secondary); line-height: 1.7; }
.wl-more { margin: 28px 0 0; text-align: center; font-size: .82em; color: var(--c-text-secondary); letter-spacing: .06em; }

/* ── 滚动换图（2026-09-26 用户要求照 examcrafts.com 的做法，放在功能简介之后）──
   它的实现：图片舞台 position: sticky（top 15vh），多张图绝对定位叠在同一位置，滚到哪段文字就交叉淡入哪张。
   我们的三条约束：① 只动 opacity，不碰尺寸/位置（避免每帧重排重绘）；② 判定用**视口中线**，只写 class 不读布局；
   ③ 没有 IntersectionObserver 时第一张常亮 —— 内容不会因为脚本没跑而消失。
   ⚠ 前提：sticky 依赖祖先不是滚动容器，所以 .wl-page 的 overflow:hidden 必须换成 overflow-x: clip（见那一条注释）。 */
/* 图框加一条"平板刘海"：居中一片墨色舌片 + 一颗镜头点，让方框读起来像横放的平板。
   刘海从顶边**向下伸**（向外凸会被 overflow:hidden 裁掉）；两个伪元素 z-index 压在图片层之上（图片是 1/2）。
   颜色跟着边框走：亮色墨色 #3A322C，暗色 #8A7A6B。 */
.wl-stage-in::before { content: ''; position: absolute; z-index: 3; top: 0; left: 50%; translate: -50% 0; width: 128px; height: 16px; background: #3A322C; border-radius: 0 0 12px 12px; }
.wl-stage-in::after { content: ''; position: absolute; z-index: 4; top: 6px; left: 50%; translate: -50% 0; width: 5px; height: 5px; border-radius: 50%; background: rgba(255,253,250,.3); }
.wl-show { margin-top: 8px; display: grid; grid-template-columns: minmax(0, 0.62fr) minmax(0, 1.38fr); gap: 40px; }
.wl-stage { grid-column: 2; grid-row: 1; }
.wl-steps { grid-column: 1; grid-row: 1; display: flex; flex-direction: column; }
/* 吸顶的是 .wl-stage 的**子元素**：外层 grid item 会被拉满整行高度（默认 stretch），
   这样 sticky 才有可移动的空间 —— 别把 sticky 写在外层，那样它的盒子已经和整行一样高，动不了。 */
.wl-stage-in { position: sticky; top: 15vh; aspect-ratio: 16 / 10; border-radius: 32px; overflow: hidden; background: #FFFCF8; border: 3px solid #3A322C; box-shadow: 0 1px 2px rgba(92,64,51,.05); }
/* 切换动画：新图**从滚动方向落定**进来（下滚从下方 18px、回滚从上方），带一点缩放与 0.35° 旋转；
   旧图留在下层淡出 —— .on 提 z-index，保证新图永远盖在上面，所以旧图的位移看不见，不用额外 JS 管离场。
   全部只动 opacity / transform，不碰尺寸与位置。 */
.wl-shot { position: absolute; inset: 0; z-index: 1; opacity: 0; transform: translateY(var(--fl-y, 18px)) scale(1.035) rotate(.35deg); transition: opacity .5s var(--ease-out-quart), transform .75s var(--ease-out-quart); }
.wl-shot.on { z-index: 2; opacity: 1; transform: none; }
.wl-stage-in.flip-up .wl-shot { --fl-y: -18px; }
.wl-shot img { display: block; width: 100%; height: 100%; object-fit: cover; }
/* 步骤块：高度就是"给图片切换留的滚动距离"，激活态用**鼠尾草小圆点 + 标题变色**表示。
   刻意**不**把未激活的文字调暗 —— 那样字号小、对比度会掉到 AA 以下，宁可只动标题色。 */
.wl-step { position: relative; min-height: 55vh; display: flex; flex-direction: column; justify-content: center; gap: 10px; padding-left: 24px; }
.wl-step::before { content: ''; position: absolute; left: 2px; top: 50%; width: 8px; height: 8px; border-radius: 50%; background: #8B9D77; opacity: 0; translate: 0 -50%; transition: opacity .4s ease; }
.wl-step.on::before { opacity: 1; }
.wl-step h3 { margin: 0; font-family: 'Noto Serif SC', serif; font-size: 1.75em; font-weight: 700; color: #5C4033; letter-spacing: .03em; transition: color .4s ease; }
.wl-step.on h3 { color: #5A6E45; }
.wl-step p { margin: 0; max-width: 22em; font-size: 1.125em; color: var(--c-text-secondary); line-height: 1.75; }

/* ── 收尾：数据带 + 第二次 CTA ── */
.wl-end { display: flex; flex-direction: column; align-items: center; padding: 96px 0 56px; }
.wl-data { display: flex; flex-wrap: wrap; align-items: stretch; justify-content: center; margin-bottom: 26px; }
.wl-data > div { display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 0 36px; border-right: 1px solid #E9E0D4; }
.wl-data > div:last-child { border-right: none; }
.wl-data b { font-family: 'Noto Serif SC', serif; font-size: 1.65em; font-weight: 700; color: #5C4033; letter-spacing: .02em; }
.wl-data span { font-size: .82em; color: var(--c-text-secondary); letter-spacing: .06em; }
.wl-badge { display: inline-flex; align-items: center; gap: 7px; margin-bottom: 32px; padding: 9px 18px; border-radius: 9999px; border: 1px solid #C6D3B6; background: #EEF2E9; color: #4F6B36; font-size: .82em; font-weight: 600; letter-spacing: .04em; }
.wl-badge svg { width: 13px; height: 13px; }

/* ── 底栏：备案信息（2026-09-26 新建）。
   与顶栏对称收口：上边界一道 1px 浅沙细线 + 一档更深的暖沙带底，页面上下各一道成为"框"。
   两个前提：① 备案号与链接**逐字保留**原 .icp-footer 里的值（备案属事实性内容，只搬不改）；
   ② .icp-footer 是门厅与工作台**共用**的类，所以这里新开 .wl-footer，共用类与工作台都不动。 */
.wl-footer { width: calc(100% + 40px); margin: 0 -20px; border-top: 1px solid #E9E0D4; background: rgba(233,224,212,.3); }
/* 2026-09-26 用户要求"内容也贴边"：去掉 1152 限宽（原来两边各空 184px），品牌贴左、备案贴右，只留 24px 呼吸。
   代价：固定定位的宠物（#dinoPet）正好压在底栏左下角 —— 贴边后 logo 就落在它身上，
   所以滚到底栏时用 JS 把宠物淡出（见 wlFooterPetYield），离开就恢复。 */
.wl-footer-inner { padding: 42px 24px 46px; display: flex; align-items: flex-start; justify-content: space-between; gap: 40px; text-align: left; }
.wl-foot-brand { display: flex; flex-direction: column; align-items: flex-start; gap: 7px; }
.wl-foot-name { display: inline-flex; align-items: center; gap: 8px; font-family: 'Noto Serif SC', serif; font-size: 1.0625em; font-weight: 700; color: #5C4033; letter-spacing: .04em; }
.wl-foot-name img { display: block; width: 22px; height: 22px; object-fit: contain; }
.wl-foot-name em { font-style: normal; color: #8B9D77; }
.wl-foot-tag { margin: 0; font-family: 'Crimson Text', serif; font-style: italic; font-size: .95em; color: #6B5D52; letter-spacing: .02em; }
.wl-foot-copy { font-size: .84em; color: var(--c-text-muted); letter-spacing: .02em; }
.wl-foot-rec { display: flex; flex-direction: column; align-items: flex-end; gap: 7px; font-size: .84em; }
.wl-foot-rec a { color: var(--c-text-muted); text-decoration: none; transition: color .3s ease; }
.wl-foot-rec a:hover { color: #5A6E45; }
.wl-foot-gongan { display: inline-flex; align-items: center; gap: 6px; }
.wl-foot-gongan img { display: block; width: 14px; height: 14px; }

/* ── 题目训练页（#trainHubPage，2026-09-26 新建）──
   顶栏复用门厅那套 .wl-topbar（全局类，标记从门厅逐字抽出）；卡片复用全局的 .cards/.cards-exam/.card/
   .cs-mode/.cb-btn（自带三列 + 平板/手机/force-* 全套响应式），所以这里只需写本页独有的部分：
   页标题、单选按钮组、三块面板、以及顶栏"当前项"高亮。 */
.th-main { width: 100%; max-width: 1152px; padding: 96px 0 80px; }
.th-title { margin: 0 0 24px; font-family: 'Noto Serif SC', serif; font-size: 1.75em; font-weight: 700; color: #5C4033; letter-spacing: .06em; text-align: center; }
.th-seg { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; margin-bottom: 36px; }
.th-seg-btn { padding: 9px 22px; font-family: inherit; font-size: .95em; font-weight: 600; letter-spacing: .04em; color: #5C4033; background: #FFFCF8; border: 1px solid #E9E0D4; border-radius: 9999px; cursor: pointer; transition: color .3s ease-in-out, background-color .3s ease-in-out, border-color .3s ease-in-out; }
.th-seg-btn:hover { background: #F2EDE4; border-color: #D8CCBC; }
.th-seg-btn.active { color: #FFFDFA; background: #5C4033; border-color: #5C4033; }
.th-seg-btn:focus-visible { outline: 3px solid rgba(90,110,69,.5); outline-offset: 2px; }
/* 科目卡那一屏靠 flex 居中；但「生成题目 / 导入题目 / 我的」三个面板里是整块界面
   （对话框 / 上传区 / 卡片网格），要**占满宽度**、不能被 flex 挤窄 —— 2026-10-05 实测：
   挤窄时导入题目的卡片只有 150px，而导入文章那边是 400px。 */
.th-panel { display: flex; justify-content: center; }
#thPanelGen, #thPanelImport { display: block; }
.th-panel .cards { margin-bottom: 0; }
.cards.cards-1 { grid-template-columns: minmax(0, 460px); max-width: 460px; }
/* 顶栏「当前所在项」：门厅那套没有激活态，本页需要，所以只加这一条 */
.wl-nav-link[aria-current="page"] { color: #5A6E45; font-weight: 600; }

/* ── 科目页（#subjectHubPage，2026-09-26 新建）──
   顶栏复用门厅那套；这里是内容区：标题 + 题型按钮排 + 左侧筛选区 + 右侧列表。
   筛选维度全部来自数据真实字段，所以不会出现"筛了永远为空"的选项。 */
.sh-main { width: 100%; max-width: 1152px; padding: 96px 0 80px; }
.sh-title { margin: 0 0 22px; font-family: 'Noto Serif SC', serif; font-size: 1.75em; font-weight: 700; color: #5C4033; letter-spacing: .06em; text-align: center; }
.sh-cats { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; margin-bottom: 30px; }
/* 标题行：##英语 + 训练模式下拉（2026-09-27 用户要求：把「精读训练」收进标题旁边的下拉）。
   原来是标题下面独立一排占位按钮（真题训练 / 精读训练），白占一行；现在收进下拉，题型行更贴近标题。
   视觉沿用顶栏「预览模式」那套（.wl-vm*）：胶囊触发键 + 圆角弹层 + 选中项描绿。 */
.sh-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 12px; margin: 0 0 22px; }
.sh-head .sh-title { margin: 0; }
/* ── 训练模式**滑动开关**（2026-10-03 用户要求，原来是标题旁的下拉「真题训练 ▾」）──────────
   左「真题训练」/ 右「精读训练」；滑块 `.sh-mode-knob` 用 `:has()` 跟着 `.active` 那一项走
   （`:has()` 站内已在用；支持不到时只是"滑块不动"，文字高亮照常 → 渐进增强）。
   默认 = 真题训练：进科目页时 showSubjectHub 会把 shState.mode 复位成 'quiz'，shSyncMode() 再加 .active。 */
.sh-mode { position: relative; flex: none; }
.sh-mode-switch { position: relative; display: inline-flex; align-items: center; height: 34px; padding: 3px;
  border: 1px solid #E9E0D4; border-radius: 9999px; background: #F2EDE4; }
.sh-mode-knob { position: absolute; top: 3px; bottom: 3px; left: 3px; width: calc(50% - 3px); border-radius: 9999px;
  background: #5C4033; box-shadow: 0 1px 4px rgba(0,0,0,.18); transition: transform .26s var(--ease-out-quart); }
.sh-mode-switch:has(.sh-mode-opt[data-shmode="train"].active) .sh-mode-knob { transform: translateX(100%); }
/* 注：`.ar-story-switch` 与 `data-arsmode` 那两条滑块规则已随「生成/导入」开关一起删除（2026-10-04：
   本栏只剩「生成」一种，导航上那颗就是入口，进来直接是对话界面，不再需要开关）。 */
.ar-story-mount { margin-bottom: 20px; }
/* ── 题目训练 · 「生成题目」把 AI 对话界面整块嵌进来（2026-10-04）──────────────
   与「文章 → 生成小说」的 .ar-story-mount 同一套收法：#basicChatView 原来是**整页**的
   （.chat-layout 满屏 fixed、顶上还有一条 fixed 的 #basicChatTopbar），嵌进页签后要收成"页签里的一块"。 */
.th-gen-mount { margin-bottom: 8px; }
#thGenMount .chat-layout { position: static; top: auto; left: auto; right: auto;
  height: auto; min-height: 460px; border: 1px solid var(--c-border); border-radius: 18px; overflow: hidden; }
#thGenMount .gen-entry { display: none; }          /* 入口翻转卡不要：点进页签直接就是对话 */
#thGenMount .chat-messages { max-height: 46vh; }
/* 「导入题目」把导入界面搬进来后：藏掉「我的阅读」那行大字（导入文章那栏也没有），内边距收齐 */
#thImpMount .lib-hero { display: none; }
#thImpMount .vocab-page { padding-top: 0; }
#impQuizPage .ar-imp-head { margin-bottom: 4px; }
/* 那两条 fixed 顶栏在嵌入态彻底不要（setBasicTopbar 会给它们写 inline display） */
#thGenMount #basicChatTopbar, #thGenMount #basicTopbar { display: none !important; }
/* 我的（生成的题目 / 导入的题目）：两个子标签 + 与「文章 → 我的」同一套卡片网格 */
/* ── 三级按钮（2026-10-05 用户要求）──────────────────────────────────────────
   基准样板 = 「导入题目」弹窗里那排「上传文件 / 拍照上传 / 我的导出」按钮（.ar-cat）：
   同 padding / 圆角 / 描边 / 字阶 / hover，**点击后实心绿底白字**；
   按钮组左边缘与下方内容大框左边对齐（同在 .mine-block 里），底部紧贴内容框（margin-bottom 8px），整块 880 居中。 */
.th-mine-tabs { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; justify-content: flex-start; margin: 0 0 8px; }
.th-mine-tab { position: relative; padding: 7px 16px; border-radius: 999px; border: 1px solid var(--c-border);
  background: var(--c-bg-card); color: var(--c-text-secondary); font: inherit; font-size: .82em; font-weight: 600;
  white-space: nowrap; cursor: pointer;
  transition: color var(--t-state) var(--ease-out-quart), background-color var(--t-state) var(--ease-out-quart),
              border-color var(--t-state) var(--ease-out-quart), box-shadow var(--t-state) var(--ease-out-quart),
              transform var(--t-press) var(--ease-out-quart); }
.th-mine-tab:hover { border-color: var(--c-accent); color: var(--c-accent-deep); background: var(--c-bg); }
.th-mine-tab.sel { background: var(--c-accent); border-color: var(--c-accent); color: #fff; }
html.dark .th-mine-tab { background: #2A2724; border-color: #3F3A37; color: #D6D3D1; }
html.dark .th-mine-tab.sel { background: var(--c-accent); border-color: var(--c-accent); color: #1C1917; }
.th-mine-tab:active { transform: scale(.97); }
/* 「三级按钮 + 下方内容大框」作为一个整体：880 宽、水平居中 → 按钮组左边自然对齐内容框左边 */
.mine-block { max-width: 880px; margin: 0 auto; }
/* 纯 div 的 .mine-block（题目训练面板 / 我的页题目栏）补 24px 左右内边距 ——
   这样它们的按钮/内容左边缘（280+24=304）与「文章-我的」「导入文章 / 导入题目」那几块**同一条竖线**，
   内容宽度也都是 832（2026-10-05 用户要求：两处我的页对齐逻辑完全一致）。 */
.mine-block:not(.vocab-page) { padding-left: 24px; padding-right: 24px; }
/* 「真题收藏 / 精读收藏」滑动切换（并进三级按钮组的第一个位置；复用站内 .sh-mode-switch 那套滑块） */
.th-mine-favswitch { position: relative; display: inline-flex; align-items: center; height: 34px; padding: 3px; flex: none;
  border: 1px solid #E9E0D4; border-radius: 9999px; background: #F2EDE4; }
/* 滑块底色 = 三级按钮选中态那个绿（var(--c-accent)），文字白 —— 两个开关都走这一份（2026-10-05 用户要求） */
.th-mine-favswitch .sh-mode-knob { position: absolute; top: 3px; bottom: 3px; left: 3px; width: calc(50% - 3px); border-radius: 9999px;
  background: var(--c-accent); box-shadow: 0 1px 4px rgba(0,0,0,.18); transition: transform .26s var(--ease-out-quart); }
.th-mine-favswitch[data-active="1"] .sh-mode-knob { transform: translateX(100%); }
.th-mine-favswitch .sh-mode-opt { position: relative; z-index: 1; height: 100%; padding: 0 14px; border: 0; border-radius: 9999px;
  background: none; font-family: inherit; font-size: .82em; font-weight: 600; color: #8A7C68; cursor: pointer; white-space: nowrap; transition: color .22s ease; }
.th-mine-favswitch .sh-mode-opt.active { color: #FFFDFA; }
html.dark .th-mine-favswitch { background: #2A2521; border-color: #3A322C; }
html.dark .th-mine-favswitch .sh-mode-knob { background: var(--c-accent); }
html.dark .th-mine-favswitch .sh-mode-opt { color: #A8A29E; }
html.dark .th-mine-favswitch .sh-mode-opt.active { color: #1C1917; }
/* 整页互斥高亮（2026-10-05 用户要求）：同一时刻只有**正在看的那一组**里选中的那一格是绿的；
   没在看的组整组不点亮 —— data-active="-1" 时滑块淡出、字色回默认。 */
.th-mine-favswitch[data-active="-1"] .sh-mode-knob { opacity: 0; }
.th-mine-favswitch[data-active="-1"] .sh-mode-opt { color: #8A7C68; }
html.dark .th-mine-favswitch[data-active="-1"] .sh-mode-opt { color: #A8A29E; }
/* 内嵌进来的两块界面（生成小说 #storyChatView / 导入小说 #storyImportView）：
   它们原来是**整页**的（.chat-layout 是全屏 fixed、导入块带自己的大字标题），嵌进栏目后要收成"栏目里的一块" */
.ar-story-mount { margin-bottom: 20px; }
.ar-story-mount .lib-hero { display: none; }                     /* 那行大字由上面的开关代劳 */
.ar-story-mount .chat-layout { position: static; top: auto; left: auto; right: auto;
  height: auto; min-height: 380px; border: 1px solid var(--c-border); border-radius: 18px; overflow: hidden; }
.ar-story-mount .gen-entry { height: auto; min-height: 240px; padding: 8px 0; }
.ar-story-mount .chat-messages { max-height: 46vh; }
.ar-story-mount .vocab-page { padding: 0; }
.sh-mode-opt { position: relative; z-index: 1; height: 100%; padding: 0 16px; border: 0; border-radius: 9999px;
  background: none; font-family: inherit; font-size: .86em; font-weight: 600; letter-spacing: .02em;
  color: #8A7C68; cursor: pointer; white-space: nowrap; transition: color .22s ease; }
.sh-mode-opt.active { color: #FFFDFA; }
.sh-mode-opt:focus-visible { outline: 3px solid rgba(90,110,69,.5); outline-offset: 2px; }
html.dark .sh-mode-switch { background: #2A2521; border-color: #3A322C; }
html.dark .sh-mode-knob { background: #A3B98C; box-shadow: 0 1px 4px rgba(0,0,0,.4); }
html.dark .sh-mode-opt { color: #A8A29E; }
html.dark .sh-mode-opt.active { color: #1C1917; }
/* 窄屏：间距收紧 + 用更高优先级把 .sh-title 在 force-phone/tablet 轨上的 margin-bottom 压成 0 */
html.force-phone .sh-head, html.force-tablet .sh-head { gap: 8px; margin-bottom: 16px; }
html.force-phone .sh-head .sh-title, html.force-tablet .sh-head .sh-title { margin: 0; }
html.force-phone .sh-mode-switch { height: 32px; }
html.force-phone .sh-mode-opt { padding: 0 12px; font-size: .82em; }
/* ── 精读训练的「卷别」切换也用这套滑块（2026-10-04 用户要求：四六级精读训练里切四级/六级的按钮要做成滑动按钮）──
   原来它是 `#shExamSeg` 里一排 `.sh-chip`（计数旁边那组）。现在**只要这一组正好是 2 项**（四级/六级、
   英语一/英语二、全国卷/地方卷 都是 2 项）就渲染成上面的 `.sh-mode-switch` 皮肤，滑块位置由
   容器上的 `data-active="0|1"` 决定（不用 `:has()`，N 项也成立）；>2 项时仍退回原来的 chip 排。 */
.sh-exam-switch.sh-mode-switch { flex: none; }
.sh-exam-switch .sh-mode-knob { width: calc(50% - 3px); }
.sh-exam-switch[data-active="1"] .sh-mode-knob { transform: translateX(100%); }
.sh-exam-switch .sh-mode-opt[aria-selected="true"] { color: #FFFDFA; }
html.dark .sh-exam-switch .sh-mode-opt[aria-selected="true"] { color: #1C1917; }
@media (max-width: 768px) {
  .sh-head { gap: 8px; margin-bottom: 16px; }
  .sh-head .sh-title { margin: 0; }
  .sh-mode-switch { height: 32px; }
  .sh-mode-opt { padding: 0 12px; font-size: .82em; }
}
.sh-cat { padding: 9px 20px; font-family: inherit; font-size: .95em; font-weight: 600; letter-spacing: .04em; color: #5C4033; background: #FFFCF8; border: 1px solid #E9E0D4; border-radius: 9999px; cursor: pointer; transition: color .3s ease-in-out, background-color .3s ease-in-out, border-color .3s ease-in-out; }
.sh-cat:hover { background: #F2EDE4; border-color: #D8CCBC; }
.sh-cat.active { color: #FFFDFA; background: #5C4033; border-color: #5C4033; }
.sh-cat:focus-visible, .sh-chip:focus-visible, .sh-item:focus-visible { outline: 3px solid rgba(90,110,69,.5); outline-offset: 2px; }
.sh-body { display: grid; grid-template-columns: 232px minmax(0, 1fr); gap: 34px; align-items: start; }
.sh-body.solo { grid-template-columns: minmax(0, 1fr); }   /* 精读模式：筛选区已隐藏，列表占满整行（2026-09-27） */
.sh-filter { position: sticky; top: 92px; padding: 20px 18px; background: #FFFCF8; border: 1px solid #E9E0D4; border-radius: 24px; }
.sh-fgroup + .sh-fgroup { margin-top: 18px; padding-top: 16px; border-top: 1px solid #F0EAE2; }
.sh-fgroup h3 { margin: 0 0 10px; font-size: .82em; font-weight: 700; color: #6B5D52; letter-spacing: .12em; }
/* 折叠标题（2026-09-26 用户要求筛选组可收起）：整行可点，右侧常显当前选中值，箭头转 90° */
.sh-fhead { display: flex; align-items: center; gap: 6px; width: 100%; margin: 0 0 10px; padding: 0; font-family: inherit; font-size: .82em; font-weight: 700; color: #6B5D52; letter-spacing: .12em; background: none; border: none; cursor: pointer; }
.sh-fhead .sh-fval { margin-left: auto; max-width: 7.5em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 500; letter-spacing: 0; color: #8A7A6B; }
.sh-chev { flex: none; width: 14px; height: 14px; transition: transform .3s var(--ease-out-quart); }
.sh-fgroup.col .sh-chev { transform: rotate(-90deg); }
.sh-fgroup.col .sh-chips { display: none; }
.sh-fhead:focus-visible { outline: 3px solid rgba(90,110,69,.5); outline-offset: 2px; }
.sh-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.sh-chip { padding: 5px 12px; font-family: inherit; font-size: .82em; color: #5C4033; background: #F7F3EC; border: 1px solid transparent; border-radius: 9999px; cursor: pointer; transition: background-color .3s ease-in-out, color .3s ease-in-out; }
.sh-chip:hover { background: #EFE7DC; }
.sh-chip.on { color: #FFFDFA; background: #5A6E45; }
.sh-clear { margin-top: 18px; width: 100%; padding: 8px 0; font-family: inherit; font-size: .84em; color: #6B5D52; background: none; border: 1px dashed #D8CCBC; border-radius: 9999px; cursor: pointer; }
.sh-clear:hover { color: #5A6E45; border-color: #8B9D77; }
.sh-count { margin: 0 0 12px; font-size: .84em; color: #6B5D52; letter-spacing: .04em; }
.sh-items { display: flex; flex-direction: column; gap: 10px; }
.sh-item { position: relative; overflow: hidden; display: flex; align-items: center; justify-content: space-between; gap: 14px; width: 100%; padding: 14px 18px; font-family: inherit; font-size: .95em; text-align: left; color: #5C4033; background: #FFFCF8; border: 1px solid #E9E0D4; border-radius: 16px; cursor: pointer; transition: border-color .3s ease-in-out, background-color .3s ease-in-out; }
.sh-item:hover { border-color: #C6B8A6; background: #FBF6EF; }
/* 悬停：左侧滑出一条主色竖线（2026-10-17 列表改版）—— 只动 transform，走合成器 */
.sh-item::before { content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; background: #5A6E45; transform: scaleY(0); transition: transform .25s var(--ease-out-quart); }
.sh-item:hover::before, .sh-item:focus-visible::before { transform: scaleY(1); }
.sh-item-main { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; color: #3F2D24; }
.sh-item.done .sh-item-main { font-weight: 400; color: #8A7A6B; }   /* 做过的退一档，没做过的更显眼 */
.sh-item-tags { display: flex; flex: none; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }
.sh-tag { padding: 2px 9px; font-size: .76em; color: #6B5D52; background: #F7F3EC; border-radius: 9999px; }
/* 难度圆点：易绿 / 中琥珀 / 难陶土；未评级是空心圈 */
.sh-diff { display: inline-flex; align-items: center; gap: 5px; }
.sh-diff i { flex: none; width: 7px; height: 7px; border-radius: 50%; background: var(--dc); }
.sh-diff.d-easy { --dc: #7E9A5F; } .sh-diff.d-mid { --dc: #D4A373; } .sh-diff.d-hard { --dc: #B5654A; }
.sh-diff.d-none i { background: none; box-shadow: inset 0 0 0 1.5px #C6B8A6; }
@media (prefers-reduced-motion: reduce) { .sh-item::before { transition: none; } }
/* 四六级写作列表：右侧两个标签**等宽对齐**（2026-10-02 用户要求）。
   原来「6月」37px、「12月」44px —— 月份标签宽度不同会把整组往左推，
   「未评级」的左边缘每行跳 7px（实测 1172 / 1165），往下滚就不在一条线上。
   固定同宽 + 文字居中后，两根列在每一行都对齐；只作用于写作这一排，其它题型不动。 */
#shItems .sh-item-writeup .sh-tag { display: inline-flex; align-items: center; justify-content: center; min-width: 60px; padding: 2px 6px; }
.sh-empty { padding: 56px 20px; text-align: center; color: #6B5D52; background: #FFFCF8; border: 1px dashed #E9E0D4; border-radius: 24px; }
.sh-empty b { display: block; margin-bottom: 8px; font-size: 1.05em; color: #5C4033; font-weight: 700; }
.sh-empty span { font-size: .86em; }

/* ── 暗夜（必须新写：工作台的暗色规则都挂在 #homePage/.home 作用域下，门厅一点都继承不到）
   2026-09-26：暗色从"冷蓝星空底"改为**暖石黑** —— Natural Organic 明令禁止冷色（蓝/紫），
   而原来的 #0A0E1C→#0E152E 是冷蓝。注意：工作台暗色的冷蓝是衬 Lightfall 星空的，
   按你的选择**不动**，所以工作台暗色仍是冷蓝、门厅暗色是暖石黑。 ── */
html.dark .wl-page { background: #1C1917; }
html.dark .wl-blob.b1 { background: rgba(212,163,115,.16); }
html.dark .wl-blob.b2 { background: rgba(139,157,119,.13); }
html.dark .wl-blob.b3 { background: rgba(233,224,212,.07); animation: wlBreathe 9s ease-in-out infinite; }
html.dark .wl-blob.b4 { background: rgba(117,161,145,.11); }
html.dark .wl-paper { background: rgba(42,37,33,.62); border-color: rgba(74,64,56,.75); box-shadow: none; }
html.dark .wl-paper::before { background: rgba(212,163,115,.32); }
html.dark .wl-paper::after, html.dark .wl-paper i { background: rgba(90,78,66,.9); }
html.dark .wl-topbar { background: rgba(28,25,23,.92); border-bottom-color: #3A322C; }
html.dark .wl-brand-pill { background: #3A322C; }
html.dark .wl-brand-text { color: #E9E0D4; }
html.dark .wl-brand-text em { color: #A8BC90; }
html.dark .wl-nav-link { color: #D6CCC2; }
html.dark .wl-icon-btn { color: #D6CCC2; }
html.dark .wl-topbar .auth-login-btn { color: #A8BC90; background: #333F2A; }
html.dark .wl-topbar .auth-login-btn:hover { background: #3D4A33; }
html.dark .wl-topbar .auth-username { color: #E9E0D4 !important; }
html.dark .wl-brand-head h1 { color: #F0EAE2; }
html.dark .wl-sub { color: #B5A797; }
html.dark .wl-lead { color: #EDE9E6; }
html.dark .wl-lead-sub { color: #A8BC90; }
html.dark .wl-donate { color: #E9E0D4; border-color: #4A4038; }
html.dark .wl-give > .wl-donate { background: #FDDF6D; border-color: #E5B93C; color: #2E2620; }
html.dark .wl-give > .wl-hot:hover ~ .wl-donate { background: transparent; border-color: #E5B93C; color: #FDDF6D; }
html.dark .wl-give-thanks { color: #E9E0D4; }
html.dark .th-title { color: #F0EAE2; }
html.dark .th-seg-btn { color: #E9E0D4; background: #221F1C; border-color: #3A322C; }
html.dark .th-seg-btn:hover { background: #2A2521; }
html.dark .th-seg-btn.active { color: #1C1917; background: #A3B98C; border-color: #A3B98C; }
html.dark .sh-title { color: #F0EAE2; }
html.dark .sh-cat { color: #E9E0D4; background: #221F1C; border-color: #3A322C; }
html.dark .sh-cat:hover { background: #2A2521; }
html.dark .sh-cat.active { color: #1C1917; background: #A3B98C; border-color: #A3B98C; }
html.dark .sh-filter, html.dark .sh-item, html.dark .sh-empty { background: #221F1C; border-color: #3A322C; }
html.dark .sh-fgroup + .sh-fgroup { border-top-color: #3A322C; }
html.dark .sh-fgroup h3, html.dark .sh-count, html.dark .sh-empty { color: #B5A797; }
html.dark .sh-fhead { color: #B5A797; }
html.dark .sh-fhead .sh-fval { color: #9A9086; }

/* ── 手机底部导航（2026-09-26 新建）：门厅/题目训练/科目页/我的 四页共用。
   视觉直接复用站内 .phone-tab-bar（同位/同高/同毛玻璃），只补两件事：
   ① 站内那条只在 html.force-phone 下显示，这里再加 ≤768 的媒体查询（双轨制），真机窄屏也出现；
   ② 有底部栏的页面要留出 56px，否则页脚/最后一行被压住。 */
/* ⚠️ 必须写 .wl-page > .wl-tabbar（不能只写 .wl-tabbar）：门厅/新页那条
   `.wl-page > *{position:relative;z-index:1}` 优先级虽同但源序在后，会把站内 .phone-tab-bar 的
   fixed 覆盖成 relative —— 实测底部栏落到文档 y=4519（页面最底），真机上根本不吸底。 */
.wl-page > .wl-tabbar { display: none; position: fixed; left: 0; right: 0; bottom: 0; z-index: 80; }
@media (max-width: 768px) { .wl-page > .wl-tabbar { display: flex; } }
html.force-phone .wl-page > .wl-tabbar { display: flex; }
html.force-desktop .wl-page > .wl-tabbar { display: none !important; }
@media (max-width: 768px) { .wl-tabbar { display: flex; } }
html.force-phone .wl-tabbar { display: flex; }
html.force-desktop .wl-tabbar { display: none !important; }
@media (max-width: 768px) { .wl-page:has(.wl-tabbar) { padding-bottom: 56px; } }
html.force-phone .wl-page:has(.wl-tabbar) { padding-bottom: 56px; }
html.dark .sh-chip { color: #E9E0D4; background: #2A2521; }
html.dark .sh-chip:hover { background: #332C26; }
html.dark .sh-chip.on { color: #1C1917; background: #A3B98C; }
html.dark .sh-item { color: #E9E0D4; }
html.dark .sh-item:hover { background: #2A2521; border-color: #4A4038; }
html.dark .sh-item::before { background: #A8BC90; }
html.dark .sh-item-main { color: #F0EAE2; }
html.dark .sh-item.done .sh-item-main { color: #9A9086; }
/* 标签提亮一档（2026-10-17）：原 #B5A797 on #2A2521 偏灰，「未评级」「6月」看不清 */
html.dark .sh-tag { color: #D6CCC2; background: #332C26; }
html.dark .sh-diff.d-easy { --dc: #A8BC90; } html.dark .sh-diff.d-mid { --dc: #E8C48F; } html.dark .sh-diff.d-hard { --dc: #E0907A; }
html.dark .sh-diff.d-none i { box-shadow: inset 0 0 0 1.5px #8A7E72; }
/* 「已做」徽章暗色（2026-10-09 改版）：底色走深色半透明，勾号圆底与文字用提亮一档的语义色，保证 ≥4.5:1 */
html.dark .sh-done.score-good { color: #CEDFB2; background: rgba(163,185,140,.15); }
html.dark .sh-done.score-good .sh-done-ic { background: #A3B98C; color: #21260F; }
html.dark .sh-done.score-good .sh-done-p { color: #CEDFB2; background: rgba(163,185,140,.22); }
html.dark .sh-done.score-mid { color: #E8D19B; background: rgba(232,209,155,.14); }
html.dark .sh-done.score-mid .sh-done-ic { background: #E8D19B; color: #3A2D12; }
html.dark .sh-done.score-mid .sh-done-p { color: #E8D19B; background: rgba(232,209,155,.22); }
html.dark .sh-done.score-low { color: #FFC4B8; background: rgba(240,169,155,.13); }
html.dark .sh-done.score-low .sh-done-ic { background: #F0A99B; color: #3A1F1A; }
html.dark .sh-done.score-low .sh-done-p { color: #FFC4B8; background: rgba(240,169,155,.18); }
html.dark .sh-done.score-none { color: #B5A797; background: #2A2521; }
html.dark .sh-done.score-none .sh-done-ic { background: #7E776D; color: #1C1917; }
html.dark .sh-empty b { color: #F0EAE2; }
html.dark .sh-clear { color: #B5A797; border-color: #4A4038; }
html.dark .wl-nav-link[aria-current="page"] { color: #A8BC90; }

/* ── 预览模式切换（下拉）放在顶栏品牌胶囊旁边（2026-09-26 用户要求改下拉）──
   形态与工作台那颗一致（按钮 + 弹层），调的还是站内 setViewMode()；
   差别只在**不用 id**：顶栏有 4 份，带固定 id 的复制品只有第一份能联动。 */
.wl-vm { position: relative; flex: none; }
.wl-vm-toggle { display: flex; align-items: center; gap: 5px; height: 30px; padding: 0 8px; font-family: inherit; font-size: .78em; color: #6B5D52; background: none; border: 1px solid transparent; border-radius: 9px; cursor: pointer; transition: color .3s ease-in-out, background-color .3s ease-in-out, border-color .3s ease-in-out; }
.wl-vm-toggle:hover { background: #F2EDE4; color: #5C4033; }
.wl-vm-toggle .wl-vm-ico { width: 15px; height: 15px; flex: none; }
.wl-vm-chev { width: 12px; height: 12px; flex: none; transition: transform .3s var(--ease-out-quart); }
.wl-vm.open .wl-vm-chev { transform: rotate(180deg); }
.wl-vm-menu { position: absolute; top: calc(100% + 6px); left: 0; min-width: 118px; padding: 6px; background: #FFFCF8; border: 1px solid #E9E0D4; border-radius: 14px; box-shadow: 0 10px 26px rgba(92,64,51,.12); display: none; z-index: 5; }
.wl-vm.open .wl-vm-menu { display: block; }
.wl-vm-menu button { display: flex; align-items: center; gap: 8px; width: 100%; padding: 8px 10px; font-family: inherit; font-size: .82em; color: #5C4033; background: none; border: none; border-radius: 9px; cursor: pointer; text-align: left; }
.wl-vm-menu button:hover { background: #F2EDE4; }
.wl-vm-menu button.on { color: #4F6B36; font-weight: 600; }
.wl-vm-menu button svg { width: 15px; height: 15px; flex: none; }
.wl-vm-toggle:focus-visible, .wl-vm-menu button:focus-visible { outline: 2px solid #8B9D77; outline-offset: 2px; }
html.dark .wl-vm-toggle { color: #B5A797; }
html.dark .wl-vm-toggle:hover { background: #2A2521; color: #E9E0D4; }
html.dark .wl-vm-menu { background: #221F1C; border-color: #3A322C; box-shadow: none; }
html.dark .wl-vm-menu button { color: #E9E0D4; }
html.dark .wl-vm-menu button:hover { background: #2A2521; }
html.dark .wl-vm-menu button.on { color: #A8BC90; }
/* ── 阅读页配色沿革（存档）──
   2026-09-26：用户要求「阅读页改回原来那版本」，这里曾把 --c-accent 族整套重声明回琥珀。
   2026-09-27：用户要求阅读页/完形页跟随主题色 → 强调色交回根令牌（鼠尾草族），只留暖纸背景；
   同一批硬编码琥珀也一并改成 color-mix(主题色)。
   悬浮件（悬浮题目按钮/悬浮题目卡/计时悬浮卡/标注悬浮按钮与工具条）按用户要求**保持琥珀不动**，
   见下面那段「悬浮件钉住」。 */
/* ── 2026-09-27 用户要求：阅读页/完形页的**强调色不再钉成琥珀**，改回跟随主题 ──
   原来这里把 --c-accent 族整套钉成琥珀（亮 #D97706 族 / 暗 #F59E0B 族），完形页在 #readingPage 里，
   于是整页（含新增的空位、进度条、选项卡）都是琥珀。现在只保留**暖纸背景**令牌，强调色交回主题根令牌：
   亮色 --c-accent #5A6E45（鼠尾草）/ 暗色 #A3B98C + --c-accent-deep #D4A373，两个主题都已配过对比度。 */
#readingPage { --c-bg: #FFFDF6; --c-bg-card: #FFFDF6; --c-bg-reading: #FFFDF6; --c-white: #FFFDF6; }
/* ── 悬浮件「钉住」：这些元素原来靠上面那套琥珀令牌上色，整页改主题色后要保证它们**一个像素都不变**
   （2026-09-27 用户要求「悬浮按钮不要动」）。就地补回原琥珀令牌即可，亮/暗各一套。
   范围限定在 #readingPage 内 —— 这几件（悬浮题目按钮/悬浮题目卡/计时按钮/标注悬浮按钮与工具条）
   都挂在阅读页里，不会波及原题训练页、基础阅读库等页面。
   ⚠️ #timerFloat（计时悬浮卡）与 #fbFloatBtn（反馈悬浮球）在 DOM 上挂在 **body 直属**（实测 parent=BODY），
   从来不继承阅读页那套琥珀 —— 它们一直是全站主题色，改前改后都不变，所以这里不用（也不该）列它们。 */
#readingPage .q-float-btn, #readingPage .float-q-card, #readingPage .float-q-head,
#readingPage .float-q-nav-btn, #readingPage .float-q-close, #readingPage .float-q-body,
#readingPage .topbar .timer-btn,
#readingPage .floating-annotate-btn, #readingPage .fab-toolbar {
  --c-accent: #D97706; --c-accent-deep: #A34909; --c-accent-hover: #F59E0B; --c-accent-light: #FDE68A; }
html.dark #readingPage .q-float-btn, html.dark #readingPage .float-q-card, html.dark #readingPage .float-q-head,
html.dark #readingPage .float-q-nav-btn, html.dark #readingPage .float-q-close, html.dark #readingPage .float-q-body,
html.dark #readingPage .topbar .timer-btn,
html.dark #readingPage .floating-annotate-btn, html.dark #readingPage .fab-toolbar {
  --c-accent: #F59E0B; --c-accent-deep: #FBBF24; --c-accent-hover: #D97706; --c-accent-light: #B45309; }
/* 暗色下的阅读页背景令牌（2026-09-27 原有修复，保留） */
/* ── 暗色修复（2026-09-27）：上面 #readingPage 的令牌覆盖是**无条件**的 —— 它写在元素自身，
   永远赢过 html.dark 继承下来的值，于是暗色下 --c-bg/--c-bg-card/--c-bg-reading/--c-white 被钉在
   近白 #FFFDF6，而 --c-text 仍是暗色根的 #EDE9E6 → 正文只有 1.19:1，整页「看不清」。
   这里按 html.dark 的根令牌把背景族补回暗色值。下面 6 组是阅读页/排行榜里**不走变量、也没有暗色分支**
   的硬编码色（实测 1.04:1 ~ 2.36:1），只新增 html.dark 版，亮色一律不动。 */
html.dark #readingPage { --c-bg: #1C1917; --c-bg-card: #292524; --c-bg-reading: #26211E; --c-white: #292524; }
html.dark .rt-stepper button { background: linear-gradient(to bottom, #3A3431, #2E2924); }
html.dark .rt-stepper button .rt-step-inner { background: linear-gradient(to bottom, rgba(255,255,255,.06), rgba(255,255,255,.02)); }
html.dark .rt-dd-item.sel { background: color-mix(in srgb, var(--c-accent) 18%, transparent); color: var(--c-accent); }
html.dark .vocab-page h2, html.dark .lib-hero-text h2 { color: var(--c-primary-dark); }
html.dark .annotate-toolbar .tool-hl.sel, html.dark .annotate-btn-dropdown .tool-hl.sel, html.dark .annotate-bottomsheet .ab-tools .tool-hl.sel { background: color-mix(in srgb, var(--c-accent) 20%, transparent); color: var(--c-accent); border-color: var(--c-accent); }
html.dark .annotate-toolbar .tool-clear, html.dark .annotate-bottomsheet .ab-tools .tool-clear { background: rgba(220,38,38,.15); border-color: rgba(248,113,113,.35); color: #FCA5A5; }
html.dark .float-q-body .word:hover, html.dark .float-q-body .word:active { background: rgba(245,158,11,.3); }
html.dark .wl-donate:hover { background: #2C2623; border-color: #5C5046; }        /* 亮鼠尾草，对 #1C1917 = 7.7:1 */
/* 深色下 CTA 反过来：浅沙底 + 深棕字（8.6:1）—— 比在暖黑底上放亮色按钮更贴这套配色，
   而且仍是"纯色、无渐变"。 */
html.dark .wl-cta { color: #3F2D24; background: #E9E0D4; box-shadow: 0 4px 14px -8px rgba(0,0,0,.6); }
html.dark .wl-cta:hover { background: #F2EDE4; }
html.dark .wl-cta:active { background: #DCD2C4; }
html.dark .wl-cta:focus-visible { outline-color: rgba(168,188,144,.6); }
html.dark .wl-feat { background: #26211E; border-color: #3A322C; box-shadow: none; }
html.dark .wl-feat:hover { background: #2C2623; border-color: #4A4038; box-shadow: none; }
html.dark .wl-feat h3 { color: #EDE9E6; }
html.dark .wl-feat:hover h3 { color: #A8BC90; }
html.dark .wl-feat-ico { background: #3A322C; color: #D4A373; }
html.dark .wl-feat:nth-child(2) .wl-feat-ico, html.dark .wl-feat:nth-child(5) .wl-feat-ico { background: #333F2A; color: #A8BC90; }
html.dark .wl-h2 { color: #F0EAE2; }
html.dark .wl-data b { color: #D4A373; }
html.dark .wl-data > div { border-right-color: #3A322C; }
html.dark .wl-badge { border-color: rgba(139,157,119,.45); background: rgba(139,157,119,.14); color: #C6D3B6; }
html.dark .wl-footer { border-top-color: #3A322C; background: rgba(233,224,212,.05); }
html.dark .wl-foot-name { color: #F0EAE2; }
html.dark .wl-foot-name em { color: #A3B98C; }
html.dark .wl-foot-tag { color: #B5A797; }
html.dark .wl-foot-copy, html.dark .wl-foot-rec a { color: #9A9086; }
html.dark .wl-foot-rec a:hover { color: #A8BC90; }
html.dark .wl-stage-in { background: #221F1C; border-color: #8A7A6B; box-shadow: none; }
html.dark .wl-stage-in::before { background: #8A7A6B; }
html.dark .wl-step h3 { color: #F0EAE2; }
html.dark .wl-step.on h3 { color: #A3B98C; }

/* ── 三端：媒体查询 + force-* 预览类，双轨都要写 ── */
@media (max-width: 1180px) {
  .wl-brand-head img { width: 65px; height: 65px; margin-right: 14px; translate: 0 2.5px; }
  .wl-brand-head h1 { font-size: 3.4375em; }
  .wl-sub { font-size: 1.25em; }
  .wl-lead { font-size: 1.5em; }
  .wl-lead-sub { font-size: 1.125em; }
  .wl-section { max-width: 940px; }
  .wl-feats { gap: 20px; }
  .wl-feat { padding: 24px 22px 26px; border-radius: 28px; }
  .wl-paper.p1 { top: 150px; left: 96px; width: 92px; height: 124px; }
  .wl-paper.p2 { top: 470px; right: 132px; width: 112px; height: 84px; }
  .wl-paper.p3 { top: 700px; left: 232px; width: 82px; height: 112px; }
  .wl-show { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 34px; }
  .th-main { padding: 88px 0 64px; }
  .th-title { font-size: 1.5em; }
  .sh-main { padding: 88px 0 64px; }
  .sh-title { font-size: 1.5em; }
  .sh-body { grid-template-columns: 200px minmax(0, 1fr); gap: 24px; }
  .wl-stage-in::before { width: 110px; height: 14px; border-radius: 0 0 10px 10px; }
  .wl-step { min-height: 50vh; }
  .wl-step h3 { font-size: 1.5em; }
  .wl-step p { font-size: 1.0625em; }
}
html.force-tablet .wl-brand-head img { width: 65px; height: 65px; margin-right: 14px; translate: 0 2.5px; }
html.force-tablet .wl-brand-head h1 { font-size: 3.4375em; }
html.force-tablet .wl-sub { font-size: 1.25em; }
html.force-tablet .wl-lead { font-size: 1.5em; }
html.force-tablet .wl-lead-sub { font-size: 1.125em; }
html.force-tablet .wl-section { max-width: 940px; }
html.force-tablet .wl-feats { gap: 20px; }
html.force-tablet .wl-feat { padding: 24px 22px 26px; border-radius: 28px; }
html.force-tablet .wl-paper.p1 { top: 150px; left: 96px; width: 92px; height: 124px; }
html.force-tablet .wl-paper.p2 { top: 470px; right: 132px; width: 112px; height: 84px; }
html.force-tablet .wl-paper.p3 { top: 700px; left: 232px; width: 82px; height: 112px; }
html.force-tablet .wl-show { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 34px; }
html.force-tablet .th-main { padding: 88px 0 64px; }
html.force-tablet .th-title { font-size: 1.5em; }
html.force-tablet .sh-main { padding: 88px 0 64px; }
html.force-tablet .sh-title { font-size: 1.5em; }
html.force-tablet .sh-body { grid-template-columns: 200px minmax(0, 1fr); gap: 24px; }
html.force-tablet .wl-stage-in::before { width: 110px; height: 14px; border-radius: 0 0 10px 10px; }
html.force-tablet .wl-step { min-height: 50vh; }
html.force-tablet .wl-step h3 { font-size: 1.5em; }
html.force-tablet .wl-step p { font-size: 1.0625em; }

@media (max-width: 768px) {
  .wl-page { padding: 0 16px; }
  /* 与 showcase 一致：手机上导航链接隐藏（它是 hidden md:flex），只留品牌 + 暗夜 + 登录 */
  /* 手机：几何块按屏宽收敛，避免压住标题 */
  .wl-blob.b1 { width: 300px; height: 300px; right: -110px; }
  .wl-blob.b2 { width: 250px; height: 250px; left: -110px; }
  .wl-blob.b3 { top: 340px; left: -140px; width: 200px; height: 200px; }
  .wl-blob.b4 { width: 240px; height: 240px; right: -90px; }
  .wl-nav-inner { padding: 0 20px; height: 60px; }
  .wl-nav-links { display: none; }
  .wl-brand-pill { padding: 6px 12px; gap: 8px; }
  .wl-brand-pill img { width: 14px; height: 14px; }
  .wl-brand-text { font-size: 13px; }
  .wl-hero { padding: 78px 0 40px; }
  .wl-brand-head { margin-bottom: 7px; }
  .wl-brand-head img { width: 57px; height: 57px; margin-right: 12px; translate: 0 2px; }
  .wl-brand-head h1 { font-size: 3em; }
  .wl-sub { font-size: 1.1875em; margin-bottom: 13px; }
  .wl-lead { font-size: 1.4375em; margin-bottom: 4px; }
  .wl-lead-sub { font-size: 1.0625em; margin-bottom: 25px; }
  .wl-hero-actions { flex-direction: column; gap: 14px; width: 100%; }
  .wl-cta { width: 100%; max-width: 340px; height: 54px; }
  .wl-donate { width: 100%; max-width: 340px; height: 54px; }
  .wl-give { display: block; width: 100%; max-width: 340px; perspective: none; }
  .th-main { padding: 84px 0 56px; }
  .sh-main { padding: 84px 0 56px; }
  .sh-title { font-size: 1.35em; margin-bottom: 16px; }
  .sh-cats { gap: 6px; margin-bottom: 20px; }
  .sh-cat { padding: 8px 14px; font-size: .875em; }
  .sh-body { grid-template-columns: minmax(0, 1fr); gap: 18px; }
  .sh-filter { position: static; padding: 16px 14px; border-radius: 20px; }
  .sh-item { padding: 12px 14px; }
  .th-title { font-size: 1.35em; margin-bottom: 18px; }
  .th-seg { gap: 6px; margin-bottom: 26px; }
  .th-seg-btn { padding: 8px 16px; font-size: .875em; }
  .wl-give > .wl-hot { display: none; }
  .wl-give-thanks { display: none; }
  .wl-hero > .home-online { margin: 22px 0 0; font-size: 1.0625em; }
  .wl-section { padding: 52px 0 8px; }
  /* 手机端**不放纸**（三端里唯一不放的一档）：390 宽下品牌组已占 318/390，左右各只剩 ~36px，
     而标题组是垂直居中的 —— y 随视口高度在 93px(568屏) ~ 240px(900屏) 之间漂，
     所以背景层没有任何一个"任意高度都安全"的落点（实测 390×667 上 p1 压到 logo 339px²）。
     纸是宽屏的呼吸感，窄屏让位给内容。 */
  .wl-paper { display: none; }
  .wl-footer { width: calc(100% + 32px); margin: 0 -16px; }
  .wl-footer-inner { flex-direction: column; align-items: center; text-align: center; gap: 26px; padding: 32px 20px 34px; }
  .wl-foot-brand { align-items: center; }
  .wl-foot-rec { align-items: center; }
  /* 手机：单列 —— 舞台落到上方并吸在顶栏下面（sticky 挂在外层 .wl-stage：单列时它的高度就是自身内容高度，
     所以吸顶的是整块带底色的舞台，文字从它下面穿过去）；内层改为静态，避免套两层 sticky。 */
  .wl-show { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .wl-stage { grid-column: 1; grid-row: auto; position: sticky; top: 0; z-index: 2; background: #FAF6F1; padding: 12px 0 14px; }
  html.dark .wl-stage { background: #1C1917; }
  .wl-stage-in { position: relative; top: auto; border-radius: 20px; }
  .wl-stage-in::before { width: 88px; height: 12px; border-radius: 0 0 9px 9px; }
  .wl-stage-in::after { top: 5px; width: 4px; height: 4px; }
  .wl-steps { grid-column: 1; grid-row: auto; }
  .wl-step { min-height: 44vh; padding-left: 18px; }
  .wl-step h3 { font-size: 1.35em; }
  .wl-step p { font-size: 1em; }
  .wl-h2 { font-size: 1.45em; margin-bottom: 28px; }
  .wl-feats { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
  .wl-feat { padding: 20px 18px 22px; gap: 12px 10px; border-radius: 26px; }
  .wl-feat-ico { width: 38px; height: 38px; border-radius: 13px; }
  .wl-feat-ico svg { width: 19px; height: 19px; }
  .wl-feat h3 { font-size: 1.06em; }
  .wl-feat p { font-size: .875em; }
  .wl-data > div { padding: 0 16px; }
  .wl-data b { font-size: 1.24em; }
  .wl-end { padding: 64px 0 40px; }
  .wl-scroll { margin-top: 30px; }
}
html.force-phone .wl-page { padding: 0 16px; }
html.force-phone .wl-nav-inner { padding: 0 20px; height: 60px; }
html.force-phone .wl-nav-links { display: none; }
html.force-phone .wl-brand-pill { padding: 6px 12px; gap: 8px; }
html.force-phone .wl-brand-pill img { width: 14px; height: 14px; }
html.force-phone .wl-brand-text { font-size: 13px; }
html.force-phone .wl-brand-head { margin-bottom: 7px; }
html.force-phone .wl-brand-head img { width: 57px; height: 57px; margin-right: 12px; translate: 0 2px; }
html.force-phone .wl-brand-head h1 { font-size: 3em; }
html.force-phone .wl-sub { font-size: 1.1875em; margin-bottom: 13px; }
html.force-phone .wl-lead { font-size: 1.4375em; margin-bottom: 4px; }
html.force-phone .wl-lead-sub { font-size: 1.0625em; margin-bottom: 25px; }
html.force-phone .wl-hero-actions { flex-direction: column; gap: 14px; }
html.force-phone .wl-cta { width: 100%; max-width: 340px; height: 54px; }
html.force-phone .wl-donate { width: 100%; max-width: 340px; height: 54px; }
html.force-phone .wl-give { display: block; width: 100%; max-width: 340px; perspective: none; }
html.force-phone .th-main { padding: 84px 0 56px; }
html.force-phone .sh-main { padding: 84px 0 56px; }
html.force-phone .sh-title { font-size: 1.35em; margin-bottom: 16px; }
html.force-phone .sh-cats { gap: 6px; margin-bottom: 20px; }
html.force-phone .sh-cat { padding: 8px 14px; font-size: .875em; }
html.force-phone .sh-body { grid-template-columns: minmax(0, 1fr); gap: 18px; }
html.force-phone .sh-filter { position: static; padding: 16px 14px; border-radius: 20px; }
html.force-phone .sh-item { padding: 12px 14px; }
html.force-phone .th-title { font-size: 1.35em; margin-bottom: 18px; }
html.force-phone .th-seg { gap: 6px; margin-bottom: 26px; }
html.force-phone .th-seg-btn { padding: 8px 16px; font-size: .875em; }
html.force-phone .wl-give > .wl-hot { display: none; }
html.force-phone .wl-give-thanks { display: none; }
html.force-phone .wl-hero > .home-online { margin: 22px 0 0; font-size: 1.0625em; }
html.force-phone .wl-section { padding: 52px 0 8px; }
/* 手机端**不放纸**（三端里唯一不放的一档）：390 宽下品牌组已占 318/390，左右各只剩 ~36px，
   而标题组是垂直居中的 —— y 随视口高度在 93px(568屏) ~ 240px(900屏) 之间漂，
   所以背景层没有任何一个"任意高度都安全"的落点（实测 390×667 上 p1 压到 logo 339px²）。
   纸是宽屏的呼吸感，窄屏让位给内容。 */
html.force-phone .wl-paper { display: none; }
html.force-phone .wl-footer { width: calc(100% + 32px); margin: 0 -16px; }
html.force-phone .wl-footer-inner { flex-direction: column; align-items: center; text-align: center; gap: 26px; padding: 32px 20px 34px; }
html.force-phone .wl-foot-brand { align-items: center; }
html.force-phone .wl-foot-rec { align-items: center; }
html.force-phone .wl-show { grid-template-columns: minmax(0, 1fr); gap: 0; }
html.force-phone .wl-stage { grid-column: 1; grid-row: auto; position: sticky; top: 0; z-index: 2; background: #FAF6F1; padding: 12px 0 14px; }
html.dark.force-phone .wl-stage { background: #1C1917; }
/* ⚠️ 这里必须是 position: relative（不能是 static）—— .wl-shot 是 position:absolute; inset:0，
   要看 .wl-stage-in 当**包含块**；设成 static 后它会认外层 .wl-stage（sticky）当包含块，
   于是图片框比边框高 26px（上 12 / 下 14 的 padding）、还整体上移 12px，而且 .wl-stage-in 的
   overflow:hidden 也夹不住它（不是它的包含块）→ 手机上门厅的图片会跑出显示器边框（2026-09-27 用户反馈）。 */
html.force-phone .wl-stage-in { position: relative; top: auto; border-radius: 20px; }
html.force-phone .wl-stage-in::before { width: 88px; height: 12px; border-radius: 0 0 9px 9px; }
html.force-phone .wl-stage-in::after { top: 5px; width: 4px; height: 4px; }
html.force-phone .wl-steps { grid-column: 1; grid-row: auto; }
html.force-phone .wl-step { min-height: 44vh; padding-left: 18px; }
html.force-phone .wl-step h3 { font-size: 1.35em; }
html.force-phone .wl-step p { font-size: 1em; }
html.force-phone .wl-h2 { font-size: 1.3em; margin-bottom: 26px; }
html.force-phone .wl-feats { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
html.force-phone .wl-feat { padding: 20px 18px 22px; gap: 12px 10px; border-radius: 26px; }
html.force-phone .wl-feat-ico { width: 38px; height: 38px; border-radius: 13px; }
html.force-phone .wl-feat-ico svg { width: 19px; height: 19px; }
html.force-phone .wl-feat h3 { font-size: 1.06em; }
html.force-phone .wl-feat p { font-size: .875em; }
html.force-phone .wl-h2 { font-size: 1.45em; margin-bottom: 28px; }
html.force-phone .wl-data > div { padding: 0 16px; }

@media (prefers-reduced-motion: reduce) {
  .wl-hero > * { animation: none; }
  .wl-scroll svg { animation: none; }
  .wl-blob { animation: none; }
  .wl-paper { animation: none; }
  .wl-shot { transition: none; }
  .wl-icon-btn svg { transition: none; }
  .wl-give > .wl-hot:hover ~ .wl-donate { transform: none !important; }
  .wl-give > .wl-hot:hover ~ .wl-donate > span { animation: none; }
  .wl-give:hover .wl-give-thanks svg { animation: none; }
  .wl-cta, .wl-feat { transition: none; }
}

/* ── Natural Organic 合规：手机端触控目标 >= 44px（规范响应式要求）── */
@media (max-width: 768px) {
  .csm-btn, .topbar .btn, .topbar .back, .vocab-actions button, .wl-icon-btn, .admin-nav-item{ min-height: 44px; }
}
html.force-phone .csm-btn, html.force-phone .topbar .btn, html.force-phone .topbar .back{ min-height: 44px; }
/* ── 合规：焦点可见（原站只有部分元素有 focus-visible）── */
a:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible,
[tabindex]:not([tabindex="-1"]):focus-visible, [role="button"]:focus-visible {
  outline: 2px solid var(--c-accent); outline-offset: 2px;
}

/* ── 手机顶栏收位（2026-09-27）────────────────────────────────────────────
   现象：390px 下品牌名「百分百英语」被 flex 压缩成**竖排两列**（实测品牌字 30×60、胶囊被压成 76×72）。
   修法两步：① 全局让品牌名 nowrap、胶囊 flex:none（见上面两条规则）；
   ② 手机轨把省下的空间补回来 —— 容器内边距 20→14、间距 16→8、预览模式只留图标、
      全屏键隐藏（手机上没意义）；≤374px 再收掉品牌名只留 logo。
   ⚠️ 不能只做 ①：实测只 nowrap 时顶栏会右侧溢出（门厅 390 溢 17px / 科目页溢 69px；
      320 时 87 / 139px），右侧登录键会被挤出屏幕。 */
@media (max-width: 768px) {
  .wl-nav-inner { padding: 0 14px; gap: 8px; }
  .wl-vm-label { display: none; }
  .wl-fs-btn { display: none; }
}
html.force-phone .wl-nav-inner { padding: 0 14px; gap: 8px; }
html.force-phone .wl-vm-label { display: none; }
html.force-phone .wl-fs-btn { display: none; }
@media (max-width: 374px) {
  .wl-brand-text, html.force-phone .wl-brand-text { display: none; }
  .wl-brand-pill, html.force-phone .wl-brand-pill { gap: 0; padding: 6px 10px; }
}

/* ── 精读训练：题型卡片网格 + 卷别切换（2026-09-27）──────────────────────
   卡片本体是弹窗那套 .train-type-*，这里只做"落到科目页"的适配：
   ① 网格列数自适应；② 把卡片原来的蓝色调收进站内暖色系；③ 计数行的卷别切换 chip。
   所有覆盖都 scope 在 .sh-items 下 —— 弹窗（.train-type-modal）保持原样。 */
.sh-list-head { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; margin-bottom: 14px; }
.sh-list-head .sh-count { margin: 0; }
.sh-exam-seg { display: flex; flex-wrap: wrap; gap: 6px; }
.sh-items .train-type-grid { grid-template-columns: repeat(auto-fill, minmax(206px, 1fr)); gap: 12px; }
.sh-items .train-type-card { padding: 16px 15px; border-radius: 18px; }
.sh-items .train-type-card:hover { border-color: rgba(90,110,69,.42); box-shadow: 0 8px 20px rgba(92,64,51,.12); }
.sh-items .train-type-icon { background: #EFE8DC; color: #5A6E45; }
.sh-items .train-type-name { font-size: .96em; }
.sh-items .train-type-desc { font-size: .72em; }
.sh-items .train-type-tag { color: #4F6B36; background: #E9E0D4; }
html.dark .sh-items .train-type-icon { background: #2A2521; color: #A8BC90; }
html.dark .sh-items .train-type-tag { color: #A8BC90; background: #2A2521; }
html.dark .sh-items .train-type-card:hover { border-color: rgba(168,188,144,.45); box-shadow: 0 8px 20px rgba(0,0,0,.4); }
@media (max-width: 768px) { .sh-items .train-type-grid { grid-template-columns: repeat(2, 1fr); gap: 10px; } }
html.force-phone .sh-items .train-type-grid { grid-template-columns: repeat(2, 1fr); gap: 10px; }

/* 筛选胶囊里的篇数（2026-09-27 高考筛选重做）：让"这个选项背后有多少篇"一眼可见 */
.sh-chip-n { margin-left: 6px; font-size: .88em; opacity: .6; font-variant-numeric: tabular-nums; }
.sh-chip.on .sh-chip-n { opacity: .85; }
/* 「题型」这一组排规整（2026-10-02 用户要求）：四个胶囊名称长短不一（全部 / 仔细阅读 / 选词填空 / 长篇阅读），
   挤在 flex 里参差 → 改成**单列整行**：胶囊撑满一行、名称靠左、数字靠右对齐、`nowrap` 不断行。
   （先试过两列等宽网格，侧栏只有 ~200px，94px 的格子会把「仔细阅读」挤成两行，反而更乱。） */
/* 筛选栏统一排规整（2026-10-02 用户要求：考研 / 四六级 / 高考都要）：
   每一组都是**单列整行**胶囊 —— 名称靠左、数字靠右对齐、`nowrap` 不断行。
   （早先只对四六级「题型」那一组做过，用户看到后要求全站统一。）
   ⚠️ 必须带 `:not(.col)`：折叠靠 `.sh-fgroup.col .sh-chips{display:none}`，这条权重更高（带 id），
   不加限定会把折叠压掉 —— 这个坑我在 179.174.4 踩过一次。 */
#shFilter .sh-fgroup:not(.col) .sh-chips { display: grid; grid-template-columns: minmax(0, 1fr); gap: 6px; }
/* 默认两列（`sh-2col`，由 shRender 按最长胶囊估宽决定）；放不下才用上面的单列（2026-10-02 用户口径） */
#shFilter .sh-fgroup.sh-2col:not(.col) .sh-chips { grid-template-columns: repeat(2, minmax(0, 1fr)); }
#shFilter .sh-fgroup.sh-2col .sh-chip { padding: 5px 9px; gap: 6px; }
#shFilter .sh-chip { display: flex; align-items: center; justify-content: space-between;
  gap: 8px; padding: 5px 12px; text-align: left; white-space: nowrap; }
#shFilter .sh-chip-n { margin-left: 0; flex-shrink: 0; }

/* 「我的」页三张卡横排（2026-09-27 用户要求）：容器用 .cards.cards-exam，
   它在题目训练页是靠父容器 .th-panel 的 flex 居中的；这里父级 .sh-main 不居中 → 自己补一条。 */
#minePage .sh-main > .cards { margin-left: auto; margin-right: auto; }

/* 打赏卡底部两颗按钮并排（2026-09-27 用户要求：「暂不打赏」与「一份神秘礼物」同一排）。
   彩蛋按钮 .gift-entry 原本是**独占一行**的整宽按钮（width:100% + margin-top:16px），
   进 .btn-row 后必须中和掉，否则它会把这一排撑到卡片外；再让两颗 flex:1 等宽更整齐。
   flex-wrap 兜住窄屏：234px 左右的内容宽度放不下两颗时自动换行，不会横向溢出。 */
.donate-card .btn-row { flex-wrap: wrap; }
.donate-card .btn-row .btn-skip,
.donate-card .btn-row .gift-entry { flex: 1 1 auto; }
.donate-card .btn-row .gift-entry { width: auto; margin-top: 0; }

/* 留言浮钮 · 暗夜（2026-09-27 改样式时补）：底色走 var(--c-accent)，暗色下它是浅鼠尾草 #A3B98C，
   所以文字/图标要翻成深色；hover 的 --c-accent-hover 也由 token 给出，不用各写一份。 */
html.dark .fb-float-btn { color: #1C1917; box-shadow: 0 4px 14px rgba(0,0,0,.42), 0 1px 2px rgba(0,0,0,.3); }
html.dark .fb-float-btn:active { background: #96A87E; }
html.dark .fb-float-btn .now { color: #1C1917; }
html.dark .fb-float-btn .fb-unread-dot { border-color: #292524; }

/* ── 手机模式下**门厅页去壳**（2026-09-27 用户要求：不要顶栏、不要底栏、不要登录按钮）──
   只作用于 #welcomePage —— 题目训练 / 科目页 / 我的 的顶栏底栏与登录照旧（手机上门厅进入 App 后仍可登录）。
   ① 顶栏底栏都是 fixed：用 #welcomePage 提高优先级，压过手机轨那两条 `.wl-page > .wl-tabbar{display:flex}`；
   ② .auth-info（登录块）的行内 display 由 JS(updateAllAuthUI) 写，所以这条必须 !important 才压得住；
   ③ 顶栏收掉后 .wl-hero 的 78px 上让位、底栏收掉后 .wl-page:has(.wl-tabbar) 的 56px 下让位都成了空隙，一起收掉。
   ⚠️ 两轨都写（媒体查询 + force-phone）：手机预览必须和真机一致，否则预览就没意义了。
      副作用：预览模式下拉在门厅顶栏里，手机模式下门厅就没这个入口了 —— 可从题目训练页顶栏切回。 */
@media (max-width: 768px) {
  #welcomePage .wl-topbar { display: none; }
  #welcomePage > .wl-tabbar { display: none; }
  #welcomePage .auth-info { display: none !important; }
  #welcomePage.wl-page:has(.wl-tabbar) { padding-bottom: 0; }
  #welcomePage .wl-hero { padding: 24px 0 40px; }
}
html.force-phone #welcomePage .wl-topbar { display: none; }
html.force-phone #welcomePage > .wl-tabbar { display: none; }
html.force-phone #welcomePage .auth-info { display: none !important; }
html.force-phone #welcomePage.wl-page:has(.wl-tabbar) { padding-bottom: 0; }
html.force-phone #welcomePage .wl-hero { padding: 24px 0 40px; }

/* 手机模式下**题目训练页顶栏的返回箭头收掉**（2026-09-27 用户要求）。
   原因：这颗箭头走 backStop()，而它的手机分支落点就是题目训练页本身 —— 点了等于原地不动，
   留着是个死按钮（桌面模式仍保留：桌面落点是门厅，有意义）。
   注意只收 #trainHubPage 这一颗：科目页/我的页那两颗在手机上是回题目训练，仍然需要。
   两轨都写（媒体查询 + force-phone），与其它手机规则同口径。
   2026-10-14 用户复核确认这条口径保留：「手机不放返回箭头，改用 logo 回门厅」——
   本页顶栏那颗 `.wl-brand-pill` 就是 showWelcome()，手机上它是回门厅的入口（见 markup 里的注释）。 */
@media (max-width: 768px) { #trainHubPage .wl-back-btn { display: none; } }
html.force-phone #trainHubPage .wl-back-btn { display: none; }

/* 手机模式：题目训练页顶栏**用全屏按钮补上原返回箭头的位置**（2026-09-27 用户要求）。
   位置天然吻合 —— 顶栏右侧组的第一个就是 .wl-fs-btn（顺序：全屏 → 暗夜 → 登录），
   而左侧那组 .wl-nav-lead 在手机上是空的（箭头已隐、导航链接本就隐藏），
   所以把全屏放出来，它就正好落在原箭头处。
   ① 只放 #trainHubPage 这一处：科目页/我的页那个位置仍是返回箭头，不能重复；
   ② 用 #id 提权压过手机轨里那条全局的 `.wl-fs-btn{display:none}`；
   ③ 桌面模式本来就是显示的，不受影响。 */
@media (max-width: 768px) { #trainHubPage .wl-fs-btn { display: inline-flex; } }
html.force-phone #trainHubPage .wl-fs-btn { display: inline-flex; }

/* 宠物页/排行榜页改用门厅同款顶栏后的适配（2026-09-27）：
   ① 宠物页原来靠 `#petPage .topbar ~ .vocab-page{padding-top:56px}` 让位，选择器里的 .topbar 已经不存在；
      新顶栏桌面高 65px（含 1px 下边框）→ 给 72px。平板/手机两档的让位写在 `#petPage{padding-top:…}` 上，
      与顶栏类名无关，仍然生效，不用动。
   ② 老 .topbar 的规则对这两页不再命中（留着无害）。 */
#petPage .wl-topbar ~ .vocab-page { padding-top: 72px; }
/* 排行榜页同理：那条 `calc(var(--lb-topbar-h…))` 的让位**本身写在 @media ≤768 里**，桌面端不生效，
   胜出的是通用 `.vocab-page{padding-top:32px}` —— 而门厅同款顶栏是**永远 fixed**（老的 .topbar 桌面端不是），
   于是桌面端标题被压在顶栏下（实测 32 < 65）。手机端仍由媒体查询里那条（实测 73px）接管。 */
#pointsPage .wl-topbar ~ .vocab-page { padding-top: 72px; }

/* 门厅同款顶栏里的用户名不换行（2026-09-27）：
   手机上顶栏位置紧，长用户名（如「凌思璐最美丽」）会折成两行并把顶栏撑高 —— 实测 .auth-username
   高 40px（两行）。这里全局禁止换行；窄屏再加省略号截断，免得反过来把顶栏撑出横向溢出。
   桌面不截断（位置够），只保证不折行。 */
.wl-topbar .auth-username { white-space: nowrap; }
@media (max-width: 768px) {
  .wl-topbar .auth-username { max-width: 5em; overflow: hidden; text-overflow: ellipsis; display: inline-block; vertical-align: middle; }
}
html.force-phone .wl-topbar .auth-username { max-width: 5em; overflow: hidden; text-overflow: ellipsis; display: inline-block; vertical-align: middle; }

/* 宠物页/排行榜页的手机底部导航（2026-09-27 用户要求补上）：
   ① 底部让位：站内那条是 `.wl-page:has(.wl-tabbar){padding-bottom:56px}`，只认 .wl-page，
      这两页容器不是 .wl-page → 给宠物页补等价规则（排行榜页已有 `.pt-nav-mobile .vocab-page{padding-bottom:76px}`，
      已够让开 56px 的底栏，不重复加）。
   ② 排行榜页**双底栏冲突**：它自带三档底栏 .pt-tab-bar（总榜/本周/日榜）。主底栏取代它，
      同时把三档改到内容里的 .lb-seg 显示 —— 否则手机上就没法切榜了。两条规则都写在原规则之后，
      同优先级靠源序覆盖。 */
@media (max-width: 768px) { #petPage:has(.wl-tabbar) { padding-bottom: 56px; } }
html.force-phone #petPage:has(.wl-tabbar) { padding-bottom: 56px; }
#pointsPage.pt-nav-mobile .pt-tab-bar { display: none; }
#pointsPage.pt-nav-mobile .lb-seg { display: inline-flex; }
/* ══════════════════════════════════════════════════════════════════════════════
   生词本 / 文章 外壳 —— **对标原网站**（2026-10-07 用户要求）
   原网站（线上站，同一套单文件应用的部署版；2026-10-13 起域名 baifenbai.xyz）这两页的形态：
     · `.topbar`：顶部一条**通栏玻璃条**，左「← 标题」、右控件组（`.ws-toolbar` 靠 `margin-left:auto` 顶到右边）；
     · `.ws-shell`（flex）= 左侧**常驻竖栏** `.ws-sidebar`（fixed，宽 150，含 `.ws-side-brand` 品牌行）+ 内容 `.ws-content`；
     · `.ws-wl-panel`：词表**向右展开的抽屉**，`left:150px`（左缘**严格对齐侧栏右缘**，绝不压住侧栏）、
       圆角 `0 16px 16px 0`、宽 48 → `.open` 280；
     · 手机档由 `#wordStudyPage.ws-nav-mobile` / `#articlePage.ar-nav-mobile` **一个类**驱动（JS: wsSyncNav/arSyncNav）：
       侧栏 `display:none` + 底部栏目栏 `.ws-tab-bar` / `.ar-tab-bar` 顶上来 + 控件组收进「⋯」面板。
   我们**只额外叠加了顶部全局一级导航栏**（`header.wl-topbar`，fixed、高 65）——所以：
     · `.ws-sidebar` 的 `top` 由原网站的 0 改成 **65px**（让开全局导航）；`html.force-desktop` 那条 `!important` 同步；
     · 页面顶部那条玻璃条 `.topbar` 的 sticky `top` 由 12px 改成 **77px**（65 + 12），免得滑上去被全局导航压住。
   2026-10-03/04 那几轮曾把这两页做成「居中横向一排胶囊 + 左边缘悬浮词表 + 停用底部栏」，
   本轮按用户口径整段撤掉，回到原网站形态。 */





.ws-shell { display: flex; }
.ws-sidebar { position: fixed; left: 0; top: 65px; bottom: 0; width: var(--ws-side-w, 150px); z-index: 30;
  display: flex; flex-direction: column; gap: var(--ws-side-gap, 4px); padding: var(--ws-side-pad, 14px 12px);
  background: var(--c-bg-card); border-right: 1px solid var(--c-border); overflow-y: auto; }
.ws-side-brand { display: flex; align-items: center; gap: var(--ws-brand-gap, 8px); padding: var(--ws-brand-pad, 4px 6px 16px);
  font-size: var(--ws-brand-fs, .95em); font-weight: 700; color: var(--c-text); }
.ws-side-brand svg { width: var(--ws-brand-icon, 20px); height: var(--ws-brand-icon, 20px); color: var(--c-accent); flex-shrink: 0; }
.ws-side-item { display: flex; align-items: center; gap: var(--ws-item-gap, 10px); min-height: var(--ws-item-minh, 44px);
  padding: var(--ws-item-pad, 10px 12px); border: none; border-radius: 16px; background: transparent;
  color: var(--c-text-secondary); font-size: var(--ws-item-fs, .86em); font-weight: 600; text-align: left;
  cursor: pointer; transition: var(--transition-fast); }
.ws-side-item svg { width: var(--ws-item-icon, 18px); height: var(--ws-item-icon, 18px); flex-shrink: 0; }
.ws-side-item:hover { background: var(--c-bg); color: var(--c-text); }
.ws-side-item.sel { background: var(--c-accent); color: #fff; }
html.dark .ws-side-item.sel { color: #1C1917; }
.ws-content { flex: 1; min-width: 0; margin-left: var(--ws-side-w, 150px); padding: var(--ws-content-pad, 24px 28px 48px); }
html.force-desktop .ws-sidebar { top: 65px !important; }
/* 右上角控件组（在玻璃顶栏里，靠右） */
.ws-toolbar { display: flex; align-items: center; gap: 3px; margin-left: auto; flex: none; }
.ws-tool-item { position: relative; display: inline-flex; align-items: center; gap: 5px; min-height: 40px;
  padding: 8px 14px; border: 0; border-radius: 9999px; background: transparent; color: var(--c-text);
  font-size: .95em; font-weight: 600; letter-spacing: .01em; white-space: nowrap; cursor: pointer;
  transition: background .18s ease, color .18s ease, transform .12s ease; }
.ws-tool-item::after { content: ''; position: absolute; inset: -2px 0; }
.ws-tool-item:hover { background: rgba(255,255,255,.62); color: var(--c-text); }
.ws-tool-item.on { background: rgba(233,224,212,.72); color: var(--c-accent-deep); }
.ws-tool-item:active { transform: scale(.96); }
.ws-tool-item svg { width: 12px; height: 12px; opacity: .45; flex-shrink: 0; }
html.dark .ws-tool-item:hover { background: rgba(255,255,255,.10); }
html.dark .ws-tool-sep { background: rgba(255,255,255,.14); }
.ws-tool-more { display: none; align-items: center; justify-content: center; width: 36px; height: 36px; padding: 0;
  border: 0; border-radius: 9999px; background: transparent; color: var(--c-text); cursor: pointer;
  transition: background .18s ease, color .18s ease, transform .12s ease; flex: none; }
/* 词表抽屉：左缘 = 侧栏右缘（150px），向右展开，圆角方条 */
.ws-wl-panel { position: fixed; left: 150px; top: 50%; transform: translateY(-50%); z-index: 35; width: 48px;
  max-height: 76vh; display: flex; flex-direction: column; background: var(--c-bg-card);
  border: 1px solid var(--c-border); border-left: none; border-radius: 0 16px 16px 0;
  overflow: hidden; transition: width .24s ease, left .22s ease; }
.ws-wl-panel.open { width: 280px; }
.ws-wl-toggle { display: flex; align-items: center; justify-content: center; padding: 16px 12px; border: none;
  background: transparent; color: var(--c-text-secondary); cursor: pointer; flex-shrink: 0; }
.ws-wordlist { display: none; flex-direction: column; gap: 2px; padding: 0 10px 12px; overflow-y: auto; }
.ws-wl-panel.open .ws-wordlist { display: flex; }
/* ── 手机档（一个类驱动，不用媒体查询）── */
#wordStudyPage .ws-tab-bar { display: none; }
#wordStudyPage.ws-nav-mobile .ws-tab-bar { display: flex; }
#wordStudyPage.ws-nav-mobile .ws-sidebar { display: none; }
#wordStudyPage.ws-nav-mobile .ws-content { margin-left: 0; padding-bottom: 16px; }
#wordStudyPage.ws-nav-mobile .ws-tool-more { display: inline-flex; }
#wordStudyPage.ws-nav-mobile .ws-toolbar { display: none; position: absolute; top: calc(100% + 8px); right: 8px;
  left: 8px; flex-direction: column; align-items: stretch; gap: 2px; padding: 8px; margin-left: 0; z-index: 60;
  background: rgba(255,255,255,.96); backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
  border: 1px solid var(--c-border); border-radius: 16px; box-shadow: 0 18px 44px rgba(41,37,36,.18); }
#wordStudyPage.ws-nav-mobile .ws-toolbar.open { display: flex; animation: wsToolIn .16s var(--ease-out-expo) both; }
#wordStudyPage.ws-nav-mobile .ws-toolbar .ws-tool-item { justify-content: flex-start; min-height: 44px;
  padding: 8px 12px; border-radius: 16px; font-size: .92em; }
#wordStudyPage.ws-nav-mobile .ws-toolbar .ws-tool-menu { position: static; min-width: 0; padding: 2px 0 6px 10px;
  background: transparent; border: 0; box-shadow: none; }
#wordStudyPage.ws-nav-mobile .ws-wl-panel { left: 0; width: 42px; max-height: 70vh; }
#wordStudyPage.ws-nav-mobile .ws-wl-panel.open { width: min(82vw, 320px); }
html.force-phone .ws-wl-panel { left: 0 !important; width: 42px !important; max-height: 70vh !important; }
html.force-phone .ws-wl-panel.open { width: min(82vw, 320px) !important; }
#articlePage .ar-tab-bar { display: none; }
#articlePage.ar-nav-mobile .ar-tab-bar { display: flex; }
#articlePage.ar-nav-mobile .ws-sidebar { display: none; }
#articlePage.ar-nav-mobile .ws-content { margin-left: 0; padding-bottom: 16px; }
/* ── 控件组显隐（用户 2026-10-07 第 2 条）：**只**在「记单词主界面」「打字记词练习界面」出现 ── */
#wsToolbar.hidden, #wsToolToggle.hidden { display: none !important; }

/* ══ 生成小说 / 生成题目的对话框放大（2026-10-07 用户要求 C）══════════════════════════
   这两处的对话界面都是**嵌进栏目的 `.chat-layout`**（原站是满屏 fixed，嵌进来后收成一块），
   它们的大小由三处共同决定：
     · `.chat-layout { min-height }` —— 整块对话框的最小高度（原：小说 380 / 题目 460）
     · `.chat-messages { max-height }` —— 消息区上限（原：都是 46vh）
     · `.chat-input-area` —— 底部输入区（原来 16px 上下内边距 + .85em 输入框）
   本轮：小说整体放大（380 → 560、46vh → 58vh、输入区与发送钮一起放大）；
        题目适当放大（460 → 560、46vh → 54vh、输入区略放大）。 */
.ar-story-mount .chat-layout { min-height: 560px; }
.ar-story-mount .chat-messages { max-height: 58vh; }
.ar-story-mount .chat-input-area { padding: 18px 0; gap: 12px; }
.ar-story-mount .chat-input-area input { font-size: .95em; padding: 12px 18px; }
.ar-story-mount .chat-input-area .btn-send { font-size: .92em; padding: 11px 26px; }
#thGenMount .chat-layout { min-height: 560px; }
#thGenMount .chat-messages { max-height: 54vh; }
#thGenMount .chat-input-area { padding: 17px 0; gap: 11px; }
#thGenMount .chat-input-area input { font-size: .92em; padding: 12px 17px; }
#thGenMount .chat-input-area .btn-send { font-size: .9em; padding: 10px 24px; }
/* 手机档：这两块按视口高度自适应，别把页面撑出滚动条 */
@media (max-width: 768px) {
  .ar-story-mount .chat-layout, #thGenMount .chat-layout { min-height: 460px; }
  .ar-story-mount .chat-messages, #thGenMount .chat-messages { max-height: 46vh; }
}
html.force-phone .ar-story-mount .chat-layout, html.force-phone #thGenMount .chat-layout { min-height: 460px; }
html.force-phone .ar-story-mount .chat-messages, html.force-phone #thGenMount .chat-messages { max-height: 46vh; }

/* ══ 2026-10-07 第七轮：标题补回 + 按钮框收干净 + 生成题目弹窗缩小（用户四组要求）════════════
   ① 生词本四个栏目（词库/生词本/词组/学习计划）与文章库/导入文章/生成小说都补上**左上角标题**，
      用的就是原网站「文章库 / 小说」那一套组件（`.lib-hero` + `.lib-hero-text h2`：4px 琥珀竖条 + 衬线大标题）；
   ② 按钮组**只保留按钮自身的小内框**：`.ws-tools-bar` / `#arCats` / `#arImportCats` 三个容器的
      描边、底色、毛玻璃全部去掉（原来那一圈"大外框"是上一轮加的，本轮按用户要求撤掉），
      栏内按钮恢复各自的胶囊小框；
   ③ 导入文章整页**左对齐**（原来是 880px 居中：标题行、上传框、拍照、导入规则一起靠左）；
   ④ 文章「我的」内容左对齐（原来 `.ar-cards` 是 justify-content:center + 880 居中）；
   ⑤ 生成题目对话框**缩小**并在底部留出空隙；生成小说弹窗整体**下移**。 */
/* ① 标题：这几处容器自带内边距，标题贴着内容左缘即可 */
#wordStudyPage .lib-hero, #articlePage .lib-hero { margin-bottom: 14px; }
#wordStudyPage .lib-hero-text h2, #articlePage .lib-hero-text h2 { font-size: 1.5em; }
/* ② 按钮组：去掉容器大外框 */
.ws-tools-bar { padding: 0; border: 0; background: transparent; backdrop-filter: none; -webkit-backdrop-filter: none; }
.ws-tools-bar .ws-tool-item { border: 1px solid var(--c-border); background: var(--c-bg-card); }
.ws-tools-bar .ws-tool-item:hover { background: var(--c-accent-light); border-color: var(--c-accent); color: var(--c-accent-deep); }
/* ⚠️ 上面两条把这条小横栏的"毛玻璃大外框"去掉了（那是 2026-10-07 第七轮的当时口径）。
   179.291 用户改口径：「速记单词主页右上角也改成毛玻璃连在一起」→ 这一组把它改回来，
   与生词本/词组本的 `.vp-toolbar` 同一套语言（整排一层玻璃底 + 按钮自身去描边去底、靠 hover 区分）。
   **必须写在这两条之后**：同权重时后写者赢，写到前面会被它们盖掉（`.vp-toolbar` 那组就踩过一次）。 */
.ws-tools-bar { padding: 4px 6px; border-radius: 9999px;
  background: linear-gradient(180deg, rgba(255,253,248,.62), rgba(247,240,229,.5));
  border: 1px solid rgba(92,64,51,.12);
  -webkit-backdrop-filter: blur(14px) saturate(1.2); backdrop-filter: blur(14px) saturate(1.2);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.5); }
.ws-tools-bar .ws-tool-item { border: 0; background: none; }
.ws-tools-bar .ws-tool-item:hover { background: rgba(92,64,51,.08); border: 0; color: var(--c-text); }
.ws-tools-bar .ws-tool-item.on { background: rgba(199,169,104,.2); color: var(--c-accent-deep); }
.ws-tools-bar .ws-tool-sep { background: rgba(92,64,51,.14); }
html.dark .ws-tools-bar { background: linear-gradient(180deg, rgba(255,255,255,.08), rgba(255,255,255,.04));
  border-color: rgba(255,255,255,.12); box-shadow: inset 0 1px 0 rgba(255,255,255,.05); }
html.dark .ws-tools-bar .ws-tool-item:hover { background: rgba(255,255,255,.1); border: 0; }
html.dark .ws-tools-bar .ws-tool-item.on { background: rgba(199,169,104,.2); color: var(--c-accent); }
html.dark .ws-tools-bar .ws-tool-sep { background: rgba(255,255,255,.14); }
#arCats, #arImportCats { padding: 0; border: 0; background: transparent; backdrop-filter: none; -webkit-backdrop-filter: none; gap: 8px; }
#arCats .ar-cat, #arImportCats .ar-cat { padding: 7px 16px; border: 1px solid var(--c-border); border-radius: 999px;
  background: var(--c-bg-card); color: var(--c-text-secondary); font-size: .82em; font-weight: 600; }
#arCats .ar-cat:hover, #arImportCats .ar-cat:hover { background: var(--c-bg); border-color: var(--c-accent); color: var(--c-accent-deep); }
#arCats .ar-cat.sel, #arImportCats .ar-cat.sel { background: var(--c-accent); border-color: var(--c-accent); color: #fff; }
html.dark #arCats .ar-cat.sel, html.dark #arImportCats .ar-cat.sel { color: #1C1917; }
/* ③ 导入文章：整页左对齐（标题行 / 上传框 / 拍照 / 导入规则都靠左）
   ⚠️ 必须带 `#articlePage` 这一层：另有一条同级规则的 `:not(.ar-imp-head)` 版本
   （`#arViewImport .vocab-page:not(.ar-imp-head){max-width:880px;margin:auto}`）权重比单 id 高，
   不加这一层压不动它 —— 实测上传框还会停在 x=379（居中）。 */
#articlePage #arViewImport .vocab-page,
#articlePage #arViewImport .vocab-page:not(.ar-imp-head),
#articlePage #arViewImport .ar-imp-head { max-width: none; margin-left: 0; margin-right: 0; }
#articlePage #arViewImport .ar-imp-head { padding-left: 0; }
/* 内层那几屏（上传 / 拍照 / 我的导入）自己带 24px 左内边距，会让上传框比标题右 24px —— 一起清零，齐左 */
#articlePage #arViewImport .vocab-page:not(.ar-imp-head) { padding-left: 0; }
#arViewImport .imp-upload { text-align: left; }
#arViewImport .imp-actions { justify-content: flex-start; }
#arViewImport .imp-actions-tip { text-align: left; }
#arViewImport .imp-rules { max-width: none; }
/* ④ 文章「我的」：内容左对齐 */
#articlePage #arViewMine .vocab-page.mine-block { max-width: none; margin-left: 0; margin-right: 0; }
#arViewMine .th-mine-tabs { justify-content: flex-start; }
#arViewMine .ar-cards { justify-content: flex-start; }
/* ⑤ 生成题目：缩小 + 底部留空隙；生成小说：整体下移 */
#thGenMount { margin-bottom: 44px; }
#thGenMount .chat-layout { min-height: 430px; }
#thGenMount .chat-messages { max-height: 40vh; }
.ar-story-mount { margin-top: 56px; }

/* ══ 2026-10-07 第八轮：两处宽度收窄（用户 1、2 条）════════════════════════════════════
   ① 导入文章：上传框/导入规则原来是**铺满内容列**的 1210px 大框，文字只占左边一段、右边一大片空 ——
      按用户「缩小宽度、让内容贴合文字」的口径收到 **800px**（站内 .vocab-page 的标准文本列宽），
      左侧对齐不变，几个子视图（上传 / 拍照 / 我的导出）一起跟着收；
   ② 生成小说 / 生成题目：对话容器原来铺满内容列（1186），而里面的消息列上限只有 760，
      于是消息列两侧各留 82px 空白（右侧那片"无效空白"就是它）——
      把容器收到 **1020px** = 左侧会话栏 260 + 消息列 760，**正好贴合**；
      消息区仍是 `overflow-y: auto`（右侧滚动条照旧，用于上下翻看聊天记录）。 */
#articlePage #arViewImport { max-width: 800px; }
.ar-story-mount .chat-layout, #thGenMount .chat-layout { max-width: 1020px; }

/* ══════════════════════════════════════════════════════════════════════════════
   2026-10-07 第十轮（用户五组 13 条）
   ══════════════════════════════════════════════════════════════════════════════ */
/* ── 一 生成题目 ────────────────────────────────────────────────────────────
   ① 滚动条贴住对话框右边缘：原来 .chat-container 左右各有 24px 内边距，
      滚动条落在内边距里侧、看起来没贴边 → 容器右侧内边距归零，把这 24px 挪进消息区自己，
      于是滚动条紧贴对话框右边线，而文字气泡仍有 24px 呼吸位；
   ② 上下留白相等：对话框上边到「真题训练/生成题目/导入题目」那排 = 对话框下边到页面内容底，
      统一 56px（上面靠 #thGenMount 的 margin-top 补，下面靠把本页 .th-main 的下内边距收到 56）。 */
#thGenMount .chat-container { padding-right: 0; }
#thGenMount .chat-messages,
#thGenMount .chat-input-area,
#thGenMount .chat-hint,
#thGenMount .chat-save-area,
#thGenMount .chat-quick { padding-right: 24px; }
/* ⚠️ 给挂载点加 margin-top 没用：它是面板的第一个子节点，外边距会和面板折叠掉（实测间距仍是 36）
   → 改成给面板加 padding-top（padding 不会折叠），这样上间距才真的是 56。 */
#thGenMount { margin-top: 0; margin-bottom: 0; }
#thPanelGen { padding-top: 20px; }
#trainHubPage .th-main { padding-bottom: 56px; }
/* ── 二 生词本 ──────────────────────────────────────────────────────────────
   ① 词表按钮：收起态改成**圆润小正方形**（46×46、圆角 16），整块方钮就是按钮本体；
      展开（.open）仍是向右拉长的列表（280 宽、最高 76vh），里面的收起钮回到 38×38 小方块；
   ② 记单词的单词展示区整体上移 14px；③ 打字界面的单词行上移 10px；
   ④ 工具栏两个新控件的样式（释义开关沿用 .vp-btn-outline；勾选框 = .vp-noconfirm）；
   ⑤ 遮挡释义：给那两栏加 .vp-hide-def，把释义模糊掉。 */
/* 词表按钮（2026-11-01 用户：「图片上那个也非常丑」）：
   收起态不再是 46×46 的白色圆角方块，改成贴在侧栏右缘（left:150）的**细长小竖条**，
   箭头 › / ‹ 与侧栏把手同一套语言；整块竖条就是按钮本体。展开态仍是 280 宽列表。 */
.ws-wl-panel:not(.open) { width: 20px; height: 46px; min-height: 0; max-height: 46px; border-radius: 0 10px 10px 0; }
.ws-wl-panel:not(.open) .ws-wl-toggle { width: 100%; height: 100%; min-height: 0; margin: 0; padding: 0;
  border: 0; border-radius: 0 10px 10px 0; background: transparent; }
.ws-wl-panel:not(.open) .ws-wl-toggle svg { width: 12px; height: 12px; }
.ws-wl-panel:not(.open) .ws-wl-toggle:hover { background: var(--c-accent-light); color: var(--c-accent-deep); }
.ws-wl-panel.open { width: 280px; height: auto; max-height: 76vh; }
.ws-wl-panel.open .ws-wl-toggle { width: 30px; height: 30px; min-height: 30px; margin: 8px 8px 8px auto;
  border: 1px solid var(--c-border); border-radius: 10px; background: var(--c-bg); }
.ws-wl-panel.open .ws-wl-toggle svg { transform: rotate(180deg); }   /* › 变 ‹ ：点它收起 */
#wsStudyView.ws-home .ws-stage-col { margin-top: -14px; }
#wsTypingPlay .ws-type-stage { margin-top: -10px; }
.vp-btn-outline[aria-pressed="true"] { background: var(--c-accent); border-color: var(--c-accent); color: #fff; }
html.dark .vp-btn-outline[aria-pressed="true"] { color: #1C1917; }
.vp-noconfirm { display: inline-flex; align-items: center; gap: 6px; margin-left: 10px;
  font-size: .78em; color: var(--c-text-muted); cursor: pointer; user-select: none; white-space: nowrap; }
.vp-noconfirm input { width: 15px; height: 15px; margin: 0; accent-color: var(--c-accent); cursor: pointer; }
.vp-hide-def .vl-meaning { filter: blur(6px); opacity: .55; user-select: none; }
/* ── 三 导入文章：外框左对齐、框内图文**居中**（2026-10-07 用户指出上轮做反了）── */
#articlePage #arViewImport .imp-upload { text-align: center; }
#articlePage #arViewImport .imp-actions { justify-content: center; }
#articlePage #arViewImport .imp-actions-tip { text-align: center; }
/* ── 四 生成小说：对话框上下留白相等 ──────────────────────────────────────────────
   实测底部那条链：storyMount(8) + .vocab-page(40) + .ws-content(48) + #articlePage(24) = 120（再多 22 由容器自身）
   → 把中间那层多余的 40px 去掉，剩下 48 + 24 = 72；上面靠 margin-top 补到同一数值（实测 64 + 8 = 72）。 */
/* 让故事视图吃掉内容列的剩余高度，对话框在其中**垂直居中** → 上边到标题、下边到页面底自然相等。
   （之前用固定 margin-top 猜数字：底部那片空白其实是"内容列撑到视口底"的余量，随窗口高度变，猜不准。） */
#arViewStory { flex: 1 1 auto; display: flex; flex-direction: column; min-height: 0; }
#arViewStory .vocab-page { flex: 1 1 auto; display: flex; flex-direction: column; min-height: 0; padding-bottom: 0; }
#arViewStory .ar-story-mount { flex: 1 1 auto; display: flex; flex-direction: column; justify-content: center;
  margin: 0; min-height: 0;
  /* 实测居中后"上"比"下"还多 22px（标题那几行的行高/外边距造成的不对称）：
     给居中盒补 22px 下内边距 → 内容整体上移 11px，上下就都是 99px。 */
  padding-bottom: 22px; }
/* 挂载点之外还有内容列 48 + 页面 24 的底部内边距，会让"下边距"比"上边距"多 72px ——
   故事视图在台前时把它们也归零，上下才是真的相等（实测差值从 72 收到 0）。 */
#articlePage:has(#arViewStory:not(.hidden)) .ws-content { padding-bottom: 0; }
#articlePage:has(#arViewStory:not(.hidden)) { padding-bottom: 0; }
/* ── 五 文章我的「收藏文章 / 保存文章」滑动开关：轨道改白底，和别处开关统一 ── */
.th-mine-favswitch { background: var(--c-white); border-color: var(--c-border); }
html.dark .th-mine-favswitch { background: #262220; border-color: #3A322C; }

/* ══ 2026-10-07 第十一轮（用户追加/修正）════════════════════════════════════════════
   ① 生成题目对话框**上下小幅拉长**（430 → 490），消息区上限同步放到 46vh；
      右缘贴边与上下留白相等不受影响（那两条是 padding 定的，不随高度变，稍后实测复核）；
   ② 记单词单词区再上移（-14 → -26px）、打字单词再上移（-10 → -18px）；
   ③ 释义遮挡：全局开关 = 默认状态；单条点一下临时显示、再点遮挡（`.vp-def-shown`）；
   ⑤ 生成小说对话框：滚动条同样贴住对话框右缘（和生成题目一套做法）。 */
#thGenMount .chat-layout { min-height: 490px; }
#thGenMount .chat-messages { max-height: 46vh; }
#wsStudyView.ws-home .ws-stage-col { margin-top: -26px; }
#wsTypingPlay .ws-type-stage { margin-top: -18px; }
.ar-story-mount .chat-container { padding-right: 0; }
.ar-story-mount .chat-messages,
.ar-story-mount .chat-input-area,
.ar-story-mount .chat-hint,
.ar-story-mount .chat-save-area,
.ar-story-mount .chat-quick { padding-right: 24px; }
/* 单条翻转（2026-10-07 用户追加）：**两种状态都能点** ——
   遮挡态点一下 = 临时看这条；显示态点一下 = 单独把这条藏起来；再点还原。
   同一个 `.vp-def-shown` 类，方向由宿主有没有 `.vp-hide-def` 决定。 */
#wsTabVocab .vl-item, #wsTabPhrases .vl-item { cursor: pointer; }
.vp-hide-def .vl-item.vp-def-shown .vl-meaning { filter: none; opacity: 1; }
#wsTabVocab:not(.vp-hide-def) .vl-item.vp-def-shown .vl-meaning,
#wsTabPhrases:not(.vp-hide-def) .vl-item.vp-def-shown .vl-meaning { filter: blur(6px); opacity: .55; user-select: none; }
#wsTabVocab .vl-item.vp-def-shown,
#wsTabPhrases .vl-item.vp-def-shown { background: rgba(90, 110, 69, .06); border-radius: 10px; }
html.dark #wsTabVocab .vl-item.vp-def-shown,
html.dark #wsTabPhrases .vl-item.vp-def-shown { background: rgba(163, 185, 140, .10); }

/* ── 删除确认小浮层（2026-10-07 用户第 4 条）：内置弹层、出现在删除按钮左侧 ── */
.vp-del-pop { position: fixed; z-index: 400; width: 236px; padding: 12px 14px 10px;
  background: var(--c-bg-card); border: 1px solid var(--c-border); border-radius: 14px;
  box-shadow: 0 14px 34px rgba(41, 37, 36, .20); }
.vp-del-pop p { margin: 0 0 10px; font-size: .84em; line-height: 1.6; color: var(--c-text); }
.vp-del-pop-btns { display: flex; justify-content: flex-end; gap: 8px; }
.vp-del-pop-btns button { font: inherit; font-size: .78em; font-weight: 600; padding: 6px 14px; border-radius: 999px;
  border: 1px solid var(--c-border); background: var(--c-bg); color: var(--c-text-secondary); cursor: pointer; }
.vp-del-pop-btns button:hover { border-color: var(--c-accent); color: var(--c-accent-deep); }
.vp-del-pop-btns .vp-del-ok { background: var(--c-danger); border-color: var(--c-danger); color: #fff; }
.vp-del-pop-btns .vp-del-ok:hover { filter: brightness(1.06); color: #fff; }
html.dark .vp-del-pop-btns button { background: #2A2623; border-color: #3F3A37; color: #D6D3D1; }
html.dark .vp-del-pop-btns .vp-del-ok { background: var(--c-danger); border-color: var(--c-danger); color: #1C1917; }

/* ── 「不再提示」旁边的小问号 + 解释浮层（2026-10-06 第三十九轮 用户要求）──────────────
   用户口径：生词本 / 词组本（全部档位）的「不再提示」旁边给一颗小问号，点开解释它是干什么的。
   问号做成 18px 小圆钮，紧跟在勾选框那一组右边；解释浮层沿用删除确认那套皮肤（同 z-index / 圆角 / 阴影），
   只是里面只有一段话 + 一颗「知道了」。 */
.vp-help { flex: none; align-self: center; width: 18px; height: 18px; min-height: 18px; padding: 0; margin: 0 0 0 2px;
  display: inline-flex; align-items: center; justify-content: center; border-radius: 50%;
  border: 1px solid var(--c-border); background: var(--c-bg-card); color: var(--c-text-muted);
  font: inherit; font-size: .68em; font-weight: 700; line-height: 1; cursor: pointer;
  transition: border-color .18s ease, color .18s ease, background-color .18s ease; }
.vp-help:hover, .vp-help:focus-visible { border-color: var(--c-accent); color: var(--c-accent-deep); background: var(--c-accent-light); }
.vp-help:active { transform: scale(.94); }
html.dark .vp-help { background: #2A2623; border-color: #3F3A37; color: #A8A29E; }
/* 浮层：定宽 268（窄屏收到视口 - 24），定位由 vpNoConfirmHelp() 给 left/top（优先贴按钮左侧） */
.vp-hint-pop { position: fixed; z-index: 400; width: 268px; max-width: calc(100vw - 24px); padding: 12px 14px 10px;
  background: var(--c-bg-card); border: 1px solid var(--c-border); border-radius: 14px;
  box-shadow: 0 14px 34px rgba(41, 37, 36, .20); text-align: left; }
.vp-hint-pop p { margin: 0 0 6px; font-size: .82em; line-height: 1.65; color: var(--c-text); }
.vp-hint-pop p:last-of-type { margin-bottom: 10px; }
.vp-hint-pop b { color: var(--c-accent-deep); font-weight: 600; }
.vp-hint-btns { display: flex; justify-content: flex-end; }
.vp-hint-btns button { font: inherit; font-size: .78em; font-weight: 600; padding: 6px 14px; border-radius: 999px;
  border: 1px solid var(--c-border); background: var(--c-bg); color: var(--c-text-secondary); cursor: pointer; }
.vp-hint-btns button:hover { border-color: var(--c-accent); color: var(--c-accent-deep); }
html.dark .vp-hint-btns button { background: #2A2623; border-color: #3F3A37; color: #D6D3D1; }

/* ══ 2026-10-06 第四十轮（用户：手机版生成题目 / 生成小说 全乱了）════════════════════════════
   手机档这两页原来有两处对不上：
     ① `.chat-input-area` 是 `position: fixed; bottom: 0`（3692 行那条，本来是给「整页版」对话页做的），
        而生成题目 / 生成小说是把对话**嵌在卡片里**用的 → 输入条跑到卡片外面、还被 56px 的手机底部导航
        整条盖住（实测输入框中心命中的是 `NAV.phone-tab-bar`）→ 看起来"输入框不见了"；
     ② `.chat-sidebar`（会话列表 = 对话记录）在手机档被 `display: none`（3689 行）→ 对话记录整个没了。
   修法：
     · 输入条回到卡片内（与平板第三十五轮同一套：卡片定高 + 消息区 flex:1 + 输入条贴卡片底）；
     · 会话侧栏在手机档改成**抽屉**：点顶部那颗 ⋯ 展开（`.chat-layout.sess-open`）、点外面/选中一条自动收起
       （JS 见 chatSessToggle / chatSessClose）；
     · 顶部那条 `.chat-mbar` 只在手机档出现：左边 ⋯（对话记录）、右边 ＋（创建新对话）。 */
.chat-mbar { display: none; }
/* ⚠️ 卡片里的 `.chat-container` 是 `.chat-main` 的弹性子项，默认 `min-width: auto` =
   内容最小宽度 —— 窄屏（实测 360×640 的小说卡）里它比卡片还宽、又被卡片的 `overflow: hidden`
   从右边裁掉：顶部条右侧那颗 ＋ 正好落在裁掉的区域里，**看得见却点不到**（elementsFromPoint 里
   根本没有它）。给它 `min-width: 0` 让它老实收进卡片，右边缘不再被裁。 */
#thGenMount .chat-container, .ar-story-mount .chat-container { min-width: 0; }
/* 手机档还要再收一步：`.chat-main` 是 column 弹性盒 + `align-items:center`（容器靠 `margin:0 auto` 居中），
   于是 `.chat-container` 不是撑满而是 **shrink-to-fit** —— 窄屏（实测 360×640 的小说卡）里它按内容
   要 321px、比卡片(276)还宽，右边缘被卡片的 `overflow:hidden` 裁掉：提示块/消息区/选项排/输入区
   右端都被切掉一截，顶部条右侧那颗 ＋ 更是整个落在裁掉的区域里（看得见、点不到，
   `elementsFromPoint` 里根本没有它）。手机档让它老实撑满卡片即可。 */
html.force-phone #thGenMount .chat-container,
html.force-phone .ar-story-mount .chat-container { align-self: stretch; max-width: 100%; }
html.force-phone .chat-mbar { display: flex; align-items: center; justify-content: flex-end; gap: 8px; padding: 8px 0 2px; }
html.force-phone .cmb-btn { width: 34px; height: 34px; min-height: 34px; padding: 0; flex: none;
  display: inline-flex; align-items: center; justify-content: center; border-radius: 12px;
  border: 1px solid var(--c-border); background: var(--c-bg-card); color: var(--c-text-secondary); cursor: pointer;
  transition: border-color .18s ease, color .18s ease, background-color .18s ease; }
html.force-phone .cmb-btn:hover { border-color: var(--c-accent); color: var(--c-accent-deep); background: var(--c-accent-light); }
html.force-phone .cmb-btn:active { transform: scale(.94); }
html.force-phone .cmb-btn svg { width: 18px; height: 18px; }
html.dark .cmb-btn { background: #2A2623; border-color: #3F3A37; color: #A8A29E; }
/* 卡片要成为抽屉的定位参照（原来是 static，absolute 抽屉会认到页面上）。
   ⚠️ 必须同时写 `top: auto`：基础 `.chat-layout` 是"整页固定"的 `position: fixed; top: 52px`
   （见第 4262 行），而第 3688 行那条 `html.force-phone .chat-layout { top: 52px }`（优先级 0,2,1）
   比内嵌挂载点那条 `top: auto`（`.ar-story-mount .chat-layout`，0,2,0）高 —— 这里把 position 改成
   relative 后 `top: 52px` 又活过来，卡片会在**自己的框里整体下坠 52px**：框顶空出一条白带、
   卡片底部同时溢出框 52px（实测手机 390：卡框顶 258，卡片实际从 310 开始 = 纯空白 52px）。 */
html.force-phone #thGenMount .chat-layout,
html.force-phone .ar-story-mount .chat-layout { position: relative; top: auto; }
/* 输入条：手机档也从「贴屏幕底的固定条」改回**卡片内的一行**（跟平板第三十五轮同一套口径）。
   原因：`bottom: 0` 时它正好被 56px 的手机底部导航整条压住（实测输入框中心命中的是
   `NAV.phone-tab-bar`）→ 看起来"输入框不见了"；而只把它抬到导航之上（bottom: 60）又会去盖住
   卡片里的选项排（实测选项按钮被输入条压住点不到）。所以走"卡片定高 + 消息区 flex:1 + 输入条贴卡片底"，
   这样输入条**永远在卡片里、也不会盖住任何东西**。
   高度按两页各自的顶部 chrome 分别标定（实测 390×844）：题目卡顶 223、小说卡顶 277，
   都留出底部 56px 导航 + 呼吸位，`min-height: 300px` 兜住 360×640 这种小屏。 */
html.force-phone #thGenMount .chat-layout { position: relative; height: calc(100vh - 300px); min-height: 260px; }
html.force-phone .ar-story-mount .chat-layout { position: relative; height: calc(100vh - 365px); min-height: 260px; }
html.force-phone #thGenMount .chat-messages,
html.force-phone .ar-story-mount .chat-messages { max-height: none; padding-bottom: 12px; }
/* 提示块在手机档限高、内部可滚：小说那块的文案在 360 宽下能到 203px，
   不限高的话小屏上"固定高度"的卡片会被它顶爆（输入条就被裁掉了）。 */
html.force-phone #thGenMount .chat-hint,
html.force-phone .ar-story-mount .chat-hint { max-height: 22vh; overflow-y: auto; }
html.force-phone #thGenMount .chat-input-area,
html.force-phone .ar-story-mount .chat-input-area { position: static; left: auto; right: auto; bottom: auto; }

/* ── 第四十四 / 四十五轮（2026-10-06 用户：手机版生成小说，对话框上方有很大一块空白 → 再定口径：
      「对话框的上面要靠近生成小说四个字，下面要贴近底部导航栏」）────────────────────────────
   改前实测手机 390×844、空会话时，卡顶到标题那一段全是空白，来源有三段：
     ① `top: 52px` 泄漏（见上面那条）＝ 52px；
     ② `.ar-story-mount` 是 `justify-content: center`（桌面那套"上下留白相等"，见第 8593 行），
        手机档卡片被它垂直居中 → 卡顶又落在 mount 顶下 90px；
     ③ 卡片里 `.chat-messages` 是 `flex: 1`，空会话时它把剩余高度全吃掉 —— 145px 纯空白。
   现在手机档的口径（用户第 45 轮明确）：卡片就**铺满标题与底部导航之间那段**：
     · 顶端对齐（不居中）→ 卡顶 = mount 顶 = 168px（标题 `.lib-hero` 底 154 + 它自己的 margin 14）；
       ⚠️ 选择器必须带 `#arViewStory`：居中是第 8593 行 `#arViewStory .ar-story-mount` 定的
       （ID + 类 = 1,2,0），光写 `html.force-phone .ar-story-mount`（0,2,1）压不住它。
     · 卡高 = 屏幕高 - 232px（= 顶部 chrome 168 + 底部导航 56 + 8px 呼吸位）
       → 卡底离底部导航恒定 8px（实测 390×844：卡 168→780，导航顶 788；360×640、414×896 同）。
       消息区照旧 `flex: 1`（有消息就把它填满、多了内部滚），输入条照旧贴卡片底。
   题目卡（#thGenMount）见下面那段（第四十六轮）。 */
html.force-phone #arViewStory .ar-story-mount { justify-content: flex-start; }
html.force-phone .ar-story-mount .chat-layout {
  height: calc(100dvh - 232px); min-height: 0; max-height: none; }

/* ── 第四十六轮（2026-10-06 用户回「改」：题目卡也按小说那套 —— 上贴上面那排按钮、下贴底部导航）────
   实测手机 390×844 的「生成题目」页：`h1.th-title`（题目训练）底 119 → 那排胶囊 `.th-seg`
   （真题训练 / 生成题目 / 导入题目）137~177 → `#thPanelGen` 顶 203（= 胶囊的 `margin-bottom: 26px`，
   见第 8158 行）→ 它自己的 `padding-top: 20px`（第 8559 行）→ 卡顶 223；卡底 767，
   离底部导航顶 788 还差 21px（小说那边是 8px）。
   与小说同一口径后：
     · 去掉这层 20px 内边距 → 卡顶 203，紧跟在胶囊那排下面（间距就是胶囊自己的 26px）；
     · 卡高 = 屏幕高 - 267px（= 顶部 chrome 203 + 底部导航 56 + 8px 呼吸位）
       → 卡底离底部导航恒定 8px（实测 390×844：卡 203→780，导航顶 788；360×640：卡 203→576，导航顶 584）。
   消息区仍是 `flex: 1`（有消息填满、多了内部滚），输入条仍是贴卡片底那一行。
   ⚠️ 只在手机档，且只针对 `#thPanelGen`（题目页另外两个面板、别的页面都不受影响）。 */
html.force-phone #thPanelGen { padding-top: 0; }
html.force-phone #thGenMount .chat-layout {
  height: calc(100dvh - 267px); min-height: 0; max-height: none; }
/* ⚠️ 极窄屏兜一档：<336px 时那排胶囊（真题训练 / 生成题目 / 导入题目）会折成**两行**
   （实测 320px：`.th-seg` 高 40 → 87，卡顶 203 → 249），上面那 267 就不够了 ——
   卡底会跑到导航下面 38px（输入条被导航盖住，正是第四十轮那个坑）。窄屏改按 249 + 56 + 8 = 313 算。 */
@media (max-width: 335px) {
  html.force-phone #thGenMount .chat-layout { height: calc(100dvh - 313px); }
}
/* 会话侧栏 → 抽屉（默认 display:none 那条仍在，靠 .sess-open 打开）。
   ⚠️ top 要让开顶部那条 44px 的 `.chat-mbar`，否则抽屉一开就把 ⋯ / ＋ 两颗按钮压住、
      再点 ⋯ 收不起来（实测 360×640 就是这个毛病）。 */
html.force-phone .chat-layout.sess-open .chat-sidebar { display: flex; position: absolute; left: 8px; right: 8px; top: 56px;
  max-height: 56%; min-height: 0; z-index: 30; padding: 4px; border-radius: 16px; border: 1px solid var(--c-border);
  background: var(--c-bg-card); box-shadow: 0 18px 44px rgba(41, 37, 36, .22); overflow: hidden; }
html.force-phone .chat-layout.sess-open .chat-sidebar .session-list { flex: 1; min-height: 0; overflow-y: auto; }
/* 抽屉里**只放历史会话**（2026-10-06 第四十三轮 用户要求）：侧栏顶部那颗「+ 新对话」在手机档收掉 ——
   新建对话交给旁边那颗加号（`.chat-mbar .cmb-new`），它点了直接弹词库选择。
   平板/电脑档的侧栏是老样子（那颗 ＋ 还在）。 */
html.force-phone .chat-layout.sess-open .chat-sidebar .sidebar-head { display: none; }
html.dark .chat-layout.sess-open .chat-sidebar { background: #262220; border-color: #3F3A37; }

/* ── 保存题目 / 保存训练：行内「对错文字标记」（2026-10-07 第十二轮修正口径）──────────
   不再点按钮，直接照记录渲染：没作答 = 灰字「未选」；答错 = 「A/C」（我的答案红、标准答案绿）；
   答对 = 「C/C」两个字符都绿。 */
.qd-ans { display: inline-flex; align-items: center; gap: 1px; flex: none; order: 2;
  font-size: .76em; font-weight: 700; font-variant-numeric: tabular-nums; letter-spacing: .03em; white-space: nowrap; }
.qd-ans .qd-ans-sep { color: var(--c-text-muted); font-weight: 600; }
.qd-ans[data-r="bad"] .qd-ans-m { color: #DC2626; }
.qd-ans[data-r="bad"] .qd-ans-k { color: #16A34A; }
.qd-ans[data-r="ok"] .qd-ans-m,
.qd-ans[data-r="ok"] .qd-ans-k { color: #16A34A; }
.qd-ans[data-r="mine"] .qd-ans-m { color: #DC2626; }
.qd-ans-none { color: var(--c-text-muted); font-weight: 600; }
html.dark .qd-ans[data-r="bad"] .qd-ans-m { color: #F87171; }
html.dark .qd-ans[data-r="bad"] .qd-ans-k,
html.dark .qd-ans[data-r="ok"] .qd-ans-m,
html.dark .qd-ans[data-r="ok"] .qd-ans-k { color: #4ADE80; }
html.dark .qd-ans[data-r="mine"] .qd-ans-m { color: #F87171; }

/* ══ 2026-10-07 第十二轮（用户修正三条）════════════════════════════════════════════
   ① 生成题目：对话框**下边缘钉住不动**，只把上边缘往上抬 —— 高度 490 → 526，配 margin-top -36
      把这 36px 全花在上边（实测 chat.bottom 755 不变），与「真题训练/生成题目/导入题目」那排的
      间距从 56 收到 20；手机档（≤768 或 force-phone）仍按 460 做视口自适应，不加这一段。
   ② 记单词单词区再上移（-26 → -42）、打字记词再上移（-18 → -34）；手机预览档给打字列补到 -42，
      让两页的单词中心落在同一条水平线上。
   ③ 对错标记由「两枚按钮」改成**文字标识**（见上面 .qd-ans）。 */
@media (min-width: 769px) {
  html:not(.force-phone) #thGenMount .chat-layout { min-height: 526px; margin-top: -36px; }
}
html.force-desktop #thGenMount .chat-layout,
html.force-tablet #thGenMount .chat-layout { min-height: 526px; margin-top: -36px; }
#wsStudyView.ws-home .ws-stage-col { margin-top: -42px; }
#wsTypingPlay .ws-type-stage { margin-top: -34px; }
html.force-phone #wsTypingPlay .ws-type-stage { margin-top: -42px; }

/* ══ 2026-10-07 第十三轮（用户两条）════════════════════════════════════════════════
   ① 精读训练（保存训练 / 已做精读）横栏里的 `A/C` 标记：从右端挪到**左边左对齐** ——
      DOM 上紧跟「题型」格，并把 order 归 0（不再用 order:2 顶到右端）；
   ② 记单词那一屏的单词再上移约 1cm（≈38px）：实测这条链上「位移 ÷ 2 = 视觉移动」
      （负 margin 也会把容器撑高同样多，居中后只剩一半）→ 记单词 -42 → **-118**、打字 -34 → **-110**
      （手机预览档 -118），两页单词中心仍落在同一条水平线上。 */
.tr-rows .qd-ans { order: 0; }
#wsStudyView.ws-home .ws-stage-col { margin-top: -64px; }
#wsTypingPlay .ws-type-stage { margin-top: -110px; }
html.force-phone #wsTypingPlay .ws-type-stage { margin-top: -118px; }

/* ══ 2026-10-07 第十九轮（用户：两条上边线对齐）════════════════════════════════════
   要求：「记单词」的【不认识 / 认识】按钮行**上边线**，与「打字记词」的**状态框**上边线同高；
   下边线不管。两页都是"贴面板底"的布局，但两块本身高度不同（按钮行 50 / 状态框 80），
   所以必须让它们**离面板底的距离相同**才能让上边线对齐：
     · 打字状态框：面板底 - 视图下内边距 24 - 框高 80 = 面板底 - 104；
     · 记单词按钮行：给 .ws-bottom 加 54px 下边距 → 面板底 - 54 - 50 = 面板底 - 104 ✓（任意面板高度下都成立）；
     · 同时把舞台列的负 margin 从 -118 收到 -64：负 margin 会让列变高、行下移，
       两者一起改正好抵掉 —— 单词位置**一点没动**（实测仍是 395，与打字页 396 对齐）。 */
#wsStudyView.ws-home .ws-bottom { margin-bottom: 54px; }
/* 面板底统一以后（见 JS 那两处调换），打字页的舞台要按新面板高度补回单词位置：
   面板矮了 70px → 单词会上移 35px；而负 margin 每 +2px 单词下移 1px → mt 由 -110 放到 -40。
   手机两轨各自的面板矮 58px → +58，底部两行的距离也不同，一并写在下面几条里。 */
#wsTypingPlay .ws-type-stage { margin-top: -40px; }
@media (max-width: 768px) {
  #wsStudyView.ws-home .ws-stage-col { margin-top: -81px; }
  #wsStudyView.ws-home .ws-bottom { margin-bottom: 37px; }
  #wsTypingPlay .ws-type-stage { margin-top: -52px; }
}
/* 强制手机（预览）档：状态框仍是 80 高 + 24 下内边距，所以底部两行的距离与电脑档一致；
   列 / 行沿用上面电脑档的数值，这里只留打字那一条把单词位置补回来。 */
html.force-phone #wsTypingPlay .ws-type-stage { margin-top: -60px; }

/* ══ 2026-10-06 第三十二轮（用户：平板端「记单词」界面三处尺寸）══════════════════════════
   用户 3 条：① 单词太大 → 缩小；② 下面解释单词的卡片框 → 做大；③「不认识 / 认识」与
   「返回上一步 / 下一个单词」那两行 → 往下放一些，给释义框腾位置。**只动平板档**
   （真机 769–1180px + 预览类 html.force-tablet），桌面与手机一个像素都不动。
   写法沿用这页的老规矩：同一组取值在媒体查询与预览类里各写一遍（不能把 @media 与类选择器 OR 在一起，
   3223 那条注释解释过原因）。
   ⚠️ 这一段必须写在第十九轮那两条对齐规则**之后**：`.ws-bottom` 的 margin-bottom 选择器权重相同（1,2,1），
      只能靠源序取胜，写在前面会被那句 54px 压掉。
   取值依据（1024×1366 竖屏实测，改前 → 改后）：
     · `.ws-word` 字号 89.6px → 70.4px；释义框（`.ws-reveal`）306 高 → 撑满到卡片底；
     · 底部两行整体下移 36px（面板底 - 54 - 50 → 面板底 - 18 - 50）。 */
@media (min-width: 769px) and (max-width: 1180px) {
  :root { --ws-word-fs: min(9.5vw, 18vh, 4.4em); }   /* 5.6em → 4.4em：1024 宽下 89.6px → 70.4px */
  /* 释义框撑满卡片剩下的高度（12px 呼吸位留给底部按钮），单词小了之后腾出来的空间全给它 */
  #wsStudyView.ws-home .ws-card.revealed .ws-reveal { flex: 1 1 auto; margin-bottom: 12px; }
  #wsStudyView.ws-home .ws-bottom { margin-bottom: 18px; }   /* 54px → 18px：底部两行一起下移 36px */
}
html.force-tablet { --ws-word-fs: min(9.5vw, 18vh, 4.4em); }
html.force-tablet #wsStudyView.ws-home .ws-card.revealed .ws-reveal { flex: 1 1 auto; margin-bottom: 12px; }
html.force-tablet #wsStudyView.ws-home .ws-bottom { margin-bottom: 18px; }

/* ══ 2026-10-06 第三十三轮（用户：平板端阅读/做题界面返回键会被挤出左边界）════════════════
   现象（1024×1180 实测）：平板档「阅读文章 / 做题」的顶栏是 `justify-content: center` 的弹性行，
   里面 10 颗按钮的**最小内容宽合计 851px**；一旦视口窄于约 880px（iPad mini 768 / iPad 820·834 竖屏、
   以及窄窗口的平板预览档），这一行就装不下 —— 居中布局让溢出**左右各分一半**：最左边的返回键被推到
   屏幕外（800px 时 l=-40、769px 时 l=-56，元素中心已在屏幕外 → 点不到），最右边那颗也一起出界。
   顶栏是 `position: fixed`，页面本身没有横向滚动，所以出界的那截**永远拉不回来**。
   修法（只动平板档，桌面与手机一个像素不动）：
     · `justify-content: flex-start` —— 不支持 `safe` 关键字的浏览器一律左对齐，返回键永远贴左可见；
     · 紧跟一句 `justify-content: safe center` —— 支持的浏览器（实测本机 Chromium 支持）够宽时仍居中，
       装不下时自动退化成左对齐（1024/1180 宽的实测值与改前**完全一致**，所以看相不变）；
     · `overflow-x: auto` + 子元素 `flex: 0 0 auto` —— 装不下的按钮改成**横向滑动**去看，不再被推出屏幕；
       滚动条隐藏（`scrollbar-width: none` + `::-webkit-scrollbar`），避免固定条上多出一条灰杠。
   ⚠️ 只挂 `#readingPage > .topbar`：手机「更多」面板（`.phone-more-sheet`）是它的**兄弟节点**，不受影响。 */
@media (min-width: 769px) and (max-width: 1180px) {
  #readingPage > .topbar {
    justify-content: flex-start;
    justify-content: safe center;
    overflow-x: auto; overflow-y: hidden;
    scrollbar-width: none; -ms-overflow-style: none; -webkit-overflow-scrolling: touch;
  }
  #readingPage > .topbar::-webkit-scrollbar { display: none; }
  #readingPage > .topbar > * { flex: 0 0 auto; }
}
html.force-tablet #readingPage > .topbar {
  justify-content: flex-start;
  justify-content: safe center;
  overflow-x: auto; overflow-y: hidden;
  scrollbar-width: none; -ms-overflow-style: none; -webkit-overflow-scrolling: touch;
}
html.force-tablet #readingPage > .topbar::-webkit-scrollbar { display: none; }
html.force-tablet #readingPage > .topbar > * { flex: 0 0 auto; }

/* ══ 2026-10-06 第三十四轮（用户：平板端精读训练六个类型变成一列）════════════════════════
   现象（1024×1366 实测）：科目页切「精读训练」后，六个类型卡片排成 **6 行 1 列、全部挤在左边**
   （`.sh-items` 只有 200px 宽、网格列就是 `206px` 一列），而桌面是 2 行 3 列。
   根因有两层：
     ① `shRender()` 精读模式会给 `.sh-body` 加 `.solo`（`grid-template-columns: minmax(0,1fr)`，7822 行），
        用意是"筛选区隐藏了，列表占满整行"；但平板档为了收窄左侧筛选列写了
        `html.force-tablet .sh-body { grid-template-columns: 200px minmax(0,1fr) }`（8055 行）——
        权重 (0,2,1) **高过** `.sh-body.solo` 的 (0,2,0)，于是 solo 失效，列表掉进 200px 那一列。
        真机上 App 在 769–1024 会自动挂 `force-tablet`，所以真平板同样中招（实测 900/1024 都一样）。
     ② 网格那边 `.sh-items .train-type-grid` 用的是 `repeat(auto-fill, minmax(206px,1fr))`，容器修好后
        在 950px 宽里会排成 4 列 —— 用户要的是**两行三列**，所以平板档（769–1079）固定成 3 列。
   修法（只动平板档；≥1080 的桌面那条「3 列 + 卡片放大一档」照旧，手机两轨保持两列）：
     · 让 solo 在强制平板档重新赢回来；
     · 平板档 769–1079 的网格固定 `repeat(3, minmax(0,1fr))`。 */
html.force-tablet .sh-body.solo { grid-template-columns: minmax(0, 1fr); }
@media (min-width: 769px) and (max-width: 1079px) {
  html:not(.force-phone) .sh-items .train-type-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; }
  html.force-tablet .sh-items .train-type-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; }
}

/* ══ 2026-10-06 第三十五轮（用户：平板端生成题目/生成小说 的输入框与选项排）══════════════════
   用户 3 条：① 输入框固定在**整个卡片框里面**；② AI 给出的可点按钮固定在**聊天框的上方**；③ UI 排版做个适配。
   现象（1024×1366 实测，改前）：
     · 生成题目：卡片 `#thGenMount .chat-layout` 只到 y=741（高 526），而输入框是
       `position: fixed`（平板档 3586 行那句）钉在**视口底部** 1281~1366、`left: 195px` —— 
       整块跑到卡片框外面 540px 处，跟卡片完全脱开；
     · 生成小说：卡片高 1314（比视口还高 136），输入框同样 fixed 在 1301~1366，**压在**卡片内容上。
   两条都是同一个原因：平板档把 `.chat-input-area` 改成 fixed（本意是给"整页版"对话页做贴底输入条），
   但「生成题目 / 生成小说」是把整页对话**嵌进卡片**用的（`#thGenMount` / `.ar-story-mount` 里
   `.chat-layout` 已经收成 `position: static` + 描边圆角的卡片），贴屏幕底的输入条就出框了。
   修法（只挂 `html.force-tablet`：真平板 769–1024 由 App 自动挂这个类；≥1025 走桌面布局、
   输入框本来就是卡片内的一行，不需要动；手机档的贴底输入条是另一套设计，也不动）：
     · 输入框回到卡片内的正常流（`position: static`）+ 给卡片一个**确定的、贴合平板视口的高度**：
       消息区 `flex: 1` 吃掉中间、内部滚动，选项排与输入框自然贴住卡片底边；
     · 消息区原来那 60px 下内边距是给"贴屏幕底的固定输入框"让位的（3588 行），输入框进卡片后收回 20px；
     · `max-height: none` —— 卡片已经是定高，消息区不用再按 vh 截断（原 46vh / 58vh）。 */
html.force-tablet #thGenMount .chat-layout,
html.force-tablet .ar-story-mount .chat-layout {
  height: calc(100vh - 300px);
  min-height: 420px;
}
html.force-tablet #thGenMount .chat-messages,
html.force-tablet .ar-story-mount .chat-messages {
  max-height: none;
  padding-bottom: 20px;
}
html.force-tablet #thGenMount .chat-input-area,
html.force-tablet .ar-story-mount .chat-input-area {
  position: static; left: auto; right: auto; bottom: auto;
}

/* ══ 2026-10-06 第三十六轮（用户：平板端「我的 → 题目 / 训练」多出一颗返回键、压住生词本）══════
   现象（1024×1366 实测）：这两页各留了一条**老工具条** `#donePage > .topbar` / `#trainDonePage > .topbar`
   —— 里面只剩一颗 `backOneLevel()` 返回键（2026-10-06 那轮把分类切换挪进二级菜单后就只剩它了）。
   平板档 `.topbar` 是 `position: fixed; z-index: 100`，而一级导航 `.wl-topbar` 只有 50、整条占 0~65：
   老工具条(16~60, x 482~542)正好压在一级导航那排链接上 —— **与「生词本」重叠 672px²**
   （实测 `elementFromPoint(生词本中心)` 命中的就是 `DIV.topbar`），点进去还会被它吃掉。
   第二十九轮已经给手机两轨与桌面档收掉过这条老工具条（8899 / 8907 / 3907 行），**只有平板档漏了**。
   修法（与另外两轨同一口径）：平板档整条隐藏；返回由一级导航左上角那颗同款返回键承担
   （语义一样是「退一级」）；顺手把页面 padding-top 从 52 补到 68（与手机档同值），
   让内容起点让开 65px 高的一级导航 —— 原来 52 是照着老工具条的高度留的，工具条收掉后就不够了。 */
html.force-tablet #donePage > .topbar,
html.force-tablet #trainDonePage > .topbar { display: none; }
html.force-tablet #donePage,
html.force-tablet #trainDonePage { padding-top: 68px; }

/* ══ 2026-10-06 第三十八轮（用户：手机版 ⋯ 面板里四个按钮不统一）══════════════════════════
   现象（真机 390 实测，记单词 / 打字记词两页一样）：点右上角「⋯」展开的面板 `#wsToolbar` 是
   `flex-direction: column; align-items: stretch` 且带 `min-width: 240px`（6399 行那条），于是
   「查词」与「切换（#wsModeBtn）」被拉成 **222px 的大长条**，而「UK / 音效」两个下拉是 **66 / 74px**
   的内容宽 —— 四个不一样，面板也被最宽那个撑到 240px。
   另外 `#wsModeBtn` 里的 emoji 与「新学 / 复习」文字在手机档被整段藏掉（2579 行 ≤768 媒体查询 +
   3351 行 force-phone 的 `!important`），面板里那一行就只剩一个空框（用户看到的就是"只有图标、没有文字"）。
   修法（只动手机档的**面板**，顶栏平铺那条老规则不动）：
     · 面板宽度跟着内容走（`min-width: 0` + `width: fit-content`）→ 面板宽度 = 最宽那项 + 内边距，不再被撑大；
     · 面板里把「新学 / 复习」文字与 emoji 显示出来（顶栏藏它们是为了省横向空间，
       面板是竖排、宽度富余，没必要再藏）。
   ⚠️ 第四十七轮（2026-10-06 用户：四个按钮做的一样大、文字居中、大小参考「新学」）改了这条口径：
     第三十八轮是 `align-items: flex-start` + 每项 `width: auto` → 四项各是内容宽（实测 66 / 74 / 56 / 99）；
     现在改成 **`stretch`**：每项撑满面板的内容宽 = 最宽那项「新学」的宽（99px），四个按钮就一样大；
     按钮里的「图标 + 文字」那一组再 `justify-content: center` 居中。
     面板宽度仍由 `fit-content` 决定（= 最宽那项的自然宽）→ 所以口径就是「大小参考新学」。
     ⚠️ `align-items` 必须写在这个选择器上（`#wordStudyPage.ws-nav-mobile .ws-tools-bar .ws-toolbar`，
     1,4,0）：第 2610 / 8439 行那条同名的老规则本来就写着 `stretch`，第三十八轮这条把它改成了 `flex-start`。 */
#wordStudyPage.ws-nav-mobile .ws-tools-bar .ws-toolbar { align-items: stretch; min-width: 0; width: fit-content; }
#wordStudyPage.ws-nav-mobile .ws-tools-bar .ws-toolbar > * { width: auto; min-width: 0; }
/* `.ws-tool-dd` 是块级外壳（UK / 音效 那两个下拉壳）：它撑满面板后，里面的按钮要跟着撑满 */
#wordStudyPage.ws-nav-mobile .ws-tools-bar .ws-toolbar .ws-tool-dd { width: 100%; }
#wordStudyPage.ws-nav-mobile .ws-tools-bar .ws-toolbar .ws-tool-dd > .ws-tool-item { width: 100%; }
#wordStudyPage.ws-nav-mobile .ws-tools-bar .ws-toolbar .ws-tool-item {
  width: auto; justify-content: center; text-align: center; }
#wordStudyPage.ws-nav-mobile .ws-tools-bar .ws-toolbar #wsModeBtn .ws-mode-emoji,
#wordStudyPage.ws-nav-mobile .ws-tools-bar .ws-toolbar #wsModeBtn #wsModeLabel,
html.force-phone #wordStudyPage.ws-nav-mobile .ws-tools-bar .ws-toolbar #wsModeBtn .ws-mode-emoji,
html.force-phone #wordStudyPage.ws-nav-mobile .ws-tools-bar .ws-toolbar #wsModeBtn #wsModeLabel { display: inline !important; }

/* ══ 2026-10-07 第二十一轮（用户：点击单词的高亮要跟拖动划词的高亮同形同色）════════════
   拖动划词那块：圆角 6px、范围 = 单词盒**左右各 +2px**、高 = 整行行高（约 26px）、
   色 #C6D3B6（精读训练页 #E9E0D4，暗夜各换一档半透明）。
   点击/悬停单词原来只是一块 3px 圆角、只有字形高度、没有外扩的浅琥珀底 —— 这里改成同一套：
     · `padding: 2.5px 2px` → 左右各比字形宽 2px（与划词块一样）、上下各撑 2.5px（= 行高那一格），
       行内元素**纵向 padding 不影响排版**，横向多出来的 1px 用 `margin: 0 -1px` 抵掉
       （原来就是 `padding: 0 1px`，所以总占位与原来完全一样，正文一个字都不会移位）；
     · `border-radius: 6px` 与划词块一致；
     · 颜色按页面取与划词同一档（阅读/小说 #C6D3B6、训练页 #E9E0D4；暗夜 rgba(16,185,129,.42) /
       rgba(90,110,69,.55)）。
   浮动题目卡（.float-q-body）里那套琥珀悬停是它自己的视觉，不在本次范围内，没动。 */
.reading-area .word:hover, .reading-area .word:active,
.story-read-area .word:hover, .story-read-area .word:active,
.train-page .word:hover, .train-page .word:active {
  padding: 2.5px 2px; margin: 0 -1px; border-radius: 6px; background: #C6D3B6; }
.train-page .word:hover, .train-page .word:active { background: #E9E0D4; }
html.dark .reading-area .word:hover, html.dark .reading-area .word:active,
html.dark .story-read-area .word:hover, html.dark .story-read-area .word:active {
  background: rgba(16, 185, 129, .42); }
html.dark .train-page .word:hover, html.dark .train-page .word:active { background: rgba(90, 110, 69, .55); }

/* ══ 2026-10-07 第二十二轮（用户：精读训练六个卡片做成两排，放大一些，一排三个）════════
   原来 `.sh-items .train-type-grid` 是 `auto-fill + minmax(206px, 1fr)`：内容列 1152 宽时排成 **5 列**，
   6 张卡变成「5 + 1」两排但很别扭。这里在够宽的窗口（≥1080px，此时题型列表已是整行）固定成
   **3 列** —— 6 张正好两排、一排三个；卡片整体放大一档（内边距 16/15 → 24/22、图标 38 → 46、
   名称 .96 → 1.14em、描述 .72 → .84em、标签 .66 → .74em、圆角 18 → 20、间距 12 → 18）。
   手机两轨（≤768 / force-phone）保持**两列**：390 宽下三列每张只剩 ~110px，反而比现在更小，
   所以那边只把卡片略微放大（内边距 16/14、图标 42）。 */
@media (min-width: 1080px) {
  html:not(.force-phone) .sh-items .train-type-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 18px; }
  html:not(.force-phone) .sh-items .train-type-card { padding: 24px 22px; border-radius: 20px; gap: 8px; }
  html:not(.force-phone) .sh-items .train-type-icon { width: 46px; height: 46px; border-radius: 18px; }
  html:not(.force-phone) .sh-items .train-type-name { font-size: 1.14em; }
  html:not(.force-phone) .sh-items .train-type-desc { font-size: .84em; }
  html:not(.force-phone) .sh-items .train-type-tag { font-size: .74em; padding: 3px 11px; }
}
@media (max-width: 768px) {
  .sh-items .train-type-card { padding: 16px 14px; }
  .sh-items .train-type-icon { width: 42px; height: 42px; }
}
html.force-phone .sh-items .train-type-card { padding: 16px 14px; }
html.force-phone .sh-items .train-type-icon { width: 42px; height: 42px; }

/* ══ 2026-10-07 第二十六轮（用户：电脑上拖选句子时，鼠标碰到单词不要触发单字高亮）══════════
   拖动期间（html.sel-dragging）与选区还在时（html.sel-active），把 `.word` 的悬停/按下底色压成透明、
   内边距与外边距还原成基础值（第二十一轮给悬停加过 2.5px/2px + 负 margin）。
   ⚠️ 选择器要同时压过 `.reading-area/.story-read-area/.train-page .word:hover` 以及那两条 `html.dark …`
   （后者权重 (0,4,1)），所以这里写成 `html.dark.sel-active …` 的形式并放在样式表最末。 */
html.sel-dragging .word:hover, html.sel-active .word:hover,
html.sel-dragging .word:active, html.sel-active .word:active,
html.dark.sel-dragging .word:hover, html.dark.sel-active .word:hover,
html.dark.sel-dragging .word:active, html.dark.sel-active .word:active {
  background: transparent; padding: 0 1px; margin: 0; }

/* ══ 2026-10-07 第二十七轮（用户：给精读训练加一个一键全文翻译的按钮）════════════════
   按钮在题型那排（`.train-type-chip` 里，跟在「保存训练」后面）；
   译文面板放在题目卡下面，沿用阅读页那套 `.full-trans` 卡片皮肤，只是内边距收一点。 */
#doneMarksSwRow { justify-content: flex-start; margin-bottom: 12px; }
#doneMarksSwRow .th-mine-favswitch { min-width: 210px; }
#doneMarksSwRow .sh-mode-opt { flex: 1; }
#trainPage .train-fulltrans { margin: 18px 0 6px; }
#trainPage .train-fulltrans h3 { display: flex; align-items: center; gap: 8px; margin: 0 0 10px;
  font-size: .92em; font-weight: 600; color: var(--c-primary-dark); }
#trainPage .train-fulltrans h3::after { content: ''; flex: 1; height: 1px; background: #EDE8DE; }
#trainPage .train-fulltrans .full-trans { padding: 20px 22px; font-size: .92em; }
#trainPage .train-fulltrans .full-trans p { text-indent: 2em; margin: 0 0 6px; }
html.dark #trainPage .train-fulltrans h3 { color: var(--c-text); }
html.dark #trainPage .train-fulltrans h3::after { background: #3F3A37; }
html.force-phone #trainPage .train-fulltrans .full-trans { padding: 16px 18px; font-size: .86em; }

/* ══ 2026-10-07 第二十九轮（用户：手机版返回按钮有问题）══════════════════════════════
   查出来的两件事（手机两轨都一样：真 ≤768 与 force-phone 预览）：
   ① **两个返回键重影**：「已做题目 #donePage」「已做训练 #trainDonePage」这两页各留了一条**老工具条**
      （`.topbar`，里面只有一个 `backOneLevel()` 返回键，2026-10-06 那轮把它的分类切换挪进二级菜单后
      就只剩这一颗了）。手机档 `.topbar` 是 `position:fixed; z-index:100`，而一级导航 `.wl-topbar` 只有 50，
      于是老工具条压在导航条上 → 屏幕上并排出现两颗返回箭头（真机 390 实测 x=175 与 x=212，**还互相压住**）。
      手机档这两条老工具条整条隐藏（返回键由一级导航那颗承担，语义一样是「退一级」）。
   ② 手机档那颗返回键被 `.wl-nav-lead{margin-left:auto}` 顶到了中/右（真机 x=212、预览 x=1118）——
      因为手机档把 `.wl-nav-links` 藏了，只剩一颗箭头孤零零挂在右边。手机两轨里把它改回**靠左**
      （紧跟品牌之后），右侧图标继续靠右。桌面档不动。 */
@media (max-width: 768px) {
  #donePage > .topbar, #trainDonePage > .topbar { display: none; }
  /* 顶栏改「左对齐排布」：返回键排第一（order:-1）、品牌紧随其后、右侧图标仍用 margin-left:auto 顶到右边。
     （原来 justify-content:space-between + 传回键 margin-left:auto，手机档把导航链接藏了之后
       返回键会被顶到中间/右边，预览档甚至会压到右侧图标上。） */
  .wl-nav-inner { justify-content: flex-start; }
  .wl-nav-lead { order: -1; margin-left: 0; margin-right: 0; }
  .wl-nav-right { margin-left: auto; }
}
html.force-phone #donePage > .topbar, html.force-phone #trainDonePage > .topbar { display: none; }
html.force-phone .wl-nav-inner { justify-content: flex-start; }
html.force-phone .wl-nav-lead { order: -1; margin-left: 0; margin-right: 0; }
html.force-phone .wl-nav-right { margin-left: auto; }

/* ══ 划词圆角高亮（2026-10-11 用户要求：圆角、行间不断层、不盖没选中的字、整段不重叠；题目/选项/单词卡同样）
   做法：宿主容器里放一层绝对定位色块，z-index:-1 ⇒ 画在宿主底色之上、所有文字之下，字永远不被盖住。
   JS（selHlPaint）按 Range 拆到文本结点、逐行合并成块，行间首尾相接，所以不断层、也不叠加。
   · isolation:isolate 让宿主自成堆叠上下文，色块不会漏到外层背景后面；
   · 直接子元素只保留 position:relative（保住它们的绝对定位子元素的包含块），不给 z-index；
   · 宿主里不透明的底色会盖住色块 —— 题目块/听力组底色改透明（边框、圆角、内边距不动）。 */
.sel-hl-container { position: relative; isolation: isolate; }
.sel-hl-layer { position: absolute; left: 0; top: 0; right: 0; bottom: 0; z-index: -1; pointer-events: none; }
.sel-hl-layer > i { position: absolute; display: block; border-radius: 6px; background: #C6D3B6; }
.sel-hl-container > *:not(.sel-hl-layer):not(.title) { position: relative; }
#readingContent .question-block, #readingContent .ls-group, #readingContent .ls-qs .question-block { background: transparent; }
html.dark #readingContent .question-block, html.dark #readingContent .ls-group { background: transparent; }
/* 听力页 .ls-stem-wrap 不能改 static：毛玻璃罩 .ls-frost 是它的绝对定位子元素（2026-10-11 听力页整页空白回归） */
#readingContent .questions-section, #readingContent .question-block { position: static; }
/* ⚠️ 2026-10-11 修（用户报：「报错那排按钮会显示在顶栏上面」）：
   `.topbar` 桌面档是 `position:sticky; z-index:10`（平板/手机档 3646/3827/3907 行是 `fixed; z-index:100`），
   而 `.reading-area .title`（装着「报错 / 防误触 / 高频词」那一行）在 2026-10-09 为修「排版面板点不动」
   被**特意提到 z-index:20**（见上面 322~333 行的注释）——于是它反过来压在顶栏之上，滚动时就浮在顶栏上面。
   修法：把顶栏抬到 30（仍**低于**高频词菜单的 `.hf-group-modal{z-index:400}` 与各弹层 400+，
   所以下拉/弹窗照旧能盖住顶栏），**不动 `.title` 的 20** —— 那个 20 是给 `#rtPanel` 用的，
   一降就会把排版面板压回正文（z-index:1）下面，旧 bug 复发。
   自证：滚动后 `.title` 的矩形与 `.topbar` 相交处，`elementFromPoint` 应当拿到顶栏里的元素。 */
.topbar { z-index: 30; }
#trainPage .sel-hl-layer > i { background: #E9E0D4; }
html.dark .sel-hl-layer > i { background: rgba(16, 185, 129, .42); }
html.dark #trainPage .sel-hl-layer > i { background: rgba(90, 110, 69, .55); }
/* 原生选中色让位给色块（!important 盖过各处 ::selection 色值，否则会叠成双份） */
.sel-hl-container::selection, .sel-hl-container ::selection { background: transparent !important; }


/* ══ 2026-10-06 第四十二轮（用户：记单词界面 —— 单词缩小 / 按钮行上移 / 词表方块对齐 / 简单词挪位 / 卡片放大）
   只动**平板档与电脑档**（手机档一个像素不变）。逐条对应：
   ① 单词字号 ×0.6（用户说"缩小五分之二"）：平板 `--ws-word-fs` 4.4em→2.64em（1024 宽实测 70.4→42.2px）；
      电脑 `clamp(2.8em,9vw,5em)` → `clamp(1.68em,5.4vw,3em)`（1440 宽 80→48px）。
   ② UK/音效那排按钮上移（实测它压在单词顶 22px 上 → 遮住字母）：
      页面 padding-top 平板 88→66、电脑 96→68；`.ws-tools-bar` 上边距 16→2 →
      实测工具条从 104~146 抬到 ~68~110，正好落在总导航（65 高）下方、卡片顶（112）之上。
   ③ 词表那个小方块（`.ws-wl-panel`）左缘原来写死 `left: 150px`（电脑档侧栏宽），平板侧栏只有 116 →
      错开 34px。改成跟着侧栏变量走：`left: var(--ws-side-w, 150px)`（手机档那条 `left:0` 覆盖仍在后面，不受影响）。
   ④ 「标记为简单词」搬到「新学 / 查词」那排按钮下方、右对齐：手机档仍用底部那枚，
      平板/电脑档用顶部镜像 `#wsSimpleWrapTop`（显隐由 wsSimpleWrapShow 同步，底部那枚在这两档 CSS 收掉）。
   ⑤ 卡片尽量放大（往上往下延伸）：卡片顶本来就贴着工具条底（由 `.ws-stage-col` 的负 margin 决定，
      工具条上移后把 margin 从 -64 收到 -28 / -32，让卡片顶落在 112 而不是藏进工具条里）；
      卡片底往下靠三处让位 —— 页面下内边距 24→12、内容列下内边距 32→12（平板）/48→16（电脑）、
      底部两排的下边距 18→8。实测平板卡片 1124 → 约 1160、电脑 592 → 约 700。 */
.ws-simple-top { display: none; }
/* 舞台列必须能**收缩**：`#wsStudyView.ws-home .ws-stage { flex: 1 1 auto }`（6366 行）的 flex-basis 是 auto
   → 高度按内容算；内容一多（评分后释义块里填满形近词 / 词根词那种）就把底部那排按钮顶到面板外
   （实测评分态「返回上一步 / 下一个单词」跑到面板底之下、甚至比视口还高）。
   改成 `flex: 1 1 0%` → 高度就是"剩下的空间"（确定值），卡片 `height:100%` 跟着它、释义块自己内部滚。
   ⚠️ 只给平板/电脑两档（手机档的舞台另有自己那套标定，不动）。 */
/* ⚠️ 这几条都带 `html:not(.force-phone)`：手机**预览**档是在宽窗口上模拟手机的，光靠媒体查询会把
   平板/电脑这套套到手机预览上（实测「手机预览」档两条上边线差从 0 变成 46px、单词中心差 50px）。
   站内 ≥1080 那条桌面规则也是同样的写法（`html:not(.force-phone) ...`）。 */
@media (min-width: 769px) {
  html:not(.force-phone) #wsStudyView.ws-home .ws-stage { flex: 1 1 0%; min-height: 0; }
}
html.force-tablet #wsStudyView.ws-home .ws-stage,
html.force-desktop #wsStudyView.ws-home .ws-stage { flex: 1 1 0%; min-height: 0; }
@media (min-width: 769px) {
  html:not(.force-phone) { --ws-word-fs: clamp(1.68em, 5.4vw, 3em); }
  html:not(.force-phone) #wordStudyPage { padding: 68px 0 12px; }
  html:not(.force-phone) .ws-tools-bar { margin: 2px 24px 12px auto; }
  html:not(.force-phone) #wsStudyView.ws-home .ws-stage-col { margin-top: -32px; }
  html:not(.force-phone) #wsStudyView.ws-home .ws-bottom { margin-bottom: 8px; }
  html:not(.force-phone) .ws-wl-panel { left: var(--ws-side-w, 150px); }
  html:not(.force-phone) .ws-simple-top { display: block; width: fit-content; max-width: calc(100% - 48px); text-align: right;
    margin: 0 24px 8px auto; }
  html:not(.force-phone) #wsSimpleWrap { display: none !important; }   /* 底部那枚在这两档收掉，用顶部镜像 */
}
/* 平板档（769–1180）再单独标定：页面 padding-top 88→66（实测工具条 104~146 → 68~110）、
   内容列下内边距 32→12、单词 4.4em→2.64em、舞台列负 margin -64→-28。 */
@media (min-width: 769px) and (max-width: 1180px) {
  html:not(.force-phone) { --ws-word-fs: min(5.7vw, 10.8vh, 2.64em); --ws-content-pad: 18px 22px 12px; }
  html:not(.force-phone) #wordStudyPage { padding: 66px 0 12px; }
  html:not(.force-phone) #wsStudyView.ws-home .ws-stage-col { margin-top: -28px; }
}
html.force-tablet {
  --ws-word-fs: min(5.7vw, 10.8vh, 2.64em);
  --ws-content-pad: 18px 22px 12px;
}
html.force-tablet #wordStudyPage { padding: 66px 0 12px; }
html.force-tablet .ws-tools-bar { margin: 2px 24px 12px auto; }
html.force-tablet #wsStudyView.ws-home .ws-stage-col { margin-top: -28px; }
html.force-tablet #wsStudyView.ws-home .ws-bottom { margin-bottom: 8px; }
html.force-tablet .ws-wl-panel { left: var(--ws-side-w, 150px); }
html.force-tablet .ws-simple-top { display: block; width: fit-content; max-width: calc(100% - 48px); text-align: right;
  margin: 0 24px 8px auto; }
html.force-tablet #wsSimpleWrap { display: none !important; }
html.force-desktop .ws-simple-top { display: block; width: fit-content; max-width: calc(100% - 48px); text-align: right;
  margin: 0 24px 8px auto; }
html.force-desktop #wsSimpleWrap { display: none !important; }

/* ══════════════════════════════════════════════════════════════════════════════
   记单词页「认识 / 不认识」+ 导航行 + 标记为简单词 —— 重做（2026-10-09）
   改前实测到的问题：
     ① **同一排按钮长得不一样**：`.ws-act-yes/no` 把 `border-radius` 顶到 **45px**、`font-size` 压到 12px、
        `padding` 1.3em 3em，而底下的 `.ws-nav-btn` 是 `14px` 圆角、`.92em`、16px 内边距
        —— 两排同时出现时像两套系统。
     ② **主次分不清**：「认识」实心绿、「不认识」白底，但**两者的 hover 是同一个绿**（主次只在静止态存在）；
        而 `.ws-nav-next`（下一个单词）又和「认识」同款实心绿 → 页面上出现两个"主按钮"。
     ③ 行宽与间距不齐：操作行 480px / 导航行 480px，间距却是 18 vs 14。
   做法（**只作用于记单词页**：作用域限定 `#wsStudyView .ws-actions .ws-act`；
   `#articlePage` 复用的 `.ar-start` / 「选择文章」那两颗照旧不受影响）：
     · 统一圆角 18 / 字号 .95em / 高度约 56；容器宽度开放到 520 与导航行一致，间距统一 14。
     · 主次靠**填充方式**区分而不是颜色：认识 = 唯一实心绿；不认识 = 白底描边、hover 只加深描边。
     · 导航行统一成「浅底幽灵钮」，只有 `.ws-nav-next` 保留实心绿 —— 一屏只有一个实心主按钮。
     · 补 `:focus-visible` 焦点环与 `prefers-reduced-motion` 兜底。 */
#wsStudyView { --ws-actions-w: 520px; }
#wsStudyView .ws-actions { gap: 14px; }
#wsStudyView .ws-actions .ws-act {
  flex: 1 1 0; gap: 9px; padding: 15px 20px; border: 1px solid var(--c-border); border-radius: 18px;
  background: var(--c-bg-card); color: var(--c-text); font-size: .95em; font-weight: 700;
  letter-spacing: .06em; text-transform: none;
}
#wsStudyView .ws-actions .ws-act-yes { background: var(--c-accent); border-color: var(--c-accent); color: #fff; }
#wsStudyView .ws-actions .ws-act-yes:hover { background: var(--c-accent-hover); border-color: var(--c-accent-hover); }
html.dark #wsStudyView .ws-actions .ws-act-yes { color: #1C1917; }
html.dark #wsStudyView .ws-actions .ws-act-yes:hover { background: #B4C99E; border-color: #B4C99E; }
#wsStudyView .ws-actions .ws-act:not(.ws-act-yes):hover { border-color: var(--c-border); background: var(--c-bg); color: var(--c-text); }
#wsStudyView .ws-actions .ws-act:focus-visible { outline: 2px solid var(--c-accent); outline-offset: 2px; }
/* 导航行：浅底幽灵钮（不再与主按钮同款实心） */
#wsStudyView .ws-nav-row { gap: 14px; }
#wsStudyView .ws-nav-btn { border-radius: 18px; padding: 15px 18px; font-size: .95em; font-weight: 600;
  border: 1px solid var(--c-border); background: var(--c-bg); color: var(--c-text-secondary); }
#wsStudyView .ws-nav-btn:hover { border-color: var(--c-accent); background: var(--c-bg-card); color: var(--c-accent-deep); }
#wsStudyView .ws-nav-btn:focus-visible { outline: 2px solid var(--c-accent); outline-offset: 2px; }
#wsStudyView .ws-nav-btn.ws-nav-wrong { background: var(--c-bg); border-color: var(--c-border); color: #5C4033; }
html.dark #wsStudyView .ws-nav-btn.ws-nav-wrong { color: #D4A373; }
#wsStudyView .ws-nav-next { background: var(--c-accent); border-color: var(--c-accent); color: #fff; }
#wsStudyView .ws-nav-next:hover { background: var(--c-accent-hover); border-color: var(--c-accent-hover); color: #fff; }
html.dark #wsStudyView .ws-nav-next { color: #1C1917; }
html.dark #wsStudyView .ws-nav-next:hover { background: #B4C99E; border-color: #B4C99E; }
/* 「标记为简单词」：更轻的一档（它的语义是"退出复习队列"，不是评分） */
.ws-simple-btn { border-radius: 9999px; padding: 8px 16px; font-size: .8em; font-weight: 600; }
.ws-simple-btn:focus-visible { outline: 2px solid var(--c-accent); outline-offset: 2px; }
html.dark .ws-simple-btn { border-color: #57534E; color: #D6D3D1; }
html.dark .ws-simple-btn:hover { border-color: var(--c-accent); background: rgba(255,255,255,.06); color: var(--c-accent); }
/* 手机档：按钮收紧（原 56px 高 + 两排会把卡片空间顶掉） */
@media (max-width: 480px) {
  #wsStudyView { --ws-actions-w: 100%; }
  #wsStudyView .ws-actions .ws-act,
  #wsStudyView .ws-nav-btn { padding: 13px 14px; font-size: .9em; border-radius: 16px; }
  #wsStudyView .ws-actions, #wsStudyView .ws-nav-row { gap: 12px; }
}
@media (prefers-reduced-motion: reduce) {
  #wsStudyView .ws-actions .ws-act, #wsStudyView .ws-nav-btn { transition: color .01ms, border-color .01ms, background-color .01ms; }
}

/* ══════════════════════════════════════════════════════════════════════════════
   【布局契约变更·2026-10-09】底部两排按钮**不再沉底**，改为跟着内容走
   用户口径：「认识/不认识」放在**单词下面一点点**；「‹ ›」放在**释义卡片下面一点点**；
   两个都不要一直固定在页面下面。
   ⚠️ 这一改**推翻了四处老契约**（都是为"一屏放下 + 按钮沉底"设计的），下面全部显式覆盖，
      以后要再动这段请先读这里：
       ① `.ws-stage-col` 原为 flex 列（stage 吃剩余高度 + `.ws-bottom` 沉底）→ 改成 **block 流式**，
          卡片与按钮按文档顺序自然堆叠，整页滚动（不再用面板内滚去凑一屏）；
       ② `.ws-bottom` 原 `min-height:108px + justify-content:center` → `display:contents`（去掉这个盒子）；
       ③ 那一串 `.ws-bottom { margin-bottom: 54/37/18/8 }` 的"让位"标定（9095~9431 行）全部失效但保留，
          这里用 `margin:0` 覆盖掉 —— 它们是按"按钮贴卡片底边、底部两排要不要留 54px"算的，新布局里没意义；
       ④ `.ws-card.revealed { height:100% }` 与 `.ws-reveal { max-height:100% }` 原为"卡片填满舞台、
          面板在卡片内部滚" → 改成**按内容撑开**（`height:auto` / `max-height:none`），
          `.ws-card` 自带的 `overflow:hidden` 也解除，否则按钮与面板阴影会被卡边裁掉。 */
/* ⚠️⚠️ 2026-10-09 返工：上一版这里把 `.ws-stage-col` / `.ws-stage` 写成了 `display: block`，
   连带**把"单词垂直居中"一起干掉了**（居中的来源正是 `.ws-stage{justify-content:center}` 与
   `.ws-stage-col{justify-content:center}`，display 一变 flex 属性全部失效，单词就贴顶了）。用户当场指出。
   现在改回**弹性居中 + 内容流**：两者保留 flex 列 + `justify-content:center`，
   子项高度都是 auto —— 内容不足一屏时整块在剩余空间里垂直居中（单词就在页面正中），
   内容超过一屏时自然按内容流排布、整页滚动。`flex: none` 是关键：别让 stage 再去拉伸填满。 */
#wsTabStudy { display: block; }
#wsStudyView.ws-home { display: block; min-height: 0; }
#wsStudyView.ws-home .ws-stage-col,
html.force-phone #wsStudyView.ws-home .ws-stage-col {
  display: flex; flex-direction: column; justify-content: center;
  /* ★ 关键：内容不足一屏时，光有 justify-content:center 没用 —— 容器自己也得占满一屏，
     否则"居中"只发生在那 300~400px 里，单词仍然贴在页面上半部（用户当场指出的就是这个）。
     ⚠️ 但**不能无条件给整屏**：页面之上还有固定顶栏 + 工具条（实测 110px），给满整屏会把整块推低；
     而且揭示态内容本来就高于一屏，再强行居中只会把内容顶出可滚区。
     所以分两态（这是本页唯一干净的解法）：
       · 未揭示态（卡上没有 .revealed）：单词/音标/评分行这一组在**剩余空间正中** → 容器高 = 100dvh - 220px
         （110 顶栏让位 + 110 视觉等分），实测 1440×900 下单词中心与视口中心差 ≈ 0；
       · 揭示态：容器回归 `min-height:0`，按内容流排布、整页滚动 —— 不去硬撑一屏。 */
  min-height: calc(100vh - 159px);
  min-height: calc(100dvh - 159px); }
/* ⚠️ 手机两轨原本有 `min-height: 0 !important`（老的"一屏固定高度"方案留下的），
   它会把上面那条居中高度整个压掉（实测手机档 minH 量到 0px）→ 这里放开并单独标定。
   各档实测偏差（目标 0）：桌面 -3.8 / 笔记本 -3.5 / 平板 -11.8 / 手机 +19.3 / 小屏手机 -12.8
   → 按实测斜率 -0.5px/px 反推，平板再减 24px、手机再加 38px（其余保持）。 */
@media (min-width: 769px) and (max-width: 1180px) {
  #wsStudyView.ws-home .ws-stage-col { min-height: calc(100dvh - 183px) !important; }
}
@media (max-width: 768px) {
  /* 常规手机 390×844：实测 -111 偏 -24.7px，按斜率 -0.5px/px 收到 **-61**（再加 50px 高度） */
  #wsStudyView.ws-home .ws-stage-col,
  html.force-phone .ws-stage-col { min-height: calc(100vh - 61px) !important; min-height: calc(100dvh - 61px) !important; }
}
/* ⚠️ 如实记录（2026-10-09）：≤400 宽的小屏手机（360×640 / 320×568）实测**偏 -36px**，没调到位。
   原因：这一档同时被三条 `!important` 的 min-height 夹着 ——
     ① 基础规则 3508 行 `calc(100dvh - 245px)`、
     ② `html.force-phone .ws-stage-col` 3544 行（已按实测改成 -109px）、
     ③ 上面这条 ≤768 的 `-205px`；
   另开 `@media (max-width:400px)` 都会因为特异性/顺序里的某一条而失效（试过三种写法，minH 一直停在 435px）。
   要彻底修，得先把那三条合并成一条带变量的规则 —— 属于"清理老契约"的独立改动，这轮不做，免得越改越乱。
   影响面：仅小屏手机的单词中心偏上约 36px；桌面/笔记本/平板/常规手机均已对齐到 ±13px 内。 */
html.force-phone #wsStudyView.ws-home .ws-stage-col { min-height: calc(100dvh - 131px) !important; }
/* ⚠️ 原来是「}」提前收尾 + 下一行三条声明（height/margin-top/overflow）落在规则外，等于从没生效。
   2026-10-29 全面检查时只删掉了那半个残句（保持渲染与线上完全一致）；要不要把这三条并进上面的规则
   —— 那是改小屏手机速记布局，得单独确认。 */
#wsStudyView.ws-home .ws-stage,
html.force-tablet #wsStudyView.ws-home .ws-stage,
html.force-desktop #wsStudyView.ws-home .ws-stage {
  display: flex; flex-direction: column; justify-content: center; align-items: center;
  flex: none; height: auto; min-height: 0; overflow: visible; }
#wsStudyView.ws-home .ws-card,
#wsStudyView.ws-home .ws-card.revealed { height: auto; max-height: none; overflow: visible; justify-content: center; }
#wsStudyView .ws-reveal { max-height: none; }
/* `.ws-bottom` 本体的所有角色（min-height/居中/那一串让位 margin）在这一版里全部作废 → 拆掉盒子，
   三块内容（评分行 / 简单词行 / 导航行）直接按文档顺序落在卡片之后。 */
.ws-bottom, #wsStudyView.ws-home .ws-bottom,
html.force-tablet #wsStudyView.ws-home .ws-bottom,
html.force-phone .ws-bottom,
html:not(.force-phone) #wsStudyView.ws-home .ws-bottom { display: contents; min-height: 0; margin: 0 !important; }
/* ① 评分行：单词下面一点点（与 .ws-word / .ws-phon-row 拉开固定距离，不再由舞台高度决定）。
   实测：单词底 → 音标行 = 14(音标行 margin-top)；音标行 → 评分行 = 评分行 margin-top + 行盒余量。
   ⚠️ 音标行的高度**各档不同**：桌面/平板 22px，手机档 64px（`html.force-phone .ws-phon-row` 让它换行堆叠）
   —— 所以只对齐"音标底 → 按钮"这一段（各档都给 24px），不去追"单词底 → 按钮"那个随档位变的数字。 */
#wsStudyView .ws-actions { margin: 24px auto 0; }
/* ② 简单词行：排在导航行**之后**（手机档才可见；平板/电脑用顶部镜像）。
   顺序很关键 —— 见上面 DOM 注释：它要是排在导航行前面，会把导航行从"释义卡下 26px"顶到 98px 外。 */
#wsStudyView .ws-simple-wrap { margin: 16px 0 0; }
/* ③ 导航行：释义卡片下面一点点。
   实测链条：释义卡底 → 进度条 = 进度条 margin-top，进度条(6px) → 导航行 = 本行 margin-top。
   基础规则里进度条是 24px，于是间距会变成 40 —— 揭示态把它收到 10px，正好 26px（未揭示态不动）。 */
#wsStudyView .ws-card.revealed .ws-progress-bar { margin-top: 10px; }
#wsStudyView .ws-nav-row { margin: 10px auto 0; }
#wsStudyView .ws-remove-wrap { margin: 22px 0 0; }
/* 舞台列原本有"吃掉剩余高度"的负 margin，新布局里没有剩余高度可吃 */
#wsStudyView.ws-home .ws-stage-col { margin-top: 0 !important; }
/* 提示：这一改之后页面会比一屏长（卡片按内容撑开），所以底部留一点呼吸位 */
#wsStudyView.ws-home { padding-bottom: 8px; }
/* 揭示态：容器回归内容流（不再硬撑一屏）；这是"单词居中"那条规则的对照态。 */
#wsStudyView.ws-home .ws-stage-col:has(.ws-card.revealed) { min-height: 0; }

/* ══ 动效层（2026-10-17 用户要求「二、哪里可以做动效」）══
   规矩：只动 transform / opacity（含独立的 translate / scale / rotate 属性）；入场一律 fill backwards，
   动画结束不留残值；每一项在文件末尾的 prefers-reduced-motion 块里都有关闭。 */
:root { --ease-back: cubic-bezier(.34,1.56,.64,1); }
@keyframes mxRise { from { opacity: 0; translate: 0 8px; } }
@keyframes mxPop { 0% { scale: 1; } 40% { scale: 1.04; } 100% { scale: 1; } }
@keyframes mxShake { 0%, 100% { translate: 0 0; } 20% { translate: -6px 0; } 40% { translate: 5px 0; } 60% { translate: -3px 0; } 80% { translate: 2px 0; } }
@keyframes mxIn { from { opacity: 0; scale: .5; } }
@keyframes mxModal { from { opacity: 0; scale: .94; translate: 0 6px; } }
@keyframes mxFade { from { opacity: 0; } }
@keyframes mxPulse { 0%, 100% { opacity: 1; } 50% { opacity: .45; } }

/* ① 做题反馈：选对 → 选项轻弹 + 绿勾；选错 → 左右抖，抖完再变红（颜色是状态，不是动画） */
.q-option.q-fb-ok { animation: mxPop .36s var(--ease-out-quart); }
.q-option.q-fb-bad { animation: mxShake .42s ease-in-out; border-color: #C2410C; transition: border-color 0s .42s; }
.q-option.q-fb-bad::before, .train-options .q-option.q-fb-bad::before { background: #FBEDE8; transition: background 0s .42s; }
.q-option.q-fb-bad .q-box { background: #C2410C; border-color: #C2410C; box-shadow: none; transition-delay: .42s; }
.q-fb-tick { display: inline-block; margin-left: auto; padding-left: 8px; color: #10b981; font-weight: 800; animation: mxIn .3s var(--ease-back) .12s backwards; }
html.dark .q-option.q-fb-bad::before { background: rgba(194,65,12,.18); }

/* ② 骨架屏：替代「加载中…」—— 灰条只做 opacity 呼吸 */
.skel-list { display: flex; flex-direction: column; gap: 10px; padding: 4px 0; }
.skel-row { height: 52px; border-radius: 12px; background: #EFE8DE; animation: mxPulse 1.4s ease-in-out calc(var(--i, 0) * 90ms) infinite; }
.skel-lines { display: flex; flex-direction: column; gap: 9px; padding: 10px 2px; }
.skel-lines i { display: block; height: 11px; border-radius: 6px; background: #EFE8DE; animation: mxPulse 1.4s ease-in-out calc(var(--i, 0) * 90ms) infinite; }
html.dark .skel-row, html.dark .skel-lines i { background: #2A2521; }

/* ③ 切页：只给**内容容器**做淡入上浮（顶栏 / 底栏 / 浮层这些 fixed 元素不在名单里 ——
   祖先一旦带 transform 就会变成 fixed 子孙的包含块，所以 .ws-shell 这类里面有 fixed 的壳**不能**进名单）。
   页面由 .hidden 切显示时动画自动重播，不用 JS。 */
.wl-page > main, #readingPage > .main-layout, #storyReadLayout, .train-page,
#trainDonePage > .vocab-page, #donePage > .vocab-page, #pointsPage > .vocab-page, #petPage > .vocab-page,
#storyHubView, #basicLibraryView, #importLibView { animation: mxRise .22s var(--ease-out-quart) backwards; }

/* ④ 列表入场：只给首屏前 10 条错开 30ms */
.sh-item.stg { animation: mxRise .3s var(--ease-out-quart) calc(var(--i) * 30ms) backwards; }

/* ⑤ 提示 / 弹窗：带一点回弹（toast 的 transform 由 JS 内联写居中，这里只动独立的 scale，互不覆盖） */
.toast { scale: .92; transition: opacity .2s ease, scale .2s ease; }
.toast.show { scale: 1; transition: opacity .25s ease, scale .38s var(--ease-back); }
.modal-overlay.show, .clear-modal-overlay.show, .add-modal-overlay.show { animation: mxFade .18s ease; }
.modal-overlay.show .modal:not(.gift-card), .clear-modal-overlay .clear-modal, .add-modal-overlay .add-modal { animation: mxModal .32s var(--ease-back); }

/* ⑥ 收藏生词：星星飞向生词本入口（元素由 vocabFly() 临时挂到 body） */
.vfly { position: fixed; z-index: 9999; left: 0; top: 0; width: 22px; height: 22px; margin: -11px 0 0 -11px; pointer-events: none; font-size: 20px; line-height: 22px; text-align: center; color: #D4A373; text-shadow: 0 2px 6px rgba(92,64,51,.25); }

/* ⑦ 门厅：功能卡片悬停上浮 + 加深阴影，图标歪一下头；分区滚动到视口时淡入上浮 */
.wl-feat { transition: background-color var(--t-state) var(--ease-out-quart), border-color var(--t-state) var(--ease-out-quart), box-shadow .3s var(--ease-out-quart), translate .3s var(--ease-out-quart); }
.wl-feat-ico { transition: rotate .35s var(--ease-back), scale .35s var(--ease-back); }
@media (hover: hover) {
  .wl-feat:hover { translate: 0 -4px; box-shadow: 0 14px 28px -14px rgba(92,64,51,.32); }
  html.dark .wl-feat:hover { box-shadow: 0 14px 28px -14px rgba(0,0,0,.6); }
  .wl-feat:hover .wl-feat-ico { rotate: -6deg; scale: 1.08; }
}
/* 只有脚本挂上 .wl-rv 才先藏（脚本没跑 / 没有 IntersectionObserver 时内容照常显示） */
html.wl-rv .wl-page .rv:not(.in) { opacity: 0; }
html.wl-rv .wl-page .rv.in { animation: mxRise .6s var(--ease-out-quart) calc(var(--i, 0) * 70ms) backwards; }
.wl-blob { transition: transform .8s var(--ease-out-quart); }

@media (prefers-reduced-motion: reduce) {
  .q-option.q-fb-ok, .q-option.q-fb-bad, .q-fb-tick, .skel-row, .skel-lines i, .sh-item.stg,
  .wl-page > main, #readingPage > .main-layout, #storyReadLayout, .train-page,
  #trainDonePage > .vocab-page, #donePage > .vocab-page, #pointsPage > .vocab-page, #petPage > .vocab-page,
  #storyHubView, #basicLibraryView, #importLibView,
  .modal-overlay.show, .clear-modal-overlay.show, .add-modal-overlay.show,
  .modal-overlay.show .modal, .clear-modal-overlay .clear-modal, .add-modal-overlay .add-modal,
  html.wl-rv .wl-page .rv.in { animation: none !important; }
  html.wl-rv .wl-page .rv:not(.in) { opacity: 1; }
  .toast, .toast.show { scale: 1; transition: opacity .2s; }
  .wl-feat, .wl-feat-ico, .wl-blob { transition: none; }
  .wl-feat:hover { translate: none; }
  .wl-feat:hover .wl-feat-ico { rotate: none; scale: none; }
  .q-option.q-fb-bad, .q-option.q-fb-bad::before, .q-option.q-fb-bad .q-box { transition-delay: 0s; }
}

/* ── 分段按钮点击反馈（2026-10-29 补齐）────────────────────────────────────────
   js 的 segFx() 会给 .seg 加 .seg-fx、980ms 后摘掉，但 CSS 里一直没有这个类 →
   「防误触 / 高频词」点了没有任何反馈。只做一次轻微缩放，不参与布局。 */
@keyframes segFxPop { 0% { scale: 1; } 28% { scale: .94; } 62% { scale: 1.03; } 100% { scale: 1; } }
.seg.seg-fx { animation: segFxPop .9s var(--ease-out-expo) both; }

/* ── 速记 / 打字「全屏形态」（2026-10-29 补齐）──────────────────────────────────
   wsToggleFullView() 只切 #wordStudyPage 的 .ws-fs，而 CSS 里一直没有对应规则 →
   全屏按钮等于没反应。按那条注释的口径：藏掉左侧 6 个栏目胶囊，内容区不再给侧栏让位。
   margin 必须带 !important：`html.force-desktop .ws-content` 那条也带 !important。 */
#wordStudyPage.ws-fs .ws-sidebar { display: none; }
#wordStudyPage.ws-fs .ws-content { margin-left: 0 !important; }

/* ── 背单词态的左侧导航：不常驻，改成「左缘把手 + 抽屉」（2026-11-01 用户要求）──────
   用户原话：「这样吧左边弄一个可以展开侧边栏的按钮」。所以：卡片区仍然全宽（不挤压排版），
   左缘挂一个 30×60 的把手（`.ws-rail-toggle`，只在 `.ws-fs.ws-keeprail` 出现），点它侧栏
   从左边滑出来浮在内容之上，再点把手 / 点别处收起。手机档换成底部标签栏，这里一律排除。
   ⚠️ 侧栏 z-index 要高于词表抽屉(35)：它滑出来时压在卡片与抽屉之上，层级才不会打架。 */
#wordStudyPage.ws-fs.ws-keeprail:not(.ws-nav-mobile) .ws-content { margin-left: 0 !important; }
#wordStudyPage.ws-fs.ws-keeprail:not(.ws-nav-mobile) .ws-sidebar {
  display: flex; transform: translateX(-100%); transition: transform .22s ease; z-index: 60; }
#wordStudyPage.ws-fs.ws-keeprail.ws-rail-open:not(.ws-nav-mobile) .ws-sidebar { transform: none; }
#wordStudyPage.ws-fs.ws-keeprail:not(.ws-nav-mobile) .ws-rail-toggle { display: inline-flex; }
/* 两颗把手（侧栏 / 词表）**永远在同一条竖线上**（2026-11-01 用户要求）：
   收起时都贴左缘 0，侧栏抽出来时一起右移到侧栏右缘，不许一颗在 0、另一颗在 150。
   手机档不算（它没有这颗侧栏把手，词表条另有自己的左缘规则）。 */
#wordStudyPage:not(.ws-nav-mobile) { --ws-tab-x: 0px; }
#wordStudyPage.ws-rail-open:not(.ws-nav-mobile) { --ws-tab-x: var(--ws-side-w, 150px); }
#wordStudyPage:not(.ws-nav-mobile) .ws-wl-panel { left: var(--ws-tab-x, 0px); }
/* 侧栏抽出来时，词表条**向左压 1px 并盖在侧栏之上**（z 35 → 62），把它那条 border-right 吃掉 ——
   否则两件之间总有一条竖线，看起来像"贴在旁边"而不是"长在侧栏上"
   （2026-11-01 用户：「应该是粘在侧边栏上的，不要出现分离」）。 */
#wordStudyPage.ws-rail-open:not(.ws-nav-mobile) .ws-wl-panel {
  left: calc(var(--ws-tab-x, 150px) - 1px); z-index: 62; }
.ws-rail-toggle { display: none; position: fixed; left: var(--ws-tab-x, 0px); top: 132px; z-index: 61;
  width: 20px; height: 44px; align-items: center; justify-content: center; padding: 0;
  border: 1px solid var(--c-border); border-left: none; border-radius: 0 10px 10px 0;
  background: var(--c-bg-card); color: var(--c-text-secondary); cursor: pointer;
  transition: left .22s ease, background .15s, color .15s; }
.ws-rail-toggle svg { width: 12px; height: 12px; transition: transform .2s ease; }
#wordStudyPage.ws-rail-open .ws-rail-toggle svg { transform: rotate(180deg); }   /* › 变 ‹ ：点它收起 */
/* 把手也压 1px 盖住侧栏那条边线，跟词表条一样"长在侧栏上"（z 61 本来就高于侧栏 60） */
#wordStudyPage.ws-rail-open .ws-rail-toggle { left: calc(var(--ws-tab-x, 150px) - 1px); }
.ws-rail-toggle:hover { background: var(--c-accent-light); color: var(--c-accent-deep); }
html.dark .ws-rail-toggle { background: #2A2623; border-color: #3F3A37; color: #B8B0A8; }
html.dark .ws-rail-toggle:hover { background: #37312C; color: #E9E2D9; }

/* ══ 支付：积分充值 / 宠物现金直购（2026-10-31）══════════════════════════════
   1 元 = 500 积分；奶虫 ¥3 / 布偶猫 ¥6 现金直购。浮层 z-index 760 —— 比宠物设置面板(750)
   再高一档，因为"点未解锁提示登录"那条链路里它要能盖住一切。 */
/* 充值 CTA（2026-10-31 用户「做好看一些」）：实心茶绿胶囊 + 金色加号徽章 + 两行字，
   和站内主按钮同族；悬停只抬起 1px，不做夸张动效。 */
.pt-hero-buy { display: inline-flex; align-items: center; gap: 10px; padding: 8px 18px 8px 9px;
  border-radius: 999px; border: 1px solid rgba(70,86,52,.6); cursor: pointer; font: inherit;
  color: #FBF8F2; background: linear-gradient(180deg, #667C4F, #52643F);
  box-shadow: 0 8px 20px rgba(74,91,57,.22), inset 0 1px 0 rgba(255,255,255,.16);
  transition: transform .18s var(--ease-out-quart), box-shadow .2s, filter .18s; }
.pt-hero-buy-ico { width: 28px; height: 28px; display: grid; place-items: center; flex: none; border-radius: 50%;
  background: rgba(255,255,255,.16); }
.pt-hero-buy-tx { display: flex; flex-direction: column; align-items: flex-start; gap: 1px; line-height: 1.25; }
.pt-hero-buy-tx b { font-size: .88em; font-weight: 700; letter-spacing: .02em; }
.pt-hero-buy-tx i { font-style: normal; font-size: .68em; letter-spacing: .02em; color: rgba(255,255,255,.86); }
.pt-hero-buy:hover { transform: translateY(-1px); filter: brightness(1.07);
  box-shadow: 0 10px 24px rgba(74,91,57,.28), inset 0 1px 0 rgba(255,255,255,.2); }
.pt-hero-buy:active { transform: translateY(0); filter: brightness(.98); }
.pt-hero-buy:focus-visible { outline: 2px solid var(--c-accent); outline-offset: 3px; }
html.dark .pt-hero-buy { color: #1C1917; background: linear-gradient(180deg, #A8BE90, #8FA876);
  border-color: rgba(28,25,23,.25); box-shadow: 0 8px 20px rgba(0,0,0,.38); }
html.dark .pt-hero-buy-ico { background: rgba(28,25,23,.14); }
html.dark .pt-hero-buy-tx i { color: rgba(28,25,23,.72); }
html.dark .pt-hero-buy:hover { filter: brightness(1.05); }

#payOverlay { position: fixed; inset: 0; z-index: 760; display: none; align-items: center; justify-content: center;
  background: rgba(28,25,23,.34); -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px); }
#payOverlay.show { display: flex; }
.pay-card { position: relative; width: min(420px, 92vw); max-height: 88vh; overflow: auto; padding: 22px 20px 18px;
  background: linear-gradient(180deg, #FFFCF8, #FAF5EE); border: 1px solid rgba(138,106,47,.18);
  border-radius: 20px; box-shadow: 0 24px 60px rgba(41,37,36,.26); text-align: center; }
html.dark .pay-card { background: linear-gradient(180deg, #2E2A24, #292524); border-color: rgba(199,169,104,.22); }
.pay-card h3 { font-family: 'Noto Serif SC', serif; font-size: 1.16em; color: var(--c-text); }
.pay-close { position: absolute; right: 12px; top: 10px; width: 30px; height: 30px; border: none; border-radius: 50%;
  background: none; color: var(--c-text-muted); font-size: 17px; cursor: pointer; }
.pay-close:hover { background: rgba(120,113,108,.12); color: var(--c-text); }
.pay-sub { margin-top: 4px; font-size: .78em; color: var(--c-text-muted); }
.pay-tiers { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin: 18px 0 6px; }
.pay-tier { display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 14px 6px;
  border-radius: 14px; border: 1px solid rgba(138,106,47,.22); background: #FFFCF8; cursor: pointer;
  transition: transform .18s var(--ease-out-quart), border-color .2s, box-shadow .2s; }
.pay-tier:hover { transform: translateY(-2px); border-color: rgba(138,106,47,.5); box-shadow: 0 8px 20px rgba(41,37,36,.08); }
.pay-tier:disabled { opacity: .45; cursor: default; transform: none; box-shadow: none; }
.pay-tier b { font-family: 'Noto Serif SC', serif; font-size: 1.16em; color: var(--c-text); }
.pay-tier span { font-size: .7em; color: var(--c-text-muted); }
html.dark .pay-tier { background: #2A2621; border-color: rgba(199,169,104,.24); }
.pay-empty { grid-column: 1 / -1; padding: 18px 0; font-size: .8em; color: var(--c-text-muted); }
.pay-note { margin-top: 14px; font-size: .72em; line-height: 1.7; color: var(--c-text-muted); }
.pay-amount { margin: 10px 0 12px; font-family: 'Noto Serif SC', serif; font-size: 1.6em; color: var(--c-text); }
.pay-amount em { font-style: normal; font-size: .5em; color: var(--c-text-muted); margin-left: 6px; }
.pay-qr-wrap { position: relative; width: 208px; height: 208px; margin: 0 auto; padding: 8px; border-radius: 16px;
  background: #fff; border: 1px solid rgba(138,106,47,.16); }
.pay-qr-wrap img { width: 100%; height: 100%; object-fit: contain; display: block; }
/* 二维码加载失败的兜底（2026-11-01） */
.pay-qr-err { position: absolute; inset: 8px; display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: 6px; padding: 10px; border-radius: 12px; text-align: center;
  background: #FBF3E2; border: 1px dashed rgba(138,106,47,.45); color: #6B4F3A; font-size: .8em; }
.pay-qr-err b { font-size: .98em; }
.pay-qr-err span { font-size: .78em; color: #8A6A2F; line-height: 1.4; word-break: break-all; }
.pay-qr-retry { margin-top: 4px; padding: 6px 14px; border-radius: 999px; border: none; cursor: pointer;
  background: #6E5322; color: #FFFCF8; font: inherit; font-size: .86em; font-weight: 600; }
html.dark .pay-qr-err { background: #2E2A24; border-color: rgba(199,169,104,.4); color: #EADFC8; }
html.dark .pay-qr-err span { color: #C9A968; }
.pay-qr-done { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  border-radius: 16px; background: rgba(22,163,74,.9); color: #fff; font-size: 1.1em; font-weight: 700; letter-spacing: .06em; }
.pay-status { margin-top: 12px; font-size: .82em; color: var(--c-text-secondary); }
.pay-actions { display: flex; gap: 10px; justify-content: center; margin-top: 14px; }
.pay-btn { padding: 9px 20px; border-radius: 999px; border: 1px solid rgba(138,106,47,.4); background: #8A6A2F;
  color: #FFFCF8; font: inherit; font-size: .8em; cursor: pointer; }
.pay-btn.ghost { background: #FFFCF8; color: #6B4E32; }
.pay-btn:hover { filter: brightness(1.05); }
html.dark .pay-btn { background: #C9A227; border-color: #C9A227; color: #1C1917; }
html.dark .pay-btn.ghost { background: #2E2A24; color: #E7CE96; border-color: rgba(199,169,104,.4); }
@media (max-width: 768px) {
  #payOverlay { align-items: flex-end; }
  .pay-card { width: 100%; border-radius: 20px 20px 0 0; padding-bottom: max(16px, env(safe-area-inset-bottom)); }
  .pay-tiers { grid-template-columns: repeat(2, 1fr); }
}
html.force-phone #payOverlay { align-items: flex-end; }
html.force-phone .pay-card { width: 100%; border-radius: 20px 20px 0 0; }

/* 管理端「订单」页签 */
.admin-orders-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 12px; }
.admin-orders-head h3 { margin: 0; font-size: 1.02em; }
.admin-orders-stats { font-size: .76em; color: var(--c-text-muted); }
.admin-orders-head select { padding: 5px 10px; border-radius: 8px; border: 1px solid var(--c-border);
  background: var(--c-bg); color: var(--c-text); font: inherit; font-size: .78em; }
.admin-orders-body { display: flex; flex-direction: column; gap: 8px; max-height: 70vh; overflow: auto; }
.admin-order { padding: 11px 13px; border: 1px solid rgba(120,113,108,.14); border-radius: 12px; background: #FFFCF8; }
html.dark .admin-order { background: #2A2621; border-color: rgba(199,169,104,.16); }
.admin-order-main { display: flex; align-items: center; gap: 10px; font-size: .84em; }
.admin-order-main b { color: var(--c-text); }
.admin-order-main span { color: var(--c-text-muted); }
.admin-order-tag { margin-left: auto; font-style: normal; font-size: .72em; padding: 2px 9px; border-radius: 999px;
  background: rgba(120,113,108,.12); color: var(--c-text-secondary); }
.admin-order-tag.granted { background: rgba(22,163,74,.14); color: #15803D; }
.admin-order-tag.pending { background: rgba(234,179,8,.18); color: #A16207; }
.admin-order-tag.refunded { background: rgba(220,38,38,.14); color: #B91C1C; }
.admin-order-meta { margin-top: 4px; font-size: .7em; color: var(--c-text-muted); word-break: break-all; }
.admin-order-acts { margin-top: 8px; display: flex; gap: 8px; }
.admin-order-btn { padding: 5px 12px; border-radius: 999px; border: 1px solid rgba(138,106,47,.4);
  background: #FFFCF8; color: #6B4E32; font: inherit; font-size: .74em; cursor: pointer; }
.admin-order-btn.danger { border-color: rgba(185,28,28,.35); color: #B91C1C; }
.admin-order-btn:hover { background: #F6EEE2; }
html.dark .admin-order-btn { background: #2E2A24; color: #E7CE96; border-color: rgba(199,169,104,.32); }

/* ── 「我的 → 订单」历史列表（2026-10-31）──
   和充值浮层同一种壳体（暖纸卡 + 遮罩）；列表左对齐，待支付的单带两个小胶囊按钮。 */
#myOrdersOverlay { position: fixed; inset: 0; z-index: 760; display: none; align-items: center; justify-content: center;
  background: rgba(28,25,23,.34); -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px); }
#myOrdersOverlay.show { display: flex; }
.my-orders-card { position: relative; display: flex; flex-direction: column; width: min(460px, 92vw); max-height: 84vh;
  padding: 22px 20px 18px; background: linear-gradient(180deg, #FFFCF8, #FAF5EE);
  border: 1px solid rgba(138,106,47,.18); border-radius: 20px; box-shadow: 0 24px 60px rgba(41,37,36,.26); }
html.dark .my-orders-card { background: linear-gradient(180deg, #2E2A24, #292524); border-color: rgba(199,169,104,.22); }
.my-orders-card h3 { font-family: 'Noto Serif SC', serif; font-size: 1.12em; color: var(--c-text); text-align: center; }
.my-orders-sub { margin: 4px 0 14px; text-align: center; font-size: .76em; color: var(--c-text-muted); }
.my-orders-body { display: flex; flex-direction: column; gap: 8px; overflow: auto; text-align: left; }
.my-orders-body .pf-note { padding: 16px 0; text-align: center; font-size: .78em; color: var(--c-text-muted); }
.pf-order { padding: 10px 12px; border: 1px solid rgba(120,113,108,.14); border-radius: 12px; background: #FFF9F0; }
html.dark .pf-order { background: #2A2621; border-color: rgba(199,169,104,.16); }
.pf-order-main { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.pf-order-main b { font-size: .88em; color: var(--c-text); }
.pf-order-main span { font-size: .74em; color: var(--c-text-muted); font-variant-numeric: tabular-nums; }
.pf-order-tag { margin-left: auto; font-style: normal; font-size: .7em; padding: 2px 9px; border-radius: 999px;
  background: rgba(120,113,108,.12); color: var(--c-text-secondary); }
.pf-order-tag.granted { background: rgba(22,163,74,.14); color: #15803D; }
.pf-order-tag.pending { background: rgba(234,179,8,.18); color: #A16207; }
.pf-order-tag.refunded { background: rgba(220,38,38,.14); color: #B91C1C; }
.pf-order-tag.closed { opacity: .72; }
.pf-order-acts { display: flex; gap: 8px; margin-top: 9px; }
.pf-order-btn { padding: 5px 13px; border-radius: 999px; border: 1px solid rgba(138,106,47,.4);
  background: #FFFCF8; color: #6B4E32; font: inherit; font-size: .74em; cursor: pointer; }
.pf-order-btn.ghost { background: none; border-color: var(--c-border); color: var(--c-text-muted); }
.pf-order-btn:hover { background: #F6EEE2; }
html.dark .pf-order-btn { background: #2E2A24; color: #E7CE96; border-color: rgba(199,169,104,.32); }
html.dark .pf-order-btn.ghost { background: none; color: var(--c-text-muted); border-color: rgba(120,113,108,.4); }
@media (max-width: 768px) {
  #myOrdersOverlay { align-items: flex-end; }
  .my-orders-card { width: 100%; max-height: 82vh; border-radius: 20px 20px 0 0;
    padding-bottom: max(16px, env(safe-area-inset-bottom)); }
}
html.force-phone #myOrdersOverlay { align-items: flex-end; }
html.force-phone .my-orders-card { width: 100%; max-height: 82vh; border-radius: 20px 20px 0 0; }

/* ── 宠物盲盒（2026-10-31 用户要求）：宠物页横幅 + 抽奖浮层 ── */
.bb-banner { display: flex; align-items: center; gap: 14px; width: 100%; margin: 0 0 18px;
  padding: 13px 18px; border-radius: 16px; cursor: pointer; font: inherit; text-align: left;
  background: linear-gradient(100deg, #FBF3E2, #F6EBD6);
  border: 1px dashed rgba(138,106,47,.5); box-shadow: 0 6px 18px rgba(138,106,47,.08);
  transition: transform .18s var(--ease-out-quart), box-shadow .2s, border-color .2s; }
.bb-banner:hover { transform: translateY(-1px); border-color: rgba(138,106,47,.72);
  box-shadow: 0 10px 24px rgba(138,106,47,.14); }
.bb-banner-ico { width: 38px; height: 38px; display: grid; place-items: center; flex: none;
  border-radius: 12px; font-size: 1.2em; background: rgba(199,169,104,.24); }
.bb-banner-tx { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.bb-banner-tx b { font-family: 'Noto Serif SC', serif; font-size: .92em; color: #5C4033; }
.bb-banner-tx span { font-size: .74em; color: #8A6A2F; }
.bb-banner-go { margin-left: auto; font-size: .8em; font-weight: 600; color: #7A5C22; white-space: nowrap; }
html.dark .bb-banner { background: linear-gradient(100deg, #2E2A24, #2A2621); border-color: rgba(199,169,104,.4); }
html.dark .bb-banner-tx b { color: #F0E2C4; }
html.dark .bb-banner-tx span, html.dark .bb-banner-go { color: #C7A968; }

#blindboxOverlay { position: fixed; inset: 0; z-index: 755; display: none; align-items: center; justify-content: center;
  /* 跟站内其它弹窗一样：淡淡一层暗 + 磨砂，**背后还是宠物页**（2026-10-31 用户口径） */
  background: rgba(28,25,23,.38); -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px); }
#blindboxOverlay.show { display: flex; }
.bb-card { position: relative; width: min(430px, 92vw); max-height: 88vh; overflow: auto; padding: 22px 20px 18px;
  text-align: center; background: linear-gradient(180deg, #FFFCF8, #FAF5EE);
  border: 1px solid rgba(138,106,47,.18); border-radius: 20px; box-shadow: 0 24px 60px rgba(41,37,36,.28); }
html.dark .bb-card { background: linear-gradient(180deg, #2E2A24, #292524); border-color: rgba(199,169,104,.22); }
.bb-box { width: 58px; height: 58px; margin: 0 auto 10px; display: grid; place-items: center;
  border-radius: 16px; font-size: 1.6em; line-height: 1;
  background: linear-gradient(160deg, #F6E8C8, #E3C994);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.6), 0 6px 16px rgba(138,106,47,.16); }
.bb-card h3 { font-family: 'Noto Serif SC', serif; font-size: 1.14em; color: #5C4033; }
html.dark .bb-card h3 { color: var(--c-text); }
.bb-sub { margin: 4px 0 14px; font-size: .76em; color: var(--c-text-muted); }
/* 奖池：2 列小卡（2026-10-31 用户要求「列出来可以抽到的角色与概率，卡片做好看一点，可以用 emoji」） */
.bb-pool-hd { margin: 2px 0 7px; font-size: .68em; letter-spacing: .04em; color: var(--c-text-muted); }
.bb-pool { display: grid; grid-template-columns: 1fr 1fr; gap: 7px; text-align: left; padding: 1px; }
.bb-tile { position: relative; display: grid; grid-template-columns: 30px minmax(0, 1fr) auto;
  grid-template-rows: auto auto 3px; gap: 1px 7px; padding: 7px 9px 7px 8px; border-radius: 12px;
  background: #FFFCF8; border: 1px solid rgba(120,113,108,.16); overflow: hidden; }
html.dark .bb-tile { background: #2A2621; border-color: rgba(199,169,104,.16); }
.bb-tile-art { grid-row: 1 / 3; align-self: center; width: 30px; height: 30px; object-fit: contain; }
/* 稀有度贴纸（💎/⭐/✨）压在立绘右下角：不占文字位，又够醒目 */
.bb-tile-stk { position: absolute; left: 21px; top: 21px; width: 18px; height: 18px; display: grid;
  place-items: center; font-size: 11px; line-height: 1; border-radius: 50%;
  background: #FFFCF8; box-shadow: 0 1px 3px rgba(90,70,40,.2); }
html.dark .bb-tile-stk { background: #332D24; }
.bb-tile-tx { grid-column: 2; display: flex; flex-direction: column; min-width: 0; }
.bb-tile-tx b { font-size: .8em; color: var(--c-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bb-tile-tx span { font-size: .62em; color: var(--c-text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bb-tile-p { grid-column: 3; grid-row: 1; justify-self: end; font-family: 'Noto Serif SC', serif; font-size: .86em;
  color: #7A5C22; font-variant-numeric: tabular-nums; }
html.dark .bb-tile-p { color: #E7CE96; }
.bb-tile-v { grid-column: 3; grid-row: 2; justify-self: end; font-size: .64em; color: var(--c-text-muted); white-space: nowrap; }
/* 概率条：宽度 ∝ 概率（按最高档 25% 归一），0.5% 只剩一丝，一眼看出谁最难 */
.bb-tile-bar { grid-column: 1 / -1; grid-row: 3; margin-top: 4px; height: 3px; border-radius: 2px;
  background: rgba(120,113,108,.16); overflow: hidden; }
.bb-tile-bar i { display: block; height: 100%; border-radius: 2px;
  background: linear-gradient(90deg, #E0C58A, #B08A44); }
.bb-tile[data-r="3"] { border-color: rgba(199,169,104,.62); background: linear-gradient(180deg, #FFFCF2, #FBF0D8); }
html.dark .bb-tile[data-r="3"] { background: linear-gradient(180deg, #332D24, #2E2A22); }
.bb-tile[data-r="3"] .bb-tile-bar i { background: linear-gradient(90deg, #F2D79A, #C79A3E); }
.bb-tile[data-r="2"] { border-color: rgba(224,150,60,.45); }
.bb-tile[data-r="2"] .bb-tile-bar i { background: linear-gradient(90deg, #F0C68A, #DE9640); }
.bb-tile.is-owned { opacity: .55; }
.bb-note { margin: 12px 0 14px; font-size: .7em; line-height: 1.6; color: var(--c-text-muted); }
.bb-draw { width: 100%; min-height: 46px; border-radius: 14px; border: 1px solid #6E5322; cursor: pointer; font: inherit;
  font-size: .9em; font-weight: 700; letter-spacing: .02em; color: #FFFCF8;
  background: linear-gradient(180deg, #8A6A2F, #6E5322);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.16), 0 6px 16px rgba(122,92,34,.2);
  transition: background .18s, transform .18s; }
.bb-draw:hover { background: linear-gradient(180deg, #97763A, #765A26); }
.bb-draw:active { transform: translateY(1px); }
.bb-draw:focus-visible, .bb-again:focus-visible { outline: 2px solid var(--c-accent); outline-offset: 2px; }
html.dark .bb-draw { color: #1C1917; background: linear-gradient(180deg, #DDB63A, #C9A227); border-color: #C9A227; }
/* ── 盲盒开箱结果（2026-10-31 用户改回**卡片样式 + 撒花**）──
   就在这张 430px 的卡里：宠物落下 → 撒花 → 名字/结果 → 按钮，不再整屏接管。
   只动 transform / opacity；重播靠 JS「去掉 .bb-play → reflow → 加回」。
   撒花是 JS 现建的 22~30 个 <i>，各自带 --x/--dx/--rot/--d/--t/--c，落完即不可见。 */
.bb-card.is-reveal { width: min(430px, 92vw); }
.bb-card.is-reveal .pay-close { z-index: 9; }

.bb-hero { position: relative; height: 176px; margin: 0 -4px 4px; display: grid; place-items: center; overflow: hidden; }
/* 宠物底下那团暖光：只在这一小块里，不是整屏背景 */
.bb-glow { position: absolute; width: 210px; height: 210px; border-radius: 50%; opacity: 0;
  background: radial-gradient(closest-side, rgba(238,205,140,.5), rgba(238,205,140,0) 72%); }
.bb-play .bb-glow { animation: bbGlowIn 420ms 40ms ease-out both; }
@keyframes bbGlowIn { from { opacity: 0; transform: scale(.7); } to { opacity: 1; transform: none; } }

/* 宠物：落下来 → 稳住；落定才出地影（有影子才像站着，不是贴图）。
   ⚠️ 这一块**不放静态原画**（2026-10-31 用户明确要求）：只有庆祝动画；动画没出来时显示 emoji 占位。 */
.bb-art { position: relative; width: 154px; height: 154px; display: grid; place-items: center; opacity: 0; }
.bb-art img { grid-area: 1 / 1; width: 100%; height: 100%; object-fit: contain; display: block; }
.bb-emoji { grid-area: 1 / 1; font-size: 62px; line-height: 1; filter: drop-shadow(0 6px 12px rgba(92,64,51,.18)); }
.bb-art-anim { opacity: 0; transition: opacity .2s ease; }
.bb-art-anim.on { opacity: 1; }
.bb-art.has-anim .bb-emoji { display: none; }
.bb-art::before { content: ''; position: absolute; left: 14%; right: 14%; bottom: 2%; height: 12%; z-index: -1;
  border-radius: 50%; filter: blur(3px); opacity: 0;
  background: radial-gradient(closest-side, rgba(92,64,51,.34), rgba(92,64,51,0) 76%); }
.bb-play .bb-art { animation: bbArtIn 420ms 40ms cubic-bezier(.2,.9,.25,1) both; }
.bb-play .bb-art::before { animation: bbCast 360ms 200ms ease-out both; }
@keyframes bbArtIn {
  0% { opacity: 0; transform: translateY(14px) scale(.6); filter: blur(6px); }
  62% { opacity: 1; transform: translateY(0) scale(1.03); filter: blur(0); }
  100% { opacity: 1; transform: none; filter: none; }
}
@keyframes bbCast { from { opacity: 0; transform: scale(.6); } to { opacity: 1; transform: none; } }

/* 撒花：小纸片从上往下落、边落边转；底部用 mask 淡掉，别让它在 hero 边缘被切一刀 */
.bb-confetti { position: absolute; inset: 0; pointer-events: none; overflow: hidden;
  -webkit-mask-image: linear-gradient(180deg, #000 58%, transparent 96%);
  mask-image: linear-gradient(180deg, #000 58%, transparent 96%); }
.bb-confetti i { position: absolute; top: -16px; left: var(--x, 50%); width: var(--w, 7px); height: var(--h, 11px);
  border-radius: 2px; background: var(--c, #E3C27C); opacity: 0;
  animation: bbFall var(--t, 1.7s) var(--d, 0ms) cubic-bezier(.25,.6,.4,1) both; }
.bb-confetti i.is-round { border-radius: 50%; height: var(--w, 7px); }
@keyframes bbFall {
  0% { opacity: 0; transform: translate3d(0, -6px, 0) rotate(0deg) scale(.9); }
  10% { opacity: 1; }
  100% { opacity: 0; transform: translate3d(var(--dx, 20px), 190px, 0) rotate(var(--rot, 240deg)) scale(1); }
}

/* 文案：名字淡入上移，结果行像盖一枚章 */
.bb-card.is-reveal #bbPrizeName { margin: 2px 0 2px; color: #5C4033; font-size: 1.32em; letter-spacing: .02em; opacity: 0; }
html.dark .bb-card.is-reveal #bbPrizeName { color: var(--c-text); }
.bb-card.is-reveal .bb-prize-sub { margin: 0 0 6px; opacity: 0; }
.bb-card.is-reveal .bb-prize-line { margin: 0 0 14px; opacity: 0; }
.bb-card.is-reveal .bb-prize-line b { color: #B45309; font-family: 'Noto Serif SC', serif; font-size: 1.25em; }
.bb-card.is-reveal .bb-prize-line.is-new { color: #8A6A2F; font-family: 'Noto Serif SC', serif; letter-spacing: .04em; }
#bbReveal.bb-play #bbPrizeName { animation: bbFadeUp 380ms 220ms var(--ease-out-quart) both; }
#bbReveal.bb-play .bb-prize-sub { animation: bbFadeUp 340ms 300ms var(--ease-out-quart) both; }
#bbReveal.bb-play .bb-prize-line { animation: bbStamp 380ms 380ms cubic-bezier(.2,1.1,.3,1) both; }
@keyframes bbFadeUp { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@keyframes bbStamp { from { opacity: 0; transform: scale(1.18) rotate(-1.2deg); } to { opacity: 1; transform: none; } }

/* 按钮：最后进场；卡片里保持站内那套金主按钮 + 虚线副按钮 */
.bb-actions { display: grid; grid-template-columns: 1fr auto; gap: 10px; }
.bb-again { min-height: 46px; padding: 0 18px; border-radius: 14px; border: 1px dashed rgba(138,106,47,.45);
  background: #F5EFE4; color: #5C4033; font: inherit; font-size: .86em; font-weight: 600; cursor: pointer; }
html.dark .bb-again { background: #2E2A24; color: #E7CE96; border-color: rgba(199,169,104,.4); }
.bb-card.is-reveal .bb-actions { opacity: 0; }
#bbReveal.bb-play .bb-actions { animation: bbFadeUp 360ms 470ms var(--ease-out-quart) both; }
/* 主按钮沿用站内那套茶金（浅金在奶油卡上对比不够，实测看着像没启用） */
.bb-card.is-reveal .bb-again { background: #F5EFE4; color: #5C4033; border-color: rgba(138,106,47,.45); }
html.dark .bb-card.is-reveal .bb-again { background: #2E2A24; color: #E7CE96; border-color: rgba(199,169,104,.42); }
.bb-card.is-reveal :focus-visible { outline: 2px solid var(--c-accent); outline-offset: 2px; }

@media (max-width: 480px) {
  .bb-hero { height: 152px; }
  .bb-art { width: 134px; height: 134px; }
  .bb-emoji { font-size: 54px; }
  .bb-card.is-reveal #bbPrizeName { font-size: 1.2em; }
  /* 手机上一张卡只有 ~154px：品种名容易顶到概率，缩一档让它写全（「妙脆角猫」不要变成「妙脆角…」）。
     这里用 px 不用 em —— 实测 em 在这个元素上被算成 12px，缩不动。 */
  .bb-tile-tx span { font-size: 10.5px; }
  .bb-tile-p { font-size: .8em; }
}
/* 这套庆祝**故意不跟随 prefers-reduced-motion**（2026-10-31 用户机器上就开着"减少动态"，
   结果他只看到静态图、撒花全被关掉，等于这个功能对他不存在）。庆祝只有 0.9 秒、没有大幅位移，
   而且用户反复要求"要有动画 + 撒花"，这里以产品要求为准。
   ⚠️ 文件前面（4274 行）有一条 `* { animation-duration:.01ms !important }` 的全局收口，
   必须用更具体的选择器把它盖回来，否则这里写的时长全被压成 0.01ms（撒花瞬间播完 = 看不见）。 */
@media (prefers-reduced-motion: reduce) {
  .bb-hero .bb-art, .bb-hero .bb-glow { animation-duration: 420ms !important; }
  .bb-hero .bb-art::before { animation-duration: 360ms !important; }
  #bbReveal.bb-play #bbPrizeName, #bbReveal.bb-play .bb-prize-sub,
  #bbReveal.bb-play .bb-prize-line, #bbReveal.bb-play .bb-actions { animation-duration: 380ms !important; }
  .bb-hero .bb-confetti i { animation-duration: var(--t, 1.7s) !important; }
  .bb-art-anim { transition-duration: .2s !important; }
}
@media (max-width: 480px) {
  .bb-banner { padding: 11px 13px; gap: 10px; }
  .bb-banner-tx span { display: none; }
}

/* ── 后台订单：今日收入 + 成功/关闭分组（2026-10-31 用户要求）── */
.admin-orders-today { display: flex; align-items: baseline; gap: 16px; flex-wrap: wrap; margin: 0 0 12px;
  padding: 13px 16px; border-radius: 14px; background: #FBF3E2; border: 1px dashed rgba(138,106,47,.45); }
.aot-main { display: flex; align-items: baseline; gap: 9px; }
.aot-main span { font-size: .76em; font-weight: 600; color: #8A6A2F; letter-spacing: .04em; }
.aot-main b { font-family: 'Noto Serif SC', serif; font-size: 1.5em; color: #5C4033; font-variant-numeric: tabular-nums; }
.aot-sub { font-size: .74em; color: var(--c-text-muted); }
.admin-orders-group { margin: 0 0 14px; }
.admin-orders-group-hd { display: flex; align-items: baseline; gap: 10px; margin: 0 0 8px; }
.admin-orders-group-hd b { font-size: .82em; font-weight: 700; color: var(--c-text); }
.admin-orders-group-hd span { font-size: .72em; color: var(--c-text-muted); }
html.dark .admin-orders-today { background: #2E2A24; border-color: rgba(199,169,104,.35); }
html.dark .aot-main span { color: #C7A968; }
html.dark .aot-main b { color: #F0E2C4; }
