/* 铅笔板书视觉系统。全站的色、线宽、字体只在这里定义一次，
   改一处全站生效。抖动幅度不在这里——它在 sketch.js 的滤镜参数里，
   因为 feDisplacementMap 的 scale 只能写在 SVG 属性上。 */
@font-face {
  font-family: 'Caveat';
  src: url('fonts/caveat-latin.woff2') format('woff2');
  font-weight: 400 700;
  font-display: swap;
}

/* 手绘框的角半径规范定义在 sketch.js 的 BOX_RADII：
   TL {h:255,v:15} TR {h:15,v:225} BR {h:225,v:15} BL {h:15,v:255}，
   规律是「TL/BR 的横半径大、TR/BL 的竖半径大」，两条对角线错开才有错落感。
   CSS 没法 import JS 常量，所以下面所有 border-radius 都手抄了同一组数值；
   改一边必须同步另一边。.lab-phoneme:nth-child(even) 是它的镜像
   （横竖对调，相当于 sketch.js 里 sketch.boxRadii 的 flip 参数）。 */

:root {
  /* 纸与墨 */
  --paper:      #faf8f3;
  /* 卡片那张纸：比页面底纸略亮一点，加上描边与错开的横竖半径，
     看起来像贴在页面上的一张小卡，而不是又一个带边框的区块 */
  --paper-card: #fffdf7;
  --ink:        #33302b;
  --ink-soft:   #9a948a;
  --ink-faint:  #b8b2a6;
  /* 动作·进行 */
  --action:     #5f7f52;
  /* 依据·答案 */
  --accent:     #8a5a34;
  --marker:     rgba(138, 90, 52, .2);
  /* 提醒·口诀。全站只给「这样记，更清楚」那一块用，红才有分量 ——
     见 .lab-concept-remark 那条注释。6.2:1，压得住 13px 的小字。 */
  --alert:      #b3261e;
  /* 判完分的底色：整块染成浅绿/浅红，而不是只换一行字的颜色。
     用实色而不是半透明 —— 原来那 8% 的 rgba 叠在纸上几乎看不出来，
     答对了和没答过长得一样。 */
  --tint-right: #eef4e8;
  --tint-wrong: #fbeceb;
  /* 线宽：主轴 / 辅助 / 标注 */
  --w-main:     2px;
  --w-aux:      1.4px;
  --w-note:     1.5px;
  /* 两栏的宽度：正文列的上限 900、导航栏 262。导航栏是定宽轨，
     正文列吃剩下的；900 只用来给正文列封顶，不参与分轨。 */
  --main-w:     900px;
  --nav-w:      262px;
  /* 字体：拉丁手写体自托管，中文走系统楷体，安卓没有楷体就回退黑体 */
  --font-note:  'Caveat', 'Kaiti SC', 'STKaiti', 'KaiTi', '楷体', cursive;
  --font-body:  'Kaiti SC', 'STKaiti', 'KaiTi', '楷体', -apple-system, 'PingFang SC', sans-serif;
  --font-ui:    -apple-system, 'PingFang SC', 'Microsoft YaHei', sans-serif;
}

*, *::before, *::after { box-sizing: border-box; }

html, body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 1.85;
  -webkit-font-smoothing: antialiased;
}

/* 壳要纵向铺满，靠的是弹性列，不是猜页头有多高。原先 .lab-layout 写的是
   min-height: calc(100vh - 58px)，58 是照着 .lab-top 估的；页头实测约 70px
   （上下 padding 28 + 品牌行高约 41 + 下边框 1.5），于是每页都多冒出一小截
   滚动条。让 body 做列、.lab-layout 吃掉剩余高度，页头将来改高也不会失配。
   dvh 是给移动端地址栏收放用的，不认识 dvh 的浏览器留在前一行。 */
body { min-height: 100vh; min-height: 100dvh; display: flex; flex-direction: column; }

/* ---------- 壳 ---------- */
.lab-top {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; padding: 14px 22px;
  border-bottom: var(--w-note) solid var(--ink-faint);
}
.lab-brand { font-family: var(--font-note); font-size: 22px; color: var(--ink); text-decoration: none; }
.lab-brand small { font-family: var(--font-ui); font-size: 12px; color: var(--ink-soft); margin-left: 8px; }
.lab-back { font-family: var(--font-ui); font-size: 13px; color: var(--ink-soft); text-decoration: none; }
.lab-back:hover { color: var(--accent); }
.lab-top-right { display: flex; align-items: center; gap: 14px; }
.lab-visitors { font-family: var(--font-ui); font-size: 12px; color: var(--action); }
.lab-visitors::before {
  content: ''; display: inline-block; width: 6px; height: 6px; margin-right: 6px;
  border-radius: 50%; background: var(--action); vertical-align: 2px;
}

/* 导航在**右**边。DOM 顺序仍是 nav 在前（不动），靠 grid-column 把它放到第二列 ——
   这样窄屏退回单列时不必重排文档（见文末窄屏那节），Tab 顺序也维持着「先菜单后正文」
   这一个既有行为，换列不会顺手改掉别的东西。 */
.lab-layout { display: grid; grid-template-columns: 1fr var(--nav-w); gap: 0; flex: 1; }
.lab-nav {
  grid-column: 2; grid-row: 1;
  border-left: var(--w-note) solid var(--ink-faint); padding: 18px 16px;
}
/* 正文在**左边这一栏内部**居中：导航栏是贴着视口右边不动的那条，正文列比
   --main-w 宽出来的部分平分到正文两侧 —— 两半都是正文的白边，跟导航无关。
   width:100% 不能省：网格项写 justify-self:center 之后是按内容定宽的，正文短的
   页会缩成一条窄栏，页与页之间宽度乱跳；先撑满轨道再让 max-width 封顶才稳定。
   ≤820px 退回单列时正文列本身就不足 900，这条居中自然失效。 */
.lab-main {
  grid-column: 1; grid-row: 1; padding: 30px 34px 80px;
  width: 100%; max-width: var(--main-w); justify-self: center;
}
/* 正文里的链接默认是浏览器蓝加下划线，落在纸色手绘风格里非常跳。
   正文链接一律走墨色，悬停才给赭色下划线。（音标格、练习选项那些是 <button>，
   不受这条影响。） */
.lab-main a { color: var(--ink); text-decoration: none; }
.lab-main a:hover { color: var(--accent); text-decoration: underline; }

/* ---------- 导航（上游的三级菜单） ----------
   菜单文字走手写体：拉丁部分是真手写体 Caveat（英文小标题、index 字形），
   中文落到系统楷体 —— 与正文同一套字体，整块看起来像写在本子边上的目录。
   边框半径照旧手抄 sketch.js 的 BOX_RADII（见文件头注释）。 */
.lab-nav { font-family: var(--font-note); }
.lab-nav-empty { margin: 0; font-size: 14px; color: var(--ink-soft); }
.lab-menu { list-style: none; margin: 0; padding: 0; }
/* 层级用缩进 + 字号 + 一道虚线三级表达。
   缩进必须**跨过父行的 index 字形那一格**（L1 的 ⋈ / ə / Aa 占 18px 加 7px 间距
   ＝ 33px），否则子行的文字起点落在父行标题的左边：15px 缩进时
   「错题与间隔复习」在 1058px、「英语结构全景」在 1068px —— 子行反而更靠左，
   下一行的 L1「音标学习」就跟父行标题对齐，读起来像是它的子项。
   虚线是第二重信号（纯靠 x 坐标分辨层级在 262px 的窄栏里不够稳），
   用 --ink-faint 而不是 --ink-soft：它只是「这条属于上面那一行」的牵引线，
   不该和正文的辅助线抢注意力。 */
.lab-menu .lab-menu {
  padding-left: 24px;
  margin-left: 11px;
  border-left: 1px dashed var(--ink-faint);
}
/* L3 再缩一点就够：父行是「组」行（没有 index 字形，标题就从 24px 处起），
   跟着 33px 走会白白吃掉窄栏的宽度。 */
.lab-menu-l2 .lab-menu { padding-left: 13px; margin-left: 8px; }
.lab-menu-item { margin: 1px 0; }
.lab-menu-row { display: flex; align-items: center; }

.lab-menu-link {
  flex: 1; min-width: 0; display: flex; align-items: baseline; gap: 7px;
  padding: 3px 8px; color: var(--ink); text-decoration: none;
  border-radius: 255px 12px 225px 12px / 12px 225px 12px 255px;
}
.lab-menu-labels { display: flex; flex-direction: column; min-width: 0; line-height: 1.3; }
.lab-menu-labels strong { font-weight: 400; font-size: 16px; }
.lab-menu-labels small {
  font-family: var(--font-note); font-size: 12px; color: var(--ink-faint);
  letter-spacing: .03em;
}
/* index 字形（⋈ / ə / Aa）是上游菜单的点睛处：留一格固定宽，各行标题才对得齐 */
.lab-menu-index {
  flex: 0 0 18px; text-align: center; font-size: 17px; color: var(--ink-soft);
}
.lab-menu-l2 .lab-menu-labels strong,
.lab-menu-l3 .lab-menu-labels strong { font-size: 15px; }
.lab-menu-l2 .lab-menu-index,
.lab-menu-l3 .lab-menu-index { font-size: 15px; }

.lab-menu-toggle {
  flex: 0 0 auto; display: flex; align-items: center; gap: 6px;
  font: inherit; font-size: 15px; color: var(--ink-soft); cursor: pointer;
  background: none; border: 0; padding: 3px 6px;
  border-radius: 255px 12px 225px 12px / 12px 225px 12px 255px;
}
/* 组行（「名词与限定词」这种自己没有页的行）整行都是那个开合按钮 */
.lab-menu-toggle.lab-menu-group { flex: 1; justify-content: space-between; color: var(--ink); }
.lab-menu-chevron { display: inline-block; transition: transform .15s ease-out; }
.lab-menu-toggle[aria-expanded='true'] .lab-menu-chevron { transform: rotate(90deg); }

.lab-menu-link:hover, .lab-menu-toggle:hover { background: rgba(138, 90, 52, .08); }
.lab-menu-link[aria-current='page'] { background: var(--marker); color: var(--accent); }
.lab-menu-link[aria-current='page'] small { color: var(--accent); }

/* ---------- 页头 ---------- */
.lab-kicker {
  font-family: var(--font-ui); font-size: 11px; letter-spacing: .16em;
  text-transform: uppercase; color: var(--ink-soft); margin: 0 0 4px;
}
/* 标题与版本切换器并排、两端对齐（标题在左、按钮在右），同一行同一条中轴。
   下边距挂在**行**上而不是标题上：没有版本可切的 78 页这一行只剩标题，
   10px 与从前逐字一致，不为「有没有按钮」分两套排版。
   弹性容器里的外边距不折叠，两个子项必须自己清零 —— 不清的话标题那 10px 会
   留在盒子里，行高比标题多出一截。窄屏放不下时按钮折到第二行，靠左。 */
.lab-title-row {
  display: flex; flex-wrap: wrap; align-items: center;
  justify-content: space-between; gap: 8px 20px;
  margin: 0 0 10px;
}
.lab-title { font-family: var(--font-body); font-size: 27px; font-weight: 700; margin: 0 0 10px; line-height: 1.35; }
.lab-title-row > .lab-title { margin: 0; }
.lab-lead { font-size: 15px; color: var(--ink); margin: 0 0 22px; }

/* ---------- 版本切换器 ----------
   只在多版本页出现，且只出现在 .lab-title-row 里（与标题并排）。
   看着像两张贴纸，当前那张用 --marker 压住底 —— 和侧栏的 aria-current='page'
   同一套语言（同色、同底色），读者不用学第二套。
   边框半径手抄 sketch.js 的 BOX_RADII 那组数值（见文件头注释）。
   自身不带外边距：行距由 .lab-title-row 管，这里再加一份会把它顶下去。 */
.lab-versions {
  display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
  margin: 0;
}
.lab-versions-label {
  font-size: 11px; color: var(--ink-faint);
}
.lab-version {
  padding: 4px 14px 5px;
  border: var(--w-note) solid var(--ink-faint); border-radius: 255px 12px 225px 12px / 12px 225px 12px 255px;
  color: var(--ink-soft); text-decoration: none;
  font-family: var(--font-body); font-size: 14px;
}
.lab-version:hover { border-color: var(--accent); color: var(--accent); }
.lab-version[aria-current='true'] {
  border-color: var(--accent); background: var(--marker); color: var(--accent);
}

/* 每个内容页开头固定是「目标 + 类比」一对（实测 65 页的 lead kind 只有这两种，
   位置固定在第 0、1 块）。类比是同一件事换孩子听得懂的说法，要跟目标贴着读，
   所以紧挨时把 .lab-lead 的 22px 下边距收成 6px（相邻外边距折叠，22 与 -16 相加）。 */
.lab-lead + .lab-lead { margin-top: -16px; }
.lab-lead-analogy { color: var(--ink-soft); }
/* 页面引言与地图小节的那句引子：它们是「子标题」性质的说明，不是正文，
   压到与 .lab-line-note / .lab-concept-en 同一个灰（13px / --ink-soft）——
   这两处本来就住着这个页面所有的次级说明文字。
   只挂在 language-map 的两段 COPY 上；那 65 页正文的 .lab-lead（目标 + 类比）
   是主句子，字号与墨色都不动，所以这里用修饰类而不是改 .lab-lead 本身。 */
.lab-lead-sub { font-size: 13px; color: var(--ink-soft); }

/* ---------- 小节 ---------- */
.lab-section { margin: 30px 0; }
.lab-section > h3 {
  font-family: var(--font-body); font-size: 18px; font-weight: 700;
  margin: 0 0 12px; padding-bottom: 6px;
}
.lab-section-head { display: flex; align-items: baseline; gap: 10px; }
.lab-step {
  font-family: var(--font-note); font-size: 20px; color: var(--action);
  min-width: 26px;
}

/* ---------- 例句行 ---------- */
.lab-lines { list-style: none; margin: 0; padding: 0; }
.lab-line { padding: 10px 0; border-bottom: 1px dashed var(--ink-faint); }
.lab-line-en { font-family: var(--font-note); font-size: 23px; line-height: 1.3; }
.lab-line-cn { color: var(--ink-soft); font-size: 14px; }
.lab-line-key { color: var(--accent); font-weight: 700; }
.lab-line-note { font-size: 13px; color: var(--ink-soft); margin-top: 3px; }

/* ---------- 词块 ---------- */
.lab-chunk {
  display: inline-block; margin: 0 8px 8px 0; padding: 3px 12px;
  border: var(--w-note) solid var(--ink);
  border-radius: 255px 14px 225px 14px / 14px 225px 14px 255px;
  font-family: var(--font-note); font-size: 20px; background: none;
  color: var(--ink); cursor: pointer;
}
.lab-chunk[aria-pressed='true'] { background: var(--marker); }

/* ---------- 对比 / 辨析（原站 04 / 05，壳见 .lab-region） ---------- */
/* 上边距 16px，和 02 的 .lab-step-grid、03 的 .lab-strips 同一格 —— 壳里第一条
   内容离标题（或引子）就是这个距离。最后一条不留 12px 下边距，否则壳的 20px
   内边距会变成 32px（03 的 .lab-strip:last-child 同理）。 */
.lab-pairs { margin: 16px 0 0; }
.lab-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 12px; }
.lab-pairs > .lab-pair:last-child { margin-bottom: 0; }
.lab-pair > div { padding: 10px 14px; border: var(--w-note) solid var(--ink-faint); border-radius: 225px 14px 255px 14px / 14px 255px 14px 225px; }
/* 栏名（汉语怎么说 / 英语怎么说 / 易错写法 / 改正后）：11px 的块级小标签，
   比它下面那句话小一号 —— 上游 `.eg-language-label` 就是 `display:block;
   font-size:11px; margin-bottom:6px`。04 里独占一行落在句子上方；
   05 里是句首的引子，所以那条要 inline-block（见下）。 */
.lab-side-label {
  display: block; margin-bottom: 4px;
  font-family: var(--font-ui); font-size: 11px; color: var(--ink-soft);
}
.lab-wrong { color: #a3423a; text-decoration: line-through; text-decoration-thickness: 2px; }
.lab-correct { color: var(--action); }
/* 05 那一句：栏名 + 句子同处一行，p 自己的 UA 外边距要清掉（不清的话这条会比
   04 那两栏矮一截，两节的行高对不上）。栏名 inline-block，不吃上面的 margin-bottom。 */
.lab-mistake-line { margin: 0; }
.lab-mistake-line .lab-side-label { display: inline; margin: 0 4px 0 0; }
.lab-reason { font-size: 13px; color: var(--ink-soft); margin-top: 4px; }
.lab-pair > .lab-reason { grid-column: 1 / -1; }

/* ---------- 练习 ---------- */
.lab-q { margin-bottom: 22px; }
/* 题干按类名点，不能用 `.lab-q > p`：那个选择器 (0,1,1) 会盖过 .lab-explain 的
   (0,1,0)，把 13px 的反馈撑成 16px；也会盖过填空那句 .lab-line-en 的 23px 手写体。
   实测改回 `.lab-q > p` 后，反馈的 computed font-size 从 13px 变成 16px。 */
.lab-prompt { font-size: 16px; margin: 0 0 8px; }
/* 题干自带的语篇：实测 123 题带 context（practice 45 + extra 的选择题 38 + 填空
   40），最长 1365 字。原文里的换行要留住，否则整段挤成一行。 */
.lab-context { font-size: 15px; color: var(--ink-soft); margin: 0 0 8px; white-space: pre-line; }
.lab-choices { list-style: none; margin: 0; padding: 0; }
.lab-choice {
  display: flex; gap: 10px; align-items: baseline;
  width: 100%; text-align: left; margin-bottom: 6px; padding: 7px 14px;
  background: none; border: var(--w-note) solid var(--ink-faint); color: var(--ink);
  border-radius: 255px 12px 225px 12px / 12px 225px 12px 255px;
  font-family: var(--font-body); font-size: 15px; cursor: pointer;
}
.lab-choice:hover:not(:disabled) { border-color: var(--ink); }
/* 判完分整组 disabled，鼠标还留着 pointer 会像是还能点。跟 .lab-check:disabled 一致。 */
.lab-choice:disabled { cursor: default; }
/* 点选即判（见 practice.js 的 settle）：只有对错两态，没有「选了但还没判」。
   答错**不锁**这道题 —— 标红的那项再点别的就换过去（practice.js 只把上一次
   的红清掉），所以 :disabled 只出现在答对和看过答案之后。 */
.lab-choice[data-state='correct'] { border-color: var(--action); color: var(--action); background: var(--tint-right); }
.lab-choice[data-state='wrong']   { border-color: #a3423a; color: #a3423a; background: var(--tint-wrong); }
/* 选项字母：给眼睛找位置用的（「选 B」），所以退一档、定宽，选项文字总是从同一列起。 */
.lab-choice-letter { flex: none; width: 1.1em; color: var(--ink-faint); font-size: 13px; }
.lab-choice[data-state='correct'] .lab-choice-letter { color: var(--action); }
.lab-choice[data-state='wrong'] .lab-choice-letter { color: #a3423a; }
.lab-explain { font-size: 13px; color: var(--ink-soft); margin-top: 6px; }

/* 填空题：上游是 sentence + hint + 输入框 + 「检查答案」。输入框和按钮的角半径
   照 .lab-choice 手抄，同一层控件用同一套外形。 */
.lab-fill-hint { font-size: 13px; color: var(--ink-soft); margin: 4px 0 0; }
.lab-fill-field { display: block; margin: 10px 0 0; }
.lab-fill-field > span { display: block; font-size: 13px; color: var(--ink-soft); margin-bottom: 4px; }
.lab-fill-input {
  display: block; width: 100%; box-sizing: border-box; padding: 7px 14px;
  background: none; border: var(--w-note) solid var(--ink-faint); color: var(--ink);
  border-radius: 255px 12px 225px 12px / 12px 225px 12px 255px;
  font-family: var(--font-body); font-size: 15px;
}
.lab-fill-input[data-state='correct'] { border-color: var(--action); color: var(--action); background: var(--tint-right); }
.lab-fill-input[data-state='wrong']   { border-color: #a3423a; color: #a3423a; background: var(--tint-wrong); }
.lab-check {
  margin-top: 10px; padding: 6px 18px 7px;
  background: none; border: var(--w-note) solid var(--ink); color: var(--ink);
  border-radius: 255px 14px 225px 14px / 14px 225px 14px 255px;
  font-family: var(--font-body); font-size: 15px; cursor: pointer;
}
.lab-check:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.lab-check:disabled { border-color: var(--ink-faint); color: var(--ink-soft); cursor: default; }

/* 排序题：上面「你排好的句子」是答案区（实线，越靠越像正文），下面词块池的
   按钮是虚线（还没放进去的东西）。两者外形不同，一眼能看出东西该往哪边走。 */
.lab-order-answer {
  display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
  min-height: 44px; padding: 8px 14px; margin: 0 0 10px;
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 255px 12px 225px 12px / 12px 225px 12px 255px;
}
.lab-order-pool { display: flex; flex-wrap: wrap; gap: 6px; }
.lab-order-empty { font-size: 13px; color: var(--ink-soft); }
/* 要排的那句中文意思（答案区**上面**）。比题干轻一档：它是题面的一部分，
   不是新的指令。 */
.lab-order-translation { margin: 0 0 10px; font-size: 15px; color: var(--accent); }
/* 「已选 N / M 个词块」/「词块已选齐，可以检查答案。」—— 排到一半看还差几块。
   min-height 撑住一行，免得计数从「已选 1 / 6」跳到「已选 2 / 6」时整页抖一下。 */
.lab-order-hint { min-height: 20px; margin: 8px 0 10px; font-size: 13px; color: var(--ink-soft); }
/* 「检查答案」和「重新排列」并排（上游 .egp-order-actions 就是这一行）。 */
.lab-order-actions { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }
.lab-order-reset {
  padding: 6px 18px 7px;
  background: none; border: var(--w-note) solid var(--ink-faint); color: var(--ink-soft);
  border-radius: 255px 14px 225px 14px / 14px 225px 14px 255px;
  font-family: var(--font-body); font-size: 15px; cursor: pointer;
}
.lab-order-reset:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.lab-order-reset:disabled { cursor: default; }
.lab-order-chip {
  padding: 4px 12px 5px;
  background: none; border: var(--w-note) dashed var(--ink-faint); color: var(--ink);
  border-radius: 255px 12px 225px 12px / 12px 225px 12px 255px;
  font-family: var(--font-body); font-size: 15px; cursor: pointer;
}
/* 已经放进答案区的词块是实线：它「定下来」了 */
.lab-order-answer .lab-order-chip { border-style: solid; }
.lab-order-chip:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.lab-order-chip:disabled { cursor: default; color: var(--ink-soft); }
.lab-q-order[data-state='correct'] .lab-order-answer { border-color: var(--action); background: var(--tint-right); }
.lab-q-order[data-state='wrong']   .lab-order-answer { border-color: #a3423a; background: var(--tint-wrong); }

/* 「已连对 N / M 组 · 请选择右侧伙伴」：连线题是一张张连过去的，连到一半得能看出
   连了几组、下一步该点哪一边 */
.lab-match-progress { font-size: 13px; color: var(--ink-soft); margin: 0 0 8px; }
/* 连线题的板子：两栏网格，且**不换行** —— 连线要横跨左右两栏，栏一折到下面去
   这条线就没地方画了。宁可把卡片挤窄（窄屏下靠内边距和字号收一收）。
   gap 留得比一般间距宽，线才有地方走出 S 形，不然两根线会贴在一起。
   minmax(0,1fr) 而不是 1fr：中文长词条不给下限会把整栏撑爆。 */
.lab-match-board {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(34px, 9vw, 104px);
  align-items: start;
}
/* 连线层垫在卡片底下（z-index 0），卡片盖在上面（z-index 1）—— 线从卡片边缘
   起笔，盖住一点点才像是插进去的。pointer-events: none 让点击照常落到卡上。
   stroke 的兜底照 sketch.js 的规矩写：缺 lab.css 时 var(--action) 没有值，
   而 SVG stroke 的初始值是 none —— 没有兜底会让所有线静默隐身。 */
.lab-match-lines { position: absolute; inset: 0; overflow: visible; pointer-events: none; z-index: 0; }
.lab-match-lines path { fill: none; stroke-width: 3; stroke-linecap: round; stroke: var(--action, currentColor); }
.lab-match-lines path[data-state='wrong'] { stroke: #a3423a; stroke-dasharray: 4 4; }
.lab-match-col { position: relative; z-index: 1; list-style: none; margin: 0; padding: 0; min-width: 0; }
.lab-match-item {
  display: block; width: 100%; text-align: left; margin-bottom: 6px; padding: 7px 14px;
  background: none; border: var(--w-note) solid var(--ink-faint); color: var(--ink);
  border-radius: 255px 12px 225px 12px / 12px 225px 12px 255px;
  font-family: var(--font-body); font-size: 15px; cursor: pointer;
}
.lab-match-item:hover:not(:disabled) { border-color: var(--ink); }
.lab-match-item:disabled { cursor: default; }
/* 选中但还没配成：只换边框色和底纹，不该看起来像已经连上了 */
.lab-match-item[data-state='picked'] { border-color: var(--accent); background: var(--marker); }
/* 对错标在**每一张卡**上，不是整个题：连对的会一张张留下来，绿的是已经连对、
   不用再管的；红的是这一次没配上的那一对（左边那张还留着，换张右边的再连） */
.lab-match-item[data-state='correct'] { border-color: var(--action); color: var(--action); background: var(--tint-right); }
.lab-match-item[data-state='wrong']   { border-color: #a3423a; color: #a3423a; background: var(--tint-wrong); }

/* 还没搬的题型（evidence/listening）：一张虚线卡，把题干原样带出来。
   实线框会看着像一道能答的题。 */
.lab-q-todo {
  padding: 12px 16px; border: var(--w-note) dashed var(--ink-faint);
  border-radius: 255px 14px 225px 14px / 14px 225px 14px 255px;
}

/* ---------- 练习页（一屏一题） ---------- */
/* 整场练习的头部：「第 N / N 题」与「首次答对 N 题」分列两端，下面一条进度条。
   进度条复用地图那张卡已经有的 .lab-progress / .lab-progress-fill —— 同一个东西
   在站里只该有一个样子。 */
.lab-set-progress { margin: 0 0 16px; }
.lab-set-meta {
  display: flex; justify-content: space-between; align-items: baseline; gap: 12px;
  margin: 0 0 6px; font-family: var(--font-ui); font-size: 13px; color: var(--ink-soft);
}
/* 首次答对是这一行里唯一的成绩，给一点重量，别和题号读成同一句话 */
.lab-set-score { color: var(--ink); font-weight: 700; }
/* 一道题一张卡。卡片外形与差异卡、概念卡同一套手绘边框，好让「这是一道待答的题」
   和别处的卡分得开。 */
.lab-set-card {
  padding: 16px 22px 18px;
  background: var(--paper-card);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 255px 16px 225px 16px / 16px 225px 16px 255px;
  box-shadow: 2px 3px 0 rgba(51, 48, 43, .07);
}
/* 题卡自己带外边距会把它和底部按钮之间的空隙撑成两倍，这里交回给 .lab-set-actions */
.lab-set-card .lab-q { margin-bottom: 0; }
/* 题头：「复习：…」靠左、题型靠右。两样都是这一题的元信息，不该抢题干的视线，
   所以都比题干小一号。 */
.lab-set-head {
  display: flex; justify-content: space-between; align-items: baseline; gap: 12px;
  margin: 0 0 12px;
}
/* 题卡与结果页轮流占的那一格。它自己不画东西 —— 换屏时只换里面的孩子，
   底部那两颗按钮不跟着重建（重建会把焦点甩出文档）。 */
.lab-set-slot { display: block; }
.lab-set-lesson { font-size: 13px; color: var(--accent); }

.lab-set-kind {
  flex: none; padding: 1px 10px 2px;
  font-family: var(--font-ui); font-size: 12px; color: var(--ink-soft);
  border: var(--w-aux) solid var(--ink-faint);
  border-radius: 225px 12px 255px 12px / 12px 255px 12px 225px;
}
/* 「查看答案和讲解」靠左、「下一题」靠右。两个按钮各占一头，手指在窄屏上也不会
   误触到另一个。 */
.lab-set-actions {
  display: flex; justify-content: space-between; align-items: center;
  gap: 12px; margin-top: 18px;
}
.lab-set-actions button {
  padding: 6px 18px 7px; background: none;
  border: var(--w-note) solid var(--ink); color: var(--ink);
  border-radius: 255px 14px 225px 14px / 14px 225px 14px 255px;
  font-family: var(--font-body); font-size: 15px; cursor: pointer;
}
/* 次要的那个（看答案）颜色浅一号：这一步不改成绩，是给自己对一下。
   选择器要两段才压得住上面那条 `.lab-set-actions button`。 */
.lab-set-actions .lab-set-reveal { border-color: var(--ink-faint); color: var(--ink-soft); }
.lab-set-actions button:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.lab-set-actions button:disabled {
  border-color: var(--ink-faint); color: var(--ink-faint); cursor: default;
}

/* 练习页末尾那两条回程（上游 `.eg-back-to-study`：`display:block; margin:20px auto`，
   所以是上下两行、每行各占一块）。这里排成一列、行距 20px —— 和上游塌陷后的
   外边距同一个距离，但不必靠外边距折叠去凑。 */
.lab-set-foot {
  display: flex; flex-direction: column; gap: 20px; margin-top: 20px; font-size: 13px;
}
.lab-set-foot a { color: var(--action); }
.lab-set-foot a:hover { text-decoration: underline; }

/* 结果页（上游 _()）：一句结论 + 分数 + 逐题回顾。它占的是题卡那一格，所以沿用
   .lab-set-card 的壳 —— 换屏时外形不该跟着跳。 */
.lab-set-result { padding-bottom: 4px; }
.lab-result-title { margin: 0 0 6px; font-size: 20px; font-weight: 500; }
.lab-result-score { margin: 0 0 4px; font-size: 28px; color: var(--action); }
.lab-result-note { margin: 0 0 16px; font-size: 12px; color: var(--ink-soft); }
.lab-result-list { list-style: none; margin: 0; padding: 0; font-size: 13px; }
.lab-result-list > li { margin-bottom: 8px; }
/* ✓ 首次答对是绿的、↻ 再巩固是浅的 —— 一眼扫过去就知道哪几题要回去看 */
.lab-result-mark { margin-right: 6px; }
.lab-result-mark.is-right { color: var(--action); }
.lab-result-mark.is-retry { color: var(--ink-soft); }
.lab-result-list a { color: var(--accent); }
.lab-result-answer { margin: 4px 0 0 2px; color: var(--ink-soft); }
.lab-result-answer summary { cursor: pointer; }
.lab-result-correct { margin: 6px 0 2px; color: var(--ink); }
/* 卷面回顾下面那一句「做错的题也是线索…」。跟回顾列表拉开距离，它说的是
   下一步该怎么办，不是列表里的第 N 条。 */
.lab-result-tail { margin: 16px 0 0; font-size: 13px; color: var(--ink-soft); }

/* 结果页顶上那块庆祝。底色跟全站的纸不一样（浅黄绿渐变），它是这一轮唯一的
   一次「结束了」，要跳出来；位置写 relative 是为了当礼花的定位祖先 —— 礼花
   那层自己是 fixed，落在哪儿都盖满屏。 */
.lab-celebration {
  position: relative; text-align: center; margin: 14px 0 20px; padding: 20px 16px;
  border: var(--w-note) solid var(--ink-faint);
  background: linear-gradient(135deg, #f8f1de, #edf5e4 70%);
  border-radius: 255px 15px 225px 15px / 15px 225px 15px 255px;
}
.lab-celebration-icon { display: block; font-size: 40px; line-height: 1; margin-bottom: 6px; }
.lab-celebration h3 { margin: 0; font-size: 22px; font-weight: 500; color: var(--action); }
.lab-celebration p { margin: 8px 0 14px; font-size: 14px; color: var(--ink-soft); }
.lab-celebration-again {
  padding: 6px 18px 7px;
  background: none; border: var(--w-note) solid var(--ink-faint); color: var(--ink-soft);
  border-radius: 255px 14px 225px 14px / 14px 225px 14px 255px;
  font-family: var(--font-body); font-size: 15px; cursor: pointer;
}
.lab-celebration-again:hover { border-color: var(--accent); color: var(--accent); }

/* 礼花：一层铺满屏的 fixed 覆盖层（pointer-events 关掉，不挡下面的按钮），
   80 个 <i> 各自带一组随机变量飞出去 —— 横向散开多少、先上抛多高、落多深、
   转几圈。方向与时长由 celebration() 现算，这里只管怎么飞。 */
.lab-confetti { position: fixed; inset: 0; z-index: 1500; pointer-events: none; overflow: hidden; }
.lab-confetti i {
  position: absolute; width: 9px; height: 13px; opacity: 0;
  animation: lab-confetti-flight 2.1s ease-out both;
}
@keyframes lab-confetti-flight {
  0%   { opacity: 0; transform: translate(0) rotate(0); }
  8%   { opacity: 1; }
  35%  { opacity: 1; transform: translate(calc(var(--confetti-x) * .55), var(--confetti-up)) rotate(calc(var(--confetti-spin) * .35)); }
  to   { opacity: 0; transform: translate(var(--confetti-x), var(--confetti-down)) rotate(var(--confetti-spin)); }
}
/* 不看动画的人不该被礼花糊一脸。JS 那边同样认这条（不生成 <i>、藏起按钮），
   两边都要有：JS 管住 DOM 里有没有，CSS 管住万一已经有了也不动。 */
@media (prefers-reduced-motion: reduce) {
  .lab-confetti { display: none; }
  .lab-confetti i { animation: none; }
}

/* ---------- 发音 ---------- */
.lab-speak {
  background: none; border: none; padding: 0 2px; cursor: pointer;
  color: var(--ink-soft); vertical-align: middle; line-height: 1;
}
.lab-speak:hover { color: var(--accent); }
.lab-speak[aria-busy='true'] { opacity: .45; }
.lab-speak svg { width: 17px; height: 17px; display: block; }

/* ---------- 音标格 ---------- */
.lab-phonemes { display: grid; grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); gap: 10px; }
/* 格子住进图谱卡（--paper-card）之后，底要退一档用 --paper：不填的话格子底和
   卡片底一样，48 个格子看着是卡片上印的字，不像 48 个可以点的方块。 */
.lab-phoneme {
  border: var(--w-main) solid var(--ink); background: var(--paper); padding: 8px 10px;
  border-radius: 255px 18px 255px 16px / 16px 255px 18px 255px;
  cursor: pointer; text-align: left; color: var(--ink);
}
.lab-phoneme:nth-child(even) { border-radius: 18px 255px 16px 255px / 255px 16px 255px 18px; }
.lab-phoneme-sym { font-family: var(--font-note); font-size: 23px; display: block; line-height: 1.1; }
.lab-phoneme-word { font-family: var(--font-note); font-size: 15px; color: var(--ink-soft); }

/* 例句词块在一行里排开。.lab-chunk 是给可点的 <button> 定的（cursor:pointer），
   span 借用同一套外观时要把「可点」的暗示去掉。 */
.lab-chunk-line { margin: 4px 0; }
.lab-chunk-line .lab-chunk { cursor: default; margin: 0 4px 4px 0; }
.lab-chunk.is-emphasis { border-color: var(--accent); color: var(--accent); }

/* ---------- 图解讲解（explorer 块） ---------- */
/* 原站这一节是三层选择器：情境 → 例句 → 拆解图。框的角半径照 sketch.js 的
   BOX_RADII 手抄，奇数颗与偶数颗横竖对调，和 .lab-phoneme / .lab-explorer-group
   同一套镜像规律。 */
.lab-explorer-groups { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 10px; }
.lab-explorer-group {
  display: block; text-align: left; padding: 6px 14px 7px;
  background: none; border: var(--w-note) solid var(--ink-faint); color: var(--ink);
  border-radius: 255px 14px 225px 14px / 14px 225px 14px 255px;
  font-family: var(--font-body); cursor: pointer;
}
.lab-explorer-group:nth-child(even) { border-radius: 14px 255px 14px 225px / 225px 14px 255px 14px; }
.lab-explorer-group strong {
  display: block; font-family: var(--font-note); font-size: 19px; font-weight: 400; line-height: 1.25;
}
.lab-explorer-group span { display: block; font-size: 13px; color: var(--ink-soft); }
.lab-explorer-group[aria-pressed='true'] { border-color: var(--accent); background: var(--marker); }
.lab-explorer-group[aria-pressed='true'] span { color: var(--accent); }

/* 情境说明照 .lab-line-note 的字号配色（13px / --ink-soft）抄一份：它和结果区
   那句 note 是同一层信息，两处字号必须一致，改一边要同步另一边。 */
.lab-explorer-description { font-size: 13px; color: var(--ink-soft); margin: 0 0 10px; }

/* 例句行直接用 .lab-chunk（图块外观 + aria-pressed 的淡棕底）。它自带
   margin: 0 8px 8px 0，那已经是行距了，所以这里不再加 flex/gap ——
   两份间距会叠在一起。 */
.lab-explorer-examples { margin: 0 0 4px; }
.lab-explorer-result { margin: 0 0 12px; }
.lab-explorer-actions { margin-top: 10px; }

/* 带可见标签的喇叭（读整句用）。.lab-speak 本身是 line-height:1 的图标按钮，
   行内塞文字会错基线，所以它下面的 <svg> 是 display:block（见上一条），
   标签就被挤到第二行 —— 凡是挂了 .lab-speak-label 的都得按 flex 中线对齐。
   两处：词块浏览器的整句发音、站点详情例句卡里的「听这一站的例句」。
   音标格那几个纯图标按钮不挂标签，不受影响。 */
.lab-explorer-actions .lab-speak,
.lab-example-actions .lab-speak { display: inline-flex; align-items: center; }
.lab-speak-label { margin-left: 5px; font-size: 13px; }

/* ---------- 图解（sentence diagram） ---------- */
/* svg 默认是 inline：底边会留一条基线间隙，整块图看着被顶下来几像素。
   display:block 消掉它，和时间线的 .lab-tenses-chart-svg 同一条理由。 */
.lab-diagram { position: relative; }
.lab-diagram svg { display: block; }

/* 这条旁白只给读屏软件听（见 diagram.js 里高亮块的 aria-live）：视觉上藏起来，
   但必须留在无障碍树里 —— display: none / visibility: hidden 会把节点整个摘出去，
   读屏就读不到，等于没加。裁到 1px 的经典写法既看不见、又仍在树里。
   clip 是老写法（已废弃，但所有浏览器都还认），clip-path: inset(50%) 是它的现代
   替代，两个都留一份，新旧都能藏住。绝对定位的祖先得是定位元素，否则它挂到初始
   包含块上 —— 上面 .lab-diagram 那条 position: relative 就是为它立的。 */
.lab-diagram-live {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ---------- 图解：一节一张区域卡（原站 .eg-diagram-section） ----------
   栏头（01 / 看得见的结构 + 标题）、读法说明、词块小卡、反馈行、工具与朗读都在
   这一张卡里 —— 原站就是把它画成一张浅底描边的面板，跟上下两节讲解分开。
   半径与底色走全站那套手绘卡片（见 .lab-alphabet，同一份数值）。 */
.lab-diagram-region {
  padding: 18px 20px 20px;
  background: var(--paper-card);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 225px 16px 255px 16px / 16px 255px 16px 225px;
  box-shadow: 2px 3px 0 rgba(51, 48, 43, .07);
}
/* 眉标与标题在左、两个工具按钮在右，两端对齐；窄屏工具折到第二行。
   这一行里的外边距不折叠，两个子项各自清零（同 .lab-title-row 那条）。 */
.lab-diagram-head {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 8px 16px;
}
.lab-diagram-number {
  display: block; margin: 0 0 4px;
  font-family: var(--font-ui); font-size: 11px; letter-spacing: .16em; color: var(--action);
}
.lab-diagram-title { margin: 0; font-family: var(--font-body); font-size: 20px; font-weight: 700; }
.lab-diagram-note { margin: 8px 0 14px; font-size: 13px; line-height: 1.8; color: var(--ink-soft); }
.lab-diagram-tools { display: flex; flex-wrap: wrap; gap: 8px; }
.lab-diagram-tools button {
  padding: 4px 12px 5px; background: var(--paper); cursor: pointer; color: var(--ink-soft);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 14px 5px 13px 5px / 5px 13px 5px 14px;
  font-family: var(--font-body); font-size: 13px;
}
.lab-diagram-tools button:hover { border-color: var(--accent); color: var(--accent); }
.lab-diagram-tools button[aria-pressed='true'] {
  border-color: var(--accent); background: var(--marker); color: var(--accent);
}
/* 练习期间标签按钮是禁用的（见 diagram.js）：变淡，且不要再跟着变手型变色。 */
.lab-diagram-tools button[disabled] { opacity: .45; cursor: default; }
.lab-diagram-tools button[disabled]:hover { border-color: var(--ink-faint); color: var(--ink-soft); }

/* 反馈行：原站那一条浅底提示（.eg-diagram-feedback），说的是现在选中的这块在
   做什么。它同时是 role=status 的活区，换一块时读屏也念一遍 —— 所以底色、
   左边那道竖线都跟「逐字母备注」用同一套（.lab-letter-note）。
   min-height 压住「有解说 / 没解说」两种选中之间那一跳。 */
.lab-diagram-feedback {
  min-height: 20px; margin: 12px 0 0; padding: 9px 14px;
  font-size: 13px; line-height: 1.8; color: var(--ink);
  background: var(--paper); border-left: 4px solid var(--action);
  border-radius: 0 10px 10px 0;
}
.lab-diagram-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 12px 0 0; }

/* ---------- 区域卡：一个正文小节 = 一张浅底描边面板 ----------
   正文页的 02 / 03 / 04 / 05 四个小节在上游是同一个 .eg-section：眉标
   「NN / 小节名」+ h2 标题 + 可选的灰色引子（.eg-section-note），外壳一模一样，
   所以四个组件统一挂这一组类，不各写一份。里面装什么由各组件决定：
   02 两栏小卡（.lab-step-grid）、03 手绘横条（.lab-strips）、
   04 双语两栏、05 错句两栏（两者都是 .lab-pairs 里的一条条 .lab-pair）。
   配色仍是那三档：眉标走 --action，标题 --ink，正文 --ink-soft。 */
.lab-region {
  padding: 18px 20px 20px;
  background: var(--paper-card);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 255px 16px 225px 16px / 16px 225px 16px 255px;
  box-shadow: 2px 3px 0 rgba(51, 48, 43, .07);
}
.lab-region-number {
  display: block; margin: 0 0 4px;
  font-family: var(--font-ui); font-size: 11px; letter-spacing: .16em; color: var(--action);
}
.lab-region-title { margin: 0; font-family: var(--font-body); font-size: 20px; font-weight: 700; }
/* 小节引子：照 .lab-diagram-note 那一档（13px / --ink-soft）。
   下边距留 0 —— 紧跟其后的内容容器自己带 16px 上边距，两者相邻会折叠成 16px，
   写在这里也是白写。只有 03、04 原站写了这句引子，02、05 没有。 */
.lab-region-note { margin: 8px 0 0; font-size: 13px; line-height: 1.8; color: var(--ink-soft); }
/* 两栏，和原站一样；窄屏落成一栏（断点见文件末尾那组 @media）。
   类名不叫 .lab-steps —— 那个名字音标页的 `<ol>` 已经在用（见文件下半截，
   padding-left: 20px），撞上去会让这张网格凭空多出 20px 左缩进和 0 上外边距。 */
.lab-step-grid {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 15px; margin: 16px 0 0;
}
/* 卡里的 h3 不再命中 .lab-section > h3（那是子选择器），字号自己也有一档：
   卡比整节窄一半，18px 的标题会顶到边上。 */
.lab-step-card {
  padding: 14px 18px 15px;
  background: var(--paper);
  border: var(--w-aux) solid var(--ink-faint);
  border-radius: 14px 5px 13px 5px / 5px 13px 5px 14px;
}
.lab-step-card h3 {
  margin: 0 0 8px; font-family: var(--font-body);
  font-size: 16px; font-weight: 700; color: var(--ink);
}
.lab-step-card p { margin: 0; font-size: 14px; line-height: 1.95; color: var(--ink-soft); }

/* 01 讲解页末尾的练习入口（原站 .eg-exercise-entry）。壳是 .lab-region，里面
   只有一行引子和一个链接。 */
/* 标题与引子之间的空隙比别的区域卡小：这一张只有两行字和一个按钮，引子按
   .lab-region-note 的 8px 落下来，卡片会显得空半格。 */
.lab-entry .lab-region-note { margin-top: 6px; }
/* 链接照 .lab-set-actions button 那一档画：同一副手绘描边、同一个圆角族。
   挂 --action（绿）而不是 --accent（棕）—— 它是「往前走一步」，与眉标同色。 */
.lab-entry-link {
  display: inline-block; margin-top: 14px; padding: 7px 20px 8px;
  border: var(--w-note) solid var(--action); border-radius: 255px 14px 225px 14px / 14px 225px 14px 255px;
  font-family: var(--font-body); font-size: 15px; color: var(--action); text-decoration: none;
}
.lab-entry-link:hover { background: var(--marker); }

/* ---------- 例句：一条条手绘横条（原站 03 / 放进真实句子） ----------
   壳是 .lab-region（见上），里面换成横条：原站 .eg-example 是「序号在左、整段
   文字在右」的两栏行，行间一条发丝线分开；纸面上更像一条条贴上去的纸带，所以
   画成手绘横条，条间留 12px，不再用虚线分隔。
   偶数条取镜像半径 —— 全站的手绘错落都这么来（见文件头那条规范）。 */

.lab-strips { list-style: none; margin: 16px 0 0; padding: 0; }
/* align-items 用 baseline：序号要落在英文那一行上，而不是跟整条顶端对齐
   （一条里三行时，顶端对齐会让序号浮在上面半格）。 */
.lab-strip {
  display: flex; align-items: baseline; gap: 14px;
  padding: 12px 18px 13px; margin: 0 0 12px;
  background: var(--paper);
  border: var(--w-aux) solid var(--ink-faint);
  border-radius: 255px 16px 225px 16px / 16px 225px 16px 255px;
}
.lab-strip:last-child { margin-bottom: 0; }
.lab-strip:nth-child(even) { border-radius: 16px 255px 16px 225px / 225px 16px 255px 16px; }
/* 序号复用 .lab-step（概念图例里那个「引导字」）：同一个东西，同一份字。
   flex 里要能压住不缩，否则长例句会把序号挤扁。 */
.lab-strip .lab-step { flex: 0 0 auto; }
.lab-strip-body { flex: 1 1 auto; min-width: 0; }

/* 行内单词：一整个词就是一颗按钮，露出来的只有「这个词带下划线」这件事。
   字体字号行高全部继承 —— 它是句子的一部分，不是嵌进去的小控件；换行时
   也要跟着句子的节奏走，所以 inline-flex + baseline 对齐，不用 inline-block
   （那会带上自己的一行高，把 23px 的手写体撑开）。
   hover / 按下时描边变色，和全站「可点 = 变 accent」一致。 */
.lab-speak-word {
  display: inline-flex; align-items: baseline; vertical-align: baseline;
  padding: 0 1px; margin: 0;
  border: 0; border-bottom: var(--w-aux) dotted var(--ink-faint);
  border-radius: 3px; background: transparent;
  color: inherit; font: inherit; line-height: inherit; cursor: pointer;
}
.lab-speak-word:hover {
  color: var(--accent); border-bottom-color: var(--accent); background: var(--marker);
}
/* 点读期间变淡（.lab-speak[aria-busy] 已有一份，这条只是把底色一起带上，
   否则 word 的 hover 底色会盖住变淡这件事）。 */
.lab-speak-word[aria-busy='true'] { opacity: .45; background: transparent; color: inherit; }
/* 单词按钮里的那截文字要跟句子一个字号。.lab-speak-label 是给「喇叭 + 标签」的
   胶囊定的 13px + 5px 左边距（见发音那一节）——照搬过来，词就比句子小一圈，
   句末那个没包进按钮的句号反倒是 23px，看着像两句话拼起来的。
   只在这个按钮里改：别处挂 .lab-speak-label 的（胶囊、explorer、alphabet）不动。 */
.lab-speak-word .lab-speak-label { margin-left: 0; font: inherit; }
/* 一句话下面那行听音按钮（03 例句的「听例句」、04 双语右栏的「听英语表达」）——
   同一件东西，共用一份声明：它是块级的（独占一行，不跟句子挤在一起），
   胶囊自己的长相在 .lab-speak-pill 里。 */
.lab-strip-actions,
.lab-pair-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 10px 0 0; }

/* ---------- 关系地图（language-map 的 v1） ---------- */
/* 一条横贯正文的虚线，用来把上下两块分开。这一页用了三条：页引与地图之间、
   地图与站点清单之间、清单与概念图之间。前两条之间那 22/30px 的空档本来就是
   「两个小节」的距离，靠多空一行是分不开的；画一条虚线，两块的分界一眼看得见。
   线在普通流里**自己不带外边距**：上下两段的外边距各自折叠到线两边
   （上 22px、下 30px），位置交给相邻元素，线只管把它画出来。 */
.lab-rule {
  height: 0; margin: 0; border: 0;
  border-top: var(--w-aux) dashed var(--ink-faint);
}
/* 这一页的页引与页头是一句话的两半（「英语结构概述」/「从一个声音，到一本书」），
   中间那一档按通行值量出来是 12.6px 墨距，比眉标到标题的 5.6px 松了一倍。
   收到同一个节奏上。`.lab-map` 是这一页独有的标记，其余 79 页共用的
   10px 一个字不动（:has 不认的老浏览器只是留着原来的间距，不会错位）。 */
.lab-main:has(.lab-map) .lab-title-row { margin-bottom: 3px; }

/* 小节的抬头是左右两栏：左边依次是英文眉标、小节标题、那句引子，右边一张
   学情记录卡，两端对齐。用栅格而不是弹性行，因为卡片要**跨过左边那三行**
   （1 / span 3）—— 弹性行只能让它跟眉标同高，右边会空出一大半。
   下面每一项都显式落在格子里：只写 grid-column 的话自动落位会把标题排到第 2 列去。
   地图 SVG 与收尾的虚线回到整幅一行（1 / -1）。 */
.lab-map {
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  column-gap: 28px; align-items: start;
}
.lab-map > .lab-kicker { grid-column: 1; grid-row: 1; }
.lab-map > h3 { grid-column: 1; grid-row: 2; }
.lab-map > .lab-lead-sub { grid-column: 1; grid-row: 3; }
.lab-map > .lab-map-record { grid-column: 2; grid-row: 1 / span 3; }
.lab-map > .lab-map-art,
.lab-map > .lab-rule { grid-column: 1 / -1; }
/* 页引那条线靠相邻外边距折叠定位，这里的线是**网格项**（地图下面那一条），
   外边距不折叠：不给它留边距就会贴着 SVG 底边，所以自己带一档上边距。
   下边距归 0，节与节之间的 30px 由 .lab-section 那头出。 */
.lab-map > .lab-rule { margin: 14px 0 0; }

/* 学情记录卡：数字与说明在上、进度条在下。卡内用栅格 gap 排行距，
   两个子项的外边距清零 —— 网格项的外边距不折叠，留着那 6px / 18px
   会各自在间距上再加一层。 */
.lab-map-record {
  display: grid; gap: 8px; align-content: start;
  padding: 12px 16px 14px;
  background: var(--paper-card);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 255px 16px 225px 16px / 16px 225px 16px 255px;
  box-shadow: 2px 3px 0 rgba(51, 48, 43, .07);
}
.lab-map-record > .lab-map-summary { margin: 0; }

/* 地图整块是 SVG，宽度自适应（viewBox 由站数算出来，见 languageMap.js）。 */
.lab-map-art svg { display: block; }
.lab-map-summary { font-size: 14px; }
/* 进度条只在记录卡里（见上面 .lab-map-record），行距由卡片的 gap 管，自己不带外边距。 */
.lab-progress {
  height: 8px; margin: 0; overflow: hidden;
  border: var(--w-aux) solid var(--ink-faint);
  border-radius: 225px 8px 255px 8px / 8px 255px 8px 225px;
}
.lab-progress-fill { display: block; height: 100%; width: 0; background: var(--action); }
/* 「声音 → 表达 → 篇章」：页头那一块的收尾（见 languageMap.js 的 cap）。
   上边距 6px 紧跟页引，下边距 22px 是原来页引到那条虚线之间的距离 ——
   .lab-rule 自己不带外边距，全靠在它上面那个元素把线推下去。 */
.lab-map-caption { margin: 6px 0 22px; font-size: 14px; }
.lab-map-caption span { color: var(--ink-soft); font-size: 13px; }

/* 站点卡片：<g> 是整块可点的，选中和获得焦点都加粗描边 + 铺底色。
   CSS 声明压得住 SVG 的 presentation attribute（后者的特异度是 0），
   所以不用在 JS 里把颜色算两遍。 */
.lab-station { cursor: pointer; }
.lab-station:focus { outline: none; }
.lab-station[data-selected='true'] .lab-station-card,
.lab-station:focus .lab-station-card { stroke-width: 3.2; fill: var(--marker); }

/* 站头：左站名与目标、右例句卡。卡片靠右而不是铺满，是为了让「这一站叫什么、
   要练什么」和「这一站的门面句」在同一眼里 —— 卡片是站头的配图，不是正文的第一块。 */
.lab-station-head {
  display: grid; grid-template-columns: 1fr 1.1fr;
  gap: 8px 24px; align-items: start; margin-bottom: 6px;
}
.lab-station-intro > h3 { margin-top: 4px; }

/* 例句卡：一张纸，自上而下三行 —— 英文、中文、发音按钮。
   底纸比 --paper 亮一档，描边与圆角沿用 sketch.js 的 BOX_RADII（横竖半径错开），
   加一点硬边投影当作纸的厚度：**不用模糊阴影**，模糊会把铅笔味弄脏。 */
.lab-example-card {
  padding: 14px 18px;
  background: var(--paper-card);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 255px 14px 225px 14px / 14px 225px 14px 255px;
  box-shadow: 2px 3px 0 rgba(51, 48, 43, .07);
}
.lab-example-card .lab-line-en { margin: 0 0 4px; }
.lab-example-card .lab-line-cn { margin: 0; }
/* 发音按钮单独一行，和上面那句用虚线隔开：它是「操作」，不是句子的一部分 */
.lab-example-actions {
  margin-top: 10px; padding-top: 8px; border-top: 1px dashed var(--ink-faint);
}
/* 计数在左、筛选在右，同一条基线。间距与 margin 都收在这一行上：
   .lab-stop-count 只负责文字样式，.lab-stop-filters 只负责三个按钮的排布。
   上面那道虚线把「站头（站名 + 例句卡）」和「这一站的知识点」分开 —— 前者是
   这一站的门面，后者是可以逐条勾掉的清单，不加分隔线会连成一片。 */
.lab-stop-bar {
  display: flex; flex-wrap: wrap; align-items: center;
  justify-content: space-between; gap: 10px 16px; margin: 16px 0 10px;
  padding-top: 14px; border-top: 1px dashed var(--ink-faint);
}
.lab-stop-filters { display: flex; gap: 8px; }
.lab-stop-filter {
  padding: 3px 14px 4px; background: none; cursor: pointer;
  border: var(--w-note) solid var(--ink-faint); color: var(--ink-soft);
  border-radius: 255px 12px 225px 12px / 12px 225px 12px 255px;
  font-family: var(--font-body); font-size: 14px;
}
.lab-stop-filter:hover { border-color: var(--accent); color: var(--accent); }
.lab-stop-filter[aria-pressed='true'] {
  border-color: var(--accent); background: var(--marker); color: var(--accent);
}
.lab-stop-count { font-size: 13px; color: var(--ink-soft); margin: 0; }
/* 知识点清单：一行两张卡。卡片自己画框，角半径照 sketch.js 的 BOX_RADII 手抄，
   偶数张横竖对调 —— 和 .lab-phoneme / .lab-stop 同一套镜像规律。
   栅格轨道写成 minmax(0, 1fr) 而不是 1fr：不写 0 的话轨道的最小尺寸是
   min-content，像「考点」这种长词会把某一列顶宽，两张卡加起来撑破容器。 */
.lab-stops { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
/* 空结果那句话是 stopsHost 的直接子节点：不跨栏的话它只占左半边，
   右半边空着，看起来像卡没渲染出来。 */
.lab-stops > .lab-lead { grid-column: 1 / -1; margin: 0; }
.lab-stop {
  display: flex; flex-direction: column;
  padding: 12px 14px 14px;
  background: var(--paper-card);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 255px 16px 225px 16px / 16px 225px 16px 255px;
  box-shadow: 2px 3px 0 rgba(51, 48, 43, .07);
}
.lab-stop:nth-child(even) { border-radius: 16px 255px 16px 225px / 225px 16px 255px 16px; }
/* 已学的那张换个边色。整张卡铺 --action 的底色会盖掉纸色，一行两张时太吵。 */
.lab-stop[data-learned='true'] { border-color: var(--action); }
.lab-stop-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px; }
.lab-stop-index { font-family: var(--font-note); font-size: 18px; color: var(--ink-soft); }
.lab-stop-status {
  padding: 0 8px; font-size: 12px; font-family: var(--font-ui);
  border: var(--w-aux) solid var(--ink-faint); border-radius: 255px 8px 225px 8px / 8px 225px 8px 255px;
  color: var(--ink-soft);
}
.lab-stop-status[data-state='done'] { border-color: var(--action); color: var(--action); }
.lab-stop-title { margin: 0; font-size: 16px; font-family: var(--font-body); font-weight: 700; }
.lab-stop-desc { margin: 4px 0 0; font-size: 14px; }
.lab-stop-perf { margin: 2px 0 0; font-size: 13px; color: var(--ink-soft); }
/* margin-top:auto 把操作条压到卡片底部：同一行的两张卡是等高拉伸的，
   而描述长短不一，不用 auto 的话按钮会一高一低。 */
.lab-stop-actions {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 10px; margin-top: auto; padding-top: 8px;
}
.lab-stop-study, .lab-stop-practice { font-size: 14px; }
/* 这两条要带 .lab-main 前缀：正文链接的通用规则 `.lab-main a` 是 (0,1,1)，比单个
   类名 (0,1,0) 高，不加前缀的话「练习」那枚的赭色会被它按下去。 */
.lab-main .lab-stop-practice { color: var(--accent); }
.lab-stop-mark {
  padding: 3px 12px 4px; background: none; cursor: pointer;
  border: var(--w-note) solid var(--ink-faint); color: var(--ink);
  border-radius: 255px 12px 225px 12px / 12px 225px 12px 255px;
  font-family: var(--font-body); font-size: 13px;
}
.lab-stop-mark:hover { border-color: var(--accent); color: var(--accent); }
.lab-stop-mark[aria-pressed='true'] { border-color: var(--action); color: var(--action); }
/* 这一节的尾注：说的是整份清单（标记存在哪、怎么反悔），不归某一张卡，
   所以居中；下面一条虚线把这一节合上（衬于清单与概念图之间）。 */
.lab-learned-note { text-align: center; }
/* 尾注那条线在普通流里，但上邻是尾注、下邻是节边界，折叠出来的空档太松，
   自己带一档上边距（与地图收尾那条同值）。 */
.lab-station-detail > .lab-rule { margin: 14px 0 0; }

/* 概念这一节两张并排的手绘卡片：左卡选（抬头 + 三组概念按钮），右卡读
   （选中那个概念的正文）。两卡顶端对齐，左沿右沿就是正文的两沿。
   轨道写 minmax(0, 1fr)：不写 0 的话最小尺寸是 min-content，长按钮与那句
   21px 的例句会把两栏撑得不等宽。窄屏落回上下，见文件末的 990px。 */
.lab-concept-cols {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  column-gap: 28px; align-items: start;
}
/* 卡片本体：纸色底、手绘边框、右下投影，角半径照旧手抄 sketch.js 的 BOX_RADII
   （见文件头）。右边那张横竖对调 —— 两张并排时同一副角看着像复制粘贴。 */
.lab-concept-card {
  padding: 14px 18px 16px;
  background: var(--paper-card);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 255px 16px 225px 16px / 16px 225px 16px 255px;
  box-shadow: 2px 3px 0 rgba(51, 48, 43, .07);
}
.lab-concept-cols > .lab-concept-card:nth-child(even) {
  border-radius: 16px 255px 16px 225px / 225px 16px 255px 16px;
}
/* 卡片里的抬头：它现在是左卡的一行，不再是整节的标题；右边那颗「全部展开」
   与它同一行两端对齐（两者说的是同一件事：这张图怎么看）。 */
.lab-concept-card-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 12px; margin: 0 0 8px;
}
.lab-concept-card-head > h3 {
  font-family: var(--font-body); font-size: 17px; font-weight: 700; margin: 0;
}
.lab-flow-expand-all {
  flex: none; padding: 2px 12px 3px; background: none; cursor: pointer;
  border: var(--w-note) solid var(--ink-faint); color: var(--ink);
  border-radius: 255px 14px 225px 14px / 14px 225px 14px 255px;
  font-family: var(--font-body); font-size: 13px;
}
.lab-flow-expand-all:disabled { color: var(--ink-faint); cursor: default; opacity: .65; }

/* 三个分组开关。开着是实线框 + 组色，收起是虚线框 + 灰 —— 虚线在这套设计语言里
   本就表示「这里还有东西没展开」（地图上的待学、流程图上那条虚线都是这个意思）。 */
.lab-stage-controls { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 12px; }
.lab-stage-btn {
  padding: 3px 13px 4px; background: none; cursor: pointer;
  border: var(--w-note) solid var(--stage-color, var(--ink-faint));
  color: var(--stage-color, var(--ink));
  border-radius: 255px 14px 225px 14px / 14px 225px 14px 255px;
  font-family: var(--font-body); font-size: 14px;
}
.lab-stage-btn[aria-expanded='false'] {
  border-style: dashed; border-color: var(--ink-faint); color: var(--ink-soft);
}

/* 流程图是整块 SVG，宽度自适应（viewBox 见 languageMap.js 的 FLOW_W）。
   但**要有上限**：单栏时卡片会宽到 600px 上下，按宽度铺满会把节点标题放到 23px，
   比周围正文还大，整张图像在放大镜里看。上限一到，两栏时（≤380）照旧铺满，
   单栏时按 1:1 居中，字号与正文齐平。 */
.lab-flow-host svg { display: block; max-width: 380px; margin: 0 auto; }
.lab-flow-node { cursor: pointer; }
.lab-flow-node:focus { outline: none; }
/* CSS 声明压得住 SVG 的 presentation attribute（后者特异度是 0），所以节点色
   不用在 JS 里算第二遍；和站点卡片一套：选中或获得焦点就换底色、加粗描边。 */
.lab-flow-node[aria-pressed='true'] .lab-flow-box,
.lab-flow-node:focus .lab-flow-box { stroke-width: 2.6; fill: var(--marker); }

.lab-flow-legend {
  display: flex; flex-wrap: wrap; gap: 4px 18px;
  margin: 10px 0 6px; font-size: 13px; color: var(--ink-soft);
}
.lab-flow-legend p { display: flex; align-items: center; gap: 8px; margin: 0; }
.lab-flow-line {
  display: inline-block; width: 26px; height: 0;
  border-top: var(--w-aux) solid var(--ink-faint);
}
.lab-flow-line.is-dashed { border-top-style: dashed; }
.lab-flow-note { margin: 0; font-size: 13px; color: var(--ink-soft); }

.lab-concept-en { font-family: var(--font-note); font-size: 15px; color: var(--ink-soft); }

/* 概念详情。它和左卡那堆按钮是两件事（一个选、一个读），现在由两张卡片本身
   分开，不必再在正文左侧画一道竖线。
   第一行两头对齐：「现在在哪一组」靠左、「第几个 / 共几个」靠右（原站
   .elm-unit-heading 也是这么排的）。只剩一个数字时 margin-left:auto 把它顶到右边。 */
.lab-concept-heading {
  display: flex; align-items: baseline; gap: 12px; margin: 0 0 2px;
  font-family: var(--font-ui); font-size: 11px; letter-spacing: .1em;
  color: var(--ink-soft);
}
.lab-concept-count { margin-left: auto; }
.lab-concept-head { display: flex; align-items: baseline; gap: 10px; margin: 2px 0 6px; font-size: 19px; }
.lab-concept-explain { margin: 0 0 10px; font-size: 15px; }

/* 例子是**卡片里的一张卡片**：标签、例句、中文、发音按钮说的是同一件事
   （拿 book 看这个音），散在卡片正文里就分不清哪些字属于例子、哪些属于讲解。
   底色退一档用 --paper（卡片是 --paper-card），角半径横竖对调、尺寸收小，
   于是它读起来是卡片上挖出的一格，而不是又一张同样的卡片。 */
.lab-concept-example {
  margin: 0 0 10px; padding: 10px 12px 12px;
  background: var(--paper);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 225px 14px 255px 14px / 14px 255px 14px 225px;
  box-shadow: 2px 3px 0 rgba(51, 48, 43, .07);
}
.lab-concept-example > .lab-line-note { display: block; margin: 0 0 4px; }
.lab-concept-example .lab-line-example { margin: 0 0 2px; }
.lab-concept-example .lab-concept-audio { margin: 10px 0 0; }
.lab-line-example {
  margin: 0; font-family: var(--font-note); font-size: 21px; line-height: 1.35;
}
.lab-concept-audio { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin: 10px 0; }
/* 概念里的发音按钮：手绘胶囊 + 喇叭图标 + 文字（`听音素 /b/`、`听完整单词 book`），
   形状照原站的 .elm-audio-btn。base .lab-speak 是纯图标按钮（无边框无内边距），
   这里整套盖掉 —— 顺带按 flex 中线对齐，否则行高 1 的图标会把文字顶到第二行。
   .lab-speak-pill 是音标页（phonetics）那套胶囊，同一件东西，共用这份声明：
   两处都是「图标 + 可见文字」的宽按钮，样式分家的话它们会慢慢长得不一样。 */
.lab-concept-audio-pill,
.lab-speak-pill {
  display: inline-flex; align-items: center;
  padding: 2px 11px 3px; background: none; color: var(--ink);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 255px 14px 225px 14px / 14px 225px 14px 255px;
  font-family: var(--font-body); font-size: 14px; line-height: 1.4;
}
.lab-concept-audio-pill:hover,
.lab-speak-pill:hover { color: var(--accent); border-color: var(--accent); }
.lab-concept-audio-pill svg,
.lab-speak-pill svg { width: 15px; height: 15px; }
.lab-concept-audio-pill .lab-speak-label,
.lab-speak-pill .lab-speak-label { margin-left: 6px; font-size: 14px; }
/* 录音小字（原站 .elm-recording-note）：说的是这段录音在示范什么、该往哪儿听。
   「/k/：」这个前缀在文本里、不在样式里 —— 它和后面那句是一句话，拆开来
   样式就得管标点。压一级字号、退到 --ink-soft：它是正文的脚注，不是又一段讲解。 */
.lab-concept-recording-note {
  margin: 8px 0 0; font-size: 13px; line-height: 1.55; color: var(--ink-soft);
}

/* 音素录音来源与许可（原站 .elm-sources）。**默认折起来**：署名必须摆在页面里
   （CC BY-SA 3.0 的硬性要求），但没人指望读者每看一个概念就通读九行出处。
   summary 做成一条虚线小字，三角是默认的（.lab-sources summary 不设 display，
   设成 inline-block 会把 ::marker 一并抹掉，那正是「点得开」的唯一提示）。 */
.lab-sources { margin: 16px 0 0; font-size: 13px; color: var(--ink-soft); }
.lab-sources summary {
  width: fit-content; cursor: pointer; color: var(--ink-soft);
  border-bottom: var(--w-aux) dashed var(--ink-faint);
}
.lab-sources summary:hover { color: var(--accent); }
.lab-sources ul { margin: 8px 0 0; padding-left: 20px; }
.lab-sources li { margin: 2px 0; line-height: 1.6; }
.lab-sources a { color: var(--accent); }
/* 「这样记，更清楚」。原站是正文里一句加粗前缀（`这样记，更清楚：…`），这里拆成
   左侧带一道竖线的两块：小标题一行、口诀另起一行，两行左边缘对齐。
   它整张卡里只有这一句「怎么记」，混在正文里会被当成又一段讲解读过去 ——
   竖线和红色就是把它从讲解里拎出来的那一下（--alert 全站只有这里用）。 */
.lab-concept-remember {
  margin: 16px 0 14px; padding: 3px 0 3px 12px;
  border-left: 3px solid var(--alert);
}
.lab-concept-remember-head {
  margin: 0; font-family: var(--font-ui); font-size: 13px;
  font-weight: 700; letter-spacing: .04em; color: var(--alert);
}
.lab-concept-remember-body { margin: 3px 0 0; font-size: 14px; }
/* 两颗翻页键顶到卡片两边。gap 留着当最小间距 —— 窄屏上两颗挤到一起时
   它保证还看得出来是两颗按钮。 */
.lab-concept-nav { display: flex; justify-content: space-between; gap: 10px; margin-top: 14px; }
.lab-concept-step {
  padding: 3px 14px 4px; background: none; cursor: pointer;
  border: var(--w-note) solid var(--ink-faint); color: var(--ink);
  border-radius: 255px 14px 225px 14px / 14px 225px 14px 255px;
  font-family: var(--font-body); font-size: 14px;
}
.lab-concept-step:hover { border-color: var(--accent); color: var(--accent); }

/* 「先记住三个区别」是一张手绘卡片：小标题和三条口诀同住一张卡，三条横向铺开。
   三条要的正是「同时记住」，摞成三行就得上下扫。
   auto-fit + minmax 而不是写死三列：正文列宽从 339（375px 的机器）到 900 之间
   随便变，宽了三列、中间两列、窄了自动落回一列，不需要再配一个断点。 */
.lab-difference-card {
  padding: 14px 20px 16px;
  background: var(--paper-card);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 255px 16px 225px 16px / 16px 225px 16px 255px;
  box-shadow: 2px 3px 0 rgba(51, 48, 43, .07);
}
/* .lab-section > h3 是子选择器，标题挪进卡片后不再命中，这里补一份同样的字。 */
.lab-difference-card h3 {
  font-family: var(--font-body); font-size: 18px; font-weight: 700;
  margin: 0 0 12px; padding-bottom: 6px;
}
.lab-difference-row {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 20px 22px;
}
.lab-difference strong { font-size: 16px; }
.lab-difference p { margin: 2px 0 0; font-size: 14px; color: var(--ink-soft); }
.lab-map-cta { margin-top: 28px; }

/* ---------- 音标页（phonetics 数据集页） ---------- */
/* 这一页比别的数据集页厚得多：介绍区（三个标签页 + 字母↔声音对照图）、48 与 44
   的区别、带筛选的图谱、发音详情卡（录音 / 视频 / 口型 / 舌位动画 / 例词 / 例句）。
   色仍然只用三档：--ink 正文、--ink-soft 脚注、--accent 可点与「这一行是重点」。
   详情卡另有一个 --lab-sound-color（由 JS 按音标分组设上去），只给符号和左边那道
   竖线用 —— 一屏 48 个音标要认得出「这张卡是哪个组的」。 */

/* 48 与 44 的区别。原站把它摆在介绍区上面，是整页的定位说明。 */
.lab-inventory {
  margin: 0 0 22px; padding: 14px 18px 16px;
  background: var(--paper-card);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 255px 16px 225px 16px / 16px 225px 16px 255px;
}
.lab-inventory-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px; }
.lab-inventory-head h2 { margin: 0; font-family: var(--font-body); font-size: 19px; }
.lab-inventory-head > span {
  padding: 1px 9px 2px; border: var(--w-note) solid var(--ink-faint);
  border-radius: 255px 12px 225px 12px / 12px 225px 12px 255px;
  font-family: var(--font-ui); font-size: 12px; color: var(--ink-soft);
}
.lab-inventory-counts { display: flex; flex-wrap: wrap; gap: 6px 26px; margin: 12px 0 4px; }
.lab-inventory-counts p { margin: 0; font-size: 14px; color: var(--ink-soft); }
.lab-inventory-counts strong {
  font-family: var(--font-note); font-size: 22px; color: var(--ink); margin-right: 5px;
}
.lab-inventory > p { margin: 8px 0 0; font-size: 14px; line-height: 1.75; }
/* 卡片底部那句说明（原站叫 ep-inventory-footnote）。它是脚注，所以压一级字号、退到
   --ink-soft；但**左边缘和上面的段落对齐**，只在上面加一道虚线把它和折起来的对照表
   分开 —— 缩进或者居中的话，它看着就像另一块东西，而不是这张卡的最后一句话。
   选择器带上 p 是为了盖住上面那条 `.lab-inventory > p`（同权重时它在前、会赢）。 */
.lab-inventory p.lab-inventory-footnote {
  margin: 14px 0 0; padding-top: 10px;
  border-top: var(--w-aux) dashed var(--ink-faint);
  font-size: 13px; line-height: 1.75; color: var(--ink-soft);
}
/* 折起来的对照表。summary 不设 display —— 设成 flex/inline-block 会把默认三角
   一并抹掉，那个三角是「点得开」的唯一提示（同 .lab-sources 那条注释）。 */
.lab-inventory details { margin-top: 12px; font-size: 13px; }
.lab-inventory details > summary {
  width: fit-content; cursor: pointer; color: var(--ink-soft);
  border-bottom: var(--w-aux) dashed var(--ink-faint);
}
.lab-inventory details > summary:hover { color: var(--accent); }
/* 四张卡片**永远一行**，不换行。原来的 auto-fit + minmax(190px) 在 794px 的正文宽度里
   四列要 814px，撑不下就把第 4 张甩到第二行 —— 四张卡本来是一组对照，拆成 3+1
   之后最后一张看着像另一块东西。轨道的下限取 110px：够宽时 1fr 把四张拉平，挤不下
   时才溢出、靠横滑看全（挤到 60px 一列的话中文会一字一行，比横滑难看得多）。
   外面那层壳只有一个作用：**把四列的 494px 最小宽度跟正文隔开**。正文那一列是
   .lab-layout 的 grid item，而 grid item 的 min-width 默认是 auto = 内容的
   min-content —— 四列一行的 min-content 是 494px，窄屏上会一路把整页顶出横向滚动条
   （375px 实测整页 568px）。壳是单列 minmax(0, 1fr) 的 grid，min-content 归 0；
   里面的四列虽然自己 overflow-x: auto，但**块**的最小宽度照样由内容决定，只有它是
   grid item 时（overflow 非 visible → min-width: auto 取 0）才会缩到壳宽、把多的横滑掉。 */
.lab-cluster-scroll { display: grid; grid-template-columns: minmax(0, 1fr); }
.lab-cluster-cards {
  display: grid; grid-template-columns: repeat(4, minmax(110px, 1fr));
  gap: 14px 18px; margin-top: 14px;
  overflow-x: auto;
}
/* 四张卡在 grid 里是等高的，但四条提示的长短不一样 —— 一列排下来、把发音按钮
   用 margin-top: auto 压到底，四颗按钮才会对齐在同一条线上，扫一眼就能挨个点。 */
.lab-cluster-cards article {
  display: flex; flex-direction: column;
  padding: 10px 13px 12px; border: var(--w-note) solid var(--ink-faint);
  border-radius: 255px 14px 225px 14px / 14px 225px 14px 255px;
}
.lab-cluster-cards article:nth-child(even) { border-radius: 14px 255px 14px 225px / 225px 14px 255px 14px; }
.lab-cluster-cards h3 { margin: 0; font-family: var(--font-note); font-size: 22px; font-weight: 400; }
.lab-cluster-cards p { margin: 4px 0 0; font-size: 13px; line-height: 1.7; color: var(--ink-soft); }
/* 卡片底部那条发音按钮（原站的 es-actions）。撑满卡片、居中：窄屏一列只有 110px，
   「听 dream」放不下会折成两行（图标和「听」在上、单词在下），撑满居中就不会折。
   宽屏下四张卡也由此各自收一条等宽的按钮，比缩在左下角好点。 */
.lab-cluster-actions { margin-top: auto; padding-top: 10px; }
.lab-cluster-actions .lab-speak-pill { width: 100%; justify-content: center; }
/* 不许在「听」和单词之间断开：110px 是这四列的硬下限（见上面的轨道下限），
   图标 +「听 dream」在这个宽度里放得下，「听 / dream」分两行才是不该有的换行。 */
.lab-cluster-actions .lab-speak-label { white-space: nowrap; }

/* 介绍区。整块默认展开（原站也是）；「收起介绍，开始练习」合上它并把焦点送到
   图谱第一个格子上 —— 那句话承诺的是「开始练习」，焦点留在原地等于什么也没发生。 */
.lab-intro {
  margin: 0 0 26px; padding: 12px 18px 14px;
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 225px 16px 255px 16px / 16px 255px 16px 225px;
}
.lab-intro-summary { cursor: pointer; font-family: var(--font-body); }
.lab-intro-summary strong { font-size: 17px; }
.lab-intro-summary:hover { color: var(--accent); }
.lab-intro-sub { margin-left: 10px; font-size: 13px; color: var(--ink-soft); }
.lab-intro-body { margin-top: 12px; }

/* 三个标签页。按钮上那个 01/02/03 是 Caveat 的手写数字，字号比中文大一号才不显小。 */
.lab-intro-tabs { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 14px; }
.lab-intro-tabs button {
  padding: 3px 14px 4px; background: none; cursor: pointer; color: var(--ink);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 255px 14px 225px 14px / 14px 225px 14px 255px;
  font-family: var(--font-body); font-size: 14px;
}
.lab-intro-tabs button span:first-child {
  margin-right: 6px; font-family: var(--font-note); font-size: 15px; color: var(--ink-soft);
}
.lab-intro-tabs button[aria-selected='true'] {
  border-color: var(--accent); background: var(--marker); color: var(--accent);
}
.lab-intro-tabs button[aria-selected='true'] span:first-child { color: var(--accent); }

/* 面板本身可聚焦（tabindex="0"），所以只给 outline-offset，别再加框 ——
   它整块就是一个 tabpanel，再加一层描边会和里面的卡片打架。 */
.lab-intro-panel { outline-offset: 4px; }

/* 「什么是音标」那一页分成左右两栏（原站的 ep-intro-definition）：左边讲解、
   右边例词卡。原站用的是 1fr 1fr + 24px 间隔、align-items: start ——
   两栏不等高，右边那张卡不跟着左边拉长。
   正文宽 = 视口 − 486（右侧 262 的菜单 + 内边距），每半 < 348px 时例词卡里那张
   三格图就开始挤，所以正文 < 720px（视口 < 1206）时落回上下。 */
.lab-intro-definition {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 24px; align-items: start;
}
.lab-intro-copy { min-width: 0; }
.lab-intro-kicker {
  margin: 0 0 2px; font-family: var(--font-ui); font-size: 12px;
  letter-spacing: .06em; color: var(--ink-soft);
}
.lab-intro-h2 { margin: 0 0 8px; font-family: var(--font-body); font-size: 21px; }
.lab-intro-lead { margin: 0 0 8px; font-size: 15px; }
/* 段落自己带类名，而不是靠 .lab-intro-panel p 这种后代选择器去够：面板里还有
   例词行、标记卡这些同样是 <p> 的东西，后代选择器会把它们一起改掉。 */
.lab-intro-p { margin: 0 0 10px; font-size: 15px; line-height: 1.85; }
.lab-intro-p strong { font-weight: 700; }
/* 「例如：字母 j……」那句。原站是一条重点提示（ep-intro-callout：浅色底 +
   左侧一道实线 + 圆角），不是脚注 —— 它举的是整段讲解里唯一的反例，
   压成灰色小字缩在左边就没人当回事。 */
.lab-intro-note {
  margin: 0; padding: 11px 14px 12px; font-size: 13px; line-height: 1.85; color: var(--ink);
  background: var(--paper-card); border-left: 3px solid var(--accent);
  border-radius: 0 255px 0 14px / 0 14px 0 255px;
}
/* 「那为什么还要学」那一段在原站是一块带竖线的重点卡，不是脚注 —— 用 --alert
   那道红（全站只有「这样记，更清楚」和这里用），把它从讲解里拎出来。 */
.lab-intro-aside {
  margin: 18px 0 0; padding: 12px 16px 14px;
  background: var(--paper-card); border-left: 3px solid var(--alert);
  border-radius: 0 255px 0 18px / 0 18px 0 255px;
}
.lab-intro-aside h3 { margin: 0 0 6px; font-family: var(--font-body); font-size: 16px; }
.lab-intro-aside p { margin: 0; font-size: 14px; line-height: 1.8; }
.lab-intro-subtitle {
  margin: 22px 0 12px; padding-bottom: 5px; font-family: var(--font-body);
  font-size: 17px; font-weight: 700; border-bottom: var(--w-aux) dashed var(--ink-faint);
}
.lab-intro-bottom {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 10px; margin-top: 20px; padding-top: 12px;
  border-top: var(--w-aux) dashed var(--ink-faint);
  font-size: 13px; color: var(--ink-soft);
}
.lab-start {
  padding: 4px 16px 5px; background: none; cursor: pointer; color: var(--ink);
  border: var(--w-note) solid var(--ink);
  border-radius: 255px 14px 225px 14px / 14px 225px 14px 255px;
  font-family: var(--font-body); font-size: 14px;
}
.lab-start:hover { border-color: var(--accent); color: var(--accent); }

/* 字母 ↔ 声音的对照图。三张 svg 共用一套：上排字母格、一支下箭头、下排声音格。
   两个 fill 走类名而不是属性 —— 属性没法跟着主题走（sketch.js 的 S.el 只认属性）。
   整块是一张卡（原站的 ep-intro-spelling：16px 内边距 + 描边 + 圆角 + 浅底），
   因为它和左边的讲解是两件事：左边讲「音标是什么」，右边当场演示一个词。
   min-width: 0 是给 grid 用的 —— 轨道是 1fr，不写的话图会把轨道撑宽。 */
.lab-spelling {
  min-width: 0; margin: 0; padding: 14px 16px 16px;
  background: var(--paper-card); border: var(--w-note) solid var(--ink-faint);
  border-radius: 225px 14px 255px 14px / 14px 255px 14px 225px;
}
.lab-spelling-picker { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; }
.lab-spelling-picker button {
  padding: 2px 13px 3px; background: none; cursor: pointer; color: var(--ink);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 255px 12px 225px 12px / 12px 225px 12px 255px;
  font-family: var(--font-note); font-size: 17px;
}
.lab-spelling-picker button[aria-pressed='true'] {
  border-color: var(--accent); background: var(--marker); color: var(--accent);
}
.lab-map-label { margin: 12px 0 4px; font-family: var(--font-ui); font-size: 13px; color: var(--ink-soft); }
.lab-spelling-map svg { display: block; width: 100%; height: auto; }
.lab-spelling-letter-bg { fill: var(--paper-card); stroke: var(--ink-faint); stroke-width: 1.5; }
.lab-spelling-sound-bg { fill: var(--paper); stroke: var(--ink-faint); stroke-width: 1.5; }
.lab-spelling-count { margin: 8px 0 0; font-family: var(--font-note); font-size: 19px; }
.lab-spelling-explain { margin: 2px 0 0; font-size: 13px; line-height: 1.7; color: var(--ink-soft); }

/* 三个理由那一列。 */
.lab-reasons {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 18px 22px;
}
/* 词典里的三个小标记：一条符号 + 一个例词 + 一句解释，三条之间没有先后，是并列的
   三个知识点 —— 各装一张卡片，边界一眼看得出来，扫读时不至于串行。
   和 .lab-difference-card 同一副纸色底、手绘边、右下投影。
   轨道写死三列而不是 auto-fit：三件东西只会在 3 列与 2 列之间跳，跳到 2 列时
   第三张孤零零占半行，比窄一点更难看；落回单列的收起点在文件末的窄屏一节。 */
.lab-intro-marks {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px 18px;
}
.lab-intro-marks article {
  padding: 13px 16px 15px;
  background: var(--paper-card);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 255px 16px 225px 16px / 16px 225px 16px 255px;
  box-shadow: 2px 3px 0 rgba(51, 48, 43, .07);
}
/* 三张并排时同一副角看着像复制粘贴，中间那张横竖对调（同 .lab-concept-cols 的做法）。 */
.lab-intro-marks article:nth-child(even) {
  border-radius: 16px 255px 16px 225px / 225px 16px 255px 16px;
}
.lab-intro-mark {
  display: block; font-family: var(--font-note); font-size: 26px; line-height: 1.15;
  color: var(--accent);
}
.lab-intro-marks h4 { margin: 4px 0 6px; font-family: var(--font-body); font-size: 15px; }
.lab-intro-marks p { margin: 0 0 4px; font-size: 13px; line-height: 1.75; color: var(--ink-soft); }
.lab-intro-marks .lab-example-ipa { color: var(--ink); }
.lab-reasons article { position: relative; padding: 10px 0 0 42px; }
.lab-reason-number {
  position: absolute; left: 0; top: 2px;
  font-family: var(--font-note); font-size: 30px; line-height: 1; color: var(--ink-faint);
}
.lab-reasons h3 { margin: 0 0 6px; font-family: var(--font-body); font-size: 17px; }
.lab-reasons p { margin: 0 0 8px; font-size: 14px; line-height: 1.8; }
/* 「记住这一条」那一行。红竖线是它的记号，理由同上（--alert 全站两处）。 */
.lab-reasons .lab-takeaway,
.lab-mnemonic-body .lab-takeaway {
  margin: 8px 0 0; padding-left: 10px; font-size: 13px; color: var(--accent);
  border-left: var(--w-aux) solid var(--accent);
}

/* 口诀：每条一个 <details>。默认只开第一条（原站如此）—— 六条全开的话，
   这一页的正文会长到没人往下滚。 */
.lab-mnemonics { display: grid; gap: 8px; }
.lab-mnemonics details { padding-left: 12px; border-left: var(--w-aux) dashed var(--ink-faint); }
.lab-mnemonics summary { cursor: pointer; font-family: var(--font-body); }
.lab-mnemonics summary strong { margin-right: 8px; font-size: 15px; }
.lab-mnemonics summary span { font-family: var(--font-note); font-size: 16px; color: var(--ink-soft); }
.lab-mnemonic-body { padding: 8px 0 4px; }
.lab-mnemonic-body p { margin: 0 0 6px; font-size: 14px; line-height: 1.8; }

.lab-steps { margin: 0; padding-left: 20px; }
.lab-steps li { margin-bottom: 8px; font-size: 14px; line-height: 1.8; }
.lab-steps strong { margin-right: 6px; font-weight: 700; }
.lab-steps span { color: var(--ink-soft); }

/* 图谱 | 发音卡两栏。比例 1.05 : 1 与原站 .ep-workspace 一致；align-items: start
   是 sticky 的前提 —— 默认的 stretch 会把图谱撑成一整栏高，没有可滚的余量。

   图谱钉在视口上（下面 .lab-board 的 sticky）：右边那张卡比图谱长得多，不钉的话
   选完一个音往下读例词、例句的时候，就看得到发音却看不到自己选的是哪一个了。
   滚到两栏底部时图谱自动跟上来（sticky 不许它越出自己的容器），于是两栏一边齐收尾。
   sticky 的 top 取 20px：这一页顶上是普通页头，没有别的吸顶元素要躲。 */
.lab-workspace {
  display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  align-items: start; gap: 22px; margin: 0 0 26px;
}

/* 图谱。原站是 SVG 图表，我们是 HTML 栅格（理由见 phoneme.js 的 board 注释）；
   格子的外观沿用早就上线的 .lab-phoneme，这里补足卡片、筛选条与分组标题。

   整块是一张卡（原站的 .ep-board 也是）：筛选条、提示行、格子同住一张纸。
   这一页别的块（48 与 44、音标入门、发音卡）都是卡，只有图谱原先散在正文上，
   三样东西看着像三段不相干的正文，不像「一块可以点的图」。 */
.lab-board {
  position: sticky; top: 20px;
  padding: 16px 18px 18px;
  background: var(--paper-card);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 225px 16px 255px 16px / 16px 255px 16px 225px;
}
/* 筛选按钮比站内其它筛选条（.lab-concept-step 那些）高一档、方一档：原站的这四个
   是 40px 高、接近直角的方按钮，是这块面板的「开关」，不是正文里的一行小标签。
   半径只留 5–16px —— 沿用 255px 那套的话，四个按钮在这个高度上会胖成一排球。 */
.lab-phoneme-filters { display: flex; flex-wrap: wrap; gap: 7px; }
.lab-phoneme-filters button {
  min-height: 40px; padding: 7px 14px; background: var(--paper); cursor: pointer; color: var(--ink);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 16px 5px 14px 5px / 5px 14px 5px 16px;
  font-family: var(--font-body); font-size: 14px;
}
.lab-phoneme-filters button:nth-child(even) { border-radius: 5px 16px 5px 14px / 14px 5px 16px 5px; }
.lab-phoneme-filters button:hover { border-color: var(--accent); color: var(--accent); }
.lab-phoneme-filters button[aria-pressed='true'] {
  border-color: var(--accent); background: var(--marker); color: var(--accent);
}
.lab-phoneme-hint { margin: 14px 0 10px; font-family: var(--font-ui); font-size: 12px; color: var(--ink-soft); }
.lab-sound-group { margin-bottom: 16px; }
.lab-sound-group-label {
  margin: 0 0 8px; font-family: var(--font-body); font-size: 15px; font-weight: 700;
}
/* 选中态：描边色由 JS 按分组设上去（inline style），这里只管底色与那颗投影 ——
   48 个格子铺开时，只换描边色不够看出「选中的是这一个」。
   底色用 --marker（全站「按下去了」都是这一层棕），比格子的纸色深浅差得开。 */
.lab-phoneme[aria-pressed='true'] {
  background: var(--marker); box-shadow: 2px 3px 0 rgba(51, 48, 43, .07);
}

/* 发音详情卡。左边那道竖线用分组的颜色，是这一屏唯一的「我现在在哪个组」的线索。 */
.lab-study {
  padding: 18px 20px 22px;
  background: var(--paper-card);
  border: var(--w-note) solid var(--ink-faint);
  border-left: 4px solid var(--lab-sound-color, var(--ink-faint));
  border-radius: 225px 16px 255px 16px / 16px 255px 16px 225px;
}
.lab-study-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 14px; }
.lab-study-symbol {
  font-family: var(--font-note); font-size: 52px; line-height: 1;
  color: var(--lab-sound-color, var(--ink));
}
.lab-study-group { font-family: var(--font-body); font-size: 16px; font-weight: 700; }
.lab-study-voicing { margin: 2px 0 0; font-size: 13px; color: var(--ink-soft); }
.lab-recording-note { margin: 8px 0 0; font-size: 13px; line-height: 1.65; color: var(--ink-soft); }
/* 视频：内嵌的 B 站播放器 + 底下一行标题（原站同款，原站是 16/9 的 iframe）。
   这是全站唯一一处第三方嵌入，理由与取舍写在 phoneme.js 的 paintStudy 里。
   没有视频的音素整块 hidden —— 但 .lab-video 不能设 display，否则作者样式会盖掉
   UA 的 [hidden]{display:none}（同权重下作者表赢），空框就露出来了。
   iframe 按宽度撑满、高度走 aspect-ratio：写死高度的 iframe 在窄屏上会露出黑边。 */
.lab-video { margin: 10px 0 0; font-size: 13px; }
.lab-video-frame {
  display: block; width: 100%; aspect-ratio: 16 / 9; height: auto;
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 225px 14px 255px 14px / 14px 255px 14px 225px;
  background: var(--ink);
}
.lab-video-caption { margin: 6px 0 0; font-size: 13px; color: var(--ink-soft); }
.lab-video-title { margin-right: 8px; }
.lab-video a { color: var(--accent); }
.lab-study-mouth { margin: 14px 0 0; font-size: 14px; line-height: 1.75; color: var(--ink-soft); }
.lab-study .lab-diagram { margin: 10px 0 0; }
.lab-study .lab-diagram svg { max-width: 100%; height: auto; }
.lab-animation { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 16px; margin: 14px 0 0; }
.lab-animation-btn {
  padding: 4px 14px 5px; background: none; cursor: pointer; color: var(--ink);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 255px 14px 225px 14px / 14px 225px 14px 255px;
  font-family: var(--font-body); font-size: 14px;
}
.lab-animation-btn:hover { border-color: var(--accent); color: var(--accent); }
.lab-animation-btn[aria-pressed='true'] { border-color: var(--accent); color: var(--accent); }
.lab-animation label {
  display: flex; flex: 1 1 180px; align-items: center; gap: 8px;
  font-size: 13px; color: var(--ink-soft);
}
.lab-animation input[type='range'] { flex: 1; min-width: 90px; accent-color: var(--accent); }
.lab-study-tip {
  margin: 16px 0 0; padding-left: 12px; font-size: 14px; line-height: 1.8;
  border-left: var(--w-aux) dashed var(--ink-faint);
}
.lab-study-title {
  margin: 26px 0 10px; padding-bottom: 5px; font-family: var(--font-body);
  font-size: 17px; font-weight: 700; border-bottom: var(--w-aux) dashed var(--ink-faint);
}

/* 例词 / 例句行：`word /ipa/ · 中文` + 一颗发音胶囊，压成一行。
   30 个例词各占三行的话，这一节会长得没法扫。 */
.lab-example-row { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin: 8px 0 0; }
.lab-example-line { margin: 0; font-size: 15px; }
.lab-example-ipa { font-family: var(--font-note); font-size: 15px; color: var(--ink-soft); }
.lab-example-cn { font-size: 13px; color: var(--ink-soft); }
.lab-example-audio { display: inline-flex; align-items: center; }
.lab-examples { margin: 10px 0 0; }
.lab-examples .lab-example-row { margin: 0 0 4px; }
/* 「放进单词，跟着读」：一个例词一张卡，每行两张（原站 .ep-words 也是两列 + .ep-word）。
   一列一条摊开时，30 个例词是 30 条长短不一的横杠，扫不出这一节收了几个词；
   两张一行时词形对齐成一列，一眼数得过来。
   始终两列、不落回一列：卡片里只有「词 + 音标 + 一颗按钮」三样，窄到 143px（375 屏）
   也放得下，而落成一列会让这一节长到十倍。 */
.lab-words {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px; margin-top: 4px;
}
.lab-word {
  min-width: 0; padding: 11px 14px 13px;
  background: var(--paper-card);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 255px 14px 225px 14px / 14px 225px 14px 255px;
}
/* 相邻两张卡横竖对调，和 .lab-phoneme / .lab-concept-cols 同一套镜像规律。 */
.lab-word:nth-child(even) { border-radius: 14px 255px 14px 225px / 225px 14px 255px 14px; }
/* 词形与中文同一行、基线对齐；中文小一号、浅一档，它是注，不是第二个词。 */
.lab-word-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 3px 8px; }
.lab-word-head strong { font-family: var(--font-note); font-size: 21px; font-weight: 400; }
.lab-word-meaning { font-size: 13px; color: var(--ink-soft); }
.lab-word-ipa { margin: 2px 0 9px; font-family: var(--font-note); font-size: 16px; color: var(--ink-soft); }
.lab-words-toggle {
  margin: 12px 0 0; padding: 2px 13px 3px; background: none; cursor: pointer; color: var(--accent);
  border: var(--w-note) dashed var(--ink-faint);
  border-radius: 255px 12px 225px 12px / 12px 225px 12px 255px;
  font-family: var(--font-body); font-size: 13px;
}
.lab-words-toggle:hover { border-color: var(--accent); }
/* 同 .lab-video：不设 display，让 [hidden] 还能压住它（只有 4 个例词时整行不出现）。 */

.lab-sentences { display: grid; gap: 12px; }
.lab-sentence {
  padding: 12px 16px 14px; border: var(--w-note) solid var(--ink-faint);
  border-radius: 255px 14px 225px 14px / 14px 225px 14px 255px;
}
.lab-sentence:nth-child(even) { border-radius: 14px 255px 14px 225px / 225px 14px 255px 14px; }
.lab-sentence-text { margin: 0; font-family: var(--font-note); font-size: 20px; line-height: 1.5; }
/* 这句话里要练的那个音落在哪几个词上。下划线走 --marker（半透明的棕），
   字色走 --accent —— 只有一种处理的话，长句里扫不到那几个词。 */
.lab-sentence-text .is-target-word {
  color: var(--accent); border-bottom: var(--w-main) solid var(--marker);
}
.lab-sentence-cn { margin: 8px 0 0; font-size: 13px; color: var(--ink-soft); }

/* ---------- 键盘焦点 ---------- */
/* 图解（Task 14）要走键盘，默认 outline 在纸色上太淡，几乎看不出焦点在哪 */
.lab-menu-link:focus-visible,
.lab-menu-toggle:focus-visible,
.lab-chunk:focus-visible,
.lab-explorer-group:focus-visible,
.lab-choice:focus-visible,
.lab-fill-input:focus-visible,
.lab-check:focus-visible,
.lab-diagram:focus-visible,
.lab-speak:focus-visible,
.lab-stop-filter:focus-visible,
.lab-stop-mark:focus-visible,
.lab-stage-btn:focus-visible,
.lab-flow-expand-all:focus-visible,
.lab-concept-step:focus-visible,
.lab-set-actions button:focus-visible,
.lab-phoneme:focus-visible,
.lab-phoneme-filters button:focus-visible,
.lab-spelling-picker button:focus-visible,
.lab-intro-tabs button:focus-visible,
.lab-intro-panel:focus-visible,
.lab-intro-summary:focus-visible,
.lab-inventory details > summary:focus-visible,
.lab-start:focus-visible,
.lab-prosody-toggle:focus-visible,
.lab-words-toggle:focus-visible,
.lab-review-tab:focus-visible,
.lab-review-swap:focus-visible,
.lab-animation-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ---------- 动效：线「长出来」 ---------- */
/* 只给「整条线从头画到尾」用。两个坑：
   1) --len 必须由 JS 设成不小于路径实长的值，设小了尾段会永远留在 dash 的
      间隙里（prefers-reduced-motion 分支同理，它把 dashoffset 归零但 dasharray
      还在）；
   2) 这条规则会盖掉 sketch.path() 写进去的 stroke-dasharray **属性** —— CSS
      属性恒定胜过 SVG presentation attribute（后者的特异度是 0）。所以同一条
      线不要既传 opts.dash 又挂 .lab-draw，虚线会静默变成实线的动画。 */
.lab-draw { stroke-dasharray: var(--len, 400); stroke-dashoffset: var(--len, 400); animation: lab-draw 1s ease-out forwards; }
@keyframes lab-draw { to { stroke-dashoffset: 0; } }
@media (prefers-reduced-motion: reduce) { .lab-draw { animation: none; stroke-dashoffset: 0; } }

/* ---------- 26 个字母的名称与音标对照（phonetics-alphabet 的 activity） ---------- */
/* 整块是一张**卡**，不是通栏的正文：原站的 .ecs-activity 就是描边 + 圆角 + 浅底的
   面板（padding clamp(16px,3vw,28px)，radius 16px），因为它和上下两节讲解是两件事 ——
   上面讲字母名与音素的区别，这里当场把 26 个字母一个一个点开听。
   面板的 padding 取 20px 的定值而不是原站那个 clamp：这一页的正文宽实测在
   374–832 之间走，clamp 到中段就只会在 16/20px 之间来回跳，看不到差别。 */
.lab-alphabet {
  padding: 18px 20px 20px;
  background: var(--paper-card);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 225px 16px 255px 16px / 16px 255px 16px 225px;
  box-shadow: 2px 3px 0 rgba(51, 48, 43, .07);
}
.lab-alphabet > h2 {
  margin: 0 0 10px; font-family: var(--font-body); font-size: 20px; font-weight: 700;
}
.lab-letter-lead { margin: 0; font-size: 13px; line-height: 1.8; color: var(--ink-soft); }

/* 26 个字母按钮。它们是**一个**选择器，不是 26 件独立的事 —— 所以按钮小、密、
   排成一片（原站也是 flex-wrap 的一排小按钮，不上网格），并且整块只占一个 Tab
   停靠点（roving tabindex，见 alphabet.js 的注释）。
   半径走全站那套手绘圆角，但幅度收敛到 5–16px：26 颗按钮在这个高度上，
   255px 那档会胖成一排球（和 .lab-phoneme-filters 同一条理由）。 */
.lab-letter-tabs { display: flex; flex-wrap: wrap; gap: 6px; margin: 14px 0 16px; }
.lab-letter-tabs button {
  min-width: 48px; padding: 4px 10px 5px; background: var(--paper); cursor: pointer;
  color: var(--ink); border: var(--w-note) solid var(--ink-faint);
  border-radius: 14px 5px 13px 5px / 5px 13px 5px 14px;
  font-family: var(--font-note); font-size: 19px; line-height: 1.3;
}
.lab-letter-tabs button:nth-child(even) { border-radius: 5px 14px 5px 13px / 13px 5px 14px 5px; }
.lab-letter-tabs button:hover { border-color: var(--accent); color: var(--accent); }
.lab-letter-tabs button[aria-pressed='true'] {
  border-color: var(--accent); background: var(--marker); color: var(--accent);
}

/* 三张卡：字母 / 名称 / 例词中的声音。auto-fit 而不是写死三列 —— 只有三件东西，
   auto-fit 最多也就出三条轨道，窄到 172px 以下自己落成两列、一列，
   不必再为它单开一个断点（和 .lab-reasons 同一条路子）。 */
.lab-letter-cards {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(172px, 1fr)); gap: 12px;
}
.lab-letter-card {
  min-width: 0; padding: 12px 14px 14px;
  background: var(--paper); border: var(--w-note) solid var(--ink-faint);
  border-radius: 16px 5px 14px 5px / 5px 14px 5px 16px;
}
.lab-letter-card small {
  display: block; font-family: var(--font-ui); font-size: 12px; color: var(--ink-soft);
}
.lab-letter-card h3 { margin: 6px 0 0; font-family: var(--font-note); font-size: 24px; font-weight: 400; }

/* 整句英文。原站用 Georgia 23px —— 这一行是**给人读的整句**，不是标签，
   所以给足字号、单独一行，和上面三张卡拉开。手写体（Caveat）在 27px 上
   比正文楷体更像「黑板上的范例」，和这块的调子一致。 */
.lab-letter-english {
  margin: 16px 0 10px; font-family: var(--font-note); font-size: 27px; line-height: 1.3;
  color: var(--ink);
}

/* 逐字母的备注。做成一条浅底提示条（原站 .ecs-note 也是左边一道竖线的浅底块）：
   它讲的是「这个字母为什么是这样」，比正文低一级、但比卡片的说明更该被看到。
   竖线用 --action 而不是原站那支绿：全站「正在讲的一件事」就是这个色。 */
.lab-letter-note {
  margin: 0; padding: 9px 14px; font-size: 13px; line-height: 1.8;
  color: var(--ink); background: var(--paper);
  border-left: 4px solid var(--action); border-radius: 0 10px 10px 0;
}
.lab-letter-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 12px 0 0; }

/* 26 行的对照表。表头吸顶 + 整表限高（原站 .ecx-reference 是 480px，窄屏 380px）：
   这张表的用处是**横向比对**，26 行一次铺开会把下面所有内容顶出首屏，
   而缩到 380px 时正好能一眼看到 10 行上下、又能滚。
   滚动与限高落在**外层 div** 上，不落在 <table> 自己身上：给 table 挂
   display:block 是常见写法但它会把 table 拆成匿名表格，thead 与 tbody 各算一套
   列宽，表头就和正文错位了（错位的是「英式名称」那一列，看着像数据串行）。
   表格是全站第一处，样式从零写：走手绘那套虚线下边框（和 .lab-line 一致），
   不画满格线 —— 满格 78 条线会把这张表画成一块棋盘。 */
.lab-letter-table-wrap { margin-top: 16px; max-height: 380px; overflow: auto; overscroll-behavior: contain; }
.lab-letter-table { width: 100%; border-collapse: collapse; }
.lab-letter-table thead { position: sticky; top: 0; background: var(--paper-card); z-index: 1; }
.lab-letter-table th {
  text-align: left; padding: 6px 10px 7px; white-space: nowrap;
  font-family: var(--font-body); font-size: 13px; font-weight: 700;
  border-bottom: var(--w-note) solid var(--ink-faint);
}
.lab-letter-table td {
  padding: 5px 10px; font-size: 14px; overflow-wrap: anywhere;
  border-bottom: 1px dashed var(--ink-faint);
}
/* 第一列是字母本身，用逐字母那颗按钮的字体 —— 表里找字母时，眼睛是顺着
   「A a / B b …」那列的手写字形往下扫的。 */
.lab-letter-table td:first-child { font-family: var(--font-note); font-size: 18px; }
.lab-letter-table tr:last-child td { border-bottom: none; }

/* ---------- 字母组合 ↔ 音标弦图（phonetics-spelling） ---------- */
/* 这一节是「一个拼写通向好几个声音」，所以主视图是左边一个源、右边一排读音。
   弦图本身是 SVG（几何在 spelling.js 里算），这里只管配色与容器。 */
.lab-chord > h2 {
  margin: 0 0 10px; font-family: var(--font-body); font-size: 20px; font-weight: 700;
}
.lab-chord-lead { margin: 0 0 14px; font-size: 13px; line-height: 1.8; color: var(--ink-soft); }

/* 两个下拉并排。窄屏折行即可 —— 它们没有先后，谁在上面都不影响读法。 */
.lab-chord-toolbar { display: flex; flex-wrap: wrap; gap: 10px 18px; margin: 0 0 8px; }
.lab-chord-toolbar label {
  display: flex; align-items: center; gap: 8px;
  font-family: var(--font-ui); font-size: 13px; color: var(--ink-soft);
}
.lab-chord-toolbar select {
  padding: 4px 8px 5px; background: var(--paper-card); color: var(--ink);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 14px 5px 13px 5px / 5px 13px 5px 14px;
  font-family: var(--font-body); font-size: 14px;
}
/* 弦图的容器要跟着正文宽度走，所以不许缩：窄屏时它靠 JS 重画（见 spelling.js
   的 ResizeObserver），CSS 这边只负责把 svg 的基线间隙消掉。 */
.lab-chord-stage { min-width: 0; margin: 6px 0 4px; }
.lab-chord-stage svg { display: block; width: 100%; height: auto; }

/* 飘带与盒子。两个 fill 走类名而不是 SVG 属性 —— 属性没法跟着主题走
   （和 .lab-spelling-letter-bg 同一条理由）。飘带用标记笔那支淡棕：
   它讲的是「这两头是同一件事」，比正文低一级，压不住右边的盒子。 */
.lab-chord-ribbon { fill: var(--marker); stroke: var(--accent); stroke-width: 1.2; }
.lab-chord-box { fill: var(--paper-card); stroke: var(--ink-faint); stroke-width: 1.5; }

/* 读音卡。一条对应关系一张 —— auto-fit 而不是写死列数：命中一条时只有一张卡，
   写死三列会让它孤零零缩在左三分之一。 */
.lab-chord-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 12px; margin: 14px 0 0;
}
.lab-chord-card {
  min-width: 0; padding: 12px 14px 14px;
  background: var(--paper-card); border: var(--w-note) solid var(--ink-faint);
  border-radius: 225px 14px 255px 14px / 14px 255px 14px 225px;
}
.lab-chord-card:nth-child(even) {
  border-radius: 14px 225px 14px 255px / 255px 14px 225px 14px;
}
.lab-chord-card h3 {
  margin: 0; font-family: var(--font-note); font-size: 22px; font-weight: 400;
}
.lab-chord-card p { margin: 6px 0 0; font-size: 14px; line-height: 1.8; color: var(--ink); }
.lab-chord-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 10px 0 0; }

/* 全部例词那一行。和字母页的整句英文同一档：它是**给人读的**英文，
   不是标签，所以给足字号、单独一行。 */
.lab-chord-english {
  margin: 16px 0 10px; font-family: var(--font-note); font-size: 27px; line-height: 1.3;
  color: var(--ink);
}
/* 小结条。和 .lab-letter-note 同一副样子：左边一道竖线的浅底块，
   讲的是「这堆线是什么意思」，比正文低一级但比卡片说明更该被看到。 */
.lab-chord-note {
  margin: 0; padding: 9px 14px; font-size: 13px; line-height: 1.8;
  color: var(--ink); background: var(--paper);
  border-left: 4px solid var(--action); border-radius: 0 10px 10px 0;
}

/* 完整索引。173 行默认收在 details 里 —— 它是查得到的兜底，不是主视图，
   铺开会把上面那三段（弦图 / 卡片 / 例句）全顶出首屏。 */
.lab-chord-index { margin: 14px 0 0; }
.lab-chord-index > summary {
  cursor: pointer; font-family: var(--font-ui); font-size: 14px; color: var(--accent);
}
.lab-chord-index > summary:hover { text-decoration: underline; }
.lab-chord-search {
  display: flex; align-items: center; gap: 8px; margin: 10px 0 0;
  font-family: var(--font-ui); font-size: 13px; color: var(--ink-soft);
}
.lab-chord-search input {
  flex: 1; min-width: 0; padding: 4px 10px 5px; background: var(--paper-card);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 14px 5px 13px 5px / 5px 13px 5px 14px;
  font-family: var(--font-body); font-size: 14px; color: var(--ink);
}
.lab-chord-count { margin: 8px 0 0; font-family: var(--font-note); font-size: 19px; color: var(--ink); }

/* 索引表。限高与吸顶落在**外层 div** 上，不落在 <table> 自己身上 ——
   给 table 挂 display:block 会把表拆成匿名表格，thead 与 tbody 各算一套列宽，
   表头就和正文错位了（与 .lab-letter-table-wrap 同一条理由）。 */
.lab-chord-table-wrap { margin-top: 10px; max-height: 380px; overflow: auto; overscroll-behavior: contain; }
.lab-chord-table { width: 100%; border-collapse: collapse; }
.lab-chord-table thead { position: sticky; top: 0; background: var(--paper-card); z-index: 1; }
.lab-chord-table th {
  text-align: left; padding: 6px 10px 7px; white-space: nowrap;
  font-family: var(--font-body); font-size: 13px; font-weight: 700;
  border-bottom: var(--w-note) solid var(--ink-faint);
}
.lab-chord-table td {
  padding: 5px 10px; font-size: 14px; overflow-wrap: anywhere;
  border-bottom: 1px dashed var(--ink-faint);
}
.lab-chord-table tr:last-child td { border-bottom: none; }
/* 第一列的条件标签是个按钮（点一条就把主视图切过去），所以它得看起来像能点的：
   手写字 + 虚线下划线，和正文里的可点词同一套语言。 */
.lab-chord-table td:first-child button {
  padding: 0 2px; background: none; cursor: pointer; color: var(--ink);
  border: none; border-bottom: 1px dashed var(--ink-faint);
  font-family: var(--font-note); font-size: 18px; line-height: 1.2;
}
.lab-chord-table td:first-child button:hover { color: var(--accent); border-bottom-color: var(--accent); }

/* ---------- 跟读实验（phonetics-stress / -intonation / -release / -chunks） ---------- */
/* 4 页共用一份渲染器（见 components/prosody.js），差别只在主题的 mode：重音与
   升降调把音节文字摆在圆点下面，失去爆破与意群是「编号在上、词排成一行」。
   配色照上游——重读那点和音高曲线是紫的（#a487b8 / #9970b0），其余是淡绿
   （#c8d5ba）。这组紫写在这里而不并进 --marker：它表示「这颗是重读」，
   是**数据含义**不是装饰，换主题配色不该把它一起换掉。 */
.lab-prosody > h2 {
  margin: 0 0 10px; font-family: var(--font-body); font-size: 20px; font-weight: 700;
}
.lab-prosody-lead { margin: 0 0 14px; font-size: 13px; line-height: 1.8; color: var(--ink-soft); }

/* 示例下拉与「遮住提示」并排。窄屏折行即可：两者没有先后。 */
.lab-prosody-toolbar {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px 18px; margin: 0 0 8px;
}
.lab-prosody-toolbar label {
  display: flex; align-items: center; gap: 8px;
  font-family: var(--font-ui); font-size: 13px; color: var(--ink-soft);
}
.lab-prosody-toolbar select {
  padding: 4px 8px 5px; background: var(--paper-card); color: var(--ink);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 14px 5px 13px 5px / 5px 13px 5px 14px;
  font-family: var(--font-body); font-size: 14px;
}
.lab-prosody-toggle {
  padding: 4px 12px 5px; background: var(--paper); cursor: pointer; color: var(--ink-soft);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 14px 5px 13px 5px / 5px 13px 5px 14px;
  font-family: var(--font-body); font-size: 13px;
}
.lab-prosody-toggle:hover { border-color: var(--accent); color: var(--accent); }
/* aria-pressed 是「提示已藏起来」——按下去的样式就取「正在起作用」那副
   （和 .lab-diagram-tools 的标签按钮同一套）。 */
.lab-prosody-toggle[aria-pressed='true'] {
  border-color: var(--accent); background: var(--marker); color: var(--accent);
}

/* 画布宽度要跟着正文走，所以不许缩；窄屏时靠 JS 重画（见 prosody.js 的
   ResizeObserver），这里只把 svg 的基线间隙消掉。 */
.lab-prosody-stage { min-width: 0; margin: 6px 0 0; }
.lab-prosody-canvas svg { display: block; width: 100%; height: auto; }

/* 圆点。大小（r=19 / 8）由 JS 给，颜色在这里——两个 fill 走类名而不是 SVG
   属性，属性没法跟着样式表走（和弦图同一条理由）。 */
.lab-prosody-dot { fill: #c8d5ba; }
.lab-prosody-dot.is-strong { fill: #a487b8; }
.lab-prosody-curve { fill: none; stroke: #9970b0; stroke-width: 4; }
.lab-prosody-hold { fill: none; stroke: #9a7ab0; stroke-width: 3; stroke-linejoin: round; }

/* 行内音频那一列（失去爆破 / 意群）：一条一组，组里是「词块文字 + 听分组 N」。
   每条右边留一段空，3 组喇叭连着排会分不出哪个读哪段。 */
.lab-prosody-tabs { display: flex; flex-wrap: wrap; align-items: center; margin: 4px 0 0; }
.lab-prosody-chunk { display: inline-flex; align-items: center; gap: 6px; margin: 0 16px 0 0; }
.lab-prosody-chunk > span:first-child {
  font-family: var(--font-note); font-size: 21px; line-height: 1.3; color: var(--ink);
}

/* 中文对照。它同时是 role=status 的活区（换一条示例时读屏念的是这句），
   遮住提示时又换成「提示已隐藏 · …」——两种身份都用 --ink-soft，不抢眼。 */
.lab-prosody-status { margin: 6px 0 0; font-size: 14px; line-height: 1.8; color: var(--ink-soft); }

/* 整句英文。和字母页、弦图页的整句同一档：它是**给人读的**英文，不是标签。 */
.lab-prosody-english {
  margin: 16px 0 10px; font-family: var(--font-note); font-size: 27px; line-height: 1.3;
  color: var(--ink);
}
/* 讲解条。和弦图的小结条同一副样子：左边一道竖线的浅底块，讲「这个图是什么意思」。 */
.lab-prosody-note {
  margin: 0; padding: 9px 14px; font-size: 13px; line-height: 1.8;
  color: var(--ink); background: var(--paper);
  border-left: 4px solid var(--action); border-radius: 0 10px 10px 0;
}
.lab-prosody-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 10px 0 0; }

/* ---------- 数量与范围集合图（pos-indefinites 的 activity:"indefinites"） ---------- */
/* 整块和字母对照区一样是**卡**不是通栏正文：原站的 .ecs-activity 就是描边 + 圆角
   + 浅底的面板（border 1px #dbe3d1、radius 16px、background #fcfdf8），因为它
   和上下的讲解是两件事 —— 上面讲不定代词怎么分，这里当场把 10 个表达点开看范围。 */
.lab-indefinites {
  padding: 18px 20px 20px;
  background: var(--paper-card);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 225px 16px 255px 16px / 16px 255px 16px 225px;
  box-shadow: 2px 3px 0 rgba(51, 48, 43, .07);
}
.lab-indefinites > h2 {
  margin: 0 0 10px; font-family: var(--font-body); font-size: 20px; font-weight: 700;
}
.lab-indefinites-lead { margin: 0; font-size: 13px; line-height: 1.8; color: var(--ink-soft); }

/* 下拉与跟读实验那一副同款（同一档描边、同一个圆角族），半径收敛到 5–14px。 */
.lab-indefinites-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 18px; margin: 14px 0 0; }
.lab-indefinites-toolbar label {
  display: flex; align-items: center; gap: 8px;
  font-family: var(--font-ui); font-size: 13px; color: var(--ink-soft);
}
.lab-indefinites-toolbar select {
  padding: 4px 8px 5px; background: var(--paper-card); color: var(--ink);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 14px 5px 13px 5px / 5px 13px 5px 14px;
  font-family: var(--font-body); font-size: 14px;
}

/* 画布宽度跟着正文走，所以不许缩；窄屏时靠 JS 重画（见 indefinites.js 的
   ResizeObserver），这里只把 svg 的基线间隙消掉。 */
.lab-indefinites-stage { min-width: 0; margin: 8px 0 0; }
.lab-indefinites-stage svg { display: block; width: 100%; height: auto; }
.lab-indefinites-stage svg [role='button'] { cursor: pointer; }
.lab-indefinites-stage svg [role='button']:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* 点阵的配色是**数据含义**，不是装饰：上色 = 落在这个数量词的范围内，淡色 =
   在范围外。和跟读实验那颗重读点同一条理由，所以写成字面值、不并进 --marker
   —— 换主题配色不该把「这颗算不算数」一起换掉。两副配色的紫与绿都照上游。 */
.lab-indefinites-frame { fill: #f7f9f2; stroke: #bccaab; stroke-width: 1; }
.lab-indefinites-frame.is-pair { fill: #f6f7f0; stroke: #cad6bf; }
.lab-indefinites-dot { fill: #e0e7d9; stroke: #8ca577; stroke-width: 1; }
.lab-indefinites-dot.is-in { fill: #a88aba; }
.lab-indefinites-pair circle { fill: #fff; stroke: #8d71a2; stroke-width: 3; }
.lab-indefinites-pair.is-in circle { fill: #b99acb; }
/* the others 那圈虚线：圈住被排除在外的几个。棕色的虚线是「另外划出来的一块」，
   和上色的实心点不是一回事。 */
.lab-indefinites-mark { fill: none; stroke: #b78761; stroke-width: 2; stroke-dasharray: 6 3; }

/* 整句英文。和字母页、跟读页的整句同一档：它是**给人读的**英文，不是标签。 */
.lab-indefinites-english {
  margin: 16px 0 10px; font-family: var(--font-note); font-size: 27px; line-height: 1.3;
  color: var(--ink);
}
/* 讲解条。和弦图小结、跟读页那条同一副样子：左边一道竖线的浅底块。 */
.lab-indefinites-note {
  margin: 0; padding: 9px 14px; font-size: 13px; line-height: 1.8;
  color: var(--ink); background: var(--paper);
  border-left: 4px solid var(--action); border-radius: 0 10px 10px 0;
}
.lab-indefinites-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 10px 0 0; }

/* ---------- 钟表、日历与分数饼（pos-numbers 的 activity:"number-tools"） ---------- */
/* 和集合图同一副卡：原站的 .ecs-activity 就是描边 + 圆角 + 浅底的面板，它是
   夹在导语与图解之间的一块活动，不是正文的一节。 */
.lab-numbers {
  padding: 18px 20px 20px;
  background: var(--paper-card);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 225px 16px 255px 16px / 16px 255px 16px 225px;
  box-shadow: 2px 3px 0 rgba(51, 48, 43, .07);
}
.lab-numbers > h2 {
  margin: 0 0 10px; font-family: var(--font-body); font-size: 20px; font-weight: 700;
}
.lab-numbers-lead { margin: 0; font-size: 13px; line-height: 1.8; color: var(--ink-soft); }

/* 控件行。**这些 label 一律不设 display**：三种工具各用一组控件，不用的那几组
   靠 hidden 属性整条收起，而作者表里的 display 会压过 UA 的 [hidden]{display:none}
   —— 设成 flex 的话「分母/分子/日期」会一直露着（同 .lab-video、.lab-spelling-audio
   那两处的理由，见各自注释）。做 flex 项的 label 会被「块化」，none 不受影响，
   所以外层容器照样可以 flex 布局。 */
.lab-numbers-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 18px; margin: 14px 0 0; }
.lab-numbers-toolbar label {
  font-family: var(--font-ui); font-size: 13px; color: var(--ink-soft);
}
.lab-numbers-toolbar label > span { margin-right: 6px; }
.lab-numbers-toolbar select,
.lab-numbers-toolbar input[type='date'] {
  padding: 4px 8px 5px; background: var(--paper-card); color: var(--ink);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 14px 5px 13px 5px / 5px 13px 5px 14px;
  font-family: var(--font-body); font-size: 14px; vertical-align: middle;
}
.lab-numbers-toolbar input[type='range'] { width: 118px; vertical-align: middle; }

/* 画布宽度跟着卡走，高度由 viewBox 的比例定（360:340）；日历模式下整张 svg 用
   display 收起（见 numbers.js，svg 没有 hidden 这条属性），所以这里同样不设
   display，只把基线那点间隙掐掉。 */
.lab-numbers-stage { min-width: 0; margin: 8px 0 0; }
.lab-numbers-stage svg { width: 100%; max-width: 480px; height: auto; vertical-align: top; }
/* 日历模式下顶掉画布的那张日期读牌。上游同样把它装在一张描边小卡里（.ecs-card），
   所以这里也给一圈描边 —— 光一行手写字会让画布这块空得只剩字。半径用按钮那套
   小圆角（大卡那种 225px 的半径套在这么矮的一条上会被压成胶囊）。 */
.lab-numbers-date {
  margin: 0; padding: 13px 16px 14px;
  background: var(--paper-card); color: var(--ink);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 14px 5px 13px 5px / 5px 13px 5px 14px;
  font-family: var(--font-note); font-size: 22px;
}

/* 钟面与分数饼的配色是**数据含义**，不是装饰：上色的那几片 = 分子点到的部分，
   紫色时针 / 绿色分针要能一眼分开。和集合图那颗上色点同一条理由，写成字面值、
   不并进 --marker —— 换主题配色不该把「这几片算不算数」一起换掉。三色照上游。 */
.lab-numbers-dial { fill: #fafcf6; stroke: #a8bb97; stroke-width: 3; }
.lab-numbers-num { fill: var(--ink); }
.lab-numbers-hand.is-hour { stroke: #8d6aa4; stroke-width: 10; }
.lab-numbers-hand.is-minute { stroke: #709656; stroke-width: 7; }
.lab-numbers-slice { fill: #e3ead9; stroke: #fff; stroke-width: 3; }
.lab-numbers-slice.is-on { fill: #aa8dbd; }

/* 整句英文。和字母页、集合图、跟读页的整句同一档：它是**给人读的**英文。 */
.lab-numbers-english {
  margin: 16px 0 10px; font-family: var(--font-note); font-size: 27px; line-height: 1.3;
  color: var(--ink);
}
/* 讲解条。和弦图小结、集合图那条同一副样子：左边一道竖线的浅底块。 */
.lab-numbers-note {
  margin: 0; padding: 9px 14px; font-size: 13px; line-height: 1.8;
  color: var(--ink); background: var(--paper);
  border-left: 4px solid var(--action); border-radius: 0 10px 10px 0;
}
.lab-numbers-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 10px 0 0; }

/* 「听力里的数字辨听」小卡：嵌在大卡里的一件独立事情（放音 → 二选一），所以自己
   也有一圈描边，半径外向反过来，看着像贴在卡片里的一张便签。 */
.lab-numbers-card {
  margin: 16px 0 0; padding: 14px 16px 16px;
  background: var(--paper);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 16px 225px 16px 255px / 255px 16px 225px 16px;
}
.lab-numbers-card > h3 {
  margin: 0 0 10px; font-family: var(--font-body); font-size: 16px; font-weight: 700;
}
.lab-numbers-audio { min-height: 0; }
.lab-numbers-tabs { display: flex; flex-wrap: wrap; gap: 10px; margin: 10px 0 0; }
.lab-numbers-tab {
  min-width: 72px; padding: 6px 16px 7px; background: var(--paper-card); cursor: pointer;
  color: var(--ink); border: var(--w-note) solid var(--ink-faint);
  border-radius: 14px 5px 13px 5px / 5px 13px 5px 14px;
  font-family: var(--font-note); font-size: 20px;
}
.lab-numbers-tab:hover { border-color: var(--accent); color: var(--accent); }
.lab-numbers-tab:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* 状态行留一行高度：从「先听声音…」换成「正确：…」时不该把下面的按钮顶下去。 */
.lab-numbers-status { margin: 10px 0 0; min-height: 1.8em; font-size: 13px; line-height: 1.8; color: var(--ink-soft); }
.lab-numbers-next {
  margin: 6px 0 0; padding: 5px 14px 6px; background: var(--paper-card); cursor: pointer;
  color: var(--ink-soft); border: var(--w-note) solid var(--ink-faint);
  border-radius: 14px 5px 13px 5px / 5px 13px 5px 14px;
  font-family: var(--font-body); font-size: 13px;
}
.lab-numbers-next:hover { border-color: var(--accent); color: var(--accent); }

/* ---------- 动词五形（pos-verb-forms 的 activity:"verb-forms"） ---------- */
/* 和集合图、数词工具同一副卡：原站的 .ecs-activity 就是描边 + 圆角 + 浅底的面板。 */
.lab-verbforms {
  padding: 18px 20px 20px;
  background: var(--paper-card);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 225px 16px 255px 16px / 16px 255px 16px 225px;
  box-shadow: 2px 3px 0 rgba(51, 48, 43, .07);
}
.lab-verbforms > h2 {
  margin: 0 0 10px; font-family: var(--font-body); font-size: 20px; font-weight: 700;
}
.lab-verbforms-lead { margin: 0; font-size: 13px; line-height: 1.8; color: var(--ink-soft); }

/* 下拉与集合图那一副同款（同一档描边、同一个圆角族）。 */
.lab-verbforms-toolbar {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px 18px; margin: 14px 0 0;
}
.lab-verbforms-toolbar label {
  display: flex; align-items: center; gap: 8px;
  font-family: var(--font-ui); font-size: 13px; color: var(--ink-soft);
}
.lab-verbforms-toolbar select {
  padding: 4px 8px 5px; background: var(--paper-card); color: var(--ink);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 14px 5px 13px 5px / 5px 13px 5px 14px;
  font-family: var(--font-body); font-size: 14px;
}
.lab-verbforms-toolbar select:disabled { opacity: .55; cursor: not-allowed; }

/* 关系图的画布宽度跟着正文走（viewBox 的宽就是量到的宽度，所以是 1:1 不缩放）；
   窄屏靠 JS 重画成竖排（见 verbforms.js 的 ResizeObserver）。max-width 760 与
   上游同一条：原站量到的 svg 宽就是 760，五张牌再摊开弧就平得看不出「从原形
   散出来」了。这里只把 svg 的基线间隙消掉 —— 它下面紧跟着标签页。 */
.lab-verbforms-stage { min-width: 0; margin: 8px 0 0; }
.lab-verbforms-stage svg { display: block; width: 100%; max-width: 760px; height: auto; }
.lab-verbforms-stage svg [role='button'] { cursor: pointer; }
.lab-verbforms-stage svg [role='button']:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* 图上那几笔的配色是**数据含义**，不是装饰：紫的那一张与它那条线 = 当前选中的
   形式，浅绿的是其余四格。和集合图那颗上色点、数词饼的亮片同一条理由，所以
   写成字面值、不并进 --marker —— 换主题配色不该把「哪一格是当前形式」一起换掉。
   三色照上游。 */
.lab-verbforms-link { fill: none; stroke: #d4dfca; stroke-width: 2; }
.lab-verbforms-link.is-on { stroke: #8567a6; stroke-width: 4; }
.lab-verbforms-node rect { fill: #f4f7ee; stroke: #d5dfca; stroke-width: 1; }
.lab-verbforms-node.is-on rect { fill: #eee7f7; stroke: #9475b4; }
.lab-verbforms-center-word {
  font-family: var(--font-note); font-size: 21px; font-weight: 700; fill: var(--ink);
}
.lab-verbforms-center-type { font-family: var(--font-ui); font-size: 13px; fill: var(--ink-soft); }
/* 牌上是动词本身 —— 那是给人读的英文，走手写体；下面那行是语法名，走正文字体。 */
.lab-verbforms-word { font-family: var(--font-note); font-size: 21px; fill: var(--ink); }
.lab-verbforms-label { font-family: var(--font-ui); font-size: 13px; fill: var(--ink-soft); }

/* 与图上那五张牌同义的标签页（两个入口都能改当前形式）。半径用按钮那一套小圆角：
   「第三人称单数」这种长标签套上大卡那种 225px 半径会被压成胶囊。 */
.lab-verbforms-tabs { display: flex; flex-wrap: wrap; gap: 8px; margin: 14px 0 0; }
.lab-verbforms-tab {
  padding: 6px 14px 7px; background: var(--paper-card); cursor: pointer;
  color: var(--ink); border: var(--w-note) solid var(--ink-faint);
  border-radius: 14px 5px 13px 5px / 5px 13px 5px 14px;
  font-family: var(--font-body); font-size: 14px;
}
.lab-verbforms-tab:hover { border-color: var(--accent); color: var(--accent); }
.lab-verbforms-tab:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* 选中的那颗标签页走**图上那套紫**，不走全站的 --accent/--marker：它和图上亮着的
   那张牌是同一件事的两个入口，两处一个棕一个紫会被读成两种状态。紫色在这一页是
   数据含义（哪一格是当前形式），所以照上游写成字面值（上游标签页的紫比牌略深
   一号，也是照抄）。 */
.lab-verbforms-tab[aria-pressed='true'] {
  border-color: #ac8cc8; background: #eee6f5; color: #725488;
}
.lab-verbforms-tab[aria-pressed='true']:hover { border-color: #9475b4; color: #725488; }

/* 整句英文。和字母页、集合图、数词工具同一档：它是**给人读的**英文。 */
.lab-verbforms-english {
  margin: 16px 0 10px; font-family: var(--font-note); font-size: 27px; line-height: 1.3;
  color: var(--ink);
}
/* 「为什么用这个形式？」原站就是一折 details（默认合着），不是常驻的讲解条 ——
   所以这里既不给它浅底也不给左边那道竖线，它下面才是例句的讲解条。 */
.lab-verbforms-why { margin: 0 0 4px; }
.lab-verbforms-why > summary {
  cursor: pointer; font-family: var(--font-body); font-size: 14px; color: var(--ink-soft);
}
.lab-verbforms-why > summary:hover { color: var(--accent); }
.lab-verbforms-why-body {
  margin: 8px 0 0; padding: 9px 14px; font-size: 13px; line-height: 1.8;
  color: var(--ink); background: var(--paper);
  border-left: 4px solid var(--action); border-radius: 0 10px 10px 0;
}
.lab-verbforms-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 10px 0 0; }

/* ---------- 不规则动词模式聚类（pos-irregular-verbs 的 activity:"irregular-verbs"） ---------- */
/* 和集合图、数词工具、动词五形同一副卡：原站的 .ecs-activity 就是描边 + 圆角 + 浅底
   的面板，它是夹在导语与图解之间的一块活动，不是正文的一节。 */
.lab-irregularverbs {
  padding: 18px 20px 20px;
  background: var(--paper-card);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 225px 16px 255px 16px / 16px 255px 16px 225px;
  box-shadow: 2px 3px 0 rgba(51, 48, 43, .07);
}
.lab-irregularverbs > h2 {
  margin: 0 0 10px; font-family: var(--font-body); font-size: 20px; font-weight: 700;
}
.lab-irregularverbs-lead { margin: 0; font-size: 13px; line-height: 1.8; color: var(--ink-soft); }

/* 三个控件并排（范围 / 模式 / 搜索），下拉与集合图、动词五形那一副同款。 */
.lab-irregularverbs-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 18px; margin: 14px 0 0; }
.lab-irregularverbs-toolbar label {
  display: flex; align-items: center; gap: 8px;
  font-family: var(--font-ui); font-size: 13px; color: var(--ink-soft);
}
.lab-irregularverbs-toolbar select,
.lab-irregularverbs-toolbar input[type='search'] {
  padding: 4px 8px 5px; background: var(--paper-card); color: var(--ink);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 14px 5px 13px 5px / 5px 13px 5px 14px;
  font-family: var(--font-body); font-size: 14px; vertical-align: middle;
}
/* 搜索框给一档最小宽度：不写的话它是浏览器按 size 属性给的那点宽，一个词都看不全。 */
.lab-irregularverbs-toolbar input[type='search'] { min-width: 160px; }

/* 状态行留一行高度：改筛选条件时数字会变，别把下面那张图顶下去（同 .lab-numbers-status）。 */
.lab-irregularverbs-status {
  margin: 12px 0 0; min-height: 1.8em; font-size: 13px; line-height: 1.8; color: var(--ink-soft);
}

/* 画布。viewBox 固定 0 0 700 500，圆心与半径由 JS 里的 d3.pack 算出来，所以这里
   只负责缩放（原站 .ecx-stage svg 就是 width:100% + max-width:900px + margin:16px auto）。 */
.lab-irregularverbs-canvas { min-width: 0; }
.lab-irregularverbs-canvas svg {
  display: block; width: 100%; max-width: 900px; height: auto; margin: 16px auto;
}
.lab-irregularverbs-canvas svg [role='button'] { cursor: pointer; }
.lab-irregularverbs-canvas svg [role='button']:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 3px;
}

/* 气泡的配色是**数据含义**，不是装饰：浅绿的一团 = 一个变化模式的词族，白底圆点 =
   一个词，紫描边的那个 = 当前选中的词。和集合图那颗上色点、动词五形亮着的那张牌
   同一条理由，所以写成字面值、不并进 --marker —— 换主题配色不该把「哪一个被选中」
   一起换掉。四色照上游（#795293 就是选中那圈的描边，粗细也从 1 变 3）。 */
.lab-irregularverbs-cluster { fill: #edf2e6; stroke: #cbd5c1; stroke-width: 1; }
.lab-irregularverbs-word circle { fill: #fff; stroke: #c4d1b7; stroke-width: 1; }
.lab-irregularverbs-word.is-on circle { stroke: #795293; stroke-width: 3; }
/* 圆点上那个词是**给人读的**英文，走手写体；字号由 JS 按气泡大小给。 */
.lab-irregularverbs-word-text { font-family: var(--font-note); fill: #4b6240; }

/* 三张卡（原形 / 过去式 / 过去分词）的外壳。**故意不设 display**：没结果时整块靠
   hidden 属性收起，而作者表里的 display 会压过 UA 的 [hidden]{display:none}
   —— 同 .lab-numbers-toolbar label 那处的理由。栅格因此挂在内层上，这里不需要样式。 */

/* 三张卡。顺序就是「原形 → 过去式 → 过去分词」，间距照上游的 12px。 */
.lab-irregularverbs-cards { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
.lab-irregularverbs-card {
  min-width: 0; padding: 12px 14px 14px;
  background: var(--paper); color: var(--ink);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 16px 225px 16px 255px / 255px 16px 225px 16px;
}
/* 三张并排时同一副角看着像复制粘贴，中间那张横竖对调（同 .lab-intro-marks 的做法）。 */
.lab-irregularverbs-card:nth-child(even) {
  border-radius: 225px 16px 255px 16px / 16px 255px 16px 225px;
}
.lab-irregularverbs-card > small {
  display: block; font-family: var(--font-ui); font-size: 12px; color: var(--ink-soft);
}
/* 卡上那个词就是这一页要背的英文本身，走手写体、和字母表那颗按钮同一档。 */
.lab-irregularverbs-card > h3 {
  margin: 4px 0 0; font-family: var(--font-note); font-size: 26px; font-weight: 400;
  line-height: 1.2; color: var(--ink);
}
.lab-irregularverbs-card-actions {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 8px 0 0;
}

/* 「按 ××× 记忆」那一句。上游是 .ecs-small：压一级字号、退到浅色。 */
.lab-irregularverbs-family { margin: 12px 0 0; font-size: 13px; line-height: 1.8; color: var(--ink-soft); }

/* 整句英文。和字母页、集合图、动词五形同一档：它是**给人读的**英文，不是标签。 */
.lab-irregularverbs-english {
  margin: 16px 0 10px; font-family: var(--font-note); font-size: 27px; line-height: 1.3;
  color: var(--ink);
}
/* 讲解条。和弦图小结、动词五形那条同一副样子：左边一道竖线的浅底块，这里放
   「中文 · 原形 → 过去式 → 过去分词」。 */
.lab-irregularverbs-note {
  margin: 0; padding: 9px 14px; font-size: 13px; line-height: 1.8;
  color: var(--ink); background: var(--paper);
  border-left: 4px solid var(--action); border-radius: 0 10px 10px 0;
}
.lab-irregularverbs-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 10px 0 0; }

/* 106 行的全表。表头吸顶 + 整表限高（原站 .ecx-reference 就是 480px）：这张表的用处
   是检索一个词的三形，106 行一次铺开会把下面的脚注顶得老远。
   滚动与限高落在**外层 div** 上，不落在 <table> 自己身上：给 table 挂 display:block
   会把 thead 与 tbody 拆成两套列宽，表头就和正文错位（同字母表那一处的理由）。 */
.lab-irregularverbs-table-wrap {
  margin-top: 18px; max-height: 480px; overflow: auto; overscroll-behavior: contain;
}
.lab-irregularverbs-table { width: 100%; border-collapse: collapse; }
.lab-irregularverbs-table thead { position: sticky; top: 0; background: var(--paper-card); z-index: 1; }
.lab-irregularverbs-table th {
  text-align: left; padding: 6px 10px 7px; white-space: nowrap;
  font-family: var(--font-body); font-size: 13px; font-weight: 700;
  border-bottom: var(--w-note) solid var(--ink-faint);
}
.lab-irregularverbs-table td {
  padding: 5px 10px; font-size: 14px; overflow-wrap: anywhere;
  border-bottom: 1px dashed var(--ink-faint);
}
/* 第二、三列是动词的两形，走手写体 —— 找一个词时，眼睛是顺着这两列的字形往下扫的
   （同字母表第一列那颗字母）。 */
.lab-irregularverbs-table td:nth-child(2),
.lab-irregularverbs-table td:nth-child(3) { font-family: var(--font-note); font-size: 18px; }
.lab-irregularverbs-table td small { font-size: 12px; color: var(--ink-soft); }
/* 原形那一列是按钮：点它与点图上的圆点是同一件事的两个入口。它长得像正文里的一个词、
   不像一颗按钮 —— 一圈描边会把 106 行的表画成一列胶囊。 */
.lab-irregularverbs-table td button {
  padding: 0; background: none; color: var(--ink); cursor: pointer;
  border: none; border-bottom: 1px dashed var(--ink-faint);
  font-family: var(--font-note); font-size: 18px; line-height: 1.5;
}
.lab-irregularverbs-table td button:hover { color: var(--accent); border-bottom-color: var(--accent); }
.lab-irregularverbs-table td button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.lab-irregularverbs-table tr:last-child td { border-bottom: none; }

/* 脚注（情态动词那一栏的说明 + 课标原表的链接）。上游是 .ecs-small。 */
.lab-irregularverbs-footnote { margin: 12px 0 0; font-size: 13px; line-height: 1.8; color: var(--ink-soft); }
.lab-irregularverbs-footnote a { margin-left: 8px; color: var(--accent); }

/* ---------- 动词短语方向图（pos-phrasal-verbs 的 activity:"phrasal-verbs"） ---------- */
/* 和集合图、数词工具、动词五形、不规则动词同一副卡：原站的 .ecs-activity 就是描边 +
   圆角 + 浅底的面板，它是夹在导语与图解之间的一块活动，不是正文的一节。 */
.lab-phrasalverbs {
  padding: 18px 20px 20px;
  background: var(--paper-card);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 225px 16px 255px 16px / 16px 255px 16px 225px;
  box-shadow: 2px 3px 0 rgba(51, 48, 43, .07);
}
.lab-phrasalverbs > h2 {
  margin: 0 0 10px; font-family: var(--font-body); font-size: 20px; font-weight: 700;
}
.lab-phrasalverbs-lead { margin: 0; font-size: 13px; line-height: 1.8; color: var(--ink-soft); }

/* 一个下拉（选动词）。与集合图、数词工具、不规则动词那一副同款。 */
.lab-phrasalverbs-toolbar {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px 18px; margin: 14px 0 0;
}
.lab-phrasalverbs-toolbar label {
  display: flex; align-items: center; gap: 8px;
  font-family: var(--font-ui); font-size: 13px; color: var(--ink-soft);
}
.lab-phrasalverbs-toolbar select {
  padding: 4px 8px 5px; background: var(--paper-card); color: var(--ink);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 14px 5px 13px 5px / 5px 13px 5px 14px;
  font-family: var(--font-body); font-size: 14px; vertical-align: middle;
}

/* 画布。viewBox 的宽是 JS 按容器宽度现算的（上限 650），所以这里只管缩放与居中 ——
   原站 .ecx-stage svg 是 width:100% + max-width:900px + margin:16px 0。
   900 那个上限别改成 650：viewBox 本身已经被 JS 卡在 650 了，再给 CSS 卡一次
   等于把图缩到 650px 宽（原站是撑满整栏、再按 894/650 放大画出来的），
   图上八个方向的字会明显比原站小一圈。 */
.lab-phrasalverbs-canvas svg {
  display: block; width: 100%; max-width: 900px; height: auto; margin: 16px auto;
}
.lab-phrasalverbs-canvas svg [role='button'] { cursor: pointer; }
.lab-phrasalverbs-canvas svg [role='button']:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 3px;
}

/* 方向图上的颜色是**数据含义**，不是装饰，全部在 JS 里按状态写成字面值：
   紫连线 = 这个动词有这个方向词的真实搭配，灰线 = 没有；圆圈选中那颗浅紫、
   能点的浅绿、不能点的近白。所以这里一个 fill / stroke 都不写 —— 写了就盖掉
   「哪个方向亮着」。只有文字走纸面配色（同不规则动词那张气泡图的圆点字）。
   半径、字号、位置全由 JS 给（宽窄两档），CSS 不插手，否则窄屏那档会错位。 */
.lab-phrasalverbs-word,
.lab-phrasalverbs-chip text { font-family: var(--font-note); fill: #4b6240; }
.lab-phrasalverbs-chip { cursor: grab; }
.lab-phrasalverbs-chip:active { cursor: grabbing; }

/* 一排搭配按钮：当前动词真实收录的那些。选中那颗用浅绿（与图上「亮着」同一色），
   没选的是纸面白 —— 两级状态在按钮排与方向图上对得上。 */
.lab-phrasalverbs-tabs { display: flex; flex-wrap: wrap; gap: 8px; margin: 4px 0 0; }
.lab-phrasalverbs-tab {
  padding: 5px 12px 6px; background: var(--paper-card); color: var(--ink); cursor: pointer;
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 14px 5px 13px 5px / 5px 13px 5px 14px;
  font-family: var(--font-note); font-size: 17px; line-height: 1.4;
}
.lab-phrasalverbs-tab:hover { border-color: var(--accent); }
.lab-phrasalverbs-tab:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.lab-phrasalverbs-tab[aria-pressed='true'] { background: #eff5e9; border-color: #a58ab6; }

/* 当前搭配那一句提示（「put on 是动作，wear 是状态」）。上游是 .ecs-small。
   留一行高度：换搭配时字长不一，别把下面那句例句顶来顶去。 */
.lab-phrasalverbs-hint {
  margin: 10px 0 0; min-height: 1.8em; font-size: 13px; line-height: 1.8; color: var(--ink-soft);
}

/* 整句英文。和字母页、集合图、数词工具同一档：它是**给人读的**英文，不是标签。 */
.lab-phrasalverbs-english {
  margin: 16px 0 10px; font-family: var(--font-note); font-size: 27px; line-height: 1.3;
  color: var(--ink);
}
/* 讲解条。和弦图小结、数词工具那条同一副样子：左边一道竖线的浅底块，这里放
   「put on · 穿上。请穿上外套。」 */
.lab-phrasalverbs-note {
  margin: 0; padding: 9px 14px; font-size: 13px; line-height: 1.8;
  color: var(--ink); background: var(--paper);
  border-left: 4px solid var(--action); border-radius: 0 10px 10px 0;
}
.lab-phrasalverbs-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 10px 0 0; }

/* ---------- 多词动词移位测试台
   （pos-phrasal-prepositional-verbs 的 activity:"phrasal-prepositional-verbs"） ---------- */
/* 与方向图、集合图、数词工具同一副卡：原站 .ecs-activity 就是描边 + 圆角 + 浅底的
   面板，它夹在推荐卡与图解之间，是一块活动、不是正文的一节。 */
.lab-multiwordverbs {
  padding: 18px 20px 20px;
  background: var(--paper-card);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 225px 16px 255px 16px / 16px 255px 16px 225px;
  box-shadow: 2px 3px 0 rgba(51, 48, 43, .07);
}
.lab-multiwordverbs > h2 {
  margin: 0 0 10px; font-family: var(--font-body); font-size: 20px; font-weight: 700;
}
.lab-multiwordverbs-lead { margin: 0; font-size: 13px; line-height: 1.8; color: var(--ink-soft); }

.lab-multiwordverbs-toolbar {
  display: flex; flex-wrap: wrap; align-items: center; gap: 12px 18px; margin: 14px 0 0;
}
.lab-multiwordverbs-toolbar label {
  display: flex; align-items: center; gap: 8px;
  font-family: var(--font-ui); font-size: 13px; color: var(--ink-soft);
}
.lab-multiwordverbs-toolbar select {
  padding: 4px 8px 5px; background: var(--paper-card); color: var(--ink);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 14px 5px 13px 5px / 5px 13px 5px 14px;
  font-family: var(--font-body); font-size: 14px; vertical-align: middle;
}

/* 两排按钮（类型筛选、三个宾语开关）同款：与方向图那排搭配按钮同一族圆角。
   选中的那颗描深一点 —— 五个筛选项里哪一个是当前档，得一眼看得出来。 */
.lab-multiwordverbs-filters,
.lab-multiwordverbs-modes { display: flex; flex-wrap: wrap; gap: 6px; }
.lab-multiwordverbs-filters button,
.lab-multiwordverbs-modes button {
  padding: 5px 12px 6px; background: var(--paper-card); color: var(--ink-soft); cursor: pointer;
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 14px 5px 13px 5px / 5px 13px 5px 14px;
  font-family: var(--font-ui); font-size: 13px; line-height: 1.5;
}
.lab-multiwordverbs-filters button:hover,
.lab-multiwordverbs-modes button:hover { border-color: var(--accent); color: var(--ink); }
.lab-multiwordverbs-filters button:focus-visible,
.lab-multiwordverbs-modes button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.lab-multiwordverbs-filters button[aria-pressed='true'],
.lab-multiwordverbs-modes button[aria-pressed='true'] {
  background: #f1ece6; border-color: var(--accent); color: var(--ink);
}
/* 不及物时前两个开关是关掉的（没有宾语位置可言）。灰掉而不是藏掉 —— 藏了会
   让人以为这一版没有这两个工具。 */
.lab-multiwordverbs-filters button:disabled,
.lab-multiwordverbs-modes button:disabled { opacity: .45; cursor: not-allowed; }

.lab-multiwordverbs-stage { min-width: 0; margin: 10px 0 0; }
.lab-multiwordverbs-modes { margin: 16px 0 0; }

/* 类型说明行（「类型：可分短语动词（separable phrasal verb）」+ 一句规则）。 */
.lab-multiwordverbs-kind { margin: 14px 0 0; font-size: 14px; line-height: 1.9; color: var(--ink); }
.lab-multiwordverbs-kind strong { font-weight: 700; }
.lab-multiwordverbs-small { font-size: 13px; color: var(--ink-soft); }

/* 句子词块。每块两行：词本身（手写体，和例句同一支笔）与它的作用（小字）。
   底色是**数据含义**不是装饰：宾语蓝、小品词黄、介词红 —— 一根绳子和一条尾巴
   的差别就在这上面，所以全部按 data-role 上色，一个字面值都不白给。 */
.lab-multiwordverbs-tokens { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; padding: 16px 0; }
.lab-multiwordverbs-token {
  display: grid; gap: 5px; min-width: 58px; padding: 11px 14px 10px;
  background: #edf3e6; text-align: center;
  border: var(--w-note) solid #c8d5bd;
  border-radius: 12px 6px 13px 6px / 6px 13px 6px 12px;
}
.lab-multiwordverbs-token span {
  font-family: var(--font-note); font-size: 22px; line-height: 1.2; color: var(--ink);
}
.lab-multiwordverbs-token small { font-family: var(--font-ui); font-size: 11px; color: var(--ink-soft); }
.lab-multiwordverbs-token[data-role*='宾语'] { background: #e6f1f5; border-color: #9bbdc7; }
.lab-multiwordverbs-token[data-role='小品词'] { background: #f7efdd; border-color: #d4b77f; }
.lab-multiwordverbs-token[data-role='介词'] { background: #fbe8e2; border-color: #d9a08a; }

/* 判定行。成立/不成立是这一块的结论，所以整行换色而不是只换一个对勾：
   ✗ 用全站那个「提醒」红（--alert），✓ 用「动作」绿（--action）。 */
.lab-multiwordverbs-verdict { margin: 0; font-size: 17px; font-weight: 700; color: var(--ink); }
.lab-multiwordverbs-verdict[data-ok='true'] { color: var(--action); }
.lab-multiwordverbs-verdict[data-ok='false'] { color: var(--alert); }

/* 这个动词的全部语序：四行（不及物一行）。当前那一行加粗描深 —— 四行字长得
   差不多，得让人知道现在看的是哪一行。 */
.lab-multiwordverbs-orders {
  margin: 12px 0 0; padding-left: 20px;
  font-size: 13px; line-height: 1.9; color: var(--ink-soft);
}
.lab-multiwordverbs-orders li[aria-current='true'] { color: var(--ink); font-weight: 700; }

/* 整句英文。和方向图、数词工具同一档：它是**给人读的**英文，不是标签。 */
.lab-multiwordverbs-english {
  margin: 16px 0 10px; font-family: var(--font-note); font-size: 27px; line-height: 1.3;
  color: var(--ink);
}
/* 讲解条。与方向图那条同一副样子：左边一道竖线的浅底块，这里放
   「为什么成立（或错在哪）+ 这个词的提示 + 中文」。 */
.lab-multiwordverbs-note {
  margin: 0; padding: 9px 14px; font-size: 13px; line-height: 1.8;
  color: var(--ink); background: var(--paper);
  border-left: 4px solid var(--action); border-radius: 0 10px 10px 0;
}
.lab-multiwordverbs-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 10px 0 0; }

/* ---------- 情态动词双尺（pos-modals 的 activity:"modal-scales"） ---------- */
/* 和集合图、数词工具同一副卡：原站的 .ecs-activity 就是描边 + 圆角 + 浅底的面板，
   它是夹在导语与图解之间的一块活动，不是正文的一节。 */
.lab-modalscales {
  padding: 18px 20px 20px;
  background: var(--paper-card);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 225px 16px 255px 16px / 16px 255px 16px 225px;
  box-shadow: 2px 3px 0 rgba(51, 48, 43, .07);
}
.lab-modalscales > h2 {
  margin: 0 0 10px; font-family: var(--font-body); font-size: 20px; font-weight: 700;
}
.lab-modalscales-lead { margin: 0; font-size: 13px; line-height: 1.8; color: var(--ink-soft); }

/* 两条滑杆并排。滑杆给一档宽度：浏览器默认那点长度在 4 个刻度上根本停不准。 */
.lab-modalscales-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 22px; margin: 14px 0 0; }
.lab-modalscales-toolbar label {
  display: flex; align-items: center; gap: 8px;
  font-family: var(--font-ui); font-size: 13px; color: var(--ink-soft);
}
.lab-modalscales-toolbar input[type='range'] { width: 150px; vertical-align: middle; }

/* 画布宽度跟着卡走，viewBox 的宽由 JS 按容器宽度给（上限 620），所以这里只负责
   缩放；原站 .ecx-stage svg 就是 width:100% + max-width:900px + margin:16px auto。 */
.lab-modalscales-stage { min-width: 0; margin: 8px 0 0; }
.lab-modalscales-canvas { min-width: 0; }
.lab-modalscales-canvas svg {
  display: block; width: 100%; max-width: 900px; height: auto; margin: 16px auto;
}

/* 点与线的位置、半径、字号全由 JS 给（宽窄两档），CSS 不插手 —— 只有颜色在这儿：
   选中的那一格照上游是紫色实心大点、其余是浅绿小点，这是**数据含义**（哪一格是当前
   选中的），所以写成字面值、不并进 --marker：换主题配色不该把「选中了哪一格」也换掉。
   两条尺同色，谁高谁低由位置分。 */
.lab-modalscales-rail { stroke: #becdab; stroke-width: 5; }
.lab-modalscales-word { fill: var(--ink); }
.lab-modalscales-tick { fill: var(--ink-soft); }

/* 那句否定提示。上游是 .ecs-small（13px 浅色），跟在尺下面当注解，不是正文。 */
.lab-modalscales-small { margin: 0 0 0; font-size: 13px; line-height: 1.8; color: var(--ink-soft); }

/* 整句英文。和方向图、数词工具同一档：它是**给人读的**英文，不是标签。 */
.lab-modalscales-english {
  margin: 16px 0 10px; font-family: var(--font-note); font-size: 27px; line-height: 1.3;
  color: var(--ink);
}
/* 讲解条。与方向图那条同一副样子：左边一道竖线的浅底块。 */
.lab-modalscales-note {
  margin: 0; padding: 9px 14px; font-size: 13px; line-height: 1.8;
  color: var(--ink); background: var(--paper);
  border-left: 4px solid var(--action); border-radius: 0 10px 10px 0;
}
.lab-modalscales-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 10px 0 0; }

/* ---------- 情境图（4 个语法页共用的 activity，id 就是各自的页 id） ---------- */
/* 同一副卡：原站这块也是描边 + 圆角 + 浅底的一整块活动，夹在导语与图解之间。 */
.lab-scenes {
  padding: 18px 20px 20px;
  background: var(--paper-card);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 225px 16px 255px 16px / 16px 255px 16px 225px;
  box-shadow: 2px 3px 0 rgba(51, 48, 43, .07);
}
.lab-scenes > h2 {
  margin: 0 0 10px; font-family: var(--font-body); font-size: 20px; font-weight: 700;
}
.lab-scenes-lead { margin: 0; font-size: 13px; line-height: 1.8; color: var(--ink-soft); }

/* 一行「表达」。每个表达是一个情境，当前那个按下去（和数词页的 tabs 同一副样子，
   只是这里放的是整句中文标题，所以不卡最小宽度）。 */
.lab-scenes-tabs { display: flex; flex-wrap: wrap; gap: 10px; margin: 14px 0 0; }
.lab-scenes-tab {
  padding: 6px 16px 7px; background: var(--paper-card); cursor: pointer;
  color: var(--ink-soft); border: var(--w-note) solid var(--ink-faint);
  border-radius: 14px 5px 13px 5px / 5px 13px 5px 14px;
  font-family: var(--font-body); font-size: 13px;
}
.lab-scenes-tab:hover { border-color: var(--accent); color: var(--accent); }
.lab-scenes-tab:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* 当前这个表达。和「遮住中文」那个按钮一样：按下去的样式就是「正在起作用」那副。 */
.lab-scenes-tab.is-on { border-color: var(--accent); background: var(--marker); color: var(--accent); }

/* 只有 pos-spend-cost / pos-past-present-perfect 两页有滑杆。滑杆给一档宽度：
   浏览器默认那点长度在 10 步上停不准。 */
.lab-scenes-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 18px; margin: 12px 0 0; }
.lab-scenes-toolbar label {
  display: flex; align-items: center; gap: 8px;
  font-family: var(--font-ui); font-size: 13px; color: var(--ink-soft);
}
.lab-scenes-toolbar input[type='range'] { width: 150px; vertical-align: middle; }
.lab-scenes-toolbar output { font-family: var(--font-note); font-size: 20px; color: var(--ink); }
/* 那句「只在『持续：起点与时长』上生效」的注解。上游是 .ecs-small（13px 浅色）。 */
.lab-scenes-small { font-size: 13px; line-height: 1.8; color: var(--ink-soft); }

/* 画布宽度跟着卡走，viewBox 的宽由 JS 按容器宽给（夹在 260~760），所以这里只负责
   缩放。760 是上游 CSS 给 svg 的上限 —— JS 量的就是它，两边因此同宽。 */
.lab-scenes-canvas { min-width: 0; max-width: 760px; }
.lab-scenes-canvas svg { display: block; width: 100%; height: auto; margin: 14px auto; }

/* 图里的字与线：位置、字号全由 JS 给（宽窄两档），CSS 只管颜色与字体。
   格子底色与描边是**数据含义**（这一格在时间轴上是过去 / 现在 / 尚未发生，以及
   哪一格是当前点开的），所以照上游写成字面值，不并进 --marker。 */
.lab-scenes-node { cursor: pointer; }
.lab-scenes-node:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.lab-scenes-node-title { font-family: var(--font-ui); fill: var(--ink-soft); }
.lab-scenes-node-label { font-family: var(--font-body); fill: var(--ink); }
.lab-scenes-link-label { font-family: var(--font-ui); fill: var(--ink-soft); }

/* 整句英文。和方向图、数词工具、双尺同一档：它是**给人读的**英文。 */
.lab-scenes-english {
  margin: 14px 0 8px; font-family: var(--font-note); font-size: 27px; line-height: 1.3;
  color: var(--ink);
}
/* 中文对照。遮起来时整段收起（hidden 属性），所以这里不写「淡」的样式 ——
   藏起来就是不在，不是变淡。 */
.lab-scenes-chinese { margin: 0 0 10px; font-size: 15px; line-height: 1.8; color: var(--ink-soft); }
.lab-scenes-chinese[hidden] { display: none; }

/* 讲解条。与方向图那条同一副样子：左边一道竖线的浅底块。 */
.lab-scenes-note {
  margin: 0; padding: 9px 14px; font-size: 13px; line-height: 1.8;
  color: var(--ink); background: var(--paper);
  border-left: 4px solid var(--action); border-radius: 0 10px 10px 0;
}
.lab-scenes-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 10px 0 0; }
.lab-scenes-speak { display: inline-flex; }
.lab-scenes-toggle {
  padding: 4px 12px 5px; background: var(--paper); cursor: pointer; color: var(--ink-soft);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 14px 5px 13px 5px / 5px 13px 5px 14px;
  font-family: var(--font-body); font-size: 13px;
}
.lab-scenes-toggle:hover { border-color: var(--accent); color: var(--accent); }
.lab-scenes-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.lab-scenes-toggle[aria-pressed='true'] {
  border-color: var(--accent); background: var(--marker); color: var(--accent);
}

/* ---------- 词块条（共享：词块实验 / 被动翻转 / 主谓一致 / 疑问句变形） ---------- */
/* 由 components/stage.js 的 LAB.ui.tokenList 产出，所以类名不带活动前缀。 */
.lab-tokens { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }
/* 一块词块：上面是词、下面是它的角色。底色与描边是**数据含义**（这一块在句子里
   是干什么的），照上游写死成字面值，不并进 --marker —— 见下面那几条 [data-role]。 */
.lab-token {
  display: grid; gap: 7px; min-width: 62px; padding: 14px 16px; text-align: center;
  background: #edf3e6; border: 1px solid #c8d5bd; border-radius: 12px;
}
.lab-token span { font-family: var(--font-body); font-size: 20px; line-height: 1.3; }
.lab-token small { font-family: var(--font-ui); font-size: 12px; color: #698157; }
/* 上游那四条角色配色，逐条照抄（今天只有「结构 / 助动词」「时态」「受动」会命中，
   其余几条是上游表里别的活动用的 —— 抄全，免得哪天活动加回来又要翻上游）。 */
.lab-token[data-role*='时态'],
.lab-token[data-role*='助动词'] { background: #eee7f6; border-color: #b8a0cb; }
.lab-token[data-role*='宾语'],
.lab-token[data-role*='受动'] { background: #e6f1f5; border-color: #9bbdc7; }
.lab-token[data-role='小品词'] { background: #f7efdd; border-color: #d4b77f; }
.lab-token[data-role='介词'] { background: #fbe8e2; border-color: #d9a08a; }

/* ---------- 切换情境看词块（8 个语法页共用的 activity，键是活动 id） ---------- */
/* 与情境图同一副卡：上游这块也是描边 + 圆角 + 浅底的一整块活动，夹在导语与图解之间。 */
.lab-patternlab {
  padding: 18px 20px 20px;
  background: var(--paper-card);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 225px 16px 255px 16px / 16px 255px 16px 225px;
  box-shadow: 2px 3px 0 rgba(51, 48, 43, .07);
}
.lab-patternlab > h2 {
  margin: 0 0 10px; font-family: var(--font-body); font-size: 20px; font-weight: 700;
}
.lab-patternlab-lead { margin: 0; font-size: 13px; line-height: 1.8; color: var(--ink-soft); }

/* 下拉 + 切换按钮一行。上游 .ecs-toolbar 就是这个排法（flex + wrap + 10px 间距）。 */
.lab-patternlab-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin: 14px 0 0; }
.lab-patternlab-toolbar label {
  display: flex; align-items: center; gap: 0;
  font-family: var(--font-ui); font-size: 13px; color: var(--ink-soft);
}
.lab-patternlab-toolbar select {
  padding: 6px 10px; background: var(--paper-card);
  color: var(--ink); border: var(--w-note) solid var(--ink-faint);
  border-radius: 12px 5px 11px 5px / 5px 11px 5px 12px;
  font-family: var(--font-body); font-size: 13px;
}
.lab-patternlab-toolbar select:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* 切换按钮。按下去的样式与「遮住中文」那类同一副：正在起作用的那副。 */
.lab-patternlab-toggle {
  padding: 4px 12px 5px; background: var(--paper); cursor: pointer; color: var(--ink-soft);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 14px 5px 13px 5px / 5px 13px 5px 14px;
  font-family: var(--font-body); font-size: 13px;
}
.lab-patternlab-toggle:hover { border-color: var(--accent); color: var(--accent); }
.lab-patternlab-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.lab-patternlab-toggle[aria-pressed='true'] {
  border-color: var(--accent); background: var(--marker); color: var(--accent);
}

/* 词块条。上游 .ecx-tokens 就是 flex + wrap + 10px 间距 + 上下 20px 留白。 */
.lab-patternlab-stage { padding: 6px 0; }

/* 整句英文。和方向图、数词工具、双尺同一档：它是**给人读的**英文。 */
.lab-patternlab-english {
  margin: 8px 0 10px; font-family: var(--font-note); font-size: 27px; line-height: 1.3;
  color: var(--ink);
}
/* 讲解条。与方向图那条同一副样子：左边一道竖线的浅底块。 */
.lab-patternlab-note {
  margin: 0; padding: 9px 14px; font-size: 13px; line-height: 1.8;
  color: var(--ink); background: var(--paper);
  border-left: 4px solid var(--action); border-radius: 0 10px 10px 0;
}
.lab-patternlab-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 10px 0 0; }
/* 只有 perfect-continuous 那一页有的指回链接（上游给 .ecx-activity a 的颜色）。 */
.lab-patternlab-link {
  display: inline-block; margin: 12px 0 0; color: #75518b; text-decoration: none;
  font-family: var(--font-ui); font-size: 13px;
}
.lab-patternlab-link:hover { text-decoration: underline; }

/* ---------- 易混词对照（pos-word-contrasts 一页的活动） ---------- */
/* 上游这一块是**两层同款卡**：外层只放「选择易混词组」那一个下拉，里层就是
   情境图的一整块（MM 把选中的组交给跟那 4 页同一个 Qv）。本地照做 ——
   里层直接复用 .lab-scenes，所以这里只管外层与下拉，再把里层那 30px 的段落
   间距收掉，免得卡中又空出一段。 */
.lab-wordcontrasts {
  padding: 18px 20px 20px;
  background: var(--paper-card);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 225px 16px 255px 16px / 16px 255px 16px 225px;
  box-shadow: 2px 3px 0 rgba(51, 48, 43, .07);
}
.lab-wordcontrasts-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.lab-wordcontrasts-toolbar label {
  display: flex; align-items: center; gap: 0;
  font-family: var(--font-ui); font-size: 13px; color: var(--ink-soft);
}
.lab-wordcontrasts-toolbar select {
  padding: 6px 10px; background: var(--paper-card);
  color: var(--ink); border: var(--w-note) solid var(--ink-faint);
  border-radius: 12px 5px 11px 5px / 5px 11px 5px 12px;
  font-family: var(--font-body); font-size: 13px;
}
.lab-wordcontrasts-toolbar select:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* 里层那张情境卡自己带 lab-section 的 30px 上下间距，放进卡里会额外空一段。 */
.lab-wordcontrasts-host { margin: 16px 0 0; }
.lab-wordcontrasts-host > .lab-scenes { margin: 0; }

/* ---------- 句法页的活动区（疑问句变形 / 转述拨盘 / 被动翻转 / 主谓一致 / 从句盒子） ----------
   五块共用同一副外壳：和情境图、词块实验一样是「描边 + 圆角 + 浅底」的一整块卡，
   夹在导语与图解之间。上游那五个渲染函数都走 .ecs-activity 这一层，所以外壳
   本地也只写一遍，各自的差异只在卡里的几件东西（下拉、拨盘、盒子、天平）。
   词块条那条 .lab-tokens 在 stage.js 那段，五块都用同一份。 */
.lab-questiontransforms,
.lab-reportedspeech,
.lab-passiveflip,
.lab-agreementbalance,
.lab-clauseboxes {
  padding: 18px 20px 20px;
  background: var(--paper-card);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 225px 16px 255px 16px / 16px 255px 16px 225px;
  box-shadow: 2px 3px 0 rgba(51, 48, 43, .07);
}
.lab-questiontransforms > h2,
.lab-reportedspeech > h2,
.lab-passiveflip > h2,
.lab-agreementbalance > h2,
.lab-clauseboxes > h2 {
  margin: 0 0 10px; font-family: var(--font-body); font-size: 20px; font-weight: 700;
}
.lab-questiontransforms-lead,
.lab-reportedspeech-lead,
.lab-passiveflip-lead,
.lab-agreementbalance-lead,
.lab-clauseboxes-lead { margin: 0; font-size: 13px; line-height: 1.8; color: var(--ink-soft); }

/* 下拉与按钮那一行（上游 .ecs-toolbar：flex + wrap + 10px 间距）。 */
.lab-questiontransforms-toolbar,
.lab-reportedspeech-toolbar,
.lab-passiveflip-toolbar,
.lab-agreementbalance-toolbar,
.lab-clauseboxes-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; margin: 14px 0 0; }
.lab-questiontransforms-toolbar label,
.lab-reportedspeech-toolbar label,
.lab-passiveflip-toolbar label,
.lab-agreementbalance-toolbar label,
.lab-clauseboxes-toolbar label {
  display: flex; align-items: center; gap: 0;
  font-family: var(--font-ui); font-size: 13px; color: var(--ink-soft);
}
.lab-questiontransforms-toolbar select,
.lab-reportedspeech-toolbar select,
.lab-passiveflip-toolbar select,
.lab-agreementbalance-toolbar select,
.lab-clauseboxes-toolbar select {
  padding: 6px 10px; background: var(--paper-card);
  color: var(--ink); border: var(--w-note) solid var(--ink-faint);
  border-radius: 12px 5px 11px 5px / 5px 11px 5px 12px;
  font-family: var(--font-body); font-size: 13px;
}
.lab-questiontransforms-toolbar select:focus-visible,
.lab-reportedspeech-toolbar select:focus-visible,
.lab-passiveflip-toolbar select:focus-visible,
.lab-agreementbalance-toolbar select:focus-visible,
.lab-clauseboxes-toolbar select:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* 工具行里的滑杆与它那一档宽度（同 .lab-scenes-toolbar）。 */
.lab-agreementbalance-toolbar input[type='range'] { width: 150px; vertical-align: middle; }

/* 舞台：词块条 + 图（盒子里、天平下）。 */
.lab-questiontransforms-stage,
.lab-agreementbalance-stage,
.lab-passiveflip-stage { padding: 6px 0; }
.lab-questiontransforms-stage .lab-tokens,
.lab-agreementbalance-stage .lab-tokens,
.lab-passiveflip-stage .lab-tokens { padding: 4px 0; }
/* 盒子里的词块条贴着虚线槽的边，不再要 .lab-tokens 上面那道 20px 的留白。 */
.lab-clauseboxes-slot .lab-tokens { padding: 0; }

/* 整句英文。和方向图、数词工具、双尺同一档：它是**给人读的**英文。 */
.lab-questiontransforms-english,
.lab-reportedspeech-english,
.lab-passiveflip-english,
.lab-agreementbalance-english,
.lab-clauseboxes-english {
  margin: 12px 0 10px; font-family: var(--font-note); font-size: 27px; line-height: 1.3;
  color: var(--ink);
}
/* 讲解条。与方向图那条同一副样子：左边一道竖线的浅底块。 */
.lab-questiontransforms-note,
.lab-reportedspeech-note,
.lab-passiveflip-note,
.lab-agreementbalance-note,
.lab-clauseboxes-note {
  margin: 0; padding: 9px 14px; font-size: 13px; line-height: 1.8;
  color: var(--ink); background: var(--paper);
  border-left: 4px solid var(--action); border-radius: 0 10px 10px 0;
}
.lab-questiontransforms-actions,
.lab-reportedspeech-actions,
.lab-passiveflip-actions,
.lab-agreementbalance-actions,
.lab-clauseboxes-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 10px 0 0; }

/* 变形 / 翻转 / 放入从句那几个开关。与词块实验那类同一副：按下去的就是正在起作用的。 */
.lab-questiontransforms-toggle,
.lab-passiveflip-button,
.lab-clauseboxes-drag {
  padding: 7px 14px 8px; background: var(--paper); cursor: pointer; color: var(--ink-soft);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 14px 5px 13px 5px / 5px 13px 5px 14px;
  font-family: var(--font-body); font-size: 14px;
}
.lab-questiontransforms-toggle:hover,
.lab-passiveflip-button:hover,
.lab-clauseboxes-drag:hover { border-color: var(--accent); color: var(--accent); }
.lab-questiontransforms-toggle:focus-visible,
.lab-passiveflip-button:focus-visible,
.lab-clauseboxes-drag:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.lab-questiontransforms-toggle[aria-pressed='true'],
.lab-passiveflip-button[aria-pressed='true'] {
  border-color: var(--accent); background: var(--marker); color: var(--accent);
}
/* 「省略执行者」在主动句上是禁用的（没有 by 短语可省）；禁用就该看出来。 */
.lab-passiveflip-button:disabled { opacity: .45; cursor: default; }
.lab-passiveflip-button:disabled:hover { border-color: var(--ink-faint); color: var(--ink-soft); }

/* 转述拨盘：三条并排的小卡，各自一个开关。上游给的是椭圆感的圆角（50%/15%）。 */
.lab-reportedspeech-stage { display: grid; gap: 12px; margin: 14px 0 0; }
.lab-reportedspeech-context {
  margin: 0; padding: 12px 16px; font-size: 14px; line-height: 1.9;
  color: var(--ink); background: var(--paper);
  border-left: 4px solid var(--action); border-radius: 0 10px 10px 0;
}
.lab-reportedspeech-quote {
  margin: 0; font-family: var(--font-note); font-size: 24px; line-height: 1.4; color: var(--ink);
}
.lab-reportedspeech-dials { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
.lab-reportedspeech-dial {
  display: grid; gap: 8px; justify-items: center; padding: 16px 12px;
  background: var(--paper-card);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 50% / 15%;
}
.lab-reportedspeech-dial small { font-family: var(--font-ui); font-size: 12px; color: var(--ink-soft); }
.lab-reportedspeech-dial strong { font-family: var(--font-body); font-size: 18px; color: var(--ink); }
.lab-reportedspeech-dial-button {
  width: 100%; padding: 6px 10px 7px; background: var(--paper); cursor: pointer;
  color: var(--ink-soft); border: var(--w-note) solid var(--ink-faint);
  border-radius: 14px 5px 13px 5px / 5px 13px 5px 14px;
  font-family: var(--font-body); font-size: 13px;
}
.lab-reportedspeech-dial-button:hover { border-color: var(--accent); color: var(--accent); }
.lab-reportedspeech-dial-button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.lab-reportedspeech-dial-button[aria-pressed='true'] {
  border-color: var(--accent); background: var(--marker); color: var(--accent);
}
.lab-reportedspeech-timeline svg { display: block; width: 100%; height: auto; }
.lab-reportedspeech-status { margin: 0; font-size: 13px; color: var(--ink-soft); }

/* 被动那一条时间轴（过去 / 现在 / 将来）。 */
.lab-passiveflip-timeline svg { display: block; width: 100%; height: auto; max-width: 620px; }
.lab-passiveflip-link {
  display: inline-block; margin: 12px 0 0; color: var(--accent); text-decoration: none;
  font-family: var(--font-ui); font-size: 13px;
}
.lab-passiveflip-link:hover { text-decoration: underline; }

/* 天平：宽度跟着卡走，viewBox 的宽由 JS 按容器量（夹在上限 620），这里只管缩放。 */
.lab-agreementbalance-canvas { min-width: 0; max-width: 620px; }
.lab-agreementbalance-canvas svg { display: block; width: 100%; height: auto; margin: 10px auto; }

/* 从句盒子。上游 .ecx-clause-box 是**相对定位的容器**：弧线那张 svg 绝对铺满它，
   坐标由 JS 按盒子的像素盒算（见 clauseboxes.js 的 drawArc），所以这几条
   position/inset/width/height 是弧线对得齐的**前提**，不是装饰。 */
.lab-clauseboxes-stage { padding: 6px 0; }
.lab-clauseboxes-box {
  position: relative; margin: 12px 0 0;
  padding: clamp(12px, 3vw, 22px);
  background: var(--paper-card);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 14px 5px 13px 5px / 5px 13px 5px 14px;
}
.lab-clauseboxes-main { display: block; font-family: var(--font-body); font-size: 18px; color: var(--ink); }
/* 先行词降格：只有定语从句、从句放进去之后，主句那截才变成「先行词」被标出来。 */
.lab-clauseboxes-main[data-antecedent='true'] { color: var(--accent); }
.lab-clauseboxes-slot {
  margin: 12px 0 0; min-height: 84px; padding: 14px 16px;
  background: var(--paper);
  border: 2px dashed #b095c2;
  border-radius: 12px 5px 11px 5px / 5px 11px 5px 12px;
}
.lab-clauseboxes-slot[data-filled='true'] { border-style: solid; }
.lab-clauseboxes-tail { display: block; margin: 12px 0 0; font-family: var(--font-body); font-size: 18px; color: var(--ink); }
.lab-clauseboxes-arc { position: absolute; inset: 0; width: 100%; height: 100%; max-width: none; margin: 0; pointer-events: none; }
.lab-clauseboxes-arc[hidden] { display: none; }

/* ---------- 时间介词范围图（pos-prepositions 的 activity:"time-prepositions"） ----------
   与上面那五块同一副外壳。里面是上游 .etp-* 那几层：抬头 + 两栏（左范围图 /
   右例句栏）+ 固定搭配 + 「容易出错」交叉区 + 记忆顺序 + 边界折叠。 */
.lab-timeprepositions {
  padding: 18px 20px 20px;
  background: var(--paper-card);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 225px 16px 255px 16px / 16px 255px 16px 225px;
  box-shadow: 2px 3px 0 rgba(51, 48, 43, .07);
}
/* 里面还有一个小节（容易出错）自带 h2，所以选择器要认「这一层自己的那个」。 */
.lab-timeprepositions > h2 { margin: 0 0 10px; font-family: var(--font-body); font-size: 20px; font-weight: 700; }
.lab-timeprepositions-lead { margin: 0; font-size: 13px; line-height: 1.8; color: var(--ink-soft); }

/* 两栏。比例照上游（实测 337.7 : 397.3 ≈ .85fr : 1fr，间隔 28，对齐 start）；
   断点也照上游：线上在视口 1050 上下从两栏折成一栏，本地正文宽比线上窄一点点
   （左边多一条导航），所以 1050 这个数也跟着稍保守地取。 */
.lab-timeprepositions-layout {
  display: grid; grid-template-columns: .85fr 1fr;
  gap: 28px; align-items: start; margin: 24px 0 0;
}
.lab-timeprepositions-range svg,
.lab-timeprepositions-context-svg { display: block; width: 100%; }
.lab-timeprepositions-caption {
  margin: 0 0 12px; font-size: 11px; line-height: 1.8; color: var(--ink-soft);
}
.lab-timeprepositions-detail > h3 { margin: 0; font-family: var(--font-body); font-size: 18px; color: var(--ink); }
/* 例句的短语：和整句英文同一档字号，颜色由 JS 按当前那一段刷（数据里的段色）。 */
.lab-timeprepositions-phrase {
  margin: 17px 0 3px; font-family: var(--font-note); font-size: 28px; line-height: 1.4;
}
.lab-timeprepositions-reason {
  margin: 12px 0; padding: 12px 14px; font-size: 13px; line-height: 1.9;
  color: var(--ink-soft); background: var(--paper); border-radius: 5px;
}
.lab-timeprepositions-sentence { margin: 10px 0 3px; font-family: var(--font-note); font-size: 21px; line-height: 1.5; }
.lab-timeprepositions-translation { margin: 0; font-size: 13px; color: var(--ink-soft); }
.lab-timeprepositions-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 10px 0 0; }

/* 例子 chip（范围例句 / 固定搭配 / 时段 / 说法）。和情境页那些开关同一副样子：
   选中的那颗按下去、底色用 --marker。 */
.lab-timeprepositions-chips { display: flex; flex-wrap: wrap; gap: 8px; margin: 14px 0; }
.lab-timeprepositions-chips button {
  padding: 8px 12px 9px; background: var(--paper); cursor: pointer; color: var(--ink-soft);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 14px 5px 13px 5px / 5px 13px 5px 14px;
  font-family: var(--font-body); font-size: 14px;
}
.lab-timeprepositions-chips button:hover { border-color: var(--accent); color: var(--accent); }
.lab-timeprepositions-chips button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.lab-timeprepositions-chips button[aria-pressed='true'] {
  border-color: var(--accent); background: var(--marker); color: var(--accent);
}

/* 三个固定搭配那块：浅紫底的一整块（上游 #f8f5fb），与「容易出错」的引言分开。 */
.lab-timeprepositions-fixed {
  margin: 20px 0 30px; padding: 16px 18px 18px;
  background: #f8f5fb; border: var(--w-note) solid #e2d9ee; border-radius: 10px;
}
.lab-timeprepositions-fixed > strong { display: block; font-family: var(--font-ui); font-size: 13px; color: #6f65a0; }
.lab-timeprepositions-fixed > p { margin: 0; font-size: 13px; line-height: 1.9; color: var(--ink-soft); }
.lab-timeprepositions-fixed .lab-timeprepositions-chips { margin: 12px 0; }

/* 「容易出错」交叉区：三个说法是**竖排小卡**（强标题 + 提示两行），与上面那排
   单行 chip 不是一件东西，所以自己一档。 */
.lab-timeprepositions-transform { padding: 24px 0 0; border-top: var(--w-note) solid var(--ink-faint); }
.lab-timeprepositions-transform > h2 {
  margin: 0 0 10px; font-family: var(--font-body); font-size: 20px; font-weight: 700;
}
.lab-timeprepositions-intro { margin: 0; font-size: 13px; line-height: 1.8; color: var(--ink-soft); }
.lab-timeprepositions-contexts { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 9px; margin: 15px 0 20px; }
.lab-timeprepositions-contexts button {
  display: grid; gap: 3px; padding: 12px; text-align: left; cursor: pointer;
  background: var(--paper); color: var(--ink-soft);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 9px 4px 8px 4px / 4px 8px 4px 9px;
  font-family: var(--font-body);
}
.lab-timeprepositions-contexts button:hover { border-color: var(--accent); color: var(--accent); }
.lab-timeprepositions-contexts button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.lab-timeprepositions-contexts button[aria-pressed='true'] { border-color: var(--accent); background: var(--marker); color: var(--accent); }
.lab-timeprepositions-contexts strong { font-size: 14px; }
.lab-timeprepositions-contexts span { font-size: 12px; color: var(--ink-soft); }
.lab-timeprepositions-contexts button[aria-pressed='true'] span { color: var(--accent); }
.lab-timeprepositions-change {
  margin: 12px 0; padding: 12px 14px; font-size: 13px; line-height: 1.9;
  color: var(--ink); background: var(--paper);
  border-left: 4px solid var(--action); border-radius: 0 10px 10px 0;
}

/* 记忆顺序 + 边界折叠：这两块是正文的一部分，比活动区里的东西低一档。 */
.lab-timeprepositions-memory {
  margin: 23px 0 0; padding: 17px 20px 18px;
  background: #faf5e9; border: var(--w-note) solid #e1d7bc; border-radius: 9px;
  font-size: 13px; line-height: 1.8;
}
.lab-timeprepositions-memory > strong { display: block; color: #8b774c; }
.lab-timeprepositions-memory > p { margin: 6px 0 0; color: var(--ink); }
.lab-timeprepositions-boundary { margin: 17px 0 0; font-size: 13px; line-height: 1.8; color: var(--ink-soft); }
.lab-timeprepositions-boundary > summary { cursor: pointer; color: var(--action); }
.lab-timeprepositions-boundary > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.lab-timeprepositions-boundary > p { margin: 10px 0 0; }

/* ---------- 窄屏 ---------- */
/* 单列时菜单回到正文**上面**（顺着文档顺序），别再压右侧 —— 一行 262px 的菜单
   挤在手机屏上是把正文挤没。菜单默认折叠，所以顶上只多十来行。 */
@media (max-width: 820px) {
  .lab-layout { grid-template-columns: 1fr; }
  .lab-nav {
    grid-column: 1; grid-row: 1;
    border-left: none; border-bottom: var(--w-note) solid var(--ink-faint);
  }
  .lab-main { grid-column: 1; grid-row: 2; padding: 20px 18px 60px; }
  .lab-pair { grid-template-columns: 1fr; }
  /* 站头两栏上下摞起来：站名与目标在上，例句卡在下 */
  .lab-station-head { grid-template-columns: 1fr; }
  /* 地图抬头同样落回上下：标题、引子、记录卡依次排。
     别的子项本来就是「整幅一行」（grid-column: 1 / -1），单列里就只有一列，
     只剩记录卡那两行跨栏要拆掉。 */
  .lab-map { grid-template-columns: 1fr; }
  .lab-map > .lab-map-record { grid-column: 1; grid-row: auto; }
}

/* 一行两张知识点卡在 620px 以下就挤了：正文宽度 = 视口 − 2×18（≤820px 的
   .lab-main padding），两张卡加 14px 间隔要 534px，即视口 ≥570px；再往上留点
   余量给「标记已学」那排按钮不折行，取 620。 */
@media (max-width: 620px) {
  .lab-stops { grid-template-columns: 1fr; }
  /* 三张形卡：每张要放下 26px 手写体的一个词（比如 understand 的过去分词
     understood），三栏在 620px 以下只剩 150px 上下，那个词会折成两行 ——
     而这张卡的全部内容就是那一个词，折了就没法一眼扫过三形。落回一栏。 */
  .lab-irregularverbs-cards { grid-template-columns: 1fr; }
}

/* 概念两栏要的正文宽度：两栏各留 316px（那句 21px 的例句在窄一档就折得难看），
   加上 28px 间隔 = 660px，而正文宽 = 视口 − 262（导航）− 68（内边距），
   即视口 ≥990。再窄就落回上下：左边选完，右边那段正文挪到它下面。 */
/* 时间介词那两栏（范围图 | 例句栏）的收起点。上游实测在视口 1050 上下折：
   1040 还是单栏、1060 已是两栏；两栏时右边那栏要放得下 28px 的手写体短语
   （in July 之类），窄了就折行。本地正文比线上窄一条导航的宽度，所以照抄
   1050 这个数、不另算。 */
@media (max-width: 1049px) {
  .lab-timeprepositions-layout { grid-template-columns: 1fr; gap: 20px; }
}

@media (max-width: 990px) {
  .lab-concept-cols { grid-template-columns: 1fr; row-gap: 18px; }
  /* 讲解小卡落成一栏。两栏各要 (正文宽 − 55) / 2：990px 视口下正文 728 宽，
     每栏 292px；再窄一档到 900 就只剩 247，821 只剩 207 —— 14px 的正文一栏
     摆不下几个字。原站也是在 991 折的，同一个位置。 */
  .lab-step-grid { grid-template-columns: 1fr; }
}

/* 音标入门那两栏（讲解 | 例词卡）的收起点：每半 < 348px 时，例词卡里的三格图
   开始挤（/æ/、/əʊ/ 这类符号比字母宽不少）。正文宽 = 视口 − 486，所以 720px 的
   正文宽 = 视口 1206。落下之后例词卡封顶 520px（原站同款）：单栏里让一张演示卡
   横铺 794px，卡片就成了页面的一部分，不再是一张「卡」。 */
@media (max-width: 1205px) {
  .lab-intro-definition { grid-template-columns: 1fr; }
  .lab-spelling { max-width: 520px; }
}

/* 「词典里的 3 个小标记」那三张卡的收起点：每张窄于 165px 时，卡里那句解释要折成
   五行，不如落回单列读顺。正文宽 = 「≥821 时 min(视口−262, 900) − 106；≤820 时
   视口−74」—— 菜单在 820 处从右侧挪到正文顶上，正文宽跟着跳一档，倒推
   3×165 + 2×18 = 531 就得到两条互不相连的线：视口 899 与 605。这也是它不能像
   别的块那样只写一个 max-width 断点的原因：899 以下并非一路变窄。 */
@media (min-width: 821px) and (max-width: 898px) {
  .lab-intro-marks { grid-template-columns: 1fr; }
}
@media (max-width: 604px) {
  .lab-intro-marks { grid-template-columns: 1fr; }
}

/* 图谱 | 发音卡两栏的收起点：两栏各自要能放下**三个**音标格子。格子的轨道是
   minmax(104px)、间隔 10px，三个要内宽 3×104 + 2×10 = 332；加上 .lab-board 的
   左右 padding 36 与边框 3，栏宽要 371。栏宽 = (可用宽 − 22) × 0.5122，于是可用宽
   要 746；可用宽 = 「≥821 时 min(视口−262, 900) − 68（.lab-main 的左右 padding
   各 34）；≤820 时 视口−36」，倒推得视口 1077。
   差这两个像素不是小事：栏窄到只剩两个格子时，图谱一下子从 619px 长到 1112px，
   比视口还高 —— 钉在视口上的图谱会把自己的下半截留在屏幕外。
   1076 以下整页落回单列：图谱 4 个一行、619px 高，比挤成两条细栏好读。
   断点只写一条，是因为 ≤820 那一档的可用宽（最多 784）其实也够 746，
   但菜单在 820 处从右侧挪到正文顶上，那一档整页本来就在重排 —— 也与原站一致
   （原站同样在 ≤1100 落回单列）。
   phoneme.js 的 select() 里还有一次同样的判断（落回单列时点完得把卡片滚进视野），
   断点写两处已经是上限，加到第三处就是等着失配。 */
@media (max-width: 1076px) {
  .lab-workspace { grid-template-columns: 1fr; row-gap: 18px; }
  /* 单列时图谱在卡上面，再钉住它只会在滚动中把卡挤到屏幕外。 */
  .lab-board { position: static; }
}

/* ---------- 错题与间隔复习（review-plan） ---------- */
/* 这一页在原站是 KPI 面板式的：状态行 + 柱状图 + 两行小字 + 标签页 + 卡片列表。
   手绘系统里保留这套结构，只是把「面板」换成纸卡 —— 卡片、筛选按钮、圆角都
   沿用 .lab-stop 那一套数值（角半径手抄 sketch.js 的 BOX_RADII，偶数张横竖对调）。 */
.lab-review-status { margin: 0 0 14px; font-size: 15px; }

/* 未来七天。竖排 7 根柱子，今天那根换色（上游也是这一根换色：紫 vs 绿）。
   柱高不写死在 JS 里，而是把「几」和「最多几」写进 CSS 变量，由下面的
   calc() 现算 —— 于是窄屏要横过来时，只需换一条算式，不必重新量容器。 */
.lab-review-chart {
  display: flex; align-items: flex-end; gap: 8px;
  margin: 0 0 4px; padding: 10px 6px 6px; list-style: none;
  border-bottom: var(--w-note) solid var(--ink-faint);
}
.lab-review-day {
  flex: 1 1 0; min-width: 0; height: 190px;
  display: flex; flex-direction: column; align-items: center; justify-content: flex-end;
  gap: 4px;
}
/* var() 的第二参数是兜底：--max 万一没写上去，calc 会在「计算值」阶段整条失效，
   height 掉回 auto —— 柱子静默变成零高，正是最难看出来的那种坏法。 */
.lab-review-bar {
  flex: 0 0 auto; width: 58%;
  height: calc(var(--n, 0) / var(--max, 1) * 130px);
  background: var(--action);
  border-radius: 255px 10px 225px 10px / 10px 225px 10px 255px;
}
.lab-review-bar[data-today='true'] { background: var(--accent); }
/* 一列全是 0 时整张图是空的，看着像图没画出来。把柱子退到最淡的墨色，
   配上下面那句「今天没有到期的题」才算说清楚。 */
.lab-review-chart[data-empty='true'] .lab-review-bar { background: var(--ink-faint); }
.lab-review-count { font-family: var(--font-note); font-size: 18px; line-height: 1; color: var(--ink-soft); }
.lab-review-label { font-size: 12px; line-height: 1.4; color: var(--ink-soft); white-space: nowrap; }

/* 两行说明与标签页。第一行是规则（答错进复习、间隔 1/3/7/14/30），
   第二行是「记录存在哪」—— 存不下的时候要**换一句话说**，不能照旧宣称已保存。 */
.lab-review-note { margin: 10px 0 0; font-size: 13px; line-height: 1.8; color: var(--ink-soft); }
.lab-review-note[data-warn='true'] { color: var(--ink); }

.lab-review-tabs { display: flex; gap: 8px; margin: 16px 0 0; }
.lab-review-tab {
  padding: 3px 14px 4px; background: none; cursor: pointer;
  border: var(--w-note) solid var(--ink-faint); color: var(--ink-soft);
  border-radius: 255px 12px 225px 12px / 12px 225px 12px 255px;
  font-family: var(--font-body); font-size: 14px;
}
.lab-review-tab:hover { border-color: var(--accent); color: var(--accent); }
.lab-review-tab[data-on='true'] { border-color: var(--accent); background: var(--marker); color: var(--accent); }

/* 错题卡。一行两张，与 .lab-stops 同一套栅格（minmax(0, 1fr) 而不是 1fr：
   不写 0 的话轨道最小尺寸是 min-content，长标题会把某一列顶宽）。 */
.lab-review-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; margin: 18px 0 0; }
.lab-review-card {
  display: flex; flex-direction: column;
  padding: 12px 14px 14px;
  background: var(--paper-card);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 255px 16px 225px 16px / 16px 225px 16px 255px;
  box-shadow: 2px 3px 0 rgba(51, 48, 43, .07);
}
.lab-review-card:nth-child(even) { border-radius: 16px 255px 16px 225px / 225px 16px 255px 16px; }
/* 空结果那句话跨满两栏：不跨的话它只占左半边，右半边空着，像卡没渲染出来。 */
.lab-review-empty { grid-column: 1 / -1; margin: 0; color: var(--ink-soft); }
.lab-review-card-title { margin: 0; font-size: 16px; font-family: var(--font-body); font-weight: 700; }
.lab-review-card-meta { margin: 4px 0 0; font-size: 14px; }
.lab-review-card-due { margin: 2px 0 0; font-size: 13px; color: var(--ink-soft); }
/* margin-top:auto 把操作条压到卡片底部：同一行的两张卡等高，简介长短不一时
   按钮会一高一低。 */
.lab-review-card-actions {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 10px; margin-top: auto; padding-top: 10px;
}
/* 前缀 .lab-main 是必需的：正文链接的通用规则 `.lab-main a` 是 (0,1,1)，
   比单个类名高，不加的话「返回讲解」那枚的赭色会被它按下去（同 .lab-stop-practice）。 */
.lab-main .lab-review-back { color: var(--accent); font-size: 14px; }
.lab-review-swap {
  padding: 3px 12px 4px; background: none; cursor: pointer;
  border: var(--w-note) solid var(--ink-faint); color: var(--ink);
  border-radius: 255px 12px 225px 12px / 12px 225px 12px 255px;
  font-family: var(--font-body); font-size: 13px;
}
.lab-review-swap:hover { border-color: var(--accent); color: var(--accent); }

/* 「换题复习」那一块：说明在上、练习在下。练习本身是 practice-set 渲染的，
   样式归那边的 .lab-set，这里只管它落在这张卡外面时的位置。 */
.lab-review-exercise { margin: 26px 0 0; }
.lab-review-run { margin: 4px 0 0; }

/* 柱状图横过来的两条区间。竖排 7 根柱子时每根要摆得下「+6 天」这种 4 字标签，
   7 × 71 ≈ 500，所以正文窄于 500 就横排（上游的判据也是 500）。正文宽 =
   「≥821 时 min(视口 − 262, 900) − 68；≤820 时 视口 − 36」—— 菜单在 820 处从
   右侧挪到正文顶上，正文宽跳一档，倒推得两条互不相连的区间（821–829 与 ≤535），
   与 .lab-intro-marks 是同一回事。两组规则完全一样，所以写进同一个媒体查询
   列表，不抄两遍。 */
@media (min-width: 821px) and (max-width: 829px), (max-width: 535px) {
  .lab-review-chart { flex-direction: column; align-items: stretch; gap: 6px; border-bottom: 0; }
  /* 一天一行：标签在左、柱在中、数字在右。order 调序而已 —— 竖排横排共用一套
     标记，所以不改 DOM（改 DOM 就得把两种排法各画一遍）。 */
  .lab-review-day {
    flex-direction: row; align-items: center; justify-content: flex-start;
    height: auto; gap: 10px;
  }
  .lab-review-label { order: 0; flex: 0 0 auto; }
  /* 柱宽吃剩下的那一截，110px 是留给「+6 天」与数字的（上游同款留白）。 */
  .lab-review-bar { order: 1; width: calc((100% - 110px) * var(--n, 0) / var(--max, 1)); height: 16px; }
  .lab-review-count { order: 2; flex: 0 0 auto; }
}

/* 一行两张错题卡在 620px 以下就挤了（与 .lab-stops 同一个断点、同一套推算）。 */
@media (max-width: 620px) {
  .lab-review-grid { grid-template-columns: 1fr; }
}

/* ---------- 大类学习目录（parts-of-speech / sentence-structure 的 v1） ----------
   原站 `_me()`：一句引子 + 三个统计数 + 两个出口按钮，然后每个分组一张区域卡
   （栏头 + 课时卡片网格）。两块都走 .lab-region 那套纸卡（见「区域卡」一节），
   这里只补各自内部这一层：统计数排、出口按钮、卡片网格。 */

/* 统计数：三个「数 + 单位」并排，窄屏折行。
   数与单位之间不许断行 —— 「28」和「个知识点」分开会读成两个东西。 */
.lab-course-stats { display: flex; flex-wrap: wrap; gap: 10px 26px; margin: 16px 0 0; }
.lab-course-stat { display: flex; align-items: baseline; gap: 6px; margin: 0; white-space: nowrap; }
.lab-course-stat strong {
  font-family: var(--font-note); font-size: 30px; line-height: 1; color: var(--action);
}
.lab-course-stat span { font-size: 13px; color: var(--ink-soft); }

/* 两个出口。主按钮沿用 .lab-entry-link 那一档（手绘描边、--action 绿）；
   次按钮换 --accent（棕）—— 它是「换个方式看看」，不是下一步该走的路。 */
.lab-course-acts { display: flex; flex-wrap: wrap; gap: 12px; margin: 18px 0 0; }
.lab-course-link {
  display: inline-block; padding: 7px 20px 8px;
  border: var(--w-note) solid var(--action);
  border-radius: 255px 14px 225px 14px / 14px 225px 14px 255px;
  font-family: var(--font-body); font-size: 15px; color: var(--action); text-decoration: none;
}
.lab-course-link:hover { background: var(--marker); }
.lab-course-link-alt { border-color: var(--accent); color: var(--accent); }

/* 卡片网格。轨道取 230px：LESSON 号 + 两行标题 + 两行说明 + 页脚，再窄就挤成
   三行标题；min() 兜住 320px 级视口（那一档可用宽度只有 300px 出头）。 */
.lab-course-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(min(230px, 100%), 1fr));
  gap: 14px; margin: 16px 0 0;
}
/* 卡片自己画框（和 .lab-step-card、.lab-phoneme 同一族手绘边），偶数张镜像半径。
   :nth-child(even) 的错落在**同一行**里对不上栅格列 —— 这是全站一贯的做法
   （见文件头那条规范），不为了对齐栅格丢掉手绘的错落感。 */
.lab-course-card {
  display: flex; flex-direction: column;
  padding: 14px 18px 15px;
  background: var(--paper);
  border: var(--w-aux) solid var(--ink-faint);
  border-radius: 14px 5px 13px 5px / 5px 13px 5px 14px;
  color: inherit; text-decoration: none;
  transition: border-color .2s, box-shadow .2s;
}
.lab-course-card:nth-child(even) { border-radius: 5px 14px 5px 13px / 13px 5px 14px 5px; }
.lab-course-card:hover { border-color: var(--accent); box-shadow: 2px 3px 0 rgba(51, 48, 43, .09); }
/* 卡头那行小字：LESSON 号与「动手演示」共用，字号与 .lab-region-number 一档。 */
.lab-course-count {
  font-family: var(--font-ui); font-size: 11px; letter-spacing: .16em; color: var(--action);
}
.lab-course-card h3 {
  margin: 6px 0 8px; font-family: var(--font-body); font-size: 16px; font-weight: 700; color: var(--ink);
}
/* margin-top:auto 把页脚压到卡底：同一行里标题长短不一时，几张卡的页脚仍在一线上。 */
.lab-course-card p { margin: 0; font-size: 14px; line-height: 1.9; color: var(--ink-soft); }
.lab-course-meta { margin-top: auto; padding-top: 10px; font-size: 12.5px; color: var(--ink-soft); }

/* 概念图例（词性缩写表 / 词性页与句型页的术语表）：**一条一张卡**，并排铺开。
   上游 `ek()` 的 `.eg-glossary-grid` 是 `repeat(4,minmax(0,1fr))` 的四列卡网格
   （窄下来两列、再窄一列），卡是描边浅底面板 —— 不是四条通栏列表行。
   这里用自适应列而不是写死四列：本节的卡片本就有的一行话长（`run quickly（快速地
   跑）；very happy（很开心）；fast（快地）`）、有的一行话短，写死四列会让长卡
   在 390px 的手机上把例句碎成四行。190px 是按最长那条还读得成一行的下限挑的，
   min() 兜住 320px 级视口（那一档可用宽度只有 300px 出头）。 */
.lab-gloss-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(min(190px, 100%), 1fr));
  gap: 12px; margin: 14px 0;
}
/* 卡自己画框（和 .lab-step-card、.lab-course-card 同一族手绘边），偶数张镜像半径。
   背景用 --paper 而不是页面底纸：上游那档也是 `background:#fbfcf6`，比页面底略亮。 */
.lab-gloss {
  padding: 13px 16px 14px;
  background: var(--paper);
  border: var(--w-aux) solid var(--ink-faint);
  border-radius: 14px 5px 13px 5px / 5px 13px 5px 14px;
}
.lab-gloss:nth-child(even) { border-radius: 5px 14px 5px 13px / 13px 5px 14px 5px; }
/* 卡头：符号与中文并排、基线对齐，两者都短，一行放得下就不断行。 */
.lab-gloss-head { display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 10px; margin: 0; }
.lab-gloss-symbol { font-family: var(--font-note); font-size: 23px; line-height: 1.2; color: var(--action); }
.lab-gloss-cn { font-size: 14px; font-weight: 700; color: var(--ink); }
/* 卡内三行（英文名 / 解释 / 例句）同档小字。dd 要显式写 margin —— 浏览器默认给
   dd 40px 的左缩进，不重置这张卡会整块右移。 */
.lab-gloss dd { margin: 6px 0 0; font-size: 13px; line-height: 1.85; color: var(--ink-soft); }
/* 英文名（noun / verb…）走手写体、比解释大一号：它是这条的主词，其余三行都是注。 */
.lab-gloss-en { font-family: var(--font-note); font-size: 16px; line-height: 1.4; }
/* 例句顶上一条虚线，和解释分开（上游 `.eg-term-example{padding-top:9px;border-top:1px}`）。 */
.lab-gloss-example { padding-top: 8px; border-top: 1px dashed var(--ink-faint); }

/* 词性缩写表的折叠（`.lab-glossary-more`）：11 条只摊开头 4 条，其余折起。
   样式照 .lab-mnemonics 那套（左侧一条虚线 + 手写体标题）—— 同一件东西
   （一条可展开的补充内容）在别处的画法，不另立一套。 */
.lab-glossary-more { margin-top: 6px; padding-left: 12px; border-left: var(--w-aux) dashed var(--ink-faint); }
.lab-glossary-more summary {
  padding: 8px 0; cursor: pointer;
  font-family: var(--font-body); font-size: 15px; color: var(--accent);
}
.lab-glossary-more summary:hover { text-decoration: underline; }
/* 折起来的那半张表顶上不留空白：details 展开后紧跟 summary，网格自己的 14px
   上边距叠在 summary 的 8px 下内边距上会空出一格。 */
.lab-glossary-more .lab-gloss-grid { margin-top: 0; }

/* ---------- 课时页的页壳导航 ----------
   面包屑 / 学习层级条 / 上一课下一课，三块都是上游 `cg()` 那套壳里的东西
   （`.eg-breadcrumb` / `.ecs-guide` / `.eg-lesson-navigation`）。上游的样式表
   是一份没混淆的独立 CSS，间距、折行、字号照它抄；颜色换成我们的纸墨，
   但**保留上游那份区分**：面包屑与上一课/下一课是绿（--action，同侧栏的链接），
   先修条里的链接是另一个色（--accent，上游那里是紫 —— 换个色才认得出
   「这一格的链接不是去别处的路，是先修」）。 */

/* 面包屑：一格一格的文字（上游整条是淡绿 #88957b，链接是 #6c8858）。
   分隔符是 aria-hidden 的斜杠，读屏不念它。
   align-items:center 而不是 baseline —— 三种格子混排时基线对不齐，中间那条
   斜杠会浮起来。 */
.lab-crumb {
  display: flex; align-items: center; flex-wrap: wrap; gap: 6px;
  margin: 0 0 22px; font-size: 12px; color: var(--ink-soft);
}
.lab-crumb-sep { color: var(--ink-faint); }
.lab-crumb a { color: var(--action); }
.lab-crumb a:hover { text-decoration: underline; }

/* 学习层级与先修条。整条是一张淡绿的底（上游 #f1f5e9），因为它是**建议**、
   不是正文 —— 和 02/03 那些手绘卡片区分开。条里的字本身也是绿的（上游
   #708360），所以整条设 --action；脚注退一档用 --ink-soft。
   flex-basis:100% 让脚注独占一行：它是这条横幅的说明，不是第三个先修。 */
.lab-guide {
  display: flex; align-items: center; flex-wrap: wrap; gap: 10px;
  margin: 0 0 24px; padding: 13px 16px;
  background: rgba(95, 127, 82, .09); color: var(--action);
  border-radius: 12px; font-size: 13px;
}
/* 层级标签（入门必学 / 中考重点 / 拓展）：一枚小圆片，比条里其余的字小一号。
   宽度不写 fit-content —— 弹性项本来就只占内容宽。 */
.lab-guide-band {
  display: inline-block; padding: 2px 9px 3px; border-radius: 12px;
  background: rgba(95, 127, 82, .16); color: var(--action);
  font-family: var(--font-ui); font-size: 11px; font-weight: 600;
}
.lab-guide a { color: var(--accent); }
.lab-guide a:hover { text-decoration: underline; }
.lab-guide small { flex-basis: 100%; font-size: 12px; color: var(--ink-soft); }

/* 上一课 / 返回 / 下一课：两端对齐的一行（上游 .eg-lesson-navigation）。
   首课没有「上一课」、末课没有「下一课」，只剩两格时一样两端撑开 ——
   space-between 就是这个行为，不必为两种格数分两套。 */
.lab-lesson-nav {
  display: flex; justify-content: space-between; flex-wrap: wrap; gap: 10px 20px;
  margin: 28px 0 0; font-size: 12px;
}
.lab-lesson-link { color: var(--action); }
.lab-lesson-link:hover { text-decoration: underline; }

/* ---------- 代词替换与人物关系互动（pos-pronouns 的 activity 区） ----------
   这一区不是 02/03/04/05 那种编号小节：它没有「NN / 小节名」的眉标，眉标位置写的
   是一句引导语（上游就是拿 .eg-section-number 这一格放那句话的），所以沿用
   .lab-region-number / .lab-region-title 的字号，但不套 .lab-region 那张卡。 */
.lab-pronoun-scenes { display: flex; flex-wrap: wrap; gap: 8px; margin: 14px 0 10px; }
.lab-pronoun-scene {
  padding: 5px 13px 6px; background: none; cursor: pointer; color: var(--ink);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 255px 14px 225px 14px / 14px 225px 14px 255px;
  font-family: var(--font-body); font-size: 14px;
}
.lab-pronoun-scene:nth-child(even) { border-radius: 14px 255px 14px 225px / 225px 14px 255px 14px; }
.lab-pronoun-scene[aria-pressed='true'] { border-color: var(--accent); background: var(--marker); color: var(--accent); }
/* 「用代词代替名字」是这一区的**动作**，不是又一个情境：给它实底，和上面那排
   选择器分开。按下之后文字变成「还原名字，做个对照」，颜色跟着走到 --action。 */
.lab-pronoun-replace {
  padding: 5px 14px 6px; cursor: pointer; color: var(--action);
  background: var(--paper); border: var(--w-note) solid var(--action);
  border-radius: 14px 5px 13px 5px / 5px 13px 5px 14px;
  font-family: var(--font-body); font-size: 14px;
}
.lab-pronoun-replace[aria-pressed='true'] { background: var(--marker); }

.lab-pronoun-stage { margin: 16px 0 0; }
.lab-pronoun-stage svg { display: block; }
/* 人和卡都是可点的：手型提示 + 焦点描边。SVG 的 <g> 拿不到 CSS 的 outline，
   用 stroke 变粗来表态（和 languageMap 的站点卡同一条）。 */
.lab-pronoun-person { cursor: pointer; }
.lab-pronoun-person:focus { outline: none; }
.lab-pronoun-person:focus .lab-pronoun-card,
.lab-pronoun-person:hover .lab-pronoun-card { stroke-width: 3.4; }

/* 句子与译文照 03 例句那一档（.lab-line-en / .lab-line-cn）：同一个页面里
   同样的东西要用同样的字号，改一处要同步另一处。 */
.lab-pronoun-sentence { margin: 14px 0 2px; font-family: var(--font-note); font-size: 23px; line-height: 1.3; }
.lab-pronoun-translation { margin: 0; color: var(--ink-soft); font-size: 14px; }
/* 反馈行照 .lab-diagram-feedback（同一层信息：现在这一句里谁是什么工作），
   min-height 压住「有解说 / 没解说」两种选中之间那一跳。 */
.lab-pronoun-feedback {
  min-height: 20px; margin: 10px 0 0; padding: 9px 14px;
  font-size: 13px; line-height: 1.8; color: var(--ink);
  background: var(--paper); border-left: 4px solid var(--action);
  border-radius: 0 10px 10px 0;
}
.lab-pronoun-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 12px 0 0; }
.lab-pronoun-actions .lab-speak { display: inline-flex; align-items: center; }

/* 折叠区：八行对照表。窄屏上整张表横向滚动，所以外面套一层 overflow-x ——
   六列压到手机上会挤成两三个字一行的窄条，那不是「看不清」而是看不懂。 */
.lab-pronoun-reference { margin: 18px 0 0; font-size: 13px; color: var(--ink-soft); }
.lab-pronoun-reference summary { cursor: pointer; color: var(--action); font-size: 14px; }
.lab-pronoun-reference summary:hover { text-decoration: underline; }
.lab-pronoun-note { margin: 8px 0; line-height: 1.8; }
.lab-pronoun-table-wrap { overflow-x: auto; margin: 10px 0; }
.lab-pronoun-table { border-collapse: collapse; font-size: 13px; color: var(--ink); }
.lab-pronoun-table caption {
  text-align: left; padding-bottom: 6px; font-size: 12px; color: var(--ink-soft);
}
.lab-pronoun-table th, .lab-pronoun-table td {
  padding: 5px 10px; border: var(--w-note) solid var(--ink-faint); text-align: left;
  white-space: nowrap;
}
.lab-pronoun-table thead th { background: var(--marker); font-weight: 400; color: var(--ink-soft); }
.lab-pronoun-table tbody th { font-weight: 400; color: var(--action); }

/* ---------- 形容词与副词（pos-adjectives 的 activity:"adjectives"） ----------
   上游这一页的活动是**一个渲染函数画三段**：先认识 → 动手试一试 → 中考深化。
   本地也是一个组件三节顺次排下来，所以三节共用同一副纸卡外壳（和 time-prepositions
   那张同一档：手绘错落圆角 + 2px 错位阴影）。

   下面的色值大多照抄上游的 `.eax-*` / `.eadj-*`：定义卡里「形容词绿 / 副词紫」的
   对照底色、说给 10 岁孩子听那块浅绿、记忆句的米黄、六个考点 tab 的紫焦点圈 ——
   这些色是这一页的辨认度所在，换成全站通用的灰反而看不出「两栏是对照的」。
   凡是与全站共用件重合的（按钮、喇叭、例句字号）仍走本地的 var()。 */
.lab-eax-definitions,
.lab-eadj-activity,
.lab-eax-exam {
  margin: 28px 0; padding: 25px; min-width: 0;
  background: var(--paper-card);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 225px 16px 255px 16px / 16px 255px 16px 225px;
  box-shadow: 2px 3px 0 rgba(51, 48, 43, .07);
}
.lab-eax-definitions h2,
.lab-eax-exam h2,
.lab-eadj-activity h2 {
  margin: 5px 0 15px; font-family: var(--font-body); font-size: 23px;
  font-weight: 700; color: var(--ink);
}
/* 考点区的标题带 tabindex=-1，是「直接看中考重点」的落点。它不可操作，
   聚焦时不该画一圈像按钮的框。 */
.lab-eax-exam h2:focus { outline: none; }

.lab-eax-intro, .lab-eadj-intro, .lab-eadj-instruction {
  margin: 9px 0 16px; font-size: 13px; line-height: 1.8; color: var(--ink-soft);
}
/* 「标准定义 / 说给 10 岁孩子听」这类小字标签：和 .lab-region-number 同一档，
   是给下面那段话贴的名字，不是正文。 */
.lab-small-label { display: block; margin-bottom: 6px; font-size: 11px; color: #758965; }

/* --- 一、两张定义卡 --- */
.lab-eax-definition-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px; }
.lab-eax-definition-grid article {
  padding: 21px; min-width: 0;
  background: #f8faf2; border: var(--w-note) solid #dce6ce; border-radius: 12px;
}
/* 第二张（副词）换紫底。形容词 / 副词是一对对照卡，底色一分家，
   不用读标题也知道左右是两种词性。 */
.lab-eax-definition-grid article + article { background: #f8f4fa; border-color: #e2d6e9; }
.lab-eax-definition-grid h3 {
  margin: 0; font-family: var(--font-body); font-size: 19px; font-weight: 700; color: #56793f;
}
.lab-eax-definition-name { margin: 4px 0 19px; font-family: var(--font-note); font-size: 20px; color: #8b947c; }
.lab-eax-standard { margin: 0; font-size: 13px; line-height: 1.9; color: #597148; }
.lab-eax-simple {
  margin: 16px 0; padding: 14px;
  background: #eef3e5; border-left: 3px solid #a4bb87; border-radius: 6px;
}
.lab-eax-simple p { margin: 0; font-size: 14px; line-height: 1.9; color: #587441; }
.lab-eax-definition-grid article + article .lab-eax-simple {
  background: #efe8f4; border-left-color: #b29ac3;
}
.lab-eax-definition-grid article + article .lab-eax-simple p { color: #78618a; }
/* 例子与译文：字号照全站的英文例句档（.lab-line-en 的 23px / --font-note），
   同一个「这是英语例句」的信号，全站只用一种长相。 */
.lab-eax-definition-example { margin: 0; font-family: var(--font-note); font-size: 23px; line-height: 1.6; color: #536f3f; }
.lab-eax-definition-translation { margin: 6px 0 12px; font-size: 12px; line-height: 1.8; color: #7b8a6d; }
.lab-eax-definition-memory { margin: 19px 0 12px; font-size: 13px; line-height: 1.8; color: #6b7e59; }

/* --- 按钮族：tab 条 / 选项 / 易混词切换 / 跳转键，上游共用一副长相 --- */
.lab-eax-tabs button,
.lab-eax-choices button,
.lab-eax-word-switch button,
.lab-eax-jump,
.lab-eadj-activity button {
  min-height: 42px; max-width: 100%; padding: 10px 13px; text-align: left;
  overflow-wrap: anywhere; cursor: pointer;
  background: var(--paper); color: var(--ink-soft);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 14px 5px 13px 5px / 5px 13px 5px 14px;
  font-family: var(--font-body); font-size: 13px; line-height: 1.5;
}
.lab-eax-tabs button:hover,
.lab-eax-choices button:hover,
.lab-eax-word-switch button:hover,
.lab-eax-jump:hover,
.lab-eadj-activity button:hover { border-color: var(--action); color: var(--action); }
.lab-eax-tabs button:focus-visible,
.lab-eax-choices button:focus-visible,
.lab-eax-word-switch button:focus-visible,
.lab-eax-jump:focus-visible,
.lab-eax-table-scroll:focus-visible,
.lab-eadj-activity button:focus-visible { outline: 2px solid #b39ac7; outline-offset: 2px; }
/* 选中：底下一道内阴影（上游 box-shadow: inset 0 -2px），像被按住的键。 */
.lab-eax-tabs button[aria-selected='true'],
.lab-eax-choices button[aria-pressed='true'],
.lab-eax-word-switch button[aria-pressed='true'] {
  color: var(--action); background: var(--marker); border-color: var(--action);
  box-shadow: inset 0 -2px var(--action);
}
.lab-eadj-activity button[aria-pressed='true'] {
  color: var(--action); background: var(--marker); border-color: var(--action);
  box-shadow: inset 0 0 0 1px var(--action);
}
.lab-eax-jump { margin: 19px 0 0; }

/* 六个考点 tab：一行六格，宽度不够就折成三格 / 两格（上游同样两个断点）。 */
.lab-eax-tabs {
  display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 8px;
  padding-bottom: 20px; margin-bottom: 23px;
  border-bottom: var(--w-note) solid var(--ink-faint);
}
.lab-eax-tabs button { padding: 12px 7px; text-align: center; font-weight: 700; }

/* --- 考点面板内部 --- */
.lab-eax-view { min-width: 0; }
.lab-eax-view h3 {
  margin: 0 0 16px; font-family: var(--font-body); font-size: 21px; line-height: 1.6; color: var(--ink);
}
/* 面板顶上那两条「一句话定义」：左绿右米黄，两种词性各占一格。 */
.lab-eax-topic-definitions { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin-bottom: 20px; }
.lab-eax-topic-definitions > div { padding: 13px 16px; border-radius: 9px; background: #f3f6ec; }
.lab-eax-topic-definitions > div + div { background: #f6f0e4; }
.lab-eax-topic-definitions span { font-size: 11px; color: #8b9479; }
.lab-eax-topic-definitions p { margin: 4px 0 0; font-size: 13px; line-height: 1.85; color: #62794f; }

.lab-eax-choices, .lab-eax-word-switch { display: flex; flex-wrap: wrap; gap: 8px; margin: 12px 0; }
.lab-eax-word-switch button { font-size: 12px; }
.lab-eax-controls [hidden] { display: none !important; }

/* 口诀条：米黄底 + 左侧一道粗线，与 .lab-eadj-memory 同一件东西。 */
.lab-eax-memory {
  margin: 15px 0; padding: 12px 16px; border-radius: 5px;
  background: #f7f1e5; border-left: 3px solid #c6b184;
  font-size: 13px; line-height: 1.9; color: #8e7446;
}

/* 图框：把图与「定义 / 选项」分开，否则图像是选项的一部分。 */
.lab-eax-picture {
  margin: 18px 0; padding: 16px; min-width: 0;
  background: #fcfdf8; border: var(--w-note) solid #e0e7d6; border-radius: 12px;
}
.lab-eax-picture-title { margin: 0 0 9px; font-size: 12px; line-height: 1.9; color: #7b8b6b; }
/* 图上写死的宽度上限：图是按容器宽度现算的，放开到整栏会横得看不完。 */
.lab-eax-chart { display: block; width: 100%; max-width: 820px; margin: 0 auto; overflow: visible; }
/* 图上每一块自己绑了 click，字压在块上会把它挡住 —— 字不吃指针。 */
.lab-eax-chart text { pointer-events: none; }

/* 可点的图块：手型 + 焦点变粗。SVG 的 <g> 拿不到 CSS 的 outline，
   和 .lab-pronoun-person 同一条路（stroke 加粗表态）。 */
.lab-eax-map-node, .lab-eax-feeling-node, .lab-eax-bar, .lab-eax-trend-point,
.lab-eax-book, .lab-eadj-token, .lab-eadj-person { cursor: pointer; }
.lab-eax-map-node:focus, .lab-eax-feeling-node:focus, .lab-eax-bar:focus,
.lab-eax-trend-point:focus, .lab-eax-book:focus, .lab-eadj-token:focus,
.lab-eax-map-node:focus-visible, .lab-eax-feeling-node:focus-visible,
.lab-eax-bar:focus-visible, .lab-eax-trend-point:focus-visible,
.lab-eax-book:focus-visible, .lab-eadj-token:focus-visible,
.lab-eg-sentence-block:focus-visible { outline: none; }
.lab-eax-map-node:focus rect, .lab-eax-map-node:hover rect,
.lab-eax-feeling-node:focus rect, .lab-eax-feeling-node:hover rect,
.lab-eax-bar:focus .lab-eax-row-background, .lab-eax-bar:hover .lab-eax-row-background,
.lab-eax-trend-point:focus .lab-eax-point-hit, .lab-eax-trend-point:hover .lab-eax-point-hit,
.lab-eax-book:focus rect, .lab-eax-book:hover rect,
.lab-eadj-token:focus rect, .lab-eadj-token:hover rect,
.lab-eadj-person:focus .lab-eadj-person-body, .lab-eadj-person:hover .lab-eadj-person-body,
.lab-eg-sentence-block:focus rect, .lab-eg-sentence-block:hover rect { stroke-width: 3.4; }

/* SVG 上的字：字号与色一律走这里（几何在内联属性里，字在 CSS 里，
   和上游一样 —— 图按容器宽度重画时只有坐标变，字号不该跟着抖）。 */
.lab-eax-node-kicker, .lab-eax-node-role, .lab-eax-relation-label { font: 11px var(--font-ui); fill: #7d8c6d; }
.lab-eax-node-word { font-family: var(--font-note); fill: #556e44; }
.lab-eax-feeling-subject { font: 23px var(--font-note); fill: #6d785d; }
.lab-eax-feeling-word { font: 25px var(--font-note); fill: #86629b; }
.lab-eax-bar-name { font-family: var(--font-note); font-size: 17px; fill: #577443; }
.lab-eax-bar-number { font: 13px var(--font-ui); fill: #7b6a90; }
.lab-eax-bar-detail { font: 11px var(--font-ui); fill: #859375; }
.lab-eax-stage, .lab-eax-unit, .lab-eax-value-axis, .lab-eax-point-value {
  font: 11px var(--font-ui); fill: #7d8e6b; color: #9ba98c;
}
.lab-eax-value-axis .domain, .lab-eax-value-axis line { stroke: #d1ddc4; }
.lab-eax-capacity-label { font: 11px var(--font-ui); fill: #8c6da0; }
.lab-eax-box-count, .lab-eax-lift-status { font: 12px var(--font-ui); fill: #6d805a; }
.lab-eax-weekday, .lab-eax-day-mark, .lab-eax-frequency-summary { font: 12px var(--font-ui); fill: #798b66; }
.lab-eax-day-mark { fill: #587641; }
.lab-eadj-token-text, .lab-eadj-person-name { font-family: var(--font-note); font-size: 20px; fill: #4f713d; }
.lab-eadj-token-role { font: 10px var(--font-ui); fill: #7a8b66; }
.lab-eadj-picture-label { font: 17px var(--font-note); fill: #688351; }
.lab-eadj-height { font: 14px var(--font-ui); fill: #6d7d5c; }
.lab-eadj-rank { font: 12px var(--font-ui); fill: #668847; }
.lab-eg-block-number { font: 11px var(--font-ui); }
.lab-eg-block-english { fill: #42583a; font: 19px var(--font-note); }
.lab-eg-block-role { font: 12px var(--font-ui); }
.lab-eg-sentence-diagram { display: block; width: 100%; overflow: visible; }

/* 结果区：例句 + 译文 + 一句为什么，浅绿底 + 左侧粗线。
   三段的 result 用同一个盒子（上游 .eax-result / .eadj-result 只差圆角）。 */
.lab-eax-result, .lab-eadj-result {
  padding: 19px 22px; background: #f2f6eb; border-left: 4px solid var(--action);
  border-radius: 10px;
}
.lab-eax-example, .lab-eadj-result > p:first-child {
  margin: 0; font-family: var(--font-note); font-size: 24px; line-height: 1.65;
  color: #496837; overflow-wrap: anywhere;
}
.lab-eax-chinese { margin: 7px 0 10px; font-size: 13px; line-height: 1.8; color: #7a8b68; }
.lab-eadj-result > p:nth-child(2) { margin: 5px 0 10px; font-size: 13px; line-height: 1.8; color: #7d8c6d; }
.lab-eax-note { margin: 0 0 13px; font-size: 13px; line-height: 1.9; color: #667d53; }
.lab-eadj-result > p[role='status'] { margin: 0 0 12px; font-size: 13px; line-height: 1.8; color: #637b50; }
/* 结果里那排喇叭：和 .lab-pronoun-actions 一样压成一行中线对齐。 */
.lab-eax-result .lab-speak, .lab-eadj-result .lab-speak { display: inline-flex; align-items: center; }
.lab-eax-result > div, .lab-eadj-result > div { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }

/* 程度句型那条公式：紫底，和「易混词」的紫一个色系。 */
.lab-eax-formula {
  padding: 11px 15px; border-radius: 8px; overflow-wrap: anywhere;
  background: #f5eff8; font-size: 14px; line-height: 1.8; color: #876ba0;
}
/* 比较句型里那根人数滑杆：标签在上、滑杆在下。 */
.lab-eax-slider {
  display: grid; gap: 6px; margin: 15px 0; padding: 13px 16px;
  background: #f2f6eb; border-radius: 9px; font-size: 13px; color: #748960;
}
.lab-eax-slider input { width: 100%; min-width: 0; min-height: 34px; accent-color: var(--action); cursor: pointer; }

/* --- 动手试一试：书包 / 身高两块 --- */
.lab-eadj-tabs, .lab-eadj-switch, .lab-eadj-tools, .lab-eadj-form-choices {
  display: flex; flex-wrap: wrap; gap: 9px; margin: 16px 0;
}
.lab-eadj-tabs {
  padding-bottom: 18px; margin-bottom: 23px;
  border-bottom: var(--w-note) solid var(--ink-faint);
}
.lab-eadj-tabs button { padding: 12px 16px; font-size: 15px; text-align: center; }
.lab-eadj-options { display: flex; flex-wrap: wrap; gap: 20px 35px; }
.lab-eadj-options > div > span { display: block; margin-bottom: 6px; font-size: 12px; color: #869573; }
.lab-eadj-options [role='group'] { display: flex; flex-wrap: wrap; gap: 8px; }
.lab-eadj-bag-svg, .lab-eadj-heights-svg {
  display: block; width: 100%; max-width: 800px; margin: 0 auto 18px; overflow: visible;
}
.lab-eadj-memory {
  margin: 18px 0 0; padding-left: 13px; font-size: 13px; line-height: 1.8; color: #99723d;
  border-left: 2px solid #c6ab7b;
}
.lab-eadj-sliders { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 16px; }
.lab-eadj-sliders label {
  display: flex; flex-direction: column; padding: 12px;
  background: #fafbf6; border: var(--w-note) solid #dce5cf; border-radius: 9px;
}
.lab-eadj-sliders span { font-size: 13px; color: #6d8458; }
.lab-eadj-sliders input { width: 100%; min-height: 34px; accent-color: var(--action); cursor: pointer; }

/* 词形变形器折叠区：它是「动手试一试」下面的一层延伸，用上边框分开，
   不与上面的结果区抢位置。 */
.lab-eadj-forms { margin-top: 24px; padding-top: 16px; border-top: var(--w-note) solid var(--ink-faint); }
.lab-eadj-forms summary { padding: 4px 0; font-size: 13px; color: var(--action); cursor: pointer; }
.lab-eadj-forms summary:focus-visible { outline: 2px solid #b39ac7; outline-offset: 2px; }
.lab-eadj-form-rule { margin: 15px 0; font-size: 15px; line-height: 1.8; color: #886a42; }
/* 点词块后那一行「这块在做什么？」：浅绿底，压住有解说 / 没解说之间的一跳。 */
.lab-eadj-forms > p[role='status'] {
  min-height: 20px; margin: 12px 0; padding: 12px;
  background: #f0f4e8; border-radius: 8px; font-size: 13px; line-height: 1.8; color: var(--ink);
}
.lab-eadj-forms > div { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }

/* --- 引用表（六个考点里凡有对照表的都走这一个壳） --- */
.lab-eax-reference { margin-top: 21px; padding-top: 12px; border-top: var(--w-note) solid var(--ink-faint); }
.lab-eax-reference summary { padding: 7px 0; font-size: 14px; color: var(--action); cursor: pointer; }
.lab-eax-table-hint { margin: 8px 0 11px; font-size: 11px; line-height: 1.8; color: #8b9a7b; }
/* 表格宽（最窄 620px），窄屏上必须能横着划 —— 压成两三个字一行就不是「看不清」
   而是看不懂。tabindex=0 + role=region 让键盘也能滚。 */
.lab-eax-table-scroll { overflow-x: auto; width: 100%; scrollbar-width: thin; scrollbar-color: #a5bd8b #f3f6ec; }
.lab-eax-table-scroll::-webkit-scrollbar { height: 5px; }
.lab-eax-table-scroll::-webkit-scrollbar-thumb { background: #a5bd8b; border-radius: 5px; }
.lab-eax-table-scroll::-webkit-scrollbar-track { background: #f3f6ec; }
.lab-eax-reference table {
  border-collapse: collapse; width: 100%; min-width: 620px;
  font-size: 13px; color: #667c52; text-align: left;
}
/* 表题视觉上不出现，但读屏要念（否则展开一张表只听到列名）。 */
.lab-eax-reference caption {
  position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%);
}
.lab-eax-reference th, .lab-eax-reference td {
  padding: 12px 14px; border: var(--w-note) solid #dce5d2; vertical-align: top; line-height: 1.8;
}
.lab-eax-reference th { font-weight: 500; background: #edf3e4; color: #688151; }
.lab-eax-reference tbody tr:nth-child(2n) { background: #f8faf3; }
.lab-eax-reference td:first-child { min-width: 110px; color: #526f3e; }
.lab-eax-reference td .lab-speak { display: inline-flex; align-items: center; margin-top: 7px; }

/* 六个 tab 的断点照上游：六格 → 三格 → 两格。 */
@media (max-width: 1100px) {
  .lab-eax-tabs { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 650px) {
  .lab-eax-definitions, .lab-eadj-activity, .lab-eax-exam { padding: 16px; }
  .lab-eax-definition-grid, .lab-eax-topic-definitions { grid-template-columns: minmax(0, 1fr); }
  .lab-eax-definition-grid article { padding: 16px; }
  .lab-eax-tabs { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .lab-eax-tabs button { font-size: 12px; }
  .lab-eax-picture { padding: 9px; }
  .lab-eax-result, .lab-eadj-result { padding: 15px; }
  .lab-eax-example, .lab-eadj-result > p:first-child { font-size: 21px; }
  .lab-eax-choices button, .lab-eax-word-switch button { font-size: 12px; }
  .lab-eax-topic-definitions { gap: 8px; }
}
@media (max-width: 540px) {
  .lab-eadj-tabs { display: grid; grid-template-columns: 1fr; }
  .lab-eadj-tabs button { text-align: left; }
  .lab-eadj-sliders { grid-template-columns: 1fr; }
  .lab-eadj-person-name { font-size: 17px; }
}

/* ===== 时态 V1 工作台（#/tenses） ===== */
:root { --violet: #6b5bd2; }   /* 观察点专用色（上游用紫色标「观察点」） */

.lab-tenses-workspace { display: grid; grid-template-columns: 250px minmax(0, 1fr);
  gap: 24px; align-items: start; }
@media (max-width: 760px) { .lab-tenses-workspace { grid-template-columns: minmax(0, 1fr); } }

.lab-tenses-controls { display: flex; flex-direction: column; gap: 14px; }
.lab-tenses-step { margin: 0; font-size: 13px; color: var(--ink); letter-spacing: .02em; }
.lab-tenses-times { display: flex; gap: 8px; }
.lab-tenses-time { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding: 8px 6px; font-family: var(--font-body); font-size: 15px; color: var(--ink);
  background: var(--paper-card); border: 1.5px solid var(--ink-faint); cursor: pointer;
  border-radius: 14px 220px 14px 200px / 200px 14px 220px 14px; }
.lab-tenses-time small { font-family: var(--font-note); font-size: 13px; color: var(--ink-soft); }
.lab-tenses-time.is-active { border-color: var(--ink); background: var(--marker); }

.lab-tenses-aspects { display: flex; flex-direction: column; gap: 8px; }
.lab-tenses-aspect { display: grid; grid-template-columns: 34px 1fr 18px; align-items: center;
  gap: 8px; padding: 8px 12px; text-align: left; font-family: var(--font-body); color: var(--ink);
  background: var(--paper-card); border: 1.5px solid var(--ink-faint); cursor: pointer;
  border-radius: 16px 255px 16px 225px / 225px 16px 255px 16px; }
.lab-tenses-aspect.is-active { border-color: var(--ink); background: var(--marker); }
.lab-tenses-sym { font-family: var(--font-note); font-size: 19px; color: var(--accent); text-align: center; }
.lab-tenses-aspect-text { display: flex; flex-direction: column; }
.lab-tenses-aspect-text strong { font-size: 15px; }
.lab-tenses-aspect-text small { font-size: 12px; color: var(--ink-soft); }
.lab-tenses-check { color: var(--action); font-size: 15px; visibility: hidden; }
.lab-tenses-aspect.is-active .lab-tenses-check { visibility: visible; }

.lab-tenses-hint { margin: 0; font-size: 12px; line-height: 1.7; color: var(--ink-soft); }
.lab-tenses-tags { display: flex; gap: 6px; }
.lab-tenses-tags span { font-size: 12px; color: var(--ink-soft);
  border: 1px dashed var(--ink-faint); border-radius: 999px; padding: 1px 8px; }

.lab-tenses-stage { min-width: 0; }
.lab-tenses-kicker { margin: 0; font-family: var(--font-note); font-size: 16px; color: var(--ink-soft); }
.lab-tenses-title-row { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.lab-tenses-title { margin: 2px 0 6px; font-size: 22px; }
.lab-tenses-ref { font-size: 12px; color: var(--violet); border: 1.5px solid var(--violet);
  border-radius: 999px; padding: 1px 10px; }
.lab-tenses-focus { margin: 0 0 10px; font-size: 15px; color: var(--ink); }
.lab-tenses-trans { margin: 2px 0; font-size: 13px; color: var(--ink-soft); }
.lab-tenses-actions { margin: 6px 0; }
.lab-tenses-summary { margin: 6px 0 0; font-size: 13px; color: var(--ink-soft); }
.lab-tenses-summary.is-band { color: var(--accent); }

.lab-tenses-chart-top { display: flex; justify-content: space-between; gap: 8px;
  margin: 12px 0 2px; font-size: 13px; color: var(--ink-soft); }
.lab-tenses-chart-svg { display: block; width: 100%; height: auto; cursor: ew-resize; }
.lab-tenses-legend { display: flex; gap: 16px; margin: 4px 0 0; padding: 0; list-style: none;
  font-size: 12px; color: var(--ink-soft); }
.lab-tenses-legend li { display: flex; align-items: center; gap: 6px; }
.lab-tenses-legend li::before { content: ''; width: 10px; height: 10px; border-radius: 50%; }
.lab-tenses-legend .is-action::before { background: var(--action); }
.lab-tenses-legend .is-ref::before { width: 14px; height: 0; border-radius: 0;
  border-top: 2px dashed var(--ink-faint); }
.lab-tenses-legend .is-obs::before { background: var(--violet); }
.lab-tenses-observation { margin: 12px 0 0; font-size: 13px; color: var(--ink); }
.lab-tenses-obs-icon { color: var(--violet); margin-right: 6px; }
.lab-tenses-observation strong { font-weight: 700; }
.lab-tenses-scrubber { display: flex; align-items: center; gap: 10px; margin-top: 8px;
  font-size: 12px; color: var(--ink-soft); }
.lab-tenses-scrubber input[type='range'] { flex: 1; accent-color: var(--violet); }
.lab-tenses-playback { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.lab-tenses-play { font-family: var(--font-body); font-size: 13px; color: var(--ink);
  background: var(--paper-card); border: 1.5px solid var(--ink-faint); cursor: pointer;
  border-radius: 14px 160px 14px 150px / 150px 14px 160px 14px; padding: 4px 12px; }
.lab-tenses-speed { font-family: var(--font-body); font-size: 13px; border: 1.5px solid var(--ink-faint);
  background: var(--paper-card); border-radius: 8px; padding: 3px 6px; }

.lab-tenses-reading { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr));
  gap: 18px; margin-top: 22px; }
.lab-tenses-reading-card { background: var(--paper-card); border: 1.5px solid var(--ink-faint);
  padding: 14px 16px; border-radius: 16px 255px 16px 225px / 225px 16px 255px 16px; }
.lab-tenses-note { border-radius: 255px 16px 225px 16px / 16px 225px 16px 255px; }
.lab-tenses-reading-card h3 { margin: 2px 0 8px; font-size: 16px; }
.lab-tenses-card-label { margin: 0; font-family: var(--font-note); font-size: 13px;
  letter-spacing: .08em; color: var(--ink-soft); }
.lab-tenses-formula-line { font-family: var(--font-note); font-size: 19px; margin: 6px 0; }
.lab-tenses-formula-hint { margin: 2px 0 8px; font-size: 13px; color: var(--ink-soft); }
.lab-tenses-signals { margin: 6px 0 2px; font-size: 13px; color: var(--accent); }
.lab-tenses-note-mark { display: block; text-align: right; color: var(--accent); font-size: 18px; }

.lab-tenses-overview { margin-top: 22px; }
.lab-tenses-overview > summary { position: relative; padding-right: 28px; cursor: pointer;
  list-style: none; }
.lab-tenses-overview > summary::-webkit-details-marker { display: none; }
.lab-tenses-overview > summary strong { font-size: 15px; }
.lab-tenses-overview > summary small { display: block; font-size: 12px; color: var(--ink-soft); }
.lab-tenses-overview-plus { position: absolute; right: 4px; top: 0;
  color: var(--ink-soft); font-size: 15px; }
.lab-tenses-matrix { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px; margin-top: 12px; }
@media (max-width: 620px) { .lab-tenses-matrix { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.lab-tenses-matrix-card { display: flex; flex-direction: column; gap: 2px; text-align: left;
  padding: 10px 12px; cursor: pointer; font-family: var(--font-body); color: var(--ink);
  background: var(--paper-card); border: 1.5px solid var(--ink-faint);
  border-radius: 14px 200px 14px 180px / 180px 14px 200px 14px; }
.lab-tenses-matrix-card[aria-pressed='true'] { border-color: var(--ink); background: var(--marker); }
.lab-tenses-matrix-card strong { font-size: 15px; }
.lab-tenses-matrix-card span { font-family: var(--font-note); font-size: 14px; color: var(--ink-soft); }
.lab-tenses-matrix-card small { font-size: 12px; color: var(--ink-soft); }
.lab-tenses-matrix-card .lab-tenses-band { color: var(--accent); }

/* ===== 时态 V2 对照学习（#/tenses/v2） ===== */
.lab-tenses2-toolbar { display: flex; flex-direction: column; gap: 10px; margin: 4px 0 18px; }
.lab-tenses2-groups { display: flex; flex-wrap: wrap; gap: 8px; }
.lab-tenses2-group { font-family: var(--font-body); font-size: 14px; color: var(--ink);
  background: var(--paper-card); border: 1.5px solid var(--ink-faint); cursor: pointer;
  padding: 5px 16px; border-radius: 14px 220px 14px 200px / 200px 14px 220px 14px; }
.lab-tenses2-group.is-active { border-color: var(--ink); background: var(--marker); }

.lab-tenses2-search-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.lab-tenses2-search { flex: 1 1 240px; min-width: 0; font-family: var(--font-body); font-size: 14px;
  color: var(--ink); background: var(--paper-card); border: 1.5px solid var(--ink-faint);
  border-radius: 10px; padding: 7px 12px; }
.lab-tenses2-search:focus { outline: none; border-color: var(--ink); }
.lab-tenses2-clear { font-family: var(--font-body); font-size: 13px; color: var(--ink);
  background: var(--paper-card); border: 1.5px solid var(--ink-faint); cursor: pointer;
  padding: 6px 12px; border-radius: 14px 160px 14px 150px / 150px 14px 160px 14px; }
.lab-tenses2-clear:disabled { color: var(--ink-faint); cursor: default; opacity: .6; }
.lab-tenses2-count { font-size: 13px; color: var(--ink-soft); }

.lab-tenses2-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20px; }
@media (max-width: 900px) { .lab-tenses2-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 600px) { .lab-tenses2-grid { grid-template-columns: minmax(0, 1fr); } }

.lab-tenses2-card { display: flex; flex-direction: column; gap: 6px; min-width: 0;
  background: var(--paper-card); border: 1.5px solid var(--ink-faint); padding: 14px 16px;
  border-radius: 16px 255px 16px 225px / 225px 16px 255px 16px; }
.lab-tenses2-card[hidden] { display: none; }
.lab-tenses2-card-label { font-family: var(--font-note); font-size: 14px; color: var(--ink-soft); }
.lab-tenses2-card-title { margin: 0; font-size: 17px; }
.lab-tenses2-card-subtitle { margin: 0; font-family: var(--font-note); font-size: 14px;
  color: var(--ink-soft); }
.lab-tenses2-example { margin: 4px 0; font-size: 15px; line-height: 1.6; }
.lab-tenses2-emphasis { color: var(--accent); font-weight: 700; }
.lab-tenses2-actions { margin: 0 0 2px; }
.lab-tenses2-figure { display: block; width: 100%; height: auto; }
.lab-tenses2-explanation { margin: 2px 0 0; font-size: 13px; color: var(--ink-soft); }
.lab-tenses2-open { margin-top: 4px; font-size: 13px; color: var(--action); }
.lab-tenses2-empty { padding: 24px 0; text-align: center; color: var(--ink-soft); }
.lab-tenses2-empty[hidden] { display: none; }

/* ---------- 英汉表达与思维（#/language-comparison） ----------
   上游这一页是五个维度工作台，每个一张区域卡：样例条 + 一个开关/复选框 + 一张
   手绘图 + 对照文字/选区说明。这里沿用全站的手绘卡腔调（纸卡底 + 错角半径 +
   浅描边），类名前缀 lab-lc-。 */

.lab-lc-page { min-width: 0; }

/* 五个维度的横向标签条。上游是五张贴纸横排；窄屏按 2/1 列折。 */
.lab-lc-tabs {
  display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 8px;
  margin: 0 0 20px; padding: 0; position: static;
}
.lab-lc-tab {
  display: flex; flex-direction: column; gap: 3px; min-width: 0; text-align: left;
  font-family: var(--font-body); font-size: 13px; color: var(--ink);
  background: var(--paper-card); border: 1.5px solid var(--ink-faint); cursor: pointer;
  padding: 10px 12px; border-radius: 14px 200px 14px 180px / 180px 14px 200px 14px;
}
.lab-lc-tab:nth-child(even) { border-radius: 200px 14px 180px 14px / 14px 180px 14px 200px; }
.lab-lc-tab:hover { border-color: var(--accent); }
.lab-lc-tab[aria-selected='true'] { border-color: var(--ink); background: var(--paper); box-shadow: inset 0 -3px 0 var(--marker); }
.lab-lc-tab-num { font-family: var(--font-ui); font-size: 11px; letter-spacing: .08em; color: var(--ink-faint); }
.lab-lc-tab-title { font-weight: 700; }
.lab-lc-tab-desc { font-size: 12px; color: var(--ink-soft); line-height: 1.5; }

/* 前提：整页的总立场，切工作台不动。 */
.lab-lc-premise {
  margin: 0 0 22px; padding: 14px 18px; background: var(--paper-card);
  border: 1.5px solid var(--ink-faint); border-left-width: 4px; border-left-color: var(--action);
  border-radius: 255px 15px 225px 15px / 15px 225px 15px 255px;
}
.lab-lc-premise strong { display: block; font-size: 15px; }
.lab-lc-premise p { margin: 4px 0 0; font-size: 13px; line-height: 1.8; color: var(--ink-soft); }

/* 标准说法 / 换个容易懂的说法：每条一段，标签加粗在前。 */
.lab-lc-explain { margin: 0 0 18px; }
.lab-lc-explain p { margin: 0 0 8px; font-size: 13.5px; line-height: 1.85; }
.lab-lc-explain p:last-child { margin-bottom: 0; }
.lab-lc-explain strong { margin-right: 6px; color: var(--accent); }

/* 工作台 = 一张区域卡。 */
.lab-lc-workspace {
  margin: 0 0 24px; padding: 18px 20px; background: var(--paper-card);
  border: 1.5px solid var(--ink-faint);
  border-radius: 16px 255px 16px 225px / 225px 16px 255px 16px;
}

/* 样例条：一排贴纸，选中的那张实色。 */
.lab-lc-samples { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 14px; }
.lab-lc-sample {
  font-family: var(--font-body); font-size: 13px; color: var(--ink);
  background: var(--paper); border: 1.5px solid var(--ink-faint); cursor: pointer;
  padding: 6px 14px; border-radius: 225px 14px 255px 14px / 14px 255px 14px 225px;
}
.lab-lc-sample:nth-child(even) { border-radius: 14px 225px 14px 255px / 255px 14px 225px 14px; }
.lab-lc-sample:hover { border-color: var(--accent); color: var(--accent); }
.lab-lc-sample[aria-pressed='true'] { border-color: var(--ink); background: var(--marker); color: var(--ink); font-weight: 700; }

/* 开关：一排小胶囊。 */
.lab-lc-switch-host { margin: 0 0 12px; }
.lab-lc-switch { display: inline-flex; flex-wrap: wrap; gap: 0; border: 1.5px solid var(--ink-faint); border-radius: 999px; overflow: hidden; }
.lab-lc-switch button {
  font-family: var(--font-body); font-size: 13px; color: var(--ink-soft);
  background: var(--paper); border: none; cursor: pointer; padding: 6px 16px;
}
.lab-lc-switch button + button { border-left: 1.5px solid var(--ink-faint); }
.lab-lc-switch button:hover { color: var(--accent); }
.lab-lc-switch button[aria-pressed='true'] { background: var(--marker); color: var(--ink); font-weight: 700; }

/* 复选框（省略主语提示）。 */
.lab-lc-check { display: inline-flex; align-items: center; gap: 8px; margin: 0 0 12px; font-size: 13px; color: var(--ink-soft); cursor: pointer; }

/* 说明行（时间/属性/段落三块各一句）。 */
.lab-lc-instruction { margin: 0 0 12px; font-size: 12.5px; line-height: 1.8; color: var(--ink-soft); }

/* 图表区：窄屏不缩 svg，改横向滑动（上游同）。提示一行 + 可聚焦滚动区。
   svg 自带 min-width（= viewBox 宽），所以到底保持原尺寸、超宽才滑。
   外面套一层 minmax(0,1fr) 网格：否则 svg 的 min-width 会顺着 grid 项
   .lab-main 的 min-width:auto 一路顶上去，把整页撑出横向滚动条，滑不动。 */
.lab-lc-chart-area { display: grid; grid-template-columns: minmax(0, 1fr); margin: 0 0 16px; }
.lab-lc-chart-hint { margin: 0 0 6px; font-size: 12.5px; line-height: 1.7; color: var(--ink-soft); }
.lab-lc-chart-scroll { overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: thin; }
.lab-lc-chart-scroll:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 6px; }
.lab-lc-chart-scroll svg { display: block; width: 100%; height: auto; }
/* 图里可点方块聚焦时描边加粗（SVG 元素没有 outline）。 */
.lab-lc-chart-scroll svg g[role=button] { cursor: pointer; }
.lab-lc-chart-scroll svg g[role=button]:focus { outline: none; }
.lab-lc-chart-scroll svg g[role=button]:focus-visible > g > path { stroke-width: 3.4; }

/* 双语对照：两段上下排，段前一行小标签。 */
.lab-lc-bilingual { display: grid; gap: 10px; margin: 4px 0 0; }
.lab-lc-bilingual section { display: grid; gap: 2px; }
.lab-lc-kicker { font-family: var(--font-ui); font-size: 11px; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-faint); }
.lab-lc-bilingual p { margin: 0; }
.lab-lc-bilingual mark { background: var(--marker); color: inherit; padding: 0 2px; border-radius: 3px; }

/* 选区说明（标题 + 一句）。 */
.lab-lc-selection { margin: 14px 0 0; padding: 12px 16px; background: var(--paper); border: 1.5px solid var(--ink-faint); border-radius: 14px 160px 14px 150px / 150px 14px 160px 14px; }
.lab-lc-selection h3 { margin: 0 0 4px; font-size: 15px; }
.lab-lc-selection p { margin: 0; font-size: 13px; line-height: 1.8; color: var(--ink-soft); }
.lab-lc-selection-plain { margin: 14px 0 0; font-size: 13px; line-height: 1.8; color: var(--ink-soft); }

/* 单词卡 / 页脚提示 / 语言小记。 */
.lab-lc-word-note { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin: 12px 0 0; }
.lab-lc-word-note p { margin: 0; font-family: var(--font-note); font-size: 22px; }
.lab-lc-note { margin: 12px 0 0; font-size: 12.5px; line-height: 1.8; color: var(--ink-soft); }
.lab-lc-language-note { margin: 16px 0 0; padding: 12px 16px; background: var(--paper); border-left: 4px solid var(--action); border-radius: 6px 160px 6px 150px / 150px 6px 160px 6px; }
.lab-lc-language-note h3 { margin: 0 0 4px; font-size: 15px; }
.lab-lc-language-note p { margin: 0; font-size: 13px; line-height: 1.8; color: var(--ink-soft); }

/* 朗读按钮那一行。 */
.lab-lc-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 8px 0 0; }

/* 段落控制：上移 / 下移 / 检查。跟变形/翻转那几个开关同副手绘按钮。 */
.lab-lc-controls { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 12px; }
.lab-lc-control-btn {
  padding: 7px 14px 8px; background: var(--paper); cursor: pointer; color: var(--ink-soft);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 14px 5px 13px 5px / 5px 13px 5px 14px;
  font-family: var(--font-body); font-size: 14px;
}
.lab-lc-control-btn:hover { border-color: var(--accent); color: var(--accent); }
.lab-lc-control-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.lab-lc-control-btn:disabled { opacity: .45; cursor: default; }
.lab-lc-control-btn:disabled:hover { border-color: var(--ink-faint); color: var(--ink-soft); }
.lab-lc-primary { font-weight: 700; }
.lab-lc-writing-text .is-active { background: var(--marker); border-radius: 3px; }

/* 边界：这条规律什么时候要留心。 */
.lab-lc-boundary { margin: 0 0 24px; padding: 16px 20px; background: var(--paper); border: 1.5px dashed var(--ink-faint); border-radius: 255px 15px 225px 15px / 15px 225px 15px 255px; }
.lab-lc-boundary h2 { margin: 0 0 6px; font-size: 17px; }
.lab-lc-boundary p { margin: 0; font-size: 13px; line-height: 1.85; color: var(--ink-soft); }

/* 研究线索：折起的一节。 */
.lab-lc-method { margin: 0 0 24px; font-size: 13px; }
.lab-lc-method summary { cursor: pointer; font-weight: 700; padding: 8px 0; }
.lab-lc-method p { margin: 8px 0; line-height: 1.85; color: var(--ink-soft); }
.lab-lc-method a { color: var(--action); word-break: break-word; }

/* 去别处继续练。 */
.lab-lc-presets { display: flex; flex-wrap: wrap; gap: 12px; }
.lab-lc-preset { font-size: 13px; color: var(--action); text-decoration: none; border-bottom: 1.5px solid transparent; }
.lab-lc-preset:hover { border-bottom-color: var(--action); }

@media (max-width: 900px) {
  .lab-lc-tabs { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 620px) {
  .lab-lc-tabs { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .lab-lc-workspace { padding: 14px 14px; }
}

/* ---------- 英汉语法对比小册子（#/grammar-booklet） ----------
   上游这一页：页头引子（英语屈折语 vs 汉语孤立语）→ 核心机制动态演示 → 语言演化
   光谱 → 12 个经典语法对比 → 总结表，末尾两条去别处的链接。沿用实验室的纸卡手绘
   腔调，类名前缀 lab-gb-。 */

.lab-gb-page { min-width: 0; }

/* 引子：一句问题（末句加粗）＋一句回答。 */
.lab-gb-premise {
  margin: 0 0 24px; padding: 16px 20px; background: var(--paper-card);
  border: 1.5px solid var(--ink-faint); border-left-width: 4px; border-left-color: var(--action);
  border-radius: 255px 15px 225px 15px / 15px 225px 15px 255px;
}
.lab-gb-lead-question { font-size: 14.5px; line-height: 1.9; }
.lab-gb-lead-question strong { color: var(--ink); border-bottom: 2px solid var(--marker); }
.lab-gb-core-answer { margin: 10px 0 0; font-weight: 700; font-size: 15px; }

/* 两张机制卡：英语（绿）/ 汉语（橙）。底色与描边由组件按上游配色内联，这里只管排版。 */
.lab-gb-mech-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin: 14px 0 0; }
.lab-gb-mech-card {
  padding: 12px 14px; border: 1.5px solid var(--ink-faint); border-radius: 14px 170px 14px 160px / 160px 14px 170px 14px;
}
.lab-gb-mech-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px; }
.lab-gb-mech-title { display: inline-flex; align-items: baseline; gap: 6px; font-weight: 700; font-size: 15px; }
.lab-gb-mech-type { font-family: var(--font-ui); font-size: 11.5px; font-weight: 500; letter-spacing: .02em; }
.lab-gb-mech-badge {
  margin-left: auto; font-size: 11.5px; padding: 1px 8px; border-radius: 999px;
  background: rgba(255, 255, 255, .7); color: var(--ink-soft); border: 1px solid var(--ink-faint);
}
.lab-gb-mech-metaphor {
  display: inline-block; margin: 8px 0 0; padding: 2px 8px; font-size: 12px; font-weight: 600;
  background: rgba(255, 255, 255, .7); border-radius: 6px;
}
.lab-gb-mech-desc { margin: 8px 0 0; font-size: 13px; line-height: 1.8; color: var(--ink-soft); }
.lab-gb-evolution-quote {
  margin: 14px 0 0; padding-top: 12px; border-top: 1px dashed var(--ink-faint);
  font-size: 13px; line-height: 1.9; color: var(--ink-soft);
}

/* 板块外壳。 */
.lab-gb-section { margin: 0 0 30px; }
.lab-gb-section-head { margin: 0 0 14px; }
.lab-gb-section-head h2 { margin: 0 0 6px; font-size: 20px; }
.lab-gb-section-head p { margin: 0; font-size: 13px; line-height: 1.8; color: var(--ink-soft); }

/* 动态演示：一排情境按钮 + 一张画布 + 一句机制透视。 */
.lab-gb-explorer { padding: 16px 18px; background: var(--paper-card); border: 1.5px solid var(--ink-faint); border-radius: 16px 255px 16px 225px / 225px 16px 255px 16px; }
.lab-gb-scenario-picker { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 14px; }
.lab-gb-scenario-btn {
  font-family: var(--font-body); font-size: 13px; color: var(--ink);
  background: var(--paper); border: 1.5px solid var(--ink-faint); cursor: pointer;
  padding: 6px 14px; border-radius: 225px 14px 255px 14px / 14px 255px 14px 225px;
}
.lab-gb-scenario-btn:hover { border-color: var(--accent); color: var(--accent); }
.lab-gb-scenario-btn[aria-pressed='true'] { border-color: var(--ink); background: var(--marker); font-weight: 700; }

/* 画布区：窄屏不缩 svg，改横向滑动（跟别处同一条约定）。 */
.lab-gb-canvas { overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: thin; }
.lab-gb-canvas svg, .lab-gb-chart svg { display: block; width: 100%; height: auto; }
.lab-gb-chart { overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: thin; }
.lab-gb-svg { display: block; height: auto; }

.lab-gb-scenario-note, .lab-gb-spectrum-tip, .lab-gb-keypoint {
  margin: 12px 0 0; padding: 10px 14px; font-size: 13px; line-height: 1.85;
  background: var(--paper); border: 1.5px dashed var(--ink-faint); border-radius: 14px 150px 14px 140px / 140px 14px 150px 14px;
  color: var(--ink-soft);
}
.lab-gb-scenario-note strong, .lab-gb-spectrum-tip strong, .lab-gb-keypoint strong { color: var(--ink); }

/* 光谱节点：SVG <g role=button>。聚焦时描边加粗（SVG 没有 outline）。 */
.lab-gb-node { cursor: pointer; }
.lab-gb-node:focus { outline: none; }
.lab-gb-node:focus-visible circle { stroke-width: 4.5; }

/* 分类按钮条（案例区与总结表区共用）。 */
.lab-gb-cat-bar { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 12px; }
.lab-gb-cat-btn {
  font-family: var(--font-body); font-size: 13px; color: var(--ink-soft);
  background: var(--paper); border: 1.5px solid var(--ink-faint); cursor: pointer;
  padding: 5px 13px; border-radius: 999px;
}
.lab-gb-cat-btn:nth-child(even) { border-radius: 14px 200px 14px 180px / 180px 14px 200px 14px; }
.lab-gb-cat-btn:hover { border-color: var(--accent); color: var(--accent); }
.lab-gb-cat-btn[aria-pressed='true'] { border-color: var(--ink); background: var(--marker); color: var(--ink); font-weight: 700; }

/* 案例选择 pills。 */
.lab-gb-pill-bar { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 14px; }
.lab-gb-pill {
  display: inline-flex; align-items: center; gap: 6px; font-family: var(--font-body); font-size: 13px;
  color: var(--ink); background: var(--paper); border: 1.5px solid var(--ink-faint); cursor: pointer;
  padding: 5px 13px; border-radius: 200px 14px 190px 14px / 14px 190px 14px 200px;
}
.lab-gb-pill:hover { border-color: var(--accent); }
.lab-gb-pill[aria-pressed='true'] { border-color: var(--ink); background: var(--marker); font-weight: 700; }
.lab-gb-pill-badge { font-size: 11px; color: var(--ink-faint); }
.lab-gb-pill[aria-pressed='true'] .lab-gb-pill-badge { color: var(--ink-soft); }

/* 案例卡。 */
.lab-gb-case-card { padding: 18px 20px; background: var(--paper-card); border: 1.5px solid var(--ink-faint); border-radius: 16px 255px 16px 225px / 225px 16px 255px 16px; }
.lab-gb-case-header h3 { margin: 0 0 4px; font-size: 17px; }
.lab-gb-case-header p { margin: 0; font-size: 13px; line-height: 1.8; color: var(--ink-soft); }
.lab-gb-case-mech { margin-top: 14px; }
.lab-gb-mech-card-en strong { color: #1b4332; }
.lab-gb-mech-card-zh strong { color: #7f4f24; }

/* 例句表。窄屏横向滑动。 */
.lab-gb-example-table { width: 100%; border-collapse: collapse; margin: 16px 0 0; font-size: 13px; }
.lab-gb-example-table th, .lab-gb-example-table td { text-align: left; vertical-align: top; padding: 8px 10px; border-bottom: 1px solid var(--ink-faint); }
.lab-gb-example-table th { font-size: 12px; color: var(--ink-faint); font-weight: 600; }
.lab-gb-en-line { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.lab-gb-hl-en { color: #1b4332; background: #e3f0e0; font-weight: 700; padding: 0 3px; border-radius: 3px; }
.lab-gb-hl-zh { color: #7f4f24; background: #fdf0d8; font-weight: 700; padding: 0 3px; border-radius: 3px; }
.lab-gb-item-note { margin: 6px 0 0; font-size: 12px; line-height: 1.7; color: var(--ink-faint); }
.lab-gb-tokens-title { margin: 18px 0 0; font-size: 15px; color: var(--ink); }

/* 总结表。 */
.lab-gb-table-scroll { overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: thin; }
.lab-gb-matrix-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.lab-gb-matrix-table th, .lab-gb-matrix-table td { text-align: left; vertical-align: top; padding: 9px 10px; border-bottom: 1px solid var(--ink-faint); }
.lab-gb-matrix-table th { font-size: 12px; color: var(--ink-faint); font-weight: 600; }
.lab-gb-tag-category { display: inline-block; font-size: 11.5px; padding: 1px 8px; border-radius: 999px; background: var(--paper); border: 1px solid var(--ink-faint); color: var(--ink-soft); white-space: nowrap; }

/* 页尾引言＋洞察。 */
.lab-gb-epilogue { margin: 26px 0 0; }
.lab-gb-epilogue-quote {
  margin: 0; padding: 14px 18px; font-size: 13.5px; line-height: 1.9; color: var(--ink);
  background: var(--paper-card); border-left: 4px solid var(--action); border-radius: 6px 170px 6px 160px / 160px 6px 170px 6px;
}
.lab-gb-epilogue-insight { margin: 12px 0 0; font-size: 13px; line-height: 1.9; color: var(--ink-soft); }

/* 去别处继续看。 */
.lab-gb-presets { display: flex; flex-wrap: wrap; gap: 12px; }
.lab-gb-preset { font-size: 13px; color: var(--action); text-decoration: none; border-bottom: 1.5px solid transparent; }
.lab-gb-preset:hover { border-bottom-color: var(--action); }

@media (max-width: 820px) {
  .lab-gb-mech-grid { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 620px) {
  .lab-gb-explorer, .lab-gb-case-card { padding: 14px 14px; }
}

/* ==========================================================================
   词汇学习与记忆（#/vocabulary-memory V1）。
   上游这一页是 .eg-app：页头（lab.js 画）→ .ev-tabs 五档导航 → 每一档一个
   .ev-view（引子 + 工具条 + 图/表）→ 页尾练习入口卡 + .ev-foundations 回别处。
   画法与全站一致：卡用 paper-card + 描边 + 错开的横竖半径；图走 sketch.js 原语，
   标注文字留在滤镜组外。颜色取自数据里带的那套（roots.kinds / semantics.categories），
   两处兜底见组件 FALLBACK_KIND / FALLBACK_CAT。 */

/* ---------- 分栏导航（原站 .ev-tabs） ---------- */
.lab-vm-tabs {
  display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 10px;
  margin: 4px 0 22px;
}
.lab-vm-tab {
  display: flex; flex-direction: column; gap: 3px; text-align: left; cursor: pointer;
  padding: 11px 13px 12px; background: var(--paper-card);
  border: var(--w-aux) solid var(--ink-faint); color: var(--ink);
  border-radius: 255px 14px 225px 14px / 14px 225px 14px 255px;
}
.lab-vm-tab:nth-child(even) { border-radius: 14px 255px 14px 225px / 225px 14px 255px 14px; }
.lab-vm-tab strong { font-family: var(--font-body); font-size: 13.5px; line-height: 1.4; }
.lab-vm-tab span { font-size: 11.5px; color: var(--ink-faint); line-height: 1.5; }
.lab-vm-tab:hover { border-color: var(--accent); }
.lab-vm-tab[aria-selected='true'] { border-color: var(--ink); background: var(--marker); }
.lab-vm-tab[aria-selected='true'] strong { font-weight: 700; }

/* ---------- 每一档的引子（原站 .ev-intro / 01 那档只有 h2 + 小字） ---------- */
.lab-vm-view > .lab-vm-intro { margin: 0 0 14px; }
.lab-vm-eyebrow { display: block; font-family: var(--font-note); font-size: 15px; color: var(--action); letter-spacing: .02em; }
.lab-vm-h2 { margin: 4px 0 0; font-family: var(--font-body); font-size: 20px; font-weight: 700; }
.lab-vm-lead { margin: 6px 0 0; font-size: 14px; line-height: 1.9; color: var(--ink-soft); }

/* ---------- 工具条（原站 .ev-toolbar / .ecs-toolbar） ---------- */
.lab-vm-toolbar { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px 20px; margin: 4px 0 16px; }
.lab-vm-field { display: flex; flex-direction: column; gap: 4px; font-size: 12px; color: var(--ink-faint); }
.lab-vm-field select, .lab-vm-field input {
  font-family: var(--font-body); font-size: 13px; color: var(--ink);
  background: var(--paper-card); border: var(--w-aux) solid var(--ink-faint);
  border-radius: 10px 90px 10px 80px / 80px 10px 90px 10px; padding: 6px 10px; max-width: 260px;
}
.lab-vm-field-block { margin: 14px 0 0; }
.lab-vm-toggle {
  font-family: var(--font-body); font-size: 13px; cursor: pointer; padding: 6px 14px;
  background: var(--paper-card); color: var(--ink); border: var(--w-aux) solid var(--ink-faint);
  border-radius: 200px 12px 190px 12px / 12px 190px 12px 200px;
}
.lab-vm-toggle:hover { border-color: var(--accent); }

/* ---------- 01 词表 ---------- */
.lab-vm-stage { margin: 6px 0 0; }
.lab-vm-small { margin: 4px 0; font-size: 12.5px; line-height: 1.8; color: var(--ink-faint); }
.lab-vm-note { margin: 14px 0 0; font-size: 12.5px; line-height: 1.8; color: var(--ink-soft); }
.lab-vm-summary { margin: 8px 0 2px; font-size: 14px; font-weight: 700; color: var(--ink); }
.lab-vm-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 12px; margin: 12px 0 0; }
.lab-vm-card {
  display: flex; flex-direction: column; gap: 4px; padding: 12px 14px 13px;
  background: var(--paper-card); border: var(--w-aux) solid var(--ink-faint);
  border-radius: 200px 12px 180px 12px / 12px 180px 12px 200px;
}
.lab-vm-card:nth-child(even) { border-radius: 12px 200px 12px 180px / 180px 12px 200px 12px; }
.lab-vm-word { margin: 0; font-family: var(--font-body); font-size: 17px; font-weight: 700; }
.lab-vm-kind { display: inline-block; font-size: 11.5px; color: var(--ink-faint); }
.lab-vm-card small, .lab-vm-card .lab-vm-src-label { font-size: 11.5px; color: var(--ink-faint); line-height: 1.6; }
.lab-vm-card small a { color: var(--accent); }
.lab-vm-star { color: var(--accent); }
.lab-vm-tag { color: var(--ink-faint); }
.lab-vm-meaning { margin: 4px 0 0; font-size: 13px; line-height: 1.75; color: var(--ink-soft); }
.lab-vm-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 7px; margin: 8px 0 0; }
.lab-vm-mark {
  font-family: var(--font-body); font-size: 12.5px; cursor: pointer; padding: 5px 12px;
  background: var(--paper); color: var(--ink-soft); border: var(--w-aux) solid var(--ink-faint);
  border-radius: 190px 12px 170px 12px / 12px 170px 12px 190px;
}
.lab-vm-mark:hover { border-color: var(--accent); color: var(--accent); }
.lab-vm-mark.is-on { border-color: var(--action); background: var(--tint-right); color: var(--action); font-weight: 700; }
.lab-vm-pager { display: flex; align-items: center; gap: 12px; margin: 14px 0 0; font-size: 13px; color: var(--ink-soft); }
.lab-vm-pager button {
  font-family: var(--font-body); font-size: 13px; cursor: pointer; padding: 5px 14px;
  background: var(--paper-card); color: var(--ink); border: var(--w-aux) solid var(--ink-faint);
  border-radius: 170px 12px 160px 12px / 12px 160px 12px 170px;
}
.lab-vm-pager button:disabled { opacity: .45; cursor: default; }

/* 来源折叠块（原站 .ev-source / .ecw-sources）。 */
.lab-vm-source { margin: 16px 0 0; font-size: 12.5px; color: var(--ink-soft); }
.lab-vm-source summary { cursor: pointer; font-size: 12.5px; color: var(--accent); }
.lab-vm-source p { margin: 8px 0 0; line-height: 1.85; }
.lab-vm-source a { color: var(--accent); }

/* ---------- 02 / 03 图 + 词卡两栏（原站 .ev-layout） ---------- */
.lab-vm-layout { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 18px; align-items: start; margin: 6px 0 0; }
.lab-vm-chart-card {
  padding: 14px 16px 16px; background: var(--paper-card);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 255px 16px 225px 16px / 16px 225px 16px 255px;
  box-shadow: 2px 3px 0 rgba(51, 48, 43, .07);
}
.lab-vm-chart-heading { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.lab-vm-chart-count { font-size: 13px; color: var(--ink-soft); margin-right: auto; }
.lab-vm-zoom { display: flex; gap: 6px; }
.lab-vm-zoom button, .lab-vm-pause {
  font-family: var(--font-body); font-size: 12.5px; line-height: 1; cursor: pointer; padding: 6px 10px;
  background: var(--paper-card); color: var(--ink); border: var(--w-aux) solid var(--ink-faint);
  border-radius: 12px 90px 12px 80px / 80px 12px 90px 12px;
}
.lab-vm-zoom button:hover, .lab-vm-pause:hover { border-color: var(--accent); }
.lab-vm-pause[aria-pressed="true"] { border-color: var(--accent); color: var(--accent); }
.lab-vm-legend { display: flex; flex-wrap: wrap; gap: 12px; margin: 0 0 8px; font-size: 12px; color: var(--ink-soft); }
.lab-vm-legend span::before {
  content: ''; display: inline-block; width: 10px; height: 10px; margin-right: 5px; border-radius: 3px;
  background: var(--lab-vm-dot, var(--ink-faint)); vertical-align: -1px;
}
.lab-vm-canvas { min-width: 0; overflow-x: auto; }
.lab-vm-canvas svg, .lab-vm-svg { display: block; width: 100%; height: auto; }
/* 词根图谱：宽度由 applyFit 内联成 max(100%, 内容外框)，图比卡片窄就按比例
   放大铺满、比卡片宽就保持原大小靠 overflow-x 滚动；高度始终由 viewBox 比例定。 */
.lab-vm-canvas svg.lab-vm-roots-svg { width: auto; height: auto; }
.lab-vm-gnode { cursor: pointer; }
.lab-vm-node { cursor: pointer; }
.lab-vm-gnode:focus-visible, .lab-vm-node:focus-visible, .lab-vm-dot-node:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.lab-vm-dot-node { cursor: pointer; }

.lab-vm-word-card {
  padding: 14px 16px 16px; background: var(--paper); border: var(--w-note) solid var(--ink-faint);
  border-radius: 16px 255px 16px 225px / 225px 16px 255px 16px;
}
.lab-vm-word-card h3 { margin: 2px 0 0; }
.lab-vm-compose {
  margin: 8px 0 0; padding: 7px 11px; font-family: var(--font-note); font-size: 17px; color: var(--accent);
  background: var(--paper-card); border-radius: 6px 80px 6px 70px / 70px 6px 80px 6px;
}
.lab-vm-h4 { margin: 14px 0 6px; font-size: 13px; color: var(--ink); }
.lab-vm-example { margin: 10px 0 0; padding: 10px 12px; background: var(--paper-card); border-radius: 6px 90px 6px 80px / 80px 6px 90px 6px; }
.lab-vm-en { margin: 0; font-size: 14px; line-height: 1.8; color: var(--ink); }
.lab-vm-zh { margin: 3px 0 0; font-size: 13px; line-height: 1.8; color: var(--ink-soft); }
.lab-vm-related, .lab-vm-neighbors { display: flex; flex-wrap: wrap; gap: 6px; margin: 4px 0 0; }
.lab-vm-related button, .lab-vm-neighbors button, .lab-vm-presets button, .lab-vm-collo-root {
  font-family: var(--font-body); font-size: 12.5px; cursor: pointer; padding: 5px 11px;
  background: var(--paper-card); color: var(--ink); border: var(--w-aux) solid var(--ink-faint);
  border-radius: 170px 12px 160px 12px / 12px 160px 12px 170px;
}
.lab-vm-related button:hover, .lab-vm-neighbors button:hover, .lab-vm-presets button:hover { border-color: var(--accent); }
.lab-vm-sim { margin: 10px 0 0; font-family: var(--font-note); font-size: 17px; color: var(--accent); }
.lab-vm-presets { display: flex; flex-wrap: wrap; gap: 8px; margin: 6px 0 14px; }
.lab-vm-search-results { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 12px; }
.lab-vm-search-results:empty { display: none; }
.lab-vm-search-results button {
  font-family: var(--font-body); font-size: 12.5px; cursor: pointer; padding: 5px 11px;
  background: var(--paper-card); color: var(--ink); border: var(--w-aux) solid var(--ink-faint);
  border-radius: 170px 12px 160px 12px / 12px 160px 12px 170px;
}

/* 学习提示条（原站 .ev-learning-note）。 */
.lab-vm-learning-note {
  margin: 16px 0 0; padding: 12px 16px; font-size: 13px; line-height: 1.85; color: var(--ink);
  background: var(--paper-card); border-left: 4px solid var(--action);
  border-radius: 6px 150px 6px 140px / 140px 6px 150px 6px;
}
.lab-vm-learning-note strong { display: block; margin-bottom: 3px; }
.lab-vm-learning-note p { margin: 0; }

/* ---------- 04 词频 ---------- */
.lab-vm-local { font-size: 12px; color: var(--ink-faint); }
.lab-vm-freq-summary { display: flex; flex-wrap: wrap; align-items: center; gap: 22px; margin: 4px 0 18px; }
.lab-vm-ring { display: flex; align-items: center; gap: 14px; }
.lab-vm-ring-svg { width: 120px; height: 120px; flex: none; }
.lab-vm-ring-txt h3 { margin: 0; font-size: 15px; }
.lab-vm-ring-txt p { margin: 4px 0 0; font-size: 13px; color: var(--ink-soft); }
.lab-vm-coverage-stat { flex: 1 1 260px; min-width: 220px; }
.lab-vm-coverage-stat span { display: block; font-size: 12px; color: var(--ink-faint); }
.lab-vm-coverage-stat strong { display: block; font-family: var(--font-note); font-size: 32px; color: var(--action); }
.lab-vm-coverage-stat p { margin: 4px 0 0; font-size: 13px; line-height: 1.8; color: var(--ink-soft); }
.lab-vm-freq-charts { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 16px; }
.lab-vm-freq-charts .lab-vm-chart-card h3 { margin: 0 0 8px; font-size: 14px; }
.lab-vm-word-browser { margin: 18px 0 0; }
.lab-vm-freq-list { display: flex; flex-direction: column; gap: 2px; margin: 4px 0 0; }
.lab-vm-freq-row { display: flex; align-items: center; gap: 12px; padding: 6px 4px; border-bottom: 1px solid var(--ink-faint); }
.lab-vm-rank { font-size: 12px; color: var(--ink-faint); min-width: 40px; }
.lab-vm-freq-word { font-family: var(--font-body); font-size: 14px; color: var(--ink); background: none; border: none; cursor: pointer; padding: 0; border-bottom: 1.5px solid transparent; }
.lab-vm-freq-word:hover { border-bottom-color: var(--accent); }
.lab-vm-freq-count { flex: 1; text-align: right; font-size: 12.5px; color: var(--ink-soft); }
.lab-vm-freq-detail { margin: 16px 0 0; padding: 14px 16px; background: var(--paper-card); border: var(--w-aux) solid var(--ink-faint); border-radius: 6px 200px 6px 180px / 180px 6px 200px 6px; }
.lab-vm-dict { display: inline-block; margin: 10px 0 0; font-size: 13px; color: var(--action); }

/* ---------- 05 搭配 ---------- */
.lab-vm-collo-roots { display: flex; flex-wrap: wrap; gap: 8px; margin: 4px 0 12px; }
.lab-vm-collo-root[aria-pressed='true'] { border-color: var(--ink); background: var(--marker); font-weight: 700; }
.lab-vm-switch { display: inline-flex; gap: 6px; }
.lab-vm-switch button {
  font-family: var(--font-body); font-size: 13px; cursor: pointer; padding: 6px 14px;
  background: var(--paper-card); color: var(--ink); border: var(--w-aux) solid var(--ink-faint);
  border-radius: 170px 12px 160px 12px / 12px 160px 12px 170px;
}
.lab-vm-switch button[aria-pressed='true'] { border-color: var(--ink); background: var(--marker); font-weight: 700; }
.lab-vm-collo-detail { margin: 14px 0 0; padding: 14px 16px; background: var(--paper); border: var(--w-aux) solid var(--ink-faint); border-radius: 6px 200px 6px 180px / 180px 6px 200px 6px; }
.lab-vm-collo-examples { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 10px; margin: 12px 0 0; }
.lab-vm-collo-examples article { padding: 10px 12px; background: var(--paper-card); border: var(--w-aux) solid var(--ink-faint); border-radius: 6px 80px 6px 70px / 70px 6px 80px 6px; }

/* ---------- 页尾 ---------- */
.lab-vm-entry {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 14px;
  margin: 26px 0 0; padding: 18px 22px; background: var(--paper-card);
  border: var(--w-note) solid var(--ink-faint); border-radius: 255px 16px 225px 16px / 16px 225px 16px 255px;
  box-shadow: 2px 3px 0 rgba(51, 48, 43, .07);
}
.lab-vm-entry h2 { margin: 0; font-family: var(--font-body); font-size: 18px; font-weight: 700; }
.lab-vm-entry p { margin: 5px 0 0; font-size: 13px; line-height: 1.8; color: var(--ink-soft); }
.lab-vm-entry-link {
  flex: none; display: inline-block; padding: 7px 20px 8px;
  border: var(--w-note) solid var(--action); border-radius: 255px 14px 225px 14px / 14px 225px 14px 255px;
  font-family: var(--font-body); font-size: 15px; color: var(--action); text-decoration: none;
}
.lab-vm-entry-link:hover { background: var(--marker); }
.lab-vm-foundations { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 16px; margin: 18px 0 0; font-size: 13px; }
.lab-vm-foundations span { color: var(--ink-faint); }
.lab-vm-foundations a { color: var(--action); text-decoration: none; border-bottom: 1.5px solid transparent; }
.lab-vm-foundations a:hover { border-bottom-color: var(--action); }

@media (max-width: 860px) {
  .lab-vm-tabs { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .lab-vm-layout { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 620px) {
  .lab-vm-tabs { grid-template-columns: minmax(0, 1fr); }
  .lab-vm-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
  .lab-vm-entry { padding: 14px 16px; }
}

/* ==========================================================================
   三大主题词汇（#/topic-vocabulary V1）与词性转换表（#/word-conversion-table V1）。
   两页正文第一块都是活动区（上游 .ecs-activity.ecx-activity）：词汇抽屉是
   「主题范围」下拉 + 一排话题按钮 + 词卡网格 + 例句；词性转换表是搜索框 +
   状态行 + 五列表格。前者的卡片 / 工具条沿用 vocabulary-memory 那套 .lab-vm-*；
   话题按钮复用 .lab-vm-toggle，另给选中态；表格按别的表组件单开一份 .lab-conv-*。 */

/* ---------- 话题按钮（原站 .ecs-tabs） ---------- */
.lab-vm-topic-tabs { display: flex; flex-wrap: wrap; gap: 8px; margin: 2px 0 14px; }
.lab-vm-topic-tab[aria-pressed='true'] { border-color: var(--ink); background: var(--marker); font-weight: 700; }

/* ---------- 词性转换表（原站 .ecw-table-wrap / .ecw-table） ---------- */
.lab-conv-wrap {
  margin-top: 6px; max-height: 520px; overflow: auto; overscroll-behavior: contain;
  border: var(--w-aux) solid var(--ink-faint); border-radius: 6px 90px 6px 80px / 80px 6px 90px 6px;
}
.lab-conv-table { width: 100%; border-collapse: collapse; }
.lab-conv-table caption {
  padding: 8px 10px; text-align: left; font-size: 12.5px; color: var(--ink-faint);
}
.lab-conv-table thead { position: sticky; top: 0; background: var(--paper-card); z-index: 1; }
.lab-conv-table th {
  text-align: left; padding: 6px 10px 7px; white-space: nowrap;
  font-family: var(--font-body); font-size: 13px; font-weight: 700;
  border-bottom: var(--w-note) solid var(--ink-faint);
}
.lab-conv-table td {
  padding: 6px 10px; font-size: 14px; vertical-align: top;
  overflow-wrap: anywhere; border-bottom: 1px dashed var(--ink-faint);
}
/* 前四列是同族词形，走手写体 —— 找一个词时眼睛顺着这几列的字形往下扫。 */
.lab-conv-table td:nth-child(-n+4) { font-family: var(--font-note); font-size: 17px; }
.lab-conv-table tr:last-child td { border-bottom: none; }
.lab-conv-en { margin: 0; font-size: 14px; line-height: 1.8; color: var(--ink); }
.lab-conv-zh { margin: 2px 0 0; font-size: 13px; line-height: 1.8; color: var(--ink-soft); }
.lab-conv-note { display: block; margin: 3px 0 0; font-size: 12px; line-height: 1.7; color: var(--ink-faint); }
.lab-conv-table .lab-vm-actions { margin: 7px 0 0; }

/* ==========================================================================
   文章单词提取（#/article-vocabulary V1）。
   上游这一页是 .eg-app：页头（lab.js 画）→ .eav-editor 编辑区 → .eav-status →
   .eav-results（统计 / 工具条 / 搜索 / 词表 / 分页 / 详情）→ .eav-method 折叠说明
   → .ev-foundations 回别处。画法与词汇工作台一致：paper-card + 描边 + 错开的横竖半径。 */

/* ---------- 编辑区（原站 .eav-editor） ---------- */
.lab-av-editor {
  margin: 4px 0 0; padding: 16px 18px 18px; background: var(--paper-card);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 255px 16px 225px 16px / 16px 225px 16px 255px;
  box-shadow: 2px 3px 0 rgba(51, 48, 43, .07);
}
.lab-av-section-title { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 6px 14px; }
.lab-av-section-title label, .lab-av-section-title h2 { margin: 0; font-family: var(--font-body); font-size: 16px; font-weight: 700; }
.lab-av-section-title > span { font-size: 12px; color: var(--ink-faint); }
.lab-av-editor textarea {
  display: block; width: 100%; box-sizing: border-box; min-height: 180px; margin: 10px 0 0; padding: 12px 14px;
  font-family: var(--font-ui); font-size: 14px; line-height: 1.8; color: var(--ink); resize: vertical;
  background: var(--paper); border: var(--w-aux) solid var(--ink-faint);
  border-radius: 12px 90px 12px 80px / 80px 12px 90px 12px;
}
.lab-av-editor textarea:focus { outline: none; border-color: var(--accent); }
.lab-av-editor-footer { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px 16px; margin: 10px 0 0; }
.lab-av-editor-footer p { margin: 0; flex: 1 1 320px; font-size: 12.5px; line-height: 1.8; color: var(--ink-soft); }

/* ---------- 按钮（.lab-av-actions 通用） ---------- */
.lab-av-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.lab-av-actions button, .lab-av-pagination button, .lab-av-tabs button {
  font-family: var(--font-body); font-size: 13px; cursor: pointer; padding: 6px 15px;
  background: var(--paper-card); color: var(--ink); border: var(--w-aux) solid var(--ink-faint);
  border-radius: 170px 12px 160px 12px / 12px 160px 12px 170px;
}
.lab-av-actions button:hover, .lab-av-pagination button:hover, .lab-av-tabs button:hover { border-color: var(--accent); }
.lab-av-actions button:disabled, .lab-av-pagination button:disabled { opacity: .45; cursor: default; }
.lab-av-actions button.lab-av-primary { border-color: var(--action); color: var(--action); font-weight: 700; }
.lab-av-actions button.lab-av-primary:hover { background: var(--marker); }

/* ---------- 状态行 ---------- */
.lab-av-status { margin: 14px 0 0; font-size: 13px; line-height: 1.85; color: var(--ink-soft); }

/* ---------- 统计（原站 .eav-stats） ---------- */
.lab-av-stats { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; margin: 4px 0 16px; }
.lab-av-stats > div {
  display: flex; flex-direction: column; gap: 2px; padding: 10px 14px 11px; background: var(--paper-card);
  border: var(--w-aux) solid var(--ink-faint);
  border-radius: 200px 12px 180px 12px / 12px 180px 12px 200px;
}
.lab-av-stats strong { font-family: var(--font-note); font-size: 26px; line-height: 1.1; color: var(--action); }
.lab-av-stats span { font-size: 12px; color: var(--ink-faint); }

/* ---------- 工具条 + 标签（原站 .eav-toolbar / .eav-tabs） ---------- */
.lab-av-toolbar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px 18px; margin: 0 0 12px; }
.lab-av-tabs { display: flex; gap: 8px; }
.lab-av-tabs button[aria-pressed='true'] { border-color: var(--ink); background: var(--marker); font-weight: 700; }

/* ---------- 搜索（原站 .eav-filter） ---------- */
.lab-av-filter { display: flex; align-items: center; gap: 12px; margin: 0 0 10px; }
.lab-av-filter input {
  flex: 1 1 auto; max-width: 420px; font-family: var(--font-body); font-size: 13px; color: var(--ink);
  background: var(--paper-card); border: var(--w-aux) solid var(--ink-faint);
  border-radius: 10px 90px 10px 80px / 80px 10px 90px 10px; padding: 6px 12px;
}
.lab-av-filter span { font-size: 12.5px; color: var(--ink-faint); }

.lab-av-note { margin: 0 0 12px; font-size: 12.5px; line-height: 1.8; color: var(--ink-soft); }

/* ---------- 词表（原站 .eav-table-scroll） ---------- */
.lab-av-table-scroll { overflow-x: auto; margin: 0; }
.lab-av-table-scroll table { width: 100%; border-collapse: collapse; font-size: 13px; }
caption.lab-av-sr, .lab-av-sr {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.lab-av-table-scroll th, .lab-av-table-scroll td {
  padding: 8px 10px; text-align: left; vertical-align: top; border-bottom: 1px solid var(--ink-faint);
}
.lab-av-table-scroll th { font-size: 12px; color: var(--ink-faint); font-weight: 400; white-space: nowrap; }
.lab-av-table-scroll td small { display: block; margin-top: 3px; font-size: 11px; color: var(--ink-faint); }
.lab-av-word {
  font-family: var(--font-body); font-size: 14.5px; color: var(--ink); background: none; border: none;
  cursor: pointer; padding: 0; border-bottom: 1.5px solid transparent;
}
.lab-av-word:hover { border-bottom-color: var(--accent); }
.lab-av-ipa summary { cursor: pointer; }
.lab-av-ipa small { display: inline-block; margin-left: 6px; font-size: 11px; color: var(--ink-faint); }
.lab-av-ipa div { margin-top: 3px; font-size: 12px; color: var(--ink-soft); }
.lab-av-other-pronunciations { margin-top: 4px; }
.lab-av-other-pronunciations summary { font-size: 11.5px; color: var(--accent); cursor: pointer; }
.lab-av-other-pronunciations div { margin-top: 3px; font-size: 11.5px; color: var(--ink-soft); line-height: 1.7; }
.lab-av-table-scroll td[data-state] { font-size: 12px; color: var(--ink-soft); }
.lab-av-table-scroll td[data-state] small { color: var(--ink-faint); }
.lab-av-table-scroll td[data-state='found'] { color: var(--action); }
.lab-av-table-scroll td[data-state='missing'] { color: var(--ink-faint); }
.lab-av-table-scroll td[data-state='error'] { color: var(--alert); }

.lab-av-empty { margin: 12px 0 0; font-size: 13px; color: var(--ink-soft); }

/* ---------- 分页 ---------- */
.lab-av-pagination { display: flex; align-items: center; gap: 14px; margin: 14px 0 0; font-size: 13px; color: var(--ink-soft); }

/* ---------- 详情（原站 .eav-detail） ---------- */
.lab-av-detail {
  margin: 18px 0 0; padding: 16px 18px 18px; background: var(--paper);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 16px 255px 16px 225px / 225px 16px 255px 16px;
}
.lab-av-detail .lab-av-section-title h2 { font-size: 17px; }
.lab-av-detail [data-detail-body] p { margin: 6px 0 0; font-size: 13px; line-height: 1.85; color: var(--ink-soft); }
.lab-av-detail [data-detail-body] a { display: inline-block; margin: 6px 12px 0 0; font-size: 12.5px; color: var(--action); }
.lab-av-detail label { display: block; margin: 12px 0 0; font-size: 12.5px; color: var(--ink-faint); }
.lab-av-detail label input {
  display: block; width: 100%; box-sizing: border-box; max-width: 520px; margin-top: 5px; padding: 7px 11px;
  font-family: var(--font-body); font-size: 13px; color: var(--ink); background: var(--paper-card);
  border: var(--w-aux) solid var(--ink-faint);
  border-radius: 10px 90px 10px 80px / 80px 10px 90px 10px;
}
.lab-av-occurrences { margin: 12px 0 0; padding-left: 22px; }
.lab-av-occurrences li { margin: 8px 0 0; }
.lab-av-occurrences strong { font-size: 12px; color: var(--ink-faint); font-weight: 400; }
.lab-av-occurrences p { margin: 3px 0 0; font-size: 13.5px; line-height: 1.85; color: var(--ink); }
.lab-av-source { margin: 10px 0 0; font-size: 13px; line-height: 1.9; color: var(--ink-soft); }
.lab-av-source mark { background: var(--marker); color: inherit; padding: 0 1px; }

/* ---------- 说明块（原站 .eav-method） ---------- */
.lab-av-method { margin: 22px 0 0; font-size: 12.5px; color: var(--ink-soft); }
.lab-av-method summary { cursor: pointer; font-size: 13px; color: var(--accent); }
.lab-av-method p { margin: 9px 0 0; line-height: 1.9; }
.lab-av-method a { color: var(--accent); }

/* ---------- 相关页（.lab-av-foundations） ---------- */
.lab-av-foundations { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 16px; margin: 18px 0 0; font-size: 13px; }
.lab-av-foundations span { color: var(--ink-faint); }
.lab-av-foundations a { color: var(--action); text-decoration: none; border-bottom: 1.5px solid transparent; }
.lab-av-foundations a:hover { border-bottom-color: var(--action); }

@media (max-width: 620px) {
  .lab-av-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .lab-av-editor, .lab-av-detail { padding: 14px 14px 16px; }
}

/* ---------- 写作工坊（#/writing-workshop 的活动区，上游 .ecs-activity） ----------
   上游这一段是 d3 画的 SVG（四块积木 + 箭头），本地改用 flex 盒子画出同一件事：
   可拖的积木块 + 箭头 + 下面的句卡。四张积木是「同名同序」的两视图 —— 上面看
   结构，下面看原句，改一处两边一起动。 */
.lab-ws-tabs { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.lab-ws-flow {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px 6px; margin: 12px 0 4px;
}
.lab-ws-node {
  display: flex; flex-direction: column; gap: 2px; min-width: 110px; cursor: grab;
  padding: 9px 12px 10px; background: var(--paper-card);
  border: var(--w-aux) solid var(--ink-faint);
  border-radius: 12px 90px 12px 80px / 80px 12px 90px 12px;
}
.lab-ws-node:nth-child(even) { border-radius: 90px 12px 80px 12px / 12px 80px 12px 90px; }
.lab-ws-node:focus-visible { outline: var(--w-aux) solid var(--accent); outline-offset: 2px; }
.lab-ws-node.is-dragging { opacity: .5; cursor: grabbing; }
.lab-ws-node-num { font-family: var(--font-note); font-size: 12px; color: var(--ink-faint); }
.lab-ws-node-role { font-family: var(--font-body); font-size: 14px; font-weight: 700; color: var(--ink); }
.lab-ws-arrow { font-size: 18px; color: var(--ink-faint); }
.lab-ws-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 12px; margin: 12px 0 0; }
.lab-ws-card {
  display: flex; flex-direction: column; gap: 4px; padding: 12px 14px 13px;
  background: var(--paper-card); border: var(--w-aux) solid var(--ink-faint);
  border-radius: 200px 12px 180px 12px / 12px 180px 12px 200px;
}
.lab-ws-card:nth-child(even) { border-radius: 12px 200px 12px 180px / 180px 12px 200px 12px; }
.lab-ws-card strong { font-size: 12.5px; color: var(--ink-faint); font-weight: 700; }
.lab-ws-en { margin: 0; font-size: 14px; line-height: 1.8; color: var(--ink); }
.lab-ws-h3 { margin: 22px 0 6px; font-family: var(--font-body); font-size: 17px; font-weight: 700; }
.lab-ws-draft {
  display: block; box-sizing: border-box; width: 100%; max-width: 620px; min-height: 96px;
  padding: 9px 11px; resize: vertical; font-family: var(--font-body); font-size: 13.5px;
  line-height: 1.8; color: var(--ink); background: var(--paper-card);
  border: var(--w-aux) solid var(--ink-faint);
  border-radius: 10px 90px 10px 80px / 80px 10px 90px 10px;
}
.lab-ws-checks { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 6px 18px; margin: 12px 0 0; }
.lab-ws-check { display: flex; align-items: flex-start; gap: 7px; font-size: 13px; line-height: 1.8; color: var(--ink-soft); }
.lab-ws-check input { margin-top: 3px; }

/* ---------- 场景功能句库（#/functional-dialogues 的活动区） ---------- */
.lab-fd-stage { margin: 6px 0 0; }
.lab-fd-context { margin: 0 0 12px; font-size: 13.5px; line-height: 1.9; color: var(--ink-soft); }
.lab-fd-card {
  display: flex; flex-direction: column; gap: 6px; margin: 0 0 12px; padding: 12px 14px 13px;
  background: var(--paper-card); border: var(--w-aux) solid var(--ink-faint);
  border-radius: 200px 12px 180px 12px / 12px 180px 12px 200px;
}
.lab-fd-card:nth-child(even) { border-radius: 12px 200px 12px 180px / 180px 12px 200px 12px; }
.lab-fd-kind { font-size: 11.5px; color: var(--ink-faint); }
.lab-fd-line { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 6px; }
.lab-fd-line strong { font-size: 13px; color: var(--accent); }
.lab-fd-en { margin: 0; font-size: 14px; line-height: 1.8; color: var(--ink); }
.lab-fd-line .lab-vm-actions { margin: 0; }
.lab-fd-zh { margin: 2px 0 0; font-size: 13px; line-height: 1.85; color: var(--ink-faint); }

/* ---------- 文化意识（#/cultural-awareness 的活动区） ---------- */
.lab-ca-stage { margin: 6px 0 0; }
.lab-ca-situation { margin: 0 0 10px; font-family: var(--font-body); font-size: 16px; font-weight: 700; color: var(--ink); }

@media (max-width: 620px) {
  .lab-ws-tabs { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .lab-ws-cards { grid-template-columns: minmax(0, 1fr); }
}


/* ====================================================================
   语法与句子结构（#/syntax-lab）—— 上游 SENTENCE EXPLORER 的样式表子集。
   这一页的正文结构与类名（.etl-* / .ec-* / .eg-* / .es-*）逐字照搬上游
   bundle（渲染器 hce/bce/Sce/xce/Hb/uce/Ud/Bd/N3/Wl），所以样式也必须
   跟着搬，否则只剩一堆没有尺寸的方框。
   全部规则都加了 `.etl-app` 前缀（组件根节点带这个类），**只在本页内生效**，
   不会碰到 lab.css 里既有的 .lab-* 皮肤。颜色是上游字面量，不并入本站的
   --paper/--ink 那套变量：这里要的是逐像素复刻，不是重新配一遍色。
   唯一的变量依赖是 --el-primary（下面补上）。
   ==================================================================== */
.etl-app { --el-primary: #52734d; }
.etl-app .es-settings{display:flex;flex-wrap:wrap;align-items:center;gap:12px 18px;margin:0 0 24px;padding:14px 18px;border:1px solid #ded7e9;border-radius:12px;background:#faf8fd;color:#736481;font:12px/1.6 -apple-system,BlinkMacSystemFont,Segoe UI,PingFang SC,sans-serif}.etl-app .es-settings,.etl-app .es-settings *{box-sizing:border-box}.etl-app .es-title{display:inline-flex;align-items:center;gap:7px;font-weight:600}.etl-app .es-settings label{display:flex;align-items:center;gap:7px}.etl-app .es-settings select{max-width:100%;min-height:36px;border:1px solid #e0d9e9;border-radius:7px;padding:5px 22px 5px 9px;font:inherit;background:#fff;color:#645375;cursor:pointer}.etl-app .es-settings select:focus-visible,.etl-app .es-actions .es-speak:focus-visible{outline:3px solid #9c8ed2;outline-offset:3px}.etl-app .es-settings .es-status{flex-basis:100%;color:#81738f;font-size:11px}.etl-app .es-settings .es-status.is-error{color:#a34d55}.etl-app .es-actions{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:9px 0 12px}.etl-app .es-actions .es-speak{display:inline-flex;align-items:center;justify-content:center;gap:6px;min-height:36px;max-width:100%;padding:6px 10px;border:1px solid #ded6e9;border-radius:8px;background:#faf8fd;color:#79658f;cursor:pointer;font:12px/1.5 -apple-system,BlinkMacSystemFont,Segoe UI,PingFang SC,sans-serif}.etl-app .es-actions .es-speak:hover{background:#f1ebf8;border-color:#b9a7ce}.etl-app .es-actions .es-speak[aria-pressed=true]{background:#eae1f4;color:#64487f;border-color:#a68dc3}.etl-app .es-actions .es-speak:disabled{opacity:.5;cursor:default}.etl-app .es-actions .es-inline-error{flex-basis:100%;color:#a34d55;font:12px/1.7 system-ui,sans-serif}.etl-app .es-actions svg,.etl-app .es-title svg{flex:none;width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:1.6;stroke-linejoin:round;stroke-linecap:round}@media(max-width:620px){.etl-app .es-settings{gap:10px 14px;padding:14px;margin-bottom:18px}.etl-app .es-title{width:100%}.etl-app .es-settings label{min-width:0}.etl-app .es-actions .es-speak{min-height:40px}}.etl-app .es-settings-disclosure{margin:24px 0 0;padding:18px 0;border-top:1px solid #e1e8d4}.etl-app .es-settings-disclosure>summary{width:fit-content;color:#7c8c6c;font:12px/1.8 system-ui,sans-serif;cursor:pointer}.etl-app .es-settings-disclosure>summary:focus-visible{outline:3px solid #a493cc;outline-offset:3px}.etl-app .es-settings-disclosure>.es-settings{margin-top:15px}.etl-app .ec-app{max-width:1140px;margin:0 auto;color:#294636;font:14px/1.7 -apple-system,BlinkMacSystemFont,Segoe UI,PingFang SC,sans-serif}.etl-app .ec-app *,.etl-app .ec-app *:before,.etl-app .ec-app *:after{box-sizing:border-box}.etl-app .ec-header{display:flex;align-items:center;justify-content:space-between;gap:24px;padding:15px 0 26px}.etl-app .ec-eyebrow{font-size:11px;color:#859872;letter-spacing:1.5px}.etl-app .ec-header h1{margin:10px 0;font-size:clamp(26px,3.5vw,36px);line-height:1.5}.etl-app .ec-header p{color:#6c805e;margin:0}@media(max-width:720px){.etl-app .ec-header{display:block}}.etl-app .ec-toolbar{background:#fff;padding:20px;border:1px solid #e0e7d6;border-radius:13px;margin-bottom:22px}.etl-app .ec-groups{display:flex;flex-wrap:wrap;gap:8px}.etl-app .ec-app button,.etl-app .ec-app input{font:inherit}.etl-app .ec-app button{cursor:pointer;background:#f9fbf5;color:#64804e;border:1px solid #dee6d3;border-radius:7px;padding:8px 12px;min-height:42px;font-size:13px}.etl-app .ec-app button.is-active{background:#e9f1df;border-color:#a9c18e;color:#4c7437}.etl-app .ec-app button:disabled{color:#a1ad93;cursor:default}.etl-app .ec-app button:focus-visible,.etl-app .ec-app input:focus-visible,.etl-app .ec-app a:focus-visible{outline:3px solid #9c8ed2;outline-offset:3px}.etl-app .ec-search-row{display:flex;align-items:center;gap:12px;margin-top:16px}.etl-app .ec-search-row input{min-width:0;width:340px;padding:9px 12px;border:1px solid #dce5d2;border-radius:7px;color:#47663a;background:#fff}.etl-app .ec-search-row>span{margin-left:auto;color:#7b8c6c;font-size:12px;white-space:nowrap}.etl-app .ec-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:20px}.etl-app .ec-card{min-width:0;display:flex;flex-direction:column;border:1px solid #e0e7d7;border-radius:14px;background:#fff;padding:20px}.etl-app .ec-card-label{color:#85986f;font-size:11px}.etl-app .ec-card h2{margin:6px 0 0;font-size:20px;font-weight:600;line-height:1.5}.etl-app .ec-card-subtitle{color:#80916d;font-size:12px;margin:4px 0 14px}.etl-app .ec-example{font:18px/1.8 Georgia,Times New Roman,serif;color:#476b3f;margin:0 0 14px}.etl-app .ec-emphasis{color:#9b7437;background:#fcf3e0;border-radius:3px}.etl-app .ec-figure{display:block;width:100%;height:auto;margin-top:auto}.etl-app .ec-explanation{color:#70845f;font-size:13px;line-height:1.9;margin:16px 0}.etl-app .ec-card>a{color:#5c8246;font-size:12px;text-decoration:none;margin-top:auto;padding-top:12px;border-top:1px solid #e6ecdf}.etl-app .ec-card>a:hover{text-decoration:underline}.etl-app .ec-empty{background:#fff;border-radius:12px;color:#738960;padding:30px;text-align:center}.etl-app .ec-empty:empty{display:none}@media(max-width:950px){.etl-app .ec-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:16px}}@media(max-width:620px){.etl-app .ec-grid{grid-template-columns:minmax(0,1fr)}.etl-app .ec-toolbar{padding:16px}.etl-app .ec-search-row{flex-wrap:wrap}.etl-app .ec-search-row input{width:100%}.etl-app .ec-search-row>span{margin-left:auto}}.etl-app .ecs-activity{padding:clamp(16px,3vw,28px);margin:24px 0;border:1px solid #dbe3d1;border-radius:16px;background:#fcfdf8;color:#526c42}.etl-app .ecs-activity [hidden]{display:none!important}.etl-app .ecs-activity h2{margin:0 0 12px;font-size:24px}.etl-app .ecs-activity h3{margin:16px 0 10px;font-size:18px}.etl-app .ecs-activity p{line-height:1.9}.etl-app .ecs-toolbar,.etl-app .ecs-tabs{display:flex;gap:10px;flex-wrap:wrap;margin:16px 0;align-items:center}.etl-app .ecs-activity button,.etl-app .ecs-activity select,.etl-app .ecs-activity input,.etl-app .ecs-activity textarea{font:inherit;color:inherit;border:1px solid #cedcc1;border-radius:8px;background:#fff;padding:9px 12px;box-sizing:border-box}.etl-app .ecs-activity>label,.etl-app .ecs-toolbar>label{display:flex;flex-wrap:wrap;gap:8px;align-items:center;min-width:0;max-width:100%}.etl-app .ecs-activity select{min-width:0;max-width:100%;text-overflow:ellipsis}.etl-app .ecs-activity input[type=range]{padding:0;max-width:100%;accent-color:#9777af}.etl-app .ecs-activity input[type=checkbox]{accent-color:#9777af}.etl-app .ecs-activity button{cursor:pointer;min-height:40px}.etl-app .ecs-activity button[aria-pressed=true]{background:#eee6f5;border-color:#ac8cc8;color:#725488}.etl-app .ecs-activity button:focus-visible,.etl-app .ecs-activity [tabindex]:focus-visible{outline:3px solid #a988c4;outline-offset:3px}.etl-app .ecs-activity>svg{display:block;width:100%;max-width:760px;margin:12px auto;overflow:visible}.etl-app .ecs-activity .es-speak{white-space:nowrap}.etl-app .ecs-activity .es-speak svg{flex:0 0 16px}.etl-app .ecs-activity svg [role=button]{cursor:pointer}.etl-app .ecs-activity svg text{fill:#4b6240;font-family:inherit}.etl-app .ecs-center{font-size:19px;font-weight:600}.etl-app .ecs-form-word{font:21px Georgia,serif!important}.etl-app .ecs-form-label{font-size:13px}.etl-app .ecs-english{font:23px/1.8 Georgia,serif;color:#4b603e}.etl-app .ecs-note{background:#f0f4e8;border-left:4px solid #a1b98b;padding:12px 16px}.etl-app .ecs-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px}.etl-app .ecs-card{border:1px solid #dce4d3;border-radius:10px;padding:16px;background:#fff;min-width:0}.etl-app .ecs-activity textarea{display:block;width:100%;min-height:180px;resize:vertical;line-height:1.9;box-sizing:border-box}.etl-app .ecs-activity summary{cursor:pointer;padding:10px 0}.etl-app .ecs-activity table{width:100%;border-collapse:collapse}.etl-app .ecs-activity th,.etl-app .ecs-activity td{padding:10px;border:1px solid #dce4d3;text-align:left}.etl-app .ecs-table{overflow-x:auto}.etl-app .ecs-error{color:#965741}.etl-app .ecs-stage-link{color:#73518b}.etl-app .ecs-small{font-size:13px;color:#718364}.etl-app .ecs-evidence-paragraph{display:block;width:100%;margin:10px 0;text-align:left;line-height:1.85}.etl-app .ecs-context{padding:18px;border-left:4px solid #abbf94;background:#f4f7ed;color:#506541;line-height:1.9;white-space:pre-wrap;font-size:16px;overflow-wrap:anywhere}.etl-app .ecs-guide{display:flex;align-items:center;flex-wrap:wrap;gap:10px;margin:12px 0 24px;padding:16px;background:#f1f5e9;border-radius:12px;font-size:13px;color:#708360}.etl-app .ecs-guide a{color:#71558b}.etl-app .ecs-guide small{flex-basis:100%;color:#879479}.etl-app .ecs-band{display:inline-block;width:fit-content;padding:3px 9px;border-radius:12px;background:#eef0e8;color:#71865e;font-size:11px;margin:5px 0}.etl-app .ecs-review-link{display:inline-block;margin-top:12px;font-size:12px}.etl-app .ecs-map-performance{margin:5px 0 12px!important;color:#887293;font-size:11px;line-height:1.8}.etl-app .ecs-card-actions{display:flex;align-items:center;gap:16px;flex-wrap:wrap;margin-top:16px}.etl-app .ecs-card-actions a{color:#725488}.etl-app .ecs-card-actions button{cursor:pointer;border:1px solid #ac8cc8;border-radius:8px;background:#eee6f5;color:#725488;font:inherit;padding:10px 16px;min-height:44px}.etl-app .ecs-card-actions button:focus-visible{outline:3px solid #a988c4;outline-offset:3px}@media(max-width:620px){.etl-app .ecs-grid{grid-template-columns:1fr}.etl-app .ecs-english{font-size:19px}.etl-app .ecs-activity{padding:15px}.etl-app .ecs-tabs{gap:6px}.etl-app .ecs-tabs button{font-size:13px;padding:8px}}@keyframes egp-confetti-flight{0%{opacity:0;transform:translate(0) rotate(0)}8%{opacity:1}35%{opacity:1;transform:translate(calc(var(--confetti-x) * .55),var(--confetti-up)) rotate(calc(var(--confetti-spin) * .35))}to{opacity:0;transform:translate(var(--confetti-x),var(--confetti-down)) rotate(var(--confetti-spin))}}.etl-app .em-map-caption .es-actions{margin:0}.etl-app .em-map-caption .es-speak{min-height:32px;padding:3px 9px;font-size:11px}.etl-app .em-example .es-actions{margin:9px 0}.etl-app .em-speech-options .es-settings{margin-bottom:0}.etl-app .em-classroom:fullscreen .em-example .es-actions{float:right;margin:0 0 0 12px}.eg-app{color:#42563d;font:15px/1.8 -apple-system,BlinkMacSystemFont,Segoe UI,PingFang SC,sans-serif;max-width:1140px;margin:0 auto}.eg-app,.eg-app *{box-sizing:border-box}.eg-app h1,.eg-app h2,.eg-app h3,.eg-app p{margin:0}.eg-app button,.eg-app a,.eg-app input,.eg-app summary{-webkit-tap-highlight-color:transparent}.eg-app button{font:inherit;cursor:pointer}.eg-app button:disabled{cursor:default;opacity:.5}.eg-app [hidden]{display:none!important}.eg-app a{color:#547841;text-decoration:none}.eg-app a:hover{color:#344f29}.eg-app button:focus-visible,.eg-app a:focus-visible,.eg-app summary:focus-visible,.etl-app .eg-sentence-block:focus-visible{outline:3px solid #a493cc;outline-offset:3px}.etl-app .eg-header{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:0 24px;margin:0 0 20px}.etl-app .eg-header>div:first-child{display:contents}.etl-app .eg-eyebrow{grid-row:1;grid-column:1;color:#82936f;font-size:10px;letter-spacing:2px;margin-bottom:9px}.etl-app .eg-header h1{grid-row:2;grid-column:1;color:#486638;font-size:clamp(24px,2.7vw,34px);font-weight:600;line-height:1.4;letter-spacing:-.5px;overflow-wrap:anywhere}.etl-app .eg-header p{grid-row:3;grid-column:1 / -1;margin-top:10px;color:#7b8b6d;font-size:13px;max-width:750px}.etl-app .eg-header .el-header-actions{grid-row:2;grid-column:2;max-width:320px}.etl-app .eg-breadcrumb{display:flex;align-items:center;flex-wrap:wrap;gap:6px;margin-bottom:22px;font-size:12px;color:#88957b}.etl-app .eg-breadcrumb a{color:#6c8858}.etl-app .eg-course-intro{border:1px solid #dce5d2;border-radius:16px;padding:28px;background:linear-gradient(110deg,#edf4e5,#fafcf6)}.etl-app .eg-intro-message{font-size:16px;color:#557344}.etl-app .eg-course-stats{display:flex;flex-wrap:wrap;gap:25px 45px;margin:22px 0}.etl-app .eg-course-stats p{display:flex;flex-direction:column}.etl-app .eg-course-stats strong{font:34px Georgia,serif;color:#698d50}.etl-app .eg-course-stats span{margin-top:5px;font-size:12px;color:#7e9170}.etl-app .eg-primary,.etl-app .eg-secondary{border-radius:9px;border:1px solid #b3c69d;padding:10px 18px;font-size:13px;min-height:44px}.etl-app .eg-primary,.etl-app a.eg-primary{background:#67894e;color:#fff}.etl-app .eg-primary:hover,.etl-app a.eg-primary:hover{background:#56783e;color:#fff}.etl-app .eg-secondary{background:#fff;color:#637f50}.etl-app .eg-link-button{display:inline-flex;align-items:center;justify-content:center;margin:4px 8px 0 0}.etl-app .eg-course-group{margin-top:34px}.etl-app .eg-group-heading{display:grid;grid-template-columns:37px 1fr;align-items:center;gap:0 10px;margin-bottom:15px}.etl-app .eg-group-heading>span{grid-row:span 2;color:#9eb687;font:26px Georgia,serif}.etl-app .eg-group-heading h2{font-size:20px;font-weight:600}.etl-app .eg-group-heading p{font-size:12px;color:#829075}.etl-app .eg-lesson-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px}.etl-app .eg-lesson-card{display:flex;flex-direction:column;border:1px solid #dde5d4;border-radius:12px;padding:20px;background:#ffffffd9;transition:border-color .15s,background .15s}.etl-app .eg-lesson-card:hover{border-color:#aebf9a;background:#f9fcf5}.etl-app .eg-lesson-count{font-size:10px;color:#94a484;letter-spacing:1px}.etl-app .eg-lesson-card h3{font-size:17px;font-weight:600;margin:7px 0}.etl-app .eg-lesson-card p{color:#7c8b70;font-size:13px;margin-bottom:15px}.etl-app .eg-card-footer{margin-top:auto;font-size:11px;color:#82996d}.etl-app .eg-analogy{padding:20px 24px;background:#ecf2e3;border-left:4px solid #a8bf8c;border-radius:7px;color:#557145}.etl-app .eg-diagram-section,.etl-app .eg-section{margin-top:30px}.etl-app .eg-diagram-section{padding:24px;border:1px solid #dbe3d2;border-radius:14px;background:#fffef9}.etl-app .eg-section-heading{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:16px}.etl-app .eg-section-number{display:block;color:#8a9e77;font-size:11px;letter-spacing:1px;margin-bottom:4px}.eg-app h2{font-size:21px;font-weight:600;color:#516c43}.etl-app .eg-section-note{font-size:13px;color:#829075;margin:9px 0 16px!important}.etl-app .eg-diagram-tools{display:flex;gap:8px;flex-wrap:wrap}.etl-app .eg-diagram-tools button{border:1px solid #d4dfc9;border-radius:7px;padding:7px 11px;background:#f5f8ef;font-size:12px;color:#6c8656}.etl-app .eg-diagram-tools button[data-find][aria-pressed=true]{background:#eee9f6;color:#796296;border-color:#c6b7da}.etl-app .eg-sentence-diagram{display:block;width:100%;overflow:visible}.etl-app .eg-sentence-block{cursor:pointer}.etl-app .eg-sentence-block:hover rect{fill:#edf3e5}.etl-app .eg-block-number{font:11px system-ui,sans-serif}.etl-app .eg-block-english{fill:#42583a;font:19px Georgia,Times New Roman,serif}.etl-app .eg-block-role{font:12px system-ui,sans-serif}.etl-app .eg-diagram-feedback{min-height:48px;margin-top:4px!important;padding:10px 14px;border-radius:8px;background:#f1f5e9;color:#687e53;font-size:13px}.etl-app .eg-explanations{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:15px;margin-top:16px}.etl-app .eg-explanations article{padding:21px 23px;background:#ffffffb8;border:1px solid #e0e6d9;border-radius:11px}.etl-app .eg-explanations h3{font-size:16px;font-weight:600;color:#567441;margin-bottom:9px}.etl-app .eg-explanations p{font-size:14px;color:#68785d;line-height:1.95}.etl-app .eg-examples{border-top:1px solid #dce5d2;margin-top:17px}.etl-app .eg-example{display:flex;gap:18px;padding:21px 4px;border-bottom:1px solid #e0e6d8}.etl-app .eg-example-index{flex:0 0 24px;padding-top:5px;color:#9bae89;font:16px Georgia,serif}.etl-app .eg-example-text{min-width:0}.etl-app .eg-english{font:22px/1.55 Georgia,Times New Roman,serif;color:#435b37;overflow-wrap:anywhere}.etl-app .eg-chinese{margin-top:5px!important;font-size:14px;color:#7a876e}.etl-app .eg-example-note{display:inline-block;margin-top:8px!important;font-size:12px;color:#84724d;background:#f3efdf;border-radius:4px;padding:3px 8px}.etl-app .eg-comparisons{display:grid;gap:16px;margin-top:16px}.etl-app .eg-comparisons article{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));border:1px solid #dedfd8;border-radius:12px;background:#fff;overflow:hidden}.etl-app .eg-language-side{padding:18px 23px;background:#f6f1e7}.etl-app .eg-language-side.is-english{background:#eff4e8}.etl-app .eg-language-label{display:block;color:#947f5a;font-size:11px;margin-bottom:6px}.etl-app .is-english .eg-language-label{color:#7b9362}.etl-app .eg-language-side p{font-size:16px}.etl-app .eg-language-side p[lang=en]{font:21px/1.55 Georgia,serif;color:#4a6740}.etl-app .eg-difference{grid-column:1 / -1;padding:14px 23px;font-size:13px;color:#747969;border-top:1px solid #e5e7dc}.etl-app .eg-mistakes{display:grid;gap:13px;margin-top:16px}.etl-app .eg-mistakes article{background:#fffdfa;border:1px solid #e6e0d4;border-radius:10px;padding:18px 22px}.etl-app .eg-wrong{color:#ae6c5a;font-size:14px}.etl-app .eg-correct{color:#5e8050;font-size:16px;margin-top:5px!important}.etl-app .eg-mistake-reason{color:#88816d;font-size:13px;margin-top:9px!important}.etl-app .eg-exercise-entry{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:18px;margin-top:32px;padding:24px;background:#edf3e6;border:1px solid #d2dfc5;border-radius:12px}.etl-app .eg-exercise-entry p{margin-top:4px;font-size:13px;color:#7f9170}.etl-app .eg-lesson-navigation{display:flex;justify-content:space-between;flex-wrap:wrap;gap:10px 20px;margin:25px 0;font-size:12px}.etl-app .eg-speech-settings{border-top:1px solid #dfe6d5;margin-top:30px}.etl-app .eg-speech-settings summary{cursor:pointer;padding:12px 0;font-size:12px;color:#829274}.etl-app .eg-footer{margin:20px 0 0;font-size:11px;color:#929e86}.etl-app .eg-practice{padding:clamp(20px,3.5vw,40px);background:#fffef9;border:1px solid #dde5d4;border-radius:16px;max-width:850px;margin:0 auto}.etl-app .eg-practice-progress{display:flex;flex-wrap:wrap;justify-content:space-between;gap:8px;font-size:13px;color:#7e916c}.etl-app .eg-practice-progress strong{font-weight:500}.etl-app .eg-practice progress{width:100%;height:8px;display:block;margin:10px 0 26px;appearance:none;border:0;border-radius:8px;background:#eaf0e2}.etl-app .eg-practice progress::-webkit-progress-bar{background:#eaf0e2;border-radius:8px}.etl-app .eg-practice progress::-webkit-progress-value{background:#9cba77;border-radius:8px}.etl-app .eg-practice progress::-moz-progress-bar{background:#9cba77;border-radius:8px}.etl-app .eg-question-lesson{display:inline-block;font-size:12px;margin-bottom:13px;color:#819769!important}.etl-app .eg-practice h2{font-size:24px;line-height:1.6;overflow-wrap:anywhere}.etl-app .eg-choices{display:grid;gap:12px;margin:24px 0}.etl-app .eg-choices button{display:flex;align-items:center;text-align:left;gap:15px;padding:15px 18px;min-height:58px;border-radius:10px;border:1px solid #d7e0cc;background:#fff;color:#526749;font-size:17px}.etl-app .eg-choices button:hover:enabled{background:#f4f8ed;border-color:#aebf95}.etl-app .eg-choice-letter{flex:0 0 29px;height:29px;border:1px solid #dae2cf;border-radius:6px;display:grid;place-items:center;font-size:13px;color:#8b9e76}.etl-app .eg-choices button.is-correct{background:#edf5e3;border-color:#91b16b;color:#507b35;opacity:1}.etl-app .eg-choices button.is-wrong{background:#fcf0e9;border-color:#d7ae91;color:#a57555}.etl-app .eg-feedback{border-radius:8px;background:#f3f5ee;color:#83916e;font-size:14px;padding:15px 18px;min-height:58px}.etl-app .eg-feedback.is-correct{background:#eaf3df;color:#5c7c41}.etl-app .eg-feedback.is-wrong{background:#fcf2e5;color:#98724d}.etl-app .eg-practice-actions{display:flex;justify-content:space-between;flex-wrap:wrap;gap:12px;margin-top:22px}.etl-app .eg-result-score{font:52px Georgia,serif;color:#729150;margin:24px 0 12px!important}.etl-app .eg-result-score+p{font-size:13px;color:#819174}.etl-app .eg-review-list{padding-left:0;list-style:none;font-size:13px;margin:20px 0}.etl-app .eg-review-list li{padding:9px 0;border-top:1px solid #e3e8da}.etl-app .eg-review-list span{color:#86966e}.etl-app .eg-review-answer{margin-top:5px;color:#6d7f5d;overflow-wrap:anywhere}.etl-app .eg-review-answer summary{cursor:pointer;padding:5px 0}.etl-app .eg-review-answer p{margin:7px 0;font-size:13px;line-height:1.9}.etl-app .eg-review-answer .eg-review-correct{color:#527839}.etl-app .eg-back-to-study{display:block;margin:20px auto;max-width:850px;font-size:13px}@media(max-width:720px){.etl-app .eg-header{display:block}.etl-app .eg-header>div:first-child{display:block}.etl-app .eg-header .el-header-actions{max-width:100%}.etl-app .eg-explanations,.etl-app .eg-lesson-grid,.etl-app .eg-comparisons article{grid-template-columns:1fr}.etl-app .eg-course-intro{padding:21px}.etl-app .eg-diagram-section{padding:18px}.etl-app .eg-english{font-size:20px}.etl-app .eg-difference{grid-column:1}.etl-app .eg-course-stats{gap:20px 25px}}@media(max-width:480px){.etl-app .eg-example{gap:10px}.etl-app .eg-analogy{padding:16px}.etl-app .eg-explanations article{padding:18px}.etl-app .eg-practice h2{font-size:21px}.etl-app .eg-practice-actions>button{width:100%}.etl-app .eg-language-side{padding:16px}.etl-app .eg-course-stats strong{font-size:28px}.etl-app .eg-course-stats span{font-size:11px}.etl-app .eg-course-stats{gap:17px}.etl-app .eg-diagram-tools{flex-direction:column;align-items:flex-start}}@media(prefers-reduced-motion:reduce){.etl-app .eg-lesson-card{transition:none}}.etl-app .ep-inventory-clusters .es-speak{font-size:11px}.etl-app .ep-intro-example-heading .es-actions{margin:0}.etl-app .ep-intro-examples .es-actions{margin:5px 0 0}.etl-app .ep-intro-examples .es-speak{min-height:34px;padding:5px 8px;font-size:11px}.etl-app .ep-word .es-actions{margin:9px 0 0}.etl-app .ep-word .es-speak{font-size:11px;padding:5px 8px}.etl-app .ep-sentence .es-actions{margin:8px 0 0}.etl-app .ep-sentence .es-speak{font-size:11px;padding:5px 8px}.etl-app .ecl-header .el-header-actions{grid-row:2;grid-column:2;max-width:320px}.etl-app .ecx-stage{min-width:0}.etl-app .ecx-stage svg{display:block;width:100%;max-width:900px;margin:16px auto}.etl-app .ecx-tokens{display:flex;flex-wrap:wrap;gap:10px;align-items:center;padding:20px 0}.etl-app .ecx-token{display:grid;gap:7px;min-width:62px;padding:14px 16px;border:1px solid #c8d5bd;border-radius:12px;background:#edf3e6;text-align:center}.etl-app .ecx-token span{font:20px/1.3 Georgia,serif}.etl-app .ecx-token small{color:#698157;font-size:12px}.etl-app .ecx-token[data-role*=时态],.etl-app .ecx-token[data-role*=助动词]{background:#eee7f6;border-color:#b8a0cb}.etl-app .ecx-token[data-role*=宾语],.etl-app .ecx-token[data-role*=受动]{background:#e6f1f5;border-color:#9bbdc7}.etl-app .ecx-token[data-role=小品词]{background:#f7efdd;border-color:#d4b77f}.etl-app .ecx-token[data-role=介词]{background:#fbe8e2;border-color:#d9a08a}.etl-app .ecx-box{border:2px solid #9cae8b;border-radius:14px;background:#f3f7ef;padding:clamp(12px,3vw,26px)}.etl-app .ecx-box>strong{display:block;margin-bottom:14px}.etl-app .ecx-slot{border:2px dashed #b095c2;border-radius:12px;padding:16px;background:#faf7fc;min-height:84px}.etl-app .ecx-clause-box{position:relative}.etl-app .ecx-clause-box>.ecx-clause-tail{margin:12px 0 0}.etl-app .ecx-clause-box>.ecx-clause-arc{position:absolute;inset:0;width:100%;height:100%;max-width:none;margin:0;pointer-events:none}.etl-app .ecx-antecedent{color:#75538a}.etl-app .ecx-clause-box>.ecx-clause-arc[hidden]{display:none}.etl-app .ecx-slot.is-filled{border-style:solid}.etl-app .ecx-slot p{margin:4px 0}.etl-app .ecx-drag{touch-action:manipulation;margin:12px 0}.etl-app .ecx-three{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px}.etl-app .ecx-dial{padding:18px;background:#fff;border:1px solid #ccd9c0;border-radius:50%/15%;text-align:center}.etl-app .ecx-dial strong{display:block;margin:10px 0;font-size:21px}.etl-app .ecx-dial button{width:100%}.etl-app .ecx-reference{max-height:480px;overflow:auto;overscroll-behavior:contain;margin-top:18px}.etl-app .ecx-reference thead{position:sticky;top:0;background:#eff4e8;z-index:1}.etl-app .ecx-reference td{overflow-wrap:anywhere}.etl-app .ecx-filter-result{display:flex;justify-content:space-between;gap:12px;flex-wrap:wrap;margin:12px 0}.etl-app .ecx-activity .ecx-inline-audio{display:inline-flex;align-items:center;gap:8px}.etl-app .ecx-activity .ecx-subtle{background:transparent;border-style:dashed}.etl-app .ecx-muted{opacity:.24}.etl-app .ecx-activity .ecx-legend{display:flex;flex-wrap:wrap;gap:16px;font-size:13px;color:#637858}.etl-app .ecx-score{font:600 28px Georgia,serif}.etl-app .ecx-activity progress{width:100%;height:15px;accent-color:#8a6aa3}.etl-app .ecx-bars{display:grid;gap:12px}.etl-app .ecx-bars label{display:grid;grid-template-columns:minmax(110px,1fr) 2fr 80px;gap:10px;align-items:center}.etl-app .ecx-activity a{color:#75518b}.etl-app .ecx-activity mark{background:#e8ddf1;color:#614977;padding:2px 4px;border-radius:4px}@media(max-width:640px){.etl-app .ecx-three{grid-template-columns:1fr}.etl-app .ecx-token{padding:10px}.etl-app .ecx-token span{font-size:17px}.etl-app .ecx-bars label{grid-template-columns:1fr;gap:3px}.etl-app .ecx-dial{border-radius:12px;display:flex;flex-wrap:wrap;align-items:center;gap:10px}.etl-app .ecx-dial button{width:auto}.etl-app .ecx-reference{max-height:380px}}@media(prefers-reduced-motion:reduce){.etl-app .ecx-activity *,.etl-app .ecx-activity *:before{animation:none!important;transition:none!important;scroll-behavior:auto!important}}.etl-app .ecw-word-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,240px),1fr));gap:12px}.etl-app .ecw-word-grid h3{overflow-wrap:anywhere;margin:0 0 8px;font-size:1.22rem}.etl-app .ecw-word-grid .ecs-card{display:flex;flex-direction:column;gap:6px;min-width:0}.etl-app .ecw-meaning{font-size:.9rem;line-height:1.6;flex:1}.etl-app .ecw-progress{width:100%;max-height:32px;display:block}.etl-app .ecw-summary{font-weight:700;line-height:1.7}.etl-app .ecw-sources{margin-top:18px;line-height:1.8;color:#526048}.etl-app .ecw-sources a{color:#42662c;text-decoration:underline}.etl-app .ecw-table-wrap{overflow:auto;max-width:100%;border:1px solid #d6dfcd;border-radius:12px}.etl-app .ecw-table{border-collapse:collapse;min-width:600px;width:100%;font-size:.92rem}.etl-app .ecw-table th,.etl-app .ecw-table td{padding:12px;text-align:left;border-bottom:1px solid #d6dfcd;vertical-align:top}.etl-app .ecw-table th{background:#eef3e8;position:sticky;top:0}.etl-app .ecw-table td p{margin:5px 0}.etl-app .ecw-table tbody tr:focus-within{background:#f4f7ed}.etl-app .ecw-table caption{padding:12px;text-align:left;font-weight:700}.etl-app .ecw-table button{white-space:normal}@media(max-width:600px){.etl-app .ecw-word-grid{grid-template-columns:1fr}.etl-app .ecw-summary{font-size:.95rem}.etl-app .ecw-table{font-size:.88rem}}.etl-app .ec-article-english>p{margin:0;white-space:pre-line}.etl-app .ec-article-english:has(table){overflow:auto;max-width:100%}.etl-app .ec-information-table{border-collapse:collapse;width:100%;min-width:490px;font:16px/1.6 system-ui,sans-serif;text-align:left}.etl-app .ec-information-table th,.etl-app .ec-information-table td{padding:11px;border:1px solid #c9d8bb;vertical-align:top}.etl-app .ec-information-table caption{font-weight:700;text-align:left;padding:10px 0}.etl-app .ec-information-table thead{background:#e7efde}.etl-app .ec-information-table tbody tr:nth-child(2n){background:#f2f6ec}.etl-app .ec-information-table tbody tr.is-evidence{background:#f7e3a5;outline:2px solid #b99335;outline-offset:-2px}.etl-app .ec-structure-questions{display:grid;gap:8px;margin:15px 0}.etl-app .ec-structure-questions>button{text-align:left;line-height:1.5}.etl-app .ec-block-label{font-size:12px;color:#6d795f;margin-bottom:7px;font-weight:600}.etl-app .ec-document-notice,.etl-app .ec-document-poster,.etl-app .ec-document-advert,.etl-app .ec-document-letter{border:1px solid #d0ddc4;padding:clamp(12px,3vw,26px);border-radius:12px;margin-top:18px;background:#fffefa}.etl-app .ec-document-poster,.etl-app .ec-document-advert{background:linear-gradient(155deg,#f0f6e4,#fcf7e8);border:2px solid #a3b97f}.etl-app .ec-document-poster>.ec-paragraph:first-child,.etl-app .ec-document-advert>.ec-paragraph:first-child{background:#dfeccf;text-align:center;border-radius:8px}.etl-app .ec-document-poster>.ec-paragraph:first-child .ec-article-english,.etl-app .ec-document-advert>.ec-paragraph:first-child .ec-article-english{font-size:1.4rem;font-weight:700}.etl-app .ec-document-poster>.ec-paragraph,.etl-app .ec-document-advert>.ec-paragraph{border-bottom:1px solid #cddbbb}.etl-app .ec-document-notice>.ec-paragraph:first-child .ec-article-english{font-weight:700}.etl-app .ec-document-letter{border-top:5px solid #a8bf93;background:#fffef9}.etl-app .ec-document-letter>.ec-paragraph:last-child{font-style:italic}.etl-app .ec-structure-parts{display:grid;gap:12px}.etl-app .ec-structure-parts .ec-paragraph{padding:16px;border:1px solid #d6dfcd;border-radius:10px}.etl-app .ec-structure-parts .ec-paragraph.is-selected{border-color:#9675b2;box-shadow:0 0 0 2px #e8deef}.etl-app .ec-structure-parts .ec-article-english{font-size:18px}.etl-app .ec-structure-parts .ec-article-chinese{font-size:14px}@media(max-width:600px){.etl-app .ec-information-table{font-size:14px}.etl-app .ec-structure-parts .ec-article-english{font-size:16px}.etl-app .ec-document-poster>.ec-paragraph:first-child .ec-article-english,.etl-app .ec-document-advert>.ec-paragraph:first-child .ec-article-english{font-size:1.15rem}}.etl-app .ec-tianjin-sections{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}.etl-app .ec-tianjin-sections button{text-align:left;line-height:1.5}.etl-app .ec-tianjin-detail{padding:18px;margin-top:20px;border:1px solid #d2dec5;border-radius:12px;background:#fffefa}.etl-app .ec-tianjin-lessons{padding:0;list-style:none;display:grid;gap:12px}.etl-app .ec-tianjin-lessons li{display:flex;flex-wrap:wrap;gap:10px;justify-content:space-between}.etl-app .ec-tianjin-lessons span{font-size:13px;color:#69765d}.etl-app .ec-tianjin-items{width:100%;border-collapse:collapse;font-size:14px;margin:20px 0;text-align:left}.etl-app .ec-tianjin-items caption{text-align:left;margin-bottom:8px;font-weight:600}.etl-app .ec-tianjin-items th,.etl-app .ec-tianjin-items td{padding:8px;border-bottom:1px solid #dce5d1}.etl-app .ec-tianjin-sector[role=button]{cursor:pointer}.etl-app .ec-tianjin-sector:focus{outline:none;stroke:#53326e;stroke-width:4}@media(max-width:600px){.etl-app .ec-tianjin-sections{grid-template-columns:1fr 1fr}.etl-app .ec-tianjin-detail{padding:12px}.etl-app .ec-tianjin-items{font-size:13px}}.etl-app .ec-tianjin-points{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,180px),1fr));gap:8px;margin:14px 0}.etl-app .ec-tianjin-points a{display:block;padding:10px;border:1px solid #cad7bd;border-radius:8px;background:#f7f9f2;font-size:14px}.etl-app .ec-tianjin-point:focus{outline:none}.etl-app .ec-tianjin-point:focus path{stroke:#513368;stroke-width:3}.etl-app .ec-completion-sentence{font:22px/2.2 Georgia,serif;color:#49673b;overflow-wrap:anywhere}.etl-app .ec-completion-sentence input{width:7.5em;max-width:100%;margin:0 4px;padding:6px 10px;font:20px/1.4 Georgia,serif;color:#49663b;border:2px solid #d5e0c8;border-radius:10px;text-align:center}.etl-app .ec-completion-sentence input.is-wrong{border-color:#d3a58f;background:#fff6ef}.etl-app .ec-completion-sentence input.is-correct{border-color:#95b471;background:#f0f7e8}.etl-app .ec-completion-bar{cursor:pointer}.etl-app .ec-completion-label{fill:#4b6240}.etl-app .ec-completion-count{fill:#69765d}.etl-app svg g[role=button]:focus .ec-completion-bar{stroke:#513368;stroke-width:2}.etl-app .ec-listening-question{margin:18px 0;padding:14px;border:1px solid #d2dec5;border-radius:12px;background:#fffefa}.etl-app .ec-listening-question h3{margin-top:0}.etl-app .ec-writing-points{padding-left:22px;line-height:1.9}.etl-app .ec-writing-useful{padding-left:20px;line-height:1.9}.etl-app .ec-writing-useful li{margin-bottom:6px}.etl-app .ec-writing-useful small{color:#718364}.etl-app .ec-writing-useful div,.etl-app .ecs-card div.es-actions{display:inline-block;margin-left:8px;vertical-align:middle}.etl-app .ec-writing-model{padding:16px;margin:16px 0;border:1px solid #d2dec5;border-radius:12px;background:#f7f9f2}.etl-app .ec-writing-draft{display:grid;gap:8px;font-size:13px;color:#698054}.etl-app .ec-writing-draft textarea{min-height:180px;resize:vertical;font:16px/1.7 Georgia,serif;color:#49663b}.etl-app .ec-writing-rubric{display:grid;gap:10px}.etl-app .ec-writing-rubric label{display:flex;gap:8px;align-items:flex-start;line-height:1.7}.etl-app .ec-writing-rubric input{margin-top:6px}@media(max-width:600px){.etl-app .ec-completion-sentence{font-size:19px}.etl-app .ec-completion-sentence input{width:6em;font-size:17px}}.etl-app .elp-example .es-speak{min-height:34px;padding:6px 9px;font-size:11px}.etl-app .elm-header .el-header-actions{grid-row:2;grid-column:2;max-width:320px}.etl-app .elm-example .es-actions{gap:8px}.etl-app .elm-app .eg-practice{margin-bottom:18px}@media(max-width:760px){.etl-app .elm-header .el-header-actions{max-width:100%;margin-top:16px;align-items:flex-start}}.etl-app .ev-app button:not(.es-speak):not(.eg-primary):not(.eg-secondary),.etl-app .ev-related button{min-height:40px;padding:8px 12px;border:1px solid #d1ddc4;border-radius:8px;background:#f8faf4;color:#658249;font-size:13px}.etl-app .ev-app button[aria-pressed=true]:not(.es-speak){background:#e7f0db;border-color:#9fb981}.etl-app .ev-example .es-actions{margin-top:12px}.etl-app .ev-collocation-examples .es-actions{margin-top:10px}.etl-app{max-width:1160px}.etl-app input,.etl-app select,.etl-app textarea{min-width:0;max-width:100%;border:1px solid #cbd9bf;border-radius:8px;background:#fffef9;color:#425d37;font:inherit;padding:8px 11px}.etl-app select,.etl-app input:not([type=checkbox]){min-height:42px}.etl-app input:focus-visible,.etl-app textarea:focus-visible,.etl-app select:focus-visible,.etl-app [tabindex]:focus-visible{outline:3px solid #b5a0c9;outline-offset:3px}.etl-app button:not(.eg-primary):not(.eg-secondary):not(.es-speak):not(.etl-text-token):not(.etl-sentence-number){min-height:40px;padding:7px 12px;border:1px solid #ccdac0;border-radius:8px;background:#f6f9f0;color:#567444;font-size:13px}.etl-app button[aria-pressed=true]:not(.es-speak):not(.etl-text-token):not(.etl-sentence-number){background:#e5eed9;border-color:#8eae70}.etl-app .etl-tabs{display:grid;grid-template-columns:repeat(var(--tab-count, 2),minmax(0,1fr));gap:12px;margin:24px 0}.etl-app .etl-tabs a{display:block;padding:16px 19px;background:#fbfcf7;border:1px solid #dbe5cf;border-radius:11px;min-width:0}.etl-app .etl-tabs strong{display:block;font-size:15px;font-weight:600}.etl-app .etl-tabs span{display:block;color:#7c906c;font-size:12px;margin-top:4px}.etl-app .etl-tabs a[aria-current=page]{background:#eaf1df;border-color:#a6be8d;box-shadow:inset 0 -3px #a4bc8a}.etl-app .etl-explain{display:grid;grid-template-columns:1fr 1fr;gap:0;border:1px solid #dfe6d4;border-radius:12px;background:#fffef9;margin:18px 0 24px;overflow:hidden}.etl-app .etl-explain p{padding:19px 22px;font-size:13px;color:#728565}.etl-app .etl-explain p+p{background:#edf3e5}.etl-app .etl-explain strong{display:block;color:#526f42;font-size:13px;margin-bottom:5px}.etl-app .etl-editor{padding:21px;background:#f2f6eb;border:1px solid #d4e1c6;border-radius:13px}.etl-app .etl-editor-heading{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:12px}.etl-app .etl-editor-heading label{font-size:15px;font-weight:600}.etl-app .etl-editor-heading span{font-size:11px;color:#829371;white-space:nowrap}.etl-app textarea{resize:vertical;width:100%;min-height:130px;max-height:500px;line-height:1.7;font-family:Georgia,Times New Roman,serif;font-size:19px;display:block;padding:15px 17px}.etl-app .etl-editor-bottom{display:flex;align-items:center;justify-content:space-between;gap:16px;margin:12px 0 16px}.etl-app .etl-editor-bottom p{color:#7b8d69;font-size:11px}.etl-app .etl-editor-bottom button{flex-shrink:0}.etl-app .etl-samples,.etl-app .etl-switch,.etl-app .etl-legend,.etl-app .etl-presets{display:flex;gap:7px;flex-wrap:wrap}.etl-app .etl-sample-note{font-size:12px;color:#7b8e67;margin-top:11px!important}.etl-app .etl-analysis-status{margin:12px 1px 24px!important;font-size:12px;color:#7d9169;min-height:24px}.etl-app .etl-analysis-status.is-error{color:#a4684e}.etl-app .etl-toolbar{display:flex;align-items:end;flex-wrap:wrap;gap:12px 18px;margin:20px 0}.etl-app .etl-toolbar label{display:grid;gap:4px;font-size:12px;color:#778e62;min-width:0}.etl-app .etl-toolbar input[type=search]{width:220px}.etl-app .etl-toolbar select{max-width:320px}.etl-app .etl-toolbar .etl-checkbox{display:flex;align-items:center;min-height:42px;gap:7px}.etl-app .etl-checkbox input{width:16px;height:16px;accent-color:#799951}.etl-app .etl-card{padding:22px;border:1px solid #dbe4d0;border-radius:13px;background:#fffef9;min-width:0}.etl-app .etl-card+.etl-card{margin-top:20px}.etl-app .etl-card h2{font-size:20px}.etl-app .etl-card h3{font-size:16px;font-weight:600;color:#516f42}.etl-app .etl-card-heading{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;margin-bottom:12px}.etl-app .etl-small,.etl-app .etl-muted{color:#7a8c6b;font-size:12px;line-height:1.9}.etl-app .etl-small{font-size:11px}.etl-app .etl-card>.etl-small{margin:9px 0}.etl-app .etl-muted{margin:9px 0!important}.etl-app .etl-chart-tools{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:9px;color:#82946f;font-size:11px;margin:10px 0}.etl-app .etl-chart-tools select{font-size:11px;min-height:34px;padding:4px 7px}.etl-app .etl-chart-scroll{overflow:auto;max-height:660px;max-width:100%;border-radius:9px;scrollbar-width:thin;scrollbar-color:#a1b684 #f0f4e9;background:#fcfdf7}.etl-app .etl-chart-scroll::-webkit-scrollbar{width:5px;height:5px}.etl-app .etl-chart-scroll::-webkit-scrollbar-track{background:#f0f4e9}.etl-app .etl-chart-scroll::-webkit-scrollbar-thumb{background:#a1b684;border-radius:8px}.etl-app .etl-chart-scroll svg{display:block;max-width:none;overflow:visible}.etl-app .etl-tree-node,.etl-app .etl-dependency-node,.etl-app .etl-dependency-edge,.etl-app .etl-cloud-word,.etl-app .etl-heat-cell,.etl-app .etl-sketch-bar,.etl-app .etl-synonym-node{cursor:pointer}.etl-app .etl-node-label{font:14px/1.4 -apple-system,BlinkMacSystemFont,Segoe UI,PingFang SC,sans-serif;fill:#425b38;pointer-events:none}.etl-app .etl-node-subtitle{font:11px/1.4 -apple-system,BlinkMacSystemFont,Segoe UI,PingFang SC,sans-serif;fill:#7b8d6a;pointer-events:none}.etl-app .etl-tree-node.is-active rect,.etl-app .etl-dependency-node.is-active rect{stroke-width:3;fill:#e6efda}.etl-app .etl-tree-node:focus-visible rect,.etl-app .etl-dependency-node:focus-visible rect,.etl-app .etl-cloud-word:focus-visible rect,.etl-app .etl-synonym-node:focus-visible rect{stroke:#a083ba;stroke-width:3}.etl-app .etl-dependency-edge text{font:11px system-ui,sans-serif;fill:#7c916b}.etl-app .etl-dependency-edge.is-active .etl-dependency-line,.etl-app .etl-dependency-edge:focus-within .etl-dependency-line{stroke:#8771a1;stroke-width:3}.etl-app .etl-dependency-edge.is-active .etl-dependency-label rect,.etl-app .etl-dependency-label:focus-visible rect{fill:#eee7f5;stroke:#9a83b0;stroke-width:2}.etl-app .etl-selection{border-left:3px solid #a0b886;border-radius:6px;background:#eef4e5;padding:16px 19px;margin:18px 0;min-height:108px}.etl-app .etl-selection h3{font-size:16px;color:#526f42}.etl-app .etl-selection p{font-size:13px;color:#70865c;margin-top:5px}.etl-app .etl-selection p[lang=en]{font:21px/1.6 Georgia,serif;color:#4b683c;overflow-wrap:anywhere}.etl-app .etl-notes{padding:13px 16px;border:1px solid #e5ddc8;border-radius:8px;background:#faf6e9;font-size:12px;color:#8e7e56;margin-bottom:18px}.etl-app .etl-notes p+p{margin-top:7px}.etl-app .etl-legend{gap:8px 14px;margin:12px 0;font-size:11px;color:#80936d}.etl-app .etl-legend span{display:inline-flex;align-items:center;gap:6px}.etl-app .etl-legend i{width:9px;height:9px;background:var(--legend-color);border-radius:50%}.etl-app .etl-source{margin-top:12px}.etl-app .etl-source-sentence{display:grid;grid-template-columns:27px minmax(0,1fr);gap:10px;padding:13px 12px;border-radius:8px;border:1px solid transparent;transition:background-color .15s}.etl-app .etl-source-sentence+.etl-source-sentence{margin-top:5px}.etl-app .etl-source-sentence.is-selected{border-color:#a5b990;box-shadow:inset 3px 0 #96ad7b}.etl-app .etl-sentence-number{width:26px;height:28px;margin-top:5px;border:1px solid #dae4cf;background:#f2f6e9;color:#7e956a;border-radius:5px;padding:0;font:11px system-ui,sans-serif}.etl-app .etl-source-words{font:20px/2 Georgia,Times New Roman,serif;color:#4a633d;overflow-wrap:anywhere;white-space:pre-wrap}.etl-app .etl-text-token{display:inline;max-width:100%;font:inherit;color:inherit;padding:1px 2px;margin:0;border:0;border-bottom:2px solid transparent;border-radius:3px;background:transparent;white-space:normal;overflow-wrap:anywhere;line-height:inherit}.etl-app .etl-text-token.has-pos-color{border-bottom-color:var(--pos-color)}.etl-app .etl-text-token.is-outside{text-decoration:underline wavy #ba9271 1px;text-underline-offset:6px}.etl-app .etl-text-token:hover{background:#edf3e5}.etl-app .etl-text-token.is-highlighted{background:#ddd1ec;color:#624e75}.etl-app .etl-two-columns{display:grid;grid-template-columns:minmax(0,1.7fr) minmax(265px,1fr);align-items:start;gap:22px}.etl-app .etl-two-columns>*{min-width:0}.etl-app .etl-word-card{background:#fffef9;border:1px solid #d9e3cd;border-top:3px solid #b49a65;border-radius:12px;padding:21px;min-width:0}.etl-app .etl-kicker{font-size:10px;letter-spacing:1px;color:#9d8965}.etl-app .etl-word-card h3{font:30px/1.45 Georgia,serif;color:#55733f;margin:7px 0;overflow-wrap:anywhere}.etl-app .etl-word-card h4{font-size:13px;margin:19px 0 11px;color:#78915f}.etl-app .etl-word-card [data-word-pos]{font-size:11px;color:#80946b}.etl-app .etl-word-card .es-actions{margin:10px 0}.etl-app .etl-word-card .etl-meaning{font-size:15px;margin:13px 0}.etl-app .etl-word-card [data-dictionary-status]{margin:8px 0}.etl-app .etl-word-card [data-mastered]{width:100%}.etl-app .etl-word-card [data-storage-note]{margin-top:5px}.etl-app .etl-example{padding:13px 15px;border-radius:8px;background:#f2f6e9;margin:12px 0}.etl-app .etl-example p[lang=en]{font:18px/1.7 Georgia,serif;color:#506e3e}.etl-app .etl-example p+p{font-size:12px;margin-top:5px;color:#81956d}.etl-app .etl-remote-definition{font-size:13px;margin:10px 0!important;overflow-wrap:anywhere}.etl-app .etl-occurrence{padding:11px 0;border-top:1px solid #e1e8d8}.etl-app .etl-occurrence p{font:16px/1.8 Georgia,serif;margin-top:5px;overflow-wrap:anywhere}.etl-app .etl-occurrence-link{padding:3px 0!important;border:0!important;background:transparent!important;font-size:11px!important;text-align:left}.etl-app .etl-method{margin:22px 0;padding:15px 18px;border:1px solid #dce5d2;border-radius:9px;font-size:12px;color:#7b8d69}.etl-app .etl-method summary{cursor:pointer;color:#68834f}.etl-app .etl-method p{margin-top:10px}.etl-app .etl-method a{text-decoration:underline;text-underline-offset:3px}.etl-app .etl-pagination{display:flex;justify-content:space-between;align-items:center;gap:9px;flex-wrap:wrap;margin:15px 0;font-size:12px;color:#82956e}.etl-app .etl-empty{padding:28px 17px;border:1px dashed #d5e0c8;border-radius:9px;font-size:13px;color:#83966f;margin:14px 0!important}.etl-app .etl-table-scroll{overflow-x:auto;margin-top:16px;scrollbar-width:thin;scrollbar-color:#a1b684 #f0f4e9}.etl-app .etl-table-scroll table{width:100%;min-width:580px;border-collapse:collapse;font-size:13px}.etl-app .etl-table-scroll th,.etl-app .etl-table-scroll td{padding:12px 15px;text-align:left;border-bottom:1px solid #dfe6d4;vertical-align:top}.etl-app .etl-table-scroll th{background:#edf3e4;color:#667f4f;font-weight:600}.etl-app .etl-table-scroll td{color:#7b8c6a}.etl-app .etl-stats{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:13px;margin:18px 0}.etl-app .etl-stats>div{background:#f1f6e8;border:1px solid #dfe7d4;border-radius:10px;padding:15px 18px}.etl-app .etl-stats strong{display:block;font:29px Georgia,serif;color:#77964e}.etl-app .etl-stats span{font-size:11px;color:#7e906c}.etl-app .etl-heat-cell text{font:12px system-ui,sans-serif;fill:#455e39;pointer-events:none}.etl-app .etl-heat-cell:focus-visible rect{stroke:#9172ab;stroke-width:3}.etl-app .etl-cloud{width:100%;display:block}.etl-app .etl-cloud-word text{font-family:Georgia,Times New Roman,serif;fill:#53773e;pointer-events:none}.etl-app .etl-cloud-word rect{fill:transparent;stroke:transparent}.etl-app .etl-cloud-word:hover rect,.etl-app .etl-cloud-word.is-active rect{fill:#eaf2df;stroke:#a9be8d}.etl-app .etl-cloud-word small{pointer-events:none}.etl-app .etl-frequency-list{display:flex;gap:7px;flex-wrap:wrap;margin:15px 0}.etl-app .etl-frequency-list button{font-family:Georgia,serif!important}.etl-app .etl-frequency-list span{color:#93a37e;padding-left:7px;font-size:11px}.etl-app .etl-sketch-bar text{font:12px system-ui,sans-serif;fill:#5c7549}.etl-app .etl-sketch-bar:focus-visible rect,.etl-app .etl-sketch-bar.is-active rect{stroke:#9276a9;stroke-width:2}.etl-app .etl-synonym-svg{width:100%;display:block;touch-action:none}.etl-app .etl-synonym-node rect{fill:#f5f1e7;stroke:#b5a075}.etl-app .etl-synonym-node.is-active rect{fill:#e9efdd;stroke:#879d6a;stroke-width:2}.etl-app .eg-choices button{min-height:58px!important;padding:15px 18px!important;border-radius:10px!important;font-size:17px!important;background:#fff!important;text-align:left}.etl-app .eg-choices button.is-correct{background:#edf5e3!important;border-color:#91b16b!important}.etl-app .eg-choices button.is-wrong{background:#fcf0e9!important;border-color:#d7ae91!important}@media(max-width:960px){.etl-app .etl-two-columns{grid-template-columns:minmax(0,1fr)}.etl-app .etl-word-card{margin-top:10px}}@media(max-width:640px){.etl-app .etl-tabs{grid-template-columns:1fr;gap:8px}.etl-app .etl-tabs a{padding:12px 16px}.etl-app .etl-tabs span{font-size:11px}.etl-app .etl-explain{grid-template-columns:1fr}.etl-app .etl-explain p{padding:16px}.etl-app .etl-editor{padding:15px}.etl-app .etl-editor-heading{align-items:start}.etl-app .etl-editor-heading label{font-size:14px}.etl-app .etl-editor-bottom{flex-direction:column;align-items:stretch}.etl-app .etl-card{padding:15px}.etl-app .etl-source-words{font-size:18px}.etl-app .etl-source-sentence{padding:9px 4px;gap:5px;grid-template-columns:23px minmax(0,1fr)}.etl-app .etl-sentence-number{width:22px}.etl-app .etl-stats{grid-template-columns:1fr 1fr;gap:9px}.etl-app .etl-stats>div{padding:13px}.etl-app .etl-word-card{padding:17px}.etl-app .etl-toolbar label{width:100%}.etl-app .etl-toolbar input[type=search],.etl-app .etl-toolbar select{width:100%;max-width:100%}.etl-app .etl-chart-scroll{max-height:530px}}@media(prefers-reduced-motion:reduce){.etl-app .etl-source-sentence{transition:none}}.etl-app .ec-intro{padding:23px 26px;background:#edf3e5;border:1px solid #d5e1c8;border-radius:13px}.etl-app .ec-intro h2{margin:7px 0!important}.etl-app .ec-intro p{font-size:13px;line-height:1.9;color:#718363;max-width:850px}.etl-app .ec-stats{margin-top:16px}.etl-app .ec-filters{padding:18px;border:1px solid #dce5d1;border-radius:11px;background:#fafcf6}.etl-app .ec-filters label:first-child{flex:1}.etl-app .ec-filters input[type=search]{width:100%}.etl-app .ec-layout{display:grid;grid-template-columns:244px minmax(0,1fr);gap:22px;align-items:start;margin-top:23px}.etl-app .ec-layout>*{min-width:0}.etl-app .ec-index{position:sticky;top:18px;border:1px solid #d7e1cb;border-radius:11px;padding:17px 13px;background:#f4f7ed}.etl-app .ec-index summary{cursor:pointer;font-size:14px;color:#567343;font-weight:600}.etl-app .ec-index>p{margin:11px 0!important}.etl-app .ec-index .etl-pagination{font-size:11px;margin-bottom:0;gap:5px}.etl-app .ec-index .etl-pagination button{padding:6px!important;font-size:11px!important}.etl-app .ec-material-list{display:grid;gap:7px;max-height:min(55vh,590px);overflow-y:auto;scrollbar-width:thin;scrollbar-color:#a1b684 #edf2e4;padding:3px}.etl-app .ec-material-list::-webkit-scrollbar{width:5px}.etl-app .ec-material-list::-webkit-scrollbar-thumb{border-radius:5px;background:#a1b684}.etl-app .ec-material-list button{display:flex;align-items:start;gap:9px;width:100%;padding:11px 9px;text-align:left;background:#fffef9;min-width:0}.etl-app .ec-material-list strong{display:block;font-size:13px;font-weight:600;line-height:1.7}.etl-app .ec-material-list small{display:block;font-size:10px;color:#83936f;line-height:1.7;margin-top:3px}.etl-app .ec-material-number{color:#98aa80;font:13px/1.8 Georgia,serif}.etl-app .ec-reader{padding:24px 27px;border:1px solid #d8e3cd;background:#fffefb;border-radius:14px;min-width:0}.etl-app .ec-reader-heading{padding-bottom:20px;margin-bottom:22px;border-bottom:1px solid #e1e7d9}.etl-app .ec-reader h2{margin:8px 0 12px!important;scroll-margin-top:22px}.etl-app .ec-reader h3{font-size:16px;color:#597348}.etl-app .ec-reader h4{font-size:14px;color:#637e4d;margin:0 0 5px}.etl-app .ec-tags{display:flex;gap:6px;flex-wrap:wrap}.etl-app .ec-tags span{padding:3px 8px;border-radius:5px;background:#eff3e8;color:#83966c;font-size:10px}.etl-app .ec-reader-controls{display:flex;gap:9px 16px;align-items:center;flex-wrap:wrap;margin:16px 0 8px}.etl-app .ec-reader-controls a{font-size:11px}.etl-app .ec-sentence{font:26px/1.9 Georgia,Times New Roman,serif;color:#4d673f;overflow-wrap:anywhere}.etl-app .ec-sentence mark{background:transparent;color:inherit;padding:2px 0;border-radius:4px;transition:background .15s}.etl-app .ec-sentence mark.is-active,.etl-app .ec-article-english mark{background:#e3d8ee;color:#65527a}.etl-app .ec-chinese{font-size:14px;color:#7d8e6a;margin:13px 0!important}.etl-app .ec-pattern{margin:19px 0!important;padding:11px 14px;border-radius:8px;background:#f3f0e6;color:#8b7a50;font-size:13px;overflow-wrap:anywhere}.etl-app .ec-sentence-diagram>p{margin-top:7px!important}.etl-app .ec-sentence-diagram{margin-top:25px}.etl-app .ec-language-note{padding:18px 21px;border-radius:10px;border:1px solid #e0d8cb;background:#faf6ee;margin-top:21px}.etl-app .ec-language-note p{font-size:13px;color:#887b61;margin-top:9px!important}.etl-app .ec-reader .ec-article-title{font:27px/1.5 Georgia,serif;margin-bottom:18px;color:#4f6b40}.etl-app .ec-reading-tools{display:flex;align-items:center;flex-wrap:wrap;gap:12px;margin-bottom:11px}.etl-app .ec-paragraph-map{display:flex;gap:8px;margin:21px 0}.etl-app .ec-paragraph-map button{flex:1;min-width:0}.etl-app .ec-paragraph-map svg{display:block;width:100%;height:8px;margin-bottom:7px}.etl-app .ec-paragraph-map span{font-size:10px}.etl-app .ec-paragraph{padding:16px 12px;border:1px solid transparent;border-radius:9px;scroll-margin-top:18px}.etl-app .ec-paragraph+.ec-paragraph{margin-top:7px}.etl-app .ec-paragraph.is-selected{background:#f6f9ef;border-color:#b1c597}.etl-app .ec-article-english{font:20px/1.95 Georgia,Times New Roman,serif;color:#4c603f;overflow-wrap:anywhere}.etl-app .ec-article-chinese{padding:13px 15px;margin-top:12px!important;font-size:13px;color:#7b886b;line-height:1.9;border-left:2px solid #c4d3b3;background:#f5f7ef}.etl-app .ec-paragraph .es-actions{margin-top:11px}.etl-app .ec-vocabulary{padding-top:22px;margin-top:12px;border-top:1px solid #e2e7d9}.etl-app .ec-vocabulary>p{margin-top:7px!important}.etl-app .ec-vocabulary-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:16px}.etl-app .ec-vocabulary-grid article{padding:14px 16px;border:1px solid #e2e5d5;background:#faf9f2;border-radius:10px;min-width:0}.etl-app .ec-vocabulary-word{font:23px/1.6 Georgia,serif!important;padding:0 0 4px!important;background:transparent!important;border:0!important;display:block;overflow-wrap:anywhere;max-width:100%;text-align:left}.etl-app .ec-vocabulary-grid p{font-size:12px;color:#83906e}.etl-app .ec-vocabulary-grid .es-actions{margin:10px 0}.etl-app .ec-vocabulary-grid [data-material-word-known]{font-size:11px!important}.etl-app .ec-analysis-actions{margin:26px 0;padding:19px 0;border-top:1px solid #e1e7d6;border-bottom:1px solid #e1e7d6}.etl-app .ec-analysis-actions .etl-presets{margin:13px 0 8px}.etl-app .ec-material-practice{border:1px solid #d4e1c5;border-radius:10px;background:#f4f8ed;padding:16px 18px}.etl-app .ec-material-practice>summary{color:#617f47;font-size:15px;cursor:pointer;font-weight:600}.etl-app .ec-material-practice .eg-practice{margin-top:17px;padding:0;border:0;background:transparent}.etl-app .ec-material-practice .eg-practice h2{font-size:18px}.etl-app .ec-material-practice .eg-choices button{font-size:15px!important}.etl-app .ec-material-practice .eg-review-list{padding-left:19px}@media(max-width:1160px){.etl-app .ec-layout{grid-template-columns:208px minmax(0,1fr);gap:15px}.etl-app .ec-reader{padding:22px}.etl-app .ec-vocabulary-grid{grid-template-columns:1fr}.etl-app .ec-index .etl-pagination{justify-content:center}.etl-app .ec-index .etl-pagination span{order:-1;width:100%;text-align:center}}@media(max-width:960px){.etl-app .ec-layout{grid-template-columns:minmax(0,1fr)}.etl-app .ec-index{position:static}.etl-app .ec-material-list{grid-template-columns:1fr 1fr;max-height:290px}.etl-app .ec-index .etl-pagination{justify-content:space-between}.etl-app .ec-index .etl-pagination span{width:auto;order:0}.etl-app .ec-vocabulary-grid{grid-template-columns:1fr 1fr}}@media(max-width:600px){.etl-app .ec-intro{padding:19px}.etl-app .ec-reader{padding:18px 14px}.etl-app .ec-reader h2{font-size:20px}.etl-app .ec-sentence{font-size:23px}.etl-app .ec-article-english{font-size:18px}.etl-app .ec-paragraph{padding:13px 5px}.etl-app .ec-article-chinese{padding:11px}.etl-app .ec-material-list,.etl-app .ec-vocabulary-grid{grid-template-columns:1fr}.etl-app .ec-paragraph-map{gap:5px}.etl-app .ec-paragraph-map button{padding:6px}.etl-app .ec-material-practice{padding:14px 11px}.etl-app .ec-language-note{padding:16px}}@media(prefers-reduced-motion:reduce){.etl-app .ec-sentence mark{transition:none}}.etl-app .elc-app .etl-tabs{gap:8px}.etl-app .elc-app .etl-tabs a{padding:15px 12px}.etl-app .elc-app .etl-tabs strong{font-size:13px}.etl-app .elc-app .etl-tabs span{font-size:11px}.etl-app .elc-workspace>.etl-switch{margin:14px 0}.etl-app .elc-bilingual .es-actions{margin-top:13px}@media(max-width:1000px){.etl-app .elc-app .etl-tabs{grid-template-columns:repeat(3,minmax(0,1fr))}}@media(max-width:640px){.etl-app .elc-app .etl-tabs{grid-template-columns:minmax(0,1fr)}}.etl-app .eep-header .el-header-actions{grid-row:2;grid-column:2;max-width:320px}.etl-app .egx-header .el-header-actions{grid-row:2;grid-column:2;max-width:320px}.etl-app .egx-stage.is-fullscreen .egx-overlay .es-actions button{background:#ffffffeb;color:#3e5533}@media(max-width:900px){.etl-app .egx-header .el-header-actions{max-width:100%}}.eg-app .eg-word-audio{display:inline;margin:0;padding:0}.eg-app .eg-word-audio .es-speak{display:inline-flex;vertical-align:baseline;min-height:0;margin:0;padding:0 1px;gap:0;border:0;border-bottom:1px dotted #a4b990;border-radius:2px;background:transparent;color:inherit;font:inherit;line-height:inherit}.eg-app .eg-word-audio .es-speak svg{display:none}.eg-app .eg-word-audio .es-speak:hover,.eg-app .eg-word-audio .es-speak[aria-pressed=true]{background:#eee7f6;color:#796191;border-bottom-color:#b59acc}.eg-app .eg-word-audio .es-inline-error{display:inline;font-size:11px;margin:0 5px}.etl-app .eg-word-audio-note{margin:9px 0!important;font-size:12px;color:#8b789c}.etl-app .eg-glossary,.etl-app .eg-structure-overview{margin-top:28px}.etl-app .eg-related-pages{margin-top:18px}.etl-app .eg-lesson-grid>.eg-related-pages{grid-column:1 / -1;margin-top:0}.etl-app .eg-reference-lead{margin:10px 0 15px!important;color:#77886a;font-size:13px;line-height:1.9}.etl-app .eg-glossary-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px;margin:14px 0}.etl-app .eg-glossary-grid>div{min-width:0;padding:17px;border:1px solid #dce5d1;border-radius:11px;background:#fbfcf6}.etl-app .eg-glossary-grid dt{display:flex;align-items:baseline;flex-wrap:wrap;gap:6px 10px;color:#516f3e}.etl-app .eg-glossary-grid dt strong{color:#769657;font:26px Georgia,serif}.etl-app .eg-glossary-grid dt span{font-size:13px;font-weight:600}.etl-app .eg-glossary-grid dd{margin:9px 0 0;color:#637653;font-size:12px;line-height:1.9;overflow-wrap:anywhere}.etl-app .eg-glossary-grid .eg-term-english{color:#8a987a;font-size:12px;margin-top:3px}.etl-app .eg-glossary-grid .eg-term-example{padding-top:9px;border-top:1px solid #e5e9dc;color:#847047}.etl-app .eg-glossary-more summary{padding:8px 0;color:#6f8958;font-size:13px;cursor:pointer}.etl-app .eg-reference-note{margin-top:14px!important;padding:14px 17px;border-radius:7px;border-left:3px solid #b4c995;color:#60734f;background:#eff4e6;font-size:13px;line-height:1.9}.etl-app .eg-reference-table-wrap{max-width:100%;overflow-x:auto;margin-top:15px;border:1px solid #d6e1ca;border-radius:12px;scrollbar-width:thin;scrollbar-color:#b6c9a2 #eef3e7}.etl-app .eg-reference-table{width:100%;min-width:640px;border-collapse:collapse;background:#fffef9;font-size:13px}.etl-app .eg-reference-table caption{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.etl-app .eg-reference-table th,.etl-app .eg-reference-table td{padding:16px 18px;text-align:left;vertical-align:top;border-bottom:1px solid #e2e8d8}.etl-app .eg-reference-table thead{background:#edf3e4;color:#6b8554;font-size:12px}.etl-app .eg-reference-table th{font-weight:500}.etl-app .eg-reference-table th[scope=row]{width:25%;min-width:192px}.etl-app .eg-reference-table th span{color:#5d764c}.etl-app .eg-reference-table td:nth-child(2){width:36%;color:#6c7e5e}.etl-app .eg-reference-table tr:last-child th,.etl-app .eg-reference-table tr:last-child td{border-bottom:0}.etl-app .eg-reference-table td p[lang=en]{margin-bottom:6px;color:#49643a;font:18px/1.65 Georgia,serif}.etl-app .eg-reference-table td p:last-child{color:#81916e;font-size:12px}.etl-app .eg-formula{display:block;margin-top:5px;color:#4b6c39;font:19px/1.6 Georgia,serif;white-space:normal}.etl-app .eg-explorer-groups{display:flex;flex-wrap:wrap;gap:8px;margin:16px 0}.etl-app .eg-explorer-groups button{display:flex;flex-direction:column;align-items:flex-start;min-height:52px;padding:8px 13px;border:1px solid #d3dfc7;border-radius:8px;background:#f7f9f1;color:#71885a;font-size:12px}.etl-app .eg-explorer-groups button strong{color:#52753d;font:17px/1.6 Georgia,serif}.etl-app .eg-explorer-groups button[aria-pressed=true]{background:#e9f2dd;border-color:#a8c085;box-shadow:inset 0 0 0 1px #b4c999}.etl-app .eg-explorer-description{padding:12px 15px;margin:10px 0!important;background:#f3f6ed;border-radius:8px;color:#6d805b;font-size:13px}.etl-app .eg-explorer-examples{display:flex;flex-wrap:wrap;gap:7px;margin:13px 0}.etl-app .eg-explorer-examples button{padding:7px 12px;min-height:40px;border:1px solid #dcd9c9;border-radius:7px;background:#fffdf6;color:#8a7850;font:17px/1.6 Georgia,serif;text-align:left;overflow-wrap:anywhere;max-width:100%}.etl-app .eg-explorer-examples button[aria-pressed=true]{border-color:#c1b080;background:#f5eedc;color:#705d33}.etl-app .eg-explorer-result{border-left:3px solid #c3d4b0;padding:6px 14px;margin:14px 0}.etl-app .eg-explorer-result p[lang=en]{font:23px/1.5 Georgia,serif;color:#4d6e3c;overflow-wrap:anywhere}.etl-app .eg-explorer-result p[data-visual-chinese]{margin-top:4px;color:#7d8d6b;font-size:13px}.etl-app .eg-explorer-result p[data-visual-note]{margin-top:7px;color:#887548;font-size:12px}.etl-app .eg-reference-table-wrap:focus-visible{outline:3px solid #a493cc;outline-offset:3px}@media(max-width:1200px){.etl-app .eg-glossary-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}@media(max-width:480px){.etl-app .eg-glossary-grid{grid-template-columns:1fr}.etl-app .eg-explorer-groups{display:grid;grid-template-columns:repeat(2,minmax(0,1fr))}.etl-app .eg-explorer-groups button{min-width:0;padding:8px}.etl-app .eg-explorer-groups button strong{font-size:15px}.etl-app .eg-explorer-examples button{font-size:16px}}.etl-app .eax-reference .es-actions{margin-top:7px}.etl-app .ec-cloze-passage{position:relative;padding:18px 26px;background:#fffefa;border:1px solid #d5dfcb;border-radius:12px}.etl-app .ecx-stage .ec-cloze-arcs{position:absolute;inset:0;width:100%;height:100%;max-width:none;margin:0;pointer-events:none;z-index:1}.etl-app .ec-cloze-text{position:relative;font:19px/2.7 Georgia,serif;overflow-wrap:anywhere}.etl-app .ec-cloze-text p{margin:20px 0}.etl-app .ec-cloze-text button{font:inherit;line-height:1.5;padding:3px 7px;position:relative;z-index:2;white-space:nowrap}.etl-app .ec-cloze-text .is-current{outline:2px solid #9773ac;outline-offset:2px;background:#eae0f2}.etl-app .ec-cloze-text .is-clue{background:#f6e7aa;text-decoration:underline;text-decoration-color:#a9843f;text-underline-offset:5px}.etl-app .ec-cloze-clues{font-size:15px;line-height:1.8;padding-left:20px}@media(max-width:560px){.etl-app .ec-cloze-passage{padding:10px 14px}.etl-app .ec-cloze-text{font-size:17px;line-height:2.9}}.etl-app .eht-header .el-header-actions{grid-row:2;grid-column:2;max-width:340px}.etl-app .eav-app button.eg-primary{background:var(--el-primary);color:#fff;border-color:var(--el-primary)}@keyframes cardSlideUp{0%{opacity:0;transform:translateY(16px) scale(.97)}to{opacity:1;transform:translateY(0) scale(1)}}.etl-app [data-english-theme=ocean] .el-content h1,.etl-app [data-english-theme=ocean] .el-content h2,.etl-app [data-english-theme=ocean] .el-content h3,.etl-app [data-english-theme=ocean] .el-content .et-header h1,.etl-app [data-english-theme=ocean] .el-content .en-header h1,.etl-app [data-english-theme=ocean] .el-content .eg-header h1,.etl-app [data-english-theme=ocean] .el-content .ep-header h1,.etl-app [data-english-theme=ocean] .el-content .ec-header h1,.etl-app [data-english-theme=ocean] .el-content .ecl-header h1,.etl-app [data-english-theme=ocean] .el-content .eep-header h1,.etl-app [data-english-theme=ocean] .el-content .elm-header h1,.etl-app [data-english-theme=ocean] .el-content .egx-header h1{color:#142230!important}.etl-app [data-english-theme=ocean] .el-content .et-header p,.etl-app [data-english-theme=ocean] .el-content .en-header p,.etl-app [data-english-theme=ocean] .el-content .ep-header p,.etl-app [data-english-theme=ocean] .el-content .ec-header p,.etl-app [data-english-theme=ocean] .el-content .eg-header p,.etl-app [data-english-theme=ocean] .el-content .ecl-header p,.etl-app [data-english-theme=ocean] .el-content .et-focus,.etl-app [data-english-theme=ocean] .el-content .et-translation,.etl-app [data-english-theme=ocean] .el-content .en-stage-heading p,.etl-app [data-english-theme=ocean] .el-content .et-summary,.etl-app [data-english-theme=ocean] .el-content .et-kicker,.etl-app [data-english-theme=ocean] .el-content .en-kicker{color:#536b84!important}.etl-app [data-english-theme=ocean] .el-content .et-eyebrow,.etl-app [data-english-theme=ocean] .el-content .en-eyebrow,.etl-app [data-english-theme=ocean] .el-content .eg-eyebrow,.etl-app [data-english-theme=ocean] .el-content .ep-eyebrow,.etl-app [data-english-theme=ocean] .el-content .ec-eyebrow,.etl-app [data-english-theme=ocean] .el-content .ecl-eyebrow,.etl-app [data-english-theme=ocean] .el-content .eep-eyebrow,.etl-app [data-english-theme=ocean] .el-content .elm-eyebrow,.etl-app [data-english-theme=ocean] .el-content .egx-eyebrow,.etl-app [data-english-theme=ocean] .el-content .eht-eyebrow{color:#3b6998!important}.etl-app [data-english-theme=ocean] .el-content .et-brand-symbol,.etl-app [data-english-theme=ocean] .el-content .en-brand-symbol,.etl-app [data-english-theme=ocean] .el-content .eg-brand-symbol{background:#e2eef8!important;color:#356291!important}.etl-app [data-english-theme=ocean] .el-content .et-stage,.etl-app [data-english-theme=ocean] .el-content .en-stage,.etl-app [data-english-theme=ocean] .el-content .eg-card,.etl-app [data-english-theme=ocean] .el-content .ep-card,.etl-app [data-english-theme=ocean] .el-content .vocab-card,.etl-app [data-english-theme=ocean] .el-content .exam-card,.etl-app [data-english-theme=ocean] .el-content .ecl-card{background:#fff!important;border-color:#d4e0ec!important;box-shadow:0 8px 24px #192d440d!important}.etl-app [data-english-theme=midnight] .el-content h1,.etl-app [data-english-theme=midnight] .el-content h2,.etl-app [data-english-theme=midnight] .el-content h3,.etl-app [data-english-theme=midnight] .el-content .et-header h1,.etl-app [data-english-theme=midnight] .el-content .en-header h1,.etl-app [data-english-theme=midnight] .el-content .eg-header h1,.etl-app [data-english-theme=midnight] .el-content .ep-header h1,.etl-app [data-english-theme=midnight] .el-content .ec-header h1,.etl-app [data-english-theme=midnight] .el-content .ecl-header h1,.etl-app [data-english-theme=midnight] .el-content .eep-header h1,.etl-app [data-english-theme=midnight] .el-content .elm-header h1,.etl-app [data-english-theme=midnight] .el-content .egx-header h1{color:#f8fafc!important}.etl-app [data-english-theme=midnight] .el-content .et-header p,.etl-app [data-english-theme=midnight] .el-content .en-header p,.etl-app [data-english-theme=midnight] .el-content .ep-header p,.etl-app [data-english-theme=midnight] .el-content .ec-header p,.etl-app [data-english-theme=midnight] .el-content .eg-header p,.etl-app [data-english-theme=midnight] .el-content .ecl-header p,.etl-app [data-english-theme=midnight] .el-content .et-focus,.etl-app [data-english-theme=midnight] .el-content .et-translation,.etl-app [data-english-theme=midnight] .el-content .en-stage-heading p,.etl-app [data-english-theme=midnight] .el-content .et-summary,.etl-app [data-english-theme=midnight] .el-content .et-kicker,.etl-app [data-english-theme=midnight] .el-content .en-kicker{color:#94a3b8!important}.etl-app [data-english-theme=midnight] .el-content .et-eyebrow,.etl-app [data-english-theme=midnight] .el-content .en-eyebrow,.etl-app [data-english-theme=midnight] .el-content .eg-eyebrow,.etl-app [data-english-theme=midnight] .el-content .ep-eyebrow,.etl-app [data-english-theme=midnight] .el-content .ec-eyebrow,.etl-app [data-english-theme=midnight] .el-content .ecl-eyebrow,.etl-app [data-english-theme=midnight] .el-content .eep-eyebrow,.etl-app [data-english-theme=midnight] .el-content .elm-eyebrow,.etl-app [data-english-theme=midnight] .el-content .egx-eyebrow,.etl-app [data-english-theme=midnight] .el-content .eht-eyebrow{color:#38bdf8!important}.etl-app [data-english-theme=midnight] .el-content .et-brand-symbol,.etl-app [data-english-theme=midnight] .el-content .en-brand-symbol,.etl-app [data-english-theme=midnight] .el-content .eg-brand-symbol{background:#1e293b!important;color:#38bdf8!important}.etl-app [data-english-theme=midnight] .el-content .et-stage,.etl-app [data-english-theme=midnight] .el-content .en-stage,.etl-app [data-english-theme=midnight] .el-content .eg-card,.etl-app [data-english-theme=midnight] .el-content .ep-card,.etl-app [data-english-theme=midnight] .el-content .vocab-card,.etl-app [data-english-theme=midnight] .el-content .exam-card,.etl-app [data-english-theme=midnight] .el-content .ecl-card{background:#1c222e!important;border-color:#2a3446!important;box-shadow:0 8px 30px #00000073!important}.etl-app .el-header-actions{display:flex;flex-direction:column;align-items:flex-end;justify-content:center;flex:0 0 auto;gap:10px;max-width:52%}.etl-app .el-header-actions .el-page-toolbar{max-width:100%;margin:0}@media(max-width:720px){.etl-app .el-header-actions{max-width:100%;align-items:flex-start;margin-top:18px}.etl-app .el-header-actions .el-page-toolbar{align-self:flex-end}}

/* ---------- 句法实验室（#/syntax-lab）与文本与阅读理解（#/reading-lab）改成站内手绘腔 ----------
   这两页（syntaxLab.js / readingLab.js）的正文逐字复用上游 SENTENCE EXPLORER 那套
   .etl-* / .ec-* 类名，原始样式是「扁平上游风」（浅绿描边 + 系统字体 + 白底），画在
   纸面站里像贴错了版式。两页的根节点都加了一个 .lab-sketch 标记类，这里把同一批类名
   重新描成站内手绘腔：纸底、墨色字、手写框半径、绿/棕强调、偏移纸影。
   规则一律带 .lab-sketch 前缀。上游那份 .etl-app 块的原始样式保持不动（两页共用同一
   份类名表），只在这个标记类的页面里覆盖 —— 新增第三个用这套上游类的页面时，别顺手
   加这个标记，否则它也会被一起改掉。 */

.lab-sketch { font-family: var(--font-body); color: var(--ink); }
.lab-sketch .etl-small, .lab-sketch .etl-muted { color: var(--ink-soft); }
.lab-sketch .etl-kicker { font-family: var(--font-ui); letter-spacing: .16em; color: var(--action); }
.lab-sketch h2, .lab-sketch h3, .lab-sketch h4 { font-family: var(--font-body); color: var(--ink); }
.lab-sketch .etl-card h3, .lab-sketch .ec-reader h3, .lab-sketch .ec-reader h4 { color: var(--accent); }

/* 纸卡：正文里每一张卡。偶数张镜像半径，取全站手绘错落的做法。 */
.lab-sketch .etl-card, .lab-sketch .ec-reader, .lab-sketch .ec-intro,
.lab-sketch .ec-filters, .lab-sketch .ec-index, .lab-sketch .etl-editor,
.lab-sketch .etl-word-card, .lab-sketch .eg-exercise-entry, .lab-sketch .ec-material-practice {
  background: var(--paper-card);
  border: var(--w-aux) solid var(--ink-faint);
  border-radius: 255px 15px 225px 15px / 15px 225px 15px 255px;
  box-shadow: 2px 3px 0 rgba(51, 48, 43, .07);
}
.lab-sketch .etl-card:nth-child(even), .lab-sketch .ec-vocabulary-grid article:nth-child(even) {
  border-radius: 15px 225px 15px 255px / 225px 15px 255px 15px;
}
.lab-sketch .ec-reader-heading { border-bottom: 1px dashed var(--ink-faint); }

/* 标签页：四张扁平贴纸换成手写钮。 */
.lab-sketch .etl-tabs a {
  background: var(--paper); border: var(--w-aux) solid var(--ink-faint);
  border-radius: 14px 5px 13px 5px / 5px 13px 5px 14px;
  transition: border-color .2s, background .2s, box-shadow .2s;
}
.lab-sketch .etl-tabs a:nth-child(even) { border-radius: 5px 14px 5px 13px / 13px 5px 14px 5px; }
.lab-sketch .etl-tabs a:hover { border-color: var(--accent); background: var(--marker); }
.lab-sketch .etl-tabs a[aria-current=page] {
  background: var(--paper); border-color: var(--ink);
  box-shadow: inset 0 -3px 0 var(--marker);
}
.lab-sketch .etl-tabs strong { color: var(--ink); }
.lab-sketch .etl-tabs span { color: var(--ink-soft); }

/* 输入 / 下拉 / 文本域：统一手写描边。文本域里是要读的英语，用楷体。 */
.lab-sketch input, .lab-sketch select, .lab-sketch textarea {
  border: var(--w-aux) solid var(--ink-faint);
  border-radius: 10px 4px 9px 4px / 4px 9px 4px 10px;
  background: var(--paper); color: var(--ink); font-family: var(--font-body);
}
.lab-sketch textarea { font-size: 19px; color: var(--ink); line-height: 1.95; }
.lab-sketch input:focus-visible, .lab-sketch select:focus-visible, .lab-sketch textarea:focus-visible,
.lab-sketch [tabindex]:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.lab-sketch .etl-toolbar label { color: var(--ink-soft); }
.lab-sketch .etl-checkbox input { accent-color: var(--action); }

/* 按钮：上游那条通用按钮规则用了五层 :not()，特异性很高；这里用同一串 :not()
   再加 .lab-sketch 前缀压过它（多一层类，靠源序在后取胜）。排除项照抄，免得把
   eg-primary / 朗读药丸 / 原文里的词元 / 句号钮也一起改了。 */
.lab-sketch button:not(.eg-primary):not(.eg-secondary):not(.es-speak):not(.etl-text-token):not(.etl-sentence-number) {
  background: var(--paper); color: var(--ink);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 255px 12px 225px 12px / 12px 225px 12px 255px;
  font-family: var(--font-body);
  transition: border-color .2s, background .2s, color .2s;
}
.lab-sketch button:not(.eg-primary):not(.eg-secondary):not(.es-speak):not(.etl-text-token):not(.etl-sentence-number):hover {
  border-color: var(--accent); color: var(--accent); background: var(--marker);
}
.lab-sketch button[aria-pressed=true]:not(.es-speak):not(.etl-text-token):not(.etl-sentence-number) {
  background: var(--marker); border-color: var(--accent); color: var(--accent);
}
.lab-sketch .etl-frequency-list button { font-family: var(--font-note) !important; }
.lab-sketch .etl-sentence-number {
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 8px 3px 7px 3px / 3px 7px 3px 8px;
  background: var(--paper); color: var(--ink-soft); font-family: var(--font-note);
}
/* 主按钮（「分析文本」「开始练习」）：改成手写描边 + 绿字，与全站 .lab-entry-link 同款。 */
.lab-sketch .eg-primary, .lab-sketch a.eg-primary {
  background: none; color: var(--action); border: var(--w-note) solid var(--action);
  border-radius: 255px 14px 225px 14px / 14px 225px 14px 255px;
}
.lab-sketch .eg-primary:hover, .lab-sketch a.eg-primary:hover { background: var(--marker); color: var(--action); }

/* 统计格子。 */
.lab-sketch .etl-stats > div {
  background: var(--paper); border: var(--w-aux) solid var(--ink-faint);
  border-radius: 14px 5px 13px 5px / 5px 13px 5px 14px;
}
.lab-sketch .etl-stats > div:nth-child(even) { border-radius: 5px 14px 5px 13px / 13px 5px 14px 5px; }
.lab-sketch .etl-stats strong { font-family: var(--font-note); font-weight: 700; color: var(--action); }
.lab-sketch .etl-stats span { color: var(--ink-soft); }

/* 选中详情 / 说明块。 */
.lab-sketch .etl-selection {
  background: var(--paper); border-left: 4px solid var(--action);
  border-radius: 255px 15px 225px 15px / 15px 225px 15px 255px;
}
.lab-sketch .etl-selection h3 { color: var(--action); }
.lab-sketch .etl-selection p { color: var(--ink-soft); }
.lab-sketch .etl-selection p[lang=en] { font-family: var(--font-note); font-size: 22px; color: var(--ink); }
.lab-sketch .etl-notes, .lab-sketch .etl-method {
  background: var(--paper); border: var(--w-aux) solid var(--ink-faint);
  border-radius: 14px 5px 13px 5px / 5px 13px 5px 14px; color: var(--ink-soft);
}
.lab-sketch .etl-method summary, .lab-sketch .ec-index summary { color: var(--action); }
.lab-sketch a { color: var(--action); }

/* 「标准说法 / 换个容易懂的说法」两栏。 */
.lab-sketch .etl-explain {
  background: var(--paper-card); border: var(--w-aux) solid var(--ink-faint);
  border-radius: 255px 15px 225px 15px / 15px 225px 15px 255px;
}
.lab-sketch .etl-explain p { color: var(--ink-soft); }
.lab-sketch .etl-explain p + p { background: var(--paper); }
.lab-sketch .etl-explain strong { color: var(--accent); }

/* 图表滚动框。 */
.lab-sketch .etl-chart-scroll {
  background: var(--paper); border: var(--w-aux) solid var(--ink-faint);
  scrollbar-color: var(--ink-faint) var(--paper);
}
.lab-sketch .etl-chart-scroll::-webkit-scrollbar-track { background: var(--paper); }
.lab-sketch .etl-chart-scroll::-webkit-scrollbar-thumb { background: var(--ink-faint); }

/* 图内文字与小标签：换成墨色 / 楷体，别再用上游那套系统字体 + 绿。 */
.lab-sketch .etl-heat-cell text { fill: var(--ink); font-family: var(--font-body); }
.lab-sketch .etl-heat-foot { fill: var(--ink-soft); }
.lab-sketch .etl-node-label { fill: var(--ink); font-family: var(--font-ui); }
.lab-sketch .etl-node-subtitle { fill: var(--ink-soft); font-family: var(--font-ui); }
.lab-sketch .etl-cloud-word text { fill: var(--action); font-family: var(--font-body); }
.lab-sketch .etl-cloud-word .etl-cloud-count { fill: var(--ink-soft); }
.lab-sketch .etl-cloud-word rect { fill: var(--paper-card); stroke: var(--ink-faint); }
.lab-sketch .etl-cloud-word:hover rect, .lab-sketch .etl-cloud-word.is-active rect,
.lab-sketch .etl-cloud-word:focus-visible rect { fill: var(--marker); stroke: var(--accent); }
.lab-sketch .etl-sketch-bar text { fill: var(--ink-soft); }
.lab-sketch .etl-sketch-bar .etl-sketch-word { fill: var(--ink); font-family: var(--font-body); }
.lab-sketch .etl-sketch-bar:focus-visible rect, .lab-sketch .etl-sketch-bar.is-active rect { stroke: var(--accent); stroke-width: 2; }
.lab-sketch .etl-synonym-node rect { fill: var(--paper-card); stroke: var(--accent); }
.lab-sketch .etl-synonym-node.is-active rect, .lab-sketch .etl-synonym-node:focus-visible rect { fill: var(--marker); stroke: var(--action); }

/* 原文联动区 / 单词卡。 */
.lab-sketch .etl-source-sentence.is-selected { border-color: var(--accent); box-shadow: inset 3px 0 var(--marker); }
.lab-sketch .etl-source-words { font-family: var(--font-note); color: var(--ink); }
.lab-sketch .etl-text-token:hover { background: var(--marker); }
.lab-sketch .etl-word-card { border-top: 3px solid var(--accent); }
.lab-sketch .etl-word-card h3 { font-family: var(--font-note); color: var(--accent); }
.lab-sketch .etl-meaning, .lab-sketch .etl-remote-definition { color: var(--ink); }
.lab-sketch .etl-example {
  background: var(--paper); border: 1px dashed var(--ink-faint);
  border-radius: 10px 4px 9px 4px / 4px 9px 4px 10px;
}
.lab-sketch .etl-example p[lang=en] { font-family: var(--font-note); color: var(--ink); }
.lab-sketch .etl-occurrence { border-top: 1px dashed var(--ink-faint); }
.lab-sketch .etl-occurrence p { font-family: var(--font-note); }

/* 编辑器。 */
.lab-sketch .etl-editor-heading label { color: var(--ink); }
.lab-sketch .etl-editor-bottom p, .lab-sketch .etl-sample-note,
.lab-sketch .etl-analysis-status { color: var(--ink-soft); }
.lab-sketch .etl-analysis-status.is-error { color: var(--alert); }

/* 素材库。 */
.lab-sketch .ec-intro p { color: var(--ink-soft); }
.lab-sketch .ec-material-list { scrollbar-color: var(--ink-faint) var(--paper); }
.lab-sketch .ec-material-list strong { color: var(--ink); }
.lab-sketch .ec-material-list small { color: var(--ink-soft); }
.lab-sketch .ec-material-number { font-family: var(--font-note); color: var(--ink-faint); }
.lab-sketch .ec-reader-controls a { color: var(--action); }
.lab-sketch .ec-tags span {
  background: var(--paper); border: var(--w-aux) solid var(--ink-faint);
  border-radius: 10px 3px 9px 3px / 3px 9px 3px 10px; color: var(--ink-soft);
}
.lab-sketch .ec-analysis-actions { border-top: 1px dashed var(--ink-faint); border-bottom: 1px dashed var(--ink-faint); }

/* 文章阅读器。 */
.lab-sketch .ec-reader .ec-article-title { font-family: var(--font-note); color: var(--ink); }
.lab-sketch .ec-article-english { font-family: var(--font-body); color: var(--ink); }
.lab-sketch .ec-article-english mark { background: var(--marker); color: var(--accent); }
.lab-sketch .ec-article-chinese {
  background: var(--paper); border-left: 2px solid var(--ink-faint); color: var(--ink-soft);
}
.lab-sketch .ec-block-label { color: var(--accent); }
.lab-sketch .ec-paragraph.is-selected { background: var(--paper); border-color: var(--accent); }
.lab-sketch .ec-document-notice, .lab-sketch .ec-document-poster,
.lab-sketch .ec-document-advert, .lab-sketch .ec-document-letter {
  background: var(--paper-card); border: var(--w-note) solid var(--ink-faint);
  border-radius: 255px 15px 225px 15px / 15px 225px 15px 255px;
}
.lab-sketch .ec-vocabulary-grid article {
  background: var(--paper); border: var(--w-aux) solid var(--ink-faint);
  border-radius: 14px 5px 13px 5px / 5px 13px 5px 14px;
}
.lab-sketch .ec-vocabulary-word { font-family: var(--font-note) !important; color: var(--ink); }

/* 练习入口与练习区。 */
.lab-sketch .eg-exercise-entry { background: var(--paper-card); }
.lab-sketch .eg-exercise-entry p { color: var(--ink-soft); }
.lab-sketch .ec-material-practice { background: var(--paper); }

/* 句法实验室专有：图例、图形工具条、依存关系图里的关系标签文字。 */
.lab-sketch .etl-legend, .lab-sketch .etl-chart-tools { color: var(--ink-soft); }
.lab-sketch .etl-dependency-edge text { fill: var(--ink-soft); font-family: var(--font-body); }
.lab-sketch .etl-occurrence-link { color: var(--action); }

/* 句法树 / 依存关系图的活动态与聚焦态：上游画的是紫（#e6efda / #a083ba / #8771a1 /
   #eee7f5），跟站内的纸墨色不搭，这里改回 marker/action/accent。选择器逐条对齐上游
   （含 .is-active / :focus-within / :focus-visible 那几个组合），否则压不过。 */
.lab-sketch .etl-tree-node.is-active rect,
.lab-sketch .etl-dependency-node.is-active rect { fill: var(--marker); stroke-width: 2.4; }
.lab-sketch .etl-tree-node:focus-visible rect,
.lab-sketch .etl-dependency-node:focus-visible rect,
.lab-sketch .etl-cloud-word:focus-visible rect,
.lab-sketch .etl-heat-cell:focus-visible rect,
.lab-sketch .etl-synonym-node:focus-visible rect { stroke: var(--accent); stroke-width: 2.4; }
.lab-sketch .etl-dependency-edge.is-active .etl-dependency-line,
.lab-sketch .etl-dependency-edge:focus-within .etl-dependency-line { stroke: var(--action); stroke-width: 2.4; }
.lab-sketch .etl-dependency-edge.is-active .etl-dependency-label rect,
.lab-sketch .etl-dependency-label:focus-visible rect { fill: var(--paper-card); stroke: var(--accent); stroke-width: 1.6; }

/* ---------- 阅读证据 / 文体结构（文本与阅读理解两页的活动区） ---------- */
/* 和集合图、数词工具同一副卡：原站 .ecs-activity 就是描边 + 圆角 + 浅底的面板，
   它是夹在导语与图解之间的一块活动，不是正文的一节。 */
.lab-readevidence, .lab-readstructure {
  padding: 18px 20px 20px;
  background: var(--paper-card);
  border: var(--w-note) solid var(--ink-faint);
  border-radius: 225px 16px 255px 16px / 16px 255px 16px 225px;
  box-shadow: 2px 3px 0 rgba(51, 48, 43, .07);
}
.lab-readevidence > h2, .lab-readstructure > h2 {
  margin: 0 0 10px; font-family: var(--font-body); font-size: 20px; font-weight: 700;
}
.lab-readevidence-lead, .lab-readstructure-lead {
  margin: 0; font-size: 13px; line-height: 1.8; color: var(--ink-soft);
}

/* 题型标签与「选择结论」是同一副按钮：一排浅底小药丸，选中的压上 marker。 */
.lab-readevidence-tabs {
  display: flex; flex-wrap: wrap; gap: 8px; margin: 14px 0 0;
}
.lab-readevidence-tabs button {
  font: inherit; font-family: var(--font-ui); font-size: 13px; color: var(--ink-soft);
  background: var(--paper); border: var(--w-aux) solid var(--ink-faint);
  border-radius: 999px; padding: 5px 12px; cursor: pointer;
}
.lab-readevidence-tabs button[aria-pressed='true'] {
  background: var(--marker); border-color: var(--accent); color: var(--accent);
}
.lab-readevidence-prompt {
  margin: 16px 0 0; font-family: var(--font-note); font-size: 22px; line-height: 1.35;
  color: var(--ink); font-weight: 400;
}
.lab-readevidence-stage { margin: 6px 0 0; }

/* 关系图那条小字与状态行。上游是 .ecs-small（13px 浅色）。 */
.lab-readevidence-small { margin: 10px 0 8px; font-size: 13px; line-height: 1.8; color: var(--ink-soft); }
.lab-readevidence-relation svg { display: block; width: 100%; max-width: 720px; height: auto; margin: 4px auto 8px; }
/* 连线的形状在手绘滤镜里（SK.group），颜色是数据含义：两格都选好才变实。 */
.lab-readevidence-edge { stroke: var(--ink-faint); stroke-width: 3; }
.lab-readevidence-edge.is-complete { stroke: var(--action); }
.lab-readevidence-relation text { fill: var(--ink); font-family: var(--font-body); }
.lab-readevidence-relation rect { fill: var(--tint-right); stroke: var(--ink-faint); }

/* 可选的原文段落：整段就是一颗按钮，选中的描重。 */
.lab-readevidence-paragraphs { display: flex; flex-direction: column; gap: 8px; margin: 0 0 10px; }
.lab-readevidence-paragraph {
  text-align: left; font: inherit; font-family: var(--font-note); font-size: 17px; line-height: 1.5;
  color: var(--ink); background: var(--paper); border: var(--w-aux) solid var(--ink-faint);
  border-radius: 10px; padding: 9px 12px; cursor: pointer;
}
.lab-readevidence-paragraph:hover:not(:disabled) { border-color: var(--ink); }
.lab-readevidence-paragraph[aria-pressed='true'] {
  background: var(--marker); border-color: var(--accent);
}
.lab-readevidence-paragraph:disabled { cursor: default; }
.lab-readevidence-status { margin: 10px 0 0; font-size: 13px; line-height: 1.8; color: var(--ink-soft); }
.lab-readevidence-check {
  font: inherit; font-family: var(--font-ui); font-size: 14px; color: var(--ink);
  background: var(--paper); border: var(--w-note) solid var(--ink-faint);
  border-radius: 10px; padding: 7px 16px; margin: 6px 0 0; cursor: pointer;
}
.lab-readevidence-check:hover:not(:disabled) { border-color: var(--ink); }
.lab-readevidence-check:disabled { cursor: default; opacity: .6; }
.lab-readevidence-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px; margin: 14px 0 0; }
.lab-readevidence-more {
  font: inherit; font-family: var(--font-ui); font-size: 14px; color: var(--ink);
  background: var(--paper); border: var(--w-note) solid var(--ink-faint);
  border-radius: 10px; padding: 7px 16px; cursor: pointer;
}
.lab-readevidence-more:hover:not(:disabled) { border-color: var(--ink); }
.lab-readevidence-more:disabled { cursor: default; opacity: .5; }
.lab-readevidence-link, .lab-readstructure-link { font-family: var(--font-ui); font-size: 13px; color: var(--action); }

/* --- 文体结构 --- */
.lab-readstructure-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 18px; margin: 14px 0 0; }
.lab-readstructure-toolbar label {
  display: flex; align-items: center; gap: 8px;
  font-family: var(--font-ui); font-size: 13px; color: var(--ink-soft);
}
.lab-readstructure-toolbar button {
  font: inherit; font-family: var(--font-ui); font-size: 13px; color: var(--ink-soft);
  background: var(--paper); border: var(--w-aux) solid var(--ink-faint);
  border-radius: 999px; padding: 5px 12px; cursor: pointer;
}
.lab-readstructure-toolbar button[aria-pressed='true'] { background: var(--marker); border-color: var(--accent); color: var(--accent); }
.lab-readstructure-note { margin: 12px 0 0; font-size: 13px; line-height: 1.8; color: var(--ink-soft); }
.lab-readstructure-svg { display: block; width: 100%; max-width: 900px; height: auto; margin: 10px auto; }
.lab-readstructure-edge { stroke: #a3b78e; stroke-width: 2; }
.lab-readstructure-block rect { fill: var(--tint-right); stroke: var(--ink-faint); }
.lab-readstructure-block.is-active rect { fill: var(--marker); stroke: var(--accent); stroke-width: 2.4; }
.lab-readstructure-block text { fill: var(--ink); font-family: var(--font-body); }
.lab-readstructure-block { cursor: pointer; }
.lab-readstructure-block:focus-visible rect { stroke: var(--accent); stroke-width: 2.4; }

.lab-readstructure-5w { display: flex; flex-wrap: wrap; gap: 8px; margin: 8px 0 0; }
.lab-readstructure-5w:empty { display: none; }
.lab-readstructure-5w button {
  font: inherit; font-family: var(--font-ui); font-size: 13px; color: var(--ink-soft);
  background: var(--paper); border: var(--w-aux) solid var(--ink-faint);
  border-radius: 999px; padding: 5px 12px; cursor: pointer;
}
.lab-readstructure-5w button:hover { border-color: var(--ink); }
.lab-readstructure-questions { margin: 14px 0 0; }
.lab-readstructure-questions h3 { margin: 0 0 8px; font-family: var(--font-body); font-size: 15px; font-weight: 700; }
.lab-readstructure-questions button {
  display: block; width: 100%; text-align: left;
  font: inherit; font-family: var(--font-note); font-size: 17px; line-height: 1.4;
  color: var(--ink); background: var(--paper); border: var(--w-aux) solid var(--ink-faint);
  border-radius: 10px; padding: 8px 12px; margin: 0 0 8px; cursor: pointer;
}
.lab-readstructure-questions button:hover { border-color: var(--ink); }
.lab-readstructure-questions button[aria-pressed='true'] { background: var(--marker); border-color: var(--accent); }
.lab-readstructure-status { margin: 10px 0 0; font-size: 13px; line-height: 1.8; color: var(--ink-soft); }

/* 原文分段：每段一张小卡，选中的段落描重；行间依据用 <mark> 标出来。 */
.lab-readstructure-parts { display: flex; flex-direction: column; gap: 12px; margin: 14px 0 0; }
.lab-readstructure-paragraph {
  padding: 10px 12px; border: var(--w-aux) solid transparent; border-radius: 10px;
}
.lab-readstructure-paragraph.is-selected { border-color: var(--accent); background: var(--paper); }
.lab-readstructure-block-label { margin: 0 0 6px; font-family: var(--font-body); font-size: 13px; font-weight: 700; color: var(--ink-soft); }
.lab-readstructure-english { font-family: var(--font-note); font-size: 18px; line-height: 1.55; color: var(--ink); }
.lab-readstructure-english p { margin: 0; }
.lab-readstructure-english mark[data-evidence] { background: var(--marker); color: var(--ink); padding: 0 2px; border-radius: 3px; }
.lab-readstructure-chinese { margin: 6px 0 0; font-size: 13px; line-height: 1.8; color: var(--ink-soft); }
.lab-readstructure-table { border-collapse: collapse; width: 100%; min-width: 480px; font-family: var(--font-body); font-size: 14px; }
.lab-readstructure-table caption { text-align: left; font-size: 13px; color: var(--ink-soft); padding: 0 0 6px; }
.lab-readstructure-table th, .lab-readstructure-table td {
  border: var(--w-aux) solid var(--ink-faint); padding: 6px 9px; text-align: left;
}
.lab-readstructure-table th { background: var(--paper); }
.lab-readstructure-link { display: inline-block; margin: 14px 0 0; }

/* ---------- 交互与动画（#/interactive-lab）----------
   照上游 html-topics 的「目录 + 嵌入查看器」。外框走站内手绘风（同一套卡片圆角、
   虚线、实色按钮），课件本体在 iframe 里、样式自管，不跟站内调色板走。 */
.lab-itv-toolbar { display: flex; gap: 14px; align-items: center; flex-wrap: wrap; margin: 2px 0 16px; }
.lab-itv-search {
  font: inherit; font-family: var(--font-ui); font-size: 14px; color: var(--ink);
  background: var(--paper-card); border: var(--w-aux) solid var(--ink-faint);
  border-radius: 999px; padding: 8px 16px; min-width: 240px; flex: 1 1 260px;
}
.lab-itv-search:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.lab-itv-stats { margin: 0; font-family: var(--font-ui); font-size: 13px; color: var(--ink-soft); }
.lab-itv-empty { margin: 8px 0; font-size: 13px; color: var(--ink-soft); }

/* 目录：卡片网格。圆角与实心按钮沿用 .lab-readevidence 那套手绘卡片。 */
.lab-itv-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 16px; }
.lab-itv-card {
  display: flex; flex-direction: column; padding: 16px 18px 14px;
  background: var(--paper-card); border: var(--w-note) solid var(--ink-faint);
  border-radius: 225px 16px 255px 16px / 16px 255px 16px 225px;
  box-shadow: 2px 3px 0 rgba(51,48,43,.07);
}
.lab-itv-badge {
  align-self: flex-start; font-family: var(--font-ui); font-size: 12px; color: var(--accent);
  background: var(--marker); border-radius: 999px; padding: 3px 11px; margin-bottom: 10px;
}
.lab-itv-card-title { margin: 0 0 6px; font-family: var(--font-note); font-size: 20px; font-weight: 400; color: var(--ink); }
.lab-itv-card-desc { margin: 0 0 14px; font-size: 13px; line-height: 1.8; color: var(--ink-soft); flex: 1; }
.lab-itv-card-footer {
  display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap;
  border-top: 1px dashed var(--ink-faint); padding-top: 10px;
}
.lab-itv-card-meta {
  font-family: var(--font-ui); font-size: 12px; color: var(--ink-soft);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 46%;
}
.lab-itv-card-actions { display: flex; gap: 8px; }

/* 按钮：一颗样式到处用（卡片、查看器工具条）。 */
.lab-itv-btn {
  font: inherit; font-family: var(--font-ui); font-size: 13px; line-height: 1; cursor: pointer;
  border-radius: 999px; padding: 7px 14px; border: var(--w-aux) solid var(--ink-faint);
  background: var(--paper); color: var(--ink-soft); text-decoration: none;
}
.lab-itv-btn:hover { border-color: var(--ink); color: var(--ink); }
.lab-itv-btn-subtle { background: transparent; }
.lab-itv-btn-primary { background: var(--action); border-color: var(--action); color: #fff; }
.lab-itv-btn-primary:hover { color: #fff; border-color: var(--action); filter: brightness(1.05); }

/* 查看器：工具条 + iframe 外框。 */
.lab-itv-viewer-toolbar {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  flex-wrap: wrap; margin: 2px 0 12px;
}
.lab-itv-viewer-title { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.lab-itv-viewer-current { font-family: var(--font-note); font-size: 18px; color: var(--ink); }
.lab-itv-select {
  font: inherit; font-family: var(--font-ui); font-size: 13px; color: var(--ink);
  background: var(--paper-card); border: var(--w-aux) solid var(--ink-faint);
  border-radius: 999px; padding: 6px 12px;
}
.lab-itv-viewer-controls { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.lab-itv-devices { display: flex; gap: 4px; }
.lab-itv-device {
  font: inherit; font-family: var(--font-ui); font-size: 12px; cursor: pointer;
  border: var(--w-aux) solid var(--ink-faint); background: var(--paper); color: var(--ink-soft);
  border-radius: 999px; padding: 6px 11px;
}
.lab-itv-device:hover { border-color: var(--ink); }
.lab-itv-device[aria-pressed='true'] { background: var(--marker); border-color: var(--accent); color: var(--accent); }

.lab-itv-frame-box {
  background: var(--paper); border: var(--w-note) solid var(--ink-faint);
  border-radius: 16px; padding: 10px; box-shadow: 2px 3px 0 rgba(51,48,43,.07);
}
.lab-itv-frame { margin: 0 auto; max-width: 100%; transition: max-width .18s ease; }
.lab-itv-frame.is-desktop { max-width: 100%; }
.lab-itv-frame.is-tablet { max-width: 820px; }
.lab-itv-frame.is-mobile { max-width: 390px; }
.lab-itv-iframe {
  display: block; width: 100%; height: 74vh; min-height: 520px; border: 0;
  border-radius: 10px; background: #fff;
}
.lab-itv-frame-box:fullscreen { background: #f3f0e9; padding: 20px; border: 0; border-radius: 0; }
.lab-itv-frame-box:fullscreen .lab-itv-frame { max-width: none; }
.lab-itv-frame-box:fullscreen .lab-itv-iframe { height: 100%; }
