/* 《未发送》Ch2 切片 —— 配色按《美术生成规格》的 Ch2 档
   1976 年安徽土屋：米白信纸、浅红竖格线、窗外发亮的稻田绿、午后强光。
   跟 Ch1 的暖黄台灯、Ch4 的冷白手机是三套，不共用变量。

   状态区分只用 alpha 与描边，不依赖色相（UI 规格 §5 色盲项）。 */

:root {
  --fs: 1;                      /* 字号缩放，无障碍项 */
  --ink: #2b2724;
  --ink-soft: #6d665f;
  --paper: #f2ece0;             /* Ch2 米白信纸 */
  --rule: rgba(178, 96, 88, .26);  /* 信纸印的浅红竖格线 */
  --rice: #7f8f4e;              /* 稻田绿 —— 本章的签名色 */
  /* 同一个绿提亮两档，只给「压在照片上的小字」用（结局页那两处）。
     #7f8f4e 亮度 0.28，14px 小字压在插图最亮处不够 4.5，靠压暗补要把插图压没。
     提亮文字 + 轻遮罩两头凑。色相不变，还是窗外那片稻子。 */
  --rice-hi: #cdd6a8;
  --ghost: 0.25;                /* 幽灵态 alpha —— 唯一定义处 */
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html, body {
  height: 100%;
  background: #16150f;
  font-family: "Songti SC", "SimSun", "Source Han Serif SC", serif;
  color: var(--ink);
  overflow: hidden;
  -webkit-tap-highlight-color: transparent;
}

#stage {
  position: relative;
  width: 100%; height: 100%;
  overflow: hidden;
}

/* ---------- 画面 ---------- */
.screen {
  position: absolute; inset: 0;
  display: none;
  align-items: center; justify-content: center;
  flex-direction: column;
}
.screen.active { display: flex; }

.bg {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  z-index: 0;
}
/* 开场心声：土屋淡入，压到只剩轮廓 */
.bg.dim  { filter: brightness(.34) saturate(.72); }
/* 桌前：她已经坐下了，场景该更实一点，但还压着 —— 字还是主角 */
.bg.desk { filter: brightness(.50) saturate(.82); }

/* 谜题屏：c04 是整套素材里最亮的一张（正午强光 + 发亮的稻田），
   信纸自己有底色不怕，但顶栏和心声压在照片上会糊。
   照片轻压一档，两条文字各自带通栏渐变（同 Ch1 的办法）。
   不敢压更多 —— 光斑是迎光的判定区，压暗了玩家就找不到它了。 */
#screen-puzzle .bg { filter: brightness(.74) saturate(.9); }

/* ---------- 按钮 ---------- */
.btn-main, .btn-ghost {
  position: relative; z-index: 20;
  font-family: inherit;
  font-size: calc(17px * var(--fs));
  padding: 10px 30px;
  border: 1px solid rgba(242, 236, 224, .5);
  background: rgba(22, 21, 15, .52);
  color: #f2ece0;
  cursor: pointer;
  transition: background .18s, border-color .18s, opacity .2s;
  backdrop-filter: blur(3px);
}
.btn-main:hover, .btn-ghost:hover {
  background: rgba(127, 143, 78, .34);
  border-color: var(--rice-hi);
}
.btn-main:disabled { opacity: .32; cursor: default; border-color: rgba(242, 236, 224, .22); }
.btn-main:disabled:hover { background: rgba(22, 21, 15, .52); border-color: rgba(242, 236, 224, .22); }
.hidden { display: none !important; }

/* ---------- 标题 ----------
   e02 是稻田，绿得发亮，上方三分之一是空的白亮天空（美术规格 §7 特意留的）。
   遮罩只吃下半幅稻子，天空和田埂上那个戴草帽的剪影都留着 —— 跟 Ch1 同一个做法。 */
.title-inner {
  position: absolute; bottom: 0; left: 0;
  width: 100%;
  z-index: 5;
  text-align: center;
  color: #f2ece0;
  padding: 74px 6vw 7vh;
  background: linear-gradient(rgba(22, 21, 15, 0) 0%, rgba(22, 21, 15, .78) 54%);
  text-shadow: 0 1px 3px rgba(0, 0, 0, .6);
}
.ch-no   { font-size: calc(15px * var(--fs)); letter-spacing: .5em; opacity: .8; }
.ch-name { font-size: calc(64px * var(--fs)); letter-spacing: .22em; margin: 10px 0 18px; }
.ch-meta { font-size: calc(14px * var(--fs)); opacity: .72; margin-bottom: 40px; letter-spacing: .08em; }

/* ---------- 心声浮字 ---------- */
.voice-stack {
  position: relative; z-index: 5;
  max-width: 46em;
  padding: 0 6vw;
  text-align: center;
}
.voice-line {
  font-size: calc(21px * var(--fs));
  line-height: 2.1;
  color: #ece8d8;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 1s, transform 1s;
  text-shadow: 0 1px 18px rgba(0, 0, 0, .85);
}
.voice-line.in { opacity: 1; transform: none; }

#intro-next, #desk-next { position: absolute; bottom: 7vh; }

/* ---------- 顶栏：橡皮额度 + 折叠状态 ----------
   折叠状态那一格是音效的视觉替代（无障碍：无纯听觉线索）——
   折对时的那声「叮」听不见也能从这里知道折住了。 */
#top-bar {
  position: absolute; top: 0; left: 0; right: 0;
  z-index: 15;
  display: flex; gap: 2.2em;
  justify-content: center; align-items: center;
  padding: 14px 20px;
  /* 渐变必须在**整条文字带**上保持高 alpha，不能在带子中间就开始衰减。
     文字带实测 y=14–32，旧写法 .58 @70%(=32.2px) 正好把拐点压在文字下沿上：
     那一行 alpha 只剩 .582，橡皮额度只有 4.58，折叠状态更是 4.48（差 0.02 不过线）。
     本章谜题页的底图是故意亮的（brightness(.74)，压暗就看不见窗光光斑了，
     而光斑是迎光机制唯一的视觉线索），所以只能靠这条带子本身够厚。
     改成 .80 一直保持到 78%(=35.9px) 再收 —— 文字带整条落在 >=.80 区，
     最亮处主色 10.51、额度 8.12。收口仍然落到 alpha 0，四边不会出硬边。 */
  background: linear-gradient(rgba(22, 21, 15, .86),
                              rgba(22, 21, 15, .80) 78%,
                              rgba(22, 21, 15, 0) 100%);
  color: #f2ece0;
  font-size: calc(16px * var(--fs));
  letter-spacing: .06em;
}
#eraser-pips {
  color: var(--rice-hi);
  letter-spacing: .3em;
  font-size: calc(15px * var(--fs));
}
/* 「暗一档」用显式颜色写，不用 opacity —— 压在遮罩上的文字再叠一层 opacity
   等于偷偷多乘一次，getComputedStyle 的 color 也量不出来。#cdc7bc 是 7.36。 */
#fold-state { color: #cdc7bc; }

/* ---------- 窗光判定区 ----------
   位置按 c04 实测：亮度 >150 的像素重心在源图 (912, 584)，即 66.3% × 76.0%。
   矩形以那个点为心。判定用「纸心是否落在矩形内」，无需精确（UI 规格 §3）。
   轮廓平时不画 —— 光斑在照片里本来就看得见，画框反而像 UI。
   只在把纸拿起来时浮出来一条，告诉玩家「往这儿放」。 */
#light-zone {
  position: absolute;
  left: 44%; top: 60%;
  width: 44%; height: 34%;
  z-index: 2;
  cursor: pointer;
  border: 1px solid transparent;
  transition: border-color .3s, background .3s;
}
#light-zone:hover { border-color: rgba(255, 248, 214, .28); }
#light-zone.hinted {
  border-color: rgba(255, 248, 214, .55);
  background: rgba(255, 248, 214, .07);
}

/* ---------- 信纸 ----------
   #paper 是定位框，高度恒为摊平高度：折痕手柄要能停在任何一道缝上，
   包括折起来之后 —— 所以框不能跟着纸一起缩。
   #paper-inner 才是那张纸，收高度 + overflow:hidden 就是「折起来」。 */
#paper {
  position: absolute;
  left: 50%; top: 92px;
  z-index: 10;
  transform: translateX(-50%) translate(var(--dx, 0px), var(--dy, 0px));
}
/* 松手弹回 / 点光斑飞过去：320ms */
#paper.springing { transition: transform .32s cubic-bezier(.3, .7, .3, 1); }
/* 举在手上：轻微抬起 */
#paper.lifted #paper-inner {
  box-shadow: 0 30px 70px rgba(0, 0, 0, .6), inset 0 0 70px rgba(255, 240, 200, .12);
  transform: scale(1.015);
}

#paper-inner {
  position: relative;
  padding: 24px 22px;
  background: url('../../assets/c03_ch2_letter_paper.webp') center / cover, var(--paper);
  box-shadow: 0 16px 48px rgba(0, 0, 0, .5), inset 0 0 60px rgba(178, 96, 88, .06);
  overflow: hidden;                 /* 折叠靠这一条：裁掉，不重排 */
  transition: height .3s ease, box-shadow .3s, transform .3s;
}
/* 折住之后纸更薄，投影收紧一点 —— 底下多了一层纸 */
#paper.folded #paper-inner {
  box-shadow: 0 10px 26px rgba(0, 0, 0, .55), 0 3px 0 rgba(160, 148, 126, .5),
              inset 0 0 60px rgba(178, 96, 88, .06);
}
/* 寄出：纸压暗，已经不是玩家的了 */
#paper.sending #paper-inner { filter: brightness(.82) saturate(.85); }

/* ---------- 6 列 × 8 行竖排 ----------
   row-reverse：先 append 的列 1 落在最右边，竖排从右往左读。
   竖格线用「每列一条左边线 + 网格一条右边线」拼出来，6 列正好 7 条 ——
   真的竖排信纸就是这样，没有横线。 */
#grid {
  display: flex;
  flex-direction: row-reverse;
  border-right: 1px solid var(--rule);
}
.col {
  display: flex;
  flex-direction: column;
  border-left: 1px solid var(--rule);
  transition: filter .25s;
}
/* 折对之后从右往左逐列亮起：让玩家读出那句话，而不是看出那句话（UI 规格 §3） */
.col.lit { filter: brightness(1.16) contrast(1.08); }

/* ---------- 字元 CharToken ----------
   四种状态见 UI 规格 §1。Ch2 用到 normal 与凹痕；没有 deleted ——
   这一章不删字，藏字靠折纸。 */
.cell {
  position: relative;
  width:  calc(42px * var(--fs));
  height: calc(42px * var(--fs));
  display: flex; align-items: center; justify-content: center;
  cursor: default;
  opacity: 0;
  transition: opacity .3s;
  outline: none;
}
.cell.in { opacity: 1; }

.cell .glyph {
  position: relative; z-index: 2;
  font-size: calc(26px * var(--fs));
  line-height: 1;
  color: var(--ink);
  /* 钢笔字：竖排信纸上她一笔一笔写的，比 Ch1 的铅笔正一点 */
  transform: rotate(-.3deg);
  transition: opacity .12s, transform .12s, color .2s;
}

/* 可擦的 6 处：铅笔压痕稍浅。这是唯一的可擦提示 ——
   不加高亮、不加描边（UI 规格 §3）。也把搜索空间从 48 缩到 6，玩家才找得到关键那一个。

   alpha 原来写 .62，逐格量下来不行：信纸纹理最暗的那几格底色只有 rgb(161,149,132)，
   第 28 格合成后只有 2.66，够不到大字档的 3.0。这六个字不只是提示，
   它们本身就是信的正文，必须读得出来 —— 「淡一点」该淡在观感上，不是淡到读不清。
   提到 .78：桌面最差格 3.53，320×568 小屏最差格 3.28（那里格子只有 33.5px，
   信纸纹理被 cover 裁到更暗的一块，同时字大了也就吃进更多暗像素，所以比桌面更紧）。
   两处都留了余量，而与同格实心墨的差最小仍有 1.26 —— 「这个字淡一点」一眼看得出。
   先试过 .74，小屏上只有 3.04，贴着 3.0 太紧，不算验过。 */
.cell.erasable { cursor: pointer; }
.cell.erasable .glyph { color: rgba(43, 39, 36, .78); }
.cell.erasable:hover .glyph,
.cell.erasable:focus-visible .glyph { transform: scale(1.05) rotate(-.3deg); color: var(--ink); }
.cell:focus-visible { box-shadow: inset 0 0 0 2px rgba(127, 143, 78, .7); }

/* 凹痕：擦过就留下，永久保留，改回原字也不消失（UI 规格 §3）。
   一封擦了三处的信，收信人看得出来。 */
.dent {
  position: absolute; inset: 4px;
  z-index: 1;
  background: rgba(109, 102, 95, .17);
  box-shadow: inset 0 1px 2px rgba(109, 102, 95, .28);
  opacity: 0;
  transition: opacity .3s;
  pointer-events: none;
}
.cell.dented .dent { opacity: 1; }

/* ---------- 折起来时露出的纸背边 ----------
   贴在 #paper-inner 的下沿，所以跟着高度动画一起走。
   上边一道 2px 高光 = 折线（UI 规格 §3），下面一小条暗的 = 翻到背面那半截的厚度。 */
#fold-back {
  position: absolute; left: 0; right: 0; bottom: 0;
  height: 8px;
  z-index: 3;
  opacity: 0;
  transition: opacity .3s;
  pointer-events: none;
  background: linear-gradient(rgba(255, 250, 232, .85) 0 2px,
                              rgba(150, 138, 116, .35) 2px,
                              rgba(120, 110, 92, .22) 100%);
}
#paper.folded #fold-back { opacity: 1; }

/* ---------- 迎光：背面透出的压痕 ----------
   alpha 0 → 0.3，600ms（UI 规格 §3）。摆在上半截靠左 ——
   左边是竖排的「后文」方向，那儿字少，压痕才看得清；也保证折起来之后仍在纸上。
   略微模糊 + 反色调：这是隔着纸看到的另一面。
   不可交互（pointer-events:none），不影响任何结局。全作唯一「看得到但碰不到」的文本。 */
#backlight {
  position: absolute;
  left: 26px; top: 30px;
  z-index: 1;
  display: flex;
  flex-direction: row-reverse;
  gap: 6px;
  opacity: 0;
  transition: opacity .6s;
  pointer-events: none;
}
#paper.backlit #backlight { opacity: .3; }
.bl-col {
  writing-mode: vertical-rl;
  font-size: calc(23px * var(--fs));
  line-height: 1.5;
  letter-spacing: .1em;
  color: #4a4038;
  filter: blur(.6px);
  transform: rotate(.8deg);
}
/* 迎光时整张纸透光：底色提亮，像光从背面打过来 */
#paper.backlit #paper-inner { filter: brightness(1.16) saturate(.92); }

/* ---------- 纸角：捏住这里把信举到窗光里 ----------
   迎光的埋点目标是 40% 发现率，一条路径不够 ——
   这是第一条（拖），点光斑是第二条。做成翻起的纸角，是个明确的「可以捏」。 */
#paper-grab {
  position: absolute; left: -3px; top: -3px;
  width: calc(34px * var(--fs)); height: calc(34px * var(--fs));
  z-index: 14;
  cursor: grab;
  outline: none;
  /* 翻起来的一角：亮三角 + 一道折边 */
  background: linear-gradient(135deg,
    rgba(255, 251, 238, .95) 0%, rgba(255, 251, 238, .95) 46%,
    rgba(168, 156, 132, .55) 47%, rgba(168, 156, 132, 0) 52%, transparent 100%);
  filter: drop-shadow(1px 2px 3px rgba(0, 0, 0, .4));
  transition: transform .18s;
}
#paper-grab:hover, #paper-grab:focus-visible { transform: scale(1.12); }
#paper-grab:focus-visible { box-shadow: 0 0 0 2px rgba(127, 143, 78, .8); }
#paper.lifted #paper-grab { cursor: grabbing; }

/* ---------- 折痕手柄 ----------
   沿纸面右侧上下拖，落点吸附到行边界（UI 规格 §3）。
   ch2_found_valid_fold 是本章核心指标（低于 70% 说明对折机制没被发现），
   所以这个手柄要够显眼 —— 做成从纸边伸出来的一个拉片。 */
#fold-handle {
  position: absolute;
  right: calc(-28px * var(--fs));
  top: 0;
  transform: translateY(-50%);
  width: calc(26px * var(--fs)); height: calc(30px * var(--fs));
  z-index: 14;
  display: flex; align-items: center; justify-content: center;
  cursor: ns-resize;
  outline: none;
  background: rgba(242, 236, 224, .93);
  border: 1px solid rgba(109, 102, 95, .45);
  box-shadow: 2px 2px 6px rgba(0, 0, 0, .35);
  transition: background .18s, transform .18s;
}
#fold-handle:hover { background: #fff; }
#fold-handle:focus-visible { box-shadow: 0 0 0 2px rgba(127, 143, 78, .85); }
/* 拉片上的三道横纹 —— 一眼看出是上下拖的 */
.fh-grip {
  width: 12px; height: 8px;
  background: repeating-linear-gradient(rgba(109, 102, 95, .75) 0 1px,
                                        transparent 1px 3px);
}

/* 折痕预览线：拖动时横贯纸面的虚线 */
#fold-guide {
  position: absolute; left: -6px; right: -6px; top: 0;
  height: 0;
  z-index: 13;
  border-top: 1px dashed rgba(43, 39, 36, .65);
  opacity: 0;
  transition: opacity .15s;
  pointer-events: none;
}
#fold-guide.on { opacity: 1; }

/* ---------- 候选字条 ----------
   擦掉之后浮在那一格旁边。摆左边（竖排的「后文」方向），不挡还没读到的字。
   原字排第一个 —— 改回原字凹痕也不消失，那个「回不去」要能被试出来。 */
#cand-strip {
  position: absolute;
  z-index: 30;
  display: flex; gap: 4px;
  padding: 5px;
  background: rgba(250, 246, 236, .97);
  border: 1px solid rgba(109, 102, 95, .4);
  box-shadow: 0 8px 24px rgba(0, 0, 0, .4);
}
.cand {
  font-family: inherit;
  font-size: calc(24px * var(--fs));
  width:  calc(38px * var(--fs));
  height: calc(38px * var(--fs));
  background: none;
  border: 1px solid rgba(109, 102, 95, .3);
  color: var(--ink);
  cursor: pointer;
  transition: background .15s, border-color .15s;
}
.cand:hover, .cand:focus-visible { background: rgba(127, 143, 78, .2); border-color: var(--rice); }
/* 当前那个字：加粗描边，不靠色相（色盲项） */
.cand.cur { border-color: var(--ink); border-width: 2px; }

/* ---------- 心声 ----------
   压在 c04 上，那张照片有大片过曝的光斑（迎光判定区，不能压暗）。
   跟 Ch1 一样给一条通栏渐变：满宽所以没有左右硬边，上下淡出到 0 所以没有上下硬边。
   纯展示，关掉命中测试 —— 否则窄窗口下它会盖住纸吞掉点击。 */
#voice-line {
  position: absolute; z-index: 16;
  left: 0; right: 0;
  bottom: 14vh;
  text-align: center;
  padding: 16px 8vw;
  pointer-events: none;
  font-size: calc(19px * var(--fs));
  color: var(--rice-hi);
  letter-spacing: .04em;
  background: linear-gradient(rgba(22, 21, 15, 0) 0%,
                              rgba(22, 21, 15, .82) 36%,
                              rgba(22, 21, 15, .82) 64%,
                              rgba(22, 21, 15, 0) 100%);
  opacity: 0;
  transition: opacity .7s;
  text-shadow: 0 1px 4px rgba(0, 0, 0, .85);
}
#voice-line.in { opacity: 1; }

#puzzle-actions {
  position: absolute; bottom: 5vh; z-index: 18;
  display: flex; gap: 14px;
}

/* ---------- 结局 ----------
   三张插图（d2a/d2b/d2c）都是室内暖光或黄昏，结局页文字满屏且可滚动 ——
   文字会滚过画面任何一处，所以按「最亮像素」验收，不能按中位。
   做法与 Ch1 结局页同源：小字提亮到 --rice-hi + 四边通铺的纯色遮罩。
   通铺纯色没有渐变也就没有边，不会像椭圆遮罩那样在屏幕中间浮出一个方块。 */
#screen-ending { justify-content: flex-start; }
#screen-ending .bg { filter: brightness(.42) saturate(.78); }
#screen-ending::before {
  content: '';
  position: absolute; inset: 0; z-index: 1;
  pointer-events: none;
  background: rgba(22, 21, 15, .30);
}
#ending-scroll {
  position: relative; z-index: 5;
  width: min(56em, 88vw);
  max-height: 100%;
  overflow-y: auto;
  padding: 8vh 2em 6vh;
  text-align: center;
  scrollbar-width: thin;
}
#ending-title {
  font-size: calc(15px * var(--fs));
  letter-spacing: .4em;
  color: #e2ddcc;
  margin-bottom: 30px;
}
.ending-line {
  font-size: calc(18px * var(--fs));
  line-height: 2.15;
  color: #ece8d8;
  margin: 12px 0;
  opacity: 0;
  transform: translateY(6px);
  transition: opacity .9s, transform .9s;
  text-shadow: 0 1px 14px rgba(0, 0, 0, .85);
}
.ending-line.in { opacity: 1; transform: none; }

/* 2C 的回信：竖排一行，写在最右 —— 跟她那封信同一个格式。
   他用她的格式回她，这件事本身就是「两层都看懂了」。 */
.reply-col {
  writing-mode: vertical-rl;
  margin: 30px auto;
  padding: 18px 14px;
  font-size: calc(25px * var(--fs));
  letter-spacing: .22em;
  color: #f4efe2;
  border-right: 1px solid rgba(205, 214, 168, .4);
  max-height: 12em;
  opacity: 0;
  transform: translateX(8px);
  transition: opacity 1.1s, transform 1.1s;
  text-shadow: 0 1px 16px rgba(0, 0, 0, .9);
}
.reply-col.in { opacity: 1; transform: none; }

/* 2B 的那一句：引擎叠字，一个一个砸出来 */
.stamp {
  display: flex; gap: .4em;
  justify-content: center; flex-wrap: wrap;
  margin: 32px 0;
}
.stamp span {
  font-size: calc(36px * var(--fs));
  color: #f4efe2;
  opacity: 0;
  transform: scale(1.6);
  transition: opacity .18s, transform .18s;
  text-shadow: 0 2px 20px rgba(0, 0, 0, .9);
}
.stamp span.in { opacity: 1; transform: none; }

#ending-ach {
  font-size: calc(14px * var(--fs));
  letter-spacing: .2em;
  color: var(--rice-hi);
  margin: 36px 0 26px;
}
.ending-btns { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; }
/* 暗底上的幽灵键。Ch4 那档 #9c9287 在这里不能用 ——
   Ch4 的结局页底是纯色近黑 #0d0c0b，本章结局页压在插图上，
   三张图过 brightness(.42) + 通铺遮罩之后最亮像素还有 rgb(82,81,78)。
   #b3ab9d 在那个像素上只有 3.49，够不到 4.5。按同一暖色比例提到 1.2 倍 = #d7cdbc，
   最亮像素上 5.05，最暗处 12.88 —— 留了余量，也没提到纯白去跟主按钮抢视觉重量。
   边框按 WCAG 1.4.11 的 3:1（非文本边界）单独验：alpha .55 合成出来只有 2.67，不够；
   .70 是 3.36，过线且仍明显比字轻 —— 提到 1.0 会让边框和字一样重，就不是幽灵键了。 */
.ending-btns .btn-ghost { color: #d7cdbc; border-color: rgba(215, 205, 188, .7); }
.ending-btns .btn-ghost:hover { color: #f8f4ea; }
#share-canvas {
  display: block;
  width: min(300px, 62vw);
  height: auto;
  margin: 26px auto 0;
  box-shadow: 0 12px 40px rgba(0, 0, 0, .6);
}

/* ---------- DEV 面板：正式版整块删掉 ---------- */
#dev {
  position: fixed; right: 10px; bottom: 10px;
  z-index: 100;
  background: rgba(22, 21, 15, .94);
  border: 1px solid rgba(127, 143, 78, .5);
  padding: 10px 12px;
  font-family: ui-monospace, Consolas, monospace;
  font-size: 12px;
  color: #d5d8c0;
  min-width: 230px;
}
.dev-row { display: flex; gap: 6px; align-items: center; margin: 5px 0; flex-wrap: wrap; }
#dev button {
  font-family: inherit; font-size: 11px;
  background: #2b2724; color: #d5d8c0;
  border: 1px solid rgba(127, 143, 78, .45);
  padding: 3px 7px; cursor: pointer;
}
#dev button:hover { background: rgba(127, 143, 78, .32); }
#dev-readout { color: #9aae86; font-size: 11px; }

/* ---------- 窄屏 ----------
   Ch2 是 16:9（信纸竖排，但场景横向 —— UI 规格 §1）。竖屏下纸要缩。
   纸宽 = 6 列 + 左右内边距；按视口反解，42px 当上限。
   高度同样要管：8 行竖排比 Ch1 的 6 行高，竖屏下更容易顶出屏幕。
   代价与 Ch1 一致 —— 竖屏下 --fs 调到 150% 时格子不再跟着长（物理放不下）。 */
@media (max-aspect-ratio: 1/1) {
  :root {
    --cell: min(calc(42px * var(--fs)),
                calc((100vw - 108px) / 6),
                calc((100vh - 300px) / 8));
  }
  .cell { width: var(--cell); height: var(--cell); }
  /* 字占格子的 .72，不是桌面那档的 .62 —— 这一条是无障碍阈值逼出来的，不是审美。
     WCAG 的「大字」线在 24px：>=24px 阈值 3.0，<24px 就跳到 4.5。
     320×568 这种小机上高度绑死，格子只有 33.5px，.62 算出 20.77px 掉到线下面，
     六个可擦字（alpha .74 压在信纸纹理最暗处）只有 3.43，过不了 4.5。
     靠提 alpha 补要提到 .92 上下，那就没有「铅笔轻一点」这条唯一线索了。
     改成 .72 → 24.1px，重新回到 3.0 档（实测可擦最差 3.43、实心最差 4.68，都过）。
     大屏上 26px 仍然赢 min()，所以只在真正挤的小屏上生效，而且是把字改大。
     竖排 CJK 字占格 70–75% 本来也比 62% 更像真的信纸。 */
  .cell .glyph { font-size: min(calc(26px * var(--fs)), calc(var(--cell) * .72)); }
  #paper { top: 78px; }
  #paper-inner { padding: 16px 14px; }
  #top-bar { gap: 1.2em; font-size: calc(13px * var(--fs)); }
  #voice-line { bottom: 12vh; font-size: calc(17px * var(--fs)); }
  .bl-col { font-size: calc(19px * var(--fs)); }
}

/* ===== 构建期注入（build.py）=====
   调试面板在公开版永久关闭。bindDev() 的调用已在构建时摘掉，
   这条 CSS 是第二道保险 —— 面板里有「填真解」「折第4行」
   「extend_recall 4min」这类直接给答案或改核心机制的按钮。
   display:none 同时也把它从 tab 顺序和无障碍树里摘掉了。 */
#dev, #devpanel { display: none !important; }
