/* 幽墟回廊 —— 亮色石廊主题 */
:root{
  --void:#F1EBDD; --stone:#FCF8F0; --stone-2:#F6F1E5; --stone-3:#ECE5D5;
  --edge:#CDC0A7; --edge-soft:#E0D7C4;
  --bone:#2E2A23; --dim:#655D50; --faint:#7E7566;
  --torch:#9C6A10; --torch-deep:#7A520C; --coin:#E3B23C;
  --blood:#A93729; --venom:#47702F; --frost:#266F7B;
  --hero:#245E8C;
  --floor:#FCF8ED; --floor-dim:#EEE7D8; --wall:#B7A78A; --wall-dim:#CCC1AA;
  --unseen:#E4DDCE; --dot:#C6B99F; --dot-dim:#D6CCB7;
  --r0:#6B665C; --r1:#2A62AD; --r2:#8E6F10; --r3:#6F3D98; --r4:#B45B12;
  --disp:"Cinzel","Songti SC",Georgia,serif;
  --body:"PingFang SC","Microsoft YaHei","Noto Sans CJK SC",system-ui,-apple-system,sans-serif;
  --mono:ui-monospace,"SFMono-Regular","Noto Sans Mono",Consolas,"PingFang SC",monospace;
  --flavor:"Spectral","Songti SC",Georgia,serif;
}
*{box-sizing:border-box}
/* 必须自己声明：下面很多类显式设了 display，会盖掉浏览器对 hidden 的默认样式。
   artifact 外壳自带这条，所以缺了只有本地会穿帮。 */
[hidden]{display:none !important}
html,body{height:100%}
/* 双击不放大、也不给页面回弹的空间 —— 整个界面是固定一屏的游戏画面。
   manipulation 只砍掉「双击缩放」这一项，单击、滚动、长按全都照常。 */
/* ⚠️ tap-highlight 一并关掉：iOS 点完按钮会留一块灰罩子，看着就像选项上糊了一层阴影。 */
html{touch-action:manipulation;-webkit-text-size-adjust:100%;text-size-adjust:100%;
  -webkit-tap-highlight-color:transparent}
body{
  background:var(--void);
  background-image:radial-gradient(95% 60% at 50% 0%, #FDFAF3 0%, var(--void) 75%);
  background-attachment:fixed;
  color:var(--bone); font-family:var(--body); font-size:14px; line-height:1.5;
  -webkit-font-smoothing:antialiased;
  margin:0; overflow:hidden;
}

/* ===== 应用外壳：地图为主体，底部四标签固定 =====
   整页不滚动，只有各视图内部滚。用 dvh 是为了躲开手机浏览器的地址栏伸缩。 */
.app{
  height:100dvh; max-width:980px; margin-inline:auto;
  display:flex; flex-direction:column; gap:10px;
  padding:14px 16px 0; overflow:hidden;
}
.views{flex:1; min-height:0; display:flex}
.view{flex:1; min-width:0; display:none; flex-direction:column; gap:10px}
.view.on{display:flex}
/* 冒险以外的标签页内容是竖着排的列表，自己滚。 */
#viewInfo,#viewSet{overflow-y:auto; padding-bottom:4px}
/* 遗物页是个例外：**整页不滚**，滚的是遗物列表本身 ——
   合成面板钉在标签页下方，带满 15 件时不用滚半天才看得见它（用户 2026-09）。
   ⚠️ 要滚的是 .relics，不是 #viewRelic；给 .panel.grow 留 min-height:0，否则 flex 不肯收缩。 */
#viewRelic{overflow:hidden; padding-bottom:4px}
#viewRelic .panel.grow{flex:1; min-height:0}
#viewRelic .panel.grow .relics{flex:1; min-height:0; overflow-y:auto;
  /* 左上角那个「new」小红点是探出卡片外的，滚动容器会裁掉它 —— 先让出这一圈 */
  padding:6px 2px 0 6px; margin:-6px -2px 0 -6px}
#viewRelic .panel.fusebar{flex:none}

/* ===== 底部标签栏 ===== */
.tabbar{
  flex:none; display:grid; grid-template-columns:repeat(4,1fr); gap:2px;
  border-top:1px solid var(--edge); background:var(--stone);
  margin-inline:-16px; padding:4px 6px calc(4px + env(safe-area-inset-bottom));
}
.nav{
  position:relative; background:none; border:0; border-radius:3px; cursor:pointer;
  font-family:var(--body); color:var(--faint);
  display:flex; flex-direction:column; align-items:center; gap:1px; padding:6px 2px 5px;
}
.nav i{font-style:normal; font-family:var(--mono); font-size:17px; line-height:1}
.nav span{font-size:11px; letter-spacing:.08em}
.nav:hover{color:var(--dim)}
.nav.on{color:var(--torch); background:var(--stone-3)}
.nav.on i{color:var(--torch)}
.nav .dot{position:absolute; top:4px; right:50%; margin-right:-20px;
  min-width:15px; height:15px; padding:0 4px; border-radius:8px;
  background:var(--blood); color:#FFF3EF; font-style:normal;
  font-family:var(--mono); font-size:10px; line-height:15px; text-align:center}
.nav .dot[hidden]{display:none}

/* ===== 错误横幅（调试用） ===== */
.errbar{position:fixed;left:0;right:0;top:0;z-index:99;background:#7E2116;color:#FFE9E4;
  font-family:var(--mono);font-size:12px;line-height:1.45;padding:8px 12px;
  display:flex;gap:10px;align-items:flex-start;box-shadow:0 2px 10px rgba(0,0,0,.3)}
.errbar[hidden]{display:none !important}
.errbar .msg{flex:1;min-width:0;word-break:break-word;white-space:pre-wrap}
.errbar button{background:#FFE9E4;color:#7E2116;border:0;border-radius:2px;
  font-family:var(--body);font-size:11.5px;padding:3px 9px;cursor:pointer;flex:none}

/* ===== 顶栏 ===== */
.top{flex:none;display:flex;align-items:baseline;justify-content:space-between;gap:10px;flex-wrap:wrap}
.title{display:flex;align-items:baseline;gap:9px;min-width:0;flex-wrap:wrap}
.title h1{font-family:var(--disp);font-weight:700;font-size:20px;margin:0;letter-spacing:.06em;line-height:1}
.title .ch{font-family:var(--mono);font-size:11.5px;color:var(--torch);letter-spacing:.12em}
.tbtns{display:flex;gap:6px}
.tbtn{background:none;border:1px solid var(--edge);color:var(--dim);font-family:var(--body);
  font-size:12px;padding:5px 10px;border-radius:2px;cursor:pointer}
.tbtn:hover{border-color:var(--torch-deep);color:var(--torch)}

/* ===== 状态行：一行装下章节+层/等级/金/剩敌 ===== */
.hudline{display:flex;align-items:center;gap:0;border:1px solid var(--edge);
  background:var(--stone);border-radius:2px;overflow:hidden}
.hi{flex:1;min-width:0;display:flex;align-items:baseline;justify-content:center;gap:5px;
  padding:4px 6px;border-left:1px solid var(--edge-soft)}
.hi:first-child{border-left:0}
.hi i{font-style:normal;font-size:10.5px;color:var(--faint);flex:none}
.hi b{font-family:var(--mono);font-size:14px;font-weight:600;font-variant-numeric:tabular-nums;
  letter-spacing:.02em}
/* Boss 房那一层（第 10/20/30/40/50 层）在顶栏写成 `10*`，血色（用户 2026-09） */
.hi b.bossfloor{color:var(--blood)}
.hi.gold b{color:var(--torch)}
.hi.left b{color:var(--blood)}
.hi.done b{color:var(--venom);font-size:12px}

/* ===== 血条 / 经验条 =====
   血是每一题都要瞄一眼的东西，做厚做显眼；经验退成一条细缝。 */
.bars{display:flex;flex-direction:column;gap:3px}
.hpbar{height:19px;border:1px solid var(--edge);background:#E7E0CF;border-radius:2px;
  position:relative;overflow:hidden}
.hpbar .fill{position:absolute;inset:0;width:0;
  background:linear-gradient(180deg,#E8978B,#D2685A);transition:width .22s ease}
.hpbar .txt{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  font-family:var(--mono);font-size:12px;font-weight:600;letter-spacing:.04em;
  color:#2B2620;text-shadow:0 1px 0 rgba(255,255,255,.6);font-variant-numeric:tabular-nums}
/* 护盾：压在血条上的一段冷色，盾满上限时正好铺满一条。
   ⚠️ 它在 .fill 之后、.txt 之前 —— 盖得住血、盖不住字。宽度按「盾 / 生命上限」算并夹在 100%，
   盾可以比上限还高（凝盾能攒到 300），铺满就是铺满。 */
/* ⚠️ 盾只占**上半条**：凝盾能攒到 300，铺满整条的话红色的血就整个被盖住，
   低血告警（.low / .crit 那两条）等于失效。压上半条，血色永远还露着下半截。*/
.hpbar .sh{position:absolute;left:0;top:0;height:42%;width:0;background:var(--frost);opacity:.6;
  border-bottom:1px solid rgba(255,255,255,.45);transition:width .22s ease}
.hpbar .shn{color:#DFF1F4;margin-left:6px;text-shadow:0 1px 1px rgba(0,0,0,.45)}
/* 血量告急：颜色变深，并轻轻搏动 */
.hpbar.low .fill{background:linear-gradient(180deg,#D4604F,#B03726)}
.hpbar.low .txt{color:#FFF1ED;text-shadow:0 1px 1px rgba(0,0,0,.45)}
.hpbar.crit .fill{background:linear-gradient(180deg,#C13B26,#8E1F0F);animation:pulse 1s ease-in-out infinite}
@keyframes pulse{0%,100%{opacity:1}50%{opacity:.62}}
@media (prefers-reduced-motion:reduce){.hpbar.crit .fill{animation:none}}
/* 掉血 / 回血各播一次 0.65s 的反馈（用户 2026-09）——
   game.js 的 paintHp 一发现数变了就挂 .hurt / .heal，HP_FX_MS 之后摘掉。
   ⚠️ 只用 transform 和一层 ::after 的闪光，**不许动布局**：血条上下都贴着别的东西，一顶就跳。 */
/* ⚠️ 闪光走 ::after，**不能用 inset box-shadow** —— .fill / .sh / .txt 都是定位子元素，
   会把父元素的内阴影整个盖住。::after 是最后一个生成盒，压在所有子元素上面。*/
.hpbar::after{content:"";position:absolute;inset:0;pointer-events:none;opacity:0;background:transparent}
.hpbar.hurt{animation:hphurt .65s ease-out}
.hpbar.heal{animation:hpheal .65s ease-out}
.hpbar.hurt::after{background:var(--blood);animation:hpflash .65s ease-out}
.hpbar.heal::after{background:var(--venom);animation:hpflash .65s ease-out}
@keyframes hpflash{0%{opacity:.5}100%{opacity:0}}
@keyframes hphurt{
  0%,100%{transform:translateX(0)}
  14%{transform:translateX(-3px)}
  32%{transform:translateX(3px)}
  50%{transform:translateX(-2px)}
  68%{transform:translateX(1px)}
}
@keyframes hpheal{
  0%,100%{transform:scaleY(1)}
  32%{transform:scaleY(1.1)}
}
@media (prefers-reduced-motion:reduce){
  .hpbar.hurt,.hpbar.heal,.hpbar.hurt::after,.hpbar.heal::after{animation:none}
}

/* 经验条：用户 2026-09 把它加粗一倍（5 → 10px，浮层里 3 → 6px）并改成金色。
   ⚠️ 加粗的是条子本身的高度 —— 它横向本来就铺满，没有别的「宽度」可翻。*/
.xpbar{height:10px;border:1px solid var(--edge-soft);background:#EAE4D5;border-radius:2px;
  position:relative;overflow:hidden}
.xpbar .fill{position:absolute;inset:0;width:0;
  background:linear-gradient(180deg,#F0CE72,var(--coin));transition:width .22s ease}

.strip{display:grid;grid-template-columns:1fr 1fr;gap:12px;align-items:start}
@media (max-width:700px){.strip{grid-template-columns:1fr}}

/* ===== 地图 ===== */
/* stage 只是个居中容器（满宽，好让 sizeMap 量到可用宽度）；
   石框画在 map 自己身上，这样地图多窄框就多窄，桌面上不会两边空一大片 */
/* stage = 取景窗：尺寸由 sizeMap 算好写死，超出部分裁掉。
   .map 是完整地图，靠 transform 平移来实现镜头跟随。*/
/* 背景跟「没探过的格子」同色：镜头永远居中，走到地图边缘时取景窗会露出地图外面，
   同色才看不出接缝 —— 露出来的那块就像还没走到的黑暗。 */
.stage{flex:0 1 auto;align-self:center;position:relative;overflow:hidden;
  border:1px solid var(--edge);background:var(--unseen);border-radius:3px;
  box-shadow:inset 0 1px 5px rgba(90,76,50,.28)}
.map{position:absolute;top:0;left:0;display:grid;gap:0;width:max-content;
  will-change:transform}

/* ===== 地图上的状态浮层 =====
   层/等级/金/敌 + 血条压在取景窗顶上，不再吃纵向预算 —— 地图因此大一圈。
   pointer-events:none 让点击穿过去落到底下的格子，整张地图仍然可点。
   半透明是故意的：挡住的那一行还看得见。 */
.mapui{position:absolute;left:0;right:0;top:0;z-index:2;pointer-events:none;
  display:flex;flex-direction:column;gap:1px;padding:2px 2px 4px;
  background:linear-gradient(180deg,
    rgba(246,241,229,.90) 0%, rgba(246,241,229,.84) 68%, rgba(246,241,229,.42) 100%)}
/* 浮层总高是固定的，格子越小它盖住的行数越多，
   所以这几个尺寸都压得很紧 —— 目标 50px 以内（约两行）。*/
.mapui .hudline{background:rgba(252,248,240,.80);border-color:var(--edge-soft)}
.mapui .hi{padding:2px 6px}
.mapui .hi b{font-size:13px;line-height:1.25}
.mapui .hi i{font-size:10px}
/* 血条在浮层里收薄一点；战斗界面那条用的是同一个 .hpbar，别去动基类 */
.mapui .hpbar{height:15px;background:rgba(231,224,207,.88)}
.mapui .hpbar .txt{font-size:11px}
.mapui .xpbar{height:6px}
/* 联机（第一期）：队友状态条，跟主状态行同一套样式，稍微淡一号区分开。
   index.html 里没有 #mateRow 这个元素，这条规则在单人版里没有目标，等于不存在。 */
.mapui .hudline.mateline{opacity:.82}
.c{display:grid;place-items:center;font-family:var(--mono);line-height:1;user-select:none;
   width:var(--cell);height:var(--cell);font-size:calc(var(--cell) * .68);font-weight:600;
   position:relative;transition:background .12s ease;background:var(--unseen)}
.c svg{width:92%;height:92%;display:block}
.c.walkable{cursor:pointer}
.c.goal::after{content:"";position:absolute;inset:10%;border:2px solid var(--torch);
  border-radius:50%;opacity:.9;animation:ping 1.1s ease-out infinite}
@keyframes ping{0%{transform:scale(.7);opacity:.9}100%{transform:scale(1.15);opacity:.25}}
@media (prefers-reduced-motion:reduce){.c.goal::after{animation:none}}

/* 联机（第一期）：队友棋子。纯视觉叠在队友最后上报的格子里，偏右下、缩小一号、半透明 ——
   不占格子、不进寻路，见 game.js 的 render()。index.html 单人版永远不会画出这个类。 */
.matepawn{position:absolute;right:2%;bottom:2%;width:60%;height:60%;
  pointer-events:none;opacity:.7;filter:saturate(.65)}
.matepawn svg{width:100%;height:100%;display:block}

/* 地格底色：先定底 */
.c.dark{background:var(--unseen);color:transparent}
/* 离地板两格以上的实心墙：跟 .stage 的底同色，等于不画（用户 2026-09「墙体只要一格」）。
   墙于是只剩贴着房间和走廊的那一圈。见 game.js 的 wallEdge。 */
.c.void{background:var(--unseen);color:transparent}
.c.wall{background:var(--wall);color:transparent}
.c.floor{background:var(--floor)}
.c.mem.wall{background:var(--wall-dim)}
.c.mem.floor{background:var(--floor-dim)}
/* 再定内容颜色 */
/* 空地板上那个点也是画的，不是「·」字符 —— 地图上一个字都不剩。
   走 ::before 是因为 ::after 被目标格的脉冲圈占了，而一格可能同时是空地板和目标格。
   用 currentColor，出了视野自己跟着 .c.mem.dot 淡下去。
   ⚠️ 别改成 SVG：空地板占了整张地图九成的格子，每帧给它们塞 innerHTML 会拖垮走路。 */
.c.dot{color:var(--dot)}
.c.mem.dot{color:var(--dot-dim)}
.c.dot::before{content:"";position:absolute;left:50%;top:50%;width:14%;height:14%;
  min-width:2px;min-height:2px;transform:translate(-50%,-50%);
  background:currentColor;border-radius:1px}
.c.you{background:#DCE9F3;color:var(--hero)}
.c.mob{color:var(--blood)}
.c.mob.boss{color:#8C2418;font-weight:700}
/* 三四章的 Boss 单独上色 —— 一张地图上红的东西已经够多了，
   烬渊给烬色的橙、墟心给冕者的靛，跟箱（棕）和坛（紫）都错开。
   类名来自 render() 挂的 m-<怪的 id>。 */
.c.mob.boss.m-priest{color:#C2510E}
.c.mob.boss.m-crown{color:#4A3A8C}
.c.stair{color:var(--venom);font-weight:700}
/* 以前有个「上锁的阶梯」的淡色状态，现在清空前压根不画阶梯，用不上了 */
/* 金币要一眼看出是金的 —— --torch 偏棕，单独给一个亮金 */
.c.gold{color:var(--coin)}
.c.feat{color:var(--frost)}   /* 泉里的水 */
.c.shop{color:var(--torch)}   /* 商摊的棚子和柜台 */
.c.chest{color:var(--torch-deep)}  /* 木箱 */
.c.altar{color:var(--r3)}     /* 坛上悬的那颗宝石 —— 用遗物紫，好跟箱子分开 */
/* 画出来的那几样走出视野后整张淡下去 ——
   它们内部有写死的固定色（石头、描边、金锁），只调 color 淡不下来。
   阶梯不在这里：它清空后才出现，是玩家要去的地方，淡了反而找不着。 */
.c.mem.gold svg,.c.mem.feat svg,.c.mem.shop svg,
.c.mem.chest svg,.c.mem.altar svg,
.c.mem.m-priest svg,.c.mem.m-crown svg{opacity:.5}
.c.it0{color:var(--r0)}.c.it1{color:var(--r1)}.c.it2{color:var(--r2)}
.c.it3{color:var(--r3)}.c.it4{color:var(--r4)}
/* hover 必须放在底色规则之后才盖得住 */
.c.walkable:hover{background:#F7E4B9}
.c.you.walkable:hover{background:#DCE9F3}

/* 窄屏：让地图撑满整宽（其它部件保留 16px 边距），换来更大的格子 */
@media (max-width:480px){
  .stage{margin-inline:-16px}   /* 正好抵消 .app 的左右 padding，地图撑满整宽 */
}

/* 取景框左下角的「放弃」和「寻路」：压在地图上，并排一行。
   .mapui 是 pointer-events:none，这两个按钮是它的兄弟节点，照样能点。
   尺寸比原来大了一倍（用户 2026-09）—— 寻路是常按的，太小按不准。 */
.mapacts{position:absolute;left:4px;bottom:4px;z-index:3;display:flex;gap:6px}
/* 右下角那一组（现在只有「锁定冒险」）。用户 2026-09 把它从地图下面那一行挪上来的 */
.mapacts.right{left:auto;right:4px}
/* ⚠️ nowrap + flex:none：这三个按钮的容器是绝对定位的，宽度会被压到可用空间以内 ——
   不钉住的话「放弃」会被挤成上下两行的「放/弃」（以前就是这样，跟右下角的「锁定冒险」放一起才看出来）。*/
.giveup{flex:none;white-space:nowrap;
  padding:6px 14px;border:1px solid var(--edge);border-radius:3px;
  background:rgba(246,241,229,.82);color:var(--faint);cursor:pointer;
  font-family:var(--mono);font-size:16px;letter-spacing:.1em;line-height:1}
@media (hover:hover){.giveup:hover{color:var(--blood);border-color:var(--blood)}}
.giveup.armed{color:var(--blood);border-color:var(--blood);background:rgba(246,241,229,.96);font-weight:600}
/* 寻路不是危险操作，hover 用火把色，别跟「放弃」的血色混 */
@media (hover:hover){.giveup.find:hover{color:var(--torch);border-color:var(--torch)}}
/* 寻路是**开关**：开着的时候亮起来，一眼能看出它还在跑 */
.giveup.find.on{color:var(--torch);border-color:var(--torch);
  background:rgba(246,241,229,.96);font-weight:600}
/* 「锁定冒险」也是开关，同一套长相，只是亮起来用金币色跟寻路区分开。
   四个字比「放弃」「寻路」宽，所以字号收一号、内边距收窄一点。 */
.giveup.lock{font-size:14px;padding:6px 10px}
@media (hover:hover){.giveup.lock:hover{color:var(--coin);border-color:var(--coin)}}
.giveup.lock.on{color:var(--torch-deep);border-color:var(--coin);
  background:rgba(246,241,229,.96);font-weight:600}

/* 地图下面那一行文字按钮（.maptools / .mapbtn）已经整块删了（用户 2026-09）——
   「锁定冒险」搬去了取景框右下角，空出来的纵向空间归日志栏。 */

.log{flex:1;min-height:62px;border:1px solid var(--edge);background:var(--stone);border-radius:2px;padding:9px 11px;
  overflow-y:auto;display:flex;flex-direction:column;gap:3px;font-size:13px}
.log p{margin:0;color:var(--dim)}
.log .hit{color:var(--bone)}
.log .crit{color:var(--torch)}
.log .hurt{color:#A8402F}
.log .good{color:var(--venom)}
.log .sys{color:var(--faint)}

.panel{border:1px solid var(--edge);background:var(--stone);border-radius:2px;padding:11px;
  display:flex;flex-direction:column;gap:10px}
.phead{font-family:var(--mono);font-size:9.5px;letter-spacing:.18em;text-transform:uppercase;color:var(--faint)}
.slots{display:flex;flex-direction:column;gap:5px}
.slot{border:1px solid var(--edge-soft);background:var(--stone-2);border-radius:2px;padding:6px 8px}
.slot .sk{font-family:var(--mono);font-size:9.5px;letter-spacing:.12em;color:var(--faint)}
.slot .sn{font-size:13px;font-weight:600;line-height:1.3}
.slot .sd{font-size:11.5px;color:var(--dim);line-height:1.4;margin-top:2px}
.stats{display:grid;grid-template-columns:1fr 1fr;gap:3px 10px;font-size:12.5px}
.stats .s{display:flex;justify-content:space-between;gap:6px;color:var(--dim)}
.stats .s b{color:var(--bone);font-family:var(--mono);font-weight:600;font-variant-numeric:tabular-nums}

/* ===== 弹层 ===== */
.veil{position:fixed;inset:0;background:rgba(58,48,32,.42);backdrop-filter:blur(2px);
  display:flex;align-items:center;justify-content:center;padding:14px;overflow-y:auto;z-index:30}
.veil[hidden]{display:none !important}
.sheet{width:100%;max-width:560px;background:var(--stone);border:1px solid var(--edge);border-radius:4px;
  box-shadow:0 18px 50px rgba(70,58,38,.28);padding:18px;display:flex;flex-direction:column;gap:13px;margin-block:auto}
.sheet h2{font-family:var(--disp);font-weight:600;font-size:20px;margin:0;letter-spacing:.04em;text-wrap:balance}
.eyebrow{font-family:var(--mono);font-size:9.5px;letter-spacing:.2em;text-transform:uppercase;color:var(--faint)}
.btn{font-family:var(--body);font-size:13.5px;padding:9px 16px;border-radius:2px;cursor:pointer;
  background:var(--stone-3);color:var(--bone);border:1px solid var(--edge)}
.btn:hover{border-color:var(--torch-deep)}
.btn.primary{background:var(--torch);color:#FFF9EC;border-color:var(--torch-deep);font-weight:600}
.btn.primary:hover{background:#B57C15}
.btn.ghost{background:none;color:var(--dim)}
.rowb{display:flex;gap:8px;flex-wrap:wrap;align-items:center}
.rowb .sp{flex:1}
button:focus-visible{outline:2px solid var(--torch);outline-offset:2px}

/* ===== 战斗界面 ===== */
/* 战斗窗要**整屏放得下**：立绘、题面、选项、间距全部跟着视口高度缩。
   矮屏（600-700）缩到最小档，高屏也有上限，免得方块越长越大反而顶出去。 */
.battle{max-width:520px;gap:clamp(6px,1.2vh,11px);padding:clamp(11px,1.8vh,18px)}
.foe{display:flex;align-items:center;gap:13px;position:relative}
.portrait{width:clamp(58px,11vh,96px);height:clamp(58px,11vh,96px);
  flex:none;border:1px solid var(--edge);border-radius:4px;
  background:radial-gradient(72% 72% at 50% 38%, #FFFCF4 0%, #E9E0CD 100%);display:grid;place-items:center;padding:7px}
.portrait svg{width:100%;height:100%;color:#57503F}
.portrait.boss svg{color:#8A3223}
.portrait.hurt{animation:jolt .28s ease}
@keyframes jolt{25%{transform:translateX(-5px)}60%{transform:translateX(5px)}100%{transform:translateX(0)}}
.foe-info{flex:1;min-width:0;display:flex;flex-direction:column;gap:5px}
.foe-name{font-family:var(--disp);font-size:17px;font-weight:600;letter-spacing:.03em}
.foe-tag{font-family:var(--mono);font-size:10px;letter-spacing:.12em;color:var(--faint);text-transform:uppercase}
.fbar{height:16px;border:1px solid var(--edge);background:#E7E0CF;position:relative;overflow:hidden;border-radius:1px}
.fbar .fill{position:absolute;inset:0;background:linear-gradient(180deg,#E89184,#D26857);transition:width .3s ease}
.fbar .txt{position:absolute;inset:0;display:grid;place-items:center;font-family:var(--mono);
  font-size:10px;color:#35302A;text-shadow:0 1px 0 rgba(255,255,255,.5)}

.qcard{position:relative;border:1px solid var(--edge-soft);background:#FFFDF7;border-radius:3px;
  padding:clamp(8px,1.6vh,16px) 12px;
  display:flex;flex-direction:column;gap:clamp(4px,0.9vh,8px);align-items:center}
/* 7 秒读条：**绝对定位压在题面卡片的顶边**，不占纵向空间 ——
   它只在选择题出现、答完就收，放回文档流的话战斗窗会在答题瞬间缩一下。
   最后 2 秒变红（.hot）。*/
.qtimer{position:absolute;left:0;right:0;top:0;height:3px;background:#E7E0CF;
  border-radius:3px 3px 0 0;overflow:hidden}
.qtimer i{display:block;height:100%;width:100%;background:var(--torch);
  transition:width .1s linear}
.qtimer.hot i{background:var(--blood)}
@media (prefers-reduced-motion:reduce){.qtimer i{transition:none}}
.qlabel{font-family:var(--mono);font-size:10px;letter-spacing:.16em;color:var(--faint);text-transform:uppercase}
.qword{font-family:var(--mono);font-size:clamp(21px,4.2vh,30px);font-weight:600;letter-spacing:.04em;
  color:var(--bone);text-align:center;word-break:break-word;line-height:1.15}
.qword.cn{font-family:var(--body);font-size:clamp(19px,3.7vh,26px);letter-spacing:.02em}
/* 🔊 是**浮在题面卡片右上角**的小圆钮，不占纵向空间。
   ⚠️ 以前它是一行按钮，答完题才冒出来 —— 弹窗当场长高 30 多像素，veil 立刻出滚动条。
   别再把它放回文档流里，也别给它加文字（JS 里只写一个喇叭）。 */
.spk{position:absolute;right:6px;top:6px;width:30px;height:30px;padding:0;line-height:1;
  background:var(--stone);border:1px solid var(--edge);color:var(--frost);border-radius:50%;
  font-size:14px;cursor:pointer;font-family:var(--body);display:grid;place-items:center}
.spk:hover{border-color:var(--frost)}
/* 心魔标签也是半路才出现的，藏起来时照样占位 —— 免得每题窗高都在跳。别改回 display:none。 */
.haunt[hidden]{display:block !important;visibility:hidden;pointer-events:none}

/* 四个选项排成 2×2 的正方块。宽度用 vh 卡住，免得矮屏上两行方块把弹窗顶出去。
   ⚠️ 方块是正方形，所以**这条宽度上限就是选项区的高度上限** —— 它是战斗窗唯一的调节阀。
   连击条 2026-09 从窗底挪到怪物血条下面，自己占了一整行（比原来在 .mybar 里挤着高十来像素），
   所以这里从 33vh 再收到 31vh 让出来。390×667 上量过：不收就会出滚动条。*/
.opts{display:grid;grid-template-columns:1fr 1fr;gap:clamp(5px,1vh,8px);
  width:min(100%, 31vh, 318px);margin-inline:auto}
.opt{position:relative;aspect-ratio:1;text-align:center;
  background:var(--stone-2);border:1px solid var(--edge);color:var(--bone);
  border-radius:3px;padding:8px;font-size:clamp(14px,2.1vh,16px);cursor:pointer;font-family:var(--body);
  display:flex;align-items:center;justify-content:center;gap:0;
  line-height:1.3;word-break:break-word;overflow:hidden}
/* 序号缩进左上角，也是个小方块 */
.opt .n{position:absolute;left:5px;top:5px;width:16px;height:16px;flex:none;
  display:grid;place-items:center;border:1px solid var(--edge);border-radius:2px;
  background:var(--stone);font-family:var(--mono);font-size:10px;color:var(--faint)}
/* ⚠️ 选项/字母键的 hover **必须关进 @media (hover:hover)**：触屏上的 hover 是「粘住」的 ——
   手指点完那一格，hover 底色会一直留到下次点别处，而下一题的新按钮又长在同一个位置上，
   看着就像上一题在这儿留了块阴影（用户 2026-09 报的那个 bug）。鼠标那一侧照旧。 */
@media (hover:hover){
  .opt:hover:not(:disabled){border-color:var(--torch-deep);background:var(--stone-3)}
}
.opt:disabled{cursor:default;opacity:.55}
.opt.right{background:#DFEDD0;border-color:var(--venom);color:#2F5220;opacity:1;font-weight:600}
.opt.wrong{background:#F6DCD7;border-color:var(--blood);color:#7E2618;opacity:1}
.opt.right .n{border-color:var(--venom);color:#2F5220;background:#EDF5E4}
.opt.wrong .n{border-color:var(--blood);color:#7E2618;background:#FBEBE7}
/* 答错之后每个方块里多出一行，把这个选项的另一半（中文题给英文、英文题给中文）也写出来。
   ⚠️ 这一行只在**方块内部**长，verdict 不加行 —— 战斗窗答题前后必须同高。
   方块是正方形（aspect-ratio:1），两行加起来还有余量，四档屏幕上量过。 */
.opt.two{flex-direction:column;gap:2px}
.opt .sub{font-family:var(--mono);font-size:clamp(11px,1.6vh,12.5px);
  font-weight:400;opacity:.72;line-height:1.2;word-break:break-word}

/* 答完题这里会多出两行（判定 + 释义）。**高度提前留够**，不然答完窗就长高、出滚动条。 */
.verdict{text-align:center;font-size:13.5px;min-height:clamp(52px,7.6vh,62px);
  display:flex;flex-direction:column;gap:3px;justify-content:center}
.verdict .big{font-family:var(--disp);font-size:17px;letter-spacing:.04em}
.verdict .big.ok{color:var(--venom)}
.verdict .big.no{color:var(--blood)}
.verdict .mean{color:var(--dim)}
.verdict .mean b{color:var(--bone);font-family:var(--mono)}

.mybar{display:flex;align-items:center;gap:10px}
.mybar .me{width:clamp(26px,4vh,36px);height:clamp(26px,4vh,36px);flex:none;color:var(--hero)}
.mybar .me svg{width:100%;height:100%}
.mybar .col{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px}
/* 联机第二期：队友的血条画在自己血条上方，半透明 50%（用户 2026-09 要求，跟真血条区分开）——
   index.html 没有 #bMateHpBar，$() 拿到 null 会自动跳过，单人版一步都跑不到这儿。
   ⚠️ 它不走 paintHp()（那个函数会顺手把「自己」的护盾数字画上去，队友那条不该顶着我的盾），
   走的是专门写的 paintMateHp()，所以没有 .sh 护盾层，也没有掉血/回血的闪光动效。*/
.hpbar.mate{opacity:.5;height:14px}
.hpbar.mate .txt{font-size:11px}
/* 连击条：三段常驻（连了几次 / 现在加百分之几 / 再对几个进下一档）。
   ⚠️ 三段永远都在，只有数字变 —— 答题前后行数一致，战斗窗才不会跳高。
   位置是**怪物血条下面**（用户 2026-09 从战斗窗底下挪上来的），所以它自己是一整行。
   ⚠️ 动效只用 transform/opacity，不动布局 —— 放大那一下不能把底下的题面顶开。 */
.combo{display:flex;align-items:center;gap:6px;flex-wrap:nowrap;line-height:1.25;
  font-family:var(--mono);font-size:10.5px;letter-spacing:.06em;color:var(--torch);
  min-height:clamp(15px,2.4vh,19px)}
/* ⚠️ 放大的是**「连击 ×N」那一小段**，不是整行 ——
   整行是满宽的，scale 一下右边会顶出去，弹层当场多一条横向滚动条。
   整行只做不影响宽度的事（淡一下、变灰）。 */
.combo .cmb-n{position:relative;z-index:1;transform-origin:left center}
/* 涨了：数字弹一下，还闪一下绿 */
.combo.up .cmb-n{animation:cmbUp .46s cubic-bezier(.3,1.5,.5,1)}
.combo.up .cmb-n b{animation:cmbUpN .46s cubic-bezier(.3,1.6,.5,1)}
/* 掉了（答错 / 超时 / 清零）：数字缩下去，整条淡一下再回来 */
.combo.down .cmb-n{animation:cmbDownN .46s ease-out}
.combo.down{animation:cmbDown .46s ease-out}
@keyframes cmbUp{0%{transform:scale(1)}38%{transform:scale(1.18)}100%{transform:scale(1)}}
@keyframes cmbUpN{0%{transform:scale(1)}38%{transform:scale(1.3);color:var(--venom)}100%{transform:scale(1)}}
@keyframes cmbDownN{0%{transform:scale(1)}45%{transform:scale(.68)}100%{transform:scale(1)}}
@keyframes cmbDown{0%{opacity:1}45%{opacity:.25;filter:grayscale(1)}100%{opacity:1}}
@media (prefers-reduced-motion:reduce){
  .combo.up,.combo.down,.combo.up .cmb-n,.combo.up .cmb-n b,.combo.down .cmb-n{animation:none}}
.combo .cmb-n{flex:none;display:inline-block;color:var(--dim)}
.combo .cmb-n b{display:inline-block;font-size:clamp(13px,2.1vh,16px);color:var(--torch);
  font-weight:700;letter-spacing:.02em}
.combo .cmb-p{flex:none;padding:0 5px;border-radius:2px;font-weight:700;
  background:#F6E6C4;border:1px solid var(--torch-deep);color:var(--torch-deep)}
.combo .cmb-p.off{background:none;border-color:var(--edge);color:var(--faint);font-weight:400}
.combo .cmb-next{flex:1;min-width:0;color:var(--faint);text-align:right;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.combo.none .cmb-n b{color:var(--faint)}

.float{position:absolute;right:8px;top:2px;font-family:var(--mono);font-weight:700;font-size:17px;
  pointer-events:none;animation:rise .85s ease-out forwards}
.float.dmg{color:#8A5A0B;text-shadow:0 1px 0 rgba(255,255,255,.7)}
.float.ouch{color:#A32E1E;text-shadow:0 1px 0 rgba(255,255,255,.7)}
.float.heal{color:#3E7A2E;text-shadow:0 1px 0 rgba(255,255,255,.7)}

/* ===== 捡东西的碎屑 =====
   挂在 body 上飞，飞完就删。纯装饰，一律不挡点击。 */
.mote{position:fixed;z-index:60;pointer-events:none;color:var(--coin);
  filter:drop-shadow(0 1px 1px rgba(90,70,30,.35))}
.mote svg{width:100%;height:100%;display:block}
/* ===== 升级：一圈光晕荡开 + 一圈金色粒子（1.5s，用户 2026-09）=====
   都挂在 body 上、定位到主角那一格、1.5s 后一起删（见 game.js 的 fxLevelUp）。
   z-index 要压过弹层（战斗中升级时地图在 veil 底下）。 */
.lvring{position:fixed;z-index:61;pointer-events:none;width:0;height:0;
  border-radius:50%;animation:lvring 1.5s cubic-bezier(.2,.7,.35,1) forwards}
@keyframes lvring{
  0%{box-shadow:0 0 0 2px currentColor, 0 0 14px 2px currentColor;opacity:.95;
     width:8px;height:8px;margin:-4px 0 0 -4px}
  60%{opacity:.5}
  100%{box-shadow:0 0 0 2px currentColor, 0 0 26px 6px currentColor;opacity:0;
     width:150px;height:150px;margin:-75px 0 0 -75px}
}
.lvmote{position:fixed;z-index:61;pointer-events:none;width:7px;height:7px;margin:-3.5px 0 0 -3.5px;
  border-radius:50%;background:currentColor;opacity:.95;
  filter:drop-shadow(0 1px 2px rgba(90,70,30,.45));
  transition:transform 1.3s cubic-bezier(.15,.75,.3,1), opacity 1.3s ease-out}
@media (prefers-reduced-motion:reduce){.lvring,.lvmote{animation:none;transition:none;display:none}}

/* 碎屑落进去的那个数字/标签，自己跳一下 */
.pop{animation:pop .4s ease-out}
@keyframes pop{0%{transform:scale(1)}35%{transform:scale(1.35)}100%{transform:scale(1)}}
@media (prefers-reduced-motion:reduce){.pop{animation:none}}
@keyframes rise{0%{opacity:0;transform:translateY(6px)}20%{opacity:1}100%{opacity:0;transform:translateY(-18px)}}
@media (prefers-reduced-motion:reduce){.float,.portrait.hurt{animation:none}}

/* 拼写题 —— 跟选项方块一个规矩：尺寸全部 clamp(最小, xvh, 最大)，整屏要放得下。
   字母键排成 6 列的方块，跟 .opt 一样是正方形，手指点得中。
   拼写时 .opts 是藏起来的，所以这一块可以比选项那两行矮，但键本身要更大。 */
/* 拼写题：字格 + 左边那个 🔊（进拼写题自动念一次，之后随时能再点）。
   按钮是 flex 的兄弟节点，不占纵向空间 —— 字格本身比它高。 */
.spellbar{display:flex;align-items:center;justify-content:center;gap:6px}
.spkline{flex:none;width:clamp(26px,4vh,32px);height:clamp(26px,4vh,32px);padding:0;line-height:1;
  background:var(--stone);border:1px solid var(--edge);color:var(--frost);border-radius:50%;
  font-size:14px;cursor:pointer;font-family:var(--body);display:grid;place-items:center}
.spkline:hover{border-color:var(--frost)}
.spellrow{display:flex;gap:clamp(4px,.8vh,6px);justify-content:center;flex-wrap:wrap}
.sbox{width:clamp(26px,4.8vh,36px);height:clamp(34px,6.2vh,46px);
  border:1px solid var(--edge);border-bottom:2px solid var(--torch-deep);
  background:#FFFDF7;display:grid;place-items:center;font-family:var(--mono);
  font-size:clamp(18px,3.2vh,25px);color:var(--torch)}
/* 长词（grandmother / comfortable 这种 11 个字母的）字格缩一号，保证还是一行 */
.spellrow.long .sbox{width:clamp(18px,3.2vh,23px);height:clamp(26px,4.8vh,35px);
  font-size:clamp(14px,2.6vh,20px)}
.letters{display:grid;grid-template-columns:repeat(5,1fr);gap:clamp(5px,1vh,8px);
  width:min(100%,52vh,380px);margin-inline:auto}
.lbtn{width:auto;height:auto;aspect-ratio:1;background:var(--stone-3);border:1px solid var(--edge);
  color:var(--bone);border-radius:3px;font-family:var(--mono);
  font-size:clamp(17px,2.9vh,23px);cursor:pointer;padding:0}
@media (hover:hover){
  .lbtn:hover:not(:disabled){border-color:var(--torch-deep);background:var(--stone-2)}
}
.lbtn:disabled{opacity:.25;cursor:default}

/* ===== 卡片 / 图鉴 ===== */
.icard{border:1px solid var(--edge-soft);background:#FFFDF7;border-radius:2px;padding:10px 12px;
  display:flex;flex-direction:column;gap:4px}
.icard.now{background:var(--stone-2);opacity:.8}
.icard .in{font-size:15px;font-weight:600;line-height:1.25}
.icard .ib{font-family:var(--mono);font-size:11px;color:var(--faint);letter-spacing:.08em}
.icard .il{font-size:12.5px;display:flex;justify-content:space-between;gap:10px}
.icard .il .d{font-family:var(--mono);font-variant-numeric:tabular-nums}
.icard .up{color:var(--venom)}.icard .dn{color:#A83E2E}
.icard .pw{font-size:12.5px;color:var(--r4);line-height:1.45}
.icard .lore{font-family:var(--flavor);font-style:italic;font-size:12px;color:var(--dim)}
.cmp{display:grid;grid-template-columns:1fr 1fr;gap:9px}
@media (max-width:480px){.cmp{grid-template-columns:1fr}}

.tabs{display:flex;gap:2px;border-bottom:1px solid var(--edge)}
.tab{background:none;border:0;border-bottom:2px solid transparent;color:var(--dim);
  font-family:var(--body);font-size:12.5px;padding:6px 10px;cursor:pointer;margin-bottom:-1px}
.tab.on{color:var(--torch);border-bottom-color:var(--torch)}
.codex{display:flex;flex-direction:column;gap:6px;max-height:52vh;overflow-y:auto;padding-right:2px}
/* ⚠️ 图鉴卡片占用了 .cx / .cn / .cd —— 战斗窗那条连击用的是带前缀的 .cmb-*，别再撞名字
   （跟当年 .opt 撞设置页复选框是同一个坑）。 */
.cx{border:1px solid var(--edge-soft);border-left:3px solid var(--edge);background:#FFFDF7;
  border-radius:2px;padding:8px 11px;display:flex;flex-direction:column;gap:3px}
.cx.lost{background:var(--stone-2)}
.cx.found{border-left-color:var(--r4)}
.cx.w-ok{border-left-color:var(--venom)}
.cx.w-bad{border-left-color:var(--blood)}
.cx .cn{font-size:14px;font-weight:600;display:flex;justify-content:space-between;gap:8px;align-items:baseline}
.cx.found .cn{color:var(--r4)}
.cx .cn .meta{font-family:var(--mono);font-size:10.5px;color:var(--faint);font-weight:400}
.cx.lost .cn{color:var(--faint)}
.cx .cd{font-size:12px;color:var(--dim);line-height:1.45}
.cx .stars{color:var(--torch);letter-spacing:.08em}
/* 图鉴的搜索框（用户 2026-09）：词库按英文/中文找，遗物按名字/效果/铭文找。
   ⚠️ 这个类**以前叫 `.find`，跟取景框里的寻路按钮 `.giveup.find` 撞了**
   （而且定义在后面，`width:100%` 被套到了按钮身上，把「放弃」挤成上下两行）——
   跟当年 `.opt` 撞设置页复选框、`.cx` 撞连击条是同一个坑。**别改回 `.find`。** */
.findbox{width:100%;box-sizing:border-box;margin:2px 0 0;padding:7px 10px;
  border:1px solid var(--edge);border-radius:2px;background:#FFFDF7;color:var(--bone);
  font-family:var(--body);font-size:13px;-webkit-appearance:none;appearance:none}
.findbox:focus{outline:none;border-color:var(--torch-deep)}
.findbox::placeholder{color:var(--faint)}
.tally{display:flex;gap:14px;flex-wrap:wrap;font-family:var(--mono);font-size:11.5px;color:var(--dim)}
.tally b{color:var(--torch);font-weight:600}

/* 结算顶上那块强调：本局正确率 vs 这一层历史上的平均正确率（用户 2026-09）。
   两个数一样大、中间一个小小的 vs，底下一行写差了多少。*/
.accbox{display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:10px;
  border:1px solid var(--edge);border-radius:3px;background:#FFFCF2;padding:11px 12px}
.accone{display:flex;flex-direction:column;gap:2px;text-align:center;min-width:0}
.accone i{font-style:normal;font-family:var(--mono);font-size:9.5px;letter-spacing:.12em;
  color:var(--faint);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.accone b{font-family:var(--mono);font-size:24px;font-weight:600;color:var(--bone);
  font-variant-numeric:tabular-nums;line-height:1.1}
.accvs{font-family:var(--mono);font-size:10px;letter-spacing:.16em;color:var(--faint)}
.accdiff{font-size:12px;color:var(--dim);text-align:center;margin-top:5px}
.accdiff.up{color:var(--venom)}
.accdiff.down{color:var(--blood)}

/* ===== 练习模式的开关（洞窟弹层，路线列表底下）===== */
.practice{width:100%;display:flex;flex-direction:column;gap:2px;text-align:left;cursor:pointer;
  font-family:var(--body);font-size:13px;color:var(--dim);
  border:1px dashed var(--edge);background:var(--stone-2);border-radius:3px;padding:9px 12px}
.practice em{font-style:normal;font-size:11.5px;color:var(--faint)}
.practice.on{border-style:solid;border-color:var(--frost);background:#EAF3F4;color:var(--bone)}
.practice.on em{color:var(--frost)}
@media (hover:hover){.practice:hover{border-color:var(--torch-deep)}}

.ledger{border:1px solid var(--edge-soft);border-radius:2px;background:#FFFDF7}
.ledger .li{display:flex;justify-content:space-between;gap:12px;padding:6px 11px;font-size:13px;
  border-top:1px solid var(--edge-soft)}
.ledger .li:first-child{border-top:0}
.ledger .li .lb{color:var(--dim)}
.ledger .li .am{font-family:var(--mono);font-variant-numeric:tabular-nums;color:var(--bone)}
.rules{font-size:13px;color:var(--dim);display:flex;flex-direction:column;gap:8px}
.rules b{color:var(--bone)}
.rules ul{margin:0;padding-left:16px;display:flex;flex-direction:column;gap:6px}
.kbd{font-family:var(--mono);background:var(--stone-3);border:1px solid var(--edge);border-radius:2px;
  padding:0 5px;color:var(--bone);font-size:11.5px}

/* ===== 游商的货架 =====
   照**三选一那种遗物卡**摆（用户 2026-09，以前是一行小字 + 右边一个按钮，太挤）：
   品质 / 名字 / 效果 / 传说各一行，买的按钮压在右下角。五件竖着排，弹层自己会滚。 */
.shop{display:flex;flex-direction:column;gap:8px}
.shopit{position:relative;display:flex;flex-direction:column;gap:2px;
  border:1px solid var(--edge);background:var(--stone-2);border-radius:3px;
  padding:9px 11px;padding-right:96px}
.shopit .rt{font-family:var(--mono);font-size:9.5px;letter-spacing:.16em}
.shopit .rn{font-family:var(--disp);font-size:16px;font-weight:600;letter-spacing:.04em}
.shopit .rp{font-size:12.5px;color:var(--bone)}
.shopit .rl{font-family:var(--flavor);font-style:italic;font-size:11.5px;color:var(--faint);margin-top:2px}
.shopit .buy{position:absolute;right:10px;top:50%;transform:translateY(-50%);
  font-family:var(--body);font-size:13px;padding:8px 12px;border-radius:2px;cursor:pointer;
  background:var(--torch);color:#FFF9EC;border:1px solid var(--torch-deep);font-weight:600;white-space:nowrap}
.shopit .buy:hover:not(:disabled){background:#B57C15}
.shopit .buy:disabled{background:var(--stone-3);color:var(--faint);border-color:var(--edge);
  cursor:default;font-weight:400}
.shopit.sold{opacity:.5}

/* ===== 背包 ===== */
.bag{display:flex;flex-direction:column;gap:6px}
.bagit{border:1px solid var(--edge-soft);background:var(--stone-2);border-radius:2px;
  padding:7px 9px;display:flex;align-items:flex-start;gap:9px}
.bagit .col{flex:1;min-width:0}
.bagit .sn{font-size:13px;font-weight:600;line-height:1.3}
.bagit .sk{font-family:var(--mono);font-size:9.5px;letter-spacing:.12em;color:var(--faint)}
.bagit .sd{font-size:11.5px;color:var(--dim);line-height:1.4;margin-top:2px}
.bagit .pw{font-size:11.5px;color:var(--r4);margin-top:2px}
.bagit .acts{display:flex;flex-direction:column;gap:4px;flex:none}
.bagit .acts button{font-family:var(--body);font-size:11.5px;padding:4px 9px;border-radius:2px;
  cursor:pointer;background:var(--stone-3);color:var(--bone);border:1px solid var(--edge);white-space:nowrap}
.bagit .acts button:hover{border-color:var(--torch-deep);color:var(--torch)}
.bagempty{font-size:12.5px;color:var(--faint);padding:8px 2px}
.slot.has{cursor:default}
.slot .off{float:right;font-family:var(--body);font-size:11px;padding:2px 8px;border-radius:2px;
  cursor:pointer;background:var(--stone-3);color:var(--dim);border:1px solid var(--edge)}
.slot .off:hover{border-color:var(--torch-deep);color:var(--torch)}
.note{margin:0;font-size:11.5px;color:var(--faint);line-height:1.5}

/* ===== 设置 ===== */
/* ⚠️ 这里以前也叫 .opt，跟战斗界面的选项按钮重名，而且定义在后面 ——
   它的 display/padding 一直在偷偷覆盖战斗选项。改名 .setopt，两边互不相干。 */
.setopt{display:flex;align-items:flex-start;gap:9px;cursor:pointer;padding:3px 0}
.setopt input{margin:2px 0 0;width:16px;height:16px;flex:none;accent-color:var(--torch)}
.setopt span{display:flex;flex-direction:column;gap:1px}
.setopt b{font-size:13px;font-weight:600}
.setopt i{font-style:normal;font-size:11.5px;color:var(--faint)}
.btn.danger{color:var(--blood);border-color:#D9B3AC}
.btn.danger:hover{background:#F6E3DF;border-color:var(--blood)}

/* ===== 存档 / 导出码 ===== */
.code{width:100%;font-family:var(--mono);font-size:11px;line-height:1.5;color:var(--dim);
  background:var(--stone-2);border:1px solid var(--edge-soft);border-radius:2px;
  padding:7px 8px;resize:vertical;word-break:break-all}
.code:focus{outline:2px solid var(--torch);outline-offset:1px}
/* 本地存档文件：拖放区 + 读出来的信息卡 */
.drop{border:1px dashed var(--edge);border-radius:2px;background:var(--stone-2);
  padding:14px 10px;text-align:center;font-size:11.5px;color:var(--faint);transition:.12s}
.drop.over{border-color:var(--torch);color:var(--torch);background:#FBF3E0}
.filecard{display:flex;flex-direction:column;gap:9px;border:1px solid var(--edge);
  border-left:2px solid var(--torch);border-radius:2px;background:var(--stone-2);padding:10px}
.filecard[hidden]{display:none !important}
.filecard .eyebrow{word-break:break-all;text-transform:none;letter-spacing:.08em}
.fallline{margin:0;font-family:var(--flavor);font-style:italic;font-size:14px;color:var(--dim)}

/* ===== 主城 ===== */
.town{flex:1;min-height:0;overflow-y:auto;display:flex;flex-direction:column;gap:12px}
.town[hidden]{display:none !important}
.townhead h2{font-family:var(--disp);font-weight:600;font-size:21px;margin:2px 0 4px;letter-spacing:.04em}
.bank{display:grid;grid-template-columns:repeat(4,1fr);border:1px solid var(--edge);
  background:var(--stone);border-radius:2px;overflow:hidden}
.bcell{padding:7px 9px;border-left:1px solid var(--edge-soft);display:flex;flex-direction:column;gap:1px;min-width:0}
.bcell:first-child{border-left:0}
.bcell .k{font-family:var(--mono);font-size:9.5px;letter-spacing:.14em;color:var(--faint)}
.bcell .v{font-family:var(--mono);font-size:15px;font-weight:600;font-variant-numeric:tabular-nums}
.bcell .v.gold{color:var(--torch)}

.places{display:flex;flex-direction:column;gap:8px}
.place{display:flex;align-items:center;gap:11px;width:100%;text-align:left;
  border:1px solid var(--edge);background:var(--stone);border-radius:3px;
  padding:11px 12px;cursor:pointer;font-family:var(--body);color:var(--bone)}
.place:hover{border-color:var(--torch-deep);background:#FDF6E7}
.place i{font-style:normal;font-family:var(--mono);font-size:17px;font-weight:600;
  color:var(--torch);flex:none;width:32px;height:32px;border:1px solid var(--edge);
  border-radius:3px;display:grid;place-items:center;background:var(--stone-2)}
.place .pn{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px;font-size:14.5px;font-weight:600}
.place .pn em{font-style:normal;font-size:11.5px;font-weight:400;color:var(--faint)}
.place .go{color:var(--torch);font-size:13px;flex:none}
.place.off{cursor:default;opacity:.55;background:var(--stone-3)}
.place.off:hover{border-color:var(--edge);background:var(--stone-3)}
.place.off i{color:var(--faint)}

/* ===== 洞窟的路线卡 ===== */
.routes{display:flex;flex-direction:column;gap:8px}
.route{position:relative;overflow:hidden;
  display:flex;flex-direction:column;gap:2px;width:100%;text-align:left;
  border:1px solid var(--edge);background:var(--stone-2);border-radius:3px;
  padding:11px 64px 11px 12px;cursor:pointer;font-family:var(--body);color:var(--bone)}
/* 卡片背后那条淡蓝 = 这一章的词遇见过多少（宽度就是百分比，openCave 里现算）。
   ⚠️ 它是**背景**，所以下面每一段文字都要 position:relative 顶到它上面去；
   ⚠️ 颜色要够淡 —— 铺到 100% 也得看得清卡片上的字。*/
.route .rfill{position:absolute;left:0;top:0;bottom:0;width:0;
  background:rgba(38,111,123,.16);border-right:1px solid rgba(38,111,123,.28);
  pointer-events:none}
.route .rt,.route .rn,.route .rd,.route .rgo{position:relative}
/* 右上角的百分数。卡片右边留了 64px 的 padding 给它，别跟章名挤在一起 */
.route .rpct{position:absolute;right:10px;top:9px;
  font-family:var(--mono);font-size:11px;letter-spacing:.06em;color:var(--frost);
  font-variant-numeric:tabular-nums}
.route.off .rpct{color:var(--faint)}
.route:hover{border-color:var(--torch-deep);background:#FDF6E7}
.route .rt{font-family:var(--mono);font-size:9.5px;letter-spacing:.14em;color:var(--faint)}
.route .rn{font-family:var(--disp);font-size:17px;font-weight:600;letter-spacing:.04em}
.route .rd{font-size:12px;color:var(--dim)}
.route .rgo{font-size:12px;color:var(--torch);margin-top:3px}
.route.off{cursor:default;opacity:.5}
.route.off:hover{border-color:var(--edge);background:var(--stone-2)}
.route.off .rgo{color:var(--faint)}
/* 联机（第一期）：轮不到这个人点（队友选路线阶段 / 还没组队）时的禁用态，
   跟 .off 长得一样但语义不同（.off 是"这条路还没挖通"）。
   .picked 是房主选中、等队友确认的那一条，高亮一圈边框。
   index.html 单人版永远不会加上这两个类。 */
.route.coopwait{cursor:default;opacity:.55}
.route.coopwait:hover{border-color:var(--edge);background:var(--stone-2)}
.route.picked{border-color:var(--torch);box-shadow:inset 0 0 0 2px var(--torch)}
.btn:disabled{opacity:.45;cursor:default}
.btn:disabled:hover{border-color:var(--edge)}

/* ===== 弱点 / 心魔 / 冒险 ===== */
.foe-weak{font-size:11.5px;color:var(--dim);margin-top:1px}
.foe-weak b{color:var(--venom)}
/* 联机第二期：怪有两条独立血条，这条画在 .fbar 下面显示队友那条剩多少
   （index.html 没有 #foeMateBar，纯联机专属）。半透明 50%——用户 2026-09 要求，
   一眼能看出这不是自己在打的那条，跟真血条区分开。*/
.fbar.mate{opacity:.5;margin-top:3px}
.haunt{font-family:var(--mono);font-size:10px;letter-spacing:.14em;color:var(--blood);
  background:#F7E3DE;border:1px solid #E2BEB6;border-radius:2px;
  padding:2px 7px;align-self:center;margin-bottom:2px}
.haunt[hidden]{display:none !important}
.wagerrow{display:flex;justify-content:center}
.wager{width:100%;display:flex;flex-direction:column;align-items:center;gap:1px;
  background:var(--stone-2);border:1px dashed var(--edge);border-radius:3px;
  padding:clamp(3px,0.8vh,6px) 10px;cursor:pointer;font-family:var(--body);color:var(--dim);
  font-size:clamp(12px,1.9vh,13px)}
.wager em{font-style:normal;font-size:10.5px;color:var(--faint)}
.wager:hover{border-color:var(--torch-deep);color:var(--torch)}
.wager.on{background:#F6E6C4;border:1px solid var(--torch-deep);color:var(--torch-deep);font-weight:600}
.wager.on em{color:var(--torch-deep)}
.wager:disabled{opacity:.5;cursor:default}

/* ===== 遗物 ===== */
.relics{display:flex;flex-direction:column;gap:8px}
.relic{display:flex;flex-direction:column;gap:2px;width:100%;text-align:left;
  border:1px solid var(--edge);background:var(--stone-2);border-radius:3px;
  padding:10px 12px;cursor:pointer;font-family:var(--body);color:var(--bone)}
.relic:hover{border-color:var(--r3);background:#F5EFF8}
/* 颜色交给品质类 .q0-.q4，这里不设色 —— 否则权重压过它们 */
.relic .rn{font-family:var(--disp);font-size:16px;font-weight:600;letter-spacing:.04em}
.relic .rp{font-size:12.5px;color:var(--bone)}
.relic .rl{font-family:var(--flavor);font-style:italic;font-size:11.5px;color:var(--faint);margin-top:2px}
.relic.own{cursor:default;padding:7px 9px;background:var(--stone-2)}
.relic.own:hover{border-color:var(--edge);background:var(--stone-2)}
.relic.own .rn{font-size:14px}
.relic.own .rp{font-size:11.5px;color:var(--dim)}

/* 换遗物弹层里高亮"新拿到的那件" */
.relic.hot{border-color:var(--r3);background:#F5EFF8;cursor:default}
.relic.hot:hover{border-color:var(--r3);background:#F5EFF8}

/* ===== 遗物品质 ===== */
:root{
  --q0:#6B665C;  /* 普通 */
  --q1:#2A62AD;  /* 稀有 */
  --q2:#6F3D98;  /* 史诗 */
  --q3:#B45B12;  /* 传奇 */
  --q4:#A8891C;  /* 神圣 */
}
.q0{color:var(--q0)} .q1{color:var(--q1)} .q2{color:var(--q2)}
.q3{color:var(--q3)} .q4{color:var(--q4)}
.relic .rt{font-family:var(--mono);font-size:9.5px;letter-spacing:.16em}
.relic.own{flex-direction:row;align-items:center;gap:9px}
.relic.own .col{flex:1;min-width:0;display:flex;flex-direction:column;gap:1px}
.relic.own .melt{flex:none;display:flex;flex-direction:column;align-items:center;gap:0;
  font-family:var(--body);font-size:11.5px;padding:5px 9px;border-radius:2px;cursor:pointer;
  background:var(--stone-3);color:var(--dim);border:1px solid var(--edge)}
.relic.own .melt em{font-style:normal;font-size:10px;color:var(--torch)}
.relic.own .melt:hover{border-color:var(--blood);color:var(--blood)}

/* ===== 合成 =====
   面板上只有「选择」「合成」两个按钮；材料是在上面那张遗物列表里点出来的。 */
.relic.own.pickable{cursor:pointer}
.relic.own.pickable:hover{border-color:var(--torch-deep);background:#FDF6E7}
.relic.own.picked{border-color:var(--torch-deep);background:#F6E6C4}
.relic.own.picked:hover{border-color:var(--torch-deep);background:#F6E6C4}
.relic.own.off{opacity:.42;cursor:default}
.relic.own.off:hover{border-color:var(--edge);background:var(--stone-2)}
.relic.own .tick{flex:none;width:22px;text-align:center;font-size:15px;color:var(--torch-deep);font-weight:700}

/* ===== 刚拿到的那几件：左上角一个「new」小红点，点一下那张卡就没了 =====
   纯界面状态，不进存档（回主城 / 重开一趟就清）。 */
.relic.own.fresh{position:relative;border-color:var(--blood)}
.newdot{position:absolute;left:-4px;top:-5px;z-index:1;
  font-family:var(--mono);font-size:8.5px;letter-spacing:.08em;line-height:1;
  padding:2px 4px;border-radius:7px;background:var(--blood);color:#FFF7EE;
  box-shadow:0 1px 2px rgba(0,0,0,.25)}
