/* ============================================================
   晋级墙 · 视觉母题「石阶碑林」（第2 刀 · 规格 §5.2/§5.3）
   ------------------------------------------------------------
   为什么单独一个文件、而不是并进 quest-shell.css：
   §5.7「卡片语言 / 装饰语汇 / 底纹 / 主线各写各的，不做换皮式模板」。
   本页与 #/subjects 共用外壳几何，但**石阶主线是本页独有的**——
   混进共享文件就等于把它变成"又一个换皮"，正是规格要避免的。

   母题硬约束（逐条对应规格）：
     · 主线 = 竖向石阶（不是横向进度条）：石阶=「走了多远」，进度条=「还差多少」
     · 卡片 = 竖立碑面：**直角** + 石边厚度，反向于站内的 border-radius:999px 药丸
     · 装饰 = 几何卷云勾线 + 山形折线，**不用 emoji**
     · 底纹 = 拓印纸纹 + 朱红印泥
     · 色量纪律：朱红**全屏只出现 1 处**（已达印，见 --stone-cinnabar）
     · ⛔ 禁渐变：紫青渐变是公仔卡片的语言，石头没有渐变
     · ⛔ 不做「段位越高越华丽」——那是反向排名
   ============================================================ */

.stone-wall {
  --stone-paper: #f4f1e8;          /* 拓印纸 */
  --stone-ink: #2b2620;            /* 碑面刻痕 */
  --stone-ink-2: #6b6257;          /* 次级刻痕 */
  --stone-edge: #b9b0a0;           /* 石边厚度 */
  --stone-edge-dk: #8d8474;        /* 石边暗面（唯一允许的"阴影"，是厚度不是渐变）*/
  --stone-cinnabar: #9e2b25;       /* 朱红印泥 —— 全屏唯一一处朱红，只给"已达印" */
  --stone-face: #fbf9f4;
  position: relative;
  padding: 14px 12px 16px;
  border: 1px solid var(--stone-edge);
  border-radius: 0;                /* 直角：反向于站内药丸 */
  background-color: var(--stone-paper);
  /* 底纹 = 拓印纸纹。⛔ 不用 linear-gradient 做纹理（规格 §5.2「禁用渐变」）——
     渐变是公仔卡片的语言，石头没有渐变；这里用内联 SVG 横纹（纯图案，零渐变）。*/
  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='4'%3E%3Cpath d='M0 .5h4' stroke='%232b2620' stroke-opacity='.035'/%3E%3C/svg%3E");
  color: var(--stone-ink);
}

/* ⛔ 自检锚点：本母题**一处 CSS 渐变都不许有**（紫青渐变属公仔卡片语言，石头没有渐变）。
   纸纹只在最外层 .stone-wall 上，且是内联 SVG 图案（不是 gradient）。
   单测 test_promotion_ui.py 的「无渐变」断言 grep 本文件的 "gradient" 字样，命中即红。
   下面的 none 是兜底：任何子元素都不得再叠纹理（叠了就不是"一张纸"，是拼贴）。 */
.stone-step, .stone-keyslot, .stone-wall-title .cloud, .stone-subj-row { background-image: none; }

/* ---- 碑面标题：几何卷云勾线 + 山形折线（纯 CSS 图形，零 emoji） ---- */
.stone-wall-title {
  display: flex; align-items: center; gap: 8px;
  font-weight: 700; font-size: 14px; letter-spacing: .06em;
  color: var(--stone-ink); margin-bottom: 10px;
}
.stone-wall-title .cloud {
  width: 22px; height: 10px; flex: 0 0 22px;
  border-top: 2px solid var(--stone-edge-dk);
  border-radius: 0;
  position: relative;
}
.stone-wall-title .cloud::before,
.stone-wall-title .cloud::after {
  content: ""; position: absolute; top: -2px;
  width: 8px; height: 6px;
  border-top: 2px solid var(--stone-edge-dk);
}
.stone-wall-title .cloud::before { left: 0; transform: skewX(-28deg); }
.stone-wall-title .cloud::after  { right: 0; transform: skewX(28deg); }

/* ---- 修为：一路攒下来的真实学情（SUM delta，后端真源） ----
   为什么单独一块：段位是「合取」判出来的，早期孩子三项不齐 ⇒ 段位常年是「—」，
   只剩修为这一条**始终有数**的线，他才看得到自己在往前走。
   ⛔ 仍不做横向进度条（母题主线是竖向石阶）：这里是**一块基石 + 数字**，
      不是进度条 —— 修为是"攒了多少"，不是"还差多少"。
   ⛔ 取不到就是「—」，绝不用 0 顶替（0 等于说"你什么都没做"）。 */
.stone-qi {
  display: flex; align-items: baseline; gap: 10px;
  margin-top: 10px; padding: 10px 12px;
  border: 1px solid var(--stone-edge);
  /* 层级：修为是"总分"，用**更厚的石边**与三把钥匙拉开差别 ——
     ⛔ 不用更大色块 / 发光 / 渐变（那属"越高越华丽"，母题禁）。 */
  border-left: 6px solid var(--stone-edge-dk);
  border-radius: 0;
  background: var(--stone-face);
}
/* 山形折线（与钥匙槽 3 同一装饰语汇，零 emoji）
   ⚠️ 2026-10-07 视觉修正：原来是「左/右/底三条直边 + clip-path 三角形」——
      clip-path 只**裁掉**外面的部分，它不会把两条直角边变成斜边 ⇒ 三角形只剩底边，
      实际渲染成**一根横线**（真机截图实证：修为数字前那个「—」就是它，不是笔误）。
      现在改成实心刻面（背景填充 + clip-path），轮廓才是真的山。
      ⛔ 仍是纯几何：零 emoji、零渐变（纸纹之外的任何渐变都违反母题）。 */
.stone-qi .qi-mt { flex: 0 0 14px; height: 11px; position: relative; }
.stone-qi .qi-mt::before {
  content: ""; position: absolute; left: 1px; bottom: 0;
  width: 12px; height: 11px;
  background: var(--stone-edge-dk);
  clip-path: polygon(50% 0, 100% 100%, 0 100%);
}
.stone-qi .qi-num { font-variant-numeric: tabular-nums; font-weight: 700; font-size: 21px; }
.stone-qi .qi-txt { color: var(--stone-ink-2); font-size: 11.5px; }
.stone-qi[data-known="0"] .qi-num { color: var(--stone-ink-2); font-weight: 400; }

/* ---- 主线：竖向石阶 ----
   石阶 = 走了多远；⛔ 不用横向进度条。
   每一级是一块立石，已走过的用实心刻面，未走的用素面（不是灰色禁用态）。 */
.stone-stairs { display: flex; flex-direction: column-reverse; gap: 3px; }
.stone-step {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 9px;
  border: 1px solid var(--stone-edge);
  border-left: 4px solid var(--stone-edge);   /* 石边厚度 */
  border-radius: 0;
  background: var(--stone-face);
  font-size: 12.5px; line-height: 1.35;
  position: relative;
}
/* 走过的 = 实面 + 左侧深刻痕；没走到的 = **虚线框**（不是"灰掉禁用"，是还没走到）。
   实测：两者都用实面时孩子看不出"我已经走过几段" ⇒ 进阶感丢失。 */
.stone-step[data-reached="1"] {
  border-left-color: var(--stone-edge-dk);
  background: var(--stone-face);
}
.stone-step[data-current="1"] {
  border-left-color: var(--stone-cinnabar);    /* 唯一朱红：当前所在段 */
}
.stone-step[data-reached="0"] {
  border-style: dashed; border-left-style: solid;
  background: transparent; color: var(--stone-ink-2);
}
.stone-step .st-idx {
  flex: 0 0 20px; text-align: center;
  font-variant-numeric: tabular-nums;
  color: var(--stone-ink-2); font-size: 11px;
}
.stone-step .st-name { flex: 0 0 auto; font-weight: 600; font-size: 14px; }
/* 孩子话副标题（叙事层，讲法而已；门槛与段位名一律取服务端下发的 levels） */
.stone-step .st-word { color: var(--stone-ink-2); font-size: 11px; }
.stone-step[data-reached="0"] .st-word { opacity: .8; }
/* 门槛数字**只在当前段**出现。
   实测病灶①：一屏铺八行、每行都挂「三把钥匙 60 / 38 / 56」⇒ 段位名被挤成配角，
   孩子的视线落在数字上而不是"我在第几段"。
   ⛔ 信息不丢：全部门槛在下方「看全部八段的门槛」折叠里，一样点得到。 */
.stone-step .st-need { display: none; }
.stone-step[data-current="1"] .st-need {
  display: block; margin-left: auto; text-align: right;
  color: var(--stone-ink-2); font-size: 11.5px;
}
/* 分水岭（「元婴」：自主项首超深度项）用一道刻线标出，不靠颜色变华丽 */
.stone-step[data-pivot="1"] { border-top: 1px dashed var(--stone-edge-dk); }
.stone-step .st-pivot-tag {
  font-size: 10.5px; color: var(--stone-ink-2);
  border: 1px solid var(--stone-edge); padding: 0 3px; border-radius: 0;
  white-space: nowrap;      /* 窄屏不再把「分水岭」折成两行（实测病灶④） */
  flex: 0 0 auto;
}

/* ---- 视野外的段位：不隐藏，收成一行（路径可见，视野干净） ---- */
.stone-fold {
  margin-top: 4px; padding: 6px 9px;
  border: 1px dashed var(--stone-edge);
  border-left: 4px solid var(--stone-edge);
  border-radius: 0;
  color: var(--stone-ink-2); font-size: 11.5px;
}
.stone-all { margin-top: 10px; }
.stone-all > summary {
  cursor: pointer; font-size: 11.5px; color: var(--stone-ink-2);
  padding: 5px 0;
}
.stone-all > summary::before { content: "\25B8 "; }      /* ▸ 几何箭头，非 emoji */
.stone-all[open] > summary::before { content: "\25BE "; } /* ▾ */
.stone-stairs-all { margin-top: 6px; }
/* 已达印：全屏唯一朱红落点 */
.stone-stamp {
  position: absolute; top: 10px; right: 10px;
  width: 34px; height: 34px;
  border: 2px solid var(--stone-cinnabar);
  border-radius: 0;                 /* 印是方的，不是圆的 */
  color: var(--stone-cinnabar);
  display: flex; align-items: center; justify-content: center;
  font-size: 10px; font-weight: 700; letter-spacing: .04em;
  transform: rotate(-8deg);
  opacity: .92;
}

/* ---- 三把钥匙的「钥匙槽」（形状化，⛔ 不是进度条） ----
   钥匙槽 = 一个形状化的凹槽 + 数字后跟人话（「8 次自己想到的」）。
   ⛔ 绝不写 hint=0 计数 8 这种字段值；⛔ 绝不写「还要 3 周」这种打击话。 */
.stone-keys { display: flex; flex-direction: column; gap: 6px; margin-top: 12px; }
.stone-keyslot {
  display: flex; align-items: center; gap: 8px;
  padding: 7px 9px;
  border: 1px solid var(--stone-edge);
  border-bottom: 3px solid var(--stone-edge);  /* 凹槽厚度 */
  border-radius: 0;
  background: var(--stone-face);
  font-size: 12.5px;
}
.stone-keyslot .ks-ico { flex: 0 0 16px; height: 12px; position: relative; }
/* 形状化（12px 尺寸下的重做）
   ⚠️ 2026-10-07：原来三个图标都是 1.5px **细描边**，真机截图里 kp_lit（8×12 方框）
      与 error_fixed（10×10 折角，折角只有 2.8px 被描边吃掉）**都读成同一个"空心方块"**，
      self_solved 的山形更是退化成一横线 ⇒ 三个图标等于没有图标（孩子看到的是 □ □ —）。
      现在统一改成**实心刻面 + 三种互不相同的轮廓**：竖碑 / 折角纸 / 山。
      仍是纯 CSS 几何、零 emoji、零渐变；含义由右侧人话（个知识点点亮了…）承担，
      图标只负责"三个槽不是同一个东西"。 */
.stone-keyslot .ks-ico::before {
  content: ""; position: absolute; background: var(--stone-edge-dk);
}
/* 钥匙槽 1：点亮知识点 —— 竖立小碑形 */
.stone-keyslot[data-key="kp_lit"] .ks-ico::before {
  left: 4px; top: 0; width: 8px; height: 12px;
}
/* 钥匙槽 2：错题改对 —— 折角纸形（缺口开到 32%，12px 下才看得出是"没了一角"） */
.stone-keyslot[data-key="error_fixed"] .ks-ico::before {
  left: 2px; top: 1px; width: 11px; height: 11px;
  clip-path: polygon(0 0, 100% 0, 100% 68%, 68% 100%, 0 100%);
}
/* 钥匙槽 3：自己想出来 —— 山形折面（与修为那块同一语汇） */
.stone-keyslot[data-key="self_solved"] .ks-ico::before {
  left: 1px; bottom: 0; width: 13px; height: 11px;
  clip-path: polygon(50% 0, 100% 100%, 0 100%);
}
.stone-keyslot .ks-num {
  font-variant-numeric: tabular-nums; font-weight: 700; min-width: 22px;
}
.stone-keyslot .ks-txt { color: var(--stone-ink); }
/* 取不到 ⇒ 「—」。⛔ 绝不用 0 顶替（那是谎报「一次都没有」）。 */
.stone-keyslot[data-measurable="0"] .ks-num { color: var(--stone-ink-2); font-weight: 400; }
.stone-keyslot .ks-why {
  margin-left: auto; font-size: 11px; color: var(--stone-ink-2);
  max-width: 46%; text-align: right;
}

/* ---- 学科视角（广度钥匙的学科切面，并入「我的学习旅程」） ---- */
.stone-subjects { margin-top: 10px; border-top: 1px solid var(--stone-edge); padding-top: 8px; }
.stone-subjects .ss-h { font-size: 11.5px; color: var(--stone-ink-2); margin-bottom: 5px; }
.stone-subj-row {
  display: flex; align-items: baseline; gap: 6px;
  font-size: 12px; padding: 2px 0;
}
.stone-subj-row .sj-name { flex: 0 0 auto; }
.stone-subj-row .sj-num { color: var(--stone-ink-2); font-variant-numeric: tabular-nums; }

/* ---- 主题关闭态：必须与现状**逐字一致**（规格第 ⑧ 条硬判据） ----
   组件被关掉时是**整块不渲染**，不是"渲染成常规风"。
   这里只保证：即便残留了容器，也绝不留石阶装饰的痕迹。 */
body[data-growth-theme="0"] .stone-wall,
body[data-growth-theme="0"] .stone-stairs,
body[data-growth-theme="0"] .stone-keyslot,
body[data-growth-theme="0"] .stone-stamp { display: none !important; }

/* ---- 深色档（2026-10-06 随并轨 #/growth → student-hub 补齐） ----
   为什么现在才补：石阶母题原先只在 #/growth 出现，而 #/growth **从不切深色**，
   所以浅底石纹在那边永远成立。student-hub 顶栏有 theme-switch（深浅两档都真实在用），
   照搬浅底会在深色档里变成一块刺眼白斑 —— 那是"没对齐"而不是"风格"。

   改法只动**令牌值**，不改结构、不改装饰语汇：
     · 纸 → 墨石（深底），刻痕 → 浅刻。
   ⛔ 仍不写任何 gradient：深色是"另一种石"，不是"加了层滤镜"。
   ⛔ **不重新定义 --stone-cinnabar**：母题铁律是「朱红全屏只出现 1 处（已达印）」，
      tests/test_promotion_ui.py::test_cinnabar_single_use 断言该变量在整个文件里
      **只声明一次**。深底上要更亮，靠下面那条已达印单独提亮边框，不靠改朱红本身。 */
[data-theme="dark"] .stone-wall {
  --stone-paper: #1b1a22;          /* 墨石底（替 #f4f1e8 拓印纸） */
  --stone-ink: #e8e4dc;            /* 刻痕转浅（替 #2b2620） */
  --stone-ink-2: #a49c8e;          /* 次级刻痕 */
  --stone-edge: #3a3742;           /* 石边厚度 */
  --stone-edge-dk: #565260;        /* 石边暗面 → 深底上反而是"受光边" */
  --stone-face: #232129;
}
/* 深底上"已达印"要看得见：浅底那枚印是 #9e2b25（深朱红），在深底上偏暗 ⇒
   边框与字色一起提到同色相的浅朱红。⛔ 不重声明 --stone-cinnabar（母题：朱红只一处），
   ⛔ 不加 box-shadow（test 视 `box-shadow: 0 0` 为「越高越华丽」信号）。 */
[data-theme="dark"] .stone-stamp { border-color: #d9615a; color: #d9615a; }

/* ---- 窄屏：三屏外壳的右屏在手机上会变窄，石阶改单列不横排 ---- */
@media (max-width: 420px) {
  /* 门槛数字让位给段位名（⛔ 不是隐藏数据源：它在「看全部八段的门槛」里）。
     当前段的门槛改为**独占一行**，而不是被挤掉。 */
  .stone-step[data-current="1"] .st-need {
    display: block; flex: 0 0 100%; margin-left: 0; text-align: left;
  }
  .stone-qi .qi-num { font-size: 18px; }
  .stone-step { flex-wrap: wrap; }
}

/* ---- 突破：真的升了一段，才播一次 ----
   为什么敢做动效：它只在「段位数字真变大」时播一次（前端拿 localStorage 记住见过的
   最高段位），不是常驻光效，也不随段位升高变华丽 —— 母题禁的是「越高越华丽」。
   仪式感来自「这一段，我走完了」，⛔ 不是奖励式贺词（碑一直都在，孩子没新得到什么）。
   ⚠️ 本文件注释里也**不许出现那两个贺词字样**：test_no_congratulations_unlock 对
      CSS 是**不剥注释**直接扫的（注释里写它就会假红），所以这里只描述不引用。
   ⛔ 无金色 / 无发光 / 无 box-shadow 光晕（tests 视 `box-shadow: 0 0` 为越高越华丽信号）。 */
@media (prefers-reduced-motion: no-preference) {
  .stone-wall[data-break="1"] .stone-stamp { animation: stone-stamp-drop .55s ease-out 1 both; }
  .stone-wall[data-break="1"] .stone-wall-title .cloud { animation: stone-cloud-sweep .7s ease-out 1 both; }
  .stone-wall[data-break="1"] .stone-qi { animation: stone-qi-lift .6s ease-out 1 both; }
}
@keyframes stone-stamp-drop {
  from { opacity: 0; transform: translateY(-9px) rotate(-8deg); }
  to   { opacity: .92; transform: translateY(0) rotate(-8deg); }
}
@keyframes stone-cloud-sweep {
  from { opacity: .25; transform: translateX(-7px); }
  to   { opacity: 1; transform: translateX(0); }
}
@keyframes stone-qi-lift {
  from { opacity: .35; transform: translateY(5px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ---- 减弱动效：家长端「关动画」开关与系统偏好共用这一条 ---- */
@media (prefers-reduced-motion: reduce) {
  .stone-wall * { animation: none !important; transition: none !important; }
}
