  @font-face {
    font-family: "fusion-pixel";
    /* fusion-pixel 12px 比例中文像素字体,子集化 woff2 */
    src: url("fonts/fusion-pixel-12px-proportional-zh_hans.ttf.woff2") format("woff2");
    font-display: swap;
  }
  * { box-sizing: border-box; margin: 0; padding: 0; }
  /* HUD/状态窗 HP·MP·SP 条尺寸的唯一真相源:两处共用,改这里两边同步。by ting */
  :root { --vbar-track-h: 12px; --vbar-fill-h: 10px; --stat-avatar-sz: 64px; --win-radius: 4px; --el-radius: 4px; --bar-radius: 2px; --win-pad: 8px; --cell-gap: 1px;
    /* 格子边框重叠量:负值让相邻格子的 1px 边框叠成一条线。gap 不能为负,故 grid 用 --cell-track 缩轨道、flex 用负 margin 实现 */
    --cell-overlap: -1px; --cell-track: calc(48px + var(--cell-overlap)); --srow-h: 46px;
    --win-title-fs: 14px;   /* 窗口标题字号:地图框内窗(#mapcard h3:道具/技能/NPC交互)+ 全屏弹窗(#modal h3:登录/角色/系统),全局共享一处 */
    --win-btn-h: 24px; }   /* 弹窗底部按钮统一高度:返回/关闭/翻页/继续/结束/书籍翻页合上等(不含页面内 #panel 行按钮与商店族矮箭头) */
  /* 表单控件默认不继承 body 字体,显式让它们跟随全局字体;统一压 line-height,防像素字体 normal 行高撑高按钮 */
  button, input, select, textarea { font-family: inherit; line-height: 1.0; }
  body {
    font-family: "fusion-pixel", sans-serif;
    background: #14110d; color: #ece5d8;
    display: flex; justify-content: center; padding: 2px 2px 2px;
    overflow: hidden;   /* 放大溢出时不出滚动条;缩放由 applyUiScale() 控制在视口内 */
  }
  /* 整体画面等比缩放:--ui-scale 由 applyUiScale() 按窗口尺寸算出(见 panel.js)。
     transform 不改变文档流尺寸(仍占 720px),故缩放比例计算用 offsetWidth/Height 不会与缩放互相循环。
     origin 顶部居中:缩小时画面贴顶居中,弹窗靠 --game-cy 跟随实际中心。 */
  #game { width: 720px; transform: scale(var(--ui-scale, 1)); transform-origin: top center; }
  .tools { display: flex; flex-wrap: wrap; gap: 2px; justify-content: flex-end; align-items: center; }
  /* 名字段(.tools-info)已从 .tools 拆出为 .hud-right 独立子节点(多端解耦)。
     桌面靠 .hud-right 的 grid 恢复"名字左 + 按钮右"同排(见下方 #hud .hud-right)。
     内部 #hud-comps 的 margin-right:auto 仍把铜币顶到名字段右端(= 按钮组左侧,近 HP 条右端)。 */
  .tools-info { min-width: 0; display: flex; align-items: center; gap: 0; }
  .tools-info .hudname { color: #c9a44c; font-weight: 700; font-size: 13px; letter-spacing: 1px; }
  .tools-info #hud-comps { margin-right: auto; }   /* 伙伴/状态徽章,用 auto 把铜币推到名字段右端 */
  .tools #btn-pk.pk-on { background: #3a2018; border-color: #6a3a2c; color: #e0a890; }
  .tools #btn-pk.pk-on:hover { background: #4a2820; }
  .tools button {
    background: #2b2419; color: #cdbf9c; border: 1px solid #5a4a2c;
    padding: 4px 12px; border-radius: var(--el-radius); cursor: pointer; font-size: 13px; line-height: 1;
  }
  .tools button:hover { background: #3a3120; }

  /* 地图区域 */
  #map {
    position: relative; width: 720px; height: 420px;
    border: 1px solid #5a4a2c; border-radius: var(--win-radius); overflow: hidden;
    box-shadow: inset 0 0 60px #000a;
    margin-top: -1px;
  }
  #bg { position: absolute; inset: 0; pointer-events: none; width: 100%; height: 100%; }
  /* 顶栏:横跨地图全宽的 flex 行,遮层渐变挂在此处。左=时间(自适应)、右=地图名(自适应)、中=公告(吃满剩余并居中) */
  #topbar {
    position: absolute; top: 0; left: 0; right: 0; z-index: 6; pointer-events: none;
    display: flex; align-items: flex-start; padding-bottom: 16px;
    background: linear-gradient(to bottom, #000a 0%, #0000 100%);
  }
  /* 地图名容器(顶栏右侧):纵向排列,地图名在上、坐标在下,整体右推靠边 */
  #maphead { flex: 0 0 auto; margin-left: auto; display: flex; flex-direction: column; align-items: flex-end; }
  /* 当前地图名称(文字浮在遮层之上) */
  #mapname {
    padding: 4px 4px 0; color: #e0c878; font-size: 14px; letter-spacing: 1px;
    text-shadow: 0 1px 3px #000, 0 0 6px #000;
  }
  /* 当前地点坐标(地图名下方一行,小字暗色不明显) */
  #mapcoord {
    padding: 0 4px 4px; color: #8a7d60; font-size: 10px; letter-spacing: 1px;
    text-shadow: 0 1px 3px #000, 0 0 6px #000;
  }
  /* 游戏时间(顶栏左侧,自适应宽度) */
  #gametime {
    flex: 0 0 auto; padding: 4px 4px; color: #e8dcc0; font-size: 14px; letter-spacing: 1px;
    text-shadow: 0 1px 3px #000, 0 0 6px #000; white-space: nowrap;
  }
  #gametime .gt-icon { margin-right: 4px; }
  #gametime .gt-flavor { font-size: 13px; color: #b0a488; margin-left: 8px; letter-spacing: 0; }
  /* 顶栏中段状态区(时间与地图名之间):伙伴头像/魔法盾/buff 徽章。占据中间弹性空间,居中排列。 */
  #map-status {
    flex: 1 1 auto; display: flex; align-items: center; justify-content: center; flex-wrap: wrap;
    gap: 5px; padding: 4px 6px; pointer-events: auto;
  }
  /* 顶栏状态区图标/文字:图标统一 16px、文字 13px,PNG 与 emoji 齐高;改大小动这三行的 font-size 和下面 .ic-sm 覆盖即可 */
  #map-status .hud-comp { font-size: 16px; line-height: 1; cursor: default; filter: drop-shadow(0 1px 2px #000); }
  #map-status .hud-shield { font-size: 16px; line-height: 1; filter: drop-shadow(0 0 3px #5fa8ff); animation: shieldPulse 3s ease-in-out infinite; }
  #map-status .hud-buffs { font-size: 13px; line-height: 1; letter-spacing: 1px; color: #e8dcc0; text-shadow: 0 1px 3px #000;
    display: inline-flex; align-items: center; flex-wrap: wrap; }   /* flex 居中:图标与倒计时数字按几何中心对齐(vertical-align:middle 够不到,数字会偏上) */
  /* 图标 20px + 2px 边框覆盖在图片最外圈:outline 外缘与 20×20 外沿齐平(offset:-2px 让 2px 描边整条落在盒内),
     且 outline 总叠在位图之上——不像 inset box-shadow 会被满幅 PNG(如诱惑之光 004)的不透明位图盖死。
     不撑大布局、不缩小图片、对 <img> 与 emoji <span> 一致生效。 */
  #map-status .ic-sm { width: 16px; height: 16px; font-size: 13px; display: inline-block; vertical-align: middle;
    border-radius: var(--el-radius); outline: 1px solid #5a4a2c; outline-offset: -1px; }
  /* 技能 PNG 全局压暗 0.7,在顶栏状态区还原正常亮度(与 HUD 快捷栏规则对称) */
  #map-status img.ic-img[src*="/skill/"] { filter: none; }
  /* 公告弹窗正文:保留换行 */
  .announce-body { white-space: pre-wrap; line-height: 1.7; color: #d8cba8; font-size: 14px; max-height: 50vh; overflow-y: auto; }
  /* 当前地点名称与描述(地图左下角,保持2行) */
  #maploc {
    position: absolute; bottom: 0px; left: 0px; right: 2px; z-index: 5; pointer-events: none;
    padding: 4px 4px 4px; text-shadow: 0 1px 3px #000, 0 0 6px #000;
    background: linear-gradient(to top, #000a 0%, #0000 100%);
  }
  #maploc .ml-name { font-size: 14px; color: #e0c878; }
  #maploc .ml-desc { font-size: 13px; color: #9a8d70; margin-top: 1px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  #maploc .ml-presence { display: inline-block; font-size: 13px; color: #7fb0e0; margin-top: 1px; }
  /* 注册头像选择 */
  .avatarpick { display: flex; flex-wrap: wrap; gap: 6px; justify-content: center; }
  /* PNG 头像统一样式:等比适配方框,行内对齐(可嵌入文本/盒子)。 */
  .av-img { object-fit: contain; vertical-align: middle; image-rendering: auto; }
  /* 图标/头像三层统一尺寸:行内文本(sm)/格子(md)/大图(lg)。img 与 emoji 同尺寸,改尺寸只动这里。
     iconHtml/avatarHtml 输出层级 class,不再写内联 px。span 用于 emoji 文本,img 用于 PNG。 */
  .ic-sm, .ic-md, .ic-lg { vertical-align: middle; }
  img.ic-sm, img.ic-md, img.ic-lg { object-fit: contain; }
  /* 图标 PNG 圆角:容器圆角约 6px,图片四角戳出时给图片本身加圆角贴合(只命中 .ic-img,不影响玩家头像 .av-img)。值按需调。by ting */
  img.ic-img { border-radius: var(--el-radius); }
  span.ic-sm, span.ic-md, span.ic-lg { display: inline-block; line-height: 1; }
  img.ic-sm { width: 16px; height: 16px; } span.ic-sm { font-size: 16px; }/*修改三种格子图标的大小by ting*/
  img.ic-md { width: 40px; height: 40px; } span.ic-md { font-size: 28px; }
  img.ic-lg { width: 48px; height: 48px; } span.ic-lg { font-size: 48px; }
  /* 缺图占位:无图片编号时渲染统一灰底方框(本游戏不使用任何 emoji,故无文字回落) */
  span.ic-empty { background: #2a2418; border: 1px solid #5a4a2c; border-radius: var(--el-radius); box-sizing: border-box; }
  span.ic-empty.ic-sm { width: 16px; height: 16px; }
  span.ic-empty.ic-md { width: 40px; height: 40px; }
  span.ic-empty.ic-lg { width: 48px; height: 48px; }
  /* ===== 通用货币芯片(铜币/点券)=====
     图标+数字统一对齐的唯一真相源:inline-flex 交叉轴居中,不依赖 vertical-align(那玩意受行高/基线影响不稳)。
     .coin 只管对齐+默认棕色铜币;.coin.premium 换点券蓝;字号继承上下文(卡片内随卡片文字、按钮内随按钮)。
     .coins 是余额组容器(多币种并排):负责右下定位与组内间距、统一 13px。改铜币外观只动这三条。by ting */
  .coin { display: inline-flex; align-items: center; gap: 2px; color: #c87f4a; white-space: nowrap; }
  .coin.premium { color: #7fb0e0; }
  .coins { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 8px; font-size: 13px; }
  /* HUD 快捷栏单独覆盖 md 尺寸(格子仅 40px,与背包/战斗的 .ic-md 区分):emoji 走 span、png 走 img,值按效果调。by ting */
  .hud-hotbar .hcell .ic span.ic-md { font-size: 24px; }            /* HUD emoji 大小 */
  .hud-hotbar .hcell .ic img.ic-md  { width: 32px; height: 32px; }  /* HUD png 大小(勿超 ~38px 否则溢出格子) */
  /* 技能图标 PNG 统一降亮度(靠路径 /skill/ 命中,不碰物品/怪物/头像);快捷栏用高特异性还原正常亮度。值按需调。by ting */
  img.ic-img[src*="/skill/"] { filter: brightness(0.7); }
  .hud-hotbar .hcell .ic img.ic-img[src*="/skill/"] { filter: none; }
  .avatarcell { width: 44px; height: 44px; font-size: 26px; line-height: 1; cursor: pointer;
    background: #14110d; border: 1px solid #5a4a2c; border-radius: var(--el-radius); display: flex;
    align-items: center; justify-content: center; padding: 0; transition: border-color .12s, background .12s; }
  .avatarcell:hover { background: #2a2418; }
  .avatarcell.sel { border-color: #e0c878; box-shadow: 0 0 10px #e0c87866; background: #2a2418; }
  /* 同地点玩家名单 */
  .ml-players { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 1px; }
  .ml-players .pchip { font-size: 13px; color: #7fb0e0; cursor: pointer; white-space: nowrap;
    pointer-events: auto; text-shadow: 0 1px 3px #000, 0 0 6px #000; }
  .ml-players .pchip:hover { color: #a9d0ff; text-decoration: underline; }
  .ml-players .pchip .act-tag { color: #c89; font-size: 12px; }
  .ml-players .pchip .act-tag.combat { color: #e08a7a; }
  .ml-players .pchip .act-tag.gambling { color: #d8b04a; }
  /* 地面物品行:暖金色 chip,与玩家(蓝)区分;空时灰色斜体占位 */
  .ml-ground { display: flex; flex-wrap: wrap; gap: 4px; align-items: center; margin-top: 1px;
    font-size: 13px; text-shadow: 0 1px 3px #000, 0 0 6px #000; }
  .ml-ground .gchip { color: #d9b870; cursor: pointer; white-space: nowrap; pointer-events: auto; font-size: 13px; }
  .ml-ground .gchip:hover { color: #f0d090; text-decoration: underline; }
  .ml-ground.empty { color: #8a7a58; font-style: normal; }
  /* 玩家/地面物品列表的翻页控件(applyRowPaging 动态挂):纯文字形式(非按钮),挂行尾。
     #maploc 是 pointer-events:none,故此处须显式 auto 才可点。页码整合在文字内(如 1/2),点击循环切页。 */
  #maploc .row-pager { margin-left: auto; flex: 0 0 auto; display: inline-flex; align-items: center; pointer-events: auto; }
  #maploc .row-pager .pg-btn { background: none; border: none; padding: 0 2px; cursor: pointer;
    font: inherit; font-size: 13px; color: #7fb0e0; text-shadow: 0 1px 3px #000, 0 0 6px #000; white-space: nowrap; }
  #maploc .row-pager .pg-btn:hover { color: #a9d0ff; text-decoration: underline; }
  /* 世界层:装连线与格子,随相机平移,使玩家始终居中 */
  #world { position: absolute; left: 0; top: 0; will-change: transform; }
  #lines { position: absolute; left: 0; top: 0; pointer-events: none; }
  .node {
    position: absolute; transform: translate(-50%, -50%);
    border-radius: var(--el-radius);
    border: 2px solid #6b5836; background: #2a2418cc; color: #e8dcc0;
    cursor: pointer; font-size: 13px; backdrop-filter: blur(1px);
    display: flex; align-items: center; justify-content: center; text-align: center;
    transition: transform .15s, box-shadow .15s, border-color .15s; z-index: 3;
  }
  .node:hover { transform: translate(-50%, -50%) scale(1.08); }
  .node.current { border-color: #e0c8787c; }
  .node.reachable { border-color: #7fafe088; }
  .node.locked { opacity: .4; cursor: not-allowed; filter: grayscale(1); }
  .node.door-locked { border-color: #c0863088; border-style: dashed; color: #d8b878; }   /* 副本锁门:虚线橙框标识需钥匙 */
  .node.busy { pointer-events: none; }
  .node.ship-deck { border-color: #3a7a9b; border-style: dashed; background: #0f2535cc; color: #a8d4e8; }

  /* 行走的主角 */
  #hero {
    position: absolute; width: 64px; height: 64px;
    transform: translate(-30%, calc(-85% - 24px)); transform-origin: 0 0; z-index: 4;
    pointer-events: none; transition: none;
  }
  /* idle / walk 两层精灵叠放:背景图常驻,切状态只切显隐,避免换 background-image 的重解码闪烁 */
  #hero .hero-sheet {
    position: absolute; top: 0; left: 0; right: 0; bottom: 0;   /* 勿用 inset 简写:iOS 13(iPad mini 4 等)不支持,精灵层会塌成 0×0 而不显示 */
    background-repeat: no-repeat; background-size: auto 64px; image-rendering: pixelated;
  }

  /* 状态栏:上排(头像 + HP/MP + 快捷栏),下排 EXP 通栏 */
  #hud {
    display: flex; flex-direction: column; gap: 4px;
    background: linear-gradient(135deg, #241d2e, #1b1610); border: 1px solid #5a4a2c;
    border-radius: var(--win-radius); padding: 4px 4px;
  }
  /* 主区:左头像(跨两行) + 右侧两行(按钮 / HP·MP·快捷栏) */
  #hud .hud-main { display: flex; align-items: stretch; gap: 8px; }
  /* 右侧网格:上排 名字段(左,1fr) + 按钮组(右,auto)同一行;下排 #hudvitals 跨两列。
     替代旧的 flex column + .tools-info 397px 魔法数(已随 DOM 拆分移除)。 */
  #hud .hud-right { flex: 1; min-width: 0; display: grid; grid-template-columns: 1fr auto;
    align-items: center; gap: 0 10px; }
  #hud .hud-right .tools-info { grid-column: 1; }
  #hud .hud-right .tools { grid-column: 2; }
  #hud .hud-right #hudvitals { grid-column: 1 / -1; display: flex; align-items: flex-end; gap: 10px; }
  /* 头像高度由此处控制;右侧整列 stretch 到同高,space-between 自动分配按钮↕快捷栏间距 */
  #hud .hud-avatar { position: relative; width: 64px; height: 64px; flex: 0 0 auto;
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 0px;
    font-size: 40px; line-height: 1;
    background: #14110d; border: 1px solid #4a3d24; border-radius: var(--el-radius);
    filter: drop-shadow(0 3px 5px #000a) saturate(.75) brightness(.85); opacity: .9; }
  #hud .hud-avatar .lvbadge {
    background: linear-gradient(135deg, #c9b478, #9a7028); color: #2a2012; font-weight: 700;
    font-size: 12px; padding: 1px 3px; border-radius: var(--el-radius); border: 1px solid #2a2012;
    box-shadow: 0 2px 4px #0008; white-space: nowrap; }
  /* 等级徽标内的职业名:与 Lv 之间留 3px 间距(HUD/观察卡共用) */
  .lvbadge .lvcls { margin-right: 3px; }
  /* 性别符号:叠在 HUD 头像框右上角 */
  #hud .hud-avatar .hud-sex { position: absolute; top: 1px; right: 2px; font-size: 13px; line-height: 1;
    text-shadow: 0 0 2px #000, 0 0 2px #000; z-index: 1; pointer-events: none; }
  /* HP/MP 缩短:占据快捷栏左侧剩余空间,两条紧贴并下移贴近 EXP */
  #hud .hud-vitals { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; justify-content: flex-end; gap: 0; }
  .copper .ic-sm { vertical-align: middle; margin-right: 0px; }   /* 铜币图标(状态窗/奖励)与数字间距 */
  /* 玩家名右侧:魔法盾/状态徽章/伙伴怪物图标(纯图标,无文字) */
  #hud .hud-comps { display: flex; gap: 0px; align-items: center; }
  #hud .hud-comp { font-size: 14px; line-height: 1; cursor: default; filter: drop-shadow(0 1px 1px #000) saturate(.8) brightness(.9); opacity: .88; }
  /* 名字行图标统一尺寸(HUD 玩家名行 + 状态窗名字行):伙伴诱惑/召唤、魔法盾、状态徽章、铜币。改大小只动这一处。 */
  #hud .tools-info img.ic-sm, .stat-head .who .nm img.ic-sm { width: 20px; height: 20px; }
  #hud .tools-info span.ic-sm, .stat-head .who .nm span.ic-sm { font-size: 20px; }
  /* 玩家名一行右侧的铜币(图标+数量),靠 #hud-comps 的 margin-right:auto 推到 tools-info 段右端(= HP 条右端) */
  #hud #hud-copper { display: inline-flex; align-items: center; color: #c87f4a; font-weight: 700; font-size: 12px; line-height: 1; white-space: nowrap; }
  #hud #hud-premium { display: inline-flex; align-items: center; color: #7fb0e0; font-weight: 700; font-size: 12px; line-height: 1; white-space: nowrap;  }
  /* 资源进度条 */
  #hud .hbar { display: flex; align-items: center; gap: 1px; font-size: 11px; }
  #hud .hbar .blabel { width: 32px; color: #8a7d60; flex: 0 0 auto; font-weight: 600; }
  #hud .hbar .track { flex: 1; height: 7px; background: #2a2418; border: 1px solid #3a3020;
    border-radius: var(--bar-radius); overflow: hidden; position: relative; }
  #hud .hbar .track > i { display: block; height: 100%; border-radius: var(--bar-radius) 0 0 var(--bar-radius); transition: width .35s; }
  #hud .hud-vitals .hbar .track { height: var(--vbar-track-h); border-radius: var(--bar-radius); }
  #hud .hud-vitals .hbar .track > i { height: var(--vbar-fill-h); }
  /* 恢复类装备(生命/魔力之源)HUD 指示:HP/MP 条右侧显图标 + 剩余充能点。flex:0 0 auto 不挤压进度条,仅占内容宽。 */
  #hud .hud-vitals .hbar .hbar-rec { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 1px;
    font-size: 11px; line-height: 1; color: #d8cba8; white-space: nowrap; }
  #hud .hud-vitals .hbar .hbar-rec img.ic-sm { width: 14px; height: 14px; }
  #hud .hud-vitals .hbar .hbar-rec span.ic-sm { font-size: 14px; }
  #hud .hud-vitals .hbar .hbar-rec .rec-n { font-weight: 700; color: #e0c878; }
  /* 进度条内数值的唯一真相源:HUD 的 .v 与战斗的 .barval 共用一套效果,改这里两边同步。by ting */
  #hud .hbar .track .v, .barval { position: absolute; inset: 0; display: flex; align-items: center; justify-content: flex-start;
    padding-left: 1px; font-size: 11px; line-height: 1; color: #c8bfac; text-shadow: 0 1px 2px #000, 0 0 3px #000;
    pointer-events: none; font-weight: bold; }
  /* 战斗进度条数值居中(HUD 保持左对齐);其余效果沿用上面共用规则 */
  .barval { justify-content: center; padding-left: 0; }
  #hud .hbar.hp i { background: linear-gradient(90deg, #732820, #897028); }
  #hud .hbar.mp i { background: linear-gradient(90deg, #1e3354, #2c5076); }
  #hud .hbar.sta i, .stat-bar.sp i { background: linear-gradient(90deg, #204d25, #3d7c3e); }   /* SP 条配色(HUD + 状态窗共用一处) */
  /* 魔法盾生效:仅靠名字旁标识(脉动),不改 MP 条样式 */
  #hud .hud-shield { font-size: 15px; line-height: 1; filter: drop-shadow(0 0 3px #5fa8ff) saturate(.8) brightness(.9); animation: shieldPulse 3s ease-in-out infinite; }
  /* HUD 战斗外状态效果(中毒/减速/加速/石化):魔法盾右侧,小字图标+剩余秒 */
  #hud .hud-buffs { font-size: 13px; line-height: 1; letter-spacing: 1px; margin-left: 2px; opacity: 1; }
  /* 状态窗的当前生效状态区:头像/EXP 条下方的专属一排(横跨整行),与上方隔行分隔 */
 
  .stat-buffs { text-align: center; }
  .stat-buffs .statbuff { font-size: 13px; color: #cdbc8f; background: rgba(120,100,60,.18); border-radius: var(--el-radius); padding: 1px 6px; letter-spacing: 0; white-space: nowrap; }
  .stat-buffs .statbuff-none { font-size: 13px; color: #6a5d44; letter-spacing: 1px; }
  @keyframes shieldPulse { 0%,100% { opacity: .88; } 50% { opacity: .48; } }
  /* 魔法盾生效中:快捷格/战斗按钮内描边脉动(呼吸边框在主边框内侧),与未生效态区分;点击改为收起 */
  .hcell.shield-on, .slotbtn.shield-on { box-shadow: inset 0 0 0 2px #5fa8ff, inset 0 0 8px rgba(95,168,255,.6); animation: shieldEdge 3s ease-in-out infinite; }
  @keyframes shieldEdge { 0%,100% { box-shadow: inset 0 0 0 2px #5fa8ff, inset 0 0 8px rgba(95,168,255,.6); } 50% { box-shadow: inset 0 0 0 2px #2c5076, inset 0 0 3px rgba(44,80,118,.5); } }
  #hud .hbar.xp i { background: linear-gradient(90deg, #946018, #a07e2c); }
  /* HUD 快捷栏:HP/MP 右侧,紧凑格子(自然宽度,右缘与按钮/经验条对齐) */
  /* 快捷栏样式脱离 #hud 作用域(改挂 .hud-hotbar):竖屏该节点被搬到 #map 后已在 #hud 外,选择器仍须命中。
     .hcell 为快捷栏专用类,一律改 .hud-hotbar .hcell 保持相对优先级顺序不变。 */
  .hud-hotbar { flex: 0 0 auto; display: flex; gap: 0; justify-content: flex-end; }
  .hud-hotbar > * + * { margin-left: var(--cell-overlap); }
  .hud-hotbar .hcell { position: relative; width: 36px; height: 36px; flex: 0 0 auto;
    border: 1px solid #4a4028; border-radius: var(--el-radius); background: #1b1710;
    display: flex; align-items: center; justify-content: center; font-size: 24px; line-height: 1;
    color: #5a4a2c; transition: border-color .12s, background .12s; }
  .hud-hotbar .hcell.filled { border-color: #8a7440; color: #ece5d8; cursor: pointer;
    filter: saturate(.8) brightness(.9); opacity: .88; }
  .hud-hotbar .hcell.filled:hover { background: #2a2418; border-color: #c0a050; filter: none; opacity: 1; }
  .hud-hotbar .hcell.filled.disabled { cursor: not-allowed; filter: grayscale(.7) brightness(.55); opacity: .5; }
  .hud-hotbar .hcell.filled.disabled:hover { background: #1b1710; border-color: #8a7440; filter: grayscale(.7) brightness(.55); opacity: .5; }
  /* 打开道具/技能窗时:快捷栏全部点亮(覆盖 disabled 变暗,纯视觉)。挂 #game(恒为快捷栏祖先,横竖屏通用) */
  #game.hotbar-lit .hud-hotbar .hcell.filled.disabled,
  #game.hotbar-lit .hud-hotbar .hcell.filled.disabled:hover { filter: none; opacity: 1; cursor: pointer; }

  /* 面板 */
  #panel {
    background: #1d1812; border: 1px solid #4a3d24; border-radius: var(--win-radius);
    padding: 4px 4px;
    margin-top: -1px;
  }
  #panel h2 { font-size: 16px; color: #e0c878; margin-bottom: 4px; }
  #panel .desc { color: #9a8d70; font-size: 13px; margin-bottom: 12px; }
  .row { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 8px; align-items: center; }
  /* 地点面板的 NPC / 怪物两行:固定高度,无内容时不收窄 */
  #panel .row { min-height: 30px; margin-bottom: 4px; gap: 4px; }
  #panel .row:last-child { margin-bottom: 0; }
  .label { width: 56px; color: #8a7d60; font-size: 13px; }
  /* 基础 action 按钮:服务地点面板之外的场景(观察窗攻击/PK 切换/PVP 等)。
     注意:地点面板内的 NPC/怪物按钮 padding 由下方 #panel .row button.action 独占覆盖,此处 6px 对它们不生效。 */
  button.action {
    background: #332b1c; color: #ece5d8; border: 1px solid #5a4a2c;
    padding: 6px 6px; border-radius: var(--el-radius); cursor: pointer; font-size: 13px;
  }
  button.action:hover { background: #443818; }
  button.monster { background: #3a2018; border-color: #6a3a2c; position: relative; font-size: 13px; }
  button.monster:hover { background: #4a2820; }
  button.monster.engaged { opacity: 0.5; cursor: default; color: #c89; border-style: dashed; }
  button.monster.engaged:hover { background: #3a2018; }
  /* 按钮内"名字+血条"竖列:图标在左不动,名字在上、血条紧贴名字下方(宽度随名字,不横跨整钮) */
  button.hasbar { position: relative; }
  .nmhp { display: inline-flex; flex-direction: column; justify-content: center; gap: 1px; min-width: 0; }
  button.monster .mhp, button.hasbar .mhp {
    display: block; width: 100%; height: 4px;
    background: rgba(0,0,0,.45); border-radius: var(--el-radius); overflow: hidden;
  }
  button.monster .mhp-fill, button.hasbar .mhp-fill {
    display: block; height: 100%; background: #6fbf5a;
    border-radius: var(--el-radius); transition: width .2s;
  }
  button.shop { background: #1e3320; border-color: #2c5a34; }
  button.shop:hover { background: #284828; }
  button.action:disabled { opacity: .4; cursor: not-allowed; }
  /* 弹窗底部按钮统一高度(--win-btn-h):观察窗壳底行(obv-actions)、独立底行(win-actions:伙伴/活动/系统/选目标等)、
     书籍窗翻页合上、技能窗翻页关闭、物品操作窗(opbtns)、格子/确认弹窗(cellmenu)。改高度只需动 :root 的 --win-btn-h 一处。
     box-sizing:border-box + inline-flex 居中,让固定高压过基础 padding:6px;不含 #panel 行按钮与商店族矮箭头(那些是页面内按钮)。 */
  .obv-actions .action,
  .win-actions .action,
  #bookwin .action,
  .skill-pager .action,
  #opmenu .opbtns .action,
  .cellmenu > .action {
    height: var(--win-btn-h); box-sizing: border-box; padding-top: 0; padding-bottom: 0;
    display: inline-flex; align-items: center; justify-content: center;
  }
  /* 地点栏 NPC/怪物按钮:图标+文字作为一组,flex 水平+垂直居中(图标参与布局,不与文字叠加);图标略小于按钮高,留边距不顶边 */
  /* ← 面板内按钮左右边距的唯一生效处(2px);上方基础 button.action 的 6px 在此被覆盖,改动只需动这一行 */
  #panel .row button.action { height: 30px; padding: 0 2px;
    display: inline-flex; align-items: center; justify-content: center; gap: 2px; }
  #panel .row button.action > img.ic-sm { width: 26px; height: 26px; }
  #panel .row button.action > span.ic-sm { font-size: 16px; }
  /* 行分页控件(applyRowPaging 动态挂,仅需翻页时出现):单个循环翻页按钮,页码整合在按钮内(如"1/2"),挂行尾。横竖屏通用 */
  #panel .row .row-pager { margin-left: auto; display: inline-flex; align-items: center; flex: 0 0 auto; }
  #panel .row .row-pager .pg-btn { height: 30px; padding: 0 4px; font-size: 11px; line-height: 1; white-space: nowrap;
    background: #332b1c; color: #cdbf9c; border: 1px solid #5a4a2c; border-radius: var(--el-radius); cursor: pointer; }
  #panel .row .row-pager .pg-btn:hover { background: #443818; }
  .empty { color: #6a5d44; font-size: 13px; font-style: italic; }
  /* 场景事件框:显示"你来到了…""此路不通"等提示(作为底部左栏) */
  #events { padding: 4px 4px; background: #14110d;
    border: 1px solid #4a3d24; border-radius: var(--win-radius); overflow-y: auto;
    flex: 1 1 0; min-width: 0; }
  #events .evt { font-size: 13px; color: #b9ad8e; line-height: 1; padding: 0; margin-bottom: 1px; }
  #events .evt.warn { color: #e0a050; }   /* 警告类:此路不通等 */
  #events .evt.good { color: #6bd17a; }   /* 利好类 */

  /* 底部:左事件信息栏 + 右聊天面板(NPC/怪物布局在上方 #panel 内,保持全宽不动)*/
  #bottom { display: flex; gap: 0; align-items: stretch; margin-top: -1px; height: 124px; }
  /* 聊天社交面板(右栏,独立持久,不随 renderPanel 重写) */
  #chat {
    flex: 1 1 0; min-width: 0; display: flex; flex-direction: column;
    background: #1d1812; border: 1px solid #4a3d24; border-radius: var(--win-radius);
    overflow: hidden;
  }
  #chat-stream { flex: 1 1 auto; min-height: 0; overflow-y: auto;
    padding: 1px 1px; background: #14110d; margin: 1px 1px 0; }
  #chat-stream .cmsg { font-size: 13px; line-height: 1; margin-bottom: 1px;
    word-break: break-word; }
  #chat-stream .cmsg .ch { font-size: 13px; }
  #chat-stream .cmsg .ch.world { color: #c0a050; }
  #chat-stream .cmsg .ch.area { color: #9a86d0; }
  #chat-stream .cmsg .ch.loc { color: #6bb0a0; }
  #chat-stream .cmsg .who { color: #7fb0e0; }
  #chat-stream .cmsg .who.me { color: #6bd17a; }
  #chat-stream .cmsg .txt { color: #cdbf9c; }
  #chat-stream .cmsg.sys { color: #6a5d44; font-style: italic; }
  /* 公告消息:聊天流里的可点击一行(点击弹正文)。[公告] 金色标记 + 标题单行省略,与普通消息一起滚动 */
  #chat-stream .cmsg.ann { cursor: pointer; font-style: normal; display: flex; align-items: baseline; }
  #chat-stream .cmsg.ann .ch.ann { flex: 0 0 auto; color: #c0a050; margin-right: 4px; }
  #chat-stream .cmsg.ann .an-title { flex: 1 1 auto; min-width: 0; color: #cdbf9c;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  #chat-stream .cmsg.ann:hover .an-title { text-decoration: underline; }
  #chat-input { display: flex; gap: 2px; padding: 2px; align-items: center; }
  #chat-channel { background: #14110d; color: #e0c878; border: 1px solid #5a4a2c;
    border-radius: var(--el-radius); padding: 0 4px; font-size: 13px; cursor: pointer; flex: 0 0 auto;
    width: 3.6em; height: 24px; text-align: center; text-align-last: center;
    -webkit-appearance: none; -moz-appearance: none; appearance: none; }
  #chat-channel:focus { outline: none; border-color: #7a6332; }
  #chat-text { flex: 1; min-width: 0; background: #14110d; color: #ece5d8;
    border: 1px solid #5a4a2c; border-radius: var(--el-radius); padding: 0 8px; font-size: 13px;
    height: 24px; overflow-y: auto; line-height: 22px; white-space: pre-wrap; word-break: break-word; }
  #chat-text:focus { outline: none; border-color: #7a6332; }
  #chat-text:empty::before { content: attr(data-ph); color: #6a5d44; pointer-events: none; }
  /* 物品/技能引用链接(聊天流 + 输入框内只读标签共用) */
  .chatref { display: inline; padding: 0 2px; border-radius: var(--el-radius); cursor: pointer;
    white-space: nowrap; }
  .chatref.item  { color: #6bb0e0; }
  .chatref.skill { color: #b489e0; }
  .chatref:hover { background: #2a2418; text-decoration: underline; }
  /* 输入框内的只读标签:不可编辑、整体选中删除 */
  #chat-text .chatref { background: #221d14; }
  /* 物品/技能引用详情:居中迷你弹窗 */
  #opmenu { position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: #0008; z-index: 9;   /* 嵌入地图框(挂 #map,与 #opwin 同源);勿用 inset 简写:iOS13 不认致卡片偏左上 */
    display: flex; align-items: center; justify-content: center; }
  #opmenu .opcard { background: #1d1812; border: 1px solid #5a4a2c; border-radius: var(--win-radius);
    padding: var(--win-pad); max-width: 280px; text-align: center; box-shadow: 0 6px 24px #000a; }
  #opmenu .opicon { font-size: 48px; line-height: 1; margin-bottom: 6px; }
  #opmenu .opname { font-size: 15px; font-weight: 700; margin-bottom: 8px; }
  #opmenu .opname.item, #opmenu .opname.affixed { color: #6bb0e0; }   /* 词缀/装备引用:蓝 */
  #opmenu .opname.skill { color: #b489e0; }                            /* 技能引用:紫 */
  #opmenu .opname.plain { color: #c8c4bc; }                            /* 普通物品:白 */
  #opmenu .opdesc { font-size: 13px; color: #9a8d70; line-height: 1.6; margin-bottom: 14px; white-space: pre-line; }
  #opmenu .opbtns { display: flex; flex-direction: row; flex-wrap: wrap; align-items: center; justify-content: center; gap: 8px; }
  #chat-send { background: #332b1c; color: #e0c878; border: 1px solid #5a4a2c;
    border-radius: var(--el-radius); padding: 0 12px; height: 24px; cursor: pointer; font-size: 13px; }
  #chat-send:hover { background: #443818; }
  /* 世界频道无小喇叭:输入框锁定 + 发送键置灰 */
  #chat-text.locked { opacity: 0.5; cursor: not-allowed; }
  #chat-send:disabled { opacity: 0.4; cursor: not-allowed; }
  #chat-send:disabled:hover { background: #332b1c; }

  /* 弹窗 */
  /* 统一弹窗卡片定位:垂直锚到 #game 中心(--game-cy,由 syncGameCenter() 实时写入),水平随页面居中。
     所有居中卡片只引用这一条,改定位算法只动这里。#overlay 铺满全屏、#opmenu 现嵌入地图框(flex 居中卡片)不在此列。 */
  #modal {
    position: fixed; left: 50%; top: var(--game-cy, 50%);
    transform: translate(-50%, -50%) scale(var(--ui-scale, 1));   /* 末尾乘缩放,与主画面同比例;以卡片中心为锚点 */
  }
  #overlay { position: fixed; inset: 0; background: #000b; display: none;
    align-items: center; justify-content: center; z-index: 10; }
  #overlay.show { display: flex; }
  #modal { background: #221c14; border: 1px solid #5a4a2c; border-radius: var(--win-radius);
    padding: var(--win-pad); width: 560px; box-shadow: 0 10px 40px #000c; max-height: 90vh; overflow-y: auto; }
  #modal h3 { color: #e0c878; font-size: var(--win-title-fs); margin-bottom: 8px; }
  /* 设置窗:每行「标签 + 开/关按钮」,按钮宽度统一,开=默认色 关=暗红(.monster) */
  .setwin { min-width: 240px; }
  .setwin h3 { text-align: center; }
  .setwin .set-row { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 8px 4px; border-bottom: 1px solid #3a3120; }
  .setwin .set-label { color: #cdbf9c; font-size: 14px; }
  .setwin .set-row .action { min-width: 52px; text-align: center; }
  /* 副本结算框:在地图框(#mapcard)内显示,仿 .setwin 紧凑风格。除标题外统一 13px(竖屏见下方媒体查询缩小)。 */
  .settle-win { min-width: 260px; font-size: 13px; }
  .settle-win h3 { text-align: center; margin-bottom: 8px; color: #e0c878; font-size: 14px; }
  .settle-stat { display: flex; justify-content: space-between; align-items: flex-start; padding: 4px 2px; gap: 12px; line-height: 1.5; }
  .settle-stat .settle-label { color: #cdbf9c; white-space: nowrap; flex-shrink: 0; }
  .settle-stat span:last-child { text-align: right; white-space: pre-wrap; }
  .settle-divider { height: 1px; background: #3a3120; margin: 2px 0; }
  /* 横排容器:队伍成员 / 击杀怪物 / 战利品 / 副本奖励,统一 flex-wrap,供 .settle-team-member / .settle-chip 使用 */
  .settle-row-flex { display: flex; flex-wrap: wrap; gap: 6px; padding: 2px 4px 4px; }
  .settle-team-member { display: flex; flex-direction: column; align-items: center; gap: 2px; width: 44px; }
  .settle-team-member .ic-sm, .settle-team-member .ic-img.ic-sm, .settle-team-member .av-img.ic-sm { width: 28px; height: 28px; border-radius: 4px; }
  .settle-team-name { color: #cdbf9c; text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 44px; font-size: 11px; }
  .settle-chip { display: inline-flex; align-items: center; gap: 4px; padding: 2px 6px; line-height: 1.6; }
  .settle-chip .ic-sm, .settle-chip .ic-img.ic-sm { width: 16px; height: 16px; }
  /* 竖屏:整体字号/间距进一步缩小,配图标/头像跟着按比例缩,避免挤爆窄屏地图框。 */
  body[data-orient="portrait"] .settle-win { font-size: 11px; }
  body[data-orient="portrait"] .settle-win h3 { font-size: 13px; margin-bottom: 6px; }
  body[data-orient="portrait"] .settle-stat { padding: 2px 2px; gap: 8px; }
  body[data-orient="portrait"] .settle-divider { margin: 2px 0; }
  body[data-orient="portrait"] .settle-row-flex { gap: 4px; padding: 1px 2px 3px; }
  body[data-orient="portrait"] .settle-team-member { width: 36px; gap: 1px; }
  body[data-orient="portrait"] .settle-team-member .ic-sm, body[data-orient="portrait"] .settle-team-member .ic-img.ic-sm, body[data-orient="portrait"] .settle-team-member .av-img.ic-sm { width: 22px; height: 22px; }
  body[data-orient="portrait"] .settle-team-name { max-width: 36px; }
  body[data-orient="portrait"] .settle-chip { padding: 1px 4px; gap: 3px; }
  body[data-orient="portrait"] .settle-chip .ic-sm, body[data-orient="portrait"] .settle-chip .ic-img.ic-sm { width: 13px; height: 13px; }
  /* 启动期(未进入游戏):整块游戏骨架隐藏,页面只剩纯色背景,登录/加载小窗后方不再透出空框架。
     startGame() 移除 body.booting 后骨架揭开。 */
  body.booting #game { visibility: hidden; }
  /* 登录加载小窗:复用 overlay/modal,但收窄成居中小卡片(转圈 + 文案)。 */
  #modal.loadwin { width: auto; min-width: 200px; text-align: center; padding: 22px 30px; }
  .loadwin-spin { width: 30px; height: 30px; margin: 0 auto 12px; border: 3px solid #5a4a2c;
    border-top-color: #e0c878; border-radius: 50%; animation: loadwin-spin .8s linear infinite; }
  .loadwin-text { color: #e0c878; font-size: 14px; }
  @keyframes loadwin-spin { to { transform: rotate(360deg); } }
  /* 资源预载进度条:轨道 + 金色填充,宽度由 JS 按百分比设置 */
  .loadwin-bar { width: 240px; height: 10px; margin: 14px auto 8px; background: #2a2118;
    border: 1px solid #5a4a2c; border-radius: var(--bar-radius); overflow: hidden; }
  .loadwin-bar-fill { width: 0; height: 100%; background: linear-gradient(90deg, #b89048, #e0c878);
    transition: width .2s ease; }
  .loadwin-pct { color: #e0c878; font-size: 14px; }
  /* 休息窗内框:框内铺背景图(叠中性黑遮罩压暗)+ 角色卡;按钮在框外下方 */
  #rest-frame { border: 1px solid #5a4a2c; border-radius: var(--el-radius); padding: 8px; height: 282px;
    display: flex; flex-direction: column; justify-content: center;
    background:
      linear-gradient(rgba(0,0,0,.55), rgba(0,0,0,.55)),
      url(images/background/02.jpg) center/cover no-repeat; }
  /* 休息窗角色卡:复用 .combatant 布局,但不显示边框/来源描边(纯展示恢复进度) */
  #rest-cards .combatant { border-color: transparent !important; background: transparent !important; }
  /* 主角卡比伙伴卡多一条 SP 条→改顶对齐,让名字/头像/HP/MP 这些每张卡都有的部分对齐,SP 条多出的部分挂在主角卡底部 */
  #rest-cards { align-items: flex-start; }
  /* 挖矿网格:5×5 方格,居中;未揭格可点,已揭格按类型显图标 */
  .mine-grid { display: grid; gap: 4px; justify-content: center; margin: 0 auto; }
  .mine-cell { width: 40px; height: 40px; display: flex; align-items: center; justify-content: center;
    font-size: 22px; line-height: 1; padding: 0; border-radius: var(--el-radius); }
  button.mine-cell { background: #3a3220; border: 1px solid #5a4a2c; cursor: pointer; }
  button.mine-cell:hover:not(:disabled) { background: #4a4028; }
  button.mine-cell:disabled { opacity: .4; cursor: default; }
  .mine-cell.revealed { border: 1px solid transparent; background: #1b1710; }
  .mine-cell.revealed img.ic-img { width: 30px; height: 30px; }   /* 矿物图标填满格子(覆盖默认 ic-sm 16px) */
  .mine-cell.revealed.waste { opacity: .45; }
  .mine-cell.revealed.hazard { background: #3a1b14; }
  /* 挖掘中:该格底部进度条由 0 撑满到 100%,时长 = digSec(inline animation-duration) */
  button.mine-cell.digging { background: #4a4028; cursor: default; position: relative; overflow: hidden; }
  .mine-prog { position: absolute; left: 0; bottom: 0; height: 4px; width: 0;
    background: #e0c040; animation-name: mine-prog-fill; animation-timing-function: linear; animation-fill-mode: forwards; }
  @keyframes mine-prog-fill { from { width: 0; } to { width: 100%; } }
  .mine-status { text-align: center; margin-top: 12px; font-size: 13px; color: #cdbf9c; }
  .mine-result { font-weight: 600; }
  .mine-result.warn { color: #e0705a; }
  .mine-result.good { color: #8fc96f; }
  /* 矿脉储量条:网格上方,居中显示剩余档位;枯竭态红字提示 */
  #mine-reserve-box { text-align: center; margin: 4px 0 10px; font-size: 13px; color: #b0a079;
    display: flex; align-items: center; justify-content: center; gap: 6px; min-height: 8px; }
  #mine-reserve-box:empty { margin: 0; }
  .mine-depleted { color: #e0705a; }
  .mine-rlevel { font-weight: 600; letter-spacing: 1px; }
  .mine-loot { margin: 0 4px; }
  .mine-basket-empty { color: #8a7d60; font-style: italic; }
  /* 钓鱼:抛竿/咬钩/遛鱼三态共用居中布局,套在 #rest-frame 内 */
  .fish-stage { display: flex; flex-direction: column; align-items: center; justify-content: center;
    height: 100%; gap: 12px; text-align: center; position: relative; overflow: hidden; }
  .fish-float { font-size: 48px; animation: fish-bob 1.6s ease-in-out infinite; }
  @keyframes fish-bob { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-8px); } }
  /* 抛竿静候:背景随机游动的黑色鱼影(纯装饰,横穿泳池;rtl 从右往左 + 朝向翻转) */
  .fish-pond { position: absolute; inset: 0; overflow: hidden; pointer-events: none; z-index: 0; }
  .pond-fish { position: absolute; color: #000; filter: brightness(0); opacity: .5; line-height: 1;
    animation: pond-swim linear infinite; will-change: transform; }
  .pond-fish.rtl { animation-name: pond-swim-rtl; }
  @keyframes pond-swim { from { left: -10%; transform: scaleX(-1); } to { left: 110%; transform: scaleX(-1); } }
  @keyframes pond-swim-rtl { from { left: 110%; transform: scaleX(1); } to { left: -10%; transform: scaleX(1); } }
  .fish-stage > :not(.fish-pond) { position: relative; z-index: 1; }
  .fish-tip { color: #b0a079; font-size: 14px; }
  .fish-bite-alert { font-size: 28px; font-weight: 700; color: #e0c040; animation: fish-flash .5s ease-in-out infinite alternate; }
  @keyframes fish-flash { from { opacity: .55; } to { opacity: 1; } }
  .fish-bite-track { width: 70%; height: 8px; background: #2a2418; border-radius: var(--bar-radius); overflow: hidden; }
  .fish-bite-bar { height: 100%; background: #e0c040; width: 100%; }
  .fish-name { font-size: 18px; font-weight: 600; color: #e8dcc0; }
  .fish-hint { font-size: 14px; color: #b0a079; font-weight: 400; }
  .fish-bar-row { display: flex; align-items: center; gap: 8px; width: 80%; margin: 2px auto; }
  .fish-bar-label { width: 32px; font-size: 12px; color: #b0a079; text-align: right; }
  .fish-bar-track { flex: 1; height: 14px; background: #2a2418; border-radius: var(--bar-radius); overflow: hidden; }
  .fish-bar-fill { height: 100%; transition: width .25s; }
  .fish-bar-fill.tension { background: #5a9c5a; }
  .fish-bar-fill.tension.warn { background: #d6a93a; }
  .fish-bar-fill.tension.danger { background: #e0705a; }
  .fish-bar-fill.escape { background: #4a90e0; }
  .fish-bar-fill.vigor { background: #c88a3a; }
  .fish-vigor-tag { width: 56px; font-size: 11px; color: #d8b888; text-align: left; white-space: nowrap; }
  .fish-text { color: #d8ccae; font-size: 13px; min-height: 18px; margin-top: 4px; }
  .fish-result { font-weight: 600; font-size: 15px; }
  .fish-result.warn { color: #e0705a; }
  .fish-result.good { color: #8fc96f; }
  /* 实时遛鱼:横向挣扎槽(甜区随鱼游动)+ 张力游标 + 张力滑杆 */
  .fish-track { position: relative; width: 86%; height: 26px; background: #2a2418;
    border-radius: var(--el-radius); overflow: hidden; margin: 4px auto 0; }
  .fish-zone { position: absolute; top: 0; height: 100%; background: rgba(90,156,90,.45);
    border-left: 1px solid #5a9c5a; border-right: 1px solid #5a9c5a; }
  .fish-marker { position: absolute; top: -2px; width: 4px; height: calc(100% + 4px);
    margin-left: -2px; background: #e8dcc0; border-radius: var(--el-radius); box-shadow: 0 0 4px rgba(0,0,0,.6); }
  .fish-marker.good { background: #8fc96f; }
  .fish-marker.tight { background: #e0705a; }
  .fish-marker.loose { background: #d6a93a; }
  /* 黑色鱼影:挣扎槽上方泳道,跟随甜区中心左右游动(泳道与槽同宽同居中,left% 才对齐) */
  .fish-shadow-lane { position: relative; width: 86%; height: 30px; margin: 6px auto 0; }
  .fish-shadow { position: absolute; bottom: -10px; font-size: 28px; line-height: 1;
    color: #000; filter: brightness(0); opacity: .7; will-change: left; }
  /* 钓鱼 prep:选饵复用背包道具格 .cell2;数量少且可变,用 flex 居中换行(不用 .grid 的刚性5列,否则不足5个会靠左) */
  #fish-bait-list { display: flex; flex-wrap: wrap; justify-content: center; gap: 2px; max-width: 260px; margin: 6px auto 0; }
  /* 实时遛鱼:挣扎槽下用「收线」按钮(复用 .action.strike)连点蓄张力,不再用滑杆 */
  button.action.strike { background: #5a3320; border-color: #8a5030; font-weight: 700; animation: fish-flash .6s ease-in-out infinite alternate; }
  button.action.strike:hover { background: #6e4028; }
  .hpbar { height: 11px; position: relative; background: #2a2418; border-radius: var(--bar-radius); overflow: hidden; margin: 2px 0 1px; }
  .hpbar > i { display: block; height: 100%; background: #e0c040; transition: width .3s; }
  .hpbar.foe > i { background: #e0c040; }
  .mpbar { height: 11px; position: relative; background: #2a2418; border-radius: var(--bar-radius); overflow: hidden; margin: 0 0 1px; }
  .mpbar > i { display: block; height: 100%; background: #4a90e0; transition: width .3s; }
  .spbar { height: 11px; position: relative; background: #2a2418; border-radius: var(--bar-radius); overflow: hidden; margin: 0 0 1px; }
  .spbar > i { display: block; height: 100%; background: linear-gradient(90deg, #204d25, #3d7c3e); transition: width .3s; }
  button.inn { background: #2a2640; border-color: #4a4470; }
  button.inn:hover { background: #34305a; }

  /* 战斗:受击特效动画 */
  @keyframes shake {
    0%,100% { transform: translateX(0) rotate(0); }
    15% { transform: translateX(-9px) rotate(-6deg); }
    30% { transform: translateX(8px) rotate(5deg); }
    45% { transform: translateX(-7px) rotate(-4deg); }
    60% { transform: translateX(5px) rotate(3deg); }
    75% { transform: translateX(-3px) rotate(-2deg); }
  }
  @keyframes flash { 0%,100% { filter: drop-shadow(0 4px 6px #000a); }
    40% { filter: drop-shadow(0 0 18px #ff5a5a) brightness(2.2) saturate(2); } }
  @keyframes healglow { 0%,100% { filter: drop-shadow(0 4px 6px #000a); }
    50% { filter: drop-shadow(0 0 16px #6bd17a) brightness(1.4); } }
  .dmgfloat { position: absolute; top: 8px; left: 50%; font-weight: bold;
    font-size: 22px; color: #ff6b6b; text-shadow: 0 2px 4px #000;
    pointer-events: none; animation: floatup 1.6s ease-out forwards; }
  .dmgfloat.heal-txt { color: #6bd17a; }
  .dmgfloat.miss-txt { color: #cfcfcf; font-size: 18px; font-style: italic; }
  .dmgfloat.crit-txt { color: #ffd84a; font-size: 30px;
    text-shadow: 0 0 6px #ff6b00, 0 2px 4px #000; }
  @keyframes floatup { 0% { transform: translate(-50%,0); opacity: 1; }
    100% { transform: translate(-50%,-50px); opacity: 0; } }
  .battlerow { display: flex; gap: 0; flex-wrap: wrap; margin-bottom: 8px; justify-content: center; }
  .battlerow > * + * { margin-left: var(--cell-overlap); }

  /* ATB 战斗:多敌横排 + 我方 */
  #enemyRow { display: flex; flex-wrap: wrap; justify-content: center; align-items: flex-end;
    gap: var(--cell-gap); margin-bottom: 14px; min-height: 150px; }   /* min-height:诱惑掉最后一只怪后敌方区清空也保留占位,战斗画面不塌陷跳变 */
  #meArea { display: flex; flex-wrap: wrap; justify-content: center; align-items: flex-start; gap: var(--cell-gap); margin-bottom: 12px; }
  /* 伙伴面板:同伴横排,复用战斗格样式 */
  .petrow { display: flex; flex-wrap: wrap; justify-content: safe center; align-items: flex-end; gap: var(--cell-gap); margin: 4px 0 6px; }
  /* 伙伴窗:统一一个黑框包住全部;框内按类型分列(佣兵/召唤/诱惑),每列一个标题 */
  .comp-frame { background: #000; border: 1px solid #5a4a2c; border-radius: var(--el-radius); padding: 6px; margin: 4px 0 6px; }
  .comp-groups { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: center; gap: 4px 12px; }
  .comp-group { display: flex; flex-direction: column; align-items: center; }
  .comp-group .petrow { margin: 0; }
  .comp-group-title { font-size: 12px; color: #8a7d60; line-height: 1; margin-bottom: 4px; }
  /* 伙伴/佣兵卡等级徽标:头像正下方居中(不重叠),套 HUD 玩家等级同款金色渐变 */
  .combatant .lvbadge { display: flex; align-items: center; justify-content: center;
    height: 16px; box-sizing: border-box;
    background: linear-gradient(135deg, #c9b478, #9a7028); color: #2a2012; font-weight: 700;
    font-size: 11px; padding: 0 3px; border-radius: var(--el-radius); border: 1px solid #2a2012;
    box-shadow: 0 2px 4px #0008; white-space: nowrap; line-height: 1; pointer-events: none; }
  /* 性别图标 + 等级框横排容器(性别在框左边、框外);font-size 限定防继承 HUD 头像 40px */
  .lvrow { display: inline-flex; align-items: center; gap: 0; font-size: 13px; line-height: 1; pointer-events: none; }
  /* ===== 统一战斗角色框:我方主角 / 我方伙伴 / 敌方角色 / 敌方伙伴共用同一套外观 =====
     布局与外观全部由 .combatant 承载;阵营(ally/enemy)、来源(charm/summon)、状态(targeted/friendsel/dead)只做差异覆盖。
     relative:让伤害飘字锚定到各自头像上方。 */
  .combatant { width: 103px; flex: 0 0 auto;
    text-align: center; padding: 4px 4px; border: 2px solid transparent; border-radius: var(--el-radius);
    position: relative; cursor: pointer; transition: border-color .15s, background .15s; }
  /* 佣兵卡:操作按钮放边框外下方,列容器把卡片与按钮竖排,整体作为 petrow 的一个格 */
  .comp-card-wrap { display: flex; flex-direction: column; align-items: stretch; gap: 4px; flex: 0 0 auto; }
  /* 佣兵操作按钮行:状态(左)+ 背包(右)等宽横排 */
  .comp-btn-row { display: flex; gap: 4px; }
  .combatant:hover { background: #ffffff0c; }
  /* 伙伴来源描边 */
  .combatant.charm  { border-color: #e07ab066; background: #e07ab012; }
  .combatant.summon { border-color: #7a9ce066; background: #7a9ce012; }
  /* 玩家自身卡(施放对象选择器):暗绿描边区分 */
  .combatant.self   { border-color: #3f7a4d; background: #3f7a4d14; }
  /* 选中态:敌方攻击目标(金)/ 友方恢复目标(绿,C2) */
  .combatant.targeted  { border-color: #dd4517c2; background: #f0c0401a; box-shadow: 0 0 10px #f0c04055; }
  .combatant.friendsel { border-color: #54d07bbd; background: #54d07c1a; box-shadow: 0 0 10px #54d07c55; }
  /* 阵亡:灰化半透、不可点选 */
  .combatant.dead { opacity: .4; cursor: default; pointer-events: none; filter: grayscale(1); }
  /* 死亡怪物展示战利品时(.has-loot):取消灰度滤镜和半透明,使战利品图标清晰可见。
     保留 pointer-events:none 禁止点击(已死亡不可选中)。 */
  .combatant.dead.has-loot { opacity: 1; filter: none; }
  /* 阵亡佣兵(伙伴栏只读展示):明显的灰色边框标记死亡;头像保持原样不灰化。
     卡片仍可查看(状态按钮可点),故不禁用 pointer-events。 */
  .combatant.merc-dead { border-color: #888; background: #8888880f; }
  /* "死亡"红字:显示在等级标签下方的状态行(.statusbadges)里,与 buff 徽章共用这行预留空间 */
  .dead-tag { font-size: 11px; font-weight: 700; color: #e0574f; line-height: 1; white-space: nowrap; }
  /* 统一头像:块级 flex(非 inline),不产生行盒、不受 img/emoji 基线差异影响,高度恒为 48px,各格血条起点一致 */
  .combatant .sprite { font-size: 48px; line-height: 1; filter: drop-shadow(0 4px 6px #000a);
    transition: transform .1s; display: flex; align-items: center; justify-content: center;
    height: 48px; position: relative; }
  /* 头像定位容器 + 性别符号叠在右上角(伙伴/主角卡:伙伴面板/休息窗/道具目标选择) */
  .combatant .sprite .cb-av { position: relative; display: inline-flex; line-height: 0; }
  .combatant .sprite .cb-av .cb-sex { position: absolute; top: -2px; right: -2px; font-size: 12px; line-height: 1;
    text-shadow: 0 0 2px #000, 0 0 2px #000; z-index: 1; pointer-events: none; }
  .sprite.hit { animation: shake .4s; }
  .sprite.flash { animation: flash .3s; }
  /* 受击时 hit+flash 同时存在:让晃动和闪光两个动画一起跑(否则后声明的 flash 会覆盖 shake) */
  .sprite.hit.flash { animation: shake .4s, flash .3s; }
  .sprite.heal { animation: healglow .5s; }
  .sprite.status { animation: statusglow .6s; }
  @keyframes statusglow { 0%,100% { filter: drop-shadow(0 4px 6px #000a); }
    50% { filter: drop-shadow(0 0 16px #b07ae0) brightness(1.3) saturate(1.6); } }
  /* 持续状态:石化(灰白半透+轻微僵硬)、中毒(绿色调) */
  .sprite.petrified { filter: grayscale(1) brightness(1.4) drop-shadow(0 0 8px #ccd) !important; opacity: .85; }
  .sprite.poisoned { filter: drop-shadow(0 0 8px #6bd17a) hue-rotate(40deg) !important; }
  /* 战败倒下:灰化 + 半透,表现"角色倒下"(不旋转) */
  .sprite.fallen { filter: grayscale(1) brightness(.7) !important; opacity: .5;
    transition: transform .5s, opacity .5s, filter .5s; }
  /* 敌人头顶状态徽章 */
  /* 块级 flex:独占一行(避免与行内的等级标签 .lvrow 挤到同一行);固定高度,空也占位保留状态行 */
  .statusbadges { font-size: 12px; margin-top: 2px; height: 16px; line-height: 16px;
    display: flex; align-items: center; justify-content: center; gap: 2px;
    white-space: nowrap; overflow: hidden; }
  .statusbadges .sbadge { display: inline-flex; align-items: center; gap: 1px; }
  /* 魔法盾/状态图标(PNG)在 HUD/状态窗/战斗徽章/行动条里:覆盖 .ic-sm 固定 16px,缩到与文字协调并居中对齐。
     只局部覆盖这些徽章上下文,不动全局 .ic-sm(背包/地点按钮等仍用 16px)。改大小动这里。by ting */
  #hud .hud-shield .ic-sm,
  #hud .hud-buffs .ic-sm,
  .stat-buffs .statbuff .ic-sm,
  .statusbadges .ic-sm,
  [id$="AtbTxt"] .ic-sm {
    width: 16px; height: 16px; font-size: 16px; vertical-align: middle;
  }
  .cbname { font-size: 13px; color: #ece5d8; margin-bottom: 1px; }
  /* 名字固定行高 */
  .combatant .cbname { height: 16px; line-height: 16px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  /* ATB 行动条(绿色) */
  .atb { height: 11px; position: relative; background: #2a2418; border-radius: var(--bar-radius); overflow: hidden;
    margin: 0 0 1px; }
  .atb > i { display: block; height: 100%; width: 0%; background: #4caf50;
    transition: width .12s linear; }
  .atb.ready > i { background: #6bd17a; box-shadow: 0 0 8px #6bd17a; }
  .price { color: #f0c040; font-size: 12px; margin-right: 8px; }

  /* 战斗指令按钮:全部统一为正方形(避免界面变形) */
  .slotbtn, .cmdsq { width: 48px; height: 48px; flex: 0 0 auto; position: relative;
    background: #332b1c; color: #ece5d8; border: 1px solid #5a4a2c; border-radius: var(--el-radius);
    cursor: pointer; font-size: 12px; padding: 3px 2px;
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px; }
  .slotbtn:hover:not(:disabled), .cmdsq:hover:not(:disabled) { background: #443818; }
  .slotbtn .sicon, .cmdsq .sicon { font-size: 24px; line-height: 1; }
  .slotbtn small, .cmdsq small { font-size: 9px; color: #9a8d70; }

  /* ===== 战斗嵌入地图区(#battlefield):替代原全屏 #overlay>#modal 弹窗 =====
     绝对定位铺满 #map、盖住 #world/#hero(z-index 高于 #topbar 的 6),背景透明露出 #bg(当前地点背景)。
     战斗骨架(#enemyRow/#meArea/#btns)由 battle.js drawBattleShell 注入这里,渲染/更新代码不变。
     战斗日志改到左下角事件框(#events)显示,战斗层不再内嵌 #log。
     地图区固定 720×420 塞不下原弹窗尺寸,故下方一批覆盖把精灵/血条/日志/间距压缩到一屏(不滚动)。
     压缩覆盖同时应用到伙伴面板(.petrow),使伙伴窗卡片与战斗窗完全一致;观察窗等其它复用 .combatant 的地方不受影响。 */
  #battlefield { position: absolute; inset: 0; z-index: 7; display: none;
    padding: 4px 8px; background: transparent; }
  #battlefield.show { display: flex; flex-direction: column; align-items: stretch; justify-content: space-between; }
  /* 备战占位:转圈居中(复用 loadwin 样式) */
  #battlefield .bf-prep { margin: auto; text-align: center; }
  /* 标题文字已移到顶栏中段(#battle-title),但骨架仍保留一个空 <h3> 占位:
     战斗层靠 space-between 把「占位↔敌方↔我方↔按钮」四块均分成 3 段等距,
     若去掉这一子元素只剩 2 段间隙,间距会整体变大导致敌我卡片位移。故留空占位保持原几何。 */
  #battlefield h3 { margin-bottom: 0; height: 15px; }
  /* 顶栏战斗标题槽:平时隐藏;战斗时占据时间(左)与地图名(右)之间的空位并居中,与二者同一行 */
  #battle-title { display: none; flex: 1 1 auto; text-align: center; padding: 4px 4px;
    color: #e0c878; font-size: 14px; letter-spacing: 1px; text-shadow: 0 1px 3px #000, 0 0 6px #000; }
  body.in-battle #battle-title { display: block; }
  /* 单元压缩:精灵 48→40、名字/徽章行高收紧、三条 11→9。
     .cb-compact 是战斗窗(#battlefield)与伙伴窗(.petrow)共享的紧凑作用域:两个容器都挂此 class,
     故这套紧凑风格只需写一次即被两处共用;观察窗/休息窗等其它复用 .combatant 的地方不挂此 class,不受影响。 */
  .cb-compact .combatant { padding: 3px 3px; }
  /* 每个角色卡:深色半透明底层,在地点背景上烘托卡片、提升可读性。
     z-index:-1 垫在所有内容与状态背景色之下,故不干扰 hover/targeted/friendsel 等状态色的叠加显示。 */
  .cb-compact .combatant::before { content: ""; position: absolute; inset: 0;
    background: #00000059; border-radius: var(--el-radius); z-index: -1; pointer-events: none; }
  .cb-compact .combatant .sprite { height: 40px; font-size: 40px; }
  .cb-compact .combatant .sprite img.ic-lg,
  .cb-compact .combatant .sprite span.ic-lg { width: 40px; height: 40px; font-size: 40px; }
  .cb-compact .combatant .cbname { height: 14px; line-height: 14px; }
  .cb-compact .statusbadges { height: 14px; line-height: 14px; margin-top: 1px; }
  .cb-compact .hpbar, .cb-compact .mpbar, .cb-compact .atb { height: 9px; }
  /* 死亡后战利品展示(cb-loot)与存活时的精灵/状态/三条(cb-body)二选一显示:
     .has-loot 加在 .combatant 上时隐藏 .cb-body 腾出空间,显示 .cb-loot。
     战利品区占满卡片主体高度(约 86px),纵向排列(flex-direction:column),每行一条,超出时内部滚动(overflow-y)。 */
  .cb-compact .combatant .cb-body { display: flex; flex-direction: column; align-items: stretch; }
  .cb-compact .combatant .cb-loot { display: none; flex-direction: column; align-items: stretch; gap: 2px;
    height: 86px; overflow-y: auto; padding: 2px 1px; }
  .cb-compact .combatant.has-loot .cb-body { display: none; }
  .cb-compact .combatant.has-loot .cb-loot { display: flex; }
  /* 战利品条目(lootchip):图标 + 名字 + 数量,每行一条左对齐。
     用普通 inline 流而非 flex:img 是 inline-block,文字是 inline,两者天然紧挨,无 flex item 边界间距。
     font-size:0 消除任何文字节点空隙;lootname 单独恢复字号。*/
  .lootchip { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    padding: 2px 4px; background: #00000044; border-radius: 3px; font-size: 0; }
  .lootchip .ic-sm, .lootchip .ic-img.ic-sm { display: inline-block; vertical-align: middle; width: 16px; height: 16px; }
  .lootchip .lootname { display: inline; vertical-align: middle; font-size: 13px; line-height: 16px; }
  /* 敌/我方行:三段间距原由 space-between 均分(标题↔敌方 / 敌方↔我方 / 我方↔按钮)。
     收紧「敌方↔我方」这一段,让两阵营同时向中间靠拢——都作用在 #enemyRow 一处:
       margin-top    正值 → 把敌方整块往下推;
       margin-bottom 负值 → 把我方阵营往上拉近敌方。
     两者对称,敌下我上各移 ~12px,中间段净缩 ~24px。改这两个值即可调节。 */
  #battlefield #enemyRow { min-height: 100px; margin-top: 12px; margin-bottom: -12px; }
  #battlefield #meArea { margin-bottom: 0; }
  /* 按钮行:收窄行距,最后一行贴底不留 margin */
  #battlefield .battlerow { margin-bottom: 3px; }
  #battlefield #btns .battlerow:last-child { margin-bottom: 0; }

  /* 战斗中隐藏左下角地点信息(#maploc z5 在透明战斗层下会透出) */
  body.in-battle #maploc { display: none; }

  /* 战斗中隐藏地图顶栏的状态图标(魔法盾/buff/伙伴):#topbar 是 #battlefield 的兄弟节点,
     不被战斗层遮住会浮在战斗画面上。只隐图标不动时间/地图名(gametime/mapname 仍有用)。 */
  body.in-battle #map-status { display: none; }
  /* 战斗中隐藏右上角地点坐标(地图名保留) */
  body.in-battle #mapcoord { display: none; }

  /* 战斗中(body.in-battle)/挖矿钓鱼中(body.in-activity):活动层只盖住 #map,不遮顶部工具栏与下方地点面板。
     为保持独占(不能中途点 NPC/怪物穿透退出、不能开其它窗覆盖活动),禁用这些按钮的点击(保留可见作上下文)。 */
  body.in-battle .tools button,
  body.in-battle #panel .row button,
  body.in-activity .tools button,
  body.in-activity #panel .row button { pointer-events: none; opacity: .5; }
  /* 例外:战斗/活动中「系统」按钮仍可点(注销走宽限、切声音等系统级操作不受独占限制) */
  body.in-battle .tools #btn-settings,
  body.in-activity .tools #btn-settings { pointer-events: auto; opacity: 1; }

  /* ===== 地图框内菜单窗(#mapwin):技能/伙伴/任务/点券 改为居中卡片浮于 #map,不走全屏 #overlay =====
     半透明遮罩只盖住 #map(不遮 HUD/聊天),卡片居中、不透明、内容超高时内部滚动。与全屏 overlay 互斥。 */
  #mapwin { position: absolute; top: 0; left: 0; right: 0; bottom: 0; z-index: 8; display: none;   /* 勿用 inset 简写:iOS 13 不认,居中容器会塌成 0×0 致卡片偏左上而非居中 */
    align-items: center; justify-content: center; background: #0009; }
  #mapwin.show { display: flex; }
  #mapcard { width: 460px; max-width: calc(100% - 12px); max-height: calc(100% - 12px);
    background: #221c14; border: 1px solid #5a4a2c; border-radius: var(--win-radius);
    padding: 6px; box-shadow: 0 10px 40px #000c; overflow-y: auto; position: relative; }   /* 内边距 6px(状态/道具/技能/任务/伙伴/点券窗共用容器);不动全局 --win-pad 以免影响弹窗/确认框 */
  #mapcard h3 { color: #e0c878; font-size: var(--win-title-fs); margin-bottom: 8px; }
  /* 冷却遮罩:覆盖整个技能格,中央显示剩余秒数;无冷却时隐藏。
     统一用于战斗按钮(.slotbtn)/ HUD 快捷栏(.hud-hotbar .hcell)/ 技能页(.cell2 .hotcell)。 */
  .slotbtn .cdmask, .hud-hotbar .hcell .cdmask, .cell2 .cdmask, .hotcell .cdmask, .skillrow .srow-ic .cdmask {
    position: absolute; inset: 0; border-radius: var(--el-radius); display: none;
    align-items: center; justify-content: center; font-size: 16px; font-weight: 700;
    color: #ffd98a; background: rgba(10,8,4,0.62); text-shadow: 0 0 3px #000; pointer-events: none; }
  .slotbtn .cdmask.on, .hud-hotbar .hcell .cdmask.on, .cell2 .cdmask.on, .hotcell .cdmask.on, .skillrow .srow-ic .cdmask.on { display: flex; }
  /* 冷却中:整格不可点(野外快捷栏/技能页用 class 控制,不依赖 disabled 属性) */
  .hud-hotbar .hcell.cooling, .cell2.cooling, .hotcell.cooling { cursor: not-allowed; }
  .hud-hotbar .hcell.cooling { pointer-events: none; }
  /* 配置态(道具/技能窗开着):即使冷却中也要能点格子卸载,恢复可点(点击走 clearSlot 而非使用) */
  #game.hotbar-lit .hud-hotbar .hcell.cooling { pointer-events: auto; cursor: pointer; }
  .slotbtn.empty { color: #5a4a2c; border-style: dashed; cursor: default; }
  .slotbtn:disabled, .cmdsq:disabled { opacity: .45; cursor: not-allowed; }
  .cmdsq[data-cmd="atk"] { border-color: #6a5a3a; }
  .cmdsq[data-cmd="flee"] { border-color: #6a4a3a; }

  .cfghint { font-size: 14px; color: #9a8d70; margin: 4px 0 10px; }
  /* ===== 合并后的物品/装备格子界面 ===== */
  .invsec { font-size: 13px; color: #8a7d60; margin: 6px 0 6px; text-align: center; }
  /* ===== 已掌握技能:竖排列表(每行一个,每页 4 条)===== */
  /* 行高=图标高 46px(--srow-h,含 1px 上下边框正好容纳 44px 图标);行距 -1(边框叠成一条线)。 */
  /* 宽度填满窗口(#mapcard),随窗口宽度自适应;高度恒为 5 行(不足也留空,窗口不塌陷) */
  /* 技能列表:整组套黑框(仿 .comp-frame),每条无边框,条间用 1px 分割线区分 */
  .skill-list { display: flex; flex-direction: column; gap: 1px; margin: 4px auto; width: 100%;
    background: #000; border: 1px solid #5a4a2c; border-radius: var(--el-radius); padding: 4px; box-sizing: border-box;
    height: calc(5 * var(--srow-h) + 8px + 2px + 4px); }   /* border-box:宽不溢出;高=5行 + 上下padding8 + 上下边框2 + 4条间距(4×1px) */
  /* 技能窗顶部提示行(替代原标题):13px */
  .skill-hint { font-size: 13px; color: #b0a079; text-align: center; margin-bottom: 4px; }
  /* 每条技能:无边框/无独立背景(透出黑框底),条间由 .skill-list 的 gap:1px 分隔(黑底缝隙即分割线);左右留 4px */
  .skillrow { display: flex; align-items: center; gap: 8px; padding: 0 4px; box-sizing: border-box;
    height: var(--srow-h); flex: 0 0 var(--srow-h); cursor: pointer; }
  .skillrow:hover { background: #201b12; }
  .skillrow.inslot { background: #241d10; }   /* 已在快捷栏(弱背景提示) */
  .skillrow .srow-ic { position: relative; width: 40px; height: 40px; flex: 0 0 40px; isolation: isolate; }
  .skillrow .srow-ic .ic { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-size: 24px; }
  .skillrow .srow-ic .star { position: absolute; left: 2px; top: 1px; z-index: 1; }
  .srow-body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
  /* 第一行:技能名靠左,经验条靠右(固定占 body 的 50%);第二行=介绍,第三行=属性 */
  .srow-l1 { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
  .srow-name { font-size: 11px; line-height: 1; color: #ece5d8; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }   /* 与介绍同字号 */
  .srow-lv { font-size: 11px; line-height: 1; color: #9fd88a; }
  /* 经验条:固定占 body 宽度的 50%、水平居右;圆角 2 */
  /* 经验条:复用 HUD 经验条(.hbar.xp)风格——同高度(--vbar-track-h)、同金色渐变、数值嵌条内(.v)。
     HUD 的 .v/渐变限定在 #hud 作用域,这里为技能行内的 .hbar.xp 补同款样式。固定占 body 宽 50%、居右。 */
  .srow-exp { flex: 0 0 50%; display: flex; }
  .srow-exp .track { flex: 1; position: relative; height: var(--vbar-track-h); background: #2a2418;
    border: 1px solid #3a3020; border-radius: var(--bar-radius); overflow: hidden; }
  .srow-exp .track > i { display: block; height: 100%; border-radius: var(--bar-radius) 0 0 var(--bar-radius);
    background: linear-gradient(90deg, #946018, #a07e2c); transition: width .35s; }
  .srow-exp .track .v { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
    font-size: 11px; line-height: 1; color: #c8bfac; text-shadow: 0 1px 2px #000, 0 0 3px #000; pointer-events: none; font-weight: bold; }
  .srow-l2 { font-size: 11px; line-height: 1; color: #9a8d70; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .srow-l3 { font-size: 11px; line-height: 1; color: #6db3f2; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }   /* 第三行:具体属性 */
  .skill-pager { display: flex; align-items: center; justify-content: center; gap: 12px; margin: 8px 0 2px; }
  .skill-page-no { font-size: 12px; color: #b0a079; }
  .grid { display: grid; grid-template-columns: repeat(5, var(--cell-track)); grid-auto-rows: var(--cell-track); gap: 0; justify-content: safe center; }   /* safe:溢出时左对齐,起始格不落入 scrollLeft 负区(窄屏 10 列网格) */
  /* 装备:人体布局 3 列 × 4 行,格子边框相邻叠成一条线(轨道缩 --cell-overlap);整体黑底边框包裹 */
  .grid.equip { position: relative; grid-template-columns: repeat(3, var(--cell-track)); gap: 0; justify-content: start;
    background: #000; border: 1px solid #5a4a2c; border-radius: var(--el-radius); padding: 6px; }
  /* "装备"标题:叠在黑边框左上角 */
  .equip-title { position: absolute; left: 7px; top: 4px; font-size: 12px; color: #8a7d60;
    line-height: 1; pointer-events: none; z-index: 1; }
  /* 装备区(观察其他玩家窗专用):498px 居中块,人形格左对齐、属性框跟在右侧;两侧等高拉伸 */
  .equip-area { display: flex; align-items: stretch; justify-content: flex-start; gap: 4px;
    width: 100%; max-width: 498px; margin: 2px auto 2px; }
  /* 道具窗上半:装备列(左,3×4 黑底框)与背包列(右)左右并排,顶端对齐;两列间距用统一 --cell-gap,装备右框紧贴背包。快捷栏已置顶。 */
  .inv-top { display: flex; align-items: flex-start; justify-content: safe center; gap: 12px; margin: 6px auto 2px; }   /* safe:溢出时左对齐,防起始列落入 scrollLeft 负区(窄屏装备+背包双列) */
  .inv-eqcol, .inv-bagcol { flex: 0 0 auto; }
  /* 两列标题等高,使下方格子从同一 Y 起排 */
  .inv-top .invsec { margin: 0 0 6px; min-height: 20px; display: flex; align-items: center; justify-content: center; }
  /* 道具窗装备格:保留黑底,去掉外边框与内衬,使格子从边缘起排、与背包精确对齐(观察其他玩家窗仍保留黑框) */
  .inv-eqcol .grid.equip { border: none; padding: 0; }
  /* 属性框:占满人形右侧剩余宽度,高度由 equip-area 拉伸自动与装备框齐平;左右两列(左=主属性,右=装备加成),超出则框内滚动 */
  .attr-box { flex: 1; box-sizing: border-box;
    border: 1px solid #5a4a2c; border-radius: var(--el-radius); background: #1b1710;
    padding: 4px 4px; display: flex; flex-direction: row;
    overflow-y: auto; gap: 8px; }
  .attr-col { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
  .attr-bonus-col { border-left: 1px solid #3a3220; padding-left: 8px; }
  /* 观察其他玩家窗:主角行 + 伙伴行纵向堆叠(主角在上,伙伴依次在下),覆盖装备窗的横向两列 */
  .attr-box.attr-box-players { flex-direction: column; gap: 0; }
  .attr-row { display: flex; align-items: baseline; justify-content: space-between;
    font-size: 13px; line-height: 1.5; border-bottom: 1px dashed #3a3220; padding: 1px 0; flex: 0 0 auto; }
  .attr-k { color: #8a7d60; }
  .attr-v { color: #e0c878; font-weight: 600; }
  .bonus-row { font-size: 12px; color: #6b9c6b; line-height: 1.0; flex: 0 0 auto; }
  .bonus-none { color: #6b7a6b; }
  /* 观察窗信息框:主角与伙伴共用的横向行(头像左,名字+HP右) */
  .obs-line { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; margin-bottom: 4px; }
  .obs-line:first-child { margin-bottom: 6px; }
  /* 可点击切换装备格的行(主角 + 佣兵):悬停提示、选中高亮 */
  .obs-selable { cursor: pointer; border-radius: var(--el-radius); }
  .obs-selable:hover { background: rgba(224, 200, 120, 0.08); }
  .obs-sel-active { background: rgba(224, 200, 120, 0.16); box-shadow: inset 0 0 0 1px rgba(224, 200, 120, 0.4); }
  /* 伙伴行:头像 48 高,信息列拉伸填满整行并上下分布(名字贴顶、血条贴底),
     消除"短内容居中于 48 高行"造成的相邻伙伴视觉空隙;行间零间距紧贴 */
  .obs-line:not(:first-child) { margin-bottom: 0; align-items: stretch; }
  .obs-line:not(:first-child) .obs-info { justify-content: center; padding: 2px 0; }
  /* 头像:统一 48×48 方框,职业金色标签叠在框内底部(见 .obs-cls),不外溢 */
  .obs-ava { position: relative; flex: 0 0 auto; width: 48px; height: 48px; display: flex; align-items: center; justify-content: center; line-height: 1; overflow: hidden; border-radius: var(--el-radius); }
  .obs-ava img.ic-lg, .obs-ava span.ic-lg { width: 48px; height: 48px; font-size: 48px; }
  /* 职业标签:绝对定位贴框底、水平居中,自适应宽度左右各留 3px(同其他徽标),超出裁剪 */
  .obs-cls { position: absolute; bottom: 0; left: 50%; transform: translateX(-50%); max-width: 100%; box-sizing: border-box;
    background: linear-gradient(135deg, #c9b478, #9a7028); color: #2a2012; font-weight: 700;
    font-size: 9px; line-height: 1.3; padding: 0 3px; border-top: 1px solid #2a2012; border-radius: var(--el-radius) var(--el-radius) 0 0;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  /* 性别符号:叠在头像框右上角 */
  .obs-sex { position: absolute; top: 0; right: 1px; font-size: 12px; line-height: 1;
    text-shadow: 0 0 2px #000, 0 0 2px #000; z-index: 1; }
  .obs-info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
  .obs-nm { color: #e0c878; font-size: 13px; font-weight: 600; line-height: 1.1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .obs-info .hpbar { width: 100%; }
  /* 玩家观察窗:HP 条只表意比例,缩短避免占满整行 */
  .attr-box-players .obs-info .hpbar { width: 60%; }
  /* 评价文字嵌在主角 HP 条下方:去掉通用函数自带的居中与大下边距 */
  .obs-assess > div { text-align: left !important; margin-bottom: 0 !important; font-size: 12px !important; line-height: 1.3 !important; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

  /* NPC/怪物观察窗:上半信息区(左头像+类型,右名字/HP/描述)+ 下半对话区 */
  .obv-head { display: flex; gap: 14px; margin-bottom: 6px; }
  /* 左列:头像框固定 64×64(内含 48 头像 + 类型),框高即整行高;竖屏缩到 48×48/36 见 portrait 覆盖 */
  .obv-ava { flex: 0 0 auto; display: flex; }
  .obv-ava .obv-pic { width: 64px; height: 64px; border: 1px solid #5a4a2c; border-radius: 2px; background: #1b1710;
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 0; overflow: hidden; }
  .obv-ava .obv-pic img.ic-lg { width: 48px; height: 48px; }
  .obv-ava .obv-pic span.ic-lg { display: none; }   /* 不显示 emoji 头像:框内只允许 PNG 图标,无图则空框 */
  .obv-type { font-size: 12px; color: #cdbf9c; text-align: center; line-height: 1.2; margin-top: -1px; }
  /* 右列:名字+HP 同行 / 描述,总高锁定 64(与头像框一致),内容垂直居中 */
  .obv-info { flex: 1; min-width: 0; height: 64px; display: flex; flex-direction: column; gap: 2px; justify-content: center; }
  /* 写信态:收件人行并入头部,信息区放开固定高度以容纳第三行(标题/邮费 + 收件人) */
  .obv-info:has(.mail-form) { height: auto; justify-content: flex-start; }
  /* 雇佣窗:招揽语下方带「可雇佣 x/x」行时,头部放开固定高度容纳第三行 */
  .obv-info:has(.merc-sec-title) { height: auto; justify-content: flex-start; }
  /* 战斗力评估:钉在描述块第二行右侧,与描述换行到第二行的文字并排同行。
     描述块保持固定两行高(34px),评估绝对定位到右下角 = 第二行右端;描述第一行照常占满整行不受影响。 */
  .obv-descrow { position: relative; }
  .obv-assess-line { position: absolute; right: 0; bottom: 0; }
  .obv-assess-line > div { text-align: right !important; margin-bottom: 0 !important; white-space: nowrap; }
  /* 名字行:名字固定宽度(对齐多目标的 HP 条起点),HP 条占余下空间 */
  .obv-nameline { display: flex; align-items: center; gap: 10px; }
  .obv-name { flex: 0 1 auto; max-width: 180px; font-size: 14px; color: #e0c878; font-weight: 600; line-height: 1.2;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  /* HP 条:前缀"HP"文字 + 只显条不显数值,固定较短宽度(不再吃满名字右侧),条复用 .hpbar 渐变风格 */
  .obv-hp { flex: 0 0 200px; min-width: 0; display: flex; align-items: center; gap: 6px; }
  .obv-hplabel { flex: 0 0 auto; font-size: 12px; color: #8a7d60; }
  .obv-hp .hpbar { flex: 1; min-width: 0; margin: 0; }
  /* 描述:固定两行文字空间(无论内容多少都占两行高),超出截断 */
  .obv-desc { font-size: 13px; color: #9a8d70; line-height: 1.3; height: 34px; overflow: hidden;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
  /* 对话区:固定高度,玩家未交谈时留空占位;有内容时显示对话/功能文字。
     flex 列布局:对话文字在上,需要/条件靠 margin-top:auto 固定到最底部 */
  .obv-dialog { background: #14110d; border-radius: var(--el-radius); padding: 10px 10px 4px; height: 180px;
    overflow-y: auto; font-size: 14px; line-height: 1.6; margin-bottom: 8px;
    display: flex; flex-direction: column; }
  /* 观察窗底部按钮行(卡片最后一个子级):去掉 .row 给表单多行留的 margin-bottom,
     使其离下边框 = padding-bottom(8px),与上方对话区间距(8px)对称 */
  #modal > .row:last-child, #mapcard > .row:last-child { margin-bottom: 0; }
  .obv-dialog > div { margin-bottom: 0px; }
  .obv-dialog .obv-empty { color: #6a5d44; font-style: italic; }
  /* 欢迎语:NPC/怪物开场白,斜体柔和色,与占位/评估同区 */
  .obv-dialog .obv-welcome { color: #cdbf9c; line-height: 1.6; margin-bottom: 6px; white-space: pre-wrap; }
  /* 任务面板:复用对话区,每条任务卡(标题+要求+按钮 同行 / 描述次行) */
  .obv-dialog .q-list { display: block; width: 100%; }
  .q-card { padding: 2px 6px; margin: 2px 0; background: rgba(0,0,0,.18); border-radius: var(--el-radius); }
  .q-card-top { display: flex; align-items: center; gap: 4px; line-height: 1.2; }
  .q-card-top > .q-name { flex: 0 0 auto; font-size: 13px; }
  .q-card-top .q-tag { color: #8aa86a; font-size: 13px; }   /* 状态标签 [可接]/[可交付]/[已接]/[完成]/[进行中] */
  .q-card-req { color: #c9b27a; font-size: 13px; flex: 1 1 auto; min-width: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .q-card-top .q-act { margin-left: auto; flex: 0 0 auto; padding: 2px 4px; }
  .q-card-desc { color: #888; font-size: 13px; line-height: 1.25; }
  /* 交付奖励:对话区内居中列出 */
  .obv-dialog .q-reward { display: block; width: 100%; text-align: center; }
  .q-reward-title { color: #6c6; font-weight: bold; margin-bottom: 6px; }
  .q-reward-item { color: #f0c040; font-size: 13px; line-height: 1.7; }   /* 经验/物品名金色;铜币段用 .coin 自带棕色覆盖 */
  /* 交易态:对话区放下货架+背包,取消固定高度与 flex 列,自适应展开由弹窗整体滚动;内边距收窄到 6px(下 4 不变) */
  .obv-dialog.trade { height: auto; display: block; overflow: visible; padding: 2px 6px 4px; }
  /* 头部招揽语行:占据原角色描述位置(obv-info 内,名字下方),招揽语居左、铜币/按钮居右下,末行对齐 */
  .shop-topline { display: flex; align-items: flex-end; justify-content: space-between; gap: 12px; }
  /* 商人招揽语:最多两行完整显示,超出省略;字号/行高对齐原 obv-desc,避免两行撑破头部 64px */
  .shop-pitch { flex: 1; min-width: 0; color: #cdbf9c; font-style: italic; font-size: 13px; line-height: 1.3;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
  /* 交互页(头像头部内)欢迎语固定两行高:即使只有一行,第三行位置也占位;铜币靠右下对齐到第三行 */
  .obv-info .shop-pitch { height: 34px; }
  /* 铜币数:靠右下、不被招揽语挤压 */
  /* 铜币/点券余额行:见通用 .coins/.coin(style.css 上方图标区) */
  /* 赌桌无头像:NPC 名字前置到欢迎语前,字号与欢迎语一致 */
  .g-npcname { flex: 0 0 auto; color: #e0c878; font-size: 13px; font-weight: 600; }
  /* 赌桌顶行:名字/欢迎语/铜币/点券同行垂直居中对齐(覆盖 .shop-topline 的 flex-end) */
  .g-topline { align-items: center; }
  /* 货架格子区顶部留点间距(招揽语行已上移到头部,交易态又删了货架标题,否则顶得太紧) */
  .obv-dialog.trade .grid.skills { margin-top: 0px; }
  /* 交易态背包栏(含仓库存取的背包侧,不含仓库格 stgrid):取消固定高度与内部滚动,随弹窗整体滚动,不产生自身滚动条 */
  .obv-dialog.trade .grid.bag:not(.stgrid) { height: auto; overflow: visible; }
  /* 交易态背包标题:上下边距一致;relative 供翻页控件绝对定位 */
  .obv-dialog.trade .invsec { margin: 2px 0; position: relative; }
  /* 商店:货架(左,3×5)与背包(右,7×5)左右并排,顶端对齐 */
  .shop-cols { display: flex; align-items: flex-start; justify-content: safe center; gap: 4px; }   /* safe:溢出时回退左对齐,防起始边落入 scrollLeft 负区被裁(窄屏双列货架/卡包) */
  .shop-shelfcol, .shop-bagcol { flex: 0 0 auto; }
  /* 货架格子区:3 列固定,格子从左上起排 */
  .grid.shopgrid { grid-template-columns: repeat(3, var(--cell-track)); justify-content: safe center; }
  /* 点券商城:默认 5 列,覆盖 shopgrid 的 3 列;窄窗(占浏览器宽 >90%)按列数修饰类收窄(货架 4 / 卡包 3) */
  .grid.pshop-grid { grid-template-columns: repeat(5, var(--cell-track)); justify-content: safe center; }
  .grid.pshop-grid.cols4 { grid-template-columns: repeat(4, var(--cell-track)); }
  .grid.pshop-grid.cols3 { grid-template-columns: repeat(3, var(--cell-track)); }
  /* 加载中/空货架:占位空格撑住尺寸(与到货同大),提示文字居中覆盖,故左侧区域不随内容到达才确定大小 */
  .shelf-wrap { position: relative; }
  .shelf-hint { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
    text-align: center; color: #888; font-size: 14px; pointer-events: none; padding: 0 8px; }
  /* 货架标题行:标题 + 翻页控件同排居中(货架列窄,不用绝对定位以免与标题重叠) */
  .shop-shelfhd { display: flex; align-items: center; justify-content: center; gap: 2px; }
  /* 仓库标题行的整理按钮(唯一放在货架标题里的),压掉其内联 margin-left,避免与 flex gap 叠加拉大间距 */
  .shop-shelfhd .action { margin-left: 0 !important; }
  .shop-pager { display: inline-flex; align-items: center; gap: 2px; }
  /* 用 .shop-pager 后代提升优先级压过 button.action(否则其 padding:6px 撑高按钮);对齐道具窗"整理"按钮 */
  .shop-pager .shop-pg-btn { padding: 2px 10px; font-size: 12px; }
  .shop-page-no { color: #8a7d60; font-size: 12px; }
  /* ===== 雇佣佣兵窗 ===== */
  .merc-sec-title { color: #e0c878; font-size: 13px; font-weight: 600; margin: 2 0 4px; }
  .merc-cap { color: #b0a079; font-weight: normal; font-size: 12px; }
  /* 顶栏内联「可雇佣 x/x」:放铜币左侧,非加粗、字号同铜币(13px 由 .coins 继承) */
  .merc-cap-inline { color: #b0a079; font-weight: normal; white-space: nowrap; }
  /* 固定 4 张卡高度:min-height 撑住下限(某页不足 4 名时不缩水,卡片顶部堆叠、下方留白);仿邮局 mail-list */
  /* 稳态高度改由外层包裹 div(min-height=每页条数×卡位高)控制,随朝向变;此处不再写死 4 卡位下限 */
  .merc-list { display: flex; flex-direction: column; gap: 2px; }
  /* 分页条:上一页/页码/下一页。与返回/关闭同处底部按钮行,渲染在其左侧 */
  .merc-pager { display: inline-flex; align-items: center; gap: 10px; }
  .merc-page-ind { color: #b0a079; font-size: 12px; }
  /* 翻页按钮:统一弹窗底部按钮高(--win-btn-h);flex 居中 + box-sizing 保证含边框正好该高度 */
  .merc-pager .action { height: var(--win-btn-h); box-sizing: border-box; padding: 0 10px; font-size: 12px;
    display: inline-flex; align-items: center; justify-content: center; }
  /* 卡片:头像 + 信息 + 操作按钮 横向紧凑一排 */
  .merc-card { display: flex; align-items: center; gap: 2px; padding: 4px 4px; }
  .merc-ic { flex: 0 0 auto; line-height: 0; display: flex; flex-direction: column; align-items: center; }
  .merc-ic img.ic-lg, .merc-ic span.ic-lg { width: 34px; height: 34px; font-size: 30px; }
  /* 头像定位容器 + 性别符号叠在右上角 */
  .merc-av { position: relative; display: inline-flex; width: 34px; height: 34px; }
  .merc-av .merc-sex { position: absolute; top: -2px; right: -2px; font-size: 11px; line-height: 1;
    text-shadow: 0 0 2px #000, 0 0 2px #000; z-index: 1; pointer-events: none; }
  /* 佣兵头像下方等级徽标:套 HUD 玩家等级同款金色渐变,间距 0 */
  .merc-ic .lvbadge { display: flex; align-items: center; justify-content: center; gap: 2px;
    margin: 0; height: 16px; box-sizing: border-box; background: linear-gradient(135deg, #c9b478, #9a7028);
    color: #2a2012; font-weight: 700; font-size: 11px; line-height: 1; padding: 0 3px; border-radius: var(--el-radius);
    border: 1px solid #2a2012; box-shadow: 0 2px 4px #0008; white-space: nowrap; }
  .merc-body { flex: 1; min-width: 0; line-height: 1.25; }
  /* 中段:属性(左)在两三行,雇佣按钮(右)等高 */
  .merc-top { display: flex; align-items: center; gap: 8px; }
  /* 第一行:名字 + 加成数字在左,雇佣条件 + 工资靠右(margin-left:auto 推到行尾) */
  .merc-row1 { display: flex; align-items: center; gap: 5px; }
  .merc-row1 .merc-cond-wage { margin-left: auto; }
  /* 状态/复活卡:第一行右侧含经验条时,行高放到 12px 容下经验条(HUD 同高);中段 .merc-top(flex:1)自动吸收 */
  .merc-offer:not(.merc-status) .merc-row1:has(.merc-exp) { height: 12px; line-height: 12px; }
  /* 可雇卡专属:头像(左)与四行(右)等高。头像列拉伸后居中头像;
     body 压紧行距贴合头像高度。第二三行(属性)与雇佣按钮等高,属性不足两行也用 min-height 防塌陷。 */
  .merc-offer:not(.merc-status) { align-items: stretch; }
  .merc-offer:not(.merc-status) .merc-ic { justify-content: center; }
  /* body 固定 50px = 头像列高(头像34+徽标16),与头像精确等高。四行内部:名字/技能各 11px,
     中段 .merc-top 用 flex:1 自动吃掉剩余(=22px,装两行属性),三处间距各 2px。 */
  .merc-offer:not(.merc-status) .merc-body { display: flex; flex-direction: column; gap: 2px; height: 50px; }
  .merc-offer:not(.merc-status) .merc-row1 { height: 11px; line-height: 11px; overflow: hidden; }
  .merc-offer:not(.merc-status) .merc-row3 { height: 11px; line-height: 11px; overflow: hidden; }
  .merc-offer:not(.merc-status) .merc-top { flex: 1; align-items: stretch; min-height: 0; }
  /* 属性块由 .merc-top(flex:1)撑满 22px,内部两行按 11px 行高排列 */
  .merc-offer:not(.merc-status) .merc-stats { flex: 1; min-width: 0; font-size: 11px; line-height: 11px; }
  /* 属性只有一行时补的第二行占位「...」(块级独占一行,承接空行) */
  .merc-offer:not(.merc-status) .merc-stats-fill { display: block; }
  .merc-offer:not(.merc-status) .merc-act { align-self: stretch; display: flex; }
  .merc-offer:not(.merc-status) .merc-hire-btn,
  .merc-offer:not(.merc-status) .merc-revive-btn { align-self: stretch; height: 100%; }
  /* 缩图标防顶高:名字行工资铜币 + 技能图标压到 11px(否则超出 11px 行盒把整行撑高) */
  .merc-offer:not(.merc-status) .merc-wage img.ic-sm,
  .merc-offer:not(.merc-status) .merc-wage span.ic-sm { width: 11px; height: 11px; font-size: 11px; }
  .merc-offer:not(.merc-status) .merc-skill img.ic-sm,
  .merc-offer:not(.merc-status) .merc-skill span.ic-sm { width: 11px; height: 11px; font-size: 11px; }
  .merc-offer:not(.merc-status) .merc-wage,
  .merc-offer:not(.merc-status) .merc-req,
  .merc-offer:not(.merc-status) .merc-skill { font-size: 11px; }
  .merc-name { color: #e8dcc0; font-weight: 600; font-size: 11px; }
  .merc-stats { color: #b0a079; font-size: 12px; }
  /* 佣兵经验条:复用 HUD 经验条(.hbar.xp),同高度(--vbar-track-h)、数值嵌在条内(.v)。
     HUD 的 .v/渐变规则限定在 #hud 作用域,这里为佣兵卡内的 .hbar.xp 补同款样式。 */
  .merc-exp { display: flex; align-items: center; margin-top: 4px; }
  .merc-exp .hbar { flex: 1; min-width: 0; display: flex; }
  /* 状态/复活卡:经验条在第一行工资左侧,固定窄宽,去掉竖排用的 margin-top */
  .merc-row1 .merc-cond-wage .merc-exp { flex: 0 0 78px; width: 78px; margin-top: 0; }
  .merc-exp .hbar .track { flex: 1; position: relative; height: var(--vbar-track-h); background: #2a2418;
    border: 1px solid #3a3020; border-radius: var(--bar-radius); overflow: hidden; }
  .merc-exp .hbar .track > i { display: block; height: 100%; border-radius: var(--bar-radius) 0 0 var(--bar-radius);
    background: linear-gradient(90deg, #946018, #a07e2c); transition: width .35s; }
  .merc-exp .hbar .track .v { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
    font-size: 11px; line-height: 1; color: #c8bfac; text-shadow: 0 1px 2px #000, 0 0 3px #000; pointer-events: none; font-weight: bold; }
  /* 第三行:仅技能。字号统一 12px */
  .merc-row3 { display: flex; align-items: center; gap: 8px; font-size: 12px; }
  .merc-skills { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; min-width: 0; }
  /* 技能:只留图标+文字(无背景框/边框);铜币同款 inline-flex 居中,图标与文字垂直对齐 */
  .merc-skill { display: inline-flex; align-items: center; gap: 3px; color: #9fc0d8; font-size: 12px; }
  .merc-skill img.ic-sm, .merc-skill span.ic-sm { width: 14px; height: 14px; font-size: 14px; }
  .merc-skill-nm { white-space: nowrap; }
  .merc-noskill { color: #888; font-size: 12px; }
  .merc-req { color: #d0885a; font-size: 12px; text-align: right; }
  .merc-var { color: #7fb069; font-size: 11px; }
  /* 名字行右侧:条件(声望)+ 工资 同一行垂直居中对齐 */
  .merc-cond-wage { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }
  .merc-act { flex: 0 0 auto; }
  .merc-wage { color: #b0a079; font-size: 12px; white-space: nowrap;
    display: flex; align-items: center; gap: 3px; }
  /* 雇佣按钮:flex 左对齐 + 垂直居中;字号/padding 压小降低按钮高度,铜币图标同步压到 13px(否则 16px 顶高) */
  .merc-hire-btn { display: flex; align-items: center; justify-content: flex-start; gap: 3px;
    font-size: 12px; padding: 2px 6px; }
  /* 复活按钮:flex 居中(图标+文字水平垂直都居中) */
  .merc-revive-btn { display: flex; align-items: center; justify-content: center; gap: 3px;
    font-size: 12px; padding: 2px 6px; }
  .merc-hire-btn img.ic-sm, .merc-hire-btn span.ic-sm,
  .merc-revive-btn img.ic-sm, .merc-revive-btn span.ic-sm,
  .merc-wage img.ic-sm, .merc-wage span.ic-sm { width: 13px; height: 13px; font-size: 13px; }
  /* 可雇卡:带边框(对齐邮局卡风格),突出为可选商品 */
  .merc-offer { background: #1b1610; border: 1px solid #4a3d24; border-radius: var(--el-radius); }
  /* ===== NPC 邮局 ===== */
  /* 收件箱列表:纵向卡片流,每条紧凑 2 行 */
  /* 固定 4 封高度:min-height 撑住下限(不足 4 封窗口不缩水),max-height 兜底(分页保证每页≤4封,实际不会触发) */
  .mail-list { display: flex; flex-direction: column; gap: 4px; margin-top: 8px; min-height: 220px; max-height: 260px; overflow-y: auto; }
  .mail-card { background: #1b1610; border: 1px solid #4a3d24; border-radius: var(--el-radius); padding: 3px 9px; }
  /* 第1行:时间 · 标题(伸缩+省略) · 来自 */
  .mail-row1 { display: flex; align-items: baseline; gap: 8px; }
  .mail-time { flex: 0 0 auto; color: #8a7d60; font-size: 12px; }
  .mail-title { flex: 1 1 auto; min-width: 0; color: #e6dcc2; font-size: 13px;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .mail-from { flex: 0 0 auto; color: #cdbf9c; font-size: 13px; font-weight: 700; }
  /* 第2行:附件(伸缩+省略) · 需付款 · 右侧按钮 */
  .mail-row2 { display: flex; align-items: center; gap: 8px; margin-top: 1px; }
  .mail-atts { flex: 1 1 auto; min-width: 0; display: flex; flex-wrap: nowrap; gap: 4px 8px;
    overflow: hidden; white-space: nowrap; }
  .mail-att { display: inline-flex; align-items: center; gap: 3px; font-size: 13px; color: #d8c9a4; }
  .mail-att .nm.plain { color: #c8c4bc; }      /* 普通物品:白 */
  .mail-att .nm.affixed { color: #6bb0e0; }    /* 词缀武器:蓝 */
  .mail-att-item { cursor: pointer; }
  .mail-att-item:hover .nm { text-decoration: underline; }
  .mail-cod { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 3px;
    color: #ffcf80; font-size: 13px; font-weight: 700; }
  .mail-btn { flex: 0 0 auto; margin-left: auto; padding: 2px 12px; font-size: 12px; }
  .mail-empty { color: #6a5d44; font-style: italic; }
  /* 收件箱分页:上一页/下一页并入底部按钮行(返回/关闭同排),不单独占行省高度 */
  .mail-pg-btn { padding: 4px 12px; }
  .mail-pg-btn:disabled { opacity: .4; cursor: default; }
  .mail-page-no { color: #9a8d70; font-size: 13px; min-width: 44px; text-align: center; }
  /* 写信表单 */
  .mail-form { display: flex; flex-direction: column; gap: 6px; margin-top: 0px; }
  /* 写信窗内错误提示(收件人不存在/铜币不足等):内联红字,塞在标题行中间不撑大布局;超长省略 */
  .mail-err { flex: 1 1 auto; min-width: 0; color: #f0a090; font-size: 13px; text-align: center;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .mail-form input[type=text], .mail-form textarea { background: #14110d; border: 1px solid #4a3d24; border-radius: var(--el-radius);
    color: #e6dcc2; font-size: 14px; height: 24px; padding: 0 9px; line-height: 22px; font-family: inherit; }
  .mail-form textarea { min-height: 0; resize: vertical; }
  /* 收件人框(约8汉字宽,固定不伸缩) + 内容框(占本行剩余宽度),同一行等高 */
  .mail-torow { display: flex; gap: 4px; align-items: stretch; }
  .mail-torow .mail-to { flex: 0 0 auto; width: 8.5em; }
  /* 内容框固定 1 行高(去掉 min-height、禁拉伸),与收件人框保持一致;多字时行内滚动 */
  .mail-torow .mail-body { flex: 1 1 auto; min-width: 0; min-height: 0; height: 24px;
    resize: none; overflow-y: auto; white-space: nowrap; line-height: 22px; }
  /* 货到付款:并入收件人/内容行右侧,固定不伸缩;标签左、铜币框+点券框紧随 */
  .mail-cod-edit { flex: 0 0 auto; display: flex; align-items: center; gap: 8px; font-size: 13px; color: #cabfa6; }
  .mail-cod-fields { display: flex; align-items: center; gap: 8px; }
  .mail-cod-box { display: inline-flex; align-items: center; gap: 3px; }
  .mail-cod-box input[type=number] { width: 56px; background: #14110d; border: 1px solid #4a3d24; border-radius: var(--el-radius);
    color: #e6dcc2; padding: 3px 6px; font-family: inherit; }
  /* ===== 赌坊骰宝 ===== */
  .g-board { display: flex; flex-direction: column; gap: 2px; margin-top: 4px; }
  /* 两列布局:左主区(押注门/注额/按钮)+ 右注单列(占 30%),从盘面底部开始等高 */
  .g-board-2col { display: flex; flex-direction: row; align-items: stretch; gap: 8px; }
  .g-board-2col .g-main { flex: 1 1 65%; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
  /* 右列:stretch 到左列高度(relative 占位),注单 absolute 铺满,内容超出走内部竖向滚动而不撑高 */
  .g-board-2col .g-side { flex: 0 0 35%; min-width: 0; position: relative; }
  .g-board-2col .g-side .g-bets { position: absolute; inset: 0; max-height: none; overflow-y: auto; }
  /* 轮次倒计时条:进度条 + 历史/文案行(betting 显剩余秒,revealing 显开奖中);各为 g-board 直接子级,统一吃 8px 间距 */
  .g-cdbar-bg { height: 5px; background: #14110d; border: 1px solid #3a2f1e; border-radius: var(--bar-radius); overflow: hidden; }
  .g-cdbar { height: 100%; background: linear-gradient(90deg, #c8a24a, #e0c068); transition: width .25s linear; }
  .g-cdrow { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
  .g-countdown { text-align: right; font-size: 12px; color: #c8b890; white-space: nowrap; flex: 0 0 auto; }
  /* 全桌注单列表:每行 名字/门类/注额(+开奖后输赢);自己的高亮 */
  .g-bets { display: flex; flex-direction: column; gap: 2px; max-height: 92px; overflow-y: auto;
    background: #14110d; border: 1px solid #3a2f1e; border-radius: var(--el-radius); padding: 5px 7px; }
  .g-bets-empty { color: #6a5d44; font-size: 12px; font-style: italic; text-align: center;
    padding: 8px 7px; min-height: unset; }
  .g-betitem { display: flex; align-items: center; gap: 6px; font-size: 12px; color: #cabfa6; }
  .g-betitem.mine { color: #f0dca0; font-weight: 700; }
  .g-betitem .g-bname { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .g-betitem .g-bdoor { color: #b39860; }
  .g-betitem .g-bamt { min-width: 36px; text-align: right; }
  .g-betitem .g-bwin { color: #6fe07a; font-weight: 700; }
  .g-betitem .g-blose { color: #e0907a; font-weight: 700; }
  /* 骰盘:三骰居中,留出 3D 透视 */
  .g-tray { position: relative; display: flex; align-items: center; justify-content: center; gap: 20px; height: 108px;
    background: #14110d; border: 1px solid #3a2f1e; border-radius: var(--el-radius); padding: 10px 6px;
    perspective: 480px; }
  /* 3D 骰子:外层 .g-die3d 撑位 + 透视;内层 .g-cube 做旋转(translateZ 半边长=20px) */
  .g-die3d { width: 40px; height: 40px; perspective: 300px; }
  .g-cube { position: relative; width: 40px; height: 40px; transform-style: preserve-3d; }
  .g-face { position: absolute; width: 40px; height: 40px; box-sizing: border-box;
    background: linear-gradient(145deg, #f4ecd8, #d8cba8); border: 1px solid #b3a274; border-radius: var(--el-radius);
    display: grid; grid-template-columns: repeat(3, 1fr); grid-template-rows: repeat(3, 1fr);
    padding: 4px; gap: 1px; box-shadow: inset 0 0 4px rgba(0,0,0,.25); }
  .g-pip { align-self: center; justify-self: center; width: 8px; height: 8px; border-radius: 50%;
    background: radial-gradient(circle at 35% 35%, #555, #1a1208); }
  .gf-front  { transform: rotateY(0deg)    translateZ(20px); }
  .gf-back   { transform: rotateY(180deg)  translateZ(20px); }
  .gf-right  { transform: rotateY(90deg)   translateZ(20px); }
  .gf-left   { transform: rotateY(-90deg)  translateZ(20px); }
  .gf-top    { transform: rotateX(90deg)   translateZ(20px); }
  .gf-bottom { transform: rotateX(-90deg)  translateZ(20px); }
  /* 翻滚(rolling):无限匀速旋转,等服务端结果(绝不在此停,否则会停在 identity=正面值1) */
  .g-cube.rolling { animation: g-tumble 1.1s linear infinite; }
  @keyframes g-tumble {
    0%   { transform: rotateX(0)      rotateY(0);    }
    100% { transform: rotateX(360deg) rotateY(720deg); }
  }
  /* 落地(landing):多圈翻滚 + ease-out 减速,终点=该结果面定格角(--land-x/y 由 JS 按真实点数传入)。
     终点叠加 1440°/1080°(均 360 整数倍)→ 视觉等同纯 --land-x/y,即真实结果面;forwards 停住不回弹。 */
  .g-cube.landing { animation: g-land 3.5s cubic-bezier(.16,.62,.24,1) forwards; }
  @keyframes g-land {
    0%   { transform: rotateX(0) rotateY(0); }
    100% { transform: rotateX(calc(var(--land-x) + 1440deg)) rotateY(calc(var(--land-y) + 1080deg)); }
  }
  /* 定格到结果面(done 态,与 landing 终点同角,不跳变):front=1/back=6/right=3/left=4/top=2/bottom=5 */
  .g-cube.show-1 { transform: rotateX(0deg)    rotateY(0deg);   }
  .g-cube.show-6 { transform: rotateX(0deg)    rotateY(180deg); }
  .g-cube.show-3 { transform: rotateX(0deg)    rotateY(-90deg); }
  .g-cube.show-4 { transform: rotateX(0deg)    rotateY(90deg);  }
  .g-cube.show-2 { transform: rotateX(-90deg)  rotateY(0deg);   }
  .g-cube.show-5 { transform: rotateX(90deg)   rotateY(0deg);   }
  .g-cube.idle { transform: rotateX(-20deg) rotateY(28deg); opacity: .5; }
  .g-sum { font-size: 16px; color: #cdbf9c; margin-left: 6px; align-self: center; }
  /* 结果行:赢金、输灰红;无结果留空占位防跳动 */
  .g-resline { position: absolute; top: 50%; right: 8px; transform: translateY(-50%);
    display: flex; flex-direction: column; align-items: flex-end; justify-content: center; text-align: right;
    gap: 3px; max-width: 44%; font-size: 13px; font-weight: 700; line-height: 1.35; color: #cdbf9c; }
  .g-resline:empty { display: none; }
  .g-resmine.win { color: #6fe07a; }
  .g-resmine.lose { color: #e0907a; }
  /* 开奖历史:小芯片横排 */
  .g-hist { display: flex; flex-wrap: wrap; gap: 3px; justify-content: flex-start; min-height: 16px; flex: 1 1 auto; overflow: hidden; }
  .g-hist-empty { color: #6a5d44; font-size: 12px; font-style: italic; }
  .g-hchip { font-size: 11px; padding: 1px 5px; border-radius: 50%; color: #1a1208; font-weight: 700; min-width: 16px; text-align: center; }
  .g-hchip.small { background: #5a8ac0; }
  .g-hchip.big { background: #c05a5a; }
  .g-hchip.triple { background: #e0b840; }
  /* 三门赔率按钮 */
  .g-doors { display: flex; gap: 6px; }
  .g-door { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 1px;
    background: #221c14; border: 1px solid #5a4a2c; border-radius: var(--el-radius); padding: 6px; cursor: pointer; color: #cdbf9c; }
  .g-door:hover { background: #2e2616; }
  .g-door.sel { background: #443818; border-color: #c8a850; box-shadow: 0 0 0 1px #c8a850 inset; }
  .g-dname { font-size: 14px; font-weight: 700; color: #e8dcc0; }
  .g-dsub { display: flex; align-items: baseline; gap: 4px; }
  .g-dhint { font-size: 11px; color: #9a8d70; }
  .g-dpay { font-size: 11px; color: #f0c040; }
  /* 注额行 */
  .g-betrow { display: flex; align-items: center; gap: 4px; }
  .g-betlbl { font-size: 13px; color: #9a8d70; flex: 0 0 auto; }
  /* 赌桌内的 .dq-step 按钮(注额行/直注押号行)统一样式:窄、不拉伸、字居中 */
  .g-betrow .dq-step, .g-stpick .dq-step {
    flex: 0 0 auto; min-width: 34px; padding: 0 6px; height: 24px; line-height: 22px;
    font-size: 13px; text-align: center; white-space: nowrap;
    background: #2a2212; color: #e0c878; border: 1px solid #5a4a2c; border-radius: var(--el-radius); cursor: pointer; }
  .g-betrow .dq-step:hover, .g-stpick .dq-step:hover { background: #3a2f1e; border-color: #8a7038; }
  .g-betrow .dq-step:active, .g-stpick .dq-step:active { background: #1f1810; }
  .g-betrow input { flex: 1; min-width: 0; background: #14110d; border: 1px solid #5a4a2c; border-radius: var(--el-radius);
    color: #e8dcc0; text-align: center; height: 24px; font-size: 14px; }
  /* 注额滑块:押注行下方,与丢弃窗滑块同款配色 */
  .g-betslider { width: 100%; margin: 0; accent-color: #c8a048; cursor: pointer; }
  .g-betslider:disabled { cursor: not-allowed; opacity: .4; }
  .g-limit { text-align: center; font-size: 11px; color: #6a5d44; }
  .action.g-roll { width: 100%; margin-top: 0; padding: 3px 6px; }
  /* 双下注按钮(铜币/点券)并排一行 */
  .g-rollrow { display: flex; gap: 8px; width: 100%; }
  .g-rollrow .action.g-roll { flex: 1; min-width: 0; }
  .action.g-roll.g-roll-premium { background: #1e2d3a; border-color: #3a5a7a; color: #bcd8f0; }
  .action.g-roll.g-roll-premium:hover:not(:disabled) { background: #26384a; border-color: #5a8ac0; }
  /* 赌博大厅:游戏选择卡片(图标 + 名称/简介 + 注限) */
  .g-gamelist { display: flex; flex-direction: column; gap: 8px; margin-top: 8px; }
  .g-gamecard { display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
    background: #221c14; border: 1px solid #5a4a2c; border-radius: var(--el-radius); padding: 10px; cursor: pointer; color: #cdbf9c; }
  .g-gamecard:hover { background: #2e2616; border-color: #c8a850; }
  .g-gameic { font-size: 30px; line-height: 1; flex: 0 0 auto; }
  .g-gamemid { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
  .g-gamename { font-size: 15px; font-weight: normal; color: #e8dcc0; }
  .g-gameblurb { font-size: 12px; color: #9a8d70; }
  .g-gamelimit { flex: 0 0 auto; font-size: 12px; color: #f0c040; }
  /* ===== 轮盘 ===== */
  /* 号码盘:转盘(红黑相间轮缘 + 中心轴)+ 绕轨小球;出结果显带色号码球 */
  .g-roul-stage { position: relative; width: 96px; height: 96px; }
  .g-roul-wheel { position: absolute; inset: 0; border-radius: 50%;
    /* 红黑相间轮缘:18 段红黑交替(36 个 10° 扇区),中心暗色盘面 */
    background:
      radial-gradient(circle at center, #14110d 0 30%, transparent 30%),
      conic-gradient(#c0392b 0 10deg, #222018 10deg 20deg, #c0392b 20deg 30deg, #222018 30deg 40deg,
        #c0392b 40deg 50deg, #222018 50deg 60deg, #c0392b 60deg 70deg, #222018 70deg 80deg,
        #c0392b 80deg 90deg, #222018 90deg 100deg, #c0392b 100deg 110deg, #222018 110deg 120deg,
        #c0392b 120deg 130deg, #222018 130deg 140deg, #c0392b 140deg 150deg, #222018 150deg 160deg,
        #c0392b 160deg 170deg, #222018 170deg 180deg, #c0392b 180deg 190deg, #222018 190deg 200deg,
        #c0392b 200deg 210deg, #222018 210deg 220deg, #c0392b 220deg 230deg, #222018 230deg 240deg,
        #c0392b 240deg 250deg, #222018 250deg 260deg, #c0392b 260deg 270deg, #222018 270deg 280deg,
        #c0392b 280deg 290deg, #222018 290deg 300deg, #c0392b 300deg 310deg, #222018 310deg 320deg,
        #c0392b 320deg 330deg, #222018 330deg 340deg, #c0392b 340deg 350deg, #222018 350deg 360deg);
    border: 3px solid #8a6d3a; box-shadow: inset 0 0 8px rgba(0,0,0,.5); }
  .g-roul-hub { position: absolute; top: 50%; left: 50%; width: 30px; height: 30px; margin: -15px 0 0 -15px;
    border-radius: 50%; background: radial-gradient(circle at 38% 38%, #d8b860, #6a4f1f); border: 2px solid #4a3713; }
  /* 绕轨小球:容器旋转带动小球绕中心转(小球本体偏置在顶部) */
  .g-roul-ballorbit { position: absolute; inset: 0; }
  .g-roul-ball { position: absolute; top: 4px; left: 50%; width: 10px; height: 10px; margin-left: -5px;
    border-radius: 50%; background: radial-gradient(circle at 35% 35%, #fff, #b8b0a0);
    box-shadow: 0 0 4px rgba(255,255,255,.6); }
  /* 转动:轮盘正转、小球反向快转,都无限循环(转到 done 才切号码球揭晓,故此处不减速停) */
  .g-roul-wheel.spinning { animation: g-wheelspin 2.2s linear infinite; }
  .g-roul-ballorbit.spinning { animation: g-ballspin 1.1s linear infinite; }
  @keyframes g-wheelspin { from { transform: rotate(0); } to { transform: rotate(360deg); } }
  @keyframes g-ballspin { from { transform: rotate(0); } to { transform: rotate(-360deg); } }
  .g-roul-wheel.idle { opacity: .45; }
  .g-roul-ballorbit.idle { opacity: .45; }
  .g-ball { display: inline-flex; align-items: center; justify-content: center; width: 96px; height: 96px;
    border-radius: 50%; font-size: 40px; font-weight: 800; color: #fff; border: 3px solid #e8dcc0; }
  .g-ball.red { background: #c0392b; }
  .g-ball.black { background: #222018; }
  .g-ball.green { background: #2e8b57; }
  /* 揭晓时号码球弹入(从轮盘"停球"过渡到放大号码) */
  .g-ball.reveal { animation: g-ballpop .35s cubic-bezier(.2,1.4,.5,1); }
  @keyframes g-ballpop { 0%{ transform: scale(.3); opacity: 0; } 100%{ transform: scale(1); opacity: 1; } }
  /* 轮盘平注六门:三列两行网格(比骰宝三门窄) */
  .g-doors.g-doors-roul { display: grid; grid-template-columns: repeat(3, 1fr); gap: 2px; }
  /* 历史芯片复用骰宝 .g-hchip,但轮盘用颜色类(red/black/green)显号码 */
  .g-hchip.red { background: #c0392b; color: #fff; }
  .g-hchip.black { background: #222018; color: #fff; }
  .g-hchip.green { background: #2e8b57; color: #fff; }
  /* 直注押号行:左侧"直注押号"按钮(选中高亮),右侧号码步进 */
  .g-straight { display: flex; align-items: stretch; gap: 6px; margin-top: 0; }
  .g-stbtn { flex: 1; display: flex; align-items: center; justify-content: center; gap: 6px;
    background: #221c14; border: 1px solid #5a4a2c; border-radius: var(--el-radius); padding: 6px; cursor: pointer; color: #cdbf9c; font-size: 13px; }
  .g-stbtn:hover { background: #2e2616; }
  .g-stbtn.sel { background: #443818; border-color: #c8a850; box-shadow: 0 0 0 1px #c8a850 inset; color: #e8dcc0; }
  .g-stpick { display: flex; align-items: center; gap: 4px; flex: 0 0 auto; }
  .g-stpick input { width: 48px; background: #14110d; border: 1px solid #5a4a2c; border-radius: var(--el-radius);
    color: #e8dcc0; text-align: center; height: 24px; font-size: 14px; }
  /* 对话区内的"需要/条件"清单:固定在对话区最下方,贴近底边,无分割横线 */
  .obv-cond { display: flex; gap: 16px; margin-top: auto; flex: 0 0 auto; }
  .obv-cond > div { font-size: 13px; color: #cdbf9c; line-height: 1.2; }
  /* 人形四角空位:占格但透明、不可交互,只为撑出十字形 */
  .cell2.slot-blank { border: none; background: none; cursor: default; pointer-events: none; }
  .cell2.slot-blank:hover { border: none; background: none; }
  /* 背包:固定 10 列 × 4 行 = 40 格(10×48 + 9×2间距 = 498px 内容宽),超出可滚动 */
  .grid.bag { grid-template-columns: repeat(10, var(--cell-track)); grid-auto-rows: var(--cell-track); gap: 0;
    height: calc(3 * var(--cell-track) + 48px); overflow-y: auto; align-content: start; }
  /* 技能格:一排 10 个,自然换行,无需像背包那样补空格占位 */
  .grid.skills { grid-template-columns: repeat(10, var(--cell-track)); }
  /* 道具窗背包:6 列 × 5 行 = 30 格(= bagCap),高度自适应不滚动;不影响商店/仓库共用的 .grid.bag */
  .grid.bag.invbag { grid-template-columns: repeat(6, var(--cell-track)); height: auto; overflow: visible; }
  .cell2 { position: relative; width: 48px; height: 48px; border: 1px solid #4a4028;
    border-radius: var(--el-radius); background: #1b1710; display: flex; flex-direction: column;
    align-items: center; justify-content: center; cursor: pointer; padding: 2px 2px 12px;
    transition: border-color .12s, background .12s; }
  .cell2:hover { border-color: #c0a050; background: #2a2418; }
  .cell2 .ic { font-size: 24px; line-height: 1; }
  /* 名字横条:绝对定位贴格子底边 + 半透明黑底,道具格/配置格/战斗按钮共用同一风格 */
  .cell2 .nm, .hotcell .nm, .slotbtn .sname, .cmdsq .sname {
    position: absolute; left: 0; right: 0; bottom: 0;
    font-size: 10.5px; color: #cdbf9c; text-align: center; line-height: 1.2;
    padding: 1px 2px; background: #00000066; border-radius: 0 0 var(--el-radius) var(--el-radius);
    overflow: hidden; text-overflow: ellipsis; pointer-events: none;
    max-width: none; margin: 0;
    /* 名称一排放不下(超过约4个汉字)自动换到两排,最多两行超出省略 */
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; word-break: break-all; }
  /* 稀有度着色:白板=白,词缀=蓝。覆盖默认 nm 色,地面 chip 同理 */
  .cell2 .nm.plain, .gchip.plain { color: #c8c4bc; }
  .cell2 .nm.affixed, .gchip.affixed { color: #6bb0e0; }
  .cell2.slot { border-style: dashed; padding-bottom: 2px; }   /* 装备槽无数量条,取消底部预留使内容垂直居中 */
  .cell2.slot .slotlabel { position: absolute; left: 3px; top: 1px; font-size: 8px; color: #6a5d44; }
  .cell2.equipped { border-color: #7fb0e0; border-style: solid; background: #1c242e; }
  /* 装备槽边框 = 物品名颜色:白装白边、蓝装蓝边(道具窗与观察窗公用) */
  .cell2.equipped.plain   { border-color: #6b5f3a; }
  .cell2.equipped.affixed { border-color: #6bb0e0; }
  .cell2.emptyslot .ic { opacity: .25; }
  /* 双手武器占用副武器栏:整格压暗 + 图标置灰(grayscale),示意"被主手双手武器占用"。 */
  .cell2.offlocked { border-style: dashed; background: #181818; cursor: default; }
  .cell2.offlocked .nm { color: #6a6a6a; }
  .ic-dim { filter: grayscale(1) brightness(.6); opacity: .5; }
  .cell2.eqitem { border-color: #6b5f3a; }
  .cell2.inslot { border-color: #f0c040; box-shadow: 0 0 8px #f0c04055; }
  /* 快捷标记星号:默认左上角,候选格已入栏(inslot)移到右上角 */
  .cell2 .star { position: absolute; left: 3px; top: 3px; width: 6px; height: 6px; border-radius: 50%; background: #f0c040; pointer-events: none; }
  .cell2.inslot .star { left: auto; right: 3px; top: 3px; }
  /* 快捷栏配置:顶部 5 格 */
  .hotbar { display: flex; gap: 0; justify-content: center; margin: 4px 0 2px; }
  /* 仅纯 flex 版 .hotbar 用负 margin 重叠;.hotbar10 是 grid,靠轨道重叠,排除以免多缩一格 */
  .hotbar:not(.hotbar10) > * + * { margin-left: var(--cell-overlap); }
  /* 统一快捷栏:10 格一行 48px,与背包/装备等宽对齐 */
  .hotbar10 { display: grid; grid-template-columns: repeat(10, var(--cell-track)); gap: 0;
    width: calc(9 * var(--cell-track) + 48px); max-width: calc(9 * var(--cell-track) + 48px); margin: 4px auto 2px; }
  .hotbar10 .hotcell { width: 48px; }
  /* 道具/技能窗快捷栏配置区:把已填充格子的边框调暗(HUD 快捷栏不受影响) */
  .hotbar10 .hotcell.filled { border-color: #6b5a30; }
  .hotcell { position: relative; width: 48px; height: 48px; border: 1px dashed #5a4a2c;
    border-radius: var(--el-radius); background: #1b1710; display: flex; flex-direction: column;
    align-items: center; justify-content: center; cursor: pointer; color: #5a4a2c;
    transition: border-color .12s, background .12s; }
  .hotcell.filled { border-style: solid; border-color: #c0a050; color: #ece5d8; background: #2a2418; }
  .hotcell.filled:hover { border-color: #e06b6b; }
  .hotcell .ic { font-size: 24px; line-height: 1; }
  /* 道具/技能窗格子底部留白略减(名字横条) */
  .grid.invbag .cell2 { padding-bottom: 2px; }
  /* ===== 图标格子覆盖文字:统一风格 + 统一阴影(单一来源)=====
     所有格子(HUD .hcell / 战斗 .slotbtn .cmdsq / 配置 .hotcell / 道具 .cell2)的覆盖文字,
     阴影在容器上一处定义,子级(名字 .nm/.sname、角标 .cmk)全靠继承,值与 HUD HP/MP/EXP 一致 */
  .cell2, .hotcell, .hud-hotbar .hcell, .slotbtn, .cmdsq { text-shadow: 0 1px 2px #000, 0 0 3px #000; }
  /* 角标基类:序号/数量/MP/CD/库存/价格共用同一视觉基底,位置由 .tl/.tr 控、颜色由语义类控 */
  .cmk { position: absolute; top: 1px; font-size: 11px; line-height: 1;
    font-weight: 400; pointer-events: none; }
  .cmk.tl { left: 3px; }           /* 左上:序号 / 商店价格 */
  .cmk.tr { right: 3px; }          /* 右上:数量 / MP / CD / 库存 */
  .cmk.idx  { font-size: 8px; color: #6a5d44; }
  .cmk.qty  { color: #c8c4bc; }
  .cmk.mp   { color: #6db3f2; }
  .cmk.cd   { color: #ffd98a; }
  .cmk.gold { color: #f0c040; }    /* 商店价格 */
  .cmk.stock { color: #ece5d8; }
  .cmk.stock.out { color: #e0907a; }   /* 售罄 */
  .cmk.lv { font-size: 10px; font-weight: 700; color: #9fd88a; text-shadow: 0 0 2px #000, 0 0 2px #000; }   /* 技能等级角标(右上,取代原 MP 数值) */
  /* 图标作为背景层:所有格子(背包/商店/装备槽/候选格/快捷栏/战斗按钮)的图标容器
     绝对定位铺满格子并沉到文字下方,文字浮于其上。布局位置不变,仅改层级。
     isolation 让 z-index:-1 只相对格子自身,不会穿到格子背景之下 */
  .cell2, .hotcell, .hud-hotbar .hcell, .slotbtn, .cmdsq { isolation: isolate; }
  .cell2 > .ic, .hotcell > .ic, .hud-hotbar .hcell > .ic, .slotbtn > .sicon, .cmdsq > .sicon {
    position: absolute; inset: 0; z-index: -1;
    display: flex; align-items: center; justify-content: center;
    pointer-events: none; }
  /* 图标脱离文档流后,名字会独自居中上移;改为靠底,恢复原来"图标下方/底部"的位置 */
  .cell2, .hotcell, .slotbtn, .cmdsq { justify-content: flex-end; }
  /* 格子操作菜单(覆盖在窗口内) */
  .cellmenu { position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: #000c; border-radius: var(--el-radius);   /* 勿用 inset 简写:iOS 13 不认,居中容器塌陷致内容偏左上 */
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px; padding: 20px; z-index: 5; }
  .cellmenu h4 { color: #e0c878; font-size: 15px; margin-bottom: 2px; }
  .cellmenu .mdesc { font-size: 13px; color: #9a8d70; text-align: center; margin-bottom: 8px; white-space: pre-line; }
  .cellmenu button { width: 200px; }
  /* 确认框/公告等直挂 #map(非 #mapcard)时,须盖住地图框内所有层(topbar6/mapwin8/opwin9/dropwin30) */
  #map > .cellmenu { z-index: 31; }
  /* 交易确认框(购买/出售/合成的 .cellmenu)弹出时禁掉 #mapcard 滚动条:确认框内容不多,覆盖可视区即可,不需背后滚动 */
  #mapcard:has(.cellmenu) { overflow: hidden; }

  /* 丢弃数量:独立小窗体(挂到 body,fixed 居中,自带遮罩,与背包大框无关) */
  /* 丢弃/数量窗:嵌入地图框(挂 #map,absolute 只盖地图区不遮 HUD/聊天),遮罩居中卡片。
     与 #opwin 同源:#map ⊂ #game 故天然继承 --ui-scale 缩放,无需自乘。z-index 高于 #mapwin(8)盖在道具窗之上。 */
  #dropwin { position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: #0009; z-index: 30;   /* 勿用 inset 简写:iOS 13 不认,居中容器塌陷致卡片偏左上 */
    display: flex; align-items: center; justify-content: center; }
  #dropwin .dropwin-card { background: #221c14; border: 1px solid #5a4a2c; border-radius: var(--win-radius);
    padding: var(--win-pad); box-shadow: 0 8px 30px #000c; display: flex; flex-direction: column; align-items: center; gap: 8px; }
  #dropwin h4 { color: #e0c878; font-size: 15px; }
  #dropwin .dropwin-have { font-size: 13px; color: #9a8d70; }
  #dropwin .dropwin-btns { display: flex; gap: 8px; width: 100%; }
  #dropwin .dropwin-btns .action { flex: 1; width: auto; }

  /* 物品操作小窗:嵌入地图框(挂 #map,absolute 只盖地图区不遮 HUD/聊天),遮罩居中卡片。
     z-index 高于 #mapwin(8)故盖在道具窗之上;#map overflow:hidden 天然裁剪、#game 缩放天然继承。 */
  #opwin { position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: #0009; z-index: 9;   /* 勿用 inset 简写:iOS 13 不认,居中容器塌陷致卡片偏左上 */
    display: flex; align-items: center; justify-content: center; }
  #opwin .opwin-card { background: #221c14; border: 1px solid #5a4a2c; border-radius: var(--win-radius);
    padding: var(--win-pad); box-shadow: 0 8px 30px #000c; display: flex; flex-direction: column; align-items: center; gap: 8px; }
  #opwin h4 { color: #e0c878; font-size: 15px; }
  #opwin .opwin-desc { font-size: 13px; color: #9a8d70; text-align: center; max-width: 200px; margin-bottom: 4px; white-space: pre-line; }
  /* 操作窗内的提示行(已学会/需求未满足等):与 opwin-desc 同字号,避免继承默认大字号 */
  #opwin .mdesc { font-size: 13px; }
  #opwin .action { width: 200px; }

  /* 书籍阅读窗:嵌入地图框(挂 #map,absolute 只盖地图区),与 #opwin 同源;正文区高度自适应地图框余量并可滚动。
     正文行数由 flex 撑开(不再固定 12 行),避免超出 420px 高的地图框。 */
  #bookwin { position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: #0009; z-index: 9;   /* 勿用 inset 简写:iOS 13 不认,居中容器塌陷致卡片偏左上 */
    display: flex; align-items: center; justify-content: center; }
  #bookwin .bookwin-card { background: #221c14; border: 1px solid #5a4a2c; border-radius: var(--win-radius);
    padding: var(--win-pad); box-shadow: 0 8px 30px #000c; display: flex; flex-direction: column; align-items: center; gap: 10px;
    width: min(440px, 90%); height: calc(100% - 16px); }
  #bookwin h4 { color: #e0c878; font-size: 15px; flex: 0 0 auto; }
  #bookwin .bookwin-page { white-space: pre-wrap; word-break: break-word; line-height: 1.7;
    font-size: 14px; color: #d8cba8; text-align: left; width: 100%;
    flex: 1 1 auto; min-height: 0; overflow-y: auto; background: #1c1710; border: 1px solid #4a3d24;
    border-radius: var(--el-radius); padding: 12px 14px; }
  #bookwin .bookwin-nav { display: flex; align-items: center; gap: 12px; width: 100%; flex: 0 0 auto; }
  /* 翻页(上一页/页码/下一页)自然宽,成组靠左;合上靠右(margin-left:auto 推到行尾) */
  #bookwin .bookwin-nav .action { flex: 0 0 auto; width: auto; }
  #bookwin .bookwin-nav .bookwin-close { margin-left: auto; }
  #bookwin .bookwin-no { font-size: 13px; color: #9a8d70; min-width: 52px; text-align: center; }
  #bookwin .action:disabled { opacity: .4; cursor: default; }

  /* 数量丢弃面板:±快捷按钮行(每行4个,含最大/最小)+ 当前数量可编辑大字 + 横向 slider */
  .dropqty { display: flex; flex-direction: column; align-items: center; gap: 6px; width: 200px; }
  .dropqty .dq-btns { display: grid; grid-template-columns: repeat(4, 1fr); gap: 4px; width: 100%; }
  .dropqty .dq-step { width: auto !important; padding: 3px 0; font-size: 13px; color: #e0c878;
    background: #2a2218; border: 1px solid #5a4a2c; border-radius: var(--el-radius); cursor: pointer; }
  .dropqty .dq-step:hover { background: #3a2f1e; border-color: #8a7038; }
  .dropqty .dq-step:active { background: #1f1810; }
  .dropqty .dq-edge { color: #f0c040; border-color: #8a7038; }
  .dropqty .dq-num { width: 80px !important; text-align: center; font-size: 20px; font-weight: bold;
    color: #f0c040; line-height: 1; background: #1f1810; border: 1px solid #5a4a2c; border-radius: var(--el-radius); padding: 3px 0;
    -moz-appearance: textfield; appearance: textfield; }
  .dropqty .dq-num::-webkit-outer-spin-button,
  .dropqty .dq-num::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
  .dropqty .dq-slider { width: 100%; accent-color: #c8a048; cursor: pointer; }

  #g-bet { -moz-appearance: textfield; appearance: textfield; }
  #g-bet::-webkit-outer-spin-button,
  #g-bet::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

  /* ===== 角色状态窗 ===== */
  .statwin { color: #ece5d8; }
  .stat-head { display: flex; flex-direction: column; gap: 4px; padding: 12px 14px; margin-bottom: 14px;
    background: linear-gradient(135deg, #241d2e, #1b1610); border: 1px solid #5a4a2c; border-radius: var(--el-radius); }
  /* 上半部:头像 + 右列(名字/三条 bar),横向并排 */
  .stat-head-top { display: flex; align-items: stretch; gap: 14px; }
  /* 头像照搬 HUD:72px 暗框 + 右上角 Lv.X 金色药丸角标 + 做旧滤镜 */
  .stat-avatar { position: relative; width: var(--stat-avatar-sz); height: var(--stat-avatar-sz); flex: 0 0 auto;
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 0px;
    font-size: 40px; line-height: 1;
    background: #14110d; border: 1px solid #4a3d24; border-radius: var(--el-radius);
    filter: drop-shadow(0 3px 5px #000a) saturate(.75) brightness(.85); opacity: .9; }
  .stat-avatar .lvbadge {
    background: linear-gradient(135deg, #c9b478, #9a7028); color: #2a2012; font-weight: 700;
    font-size: 12px; padding: 1px 8px; border-radius: var(--el-radius); border: 1px solid #2a2012;
    box-shadow: 0 2px 4px #0008; white-space: nowrap; }
  /* 右列:锁定与头像同高(随头像尺寸变量),名字行在上、HP/MP/SP 三条贴底 */
  .stat-head .who { flex: 1; min-width: 0; height: var(--stat-avatar-sz); display: flex; flex-direction: column; justify-content: space-between; }
  /* 名字行照搬 HUD:左金色名字,右古铜色金币 */
  .stat-head .who .nm { font-size: 13px; font-weight: 700; color: #c9a44c; letter-spacing: 1px;
    text-shadow: 0 1px 2px #000; display: flex; justify-content: space-between; align-items: baseline; gap: 8px; }
  .stat-head .who .nm .nmwrap { display: flex; align-items: center; gap: 8px; min-width: 0; }
  .stat-head .who .nm .sex { color: #9a8d70; font-weight: 400; letter-spacing: 0; font-size: 12px; }
  .stat-head .who .nm .copper { color: #c87f4a; font-weight: 700; letter-spacing: 0;
    filter: saturate(.8) brightness(.9); opacity: .88; flex: 0 0 auto; }
  /* 三条资源进度条:照搬 HUD(暗调做旧渐变 + 值嵌条内左对齐) */
  .stat-bars { display: flex; flex-direction: column; gap: 3px; }
  .stat-bar { display: flex; align-items: center; font-size: 13px; }
  .stat-bar .track { flex: 1; height: var(--vbar-track-h); background: #2a2418; border: 1px solid #3a3020;
    border-radius: var(--bar-radius); overflow: hidden; position: relative; }
  .stat-bar .track > i { display: block; height: var(--vbar-fill-h); border-radius: var(--bar-radius) 0 0 var(--bar-radius); transition: width .35s; }
  .stat-bar .track .v { position: absolute; inset: 0; display: flex; align-items: center; justify-content: flex-start;
    padding-left: 8px; font-size: 11px; color: #c8bfac; text-shadow: 0 1px 2px #000, 0 0 3px #000;
    pointer-events: none; font-weight: bold; }
  .stat-bar.hp i { background: linear-gradient(90deg, #732820, #897028); }
  .stat-bar.mp i { background: linear-gradient(90deg, #1e3354, #2c5076); }
  .stat-bar.xp i { background: linear-gradient(90deg, #946018, #a07e2c); }
  /* 状态窗主体:左列所有属性卡(主属性 + 战斗属性),右列装备加成框。
     两列按比例(2:1)分宽而非固定像素,竖屏窄屏也等比缩放不重叠。
     单行两项 align-items:stretch 自动等高 → 加成框与左侧卡片区通高。 */
  .stat-body { display: grid; grid-template-columns: 2fr 1fr; gap: 8px; align-items: stretch; }
  .stat-main { grid-column: 1; min-width: 0; }
  /* 战斗属性卡:每行 3 个(与主属性同为 3 列,卡片随之缩窄) */
  .stat-body .stat-cards { grid-template-columns: repeat(3, 1fr); }
  /* 装备加成框:占右列,拉伸到与左侧等高,内容超出则框内滚动 */
  .stat-bonus-box { grid-column: 2; min-width: 0; box-sizing: border-box;
    border: 1px solid #4a4028; border-radius: var(--el-radius); background: #1b1710;
    padding: 6px 10px; overflow-y: auto; }
  .stat-bonus-title { font-size: 12px; color: #8a7d60; text-align: center;
    padding-bottom: 4px; margin-bottom: 4px; }
  /* 属性卡片网格 */
  .stat-cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; margin-bottom: 4px; }
  .stat-card { background: #1b1710; border: 1px solid #4a4028; border-radius: var(--el-radius);
    padding: 4px 4px; text-align: center; height: 48px;
    display: flex; flex-direction: column; align-items: center; justify-content: center; }
  .stat-card .k { font-size: 12px; color: #8a7d60; }
  .stat-card .v { font-size: 12px; color: #e0c878; font-weight: 600; }
  .stat-card .b { font-size: 12px; color: #6bd17a; min-height: 12px; }      /* 第三行:装备加成绿字 */
  .stat-card .hint { font-size: 12px; color: #6a5d44; min-height: 12px; }   /* 第三行:说明文字(幸运/魅力等) */

  /* 加点草稿:数值上的绿色增量提示 */
  .stat-card .v .up { font-size: 12px; color: #6bd17a; margin-left: 3px; vertical-align: middle; }
  /* 加/减点按钮:与数值同一水平排 [-] 19 [+] */
  .stat-card .addrow { display: flex; gap: 8px; align-items: center; justify-content: center; margin-top: 4px; }
  .stat-card .addrow .v { flex: 1 1 auto; }
  .stat-card .stepbtn { flex: 0 0 auto; width: 28px; height: 28px; line-height: 26px; padding: 0;
    text-align: center; border-radius: var(--el-radius); border: 1px solid #5a4a2c; background: #332b1c;
    color: #e0c878; font-size: 13px; cursor: pointer; }
  .stat-card .stepbtn:hover { border-color: #c0a050; background: #43381f; }
  .stat-card .stepbtn:disabled { opacity: .3; cursor: not-allowed; }
  /* 主属性卡(力量/智力/敏捷):带 +/- 加点按钮故偏高,单独压矮;缩小按钮与行距配合 */
  .stat-cards.main-attrs .stat-card { height: 48px !important; padding: 2px 4px; min-width: 0; }
  .stat-cards.main-attrs .stat-card .addrow { margin-top: 1px; gap: 4px; }
  .stat-cards.main-attrs .stat-card .b { margin-top: 1px; min-height: 12px; display: block; }  /* 装备加成始终占位，保持高度不塌陷 */
  .stat-cards.main-attrs .stat-card .v { font-size: 12px !important; }  /* 属性数值字体统一12px */
  /* +/- 按钮允许收缩(flex:0 1 auto)以 24px 为起点、18px 为可点地板;
     配合卡片 min-width:0 解开 grid 轨道 min-content 下限,窄屏可继续等比缩小 */
  .stat-cards.main-attrs .stat-card .stepbtn { flex: 0 1 auto; width: 14px; min-width: 14px; height: 14px; line-height: 12px; font-size: 12px; }
  /* 战斗属性卡(标签+数值+加成/提示三行):收紧行高 + 缩字号让内容变矮,卡高压到 44px(基础 66px 偏高) */
  .stat-body .stat-cards .stat-card { height: 48px; padding: 1px 4px; }
  .stat-body .stat-cards .stat-card .k,
  .stat-body .stat-cards .stat-card .v,
  .stat-body .stat-cards .stat-card .b,
  .stat-body .stat-cards .stat-card .hint { line-height: 1.05; }
  .stat-body .stat-cards .stat-card .k,
  .stat-body .stat-cards .stat-card .b,
  .stat-body .stat-cards .stat-card .hint { font-size: 12px; min-height: 12px; }
  .stat-body .stat-cards .stat-card .v { font-size: 12px; }
  /* sp-head:异常状态行 + 可分配点数(左侧并排)+ 确定/取消(绝对贴右)。留出右侧按钮宽度不被遮挡。 */
  .sp-head { position: relative; display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 6px; min-height: 24px; }
  .sp-head .stat-buffs { flex: 0 1 auto; min-width: 0; text-align: left; overflow: hidden; display: flex; align-items: center; }
  .sp-head .sp-actions { flex: 0 0 auto; display: flex; align-items: center; gap: 6px; }
  .sp-head .pts { font-size: 13px; color: #6a5d44; display: flex; align-items: center; }
  .sp-head .resetbtn { font-size: 13px; padding: 4px 18px; border-radius: var(--el-radius);
    border: 1px solid #5a4a2c; background: #2a2418; color: #cdbf9c; cursor: pointer; }
  .sp-head .resetbtn:hover { border-color: #c0a050; }
  .sp-head .resetbtn:disabled { opacity: .3; cursor: not-allowed; }
  /* ===== 背包↔快捷栏拖拽 ===== */
  /* 拖动时浏览器会以按下点为锚启动文本选区,把格子里的名字刷成蓝色;锚点格子设为不可选即根除
     (选区锚点在格子上,锚点不可选则拖动经过别处也不会产生选区,无需全局禁用、不误伤聊天框复制) */
  .cell2, .hotcell, .hcell { -webkit-user-select: none; user-select: none; }
  /* 跟手幽灵图标:挂 body、fixed、不挡命中检测(pointer-events:none) */
  .drag-ghost { position: fixed; transform: translate(-50%, -50%) scale(var(--ui-scale, 1)); z-index: 9999;
    pointer-events: none; opacity: .85; width: 44px; height: 44px;
    display: flex; align-items: center; justify-content: center;
    border: 1px solid #c0a050; border-radius: var(--el-radius); background: #2a2418; }
  .drag-ghost .ic { font-size: 24px; line-height: 1; }
  /* 落点高亮:金色描边 + 微亮底,套用于背包格/空格/快捷栏格(配置窗 .hotcell 与 HUD .hcell) */
  .cell2.drop-hover, .hotcell.drop-hover, .hcell.drop-hover { border-color: #f0c040 !important; background: #3a3018 !important; }
  /* 仓库拖拽:整个目标区域(仓库格区/背包格区)描金边高亮,提示"松手放这里" */
  .grid.bag.drop-zone, .grid.shopgrid.drop-zone { outline: 2px dashed #f0c040; outline-offset: -2px; border-radius: var(--el-radius); }

  /* ===== 乐观交互反馈样式 ===== */
  /* 按钮加载态:半透明 + 等待光标 + 禁止点击 */
  button.optimistic-loading {
    opacity: 0.6;
    cursor: wait;
    pointer-events: none;
  }

  /* 按压动画:模拟按钮被按下的效果 */
  @keyframes anim-press {
    0% { transform: scale(1); }
    50% { transform: scale(0.95); }
    100% { transform: scale(1); }
  }
  .anim-press {
    animation: anim-press 0.2s ease;
  }

  /* 旋转加载动画:在按钮后用 CSS 画一个旋转圆环(不用 emoji) */
  @keyframes anim-spin {
    to { transform: rotate(360deg); }
  }
  button.anim-spin::after {
    content: "";
    display: inline-block;
    width: 11px; height: 11px;
    margin-left: 4px;
    vertical-align: -1px;
    border: 2px solid currentColor;
    border-top-color: transparent;
    border-radius: 50%;
    animation: anim-spin 0.7s linear infinite;
  }

  /* 抖动动画:用于错误反馈 */
  @keyframes anim-shake {
    0%, 100% { transform: translateX(0); }
    25% { transform: translateX(-4px); }
    75% { transform: translateX(4px); }
  }
  .anim-shake {
    animation: anim-shake 0.4s ease;
  }

  /* 成功闪烁:绿色闪光表示操作成功 */
  @keyframes optimistic-success-flash {
    0%, 100% { background-color: inherit; }
    50% { background-color: #4ade80; }
  }
  .optimistic-success {
    animation: optimistic-success-flash 0.3s ease;
  }

  /* ===== 竖屏(手机)布局 =====
     朝向由 JS(applyUiScale)判定并写 body[data-orient]:单一真相源,此处只读不重判。
     竖屏放弃 transform:scale(会与"铺满高度"打架),改真流式:#game 撑满视口、纵向 flex 堆叠,
     #map flex:1 吸收纵向盈亏 → 无滚动、无横向溢出、字号回自然 px(不再被缩小)。
     只覆盖与横屏的差异,不复制规则;VIEW_W/H 由 syncViewport() 实测 #map,尺寸随之自洽。 */
  body[data-orient="portrait"] { overflow: hidden; }
  body[data-orient="portrait"] #game {
    width: 100vw; height: 100vh; height: 100dvh; height: var(--app-vh, 100dvh); transform: none;   /* 竖屏 --ui-scale 恒为 1,不缩放。高度三层兜底:JS 实测 --app-vh 最权威(iOS 100vh 会高估致地图过高,innerHeight 才是真实可见高);未设时新浏览器用 dvh,iOS<15.4(iPad mini 4)不认 dvh 再回落 100vh */
    display: flex; flex-direction: column; gap: 2px;
  }
  /* HUD 竖屏:拍平三层容器(.hud-main/.hud-right/#hudvitals),把深层的血条/快捷栏提为 #hud 直接子项,
     再用 grid-template-areas 精确排布(自文档化,利于多端复用):
       顶部按钮整行 → 头像跨两行居左·右侧 名字行/HP·MP·SP → 经验条整行 → 快捷栏整行。
     头像 area 跨 info+bars 两行,视觉上正好贴住"名字+HP+MP+SP"四行高度。 */
  body[data-orient="portrait"] #hud .hud-main,
  body[data-orient="portrait"] #hud .hud-right,
  body[data-orient="portrait"] #hud #hudvitals { display: contents; }
  body[data-orient="portrait"] #hud {
    display: grid; grid-template-columns: auto 1fr; gap: 2px 2px; align-items: center;
    grid-template-areas:
      "buttons buttons"
      "avatar  info"
      "avatar  bars"
      "avatar  exp";
  }
  body[data-orient="portrait"] #hud .tools { grid-area: buttons; justify-content: flex-start; gap: 4px; }
  /* 按钮:收窄左右内边距(桌面 12px 偏宽致换行)+ 等宽撑满整行;归零桌面的 #btn-status margin-left:auto(否则留白+挤换行) */
  body[data-orient="portrait"] #hud .tools button { padding: 5px 4px; flex: 1 1 0; min-width: 0; }
  body[data-orient="portrait"] #hud .tools #btn-status { margin-left: 0; }
  /* 头像:沿用基础元素/样式(边框/圆角/背景/等级徽标/性别符号),仅竖屏缩到 48px 并顶部对齐名字行(不再撑满两行)。
     配套字号/图标按 48/64=0.75 同步收:头像字形(emoji span 或 img)、等级徽标、性别符号,避免小框里溢出/被裁。 */
  body[data-orient="portrait"] #hud .hud-avatar { grid-area: avatar; align-self: start; width: 48px; height: 48px; font-size: 30px; }
  body[data-orient="portrait"] #hud .hud-avatar span.ic-lg { font-size: 36px; }
  body[data-orient="portrait"] #hud .hud-avatar img.ic-lg { width: 36px; height: 36px; }
  body[data-orient="portrait"] #hud .hud-avatar .lvbadge { font-size: 10px; padding: 0 2px; }
  body[data-orient="portrait"] #hud .hud-avatar .hud-sex { font-size: 10px; }
  body[data-orient="portrait"] #hud .tools-info { grid-area: info; }
  /* 竖屏:状态徽章(魔法盾/buff/伙伴)从顶栏 #map-status 搬到名字右侧 #hud-comps,
     复刻 #map-status 的尺寸/对齐(图标 16、文字 13、inline-block 消基线防秒数换行),否则退回基础 14px 且重现基线错位。 */
  body[data-orient="portrait"] #hud .hud-comps { gap: 4px; flex-wrap: wrap; }
  body[data-orient="portrait"] #hud .hud-comps .hud-comp,
  body[data-orient="portrait"] #hud .hud-comps .hud-shield { font-size: 16px; }
  body[data-orient="portrait"] #hud .hud-comps .hud-buffs { font-size: 13px; line-height: 1; letter-spacing: 1px; color: #e8dcc0;
    display: inline-flex; align-items: center; flex-wrap: wrap; }   /* 同 #map-status:flex 居中,倒计时数字与图标几何中心对齐 */
  body[data-orient="portrait"] #hud .hud-comps .ic-sm { width: 16px; height: 16px; font-size: 13px; display: inline-block; vertical-align: middle;
    border-radius: var(--el-radius); outline: 1px solid #5a4a2c; outline-offset: -1px; }
  /* 血条:HP / MP / SP 同一行三等分(基础是纵向堆叠,此处改横向平分) */
  body[data-orient="portrait"] #hud .hud-vitals { grid-area: bars; flex-direction: row; flex-wrap: wrap; column-gap: 2px; }
  /* 竖屏三等分空间紧张:隐藏条内 HP/MP/SP 标签(含尾随空格),只留数值 */
  body[data-orient="portrait"] #hud .hud-vitals .hbar .v .vlab { display: none; }
  /* HP/MP/SP 条:数值居中(横屏+竖屏一致);标签绝对定位钉左侧,脱离居中流不参与 */
  #hud .hud-vitals .hbar .v { justify-content: center; padding-left: 0; }
  #hud .hud-vitals .hbar .v .vlab { position: absolute; left: 2px; }
  /* 横屏:三条进度条等长(以最短为准)。共享 1fr(进度条)+auto(恢复装备后缀)两列网格,
     .hbar 拍平为网格项;auto 列取最宽后缀,1fr 进度条列随之对齐并被最宽后缀那行压到最短。 */
  body:not([data-orient="portrait"]) #hud .hud-vitals { display: grid; grid-template-columns: 1fr auto; column-gap: 1px; row-gap: 0; }
  body:not([data-orient="portrait"]) #hud .hud-vitals .hbar { display: contents; }
  #hud .hud-vitals .hbar-suf { display: inline-flex; align-items: center; }
  body[data-orient="portrait"] #hud .hud-vitals .hbar.hp,
  body[data-orient="portrait"] #hud .hud-vitals .hbar.mp,
  body[data-orient="portrait"] #hud .hud-vitals .hbar.sta { flex: 1 1 0; min-width: 0; }
  body[data-orient="portrait"] #hud #hudexp { grid-area: exp; }
  /* 竖屏快捷栏:已由 placeHotbar 搬到 #map 与 #panel 之间,作为 #game 纵向 flex 的独立一行。
     flex:0 0 auto 防被拉伸;左对齐整行,不再贴右。 */
  body[data-orient="portrait"] #hotbar { flex: 0 0 auto; justify-content: flex-start; }
  /* 竖屏空间不足:隐藏战斗内 10 格快捷栏(#btns 第一 .battlerow),改用 HUD 快捷栏(战斗中已由 syncHudHotbarBattle 保持可用、
     battleUseHotbar 已绑点击)。仅隐藏技能/物品格那一行;攻击/防御/逃跑(第二 .battlerow)保留,HUD 快捷栏不含这三项。 */
  body[data-orient="portrait"] #battlefield #btns .battlerow:first-child { display: none; }
  /* 竖屏战斗区更矮,横屏的敌我收拢量(#enemyRow 负 margin-bottom 上拉我方)会过头致卡片边框重叠。
     竖屏归零收拢,间距交还 space-between 均分即可;如需竖屏也略收拢,把这两个值改成小幅 4px/-4px。 */
  body[data-orient="portrait"] #battlefield #enemyRow { margin-top: 0; margin-bottom: 0; }
  /* 地图:去掉固定 720×420,吃满剩余竖向空间(唯一伸缩项,吸收盈亏防溢出) */
  body[data-orient="portrait"] #map { width: auto; height: auto; flex: 1 1 auto; min-height: 0; }
  /* 面板/底部:自然高度,不抢地图空间 */
  body[data-orient="portrait"] #panel { flex: 0 0 auto; padding: 2px 2px; }                 /* 竖屏收紧:内容离边框 2px(横屏 4px) */
  /* 竖屏地点交互栏(NPC/怪物两排)按钮压到 24px;行最小高与翻页按钮同步,保持两排对齐 */
  body[data-orient="portrait"] #panel .row { min-height: 24px; margin-bottom: 2px; gap: 2px; }  /* 竖屏收紧:行间距/横向按钮间距 2px(横屏 4px) */
  body[data-orient="portrait"] #panel .row button.action { height: 24px; }
  body[data-orient="portrait"] #panel .row .row-pager .pg-btn { height: 24px; }
  /* 图标随按钮缩到 22px(24px 按钮减上下 1px 边框=22px 内容盒,恰好不溢出);emoji 同步略缩 */
  body[data-orient="portrait"] #panel .row button.action > img.ic-sm { width: 22px; height: 22px; }
  body[data-orient="portrait"] #panel .row button.action > span.ic-sm { font-size: 15px; }
  /* NPC/怪物观察窗头像:竖屏框缩到 48×48、头像 36×36(普通版 64/48) */
  body[data-orient="portrait"] .obv-ava .obv-pic { width: 48px; height: 48px; }
  body[data-orient="portrait"] .obv-ava .obv-pic img.ic-lg { width: 36px; height: 36px; flex: 0 0 auto; }   /* flex:0 0 auto 防 48px 框内被类型文字挤压纵向收缩(否则 36→33 变形) */
  /* 右侧三行文字区高度跟随左侧头像框(竖屏 48,桌面基础 64):两侧等高。
     须同时在竖屏重申 :has() 特例放开高度——否则本规则(0,2,1)特异度高于基础 .obv-info:has(...)(0,2,0),
     会把邮件/评估/雇佣的第三行强制压回 48px 裁掉。竖屏 :has()(0,3,1)特异度更高,正确放开。 */
  body[data-orient="portrait"] .obv-info { height: 48px; gap: 2px; }   /* 收紧三行间距(桌面 4px) */
  /* 竖屏字号整体缩小:名字 16→14、HP 标签 12→11、描述 13→11 并收紧行高;描述两行高随之压到 28px(11×1.25×2) */
  body[data-orient="portrait"] .obv-name { font-size: 13px; }
  body[data-orient="portrait"] .obv-hplabel { font-size: 11px; }
  body[data-orient="portrait"] .obv-desc { font-size: 11px; line-height: 1.25; height: 28px; }
  /* 战斗力评估字号竖屏同步缩小:assessLineHTML 内联写死 13px,须 !important 覆盖内联,对齐描述 11px */
  body[data-orient="portrait"] .obv-assess-line > div { font-size: 11px !important; line-height: 1.25 !important; }
  /* 交互页欢迎语竖屏同步:字号/行高/两行高对齐 obv-desc,避免撑破缩小后的 48px 头部 */
  body[data-orient="portrait"] .obv-info .shop-pitch { font-size: 11px; line-height: 1.25; height: 28px; }
  body[data-orient="portrait"] .obv-info:has(.mail-form),
  body[data-orient="portrait"] .obv-info:has(.obv-assess-line),
  body[data-orient="portrait"] .obv-info:has(.merc-sec-title) { height: auto; }
  /* 底部:事件区(上) + 聊天区(下)纵向堆叠,替代横屏的左右并排 */
  /* 地图吃掉全部剩余弹性高度(唯一 grow 项);底部(系统消息+聊天)按内容收缩、各自封顶 3 行,永不抢地图空间。
     3 行 = 字号 13px × 行高 1.15 × 3 ≈ 45px;系统消息框另加上下内边距 8px。 */
  body[data-orient="portrait"] #map { flex: 1 1 0; min-height: 140px; }
  /* 竖屏三框边框重叠成单线:相邻两框各 1px 边,净距 -1px 才让两条边正好叠成一条。
     panel↔bottom:#game 全局 gap 2px 抵不掉,故 #bottom margin-top -3px(=-2 抵 gap -1 重叠)。
     events↔chat:#bottom gap 归 0,由 #chat margin-top -1px 造重叠。 */
  body[data-orient="portrait"] #bottom { flex: 0 0 auto; flex-direction: column; height: auto; gap: 0; margin-top: -3px; }
  body[data-orient="portrait"] #events { flex: 0 0 auto; height: 49px; }                    /* 系统消息:固定 3 行(行高1×13×3=39 + 内边距8 + 边框2),少则留空多则内部滚动 */
  body[data-orient="portrait"] #chat { flex: 0 0 auto; margin-top: -1px; }                  /* 随内容收缩(输入行固定);margin-top -1px 与上方系统信息框边框重叠成单线 */
  body[data-orient="portrait"] #chat-stream { flex: 0 0 auto; height: 43px; }               /* 聊天消息流:固定 3 行(行高1×13×3=39 + 内边距4,无边框);公告已并入消息流按普通消息滚动,超出内部滚动 */
  /* 竖屏行间距归 0(保住上面按 13px/行算的 3 行固定高度紧凑);横屏行间 2px */
  body[data-orient="portrait"] #events .evt,
  body[data-orient="portrait"] #chat-stream .cmsg { margin-bottom: 0; }
  /* 弹窗(系统菜单等走 #modal):桌面固定 560px 靠 transform:scale 缩小;竖屏 --ui-scale=1 不缩放,
     560px 会超出手机屏 → 溢出。竖屏改自适应宽度,比视口窄一点留边距(收口所有 #modal 弹窗) */
  body[data-orient="portrait"] #modal { width: auto; max-width: calc(100vw - 24px); }
  /* 状态窗:竖屏收紧所有卡片间距(左右列间距、卡片间距、主属性行↔战斗卡行间距) */
  body[data-orient="portrait"] .stat-body { gap: 1px; }
  body[data-orient="portrait"] .stat-cards { gap: 1px; margin-bottom: 2px; }
