/* ===== 阅读探险家 · 设计系统 ===== */
:root{
  --bg:#FBF7F0;
  --surface:#FFFFFF;
  --surface-2:#F5EFE6;
  --line:#E7DDCE;
  --line-soft:#F0E8DB;
  --ink:#3A3227;
  --ink-2:#6B6152;
  --ink-3:#9C9182;
  --brand:#E8813A;
  --brand-soft:#FDEEE2;
  --brand-deep:#C8642A;
  --sky:#4A9BC4;
  --sky-soft:#E6F3FA;
  --green:#5FA36B;
  --green-soft:#E8F4EA;
  --red:#D4614F;
  --red-soft:#FBE9E6;
  --purple:#8B7BC7;
  --purple-soft:#EFECFA;
  --amber:#E3A32A;
  --radius:16px;
  --radius-sm:10px;
  --shadow:0 2px 8px rgba(120,100,70,.06), 0 12px 28px rgba(120,100,70,.06);
  --shadow-lg:0 8px 30px rgba(120,100,70,.12);
  --font: "PingFang SC","Microsoft YaHei","Hiragino Sans GB",system-ui,-apple-system,"Segoe UI",sans-serif;
}
*{box-sizing:border-box}
html,body{height:100%}
body{
  margin:0;background:var(--bg);color:var(--ink);font-family:var(--font);
  font-size:15px;line-height:1.65;-webkit-font-smoothing:antialiased;
}
h1,h2,h3{margin:0;line-height:1.35}
button{font-family:inherit;cursor:pointer}
input,textarea,select{font-family:inherit;font-size:15px;color:var(--ink)}
/* 提示文字统一成一个颜色。不写这条的话各浏览器默认值不一样
   （Chrome 偏灰、Safari 偏淡、Firefox 还带透明度），
   同一个表单里几个框的提示文字看着深浅不一。 */
::placeholder{color:var(--ink-3);opacity:1}
.muted{color:var(--ink-3)}
.hidden{display:none !important}

/* ===== 顶栏 ===== */
.topbar{
  height:62px;display:flex;align-items:center;gap:24px;padding:0 22px;
  background:var(--surface);border-bottom:1px solid var(--line);
  position:sticky;top:0;z-index:50;
}
.brand{display:flex;align-items:center;gap:10px}
.brand-mark{
  width:36px;height:36px;border-radius:11px;display:grid;place-items:center;
  background:linear-gradient(135deg,var(--brand),var(--amber));color:#fff;font-weight:800;font-size:14px;
  letter-spacing:.5px;box-shadow:0 3px 10px rgba(232,129,58,.32);
}
.brand-text{display:flex;flex-direction:column;line-height:1.2}
.brand-text strong{font-size:15px}
.brand-text small{color:var(--ink-3);font-size:11px}
.nav{display:flex;gap:4px;margin-left:8px}
.nav-btn{
  border:0;background:transparent;padding:8px 16px;border-radius:10px;
  color:var(--ink-2);font-size:14px;font-weight:600;transition:.15s;
}
.nav-btn:hover{background:var(--surface-2)}
.nav-btn.active{background:var(--brand-soft);color:var(--brand-deep)}
.topbar-right{margin-left:auto;display:flex;align-items:center;gap:10px}
.points-chip{
  background:var(--surface-2);border:1px solid var(--line);padding:5px 12px;border-radius:20px;
  font-size:13px;font-weight:700;color:var(--ink-2);
}
.api-chip{
  font-size:12px;padding:5px 12px;border-radius:20px;background:var(--red-soft);color:var(--red);font-weight:600;
}
.api-chip.ok{background:var(--green-soft);color:var(--green)}
.api-chip.trial{background:#FBEFD6;color:#9A6C15}

/* 顶栏：云端同步状态 + 当前账号 */
.sync-chip{
  font-size:12px;padding:5px 12px;border-radius:20px;font-weight:600;
  background:var(--surface-2);border:1px solid var(--line);color:var(--ink-3);
}
.sync-chip.ok{background:var(--green-soft);color:var(--green);border-color:transparent}
.sync-chip.busy{background:var(--sky-soft);color:var(--sky);border-color:transparent}
.sync-chip.warn{background:#FBEFD6;color:#9A6C15;border-color:transparent}
.sync-chip.err{background:var(--red-soft);color:var(--red);border-color:transparent}
.user-chip{
  display:flex;align-items:center;gap:8px;font-size:13px;color:var(--ink-2);
  background:var(--surface-2);border:1px solid var(--line);padding:4px 10px;border-radius:20px;
}
.user-chip b{font-weight:700;color:var(--ink)}
.link{
  border:0;background:none;padding:0;cursor:pointer;font-family:inherit;
  color:var(--sky);font-size:13px;font-weight:600;
  text-decoration:underline;text-underline-offset:2px;
}
.link:hover{color:var(--brand-deep)}
.link.sm{font-size:12px}

/* ===== 登录门禁 =====
   默认可见（index.html 里不带 hidden），登录成功才由 auth.js 摘掉，
   这样不会先闪一下应用界面再盖住。 */
.auth-gate{
  position:fixed;inset:0;z-index:9999;overflow:auto;
  display:flex;align-items:center;justify-content:center;padding:24px;
  background:radial-gradient(1200px 600px at 50% -10%, #FFF3E6 0%, var(--bg) 62%);
}
.auth-gate.hidden{display:none}
.auth-card{
  width:min(400px,100%);background:var(--surface);border:1px solid var(--line);
  border-radius:18px;box-shadow:var(--shadow-lg);padding:26px 24px 20px;
}
.auth-brand{display:flex;align-items:center;gap:11px;margin-bottom:20px}
.auth-brand strong{font-size:16px;display:block;line-height:1.3}
.auth-brand small{color:var(--ink-3);font-size:11px}
.auth-tabs{display:flex;gap:6px;background:var(--surface-2);padding:4px;border-radius:12px;margin-bottom:18px}
.auth-tabs.hidden{display:none}
.atab{
  flex:1;border:0;background:transparent;padding:8px 0;border-radius:9px;cursor:pointer;
  font-size:14px;font-weight:600;color:var(--ink-2);transition:.15s;font-family:inherit;
}
.atab:hover{color:var(--brand-deep)}
.atab.on{background:var(--surface);color:var(--brand-deep);box-shadow:0 1px 4px rgba(120,100,70,.1)}
.auth-panel{display:flex;flex-direction:column;gap:14px}
/* 字段之间的间距只由 .auth-panel 的 gap 决定。
   以前两边都留了 14px（.field 自带 margin-bottom），框与框之间就成了 28px，
   而输入框到按钮、按钮到「忘记密码」只有 14px —— 一眼就能看出没对齐。 */
.auth-panel .field{margin-bottom:0}
.auth-panel.hidden{display:none}
.auth-sub{margin:0;font-size:13px;color:var(--ink-2);line-height:1.65}
.auth-alt{margin:0;text-align:center}
.btn.block{width:100%;padding:11px 16px;font-size:15px}
.auth-msg{
  margin-top:14px;padding:10px 12px;border-radius:10px;font-size:13px;line-height:1.65;
  background:var(--surface-2);color:var(--ink-2);
}
.auth-msg.hidden{display:none}
.auth-msg.ok{background:var(--green-soft);color:#3F7A49}
.auth-msg.err{background:var(--red-soft);color:var(--red)}
.auth-msg.warn{background:#FBEFD6;color:#9A6C15}

/* 试用模式开关 */
.trial-row{
  display:flex;flex-direction:column;gap:4px;padding:12px 14px;margin-bottom:16px;
  background:var(--surface-2);border:1px dashed var(--line);border-radius:12px;
}
.trial-row label{font-size:14px;display:flex;align-items:center;gap:7px}
.trial-row .muted{font-size:12px;line-height:1.6}

/* 服务商说明 */
.preset-info{
  display:flex;flex-direction:column;gap:6px;align-items:flex-start;
  padding:10px 14px;margin-bottom:14px;background:var(--surface-2);border-radius:12px;
}
.pi-note{font-size:13px;color:var(--ink-2);line-height:1.6}
.pi-link{font-size:12.5px}
.pi-link a{color:var(--sky);text-decoration:none}
.pi-link a:hover{text-decoration:underline}
.tag.t-free{background:var(--green-soft);color:var(--green);font-weight:700}
.tag.t-gift{background:var(--purple-soft);color:var(--purple);font-weight:700}
.tag.t-paid{background:var(--surface-2);color:var(--ink-3);font-weight:700}

/* 免费 Key 步骤 */
.howto{margin-top:16px;border-top:1px solid var(--line-soft);padding-top:12px}
.howto summary{
  cursor:pointer;font-size:14px;font-weight:700;color:var(--brand-deep);
  padding:6px 0;list-style:none;
}
.howto summary::-webkit-details-marker{display:none}
.howto summary::before{content:"▸ ";display:inline-block;transition:.15s}
.howto[open] summary::before{transform:rotate(90deg)}
.howto-body{padding:8px 0 4px;font-size:13.5px;line-height:1.75}
.howto-body h4{margin:14px 0 6px;font-size:14px;color:var(--ink)}
.howto-body ol{margin:0;padding-left:20px}
.howto-body li{margin-bottom:4px}
.howto-body code{
  background:var(--surface-2);padding:1px 6px;border-radius:5px;font-size:12.5px;
  font-family:ui-monospace,Consolas,monospace;color:var(--brand-deep);
}

/* ===== 视图 ===== */
.view{display:none;padding:26px 22px 60px;max-width:1320px;margin:0 auto}
.view.active{display:block}
#view-class{display:none;padding:0;max-width:none}
#view-class.active{display:flex;flex-direction:column;height:calc(100vh - 62px)}

/* ===== 首页 ===== */
.home-hero{
  display:flex;align-items:flex-end;justify-content:space-between;gap:20px;flex-wrap:wrap;
  margin-bottom:22px;
}
.home-hero h1{font-size:26px;letter-spacing:.2px}
.hero-stat{display:flex;gap:12px}
.stat{
  background:var(--surface);border:1px solid var(--line);border-radius:14px;
  padding:10px 18px;text-align:center;min-width:96px;
}
.stat b{display:block;font-size:22px;color:var(--brand-deep)}
.stat span{font-size:11px;color:var(--ink-3)}

.unit-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:14px}

.notice{
  display:flex;align-items:center;gap:14px;padding:14px 18px;margin-bottom:18px;
  background:linear-gradient(135deg,#FFF6E9,#FDEEE2);border:1px solid #F3D9BE;border-radius:14px;
}
.notice .n-ico{font-size:22px}
.notice .n-txt{flex:1;font-size:14px;line-height:1.6}
.notice .n-txt b{color:var(--brand-deep)}
.unit-card{
  background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);
  padding:16px 18px;transition:.18s;position:relative;overflow:hidden;
}
.unit-card:hover{transform:translateY(-2px);box-shadow:var(--shadow)}
.unit-card::before{
  content:"";position:absolute;left:0;top:0;bottom:0;width:4px;background:var(--line);
}
.unit-card.s0::before{background:var(--line)}
.unit-card.s1::before{background:var(--amber)}
.unit-card.s2::before{background:var(--green)}
.uc-head{display:flex;align-items:center;justify-content:space-between;gap:8px}
.uc-code{font-weight:800;font-size:16px}
.uc-state{font-size:11px;padding:3px 9px;border-radius:20px;background:var(--surface-2);color:var(--ink-3);font-weight:700}
.unit-card.s1 .uc-state{background:#FBEFD6;color:#9A6C15}
.unit-card.s2 .uc-state{background:var(--green-soft);color:var(--green)}
.uc-title{color:var(--ink-2);font-size:13px;margin:4px 0 12px;min-height:20px}
.uc-dots{display:flex;gap:6px;margin-bottom:12px}
.uc-dot{height:6px;flex:1;border-radius:4px;background:var(--line-soft)}
.uc-dot.on{background:var(--brand)}
.uc-actions{display:flex;gap:8px}
.btn{
  border:1px solid var(--line);background:var(--surface);color:var(--ink);
  padding:8px 16px;border-radius:10px;font-size:14px;font-weight:600;transition:.15s;
}
.btn:hover{border-color:var(--brand);color:var(--brand-deep)}
.btn.primary{background:var(--brand);border-color:var(--brand);color:#fff}
.btn.primary:hover{background:var(--brand-deep);border-color:var(--brand-deep);color:#fff}
.btn.ghost{background:transparent}
.btn.danger{color:var(--red)}
.btn.danger:hover{border-color:var(--red);color:var(--red)}
.btn.sm{padding:6px 12px;font-size:13px}
.btn.tiny{padding:4px 10px;font-size:12px;border-radius:8px}
.btn:disabled{opacity:.45;cursor:not-allowed}

/* ===== 课堂 ===== */
.class-top{
  display:flex;align-items:center;gap:16px;padding:12px 20px;
  background:var(--surface);border-bottom:1px solid var(--line);
}
.class-title{display:flex;align-items:baseline;gap:10px}
.class-title strong{font-size:17px}
.pill{font-size:11px;padding:3px 10px;border-radius:20px;background:var(--brand-soft);color:var(--brand-deep);font-weight:700}
.class-clock{margin-left:auto;text-align:center;line-height:1.1}
.clock-main{font-size:22px;font-weight:800;font-variant-numeric:tabular-nums;color:var(--ink)}
.class-clock small{font-size:10px;color:var(--ink-3)}
.class-actions{display:flex;gap:8px}

.class-body{flex:1;display:grid;grid-template-columns:230px 1fr 280px;min-height:0}
.stepbar{background:var(--surface);border-right:1px solid var(--line);padding:16px 14px;overflow-y:auto}
.step-item{
  display:flex;gap:10px;padding:10px 10px;border-radius:12px;transition:.15s;position:relative;
}
.step-item .si-no{
  width:24px;height:24px;flex:none;border-radius:50%;background:var(--surface-2);color:var(--ink-3);
  display:grid;place-items:center;font-size:12px;font-weight:800;margin-top:1px;
}
.step-item .si-name{font-size:13px;font-weight:600;color:var(--ink-2)}
.step-item .si-time{font-size:11px;color:var(--ink-3);font-variant-numeric:tabular-nums}
.step-item.done .si-no{background:var(--green-soft);color:var(--green)}
.step-item.done .si-name{color:var(--ink-3);text-decoration:line-through}
.step-item.active{background:var(--brand-soft)}
.step-item.active .si-no{background:var(--brand);color:#fff}
.step-item.active .si-name{color:var(--brand-deep)}
.step-item.locked{opacity:.5}

.stage{padding:18px 22px;display:flex;flex-direction:column;min-height:0;overflow:hidden}
.stage-head{display:flex;justify-content:space-between;align-items:flex-start;gap:20px;margin-bottom:14px}
.stage-head h2{font-size:19px}
.stage-timer{display:flex;align-items:center;gap:10px;flex:none}
.ring{position:relative;width:64px;height:64px}
.ring svg{width:64px;height:64px;transform:rotate(-90deg)}
.ring circle{fill:none;stroke-width:6}
.ring-bg{stroke:var(--line-soft)}
.ring-fg{stroke:var(--brand);stroke-linecap:round;stroke-dasharray:213.6;stroke-dashoffset:0;transition:stroke-dashoffset .5s linear,stroke .3s}
.ring.warn .ring-fg{stroke:var(--amber)}
.ring.over .ring-fg{stroke:var(--red)}
.ring span{
  position:absolute;inset:0;display:grid;place-items:center;font-size:14px;font-weight:800;
  font-variant-numeric:tabular-nums;
}
.timer-btns{display:flex;flex-direction:column;gap:6px}

.activity{flex:1;display:flex;flex-direction:column;min-height:0;background:var(--surface);
  border:1px solid var(--line);border-radius:var(--radius);overflow:hidden}

/* ---------- 预热环节的课本大图 ----------
   设计的前提：孩子手上**可能没有纸质课本**，而 WARM UP 的设计是「看图预测」。
   所以把课本开篇那一页（通版大图 + 标题 + 印在图上的 WARM UP 问题）直接搬进页面：
   左图右问题，一眼就能用；不用时点「收起」腾出聊天空间。
   图是 assets/units/uNN.jpg，880 宽、约 150KB，一个单元只加载一张。 */
.warm-pic{flex:none;margin-bottom:12px;border:1px solid var(--line);border-radius:var(--radius);
  background:var(--surface-2);overflow:hidden}
.warm-pic.hidden{display:none}
.wp-head{display:flex;align-items:center;gap:8px;padding:9px 12px;font-size:12.5px;
  font-weight:700;color:var(--ink-2);border-bottom:1px solid var(--line-soft)}
.wp-head .wp-tag{padding:1px 8px;border-radius:999px;background:var(--brand-soft);color:var(--brand-deep);
  font-size:11px;font-weight:800}
.wp-head .wp-tip{font-weight:500;color:var(--ink-3);font-size:11.5px}
.wp-head .wp-acts{margin-left:auto;display:flex;gap:6px;flex:none}
.wp-body{display:flex;gap:14px;padding:12px}
.wp-body.hidden{display:none}
/* 固定高度 + object-fit:contain —— 不裁图（WARM UP 的问题框就印在图上），
   也不因为图长把聊天区挤没。
   ★ 高度跟视口走：笔记本屏矮的时候图会自己变小，聊天区才留得下地方
     （矮屏上宁可图小一点，也不能让孩子看不见老师问的那句话）。
   ★ 宽度必须写 auto：课本页是竖的（880×1150），写 width:38% 会得到一个
     比图本身宽得多的框，contain 之后右边留一大片白 —— 图没变大，白边倒很显眼。 */
.wp-img{height:clamp(160px,26vh,300px);width:auto;max-width:42%;object-fit:contain;
  background:#fff;border-radius:8px;display:block;cursor:zoom-in}
.wp-side{flex:1;min-width:0;display:flex;flex-direction:column;gap:8px;
  max-height:clamp(160px,26vh,300px);overflow-y:auto}
.wp-cap{font-size:12.5px;color:var(--ink-3);line-height:1.6}
.wp-cap b{color:var(--ink-2)}
.wp-qs{margin:0;padding-left:18px;font-size:13px;line-height:1.75;color:var(--ink)}
.wp-qs li{margin-bottom:5px}
.wp-qs li::marker{color:var(--brand);font-weight:700}
.wp-ask{font-size:12.5px;font-weight:800;color:var(--brand-deep)}
/* 放大看：整页竖图，占满屏幕高度 */
.wp-full{width:100%;max-height:70vh;object-fit:contain;background:#fff;border-radius:8px;display:block}

.act-chat{display:flex;flex-direction:column;height:100%;min-height:0}
.chat-scroll{flex:1;overflow-y:auto;padding:16px 18px;display:flex;flex-direction:column;gap:14px}
.chat-scroll.mini{max-height:220px;border-top:1px solid var(--line-soft);background:var(--surface-2)}
.msg{display:flex;gap:10px;max-width:85%}
.msg.ai{align-self:flex-start}
.msg.me{align-self:flex-end;flex-direction:row-reverse}
.avatar{
  width:30px;height:30px;border-radius:50%;flex:none;display:grid;place-items:center;
  font-size:13px;font-weight:800;color:#fff;
}
.msg.ai .avatar{background:linear-gradient(135deg,var(--sky),var(--purple))}
.msg.me .avatar{background:var(--brand)}
.bubble{
  background:var(--surface-2);border-radius:14px;padding:10px 14px;font-size:14.5px;
  border-top-left-radius:4px;white-space:pre-wrap;word-break:break-word;
}
.msg.me .bubble{background:var(--brand-soft);border-top-left-radius:14px;border-top-right-radius:4px}
.bubble .en{color:var(--sky);font-weight:600}
.bubble em{color:var(--brand-deep);font-style:normal;font-weight:700}
.typing span{
  display:inline-block;width:6px;height:6px;border-radius:50%;background:var(--ink-3);
  margin-right:3px;animation:blink 1.2s infinite;
}
.typing span:nth-child(2){animation-delay:.2s}
.typing span:nth-child(3){animation-delay:.4s}
@keyframes blink{0%,60%,100%{opacity:.25}30%{opacity:1}}
.sys-note{align-self:center;font-size:11px;color:var(--ink-3);background:var(--surface-2);
  padding:3px 12px;border-radius:20px}

.quick-replies{display:flex;gap:8px;flex-wrap:wrap;padding:0 18px 8px}
.qr{border:1px solid var(--line);background:var(--surface);border-radius:20px;padding:5px 13px;
  font-size:13px;color:var(--ink-2);transition:.15s}
.qr:hover{border-color:var(--brand);color:var(--brand-deep);background:var(--brand-soft)}

.composer{display:flex;gap:10px;padding:12px 18px;border-top:1px solid var(--line);background:var(--surface)}
.composer textarea{
  flex:1;border:1px solid var(--line);border-radius:12px;padding:10px 14px;resize:none;
  background:var(--surface);outline:none;transition:.15s;max-height:110px;
}
.composer textarea:focus{border-color:var(--brand)}
#btnSend{padding:0 22px;height:auto}

.vocab-strip{display:flex;gap:6px;flex-wrap:wrap;padding:0 18px 10px}
.vchip{
  font-size:12px;padding:3px 10px;border-radius:20px;background:var(--sky-soft);color:var(--sky);
  border:1px solid #cfe7f2;font-weight:600;
}

/* 词汇闯关 */
.act-vocab{padding:20px;display:flex;flex-direction:column;gap:14px;height:100%;min-height:0}
.vocab-card{
  background:linear-gradient(135deg,#FFF6EC,#FDEEE2);border:1px solid #F5DCC4;border-radius:var(--radius);
  padding:26px 20px;text-align:center;
}
.vocab-word{font-size:30px;font-weight:800;letter-spacing:.5px;color:var(--brand-deep)}
.vocab-hint{font-size:13px;margin-top:6px}
.vocab-input-row{display:flex;gap:10px}
.vocab-progress{font-size:12.5px;text-align:center;color:var(--ink-3);font-variant-numeric:tabular-nums}
.vocab-input-row input{
  flex:1;border:1px solid var(--line);border-radius:12px;padding:11px 14px;outline:none;background:var(--surface);
}
.vocab-input-row input:focus{border-color:var(--brand)}

/* 单词卡上的 🔇 发音按钮：点一下就念这个单词 */
.vocab-word-row{display:flex;align-items:center;justify-content:center;gap:10px}
.spk-word{
  flex:none;width:38px;height:38px;padding:0;border-radius:50%;
  border:1px solid #F0D6BC;background:#fff;color:var(--brand);
  font-size:17px;line-height:1;cursor:pointer;transition:transform .15s,background .15s;
}
.spk-word:hover{background:#FFF6EC;transform:scale(1.08)}
.spk-word:active{transform:scale(.92)}

/* 猜词行的 🎤：做成大圆钮，孩子手指点得中。
   注意这里是**主按钮**——孩子打字不方便，语音才是主路径，
   所以它用品牌色实心，反倒把「提交」降级成描边，别让打字抢了视线。 */
.vocab-input-row .btn.mic{
  flex:none;align-self:center;width:52px;height:52px;min-width:52px;padding:0;
  border-radius:50%;font-size:22px;line-height:1;
  background:var(--brand);border:1.5px solid var(--brand);color:#fff;
  box-shadow:0 3px 12px rgba(232,129,58,.34);
}
.vocab-input-row .btn.mic:hover{background:var(--brand-deep);border-color:var(--brand-deep);color:#fff}
.vocab-input-row .btn.mic.off{
  opacity:.45;border-style:dashed;background:var(--surface);color:var(--ink-2);box-shadow:none;
}

/* 语音听写提示：屏幕上明明白白告诉她「听到了什么」，并且不催她 */
#vocabMicHint{margin:0;padding:0 2px;line-height:1.7}
#vocabMicHint b{color:var(--brand-deep)}
#vocabMicHint .mh-soft{color:var(--ink-3);font-size:12.5px}
#vocabMicHint .btn{vertical-align:middle;margin-left:6px}

@media (max-width:560px){
  .vocab-input-row{flex-wrap:wrap}
  .vocab-input-row input{flex:1 1 100%}
}

/* 限时阅读 */
.act-read{padding:30px 20px;display:flex;flex-direction:column;align-items:center;gap:16px;height:100%}
.read-big{font-size:64px;font-weight:800;font-variant-numeric:tabular-nums;color:var(--brand);
  letter-spacing:2px;line-height:1}
.read-big.warn{color:var(--amber)}
.read-big.over{color:var(--red)}
.read-tip{color:var(--ink-2);text-align:center;max-width:520px;margin:0}
.read-btns{display:flex;gap:10px}

/* 做题 */
.act-quiz{padding:20px;overflow-y:auto;height:100%}
.q-card{background:var(--surface-2);border-radius:var(--radius);padding:18px;margin-bottom:16px}
.q-no{font-size:12px;color:var(--ink-3);font-weight:700}
.q-text{font-size:16px;font-weight:600;margin:6px 0 12px}
.q-opts{display:flex;flex-direction:column;gap:8px}
.q-opt{
  text-align:left;border:1px solid var(--line);background:var(--surface);border-radius:12px;
  padding:10px 14px;font-size:14.5px;transition:.15s;
}
.q-opt:hover{border-color:var(--brand)}
.q-opt.right{background:var(--green-soft);border-color:var(--green);color:#2F6B3D}
.q-opt.wrong{background:var(--red-soft);border-color:var(--red);color:#9B3A2A}

/* 复习 */
.act-review{padding:20px;overflow-y:auto;height:100%}
.rv-card{
  background:var(--surface-2);border-radius:var(--radius);padding:26px;text-align:center;margin-bottom:14px;
}
.rv-word{font-size:30px;font-weight:800;color:var(--ink)}
.rv-mean{font-size:17px;color:var(--brand-deep);margin-top:10px}
.rv-ex{font-size:13px;color:var(--ink-2);margin-top:8px;font-style:italic}
.rv-btns{display:flex;gap:10px;justify-content:center}

/* 右侧面板 */
.sidepanel{background:var(--surface);border-left:1px solid var(--line);display:flex;flex-direction:column;min-height:0}
.panel-head{display:flex;align-items:center;justify-content:space-between;padding:14px 16px 8px}
.panel-head strong{font-size:14px}
.panel-tabs{display:flex;gap:6px;padding:0 16px 10px;border-bottom:1px solid var(--line-soft)}
.ptab{
  flex:1;border:0;background:var(--surface-2);border-radius:9px;padding:6px 4px;font-size:12px;
  color:var(--ink-2);font-weight:600;
}
.ptab.active{background:var(--brand-soft);color:var(--brand-deep)}
.panel-list{flex:1;overflow-y:auto;padding:12px 16px;display:flex;flex-direction:column;gap:8px}
.kitem{
  border:1px solid var(--line-soft);border-radius:12px;padding:9px 12px;background:var(--surface);
  font-size:13px;
}
.kitem b{color:var(--brand-deep)}
.kitem .k-src{font-size:11px;color:var(--ink-3);margin-top:3px}
.kitem .k-ex{font-size:12px;color:var(--ink-2);margin-top:3px;font-style:italic}
.empty-hint{color:var(--ink-3);font-size:13px;text-align:center;padding:24px 10px;line-height:1.7}

/* ===== 知识库 ===== */
.view-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:18px;gap:12px;flex-wrap:wrap}
.view-head h1{font-size:24px}
.head-actions{display:flex;gap:8px;align-items:center}
.badge{background:var(--red);color:#fff;border-radius:20px;padding:1px 7px;font-size:11px;margin-left:4px}
.lib-tabs{display:flex;gap:6px;margin-bottom:16px;border-bottom:1px solid var(--line)}
.libtab{border:0;background:transparent;padding:10px 18px;font-size:14px;font-weight:600;color:var(--ink-3);
  border-bottom:2px solid transparent;margin-bottom:-1px}
.libtab.active{color:var(--brand-deep);border-bottom-color:var(--brand)}
.lib-body{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:12px}
.lib-item{background:var(--surface);border:1px solid var(--line);border-radius:14px;padding:14px 16px}
.lib-item .li-top{display:flex;justify-content:space-between;align-items:flex-start;gap:10px}
.lib-item h3{font-size:16px;margin:0}
.lib-item .li-mean{color:var(--ink-2);font-size:13.5px;margin-top:4px}
.lib-item .li-ex{font-size:12.5px;color:var(--ink-3);margin-top:6px;font-style:italic}
.lib-item .li-meta{display:flex;gap:8px;align-items:center;margin-top:10px;font-size:11px;color:var(--ink-3)}
.mastery{display:flex;gap:3px}
.mastery i{width:14px;height:5px;border-radius:3px;background:var(--line);display:block}
.mastery i.on{background:var(--green)}
.tag{background:var(--surface-2);padding:2px 8px;border-radius:20px;font-size:11px}
.tag.sky{background:var(--sky-soft);color:var(--sky)}
.tag.purple{background:var(--purple-soft);color:var(--purple)}
.icon-btn{border:0;background:transparent;color:var(--ink-3);font-size:16px;padding:0 4px;line-height:1}
.icon-btn:hover{color:var(--red)}

/* ===== 报告 ===== */
.report-card{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);
  padding:18px 20px;margin-bottom:14px}
.rc-head{display:flex;justify-content:space-between;align-items:center;gap:10px;flex-wrap:wrap}
.rc-head h3{font-size:17px}
.rc-meta{font-size:12px;color:var(--ink-3)}
.rc-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(110px,1fr));gap:10px;margin:14px 0}
.rc-cell{background:var(--surface-2);border-radius:12px;padding:10px 12px;text-align:center}
.rc-cell b{display:block;font-size:19px;color:var(--brand-deep)}
.rc-cell span{font-size:11px;color:var(--ink-3)}
.rc-steps{display:flex;flex-direction:column;gap:6px;margin:10px 0}
.rc-step{display:grid;grid-template-columns:110px 1fr 90px;gap:10px;align-items:center;font-size:13px}
.bar{height:8px;background:var(--line-soft);border-radius:5px;overflow:hidden}
.bar i{display:block;height:100%;background:var(--brand);border-radius:5px}
.bar.over i{background:var(--amber)}
.rc-comment{background:var(--brand-soft);border-radius:12px;padding:12px 14px;font-size:14px;
  white-space:pre-wrap;line-height:1.75}

/* ===== 设置 ===== */
.settings-wrap{display:grid;grid-template-columns:repeat(auto-fit,minmax(380px,1fr));gap:16px;align-items:start}
.card{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);padding:18px 20px}
.card h3{font-size:16px;margin-bottom:4px}
.card .card-sub{font-size:12.5px;color:var(--ink-3);margin-bottom:14px}
.field{margin-bottom:14px}
.field label{display:block;font-size:13px;font-weight:600;margin-bottom:5px;color:var(--ink-2)}
/* 所有「能打字」的输入框必须长一样。这里踩过两层坑：
     ① 原来只列了 [type=text] / [type=password] / [type=number]，
        漏了 [type=email] —— 「注册」「忘记密码」的邮箱框退回浏览器默认外观；
     ② 更隐蔽的是：<input> 不写 type 时并不等于 [type=text]，要用 :not([type]) 才管得住。
        登录页的用户名、注册页的用户名和邀请码都是裸 <input>，
        所以当时整张表单里**只有密码框有样式**，其余全是又矮又细的默认框 ——
        宽高、边框、圆角、内边距全对不齐，这就是「格式不统一」的来源。
   ★ 以后再加别的 type（tel / search / url…）记得补进这个白名单，
     index.html 里也别再写没有 type 的裸 <input>（_smoke.js 有断言盯着）。
   ★ 别图省事改成 input:not([type=checkbox])… 那种黑名单写法：
     四个 :not() 会把权重从 (0,2,1) 抬到 (0,5,1)，直接压掉下面
     .field input:focus 的橙色描边 —— 聚焦时看不出选中了哪个框。 */
.field input[type=text],.field input[type=password],.field input[type=email],
.field input[type=number],.field input[type=tel],.field input[type=search],
.field input[type=url],.field input:not([type]),
.field select,.field textarea{
  width:100%;border:1px solid var(--line);border-radius:10px;padding:9px 12px;background:var(--surface);outline:none;
}
/* 输入类控件在 Safari/iOS 上自带内阴影和一圈圆角，关掉才和上面那套边框统一。
   ★ select 不能写进来 —— 一并关掉会把下拉箭头也弄没。 */
.field input[type=text],.field input[type=password],.field input[type=email],
.field input[type=number],.field input[type=tel],.field input[type=search],
.field input[type=url],.field input:not([type]){-webkit-appearance:none;appearance:none}
.field input:focus,.field select:focus,.field textarea:focus{border-color:var(--brand)}
.field .hint{font-size:11.5px;color:var(--ink-3);margin-top:4px;line-height:1.5}
.row2{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.seg{display:flex;gap:6px;flex-wrap:wrap}
.seg button{
  border:1px solid var(--line);background:var(--surface);border-radius:9px;padding:6px 13px;
  font-size:13px;color:var(--ink-2);font-weight:600;
}
.seg button.on{background:var(--brand-soft);border-color:var(--brand);color:var(--brand-deep)}

/* —— 老师形象选择 ——
   为什么不用 .seg 文字按钮：光看「猫头鹰老师 / 手绘小人」两个词，
   家长和孩子都不知道选出来长什么样。得先让人「看见」老师，再决定选哪个。 */
.avatar-pick{display:flex;gap:12px;flex-wrap:wrap}
.ap-card{
  position:relative;width:110px;padding:10px 8px 9px;cursor:pointer;
  border:1px solid var(--line);background:var(--surface);border-radius:var(--radius-sm);
  display:flex;flex-direction:column;align-items:center;gap:7px;
  transition:border-color .15s,background .15s,transform .12s,box-shadow .15s;
}
.ap-card:hover{border-color:var(--brand);transform:translateY(-2px)}
.ap-card:active{transform:translateY(0)}
.ap-card.on{border-color:var(--brand);background:var(--brand-soft);box-shadow:0 0 0 2px var(--brand-soft)}
.ap-pic{
  width:78px;height:86px;display:flex;align-items:center;justify-content:center;
  border-radius:10px;background:var(--surface-2);overflow:hidden;
}
.ap-card.on .ap-pic{background:#FFF7F0}
.ap-pic img{width:100%;height:100%;object-fit:contain}
.ap-pic svg{width:100%;height:100%;display:block}
.ap-name{font-size:12.5px;font-weight:600;color:var(--ink-2);line-height:1.25;text-align:center}
.ap-card.on .ap-name{color:var(--brand-deep)}
.ap-tick{
  position:absolute;top:-7px;right:-7px;width:20px;height:20px;border-radius:50%;
  background:var(--brand);color:#FFF;font-size:12px;line-height:20px;text-align:center;
  opacity:0;transform:scale(.5);transition:opacity .15s,transform .15s;
}
.ap-card.on .ap-tick{opacity:1;transform:scale(1)}
.field .hint.warn{color:var(--red)}
.step-cfg{display:grid;grid-template-columns:1fr 90px 70px;gap:8px;align-items:center;margin-bottom:8px;font-size:13px}
.step-cfg input{width:100%;border:1px solid var(--line);border-radius:8px;padding:5px 8px;text-align:center}
.total-line{display:flex;justify-content:space-between;border-top:1px dashed var(--line);padding-top:10px;
  margin-top:6px;font-size:13px;font-weight:700}
.total-line.warn{color:var(--red)}

/* ===== 弹窗 / toast ===== */
.modal{position:fixed;inset:0;background:rgba(58,50,39,.42);display:grid;place-items:center;z-index:100;padding:20px}
.modal-box{background:var(--surface);border-radius:18px;width:min(560px,100%);max-height:86vh;display:flex;flex-direction:column;
  box-shadow:var(--shadow-lg)}
.modal-head{display:flex;justify-content:space-between;align-items:center;padding:16px 20px;border-bottom:1px solid var(--line)}
.modal-head .x{border:0;background:transparent;font-size:24px;color:var(--ink-3);line-height:1}
.modal-body{padding:18px 20px;overflow-y:auto}
.modal-foot{padding:14px 20px;border-top:1px solid var(--line);display:flex;justify-content:flex-end;gap:8px}
.toast{
  position:fixed;bottom:26px;left:50%;transform:translateX(-50%);background:var(--ink);color:#fff;
  padding:10px 20px;border-radius:24px;font-size:14px;z-index:200;box-shadow:var(--shadow-lg)
}

/* 滚动条 */
::-webkit-scrollbar{width:8px;height:8px}
::-webkit-scrollbar-thumb{background:var(--line);border-radius:4px}
::-webkit-scrollbar-thumb:hover{background:var(--ink-3)}
::-webkit-scrollbar-track{background:transparent}

@media (max-width:1080px){
  .class-body{grid-template-columns:190px 1fr}
  .sidepanel{display:none}
}
@media (max-width:820px){
  .class-body{grid-template-columns:1fr}
  .stepbar{display:none}
  .nav{overflow-x:auto}
}


/* ================= 语音对话 ================= */
.composer-btns{display:flex;flex-direction:column;gap:6px}
.btn.mic{
  padding:0 12px;font-size:17px;line-height:1;border-radius:10px;
  border:1px solid var(--line);background:var(--surface);color:var(--ink-2);min-width:44px;height:34px;
}
.btn.mic:hover{border-color:var(--brand);color:var(--brand)}
.btn.mic.rec{
  background:var(--red);border-color:var(--red);color:#fff;
  animation:micPulse 1.1s ease-in-out infinite;
}
@keyframes micPulse{
  0%,100%{box-shadow:0 0 0 0 rgba(212,97,79,.45)}
  50%{box-shadow:0 0 0 8px rgba(212,97,79,0)}
}
.btn.tiny.off{opacity:.45}

.mic-hint{
  padding:0 18px 10px;font-size:12.5px;color:var(--ink-3);
}
.mic-hint.err{color:var(--red)}

/* 气泡旁的小喇叭（作为 flex 子项跟在气泡后面，不用绝对定位，避免被裁切） */
.spk{
  flex:0 0 auto;align-self:flex-start;margin:6px 0 0 6px;
  width:24px;height:24px;padding:0;border:none;border-radius:50%;
  background:var(--surface-2);color:var(--ink-3);cursor:pointer;
  font-size:12px;line-height:24px;text-align:center;
  opacity:0;transition:.15s;
}
.msg:hover .spk{opacity:1}
.spk:hover{background:var(--brand-soft);color:var(--brand-deep)}

/* 设置页语音区 */
.voice-grid{display:grid;grid-template-columns:1fr 1fr;gap:22px}
@media (max-width:820px){.voice-grid{grid-template-columns:1fr}}
.vcol{
  background:var(--surface-2);border-radius:var(--radius-sm);padding:14px 16px;
}
.vcol h4{margin:0 0 10px;font-size:14px;color:var(--ink)}
.warn-box{
  margin-top:14px;padding:10px 14px;border-radius:var(--radius-sm);
  background:#FFF6E5;border:1px solid #F2DFB4;color:#8A6316;font-size:13px;line-height:1.6;
}


/* ================= 全英文沉浸 ================= */
.spk.tr{width:auto;padding:0 9px;border-radius:12px;font-size:12px;letter-spacing:1px}
.spk.tr:hover{background:var(--brand-soft);color:var(--brand-deep)}

.zh-note{
  flex:1 1 100%;margin:6px 0 2px 34px;padding:7px 11px;
  background:var(--surface-2);border-left:3px solid var(--brand);
  border-radius:0 8px 8px 0;font-size:13px;line-height:1.65;color:var(--ink-2);
}
.msg.me .zh-note{margin-left:0}

.btn.sos{
  padding:0 10px;height:34px;min-width:40px;font-size:15px;line-height:1;
  border-radius:10px;border:1px solid #F2DFB4;background:#FFF6E5;color:#8A6316;
}
.btn.sos:hover{background:#FDEBC8;border-color:#E5C67E}

.li-cn{display:inline-block;margin-left:8px;font-size:12px;color:var(--ink-3);opacity:.85}


/* ================= 七层脚手架徽章 ================= */
.layer-chip{
  display:inline-block;margin-right:8px;padding:2px 10px;border-radius:999px;
  background:var(--brand);color:#fff;font-size:12.5px;font-weight:600;vertical-align:2px;
}
.layer-n{font-size:12.5px;color:var(--ink-3);font-weight:400;margin-left:6px}

/* ================= 词汇模式切换 ================= */
.vocab-modes{display:flex;gap:8px;margin-bottom:12px;flex-wrap:wrap}
.vmode{
  padding:7px 14px;border-radius:999px;border:1.5px solid var(--line);
  background:var(--surface);color:var(--ink-2);cursor:pointer;font-size:13.5px;font-weight:600;
  transition:.15s;
}
.vmode:hover{border-color:var(--brand);color:var(--brand)}
.vmode.on{background:var(--brand);border-color:var(--brand);color:#fff}

.game-empty{padding:34px 20px;text-align:center;font-size:14.5px;line-height:1.8}
.game-title{font-size:15px;font-weight:700;margin-bottom:12px}
.game-meta{margin-top:12px;font-size:13px;text-align:center}
.game-streak{color:#E58F2A;font-size:13px;margin-left:8px}

/* ---- 配对连线 ---- */
.match-wrap{display:flex;gap:14px}
.match-col{flex:1;display:flex;flex-direction:column;gap:8px}
.mcell{
  padding:10px 12px;border-radius:10px;border:1.5px solid var(--line);
  background:var(--surface);cursor:pointer;font-size:14px;text-align:left;transition:.12s;
  min-height:42px;
}
.mcell:hover{border-color:var(--brand)}
.mcell.sel{border-color:var(--brand);background:var(--brand-soft)}
.mcell.ok{border-color:var(--green);background:var(--green-soft);color:var(--green);cursor:default;opacity:.75}
.mcell.bad{border-color:var(--red);background:#FDECEA;animation:shake .35s}
@keyframes shake{0%,100%{transform:translateX(0)}25%{transform:translateX(-4px)}75%{transform:translateX(4px)}}

/* ---- 拼字挑战 ---- */
.spell-hint{font-size:14.5px;margin-bottom:14px}
.spell-built{
  min-height:44px;margin-bottom:12px;padding:8px 14px;border-radius:10px;
  background:var(--surface-2);font-size:20px;font-weight:700;letter-spacing:4px;text-align:center;
}
.spell-built.win{background:var(--green-soft);color:var(--green)}
.spell-built.lose{background:#FDECEA;color:var(--red);animation:shake .35s}
.spell-tiles{display:flex;gap:7px;flex-wrap:wrap;margin-bottom:12px}
.stile{
  width:42px;height:46px;border-radius:10px;border:1.5px solid var(--line);
  background:var(--surface);font-size:19px;font-weight:700;cursor:pointer;transition:.12s;
}
.stile:hover{border-color:var(--brand);background:var(--brand-soft)}
.stile.used{opacity:.25;cursor:default}
.spell-btns{display:flex;gap:8px}
.spell-btns .hint-me{border-color:var(--brand);color:var(--brand)}

/* ---- 快问快答 ---- */
.speed-word{font-size:30px;font-weight:800;text-align:center;margin:10px 0 12px}
.speed-bar{height:8px;border-radius:99px;background:var(--surface-2);overflow:hidden;margin-bottom:14px}
.speed-bar-fill{height:100%;width:100%;background:var(--brand);border-radius:99px;transition:width .1s linear}
.speed-opts{display:grid;grid-template-columns:1fr 1fr;gap:9px}
.sopt{
  padding:11px 14px;border-radius:10px;border:1.5px solid var(--line);
  background:var(--surface);cursor:pointer;font-size:14px;text-align:left;transition:.12s;
}
.sopt:hover{border-color:var(--brand)}
.sopt.right{border-color:var(--green);background:var(--green-soft);color:var(--green)}
.sopt.wrong{border-color:var(--red);background:#FDECEA;color:var(--red)}

/* ================= 点词即查 ================= */
.w-tip{cursor:pointer;border-bottom:1.5px dotted var(--brand);padding-bottom:1px}
.w-tip:hover{color:var(--brand-deep);background:var(--brand-soft);border-radius:3px}
#wordPop{
  position:fixed;z-index:9999;width:280px;padding:12px 14px;
  background:var(--surface);border:1.5px solid var(--line);border-radius:14px;
  box-shadow:0 10px 34px rgba(30,30,60,.16);
}
#wordPop.hidden{display:none}
.wp-head{display:flex;justify-content:space-between;align-items:center;margin-bottom:6px}
.wp-head b{font-size:17px}
.wp-x{border:none;background:none;cursor:pointer;color:var(--ink-3);font-size:13px}
.wp-line{font-size:13.5px;line-height:1.55;margin-bottom:4px}
.wp-cn{color:var(--brand-deep);font-weight:600}
.wp-ex{color:var(--ink-3);font-style:italic}
.wp-btns{display:flex;gap:8px;margin-top:9px}

/* =========================================================
   老师的形象（形象包：p-owl 图片立绘 / p-svg 内置手绘）
   状态：idle 待机 / think 思考 / nod 点头 / talk 讲话 / cheer 欢呼 / listen 倾听
   所有动作都加在 .tf-stage 上，形象本身（图片或 SVG）只负责被看见。
   ========================================================= */
.teacher-dock{
  flex:none;height:106px;margin-bottom:12px;padding:0 16px;
  display:flex;align-items:center;gap:14px;
  background:linear-gradient(100deg,#F2F9FE 0%,#FDF7F0 55%,#FFFFFF 100%);
  border:1px solid var(--line-soft);border-radius:14px;overflow:hidden;
}
.teacher-wrap{position:relative;display:flex;align-items:center;gap:16px;height:100%;min-width:0}
.tf{width:70px;height:86px;flex:none;position:relative;z-index:1}
.tf-stage{
  position:absolute;inset:0;transform-origin:50% 88%;
  animation:tfBreath 3.6s ease-in-out infinite;
}

/* —— 图片立绘：两层叠着交叉淡入淡出，换表情时不闪白 —— */
.tf-pic{
  position:absolute;inset:0;width:100%;height:100%;
  object-fit:contain;object-position:50% 100%;
  opacity:0;transition:opacity .22s ease;pointer-events:none;user-select:none;
}
.tf-pic.show{opacity:1}

/* 内置 SVG 形象 */
.tf-fig{width:100%;height:100%;display:block;overflow:visible}
.tf-face{fill:#FFE2C8}
.tf-hair,.tf-hair-back{fill:#6E4A31}
.tf-hair-back{fill:#5A3B26}
.tf-torso{fill:#8B7BC7}
.tf-collar{fill:none;stroke:#FFFFFF;stroke-width:3.4;stroke-linecap:round;stroke-linejoin:round}
.tf-arm{fill:none;stroke:#8B7BC7;stroke-width:7;stroke-linecap:round}
.tf-eye{fill:#3A3227}
.tf-brow{fill:none;stroke:#6E4A31;stroke-width:2.2;stroke-linecap:round}
.tf-blush{fill:#F09A92;opacity:.5}
.tf-mouth{fill:#C4553F}
.tf-smile{fill:none;stroke:#C4553F;stroke-width:2.4;stroke-linecap:round;opacity:0}
.tf-chin-hand circle{fill:#FFE2C8;stroke:#E8B995;stroke-width:1.4}
.tf-head,.tf-body{transform-box:view-box}
.tf-eye{transform-box:fill-box;transform-origin:center;animation:tfBlink 5.2s infinite}

/* —— 默认隐藏的装饰部件（图片版和 SVG 版共用同一套开关）—— */
.tf-chin-hand,.tf-think,.tf-think-svg,.tf-waves,.tf-sparks,.tf-sparks-svg{opacity:0;transition:opacity .22s}
.tf-think-svg circle{fill:#C9DCEA}
.tf-sparks-svg .sp{fill:var(--amber);font-size:15px}
.tf-waves path{fill:none;stroke:#4A9BC4;stroke-width:2.6;stroke-linecap:round}
.tf-waves{position:absolute;width:15px;height:24px}
.tf.p-svg .tf-waves{left:52px;top:30px}
.tf.p-owl .tf-waves{right:-4px;top:24px}

/* 思考泡（图片版：三个小圆点飘上去） */
.tf-think{position:absolute;right:-4px;top:1px;width:24px;height:20px;display:block}
.tf-think i{position:absolute;display:block;background:#C3DAEA;border-radius:50%}
.tf-think i:nth-child(1){width:5.5px;height:5.5px;left:0;bottom:0}
.tf-think i:nth-child(2){width:7.5px;height:7.5px;left:6px;bottom:6px}
.tf-think i:nth-child(3){width:9.5px;height:9.5px;left:12px;bottom:12px}

/* 欢呼的星星（图片版：一个字符 + 两个伪元素） */
.tf-sparks{position:absolute;left:-8px;top:-9px;color:var(--amber);font-size:15px;line-height:1}
.tf-sparks::before,.tf-sparks::after{content:"✦";position:absolute;font-size:10px;opacity:.85}
.tf-sparks::before{left:18px;top:12px}
.tf-sparks::after{left:-2px;top:19px}

/* —— idle：轻轻呼吸（.tf-stage 默认就是） —— */
@keyframes tfBreath{0%,100%{transform:translateY(0)}50%{transform:translateY(-2.5px)}}
@keyframes tfBlink{0%,92%,100%{transform:scaleY(1)}95%{transform:scaleY(.12)}}

/* —— think：头微侧 + 飘思考泡 —— */
.tf.is-think .tf-stage{animation:none;transform:rotate(-5deg) translateY(-1px)}
.tf.is-think .tf-think,.tf.is-think .tf-think-svg{opacity:1}
.tf.is-think .tf-think i{animation:thinkFloat 1.6s ease-in-out infinite}
.tf.is-think .tf-think i:nth-child(2){animation-delay:.18s}
.tf.is-think .tf-think i:nth-child(3){animation-delay:.36s}
.tf.is-think .tf-think-svg circle{animation:thinkFloat 1.6s ease-in-out infinite}
.tf.is-think .tf-think-svg circle:nth-child(2){animation-delay:.18s}
.tf.is-think .tf-think-svg circle:nth-child(3){animation-delay:.36s}
/* SVG 版还多一个「手托下巴」和眯眼 */
.tf.p-svg.is-think .tf-chin-hand{opacity:1;animation:chinIn .3s ease-out}
.tf.p-svg.is-think .tf-head{transform:rotate(-7deg) translateX(-2px);transition:transform .3s}
.tf.p-svg.is-think .tf-brow.l{transform:translateY(-1.5px)}
@keyframes chinIn{from{opacity:0;transform:translate(6px,-6px)}to{opacity:1;transform:none}}
@keyframes thinkFloat{0%,100%{transform:translateY(0);opacity:.55}50%{transform:translateY(-3px);opacity:1}}

/* —— nod：文字一个个冒出来时轻轻点头 —— */
.tf.is-nod .tf-stage{animation:tfNod .9s ease-in-out infinite}
.tf.p-svg.is-nod .tf-head{animation:tfNodSvg .9s ease-in-out infinite;transform-origin:60px 90px}
.tf.p-svg.is-nod .tf-smile,.tf.p-svg.is-talk .tf-smile,.tf.p-svg.is-listen .tf-smile{opacity:1}
@keyframes tfNod{0%,100%{transform:rotate(0)}35%{transform:rotate(4deg)}70%{transform:rotate(-1.5deg)}}
@keyframes tfNodSvg{0%,100%{transform:rotate(0)}35%{transform:rotate(6deg)}70%{transform:rotate(-2deg)}}

/* —— talk：打拍子 + 声波 —— */
.tf.is-talk .tf-stage{animation:tfBob .62s ease-in-out infinite}
.tf.is-talk .tf-waves{opacity:1}
.tf.is-talk .tf-waves path{animation:tfWave 1s ease-in-out infinite}
.tf.is-talk .tf-waves path:nth-child(2){animation-delay:.18s}
.tf.p-svg.is-talk .tf-mouth{animation:tfMouth .34s ease-in-out infinite;transform-box:fill-box;transform-origin:center}
@keyframes tfBob{0%,100%{transform:translateY(0)}50%{transform:translateY(-1.6px)}}
@keyframes tfMouth{0%,100%{transform:scaleY(1)}50%{transform:scaleY(2.1)}}
@keyframes tfWave{0%,100%{opacity:.35;transform:translateX(0)}50%{opacity:1;transform:translateX(2px)}}

/* —— cheer：蹦一下 + 星星 —— */
.tf.is-cheer .tf-stage{animation:tfJump .62s ease-out 3}
.tf.is-cheer .tf-sparks,.tf.is-cheer .tf-sparks-svg{opacity:1}
.tf.is-cheer .tf-sparks{font-size:19px;animation:sparkPop 1s ease-out infinite}
.tf.is-cheer .tf-sparks::before,.tf.is-cheer .tf-sparks::after{font-size:13px}
.tf.is-cheer .tf-sparks::before{animation:sparkPop 1s ease-out infinite;animation-delay:.2s}
.tf.is-cheer .tf-sparks::after{animation:sparkPop 1s ease-out infinite;animation-delay:.4s}
.tf.is-cheer .tf-sparks-svg .sp{animation:sparkPop 1s ease-out infinite;text-anchor:middle}
.tf.is-cheer .tf-sparks-svg .s2{animation-delay:.2s}
.tf.is-cheer .tf-sparks-svg .s3{animation-delay:.4s}
.tf.p-svg.is-cheer .tf-arm{animation:armUp .5s ease-out forwards}
.tf.p-svg.is-cheer .arm-l{transform-box:view-box;transform-origin:40px 96px}
.tf.p-svg.is-cheer .arm-r{transform-box:view-box;transform-origin:80px 96px}
@keyframes tfJump{0%,100%{transform:translateY(0)}40%{transform:translateY(-9px)}}
@keyframes sparkPop{0%{opacity:0;transform:scale(.4)}45%{opacity:1;transform:scale(1.15)}100%{opacity:.2;transform:scale(.9)}}
@keyframes armUp{from{transform:rotate(0)}to{transform:rotate(-32deg)}}

/* —— listen：侧身倾听 + 轻点头 —— */
.tf.is-listen .tf-stage{animation:tfNod 1.6s ease-in-out infinite;transform:rotate(4deg)}
.tf.p-svg.is-listen .tf-head{transform:rotate(6deg);transition:transform .3s;animation:tfNodSvg 1.6s ease-in-out infinite;transform-origin:60px 90px}

/* —— 气泡配文 —— */
.tf-caption{
  align-self:center;max-width:min(560px,60vw);
  background:#fff;border:1.5px solid var(--line);border-radius:13px;
  padding:6px 13px;font-size:13.5px;color:var(--ink-2);line-height:1.5;
  opacity:0;transform:translateY(5px);transition:.2s;pointer-events:none;
}
.tf-caption.show{opacity:1;transform:none}
.tf-shadow{
  position:absolute;left:4px;bottom:-1px;width:64px;height:9px;border-radius:50%;
  background:rgba(118,98,68,.22);filter:blur(1.2px);z-index:0;
}
@media (prefers-reduced-motion:reduce){
  .tf-stage,.tf-eye{animation:none!important}
}

/* =========================================================
   闯关地图（打卡 · 星星 · 徽章 · 48 关）
   ========================================================= */
.unit-grid.map-mode{display:block}

.map-top{margin-bottom:14px}
.mp-bar{height:12px;border-radius:99px;background:var(--surface-2);border:1px solid var(--line);overflow:hidden}
.mp-fill{height:100%;border-radius:99px;background:linear-gradient(90deg,var(--amber),var(--brand));transition:width .6s ease}
.mp-line{display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap;margin-top:7px;font-size:13px;color:var(--ink-2)}
.mp-line b{color:var(--brand-deep)}
.mp-star{font-weight:800;color:var(--amber)}

.checkin.card{padding:13px 16px;margin-bottom:14px}
.ci-head{display:flex;justify-content:space-between;align-items:center;font-size:13.5px;margin-bottom:10px}
.ci-head b{color:var(--brand-deep);font-size:16px}
.ci-row{display:flex;gap:8px}
.ci-day{
  flex:1;display:flex;flex-direction:column;align-items:center;gap:5px;padding:7px 0;
  border-radius:11px;background:var(--surface-2);border:1px solid var(--line-soft);
}
.ci-dot{width:17px;height:17px;border-radius:50%;background:var(--line);display:grid;place-items:center;transition:.2s}
.ci-day.on{background:#FFF6E9;border-color:#F3D9BE}
.ci-day.on .ci-dot{background:var(--brand);box-shadow:0 0 0 3px rgba(232,129,58,.18)}
.ci-day.on .ci-dot::after{content:"✓";color:#fff;font-size:10px;font-weight:800;line-height:1}
.ci-day.today{outline:2px dashed var(--amber);outline-offset:2px}
.ci-num{font-size:11px;color:var(--ink-3)}

.badges.card{padding:13px 16px;margin-bottom:16px}
.bg-head{font-size:13.5px;font-weight:700;margin-bottom:10px;display:flex;gap:8px;align-items:baseline}
.bg-head .muted{font-size:12px;font-weight:400}
.bg-row{display:flex;gap:8px;flex-wrap:wrap}
.badge{
  display:flex;align-items:center;gap:6px;padding:5px 11px;border-radius:20px;
  background:var(--surface-2);border:1px solid var(--line-soft);
  font-size:12px;color:var(--ink-3);filter:grayscale(1);opacity:.65;transition:.2s;
}
.badge.got{filter:none;opacity:1;background:#FFF6E9;border-color:#F3D9BE;color:#9A6C15;font-weight:700}
.badge:hover{transform:translateY(-1px)}
.bg-ico{font-size:15px}

.map-path{display:flex;flex-direction:column;gap:14px}
.map-unit{position:relative;padding-left:48px}
.mu-badge{
  position:absolute;left:0;top:16px;width:36px;height:36px;border-radius:50%;
  background:linear-gradient(135deg,var(--sky),var(--purple));color:#fff;
  display:grid;place-items:center;font-weight:800;font-size:14px;
  box-shadow:0 3px 10px rgba(139,123,199,.28);
}
.mu-card{
  background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);
  padding:12px 16px 14px;transition:.18s;
}
.mu-card:hover{box-shadow:var(--shadow)}
.mu-head{display:flex;justify-content:space-between;align-items:center;gap:10px;margin-bottom:10px}
.mu-title{display:flex;align-items:baseline;gap:8px;min-width:0}
.mu-code{font-weight:800;font-size:15px;flex:none}
.mu-theme{font-size:12.5px;color:var(--ink-3);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mu-actions{display:flex;gap:6px;flex:none}
.mu-body{display:grid;grid-template-columns:1fr 1fr;gap:12px}
.mu-side{background:var(--surface-2);border-radius:12px;padding:10px 12px;min-width:0}
.ms-label{display:flex;gap:8px;align-items:baseline;margin-bottom:9px;font-size:12.5px;min-width:0}
.ms-label b{font-size:13px;color:var(--ink);flex:none}
.ms-label span{color:var(--ink-3);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ms-nodes{display:flex;gap:8px}

.map-node{
  flex:1;display:flex;flex-direction:column;align-items:center;gap:4px;
  padding:9px 6px 8px;border-radius:12px;border:1.5px solid var(--line);
  background:var(--surface);cursor:pointer;transition:.15s;min-width:0;
}
.map-node:hover:not(.locked){border-color:var(--brand);transform:translateY(-2px);box-shadow:var(--shadow)}
.mn-ring{
  width:34px;height:34px;border-radius:50%;display:grid;place-items:center;
  background:var(--surface-2);color:var(--ink-3);font-weight:800;font-size:14px;transition:.2s;
}
.map-node.done{border-color:#CBE3D2;background:#F7FCF8}
.map-node.done .mn-ring{background:var(--green-soft);color:var(--green)}
.map-node.current{border-color:var(--brand);background:var(--brand-soft)}
.map-node.current .mn-ring{background:var(--brand);color:#fff;animation:nodePulse 1.9s infinite}
.map-node.locked{opacity:.62;cursor:not-allowed;background:var(--surface-2);border-style:dashed}
/* 「第 1 次课」是关卡点上唯一说明"这是什么"的文字，原来 11.5px 比
   正文（13px）还小一圈，家长得凑近看。提到 13px 跟正文齐平。 */
.mn-txt{font-size:13px;color:var(--ink-2);font-weight:600;white-space:nowrap}
.mn-stars{font-size:12px;color:var(--amber);letter-spacing:1.5px;min-height:16px}
.map-node.shake{animation:shake .4s}
@keyframes nodePulse{
  0%,100%{box-shadow:0 0 0 4px rgba(232,129,58,.18)}
  50%{box-shadow:0 0 0 9px rgba(232,129,58,.06)}
}

/* =========================================================
   Skim · 语音说大意
   ========================================================= */
.skim-ask{padding:15px 18px;display:flex;flex-direction:column;gap:10px}
.skim-ask.compact{padding-top:4px}
.skim-q{font-weight:700;font-size:15px}
.skim-sub{font-size:13px;color:var(--ink-2);line-height:1.6}
.skim-rec{display:flex;align-items:center;gap:13px;padding:2px 0}
.mic-orb{
  width:56px;height:56px;flex:none;border-radius:50%;border:0;
  background:linear-gradient(135deg,var(--brand),var(--amber));color:#fff;font-size:23px;
  display:grid;place-items:center;box-shadow:0 6px 18px rgba(232,129,58,.3);transition:.15s;
}
.mic-orb:hover{transform:scale(1.06)}
.mic-orb.rec{background:linear-gradient(135deg,var(--red),#E8813A);animation:micPulse 1.1s infinite}
.mic-orb.off{background:var(--line);box-shadow:none;opacity:.55;cursor:not-allowed}
.mic-orb.sm{width:44px;height:44px;font-size:18px}
.skim-mic-tip{font-size:13px;color:var(--ink-2)}
.skim-btns{display:flex;gap:8px;flex-wrap:wrap}
.skim-tail{display:flex;gap:8px;flex-wrap:wrap;align-items:center;padding:0 18px 16px}

@media (max-width:820px){
  .mu-body{grid-template-columns:1fr}
  .teacher-dock{height:92px;gap:10px;padding:0 12px}
  .tf,.tf svg{width:70px;height:88px}
  .tf-caption{font-size:12.5px;max-width:none}
}

/* =========================================================
   课本原文（第三版真实课文）
   ========================================================= */
.act-read{display:flex;flex-direction:column;min-height:0;height:100%}
.read-top{display:flex;align-items:center;gap:22px;padding:16px 18px 10px;flex:none}
.read-top .read-big{flex:none}
.read-side{flex:1;min-width:0}
.read-side .read-tip{margin:0 0 8px}
.read-side .read-btns{display:flex;gap:8px;flex-wrap:wrap}

.passage{
  flex:1;min-height:0;overflow-y:auto;margin:0 18px 14px;
  background:#FFFDF9;border:1px solid var(--line);border-radius:14px;padding:16px 20px 18px;
}
.ps-head{
  display:flex;justify-content:space-between;align-items:flex-start;gap:14px;
  border-bottom:1px dashed var(--line);padding-bottom:10px;margin-bottom:12px;
}
.ps-title{font-size:19px;font-weight:800;letter-spacing:.3px;color:var(--brand-deep)}
.ps-meta{font-size:11.5px;color:var(--ink-3);margin-top:3px}
.ps-tools{display:flex;gap:6px;flex:none}
.ps-tools .btn.on{background:var(--brand-soft);border-color:var(--brand);color:var(--brand-deep)}

.ps-body{display:flex;flex-direction:column;gap:11px}
.ps-p{display:flex;gap:10px;align-items:flex-start;padding:2px 0;border-radius:10px;transition:.2s}
.ps-p.speaking{background:var(--brand-soft)}
.ps-lab{
  flex:none;width:20px;height:20px;border-radius:6px;background:var(--surface-2);
  color:var(--ink-3);font-size:11.5px;font-weight:800;display:grid;place-items:center;margin-top:3px;
}
.ps-txt{flex:1;font-size:15.5px;line-height:1.85;color:var(--ink);font-family:Georgia,"Times New Roman",serif}
.ps-speak{
  flex:none;border:1px solid var(--line);background:transparent;border-radius:8px;
  width:26px;height:26px;font-size:12px;color:var(--ink-3);opacity:0;transition:.15s;margin-top:2px;
}
.ps-p:hover .ps-speak{opacity:1}
.ps-speak:hover{border-color:var(--brand);color:var(--brand-deep)}
.ps-notes{border-top:1px dashed var(--line);margin-top:14px;padding-top:10px}
.ps-note{font-size:12.5px;color:var(--ink-2);line-height:1.6;margin-bottom:4px}
.ps-note b{
  display:inline-grid;place-items:center;width:15px;height:15px;border-radius:50%;
  background:var(--surface-2);color:var(--ink-3);font-size:9.5px;margin-right:5px;
}
.ps-foot{margin-top:12px;font-size:11px;color:var(--ink-3)}
.ps-empty{padding:24px;text-align:center;color:var(--ink-2);font-size:13.5px;line-height:1.8}

/* 生词高亮：只在开启时显形，关掉就是干净的课文 */
.passage .w-book{background:linear-gradient(transparent 62%, #FBE3C9 62%);border-bottom:none}
.passage.no-mark .w-book{background:none;border-bottom:none;cursor:text}
.passage.no-mark .w-book::after{content:none}

/* 做题环节：课本原题 / 老师判定 / 自评 */
.q-opt.picked{border-color:var(--brand);background:var(--surface-2)}
.quiz-input-row{display:flex;gap:8px;align-items:flex-end;margin-top:4px}
.quiz-input-row textarea{
  flex:1;min-height:44px;resize:vertical;font-size:14.5px;line-height:1.6;
  border:1.5px solid var(--line);border-radius:10px;padding:9px 11px;font-family:inherit;
}
.quiz-input-row textarea:focus{outline:none;border-color:var(--brand)}
.hint-loading{color:var(--ink-3);font-size:13px;padding:8px 2px}
.hint-loading::after{content:'';animation:dots 1.2s steps(4,end) infinite}
@keyframes dots{0%{content:''}25%{content:'.'}50%{content:'..'}75%{content:'...'}}
.hint-empty{
  color:var(--ink-2);font-size:13px;line-height:1.7;
  background:var(--surface-2);border-radius:10px;padding:12px 14px;
}
.hint-empty .btn.tiny{margin-top:2px}

@media (max-width:820px){
  .read-top{flex-direction:column;align-items:stretch;gap:10px}
  .passage{margin:0 10px 10px;padding:12px 14px}
  .ps-txt{font-size:14.5px;line-height:1.8}
  .quiz-input-row{flex-direction:column;align-items:stretch}
}
