/* ============================================================
   单词记忆 · 视觉系统 v3
   ------------------------------------------------------------
   风格：新绿（Fresh Mint）· 扁平化 · 轻快
     · 完全扁平：无渐变、无立体投影，靠"色块 + 细描边 + 大圆角"分层
     · 淡绿护眼：纸底是低饱和薄荷绿，长时间阅读不刺眼、蓝光更低
     · 文字不用纯黑（#1B2A22 深墨绿），浅底配纯黑会发毛
     · 图标全部是内联 SVG 线性图标（24 网格 / 圆角端点），不用字符画
   主题：跟随系统明暗（prefers-color-scheme），无额外开关
   ============================================================ */

/* ================= 1. 设计令牌 ================= */
:root{
  color-scheme: light;

  /* —— 淡绿纸感底色 —— */
  --paper:#EDF4EE;          /* 页面底：低饱和薄荷绿，护眼关键 */
  --paper-2:#E3EDE5;
  --surface:#FAFDFA;        /* 卡片面：带一点绿的白，不用纯白 */
  --surface-2:#F0F6F0;      /* 内嵌面（输入框、次级块） */
  --surface-3:#E4EDE4;
  --line:#DDE8DD;
  --line-2:#C7D8C7;
  --glass:rgba(237,244,238,.82);   /* 顶栏/底栏毛玻璃 */

  /* —— 文字（深墨绿阶，不用纯黑） —— */
  --text:#1B2A22;
  --text-2:#4B5D51;
  --text-3:#5F7265;

  /* —— 主色：翡翠绿 —— */
  --brand:#0E7B4D;
  --brand-600:#0A6640;
  --brand-300:#7FCBA4;
  --brand-50:#E7F6EE;
  --brand-line:#A9D9C1;
  --on-brand:#FFFFFF;

  /* —— 次色：深青（词性、次级强调） —— */
  --accent:#0B6F68;
  --accent-50:#E2F2F0;
  --accent-line:#AEDAD6;
  --on-accent:#FFFFFF;      /* 次色实心块上的文字 */
  --wash-2:#E6F4F1;         /* 背景第二层色晕 */

  /* —— 语义色 —— */
  --amber:#9A5B08;          /* 生词 / 需巩固 */
  --amber-50:#FDF4E4;
  --amber-line:#EBD3A6;
  --red:#B23B30;            /* 删除 / 忘记 */
  --red-50:#FBEDEA;
  --red-line:#EFC7C0;

  /* —— 文中标注 —— */
  --hl-unknown-bg:#FDF0CE;
  --hl-unknown-line:#C79A2C;
  --hl-unknown-text:#6A4A10;
  --hl-marked-bg:#F9DCC0;
  --hl-marked-line:#B8722F;
  --hl-marked-text:#7A3E12;
  --hl-sel-bg:#CBE5DC;
  --hl-sent-bg:#E4F1E8;
  --hl-hover:#E8F2EA;
  --hl-row:#E9F6EF;         /* 连读时的高亮行 */

  /* —— 反馈层 —— */
  --badge:#B23B30;
  --badge-fg:#FFFFFF;
  --toast-bg:#16241D;
  --toast-fg:#F1FAF4;
  --mask:rgba(12,28,20,.40);

  /* —— 形状与投影（扁平：只给浮层留一点点影子） —— */
  --radius:16px;
  --radius-sm:12px;
  --radius-lg:22px;
  --radius-pill:999px;
  --shadow:0 1px 2px rgba(16,40,26,.05);
  --shadow-md:0 2px 10px rgba(16,40,26,.07);
  --shadow-lg:0 12px 34px rgba(16,40,26,.16);

  --nav-h:58px;
  --tab-h:58px;
  --measure:770px;          /* 正文最佳行宽，过长伤眼 */

  /* —— 字体：界面无衬线 / 正文衬线 / 音标等宽 —— */
  --font-ui:"PingFang SC","HarmonyOS Sans SC","Noto Sans SC","Source Han Sans SC",
            -apple-system,BlinkMacSystemFont,"Segoe UI","Microsoft YaHei",sans-serif;
  --font-read:"Iowan Old Style","Palatino Linotype",Palatino,"Book Antiqua",
              Georgia,"Songti SC","SimSun",serif;
  --font-mono:ui-monospace,SFMono-Regular,Menlo,Consolas,"Courier New",monospace;
}

/* 夜间：深墨绿底（不是纯黑），文字压到 #E6EFE8 避免高对比刺眼 */
@media (prefers-color-scheme: dark){
  :root{
    color-scheme: dark;

    --paper:#0D1512;
    --paper-2:#131D18;
    --surface:#16211C;
    --surface-2:#1C2923;
    --surface-3:#243430;
    --line:#26342E;
    --line-2:#374842;
    --glass:rgba(13,21,18,.82);

    --text:#E6EFE8;
    --text-2:#AFC0B4;
    --text-3:#8FA396;

    --brand:#5FD39A;
    --brand-600:#7FE0B2;
    --brand-300:#2F6B4E;
    --brand-50:#16291F;
    --brand-line:#2C5A44;
    --on-brand:#08281A;

    --accent:#6FD8CE;
    --accent-50:#142A27;
    --accent-line:#2A5350;
    --on-accent:#062B27;
    --wash-2:#14241F;

    --amber:#E8B768;
    --amber-50:#2A2214;
    --amber-line:#4C3D22;
    --red:#F08C82;
    --red-50:#2B1A17;
    --red-line:#4C2F2A;

    --hl-unknown-bg:#3D3316;
    --hl-unknown-line:#A08730;
    --hl-unknown-text:#F4E4A8;
    --hl-marked-bg:#40291A;
    --hl-marked-line:#A2682F;
    --hl-marked-text:#F7D3AC;
    --hl-sel-bg:#23453A;
    --hl-sent-bg:#1E3026;
    --hl-hover:#1E2B25;
    --hl-row:#1B3128;

    --badge:#E06B60;
    --badge-fg:#20100E;
    --toast-bg:#E6F0E9;
    --toast-fg:#0D1512;
    --mask:rgba(0,0,0,.60);

    --shadow:0 1px 2px rgba(0,0,0,.30);
    --shadow-md:0 2px 10px rgba(0,0,0,.34);
    --shadow-lg:0 12px 34px rgba(0,0,0,.48);
  }
}

/* ================= 2. 基础 ================= */
*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
html{background:var(--paper);scroll-behavior:smooth}
html,body{margin:0;padding:0}
body{
  background:transparent;
  color:var(--text);
  font-family:var(--font-ui);
  font-size:16px;
  line-height:1.65;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
  overflow-wrap:break-word;
}
/* 扁平背景：纯色底 + 两团极淡的色晕（不用渐变质感、不加噪点） */
body::before{
  content:"";position:fixed;inset:0;z-index:0;pointer-events:none;
  background:
    radial-gradient(820px 400px at 8% -10%, var(--brand-50) 0%, transparent 68%),
    radial-gradient(660px 360px at 102% -4%, var(--wash-2) 0%, transparent 62%);
}
#app{position:relative;z-index:1;min-height:100vh}
a{color:var(--brand);text-decoration:none}
a:hover{text-decoration:underline}
button{font-family:inherit}
.hide{display:none !important}
::selection{background:var(--hl-sel-bg);color:var(--text)}

/* 启动占位 */
.boot{
  min-height:100vh;display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:14px;color:var(--text-3)
}
.boot-mark{
  width:34px;height:34px;border-radius:12px;border:3px solid var(--brand-50);
  border-top-color:var(--brand);animation:spin .8s linear infinite
}
.boot-txt{font-size:13.5px;letter-spacing:.4px}

/* —— 图标基类：尺寸跟 font-size 走，颜色跟 currentColor —— */
.sprite{position:absolute;width:0;height:0;overflow:hidden}
.i{
  display:inline-block;flex:0 0 auto;
  width:1em;height:1em;vertical-align:-.14em;
  fill:none;stroke:currentColor;stroke-width:1.75;
  stroke-linecap:round;stroke-linejoin:round
}
.i.solid{fill:currentColor;stroke:none}

/* 键盘可达性：任何可交互元素都要有可见焦点环 */
:focus-visible{outline:2px solid var(--brand);outline-offset:2px;border-radius:8px}
.btn:focus-visible,.chip:focus-visible,.icon-btn:focus-visible,
.nav-item:focus-visible,.tab:focus-visible,.seg-item:focus-visible,
.auth-tab:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
.input:focus-visible,.textarea:focus-visible,.select:focus-visible{outline:none}

/* ================= 3. 布局 ================= */
.layout{display:block}

/* 侧边栏（电脑端）：透明底，跟页面同色，去掉"后台面板"感 */
.sidebar{
  display:none;
  position:sticky; top:0;
  height:100vh;
  width:212px;
  flex:0 0 212px;
  background:transparent;
  border-right:1px solid var(--line);
  padding:22px 14px;
}
.brand{
  display:flex;align-items:center;gap:10px;padding:0 8px 22px;
  font-size:17px;font-weight:700;letter-spacing:-.2px
}
.brand .logo{
  width:34px;height:34px;border-radius:11px;
  background:var(--brand);color:var(--on-brand);
  display:flex;align-items:center;justify-content:center;
  font-size:19px
}
.nav-item{
  position:relative;
  display:flex;align-items:center;gap:11px;
  min-height:44px;padding:11px 12px;margin-bottom:4px;
  border-radius:var(--radius-sm);
  color:var(--text-2);font-size:14.5px;cursor:pointer;
  transition:background .16s,color .16s;
}
.nav-item:hover{background:var(--surface-2);color:var(--text)}
.nav-item.active{background:var(--brand-50);color:var(--brand);font-weight:600}
.nav-item.active::before{
  content:"";position:absolute;left:-14px;top:50%;transform:translateY(-50%);
  width:4px;height:20px;border-radius:0 4px 4px 0;background:var(--brand)
}
.nav-item .ic{display:flex;align-items:center;justify-content:center;font-size:20px}
.nav-item .badge{
  margin-left:auto;background:var(--badge);color:var(--badge-fg);
  font-size:11px;font-weight:600;min-width:19px;height:19px;line-height:19px;
  border-radius:var(--radius-pill);text-align:center;padding:0 6px
}

.main{flex:1 1 auto;min-width:0}
.topbar{
  display:flex;align-items:center;gap:12px;
  height:var(--nav-h);padding:0 16px;
  background:var(--glass);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);
  border-bottom:1px solid var(--line);
  position:sticky;top:0;z-index:50;
}
.topbar h1{
  font-size:18px;font-weight:700;letter-spacing:-.2px;margin:0;flex:1;min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap
}
/* .content 是全站唯一的页面容器（文章列表/生词/复习/我的 都用它）。
   底部内边距不是"留白"，是「避让吸底 tabbar」的功能性间距 —— 两个断点只会覆盖
   左右上三边，底部这一项必须显式保留，别用 padding 简写把它冲掉（踩过一次，见移动端那段注释）。 */
.content{padding:16px;max-width:1080px;margin:0 auto;padding-bottom:calc(var(--tab-h) + env(safe-area-inset-bottom) + 20px)}

/* 底部 Tab（手机端） */
.tabbar{
  position:fixed;left:0;right:0;bottom:0;z-index:100;
  display:flex;background:var(--glass);
  backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);
  border-top:1px solid var(--line);
  padding-bottom:env(safe-area-inset-bottom);
}
.tab{
  flex:1;min-height:var(--tab-h);text-align:center;padding:6px 0 5px;
  color:var(--text-3);font-size:11px;font-weight:500;cursor:pointer;position:relative;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;
  transition:color .16s
}
/* 选中态：图标落进一枚淡绿圆角块里 —— 比只变色更年轻、更好认 */
.tab .ic{
  display:flex;align-items:center;justify-content:center;
  width:38px;height:26px;border-radius:9px;font-size:20px;
  transition:background .18s,transform .18s
}
.tab.active{color:var(--brand);font-weight:600}
.tab.active .ic{background:var(--brand-50)}
.tab:active .ic{transform:scale(.92)}
.tab .badge{
  position:absolute;top:2px;left:50%;margin-left:5px;
  background:var(--badge);color:var(--badge-fg);font-size:10px;font-weight:600;
  min-width:16px;height:16px;line-height:16px;border-radius:var(--radius-pill);padding:0 4px
}

/* ================= 4. 通用组件 ================= */
.card{
  background:var(--surface);border:1px solid var(--line);
  border-radius:var(--radius);padding:16px;margin-bottom:14px;
  box-shadow:var(--shadow);
}
.card.tight{padding:12px 14px}
.card-title{
  display:flex;align-items:center;gap:8px;
  font-size:15px;font-weight:700;letter-spacing:-.2px;margin:0 0 14px
}
.card-title .i{font-size:15px;color:var(--brand)}

.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:7px;
  border:1px solid var(--line-2);background:var(--surface);
  color:var(--text);border-radius:var(--radius-pill);
  min-height:40px;padding:9px 18px;font-size:14.5px;font-weight:500;cursor:pointer;
  transition:background .16s,border-color .16s,color .16s,transform .1s;
  white-space:nowrap;
}
.btn .i{font-size:16px}
.btn:hover{border-color:var(--brand-line);color:var(--brand);background:var(--brand-50)}
.btn:active{transform:scale(.975)}
.btn.primary{
  background:var(--brand);border-color:var(--brand);color:var(--on-brand);
  font-weight:600
}
.btn.primary:hover{background:var(--brand-600);border-color:var(--brand-600);color:var(--on-brand)}
.btn.ghost{background:transparent;border-color:transparent;color:var(--text-2)}
.btn.ghost:hover{background:var(--surface-2);color:var(--text)}
.btn.danger{color:var(--red);border-color:var(--red-line);background:var(--surface)}
.btn.danger:hover{background:var(--red-50);border-color:var(--red);color:var(--red)}
.btn.sm{min-height:36px;padding:6px 14px;font-size:13.5px}
.btn.sm .i{font-size:15px}
.btn.block{width:100%}
.btn:disabled{opacity:.5;cursor:not-allowed;transform:none}

.input,.textarea,.select{
  width:100%;border:1px solid var(--line-2);border-radius:var(--radius-sm);
  min-height:44px;padding:11px 14px;font-size:16px;background:var(--surface-2);
  color:var(--text);font-family:inherit;outline:none;
  transition:border-color .16s,box-shadow .16s,background .16s
}
.input::placeholder,.textarea::placeholder{color:var(--text-3)}
.input:focus,.textarea:focus,.select:focus{
  border-color:var(--brand);background:var(--surface);
  box-shadow:0 0 0 3px var(--brand-50)
}
.textarea{min-height:180px;resize:vertical;line-height:1.75}
.field{margin-bottom:14px}
.field label{display:block;font-size:13.5px;font-weight:600;color:var(--text-2);margin-bottom:6px}
/* 字段说明：口令等需要"去哪拿 / 怎么拿"的输入框下方给一条淡绿提示条 */
.field-hint{
  display:flex;gap:7px;align-items:flex-start;
  margin-top:9px;padding:9px 11px;border-radius:var(--radius-sm);
  background:var(--brand-50);border:1px solid var(--brand-line);
  font-size:12.5px;line-height:1.6;color:var(--text-2)
}
.field-hint .i{width:15px;height:15px;margin-top:1.5px;color:var(--brand)}
.field-hint b{color:var(--brand-600);font-weight:700;letter-spacing:.2px}

.empty{text-align:center;padding:44px 20px;color:var(--text-3)}
.empty .big{
  width:64px;height:64px;margin:0 auto 14px;border-radius:22px;
  background:var(--brand-50);color:var(--brand);
  display:flex;align-items:center;justify-content:center;font-size:30px
}
.empty .big .i{width:30px;height:30px}
.empty>div:nth-child(2){font-size:14.5px}

.toast{
  position:fixed;left:50%;bottom:88px;transform:translateX(-50%);
  background:var(--toast-bg);color:var(--toast-fg);padding:11px 20px;
  border-radius:var(--radius-pill);font-size:14.5px;font-weight:500;z-index:999;opacity:0;
  transition:opacity .22s,transform .22s;pointer-events:none;max-width:82vw;text-align:center;
  box-shadow:var(--shadow-lg)
}
.toast.show{opacity:1;transform:translateX(-50%) translateY(-6px)}
/* 选择模式时把 toast 抬到选择条上方，避免两者叠在一起 */
body.selecting .toast{bottom:calc(var(--tab-h) + 120px)}

.spinner{
  width:24px;height:24px;border:3px solid var(--brand-50);
  border-top-color:var(--brand);border-radius:50%;
  animation:spin .75s linear infinite;margin:28px auto
}
@keyframes spin{to{transform:rotate(360deg)}}

/* ================= 5. 登录页 ================= */
.auth-wrap{
  min-height:100vh;display:flex;align-items:center;justify-content:center;padding:20px;
  position:relative;overflow:hidden
}
/* 扁平装饰：两枚淡绿色块（不用渐变球、不用模糊） */
.auth-wrap::before,.auth-wrap::after{
  content:"";position:absolute;border-radius:44px;background:var(--brand-50);z-index:0
}
.auth-wrap::before{width:230px;height:230px;left:-92px;top:-70px;transform:rotate(18deg)}
.auth-wrap::after{width:180px;height:180px;right:-72px;bottom:-64px;transform:rotate(-14deg);
  background:var(--wash-2)}
.auth-box{
  position:relative;z-index:1;
  width:100%;max-width:400px;background:var(--surface);
  border:1px solid var(--line);
  border-radius:var(--radius-lg);padding:34px 28px;box-shadow:var(--shadow-lg)
}
.auth-box .auth-logo{
  width:48px;height:48px;border-radius:16px;background:var(--brand);color:var(--on-brand);
  display:flex;align-items:center;justify-content:center;font-size:26px;margin-bottom:16px
}
.auth-box h2{margin:0 0 5px;font-size:24px;font-weight:700;letter-spacing:-.5px}
.auth-box .sub{color:var(--text-2);font-size:13.5px;margin-bottom:24px}
/* 账号状态说明（使用到期 / 已被停用）
   常驻在登录框里，联系方式必须看得清楚——只靠一闪而过的 toast 是看不到微信号的 */
.auth-notice{
  display:flex;gap:9px;align-items:flex-start;
  padding:11px 13px;border-radius:var(--radius-sm);
  font-size:13px;line-height:1.6;margin-bottom:18px;
  border:1px solid transparent;
}
.auth-notice .i{width:16px;height:16px;flex:none;margin-top:2px}
.auth-notice span{flex:1}
.auth-notice.expired{background:var(--amber-50);border-color:var(--amber-line);color:var(--amber)}
.auth-notice.disabled{background:var(--red-50);border-color:var(--red-line);color:var(--red)}
.auth-tabs{display:flex;gap:4px;background:var(--surface-2);padding:4px;border-radius:14px;margin-bottom:20px}
.auth-tab{
  flex:1;text-align:center;padding:9px;border-radius:11px;font-size:14.5px;font-weight:500;
  color:var(--text-2);cursor:pointer;transition:background .16s,color .16s
}
.auth-tab.active{background:var(--surface);color:var(--brand);font-weight:700;
  box-shadow:var(--shadow)}
.captcha-row{display:flex;gap:10px}
.captcha-row .input{flex:1}
.captcha-img{
  height:44px;border:1px solid var(--line-2);border-radius:var(--radius-sm);
  cursor:pointer;background:var(--surface)
}

/* 验证码框按需展开（密码输错一次后出现） */
@keyframes capIn{from{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:none}}
.field.cap-in{animation:capIn .28s ease}
.field .cap-hint{font-size:12.5px;color:var(--text-3);margin-bottom:6px}

/* ================= 6. 文章列表 ================= */
.article-item{
  position:relative;display:flex;gap:13px;align-items:flex-start;overflow:hidden;
  background:var(--surface);border:1px solid var(--line);
  border-left:5px solid var(--line-2);           /* 书脊：左侧色条 */
  border-radius:var(--radius);padding:15px 18px;margin-bottom:11px;
  cursor:pointer;transition:border-color .16s,background .16s,transform .16s;
  box-shadow:var(--shadow)
}
.article-item.has-uk{border-left-color:var(--amber)}
.article-item:hover{border-color:var(--brand-line);transform:translateY(-2px)}
.article-item.has-uk:hover{border-left-color:var(--amber);border-top-color:var(--brand-line)}
/* 文档图标：放在一枚淡绿圆角块里，让列表有"条目感"而不死板 */
.article-item .art-ic{
  flex:0 0 auto;width:38px;height:38px;border-radius:12px;
  background:var(--brand-50);color:var(--brand);
  display:flex;align-items:center;justify-content:center;font-size:19px;
  transition:background .16s,color .16s
}
.article-item.has-uk .art-ic{background:var(--amber-50);color:var(--amber)}
.article-item:hover .art-ic{background:var(--brand);color:var(--on-brand)}
.article-item.has-uk:hover .art-ic{background:var(--amber);color:#FFFDF7}
.article-item .art-main{flex:1;min-width:0}
.article-item .t{
  font-size:16.5px;font-weight:700;letter-spacing:-.2px;line-height:1.45;
  margin-bottom:7px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap
}
.article-item .m{display:flex;flex-wrap:wrap;align-items:center;gap:10px;font-size:12.5px;color:var(--text-3)}
.article-item .m .uk{
  color:var(--text-3);background:var(--surface-2);border:1px solid var(--line);
  padding:2px 10px;border-radius:var(--radius-pill);font-weight:600
}
.article-item.has-uk .m .uk{
  color:var(--amber);background:var(--amber-50);border-color:var(--amber-line)
}

/* ================= 7. 阅读页 ================= */
.reader-toolbar{
  display:flex;align-items:center;gap:8px;flex-wrap:wrap;
  max-width:var(--measure);margin:0 auto 14px;
  background:var(--surface);border:1px solid var(--line);
  border-radius:var(--radius);padding:10px 12px;
  position:sticky;top:var(--nav-h);z-index:40;box-shadow:var(--shadow)
}
.seg{display:flex;background:var(--surface-2);padding:3px;border-radius:var(--radius-pill);gap:2px}
.seg-item{
  padding:7px 14px;border-radius:var(--radius-pill);font-size:13.5px;font-weight:500;
  color:var(--text-2);
  cursor:pointer;transition:background .16s,color .16s;min-height:34px;display:inline-flex;align-items:center
}
.seg-item:hover{color:var(--text)}
.seg-item.active{background:var(--brand);color:var(--on-brand);font-weight:600}
.spacer{flex:1}

/* 正文：淡绿纸感 + 衬线 + 限制行宽（一行别超过 ~70 字符，长文才不累眼） */
.article-body{
  max-width:var(--measure);margin:0 auto 14px;
  background:var(--surface);border:1px solid var(--line);
  border-radius:var(--radius-lg);padding:32px 36px 36px;
  font-family:var(--font-read);
  font-size:19px;line-height:2;letter-spacing:.15px;
  color:var(--text);box-shadow:var(--shadow);
  position:relative;overflow:hidden
}
/* 页眉压边线：扁平纯色，不用渐变 */
.article-body::before{
  content:"";position:absolute;left:0;right:0;top:0;height:4px;background:var(--brand)
}
.para{position:relative;margin-bottom:18px;padding-left:0}
.para:last-child{margin-bottom:0}
.para-num{
  display:inline-block;min-width:20px;margin-right:7px;
  color:var(--text-3);font-size:12px;font-weight:700;
  font-family:var(--font-ui);user-select:none
}
.para-btn{
  display:inline-flex;align-items:center;justify-content:center;
  width:27px;height:27px;border-radius:var(--radius-pill);
  border:1px solid var(--brand-line);
  background:var(--brand-50);color:var(--brand);font-size:13px;
  cursor:pointer;margin-right:7px;vertical-align:middle;transition:all .15s;
  font-family:var(--font-ui);
  touch-action:manipulation
}
.para-btn:hover{background:var(--brand);border-color:var(--brand);color:var(--on-brand)}
.para-btn.playing{background:var(--brand);border-color:var(--brand);color:var(--on-brand)}

.para.playing{
  background:var(--brand-50);border-radius:10px;
  box-shadow:-10px 0 0 var(--brand-50),10px 0 0 var(--brand-50)
}
.sent{cursor:pointer;border-radius:6px;padding:1px 0;transition:background .15s}
.sent:hover{background:var(--surface-2)}
.sent.playing{background:var(--hl-sel-bg);box-shadow:0 0 0 3px var(--hl-sel-bg)}
.mode-sentence .sent{cursor:pointer}
.mode-sentence .sent:hover{background:var(--amber-50)}
/* 句子级播放按钮（仅句子模式出现；点单词只弹窗，所以需要一个明确的朗读入口）
   注意：必须用 display:inline —— inline-flex/inline-block 是"原子内联"，行内断行时
   两侧都允许断行，按钮会被甩到上一行行尾、和它要朗读的句子分家（实测截图可见）。 */
.sent-btn{
  display:inline;padding:3px 9px;border-radius:var(--radius-pill);
  border:1px solid var(--brand-line);background:var(--brand-50);
  color:var(--brand);font-size:10px;line-height:1.5;
  font-family:var(--font-ui);
  cursor:pointer;vertical-align:1px;margin-right:2px;
  position:relative;z-index:2;                 /* 保证在句子文本之上，不会被压住点不到 */
  touch-action:manipulation;                   /* 去掉移动端双击缩放延迟，点击即时响应 */
  transition:all .15s;user-select:none;white-space:nowrap
}
.sent-btn .i{width:10px;height:10px;vertical-align:-.06em}
.sent-btn:hover{background:var(--brand);border-color:var(--brand);color:var(--on-brand)}
.sent-btn.playing{background:var(--brand);border-color:var(--brand);color:var(--on-brand)}

/* 句子翻译按钮（与朗读按钮同规格、同时出现，紧跟句末）
   同样必须 display:inline —— 理由见上方 .sent-btn 注释 */
.tr-btn{
  display:inline;padding:3px 8px;border-radius:var(--radius-pill);
  border:1px solid var(--accent-line);background:var(--accent-50);
  color:var(--accent);font-size:10px;line-height:1.5;
  font-family:var(--font-ui);
  cursor:pointer;vertical-align:1px;margin:0 2px 0 5px;
  position:relative;z-index:2;
  touch-action:manipulation;
  transition:all .15s;user-select:none;white-space:nowrap
}
.tr-btn .i{width:10px;height:10px;vertical-align:-.06em;margin-right:2px}
.tr-btn:hover{background:var(--accent);border-color:var(--accent);color:var(--on-accent)}
/* 已翻译：实心次色，表示"译文已展开"，再点即关闭 */
.tr-btn[data-state="on"]{background:var(--accent);border-color:var(--accent);color:var(--on-accent)}
/* 翻译中：虚线边框 + 转圈，避免重复点击 */
.tr-btn[data-state="loading"]{
  border-style:dashed;cursor:progress;opacity:.9;
  background:var(--accent-50);color:var(--accent)
}
.tr-spin{
  display:inline-block;width:9px;height:9px;margin-right:3px;vertical-align:-1px;
  border:1.5px solid currentColor;border-top-color:transparent;border-radius:50%;
  animation:spin .7s linear infinite
}

/* 译文块：另起一行贴在句子下方，左侧色条区隔，用界面字体（比正文更紧凑） */
.sent-zh{
  display:block;margin:7px 0 11px;padding:9px 13px;
  border-left:3px solid var(--accent);background:var(--accent-50);
  border-radius:0 var(--radius-sm) var(--radius-sm) 0;
  font-family:var(--font-ui);font-size:15px;line-height:1.75;
  letter-spacing:0;color:var(--text-2)
}
.sent-zh::before{
  content:"译";display:inline-block;margin-right:7px;padding:0 6px;
  border-radius:var(--radius-pill);background:var(--accent);color:var(--on-accent);
  font-size:10px;font-weight:700;line-height:1.7;vertical-align:1px;letter-spacing:.5px
}

/* 单词释义块：本地词库排版（词头 / 音标 / 词性释义）。
   与句子译文共用 .sent-zh 外壳与配色，但去掉「译」标签 —— 单词不是"翻译"，
   而是查本地词库，词头右侧的「本地词库」小标把来源说清楚 */
.sent-zh.dict{padding:9px 13px 11px}
.sent-zh.dict::before{content:none;display:none}
.dict-hd{display:flex;align-items:baseline;gap:9px;flex-wrap:wrap;margin-bottom:6px}
.dict-w{
  font-family:var(--font-read);font-size:17px;font-weight:600;
  line-height:1.25;color:var(--text);letter-spacing:.2px
}
.dict-pho{
  font-family:var(--font-mono);font-size:12.5px;line-height:1.45;
  color:var(--text-2);word-break:break-all
}
.dict-src{
  margin-left:auto;padding:0 8px;border-radius:var(--radius-pill);
  background:var(--accent);color:var(--on-accent);
  font-size:10px;font-weight:700;line-height:1.8;letter-spacing:.4px;white-space:nowrap
}
.dict-defs{display:flex;flex-direction:column;gap:3px}
.dict-def{
  display:flex;align-items:baseline;gap:8px;
  font-size:14.5px;line-height:1.7;color:var(--text-2)
}
/* 词性占固定宽度，使不同词条之间释义左边缘对齐（无词性时留白，不塌陷） */
.dict-pos{
  flex:0 0 auto;min-width:26px;
  font-family:var(--font-mono);font-size:12px;font-weight:600;color:var(--accent)
}
.dict-txt{flex:1 1 auto;min-width:0}

/* 单词标注：底部虚线 + 柔和底纹，比大面积色块更不抢眼 */
.w{cursor:pointer;border-radius:6px;padding:2px 2px;transition:background .12s;
  touch-action:manipulation}
.w:hover{background:var(--hl-hover)}
.w.known-word{border-bottom:1.5px dashed var(--line-2)}
.w.unknown-word{
  background:var(--hl-unknown-bg);border-bottom:1.5px dashed var(--hl-unknown-line);
  color:var(--hl-unknown-text);box-shadow:inset 0 -1px 0 var(--hl-unknown-line)
}
.w.marked-word{
  background:var(--hl-marked-bg);border-bottom:1.5px solid var(--hl-marked-line);
  color:var(--hl-marked-text)
}
.w.speaking{background:var(--brand) !important;color:var(--on-brand) !important}
.w.selected{background:var(--hl-sel-bg) !important;box-shadow:0 0 0 2px var(--brand)}

/* 选择模式操作条：必须"常驻可见"。
   原来是 position:sticky 且挂在文章末尾的 #selArea 里，长按第一段时它其实在
   屏幕外 —— 用户看不到任何变化，只觉得"点了没反应、单词点不出弹窗"。 */
.sel-bar{
  position:fixed;left:0;right:0;bottom:calc(var(--tab-h) + 10px);z-index:150;
  display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  max-width:680px;margin:0 auto;
  background:var(--brand);color:var(--on-brand);border-radius:var(--radius-lg);
  padding:12px 15px;box-shadow:var(--shadow-lg)
}
.sel-bar .txt{font-size:14.5px;font-weight:600;flex:1;min-width:120px}
.sel-bar .btn{background:rgba(255,255,255,.18);border-color:rgba(255,255,255,.34);color:var(--on-brand)}
.sel-bar .btn:hover{background:rgba(255,255,255,.32);color:var(--on-brand);border-color:var(--on-brand)}

/* 单词弹窗 */
.mask{
  position:fixed;inset:0;background:var(--mask);z-index:200;opacity:0;
  transition:opacity .2s;pointer-events:none
}
.mask.show{opacity:1;pointer-events:auto}
.word-pop{
  position:fixed;z-index:201;background:var(--surface);
  box-shadow:var(--shadow-lg);
  transform:translateY(100%);
  /* ⚠️ 隐藏态必须连"命中测试"和"无障碍树"一起退出。
     只靠 transform / opacity 隐藏时，元素仍然会被 elementFromPoint 命中：
     弹窗关闭后它就变成一块贴在正文上的"看不见的盖子"，把下面的单词、句子 ▶
     全部吃掉（桌面端实测 40% 单词 / 46% 句子按钮点不动，且会随滚动位置变化，
     表现为"有时候点不动"）。pointer-events 立即生效；visibility 用 0s+延迟
     跟随动画，既不打断动效，也避免键盘 Tab 跑进看不见的按钮。 */
  visibility:hidden;pointer-events:none;
  transition:transform .26s cubic-bezier(.32,.72,0,1),visibility 0s .26s;
  max-height:78vh;overflow-y:auto;
}
.word-pop.show{
  transform:translateY(0);
  visibility:visible;pointer-events:auto;
  transition:transform .26s cubic-bezier(.32,.72,0,1),visibility 0s
}
.word-pop .ph{padding:22px 20px 14px}
.word-pop .word{
  font-family:var(--font-read);font-size:30px;font-weight:600;
  letter-spacing:.3px;line-height:1.2
}
.word-pop .pho{color:var(--text-3);font-size:14px;margin-top:5px;font-family:var(--font-mono)}
.word-pop .defs{padding:0 20px 6px}
.word-pop .def{display:flex;gap:9px;margin-bottom:10px;font-size:15px;line-height:1.7}
.word-pop .pos{color:var(--accent);font-weight:700;flex:0 0 auto;min-width:34px}
/* 弹窗内部顺序：单词/音标 → 释义 → 生词本状态 → 操作区 → AI 分析。
   操作区必须排在 AI 块【之上】：弹窗是 max-height:78vh 的滚动容器，
   AI 内容（记忆方法 + 3 条例句）长度不可控，按钮排在它下面会被顶出可视区。 */
.word-pop .acts{display:flex;gap:9px;padding:10px 20px 16px;flex-wrap:wrap}
.word-pop .meta{
  padding:0 20px 4px;font-size:12.5px;color:var(--text-3);
  display:flex;align-items:center;gap:6px
}
.widget-grip{ /* 手机端底部弹窗的抓手条 */
  width:38px;height:4px;border-radius:2px;background:var(--line-2);
  margin:10px auto 0
}

/* —— 单词弹窗：AI 分析（记忆方法 + 例句） ——
   内容由接口异步填充：先渲染加载态，拿到结果再整体替换，
   所以 loading / 正常 / error 三种形态都要有对应样式。
   配色一律走 :root 令牌（暗色主题自动跟随），不用渐变。 */
.word-pop .ai-block{
  margin:0 20px 20px;padding:12px 13px;
  background:var(--surface-2);border:1px solid var(--line);border-radius:12px
}

/* —— 共享部件：单词弹窗的 AI 块 与 阅读页的句子 AI 块长得一样 ——
   这些类名全站只有这两处在用，所以直接从 .word-pop 作用域里提出来共用，
   不要各自复制一套（配色差异由各自的上下文规则覆盖）。

   ⭐ AI 解析块的阅读字阶（2026-09-19 统一调大，改之前先读这段）
     正文   语法点 / 主干结构 / 疑难词释义 / 例句中文 / 记忆方法 ……… 15px
     强调   例句英文、疑难词词形 ………………………………………… 16px
     标题   块标题「AI 分析」/ 四段小标题 ……………………………… 13.5px
     胶囊   语法点名 / 缓存标签 / 「译」 ……………………………… 11.5~12.5px

   为什么定在 15px：要和译文块 .sent-zh（15px）**同层**。
   原先 AI 讲解正文只有 13.5px，同一个句子里「中文译文」反而比「讲解」更显眼，
   讲解被读成了次要注脚 —— 但它其实是这个功能里最该被读的内容。
   再往上加到 16px 就会把卡片和句子撑得过长（AI 块本身就有四段），15px 是平衡点。
   英文/词形给 16px 是因为拉丁字母 x-height 小、同样字号视觉上比汉字轻一档。

   ⚠️ 这里刻意不引 --fs-* 令牌：本文件所有字号都是直写，只给这一组上令牌
      会形成两套体系、以后改配色式统一时更容易漏。 */
.ai-head{
  display:flex;align-items:center;gap:7px;
  font-size:13.5px;font-weight:700
}
.ai-head .i{font-size:15px}
.ai-title{letter-spacing:.2px}
.ai-tag{
  margin-left:auto;padding:1px 7px;border-radius:999px;
  font-size:12px;font-weight:400;
  /* 用 text-2 而不是 text-3：text-3 在这块底上只有 4.30:1，达不到 AA 的 4.5 */
  background:var(--surface-3);color:var(--text-2)
}
.ai-tag.fresh{background:var(--brand-50);color:var(--brand-600)}
/* 复用全站加载圈，但改成小号内联（默认那个是整页居中用的） */
.ai-load{
  display:flex;align-items:center;gap:7px;
  margin-top:9px;font-size:13.5px
}
.ai-load .spinner{display:inline-block;width:13px;height:13px;border-width:2px;margin:0}
.ai-err{margin-top:9px;font-size:13.5px;line-height:1.7;color:var(--red)}

/* 单词弹窗里的配色（块底是中性面，用次色青做标题） */
.word-pop .ai-head{color:var(--accent)}
.word-pop .ai-load{color:var(--text-3)}

/* —— 记忆方法 + 例句：单词弹窗 与 复习卡 共用（这批类名全站只这两处用） ——
   顺序：记忆方法在上、例句在下（2026-09-23 起）。间距跟着顺序走 ——
   紧跟标题的那块小一点，跟在内容后面的那块大一点。
   改顺序时记得同时改 .ai-exs / .ai-mem 这两处 margin-top。 */

/* 例句列表：现在排在记忆方法块【下面】，间距比"紧跟标题"时大一档 */
.ai-exs{margin-top:11px}
.ai-ex{padding:9px 0;border-top:1px solid var(--line)}
.ai-ex:first-child{border-top:0;padding-top:5px}
.ai-ex-line{display:flex;align-items:flex-start;gap:7px}
/* 例句英文：比中文正文大一档（1.75 → 见字阶说明），行高 1.6 保持紧凑不成块 */
.ai-en{flex:1;font-size:16px;line-height:1.65;color:var(--text)}

/* 例句播放：圆形小按钮；播放态读 data-state（与全站朗读按钮同一约定）
   margin-top 随例句行高走：例句 16px×1.65 ≈ 26.4px 行框，(26.4-22)/2 ≈ 2px，
   正好把 22px 的圆钮居中在英文首行上；写死 1px 会让它偏高半像素。 */
.ai-play{
  flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;
  width:22px;height:22px;margin-top:2px;padding:0;border-radius:50%;
  border:1px solid var(--line-2);background:var(--surface);color:var(--brand);
  font-size:10px;cursor:pointer
}
.ai-play:hover{border-color:var(--brand);background:var(--brand-50)}
.ai-play[data-state="stop"]{
  background:var(--brand);border-color:var(--brand);color:var(--on-brand)
}

/* 「译」小胶囊：中文是生成时一起拿到的，点开只是展开，不再请求翻译接口 */
.ai-tr{
  flex:0 0 auto;display:inline-flex;align-items:center;gap:2px;
  margin-top:2px;padding:2px 8px;border-radius:999px;
  border:1px solid var(--accent-line);background:var(--accent-50);color:var(--accent);
  font-size:12px;line-height:1.5;cursor:pointer
}
.ai-tr .i{font-size:11px}
.ai-tr:hover{border-color:var(--accent)}
.ai-tr[data-state="on"]{
  background:var(--accent);border-color:var(--accent);color:var(--on-accent)
}
.ai-zh{
  margin:6px 0 0 29px;   /* 29 = 播放按钮 22 + 间距 7，让中文与例句左对齐 */
  font-size:15px;line-height:1.7;color:var(--text-2)
}

/* 记忆方法：现在紧随 AI 标题（在例句【之上】），间距收到 9px */
.ai-mem{
  margin-top:9px;padding:10px 12px;border-radius:10px;
  background:var(--brand-50);border-left:2px solid var(--brand-line)
}
.ai-mem-h{
  display:flex;align-items:center;gap:5px;
  font-size:13px;font-weight:700;color:var(--brand-600)
}
.ai-mem-h .i{font-size:14px}
/* 记忆方法的整段朗读键，紧跟在「记忆方法」四个字后面。
   刻意继续复用 .ai-play 这个类 —— resetSpeechUI() 是按它统一复位图标的，
   另起类名就会重演"播完图标还卡在 ■"的老问题（见 app.js 里的注释）。
   这里只做尺寸与描边的覆盖，播放态仍由 .ai-play[data-state="stop"] 接管。 */
.ai-mem-play{
  width:20px;height:20px;
  /* .ai-play 的 2px 是为 16px 例句英文首行对中调的；
     这里是 13px 的标题行、且父级已经 align-items:center，必须归零 */
  margin-top:0;
  border-color:var(--brand-line)
}
.ai-mem-t{
  margin:5px 0 0;font-size:15px;line-height:1.75;color:var(--text-2)
}

/* 失败态的重试键：三处（弹窗 / 复习卡 / 句子）都有 */
.ai-block.error .ai-retry{margin-top:9px}

/* ============================================================
   单词配图块（AI 生图辅助记忆）
   ------------------------------------------------------------
   位置：弹窗里「操作区 .acts」之后、「AI 分析 #pwAi」之前。
   五态：占位 idle / 加载 loading / 成功 / 跳过 skip / 失败 error。
   块底与 .ai-block 同构（surface-2 + line），标题改用主色绿，
   这样"配图"和"AI 分析"两块看起来是一家人但彼此可区分。
   配色只走 :root 变量，无渐变，图标全部是内联 SVG 精灵。
   ============================================================ */

.word-pop .wi-block{
  margin:0 20px 14px;padding:12px 13px;
  background:var(--surface-2);border:1px solid var(--line);border-radius:12px
}

/* —— 标题 —— */
.wi-head{display:flex;align-items:center;gap:7px;font-size:13.5px;font-weight:700;color:var(--brand-600)}
.wi-head .i{font-size:15px}
.wi-title{letter-spacing:.2px}

/* —— 成功态：整块可点，点开全屏看 —— */
.wi-figure{
  display:block;width:100%;margin:10px 0 0;padding:0;position:relative;
  border:1px solid var(--line-2);border-radius:var(--radius-sm);
  background:var(--surface-3);overflow:hidden;cursor:zoom-in;
  line-height:0;appearance:none
}
.wi-img{display:block;width:100%;height:auto;aspect-ratio:1/1;object-fit:cover}
.wi-zoom{
  position:absolute;right:8px;bottom:8px;
  display:inline-flex;align-items:center;justify-content:center;
  width:32px;height:32px;border-radius:var(--radius-pill);
  background:var(--glass);color:var(--text);border:1px solid var(--line-2)
}
.wi-zoom .i{font-size:16px}
.wi-note{margin-top:7px;font-size:12.5px;color:var(--text-3)}

/* —— 占位态（click 模式）：一张"点我生成"的卡片 —— */
.wi-cta{
  display:flex;align-items:center;gap:10px;width:100%;
  padding:14px 13px;border-radius:var(--radius-sm);
  background:var(--surface);border:1px dashed var(--line-2);
  color:var(--text);text-align:left;appearance:none;cursor:pointer
}
.wi-cta-ic{
  display:inline-flex;align-items:center;justify-content:center;
  width:36px;height:36px;flex:0 0 auto;border-radius:var(--radius-pill);
  background:var(--brand-50);color:var(--brand-600)
}
.wi-cta-ic .i{font-size:19px}
.wi-cta-tx{flex:1 1 auto;min-width:0;font-size:14px;font-weight:600;line-height:1.35}
.wi-cta-sub{display:block;margin-top:2px;font-size:12.5px;font-weight:400;color:var(--text-3)}

/* —— 加载态（实测要 10~25 秒，文案是必须的） —— */
.wi-load{display:flex;align-items:center;gap:7px;font-size:13.5px;color:var(--text-3)}
.wi-load .spinner{display:inline-block;width:13px;height:13px;border-width:2px;margin:0}

/* —— 跳过态：一行浅灰说明。不做成"整块消失"——
      用户会更容易理解"为什么别的词有图、这个词没有"。 —— */
.wi-block.skip{padding:10px 13px}
.wi-skip{display:flex;align-items:center;gap:7px;font-size:13px;color:var(--text-3);line-height:1.6}
.wi-skip .i{font-size:15px;flex:0 0 auto}

/* —— 失败态 —— */
.wi-err{font-size:13.5px;line-height:1.7;color:var(--red)}
.wi-block.error .wi-retry{margin-top:9px}

/* —— 全屏查看层（常驻浮层，只切 class）
      ⚠️ 隐藏态同样要 visibility:hidden + pointer-events:none，
         只靠 opacity 隐藏会在页面上留一块"看不见的盖子"。 —— */
.wi-zoom-layer{
  position:fixed;left:0;right:0;top:0;bottom:0;z-index:260;
  display:flex;align-items:center;justify-content:center;flex-direction:column;gap:14px;
  padding:20px;background:var(--mask);
  visibility:hidden;pointer-events:none;opacity:0;
  transition:opacity .18s,visibility 0s .18s
}
.wi-zoom-layer.show{visibility:visible;pointer-events:auto;opacity:1;transition:opacity .18s,visibility 0s}
.wi-zoom-img{
  max-width:min(92vw,720px);max-height:78vh;width:auto;height:auto;
  border-radius:var(--radius);border:1px solid var(--line-2);background:var(--surface)
}
.wi-zoom-tip{font-size:13px;color:var(--toast-fg)}

@media(max-width:560px){
  /* 触摸目标放大一点；图片区左右留白收窄，让图更大 */
  .wi-zoom{width:38px;height:38px}
  .wi-zoom .i{font-size:18px}
  .word-pop .wi-block{margin:0 20px 12px}
}

/* ============================================================
   句子 AI 语法分析块（阅读页「句子」模式）
   ------------------------------------------------------------
   位置：紧跟译文块 .sent-zh 之后，同样是 .sent 的兄弟节点（进 .sent 会污染朗读文本）。
   与译文块同构（左侧色条 + 浅底），但**用主色绿而不是次色青** ——
   一眼分得清「这句话的中文」和「AI 的讲解」。
   ============================================================ */
.sent-ai{
  display:block;margin:0 0 13px;padding:11px 13px 13px;
  border-left:3px solid var(--brand);background:var(--brand-50);
  border-radius:0 var(--radius-sm) var(--radius-sm) 0;
  font-family:var(--font-ui);font-size:15px;line-height:1.75;
  letter-spacing:0;color:var(--text-2)
}
/* 块底是绿调，标题/标签都要按绿调重新定色（青色的 text-3 在这块底上会掉到 4.5 以下） */
.sent-ai .ai-head{color:var(--brand-600)}
.sent-ai .ai-load{color:var(--text-2)}
.sent-ai .ai-tag{background:var(--surface);color:var(--text-2)}
.sent-ai .ai-tag.fresh{background:var(--brand-600);color:var(--on-brand)}
.sent-ai .ai-retry{margin-top:9px}

/* 四段：主干结构 / 语法点 / 疑难词 / 理解与记忆
   ⭐ 正文字号统一 15px —— 与译文块 .sent-zh 等大，理由见上方「AI 解析块的阅读字阶」 */
.sent-ai .ai-sec{margin-top:11px}
/* 第一段紧跟标题，不需要那么大的间距。
   注意别写 :first-of-type —— 块的第一个 div 是 .ai-head，.ai-sec 永远不满足 */
.sent-ai .ai-head + .ai-sec{margin-top:9px}
.sent-ai .ai-sec-h{
  display:flex;align-items:center;gap:5px;
  font-size:13px;font-weight:700;color:var(--brand-600)
}
.sent-ai .ai-sec-h .i{font-size:14px}

.sent-ai .ai-struct{
  margin:4px 0 0;font-size:15px;line-height:1.75;color:var(--text-2)
}

/* 语法点：点名用小胶囊，解释跟在后面自然折行 */
.sent-ai .ai-gram{margin-top:5px;font-size:15px;line-height:1.75}
.sent-ai .ai-gram-t{
  display:inline-block;margin-right:6px;padding:0 8px;
  border-radius:var(--radius-pill);background:var(--surface);color:var(--brand-600);
  font-size:12.5px;font-weight:700;line-height:1.75;vertical-align:1px
}
.sent-ai .ai-gram-d{color:var(--text-2)}

/* 疑难词：词形用正文字体加粗，与释义拉开层次；音标用等宽但不抢眼 */
.sent-ai .ai-w{margin-top:5px;font-size:15px;line-height:1.75;color:var(--text-2)}
.sent-ai .ai-w-w{
  margin-right:6px;font-family:var(--font-read);font-size:16px;
  font-weight:600;color:var(--text);letter-spacing:.2px
}
.sent-ai .ai-w-ph{
  margin-right:6px;font-family:var(--font-mono);font-size:12.5px;color:var(--text-2)
}

/* 理解与记忆：整块的收尾，用一条虚线分隔而不是再套一层卡片 ——
   块底本来就是绿的，再叠绿卡片会糊在一起 */
.sent-ai .ai-mem{
  margin-top:12px;padding:10px 0 0;
  background:none;border:0;border-top:1px dashed var(--brand-line);border-radius:0
}
.sent-ai .ai-mem-h{
  display:flex;align-items:center;gap:5px;
  font-size:13px;font-weight:700;color:var(--brand-600)
}
.sent-ai .ai-mem-h .i{font-size:14px}
.sent-ai .ai-mem-t{
  margin:4px 0 0;font-size:15px;line-height:1.75;color:var(--text-2)
}

/* ============================================================
   文章设置面板 / 二次确认框 / 回收站
   ------------------------------------------------------------
   这两层浮层都比单词弹窗（200/201）高：面板 290/291，确认框 300/301。
   ⚠️ 隐藏态一律 visibility:hidden + pointer-events:none（同 .word-pop 的坑）：
      只靠 opacity/transform 隐藏，关闭后仍会被 elementFromPoint 命中，
      变成盖在正文上的一块"看不见的盖子"。
   ============================================================ */

/* —— 文章设置面板（手机底部抽屉 / 桌面居中卡片） —— */
.sheet-mask{
  position:fixed;inset:0;background:var(--mask);z-index:290;opacity:0;
  visibility:hidden;pointer-events:none;
  transition:opacity .2s,visibility 0s .2s
}
.sheet-mask.show{
  opacity:1;visibility:visible;pointer-events:auto;
  transition:opacity .2s,visibility 0s
}
.sheet{
  position:fixed;z-index:291;background:var(--surface);
  border:1px solid var(--line);box-shadow:var(--shadow-lg);
  left:0;right:0;bottom:0;border-radius:26px 26px 0 0;
  padding-bottom:env(safe-area-inset-bottom);
  max-height:86vh;overflow-y:auto;
  transform:translateY(100%);
  visibility:hidden;pointer-events:none;
  transition:transform .26s cubic-bezier(.32,.72,0,1),visibility 0s .26s
}
.sheet.show{
  transform:translateY(0);visibility:visible;pointer-events:auto;
  transition:transform .26s cubic-bezier(.32,.72,0,1),visibility 0s
}
@media(min-width:1024px){
  .sheet{
    left:50%;top:50%;right:auto;bottom:auto;width:560px;
    border-radius:var(--radius-lg);
    transform:translate(-50%,-46%) scale(.96);opacity:0;
    transition:transform .2s,opacity .2s,visibility 0s .2s
  }
  .sheet.show{
    transform:translate(-50%,-50%) scale(1);opacity:1;
    visibility:visible;pointer-events:auto;
    transition:transform .2s,opacity .2s,visibility 0s
  }
}
.sheet-hd{
  display:flex;align-items:center;gap:10px;
  padding:18px 20px 13px;border-bottom:1px solid var(--line)
}
.sheet-hd .t{flex:1;font-size:16.5px;font-weight:650;letter-spacing:.2px}
.sheet-x{
  flex:0 0 auto;width:32px;height:32px;display:grid;place-items:center;
  border:1px solid transparent;border-radius:var(--radius-pill);
  background:transparent;color:var(--text-3);cursor:pointer;
  transition:background .15s,color .15s
}
.sheet-x:hover{background:var(--surface-2);color:var(--text)}
.sheet-x:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
.sheet-body{padding:16px 20px 2px}
.sheet-body .field:last-of-type{margin-bottom:0}
/* 面板里正文框压矮一些：标题 + 正文 + 来源 + 按钮要能同屏看全 */
.sheet-body .textarea{min-height:150px;max-height:38vh}
.sheet-note{
  display:flex;gap:9px;align-items:flex-start;
  margin:14px 20px 0;padding:11px 13px;border-radius:var(--radius-sm);
  font-size:12.8px;line-height:1.7;color:var(--text-2);
  background:var(--surface-2);border:1px solid var(--line)
}
.sheet-note .i{margin-top:1px;flex:0 0 auto;color:var(--text-3)}
.sheet-acts{
  display:flex;gap:10px;align-items:center;flex-wrap:wrap;
  padding:16px 20px 20px
}
.sheet-acts .grow{flex:1}

/* —— 二次确认框（独立遮罩，绝不与单词弹窗共用，避免点击穿透误触） —— */
.dlg-mask{
  position:fixed;inset:0;background:var(--mask);z-index:300;opacity:0;
  visibility:hidden;pointer-events:none;
  transition:opacity .18s,visibility 0s .18s
}
.dlg-mask.show{
  opacity:1;visibility:visible;pointer-events:auto;
  transition:opacity .18s,visibility 0s
}
.dlg{
  position:fixed;z-index:301;left:50%;top:50%;
  width:min(380px,calc(100vw - 44px));
  padding:21px 22px 18px;
  background:var(--surface);border:1px solid var(--line);
  border-radius:var(--radius-lg);box-shadow:var(--shadow-lg);
  transform:translate(-50%,-50%) scale(.94);opacity:0;
  visibility:hidden;pointer-events:none;
  transition:transform .18s,opacity .18s,visibility 0s .18s
}
.dlg.show{
  transform:translate(-50%,-50%) scale(1);opacity:1;
  visibility:visible;pointer-events:auto;
  transition:transform .18s,opacity .18s,visibility 0s
}
.dlg-ic{
  display:grid;place-items:center;width:42px;height:42px;
  margin-bottom:13px;border-radius:var(--radius-pill);
  color:var(--brand);background:var(--brand-50);border:1px solid var(--brand-line)
}
.dlg-ic.danger{color:var(--red);background:var(--red-50);border-color:var(--red-line)}
.dlg-t{font-size:16.5px;font-weight:650;margin-bottom:7px;letter-spacing:.2px}
.dlg-p{font-size:13.6px;line-height:1.75;color:var(--text-2);margin-bottom:18px}
.dlg-acts{display:flex;gap:10px;justify-content:flex-end;flex-wrap:wrap}
.dlg-acts .btn{min-width:86px}

/* —— 回收站列表 —— */
.trash-item{
  display:flex;align-items:center;gap:12px;
  margin-bottom:10px;padding:13px 15px;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--radius)
}
.trash-item .main{flex:1;min-width:0}
.trash-item .t{
  font-size:15.5px;font-weight:600;line-height:1.45;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap
}
.trash-item .m{
  display:flex;flex-wrap:wrap;gap:4px 11px;margin-top:5px;
  font-size:12.5px;color:var(--text-3)
}
.trash-item .acts{display:flex;flex:0 0 auto;gap:8px}
@media(max-width:560px){
  .trash-item{flex-direction:column;align-items:stretch}
  .trash-item .acts{justify-content:flex-end}
}

/* 电脑端：弹窗居中 */
@media(min-width:1024px){
  .word-pop{
    left:50%;top:50%;right:auto;bottom:auto;
    width:452px;border-radius:var(--radius-lg);
    border:1px solid var(--line);
    transform:translate(-50%,-46%) scale(.96);opacity:0;
    transition:transform .2s,opacity .2s,visibility 0s .2s
  }
  .word-pop.show{
    transform:translate(-50%,-50%) scale(1);opacity:1;
    visibility:visible;pointer-events:auto;
    transition:transform .2s,opacity .2s,visibility 0s
  }
}
/* 手机端：底部弹出 */
@media(max-width:1023px){
  .word-pop{left:0;right:0;bottom:0;border-radius:26px 26px 0 0;
    padding-bottom:env(safe-area-inset-bottom)}
  .widget-grip{display:block}
}

/* ================= 8. 生词本 ================= */
.filters{
  display:flex;gap:8px;overflow-x:auto;padding-bottom:6px;margin-bottom:14px;
  -webkit-overflow-scrolling:touch;
  scrollbar-width:thin;scrollbar-color:var(--line-2) transparent
}
.filters::-webkit-scrollbar{height:5px}
.filters::-webkit-scrollbar-track{background:transparent}
.filters::-webkit-scrollbar-thumb{background:var(--line-2);border-radius:3px}
.chip{
  display:inline-flex;align-items:center;justify-content:center;
  min-height:36px;padding:6px 16px;border-radius:var(--radius-pill);
  background:var(--surface);border:1px solid var(--line);
  font-size:13.5px;font-weight:500;color:var(--text-2);
  cursor:pointer;white-space:nowrap;transition:all .16s
}
.chip:hover{border-color:var(--brand-line);color:var(--brand);background:var(--brand-50)}
.chip.active{
  background:var(--brand);border-color:var(--brand);color:var(--on-brand);font-weight:600
}

.word-row{
  display:flex;align-items:center;gap:12px;
  background:var(--surface);border:1px solid var(--line);
  border-radius:var(--radius);padding:13px 15px;margin-bottom:9px;box-shadow:var(--shadow);
  transition:border-color .16s,background .16s,transform .16s
}
.word-row:hover{border-color:var(--brand-line);transform:translateY(-1px)}
.word-row .info{flex:1;min-width:0}
/* 点词条主体 = 看复习记录（原来这一大片是死的，什么都不响应） */
.word-row .info[data-hist]{cursor:pointer}
.word-row .info[data-hist]:hover .w-t{color:var(--brand)}
.word-row .w-t{
  font-size:18px;font-weight:700;letter-spacing:-.2px;
  display:flex;align-items:center;gap:8px;flex-wrap:wrap;line-height:1.3
}
.word-row .w-p{
  color:var(--text-3);font-size:13px;font-weight:400;
  font-family:var(--font-mono);letter-spacing:0
}
.word-row .w-d{
  color:var(--text-2);font-size:13.5px;margin-top:4px;
  overflow:hidden;text-overflow:ellipsis;display:-webkit-box;
  -webkit-line-clamp:2;-webkit-box-orient:vertical
}
.word-row .acts{display:flex;flex-direction:row;gap:6px;flex:0 0 auto}

/* —— 熟练度行（生词本 / 复习记录面板共用）——
   取代原来的 Lv.N：内部等级用户看不懂，"复习过几次 / 连对几格 / 下次什么时候见"才看得懂。 */
.w-prof{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-top:6px}
.pv{display:inline-flex;align-items:center;gap:4px;font-size:12px;color:var(--text-3);white-space:nowrap}
.pv b{color:var(--text-2);font-weight:700}
.pv.warn b{color:var(--red)}
.pv.ok{color:var(--brand);font-weight:600}
.pv.new{color:var(--amber);font-weight:600}
/* 操作按钮默认"安静"（无边框），hover/focus 才亮起来，列表才不吵 */
.icon-btn{
  width:36px;height:36px;border-radius:var(--radius-sm);border:1px solid transparent;
  background:var(--surface-2);color:var(--text-2);cursor:pointer;font-size:17px;
  display:flex;align-items:center;justify-content:center;transition:all .15s
}
.icon-btn:hover{border-color:var(--brand);color:var(--brand);background:var(--brand-50)}
.icon-btn.on{background:var(--amber);border-color:var(--amber);color:#FFFDF7}
.tag{
  display:inline-flex;align-items:center;gap:4px;
  font-size:11.5px;padding:2px 9px;border-radius:var(--radius-pill);
  background:var(--surface-2);color:var(--text-2);border:1px solid var(--line);
  font-family:var(--font-ui);font-weight:600
}
.tag.marked{background:var(--amber-50);color:var(--amber);border-color:var(--amber-line)}
.tag.mastered{background:var(--accent-50);color:var(--accent);border-color:var(--accent-line)}

/* ================= 9. 复习卡 ================= */
.review-wrap{max-width:540px;margin:0 auto}
.rv-card{
  background:var(--surface);border:1px solid var(--line);border-radius:var(--radius-lg);
  padding:48px 26px 32px;text-align:center;box-shadow:var(--shadow);min-height:300px;
  display:flex;flex-direction:column;position:relative;overflow:hidden
}
.rv-card::before{
  content:"";position:absolute;left:0;right:0;top:0;height:4px;background:var(--brand)
}
.rv-word{
  font-family:var(--font-read);font-size:38px;font-weight:600;
  letter-spacing:.5px;word-break:break-word;line-height:1.2
}
/* 音标行 = 音标 + 朗读键（+ 需巩固标签），横排居中。
   朗读键挂在这里，而不是像以前那样吊在卡片底部：揭晓释义后下面还要长出一整块
   AI 分析，吊在底部一定会被顶出屏幕 —— 想听一下读音还得先往下滚。 */
.rv-pho{
  display:flex;align-items:center;justify-content:center;gap:10px;
  margin-top:10px;color:var(--text-3);font-size:15px;font-family:var(--font-mono)
}
.rv-ipa{letter-spacing:.2px}
.rv-spk{
  flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;
  width:32px;height:32px;padding:0;border-radius:50%;
  border:1px solid var(--line-2);background:var(--surface);color:var(--brand);
  font-size:15px;cursor:pointer;
  transition:transform .12s,border-color .16s,background .16s
}
.rv-spk:hover{border-color:var(--brand);background:var(--brand-50);transform:translateY(-1px)}
.rv-spk:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
.rv-mean{margin-top:22px;padding-top:20px;border-top:1px dashed var(--line-2)}
/* 复习卡里的 AI 分析块：与单词弹窗同款内容（记忆方法 + 例句），
   所以样式直接复用共用部件，只补三件它自己的事 ——
   ① 卡片是 text-align:center，这里要显式左对齐，否则例句逐行居中没法读；
   ② 外边距由卡片统一给（弹窗那边是左右 20px 的固定内边距）；
   ③ 块底是卡片白面，用 --surface-2 内嵌 + --accent 标题，与弹窗保持一致。
   ⚠ 它现在排在评价按钮【之下】（评价按钮必须留在首屏，见 app.js 里的顺序注释），
     所以上边距要留够，把「打分区」和「讲解区」在视觉上分开；同时 0 0 auto
     保证 flex 布局下它不会被挤扁。 */
.rv-card .ai-block{
  flex:0 0 auto;margin:26px 0 0;padding:12px 13px;text-align:left;
  background:var(--surface-2);border:1px solid var(--line);border-radius:12px
}
.rv-card .ai-head{color:var(--accent)}
.rv-card .ai-load{color:var(--text-3)}
.rv-mean .def{font-size:16px;margin-bottom:8px;line-height:1.7}
.rv-mean .pos{color:var(--accent);font-weight:700;margin-right:7px}
/* —— 顶部：今日配额进度（"今天要做完多少 / 还剩多少"）—— */
.rv-top{margin-bottom:12px}
.rv-top-l{display:flex;align-items:baseline;gap:6px;font-size:13px;color:var(--text-2);margin-bottom:8px}
.rv-top-l .n{font-size:19px;font-weight:700;color:var(--brand);letter-spacing:-.4px}
.rv-top-l .sep,.rv-top-l .g{color:var(--text-3)}
.rv-top-r{margin-left:auto;font-size:12.5px;color:var(--text-3)}
.rv-top-r b{font-size:13.5px;color:var(--text)}
.rv-top-r.done{color:var(--brand);font-weight:600}

.rv-progress{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:14px;font-size:13.5px;color:var(--text-2)}
.rv-progress .rv-pg{font-weight:600;white-space:nowrap}
/* 重来/积压提示单独一节，窄屏会自动换到第二行，不会把进度条挤没 */
.rv-progress .rv-pg-x{font-size:12.5px;font-weight:400;color:var(--text-3);white-space:nowrap}
.rv-bar{flex:1;min-width:70px;height:8px;background:var(--surface-3);border-radius:var(--radius-pill);overflow:hidden}
.rv-bar.thin{height:6px}
.rv-bar i{display:block;height:100%;background:var(--brand);border-radius:var(--radius-pill);
  transition:width .3s}

/* —— 词头元信息：第几次复习 / 连对几格 / 上次答得如何 ——
   这三个量以前完全看不到，而"哪些复习了好几遍、哪些复习得少"正是本次重做要回答的问题。 */
.rv-meta{display:flex;align-items:center;justify-content:center;gap:8px;flex-wrap:wrap;margin-top:12px}
.rv-badge{
  font-size:11.5px;font-weight:600;padding:3px 10px;border-radius:var(--radius-pill);
  background:var(--surface-2);color:var(--text-2);border:1px solid var(--line);font-family:var(--font-ui)
}
.rv-badge.fresh{background:var(--brand-50);color:var(--brand);border-color:var(--brand-line)}
.rv-badge.mastered{background:var(--accent-50);color:var(--accent);border-color:var(--accent-line)}
.rv-streak,.rv-last{display:inline-flex;align-items:center;gap:5px;font-size:12.5px;color:var(--text-3)}
.rv-streak b,.rv-last b{font-size:13.5px;color:var(--text);font-weight:700}

/* 记忆度圆点：实心 = 已连对的格数，空心 = 还差几格毕业 */
.rv-dots{display:inline-flex;gap:2px;vertical-align:middle}
.rv-dots i{
  display:block;width:6px;height:6px;border-radius:50%;
  border:1px solid var(--line-2);background:transparent
}
.rv-dots i.on{background:var(--brand);border-color:var(--brand)}
.tag .rv-dots,.pv .rv-dots{margin-left:2px}

/* —— 评价按钮：揭晓释义后紧贴释义出现，是这张卡的主要操作区 ——
   四档：不认识 / 有点模糊 / 认识 / 秒答（编码 1~4，与后端 config/review.php 对齐）。
   每个按钮的第二行是这个选项对应的"下次什么时候见" —— 把算法的决定摊开给用户看，
   比只写"认识/不认识"有用得多：点之前就知道这一下会把间隔推到多远。
   它是 flex 列里的固定项，必须 flex:0 0 auto —— 否则一旦下面的 AI 块撑高卡片，
   flex 会先压缩可压缩项，按钮高度就被吃掉了，点着更难受。 */
.rv-acts{display:grid;grid-template-columns:repeat(4,1fr);gap:8px;margin-top:22px;flex:0 0 auto}
/* 揭晓前只有一颗「显示释义」：让它独占整行（不然 4 列网格里它只占 1/4 宽，缩在左边） */
.rv-acts.single{grid-template-columns:1fr}
.rv-btn{
  min-height:58px;padding:9px 6px;border-radius:var(--radius);border:1px solid var(--line-2);
  background:var(--surface);cursor:pointer;color:var(--text);
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;
  transition:transform .12s,background .16s;font-family:inherit
}
.rv-btn:hover{transform:translateY(-2px)}
.rv-btn .lb{font-size:15.5px;font-weight:700;line-height:1.25}
.rv-btn .sub{font-size:11.5px;font-weight:500;line-height:1.3;opacity:.8}
.rv-btn .sub.grad{font-weight:700;opacity:1}
.rv-btn.k{color:var(--accent);border-color:var(--accent-line);background:var(--accent-50)}
.rv-btn.f{color:var(--amber);border-color:var(--amber-line);background:var(--amber-50)}
.rv-btn.n{color:var(--red);border-color:var(--red-line);background:var(--red-50)}
/* 秒答 = 连对直接加两格，最积极的一档，用主色 */
.rv-btn.s{color:var(--brand);border-color:var(--brand-line);background:var(--brand-50)}
.rv-hint{text-align:center;color:var(--text-3);font-size:13.5px;margin-top:14px}

/* ================= 9b. 复习记录面板（生词本点词打开） =================
   回答"这个词复习了多少次、每次记不记得"：上面是熟度概览，下面是流水时间轴。
   颜色按四档结果分：不认识(红) / 有点模糊(琥珀) / 认识(青) / 秒答(主绿)。
   ⚠️ 只看 --* 令牌，明暗两套主题自动跟随，别写死颜色。 */
.wh-head{padding:2px 0 14px;border-bottom:1px dashed var(--line-2);margin-bottom:12px}
.wh-word{
  font-family:var(--font-read);font-size:26px;font-weight:600;line-height:1.25;
  display:flex;align-items:baseline;gap:9px;flex-wrap:wrap
}
.wh-word .w-p{font-size:13px;font-family:var(--font-mono);color:var(--text-3);font-weight:400}
.wh-def{font-size:13.5px;color:var(--text-2);margin-top:5px;line-height:1.6}
.wh-prof{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-top:10px}
.wh-sub{font-size:12.5px;color:var(--text-3);margin-bottom:6px}
.wh-tl{list-style:none;margin:0;padding:0}
.wh-item{
  display:flex;align-items:center;gap:9px;flex-wrap:wrap;
  padding:9px 0;border-bottom:1px solid var(--line);font-size:13px
}
.wh-item:last-child{border-bottom:0}
.wh-item .dot{width:8px;height:8px;border-radius:50%;flex:0 0 auto;background:var(--text-3)}
.wh-item .lb{font-weight:700;min-width:62px}
.wh-item .st{font-size:12px;color:var(--text-3)}
.wh-item .nx{font-size:12px;color:var(--text-3)}
.wh-item .tm{margin-left:auto;font-size:12px;color:var(--text-3);font-family:var(--font-mono)}
.wh-item.r-unknown .dot{background:var(--red)}
.wh-item.r-unknown .lb{color:var(--red)}
.wh-item.r-vague .dot{background:var(--amber)}
.wh-item.r-vague .lb{color:var(--amber)}
.wh-item.r-known .dot{background:var(--accent)}
.wh-item.r-known .lb{color:var(--accent)}
.wh-item.r-instant .dot{background:var(--brand)}
.wh-item.r-instant .lb{color:var(--brand)}

/* ================= 10. 统计 / 我的 ================= */
.stats-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(116px,1fr));gap:11px;margin-bottom:14px}
.stat{
  background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);
  padding:15px 12px 14px;text-align:center;box-shadow:var(--shadow);
  display:flex;flex-direction:column;align-items:center;gap:8px
}
.stat .si{
  width:34px;height:34px;border-radius:11px;
  background:var(--brand-50);color:var(--brand);
  display:flex;align-items:center;justify-content:center;font-size:18px
}
.stat .n{
  font-size:26px;font-weight:700;letter-spacing:-.6px;line-height:1.1;color:var(--text)
}
.stat .l{font-size:12.5px;color:var(--text-3);margin-top:-4px}
.curve{display:flex;align-items:flex-end;gap:7px;height:112px;padding-top:8px}
.curve .col{flex:1;display:flex;flex-direction:column;align-items:center;gap:5px;height:100%;justify-content:flex-end}
.curve .bar{
  width:100%;max-width:28px;border-radius:6px;min-height:3px;
  background:var(--brand-300);transition:height .4s
}
.curve .col:last-child .bar{background:var(--brand)}
.curve .lb{font-size:11px;color:var(--text-3)}
.curve .vl{font-size:11px;font-weight:600;color:var(--text-2)}

/* 头像：把 JS 里的内联色块收进样式表，主题切换才不会漏色 */
.avatar{
  width:46px;height:46px;border-radius:var(--radius-sm);
  background:var(--brand-50);color:var(--brand);
  display:flex;align-items:center;justify-content:center;
  font-weight:700;font-size:19px
}
.meta-line{font-size:13px;color:var(--text-2);line-height:1.9}
.meta-line b{color:var(--text)}

/* —— 每日复习计划（可调配额）—— */
.quo-top{display:flex;align-items:baseline;gap:6px;font-size:13px;color:var(--text-2);margin-bottom:8px}
.quo-top-l{display:flex;align-items:baseline;gap:5px}
.quo-top-l .n{font-size:19px;font-weight:700;color:var(--brand);letter-spacing:-.4px}
.quo-top-l .sep,.quo-top-l .g{color:var(--text-3)}
.quo-top-r{margin-left:auto;font-size:12.5px;color:var(--text-3)}
.quo-rows{margin-top:18px}
.quo-row{display:flex;align-items:center;gap:14px;padding:12px 0;border-top:1px solid var(--line)}
.quo-l{flex:1;min-width:0}
.quo-t{font-size:14.5px;font-weight:600}
.quo-d{font-size:12.5px;color:var(--text-3);margin-top:2px;line-height:1.5}
/* 数字步进器：− 20 +。改动乐观更新 + 防抖，连点只发一次请求（见 app.js bindSteppers） */
.stepper{
  flex:0 0 auto;display:flex;align-items:center;
  border:1px solid var(--line-2);border-radius:var(--radius-sm);overflow:hidden;background:var(--surface)
}
.stepper button{
  width:38px;height:38px;border:0;background:var(--surface-2);color:var(--text);
  cursor:pointer;font-size:19px;line-height:1;padding:0;
  transition:background .15s,color .15s
}
.stepper button:hover{background:var(--brand-50);color:var(--brand)}
.stepper b{
  min-width:56px;text-align:center;font-size:16px;font-weight:700;
  font-variant-numeric:tabular-nums;color:var(--text)
}

/* ================= 11. 断点 ================= */
@media(max-width:1023px){
  .sidebar{display:none}
  .tabbar{display:flex}
  /* ⚠️ 这里不能用 padding 简写收尾。写成 padding:12px 会把「避让吸底 tabbar」的
     padding-bottom 一起冲掉 —— 而 .tabbar 恰好只在移动端显示（桌面 display:none），
     结果移动端底部只剩 12px，最后一条文章被 58px 高的导航压住约 46px。
     底部必须显式再写一次；env(safe-area-inset-bottom) 与 .tabbar 自身的 padding 对齐，
     否则 iPhone 刘海屏的安全区又会多压掉一截。 */
  .content{padding:12px;padding-bottom:calc(var(--tab-h) + env(safe-area-inset-bottom) + 20px)}
  .article-body{padding:22px 18px 26px;font-size:18px;line-height:1.95}
  .article-item{padding:14px 15px;gap:11px}
  .article-item .art-ic{width:36px;height:36px;font-size:18px}
  .article-item .t{font-size:16px}
  /* 触摸目标 ≥44px（移动端） */
  .chip{min-height:40px;padding:8px 17px}
  .icon-btn{width:44px;height:44px}
  .btn{min-height:44px}
  .rv-spk{width:44px;height:44px;font-size:18px}
  .stepper button{width:44px;height:44px}
}
/* 窄屏手机：四档按钮排成 2×2 ——
   375px 屏上卡片内宽只剩约 300px，四列每列 68px，"有点模糊"四个字放不下。
   2×2 每列约 145px，字号不用缩，触摸目标也更大。 */
@media(max-width:560px){
  .rv-acts{grid-template-columns:repeat(2,1fr);gap:9px}
  .rv-btn{min-height:56px}
  /* 复习记录行在窄屏放不下「连对 N」这一节，优先保住结果、下次、时间三列 */
  .wh-item .st{display:none}
  .wh-item .lb{min-width:56px}
}
@media(min-width:1024px){
  .layout{display:flex;min-height:100vh}
  .sidebar{display:block}
  .tabbar{display:none}
  .content{padding:24px 30px 46px}
  .topbar{display:none}
  .reader-toolbar{top:0}
  .toast{bottom:40px}
  .rv-hint{display:none}
  .sel-bar{left:212px;bottom:20px;max-width:900px}
  body.selecting .toast{bottom:92px}
}

/* ================= 12. 无障碍：尊重系统减弱动效 ================= */@media (prefers-reduced-motion: reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{
    animation-duration:.01ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.01ms !important
  }
}
