/* ==========================================================================
   童行思辨 · 续课率看板
   视觉参考 tongxingshuyuan.cn：深靛蓝 + 青绿的品牌渐变，浅蓝调底，大圆角，柔和彩色阴影
   ========================================================================== */
:root{
  /* 童行书院品牌色（取自官网 CSS 变量：--brand-navy / --brand-teal / --brand-pink） */
  --navy:#3b4c8b;          /* 主色：深靛蓝 rgb(59,76,139) */
  --navy-d:#263d82;
  --navy-l:#4a6ab0;
  --teal:#5fcbc3;          /* 辅色：青绿 rgb(95,203,195) */
  --teal-d:#2fa79f;
  --pink:#ffb6c1;

  --grad:linear-gradient(135deg,#3b4c8b 0%,#4a6ab0 48%,#5fcbc3 100%);
  --grad-soft:linear-gradient(135deg,rgba(59,76,139,.10),rgba(95,203,195,.16));
  --grad-line:linear-gradient(90deg,rgba(59,76,139,.55),rgba(95,203,195,.55));

  --bg:#f2f6fd;
  --bg-2:#f8fbff;
  --card:#fff;
  --line:rgba(38,61,130,.10);
  --line-2:rgba(38,61,130,.22);
  --text:#16203a;
  --text-2:#5b6b8c;
  --text-3:#8e9bb5;
  --soft:#eef3fb;
  --brand:#3b4c8b;
  --brand-soft:#e8edfa;

  --green:#3f9b6d; --green-d:#2b6f4e; --green-s:#e6f6ee;
  --amber:#c07a15; --amber-d:#8a5409; --amber-s:#fdf3e2;
  --red:#dc4b4b;   --red-d:#a92c2c;   --red-s:#fdecec;

  --r:16px;
  --shadow:0 10px 26px rgba(38,61,130,.10);
  --shadow-sm:0 4px 14px rgba(38,61,130,.07);
}
*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
html,body{margin:0;padding:0;height:100%}
body{
  background:#e8eef9;
  color:var(--text);
  font:400 14px/1.6 -apple-system,BlinkMacSystemFont,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","Noto Sans SC","Segoe UI",sans-serif;
  -webkit-font-smoothing:antialiased;
}
input,select,button,textarea{font:inherit;color:inherit}
button{cursor:pointer}
.hide{display:none !important}

/* 手机容器 */
#phone{
  max-width:680px;margin:0 auto;min-height:100vh;
  background:linear-gradient(#f8fbff,#f4f8ff 42%,#f7fafe);
  display:flex;flex-direction:column;position:relative;
  box-shadow:0 0 0 .5px rgba(38,61,130,.06);
}
.topbar{
  position:sticky;top:0;z-index:20;
  background:rgba(255,255,255,.9);
  -webkit-backdrop-filter:saturate(180%) blur(14px);
  backdrop-filter:saturate(180%) blur(14px);
  border-bottom:.5px solid var(--line);
  padding:12px 16px 11px;display:flex;align-items:center;gap:10px;
}
.topbar::after{
  content:"";position:absolute;left:0;right:0;bottom:-1px;height:2px;
  background:var(--grad-line);opacity:.55;
}
.topbar h1{font-size:16px;font-weight:600;margin:0;flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--navy-d);letter-spacing:.2px}
.topbar .me{font-size:12px;color:var(--text-2);white-space:nowrap}
.topbar .back{
  flex:none;width:28px;height:28px;margin-left:-4px;border:0;background:none;
  font-size:24px;line-height:1;color:var(--navy);padding:0;border-radius:8px;
}
.topbar .back:hover{background:var(--brand-soft)}
.rolechip{
  display:inline-block;font-size:11px;padding:4px 10px;border-radius:999px;
  background:var(--grad);color:#fff;white-space:nowrap;font-weight:500;
  box-shadow:0 3px 10px rgba(59,76,139,.28);
}
main{flex:1;padding:14px 14px calc(96px + env(safe-area-inset-bottom, 0px))}

/* 底部导航（用 left/right + margin auto 居中，避免 transform 与 fixed 叠加在手机上出问题） */
.tabbar{
  position:fixed;left:0;right:0;bottom:0;z-index:40;
  margin:0 auto;max-width:680px;
  background:rgba(255,255,255,.94);
  -webkit-backdrop-filter:saturate(180%) blur(14px);
  backdrop-filter:saturate(180%) blur(14px);
  border-top:.5px solid var(--line);
  /* 栏目数量按角色 5 或 6 个：自动流式布局，隐藏的 tab 不占位 */
  display:grid;grid-auto-flow:column;grid-auto-columns:1fr;
  padding-bottom:max(10px, env(safe-area-inset-bottom, 0px));
}
.tabbar button.hidetab{display:none}
.tabbar button{
  position:relative;background:none;border:0;padding:7px 0 9px;font-size:10px;color:var(--text-3);
  display:flex;flex-direction:column;align-items:center;gap:2px;white-space:nowrap;
}
.tabbar button .ic{width:19px;height:19px;display:block}
.tabbar button .bar{width:5px;height:5px;border-radius:50%;background:var(--grad);opacity:0}
.tabbar button.on{color:var(--navy);font-weight:500}
.tabbar button.on .bar{opacity:1}
.tabbar button .dot{
  position:absolute;top:4px;left:50%;margin-left:4px;min-width:15px;height:15px;line-height:15px;
  background:var(--red);color:#fff;font-size:10px;border-radius:999px;padding:0 4px;text-align:center;
}

/* 卡片与通用 */
.card{background:var(--card);border:.5px solid var(--line);border-radius:var(--r);padding:14px;box-shadow:var(--shadow-sm)}
.card + .card{margin-top:12px}
/* 待办顶部的「被看见」条：只报事实的肯定，不是考核成绩单 —— 所以用品牌青绿的柔和渐变，
   不用绿(达成)/红(落后)那套能被误读成评分的颜色 */
.card.praise{background:var(--grad-soft);border-color:rgba(95,203,195,.35);box-shadow:none;padding:12px 14px;color:var(--navy-d)}
/* 看板底部的「过程动作」（只给负责人）：不是 KPI，所以不抢续课率的视觉主角 ——
   只用一道浅靛蓝描边区分开，别用红黄那套能被读成"亮红灯"的颜色 */
.card.procm{border-color:rgba(59,76,139,.20)}
.procm-sum{display:block;padding:10px 12px;background:var(--soft);border-radius:12px;line-height:1.9}
.procm-ok{padding:4px 0}
.procm-note{margin-top:10px;line-height:1.7}
.sec-title{font-size:13px;font-weight:600;margin:16px 2px 8px;color:var(--navy-d);display:flex;align-items:baseline;gap:4px}
.sec-title:first-child{margin-top:0}
.muted{color:var(--text-2)}
.tiny{font-size:12px;color:var(--text-3)}

.kpis{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}
.kpi{
  background:linear-gradient(#fff,#fbfdff);
  border:.5px solid var(--line);border-radius:var(--r);padding:13px 14px;
  position:relative;overflow:hidden;box-shadow:var(--shadow-sm);
}
.kpi::before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--grad);opacity:.85}
.kpi .l{font-size:12px;color:var(--text-2)}
.kpi .v{font-size:24px;font-weight:600;margin-top:2px;letter-spacing:-.4px;color:var(--navy-d);font-variant-numeric:tabular-nums}
.kpi .f{font-size:11px;color:var(--text-3);margin-top:1px}
/* 目标续课率：项目负责人端可直接改（其他角色端是纯文字） */
.tgt-edit{display:inline-flex;align-items:baseline;gap:2px}
.tgt-edit input{
  width:46px;padding:1px 4px;border:.5px solid var(--line);border-radius:6px;background:#fff;
  font-size:12px;font-weight:600;color:var(--navy-d);text-align:center;font-variant-numeric:tabular-nums;
  -moz-appearance:textfield;appearance:textfield;vertical-align:baseline;
}
.tgt-edit input:focus{outline:none;border-color:var(--navy);box-shadow:0 0 0 2px rgba(95,203,195,.35)}
.tgt-edit input::-webkit-outer-spin-button,.tgt-edit input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.v-green{color:var(--green-d) !important} .v-amber{color:var(--amber-d) !important} .v-red{color:var(--red-d) !important}

/* 四个分阶段续课率卡片 */
.stages{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;margin-top:2px}
.stage{
  background:linear-gradient(135deg,#f4f8ff,#eef4ff);
  border:.5px solid var(--line);border-radius:13px;padding:11px 12px;
  cursor:pointer;transition:background .15s,border-color .15s,box-shadow .15s;
}
.stage:hover{box-shadow:var(--shadow-sm)}
.stage.on{background:#fff;border-color:transparent;box-shadow:var(--shadow),0 0 0 2px rgba(95,203,195,.45)}
.stage.dim{opacity:.6}
.stage.warn{background:linear-gradient(135deg,#fdf3e2,#fdf7ec);border-color:rgba(192,122,21,.28)}
.stage.warn.on{box-shadow:var(--shadow),0 0 0 2px var(--amber)}
.stage .st-top{display:flex;align-items:baseline;gap:6px}
.stage .st-nm{font-size:13px;font-weight:600;color:var(--navy-d)}
.stage .st-rt{margin-left:auto;font-size:18px;font-weight:600;font-variant-numeric:tabular-nums;color:var(--navy)}
.stage .st-rt .rt-lb{font-style:normal;font-size:10px;font-weight:500;color:var(--text-3);margin-right:3px}
.stage .st-stats{display:flex;flex-wrap:wrap;gap:4px 12px;margin-top:8px}
.stage .st-stats span{display:inline-flex;align-items:baseline;gap:3px;font-size:11px;color:var(--text-3)}
.stage .st-stats i{font-style:normal;color:var(--text-3)}
.stage .st-stats b{font-size:13px;font-weight:600;color:var(--navy-d);font-variant-numeric:tabular-nums}
.stage .st-f{font-size:11px;color:var(--text-3);margin-top:7px;line-height:1.5}
.stage .bar{margin-top:9px;height:6px;background:rgba(38,61,130,.08)}

.pill{font-size:11px;padding:3px 9px;border-radius:999px;background:var(--soft);color:var(--text-2);white-space:nowrap;display:inline-block;font-weight:500}
.pill.g{background:var(--green-s);color:var(--green-d)}
.pill.a{background:var(--amber-s);color:var(--amber-d)}
.pill.r{background:var(--red-s);color:var(--red-d)}
.pill.b{background:var(--brand-soft);color:var(--navy)}
.pill.k{background:#e8ebf2;color:var(--text-2)}
.pill.dash{background:transparent;border:1px dashed var(--line-2);color:var(--text-3)}
.tagbtn{cursor:pointer}

.rowline{display:flex;align-items:center;gap:10px}
.grow{flex:1;min-width:0}
.ell{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* 班级进度条 */
.cls{padding:13px 0;border-bottom:.5px solid var(--line)}
.cls:last-child{border-bottom:0}
.cls .head{display:flex;align-items:baseline;gap:8px;margin-bottom:7px}
.cls .head .nm{font-weight:600;font-size:13.5px;color:var(--text)}
.cls .head .num{font-size:12px;color:var(--text-2)}
.cls .head .rt{margin-left:auto;font-size:14px;font-weight:600;font-variant-numeric:tabular-nums}
.bar{position:relative;height:7px;background:rgba(38,61,130,.08);border-radius:999px;overflow:visible}
.bar .fill{position:absolute;left:0;top:0;bottom:0;border-radius:999px;transition:width .25s}
.bar .mark{position:absolute;top:-4px;bottom:-4px;width:1px;background:var(--line-2)}
.cls .foot{display:flex;gap:8px;margin-top:6px;font-size:11.5px;color:var(--text-3)}

/* 列表项 */
.item{display:flex;align-items:center;gap:10px;padding:12px 0;border-bottom:.5px solid var(--line)}
.item:last-child{border-bottom:0}
.item .av{
  width:38px;height:38px;border-radius:12px;flex:none;display:flex;align-items:center;justify-content:center;
  background:var(--grad-soft);color:var(--navy);font-size:14px;font-weight:600;
}
.item .nm{font-size:14px}
.item .sub{font-size:12px;color:var(--text-3)}

/* 学员卡片 / 班级明细 */
.stucard{padding:12px 0;border-bottom:.5px solid var(--line);cursor:pointer}
.stucard:last-child{border-bottom:0}
.stucard:active{background:var(--soft)}
.stucard .smeta{font-size:11.5px;color:var(--text-3);line-height:1.5}
.stats4{display:grid;grid-template-columns:repeat(4,1fr);gap:8px;margin-top:11px;text-align:center}
.stats4 div{background:var(--grad-soft);border-radius:11px;padding:8px 2px}
.stats4 span{display:block;font-size:11px;color:var(--text-2)}
.stats4 b{font-size:16px;font-weight:600;color:var(--navy-d)}

/* 表单 */
.field{margin-bottom:11px}
.field label{display:block;font-size:12px;color:var(--text-2);margin-bottom:5px}
input[type=text],input[type=password],input[type=date],input[type=number],select,textarea{
  width:100%;background:var(--soft);border:.5px solid transparent;border-radius:11px;
  padding:10px 11px;font-size:14px;outline:none;
}
input:focus,select:focus,textarea:focus{border-color:var(--navy-l);background:#fff;box-shadow:0 0 0 3px rgba(74,106,176,.14)}
textarea{min-height:78px;resize:vertical}
/* 学情反馈要写 600–1000 字，默认 78px 的框太憋屈了，单独放高一点 */
#fbTxt{min-height:190px;line-height:1.75}
/* 字数计数器：不足给琥珀、超出给红、达标给绿，光标不用离开输入框就知道够没够 */
.fbcount{margin-top:6px;font-size:12px;text-align:right;color:var(--text-3)}
.fbcount.low{color:var(--amber-d)}
.fbcount.over{color:var(--red-d)}
.fbcount.ok{color:var(--green-d)}
.btn{
  width:100%;background:var(--grad);color:#fff;border:0;border-radius:11px;
  padding:11px;font-size:15px;font-weight:600;margin-top:4px;
  box-shadow:0 6px 16px rgba(59,76,139,.26);
}
.btn:active{transform:translateY(1px)}
.btn.ghost{background:#fff;color:var(--navy);border:.5px solid var(--line-2);box-shadow:none}
.btn.sm{width:auto;padding:7px 13px;font-size:13px;font-weight:500;border-radius:10px;margin:0;box-shadow:none}
.btn.danger{background:var(--red-s);color:var(--red-d);border:0}
.btn.ghost.danger{background:#fff;color:var(--red-d);border:.5px solid rgba(220,75,75,.35)}
.btn:disabled{opacity:.5}
/* 2026-10-15 真机修复（微信 webview）：两个长按钮并排（如「记一次课堂」+「上传课堂表格（整班拆分）」）
 * 在窄屏上 min-content 超过可用宽度，flex 不换行就把整卡撑爆 → 整页横向溢出、左侧文字全被裁。
 * 改成可换行 + 按内容分配：放得下照旧并排，放不下第二个按钮换行独占一行，绝不再撑破页面。 */
.btnrow{display:flex;gap:8px;flex-wrap:wrap}
.btnrow .btn{flex:1 1 auto;min-width:0}

/* 筛选条 */
.filters{display:flex;gap:8px;overflow-x:auto;padding:2px 0 10px;-webkit-overflow-scrolling:touch}
/* 班型筛与阶段筛之间的分隔（2026-10-17）：同一排并列，但两维是「与」关系，不能看着像一组 */
.chipsep{flex:0 0 auto;align-self:center;color:var(--sub);font-size:12px;margin:0 -2px;opacity:.7}
.filters::-webkit-scrollbar{display:none}
.chip{
  flex:none;font-size:12.5px;padding:6px 13px;border-radius:999px;
  background:#fff;border:.5px solid var(--line);color:var(--text-2);box-shadow:var(--shadow-sm);
}
.chip.on{background:var(--grad);border-color:transparent;color:#fff;box-shadow:0 5px 14px rgba(59,76,139,.28)}

/* 弹层 */
.sheet-mask{
  position:fixed;inset:0;background:rgba(22,32,58,.42);z-index:50;display:flex;align-items:flex-end;
  justify-content:center;
  -webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);
}
.sheet{
  background:var(--bg);width:100%;max-width:680px;border-radius:22px 22px 0 0;
  max-height:88vh;overflow-y:auto;padding:16px 16px 26px;box-shadow:0 -12px 40px rgba(38,61,130,.18);
}
.sheet::before{content:"";display:block;width:38px;height:4px;border-radius:999px;background:var(--line-2);margin:-4px auto 12px}
.sheet h3{font-size:15.5px;font-weight:600;margin:0 0 12px;display:flex;align-items:center;color:var(--navy-d)}
.sheet h3 button{margin-left:auto;background:none;border:0;font-size:20px;color:var(--text-3);line-height:1}
.sheet .card{box-shadow:var(--shadow-sm)}
/* 应用内确认框：永远居中，不跟随底部弹层的对齐方式 */
.cfm-mask{align-items:center;z-index:80}
.cfm-mask .cfm-sheet{max-width:420px;border-radius:20px;margin:0;padding:16px 16px 18px}
.cfm-mask .cfm-sheet::before{display:none}
/* 确认框正文保留换行：删账号 / 改角色这类多行提醒以前被压成一整段，读起来像一长串 */
.cfm-mask .cfm-msg{font-size:14px;line-height:1.75;white-space:pre-line}
.toast{
  position:fixed;left:50%;bottom:96px;transform:translateX(-50%);z-index:99;
  background:rgba(38,61,130,.94);color:#fff;font-size:13px;padding:10px 18px;border-radius:12px;
  max-width:80%;text-align:center;box-shadow:0 10px 26px rgba(38,61,130,.35);
}

/* 看板顶部的品牌抬头：看板全名 + slogan */
.brandhead{padding:2px 6px 14px;text-align:center}
.brandhead .bh-title{font-size:17px;font-weight:600;color:var(--navy-d);letter-spacing:.2px}
.brandhead .bh-slogan{display:inline-block;margin-top:8px;padding:5px 13px;border-radius:999px;
  background:var(--grad-soft);font-size:12.5px;line-height:1.6;color:var(--navy)}

/* 批量上传的「班级信息参考模板」表 */
.tpl-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch;border-radius:12px}
.tpl{min-width:100%;border-collapse:collapse;font-size:12.5px;margin:2px 0 8px;background:#fff;
  border-radius:12px;overflow:hidden;box-shadow:0 0 0 1px var(--line)}
.tpl th,.tpl td{padding:7px 8px;text-align:left;white-space:nowrap;border-bottom:.5px solid var(--line)}
.tpl th{background:var(--grad-soft);color:var(--navy-d);font-weight:600;font-size:12px}
.tpl td{color:var(--text)}
.tpl td.mono{font-family:ui-monospace,Consolas,"Courier New",monospace;color:var(--text-2)}
.tpl tr:last-child td{border-bottom:0}
.tpl-req{display:inline-block;margin-left:4px;padding:0 4px;border-radius:4px;font-size:10px;
  font-weight:500;color:#fff;background:var(--teal-d);vertical-align:1px}
.tpl-lab{font-size:12px;line-height:1.85;color:var(--text-3);margin:0 2px 2px}

/* 时间线 */
.tl{position:relative;padding-left:16px}.tl .t{position:relative;padding:0 0 14px}
.tl .t::before{content:"";position:absolute;left:-16px;top:6px;width:7px;height:7px;border-radius:50%;background:var(--grad)}
.tl .t::after{content:"";position:absolute;left:-13.5px;top:14px;bottom:0;width:1px;background:var(--line-2)}
.tl .t:last-child::after{display:none}
.tl .t .meta{font-size:11.5px;color:var(--text-3)}
.tl .t .txt{font-size:13.5px;margin-top:2px}
/* 跟进时间轴（2026-10-19）：一个孩子一条落在日期上的动作序列。
 * 行内 = 勾 + 文字 + 动作按钮。★ 窄屏必须 flex-wrap + min-width:0，
 *   否则「去开班会的节点」这种长按钮会把整行撑破（v1.31 横溢 58–89px 的老坑）。 */
.tl-step{display:flex;flex-wrap:wrap;align-items:flex-start;gap:6px;margin-top:3px}
.tl-step .tl-ic{flex:0 0 13px;width:13px;line-height:1.5}
.tl-step .tl-txt{flex:1 1 0;min-width:0;font-size:12px;line-height:1.55;color:var(--ink-3);overflow-wrap:anywhere}
.tl-step .tl-txt.tl-done{color:var(--sub);text-decoration:line-through}
.tl-step .tl-btn{flex:0 0 auto;margin-left:auto}
.tl .t.tl-open .meta b{color:var(--red-d)}

/* 学情反馈附件（PDF / Word） */
.fitem{display:flex;align-items:center;gap:9px;padding:9px 0;border-bottom:.5px solid var(--line)}
.fitem:last-child{border-bottom:0}
.ficon{
  flex:none;width:42px;height:28px;border-radius:8px;background:var(--grad);color:#fff;
  font-size:10px;font-weight:600;display:flex;align-items:center;justify-content:center;letter-spacing:.4px;
}
.fname{font-size:13.5px}
.fitem .btn.sm{padding:5px 10px;font-size:12px}
input[type=file]{width:100%;font-size:13px;padding:9px 0;color:var(--text-2)}

.empty{text-align:center;padding:30px 14px;color:var(--text-3);font-size:13px}

/* 登录页：品牌渐变背景 + 白色卡片 */
#login{
  display:flex;align-items:center;justify-content:center;min-height:100vh;padding:24px;
  background:
    radial-gradient(900px 420px at 12% -8%, rgba(95,203,195,.45), transparent 62%),
    radial-gradient(760px 420px at 92% 6%, rgba(255,182,193,.35), transparent 60%),
    linear-gradient(160deg,#eef4ff,#e7eefb 55%,#f3f7ff);
}
.login-card{
  width:100%;max-width:400px;background:#fff;border-radius:22px;padding:66px 24px 24px;
  border:.5px solid var(--line);box-shadow:0 22px 50px rgba(38,61,130,.16);position:relative;overflow:hidden;
}
.login-card::before{content:"";position:absolute;left:0;right:0;top:0;height:5px;background:var(--grad)}
/* 标题 = logo（横版组合标，含品牌名）+「都在」两字，flex 组成一个整体并居中（2026-10-11 晚定稿） */
.login-card h1{display:flex;align-items:center;justify-content:center;gap:10px;
  font-size:24px;font-weight:700;line-height:1.2;margin:0 0 12px;color:var(--navy-d);letter-spacing:.5px;text-align:center}
/* 「都在」用圆润字体（2026-10-11 晚用户要求：令人心生好感）。
 * douzai.woff2 是按字裁的子集（只有「都」「在」两个字形，876 字节，站酷快乐体 · OFL 可商用），
 * 加载零负担；加载失败时退到系统圆体栈（iOS 圆体-简 / Windows 幼圆），再不行退回雅黑。 */
@font-face{
  font-family:'DouZaiRound';
  src:url('/douzai.woff2') format('woff2');
  font-weight:400;font-style:normal;font-display:swap;
  unicode-range:U+5728,U+90FD;
}
.login-card h1 .zai{
  font-family:'DouZaiRound','Yuanti SC','YouYuan','幼圆','STYuanti','Hiragino Maru Gothic ProN','Microsoft YaHei',sans-serif;
  font-weight:400;letter-spacing:2px;
}
.login-logo{display:block;width:auto;height:32px}
/* ★ 2026-10-15 用户拍板「红框的文字删掉，页面干净简约」：
 *   登录页的品牌口号（.bslogan）/ 副行（.bsub）/ 平台口号（.slogan）三块撤下，
 *   这三条 login 作用域的规则一并删除；.bslogan 通用样式仍留给品牌介绍弹层用。 */
.login-card .btn{box-shadow:0 8px 22px rgba(59,76,139,.30)}
/* ---- 登录页字体统一方案（2026-10-11 晚定稿）----
 * 五级字号梯：24（品牌标题）→ 16（主按钮）→ 15（输入）→ 13（标签/slogan/示例）→ 12（说明）。
 * 字重配：700 标题 / 600 标签·按钮 / 500 slogan / 400 其余。字距：标题 .5 · slogan 3（标签感）· 按钮 2。
 * ★ 全部限定在 #login 下 —— `.field label` / `input` / `.btn` / `.tiny` 是全站共用的类，
 *   不限定作用域会连带改掉所有弹层表单。 */
#login .field label{font-size:13px;font-weight:600;letter-spacing:.5px;line-height:1.4;color:var(--text-2);margin-bottom:7px}
#login .field input{font-size:15px;font-weight:400;line-height:1.4}
#login .btn{font-size:16px;font-weight:600;letter-spacing:2px;line-height:1.2}
#login .btn.ghost{font-size:14px;letter-spacing:0}
#login .tiny{font-size:12px;font-weight:400;line-height:1.7}
#login .demo .d{font-size:13px}
.demo{margin-top:18px;border-top:.5px solid var(--line);padding-top:14px}
.demo .d{display:flex;gap:8px;font-size:12.5px;padding:5px 0;align-items:center}
.demo .d b{font-weight:600;color:var(--navy-d)}
.demo .d button{margin-left:auto}

/* ---- 品牌介绍弹层内容（四承载位共用；品牌色沿用 VI：navy/teal/pink/圆角 16） ---- */
.bname{font-size:18px;font-weight:700;color:var(--navy-d);letter-spacing:.5px}
.bsec .bst{font-size:14px;font-weight:600;color:var(--navy);margin:16px 0 8px;
  padding-left:10px;border-left:3px solid var(--teal)}
.bi{font-size:13px;line-height:1.8;color:var(--text-2);padding-left:6px}
.bi.ok{color:var(--teal-d)}
.bi.no{color:var(--amber-d)}
.bok{margin-top:4px}
.bno{margin-top:8px;padding-top:8px;border-top:.5px dashed var(--line)}
.blead{font-size:13px;line-height:1.8;color:var(--text-2);margin:10px 0 2px;
  padding:10px 12px;border-radius:12px;background:var(--grad-soft)}
/* 弹层里复用的品牌口号三级（与登录页同款，但字号按弹层收一档） */
.bslogan{font-size:15px;font-weight:600;letter-spacing:1px;color:var(--navy-d);margin-top:6px}
.btagline{font-size:13px;font-weight:500;letter-spacing:2px;color:var(--teal-d);margin-top:2px}
.borigin{font-size:12px;color:var(--text-3);margin-top:4px}

/* 微信自带浏览器底部有工具栏，会把固定底栏盖住：整体上抬让开 */
html.in-wechat .tabbar{
  padding-bottom: max(56px, env(safe-area-inset-bottom, 0px));
  border-bottom:.5px solid var(--line);
}
html.in-wechat main{padding-bottom:calc(150px + env(safe-area-inset-bottom, 0px))}
html.in-wechat .toast{bottom:170px}

/* 手机横屏/矮屏时也不至于完全压住内容 */
@media (max-height:520px){
  main{padding-bottom:110px}
}

/* 电脑/宽屏：底部那排手机式导航在宽屏上容易被忽略，直接提到最上面做横向导航条 */
@media (min-width:760px){
  #phone{max-width:860px}
  .tabbar{
    position:sticky;top:0;bottom:auto;order:-1;z-index:30;
    max-width:none;margin:0;border-top:0;border-bottom:.5px solid var(--line);
    display:flex;justify-content:center;gap:2px;padding:0;overflow-x:auto;
  }
  .tabbar button{
    flex:0 0 auto;flex-direction:row;align-items:center;gap:6px;
    padding:13px 12px;font-size:13px;border-radius:0;
  }
  .tabbar button .ic{width:17px;height:17px}
  .tabbar button .bar{display:none}
  .tabbar button.on{color:var(--navy);box-shadow:inset 0 -2px 0 var(--navy)}
  .tabbar button .dot{top:3px;left:auto;right:8px;margin-left:0}
  .topbar{position:static}
  .topbar::after{display:none}
  main{padding:16px 18px 30px}
  .kpis{grid-template-columns:repeat(4,minmax(0,1fr))}
  .stages{grid-template-columns:repeat(4,minmax(0,1fr))}
  .stage.warn{grid-column:auto}
  .sheet{max-width:640px;border-radius:20px;margin-bottom:40px}
  .sheet-mask{align-items:center}
  .toast{bottom:40px}
}

/* 体验课客户模块（独立）：概览的小表格 + 客户名单 */
.lt-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch}
.ltable{width:100%;border-collapse:collapse;font-size:12.5px}
.ltable th{font-weight:500;color:var(--text-3);text-align:left;padding:6px 8px;border-bottom:.5px solid var(--line);white-space:nowrap}
.ltable td{padding:8px;border-bottom:.5px solid var(--line);color:var(--text-2);font-variant-numeric:tabular-nums}
.ltable tr:last-child td{border-bottom:0}
.ltable td:first-child{max-width:150px;color:var(--text)}
.ltable th:not(:first-child),.ltable td:not(:first-child){text-align:right}

/* 学员生命周期四段漏斗（看板最上方）：四段各配一个专属色，画面和谐又一眼能分清。
 * 只作用于 #lifeTiles，分阶段续课率卡片（.stage 无 .life）不受影响。
 * ① 体验=青绿（新芽） ② 在班=靛蓝（主力） ③ 续课=琥珀（要收的关键动作） ④ 转介绍=玫红（裂变）。
 * 大数字保留原有的语义色（达标绿 / 警示琥珀 / 危险红），段落身份靠左侧色条 + 段名 + 底色区分。 */
#lifeTiles .stage{position:relative;overflow:hidden}
#lifeTiles .stage::before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--seg);opacity:.9}
#lifeTiles .stage:nth-child(1){--seg:#2e9c92;background:linear-gradient(135deg,#ecf8f6,#e2f3f0);border-color:rgba(46,156,146,.25)}
#lifeTiles .stage:nth-child(2){--seg:#3b4c8b;background:linear-gradient(135deg,#f0f3fc,#e9eefa);border-color:rgba(59,76,139,.22)}
#lifeTiles .stage:nth-child(3){--seg:#c97f1b;background:linear-gradient(135deg,#fbf4e7,#f7eeda);border-color:rgba(201,127,27,.25)}
#lifeTiles .stage:nth-child(4){--seg:#c2537e;background:linear-gradient(135deg,#fbeef4,#f7e5ed);border-color:rgba(194,83,126,.25)}
#lifeTiles .stage .st-nm{color:var(--seg)}
#lifeTiles .stage .st-rt .rt-lb{color:var(--seg);opacity:.8}
#lifeTiles .stage .st-rt{font-size:17px}
/* 表格末行「合计/平均」：跟普通数据行区分开 */
.ltable tfoot td{border-top:.5px solid var(--line);border-bottom:0;color:var(--text);font-weight:500}
/* 渠道表里把「转介绍」那一行高亮出来 —— 整页就是要看它 */
.ltable tr.refrow td{background:rgba(95,203,195,.16)}
.ltable tr.refrow td:first-child{font-weight:600;color:var(--navy-d)}

/* 家长链接二维码（学员档案 → 客户与课时 → 家长专属链接）
 * 二维码本身就是黑白方块，给白底 + 一点留白才扫得稳；
 * 手机上要留够点击/长按保存的余地，所以宽度给到 200px 且居中。 */
.qrwrap{margin:2px auto 0;width:196px;max-width:70%;background:#fff;border-radius:14px;padding:10px;
        box-shadow:0 6px 18px rgba(38,61,130,.12);border:.5px solid var(--line)}
.qrimg{display:block;width:100%;height:auto;image-rendering:pixelated}
.hr{height:.5px;background:var(--line);margin:14px 0}

/* 看板顶部的「分阶段跟进守则」轮播（2026-10-11 用户给的内容方案）
 * 位置：品牌抬头、项目筛选之下，四段漏斗之上。
 * 视觉：中性淡底 + 每张一个弱饱和的段落色（左侧细条 + 插画线条），留白足够，一屏只说一件事。
 * 用户明确要求"温和、不刺眼、避免强营销感的红黄"，所以颜色只做点缀，不做大面积色块。 */
.gcar{margin-top:12px;border:.5px solid var(--line);border-radius:var(--r);
      background:linear-gradient(135deg,#f8fafd,#f3f6fc);overflow:hidden}
.gcar .gbar{display:flex;align-items:baseline;gap:6px;padding:10px 13px 0}
.gcar .gname{font-size:12.5px;font-weight:600;color:var(--navy-d)}
.gcar .gview{overflow:hidden}
.gcar .gtrack{display:flex;transition:transform .38s cubic-bezier(.22,.61,.36,1)}
.gcar .gslide{position:relative;flex:0 0 100%;display:flex;gap:10px;align-items:flex-start;padding:10px 13px 9px}
.gcar .gslide::before{content:"";position:absolute;left:0;top:12px;bottom:12px;width:3px;
      border-radius:0 3px 3px 0;background:var(--seg);opacity:.7}
.gcar .gart{flex:0 0 56px;width:56px;height:56px;margin:1px 2px 0 5px}
/* 配图 / 内置插画共用的方框：看板轮播与「守则维护」弹层都用它。
 * 没配图时不加底色和描边 —— 保持原来「线条插画直接浮在卡片上」的样子；
 * 有配图才出现圆角块（.has），于是照片和插画在同一个 56×56 的位置上，布局不跳。 */
.gpix{position:relative;flex:0 0 56px;width:56px;height:56px;border-radius:13px;overflow:hidden}
.gpix .gart{display:block;width:56px;height:56px;margin:0}
.gpix .gimg{position:absolute;left:0;top:0;width:56px;height:56px;object-fit:cover}
.gpix.has{border:.5px solid var(--line-2);background:#eef2fa}
.gcar .gpix{margin:1px 2px 0 5px}
.gprev{flex:0 0 56px}
.gprev .gpix{width:56px;height:56px}
.gcar .gbody{min-width:0;flex:1}
.gcar .gttl{font-size:13px;font-weight:600;color:var(--navy-d)}
.gcar .gr{font-size:12px;color:var(--text-2);line-height:1.6;margin-top:3px}
.gcar .gr b{color:var(--navy);font-weight:600;margin-right:3px}
.gcar .gpt{font-size:11px;color:var(--text-3);margin-top:6px;padding-top:5px;border-top:.5px dashed var(--line-2)}
.gcar .gfoot{display:flex;align-items:center;gap:8px;padding:0 12px 9px}
.gcar .gdots{display:flex;align-items:center;gap:5px;flex:1}
.gcar .gdot{width:6px;height:6px;padding:0;border:0;border-radius:50%;background:var(--line-2);
      transition:width .2s,background .2s}
.gcar .gdot.on{width:16px;border-radius:999px;background:var(--navy)}
.gcar .garrow{display:flex;gap:6px}
.gcar .gnav{width:26px;height:26px;padding:0;border:.5px solid var(--line-2);border-radius:50%;
      background:#fff;color:var(--navy);font-size:14px;line-height:1}
.gcar .gnav:active{background:var(--brand-soft)}
@media (prefers-reduced-motion: reduce){ .gcar .gtrack{transition:none} }

/* 员工端品牌卡（看板首页，守则轮播下方 · 2026-10-12）
 * 位置：紧跟守则轮播。守则=怎么做，这里=为什么做。
 * 视觉比守则轮播更"静"：白底 + 左侧 teal 细条，一屏看完不翻页，不抢守则的戏。 */
.bcard{margin-top:12px;border:.5px solid var(--line);border-radius:var(--r);
  background:#fff;padding:12px 14px;position:relative;overflow:hidden}
.bcard::before{content:"";position:absolute;left:0;top:12px;bottom:12px;width:3px;border-radius:0 3px 3px 0;
  background:var(--teal);opacity:.7}
.bcard-h{display:flex;align-items:baseline;gap:6px;margin-bottom:4px}
.bcard-t{font-size:12.5px;font-weight:600;color:var(--navy-d)}
.bcard-lead{font-size:12.5px;color:var(--text-2);line-height:1.7;margin-bottom:6px}
.bcard-b .bi{font-size:12.5px;padding-left:17px;position:relative}
.bcard-b .bi::before{content:"·";position:absolute;left:6px;color:var(--teal-d);font-weight:700}
.bcard-foot{font-size:11.5px;color:var(--text-3);line-height:1.7;margin-top:8px;padding-top:7px;
  border-top:.5px dashed var(--line-2)}
.bcard-act{margin-top:10px}
.bcard-act .btn{width:auto}

/* ==========================================================================
   自媒体小组（2026-10-12）
   素材库 / 内容管理 / 我的剪辑。视觉沿用品牌色，但用「卡中卡」把素材与内容分开：
   素材是「原料」（暖一点的米白底，暗示真实课堂），内容是「成品」（纯白卡）。
   ========================================================================== */
.mp{background:var(--grad);color:#fff;border:0;box-shadow:0 12px 30px rgba(38,61,130,.20)}
.mp .mp-t{font-size:19px;font-weight:600;letter-spacing:.3px}
.mp .mp-s{font-size:12px;color:rgba(255,255,255,.85);margin-top:3px;line-height:1.7}
.mp .kpi{background:rgba(255,255,255,.14);border:.5px solid rgba(255,255,255,.22)}
.mp .kpi::before{display:none}
.mp .kpi .l{color:rgba(255,255,255,.82)}
.mp .kpi .v{color:#fff}
.mp .kpi .f{color:rgba(255,255,255,.7)}

/* 素材卡：原料感 —— 米白底 + 左侧一道青绿细边，跟「成品」白卡区分开 */
.mcard{background:#fbfaf6;border-color:rgba(38,61,130,.10)}
.mcard .mq{font-size:14px;line-height:1.85;margin-top:9px;color:var(--text)}
.mcard .mtitle{font-size:15px;font-weight:500;margin-top:8px}
.mlink{display:block;font-size:12px;color:var(--navy-l);word-break:break-all;margin-top:6px;text-decoration:none}

/* 「可用 / 不可用」这类横排键值（素材库、边界卡共用） */
.mrow{display:flex;gap:10px;padding:8px 0;border-bottom:.5px solid var(--line);font-size:13px;line-height:1.8}
.mrow:last-child{border-bottom:0}
.mrow .mk{flex:0 0 58px;color:var(--text-3);font-size:12px}
.mrow .mv{flex:1;min-width:0}
.swatch{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:var(--text-2);
  background:var(--soft);border-radius:999px;padding:3px 10px 3px 4px}
.swatch i{width:14px;height:14px;border-radius:50%;display:inline-block;border:.5px solid rgba(0,0,0,.08)}

/* 「选素材」那一列：整行可点，勾选框不抢视线 */
.pickline{display:flex;align-items:center;gap:8px;padding:9px 2px;border-bottom:.5px solid var(--line);cursor:pointer;font-size:13px}
.pickline:last-child{border-bottom:0}
.pickline input{width:auto;margin:0;flex:0 0 auto}
.pickline .grow{min-width:0}

/* 内容管理/我的剪辑页里的分区标题带一句说明，窄屏会换行，别挤成一行 */
@media (max-width:420px){ .mrow .mk{flex-basis:48px} }

/* ==========================================================================
   移动端触控适配（2026-10-16）
   —— 用户：「该平台页面用户在手机上用得比较多，全部界面要做手机用户使用方便适应性调整」。
   基准机型 iPhone 12/13（390×844），向下兼容安卓 360px，向上 430px 大屏留余量。
   ★ 原则：只做「手感」与「溢出」的兜底，**不动任何版面骨架**（栏位、卡片顺序、信息分层都不变）——
     骨架改了用户会觉得"页面变样了"，这一轮要的是"同样内容，手指更好按、字更好读"。
   ★ 适用范围：所有手机宽度（≤560px）。宽屏 @media(min-width:760px) 的桌面形态不受影响。
   ========================================================================== */

/* ---- ① 全局：横竖屏切换时字号自动稳一手，避免 iOS 横屏把正文放大到失真 ---- */
html{ -webkit-text-size-adjust:100%; text-size-adjust:100%; }

/* ---- ①-2 ★ 横向溢出总闸门（2026-10-16 实测揪出来的真问题）----
 * 首轮 390px 实测：学员页横溢 58px、360px 横溢 89px。
 * 真正的元凶有两处，且都是**外壳右边界超出视口**，不是某张卡片自己撑破：
 *   ① `.filters`（chip 横向滚动条）：chip 总宽 728px，虽然容器可滚，但容器自身的
 *      右边界被算到 728px（子元素把可滚动容器的 scrollWidth 顶出去），在窄屏上表现为整页可拖。
 *   ② `.rowline .grow` 里的长姓名/长文本没有 min-width:0，flex 子项不肯收缩，把行撑破。
 * 兜底策略：容器一律 max-width:100% + min-width:0；真正需要横向滚动的表/条给明确 overflow。
 * ★ 这是"防撑破"的最后一层网 —— 单页布局问题仍应单独修，这里只保证整页绝不横向可拖。 */
@media (max-width:560px){
  #phone, main, .card, .sheet, .topbar{max-width:100%}
  .filters{max-width:100%;width:100%}
  /* flex/grid 子项默认 min-width:auto，长内容不肯收缩 —— 这是窄屏撑破最常见的成因 */
  .rowline > *, .btnrow > *, .item > *, .cls .head > *, .grow{min-width:0}
  .rowline{max-width:100%}
  /* 长不可断内容（姓名连写、订单号、外链）允许任意位置断行 */
  #view, #view *{overflow-wrap:break-word}
  /* 学员卡片的标记胶囊允许换行 —— 行里常有 4~5 个胶囊（资料缺/上完/续课状态），
   * 硬塞一行必挤爆重叠（2026-10-17 实测「结课日到」与「已续课」叠字）。 */
  .stucard .rowline{flex-wrap:wrap}
  .stucard .rowline .pill{flex:0 0 auto}
}

/* ---- ② 点击区：正文里那些"看着是字、实际要按"的小按钮，全部撑到 44px 触控目标 ----
 * 为什么不做成 44px 高而不是加大 padding：这些按钮多数挤在 .rowline/.meta 里，
 * 只是加 padding 会把行高顶起来、版面跳动；用 min-height + flex 居中，四周留白也就自然够了。 */
@media (max-width:560px){
  /* 文字型小按钮（.btn.sm 已带边框）—— 视觉高 34px，触控靠 44px 的 min-height 撑 */
  .btn.sm{min-height:40px;padding:9px 14px;font-size:13.5px;display:inline-flex;align-items:center;justify-content:center}
  /* 图标×删除按钮：竖排两三个时最容易误触，给足方形触控区 */
  .btn.sm.danger{min-width:40px}
  /* 弹层右上角关闭 ×：28px 在手机上太难点中，撑到 44 */
  .sheet h3 button{width:40px;height:40px;margin:-8px -8px -8px auto;display:flex;align-items:center;justify-content:center;font-size:22px}
  /* 带副标题的设置行（.item，整行可点）：行高不足时补到 52px */
  .item{min-height:52px}
  /* 顶栏返回键：原本 28px，按起来容易踩到标题 */
  .topbar .back{width:36px;height:36px;font-size:26px}
  /* 筛选 chip：横向滚动的胶囊，撑到 36 高，指腹按得住 */
  .chip{padding:9px 15px;font-size:13px}
  /* 轮播小圆点（看板守则）：点中区域太小，视觉不变、触控补到 22px */
  .gcar .gdot{position:relative}
  .gcar .gdot::after{content:"";position:absolute;left:50%;top:50%;width:22px;height:22px;transform:translate(-50%,-50%)}
  .gcar .gnav{width:34px;height:34px;font-size:16px}
  /* A/B/C 意向标签（学员列表里直接点着改）：视觉是 11.5px 的小胶囊，但它是"能改数据"的按钮，
   * 25px 高在真机上按不准。用 ::after 把触控区撑到 40px，胶囊外观保持不变。 */
  .pill.tagbtn{position:relative}
  .pill.tagbtn::after{content:"";position:absolute;left:50%;top:50%;width:100%;height:40px;min-width:40px;transform:translate(-50%,-50%)}
  /* 底部导航：图标 19→21，标签 10→11px（10px 在手机上普遍读不清） */
  .tabbar button{font-size:11px;padding:8px 0 10px}
  .tabbar button .ic{width:21px;height:21px}
  /* 弹层里的「保存草稿 / 发送给家长」这类并排主按钮：放不下就整行换行，别硬挤成两条窄缝 */
  .sheet .btnrow .btn{flex:1 1 46%}
}

/* ---- ③ 字号下限：11px 及以下的中文在手机上基本读不了，统一抬到 11.5/12px ----
 * 只抬"给人读的正文级"文字；.tpl th 这类表格表头保持紧凑（有横向滚动兜着）。 */
@media (max-width:560px){
  .tiny,.sub{font-size:12px}
  .pill{font-size:11.5px;padding:3.5px 9px}
  .kpi .f,.stage .st-f,.stage .st-rt .rt-lb{font-size:11.5px}
  .cls .foot{font-size:12px}
  .tl .t .meta{font-size:12px}
  .rolechip{font-size:11.5px;padding:5px 11px}
  .toast{font-size:13.5px;max-width:86%}
}

/* ---- ④ 表格：窄屏靠横向滚动，但要"看得出能滚" ----
 * 渐变遮罩给右边缘一道提示，用户知道右边还有列；不要用 overflow-x:visible 强塞（会撑破整页）。 */
@media (max-width:560px){
  .lt-wrap,.tpl-wrap{position:relative;border-radius:12px}
  .ltable,.tpl{min-width:0}
  .ltable th,.ltable td{white-space:nowrap}
  .ltable td:first-child{max-width:120px}
  /* 表格外层滚动区补一点内边距，最右列不会贴着屏幕边 */
  .lt-wrap{padding-bottom:2px}
  .tpl{font-size:12px}
  .tpl th,.tpl td{padding:8px 9px}
}

/* ---- ⑤ 分阶段续课率卡片：窄屏 4 列会挤到两行折断，改 2×2 ---- */
@media (max-width:560px){
  .stats4{grid-template-columns:repeat(2,minmax(0,1fr));gap:9px}
  .stats4 b{font-size:17px}
  /* 生命周期四段漏斗：2 列，段名与数字才不打架 */
  #lifeTiles{grid-template-columns:repeat(2,minmax(0,1fr))}
}

/* ---- ⑥ 弹层：给键盘留位（微信/iOS 上键盘弹起会盖住输入框与保存按钮） ----
 * 两种环境的行为不同：iOS 上 vh 不随键盘变化，所以用 visualViewport 的高度在 JS 里兜（见 app.js）；
 * 这里先把"最坏情况"的上限压一压，并保证左右内边距在窄屏收一档。 */
@media (max-width:560px){
  .sheet{max-height:82vh;padding:15px 14px calc(24px + env(safe-area-inset-bottom,0px))}
  .sheet h3{font-size:16px}
  .cfm-mask .cfm-sheet{padding:16px 14px 18px}
  /* 底部弹层的圆角在大屏上好看，手机上收一点更贴边 */
  .sheet{border-radius:18px 18px 0 0}
}

/* ---- ⑦ 弹层里的"多列输入行"（停课区间的 起/止/原因/存/删）：窄屏改两行堆叠 ----
 * 原来是 flex 1:1:1.3 + 两个按钮挤在一行，390px 下日期框只剩 ~70px，日期被截成"2026/1"。 */
@media (max-width:560px){
  .rowline.pauserow{flex-wrap:wrap;gap:7px}
  .rowline.pauserow input[type=date]{flex:1 1 calc(50% - 4px)}
  .rowline.pauserow input[type=text]{flex:1 1 100%}
  .rowline.pauserow .btn.sm{flex:0 0 auto}
}

/* ---- ⑧ 时间线里 float:right 的删除/编辑按钮：窄屏改成不浮动，跟着 meta 行右对齐 ----
 * float 会把按钮顶出内容流，窄屏上容易与长日期串行重叠。 */
@media (max-width:560px){
  .tl .t .meta{display:flex;flex-wrap:wrap;align-items:center;gap:4px 6px}
  .tl .t .meta .btn.sm{float:none !important;margin-left:auto}
  .tl .t .txt{width:100%}
}

/* ---- ⑨ 输入框：手机字号 <16px 时 iOS Safari 会在聚焦瞬间自动放大整页（页面"跳一下"） ----
 * 全站输入统一到 16px 会让桌面太松，所以只在手机宽度生效；这是移动端最容易惹恼用户的一处。 */
@media (max-width:560px){
  input[type=text],input[type=password],input[type=date],input[type=number],input[type=email],input[type=tel],select,textarea{font-size:16px}
  /* 多行文本（学情反馈等）本来就长，16px 太稀疏，保持 15.5 并单独关掉缩放风险（有 no-scale viewport 兜） */
  textarea{font-size:15.5px}
  #login .field input{font-size:16px}
}

/* ---- ⑩ 微信内置浏览器：底部工具栏会盖住固定底栏 + 最后一张卡片的按钮 ----
 * 原来只给 .tabbar 加了 56px 内边距，但内容区（main）的底部留白不足以让"最后一个按钮"浮出工具栏之上，
 * 用户在一线最常做的动作（在学员档案末尾点"记一次课堂"）会被挡住。 */
@media (max-width:560px){
  html.in-wechat .tabbar{padding-bottom:max(58px,env(safe-area-inset-bottom,0px))}
  html.in-wechat main{padding-bottom:calc(178px + env(safe-area-inset-bottom,0px))}
  html.in-wechat .toast{bottom:196px}
  /* 微信里横屏（矮屏）：工具栏更占地方 */
  html.in-wechat .sheet{max-height:74vh}
}

/* ---- ⑪ 矮屏（横屏手机 / 键盘弹起后的可视高度）：内容区底部留白别把内容全顶走 ---- */
@media (max-width:560px) and (max-height:560px){
  main{padding-bottom:120px}
  .tabbar{padding-bottom:max(6px,env(safe-area-inset-bottom,0px))}
}

/* ---- ⑫ 长单词/长链接断行：素材库外链、邮箱、订单号在窄屏会撑破卡片 ---- */
@media (max-width:560px){
  .mlink,.mcard .mq,#phone a{overflow-wrap:anywhere;word-break:break-word}
  .card,.sheet{overflow-wrap:anywhere}
}

/* ---- ⑬ 顶栏：窄屏下标题 + 身份胶囊容易把标题压成两行，让标题可收缩、身份胶囊不压缩 ---- */
@media (max-width:560px){
  .topbar{padding:11px 13px 10px;gap:8px}
  .topbar h1{font-size:15.5px}
  .rolechip{flex:none;max-width:38%;overflow:hidden;text-overflow:ellipsis}
  main{padding-left:13px;padding-right:13px}
}

/* ---- ⑭ 极窄（<360px，老安卓/分屏）：再收一档，保证不横向溢出 ---- */
@media (max-width:359px){
  .kpis,.stages{grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}
  .kpi{padding:11px 12px}
  .kpi .v{font-size:21px}
  main{padding-left:11px;padding-right:11px}
  .tabbar button{font-size:10px}
  .tabbar button .ic{width:19px;height:19px}
  .card{padding:12px}
  .sheet{padding:14px 12px calc(22px + env(safe-area-inset-bottom,0px))}
}

/* ---- ⑮ 触控反馈：手机上 hover 不生效，用 :active 给即时回馈，让"按到了"有感觉 ---- */
@media (hover:none){
  .btn:active{transform:translateY(1px);filter:brightness(.96)}
  .chip:active{filter:brightness(.96)}
  .item:active,.stucard:active{background:var(--soft)}
  .tabbar button:active{background:rgba(38,61,130,.05)}
  .kpi:active,.stage:active{filter:brightness(.99)}
}

/* ---- ⑯ 减少动效偏好（系统级）：旋转/位移全部关掉 ---- */
@media (prefers-reduced-motion:reduce){
  *{animation-duration:.01ms !important;transition-duration:.01ms !important}
}

/* ==========================================================================
   安卓 / 鸿蒙专项适配（2026-10-16 实测后补）
   用户追问「可以适配安卓和鸿蒙吗」。先把平台差异量清楚（见 实测安卓鸿蒙.js / 模拟安卓工具栏.js）：
   · 安卓 Chrome / 鸿蒙 ArkWeb / 小米浏览器 / 微信安卓：dvh、svh、backdrop-filter、visualViewport **全部支持**，
     横溢 0，固定底栏在视口 756~836 动态变化时始终贴底（出屏 0）。**没有需要魔改的地方。**
   · 与 iOS 的差别只有两点：
     ① 安卓/鸿蒙**没有安全区**（env(safe-area-inset-bottom) = 0px），但**浏览器工具栏会动态收放**，
        所以底部留白不能只靠 env —— 要有一个固定的"工具栏高度"余量。
     ② 软键盘走 visualViewport 的比例不同，且视口骤降更多（安卓键盘常占 300px+）。
   ------------------------------------------------------------------------ */

/* ---- ⑰ 底部视口单位兜底：安卓工具栏收放时 100vh 会多算一截 ----
 * 用 dvh（动态视口）让容器高度跟着工具栏走；不支持 dvh 的老 WebView 自动退回 vh，不影响。 */
@supports (height: 100dvh){
  #phone{min-height:100dvh}
}

/* ---- ⑱ 固定底栏的"工具栏余量"：安卓没有安全区，但要给浏览器工具栏留位 ----
 * 策略：底栏自身的内边距取「安全区」与「固定 8px」的较大值 —— iOS 上拿到安全区，
 *      安卓/鸿蒙上拿到 8px 的留白，底栏文字不会被工具栏压住。 */
@media (max-width:560px){
  .tabbar{padding-bottom:max(8px, env(safe-area-inset-bottom, 0px))}
}

/* ---- ⑲ 内容区底部留白：安卓/鸿蒙的可视高度会随工具栏变，留白要够"工具栏 + 底栏"两份 ----
 * iOS 靠 96px + 安全区；安卓/鸿蒙没有安全区，96px 只够底栏自己，工具栏一出来就压住最后一个按钮。
 * 所以非 iOS 环境补一档：识别不了 UA 时按"可能被压"处理，宁多留一点（多出来的空白无副作用）。 */
@media (max-width:560px){
  /* 安卓/鸿蒙/其它：底栏(约 58px) + 浏览器工具栏(约 40px) + 呼吸 20px */
  main{padding-bottom:calc(118px + env(safe-area-inset-bottom, 0px))}
}
/* iOS（有安全区）走原值即可：安全区本身已经把 Home 条算进去了 */
@supports (-webkit-touch-callout: none){
  @media (max-width:560px){
    main{padding-bottom:calc(96px + env(safe-area-inset-bottom, 0px))}
  }
}

/* ---- ⑳ 弹层：安卓软键盘占位更高，底部留白加大 + 明确可滚 ----
 * 实测：视口从 836 降到 620 时弹层内容会溢出（靠内部滚动保证能点到按钮），
 * 所以给底部多留一档，并保证 .sheet 的滚动条行为正常（安卓有一批浏览器默认 overflow 处理不同）。 */
@media (max-width:560px){
  .sheet{
    -webkit-overflow-scrolling:touch;
    overscroll-behavior:contain;     /* 滚到弹层尽头不要把页面带着滚 */
    padding-bottom:calc(30px + env(safe-area-inset-bottom, 0px));
  }
  /* 弹层里的表单底部操作区：给键盘留出"还能看见按钮"的空间（JS 会把聚焦框滚进可视区，
   * 这里只是保证按钮上方有足够空隙，滚动后不会贴边） */
  .sheet > .card:last-child .btnrow{margin-bottom:6px}
}

/* ---- ㉑ 降级：老安卓 WebView 不支持 backdrop-filter 时，毛玻璃变成"半透明 + 更实的白底" ----
 * 不然会是完全透明的一层，底栏文字和内容叠在一起糊成一片。 */
@supports not ((backdrop-filter: blur(4px)) or (-webkit-backdrop-filter: blur(4px))){
  .topbar{background:rgba(255,255,255,.985)}
  .tabbar{background:rgba(255,255,255,.99)}
  .sheet-mask{background:rgba(22,32,58,.5)}
}

/* ---- ㉒ 高刷/低性能安卓机：系统开启"移除动画"时不强制补动画（已被 ⑯ 覆盖），
 *      另把过渡属性限制成像素级廉价属性，避免滚动时掉帧 ---- */
@media (max-width:560px){
  .bar .fill{transition:width .2s ease-out}
  .gcar .gtrack{will-change:transform}
}


/* ============================================================
   ㉓ 学员档案「动作便签 + 高亮」（Request H，2026-10-16）
   手机端实测：班主任「标记续课结果」在第 5.8 屏、「记日常跟进」4.7 屏、「写一条鼓励」5.0 屏；
   老师「记一次课堂」2.4 屏。改法 = 抬头卡里给一枚动作便签，一点跳到对应卡片并闪一下。
   便签用最朴素的按钮外观（不抢抬头卡的注意力），高亮是一层会自己散掉的浅色底。
   ============================================================ */
.cfhops{gap:7px}
.cfhops .btn{flex:1 1 auto;min-width:0}          /* 三枚平铺一行；窄屏自动换行也不塌 */
.cf-hi{
  animation:cfHi 1.5s ease-out;
  border-radius:12px;
}
@keyframes cfHi{
  0%   {box-shadow:0 0 0 3px rgba(43,102,214,.34); background:rgba(43,102,214,.07)}
  60%  {box-shadow:0 0 0 3px rgba(43,102,214,.20); background:rgba(43,102,214,.04)}
  100% {box-shadow:0 0 0 3px rgba(43,102,214,0);   background:transparent}
}
@media (prefers-reduced-motion: reduce){
  .cf-hi{animation:none;box-shadow:0 0 0 3px rgba(43,102,214,.24)}
}

/* ============================================================
   ㉔ 交流区 · 童行思辨团队展示（2026-10-18）
   三组（运营 / 教研教学 / 自媒体）各一排小卡，点开看教资卡大图。
   窄屏两列按 56px 头像 + 两行字算过：卡片最小 96px，360px 宽屏放两列不挤。
   ============================================================ */
.team-grid{
  display:grid;
  grid-template-columns:repeat(auto-fill,minmax(96px,1fr));
  gap:8px;
}
.team-card{
  min-width:0;                      /* 窄屏 flex/grid 子项必须能压缩，否则长名字撑破整页 */
  padding:8px 6px;
  border-radius:14px;
  background:var(--soft,#f4f6fb);
  cursor:pointer;
  transition:transform .12s ease, box-shadow .12s ease;
}
.team-card:active{transform:scale(.97)}
.team-card img{pointer-events:none}
@media (hover:hover){
  .team-card:hover{box-shadow:0 4px 14px rgba(59,76,139,.12)}
}

/* ============================================================
   ㉕ 交流区 · 内部通知（2026-10-18）
   负责人手写的通知进「通知中心」，与系统通知同卡不同区。
   设计取向：新通知靠左侧一个圆点 + 加粗标题区分，不靠整行变色（一整排彩色反而看不出哪条是新的）。
   ============================================================ */
.notice-head{
  display:flex; align-items:center; gap:8px;
  margin:14px 0 6px; padding-top:12px;
  border-top:1px dashed rgba(59,76,139,.14);
}
.notice-head-t{
  flex:1 1 auto; min-width:0;
  font-size:13px; font-weight:600; color:var(--navy);
  display:flex; align-items:center; gap:6px;
}
.notice-row{position:relative; padding-left:16px!important}
.notice-dot{
  position:absolute; left:5px; top:50%; transform:translateY(-50%);
  width:6px; height:6px; border-radius:50%;
  background:var(--pink);
}
.notice-dot.is-read{background:transparent}
.notice-title{
  font-size:13.5px; line-height:1.5; color:var(--text);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.notice-row.is-new .notice-title{font-weight:600}
.notice-sub{
  font-size:11.5px; color:var(--text-3); margin-top:2px;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.notice-sent-toggle{
  margin-top:8px; padding:8px 2px;
  font-size:12.5px; color:var(--navy); cursor:pointer;
  border-top:1px solid rgba(59,76,139,.08);
}
.notice-sent{padding-left:2px!important}
.notice-bar{
  height:4px; border-radius:3px; background:rgba(59,76,139,.10);
  margin:6px 0 4px; overflow:hidden;
}
.notice-bar i{display:block; height:100%; border-radius:3px; background:var(--teal)}
/* 写通知：收件人选择区可以横向滚（一个班几十个名字，不许撑破卡片） */
.notice-pick{
  display:flex; flex-wrap:wrap; gap:6px;
  max-height:168px; overflow-y:auto;
  padding:2px;
}
.notice-pick .chip{
  flex:0 0 auto; max-width:100%;
  min-height:32px;                          /* 点选区要够大，手指点得中 */
  display:inline-flex; align-items:center;
}
.notice-pick .chip span, .notice-pick .chip{overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.notice-ack{
  display:flex; align-items:center; gap:8px;
  font-size:13px; color:var(--text);
  margin:4px 0 14px;
  min-height:40px;                          /* 触控区 ≥40px（项目红线） */
  cursor:pointer;
}
.notice-ack input{width:18px; height:18px; flex:0 0 auto}

/* ============================================================
   ㉖ 班级页 · 班表课次（2026-10-18）
   「班级页看不到课表」—— 一期 12~48 讲，一行一讲，等宽数字对齐。
   设计取向：日期与周几在前（人按日子找），课次号与书在后（查上什么）。
   已上过的整行压暗、不抢眼；「请假 N」用粉色小 pill —— 这是这节课唯一需要人注意的事。
   ★ 行高 ≥40px：整行可点是「改这一讲」的入口，手机上必须点得中（项目红线）。
   ★ 所有格子 min-width:0 + 省略号：书名单行会撑破卡片（移动端横溢红线）。
   ============================================================ */
.ls-row{
  display:flex; align-items:center; gap:8px;
  min-height:40px; padding:6px 2px;
  border-bottom:1px solid rgba(59,76,139,.07);
  font-size:13px; min-width:0;
}
.ls-row:last-of-type{border-bottom:0}
.ls-row.is-past{color:var(--text-3)}
.ls-mk{
  flex:0 0 18px; width:18px; text-align:center;
  font-size:11px; color:var(--text-3);
}
.ls-mk.is-done{color:var(--green-d)}
.ls-mk.is-today{color:#fff; background:var(--navy); border-radius:50%; height:18px; line-height:18px; font-size:10px}
.ls-d{flex:0 0 44px; font-variant-numeric:tabular-nums; font-weight:500}
.ls-w{flex:0 0 28px; font-size:11.5px; color:var(--text-3)}
.ls-no{flex:0 0 auto; max-width:96px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.ls-book{flex:1 1 auto; min-width:0; font-size:12px; color:var(--text-3)}
.ls-leave{flex:0 0 auto; font-size:10px!important; padding:1px 6px!important}
.ls-more{
  margin-top:6px; padding:9px 2px;
  min-height:40px; box-sizing:border-box;
  font-size:12.5px; color:var(--navy); text-align:center; cursor:pointer;
}
@media (max-width:380px){
  /* 极窄屏：周几缩到 24px，书让位（书是次要信息，宁可省略也别换行） */
  .ls-w{flex-basis:24px}
  .ls-no{max-width:80px}
}
