/* layout.css —— 两级导航 + 页面骨架 + 响应式
   断点：>=1200 三列 / 900-1199 两列 / <900 单列并收起侧栏 / <768 汉堡菜单
   面向安卓平板：横向 1280 走三列，纵向 800 走单列，触控目标不低于 44px */

.wrap {
  max-width: var(--wrap);
  margin: 0 auto;
  padding: 0 16px;
}

/* ---------- 一级导航 ---------- */
.topbar {
  background: var(--c-deep);
  position: sticky;
  top: 0;
  z-index: 40;
}

.topbar-inner {
  max-width: var(--wrap);
  margin: 0 auto;
  padding: 0 16px;
  height: 56px;
  display: flex;
  align-items: center;
  gap: 6px;
}

.hamburger {
  display: none;
  width: var(--tap);
  height: var(--tap);
  margin-left: -8px;
  background: transparent;
  border: 0;
  padding: 0;
  cursor: pointer;
  color: #e9f1fa;
  align-items: center;
  justify-content: center;
}

/* ============================================================================
   雅思入口的**光圈**（老师 2026-10-05 第三次，最终版）

   老师原话：「双击SPRINT的logo，logo开始闪烁黄色光圈（类似于时钟走一圈），
              如果有进入雅思模考的权限，黄色光圈就会变成绿色，此时再双击logo
              就进入系统（不做任何文字提示），这里两次双击的间隔设置为5秒，
              就是最长5秒内光圈跑完一圈」

   ★★ 这里我改过一版实现，记下来免得再退回去：
      第一版画的是 `conic-gradient` + `mask` 的 **3px 细圆环**（想做"时钟指针"）。
      截图一看**根本不显示** —— 两个原因叠加：
        ① `mask` 的 `radial-gradient` 把环带整个遮掉了（可见区算错）；
        ② **就算画对了也太细**：顶栏是深色，5px 的环在这样的小 logo 上
           几乎看不见，而老师要的是"一眼看出状态"。
      ⇒ 改成**大面积光晕**：整块圆角矩形染成黄/绿 + 呼吸闪烁 + 外发光。
        这才叫"光圈"，在深色顶栏上隔着两米都看得见。
      （教训：**视觉的东西必须截图看**，别靠读 CSS 推演。我第一版要是只看代码
        会以为它是对的。）

   ★ 环由**外层 div** 画，不给 button 加 border —— border 会改盒模型尺寸，
     一加环 logo 就跳一下。外层固定、环浮在它下面，logo 一动不动。
   ============================================================================ */

.brand-wrap {
  position: relative;
  display: flex;
  align-items: center;
  flex: 0 0 auto;
}

/* 光圈：绝对定位在 logo 那一段的**下面一层**（z-index 负），
   这样 logo 与文字压在光上，字始终清楚。
   ★ `pointer-events: none` —— 光圈不能吃掉点击，否则双击点不到 logo。 */
.brand-ring {
  position: absolute;
  inset: -3px -5px;
  border-radius: 10px;
  pointer-events: none;
  z-index: -1;
  opacity: 0;
  transition: opacity .15s linear, background .2s linear;
}

/* 黄：正在跑。★「闪烁」是老师点名的 —— 呼吸式（不做频闪，那会晕）。
   亮度/外发光随呼吸起伏，5 秒一圈由 JS 的 --ring-sec 控制（见下 animation）。 */
.brand-ring.is-asking {
  opacity: 1;
  background: rgba(245, 197, 66, .92);
  animation: brand-ring-pulse 1.1s ease-in-out infinite,
             brand-ring-sweep-fade var(--ring-sec, 5s) linear forwards;
}

/* 绿：已放行。**稳定不闪** —— 它在说"可以进了"，闪反而让人不敢点。 */
.brand-ring.is-ready {
  opacity: 1;
  background: rgba(34, 197, 94, .95);
  box-shadow: 0 0 0 3px rgba(34, 197, 94, .28),
              0 0 18px rgba(34, 197, 94, .75);
}

/* 呼吸：连外发光一起起伏，看起来才像"光"而不是"一块色" */
@keyframes brand-ring-pulse {
  0%, 100% {
    box-shadow: 0 0 0 2px rgba(245, 197, 66, .35),
                0 0 10px rgba(245, 197, 66, .55);
  }
  50% {
    box-shadow: 0 0 0 4px rgba(245, 197, 66, .55),
                0 0 22px rgba(245, 197, 66, .95);
  }
}

/* 「时钟走一圈」这层意思：5 秒内从**暗→亮→最亮**再收住。
   ★ 它是**视觉计时器** —— 用户看得出来"还剩多少时间"，而不是干等。
   ★ 跑完（forwards）停在最亮处，此时若已放行就接上绿光。 */
@keyframes brand-ring-sweep-fade {
  0%   { filter: brightness(.55) saturate(.8); transform: scale(.97); }
  70%  { filter: brightness(1.15) saturate(1.15); transform: scale(1.01); }
  100% { filter: brightness(1.45) saturate(1.25); transform: scale(1.04); }
}

/* 视觉隐藏、只给读屏用（老师要"不做任何文字提示"，
   但读屏用户看不到颜色，得有句话） */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* 顶栏里 SPRINT 那一段本该占的位置由 wrap 接管。
   ★ 因为给 wrap 加了 `position: relative` 但没有 z-index，
     光圈用 `z-index:-1` 会掉到顶栏背景**后面**去 —— 所以这里给 wrap 一个
     独立的层叠上下文，把光圈关在里面（负值只对内层有效）。 */
.brand-wrap { z-index: 0; }

@media (prefers-reduced-motion: reduce) {
  /* 动效敏感的人：不闪、不缩放，只留纯色光（状态照样看得出来） */
  .brand-ring.is-asking {
    animation: none;
    background: rgba(245, 197, 66, .85);
  }
}

.brand {
  display: flex;
  align-items: center;
  gap: 8px;
  height: var(--tap);
  padding-right: 12px;
  color: var(--t-bright);
  font-size: var(--fs-lg);
  white-space: nowrap;
  /* ★★★ 透明底 + 无边框。**必须有这两行**。
     原因：这个元素是 `<button>`（第二轮为了不进 SPA 路由从 `<a>` 换过来的），
     而浏览器给 button 的默认样式是 `background-color: buttonface`（一块灰）+ 一圈边框。
     老师看到的就是那块灰：「为什么现在这个部分加了灰色的框体颜色？
     把这个背景色透明掉，不要让它看起来和周围的格格不入」。
     ⇒ 项目里没有全局 button 重置（theme.css 只重置了 font/color），
       所以这里要显式写掉。**以后再把 logo 换成 button 时别忘了这两行。** */
  background: transparent;
  border: 0;
  cursor: pointer;
  /* 透明底之后按下/悬停也不该出现默认底色 */
  -webkit-appearance: none;
  appearance: none;
}

.brand:hover,
.brand:focus,
.brand:active {
  background: transparent;
}

/* 键盘可达性：不要用 outline 之外的方式"去掉焦点环"——
   去掉焦点环会让键盘用户不知道焦点在哪。这里只把默认蓝框换成主题色。 */
.brand:focus-visible {
  outline: 2px solid var(--t-bright);
  outline-offset: 2px;
}

.brand-mark {
  /* ★ 2026-10-06：22px → **34px**，与弧线（`.brand-arc` 34px）同尺寸 ——
     照登录页 `.login-mark .mark { width:34px }` 与 `.login-ring`（52px 容器
     里的 34px 环）的比例。两者同尺寸时**圆心自然重合**，不需要再算偏移。 */
  width: 34px;
  height: 34px;
  flex: 0 0 auto;
}

/* ★★★ 2026-10-06（老师）：
   「我之前设想的是这个上面的**白圈换成转动的光圈**，而且这个部分和 SPRINT
     **独立成两块区域**，只有点中 S 的区域才会开始转动。
     现在判定的范围把 SPRINT 字母所在的位置也算进去了。」
   ⇒ **几何完全照抄登录页**（`.login-mark` / `.login-ring`）——
     我先去看了登录页截图，那个效果正是老师要的：
       · 弧线 = **CSS 边框的两条边**（上=绿、右=蓝），不是 SVG
       · 弧线尺寸 34px、`border:2px`、`border-radius:50%`
       · S 图标也是 34px，两者**同心**（都居中在同一个容器里）
     ★ 我第一版自己造了个 34px 的 SVG 弧套在外面 ⇒ 与白圈**不同心**，
       看着"套在字母上"（老师一眼看出）。**教训：照抄已验证的实现，别自己推几何。**
     ★ 与登录页唯一的区别：**不写 animation** —— 角度由 JS 逐帧驱动
       （`ielts.js` 的 `brandSpin`）。写了 CSS 动画会和 JS 抢 `transform`，
       表现就是"怎么按都不转"。 */
.brand-mark-hit {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  flex: 0 0 auto;
  cursor: pointer;
}

.brand-arc {
  position: absolute;
  inset: 0;                     /* ← 与登录页 `.login-ring` 同一条 */
  width: 34px;
  height: 34px;
  border-radius: 50%;
  border: 2px solid transparent;
  border-top-color: rgba(117, 176, 34, .85);    /* 绿弧（登录页同色） */
  border-right-color: rgba(102, 192, 244, .6);  /* 蓝弧（登录页同色） */
  pointer-events: none;         /* ★ 别抢"按住" —— 事件要落在 .brand-mark-hit 上 */
  transform: rotate(0deg);
  transition: box-shadow .18s linear;
  will-change: transform;
}

/* 转速到最大：加一圈发光。**这是唯一的可发现性提示**（老师要求不写任何文字） */
.brand-arc.is-max {
  box-shadow: 0 0 6px rgba(117, 176, 34, .8), 0 0 12px rgba(102, 192, 244, .45);
}

/* 触屏没有 hover，"按住"期间也要给反馈 */
.brand-arc.is-press {
  box-shadow: 0 0 5px rgba(117, 176, 34, .6);
}

/* ★★★ 2026-10-06（老师第二轮）：**注水动画**。
   把 S 的圈当容器，液面由 JS 驱动（`brandFill` / `paintFill`）。
   ★ 与弧线**同尺寸、同位置**（都是 34px 居中在 `.brand-mark-hit` 里）
     ⇒ 液面正好在圆圈内部升，不会溢出白圈。
   ★ `pointer-events:none`：别抢"按住"事件（事件要落在 `.brand-mark-hit` 上）。
   ★ 放在弧线**之后**（DOM 顺序）⇒ 液体盖在弧线上；弧线本来就压在圈的边上，
     液体在内部，视觉上不打架。 */
.brand-liquid {
  position: absolute;
  inset: 0;
  width: 34px;
  height: 34px;
  pointer-events: none;
}

.mainnav {
  display: flex;
  align-items: center;
  gap: 2px;
  flex: 1 1 auto;
  min-width: 0;
}

.navlink {
  display: flex;
  align-items: center;
  height: 38px;
  padding: 0 13px;
  border-radius: 10px;
  color: rgba(237, 244, 251, .68);
  font-size: 13.5px;
  font-weight: 600;
  letter-spacing: .02em;
  white-space: nowrap;
  cursor: pointer;
  border: 0;
  background: transparent;
  transition: background .14s ease, color .14s ease;
}

.navlink:hover {
  background: rgba(255, 255, 255, .07);
  color: #ffffff;
}

/* 激活项：主色淡底 + 底部 2px 亮线（比旧版左缘渐变条更容易一眼定位） */
.navlink.is-active {
  background: rgba(124, 196, 245, .14);
  color: #ffffff;
  box-shadow: inset 0 -2px 0 #7cc4f5;
}

.navlink .badge-dot {
  margin-left: 6px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--c-gold);
}

.topbar-right {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 0 0 auto;
  /* 用户菜单是绝对定位的，必须锚到这一层，否则会挂到 sticky 的 .topbar 上 */
  position: relative;
}

.searchbox {
  position: relative;
}

.searchbox input {
  width: 220px;
  height: 34px;
  padding: 0 30px 0 10px;
  background: var(--c-input);
  border: 1px solid transparent;
  border-radius: var(--r-md);
  color: var(--t-primary);
  font-size: var(--fs-md);
}

.searchbox input::placeholder {
  color: var(--t-dim);
}

.searchbox input:focus {
  outline: none;
  border-color: var(--c-accent);
  background: #0a1119;
}

.searchbox .icon {
  position: absolute;
  right: 8px;
  top: 50%;
  transform: translateY(-50%);
  width: 14px;
  height: 14px;
  color: var(--t-dim);
  pointer-events: none;
}

.userbox {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 38px;
  padding: 0 8px;
  border-radius: var(--r-md);
  cursor: pointer;
  position: relative;
  background: transparent;
  border: 0;
}

.userbox:hover {
  background: var(--c-hover);
}

.usermeta {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  line-height: 1.25;
}

.usermeta .uname {
  color: var(--t-bright);
  font-size: var(--fs-sm);
}

.usermeta .urole {
  color: var(--t-dim);
  font-size: var(--fs-xs);
}

.avatar {
  width: 30px;
  height: 30px;
  border-radius: var(--r-sm);
  flex: 0 0 auto;
}

.usermenu {
  position: absolute;
  right: 0;
  top: 46px;
  min-width: 190px;
  background: var(--c-card);
  border: 1px solid var(--c-line);
  border-radius: var(--r-md);
  padding: 6px;
  box-shadow: 0 8px 22px rgba(0, 0, 0, 0.45);
  display: none;
  z-index: 50;
}

.usermenu.is-open {
  display: block;
}

.usermenu button {
  display: block;
  width: 100%;
  text-align: left;
  padding: 9px 10px;
  background: transparent;
  border: 0;
  color: var(--t-primary);
  font-size: var(--fs-md);
  border-radius: var(--r-sm);
  cursor: pointer;
}

.usermenu button:hover {
  background: var(--c-hover);
  color: var(--t-bright);
}

.usermenu .sep {
  height: 1px;
  background: var(--c-line);
  margin: 5px 0;
}

.usermenu .who {
  padding: 8px 10px 4px;
  font-size: var(--fs-xs);
  color: var(--t-dim);
}

/* ---------- 二级上下文条 ---------- */
.subbar {
  background: var(--c-bg);
  border-bottom: 1px solid var(--c-line-soft);
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
}

.subbar-inner {
  max-width: var(--wrap);
  margin: 0 auto;
  padding: 0 16px;
  min-height: 42px;
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

.crumb {
  font-size: var(--fs-md);
  color: var(--t-primary);
}

.crumb .sep {
  color: var(--t-dim);
  margin: 0 6px;
}

.crumb a {
  color: var(--c-accent);
}

.subhint {
  font-size: var(--fs-sm);
  color: var(--t-dim);
  margin-left: auto;
}

/* ---------- 主视图 ---------- */
.view {
  min-height: calc(100vh - 130px);
  padding: 18px 0 40px;
}

.row {
  display: flex;
  gap: var(--gap);
  align-items: flex-start;
}

.side {
  flex: 0 0 196px;
  width: 196px;
}

.main {
  flex: 1 1 auto;
  min-width: 0;
}

/* ---------- 卡片网格 ---------- */
.grid {
  display: grid;
  gap: 14px;
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

@media (max-width: 1199px) {
  .grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 899px) {
  .row { flex-direction: column; }
  .side { width: 100%; flex: 0 0 auto; }
  .grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 767px) {
  .hamburger { display: flex; }

  .mainnav {
    display: none;
    position: absolute;
    left: 0;
    right: 0;
    top: 100%;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    background: var(--c-deep);
    padding: 6px;
    border-bottom: 1px solid var(--c-line);
    z-index: 45;
  }

  .mainnav.is-open { display: flex; }

  .navlink {
    height: var(--tap);
    border-radius: var(--r-sm);
  }

  .searchbox input { width: 130px; }

  .usermeta { display: none; }

  .grid { grid-template-columns: minmax(0, 1fr); }
  .view { padding-top: 14px; }
}

@media (max-width: 420px) {
  .searchbox input { width: 96px; }
  /* ★ 2026-10-19：只收字标，别把标记（.brand-mark-hit 也是 span）一起收掉 ——
     旧规则 `.brand span{display:none}` 会让 SPRINT 的 S 圆圈整块消失。 */
  .brand #brand-name { display: none; }
}

/* ============================================================================
   四系统顶栏（2026-10-18 拆分令；10-19 两轮定稿）
   ----------------------------------------------------------------------------
   老师口径（10-19 第三轮，逐字）：
     「把各个系统里的最顶部，都留给四个接口，外观 / 键盘 / Andrea / 教师 /
       羽扇军师 这些信息都移到下一层，和 商店 库 班级 我的 成就商店 任务 后台
       一排。现在的 logo 和字体都超级难看，重新设计。」
     （更早一轮：「……激活的系统在左边。未激活的靠右。激活了就和左边对换。
       子菜单放下一层。」）

   ⇒ 结构（index.html）：
     第一行 .topbar-inner = **只有** [#sys-active 激活槽] [#sys-queue 候选槽(靠右)]
                            [#sys-pinned 我的词库(固定最右)]
     第二行 .topbar-navrow = [汉堡(窄屏)] [mainnav 商店/库/…] ……… [外观][键盘][用户框]
     第三行 .subbar = 面包屑（仅 SPRINT）
   ★ 换位 = sysbar.js 的 apply() 把激活节点 appendChild 进左槽、其余进右槽；
     vocabulary（第四个系统）**不参与换位**，永远固定在候选槽右侧。
   ★ 第一行**不放任何工具**：老师这次点名"最顶部留给四个接口"。
   ● 标志/字标的新皮见下面「四个系统入口的新皮」。
   ============================================================================ */

/* 激活槽（左）与候选槽（右）
   ★ 左槽里常驻 #ielts-mode-badge（模式徽标）—— 激活徽章永远在它前面
   （sysbar.js 用 insertBefore 保证），老师 10-19：「模式应当出现在 LOGO 后面」。 */
.sys-active {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 0 0 auto;
}

.sys-queue {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: 0 0 auto;
  margin-left: auto;      /* ★ 整体推到最右 —— 老师的"未激活的靠右" */
  padding-left: 10px;
}

/* ★★★ 2026-10-19（老师）：「把我的词库……直接做到 SPRINT、雅思、ESL 后面的
   **第四个系统**，而且长期固定在最右边。也是 logo 加文字，用字母 i 来模仿
   SPRINT 里的 S-logo，vocabulary 作为文字。」
   ⇒ 第四系统（我的词库 vocabulary）**不参与换位**：常驻在候选槽右侧，
     永远是三个老系统右边的那一个。 */
.sys-pinned {
  display: flex;
  align-items: center;
  flex: 0 0 auto;
  padding-left: 10px;
}

/* ============================================================================
   四个系统入口的新皮（2026-10-19 第三轮：老师「logo 和字体超级难看，重新设计」）
   ---------------------------------------------------------------------------
   设计口径：
     · 统一成「标记 + 字标」的标签，**不再用白底小药丸**（白色小框把四个 logo
       挤成四块药丸，字又小又散，正是"难看"的来源）；
     · 标记统一 26px、字标统一 13px/800、间距 9px；字标大写 + 加宽字距，
       vocabulary 保持小写（它本来就是小写词）；
     · 每个系统一个主色：SPRINT 天蓝 / IELTS 红 / ESL 剑桥蓝 / 词库墨绿；
       未激活压暗、激活时字标点亮 + 淡底（位置本身仍是强信号）。
   ============================================================================ */

#brand-sprint, .sys-tab {
  display: flex;
  align-items: center;
  gap: 9px;
  height: 42px;
  padding: 0 10px;
  border: 0;
  border-radius: 12px;
  background: transparent;
  color: inherit;
  font: inherit;
  cursor: pointer;
  white-space: nowrap;
  -webkit-appearance: none;
  appearance: none;
  transition: background .15s ease, opacity .15s ease;
}

#brand-sprint { --sys-accent: #7cc4f5; --sys-tint: rgba(124, 196, 245, .16); }
#tab-ielts   { --sys-accent: #e33a52; --sys-tint: rgba(227, 58, 82, .11); }
#tab-esl     { --sys-accent: #2f86d6; --sys-tint: rgba(47, 134, 214, .11); }
#tab-vocab   { --sys-accent: #2ab07c; --sys-tint: rgba(42, 176, 124, .11); }

/* 未激活压暗；悬停恢复 */
#sys-queue .sys-tab { opacity: .72; }
#sys-queue .sys-tab:hover,
#sys-queue .sys-tab:focus-visible { opacity: 1; }

#brand-sprint:hover, #brand-sprint:focus-visible,
.sys-tab:hover, .sys-tab:focus-visible {
  background: rgba(255, 255, 255, .07);
  outline: none;
}

/* 激活 = 该系统的**主色淡底**（天蓝/红/蓝/绿各一层，比统一灰底更清楚） */
#brand-wrap[aria-current="true"] #brand-sprint,
.sys-tab[aria-current="true"],
.vocab-tab.is-open {
  background: var(--sys-tint);
}

/* 字标（统一字体/字号/字距；原来混着 badge 自己的字号，才会大小不一） */
#brand-name, .sys-word {
  font-family: "Segoe UI", "Microsoft YaHei", system-ui, -apple-system, sans-serif;
  font-size: 13px;
  font-weight: 800;
  letter-spacing: .10em;
  line-height: 1;
  text-transform: uppercase;
  color: #edf4fb;
}

.vocab-word {
  text-transform: none;
  letter-spacing: .02em;
  font-size: 13.5px;
  font-weight: 700;
}

#brand-wrap[aria-current="true"] #brand-name,
.sys-tab[aria-current="true"] .sys-word { color: var(--sys-accent); }

/* 标记统一尺寸（S 的圆圈、盾徽、加乘图标、i 圆圈同高） */
.brand-mark-hit { width: 30px; height: 30px; }
.brand-mark { width: 30px; height: 30px; color: var(--sys-accent); }
.brand-arc, .brand-liquid { width: 30px; height: 30px; }

.sys-badge {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  border-radius: 12px;
  overflow: hidden;
}

.sys-badge img {
  width: 26px;
  height: 26px;
  object-fit: contain;
  display: block;
  flex: 0 0 auto;
}

.ielts-badge { gap: 8px; }
.ielts-badge img { width: 22px; height: 27px; }
.esl-badge { gap: 8px; }

/* ESL 的三色书脊小标记（蓝/黄/橙，与 ESL 书架三色书脊同源）。
   26×26 里三条圆角横条 —— 原来那张 114×96 的"加乘 + ×"图标缩到 26px 糊成一团。 */
.esl-mark {
  width: 26px;
  height: 26px;
  flex: 0 0 auto;
  display: inline-flex;
  flex-direction: column;
  justify-content: center;
  gap: 2.5px;
  padding: 2px 1px;
  box-sizing: border-box;
}

.esl-mark i {
  display: block;
  height: 5.5px;
  border-radius: 1.5px;
  background: #00539b;
}

.esl-mark i:nth-child(2) { background: #ffc72c; }
.esl-mark i:nth-child(3) { background: #e35205; }

.vocab-mark {
  width: 26px;
  height: 26px;
  flex: 0 0 auto;
  display: block;
  color: var(--sys-accent);
}

.vocab-badge { gap: 9px; }

/* 注水层（彩蛋保留）：透明标签里的淡淡一层 + 顶部水花 */
.bw-body {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 0%;
  pointer-events: none;
}

.ielts-badge .bw-body {
  background: rgba(227, 58, 82, .22);
  box-shadow: inset 0 2.5px 0 rgba(227, 58, 82, .8);
}
.esl-badge .bw-body {
  background: rgba(47, 134, 214, .20);
  box-shadow: inset 0 2.5px 0 rgba(47, 134, 214, .8);
}
.vocab-badge .bw-body {
  background: rgba(42, 176, 124, .18);
  box-shadow: inset 0 2.5px 0 rgba(42, 176, 124, .7);
}

.bw-splash {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 10px;
  pointer-events: none;
  opacity: 0;
  transition: opacity .12s linear;
}

.bw-splash i {
  position: absolute;
  top: 0;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  animation: bw-jump .38s ease-in-out infinite alternate;
}

.bw-splash i:nth-child(1) { left: 16%; animation-delay: 0s; }
.bw-splash i:nth-child(2) { left: 40%; width: 4px; height: 4px; animation-delay: .1s; }
.bw-splash i:nth-child(3) { left: 62%; width: 6px; height: 6px; animation-delay: .18s; }
.bw-splash i:nth-child(4) { left: 83%; width: 4px; height: 4px; animation-delay: .26s; }

.ielts-badge .bw-splash i { background: rgba(227, 58, 82, .8); }
.esl-badge .bw-splash i { background: rgba(47, 134, 214, .8); }

@keyframes bw-jump {
  from { transform: translateY(0); }
  to   { transform: translateY(-5px); }
}

/* 白顶栏世界（is-exam / is-esl）：字标转深色；激活仍是各系统的主色淡底
   （上面 `var(--sys-tint)` 那条在浅色底上同样成立，不用换一种颜色） */
body.is-exam #brand-name,
body.is-esl #brand-name,
body.is-exam .sys-word,
body.is-esl .sys-word { color: #1b2838; }

body.is-exam #brand-sprint:hover, body.is-exam #brand-sprint:focus-visible,
body.is-esl #brand-sprint:hover, body.is-esl #brand-sprint:focus-visible,
body.is-exam .sys-tab:hover, body.is-exam .sys-tab:focus-visible,
body.is-esl .sys-tab:hover, body.is-esl .sys-tab:focus-visible {
  background: rgba(15, 23, 32, .05);
}

body.is-exam #brand-wrap[aria-current="true"] #brand-name,
body.is-esl #brand-wrap[aria-current="true"] #brand-name,
body.is-exam .sys-tab[aria-current="true"] .sys-word,
body.is-esl .sys-tab[aria-current="true"] .sys-word { color: var(--sys-accent); }

/* 窄屏：先收字标、只留标记（与旧版"文字收起"同一套处理） */
@media (max-width: 560px) {
  .ielts-badge .sys-word, .esl-badge .sys-word { display: none; }
}
@media (max-width: 420px) {
  .vocab-word { display: none; }
}

/* ★★ 我的词库弹窗（第四系统）：从任何页面点 i-vocabulary 都在**这一层**打开，
   不跳路由 ⇒ 关掉就回到原来那一屏（ESL 做题页不丢）。 */
.vocab-mask {
  position: fixed;
  inset: 0;
  z-index: 2147483000;            /* 高于顶栏/浮层，低于系统级遮罩（词库菜单不用跟它抢） */
  display: none;
  align-items: center;
  justify-content: center;
  padding: 22px;
  background: rgba(8, 14, 26, .52);
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
}

.vocab-mask.is-open { display: flex; }

.vocab-win {
  width: min(1180px, 96vw);
  height: min(90vh, 940px);
  display: flex;
  flex-direction: column;
  background: #fff;
  border-radius: 16px;
  overflow: hidden;
  box-shadow: 0 30px 80px rgba(0, 0, 0, .38);
}

.vocab-head {
  display: flex;
  align-items: center;
  gap: 9px;
  flex: 0 0 auto;
  padding: 9px 12px;
  background: linear-gradient(180deg, #f7f9fc, #eef2f8);
  border-bottom: 1px solid #e6ebf3;
}

.vocab-head .vmk {
  width: 27px;
  height: 27px;
  border-radius: 50%;
  border: 1.7px solid #0e7a53;
  color: #0e7a53;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
}

.vocab-head .vmk svg { width: 20px; height: 20px; display: block; }

.vocab-head b { font-size: 15px; color: #16202c; }
.vocab-head .ven { font-size: 11px; font-weight: 700; letter-spacing: .09em; color: #8a93a0; }
.vocab-head .vsub { font-size: 12px; color: #8b95a3; margin-left: 4px; }
.vocab-head .vopen { margin-left: auto; font-size: 12px; color: #2f6fed; text-decoration: none; }
.vocab-head .vopen:hover { text-decoration: underline; }

.vocab-head .vclose {
  margin-left: 10px;
  width: 34px;
  height: 34px;
  flex: 0 0 auto;
  border: 1px solid #d7dbe2;
  border-radius: 9px;
  background: #fff;
  color: #333b48;
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
}

.vocab-head .vclose:hover { border-color: #0e7a53; color: #0e7a53; background: #f1faf6; }

.vocab-frame {
  flex: 1 1 auto;
  width: 100%;
  min-height: 0;
  border: 0;
  background: #f6f8fb;
  display: block;
}

/* 弹窗开着时锁住背后的滚动 */
html.vocab-open, html.vocab-open body { overflow: hidden; }

@media (max-width: 700px) {
  .vocab-mask { padding: 0; }
  .vocab-win { width: 100vw; height: 100vh; border-radius: 0; }
  .vocab-head .vsub { display: none; }
}

/* ★ 弹窗版的词库页：外壳（顶栏 / 二级条 / 页脚）不画，只留内容。 */
html.is-embed-vocab .topbar,
html.is-embed-vocab .subbar,
html.is-embed-vocab .foot { display: none !important; }

html.is-embed-vocab .wrap { padding-top: 12px; }

/* 第二行：子菜单 + 工具（老师 10-19 第三轮：「外观 键盘 Andrea 教师 羽扇军师
   这些信息都移到下一层，和 商店 库 班级 我的 成就商店 任务 后台 一排」）
   ⇒ [汉堡] [主导航] ……… [外观] [键盘] [用户框]
   ★ 雅思 / ESL 世界没有主导航，但这一行**仍然在**（右侧工具+用户保留）。 */
.topbar-navrow {
  max-width: var(--wrap);
  margin: 0 auto;
  padding: 0 16px;
  display: flex;
  align-items: center;
  gap: 6px;
  min-height: 44px;
  position: relative;       /* 窄屏时 .mainnav 绝对定位的锚点 */
}

.navrow-right {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 6px;
}

/* ---- ESL 世界的整体色调：浅天蓝 #C5E2FF（老师 2026-10-18 拍的板） ---- */
body.is-esl .topbar {
  background: #ffffff;
  border-bottom: 1px solid #d5e5f7;
}

/* ★ 2026-10-19（老师第三轮）：「外观 键盘 Andrea 教师 羽扇军师 这些信息都移到
   下一层，和 商店 库 班级 我的 成就商店 任务 后台 一排。」
   ⇒ 雅思 / ESL 世界里**第二行不再整行收掉**：只藏主导航（那排是 SPRINT 的
     商店/库/…），右侧工具与用户框保留 —— 每个系统都要看得到。
   ★ 顶栏因此是两个 44px 行：--topbar-h 从 56 改成 100（模考整屏高度要扣两行）。 */
body.is-esl .mainnav,
body.is-esl .searchbox,
body.is-esl .subbar,
body.is-esl .foot,
body.is-esl #notice-slot { display: none; }

body.is-exam, body.is-esl { --topbar-h: 101px; }

/* 白顶栏世界里的工具按钮 / 用户名（原来只在 SPRINT 深色顶栏用过浅色配色） */
body.is-exam .sp-look,
body.is-esl .sp-look { background: #ffffff; border-color: #d7dbe2; color: #3f4854; }
body.is-exam .sp-look:hover,
body.is-esl .sp-look:hover,
body.is-exam .sp-look.is-on,
body.is-esl .sp-look.is-on { border-color: #0e7a53; color: #0e7a53; background: #f1faf6; }
body.is-exam .userbox .uname,
body.is-esl .userbox .uname { color: #16202c; }
body.is-exam .userbox .urole,
body.is-esl .userbox .urole { color: #7a8492; }
body.is-exam .userbox:hover,
body.is-esl .userbox:hover { background: #f1f4f8; }
body.is-exam .hamburger,
body.is-esl .hamburger { color: #1b2838; }

body.is-esl { background: #c5e2ff; }

/* ★ ESL 世界用自己的纯色底色，SPRINT 的背景层（.sp-bg，z-index:-1 的
   纯色兜底 #0e1621）会盖在 body 底色**上面**（body 的底色是"画布"，
   永远在最底）⇒ 必须把那层收掉，浅天蓝才露得出来。
   （雅思世界没有这条：它的内容是白底大容器/整屏 iframe，自带不透明底，
   把背景层盖住了 —— 所以它不需要。） */
body.is-esl .sp-bg { display: none; }

body.is-esl main.wrap {
  max-width: none;
}

body.is-esl .view {
  padding-top: 10px;
}

/* ---- ESL 页面件（views/esl.js） ---- */
.esl-page {
  max-width: 1080px;
  margin: 0 auto;
  padding: 6px 18px 48px;
}

.esl-head {
  display: flex;
  align-items: baseline;
  gap: 14px;
  flex-wrap: wrap;
  margin: 10px 0 18px;
}

.esl-back {
  flex: 0 0 auto;
}

.esl-title {
  margin: 0;
  font-size: 24px;
  color: #12314f;
}

.esl-sub {
  margin: 0;
  color: #3c5876;
}

/* 单词搜索框（接口 Phase 2.5 接通前禁用，如实标注 —— 不摆假框） */
.esl-search {
  display: flex;
  align-items: center;
  gap: 8px;
  background: #ffffff;
  border: 1.5px solid #a8c8ea;
  border-radius: 12px;
  padding: 8px 12px;
  margin-bottom: 22px;
  box-shadow: 0 2px 8px rgba(16, 52, 96, 0.08);
}

.esl-search input {
  flex: 1 1 auto;
  border: 0;
  outline: 0;
  font: inherit;
  color: #12314f;
  background: transparent;
  min-width: 0;
}

.esl-search-go {
  flex: 0 0 auto;
}

.esl-search-note {
  flex: 0 0 auto;
  font-size: 12px;
  color: #7d93ab;
}

/* 封面网格：主页是系列卡，教材页是册卡 —— 同一套尺寸语言 */
.esl-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 18px;
}

.esl-card {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 0;
  padding: 0;
  border: 0;
  border-radius: 12px;
  overflow: hidden;
  background: #ffffff;
  cursor: pointer;
  box-shadow: 0 3px 12px rgba(16, 52, 96, 0.14);
  transition: transform .12s ease, box-shadow .12s ease;
  font: inherit;
  text-align: left;
  -webkit-appearance: none;
  appearance: none;
}

.esl-card:hover,
.esl-card:focus-visible {
  transform: translateY(-2px);
  box-shadow: 0 6px 18px rgba(16, 52, 96, 0.2);
}

.esl-card:focus-visible {
  outline: 2px solid #00539b;
  outline-offset: 2px;
}

.esl-card.is-pending {
  opacity: 0.75;
}

.esl-card-cov {
  display: block;
  aspect-ratio: 4 / 5;
  background: #eef4fb;
}

.esl-card-cov img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.esl-card-cap {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 9px 11px 11px;
}

.esl-card-cap b {
  font-size: 14px;
  color: #12314f;
  line-height: 1.3;
}

.esl-card-cap i {
  font-style: normal;
  font-size: 12px;
  color: #67809b;
}

.esl-card-note {
  position: absolute;
  top: 8px;
  right: 8px;
  background: #ffc72c;
  color: #1b1b1b;
  font-size: 11.5px;
  font-weight: 700;
  padding: 3px 9px;
  border-radius: 999px;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
}

.esl-foot {
  margin-top: 30px;
  text-align: center;
  color: #56759a;
  font-size: 13px;
}

/* ============================================================================
   雅思模考世界（老师 2026-10-05）
   ----------------------------------------------------------------------------
   老师原话：「点击 SPRINT 的 logo 的时候，切换到雅思模考系统，同时整体色调
   换成白色，仪式感象征着进入了雅思系统。再点一次雅思的 Logo，就又切换回
   SPRINT 的系统。」

   ⇒ 整页换成白色调 —— 这就是"换世界"的全部视觉。
   ★ `is-exam` 这个类由 `ELP.app.chrome('exam')` 打在 <body> 上，
     所以**离开雅思那一页时它会自动摘掉**（每个视图都自己调 chrome()）。
   ★ 2026-10-18：三系统标签常驻后，原来的
     `body.is-exam #brand-sprint{display:none}` / `.brand-ielts` 系列规则
     已删除 —— 顶栏在任何世界都显示三个标签（排队条，见上）。
   ============================================================================ */

/* ★ 模式徽标只该出现在雅思世界（2026-10-06 老师报的
   「切换按钮出现在 SPRINT 主页挤占导航」的修法）：默认 display:none，
   只在 body.is-exam 里显示；`:empty{display:none}`（文末）再保证
   进雅思还没选模式时零占位。 */
.mode-badge-host { display: none; }
body.is-exam .mode-badge-host { display: inline-flex; align-items: center; }

/* ---- 雅思世界的整体色调：白 ---- */
body.is-exam .topbar {
  background: #ffffff;
  border-bottom: 1px solid #e3e6ea;
}

/* 雅思世界只藏 SPRINT 的导航 / 搜索 / 面包屑 / 页脚；
   ★ 2026-10-19 第三轮：第二行的工具与用户框**保留**（老师要求每个系统都有）。 */
body.is-exam .mainnav,
body.is-exam .searchbox,
body.is-exam .subbar,
body.is-exam .foot,
body.is-exam #notice-slot { display: none; }

body.is-exam { background: #ffffff; }

/* 模考那一屏：填满顶栏以下的所有空间。
   ★ 用 `--topbar-h` 而不是 `calc(100% - ...)`：顶栏高度是 `--tap` 派生的，
     写死一个 px 会在不同触控目标尺寸下错位。
   ★★ 2026-10-05 第二轮：教师会多一条「答案录入」窄栏，所以这里改成
      **纵向 flex**（`.view` 撑满 → 窄栏 + 模考区自动分高度），
      而不是给模考区写死 `calc(100vh - 顶栏)` —— 那样多一条栏就会顶出屏幕。 */
body.is-exam .view {
  padding: 0;
  max-width: none;
  height: calc(100vh - var(--topbar-h, 56px));
  display: flex;
  flex-direction: column;
  min-height: 0;
}

/* ★★★ 2026-10-18（老师）：「有些练习没按照雅思的强制全屏，左右留有空格。」
   ⇒ `.view` 自己虽然放开了宽度，但它外层装内容的是 `<main class="wrap">`，
     而 `.wrap` 有 `max-width: var(--wrap)`（1200px）+ 居中 —— 于是在宽屏上
     雅思世界（模考 iframe / 学习模式 iframe）左右各留一大块黑边。
     雅思世界按"强制全屏"处理：把这一层容器也放开。
     ★ 只对 `body.is-exam` 生效（`ELP.app.chrome('exam')` 打的类），
       商店/库/其它页面一个字都不改。 */
body.is-exam main.wrap {
  max-width: none;
  padding-left: 0;
  padding-right: 0;
}

.ielts-wrap {
  flex: 1 1 auto;
  display: flex;
  min-height: 0;
}

/* 雅思世界里给教师的那条窄栏（答案录入入口）。
   ★ 只在教师身份下由 ielts.js 生成，学生看不到。
   ★ 它不写高度 —— `flex: 0 0 auto` 按内容撑，剩下的全给下面的模考区。 */
.ielts-teacherbar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 16px;
  background: #fff;
  border-bottom: 1px solid #e3e6ea;
  flex: 0 0 auto;
}

.ielts-teacherbar .btn {
  padding: 4px 12px;
  text-decoration: none;
}

.ielts-frame {
  flex: 1 1 auto;
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
  background: #ffffff;
}

/* 窄屏：模考自己已有 <820px 的单栏降级（见它的说明），
   这里只要保证容器不抢高度、不加内边距。 */
@media (max-width: 820px) {
  .ielts-wrap { height: calc(100vh - var(--topbar-h, 52px)); }
}

/* ★★★ 2026-10-05：雅思**模式徽标**（老师：「以 logo 的形式一直出现在
   IELTS 的 logo 旁边」）
   · 两种模式用颜色区分：模拟考试=红（严肃、不可逆）、自由练习=绿（宽松）
   · 它是**按钮**（点一下能改模式），所以样式按按钮做，别做成纯标记

   ★★★ 2026-10-06：**页面级显示控制放在上面 `body.is-exam` 那一段**
   （原来这里只写了 `:empty`，导致徽标跑进 SPRINT 主页 —— 见那一段的注释）。
   这里只留"内容为空时零占位"这一条。 */
.mode-badge-host:empty{display:none}
.mode-badge{font:inherit;font-size:12px;font-weight:700;letter-spacing:.04em;
  line-height:1;cursor:pointer;padding:6px 10px;border-radius:999px;
  border:1px solid transparent;margin-left:8px;white-space:nowrap;
  -webkit-appearance:none;appearance:none}
.mode-badge.is-exam{background:#fde8e8;color:#a41f1f;border-color:#f3bcbc}
.mode-badge.is-exam:hover{border-color:#a41f1f}
.mode-badge.is-practice{background:#e7f6ec;color:#1c6b3a;border-color:#b7e0c5}
.mode-badge.is-practice:hover{border-color:#1c6b3a}

/* 模式选择窗：全屏遮罩 + 居中卡片。
   ★ 遮罩用 position:fixed + 深色半透明：**必须盖住一切** ——
     这是首要选择，不能让学生绕过它就去答题。 */
.mode-mask{position:fixed;inset:0;z-index:9999;background:rgba(12,15,20,.55);
  display:flex;align-items:center;justify-content:center;padding:20px}
.mode-box{background:#fff;border-radius:14px;padding:22px 24px;max-width:560px;
  width:100%;box-shadow:0 18px 50px rgba(0,0,0,.28)}
.mode-box h3{margin:0 0 6px;font-size:20px}
.mode-box .sub{margin:0 0 16px;color:#5b6472;font-size:13px;line-height:1.6}
.mode-row{display:block;width:100%;text-align:left;font:inherit;cursor:pointer;
  padding:14px 16px;margin:0 0 10px;border-radius:11px;
  border:1.5px solid #d7dbe2;background:#fff}
.mode-row:hover{border-color:#2f6fed;background:#f6f9ff}
.mode-row.on{border-color:#2f6fed;background:#eef4ff}
.mode-row b{display:block;font-size:16px;margin-bottom:4px}
.mode-row span{display:block;font-size:13px;color:#5b6472;line-height:1.55}
.mode-box .acts{display:flex;justify-content:flex-end;gap:8px;margin-top:6px}
.mode-box .acts button{font:inherit;font-size:14px;cursor:pointer;padding:8px 16px;
  border-radius:8px;border:1px solid #d7dbe2;background:#eef1f5;color:#333b48}

/* ---- ESL 2026-10-19：教材简介 / 单元列表 / 原版教材迁移 ---- */
.esl-sec-title{margin:28px 0 8px;font-size:18px;color:#12314f}
.esl-sec-sub{margin:0 0 14px;font-size:13px;color:#5a7694}
a.esl-card{text-decoration:none;color:inherit}
.esl-card-pub{font-size:12px;color:#45617d;line-height:1.35}
.esl-card-intro{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;font-size:12px;color:#64809c;line-height:1.4;margin-top:2px}
.esl-grid-textbooks{grid-template-columns:repeat(auto-fill,minmax(118px,1fr));gap:12px}
.esl-grid-textbooks .esl-card-cap{padding:7px 8px 9px}
.esl-grid-textbooks .esl-card-cap b{font-size:12.5px}
.esl-grid-textbooks .esl-card-pub{font-size:11px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
/* EI 白板互动（ActiveTeach 组合版）入口卡 */
.esl-atlas{margin:0 0 16px}
.esl-atlas-card{display:flex;align-items:center;gap:14px;padding:14px 16px;border-radius:14px;background:#fff;
  border:1px solid #bcd9f7;box-shadow:0 4px 16px rgba(16,52,96,.14);text-decoration:none;color:inherit;
  transition:transform .12s ease,box-shadow .12s ease}
.esl-atlas-card:hover,.esl-atlas-card:focus-visible{transform:translateY(-2px);box-shadow:0 8px 22px rgba(16,52,96,.22)}
.esl-atlas-k{flex:0 0 auto;background:#00539b;color:#fff;border-radius:8px;padding:6px 10px;font-size:12.5px;font-weight:700}
.esl-atlas-body{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;gap:3px}
.esl-atlas-body b{font-size:15px;color:#12314f}
.esl-atlas-body i{font-style:normal;font-size:12.5px;color:#67809b}
.esl-atlas-go{flex:0 0 auto;font-size:13px;color:#00539b;font-weight:700}
.esl-unit-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:12px}
.esl-unit{display:flex;align-items:center;gap:12px;padding:12px 14px;border-radius:12px;background:#fff;box-shadow:0 3px 12px rgba(16,52,96,.12);text-decoration:none;color:inherit;transition:transform .12s ease,box-shadow .12s ease}
.esl-unit:hover,.esl-unit:focus-visible{transform:translateY(-2px);box-shadow:0 6px 18px rgba(16,52,96,.2)}
.esl-unit-num{flex:0 0 auto;width:44px;height:44px;border-radius:10px;background:#e7f2ff;color:#00539b;font-weight:800;font-size:18px;display:flex;align-items:center;justify-content:center}
.esl-unit-body{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;gap:2px}
.esl-unit-body b{font-size:14px;color:#12314f;line-height:1.35}
.esl-unit-body i{font-style:normal;font-size:12px;color:#67809b}
.esl-unit-go{flex:0 0 auto;font-size:12.5px;color:#00539b;font-weight:700}
.esl-book-detail{display:flex;align-items:flex-start;gap:26px;flex-wrap:wrap}
.esl-book-cover{flex:0 0 auto;width:240px;max-width:60vw}
.esl-book-cover img{width:100%;display:block;border-radius:12px;box-shadow:0 8px 24px rgba(16,52,96,.2)}
.esl-book-info{flex:1 1 320px;min-width:0}
.esl-book-pub{margin:0 0 4px;font-size:14px;color:#12314f;font-weight:600}
.esl-book-cefr{margin:0 0 10px;font-size:12.5px;color:#67809b}
.esl-book-intro{margin:0 0 14px;font-size:14px;line-height:1.65;color:#2d4a66}
.esl-book-status{margin:0;padding:10px 12px;border-radius:10px;background:#fff6dc;color:#6b530f;font-size:13px}

/* ESL 底板：若用户开了动态背景（body.sp-bg-on），body 会透明露出深色背景；
   ESL 必须固定浅天蓝（老师 2026-10-18 定），否则深色文字看不清。 */
body.is-esl,
body.is-esl.sp-bg-on {
  background: #c5e2ff !important;
}
body.is-esl .sp-bg { display: none !important; }

/* Pathways 单册页：强制每排 5 本（RW 一排 + LS 一排），窄屏回落 2 列 */
.esl-title-lv {
  display: block;
  margin-top: 4px;
  font-size: .58em;
  font-weight: 600;
  opacity: .58;
  letter-spacing: .02em;
}

.esl-card-lv {
  display: block;
  margin-top: 2px;
  font-size: 12px;
  font-weight: 600;
  opacity: .62;
  letter-spacing: .02em;
}

.esl-grid-five {
  grid-template-columns: repeat(5, minmax(0, 1fr));
}
@media (max-width: 820px) {
  .esl-grid-five { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ESL 搜词结果 + 加入我的词库 */
.esl-wordres { margin: -8px 0 18px; }
.esl-wres-head {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  margin: 0 0 8px; color: #12314f; font-size: 13px;
}
.esl-wres-head b { font-size: 14px; }
.esl-wres-head span { color: #5f7b98; font-size: 12.5px; }
.esl-wres {
  display: flex; align-items: flex-start; gap: 14px;
  background: #fff; border-radius: 12px; padding: 12px 14px; margin: 0 0 8px;
  box-shadow: 0 2px 10px rgba(16, 52, 96, .1);
}
.esl-wres-main { flex: 1 1 auto; min-width: 0; }
.esl-wres-word { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.esl-wres-word b { font-size: 17px; color: #12314f; }
.esl-wres-ph { color: #67809b; font-size: 13px; }
.esl-wres-pos {
  color: #00539b; background: #e7f2ff; border-radius: 6px;
  padding: 1px 6px; font-size: 11.5px;
}
.esl-wres-cn { margin-top: 3px; font-size: 14px; color: #1f3b5a; }
.esl-wres-en { margin-top: 2px; font-size: 12.5px; color: #4a657f; }
.esl-wres-ex {
  margin-top: 5px; font-size: 12.5px; color: #5b7188;
  border-left: 3px solid #d7e7f7; padding-left: 8px; line-height: 1.5;
}
.esl-wres-add { flex: 0 0 auto; align-self: center; white-space: nowrap; }
.esl-wres-add.is-in {
  background: #eef6ec; color: #2e6b3e; opacity: 1; cursor: default;
}
.esl-wres-empty {
  background: rgba(255, 255, 255, .78); border-radius: 10px;
  padding: 12px 14px; color: #4a657f; font-size: 13px;
}

/* ESL 自定义右键/长按菜单 + 查词面板 */
body.is-esl { -webkit-touch-callout: none; }
.esl-ctxmenu {
  position: fixed; z-index: 100000; min-width: 190px;
  background: #fff; border: 1px solid #d7dbe2; border-radius: 10px;
  box-shadow: 0 14px 36px rgba(0, 0, 0, .28); padding: 5px;
  font: 14px/1.4 system-ui, "Microsoft YaHei", sans-serif; color: #1f2d3d;
}
.esl-ctx-head {
  padding: 7px 10px 6px; font-size: 12.5px; color: #67809b;
  border-bottom: 1px solid #eef1f5; margin-bottom: 4px; max-width: 260px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.esl-ctx-item {
  display: block; width: 100%; text-align: left; border: 0; background: transparent;
  font: inherit; color: inherit; padding: 8px 10px; border-radius: 7px; cursor: pointer;
}
.esl-ctx-item:hover { background: #eef4ff; }
.esl-ctx-item:disabled { color: #9aa9b8; cursor: default; background: transparent; }
.esl-ctx-sep { height: 1px; background: #eef1f5; margin: 4px 2px; }
.esl-wordpanel {
  position: fixed; z-index: 100001; width: 320px; max-width: 86vw;
  background: #fff; border: 1px solid #d7dbe2; border-radius: 12px;
  box-shadow: 0 16px 44px rgba(0, 0, 0, .28); padding: 12px 14px;
  font: 14px/1.55 system-ui, "Microsoft YaHei", sans-serif; color: #1f2d3d;
}
.esl-wp-head { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; margin-bottom: 6px; }
.esl-wp-head b { font-size: 17px; }
.esl-wp-head span { color: #67809b; font-size: 13px; }
.esl-wp-head i {
  font-style: normal; color: #00539b; background: #e7f2ff;
  border-radius: 6px; padding: 1px 6px; font-size: 12px;
}
.esl-wp-cn { font-size: 14px; }
.esl-wp-en { color: #4a657f; font-size: 12.5px; margin-top: 2px; }
.esl-wp-ex {
  color: #5b7188; font-size: 12.5px; margin-top: 5px;
  border-left: 3px solid #d7e7f7; padding-left: 8px; line-height: 1.5;
}
.esl-wp-empty { color: #6b7785; font-size: 13px; }
.esl-wp-acts { display: flex; gap: 8px; justify-content: flex-end; margin-top: 10px; }
/* 词形推断命中：difficulties = difficulty（复数）—— 2026-10-19 */
.esl-wp-lemma {
  font-size: 12.5px; color: #0e5a3c; background: #eefaf4;
  border: 1px solid #cfeade; border-radius: 7px;
  padding: 5px 8px; margin: 0 0 7px;
}
.esl-wp-alt { font-size: 12px; color: #7a8695; margin: 3px 0 6px; }

/* ESL 单元入口：用单元封面替代纯文字行（2026-10-19） */
.esl-unit-grid {
  grid-template-columns: repeat(auto-fill, minmax(176px, 1fr));
  gap: 14px;
}
.esl-unit {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 0;
  padding: 0;
  overflow: hidden;
  background: #fff;
}
.esl-unit-cover {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 4 / 5;
  background: #dceafa;
  overflow: hidden;
}
.esl-unit-cover img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.esl-unit-cover.is-fallback img { filter: saturate(.82); opacity: .92; }
.esl-unit-cover.is-empty { background: linear-gradient(145deg, #dbeaf9, #eef6ff); }
.esl-unit-badge {
  position: absolute;
  left: 8px;
  top: 8px;
  padding: 3px 8px;
  border-radius: 6px;
  background: rgba(10, 27, 45, .76);
  color: #fff;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .2px;
}
.esl-unit-body {
  flex: 0 0 auto;
  padding: 8px 10px 0;
  gap: 2px;
}
.esl-unit-body b {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  font-size: 13px;
  line-height: 1.35;
}
.esl-unit-body i { font-size: 11.5px; }
.esl-unit-go {
  padding: 3px 10px 10px;
  font-size: 12.5px;
}
@media (max-width: 620px) {
  .esl-unit-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.esl-unit-kicker {
  display: block;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .4px;
  color: #00539b;
  text-transform: uppercase;
  margin: 0 0 2px;
}
.esl-unit-badge { display: none; }

/* Unlock 第二版：读写一排、听说一排（每排 6 本） */
.esl-grid-six{grid-template-columns:repeat(6,minmax(0,1fr));gap:14px}
@media (max-width:1200px){.esl-grid-six{grid-template-columns:repeat(3,minmax(0,1fr))}}
@media (max-width:760px){.esl-grid-six{grid-template-columns:repeat(2,minmax(0,1fr))}}
/* Grammar in Context 图文版：一排 4 本 */
.esl-grid-four{grid-template-columns:repeat(4,minmax(0,1fr));gap:16px}
@media (max-width:1000px){.esl-grid-four{grid-template-columns:repeat(2,minmax(0,1fr))}}

/* Prepare 图文版：7 列（SB 一行 / WB 一行 / TB 一行） */
.esl-grid-seven{grid-template-columns:repeat(7,minmax(0,1fr));gap:12px}
@media (max-width:1500px){.esl-grid-seven{grid-template-columns:repeat(4,minmax(0,1fr))}}
@media (max-width:900px){.esl-grid-seven{grid-template-columns:repeat(2,minmax(0,1fr))}}
