/* ==========================================================================
   快乐学霸AI工作台 · Page level composition
   ========================================================================== */

/* --------------------------------------------------------------------------
   Auth (login / register)
   -------------------------------------------------------------------------- */

.auth {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.06fr);
  min-height: 100vh;
}

.auth-form-col {
  display: flex;
  flex-direction: column;
  padding: var(--gap-8) var(--gap-8) var(--gap-6);
  background: rgba(252, 252, 251, 0.6);
  backdrop-filter: blur(10px);
}

.auth-body {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--gap-8) 0 var(--gap-6);
}

.auth-inner {
  width: 100%;
  max-width: 384px;
}

.auth-head .h1 {
  font-size: 24px;
  letter-spacing: -0.028em;
}

.auth-head .sub {
  margin-top: 7px;
  font-size: 13px;
}

.auth-form {
  display: flex;
  flex-direction: column;
  gap: var(--gap-4);
  margin-top: var(--gap-6);
}

.auth-divider {
  display: flex;
  align-items: center;
  gap: var(--gap-3);
  font-size: var(--fs-micro);
  color: var(--ink-300);
}

.auth-divider::before,
.auth-divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--line);
}

.auth-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap-4);
  flex-wrap: wrap;
  font-size: var(--fs-micro);
  color: var(--ink-400);
}

.auth-note {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 14px;
  border-radius: var(--r-lg);
  border: 1px dashed var(--line-2);
  background: rgba(255, 255, 255, 0.5);
}

.auth-side {
  position: relative;
  overflow: hidden;
  padding: var(--gap-10) var(--gap-10) var(--gap-8);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  background: linear-gradient(170deg, #1a1d23 0%, #12151a 55%, #0f1216 100%);
  color: rgba(255, 255, 255, 0.72);
}

.auth-side::before {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(620px 420px at 82% 6%, rgba(18, 140, 122, 0.22), transparent 62%),
    radial-gradient(520px 380px at 10% 96%, rgba(184, 130, 43, 0.1), transparent 60%);
  pointer-events: none;
}

.auth-side::after {
  content: "";
  position: absolute;
  inset: 0;
  opacity: 0.05;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
  pointer-events: none;
}

.auth-side > * {
  position: relative;
}

.auth-brand {
  display: flex;
  align-items: center;
  gap: 10px;
}

.auth-brand .brand-mark {
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.14);
  box-shadow: none;
  color: #fff;
}

.auth-brand-text {
  display: flex;
  flex-direction: column;
  line-height: 1.25;
}

.auth-brand-name {
  font-size: 14px;
  font-weight: 600;
  color: #fff;
  letter-spacing: -0.01em;
}

.auth-brand-sub {
  font-size: 10.5px;
  letter-spacing: 0.02em;
  line-height: 1.5;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.45);
}

.auth-side-main {
  max-width: 460px;
}

.auth-quote {
  font-family: var(--font-serif);
  font-size: 30px;
  line-height: 1.42;
  letter-spacing: 0.01em;
  color: rgba(255, 255, 255, 0.94);
}

.auth-quote em {
  font-style: normal;
  color: #7fd3c2;
}

.auth-side-desc {
  margin-top: var(--gap-5);
  font-size: 13px;
  line-height: 1.8;
  color: rgba(255, 255, 255, 0.56);
  max-width: 42ch;
}

.auth-preview {
  margin-top: var(--gap-8);
  max-width: 420px;
  border-radius: var(--r-2xl);
  border: 1px solid rgba(255, 255, 255, 0.1);
  background: rgba(255, 255, 255, 0.055);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  box-shadow: 0 24px 60px -30px rgba(0, 0, 0, 0.7);
  padding: var(--gap-5);
}

.auth-preview-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap-3);
  font-size: var(--fs-micro);
  color: rgba(255, 255, 255, 0.45);
}

.auth-preview-value {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-top: 10px;
  font-size: 34px;
  font-weight: 600;
  letter-spacing: -0.035em;
  color: #fff;
  font-variant-numeric: tabular-nums;
}

.auth-preview-value span {
  font-size: 12px;
  letter-spacing: 0;
  color: #7fd3c2;
  font-weight: 500;
}

.auth-side-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap-4);
  flex-wrap: wrap;
  padding-top: var(--gap-6);
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  font-size: var(--fs-micro);
  color: rgba(255, 255, 255, 0.4);
}

.auth-side-foot ul {
  display: flex;
  gap: var(--gap-5);
}

/* Role picker (register) */
.role-pick {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
}

.role-pick label {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding: 12px;
  border-radius: var(--r-lg);
  border: 1px solid var(--line-2);
  background: rgba(255, 255, 255, 0.7);
  cursor: pointer;
  transition: border-color var(--t-fast) var(--ease-out), background var(--t-fast) var(--ease-out),
    box-shadow var(--t-fast) var(--ease-out), transform var(--t-fast) var(--ease-out);
}

.role-pick label:hover {
  border-color: var(--line-3);
  background: var(--white);
}

.role-pick label:active {
  transform: scale(0.99);
}

.role-pick input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.role-pick .role-pick-title {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--ink-800);
}

.role-pick .role-pick-desc {
  font-size: 11px;
  color: var(--ink-400);
  line-height: 1.45;
}

.role-pick .ic {
  color: var(--ink-400);
}

.role-pick input:checked ~ .role-pick-title,
.role-pick label.is-checked .role-pick-title {
  color: var(--brand-700);
}

.role-pick label.is-checked {
  border-color: rgba(13, 114, 100, 0.35);
  background: var(--brand-50);
  box-shadow: 0 0 0 3px rgba(18, 140, 122, 0.08);
}

.role-pick label.is-checked .ic {
  color: var(--brand-600);
}

/* --------------------------------------------------------------------------
   Dashboard
   -------------------------------------------------------------------------- */

.greeting {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--gap-6);
  flex-wrap: wrap;
  margin-bottom: var(--gap-5);
}

.greeting-text {
  font-family: var(--font-serif);
  font-size: 25px;
  line-height: 1.4;
  letter-spacing: 0.005em;
  color: var(--ink-900);
}

.greeting-text .accent {
  color: var(--brand-700);
}

.hero-card {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
  gap: var(--gap-6);
  align-items: center;
}

.ring-wrap {
  position: relative;
  width: 148px;
  height: 148px;
  flex: none;
}

.ring-wrap svg {
  transform: rotate(-90deg);
  overflow: visible;
}

.ring-center {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1px;
}

.ring-center .num-lg {
  font-size: 30px;
}

.ring-center .ring-unit {
  font-size: 11px;
  color: var(--ink-400);
  letter-spacing: 0.06em;
}

.ring-track {
  fill: none;
  stroke: rgba(20, 22, 27, 0.075);
}

.ring-fill {
  fill: none;
  stroke-linecap: round;
  transition: stroke-dashoffset 900ms var(--ease-out);
}

.subject-row {
  display: grid;
  grid-template-columns: 34px minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--gap-4);
  padding: 14px 0;
  border-bottom: 1px solid var(--line);
}

.subject-row:last-child {
  border-bottom: 0;
}

.subject-glyph {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: var(--surface-sunken);
  font-family: var(--font-serif);
  font-size: 15px;
  color: var(--ink-700);
}

.subject-glyph.is-brand {
  background: var(--brand-50);
  border-color: rgba(13, 114, 100, 0.16);
  color: var(--brand-700);
}

/* 学科行右侧的两个同级数据（预估成绩 · 超前学进度）：
   同一个 .num-md 字号、同一条基线，中间只用一条发丝线分开 —— 不加底色、不加阴影
   （用户口径：超前学跟分数一样重要；设计令牌见 DESIGN.md / theme.css） */
.subject-stats {
  display: flex;
  align-items: stretch;
  gap: var(--gap-5);
  text-align: right;
}

.subject-stat + .subject-stat {
  padding-left: var(--gap-5);
  border-left: 1px solid var(--line);
}

.subject-stat-of {
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0;
  color: var(--ink-400);
}

.task-list {
  display: flex;
  flex-direction: column;
}

.task {
  display: flex;
  align-items: flex-start;
  gap: var(--gap-3);
  padding: 11px 0;
  border-bottom: 1px solid var(--line);
  transition: opacity var(--t-base) var(--ease-out);
}

.task:last-child {
  border-bottom: 0;
}

.task.is-done {
  opacity: 0.5;
}

.task-check {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  margin-top: 2px;
  border-radius: 6px;
  border: 1.5px solid var(--line-3);
  color: transparent;
  flex: none;
  transition: background var(--t-fast) var(--ease-out), border-color var(--t-fast) var(--ease-out),
    color var(--t-fast) var(--ease-out), transform var(--t-fast) var(--ease-out);
}

.task-check:hover {
  border-color: var(--brand-500);
}

.task-check:active {
  transform: scale(0.9);
}

.task.is-done .task-check {
  background: var(--brand-600);
  border-color: var(--brand-600);
  color: #fff;
}

.task-title {
  font-size: 12.5px;
  font-weight: 500;
  color: var(--ink-800);
  line-height: 1.5;
}

.task.is-done .task-title {
  text-decoration: line-through;
  text-decoration-color: var(--ink-300);
}

.task-meta {
  margin-top: 2px;
  font-size: 11px;
  color: var(--ink-400);
  display: flex;
  align-items: center;
  gap: 8px;
}

.focus-card {
  background: linear-gradient(168deg, #1a1e23 0%, #14171c 58%, #111419 100%);
  border-color: rgba(255, 255, 255, 0.07);
}

.focus-card::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: radial-gradient(420px 240px at 88% -10%, rgba(18, 140, 122, 0.24), transparent 66%);
  pointer-events: none;
}

.focus-card > * {
  position: relative;
  z-index: 1;
}

.focus-index {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 9px;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.12);
  font-family: var(--font-mono);
  font-size: 11px;
  color: rgba(255, 255, 255, 0.72);
}

/* sparkline / chart shells */

.chart-shell {
  position: relative;
  width: 100%;
}

.chart-shell svg {
  width: 100%;
  height: auto;
  overflow: visible;
}

.chart-axis text {
  font-size: 10.5px;
  fill: var(--ink-400);
}

.chart-grid line {
  stroke: var(--line);
  stroke-width: 1;
}

/* --------------------------------------------------------------------------
   Math · progress rail
   -------------------------------------------------------------------------- */

.rail {
  position: relative;
  padding: var(--gap-5) 0 var(--gap-2);
}

.rail-track {
  position: absolute;
  left: 0;
  right: 0;
  top: 34px;
  height: 2px;
  background: var(--line-2);
  border-radius: 2px;
}

.rail-fill {
  position: absolute;
  left: 0;
  top: 34px;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--brand-600), var(--brand-500));
}

.rail-stops {
  position: relative;
  display: flex;
  justify-content: space-between;
  gap: var(--gap-3);
  min-width: 620px;
}

.rail-stop {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 9px;
  flex: 1;
  min-width: 0;
  cursor: pointer;
  text-align: center;
}

.rail-dot {
  position: relative;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--surface-solid);
  border: 2px solid var(--line-3);
  transition: border-color var(--t-base) var(--ease-out), transform var(--t-base) var(--ease-out),
    background var(--t-base) var(--ease-out);
}

.rail-stop.is-done .rail-dot {
  background: var(--brand-600);
  border-color: var(--brand-600);
}

.rail-stop.is-current .rail-dot {
  border-color: var(--brand-600);
  background: var(--surface-solid);
  box-shadow: 0 0 0 4px rgba(18, 140, 122, 0.14);
  transform: scale(1.06);
}

.rail-stop:hover .rail-dot {
  transform: scale(1.14);
}

.rail-label {
  font-size: 11.5px;
  font-weight: 500;
  color: var(--ink-700);
  white-space: nowrap;
}

.rail-stop.is-pending .rail-label {
  color: var(--ink-400);
  font-weight: 400;
}

.rail-state {
  font-size: 10.5px;
  color: var(--ink-400);
  white-space: nowrap;
}

.rail-stop.is-current .rail-state {
  color: var(--brand-700);
}

/* --------------------------------------------------------------------------
   预估成绩卡（快乐提分页左上那张）
   结构：标题 → 居中主数字 → 占比条 → 分项 → 计数 → 口径脚注，全部靠发丝线分段
   -------------------------------------------------------------------------- */

.est-card {
  --est-pad: 22px;
}

.est-head {
  padding: 20px var(--est-pad) 15px;
  border-bottom: 1px solid var(--line);
}

.est-title {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px 8px;
  font-size: 17px;
  font-weight: 650;
  letter-spacing: -0.022em;
  color: var(--ink-900);
}

.est-title-ic {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  margin-right: 2px;
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: linear-gradient(180deg, #fff, var(--surface-sunken));
  color: var(--ink-700);
  box-shadow: var(--sh-hairline);
}

.est-title-ic .ic {
  width: 16px;
  height: 16px;
}

.est-title-sub {
  font-size: 12.5px;
  font-weight: 400;
  letter-spacing: 0;
  color: var(--ink-400);
}

/* 居中主数字 */

.est-hero {
  padding: 26px var(--est-pad) 20px;
  text-align: center;
}

.est-score-line {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
}

.est-score {
  font-size: 56px;
  font-weight: 650;
  line-height: 1;
  letter-spacing: -0.045em;
  color: var(--ink-900);
  font-variant-numeric: tabular-nums;
}

.est-score-unit {
  font-size: 12.5px;
  color: var(--ink-400);
}

.est-range {
  margin-top: 12px;
  font-size: 12px;
  color: var(--ink-400);
}

.est-range b {
  color: var(--ink-700);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* 掌握情况占比 */

.est-bar {
  padding: 0 var(--est-pad) 18px;
}

.est-stacked {
  height: 8px;
}

.est-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 7px 16px;
  margin-top: 11px;
}

.est-legend > span {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11.5px;
  color: var(--ink-500);
  font-variant-numeric: tabular-nums;
}

.est-dot {
  width: 7px;
  height: 7px;
  border-radius: 2px;
  flex: none;
}

/* 分项 */

.est-rows {
  border-top: 1px solid var(--line);
}

.est-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding: 12px var(--est-pad);
  border-bottom: 1px solid var(--line);
}

.est-row-label {
  font-size: 12.5px;
  color: var(--ink-500);
}

/* 语文：还没练过的维度（不参与合算）——压一档，别跟有数据的行抢注意力 */
.est-row.is-off .est-row-label { color: var(--ink-300); }

.est-row-val {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-900);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.est-unit {
  margin-left: 3px;
  font-size: 11px;
  font-weight: 400;
  color: var(--ink-400);
}

.est-counts {
  padding: 14px var(--est-pad);
  font-size: 11.5px;
  line-height: 1.7;
  color: var(--ink-400);
  font-variant-numeric: tabular-nums;
}

.est-counts b {
  color: var(--ink-700);
  font-weight: 600;
}

.est-foot {
  padding: 13px var(--est-pad) 15px;
  border-top: 1px solid var(--line);
  background: linear-gradient(180deg, rgba(247, 247, 245, 0.55), rgba(247, 247, 245, 0.12));
  font-size: 11.5px;
  line-height: 1.7;
  color: var(--ink-400);
}

.est-foot b {
  color: var(--ink-600);
  font-weight: 600;
}

/* 还没有掌握记录时的蒙层：毛玻璃盖住卡片，中间给「成绩 AI 分析录入」 */

.est-mask {
  position: absolute;
  inset: 0;
  z-index: 4;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 22px;
  border-radius: inherit;
  background: rgba(247, 247, 245, 0.78);
  backdrop-filter: blur(7px) saturate(130%);
  -webkit-backdrop-filter: blur(7px) saturate(130%);
  animation: est-mask-in 240ms var(--ease-out);
}

@keyframes est-mask-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

.est-mask-card {
  max-width: 300px;
  text-align: center;
}

.est-mask-ic {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  margin-bottom: 12px;
  border-radius: var(--r-lg);
  border: 1px solid rgba(13, 114, 100, 0.16);
  background: var(--brand-50);
  color: var(--brand-700);
}

.est-mask-title {
  font-size: 15px;
  font-weight: 650;
  letter-spacing: -0.015em;
  color: var(--ink-900);
}

.est-mask-sub {
  margin-top: 7px;
  font-size: 12px;
  line-height: 1.7;
  color: var(--ink-500);
}

/* --------------------------------------------------------------------------
   AI创造（小游戏 / 思维导图 / 学习卡片 / 动画 / 我的作品）
   -------------------------------------------------------------------------- */

.ai-wrap {
  display: flex;
  flex-direction: column;
  gap: var(--gap-5);
  margin-top: var(--gap-5);
}

/* 生成条 */
.ai-gen-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--gap-4);
}

.ai-gen-lead {
  display: flex;
  align-items: center;
  gap: 13px;
  min-width: 0;
}

.ai-gen-ic {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  flex: none;
  border-radius: var(--r-md);
  border: 1px solid rgba(13, 114, 100, 0.16);
  background: var(--brand-50);
  color: var(--brand-700);
}

.ai-gen-title {
  font-size: 15px;
  font-weight: 650;
  letter-spacing: -0.015em;
  color: var(--ink-900);
}

.ai-gen-actions {
  display: flex;
  align-items: center;
  gap: var(--gap-2);
  flex: 1;
  min-width: 300px;
  max-width: 520px;
}

.ai-gen-actions .input {
  flex: 1;
}

/* 小游戏 */
.ai-quiz-q {
  font-size: 17px;
  font-weight: 600;
  line-height: 1.6;
  letter-spacing: -0.015em;
  color: var(--ink-900);
  margin-bottom: var(--gap-4);
}

.ai-opts {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}

.ai-opt {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 13px 15px;
  text-align: left;
  border-radius: var(--r-lg);
  border: 1px solid var(--line-2);
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.98), rgba(250, 250, 249, 0.94));
  color: var(--ink-800);
  font-size: 13.5px;
  transition: border-color var(--t-fast) var(--ease-out), background var(--t-fast) var(--ease-out),
    color var(--t-fast) var(--ease-out), transform var(--t-fast) var(--ease-out);
}

.ai-opt:not([disabled]):hover {
  border-color: var(--brand-500);
  background: var(--white);
}

.ai-opt:not([disabled]):active {
  transform: scale(0.99);
}

.ai-opt[disabled] {
  cursor: default;
}

.ai-opt-key {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  flex: none;
  border-radius: var(--r-xs);
  border: 1px solid var(--line-2);
  background: var(--surface-sunken);
  color: var(--ink-500);
  font-size: 11px;
  font-weight: 600;
}

.ai-opt.is-right {
  border-color: rgba(13, 114, 100, 0.45);
  background: var(--brand-50);
  color: var(--brand-900);
}

.ai-opt.is-right .ai-opt-key {
  border-color: transparent;
  background: var(--brand-600);
  color: #fff;
}

.ai-opt.is-wrong {
  border-color: rgba(176, 66, 58, 0.4);
  background: rgba(176, 66, 58, 0.05);
  color: var(--danger-600);
}

.ai-opt.is-wrong .ai-opt-key {
  border-color: transparent;
  background: var(--danger-600);
  color: #fff;
}

.ai-explain {
  margin-top: var(--gap-4);
  padding: 13px 15px;
  border-radius: var(--r-lg);
  border: 1px solid var(--line);
  background: var(--surface-sunken);
  font-size: 13px;
  line-height: 1.7;
  color: var(--ink-700);
}

.ai-explain.is-right {
  border-color: rgba(13, 114, 100, 0.24);
  background: var(--brand-50);
}

.ai-result {
  padding: 30px 8px;
  text-align: center;
}

.ai-result-num {
  font-size: 46px;
  font-weight: 650;
  line-height: 1;
  letter-spacing: -0.04em;
  color: var(--ink-900);
  font-variant-numeric: tabular-nums;
}

.ai-result-txt {
  margin-top: 10px;
  font-size: 13.5px;
  color: var(--ink-600);
}

/* 思维导图：三层 */
.ai-tree {
  display: flex;
  align-items: stretch;
  gap: 0;
  overflow-x: auto;
  padding: 18px 4px 22px;
}

.ai-tree-root {
  display: flex;
  align-items: center;
  flex: none;
}

.ai-tree-root > span {
  display: inline-flex;
  align-items: center;
  padding: 14px 18px;
  border-radius: var(--r-lg);
  background: linear-gradient(160deg, #1b1f24, #14161b);
  color: #fff;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: -0.01em;
  white-space: nowrap;
}

.ai-tree-cols {
  display: flex;
  flex: 1;
  gap: 26px;
  padding-left: 26px;
  min-width: 0;
}

.ai-tree-branch {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 10px;
  flex: 1;
  min-width: 148px;
}

.ai-tree-branch::before {
  content: "";
  position: absolute;
  left: -14px;
  top: 50%;
  width: 14px;
  height: 1px;
  background: var(--line-2);
}

.ai-tree-node > span {
  display: block;
  padding: 9px 12px;
  border-radius: var(--r-md);
  border: 1px solid rgba(13, 114, 100, 0.18);
  background: var(--brand-50);
  color: var(--brand-900);
  font-size: 12.5px;
  font-weight: 600;
}

.ai-tree-leaves {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding-left: 14px;
  border-left: 1px solid var(--line-2);
}

.ai-tree-leaf {
  position: relative;
  padding: 7px 10px;
  border-radius: var(--r-sm);
  border: 1px solid var(--line);
  background: var(--surface-solid);
  color: var(--ink-700);
  font-size: 12px;
}

.ai-tree-leaf::before {
  content: "";
  position: absolute;
  left: -14px;
  top: 50%;
  width: 14px;
  height: 1px;
  background: var(--line-2);
}

/* 学习卡片 */
.ai-deck {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--gap-4);
  padding: 14px 0 4px;
}

.ai-flip {
  position: relative;
  width: 100%;
  max-width: 460px;
  height: 240px;
  perspective: 1200px;
  cursor: pointer;
}

.ai-flip-inner {
  position: absolute;
  inset: 0;
  transition: transform 520ms var(--ease-out);
  transform-style: preserve-3d;
}

.ai-flip.is-flipped .ai-flip-inner {
  transform: rotateY(180deg);
}

.ai-flip-face {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 10px;
  padding: 26px 26px;
  border-radius: var(--r-xl);
  border: 1px solid var(--line-2);
  background: var(--surface-solid);
  box-shadow: var(--sh-2), var(--sh-inset-top);
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

.ai-flip-back {
  transform: rotateY(180deg);
  border-color: rgba(13, 114, 100, 0.22);
  background: var(--brand-50);
}

.ai-flip-text {
  font-size: 17px;
  font-weight: 600;
  line-height: 1.6;
  letter-spacing: -0.015em;
  color: var(--ink-900);
  text-align: center;
}

.ai-flip-hint,
.ai-flip-eg {
  font-size: 12px;
  line-height: 1.6;
  color: var(--ink-500);
  text-align: center;
}

.ai-flip-eg {
  color: var(--brand-700);
}

.ai-deck-ctrl {
  display: flex;
  align-items: center;
  gap: var(--gap-2);
}

/* 动画舞台 */
.ai-stage {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 280px;
  padding: 18px;
  border-radius: var(--r-xl);
  border: 1px solid var(--line);
  background:
    radial-gradient(420px 300px at 50% 118%, rgba(18, 140, 122, 0.1), transparent 70%),
    linear-gradient(180deg, rgba(255, 255, 255, 0.72), rgba(247, 247, 245, 0.55));
  overflow: hidden;
}

.ai-visual {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  width: 100%;
}

.ai-svg {
  width: 224px;
  height: 224px;
}

.ai-visual-note {
  font-size: 12.5px;
  color: var(--ink-500);
}

.ai-bar {
  display: flex;
  width: 100%;
  max-width: 460px;
  height: 46px;
  border-radius: var(--r-md);
  overflow: hidden;
  border: 1px solid var(--line);
}

.ai-bar-part {
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-size: 12px;
  font-weight: 600;
  transform-origin: left center;
  animation: ai-bar-grow 520ms var(--ease-out) both;
}

.ai-steps {
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: 100%;
  max-width: 460px;
}

.ai-step {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  padding: 12px 14px;
  border-radius: var(--r-lg);
  border: 1px solid var(--line);
  background: var(--surface-solid);
  animation: ai-step-in 460ms var(--ease-out) both;
}

.ai-step-no {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  flex: none;
  border-radius: 50%;
  background: var(--brand-600);
  color: #fff;
  font-size: 11.5px;
  font-weight: 600;
}

.ai-step-label {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-900);
}

.ai-caption {
  margin-top: var(--gap-4);
  text-align: center;
  font-size: 14px;
  font-weight: 500;
  line-height: 1.7;
  color: var(--ink-800);
}

.ai-anim-ctrl {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--gap-2);
  margin-top: var(--gap-4);
  flex-wrap: wrap;
}

.ai-dots {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-left: var(--gap-2);
}

.ai-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--line-3);
  cursor: pointer;
  transition: background var(--t-fast) var(--ease-out), transform var(--t-fast) var(--ease-out);
}

.ai-dot:hover {
  transform: scale(1.2);
}

.ai-dot.is-on {
  background: var(--brand-600);
}

/* 我的作品 */
.ai-works {
  display: flex;
  flex-direction: column;
}

.ai-work {
  display: flex;
  align-items: center;
  gap: 13px;
  padding: 14px 4px;
  border-bottom: 1px solid var(--line);
}

.ai-work:last-child {
  border-bottom: 0;
}

.ai-work-ic {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  flex: none;
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: var(--surface-sunken);
  color: var(--ink-700);
}

.ai-work-title {
  font-size: 13.5px;
  font-weight: 600;
  color: var(--ink-900);
}

@keyframes ai-pop {
  from { opacity: 0; transform: scale(0.86); }
  to { opacity: 1; transform: scale(1); }
}

@keyframes ai-bar-grow {
  from { transform: scaleX(0); opacity: 0.4; }
  to { transform: scaleX(1); opacity: 1; }
}

@keyframes ai-step-in {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}

/* 陪学计时（学习陪伴页） */
.pet-focus {
  padding: 14px 16px;
  border-radius: var(--r-lg);
  border: 1px solid var(--line);
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.72), rgba(247, 247, 245, 0.5));
}

.pet-focus-time {
  margin: 4px 0 3px;
  font-size: 26px;
  font-weight: 650;
  line-height: 1.1;
  letter-spacing: -0.03em;
  color: var(--ink-900);
  font-variant-numeric: tabular-nums;
}

/* Knowledge point rows · 知识点掌握明细
   设计语言：发丝线分栏、克制留白；品牌色只给「掌握度」，琥珀色只给「需要补练」 */

.kp-card {
  --kp-gutter: 20px;
  --kp-col-w: 118px;
  --kp-col-m: 118px;
  --kp-col-a: 176px;
  position: relative;
  overflow: hidden;
  /* 这张卡的筛选行有多宽，取决于**卡片自己**的宽度（bento 里是 span-8，最宽也只有 ~841px），
     跟窗口宽度没关系 —— 所以组标题的长 / 短、要不要再收紧一档，都按下面的容器查询判断。
     （以前按窗口宽度 1400px 判断，在宽显示器上永远不触发，三科里最宽的语文就会换行。） */
  container: kpcard / inline-size;
}

/* --- 头部：标题 / 年级选择 / 动作 --- */

.kp-top {
  display: flex;
  flex-direction: column;
  gap: 15px;
  padding: 22px var(--kp-gutter) 17px;
  border-bottom: 1px solid var(--line);
}

.kp-top-head {
  display: flex;
  align-items: center;       /* 这一行只有「标题 + 右上角动作按钮」，居中对齐即可 */
  flex-wrap: wrap;           /* 卡片很窄时按钮整组换到下一行，不会把标题挤没 */
  gap: 14px;
  min-width: 0;
}

.kp-top-text {
  min-width: 0;
}

.kp-top-title {
  margin: 0;
  font-size: 17px;
  font-weight: 650;
  letter-spacing: -0.022em;
  color: var(--ink-900);
}

.kp-top-sub {
  margin: 0;                 /* 说明另外一行（标题行让给动作按钮），行距交给 .kp-top 的 gap */
  max-width: 620px;
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--ink-500);
}

/* 说明紧跟在标题行下面（.kp-top 的 gap 是 15px，这里收一点，让它明显属于标题那一块） */
.kp-top-head + .kp-top-sub {
  margin-top: -6px;
}

.kp-top-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
}

.kp-top-tools {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
  margin-left: auto;
}

/* 动作组左侧的分隔竖线（原来那把，跟按钮挨着） */
.kp-top-rule {
  flex: none;
  width: 1px;
  height: 22px;
  background: var(--line-2);
}

.kp-pick {
  display: inline-flex;
  align-items: center;
  gap: 9px;
}

.kp-pick > span {
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--ink-400);
  white-space: nowrap;
}

.kp-pick .select {
  width: auto;
  min-width: 122px;
}

/* --- 过滤条 --- */

.kp-filter {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--gap-3) var(--gap-4);
  padding: 11px var(--kp-gutter);
  border-bottom: 1px solid var(--line);
  background: linear-gradient(180deg, rgba(247, 247, 245, 0.72), rgba(247, 247, 245, 0.3));
}

.kp-seg button {
  gap: 7px;
}

/* 过滤条分两大部分：学校已学 / 学校未学，每部分都是 全部 · 未练习 · 巩固中 · 已掌握。
   用户要求「一行放得下、不要出现滚动条」：所以这里把两组收紧（更小的内边距 / 字距 / 字号），
   并且两组都能按比例收缩（flex: 1 1 auto + min-width: 0），窄屏也不会撑出横向滚动。 */
.kp-filter-row {
  display: flex;
  align-items: center;
  /* 一行放得下就一行；实在放不下（很窄的窗口）就整组折到下一行 —— 永远不出现横向滚动条、也不挤压文字 */
  flex-wrap: wrap;
  /* 铺满整条筛选栏：两组按比例摊开（各自的按钮跟着变宽），右边不留一大块空白
     （以前这个行按内容宽度收敛，行尾就空着一截 —— 用户 2026-10-08 提的） */
  flex: 1 1 auto;
  gap: 8px 10px;
  min-width: 0;
}

.kp-filter-group {
  display: flex;
  align-items: center;
  gap: 5px;
  flex: 1 1 auto;
  min-width: 0;
  justify-content: center;
}

.kp-filter-group + .kp-filter-group {
  padding-left: 10px;
  border-left: 1px solid var(--line);
}

.kp-filter-cap {
  font-size: 10.5px;
  color: var(--ink-400);
  white-space: nowrap;
}

/* 组标题的长 / 短两份：默认显示「学校已学 / 学校未学」，卡片窄了换成「已学 / 未学」（宽度不够时优先保住字号） */
.kp-cap-short {
  display: none;
}

/* 「知识点年级」的下拉框（用户 2026-10-08 要求：不要文案标签、放在两组筛选前面同一行） */
.kp-filter-row .kp-pick {
  flex: none;
  min-width: 0;
  gap: 0;
}

.kp-filter-row .kp-pick .select-sm {
  height: 26px;
  padding: 0 24px 0 8px;
  font-size: 11.5px;
  max-width: 148px;
}

.kp-filter-row .kp-pick + .kp-filter-group {
  padding-left: 12px;
  border-left: 1px solid var(--line);
}

.kp-filter-row .kp-seg {
  padding: 2px;
  gap: 1px;
  flex: 1 1 auto;
  min-width: 0;
}

.kp-filter-row .kp-seg button {
  gap: 3px;
  height: 25px;
  padding: 0 5px;
  font-size: 11px;
  flex: 1 1 auto;
  min-width: 0;
  justify-content: center;
}

.kp-seg button em {
  font-style: normal;
  font-size: 9.5px;
  font-variant-numeric: tabular-nums;
  color: var(--ink-400);
  transition: color var(--t-fast) var(--ease-out);
}

.kp-seg button.is-active em {
  color: var(--brand-600);
}

/* 卡片宽度不够时（≤ 820px）把组标题缩成「已学 / 未学」，让「下拉框 + 两组 × 四档（带计数）」
   仍然排在一行；再窄就靠上面的 flex-wrap 整组折行 —— 计数**一直都在**，不再藏进悬停提示。
   按卡片宽度判断（不是窗口宽度）：卡片最多只有 ~841px，窗口再宽也变不出更多地方。 */
@container kpcard (max-width: 820px) {
  .kp-cap-full {
    display: none;
  }

  .kp-cap-short {
    display: inline;
  }
}

/* 卡片再窄一档（≤ 760px）：两组一起收紧（内边距 / 字距 / 计数），把换行的门槛往下压。
   语文 / 英语的计数是三位数（数学是两位数），不收紧会比数学宽 20~70px。 */
@container kpcard (max-width: 760px) {
  .kp-filter-row {
    gap: 6px 8px;
  }

  .kp-filter-group {
    gap: 4px;
  }

  .kp-filter-group + .kp-filter-group {
    padding-left: 8px;
  }

  .kp-filter-row .kp-seg {
    padding: 1px;
  }

  .kp-filter-row .kp-seg button {
    gap: 2px;
    padding: 0 4px;
  }

  .kp-seg button em {
    font-size: 9px;
  }
}

/* 不认容器查询的老浏览器：退回原来按窗口宽度判断的那一档（行为跟以前一致，只是不见得更宽裕） */
@media (max-width: 1400px) {
  .kp-cap-full {
    display: none;
  }

  .kp-cap-short {
    display: inline;
  }
}

/* --- 列标题与行 --- */

.kp-list {
  padding-bottom: 6px;
}

.kp-cols {
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--kp-col-w) var(--kp-col-m) var(--kp-col-a);
  gap: var(--gap-3);
  align-items: center;
  padding: 12px var(--kp-gutter) 10px calc(var(--kp-gutter) + 34px);
  border-bottom: 1px solid var(--line);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--ink-600);
}

.kp-cols span:last-child {
  /* 「操作」居中：列宽 176px、按钮组基本占满，居中后正好压在按钮对的中线上 */
  text-align: center;
}

.kp-group + .kp-group {
  border-top: 1px solid var(--line);
}

.kp-head {
  display: grid;
  grid-template-columns: 22px minmax(0, 1fr) var(--kp-col-w) var(--kp-col-m) var(--kp-col-a);
  align-items: center;
  gap: var(--gap-3);
  padding: 13px var(--kp-gutter);
  cursor: pointer;
  transition: background var(--t-fast) var(--ease-out);
}

/* 单元行上的「立即练习」按钮（跟知识点行同一个操作列） */
.kp-head .kp-actions {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 6px;
}

.kp-head .kp-actions .btn {
  white-space: nowrap;
}

.kp-head:hover {
  background: rgba(20, 22, 27, 0.024);
}

.kp-head:focus-visible {
  outline: none;
  background: rgba(20, 22, 27, 0.024);
  box-shadow: inset 0 0 0 1px var(--line-2);
}

.kp-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: var(--r-xs);
  color: var(--ink-400);
  transition: transform var(--t-base) var(--ease-out), background var(--t-fast) var(--ease-out),
    color var(--t-fast) var(--ease-out);
}

.kp-group.is-open .kp-toggle {
  transform: rotate(90deg);
  color: var(--brand-600);
}

.kp-head:hover .kp-toggle {
  background: rgba(20, 22, 27, 0.05);
  color: var(--ink-700);
}

.kp-group.is-open .kp-head:hover .kp-toggle {
  color: var(--brand-700);
}

.kp-name {
  display: flex;
  align-items: center;
  gap: 9px;
  min-width: 0;
  font-size: 13.5px;
  font-weight: 600;
  letter-spacing: -0.012em;
  color: var(--ink-900);
}

.kp-name .truncate {
  max-width: 100%;
}

.kp-count {
  text-align: right;
  font-size: 11.5px;
  color: var(--ink-400);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* 展开区：高度动画 + 左侧引导线，表示层级而不是再套一层卡片 */

.kp-body {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--t-slow) var(--ease-out);
}

.kp-group.is-open .kp-body {
  grid-template-rows: 1fr;
}

.kp-body-inner {
  overflow: hidden;
}

/* 语文：单元下面的维度分类（识字 / 背诵 / 作文及课外阅读，里面再分精读 / 泛读）
   —— 一行小标题 + 计数，**默认收起**，点标题展开（跟单元同一套 grid 展开动画）。 */
.kp-cat-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px var(--kp-gutter) 12px calc(var(--kp-gutter) + 34px);
  border-top: 1px solid var(--line);
  margin-top: 6px;
  cursor: pointer;
  border-radius: var(--r-md);
  transition: background var(--t-fast) var(--ease-out);
}

.kp-cat-head:hover {
  background: var(--surface-2);
}

.kp-cat:first-child > .kp-cat-head {
  border-top: 0;
  margin-top: 0;
}

.kp-cat-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  margin-left: -4px;
  color: var(--ink-400);
  transition: transform var(--t-base) var(--ease-out), color var(--t-fast) var(--ease-out);
}

.kp-cat.is-open > .kp-cat-head .kp-cat-toggle {
  transform: rotate(90deg);
  color: var(--ink-700);
}

.kp-cat-body {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--t-slow) var(--ease-out);
}

.kp-cat.is-open > .kp-cat-body {
  grid-template-rows: 1fr;
}

.kp-cat-inner {
  overflow: hidden;
}

.kp-sub-name {
  font-size: 12.5px;
  font-weight: 650;
  letter-spacing: 0.01em;
  color: var(--ink-800);
}

.kp-sub-count {
  font-size: 11.5px;
  color: var(--ink-400);
}

/* 二级分类（作文及课外阅读里的 精读 / 泛读）：缩进一点、字更小 */
.kp-cat .kp-cat > .kp-cat-head {
  padding: 10px var(--kp-gutter) 10px calc(var(--kp-gutter) + 46px);
  border-top: 0;
  margin-top: 0;
}

.kp-cat .kp-cat > .kp-cat-head .kp-sub-name {
  font-size: 11.5px;
  font-weight: 500;
  color: var(--ink-500);
}

.kp-group.is-open .kp-body-inner {
  padding-bottom: 6px;
}

.kp-item {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--kp-col-w) var(--kp-col-m) var(--kp-col-a);
  align-items: center;
  gap: var(--gap-3);
  padding: 10px var(--kp-gutter) 10px calc(var(--kp-gutter) + 34px);
  border-radius: var(--r-md);
  transition: background var(--t-fast) var(--ease-out);
}

.kp-item::before {
  content: "";
  position: absolute;
  left: 31px;
  top: -3px;
  bottom: -3px;
  width: 1px;
  background: linear-gradient(180deg, var(--line-2), var(--line) 72%, transparent);
}

.kp-item:first-child::before {
  top: 50%;
}

.kp-item:last-child::before {
  bottom: 50%;
}

.kp-item:hover {
  background: rgba(20, 22, 27, 0.022);
}

.kp-item-name {
  min-width: 0;
}

.kp-item-line {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.kp-item-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 13px;
  font-weight: 500;
  color: var(--ink-800);
}

.kp-item-meta {
  margin-top: 3px;
  padding-left: 14px;
  font-size: 11.5px;
  color: var(--ink-400);
  font-variant-numeric: tabular-nums;
}

.kp-need {
  display: inline-flex;
  align-items: center;
  flex: none;
  height: 18px;
  padding: 0 8px;
  border-radius: var(--r-full);
  border: 1px solid rgba(184, 130, 43, 0.2);
  background: var(--amber-50);
  color: var(--amber-700);
  font-size: 10.5px;
  font-weight: 500;
  white-space: nowrap;
}

.kp-card .dot {
  width: 7px;
  height: 7px;
}

.kp-card .dot-idle {
  background: transparent;
  box-shadow: inset 0 0 0 1.5px var(--ink-200);
}

.kp-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 6px;
}

.kp-card .kp-actions .btn {
  --btn-h: 28px;
  padding: 0 10px;
  font-size: 12px;
}

.kp-card .btn-practice {
  border-color: rgba(13, 114, 100, 0.16);
  background: var(--brand-50);
  color: var(--brand-700);
  box-shadow: none;
}

.kp-card .btn-practice:hover {
  border-color: rgba(13, 114, 100, 0.26);
  background: var(--brand-100);
  color: var(--brand-900);
  box-shadow: none;
}

.kp-card .kp-actions .btn-ghost {
  color: var(--ink-500);
}

.kp-card .kp-actions .btn-ghost:hover {
  background: rgba(20, 22, 27, 0.06);
  color: var(--ink-900);
}

/* --- 权重（中性灰阶，避免和掌握度抢色） --- */

.wp {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 11.5px;
  color: var(--ink-500);
  font-variant-numeric: tabular-nums;
}

.wp-bar {
  display: inline-flex;
  gap: 2px;
}

.wp-bar i {
  width: 3px;
  height: 12px;
  border-radius: 1.5px;
  background: rgba(20, 22, 27, 0.09);
}

.wp-bar i.on {
  background: var(--ink-600);
}

.wp-bar.is-high i.on {
  background: var(--ink-900);
}

.wp-num {
  color: var(--ink-700);
  font-weight: 500;
}

/* 权重按「高 / 中 / 低」展示（用户 2026-10-08 口径，替代原来的小竖条 + 「权重 N」）：
   做成一枚带**颜色边框**的小按钮（用户要求「要有按钮边框颜色」）——
   高 = 品牌色（矿物青）· 中 = 琥珀 · 低 = 中性灰；具体数值放在悬停提示里 */
.wp-level {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 22px;
  padding: 1px 7px;
  border-radius: var(--r-full);
  border: 1px solid var(--line-2);
  background: var(--surface-sunken);
  font-size: 10.5px;
  line-height: 16px;
  font-weight: 500;
  color: var(--ink-500);
}

.wp-level.is-mid {
  border-color: var(--amber-500);
  background: var(--amber-50);
  color: var(--amber-500);
}

.wp-level.is-high {
  border-color: var(--brand-600);
  background: var(--brand-50);
  color: var(--brand-700);
  font-weight: 600;
}

.wp-default {
  padding: 1px 6px;
  border-radius: var(--r-full);
  border: 1px solid var(--line);
  background: var(--surface-sunken);
  color: var(--ink-400);
  font-size: 10px;
  line-height: 14px;
}

/* --- 掌握度：数字 + 一条细进度条 --- */

.mastery-cell {
  display: flex;
  align-items: center;
  gap: 9px;
  min-width: 0;
}

.kp-card .mastery-cell .num-md {
  min-width: 40px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--ink-900);
  font-variant-numeric: tabular-nums;
}

.mastery-cell .meter {
  display: block;
  flex: none;
  width: 38px;
  height: 4px;
  border-radius: var(--r-full);
  background: rgba(20, 22, 27, 0.075);
  overflow: hidden;
}

.mastery-cell .meter > i {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: var(--brand-500);
  transition: width var(--t-slow) var(--ease-out);
}

.mastery-cell.is-mastered .meter > i {
  background: linear-gradient(90deg, var(--brand-500), var(--brand-700));
}

.mastery-cell.is-learning .meter > i {
  background: linear-gradient(90deg, #c8923a, var(--amber-500));
}

.mastery-cell.is-none .num-md {
  color: var(--ink-300);
  font-weight: 500;
}

.mastery-cell.is-none .meter {
  background: transparent;
  box-shadow: inset 0 0 0 1px var(--line);
}

/* 学校已学、还没练过：按 unpracticed 折算（默认 30%）计入 —— 数字与进度条都用中性灰，
   跟「已掌握（品牌色）/ 巩固中（琥珀）」区分开，不新造颜色 */
.mastery-cell.is-credited .num-md {
  color: var(--ink-500);
}

.mastery-cell.is-credited .meter > i {
  background: var(--line-2);
}

/* --- 空状态 / 脚注 --- */

.kp-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 7px;
  padding: 56px var(--kp-gutter) 60px;
  text-align: center;
}

.kp-empty-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 46px;
  height: 46px;
  margin-bottom: 4px;
  border-radius: var(--r-lg);
  border: 1px solid var(--line);
  background: var(--surface-sunken);
  color: var(--ink-400);
}

.kp-empty-title {
  font-size: 14.5px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--ink-800);
}

.kp-empty-sub {
  font-size: 12.5px;
  color: var(--ink-400);
}

/* 注：明细卡最下面那条「权重来源：人工标定 N 个 · 模型估算 M 个（…）」的样式（.kp-foot）
   随文案一起删掉了（用户 2026-10-08 要求）。后端仍然下发 kpWeightSourceCounts，只是不再展示。 */
}

/* Heatmap */

/* Knowledge-point picker (update school progress) */

.kp-pick-scroll {
  max-height: 320px;
  overflow-y: auto;
  padding: 14px;
  border-radius: var(--r-lg);
  border: 1px solid var(--line);
  background: var(--surface-sunken);
}

.kp-pick-unit + .kp-pick-unit {
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
}

.heatmap {
  display: grid;
  gap: 4px;
  min-width: 560px;
}

.heat-row {
  display: grid;
  grid-template-columns: 92px repeat(6, minmax(0, 1fr));
  gap: 4px;
  align-items: stretch;
}

.heat-row-label {
  display: flex;
  align-items: center;
  font-size: 11.5px;
  color: var(--ink-600);
  padding-right: var(--gap-2);
}

.heat-col-label {
  font-size: 10.5px;
  color: var(--ink-400);
  text-align: center;
  padding-bottom: 7px;
  letter-spacing: 0.02em;
}

.heat-cell {
  position: relative;
  height: 46px;
  border-radius: var(--r-sm);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1px;
  font-size: 11.5px;
  font-variant-numeric: tabular-nums;
  color: var(--ink-700);
  transition: transform var(--t-fast) var(--ease-out), box-shadow var(--t-fast) var(--ease-out);
}

.heat-cell:hover {
  transform: translateY(-1px);
  box-shadow: var(--sh-2);
}

.heat-cell.is-selected {
  box-shadow: 0 0 0 1.5px var(--ink-900), var(--sh-2);
}

.heat-cell .heat-sub {
  font-size: 9.5px;
  color: inherit;
  opacity: 0.78;
  letter-spacing: 0.02em;
}

/* 颜色分档由内联样式给出（U.heatStyle），这里只负责文字与边框 */
.heat-cell[style*="background"] {
  border: 0;
  font-weight: 500;
  box-shadow: none;
}

.heat-cell[style*="background"]:hover {
  box-shadow: var(--sh-2);
}

.heat-cell.is-unpracticed {
  background: #e4e0da;
  color: #6b6a66;
  border: 1px dashed rgba(20, 22, 27, 0.14);
  font-size: 10.5px;
}

.heat-cell.is-unpracticed .heat-sub {
  color: inherit;
  opacity: 0.7;
}

/* 学段覆盖概览：按册一行，避免长文案把布局挤乱 */
.book-row {
  display: grid;
  /* 册名 · 已掌握/总数（短，不截断）· 进度条（占满剩余）· 百分比 */
  grid-template-columns: minmax(92px, auto) auto minmax(56px, 1fr) 50px;
  align-items: center;
  gap: var(--gap-3);
  padding: 7px 10px;
  border-radius: var(--r-sm);
  border: 1px solid var(--line);
  background: var(--surface-solid);
}

.book-row-name {
  font-size: 12.5px;
  font-weight: 500;
  color: var(--ink-800);
  white-space: nowrap;
}

.book-row-counts {
  font-size: 11px;
  color: var(--ink-500);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 已掌握占比的进度条 + 百分比徽标（颜色由 U.masteryStyle 内联给出） */
.book-bar {
  width: 100%;
}

.book-pct {
  justify-content: center;
  font-variant-numeric: tabular-nums;
}

@media (max-width: 640px) {
  .book-row {
    grid-template-columns: minmax(0, 1fr) 52px;
    row-gap: 2px;
  }

  .book-row-counts {
    grid-column: 1 / -1;
  }

  .book-bar {
    grid-column: 1 / 2;
  }
}

.heat-cell.is-blank {
  background: rgba(20, 22, 27, 0.035);
  color: var(--ink-300);
}

.heat-cell.is-blank .heat-sub {
  color: transparent;
}

/* Capability list */

.cap-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(120px, 2fr) 46px;
  align-items: center;
  gap: var(--gap-4);
  padding: 11px 0;
  border-bottom: 1px solid var(--line);
}

.cap-row:last-child {
  border-bottom: 0;
}

/* --------------------------------------------------------------------------
   Math · mind map (left → right)
   -------------------------------------------------------------------------- */

.mm-wrap {
  position: relative;
  border-radius: var(--r-xl);
  border: 1px solid var(--line);
  background: rgba(252, 252, 251, 0.7);
  overflow: hidden;
}

/* 全屏看图：真全屏用 :fullscreen，退化模式用 .is-fullpage 铺满窗口。
   注意背景要用**不透明白底**：--surface 是半透明的，背后透出页面灰底就会显得发灰。 */
.mm-wrap:fullscreen,
.mm-wrap.is-fullscreen,
.mm-wrap.is-fullpage {
  background: var(--surface-solid);
  border-radius: 0;
  display: flex;
  flex-direction: column;
}

.mm-wrap:fullscreen::backdrop {
  background: rgba(20, 22, 27, 0.4);
}

.mm-wrap:fullscreen .mm-canvas,
.mm-wrap.is-fullscreen .mm-canvas,
.mm-wrap.is-fullpage .mm-canvas {
  background-color: var(--surface-solid);
}

/* 全屏时右上角的图例（绿色 = 已掌握） */
.mm-legend-fs {
  position: absolute;
  top: 14px;
  right: 16px;
  z-index: 4;
  display: none;
  background: var(--surface-strong);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 5px 12px;
  box-shadow: var(--sh-2, 0 6px 18px rgba(20, 22, 27, 0.08));
  backdrop-filter: blur(8px);
}

.mm-wrap:fullscreen .mm-legend-fs,
.mm-wrap.is-fullscreen .mm-legend-fs,
.mm-wrap.is-fullpage .mm-legend-fs {
  display: flex;
  align-items: center;
  gap: 12px;
}

.mm-wrap:fullscreen .mm-canvas,
.mm-wrap.is-fullscreen .mm-canvas {
  max-height: none;
  flex: 1;
  height: 100%;
}

.mm-wrap.is-fullpage {
  position: fixed;
  inset: 0;
  z-index: 60;
  border-radius: 0;
}

.mm-wrap.is-fullpage .mm-canvas {
  max-height: none;
  flex: 1;
}

.mm-wrap:fullscreen .mm-toolbar,
.mm-wrap.is-fullscreen .mm-toolbar,
.mm-wrap.is-fullpage .mm-toolbar {
  bottom: 18px;
  right: 18px;
}

.mm-canvas {
  position: relative;
  overflow: auto;
  max-height: 688px;
  background-image: radial-gradient(rgba(20, 22, 27, 0.055) 1px, transparent 1px);
  background-size: 24px 24px;
  background-position: 12px 12px;
}

.mm-stage {
  position: relative;
  transform-origin: 0 0;
  transition: transform var(--t-base) var(--ease-out);
}

.mm-links {
  position: absolute;
  inset: 0;
  pointer-events: none;
  overflow: visible;
}

.mm-links path {
  fill: none;
  stroke: rgba(20, 22, 27, 0.16);
  stroke-width: 1.2;
  transition: stroke var(--t-base) var(--ease-out), stroke-width var(--t-base) var(--ease-out);
}

.mm-links path.is-active {
  stroke: var(--brand-500);
  stroke-width: 1.6;
}

.mm-node {
  position: absolute;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  justify-content: center;
  gap: 4px;
  padding: 8px 11px;
  border-radius: var(--r-md);
  border: 1px solid var(--line-2);
  background: var(--surface-solid);
  box-shadow: var(--sh-1);
  text-align: left;
  transition: border-color var(--t-fast) var(--ease-out), box-shadow var(--t-fast) var(--ease-out),
    transform var(--t-fast) var(--ease-out), background var(--t-fast) var(--ease-out);
}

.mm-node:hover {
  border-color: var(--line-3);
  box-shadow: var(--sh-2);
  transform: translateY(-1px);
}

.mm-node:active {
  transform: translateY(0) scale(0.99);
}

.mm-node.is-selected {
  border-color: var(--brand-500);
  box-shadow: 0 0 0 3px rgba(18, 140, 122, 0.12), var(--sh-2);
}

.mm-node.is-on-path {
  border-color: rgba(13, 114, 100, 0.4);
}

.mm-node-main {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.mm-node-label {
  font-size: 12.5px;
  font-weight: 500;
  color: var(--ink-800);
  line-height: 1.4;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex: 1;
  min-width: 0;
}

.mm-node-sub {
  font-size: 10.5px;
  color: var(--ink-400);
  margin-top: 1px;
}

/* 「按分类」视图里挂在节点上的年级角标（如「一年级上」） */
.mm-grade {
  flex: none;
  padding: 1px 6px;
  border-radius: 999px;
  border: 1px solid var(--line-2);
  background: var(--surface-sunken);
  color: var(--ink-500);
  font-size: 10px;
  line-height: 15px;
  white-space: nowrap;
}

/* 非叶子节点按「已掌握占比」上色（色阶与热力图相同），里面的字与徽标跟着用前景色 */
.mm-node.is-heat .mm-node-label,
.mm-node.is-heat .mm-node-sub,
.mm-node.is-heat .mm-glyph {
  color: inherit;
}

/* 深色底（已掌握占比 100% / ≥60%）上的册简称小牌：换成半透明白底 + 白字，别用浅色牌配白字 */
.mm-node.is-heat.is-band-full .mm-glyph,
.mm-node.is-heat.is-band-high .mm-glyph,
.mm-node.is-heat.is-band-full .mm-weight,
.mm-node.is-heat.is-band-high .mm-weight,
.mm-node.is-heat.is-band-full .mm-grade,
.mm-node.is-heat.is-band-high .mm-grade {
  background: rgba(255, 255, 255, 0.26);
  border-color: rgba(255, 255, 255, 0.5);
  color: #ffffff;
}

/* 浅色底（1–59% / 0%）上的小牌：白一点的底 + 深字，保证对比度 */
.mm-node.is-heat.is-band-low .mm-glyph,
.mm-node.is-heat.is-band-none .mm-glyph,
.mm-node.is-heat.is-band-low .mm-weight,
.mm-node.is-heat.is-band-none .mm-weight,
.mm-node.is-heat.is-band-low .mm-grade,
.mm-node.is-heat.is-band-none .mm-grade {
  background: rgba(255, 255, 255, 0.78);
  border-color: rgba(20, 22, 27, 0.14);
  color: var(--ink-800);
}

.mm-node.is-heat .mm-weight,
.mm-node.is-heat .mm-grade {
  background: rgba(255, 255, 255, 0.28);
  border-color: rgba(255, 255, 255, 0.4);
  color: inherit;
}

.mm-node.is-heat .mm-toggle {
  opacity: 0.75;
}

/* 「学校已学」筛选下：整条都还没学到的知识点 / 节点淡出显示 */
.mm-node.is-out-scope {
  opacity: 0.45;
}

.mm-node.is-out-scope .mm-node-label {
  color: var(--ink-500);
}

/* 图例里的「全部」与数量 */
.mm-dot.m-all {
  background: #3f4f4b;
}

.legend-num {
  margin-left: 5px;
  padding: 0 6px;
  border-radius: 999px;
  background: var(--surface-sunken);
  border: 1px solid var(--line-2);
  color: var(--ink-600, #4b5a56);
  font-size: 10.5px;
  line-height: 16px;
  font-variant-numeric: tabular-nums;
}

/* 知识点权重 / 单元权重合计 */
.mm-weight {
  flex: none;
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  gap: 3px;
  padding: 1px 6px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--surface-sunken);
  color: var(--ink-500);
  font-size: 10px;
  line-height: 15px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.mm-weight.is-high {
  border-color: rgba(13, 114, 100, 0.22);
  background: var(--brand-50);
  color: var(--brand-700);
}

.mm-weight i {
  font-style: normal;
  color: var(--ink-300);
}

.mm-weight-sum {
  color: var(--ink-400);
}

.mm-node-root {
  background: linear-gradient(165deg, #22262c, #14161b);
  border-color: #0f1114;
  box-shadow: var(--sh-3);
}

.mm-node-root .mm-node-label {
  color: #fff;
}

.mm-node-root .mm-node-sub {
  color: rgba(255, 255, 255, 0.5);
}

.mm-node-root .mm-node-label {
  font-size: 13.5px;
  letter-spacing: -0.01em;
}

.mm-node-l1 {
  background: var(--surface-solid);
  border-color: var(--line-2);
}

.mm-node-l1 .mm-node-label {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-900);
}

.mm-node-l2 {
  background: rgba(255, 255, 255, 0.82);
}

.mm-node-l3 {
  background: var(--surface-sunken);
  border-color: var(--line);
  box-shadow: none;
}

.mm-node-l3 .mm-node-label {
  font-size: 12px;
  font-weight: 400;
  color: var(--ink-600);
}

.mm-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex: none;
  background: var(--ink-200);
}

.mm-dot.m-strong { background: var(--brand-500); }
.mm-dot.m-mid { background: var(--amber-500); }
.mm-dot.m-weak { background: var(--danger-600); }
.mm-dot.m-idle { background: var(--ink-200); }

.mm-glyph {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* 「一上 / 四下」是两个字的书册简称：固定 24px 会把字挤出底色，
     改成最小宽度 + 内边距自适应，单字仍然是一个 24px 的小方牌 */
  min-width: 24px;
  height: 24px;
  padding: 0 5px;
  border-radius: var(--r-sm);
  background: var(--surface-sunken);
  border: 1px solid var(--line);
  font-family: var(--font-serif);
  font-size: 11.5px;
  line-height: 1;
  letter-spacing: 0;
  white-space: nowrap;
  color: var(--ink-600);
  flex: none;
}

.mm-node-root .mm-glyph {
  background: rgba(255, 255, 255, 0.1);
  border-color: rgba(255, 255, 255, 0.14);
  color: #fff;
}

.mm-node-l1 .mm-glyph {
  background: var(--brand-50);
  border-color: rgba(13, 114, 100, 0.16);
  color: var(--brand-700);
}

.mm-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border-radius: 5px;
  border: 1px solid var(--line-2);
  background: var(--surface-solid);
  color: var(--ink-400);
  flex: none;
  transition: background var(--t-fast) var(--ease-out), color var(--t-fast) var(--ease-out),
    transform var(--t-base) var(--ease-out);
}

.mm-node:hover .mm-toggle {
  color: var(--ink-800);
  background: var(--surface-sunken);
}

.mm-node.is-expanded .mm-toggle {
  transform: rotate(90deg);
}

.mm-node-root .mm-toggle {
  background: rgba(255, 255, 255, 0.12);
  border-color: rgba(255, 255, 255, 0.16);
  color: rgba(255, 255, 255, 0.8);
}

.mm-toolbar {
  position: absolute;
  right: 12px;
  bottom: 12px;
  z-index: 3;
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 4px;
  border-radius: var(--r-md);
  border: 1px solid var(--line-2);
  background: rgba(255, 255, 255, 0.9);
  backdrop-filter: blur(12px);
  box-shadow: var(--sh-2);
}

.mm-toolbar button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: var(--r-sm);
  color: var(--ink-500);
  transition: background var(--t-fast) var(--ease-out), color var(--t-fast) var(--ease-out);
}

.mm-toolbar button:hover {
  background: rgba(20, 22, 27, 0.06);
  color: var(--ink-900);
}

.mm-hint {
  position: absolute;
  left: 12px;
  bottom: 14px;
  z-index: 3;
  font-size: var(--fs-micro);
  color: var(--ink-400);
  background: rgba(252, 252, 251, 0.86);
  backdrop-filter: blur(8px);
  padding: 3px 8px;
  border-radius: var(--r-full);
  border: 1px solid var(--line);
  pointer-events: none;
}

.mm-legend {
  display: flex;
  align-items: center;
  gap: var(--gap-5);
  flex-wrap: wrap;
  padding: 11px var(--gap-5);
  border-top: 1px solid var(--line);
  background: rgba(247, 247, 245, 0.66);
}

/* --------------------------------------------------------------------------
   Permissions
   -------------------------------------------------------------------------- */

.role-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--gap-3);
  padding: var(--gap-4);
  border-radius: var(--r-lg);
  border: 1px solid var(--line);
  background: rgba(255, 255, 255, 0.62);
  text-align: left;
  transition: border-color var(--t-fast) var(--ease-out), background var(--t-fast) var(--ease-out),
    box-shadow var(--t-fast) var(--ease-out), transform var(--t-fast) var(--ease-out);
}

.role-card:hover {
  background: var(--white);
  border-color: var(--line-2);
  transform: translateY(-1px);
  box-shadow: var(--sh-2);
}

.role-card.is-active {
  border-color: rgba(13, 114, 100, 0.34);
  background: var(--white);
  box-shadow: 0 0 0 3px rgba(18, 140, 122, 0.09), var(--sh-2);
}

.perm-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) repeat(4, 88px);
  align-items: center;
  gap: var(--gap-3);
  padding: 12px var(--gap-3);
  border-bottom: 1px solid var(--line);
}

.perm-row:last-child {
  border-bottom: 0;
}

.perm-row:hover {
  background: rgba(20, 22, 27, 0.02);
}

.perm-head {
  font-size: var(--fs-micro);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-400);
  padding: 0 var(--gap-3) 10px;
  border-bottom: 1px solid var(--line);
}

.perm-group-label {
  grid-column: 1 / -1;
  padding: 14px var(--gap-3) 6px;
  font-size: 10.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-300);
}

.perm-cell {
  display: flex;
  justify-content: center;
}

.save-bar {
  position: sticky;
  bottom: var(--gap-4);
  z-index: 30;
  display: flex;
  align-items: center;
  gap: var(--gap-4);
  margin-top: var(--gap-5);
  padding: 11px 11px 11px var(--gap-5);
  border-radius: var(--r-xl);
  border: 1px solid rgba(255, 255, 255, 0.08);
  background: rgba(19, 21, 25, 0.94);
  backdrop-filter: blur(14px);
  color: rgba(255, 255, 255, 0.82);
  box-shadow: var(--sh-4);
  animation: page-in 200ms var(--ease-out);
}

.save-bar .muted {
  color: rgba(255, 255, 255, 0.55);
}

.nav-preview {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 8px;
  border-radius: var(--r-lg);
  border: 1px solid var(--line);
  background: var(--surface-sunken);
}

.nav-preview-item {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 7px 9px;
  border-radius: var(--r-sm);
  font-size: 12px;
  color: var(--ink-500);
  transition: opacity var(--t-base) var(--ease-out);
}

.nav-preview-item.is-on {
  background: rgba(255, 255, 255, 0.9);
  color: var(--ink-800);
  box-shadow: var(--sh-1);
}

.nav-preview-item.is-off {
  opacity: 0.42;
  text-decoration: line-through;
  text-decoration-color: var(--ink-200);
}

/* --------------------------------------------------------------------------
   Users
   -------------------------------------------------------------------------- */

.toolbar {
  display: flex;
  align-items: center;
  gap: var(--gap-3);
  flex-wrap: wrap;
}

.toolbar-right {
  display: flex;
  align-items: center;
  gap: var(--gap-2);
  margin-left: auto;
}

.bulk-bar {
  display: flex;
  align-items: center;
  gap: var(--gap-3);
  padding: 9px var(--gap-4);
  border-radius: var(--r-lg);
  border: 1px solid rgba(13, 114, 100, 0.2);
  background: var(--brand-50);
  animation: page-in 180ms var(--ease-out);
}

.pager {
  display: flex;
  align-items: center;
  gap: var(--gap-3);
  padding: 12px var(--gap-5);
  border-top: 1px solid var(--line);
  flex-wrap: wrap;
}

.pager-pages {
  display: flex;
  align-items: center;
  gap: 2px;
  margin-left: auto;
}

.page-num {
  min-width: 28px;
  height: 28px;
  padding: 0 7px;
  border-radius: var(--r-sm);
  font-size: 12.5px;
  color: var(--ink-500);
  font-variant-numeric: tabular-nums;
  transition: background var(--t-fast) var(--ease-out), color var(--t-fast) var(--ease-out);
}

.page-num:hover {
  background: rgba(20, 22, 27, 0.05);
  color: var(--ink-900);
}

.page-num.is-active {
  background: var(--ink-900);
  color: #fff;
}

.user-cell {
  display: flex;
  align-items: center;
  gap: 11px;
  min-width: 0;
}

.user-name {
  font-size: 13px;
  font-weight: 500;
  color: var(--ink-900);
  line-height: 1.35;
}

.user-sub {
  font-size: 11px;
  color: var(--ink-400);
}

/* --------------------------------------------------------------------------
   Pet / guide
   -------------------------------------------------------------------------- */

.pet-stage {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 250px;
  border-radius: var(--r-xl);
  border: 1px solid var(--line);
  background:
    radial-gradient(420px 300px at 50% 118%, rgba(18, 140, 122, 0.12), transparent 70%),
    linear-gradient(180deg, rgba(255, 255, 255, 0.72), rgba(247, 247, 245, 0.6));
  overflow: hidden;
}

.pet-stage::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: radial-gradient(rgba(20, 22, 27, 0.05) 1px, transparent 1px);
  background-size: 26px 26px;
  mask-image: radial-gradient(70% 62% at 50% 46%, #000 20%, transparent 78%);
  -webkit-mask-image: radial-gradient(70% 62% at 50% 46%, #000 20%, transparent 78%);
}

.pet-stage > * {
  position: relative;
}

.pet-figure {
  animation: pet-float 5.5s var(--ease-in-out) infinite;
}

/* 小萌宠换成用户给的 3D 小兔子：
   · 大图是视频（动态），素材是纯白背景 —— 用 multiply 把白色融进页面的浅色底，
     兔子就像直接长在卡片上，不会出现一个白方块；
   · 底部再淡出一点，避免出现矩形的硬边。 */
.pet-video {
  display: block;
  width: 100%;
  max-width: 220px;
  max-height: 360px;
  margin: 0 auto;
  mix-blend-mode: multiply;
  /* 只淡掉最下面一点点（兔子的脚在底部附近，别裁到它） */
  -webkit-mask-image: linear-gradient(180deg, #000 0 96%, rgba(0, 0, 0, 0) 100%);
  mask-image: linear-gradient(180deg, #000 0 96%, rgba(0, 0, 0, 0) 100%);
}

/* 小头像（聊天气泡、深色卡片、启动器）：抠掉白底的透明 PNG + 圆形裁切，
   图里已经是「整只脑袋（含耳朵）居中留白」，所以圆里不会切到耳朵或下巴；
   底下垫一层很淡的暖色，深色卡片上也能看清是个头像。 */
.pet-head {
  display: block;
  flex: none;
  object-fit: contain;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 32%, #ffffff, #f7f2ea);
  box-shadow: inset 0 0 0 1px rgba(20, 22, 27, 0.06);
  filter: drop-shadow(0 2px 5px rgba(20, 22, 27, 0.14));
}

.pet-still {
  display: block;
  object-fit: contain;
}

@keyframes pet-float {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-7px); }
}

.pet-eye {
  transform-origin: center;
  animation: pet-blink 6.2s infinite;
}

@keyframes pet-blink {
  0%, 92%, 100% { transform: scaleY(1); }
  95% { transform: scaleY(0.08); }
}

.pet-shadow {
  animation: pet-shadow 5.5s var(--ease-in-out) infinite;
}

@keyframes pet-shadow {
  0%, 100% { transform: scale(1); opacity: 0.3; }
  50% { transform: scale(0.92); opacity: 0.22; }
}

.speech {
  position: relative;
  padding: 14px var(--gap-5);
  border-radius: var(--r-xl);
  border: 1px solid var(--line);
  background: rgba(255, 255, 255, 0.86);
  backdrop-filter: blur(12px);
  box-shadow: var(--sh-2);
  font-size: 13px;
  line-height: 1.7;
  color: var(--ink-700);
}

.speech::before {
  content: "";
  position: absolute;
  left: -5px;
  top: 22px;
  width: 9px;
  height: 9px;
  background: inherit;
  border-left: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  transform: rotate(45deg);
}

.chat {
  display: flex;
  flex-direction: column;
  gap: var(--gap-4);
  padding: var(--gap-5) 0;
}

.chat-row {
  display: flex;
  gap: 11px;
  align-items: flex-start;
}

.chat-row.is-me {
  flex-direction: row-reverse;
}

.chat-bubble {
  max-width: 76%;
  padding: 10px 14px;
  border-radius: var(--r-lg);
  border: 1px solid var(--line);
  background: rgba(255, 255, 255, 0.86);
  font-size: 12.5px;
  line-height: 1.7;
  color: var(--ink-700);
}

.chat-row.is-me .chat-bubble {
  background: var(--ink-900);
  border-color: var(--ink-900);
  color: rgba(255, 255, 255, 0.92);
}

.chat-time {
  margin-top: 5px;
  font-size: 10.5px;
  color: var(--ink-300);
}

.composer {
  display: flex;
  align-items: flex-end;
  gap: var(--gap-3);
  padding: 10px;
  border-radius: var(--r-xl);
  border: 1px solid var(--line-2);
  background: rgba(255, 255, 255, 0.8);
  box-shadow: var(--sh-hairline);
  transition: border-color var(--t-fast) var(--ease-out), box-shadow var(--t-fast) var(--ease-out);
}

.composer:focus-within {
  border-color: var(--brand-500);
  box-shadow: 0 0 0 3px rgba(18, 140, 122, 0.12);
}

.composer textarea {
  flex: 1;
  border: 0;
  background: none;
  resize: none;
  min-height: 24px;
  max-height: 120px;
  font-size: 13px;
  outline: none;
  line-height: 1.6;
}

.chip-row {
  display: flex;
  gap: var(--gap-2);
  flex-wrap: wrap;
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 28px;
  padding: 0 11px;
  border-radius: var(--r-full);
  border: 1px solid var(--line-2);
  background: rgba(255, 255, 255, 0.7);
  font-size: 12px;
  color: var(--ink-600);
  transition: background var(--t-fast) var(--ease-out), border-color var(--t-fast) var(--ease-out),
    color var(--t-fast) var(--ease-out), transform var(--t-fast) var(--ease-out);
}

.chip:hover {
  background: var(--white);
  border-color: var(--line-3);
  color: var(--ink-900);
}

.chip:active {
  transform: scale(0.98);
}

.chip.is-active {
  background: var(--ink-900);
  border-color: var(--ink-900);
  color: #fff;
}

/* Floating launcher */

.launcher {
  position: fixed;
  right: var(--gap-5);
  bottom: var(--gap-5);
  z-index: 45;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--gap-3);
}

.launcher-btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  height: 46px;
  padding: 0 16px 0 12px;
  border-radius: var(--r-full);
  border: 1px solid rgba(255, 255, 255, 0.1);
  background: linear-gradient(165deg, #22262c, #14161b);
  color: rgba(255, 255, 255, 0.92);
  font-size: 12.5px;
  font-weight: 500;
  box-shadow: var(--sh-4);
  transition: transform var(--t-base) var(--ease-out), box-shadow var(--t-base) var(--ease-out);
}

.launcher-btn:hover {
  transform: translateY(-2px);
}

.launcher-btn:active {
  transform: translateY(0) scale(0.985);
}

.launcher-panel {
  width: 340px;
  max-width: calc(100vw - 32px);
  border-radius: var(--r-2xl);
  border: 1px solid var(--line-2);
  background: rgba(255, 255, 255, 0.94);
  backdrop-filter: blur(20px) saturate(150%);
  box-shadow: var(--sh-4);
  overflow: hidden;
  animation: menu-in 200ms var(--ease-out);
}

.launcher-panel-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  border-bottom: 1px solid var(--line);
  background: linear-gradient(180deg, rgba(247, 247, 245, 0.9), rgba(255, 255, 255, 0.6));
}

.launcher-panel-body {
  padding: 14px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  max-height: 380px;
  overflow-y: auto;
}

.launcher-msg {
  font-size: 12.5px;
  line-height: 1.7;
  color: var(--ink-700);
}

/* 右下角浮动对话框：家长 / 学生主要在这里和萌宠交互 */
.launcher-chat {
  display: flex;
  flex-direction: column;
  gap: 8px;
  font-size: 12.5px;
  line-height: 1.65;
  color: var(--ink-700);
}

.launcher-turn {
  align-self: flex-start;
  max-width: 92%;
  padding: 9px 12px;
  border-radius: var(--r-lg);
  border: 1px solid var(--line);
  background: var(--surface-solid);
  animation: ai-step-in 220ms var(--ease-out) both;
}

.launcher-turn.is-me {
  align-self: flex-end;
  border-color: transparent;
  background: var(--brand-50);
  color: var(--brand-900);
}

.launcher-turn.is-typing {
  border-style: dashed;
  color: var(--ink-400);
}

.launcher-composer {
  display: flex;
  align-items: center;
  gap: 8px;
}

.launcher-composer .input {
  height: 32px;
  font-size: 12.5px;
}

.launcher-foot {
  padding: 10px 14px 12px;
  border-top: 1px solid var(--line);
}

/* --------------------------------------------------------------------------
   Command palette
   -------------------------------------------------------------------------- */

.palette {
  width: 100%;
  max-width: 560px;
  align-self: flex-start;
  margin-top: 12vh;
  border-radius: var(--r-2xl);
  border: 1px solid var(--line-2);
  background: rgba(255, 255, 255, 0.96);
  backdrop-filter: blur(24px);
  box-shadow: var(--sh-4);
  overflow: hidden;
  animation: modal-in 200ms var(--ease-out);
}

.palette-input {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--line);
}

.palette-input input {
  flex: 1;
  border: 0;
  background: none;
  outline: none;
  font-size: 14px;
}

.palette-list {
  max-height: 320px;
  overflow-y: auto;
  padding: 6px;
}

.palette-item {
  display: flex;
  align-items: center;
  gap: 11px;
  width: 100%;
  padding: 9px 11px;
  border-radius: var(--r-md);
  font-size: 13px;
  color: var(--ink-700);
  text-align: left;
}

.palette-item .ic {
  color: var(--ink-400);
}

.palette-item.is-active {
  background: rgba(20, 22, 27, 0.055);
  color: var(--ink-900);
}

.palette-item.is-active .ic {
  color: var(--ink-700);
}

.palette-group {
  padding: 9px 11px 4px;
  font-size: 10.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-300);
}

.palette-foot {
  display: flex;
  align-items: center;
  gap: var(--gap-4);
  padding: 9px 14px;
  border-top: 1px solid var(--line);
  background: var(--surface-sunken);
  font-size: var(--fs-micro);
  color: var(--ink-400);
}

/* --------------------------------------------------------------------------
   Responsive tuning for page composition
   -------------------------------------------------------------------------- */

@media (max-width: 1080px) {
  .auth {
    grid-template-columns: minmax(0, 1fr);
  }

  .auth-side {
    order: -1;
    padding: var(--gap-8) var(--gap-6) var(--gap-6);
    min-height: auto;
  }

  .auth-preview,
  .auth-side-desc {
    display: none;
  }

  .auth-quote {
    font-size: 22px;
    margin-top: var(--gap-5);
  }

  .auth-side-foot {
    margin-top: var(--gap-5);
  }

  .auth-form-col {
    padding: var(--gap-6) var(--gap-6) var(--gap-5);
  }

  .hero-card {
    grid-template-columns: minmax(0, 1fr);
  }
}

@media (max-width: 900px) {
  .launcher {
    bottom: 78px;
  }
}

@media (max-width: 1180px) {
  .kp-cols {
    display: none;
  }

  .kp-head {
    grid-template-columns: 22px minmax(0, 1fr) auto auto auto;
  }

  .kp-item {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    row-gap: 10px;
    padding-left: 18px;
  }

  .kp-item-name {
    grid-column: 1 / -1;
  }

  .kp-actions {
    grid-column: 1 / -1;
    justify-content: flex-start;
  }

  .kp-item::before {
    display: none;
  }

  .perm-row {
    grid-template-columns: minmax(0, 1fr) repeat(4, 52px);
  }

  .cap-row {
    grid-template-columns: minmax(0, 1fr) 44px;
    row-gap: 6px;
  }

  .cap-row .progress {
    grid-column: 1 / -1;
  }
}

@media (max-width: 560px) {
  .auth-quote {
    font-size: 19px;
  }

  .role-pick {
    grid-template-columns: minmax(0, 1fr);
  }

  .ring-wrap {
    width: 124px;
    height: 124px;
  }

  .greeting-text {
    font-size: 21px;
  }

  .kp-item {
    grid-template-columns: minmax(0, 1fr);
  }

  .kp-head {
    grid-template-columns: 22px minmax(0, 1fr);
    row-gap: 8px;
  }

  .perm-row {
    grid-template-columns: minmax(0, 1fr) repeat(2, 46px);
  }

  .perm-row .perm-cell:nth-of-type(n + 3) {
    display: none;
  }

  .launcher-panel {
    width: calc(100vw - 32px);
  }
}

/* Single-select row used by 「更新学校学习进度」 */
.pick-row {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px 10px;
  margin-top: 6px;
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: rgba(255, 255, 255, 0.7);
  font-size: 12.5px;
  color: var(--ink-700);
  text-align: left;
  transition: border-color var(--t-fast) var(--ease-out), background var(--t-fast) var(--ease-out),
    color var(--t-fast) var(--ease-out);
}

.pick-row:hover {
  border-color: var(--line-3);
  background: var(--white);
  color: var(--ink-900);
}

.pick-row .pick-dot {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 1.5px solid var(--line-3);
  background: var(--white);
  flex: none;
  transition: border-color var(--t-fast) var(--ease-out), box-shadow var(--t-fast) var(--ease-out);
}

.pick-row.is-active {
  border-color: var(--brand-500);
  background: var(--brand-50);
  color: var(--brand-700);
  font-weight: 500;
}

.pick-row.is-active .pick-dot {
  border-color: var(--brand-600);
  box-shadow: inset 0 0 0 3px var(--brand-600);
}

/* 导入学习记录：图片上传与识别 */
.upload-zone {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 30px 20px;
  border-radius: var(--r-xl);
  border: 1.5px dashed var(--line-2);
  background: var(--surface-sunken);
  text-align: center;
  cursor: pointer;
  transition: border-color var(--t-fast) var(--ease-out), background var(--t-fast) var(--ease-out);
}

.upload-zone:hover,
.upload-zone.is-over {
  border-color: var(--brand-500);
  background: var(--brand-50);
}

.upload-zone.is-filled {
  display: none;
}

.upload-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: var(--r-lg);
  border: 1px solid var(--line);
  background: var(--white);
  color: var(--brand-600);
}

.upload-title {
  font-size: 13px;
  font-weight: 500;
  color: var(--ink-800);
}

.upload-preview-wrap {
  border-radius: var(--r-xl);
  border: 1px solid var(--line);
  overflow: hidden;
  background: var(--surface-sunken);
}

.upload-preview {
  display: block;
  width: 100%;
  max-height: 260px;
  object-fit: contain;
  background: #0f1114;
}

.upload-preview-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 8px 12px;
  border-top: 1px solid var(--line);
  background: var(--white);
}

.concept-box {
  padding: 14px 16px;
  border-radius: var(--r-lg);
  border: 1px solid var(--line);
  background: var(--surface-sunken);
  font-size: 13px;
  line-height: 1.85;
  color: var(--ink-800);
}

/* --------------------------------------------------------------------------
   学习进度（快乐提分顶部）：领跑 / 落后 一眼看出来，用段位 + 一句话推着孩子去练
   配色：一整块同色系浅底 + 左侧色条（白底套浅黄那种「两块拼色」已经被用户否掉）
   -------------------------------------------------------------------------- */

.pace-card {
  border: 1px solid #d9e7e2;
  border-left: 4px solid #17a08a;
  border-radius: var(--r-xl);
  background: #edf7f4;
  box-shadow: none;
  color: var(--ink-800);
}

.pace-card.is-behind {
  border-color: #f0dcbc;
  border-left-color: #d9922a;
  background: #fdf4e4;
}

.pace-card.is-even {
  border-color: #dee2e9;
  border-left-color: #7b8595;
  background: #f2f4f7;
}

.pace-card .card-body {
  padding: 13px 16px;
}

.pace-grid {
  display: flex;
  align-items: center;
  gap: 14px;
}

/* 左侧徽章：糯糯头像 + 段位（加图片是为了不单调） */
.pace-badge {
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1px;
  width: 74px;
  padding: 7px 6px;
  border-radius: var(--r-lg);
  background: rgba(255, 255, 255, 0.72);
  border: 1px solid rgba(20, 22, 27, 0.08);
}

.pace-medal {
  width: 34px;
  height: 34px;
  object-fit: contain;
  margin-bottom: 1px;
}

.pace-rank {
  font-size: 15px;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: #0b5f52;
}

.pace-card.is-behind .pace-rank { color: #9a6113; }
.pace-card.is-even .pace-rank { color: var(--ink-700); }

.pace-rank-note {
  font-size: 10px;
  letter-spacing: 0.04em;
  color: var(--ink-400);
}

.pace-main {
  min-width: 0;
  flex: 1;
}

/* 底部一行：左侧三个数字，右侧「学校进度」（图标与文字必须同一行） */
.pace-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: 2px;
}

.pace-scope {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  flex: none;
  max-width: 100%;
  padding: 2px 9px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.75);
  border: 1px solid rgba(20, 22, 27, 0.07);
  color: var(--ink-500);
  font-size: 11.5px;
  white-space: nowrap;
}

.pace-scope svg {
  flex: none;
}

/* 文字太长就省略号，绝不换行（图标与文字必须同一行） */
.pace-scope-text {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.pace-headline {
  margin-top: 2px;
  font-size: 18px;
  font-weight: 700;
  line-height: 1.35;
  color: var(--ink-900);
}

.pace-headline em {
  font-style: normal;
  font-size: 22px;
  padding: 0 3px;
  color: #0b5f52;
  font-variant-numeric: tabular-nums;
}

.pace-card.is-behind .pace-headline em { color: #a3651a; }

.pace-sub {
  margin-top: 5px;
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--ink-600);
}

.pace-bar {
  position: relative;
  height: 6px;
  margin: 10px 0 8px;
  border-radius: 999px;
  background: rgba(20, 22, 27, 0.07);
}

.pace-bar i {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: #17a08a;
  transition: width 600ms var(--ease-out);
}

.pace-card.is-behind .pace-bar i { background: #d9922a; }
.pace-card.is-even .pace-bar i { background: #7b8595; }

.pace-bar span {
  position: absolute;
  right: 0;
  top: -17px;
  font-size: 11px;
  color: var(--ink-500);
  font-variant-numeric: tabular-nums;
}

/* 进度百分比那一位数字（会跟着滚动）：跟卡片里其它数字一样 600 字重，滚动时宽度不跳 */
.pace-bar span b {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.pace-stats {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 16px;
  font-size: 12px;
  color: var(--ink-500);
  min-width: 0;
}

.pace-stats b {
  font-size: 12.5px;
  color: var(--ink-800);
  font-variant-numeric: tabular-nums;
}

.pace-stats em {
  font-style: normal;
  color: var(--ink-400);
}

/* 右上角：只看一个「查看星阶」图标 */
.pace-ladder-btn {
  flex: none;
  width: 32px;
  height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  border: 1px solid rgba(20, 22, 27, 0.08);
  background: rgba(255, 255, 255, 0.72);
  color: #0b5f52;
  cursor: pointer;
}

.pace-card.is-behind .pace-ladder-btn { color: #9a6113; }
.pace-card.is-even .pace-ladder-btn { color: var(--ink-700); }

/* 星阶按钮跟在「小学还剩 N 个…」后面（用户 2026-10-11：不要单独占一块），所以做小一点 */
.pace-head .pace-ladder-btn {
  width: 22px;
  height: 22px;
  margin-left: 2px;
  align-self: center;
}

.pace-head .pace-ladder-btn .ic {
  width: 14px;
  height: 14px;
}

.pace-ladder-btn:hover {
  background: #ffffff;
  border-color: currentColor;
  transform: translateY(-1px);
}

/* 标题这一行：左边大字，右端一行小字「小学还剩 X 个知识点需掌握」。
   小字跟标题共用一行，所以不会去挤主列宽度（进度条 / 三个数字的宽度不变）。
   只用字号 / 字重 / 灰度拉层级，不加底色、不加描边、不加阴影。 */
.pace-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 6px 14px;
  flex-wrap: wrap;
}

.pace-rest {
  flex: none;
  /* 靠右对齐（用户 2026-10-11）：把「小学还剩 N 个…需掌握」推到最右边，星阶按钮紧跟在它后面 */
  margin-left: auto;
  font-size: 12px;
  line-height: 1.3;
  color: var(--ink-500);
  white-space: nowrap;
}

.pace-rest b {
  font-size: 13px;
  font-weight: 600;
  color: var(--brand-700);
  font-variant-numeric: tabular-nums;
}

.pace-card.is-behind .pace-rest b { color: #9a6113; }
.pace-card.is-even .pace-rest b { color: var(--ink-700); }

/* --------------------------------------------------------------------------
   星级上升阶梯（弹窗）：左边最低、右边最高的台阶图，点亮 = 品牌色实心
   -------------------------------------------------------------------------- */

.step-wrap {
  overflow-x: auto;
  padding: 4px 2px 2px;
}

.step-chart {
  display: flex;
  align-items: flex-end;
  gap: 6px;
  min-width: 100%;
  padding-bottom: 4px;
}

.step-col {
  flex: 1 0 46px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}

.step-tier {
  font-size: 10.5px;
  line-height: 1.1;
  text-align: center;
  color: var(--ink-400);
  white-space: nowrap;
}

/* 段位图标：已点亮彩色、正在攻的亮一点、还没到的灰掉 */
.step-icon {
  width: 34px;
  height: 34px;
  object-fit: contain;
  transition: filter 200ms var(--ease-out), transform 200ms var(--ease-out);
}

.step-col.is-locked .step-icon {
  filter: grayscale(0.9) opacity(0.45);
}

.step-col.is-next .step-icon {
  filter: saturate(1.1) drop-shadow(0 2px 6px rgba(224, 163, 78, 0.4));
  transform: scale(1.06);
}

.step-col.is-lit .step-tier {
  color: var(--brand-700);
  font-weight: 600;
}

.step-col.is-next .step-tier {
  color: #a3651a;
  font-weight: 600;
}

.step-bar {
  width: 100%;
  display: flex;
  align-items: flex-end;
}

/* 台阶高度：用 --i（第几级）算，越往右越高，形成楼梯 */
.step-bar i {
  display: block;
  width: 100%;
  height: calc(16px + var(--i, 0) * 13px);
  border-radius: 6px 6px 3px 3px;
  background: #e7ebef;
  border: 1px solid #dde2e8;
  transition: background 200ms var(--ease-out);
}

.step-col.is-lit .step-bar i {
  background: linear-gradient(180deg, #23b499, #128373);
  border-color: #0f7a6b;
}

.step-col.is-next .step-bar i {
  background: repeating-linear-gradient(135deg, #fff3dc, #fff3dc 4px, #f7e3bd 4px, #f7e3bd 8px);
  border-color: #e0a34e;
}

.step-book {
  font-size: 10.5px;
  color: var(--ink-500);
  white-space: nowrap;
}

.step-col.is-lit .step-book {
  color: var(--ink-800);
  font-weight: 600;
}

.step-now {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 12px;
  font-size: 13.5px;
  color: var(--ink-800);
}

.step-now-badge {
  padding: 1px 8px;
  border-radius: 999px;
  background: var(--brand-50);
  border: 1px solid rgba(13, 114, 100, 0.18);
  color: var(--brand-700);
  font-size: 11.5px;
  font-weight: 600;
}

.step-next {
  margin-top: 6px;
  color: var(--ink-500);
}

.step-legend {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 16px;
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid var(--line);
  color: var(--ink-400);
}

.step-legend span {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}

.lg-dot {
  width: 10px;
  height: 10px;
  border-radius: 3px;
  display: inline-block;
  background: #e7ebef;
  border: 1px solid #dde2e8;
}

.lg-dot.is-lit {
  background: linear-gradient(180deg, #23b499, #128373);
  border-color: #0f7a6b;
}

.lg-dot.is-next {
  background: #fff3dc;
  border-color: #e0a34e;
}

/* --------------------------------------------------------------------------
   英语「练一练」——照「兔兔单词屋」背单词小游戏的交互做的（选项 / 拼写键盘 / 听音喇叭）
   样式仍然只用本项目的设计令牌：发丝线、克制阴影、品牌色只用在选中与强调。
   -------------------------------------------------------------------------- */

.en-prompt {
  text-align: center;
  padding: 6px 0 2px;
}

.en-word {
  font-size: 34px;
  font-weight: 700;
  letter-spacing: 0.01em;
  color: var(--ink-900);
  line-height: 1.2;
}

.en-orb-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
}

.en-orb {
  width: 62px;
  height: 62px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
}

.en-choice {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 11px 14px;
  border-radius: var(--r-md);
  border: 1px solid var(--line-2);
  background: var(--surface-solid);
  color: var(--ink-800);
  font-size: 14.5px;
  text-align: left;
  cursor: pointer;
  transition: border-color var(--t-fast) var(--ease-out), background var(--t-fast) var(--ease-out),
    transform var(--t-fast) var(--ease-out);
}

.en-choice:hover:not(:disabled) {
  border-color: var(--line-3);
  transform: translateY(-1px);
}

.en-choice.is-picked {
  border-color: var(--brand-500);
  background: var(--brand-50);
  color: var(--brand-700);
}

.en-choice.is-right {
  border-color: rgba(47, 122, 78, 0.35);
  background: #f1f7f3;
  color: var(--ok-600);
}

.en-choice.is-wrong {
  border-color: rgba(176, 66, 58, 0.3);
  background: #fdf3f1;
  color: var(--danger-600);
}

.en-choice-key {
  flex: none;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 1px solid var(--line-2);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--ink-500);
}

.en-spell {
  min-height: 46px;
  border-radius: var(--r-md);
  border: 1px dashed var(--line-3);
  background: var(--surface-sunken);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 22px;
  font-weight: 600;
  letter-spacing: 0.16em;
  color: var(--ink-800);
  padding: 6px 10px;
}

.en-keyboard {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 5px;
  margin-top: 12px;
  max-width: 520px;
  margin-left: auto;
  margin-right: auto;
}

.en-key {
  min-width: 30px;
  height: 34px;
  padding: 0 6px;
  border-radius: var(--r-sm);
  border: 1px solid var(--line-2);
  background: var(--surface-solid);
  color: var(--ink-800);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
}

.en-key:hover:not(:disabled) {
  border-color: var(--line-3);
  background: var(--brand-50);
}

.en-key-del {
  color: var(--ink-500);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.en-feedback {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 10px 12px;
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: var(--surface-sunken);
  color: var(--ink-700);
}

.en-feedback b {
  display: block;
  font-size: 13.5px;
}

.en-feedback small {
  color: var(--ink-500);
}

.en-feedback.is-ok {
  border-color: rgba(47, 122, 78, 0.22);
  background: #f1f7f3;
  color: var(--ok-600);
}

.en-feedback.is-bad {
  border-color: rgba(176, 66, 58, 0.2);
  background: #fdf3f1;
  color: var(--danger-600);
}

.en-key-space {
  min-width: 52px;
  font-size: 12px;
}

/* 「单词解析」里的 emoji 示意图（跟背单词小游戏的 meaning-art 一样，一眼看懂这个词是什么） */
.en-symbol {
  flex: none;
  width: 72px;
  height: 72px;
  border-radius: var(--r-lg);
  border: 1px solid var(--line);
  background: var(--surface-sunken);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 40px;
  line-height: 1;
}

/* --------------------------------------------------------------------------
   语文「立即练习」四关（玩 / 认 / 练 / 写）—— 令牌全部取自 theme.css
   -------------------------------------------------------------------------- */
.cn-steps { display: flex; gap: 6px; flex-wrap: wrap; }
.cn-step {
  display: inline-flex; align-items: center; gap: 4px; padding: 4px 10px;
  border: 1px solid var(--line); border-radius: var(--r-full);
  font-size: var(--fs-xs); color: var(--ink-500); background: var(--surface-solid);
}
.cn-step.is-now { border-color: rgba(13,114,100,.35); background: var(--brand-50); color: var(--brand-700); font-weight: 600; }
.cn-step.is-done { color: var(--ink-400); }
.cn-step-ic { font-size: 13px; }
.cn-step-tick { color: var(--brand-600); }
.cn-card {
  display: flex; align-items: center; gap: 12px; padding: 12px 14px;
  border: 1px solid var(--line); border-radius: var(--r-lg); background: var(--surface-sunken);
}
.cn-symbol { font-size: 34px; line-height: 1; }
.cn-char { font-size: 26px; font-weight: 800; letter-spacing: .02em; }
.cn-tap {
  font-size: 58px; line-height: 1.1; padding: 16px 26px; border-radius: var(--r-2xl);
  background: #fff; border: 1px solid var(--line-2); box-shadow: var(--sh-2);
  transition: transform .16s var(--ease-out);
}
.cn-tap.is-pop { transform: scale(1.07); }
.cn-recognize { text-align: center; padding: 16px; border: 1px solid var(--line); border-radius: var(--r-lg); background: #fff; }
.cn-recognize-symbol { font-size: 52px; }
.cn-recognize-char { font-size: 44px; font-weight: 800; margin-top: 4px; }
.cn-recognize-pinyin { color: var(--ink-600); margin-top: 2px; }
.cn-options { display: grid; gap: 10px; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); }
.cn-option {
  font-size: 24px; font-weight: 700; padding: 14px 10px;
  border-radius: var(--r-lg); border: 1px solid var(--line-2); background: #fff;
}
.cn-option:hover { border-color: rgba(13,114,100,.3); background: var(--brand-50); }
.cn-option.is-right { border-color: rgba(47,122,78,.45); background: #f1f7f3; color: var(--ok-600); }
.cn-option.is-wrong { border-color: rgba(176,66,58,.35); background: #fdf3f1; color: var(--danger-600); }
.cn-option.is-reveal { box-shadow: 0 0 0 2px rgba(13,114,100,.35); }
.cn-grid {
  position: relative; width: 220px; height: 220px; background: #fffdf7;
  border: 3px solid #e3b57f; border-radius: var(--r-md); touch-action: none;
}
.cn-grid-v { position: absolute; left: 50%; top: 0; bottom: 0; border-left: 2px dashed #ebc79a; }
.cn-grid-h { position: absolute; top: 50%; left: 0; right: 0; border-top: 2px dashed #ebc79a; }
.cn-grid-char {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  font-size: 150px; font-weight: 800; color: rgba(70,53,35,.16);
}
.cn-grid canvas { position: absolute; inset: 0; width: 100%; height: 100%; }

/* 语文练习的「四个维度」标签（读准音 / 认清形 / 理解义 / 会运用） */
.cn-dim {
  display: inline-flex; align-items: center; gap: 6px; padding: 5px 12px;
  border: 1px solid rgba(13,114,100,.22); border-radius: var(--r-full);
  background: var(--brand-50); color: var(--brand-700); font-weight: 600; font-size: var(--fs-body);
}
.cn-dim .micro { color: var(--ink-500); font-weight: 400; }

/* 英语拼写题：一个字母一个横线格（字母用键盘敲，不再点屏幕键盘） */
.en-spell-boxes { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; margin-top: 6px; }
.en-spell-box {
  width: 38px; height: 52px; display: flex; align-items: center; justify-content: center;
  border-bottom: 3px solid var(--line-3); font-size: 26px; font-weight: 700;
  color: var(--ink-900); text-transform: lowercase;
}
.en-spell-box.is-filled { border-bottom-color: var(--brand-500); }
.en-spell-gap { display: flex; align-items: flex-end; padding-bottom: 12px; color: var(--ink-400); font-size: 20px; }

/* --------------------------------------------------------------------------
   游戏学园（views/games.js · 「创造」板块下的新菜单）
   一张卡 = 一个游戏：图标 + 学科标签 + 名字 + 一句话 + 时长 + 「开始玩」。
   克制版：白底 + 发丝线 + 极轻阴影，悬停只轻轻抬 2px（见 DESIGN.md）。
   -------------------------------------------------------------------------- */

.games-grid {
  display: grid;
  gap: var(--gap-5);
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
}

.game-card {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 18px 20px 20px;
  border-radius: var(--r-2xl);
  border: 1px solid var(--line-2);
  background: var(--surface-solid);
  box-shadow: var(--sh-1);
  transition: transform var(--t-fast) var(--ease-out), box-shadow var(--t-fast) var(--ease-out);
}

.game-card:hover {
  transform: translateY(-2px);
  box-shadow: var(--sh-2);
}

.game-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.game-ic {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: var(--r-lg);
  background: var(--brand-100);
  color: var(--brand-700);
}

.game-title {
  margin: 0;
  font-size: 16px;
  font-weight: 650;
  letter-spacing: -0.01em;
  color: var(--ink-900);
}

.game-desc {
  margin: 0;
  font-size: 12.5px;
  line-height: 1.75;
  color: var(--ink-500);
}

.game-meta {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11.5px;
  color: var(--ink-400);
}

.game-meta .ic {
  color: var(--ink-300);
}

/* 按钮沉到卡片底部，几张卡高度不同也对齐 */
.game-play {
  margin-top: auto;
  justify-content: center;
}

/* 「更新学校学习进度」里的单元列表：**默认按单元折起来**，点标题展开（用户 2026-10-11） */
.pick-unit-head {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  padding: 7px 8px;
  border: 0;
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--ink-600);
  font-size: 12px;
  font-weight: 600;
  text-align: left;
  cursor: pointer;
}

.pick-unit-head:hover {
  background: rgba(20, 22, 27, 0.04);
}

.pick-caret {
  flex: none;
  color: var(--ink-400);
  transition: transform var(--t-fast) var(--ease-out);
}

.kp-pick-unit.is-open .pick-caret {
  transform: rotate(90deg);
}

.pick-unit-count {
  color: var(--ink-400);
}

.pick-unit-picked {
  margin-left: auto;
  color: var(--brand-700);
}

.pick-unit-body {
  display: none;
  padding-left: 6px;
}

.kp-pick-unit.is-open .pick-unit-body {
  display: block;
}

/* ==========================================================================
   英语 › 动画磨耳朵（用户 2026-10-11）

   列表卡片直接复用「游戏学园」那套 .games-grid / .game-card，进度条用既有 .progress
   （同一套视觉语言，见 DESIGN.md：白底 + 发丝线 + 极轻阴影）；这里只补播放器、
   两个按钮的排列与「本周已看完」清单。
   ========================================================================== */

.listen-frame {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  border-radius: var(--r-xl);
  overflow: hidden;
  background: #0d0f13;
  border: 1px solid var(--line-2);
}

.listen-frame > iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
}

/* 卡片里的播放区（16:9）：初始只有封面图 + 播放键；
   点下去才由 JS 创建 iframe 换掉封面（这样才能带声音自动播，见 views/listening.js） */
.listen-stage {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  border-radius: var(--r-xl);
  overflow: hidden;
  border: 1px solid var(--line-2);
  background: #0d0f13;
  cursor: pointer;
}

.listen-stage.is-playing {
  cursor: default;
}

/* 管理员停用的动画：灰掉、点不动（孩子那边看到的是「已停用」徽章，只能「换一部」） */
.listen-stage.is-disabled {
  cursor: not-allowed;
}

.listen-stage.is-disabled::after {
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(20, 22, 27, 0.34);
  pointer-events: none;
}

.listen-stage > iframe {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
}

/* 封面图挂了 / 管理员没填封面时露出来的海报（动画名 + 标题） */
.listen-poster {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 4px;
  padding: 14px 16px;
  color: #fff;
  background:
    linear-gradient(135deg, rgba(18, 140, 122, 0.42), rgba(13, 15, 19, 0.82)),
    var(--surface-sunken);
}

.listen-poster-series {
  font-size: 11.5px;
  letter-spacing: 0.06em;
  opacity: 0.85;
}

.listen-poster-title {
  font-size: 14px;
  font-weight: 600;
  line-height: 1.45;
}

.listen-cover {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.listen-cover.is-broken {
  display: none;
}

.listen-play {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  display: grid;
  place-items: center;
  width: 58px;
  height: 58px;
  padding-left: 4px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.92);
  color: var(--brand-700);
  box-shadow: 0 8px 22px rgba(0, 0, 0, 0.3);
  transition: transform var(--t-fast) var(--ease-out);
}

.listen-stage:hover .listen-play,
.listen-stage:focus-visible .listen-play {
  transform: translate(-50%, -50%) scale(1.07);
}

.listen-dur,
.listen-flag {
  position: absolute;
  z-index: 2;
}

.listen-dur {
  right: 10px;
  bottom: 10px;
  padding: 2px 8px;
  border-radius: var(--r-full);
  background: rgba(13, 15, 19, 0.72);
  color: #fff;
  font-size: 11.5px;
  font-variant-numeric: tabular-nums;
}

.listen-flag {
  left: 10px;
  top: 10px;
}

/* 全屏（真全屏 API，或退化成铺满窗口）：铺满屏幕、黑底、播放器按 16:9 居中。
   注意：**播放中不要给这块播放区加 fixed / transform / 遮罩之类的样式** —— 实测那会让
   浏览器把播放判成「没有用户交互」，B 站播放器就默认静音开播（用户 2026-10-11 反复确认过：
   「点封面就地替换封面」的那版才有声音）。放大请走「全屏」按钮或播放器自带的全屏。 */
.listen-stage:fullscreen,
.listen-stage.is-fullpage {
  position: fixed;
  left: 0;
  top: 0;
  transform: none;
  width: 100vw;
  height: 100vh;
  aspect-ratio: auto;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  background: #000;
  display: grid;
  place-items: center;
}

.listen-stage:fullscreen > iframe,
.listen-stage.is-fullpage > iframe {
  width: min(100%, calc(100vh * 16 / 9));
  aspect-ratio: 16 / 9;
}

/* 管理端「预览」还是弹窗里播（那边不需要自动播放带声音），全屏时同样按高度收一下 */
.modal:fullscreen .listen-stage,
.modal.is-fullpage .listen-stage {
  width: min(100%, calc((100vh - 210px) * 16 / 9));
  margin: 0 auto;
}

.listen-card .game-title {
  margin-top: -2px;
}

/* 卡片上的动画名（一套动画的第一行，字号比标题小、比 meta 大一点） */
.listen-series {
  font-size: 11.5px;
  letter-spacing: 0.04em;
  color: var(--ink-400);
  margin-top: -4px;
}

/* 动画列表：最多两列（三列时卡片太窄，就地播放的画面会看不清）；手机上仍是一列 */
.listen-grid {
  grid-template-columns: repeat(auto-fill, minmax(460px, 1fr));
}

/* 标题那一行：标题 + 右边一个「标记已听完 / 更换」的小图标按钮（只有图标，省空间） */
.listen-title-row {
  display: flex;
  align-items: center;
  gap: 8px;
}

.listen-title-row .game-title {
  flex: 1 1 auto;
  min-width: 0;
}

.listen-swap {
  margin-left: auto;
  width: 28px;
  height: 28px;
  flex: none;
}

/* 「动画磨耳朵」顶部那三个统计（可以看 / 本周已听 / 累计磨耳朵）靠右对齐 */
.listen-stats {
  justify-content: flex-end;
  text-align: right;
}

/* .stat-val 本身是 flex（数字 + 小号单位），光靠 text-align 管不到它，得显式靠右 ——
   否则会出现「标签靠右、数字还靠左」的错位（用户 2026-10-11 报过） */
.listen-stats .stat-val {
  justify-content: flex-end;
}

.listen-actions {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: auto;
}

/* 「设置 › 动画管理」的表格：短列不换行、操作按钮紧凑一点，长标题 / 地址才折行 */
.listen-anim-table th,
.listen-anim-table td {
  white-space: nowrap;
  padding-left: 9px;
  padding-right: 9px;
}

.listen-anim-table td:nth-child(2) {
  white-space: normal;
  min-width: 150px;
}

.listen-anim-table td:last-child .btn {
  padding-left: 8px;
  padding-right: 8px;
}

/* 「新增动画」弹窗里的多年级勾选 + 动画名筛选行 */
.listen-grade-pick {
  font-size: 13px;
  color: var(--ink-700);
  cursor: pointer;
}

.listen-series-filter {
  margin-top: var(--gap-3);
}

.listen-series-filter .btn .micro {
  margin-left: 2px;
  color: inherit;
  opacity: 0.7;
}

/* 窄屏（平板 / 手机）下把「地址」这一列收起来（想确认地址点「预览」看播放器就行），
   剩下的列刚好一行放得下，不用横向拖表格 */
@media (max-width: 900px) {
  .listen-anim-table th:nth-child(3),
  .listen-anim-table td:nth-child(3) {
    display: none;
  }

  .listen-anim-table td:nth-child(2) {
    min-width: 110px;
  }

  /* 窄屏上按钮只留图标（都有 title / aria-label），表格一行放得下 */
  .listen-anim-table .wide-only {
    display: none;
  }

  .listen-anim-table td:last-child .btn {
    padding-left: 7px;
    padding-right: 7px;
  }
}

/* ==========================================================================
   手机端适配（用户 2026-10-10：手机上很多页面是乱的，尤其「快乐提分」整个模块）

   断点 ≤640px = 手机竖屏（360–430 宽）。原则：
     · 卡片一律**单列堆叠**（不要再并排挤成竖排字）；
     · 表格 / 明细行改成「上下两段」，按钮铺满一行（手指点得准）；
     · 宽图（整个小学热力图）**在卡片内部横向滑动**，绝不把整页撑宽。
   数学 / 语文 / 英语三个「快乐提分」共用这一套（三科视图是同一份）。
   ========================================================================== */
@media (max-width: 640px) {
  .page {
    padding-left: 12px;
    padding-right: 12px;
  }

  /* --- 卡片头：标题、说明、右侧图例/控件改成上下排，别互相挤 --- */
  .card-head {
    padding: 14px 14px 10px;
    gap: 10px;
  }

  /* 「flex: none」会让图例（热力图那张卡）撑破卡片 —— 手机上让它占满一行并允许折行 */
  .card-head > .legend,
  .card-head > .row,
  .card-head > .segmented {
    flex: 1 1 100%;
    margin-left: 0;
  }

  .legend {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 10px;
  }

  .legend-item {
    font-size: 10.5px;
  }

  /* --- 学习进度卡：徽章一行 → 正文 → 统计（统计换行，绝不再竖排） --- */
  .pace-grid {
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
  }

  .pace-badge {
    flex-direction: row;
    align-items: center;
    justify-content: flex-start;
    gap: 8px;
    flex-wrap: wrap;
  }

  /* 段位与「领跑段位」不许再被挤成竖排一个字一行 */
  .pace-badge > * {
    flex: none;
  }

  .pace-rank,
  .pace-rank-note {
    white-space: nowrap;
  }

  .pace-medal {
    width: 34px;
    height: 34px;
    margin: 0;
  }

  .pace-rank {
    font-size: 15px;
  }

  .pace-rank-note {
    font-size: 11px;
  }

  .pace-main {
    width: 100%;
  }

  .pace-head {
    flex-direction: column;
    align-items: flex-start;
    gap: 3px;
  }

  /* 手机上也靠右：这一行（还剩 N 个 + 星阶按钮）贴右边缘 */
  .pace-rest {
    margin-left: auto;
  }

  .pace-head .pace-ladder-btn {
    align-self: flex-end;
  }

  .pace-headline {
    font-size: 17px;
    line-height: 1.5;
  }

  .pace-rest {
    font-size: 11.5px;
  }

  .pace-sub {
    font-size: 12px;
    line-height: 1.7;
  }

  .pace-foot {
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
  }

  .pace-stats {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 12px;
    font-size: 11.5px;
  }

  .pace-stats span {
    white-space: nowrap;
  }

  .pace-scope {
    max-width: 100%;
  }

  .pace-scope-text {
    white-space: normal;
  }

  .pace-ladder-btn {
    width: 22px;
    height: 22px;
  }

  /* --- 预估成绩卡 --- */
  .est-hero {
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
  }

  .est-score {
    font-size: 42px;
  }

  .est-legend {
    flex-wrap: wrap;
    gap: 4px 10px;
  }

  .est-counts {
    flex-wrap: wrap;
    gap: 4px 10px;
  }

  /* --- 知识点掌握明细：表头去掉，单元行 / 知识点行都改上下两段 --- */
  .kp-card {
    --kp-col-w: auto;
    --kp-col-m: auto;
    --kp-col-a: auto;
  }

  .kp-cols {
    display: none;
  }

  .kp-item,
  .kp-head {
    grid-template-columns: minmax(0, 1fr);
    gap: 8px;
    padding: 12px var(--kp-gutter);
  }

  .kp-item {
    padding-left: calc(var(--kp-gutter) + 16px);
  }

  .kp-item::before {
    left: 13px;
  }

  .kp-item .wp {
    justify-content: flex-start;
  }

  /* 知识点名字允许折行（桌面上是省略号） */
  .kp-item-label {
    white-space: normal;
  }

  .kp-item-meta {
    padding-left: 0;
  }

  /* 按钮铺满一行：手机上好点 */
  .kp-actions,
  .kp-head .kp-actions {
    justify-content: stretch;
  }

  .kp-actions .btn,
  .kp-head .kp-actions .btn,
  .kp-card .kp-actions .btn {
    flex: 1 1 auto;
    --btn-h: 34px;
    font-size: 12.5px;
    justify-content: center;
  }

  /* 头部动作按钮（导入学习记录 / 手动标记）也铺开 */
  .kp-top {
    padding: 16px var(--kp-gutter) 12px;
    gap: 10px;
  }

  .kp-top-tools {
    margin-left: 0;
    width: 100%;
    gap: 8px;
  }

  .kp-top-tools .kp-top-rule {
    display: none;
  }

  .kp-top-tools .btn {
    flex: 1 1 auto;
    justify-content: center;
  }

  /* 筛选条：年级下拉一整行，两组各一整行 */
  .kp-filter {
    padding: 10px var(--kp-gutter);
  }

  .kp-filter-row {
    gap: 8px;
  }

  .kp-filter-row .kp-pick {
    flex: 1 1 100%;
  }

  .kp-filter-row .kp-pick .select-sm {
    width: 100%;
    max-width: none;
  }

  .kp-filter-group {
    flex: 1 1 100%;
    justify-content: space-between;
  }

  .kp-filter-group + .kp-filter-group,
  .kp-filter-row .kp-pick + .kp-filter-group {
    padding-left: 0;
    border-left: 0;
    border-top: 1px solid var(--line);
    padding-top: 8px;
  }

  /* --- 整个小学热力图 / 覆盖率：在卡片里横向滑动 --- */
  .scroll-x {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }

  .heatmap {
    min-width: 500px;
  }

  .heat-row {
    grid-template-columns: 70px repeat(6, minmax(0, 1fr));
  }

  .heat-cell {
    height: 42px;
    font-size: 11px;
  }

  /* --- 表格（复习优先级、练习报告明细…）：横向滑动，别撑破卡片 --- */
  .table-wrap {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }

  /* --- 游戏学园卡片：一行一个 --- */
  .games-grid {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--gap-4);
  }
}
