/* 杀青梦境 —— v21：开头引导 + 纯白梦境空间（三只吉祥物预览） */
*{margin:0;padding:0;box-sizing:border-box;-webkit-tap-highlight-color:transparent;
  -webkit-user-select:none;user-select:none}
img{-webkit-touch-callout:none;-webkit-user-drag:none}
/* 角色名专用宋体子集（3.4KB），保证手机和电脑一致 */
@font-face{font-family:"HLR Script";
  src:url("../assets/fonts/staff-script.woff2?v=164") format("woff2");
  font-display:block}
/* 留言板「Back」叶形退出键：Great Vibes 花体，只含 B a c k 四字母 */
@font-face{font-family:"HLR Back";src:url("../assets/fonts/back-script.woff2?v=164") format("woff2");font-display:swap}
@font-face{font-family:"HLR Name";
  src:url("../assets/fonts/name-serif.woff2?v=164") format("woff2");
  font-weight:700;font-display:swap}
:root{
  /* 画面基准比例 = 16:9，跟原作一致（iPad 铺满宽度上下留边、
     超宽手机铺满高度左右留边）。--u = 画面高度的 1%，两处数字要一起改。 */
  --R:1.7778;
  /* --vh 由 JS 写成 innerHeight/100 px（见 main.js syncVH）：iOS Safari 把软键盘算进
     动态视口，1dvh 会被键盘顶小、整个画面盒跟着缩（真机验出来的）；innerHeight 不受
     键盘影响，地址栏收起时照样会变，所以 dvh 的好处一点不丢。没 JS 时退回 1dvh。 */
  --u:min(var(--vh, 1dvh), 1vw / 1.7778);
}
html{background:#0b0d12;-webkit-text-size-adjust:100%}
/* body 比视口高出一截，给「上滑收地址栏」留真实滚动空间；
   盖在上面的 #gate-fs 高度必须与此绑死（坑 37 号） */
body{min-height:calc(100lvh + 45vh);overflow-x:hidden;background:#0b0d12;
  font-family:-apple-system,BlinkMacSystemFont,"PingFang SC","Microsoft YaHei",sans-serif;
  -webkit-tap-highlight-color:transparent}

/* 全局点击光效：只负责绘制，不参与任何点击命中 */
#tap-fx{position:fixed;inset:0;width:100%;height:100%;z-index:50;
  pointer-events:none}

/* ---------- 舞台：纯白梦境空间 ---------- */
/* #stage = 整个视口：毛玻璃补边、白空间氛围、点击区、整屏震动都在这层 */
#stage{position:fixed;left:0;right:0;top:0;height:calc(var(--vh, 1dvh) * 100);overflow:hidden;cursor:pointer;
  background:
    radial-gradient(120% 90% at 50% 110%, #ced3e4 0%, rgba(206,211,228,0) 58%),
    radial-gradient(90% 70% at 50% -12%, #ffffff 0%, rgba(255,255,255,0) 60%),
    linear-gradient(180deg, #ffffff 0%, #f8f9fc 48%, #e7eaf4 100%)}
/* 背景图层（毛玻璃补边 + 清晰主图）：白空间阶段为空，进场景后由 JS 填图 */
#bgblur{position:absolute;inset:calc(var(--u) * -8);background-size:cover;background-position:center;
  filter:blur(40px) saturate(1.08);transform:scale(1.08)}
#bgmain{position:absolute;inset:0;background-size:auto 100%;
  background-position:center;background-repeat:no-repeat}
#vig{position:absolute;inset:0;pointer-events:none;
  box-shadow:inset 0 0 22vmin 4vmin rgba(30,40,60,.18)}

/* 顶部柔光晕 */
#bloom{position:absolute;left:50%;top:-28%;width:120vmin;height:80vmin;
  transform:translateX(-50%);border-radius:50%;
  background:radial-gradient(closest-side, rgba(255,255,252,.95), rgba(255,255,252,0) 70%);
  filter:blur(6px)}
/* 斜向光带，压平面感 */
#ray{position:absolute;inset:-20%;
  background:linear-gradient(112deg,
    rgba(255,255,255,0) 30%, rgba(252,253,255,.5) 44%,
    rgba(255,255,255,0) 55%, rgba(250,251,255,.3) 66%, rgba(255,255,255,0) 78%);
  mix-blend-mode:screen}

/* 场景层（全视口：毛玻璃补边 + 白空间氛围） */
#scene{position:absolute;inset:0}
/* #view = 画面盒：锁死 16:9（原作基准），按短边等比缩放居中、尽量占满。
   立绘/对话框/选项/浮字全部锚在它上面，所以 iPad 这种方屏版式也不会变形；
   画面盒之外露出的部分由底下的 #bgblur 毛玻璃补满（横竖都补）。 */
#view{position:absolute;left:50%;top:50%;
  height:calc(var(--u) * 100);width:calc(var(--u) * 100 * var(--R));
  margin-top:calc(var(--u) * -50);margin-left:calc(var(--u) * -50 * var(--R));
  overflow:hidden}
/* 震动加在 #stage 上（整屏，背景一起动）；
   平移会露屏幕边，所以震动期间整体微放大兜住边缘 */
#stage.shake{animation:cam-shake .5s linear}
@keyframes cam-shake{
  0%{transform:translate(0,0) scale(1)}
  12%{transform:translate(calc(var(--u) * -1.8),calc(var(--u) * 1)) scale(1.035)}
  28%{transform:translate(calc(var(--u) * 1.6),calc(var(--u) * -1.3)) scale(1.035)}
  44%{transform:translate(calc(var(--u) * -1.3),calc(var(--u) * -.8)) scale(1.03)}
  60%{transform:translate(calc(var(--u) * 1.1),calc(var(--u) * .9)) scale(1.03)}
  76%{transform:translate(calc(var(--u) * -.6),calc(var(--u) * .4)) scale(1.02)}
  90%{transform:translate(calc(var(--u) * .3),calc(var(--u) * -.2)) scale(1.01)}
  100%{transform:translate(0,0) scale(1)}
}

/* 睁眼动画：中央一个椭圆「瞳孔洞」用 scaleY 撑开（中间先开、两侧后开），
   洞外的黑由超大 box-shadow 铺满，边缘用 shadow 模糊羽化。
   纯 transform + box-shadow，iOS 安全（mask 方案会翻车，两片眼睑方向会反）。 */
#lid{position:absolute;inset:0;z-index:14;pointer-events:none;overflow:hidden;
  background:#000}
/* 注意：不能用 scaleY——transform 会连 box-shadow 的覆盖范围一起缩，
   缝隙小时上下露白（真机踩过）。直接动画 height，阴影恒定铺满。 */
#lid .iris{position:absolute;left:50%;top:50%;width:164%;height:.4%;
  border-radius:50%;
  transform:translate(-50%,-50%);
  box-shadow:inset 0 0 calc(var(--u) * 9) calc(var(--u) * 3) rgba(0,0,0,.85), 0 0 calc(var(--u) * 7) 200vmax #000}
#lid.open{background:transparent}
#lid.open .iris{animation:iris 3.8s ease-in-out forwards}
@keyframes iris{
  0%{height:.4%}
  28%{height:46%}
  46%{height:8%}
  58%{height:11%}
  100%{height:300%}
}
#lid.off{display:none}

/* 异界感：漂浮光尘，六粒，模糊小圆点慢慢上飘 */
#fx{position:absolute;inset:0;overflow:hidden;pointer-events:none}
#fx i{position:absolute;display:block;border-radius:50%;
  background:radial-gradient(closest-side, rgba(255,255,255,.95), rgba(214,219,240,.4) 60%,
    rgba(255,255,255,0) 100%);
  filter:blur(1px);bottom:calc(var(--u) * -6);
  animation:drift linear infinite}
#fx i:nth-child(1){left:12%;width:calc(var(--u) * 2.2);height:calc(var(--u) * 2.2);animation-duration:19s}
#fx i:nth-child(2){left:28%;width:calc(var(--u) * 1.3);height:calc(var(--u) * 1.3);animation-duration:26s;animation-delay:-9s}
#fx i:nth-child(3){left:45%;width:calc(var(--u) * 1.8);height:calc(var(--u) * 1.8);animation-duration:22s;animation-delay:-15s}
#fx i:nth-child(4){left:62%;width:calc(var(--u) * 1.1);height:calc(var(--u) * 1.1);animation-duration:29s;animation-delay:-4s}
#fx i:nth-child(5){left:78%;width:calc(var(--u) * 2);height:calc(var(--u) * 2);animation-duration:21s;animation-delay:-12s}
#fx i:nth-child(6){left:90%;width:calc(var(--u) * 1.4);height:calc(var(--u) * 1.4);animation-duration:25s;animation-delay:-20s}
@keyframes drift{
  0%{transform:translateY(0);opacity:0}
  12%{opacity:.8}
  85%{opacity:.5}
  100%{transform:translateY(calc(var(--u) * -118));opacity:0}
}

/* 异界感：底部白雾，抹掉地平线，空间无边界 */
#mist{position:absolute;left:-5%;right:-5%;bottom:calc(var(--u) * -4);height:calc(var(--u) * 34);
  background:linear-gradient(180deg, rgba(255,255,255,0) 0%, rgba(255,255,255,.55) 46%,
    rgba(250,251,255,.9) 100%);
  filter:blur(8px)}

/* ---------- 三只吉祥物 ---------- */
/* 高度 = 裁切高/1640 × K，K=1.0；同源画布保画师体型比 */
/* 悬浮在画面中层（对话框之上），静止，不落地不投影——对齐原作吉祥物演出
   站位由 JS 写 left/bottom（slot 系统），带过渡以支持「排好队」滑移 */
.mascots{position:absolute;left:0;right:0;bottom:0;top:0;pointer-events:none}
.m{position:absolute;transform:translateX(-50%);
  transition:left .8s cubic-bezier(.5,1.4,.5,1), bottom .8s ease, opacity .85s ease}
.m img{display:block;height:100%}
.m.hid{opacity:0}
#m-bajiu{left:50%;height:calc(var(--u) * 70);bottom:calc(var(--u) * 24)}
#m-feiyi{left:25%;height:calc(var(--u) * 34);bottom:calc(var(--u) * 36)}
#m-zuozuo{left:75%;height:calc(var(--u) * 34.5);bottom:calc(var(--u) * 35)}
/* ---------- 赫洛斯线的两个氛围层（都锚在画面盒内、不吃点击） ---------- */
/* 书卷暖光：摊开书卷时文字浮起，暖黄的光「呼吸般」明灭。中心偏下＝手持书卷的高度 */
#warm{position:absolute;left:50%;top:70%;width:calc(var(--u) * 46);height:calc(var(--u) * 30);
  transform:translate(-50%,-50%);pointer-events:none;opacity:0;transition:opacity 1.6s ease}
#warm.on{opacity:1}
/* 呼吸放在子元素上：父层只管淡入淡出。
   合在一起的话 .on 一挂 animation 就立刻按关键帧跳到亮度，淡入被吃掉、显得很突然。 */
#warm i{position:absolute;inset:0;display:block;
  background:radial-gradient(closest-side,
    rgba(255,206,120,.62), rgba(255,186,86,.28) 38%, rgba(255,178,74,0) 70%);
  mix-blend-mode:screen;animation:warm-breathe 3.4s ease-in-out infinite}
@keyframes warm-breathe{0%,100%{opacity:.55;transform:scale(.94)}
  50%{opacity:1;transform:scale(1.05)}}
/* 离别白雾：从画面左右两侧漫进来，中间和底部留空——糊住对话框只会让人觉得字看不清。
   只淡入、到位就停：让它飘反而看得出是两块渐变在平移，穿帮。 */
#fog{position:absolute;inset:0;pointer-events:none;opacity:0;transition:opacity 2.4s ease}
#fog.on{opacity:1}
#fog i,#fog b{position:absolute;top:0;bottom:0;width:46%;display:block}
/* 画灵施法（v147 定稿；2026-09-10 外圈由淡紫改近白微暖（浅金太黄、冷白偏蓝也试过，用户都否），用户：紫色不像攻击光，v148 改过一版半透明叠光晕被用户否掉又退回来；霍列斯线，照原作参考 动画参考/攻击.mov）：一堆光晕从四周汇聚到右下一点成一颗小光球
   （spell-gather，之后呼吸悬停），出手时对话框先收、光球处炸开一团柔白光晕铺满画面再退掉（spell-burst）。
   全是 transform/opacity 动画，iOS 安全 */
#spell{position:absolute;inset:0;pointer-events:none;overflow:hidden}
#spell .orb{position:absolute;left:0;top:0;width:0;height:0;transform:translate(var(--x0),var(--y0))}
#spell .orb i{position:absolute;left:0;top:0;width:calc(var(--u) * 2.2);height:calc(var(--u) * 2.2);
  margin:calc(var(--u) * -1.1);border-radius:50%;
  background:radial-gradient(circle,#fff 0%,rgba(255,250,235,.95) 22%,rgba(255,251,240,.6) 50%,rgba(255,251,240,0) 72%);
  opacity:0;transform:translate(var(--dx),var(--dy)) scale(.5);
  animation:sp-gather 1.15s cubic-bezier(.3,.7,.2,1) forwards;animation-delay:var(--d)}
@keyframes sp-gather{0%{opacity:0;transform:translate(var(--dx),var(--dy)) scale(.5)}
  25%{opacity:1}100%{opacity:.85;transform:translate(0,0) scale(.75)}}
#spell .core{position:absolute;left:0;top:0;width:calc(var(--u) * 9);height:calc(var(--u) * 9);
  margin:calc(var(--u) * -4.5);border-radius:50%;
  background:radial-gradient(circle,#fff 0%,rgba(255,252,240,.98) 18%,rgba(255,250,238,.75) 40%,rgba(255,250,238,0) 70%);
  filter:drop-shadow(0 0 calc(var(--u) * 1.6) rgba(255,253,245,.95));
  opacity:0;transform:scale(.2);
  animation:sp-core 1.1s ease-out 1s forwards,sp-breathe 2.4s ease-in-out 2.1s infinite}
@keyframes sp-core{to{opacity:1;transform:scale(1)}}
@keyframes sp-breathe{0%,100%{transform:scale(1)}50%{transform:scale(1.12)}}
/* 炸开：光球处一团柔白光晕从 0 涨到铺满画面（直径 ≈ 画面对角线的 1.6 倍），停一拍再淡掉；光点同时向外飞散 */
#spell .bloom{position:absolute;left:0;top:0;width:calc(var(--u) * 60);height:calc(var(--u) * 60);
  margin:calc(var(--u) * -30);border-radius:50%;
  background:radial-gradient(circle,rgba(255,255,255,.96) 0%,rgba(255,255,255,.8) 22%,rgba(255,252,244,.5) 48%,rgba(255,250,240,0) 70%);
  transform:translate(var(--x0),var(--y0)) scale(.05);opacity:0;
  animation:sp-bloom 1.6s cubic-bezier(.2,.6,.3,1) forwards}
/* 柔一点：最大直径约 1.4 个画面高、半透明、1.6s 完事（第一版铺满全白，用户：核爆） */
@keyframes sp-bloom{0%{opacity:0;transform:translate(var(--x0),var(--y0)) scale(.05)}
  22%{opacity:.9}55%{opacity:.85;transform:translate(var(--x0),var(--y0)) scale(2.3)}
  100%{opacity:0;transform:translate(var(--x0),var(--y0)) scale(2.6)}}
#spell.burst .orb i{animation:sp-scatter 1.1s ease-out forwards;animation-delay:var(--d2)}
@keyframes sp-scatter{0%{opacity:.9;transform:translate(0,0) scale(.75)}
  100%{opacity:0;transform:translate(calc(var(--dx) * 1.6),calc(var(--dy) * 1.6)) scale(1.2)}}
#spell.burst .core{animation:sp-core-out .5s ease-in forwards}
@keyframes sp-core-out{to{opacity:0;transform:scale(2.2)}}
#fog i{left:0;background:linear-gradient(to right,
  rgba(255,255,255,.96), rgba(255,255,255,.5) 34%, rgba(255,255,255,0) 100%)}
#fog b{right:0;background:linear-gradient(to left,
  rgba(255,255,255,.96), rgba(255,255,255,.5) 34%, rgba(255,255,255,0) 100%)}

/* 三人线：单人居中。这行只是兜底，实际尺寸/位置由 main.js 的 fitNpc() 按锚点算 */
#m-npc{left:50%;height:calc(var(--u) * 90);top:calc(var(--u) * 10)}
/* 说话起头轻跳一下（参考立绘跳动.mov） */
.m.hop img{animation:hop .32s ease-out}
@keyframes hop{0%{transform:translateY(0)}45%{transform:translateY(calc(var(--u) * -2.4))}100%{transform:translateY(0)}}
/* 被撞（向右弹）：先向右歪再回正的挣扎 */
.m.knock img{animation:knock .7s ease-out}
@keyframes knock{
  0%{transform:rotate(0)}
  25%{transform:rotate(14deg)}
  55%{transform:rotate(-9deg)}
  80%{transform:rotate(4deg)}
  100%{transform:rotate(0)}
}
/* 入场：纯淡入（.hid 的 opacity 过渡），不加位移 */
/* 撞入：从左侧冲进来带一点回弹（浮现要快，不吃慢淡入） */
.m.slam-in{transition:left .8s cubic-bezier(.5,1.4,.5,1), bottom .8s ease, opacity .22s ease}
.m.slam-in img{animation:slam-in .5s cubic-bezier(.3,1.5,.55,1)}
@keyframes slam-in{0%{transform:translateX(calc(var(--u) * -16))}100%{transform:translateX(0)}}
/* 非说话人压暗蒙层：只作用于立绘 */
.m.dim img{filter:brightness(.62) saturate(.92);transition:filter .35s ease}
.m img{transition:filter .35s ease}

/* ---------- 对话框（v20 原样保留：整屏手绘素材 + 百分比锚点） ---------- */
/* 对话框素材按「画面盒高度」贴合，不是按宽度——16:9 比素材自身的 2.1679 窄，
   按宽度缩会矮 18%。横向溢出的部分由 #view 裁掉，素材左右各 10% 是透明淡出区
   （墨迹只在 10.4%~89.8%），可见窗口是中间 82%，一点画都不会切到。 */
#box{position:absolute;left:50%;bottom:0;transform:translateX(-50%);
  height:100%;width:calc(var(--u) * 216.79);pointer-events:none;
  opacity:0;transition:opacity .45s ease .15s}
#box.in{opacity:1}
#frame{display:block;width:100%;height:auto;pointer-events:none}
#name-t{position:absolute;left:20%;top:73.5%;width:19%;
  transform:translateY(-50%) skewX(-8deg);
  text-align:center;line-height:1;
  color:#453e37;font-size:calc(var(--u) * 3.95);letter-spacing:.06em;
  font-family:"HLR Name","Songti SC",serif;font-weight:700;
  -webkit-font-smoothing:antialiased;
  text-shadow:0 1px 2px rgba(255,255,255,.8),0 0 8px rgba(255,255,255,.6)}
#line{position:absolute;left:22%;right:19%;top:79.2%;
  color:#4a3f38;font-size:calc(var(--u) * 3.56);line-height:1.62;letter-spacing:.02em;
  font-family:-apple-system,"PingFang SC","Noto Sans CJK SC",sans-serif;font-weight:400;
  -webkit-font-smoothing:antialiased;
  text-shadow:0 1px 2px rgba(255,255,255,.85)}
#line.big{font-size:calc(var(--u) * 4.9);line-height:1.5}   /* 单句加大：t 节点带 big:true */
#tip{position:absolute;right:14%;top:90.5%;width:1.7em;height:.9em;
  font-size:calc(var(--u) * 3.56);color:#6b4136;
  opacity:0;animation:tip-bob 2.2s ease-in-out infinite}
#tip.on{opacity:.75}
@keyframes tip-bob{0%,100%{transform:translateX(0)}50%{transform:translateX(3px)}}
/* 对话头像（头像线，v134）：贴在名牌凸起左侧，顶齐凸起、底收进面板，底部渐隐；
   该 NPC 说话时 .on 淡入，其余台词行淡出（avaFor） */
#ava{position:absolute;left:13.3%;bottom:3%;height:24%;   /* 2026-09-10 用户调：原 bottom:0 高 27%，羽化露在面板上 */
  opacity:0;transition:opacity .35s ease;pointer-events:none;
  filter:drop-shadow(0 0 5px rgba(255,255,255,.55));
  /* 两层 mask 相交：竖向底部收进面板 + 横向左右羽化（用户：左右边缘线太清晰，用白雾缓一下） */
  -webkit-mask-image:linear-gradient(180deg,#000 84%,transparent 99%),
    linear-gradient(90deg,transparent 0,#000 18%,#000 82%,transparent 100%);
  -webkit-mask-composite:source-in;
  mask-image:linear-gradient(180deg,#000 84%,transparent 99%),
    linear-gradient(90deg,transparent 0,#000 18%,#000 82%,transparent 100%);
  mask-composite:intersect}
#ava.on{opacity:1}
/* 台词行内红字（台本标红）：跟浮现文字的 big-red 同一个红，不加大 */
#line em.red{font-style:normal;color:#c2452e;font-weight:500}

/* ---------- 选项 ---------- */
/* 选项浮层：容器铺满「画面顶部→对话框上沿」区域（素材实测上沿在 76%），
   内部 flex 居中——任意条数都自动在该区域垂直居中（对齐原作） */
#choices{position:absolute;left:50%;top:0;height:calc(var(--u) * 76);transform:translateX(-50%);
  display:none;flex-direction:column;gap:calc(var(--u) * 2.6);align-items:center;justify-content:center;
  z-index:10;min-width:44%}
#choices.on{display:flex}
/* 没有对话框时（浮现文字段落里的选项），容器改成铺满整屏再居中，
   否则还按「顶部→名牌线 calc(var(--u) * 72)」算会整体偏上 */
#choices.nobox{height:calc(var(--u) * 100)}
#choices button{font:inherit;font-size:calc(var(--u) * 3.2);letter-spacing:.14em;text-indent:.14em;
  color:#3d4152;background:rgba(255,255,255,.66);
  border:1px solid rgba(120,128,160,.45);border-radius:2.2em;
  padding:.72em 3em;min-width:100%;cursor:pointer;
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
  box-shadow:0 2px 14px rgba(120,128,168,.18);
  animation:choice-in .4s ease-out backwards}
#choices button:nth-child(2){animation-delay:.08s}
#choices button:nth-child(3){animation-delay:.16s}
#choices button:nth-child(4){animation-delay:.24s}
#choices button:active{background:rgba(255,255,255,.92)}
@keyframes choice-in{0%{opacity:0;transform:translateY(calc(var(--u) * 1.6))}100%{opacity:1;transform:translateY(0)}}

/* ---------- HUD：◇ 按钮（仿原作：旋转 45° 的圆角方块里放图标） ---------- */
#hud-r{position:absolute;right:2%;top:4.2%;z-index:12;
  display:flex;gap:calc(var(--u) * 4.4)}
.hud{position:relative;width:calc(var(--u) * 7);height:calc(var(--u) * 7);
  background:none;border:none;padding:0;cursor:pointer;color:#5a5468}
.hud::before{content:'';position:absolute;inset:9%;
  transform:rotate(45deg);border-radius:26%;
  background:rgba(252,252,255,.82);
  border:1px solid rgba(112,106,140,.5);
  box-shadow:0 calc(var(--u) * .4) calc(var(--u) * 1.6) rgba(50,44,80,.25),
    inset 0 1px 0 rgba(255,255,255,.9)}
.hud svg{position:absolute;left:50%;top:50%;width:56%;height:56%;
  transform:translate(-50%,-50%);fill:currentColor}
.hud:active::before{background:#fff}
.hud.lock{color:#b0adbc;cursor:default}
.hud.lock::before{background:rgba(235,235,240,.55);
  border-color:rgba(140,136,160,.3);box-shadow:none}
/* 喇叭：静音时藏声波、出叉 */
#hud-snd .x{display:none}
#hud-snd.off .w{display:none}
#hud-snd.off .x{display:block}
/* 左上：留言板 + 操作说明 */
#hud-l{position:absolute;left:2%;top:4.2%;z-index:12;
  display:flex;gap:calc(var(--u) * 4.4)}

/* ---------- 操作说明蒙层（coach mark） ----------
   与 HUD 同 z-index 但排在它前面，所以按钮浮在蒙层之上保持白钻；
   蒙层打开期间按钮不吃点击，点到哪都落到蒙层上=关闭 */
#coach{position:absolute;inset:0;z-index:12;background:rgba(8,6,18,.7);
  opacity:0;visibility:hidden;transition:opacity .3s ease, visibility 0s .3s;cursor:pointer}
#coach.on{opacity:1;visibility:visible;transition:opacity .3s ease}
#coach-svg{position:absolute;inset:0;width:100%;height:100%;overflow:visible}
#coach-svg path{fill:none;stroke:rgba(255,255,255,.7);stroke-linecap:round;stroke-linejoin:round}
#coach-svg circle{fill:#fff}
#coach-svg text{fill:#f3f1f8;letter-spacing:.1em;
  font-family:"HLR Name","Songti SC","Noto Serif SC",serif;font-weight:700}
#coach-note{position:absolute;left:50%;top:58%;transform:translate(-50%,-50%);
  text-align:center;color:#f3f1f8;font-size:calc(var(--u) * 2.9);line-height:1.9;letter-spacing:.12em;
  font-family:"HLR Name","Songti SC","Noto Serif SC",serif;font-weight:700}
#coach-close{position:absolute;left:50%;bottom:calc(var(--u) * 4);transform:translateX(-50%);
  color:#fff;font-size:calc(var(--u) * 2.2);letter-spacing:.18em;
  animation:ftx-blink 2.2s ease-in-out infinite}
/* 点名面板上的操作说明：面板整个压在蒙层下，说明改成引线标注（layoutCoach 的 nm 分支），中间那句不显示 */
#coach.nm{background:rgba(8,6,18,.72)}
#coach.nm #coach-note{display:none}
#view.coach-on .hud{pointer-events:none}
#view.coach-on .hud::before{box-shadow:0 0 calc(var(--u) * 2.4) rgba(255,255,255,.75),
  0 0 0 1px rgba(255,255,255,.5)}

/* ---------- 确认对话框 ---------- */
/* z 高于留言墙(15)：投稿须知、退出确认都要压在墙上面 */
#dlg{position:absolute;inset:0;z-index:16;display:none;
  align-items:center;justify-content:center;
  background:rgba(14,10,26,.32)}
#dlg.on{display:flex;animation:choice-in .3s ease-out}
#dlg-in{min-width:38%;max-width:70%;padding:calc(var(--u) * 5) calc(var(--u) * 7);
  border-radius:calc(var(--u) * 2.4);text-align:center;
  background:rgba(252,252,255,.9);border:1px solid rgba(120,114,150,.4);
  box-shadow:0 calc(var(--u) * 1.5) calc(var(--u) * 6) rgba(30,24,60,.35);
  backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px)}
#dlg-t{font-size:calc(var(--u) * 3.4);letter-spacing:.12em;line-height:1.9;color:#3d3850}
#dlg-b{display:flex;gap:calc(var(--u) * 3);justify-content:center;
  margin-top:calc(var(--u) * 4)}
#dlg-b button{font:inherit;font-size:calc(var(--u) * 3);letter-spacing:.18em;text-indent:.18em;
  border-radius:2.2em;padding:.5em 2.2em;cursor:pointer;
  color:#4a4456;background:rgba(255,255,255,.8);
  border:1px solid rgba(120,128,160,.5)}
#dlg-b button.pri{color:#fff;background:linear-gradient(180deg,#a39ddc,#8a84c8);
  border-color:rgba(255,255,255,.5)}
#stage.dark #dlg-in{background:rgba(30,24,56,.88);border-color:rgba(214,208,255,.35)}
#stage.dark #dlg-t{color:#ece9f6}
#stage.dark #dlg-b button{color:#ece9f6;background:rgba(26,20,48,.6);
  border-color:rgba(214,208,255,.4)}
#stage.dark #dlg-b button.pri{color:#fff;background:linear-gradient(180deg,#8a84c8,#6f68b0)}

/* ---------- 制作名单：整屏 staff roll ----------
   深色蒙层压住画面，宋体（与名牌同一套子集），STAFF 标题配菱形细线呼应 HUD 的 ◇；
   职务右对齐、名字左对齐成两栏，整块居中；打开时逐行错落浮现 */
#credits{position:absolute;inset:0;z-index:13;cursor:pointer;
  background:rgba(8,6,18,.7);
  opacity:0;visibility:hidden;transition:opacity .4s ease, visibility 0s .4s}
#credits.opening{opacity:1;visibility:visible;transition:opacity .24s ease}
#credits.on{opacity:1;visibility:visible;transition:opacity .4s ease}
#cr-in{position:absolute;left:50%;top:47.5%;transform:translate(-50%,-50%);
  width:max-content;max-width:92%;
  display:flex;flex-direction:column;align-items:center;
  font-family:"HLR Name","Songti SC","Noto Serif SC",serif;font-weight:700;color:#f2f0ea;
  text-shadow:0 2px 12px rgba(0,0,0,.5)}
#credits.on #cr-in > *{animation:cr-in .7s ease-out both}
@keyframes cr-in{0%{opacity:0;transform:translateY(calc(var(--u) * 1.6))}100%{opacity:1;transform:none}}
.cr-title{font-family:"HLR Script","Snell Roundhand",cursive;font-weight:400;
  font-size:calc(var(--u) * 9.5);letter-spacing:.04em;line-height:1;
  color:#f6f4ee}
.cr-rule{display:flex;align-items:center;gap:calc(var(--u) * 1.4);
  margin:calc(var(--u) * 2.2) 0 calc(var(--u) * 3.6)}
.cr-rule::before,.cr-rule::after{content:'';width:calc(var(--u) * 14);height:1px;
  background:linear-gradient(90deg,rgba(242,240,234,0),rgba(242,240,234,.7))}
.cr-rule::after{background:linear-gradient(90deg,rgba(242,240,234,.7),rgba(242,240,234,0))}
.cr-rule i{width:calc(var(--u) * 1);height:calc(var(--u) * 1);transform:rotate(45deg);
  border:1px solid rgba(242,240,234,.85)}
.cr-rule.sm{margin:calc(var(--u) * .4) 0 calc(var(--u) * 3.2)}
.cr-rule.sm::before,.cr-rule.sm::after{width:calc(var(--u) * 7)}
/* 每一块：职务一行（小、灰）、名字一行（大、白），整块居中 */
.cr-blk{display:flex;flex-direction:column;align-items:center;text-align:center;
  gap:calc(var(--u) * .7);margin-bottom:calc(var(--u) * 3)}
.cr-blk:last-child{margin-bottom:0}
.cr-role{white-space:nowrap;color:#b4aecb;
  font-size:calc(var(--u) * 2.3);letter-spacing:.3em;text-indent:.3em}
.cr-name{display:flex;flex-wrap:wrap;justify-content:center;gap:.2em 1.4em;
  max-width:calc(var(--u) * 118);     /* 缩号后文案七人正好一行 */
  font-size:calc(var(--u) * 3.1);letter-spacing:.12em;text-indent:.12em;line-height:1.4}
.cr-note{margin-top:calc(var(--u) * .4);color:#8f8aa6;
  font-size:calc(var(--u) * 1.9);letter-spacing:.2em;text-indent:.2em}
/* 外链不变色不加线（变色很丑），只跟一个很淡的小箭头示意可点 */
.cr-name a{color:inherit;text-decoration:none;white-space:nowrap}
.cr-name a svg{width:.5em;height:.5em;margin-left:.12em;vertical-align:.45em;opacity:.5;
  fill:none;stroke:currentColor;stroke-width:2.4;stroke-linecap:round;stroke-linejoin:round}
#cr-close{position:absolute;left:50%;bottom:calc(var(--u) * 4);transform:translateX(-50%);
  color:#fff;font-size:calc(var(--u) * 2);letter-spacing:.18em;
  animation:ftx-blink 2.2s ease-in-out infinite}

/* ---------- 浮现文字（*…*：无对话框、画面中央） ---------- */
#float-t{position:absolute;left:50%;top:42%;transform:translate(-50%,-50%);
  z-index:9;width:80%;text-align:center;color:#565b6e;
  font-size:calc(var(--u) * 3);line-height:2.1;letter-spacing:.14em;
  text-shadow:0 0 12px rgba(255,255,255,.9);
  opacity:0;transition:opacity .8s ease;pointer-events:none}
#float-t.on{opacity:1}

/* ---------- 三扇门：白乎乎发光的漩涡 ---------- */
#doors{position:absolute;inset:0;pointer-events:none;opacity:0;transition:opacity 1s ease}
#doors.on{opacity:1}
.dv{position:absolute;top:40%;width:calc(var(--u) * 32);height:calc(var(--u) * 32);
  transform:translate(-50%,-50%);
  /* 外圈光环，随呼吸微微起伏 */
  background:radial-gradient(closest-side, rgba(255,255,255,0) 46%,
    rgba(168,177,222,.52) 58%, rgba(255,255,255,0) 70%);
  animation:dv-breathe 5.2s ease-in-out infinite}
#d1{left:25%} #d2{left:50%;animation-delay:-1.7s} #d3{left:75%;animation-delay:-3.4s}
/* v141 台本拆门：只剩一扇（中间那颗），两侧的留着 DOM 不显示 */
#d1,#d3{display:none}
/* 亮核心：白洞的光 */
.dv::before{content:'';position:absolute;inset:-14%;border-radius:50%;
  background:radial-gradient(closest-side, #fff 0%, rgba(250,251,255,.96) 20%,
    rgba(208,214,242,.5) 46%, rgba(255,255,255,0) 74%)}
/* 旋转的柔雾：大模糊双瓣光晕，看不出形状只看得出在流动 */
.dv::after{content:'';position:absolute;inset:2%;border-radius:50%;
  background:conic-gradient(from 0deg,
    rgba(146,156,210,.46) 0deg, rgba(146,156,210,.07) 100deg,
    rgba(157,167,216,.4) 180deg, rgba(146,156,210,.07) 275deg,
    rgba(146,156,210,.46) 360deg);
  filter:blur(11px);
  animation:dv-spin 11s linear infinite}
#d2::after{animation-duration:8.5s;animation-direction:reverse}
#d3::after{animation-duration:13s}
@keyframes dv-spin{to{transform:rotate(360deg)}}
@keyframes dv-breathe{0%,100%{opacity:.8}50%{opacity:1}}

/* ---------- 顶部提示条 ---------- */
#swipe{position:fixed;left:50%;top:8px;transform:translateX(-50%);z-index:8;
  background:rgba(20,24,32,.72);color:#e6ebf2;font-size:11.5px;letter-spacing:.04em;
  padding:5px 12px;border-radius:14px;transition:opacity .6s ease;pointer-events:none;opacity:0}
#swipe.on{opacity:1} #swipe.gone{opacity:0}

/* ---------- 门/遮罩通用 ---------- */
.gate{position:fixed;inset:0;height:100dvh;z-index:20;display:none;
  flex-direction:column;align-items:center;justify-content:center;gap:1.2em;
  background:#0e1118;color:#cbd3e1;text-align:center;padding:2em;
  font-size:15px;line-height:2}
.gate.on{display:flex}
.gate .sub{font-size:12.5px;color:#7d8595;line-height:1.8}
.gate button{font:inherit;font-size:14px;color:#e6ebf2;background:rgba(255,255,255,.08);
  border:1px solid rgba(255,255,255,.28);border-radius:2em;padding:.55em 2.2em;cursor:pointer}
.gate button:active{background:rgba(255,255,255,.18)}
.gate .skip{border-color:transparent;color:#6b7383;font-size:12.5px;padding:.4em 1.5em}

#rot{z-index:40}
@media(orientation:portrait){#rot.armed{display:flex}}

/* 上滑引导门不用 fixed：跟随文档滚动，手指一划门会真的动，
   iOS 才有跟手反馈、地址栏也才收得起来。
   高度必须盖满 body 的 min-height：iOS 会在脚本执行后异步恢复
   scrollY，门若只有一屏高就会被顶上去露出 body 背景（坑 37 号）。
   文字用 sticky 内层钉在视口居中，滚到哪都看得见。 */
#gate-fs{position:absolute;top:0;left:0;right:0;bottom:auto;
  height:calc(100lvh + 45vh);padding:0}
#gate-fs.on{display:block}
#fs-in{position:sticky;top:0;height:100dvh;display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:1.2em;padding:2em;text-align:center}

/* 上滑手势动画：细长胶囊里一颗小点往上飘，只在 iPhone 引导文案时显示 */
#fs-hand{display:none;width:30px;height:64px;position:relative;
  border:1.5px solid rgba(255,255,255,.35);border-radius:15px}
#fs-hand.on{display:block}
#fs-hand::after{content:'';position:absolute;left:50%;width:7px;height:7px;
  margin-left:-3.5px;border-radius:50%;background:#e6ebf2;
  animation:fs-up 1.6s ease-in-out infinite}
@keyframes fs-up{
  0%{top:42px;opacity:0}
  25%{opacity:1}
  70%{top:11px;opacity:1}
  100%{top:11px;opacity:0}
}

/* ---------- 开场版权声明：两屏 ----------
   第一屏核心三句逐句淡入、读完点任意处；第二屏须知整块 → 耳机提示 → 进入按钮。
   与游戏主体共用 --u：按 16:9 画面盒等比缩放，手机保持原尺寸，电脑不再卡在 px 上限。 */
#disc{padding:0;letter-spacing:.08em;line-height:1.85;
  font-size:calc(var(--u) * 3.85)}
#disc p{margin:0}
.disc-pg{position:absolute;inset:0;display:none;flex-direction:column;
  align-items:center;justify-content:center;padding:1.5em 2.5em;
  transition:opacity .6s ease}
.disc-pg.on{display:flex}
.disc-pg.out{opacity:0;pointer-events:none}
/* 视觉重心抬高（同浮现文字锚 46% 的道理）：几何正中在手机上看着偏低 */
#disc-p1{padding-bottom:calc(var(--u) * 17)}
/* 核心声明：浮现文字同款质感——宋体、暖白、宽字距。
   第一句是定性，当小标题放大；第二组缩一号做说明 */
.disc-core{font-family:"HLR Name","Songti SC","Noto Serif SC",serif;font-weight:700;
  color:#f2f0ea;text-align:center;text-shadow:0 2px 14px rgba(0,0,0,.45)}
.disc-core p{opacity:0;transform:translateY(.5em);
  transition:opacity 1.1s ease, transform 1.1s ease}
.disc-core p.on{opacity:1;transform:none}
.disc-core p:first-child{font-size:calc(var(--u) * 4.87);letter-spacing:.34em;text-indent:.34em;
  line-height:1}
.disc-core p + p{font-size:calc(var(--u) * 3.33);letter-spacing:.14em;text-indent:.14em;
  line-height:2.1;color:#cfccc4}
#disc .disc-core p + p{margin-top:calc(var(--u) * 5.5)}
/* 第一屏读完浮出的提示：浅浅的、缓缓闪动 */
#disc-hint{position:absolute;left:0;right:0;bottom:calc(var(--u) * 9);
  font-size:calc(var(--u) * 2.95);letter-spacing:.22em;text-indent:.22em;
  color:#8d97ab;opacity:0;transition:opacity 1.2s ease}
#disc-hint.on{animation:hint-pulse 2.6s ease-in-out .9s infinite;opacity:.2}
@keyframes hint-pulse{0%,100%{opacity:.2}50%{opacity:.7}}
.disc-sub{font-family:"HLR Name","Songti SC","Noto Serif SC",serif;font-weight:700;
  font-size:calc(var(--u) * 3.33);letter-spacing:.14em;color:#cfccc4;line-height:1.95;
  text-align:center;text-shadow:0 2px 12px rgba(0,0,0,.4);
  opacity:0;transform:translateY(.4em);transition:opacity .9s ease, transform .9s ease}
.disc-sub.on{opacity:1;transform:none}
#disc .disc-sub .brand{margin-top:1.15em;color:#f2f0ea;letter-spacing:.22em;text-indent:.22em}
.disc-sub .star{color:#b9b3e6}
/* 耳机提示：第一屏的氛围注脚——灰、小、宽字距，和底部提示同声线 */
.disc-ear{margin-top:calc(var(--u) * 5.6);display:flex;align-items:center;gap:.6em;
  font-family:"HLR Name","Songti SC","Noto Serif SC",serif;font-weight:700;
  letter-spacing:.26em;text-indent:.26em;
  font-size:calc(var(--u) * 2.82);color:#8b93a5;
  opacity:0;transition:opacity 1.2s ease}
.disc-ear.on{opacity:1}
.disc-ear svg{width:1.35em;height:1.35em;flex:none;opacity:.85}
/* 进入按钮：站内统一的紫色主按钮（同 #nm-go / 确认框主按钮） */
#disc-agree{margin-top:calc(var(--u) * 6);
  font-family:"HLR Name","Songti SC","Noto Serif SC",serif;font-weight:700;
  font-size:calc(var(--u) * 2.69);letter-spacing:.2em;text-indent:.2em;color:#8b8880;
  opacity:0;transition:opacity .9s ease}
#disc-agree.on{opacity:1}
#disc-go{margin-top:calc(var(--u) * 2.8);font-size:calc(var(--u) * 3.33);letter-spacing:.34em;text-indent:.34em;
  font-family:"HLR Name","Songti SC","Noto Serif SC",serif;font-weight:700;
  padding:.5em 2.8em .44em;color:#fff;background:linear-gradient(180deg,#a39ddc,#8a84c8);
  border:1px solid rgba(255,255,255,.5);box-shadow:0 2px 14px rgba(138,132,200,.4);
  opacity:0;visibility:hidden;
  transition:opacity .9s ease, visibility 0s .9s}
#disc-go.on{opacity:1;visibility:visible;transition:opacity .9s ease}
#disc-go:active{filter:brightness(1.12);background:linear-gradient(180deg,#a39ddc,#8a84c8)}

/* ---------- 第二扇门：暗场景（背景图取代白空间） ---------- */
#bgblur,#bgmain{opacity:0;transition:opacity 1.1s ease}
/* .dark = 有背景图 + 暗色 UI（星空、夜房间）；.lit = 有背景图 + 亮色 UI（白天房间） */
#stage.dark #bgblur,#stage.dark #bgmain,
#stage.lit #bgblur,#stage.lit #bgmain{opacity:1}
#bloom,#ray,#mist,#fx{transition:opacity .9s ease}
#stage.dark #bloom,#stage.dark #ray,#stage.dark #mist,#stage.dark #fx,
#stage.lit #bloom,#stage.lit #ray,#stage.lit #mist,#stage.lit #fx{opacity:0}
#stage.dark{background:#0a0812}
#stage.lit{background:#cfd8e2}
/* 暗场景下的选项药丸：白药丸在星空上会糊成一片 */
#stage.dark #choices button{color:#ece9f6;background:rgba(26,20,48,.52);
  border-color:rgba(214,208,255,.42);box-shadow:0 2px 16px rgba(0,0,0,.4)}
#stage.dark #choices button:active{background:rgba(52,42,90,.8)}

/* 白光吞没：一次性全屏闪白 */
/* 场景之间的黑色交叉渐变 */
#fade{position:absolute;inset:0;z-index:19;background:#000;opacity:0;pointer-events:none;
  transition:opacity .75s ease}
#fade.on{opacity:1}
#flash{position:absolute;inset:0;z-index:20;background:#fff;opacity:0;pointer-events:none}
#flash.on{animation:flash-white 1.5s ease-out}
@keyframes flash-white{0%{opacity:0}18%{opacity:1}45%{opacity:1}100%{opacity:0}}

/* ---------- 浮现文字序列（*…*：无对话框、画面中央、点击逐句推进） ----------
   取值照《文字浮现》参考图量：单行居中在画面 50% 高；长文左对齐、
   左右 16%/84%，整块垂直居中，逐句浮出后整段一起淡出。 */
/* 出字期间的黑蒙层：星空背景太花，白字压不住（一整段浮现流程里常驻，
   不随每条文字开关，否则连着好几条时会一闪一闪） */
#ftx-dim{position:absolute;inset:0;z-index:9;pointer-events:none;
  background:rgba(6,4,14,.58);opacity:0;transition:opacity .8s ease}
#ftx-dim.on{opacity:1}
#ftx-dim.slow{transition-duration:2.4s}   /* fx dim-slow：慢压 */
#ftx{position:absolute;inset:0;z-index:11;pointer-events:none;display:none}
#ftx.on{display:block}
#ftx-in{position:absolute;left:50%;top:46%;transform:translate(-50%,-50%);
  width:80%;color:#f2f0ea;
  font-family:"HLR Name","Songti SC","Noto Serif SC",serif;
  font-size:calc(var(--u) * 4.6);line-height:1.95;letter-spacing:.08em;
  text-shadow:0 0 10px rgba(255,255,255,.26),0 2px 12px rgba(0,0,0,.55)}
/* 单行、多行一律居中：台本里的句子都短，左对齐两行很难看 */
#ftx-in{text-align:center;text-indent:.08em}
#ftx-in p{margin:0;opacity:0;transform:translateY(12px);
  transition:opacity .9s ease,transform .9s ease}
#ftx-in p.on{opacity:1;transform:translateY(0)}
#ftx-in p.snap{transition:none}                 /* 浮入途中点击=立刻到位 */
#ftx.out #ftx-in p{opacity:0;transition:opacity .45s ease}   /* 整段淡出 */
#ftx-in p.big-red{color:#c2452e;font-weight:700;font-size:1.5em;line-height:1.5}
/* 信件模式（菲利线，v135）：整块左对齐、字比浮字小一档、段间留空；.r = 署名靠右 */
#ftx-in.letter{text-align:left;text-indent:0;width:72%;top:50%;   /* 信件整块几何居中，不抬 */
  font-size:calc(var(--u) * 3.7);line-height:1.9;letter-spacing:.06em}
#ftx-in.letter p{margin:0 0 calc(var(--u) * 1.6)}
#ftx-in.letter p:last-child{margin-bottom:0}
#ftx-in.letter p.r{text-align:right}
/* 不压蒙层的浮字（ft 节点 nodim:true）：白空间上白字看不见，换成对话框那种深墨色、去掉白光 */
#ftx.nodim #ftx-in{color:#4a3f38;text-shadow:0 1px 2px rgba(255,255,255,.7)}
#stage.dark #ftx.nodim #ftx-in{color:#f2f0ea;text-shadow:0 0 10px rgba(255,255,255,.26),0 2px 12px rgba(0,0,0,.55)}
#ftx.nodim #ftx-tip{color:#4a3f38}
#stage.dark #ftx.nodim #ftx-tip{color:#fff}
#ftx-tip{position:absolute;left:50%;bottom:calc(var(--u) * 6);transform:translateX(-50%);
  color:#fff;font-size:calc(var(--u) * 2.2);letter-spacing:.18em;opacity:0}
/* 先 1.2s 淡入到 .72，再接呼吸闪烁（以前直接从 .72 开始闪，用户说出来得突然） */
#ftx-tip.on{animation:ftx-tip-in 1.2s ease forwards,ftx-blink 2.2s ease-in-out 1.2s infinite}
@keyframes ftx-tip-in{from{opacity:0}to{opacity:.72}}
@keyframes ftx-blink{0%,100%{opacity:.72}50%{opacity:.28}}
/* 暗场景下的占位/结语浮字 */
#stage.dark #float-t{color:#ece9f6;text-shadow:0 0 14px rgba(0,0,0,.85)}

/* 结语/占位画面：浮字与按钮各让一块，否则按钮压在字上 */
#stage.fin #float-t{top:30%}
#stage.fin #choices{top:calc(var(--u) * 44);height:calc(var(--u) * 52)}

/* ---------- NPC 点名选择器 ---------- */
/* 点名时画面上没有对话框，面板按整屏垂直居中；
   纵向单列对称：标题→输入框→候选一行→见面按钮 */
#namer{position:absolute;left:50%;top:0;height:calc(var(--u) * 100);transform:translateX(-50%);
  width:calc(var(--u) * 92);display:none;flex-direction:column;align-items:center;
  justify-content:center;gap:calc(var(--u) * 4.6);z-index:11;
  padding-top:calc(var(--u) * 4);box-sizing:border-box}   /* 整块往下压 2u：几何居中肉眼偏上（2026-09-10 用户） */
#namer.on{display:flex;animation:namer-in .45s ease-out}
/* Keep horizontal centering throughout the entrance animation. */
@keyframes namer-in{
  0%{opacity:0;transform:translate(-50%,calc(var(--u) * 1.6))}
  100%{opacity:1;transform:translate(-50%,0)}
}
.nm-prompt{font-family:"HLR Name","Songti SC",serif;font-weight:700;
  font-size:calc(var(--u) * 4.2);letter-spacing:.3em;text-indent:.3em;
  color:#4a4456;text-shadow:0 0 calc(var(--u) * 2) rgba(255,255,255,.8)}
/* 输入框：刻意做成「文本框」而不是药丸——方角、左对齐、放大镜、闪着的光标；
   药丸留给候选按钮，两者一眼能分开（以前同一副皮，大家以为中间也是按钮） */
.nm-field{width:calc(var(--u) * 62);display:flex;align-items:center;gap:.6em;
  font-size:calc(var(--u) * 3.4);  /* 不设 px 底线：iOS 聚焦放大已由 viewport maximum-scale=1 挡住，跟画面等比缩 */
  color:#3d4152;background:rgba(255,255,255,.86);
  border:1px solid rgba(120,128,160,.55);border-bottom:2px solid rgba(138,132,200,.75);
  border-radius:.35em;padding:.5em .9em;cursor:text;position:relative;
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
  box-shadow:inset 0 2px 6px rgba(120,128,168,.14);
  transition:border-color .25s ease, box-shadow .25s ease}
/* 放大镜贴左浮在框上，输入框铺满整框，文字对整框居中（名字最多几个字，不会撞到图标） */
.nm-field svg{position:absolute;left:.9em;top:50%;transform:translateY(-50%);
  width:1.05em;height:1.05em;color:#8a84c8;pointer-events:none}
.nm-field:focus-within{border-color:rgba(138,132,200,.9);
  box-shadow:inset 0 2px 6px rgba(120,128,168,.1), 0 0 0 calc(var(--u) * .35) rgba(138,132,200,.28)}
#nm-input{flex:1;min-width:0;width:100%;font:inherit;letter-spacing:.08em;text-align:center;color:inherit;
  background:none;border:0;padding:0 1.2em;outline:none;caret-color:#8a84c8}
#nm-input::placeholder{color:#9aa0b4;letter-spacing:.06em}
.nm-or{font-size:calc(var(--u) * 2.7);letter-spacing:.2em;text-indent:.2em;color:#7f7890;
  line-height:1;transition:opacity .3s ease}
.nm-hint.on + .nm-or{opacity:0}   /* 没匹配到时候选是空的，「或者挑一位」让位给提示 */
#nm-go{font:inherit;font-size:calc(var(--u) * 3.2);letter-spacing:.3em;text-indent:.3em;
  color:#fff;background:linear-gradient(180deg, #a39ddc, #8a84c8);
  border:1px solid rgba(255,255,255,.5);border-radius:2.2em;padding:.55em 3.4em;
  cursor:pointer;box-shadow:0 2px 14px rgba(138,132,200,.4);
  margin-top:calc(var(--u) * 1.6);
  transition:opacity .25s ease, filter .25s ease}
#nm-go:active{filter:brightness(1.12)}
#nm-go:disabled{background:rgba(150,153,165,.4);border-color:rgba(255,255,255,.3);
  color:rgba(255,255,255,.75);box-shadow:none;cursor:default}
/* 提示不占布局空间：高度 0、文字溢出到输入框和候选之间的间隙里，
   出现/消失都不会顶动别的元素 */
.nm-hint{height:0;overflow:visible;line-height:1;
  display:flex;justify-content:center;align-items:flex-start;
  margin-top:calc(var(--u) * -4.6);   /* 不吃 flex 的 gap：整块贴在输入框底边，下面的「或者…」才落在正中 */
  transform:translateY(calc(var(--u) * 4.6));   /* 文字落到「或者…」同一位置（那行此时藏起来） */
  font-size:calc(var(--u) * 2.6);letter-spacing:.16em;color:#9a90a8;
  opacity:0;transition:opacity .3s ease}
.nm-hint.on{opacity:.9}
.nm-list{display:flex;flex-wrap:nowrap;justify-content:center;
  gap:calc(var(--u) * 2.6);width:100%;min-height:calc(var(--u) * 8)}
.nm-list button{font:inherit;font-size:calc(var(--u) * 3.2);letter-spacing:.18em;text-indent:.18em;
  font-family:"HLR Name","Songti SC",serif;font-weight:700;
  color:#4a4456;background:rgba(255,255,255,.62);
  border:1px solid rgba(120,128,160,.45);border-radius:2.2em;
  padding:.5em 1.8em;cursor:pointer;
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
  box-shadow:0 2px 12px rgba(120,128,168,.16);
  animation:choice-in .35s ease-out backwards;
  transition:background .25s ease, border-color .25s ease, box-shadow .25s ease}
.nm-list button:nth-child(2){animation-delay:.06s}
.nm-list button:nth-child(3){animation-delay:.12s}
.nm-list button:nth-child(4){animation-delay:.18s}
.nm-list button.sel{background:rgba(255,255,255,.95);border-color:#8a84c8;
  box-shadow:0 0 0 calc(var(--u) * .35) rgba(138,132,200,.35), 0 2px 16px rgba(138,132,200,.35)}

/* 暗色场景（星空）下的配色 */
#stage.dark .nm-prompt{color:#ece9f6;text-shadow:0 0 calc(var(--u) * 2.4) rgba(120,110,200,.6)}
#stage.dark .nm-field{color:#ece9f6;background:rgba(26,20,48,.7);
  border-color:rgba(214,208,255,.42);border-bottom-color:rgba(190,182,255,.8);
  box-shadow:inset 0 2px 8px rgba(0,0,0,.35)}
#stage.dark .nm-field svg{color:#cfc8ff}
#stage.dark .nm-field:focus-within{border-color:#cfc8ff;
  box-shadow:inset 0 2px 8px rgba(0,0,0,.3), 0 0 0 calc(var(--u) * .35) rgba(190,182,255,.32)}
#stage.dark #nm-input::placeholder{color:#8d87a8}
#stage.dark .nm-or{color:#c4bde0;text-shadow:0 0 calc(var(--u) * 1.2) rgba(0,0,0,.6)}
#stage.dark .nm-hint{color:#b0a8cc}
#stage.dark .nm-list button{color:#ece9f6;background:rgba(26,20,48,.52);
  border-color:rgba(214,208,255,.42);box-shadow:0 2px 16px rgba(0,0,0,.4)}
#stage.dark .nm-list button.sel{background:rgba(70,58,120,.85);border-color:#cfc8ff;
  box-shadow:0 0 0 calc(var(--u) * .35) rgba(190,182,255,.4), 0 0 calc(var(--u) * 3) rgba(150,140,230,.5)}

/* 暗场景下 HUD 保持白钻（原作在暗景也是白色系按钮），只调阴影 */
#stage.dark .hud::before{box-shadow:0 calc(var(--u) * .4) calc(var(--u) * 2) rgba(0,0,0,.5),
  inset 0 1px 0 rgba(255,255,255,.9)}

/* ---------- 心音墙（留言板 v70） ----------
   盖满画面盒（z=15，在 HUD 之上、#dlg(16) 之下）。背景整张手绘墙，
   中央区域竖向无限滚动；叶子 = 单色底 + 静态 mask（iOS 只禁 mask 动画）。 */
#board{position:absolute;inset:0;z-index:15;display:none;cursor:default;background:#41696f;  /* 墙图平均色：慢网上图还没到时垫着，别是黑的 */
  font-family:"HLR Name","Songti SC","Noto Serif SC",serif}
#board.on{display:block;animation:bd-in .55s ease-out}
@keyframes bd-in{0%{opacity:0}100%{opacity:1}}
#bd-bg{position:absolute;inset:0;
  background:url(../assets/bg/wall.webp?v=164) center/cover no-repeat}
/* 三张墙图各自到了才淡入（wallPreload 点 .ld）；慢网上先看到平色底 → 底图 → 人物藤蔓，不是黑底突然蹦出来 */
#bd-bg,#bd-fg,#bd-ch{opacity:0;transition:opacity .6s ease-out}
#bd-bg.ld,#bd-fg.ld,#bd-ch.ld{opacity:1}
/* 滚动区：左右避开藤蔓相框，顶部从标题牌下开始；上下渐隐（静态 mask） */
#bd-scroll{position:absolute;left:12%;right:12%;top:16%;bottom:0;
  overflow-y:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch;
  scrollbar-width:none;
  /* 顶部渐隐拉长到 14%（牌子底边在画面 25.6%，便签滚上去时先淡掉，不压标题） */
  -webkit-mask-image:linear-gradient(180deg,transparent 0,#000 11%,#000 76%,transparent 93%);
  mask-image:linear-gradient(180deg,transparent 0,#000 11%,#000 76%,transparent 93%)}
#bd-scroll::-webkit-scrollbar{display:none}
#bd-canvas{position:relative;width:100%}
#bd-empty{position:absolute;left:50%;top:34%;transform:translate(-50%,-50%);
  color:rgba(236,242,238,.6);font-size:calc(var(--u) * 2.6);letter-spacing:.22em;text-indent:.22em;
  font-weight:700;white-space:nowrap}

/* ---------- 叶子便签 ----------
   结构：.lf > .lf-bg(换色底，旋转/镜像只加在这层) + .lf-tx(文字区不跟着转)
   文字区取叶片最宽的中段：左让叶柄、右让叶尖，垂直居中往下堆 */
.lf{position:absolute;color:#f7f5ee;text-shadow:0 1px 4px rgba(22,42,34,.28);
  font-size:calc(var(--u) * 2.4);line-height:1.72;letter-spacing:.05em;font-weight:700}
.lf-bg{position:absolute;inset:0;background:var(--lc,#699b82);
  -webkit-mask:url(../assets/ui/leaf.webp?v=164) center/100% 100% no-repeat;
  mask:url(../assets/ui/leaf.webp?v=164) center/100% 100% no-repeat}
.lf-tx{position:absolute;left:22%;right:18%;top:14%;bottom:16%;
  display:flex;flex-direction:column;justify-content:center;
  font-family:"Songti SC","STSong","Noto Serif SC",serif}   /* 正文任意汉字，不走子集 */
.lf-tx p{margin:0;white-space:pre-wrap;word-break:break-all;overflow:hidden}
.lf-sig{display:block;text-align:right;font-size:.8em;opacity:.85;margin-top:.25em;
  padding-right:2%;white-space:nowrap;overflow:hidden}   /* 右缩进：躲开叶尖收窄 */
/* 三档大小（高 = 宽 × 0.581，随叶子素材比例） */
.lf.lf-s{width:calc(var(--u) * 36);height:calc(var(--u) * 20.9)}
.lf.lf-m{width:calc(var(--u) * 44);height:calc(var(--u) * 25.6)}
.lf.lf-l{width:calc(var(--u) * 54);height:calc(var(--u) * 31.4)}
/* 上墙浮现：淡入 + 轻微上浮，延迟由 JS 按行错落 */
#bd-canvas .lf{animation:lf-in .8s ease-out backwards}
@keyframes lf-in{0%{opacity:0;transform:translateY(calc(var(--u) * 2.2))}100%{opacity:1;transform:none}}

/* 光尘画布：盖满墙面，在便签之上、藤蔓之下，不吃点击 */
#bd-dust{position:absolute;inset:0;width:100%;height:100%;z-index:1;pointer-events:none}
/* 前景藤蔓花叶层：贴底铺满宽，压在滚动区之上、按钮之下，不吃点击 */
#bd-fg{position:absolute;left:0;right:0;bottom:0;z-index:2;pointer-events:none;
  aspect-ratio:1904/498;background:url(../assets/bg/wall-fg.webp?v=164) center bottom/100% 100% no-repeat}
/* 五个 Q 版人物 + 「心音墙」牌子：整幅带 alpha 的图层（源图 = 五张全幅透明层 + 牌子按模板匹配定位合成），
   压在藤蔓层之上，不被叶子和便签挡 */
#bd-ch{position:absolute;inset:0;z-index:2;pointer-events:none;
  background:url(../assets/bg/wall-chars.webp?v=164) center/100% 100% no-repeat}
/* 底部「我要投稿」：手绘按钮素材 */
#bd-post{position:absolute;left:50%;bottom:3.2%;transform:translateX(-50%);
  width:calc(var(--u) * 30);background:none;border:none;padding:0;cursor:pointer;z-index:3;
  filter:drop-shadow(0 calc(var(--u) * .6) calc(var(--u) * 1.8) rgba(10,30,24,.4));
  transition:filter .25s ease, transform .25s ease}
#bd-post img{display:block;width:100%}
#bd-post:active{filter:brightness(1.1) drop-shadow(0 calc(var(--u) * .3) calc(var(--u) * 1.2) rgba(10,30,24,.5));
  transform:translateX(-50%) scale(.97)}
/* 左上退出（回到梦境）：沿用 ◇ HUD 样式，位置与游戏内 HUD 对齐 */
/* 退出键：一片深绿叶子（同叶子夹），花体白字「Back」，无投影；放牌子右侧藤蔓上（左上角是罗夏的脸） */
#bd-exit{position:absolute;left:63.5%;top:7.5%;z-index:3;width:calc(var(--u) * 14);height:calc(var(--u) * 8.2);
  background:none;border:none;padding:0;cursor:pointer;transform:rotate(-22deg);   /* 往左倒，像从顶部藤上垂下来 */
  transition:transform .2s ease}
#bd-exit i{position:absolute;inset:0;display:block;background:linear-gradient(160deg,#79a878,#5f9166);
  -webkit-mask:url(../assets/ui/leaf.webp?v=164) center/100% 100% no-repeat;
  mask:url(../assets/ui/leaf.webp?v=164) center/100% 100% no-repeat}   /* 不带投影：像长在藤上的一片叶 */
#bd-exit span{position:relative;display:block;color:#f4f7ee;font-size:calc(var(--u) * 3.9);
  font-family:"HLR Back","Snell Roundhand",cursive;font-weight:400;   /* button 不继承字体，点名花体子集 */
  letter-spacing:0;text-indent:0;line-height:calc(var(--u) * 7.6);padding:calc(var(--u) * .9) 0 0 calc(var(--u) * .6);   /* 花体视觉重心偏上，往下压一点 */
  text-shadow:0 1px 2px rgba(20,40,25,.5)}
#bd-exit:active{transform:rotate(-22deg) scale(.95)}
/* 静音键：牌子左侧、与 Back 镜像的一片叶（右倾 + 水平翻转），花体「Music」；静音时叶子变灰、字换「Muted」 */
#bd-snd{position:absolute;right:63.5%;top:7.5%;z-index:3;width:calc(var(--u) * 14);height:calc(var(--u) * 8.2);
  background:none;border:none;padding:0;cursor:pointer;transform:rotate(22deg);
  transition:transform .2s ease}
#bd-snd i{position:absolute;inset:0;display:block;background:linear-gradient(200deg,#79a878,#5f9166);
  transform:scaleX(-1);transition:filter .3s ease;
  -webkit-mask:url(../assets/ui/leaf.webp?v=164) center/100% 100% no-repeat;
  mask:url(../assets/ui/leaf.webp?v=164) center/100% 100% no-repeat}
#bd-snd span{position:relative;display:block;color:#f4f7ee;font-size:calc(var(--u) * 3.6);
  font-family:"HLR Back","Snell Roundhand",cursive;font-weight:400;
  line-height:calc(var(--u) * 7.6);padding:calc(var(--u) * .9) calc(var(--u) * .6) 0 0;
  text-shadow:0 1px 2px rgba(20,40,25,.5)}
#bd-snd.off i{filter:saturate(.35) brightness(.85)}
#bd-snd.off span{opacity:.75}
#bd-snd:active{transform:rotate(22deg) scale(.95)}

/* ---------- 投稿编辑器：所见即所得 ----------
   蒙层压住墙面，中央一片真实叶子即预览：打字实时排版、跨档实时变形、点色实时换色。
   编辑叶按墙上三档 ×1.7 放大（字号 ≥16px，防 iOS 聚焦自动放大） */
#bd-ed{position:absolute;inset:0;z-index:5;display:none;
  align-items:center;justify-content:center;
  background:rgba(6,12,14,.55);backdrop-filter:blur(7px);-webkit-backdrop-filter:blur(7px)}
#bd-ed.on{display:flex;animation:bd-in .35s ease-out}
#bd-ed.out{animation:none;opacity:0;pointer-events:none;transition:opacity 1.3s ease;will-change:opacity}
.ed-wrap{display:flex;flex-direction:column;align-items:center;gap:calc(var(--u) * 3)}
/* 编辑叶：position 改 relative 参与布局；变形带过渡 = 跨档实时变形 */
#ed-leaf{position:relative;transition:width .4s ease, height .4s ease, font-size .4s ease}
#bd-ed .lf.lf-s{width:calc(var(--u) * 61);height:calc(var(--u) * 35.5);font-size:max(16px, calc(var(--u) * 4.42))}
#bd-ed .lf.lf-m{width:calc(var(--u) * 75);height:calc(var(--u) * 43.6);font-size:max(16px, calc(var(--u) * 4.42))}
#bd-ed .lf.lf-l{width:calc(var(--u) * 92);height:calc(var(--u) * 53.5);font-size:max(16px, calc(var(--u) * 4.42))}
.ed-tx{position:absolute;left:22%;right:18%;top:22%;bottom:34%}
#ed-text{display:block;width:100%;height:100%;background:none;border:none;outline:none;resize:none;
  font:inherit;color:inherit;line-height:inherit;letter-spacing:inherit;
  font-family:"Songti SC","STSong","Noto Serif SC",serif;overflow:hidden;caret-color:#f7f5ee}
#ed-text::placeholder{color:rgba(255,255,255,.55);font-family:"HLR Name","Songti SC",serif}
.ed-sig{position:absolute;right:16%;bottom:19%;display:flex;align-items:baseline;
  font-size:.8em;opacity:.92}
#ed-sig{width:9.5em;background:none;border:none;outline:none;font:inherit;color:inherit;
  letter-spacing:inherit;text-align:right;caret-color:#f7f5ee;
  font-family:"Songti SC","STSong","Noto Serif SC",serif;
  border-bottom:1px dashed rgba(255,255,255,.45);padding-bottom:.1em}
#ed-sig::placeholder{color:rgba(255,255,255,.55);font-family:"HLR Name","Songti SC",serif}
/* 字数：叶子右下方外侧，很淡 */
.ed-count{align-self:flex-end;height:0;overflow:visible;line-height:1;
  transform:translateY(calc(var(--u) * -2));
  color:rgba(240,245,242,.55);font-size:calc(var(--u) * 2.1);letter-spacing:.12em}
/* 色板：六个色点（五男主 红绿黄蓝紫 + 粉），选中亮环 */
.ed-pal{display:flex;gap:calc(var(--u) * 3)}
.ed-dot{width:calc(var(--u) * 4.6);height:calc(var(--u) * 4.6);border-radius:50%;
  border:1px solid rgba(255,255,255,.55);background:var(--lc);cursor:pointer;padding:0;
  transition:box-shadow .25s ease, transform .25s ease}
.ed-dot.sel{box-shadow:0 0 0 calc(var(--u) * .55) rgba(255,255,255,.85);transform:scale(1.08)}
/* 按钮行：与站内确认框同款 */
.ed-btns{display:flex;gap:calc(var(--u) * 3);margin-top:calc(var(--u) * .4)}
.ed-btns button{font:inherit;font-size:calc(var(--u) * 3);letter-spacing:.18em;text-indent:.18em;
  border-radius:2.2em;padding:.5em 2.2em;cursor:pointer;
  color:#ece9f6;background:rgba(26,20,48,.55);border:1px solid rgba(214,208,255,.4)}
.ed-btns button.pri{color:#fff;background:linear-gradient(180deg,#a39ddc,#8a84c8);
  border-color:rgba(255,255,255,.5);box-shadow:0 2px 14px rgba(80,72,140,.4)}
.ed-btns button.pri:disabled{background:rgba(150,153,165,.4);border-color:rgba(255,255,255,.3);
  color:rgba(255,255,255,.7);box-shadow:none;cursor:default}

/* ---------- 提交演出：叶子飞走 ---------- */
#bd-fly{position:absolute;inset:0;z-index:6;pointer-events:none;overflow:hidden}
#bd-fly .lf{animation:none}
/* 投稿：纸就是编辑器里那张真纸，靠 #bd-ed.out 原地淡掉（1.3s）。
   这里只留几点伴随的微光——不再造纸的副本，副本没有信纸横线，看着像张空白假纸 */
.fly-sp{position:absolute;width:calc(var(--u) * 1.2);height:calc(var(--u) * 1.2);border-radius:50%;
  background:radial-gradient(closest-side, rgba(255,255,250,.95), rgba(255,255,250,0));
  animation:fly-sp 1.6s ease-out forwards}
@keyframes fly-sp{
  0%{transform:translate(0,0) scale(.6);opacity:0}
  20%{opacity:1}
  100%{transform:translate(calc(var(--u) * 14),calc(var(--u) * -22)) scale(0);opacity:0}
}
/* 提交完的轻提示 */
/* 投稿后的一句话：画面正中，淡入 → 停 → 淡出，全程不挡点击 */
#bd-toast{position:absolute;left:50%;top:46%;transform:translate(-50%,-50%);z-index:7;
  font-family:"HLR Name","Songti SC","STSong",serif;
  color:#f4f2ea;font-size:calc(var(--u) * 4.2);letter-spacing:.22em;text-indent:.22em;
  text-shadow:0 calc(var(--u) * .25) calc(var(--u) * 1.4) rgba(8,20,16,.75),
    0 0 calc(var(--u) * 3.4) rgba(8,20,16,.5);white-space:nowrap;
  opacity:0;transition:opacity .9s ease;pointer-events:none}
#bd-toast.on{opacity:1}

/* ---------- 对比试验：纸条样式（#board.paper 切换，排布共用） ---------- */
#board.paper .lf-bg{-webkit-mask:none;mask:none;
  border-radius:calc(var(--u) * 1.1);
  filter:brightness(1.22) saturate(.72);
  box-shadow:0 calc(var(--u) * .45) calc(var(--u) * 1.5) rgba(12,28,22,.32),
    inset 0 0 0 1px rgba(255,255,255,.25)}
#board.paper .lf{color:#3f5147;text-shadow:none}
/* 顶部一截半透明胶带 */
#board.paper .lf::after{content:'';position:absolute;left:50%;top:-3.5%;
  width:20%;height:10%;transform:translateX(-50%) rotate(-2.5deg);
  background:rgba(252,252,248,.42);
  box-shadow:0 1px 3px rgba(10,25,20,.15);
  border-left:1px dashed rgba(255,255,255,.35);border-right:1px dashed rgba(255,255,255,.35)}
/* 纸条比叶子能装：文字区放宽一点 */
#board.paper .lf-tx{left:11%;right:11%;top:11%;bottom:12%}

/* ---------- Plan B：等宽纸卡（#board.card，?wall=card 切换） ----------
   与叶子版并存：叶子版 CSS 一行不动，这里只覆盖。
   所有尺寸按心穹尾迹（sistery，390 基准）换算到画面高 100u：13px→3.3u、14px→3.6u……
   纸 = 五色纸底 + 半透描边 + 噪点纸纹(SVG feTurbulence 静态平铺) + 内侧轻晕，墨色深灰；
   顶边中央一片叶子当固定物。宽统一、高随内容，JS 三列瀑布流。
   变量由 JS paintEl 给：--pb 纸色 --ps 描边 --pi 墨色 --pp 叶色 --rot 歪角 */
#board.card .lf{width:calc(var(--u) * 30);height:auto;color:var(--pi,#52604a);text-shadow:none;
  font-size:calc(var(--u) * 2.5);line-height:2;letter-spacing:.04em;font-weight:400}
#board.card .lf.lf-s,#board.card .lf.lf-m,#board.card .lf.lf-l{width:calc(var(--u) * 30);height:auto}
#board.card .lf-bg{-webkit-mask:none;mask:none;
  border-radius:calc(var(--u) * .3);
  background:var(--pb,#f4f9f0);
  box-shadow:0 calc(var(--u) * .55) calc(var(--u) * 1.6) rgba(70,45,25,.30),
    0 0 0 1px var(--ps,rgba(168,188,152,.6)),
    inset 0 0 calc(var(--u) * 2.4) rgba(120,90,60,.10);
  transform:rotate(var(--rot,0deg))}
/* 纸纹：只叠一层静态噪点颗粒 */
#board.card .lf-bg::before{content:'';position:absolute;inset:0;border-radius:inherit;
  opacity:.5;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .42 0 0 0 0 .34 0 0 0 0 .24 0 0 0 .5 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size:160px 160px;
  mix-blend-mode:multiply}
/* 固定物：一片叶子压在顶边中央，微斜；::before 同形投影（下移、半透黑）+ ::after 叶子，各自 mask */
#board.card .lf-pin{position:absolute;left:50%;top:calc(var(--u) * -1.5);
  width:calc(var(--u) * 7.4);height:calc(var(--u) * 4.3);margin-left:calc(var(--u) * -3.7);
  transform:rotate(var(--rot,0deg));pointer-events:none}
#board.card .lf-pin::before,#board.card .lf-pin::after{content:'';position:absolute;inset:0;
  transform:rotate(-14deg);
  -webkit-mask:url(../assets/ui/leaf.webp?v=164) center/100% 100% no-repeat;
  mask:url(../assets/ui/leaf.webp?v=164) center/100% 100% no-repeat}
#board.card .lf-pin::before{background:rgba(20,30,15,.28);
  transform:translate(calc(var(--u) * .2),calc(var(--u) * .65)) rotate(-14deg)}
#board.card .lf-pin::after{background:var(--pp,#6c9668)}
/* 文字区：一两行的短留言撑到近方形（30×24），三行起随内容长，字多的永远不比字少的矮 */
#board.card .lf-tx{position:relative;inset:auto;display:flex;flex-direction:column;
  box-sizing:border-box;min-height:calc(var(--u) * 24);
  padding:calc(var(--u) * 3.4) calc(var(--u) * 3) calc(var(--u) * 2.2);
  transform:rotate(var(--rot,0deg))}
#board.card .lf-tx p{line-height:2}
#board.card .lf-sig{margin-top:auto;padding-top:calc(var(--u) * .8);padding-right:0;opacity:1;
  color:#b08f53;font-size:.85em;letter-spacing:.06em}
#board.card .lf-anon{color:#b0a88c}
/* 编辑器：一张横向信纸 84×58u，叶子夹带投影压顶边中央。淡横线间距 = 行高，字坐在线上；
   正文 3.1u（手机上要看得清）、行高 2.0 → 一行约 23 字，可见 7 行，再长在纸内滚动。 */
#board.card #bd-ed .lf,#board.card #bd-ed .lf.lf-s,#board.card #bd-ed .lf.lf-m,#board.card #bd-ed .lf.lf-l{
  width:calc(var(--u) * 84);height:calc(var(--u) * 58);min-height:0;display:block;padding:0;
  font-size:calc(var(--u) * 3.1);line-height:2;--rot:-.4deg}
#board.card #bd-ed .lf-bg::after{display:none}
/* 叶子夹：::before 投影（同形、下移、半透黑）+ ::after 叶子，各自 mask */
#board.card .ed-pin{position:absolute;left:50%;top:calc(var(--u) * -1.8);
  width:calc(var(--u) * 9.4);height:calc(var(--u) * 5.4);margin-left:calc(var(--u) * -4.7);
  transform:rotate(var(--rot,0deg));pointer-events:none}
#board.card .ed-pin::before,#board.card .ed-pin::after{content:'';position:absolute;inset:0;
  transform:rotate(-12deg);
  -webkit-mask:url(../assets/ui/leaf.webp?v=164) center/100% 100% no-repeat;
  mask:url(../assets/ui/leaf.webp?v=164) center/100% 100% no-repeat}
#board.card .ed-pin::before{background:rgba(20,30,15,.28);transform:translate(calc(var(--u) * .3),calc(var(--u) * .9)) rotate(-12deg)}
#board.card .ed-pin::after{background:var(--pp,#6c9668)}
#board.card #bd-ed .lf-bg{box-shadow:0 calc(var(--u) * 1.2) calc(var(--u) * 3.6) rgba(40,30,15,.35),
  0 0 0 1px var(--ps),inset 0 0 calc(var(--u) * 3) rgba(120,90,60,.08)}
/* 横线：每行一条，压在字底下一点 */
#board.card .ed-tx{position:absolute;left:calc(var(--u) * 5);right:calc(var(--u) * 5);
  top:calc(var(--u) * 4.4);bottom:calc(var(--u) * 10.2);
  background-image:repeating-linear-gradient(to bottom,transparent 0 calc(var(--u) * 5.3),
    var(--pl,rgba(120,150,110,.22)) calc(var(--u) * 5.3) calc(var(--u) * 5.3 + 1px),transparent calc(var(--u) * 5.3 + 1px) calc(var(--u) * 6.2))}
#board.card #ed-text{height:100%;line-height:2;padding:0;caret-color:var(--pi);overflow-y:auto;scrollbar-width:none}
#board.card #ed-text::-webkit-scrollbar{display:none}
#board.card #ed-text::placeholder,#board.card #ed-sig::placeholder{color:#b0a88c;font-family:inherit}
#board.card .ed-sig{position:absolute;inset:auto;right:calc(var(--u) * 5);bottom:calc(var(--u) * 3.4);
  color:#b08f53;opacity:1;font-size:.85em;letter-spacing:.06em;line-height:1.72}
#board.card #ed-sig{width:5em;text-align:left;border-bottom:1px dashed rgba(176,143,83,.35);
  caret-color:#b08f53;padding-bottom:0;transition:width .15s ease}
#board.card .ed-count{font-size:calc(var(--u) * 1.9);color:rgba(230,224,204,.55);letter-spacing:.1em;
  transform:translateY(calc(var(--u) * -1))}
/* 选纸：五张小方纸并排，选中的抬起来、顶上压一片小叶子 */
#board.card .ed-pal{gap:calc(var(--u) * 3);align-items:flex-end}
#board.card .ed-dot{position:relative;width:calc(var(--u) * 5.2);height:calc(var(--u) * 5.2);
  border-radius:calc(var(--u) * .3);border:1px solid var(--ring);
  background:var(--lc);box-shadow:0 calc(var(--u) * .3) calc(var(--u) * .9) rgba(0,0,0,.28);
  transform:rotate(-2deg);transition:transform .2s ease, box-shadow .2s ease}
#board.card .ed-dot:nth-child(2n){transform:rotate(2deg)}
#board.card .ed-dot::after{content:'';position:absolute;left:50%;top:calc(var(--u) * -.9);
  width:calc(var(--u) * 3.6);height:calc(var(--u) * 2.1);margin-left:calc(var(--u) * -1.8);
  background:#6c9668;transform:rotate(-14deg);opacity:0;transition:opacity .2s ease;
  -webkit-mask:url(../assets/ui/leaf.webp?v=164) center/100% 100% no-repeat;
  mask:url(../assets/ui/leaf.webp?v=164) center/100% 100% no-repeat}
#board.card .ed-dot.sel{transform:translateY(calc(var(--u) * -.9)) rotate(0);
  box-shadow:0 calc(var(--u) * .8) calc(var(--u) * 1.8) rgba(0,0,0,.4)}
#board.card .ed-dot.sel::after{opacity:1}
#board.card .ed-btns button{font-size:calc(var(--u) * 2.5);padding:.42em 1.9em}
#board.card .ed-wrap{gap:calc(var(--u) * 2.4)}
.ed-count,.ed-pal,.ed-btns{transition:opacity .2s ease}
/* 蜜罐输入框：挪出画面、不可见、不接指针、不进 tab 序。别用 display:none——
   有些脚本会跳过彻底隐藏的字段，这样藏反而更容易上钩 */
.ed-hp{position:absolute;left:-9999px;top:0;width:1px;height:1px;opacity:0;
  pointer-events:none;border:0;padding:0}
/* 纸上的正文/署名是只读预览，点一下开写字态：不要文本光标，给个手型 */
#board.card #ed-text,#board.card #ed-sig,#board.card .ed-sig{cursor:pointer;caret-color:transparent}

/* ---------- 写字态面板（软键盘避让的正解，取代 v90 的缩放平移）----------
   纸卡按画面盒定尺寸，键盘一弹可见区就比纸矮，缩放/顶起都救不回来（缩了看不清、
   顶了切上半、光标还不跟随换行）。所以打字时干脆不要那张纸：另开一个输入框浮在
   可见区顶部，textarea 自己滚、光标由浏览器原生跟随。
   样式**刻意做成类原生**（白底细边、系统字体、聚焦蓝边）：这是「打字的地方」，
   一眼就懂，不跟纸卡的手绘皮混在一起。
   宽度对齐画面盒 #view（左右毛玻璃区不碰），高度跟着内容长，封顶 46vh：
   即使 visualViewport 的数不可信（v90 的死因），键盘在下半屏也盖不到。 */
#ed-kb{position:fixed;left:0;top:0;width:100%;height:100%;z-index:60;display:none}
#ed-kb.on{display:block}   /* 整层拦点击：点面板外＝完成，不许漏到下面的纸上 */
#ed-kb .kb-in{position:absolute;left:0;top:0;box-sizing:border-box;
  display:flex;flex-direction:column;overflow:hidden;
  padding:10px 12px 6px;background:#fff;border-radius:10px;
  border:1px solid #c7ccd4;box-shadow:0 4px 16px rgba(0,0,0,.18);
  animation:kb-drop .2s ease-out}
#ed-kb .kb-in.foc{border-color:#5b9bf8;box-shadow:0 0 0 1px #5b9bf8, 0 4px 16px rgba(0,0,0,.18)}
@keyframes kb-drop{from{transform:translateY(-12px);opacity:0}}
#kb-text,#kb-sig{position:relative;display:none;width:100%;box-sizing:border-box;flex:none;
  background:none;border:none;outline:none;resize:none;color:#1c1c1e;
  font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue",
    "PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif;
  -webkit-text-size-adjust:100%}
#kb-text{font-size:17px;line-height:1.55;overflow-y:auto}
#kb-sig{font-size:17px;line-height:1.8}
#ed-kb.text #kb-text{display:block}
#ed-kb.sig #kb-sig{display:block}
#kb-text::placeholder,#kb-sig::placeholder{color:#b0b3ba}
/* 底栏：只有字数，很轻。没有「完成」按钮——iOS 用 Safari 辅助栏的 ✓、安卓用返回键收
   键盘，两者都会被 kbWatch 接住自动写回（详见 main.js） */
#ed-kb .kb-bar{position:relative;display:flex;justify-content:flex-end;flex:none;margin-top:2px}
#kb-count{font-size:12px;color:#9a9ea6;font-variant-numeric:tabular-nums;
  font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif}
/* 深色模式：既然是类原生的输入框，就跟着系统走一套暗色（iOS 深色的那套灰和蓝） */
@media (prefers-color-scheme: dark){
  #ed-kb .kb-in{background:#1c1c1e;border-color:#3f3f42;
    box-shadow:0 4px 18px rgba(0,0,0,.55)}
  #ed-kb .kb-in.foc{border-color:#0a84ff;box-shadow:0 0 0 1px #0a84ff, 0 4px 18px rgba(0,0,0,.55)}
  #kb-text,#kb-sig{color:#f2f2f7}
  #kb-text::placeholder,#kb-sig::placeholder{color:#6d6d72}
  #kb-count{color:#79797f}
}

/* ---------- 心音墙里的弹窗 / 按钮：纸 + 叶的配色，不用游戏里的紫 ----------
   showDialog 在墙打开时给 #dlg 加 .bd，整体换皮（退出确认、投稿须知都走这套） */
#dlg.bd{background:rgba(8,20,16,.42)}
#dlg.bd #dlg-in{max-width:74%;border-radius:calc(var(--u) * .3);   /* 直角纸卡，同便签 */
  background:#f6f2e4;border:1px solid rgba(150,125,70,.45);
  box-shadow:0 calc(var(--u) * 1.5) calc(var(--u) * 5) rgba(10,25,18,.45);
  backdrop-filter:none;-webkit-backdrop-filter:none;position:relative;overflow:hidden}
#dlg.bd #dlg-in::before{content:'';position:absolute;inset:0;pointer-events:none;opacity:.35;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .42 0 0 0 0 .34 0 0 0 0 .24 0 0 0 .5 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size:160px 160px;mix-blend-mode:multiply}
#dlg.bd #dlg-t{color:#4d5a48;position:relative}
#dlg.bd #dlg-b{position:relative}
#dlg.bd #dlg-b button{color:#4d6a52;background:rgba(255,255,255,.55);border:1px solid rgba(95,145,102,.55);
  border-radius:2.2em;padding:.5em 2.4em}   /* 药丸，和站内其他按钮一致 */
#dlg.bd #dlg-b button.pri{color:#f4f7ee;background:linear-gradient(160deg,#79a878,#5f9166);   /* 叶绿，与叶子同源 */
  border-color:rgba(255,255,255,.4);box-shadow:0 2px 10px rgba(60,100,70,.3)}
/* 投稿须知：标题 + 细线上一片小叶 + 四条 */
.bd-notice{text-align:left}
.bd-notice h3{margin:0;text-align:center;font-size:calc(var(--u) * 3.6);letter-spacing:.32em;text-indent:.32em;
  color:#3f5a47;font-weight:700;line-height:1.6}
/* 分割线：同制作名单的菱形细线（两侧渐隐 + 中央 45° 小方块），配色换成纸卡的金棕 */
.bd-orn{display:flex;align-items:center;justify-content:center;gap:calc(var(--u) * 1.4);
  margin:calc(var(--u) * 1.6) auto calc(var(--u) * 2.6)}
.bd-orn::before,.bd-orn::after{content:'';width:calc(var(--u) * 12);height:1px}
.bd-orn::before{background:linear-gradient(90deg,rgba(150,125,70,0),rgba(150,125,70,.7))}
.bd-orn::after{background:linear-gradient(90deg,rgba(150,125,70,.7),rgba(150,125,70,0))}
.bd-orn i{width:calc(var(--u) * 1);height:calc(var(--u) * 1);transform:rotate(45deg);background:rgba(150,125,70,.8)}
.bd-notice ul{margin:0;padding:0}
.bd-notice li{list-style:none;position:relative;padding-left:calc(var(--u) * 2.8);
  font-size:calc(var(--u) * 2.6);line-height:2;letter-spacing:.06em;color:#4d5a48;font-weight:400}
.bd-notice li::before{content:'';position:absolute;left:calc(var(--u) * .4);top:calc(1em - var(--u) * .2);
  width:calc(var(--u) * .9);height:calc(var(--u) * .9);border-radius:50%;background:#8fb380}
/* 编辑器按钮同套 */
/* 与弹窗按钮同一套青绿、同一种小圆角矩形 */
#board.card .ed-btns button{color:#4d6a52;background:rgba(246,242,228,.85);border:1px solid rgba(95,145,102,.55);
  border-radius:2.2em;padding:.5em 2.4em}
#board.card .ed-btns button.pri{color:#f4f7ee;background:linear-gradient(160deg,#79a878,#5f9166);
  border-color:rgba(255,255,255,.4);box-shadow:0 2px 10px rgba(60,100,70,.3)}
#board.card .ed-btns button.pri:disabled{color:rgba(255,255,255,.75);background:rgba(120,140,125,.45);
  border-color:rgba(255,255,255,.3);box-shadow:none}

/* 截配图用（?dev=…&shot=1）：把 HUD 藏掉 */

/* 二周目声明快进：点一下这一屏的东西直接出来，过渡压到 .25s */
#disc.fast .disc-core p,#disc.fast .disc-ear,#disc.fast #disc-hint,
#disc.fast .disc-sub,#disc.fast #disc-agree,#disc.fast #disc-go{transition-duration:.25s}

/* ---------- 章节地图（左上 ◇）----------
   游戏路线图式：一条路横穿画面正中，五颗菱形节点等距落在路上，卡片上下交错挂在节点上
   （贰肆在路上方、壹叁伍在下方）。交错后卡宽能到 34u（16:9 → 19.1u 高），互不相挤 */
#map{position:absolute;inset:0;z-index:13;cursor:pointer;background:rgba(8,6,18,.82);
  opacity:0;visibility:hidden;transition:opacity .4s ease, visibility 0s .4s;
  font-family:"HLR Name","Songti SC","Noto Serif SC",serif;font-weight:700;color:#f2f0ea}
#map.on{opacity:1;visibility:visible;transition:opacity .4s ease}
#map-in{position:absolute;inset:0}
/* 路：走过的那段亮、没走到的暗（.mp-road 分段，宽度由 JS 定） */
.mp-road{position:absolute;top:50%;height:1px;background:rgba(242,240,234,.3)}
.mp-road.done{background:rgba(242,240,234,.6)}
/* 节点：落在路上的菱形，实心深底盖住路线 */
.mp-node{position:absolute;top:50%;width:calc(var(--u) * 1.5);height:calc(var(--u) * 1.5);
  transform:translate(-50%,-50%) rotate(45deg);
  border:1px solid rgba(242,240,234,.85);background:#1b1727}
.mp-node.cur{background:#fff;box-shadow:0 0 calc(var(--u) * 1.8) rgba(255,255,255,.9)}
.mp-node.dim{border-color:rgba(242,240,234,.35)}
/* 卡片：绝对定位在节点正上/正下，靠一根短竖线（stub）挂到节点 */
.mp-card{position:absolute;width:calc(var(--u) * 34);transform:translateX(-50%);
  display:flex;flex-direction:column;align-items:center;cursor:pointer}
.mp-card.up{bottom:50%}
.mp-card.dn{top:50%;flex-direction:column-reverse}
#map.on .mp-card{animation:mp-in .7s ease-out both}
@keyframes mp-in{0%{opacity:0;transform:translateX(-50%) translateY(calc(var(--u) * 1.6))}100%{opacity:1;transform:translateX(-50%)}}
.mp-card.soon{cursor:default}
.mp-stub{width:1px;height:calc(var(--u) * 5.2);background:rgba(242,240,234,.5)}
.mp-card.soon .mp-stub{background:rgba(242,240,234,.22)}
.mp-name{font-size:calc(var(--u) * 3.1);letter-spacing:.32em;text-indent:.32em;line-height:1.4;
  margin:calc(var(--u) * 1.1) 0 calc(var(--u) * .5)}
.mp-card.dn .mp-name{margin:calc(var(--u) * .5) 0 calc(var(--u) * 1.1)}
.mp-name b{font-weight:inherit;font-size:.68em;letter-spacing:.12em;color:#b4aecb;margin-right:.9em}
.mp-card.soon .mp-name{color:#8f8aa6}
.mp-card.soon .mp-name b{color:#6f6a86}
.mp-thumb{position:relative;width:100%;height:calc(var(--u) * 19.1);border-radius:calc(var(--u) * 1.4);overflow:hidden;
  background:#1a1626 center/cover no-repeat;border:1px solid rgba(255,255,255,.3);
  box-shadow:0 calc(var(--u) * 1) calc(var(--u) * 3) rgba(0,0,0,.5);
  transition:transform .35s ease, border-color .35s ease, box-shadow .35s ease}
.mp-thumb::after{content:'';position:absolute;inset:0;border-radius:inherit;box-shadow:inset 0 1px 0 rgba(255,255,255,.35)}
.mp-card:not(.soon):hover .mp-thumb{transform:translateY(calc(var(--u) * -.6));border-color:rgba(255,255,255,.7)}
.mp-card:not(.soon):active .mp-thumb{transform:scale(.985)}
.mp-card.cur .mp-thumb{border-color:rgba(255,255,255,.9);
  box-shadow:0 0 0 1px rgba(255,255,255,.55),0 0 calc(var(--u) * 3) rgba(214,208,255,.6),
    0 calc(var(--u) * 1) calc(var(--u) * 3) rgba(0,0,0,.5)}
.mp-card.soon .mp-thumb{background:linear-gradient(160deg,#2c2742,#151021);border-color:rgba(255,255,255,.16);box-shadow:none}
.mp-tag{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);white-space:nowrap;
  font-size:calc(var(--u) * 2.3);letter-spacing:.3em;text-indent:.3em;color:#9a95b4}
#map-close{position:absolute;left:50%;bottom:calc(var(--u) * 4);transform:translateX(-50%);
  color:#fff;font-size:calc(var(--u) * 2);letter-spacing:.18em;animation:ftx-blink 2.2s ease-in-out infinite}
