/* Shared contract glyphs keep geometry fixed while each skin owns color/background. */
.profile-menu-glyph {
  width: 20px;
  height: 20px;
  display: block;
  flex: 0 0 auto;
  color: inherit;
}
.dt-um-icon .profile-menu-glyph {
  width: 16px;
  height: 16px;
}

/* ============================================================
   全网日夜模式 — 主题变量层
   ----------------------------------------------------------------
   设计原则 (与 i18n 模块同样的解耦哲学):
   - 默认 (无 data-theme 或 data-theme="dark") 走 dark, 与历史硬编码值
     完全等价, 所以本文件里仍有大量未替换的 #fff / rgba(255,255,255,*)
     在 dark 下结果不变, 不会破坏老外观。
   - data-theme="light" 仅覆盖语义变量, 子元素只要引用 var(--*) 就会
     自动反白; 业务面板内部的硬编码会按计划分批替换。
   - 品牌色 (TikTok 红 #FE2C55, 绿 #43A047, 黄 #FFB300) 跨主题不变,
     不进变量, 直接引用即可。
   - 阴影/遮罩在 light 下用更轻的 alpha, dark 下保留较强对比。
   控制属性: <html data-theme="light|dark"> + <html data-theme-mode="light|dark|auto">
   切换入口: 桌面 sidebar 底部 / 登录注册右上角 / 移动端 settings 三处.
   引擎模块: assets/js/theme.js (NGTHEME.setTheme).
   ============================================================ */

:root,
:root[data-theme="dark"] {
  /* surface — 用户口径: "夜间模式 = 背景黑色", 所以 --bg 直接给纯黑.
     2026-04-28 用户参考抖音 dark 截图, 把 surface-* 系列从带紫调
     (#1a1b2e / #232438) 改成中性近黑灰, 去掉品牌紫色, 更接近抖音
     #1c1c1e / #2c2c2e 视觉. */
  --bg:           #000000;
  --bg-elev:      #14151a;
  --surface:      #121214;
  --surface-2:    #1c1d22;
  --surface-3:    #2c2d33;
  /* 操作型 page 容器底色 (.login-panel / .profile-page / .vendor-profile-page
     / .follows-page / .profile-side-menu).
     2026-04-29 用户反馈"还是太黑了": 从 #16171c 提到 #1c1c1e, 跟抖音 dark
     卡片/page 色完全一致, 跟 body #000 之间有更明显的层次差.
     light: #ffffff (与 --bg 同纯白). */
  --panel-bg:     #1c1c1e;
  /* text */
  --text:         #fff;
  --text-soft:    rgba(255,255,255,.72);
  --text-mute:    rgba(255,255,255,.45);
  --text-faint:   rgba(255,255,255,.25);
  /* lines */
  --border:       rgba(255,255,255,.08);
  --border-soft:  rgba(255,255,255,.06);
  --divider:      rgba(255,255,255,.06);
  /* shadows */
  --shadow:       0 4px 14px rgba(0,0,0,.35);
  --shadow-lg:    0 12px 36px rgba(0,0,0,.55);
  /* overlay / mask */
  --mask:         rgba(0,0,0,.55);
  --backdrop:     rgba(0,0,0,.45);
  /* form */
  --input-bg:     rgba(255,255,255,.06);
  /* 2026-04-28 用户反馈: dark 下输入框边框 .08 几乎不可见, 提到 .14 让"用户名/密码"
     等 input 在黑底上有清晰可识别的灰色边框 */
  --input-border: rgba(255,255,255,.14);
  --chip-bg:      rgba(255,255,255,.06);
  /* layout regions */
  --topbar-bg:    rgba(0,0,0,.55);
  --sidebar-bg:   #121212;
  --sidebar-border: rgba(255,255,255,.06);
  --bottomnav-bg: rgba(0,0,0,.85);
  /* 2026-04-28 抖音风: 紫色渐变 → 中性近黑灰渐变 (去紫调) */
  --overlay-bg:   linear-gradient(170deg, #14151a 0%, #1c1d22 40%, #232428 100%);
  --picker-bg:    #1c1d22;
  /* 强调色 (跨主题不变, 这里也提供一份变量便于配色统一) */
  --accent:       #FE2C55;
  --accent-soft:  rgba(254,44,85,.18);
  --warn:         #FFB300;
  --success:      #43A047;
  --info:         #25F4EE;
  --danger:       #ef4444;
}

:root[data-theme="light"] {
  /* 用户口径: "日间模式 = 背景白色", 所以 --bg 直接给纯白 */
  --bg:           #ffffff;
  --bg-elev:      #ffffff;
  --surface:      #ffffff;
  --surface-2:    #f1f2f6;
  --surface-3:    #e7e8ee;
  --panel-bg:     #ffffff;  /* light 下 page 容器同纯白 (与 --bg 一致) */
  --text:         #161823;
  --text-soft:    rgba(22,24,35,.72);
  --text-mute:    rgba(22,24,35,.5);
  --text-faint:   rgba(22,24,35,.32);
  --border:       rgba(22,24,35,.1);
  --border-soft:  rgba(22,24,35,.06);
  --divider:      rgba(22,24,35,.06);
  --shadow:       0 4px 14px rgba(22,24,35,.06);
  --shadow-lg:    0 12px 36px rgba(22,24,35,.18);
  --mask:         rgba(22,24,35,.45);
  --backdrop:     rgba(22,24,35,.35);
  --input-bg:     rgba(22,24,35,.04);
  --input-border: rgba(22,24,35,.1);
  --chip-bg:      rgba(22,24,35,.04);
  --topbar-bg:    rgba(255,255,255,.92);
  --sidebar-bg:   #ffffff;
  --sidebar-border: rgba(22,24,35,.08);
  --bottomnav-bg: rgba(255,255,255,.92);
  /* 2026-04-29: 优惠中心 / 活动 / 签到 / 成就 / 钱包 / 提现等所有 ci-overlay
     hub 在 light 下直接纯白, 与 .login-panel / .vendor-profile-page /
     .profile-page (--panel-bg #fff) 风格统一; 之前用 fff→f6f7fb→f1f2f6
     渐变会让"优惠中心" 顶部看上去有一层灰底, 跟其他页面色调不一致. */
  --overlay-bg:   #ffffff;
  --picker-bg:    #ffffff;
  --accent-soft:  rgba(254,44,85,.12);
}

/* 2026-06-08 问题3: 首帧按 <html data-auth> 切换桌面侧栏登录/用户区, 配合
   index.html 头部内联脚本, 消除"刷新后几秒显示未登录"的闪烁. data-auth 由头部
   脚本(首帧)与 app.js updateDesktopAuth()(登录/登出/被踢) 持续同步, 故 !important
   始终反映真实登录态, 不会与 JS 切换冲突. */
html[data-auth="user"]  #dtSidebarLogin { display: none !important; }
html[data-auth="user"]  #dtSidebarUser  { display: flex !important; }
html[data-auth="guest"] #dtSidebarUser  { display: none !important; }

/* ===== Reset ===== */
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
/* 全站去加粗 (用户偏好 2026-04-28 / 2026-04-29 多次强调: "所有的字体都不要加粗").
   早先方案靠 sed + h1-h6 reset, 但仍有 100+ 处硬编码 .ach-card-title /
   .ach-summary-title / .dt-fav-name 等 font-weight: 600/700/800/900 漏网,
   用户看截图发现"成就"标题、"L9 / L10"等仍然偏粗, 反复反馈.
   现在改成: 全局 !important 一锤定音, 所有元素强制 400, 不再依赖各处自觉.
   想恢复局部加粗 (个别促销价格 / banner 标题), 用 .allow-bold 类显式覆盖. */
*, *::before, *::after { font-weight: 400 !important; }
.allow-bold,
.allow-bold *,
.allow-bold *::before,
.allow-bold *::after { font-weight: 600 !important; }
h1, h2, h3, h4, h5, h6,
b, strong, th, dt, address, optgroup, legend {
  font-weight: 400;
}
html, body {
  width: 100%; height: 100%;
  overflow: hidden;
  font-family: 'Noto Sans SC', -apple-system, BlinkMacSystemFont, sans-serif;
  background: var(--bg);
  color: var(--text);
  font-weight: 400;
  overscroll-behavior: none;
  -webkit-tap-highlight-color: transparent;
  user-select: none;
  /* 禁止 iOS Safari 双击放大：viewport 的 user-scalable=no 在 iOS 上被忽略，
     必须用 touch-action:manipulation 才能去掉双击缩放 + 300ms 点击延迟，
     同时保留正常的滚动/滑卡/点击响应。 */
  touch-action: manipulation;
  transition: background .25s ease, color .25s ease;
}

/* ===== Layout Switch ===== */
.desktop-layout { display: none; }
.mobile-layout  { display: block; }

@media (min-width: 768px) {
  body:not(.is-mobile-device) .desktop-layout { display: flex; width: 100%; height: 100%; }
  body:not(.is-mobile-device) .mobile-layout  { display: none; }
  body:not(.is-mobile-device) .top-bar { display: none; }
  body:not(.is-mobile-device) .game-info-overlay { display: none; }
  body:not(.is-mobile-device) #bottomNav { display: none; }

  /* 桌面端：action-bar 始终作为右侧 96px 固定 sidebar
     feed 模式 → 显示当前可见卡片的厂商/收藏/转发等，下方预览下一张
     game-playing 模式 → 同样显示，预览跳到下一张游戏 */
  body:not(.is-mobile-device) .action-bar {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
    position: fixed;
    top: 0; right: 0; bottom: 0;
    width: 96px;
    padding: 12px 0 16px;
    gap: 18px;
    /* 桌面侧栏化的 action-bar 在 light 主题下需要变成半透明浅色,
       否则黑条贴在白底上对比突兀. */
    background: var(--topbar-bg);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border-left: 1px solid var(--border-soft);
    z-index: 95;
    overflow-y: auto;
    scrollbar-width: none;
    transition: background .25s ease, border-color .25s ease;
  }
  body:not(.is-mobile-device) .action-bar::-webkit-scrollbar { display: none; }
  /* 全屏模式 (2026-04-22 改造): 不再硬隐藏桌面 actionBar, 由 JS 强制
     body.action-bar-collapsed 进入小拉手形态; 用户点拉手可展开 actionBar
     悬浮在游戏右侧, 关闭/退出全屏自动恢复进入前的展开/收起状态. */
  /* 桌面端右栏内的 action-item 文字稍小，避免占满 */
  body:not(.is-mobile-device) .action-bar .action-item .action-count { font-size: 11px; }
  /* 桌面端预览栏可见 + 紧跟转发按钮，与上面 action-item 保持 18px 间距 */
  body:not(.is-mobile-device) .next-game-preview {
    display: flex !important;
    margin-top: 0;
  }
  /* 桌面端隐藏移动端遗留的 game-info-overlay */
  body:not(.is-mobile-device) .game-info-overlay { display: none !important; }

  /* dt-main 让出右侧 96px 给 actionBar，避免 dt-game-card 被遮挡 */
  body:not(.is-mobile-device) .dt-main { padding-right: 96px; }
  /* 进入游戏 game-fullscreen 已自带 right:96px，不再叠加 padding */
  body:not(.is-mobile-device).game-playing .dt-main { padding-right: 0; }
  body:not(.is-mobile-device).game-playing.game-fs-landscape .dt-main { padding-right: 0; }
}

/* 桌面端 actionBar 顶部上下切换按钮组（移动端隐藏） */
.action-nav-group {
  display: none;
  flex-direction: column;
  gap: 6px;
  pointer-events: auto;
}
.action-nav-btn {
  width: 40px; height: 40px;
  border-radius: 50%;
  border: 1px solid rgba(255,255,255,.18);
  background: rgba(255,255,255,.08);
  color: #fff;
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: background .15s, transform .12s;
}
.action-nav-btn:hover { background: rgba(255,255,255,.18); }
.action-nav-btn:active { transform: scale(.92); background: rgba(255,255,255,.25); }
/* 搜索按钮：放在上下切换按钮组「上方」，仅用 margin-bottom 留 6px 间距
   做"切游戏 vs 跳任意游戏/厂商"的语义分组（之前用粉红描边过于醒目，
   会和 iframe 内画面强冲突，2026-04-23 改回与 .action-nav-btn 同色）。 */
.action-nav-btn.action-nav-search {
  margin-bottom: 6px;
}
@media (min-width: 768px) {
  /* 桌面端 actionBar 顶部上下切换按钮：feed 模式滚 dt-feed，game-playing 模式切游戏 */
  body:not(.is-mobile-device) .action-nav-group { display: flex; }
}

/* 2026-05-04 移动端: 当用户在「快捷设置」里把"滑动"关闭后, 在右侧 actionBar
   展示「↑ ↓」切换按钮, 补回 swipe 关闭后失去的上下切换游戏能力.
   - 与 actionBar 共用同一容器, 收起 actionBar (action-bar-collapsed) 时整条
     transform 走掉, 这组按钮自然跟随消失;
   - 移动端 search 已在顶部 .top-bar 提供, 这里隐藏 .action-nav-search 避免重复;
   - 只显示 prev / next 两枚, 与桌面端 #actionNavGroup 共用 _navByDir 路由.

   2026-05-04 v7 修正定位 (用户反馈"按钮不可见"):
   .action-bar 默认 flex-direction:column + justify-content:flex-end, 而
   .action-item.provider-avatar 自带 margin-top:auto, 这把 action-nav-group
   推到屏幕最顶端 (孤悬在游戏标题边, 用户以为不可见 / 不在 actionBar 里).
   修法: 在这种态下把 provider-avatar 的 margin-top:auto 直接归零, flex-end
   会自然把所有项一起 packed 到 actionBar 底部, action-nav-group 紧贴在
   provider-avatar 上方, "↑ ↓ → ≫ 头像 → ❤ 客服 ⭐ ↗" 一整列连续布局.
   `!important` 是因为 .action-item.provider-avatar 本身已有 (0,2,0) 特异度,
   再叠 4 个 body class 也只是 (0,5,0), 但同时 1715 行 `.action-item { ... }` 是
   (0,1,0), 那条会被 1719 行的 .action-item.provider-avatar 覆盖. 加 !important
   保险, 防止后续有人在更高特异度处再写 margin-top:auto 把这条又顶回去. */
body.is-mobile-device.swipe-disabled.game-playing .action-nav-group {
  display: flex;
  /* >> 收起按钮 .action-collapse-btn 是 position:absolute 锚在 provider-avatar
     上方 6px, 高 22px, 占 provider-avatar 之上 6~28px 这条区间; flex gap 默认 4px,
     action-nav-group 底部正好踩到这条区间, 跟 ↓ (actionNavNext) 视觉重叠.
     这里把 nav-group 底部上抬 32px (28px 占位 + 4px 间距) 给 >> 留出呼吸位. */
  margin-bottom: 32px;
}
body.is-mobile-device.swipe-disabled.game-playing .action-item.provider-avatar {
  margin-top: 0 !important;
}
body.is-mobile-device.swipe-disabled.game-playing .action-nav-search {
  display: none;
}
/* 移动端 actionBar 在游戏中 z-index 是 200, action-nav-btn 默认 rgba(255,255,255,.08)
   背景在浅色游戏画面 (老虎机/百家乐通常是花花绿绿) 上几乎看不见, 这里给它一个
   深色玻璃背景 + 1px 白描边, 不论游戏背景什么颜色都能识别. */
body.is-mobile-device.swipe-disabled.game-playing .action-nav-btn {
  background: rgba(0,0,0,.55) !important;
  border: 1px solid rgba(255,255,255,.6) !important;
  color: #fff !important;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  box-shadow: 0 4px 12px rgba(0,0,0,.35);
}
body.is-mobile-device.swipe-disabled.game-playing .action-nav-btn:active {
  background: rgba(254,44,85,.85) !important;
  border-color: #fff !important;
  transform: scale(.92);
}

/* ======================================================
   DESKTOP — TikTok Web Style (3-column)
   ====================================================== */

/* -- Left Sidebar -- */
/* 桌面端导航栏宽度变量，窗口缩小时折叠
   学 TikTok 桌面：宽屏 240px 完整展示，窄屏只剩图标 */
/* sidebar 宽度: 240px 默认放不下 "$ 10,069.36" 这类 5 位数余额 (2026-04-22
   用户反馈, 余额会被换行成 "$" + 数字两行). 加到 256px 给会员卡片留出
   完整显示空间, 同时 game-fullscreen left:var(--dt-sidebar-w) 自动跟随,
   iframe 仅相应窄 16px, 视觉无明显损失. */
:root {
  --dt-sidebar-w: 256px;
  /* 2026-05-15: 桌面端 sidebar 顶部 LOGO header 与右侧抽屉 panel-header 的
     统一高度. .dt-sidebar-logo / .finance-panel .panel-header 都 box-sizing:
     border-box + min-height = 这个值, 这样无论 LOGO svg 多高 / 标题字号多大,
     两块 header 的 border-bottom 都在同一 Y 像素, 不再错位. */
  --dt-header-h: 56px;
}
.dt-sidebar {
  width: var(--dt-sidebar-w, 240px);
  min-width: var(--dt-sidebar-w, 240px);
  height: 100vh; /* 旧浏览器兜底 */
  height: 100dvh; /* 折叠屏/移动工具栏: 用动态视口高度, 避免内容被截 */
  background: var(--sidebar-bg);
  border-right: 1px solid var(--sidebar-border);
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: #333 transparent;
  /* 默认状态：在 desktop-layout flex 流里正常占位 */
  position: relative;
  z-index: 1;
  transition: width .2s ease, min-width .2s ease, background .25s ease, border-color .25s ease;
}

/* === 进入游戏后，sidebar 单独提升到 game-fullscreen 之上 ===
   只在 game-playing 时把 .dt-sidebar 提到 fixed + 极高 z-index，
   不动 .dt-main 布局（dt-main 反正被 #dtFeed visibility:hidden 让位了，
   不会因 sidebar 离开 flex 而抖动）。这样 sidebar 上的"推荐/老虎机/..."
   按钮永远可点，不会被全屏游戏 iframe 覆盖。
   z-index 设到 9999 + !important 是为了确保任何情况下都不会被其他覆盖物盖住，
   pointer-events:auto !important 防止任何上游规则把 sidebar 关闭点击。 */
@media (min-width: 768px) {
  body:not(.is-mobile-device).game-playing .dt-sidebar {
    position: fixed !important;
    top: 0 !important;
    left: 0 !important;
    bottom: 0 !important;
    z-index: 9999 !important;
    pointer-events: auto !important;
  }
  body:not(.is-mobile-device).game-playing .dt-sidebar * {
    pointer-events: auto !important;
  }
  body:not(.is-mobile-device).game-playing .action-bar {
    z-index: 9999 !important;
    pointer-events: none !important;  /* 容器透明，子元素接管 */
  }
  body:not(.is-mobile-device).game-playing .action-bar > * {
    pointer-events: auto !important;
  }
}

/* ====== 折叠模式：窗口 ≤1024px 时左侧导航变为 64px 图标-only ====== */
@media (max-width: 1024px) {
  :root { --dt-sidebar-w: 64px; }
  /* overflow-x:hidden 是兜底: 即便下面任何子元素 (用户名/余额/厂商名等) 因
     特殊状态 没收到 display:none, 也只会在 sidebar 内部被裁掉,
     不会"穿出" 64px 边界, 流到屏幕左外 (用户反馈 2026-05-04 桌面游戏页右下角
     截图: WWW222 + 9,793.41 整段红字流到屏幕左侧 cut off). */
  .dt-sidebar { overflow-y: auto; overflow-x: hidden; }
  /* 隐藏所有文字 */
  .dt-sidebar.is-collapsed .dt-sidebar-brand,
  body.is-collapsed-nav .dt-sidebar-brand,
  .dt-sidebar-brand { display: none; }
  .dt-nav-item span,
  .dt-nav-section-title { display: none; }
  /* 图标居中 */
  .dt-sidebar-logo {
    justify-content: center;
    padding: 16px 0 14px;
    gap: 0;
  }
  .dt-nav-item {
    justify-content: center;
    padding: 12px 8px;
    gap: 0;
  }
  .dt-nav-item svg { width: 22px; height: 22px; }
  /* 关注厂商等以前折行的菜单 → 单图标 */
  .dt-nav-divider { margin: 6px 8px; }
  /* footer：登录/注册改图标按钮、avatar 居中、文字隐藏 */
  .dt-sidebar-footer { padding: 10px 6px; }
  .dt-sidebar-login {
    flex-direction: column;
    gap: 6px;
  }
  .dt-login-btn, .dt-register-btn {
    padding: 8px 4px;
    font-size: 11px;
    width: 100%;
  }
  /* .dt-sidebar-user 默认 flex-direction:row, 把 trigger + logout 横排.
     折叠态 64px 宽塞不下两个子元素, 强制改成纵向: 头像在上, logout 在下,
     与 .dt-sidebar-login 折叠态一致 (2026-05-04 修复: 之前只改 trigger 自己
     竖排, 没改父容器, 触发了 trigger 被挤窄 → .dt-user-info 文本溢出
     -> WWW222 / 余额 串到 sidebar 外的问题). */
  .dt-sidebar-user {
    flex-direction: column;
    align-items: center;
    padding: 8px 4px;
    gap: 6px;
    overflow: hidden;
  }
  .dt-user-trigger {
    width: 100%;
    min-width: 0;
    padding: 6px;
    flex-direction: column;
    gap: 2px;
    overflow: hidden;
  }
  /* !important 兜底: 防止下游或主题重写规则不小心把 display 又改回 flex/block,
     导致用户名+余额在 64px 侧栏里溢出 (用户反馈 2026-05-04). */
  .dt-user-info { display: none !important; }
  .dt-user-caret { display: none !important; }
  .dt-user-avatar { margin: 0 auto; }
  .dt-user-logout { display: flex; margin-top: 0; padding: 6px; }
  /* 折叠模式下下拉菜单要完全在 sidebar 之外，避免被 64px 截断 */
  .dt-user-menu {
    position: fixed !important;
    left: 70px !important;
    bottom: 12px !important;
    width: 240px !important;
  }
}

.dt-sidebar-logo {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 20px;
  border-bottom: 1px solid var(--divider);
  /* 2026-05-15: 让 LOGO header 与右侧抽屉 (.finance-panel .panel-header /
     #followedProvidersOverlay .panel-header) 桌面态共享同一变量高度,
     这样两块 header 的 border-bottom 在同一 Y 像素, 视觉上"贴得齐齐".
     2026-05-15(2): min-height 在 svg 与 h3 行高基线不同的情况下还是会差几像素;
     直接 height: 强制等高 + flex-align:center, content 自动垂直居中, 两边无差. */
  height: var(--dt-header-h, 56px);
  flex-shrink: 0;
}
/* dt-feed-overlay (游戏中浏览大厅) 下，LOGO 充当返回游戏的入口，
   给一点可点击反馈 */
body.dt-feed-overlay .dt-sidebar-logo {
  cursor: pointer;
  transition: opacity .15s ease, transform .12s ease;
}
body.dt-feed-overlay .dt-sidebar-logo:hover { opacity: .8; }
body.dt-feed-overlay .dt-sidebar-logo:active { transform: scale(.96); }
.dt-sidebar-brand {
  font-size: 20px;
  font-weight: 900;
  background: linear-gradient(135deg, #FE2C55, #25F4EE);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  letter-spacing: .5px;
}

.dt-nav {
  flex: 1;
  padding: 8px 10px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.dt-nav-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  border-radius: 8px;
  color: var(--text-soft);
  text-decoration: none;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: background .2s, color .2s;
}
.dt-nav-item:hover {
  background: var(--surface-2);
  color: var(--text);
}
.dt-nav-item.active {
  color: var(--accent);
  font-weight: 700;
}
/* disabled 仅做视觉灰提示（"当前缓存里该分类没卡片游戏"），但仍允许点击：
   updateDisabledTabs 依赖 state.allGames 缓存判断，缓存可能不全（首页只拉
   card_only=true 池子，cat 游戏数为 0 不代表后端真的没有），早期版本加
   pointer-events:none 后体育/捕鱼这类小品类用户根本点不动，sidebar handler
   完全不触发，active 也无法切换。点击后 switchCategory 会调 loadGames 拉
   该分类真实数据，空了也会有「该分类暂无游戏」兜底 UI，比"按钮死了"更友好。 */
.dt-nav-item.disabled {
  color: var(--text-mute);
}
.dt-nav-item svg {
  width: 22px;
  height: 22px;
  flex-shrink: 0;
}

.dt-nav-divider {
  height: 1px;
  background: var(--divider);
  margin: 8px 14px;
}

.dt-nav-section-title {
  font-size: 11px;
  font-weight: 600;
  color: var(--text-faint);
  padding: 4px 14px 2px;
  text-transform: uppercase;
  letter-spacing: 1px;
}

.dt-sidebar-footer {
  padding: 16px;
  border-top: 1px solid var(--divider);
}

.dt-sidebar-login {
  display: flex;
  gap: 8px;
}
.dt-login-btn, .dt-register-btn {
  flex: 1;
  padding: 9px 0;
  border: none;
  border-radius: 6px;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: opacity .2s;
}
.dt-login-btn {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text);
}
.dt-register-btn {
  background: var(--accent);
  color: #fff;
}
.dt-login-btn:hover, .dt-register-btn:hover { opacity: .85; }

/* Desktop sidebar user (logged in) */
.dt-sidebar-user {
  position: relative;
  display: flex; align-items: center; flex-wrap: wrap; gap: 4px;
  /* flex-wrap:wrap 必需: 币别切换器 (.dt-ccy-switcher) 用 flex-basis:100% 的"独占一行"技巧,
     只有父容器允许换行时才会落到第 2 行; 否则会与 trigger/logout 挤在同一行导致头像与退出按钮重叠。 */
  /* 把左右 padding 从 12 缩到 8, 给 trigger 内的会员名 / 余额多 8px 空间 */
  padding: 10px 8px;
}
.dt-user-trigger {
  flex: 1; min-width: 0;
  /* gap 从 10 缩到 8, 释放给 dt-user-info, 让长余额能完整一行展示 */
  display: flex; align-items: center; gap: 8px;
  padding: 6px 6px;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 10px;
  cursor: pointer;
  transition: background .15s, border-color .15s;
  text-align: left;
  color: inherit;
}
.dt-user-trigger:hover {
  background: rgba(255,255,255,.05);
  border-color: rgba(255,255,255,.06);
}
.dt-user-trigger.open {
  background: rgba(255,255,255,.07);
  border-color: rgba(255,255,255,.1);
}
.dt-user-avatar {
  width: 36px; height: 36px; border-radius: 50%;
  background: linear-gradient(135deg, #FE2C55, #25F4EE);
  display: flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: 14px; color: #fff;
  flex-shrink: 0;
}
.dt-user-info {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column; gap: 2px;
}
.dt-user-name {
  font-size: 13px; font-weight: 600; color: #fff;
  /* 2026-07-17: 强制单行省略。此前(2026-06-01)为让 14 位 guest 账号完整展示改成
     2 行 word-break:break-all 换行, 但 2026-07-16 币别切换器移到 trigger 同排后,
     MYR 等 3 字符币种胶囊更宽 → 挤窄会员名区 → break-all 把 "WWW222" 断成两行
     (用户反馈). 改回单行 + ellipsis, 与 .dt-user-balance 一致; 完整账号仍可靠
     JS 设置的 title 属性 hover 查看, 兼顾长 guest ID 与短名不断行两个诉求。 */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: 1.25;
  /* 用户名统一大写显示 (用户偏好 2026-04-28: "www111" → "WWW111"). */
  text-transform: uppercase;
  letter-spacing: .2px;
}
.dt-user-balance {
  /* 余额颜色: 用品牌红 #FE2C55, 与"立即充值/Hot 标签"等关键 CTA 一致,
     替代原青色 #25F4EE. light 模式下品牌红在白底也清晰可见 (#25F4EE
     在白底上对比度太低 — 用户反馈 2026-04-28). */
  font-size: 12px; color: #FE2C55; font-weight: 600;
  font-variant-numeric: tabular-nums;
  /* 强制单行显示: 默认会换行, 5 位以上余额会变成 "$" + 数字两行 (2026-04-22 修) */
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.dt-user-caret {
  flex-shrink: 0;
  color: rgba(255,255,255,.4);
  transition: transform .2s;
}
.dt-user-trigger.open .dt-user-caret {
  transform: rotate(180deg);
  color: rgba(255,255,255,.7);
}
.dt-user-logout {
  background: none; border: none; color: rgba(255,255,255,.5);
  cursor: pointer; padding: 6px; border-radius: 6px;
  transition: color .2s, background .2s;
  flex-shrink: 0;
}
.dt-user-logout:hover { color: #FE2C55; background: rgba(255,255,255,.05); }

/* 单会员多币别: 侧栏币别切换器 (chips) */
.dt-ccy-switcher {
  position: relative;
  /* 2026-07-16: 由"独占第二行"改为 trigger 行右侧 (原退出按钮位置)。
     flex:0 0 auto 让它只占内容宽度, trigger(flex:1) 自动让出空间; 父级 flex-wrap 仍在,
     万一空间不足则回退换行而非重叠。 */
  flex: 0 0 auto;
  display: flex; align-items: center; gap: 4px;
  margin: 0; padding: 0; border-top: none;
}
/* 桌面币别: 默认只显示【当前活跃币别】胶囊 (.dt-ccy-current);
   鼠标悬停 / 键盘聚焦时向上弹出【多币别窗口】(.dt-ccy-pop) 列出全部币别可切换。 */
.dt-ccy-current {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 4px 10px; border-radius: 999px;
  font-size: 11px; font-weight: 600; line-height: 1;
  color: #fff; background: rgba(254,44,85,.16);
  border: 1px solid #FE2C55; cursor: pointer;
  font-variant-numeric: tabular-nums;
  transition: background .15s, border-color .15s;
}
.dt-ccy-current:hover { background: rgba(254,44,85,.24); }
.dt-ccy-current .dt-ccy-bal { opacity: .8; font-weight: 500; }
.dt-ccy-current .dt-ccy-caret { color: rgba(255,255,255,.7); transition: transform .18s; }
.dt-ccy-switcher:hover .dt-ccy-current .dt-ccy-caret,
.dt-ccy-switcher:focus-within .dt-ccy-current .dt-ccy-caret { transform: rotate(180deg); }
.dt-ccy-pop {
  /* 右对齐: 选择器在侧栏右侧, 弹窗向左展开, 避免 min-width 撑出侧栏右边界 */
  position: absolute; right: 0; left: auto; bottom: calc(100% + 8px);
  display: none; flex-direction: column; gap: 4px;
  min-width: 168px; max-height: 240px; overflow-y: auto;
  padding: 8px; z-index: 60;
  background: #1f1f24; border: 1px solid rgba(255,255,255,.08);
  border-radius: 12px; box-shadow: 0 10px 34px rgba(0,0,0,.45);
}
/* 透明桥接: 补上 current 与 pop 间 8px 间隙的可悬停区, 防止移动鼠标时弹窗闪烁关闭 */
.dt-ccy-pop::after { content: ''; position: absolute; left: 0; right: 0; top: 100%; height: 8px; }
.dt-ccy-switcher:hover .dt-ccy-pop,
.dt-ccy-switcher:focus-within .dt-ccy-pop { display: flex; }
.dt-ccy-pop .dt-ccy-chip { width: 100%; justify-content: space-between; }
.dt-ccy-chip {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 8px; border-radius: 999px;
  font-size: 11px; font-weight: 600; line-height: 1;
  color: rgba(255,255,255,.72);
  background: rgba(255,255,255,.06);
  border: 1px solid transparent;
  cursor: pointer; transition: color .15s, background .15s, border-color .15s;
  font-variant-numeric: tabular-nums;
}
.dt-ccy-chip:hover { color: #fff; background: rgba(255,255,255,.1); }
.dt-ccy-chip.active {
  color: #fff; background: rgba(254,44,85,.16);
  border-color: #FE2C55; cursor: default;
}
.dt-ccy-chip .dt-ccy-bal { opacity: .7; font-weight: 500; }
/* 折叠(64px)侧栏下隐藏切换器, 避免溢出 (与 .dt-user-info 折叠断点一致) */
@media (max-width: 1024px) {
  .dt-ccy-switcher { display: none !important; }
}

/* 单会员多币别: 移动端个人中心币别切换器 (chips), 放余额卡片内、余额子项下方 */
.mb-ccy-switcher {
  display: flex; flex-wrap: wrap; gap: 6px;
  margin-top: 10px; padding-top: 10px;
  border-top: 1px solid rgba(255,255,255,.12);
}
.mb-ccy-chip {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 5px 12px; border-radius: 999px;
  font-size: 12px; font-weight: 600; line-height: 1;
  color: rgba(255,255,255,.85);
  background: rgba(255,255,255,.12);
  border: 1px solid transparent;
  cursor: pointer; transition: color .15s, background .15s, border-color .15s;
  font-variant-numeric: tabular-nums;
}
.mb-ccy-chip:active { background: rgba(255,255,255,.2); }
.mb-ccy-chip.active {
  color: #fff; background: rgba(254,44,85,.22);
  border-color: #FE2C55; cursor: default;
}
.mb-ccy-chip .dt-ccy-bal { opacity: .75; font-weight: 500; }

/* 2026-07-15 修复: light(浅色)主题下币别切换器 chips 原样式为白字 + 近透明白底,
   在浅色侧栏 / 余额卡上文字几乎不可见, active chip 只剩一团淡红块(rgba(254,44,85,.16))+红边
   —— 桌面看到"USD x 只剩模糊红胶囊、其余币种看不见"。这里按浅色主题重写为深字浅底,
   active 用品牌红字 + 淡红底 + 红边, 保证可读。dark 主题不受影响。 */
:root[data-theme="light"] .dt-ccy-switcher { border-top-color: rgba(0,0,0,.1); }
:root[data-theme="light"] .dt-ccy-chip {
  color: var(--text-soft, #555); background: rgba(0,0,0,.05);
}
:root[data-theme="light"] .dt-ccy-chip:hover {
  color: var(--text, #111); background: rgba(0,0,0,.08);
}
:root[data-theme="light"] .dt-ccy-chip.active {
  color: #FE2C55; background: rgba(254,44,85,.10); border-color: #FE2C55;
}
:root[data-theme="light"] .dt-ccy-chip.active .dt-ccy-bal { opacity: .85; }
:root[data-theme="light"] .dt-ccy-current {
  color: #FE2C55; background: rgba(254,44,85,.10); border-color: #FE2C55;
}
:root[data-theme="light"] .dt-ccy-current:hover { background: rgba(254,44,85,.16); }
:root[data-theme="light"] .dt-ccy-current .dt-ccy-caret { color: #FE2C55; }
:root[data-theme="light"] .dt-ccy-pop {
  background: #fff; border-color: rgba(0,0,0,.1);
  box-shadow: 0 10px 34px rgba(0,0,0,.18);
}
:root[data-theme="light"] .mb-ccy-switcher { border-top-color: rgba(0,0,0,.12); }
:root[data-theme="light"] .mb-ccy-chip {
  color: var(--text-soft, #555); background: rgba(0,0,0,.06);
}
:root[data-theme="light"] .mb-ccy-chip.active {
  color: #FE2C55; background: rgba(254,44,85,.12); border-color: #FE2C55;
}
:root[data-theme="light"] .mb-ccy-chip.active .dt-ccy-bal { opacity: .85; }

/* Desktop sidebar user popover menu */
.dt-user-menu {
  position: absolute;
  left: 12px;
  right: 12px;
  bottom: calc(100% + 6px);
  padding: 8px;
  /* 主题化: dark 下沿用原 #1f1f24 深色浮窗, light 下白底 (与 sidebar 协调,
     避免黑色 dropdown 突兀地盖在白底 sidebar 上, 用户反馈截图 2026-04-28). */
  background: var(--picker-bg);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: var(--shadow-lg);
  display: none;
  flex-direction: column;
  gap: 2px;
  z-index: 200;
  opacity: 0;
  transform: translateY(6px);
  transition: opacity .15s ease, transform .15s ease;
  /* 2026-05-06 dropdown 从 8 项扩到 15 项 (新增 修改密码/OTP/身份认证/银行卡/
     VIP/返水/推荐), 在矮屏 (≤768 高度) 上向上展开会越界. 给一个不超过视口
     的最大高度 + 内部滚动, 保证小屏也能滑到底部"退出登录". */
  max-height: calc(100vh - 120px); /* 旧浏览器兜底 */
  max-height: calc(100dvh - 120px);
  overflow-y: auto;
  overscroll-behavior: contain;
}
.dt-user-menu.open {
  display: flex;
  opacity: 1;
  transform: translateY(0);
}
.dt-user-menu-item {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 10px;
  background: transparent;
  border: none;
  border-radius: 8px;
  color: var(--text);
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  text-align: left;
  transition: background .15s;
  width: 100%;
}
.dt-user-menu-item:hover {
  background: var(--surface-2);
}
.dt-user-menu-item.dt-um-danger:hover {
  background: rgba(254,44,85,.1);
  color: #FE2C55;
}
.dt-um-icon {
  width: 28px; height: 28px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 8px;
  color: #fff;
  flex-shrink: 0;
}
/* 中性灰图标 (无品牌色, 用于 messages/follows/profile 等次要菜单项).
   - dark dropdown (背景 #1a1b2e) 下: 半透明白底 + 白图标 (与原 inline 一致)
   - light dropdown (背景 #fff) 下: 浅灰底 + 深灰图标, 与彩色品牌图标
     形成对比层次, 同时保证可见 (用户反馈 2026-04-28 截图: 原 inline 在
     light 下完全消失, "我的消息/关注厂商/个人资料" 三项看不到图标). */
.dt-um-icon-neutral {
  background: rgba(255,255,255,.08);
}
:root[data-theme="light"] .dt-um-icon-neutral {
  background: rgba(22,24,35,.06);
  color: rgba(22,24,35,.72);
}
.dt-um-text {
  flex: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.dt-um-badge {
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  background: #FE2C55;
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  border-radius: 9px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.dt-user-menu-divider {
  height: 1px;
  background: var(--divider);
  margin: 4px 4px;
}

/* ─────────────────────────────────────────────────────────────────────────────
   2026-05-15 桌面 user-menu 折叠分组 (资金中心 / 安全中心 / 我的福利).
   不再一字排开 15 项, 而是 group-header (点击切换) + group-body (子项).
   - group-body 默认 display:none, 仅当父 .dt-um-group.open 时才显示;
     避免一打开下拉就全平铺出来 (原本 nova39 截图就是这种"还原后"的状态).
   - group-body 用 position:fixed 作为 flyout 飞出面板, left/top 由 app.js
     的 positionGroupFlyout(group) 实时填充 (header.right + 8px 偏移,
     视口右侧不够会翻到左侧). 这样:
       a) 不挤占主菜单纵向空间, 不论 dropdown 多窄都能撑开子菜单;
       b) 触屏滚动 / 多 group 互斥时 JS 已有 _scheduleReposition 兜底.
   - .dt-um-caret 是 group-header 右侧的 chevron, .open 时旋转 90°
     视觉提示"已展开".
   - .dt-um-sub 子项样式与顶层一致, 只是 padding-left 略缩进, 在 flyout
     里看不到差异, 在 fallback (非 fixed flyout) 模式下也好辨认. */
.dt-um-group {
  position: relative;
}
.dt-um-group-header {
  /* 继承 .dt-user-menu-item 主体, 这里只是确保 caret 推到末尾 */
}
.dt-um-caret {
  margin-left: 4px;
  color: var(--text-mute);
  transition: transform .18s ease;
  flex-shrink: 0;
}
.dt-um-group.open .dt-um-caret {
  transform: rotate(90deg);
  color: var(--text, #fff);
}
.dt-um-group-body {
  display: none;
  flex-direction: column;
  gap: 2px;
  /* flyout: app.js 会在 open 时计算 left/top 填进来 (按 group-header rect),
     不指定 left/top 时 fixed 元素会停在视口左上角, 所以必须配合 JS 用.
     2026-05-23: app.js 现在 portal 把 body 挪到 document.body 下 (.dt-um-group-body-portal),
     绕过 .dt-user-menu 自己的 transform 把 fixed 强制变 absolute 的坑. */
  position: fixed;
  z-index: 250;
  min-width: 220px;
  max-width: 280px;
  max-height: calc(100vh - 40px); /* 旧浏览器兜底 */
  max-height: calc(100dvh - 40px);
  overflow-y: auto;
  padding: 8px;
  background: var(--picker-bg);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: var(--shadow-lg);
}
.dt-um-group.open .dt-um-group-body {
  display: flex;
}
/* portal 后挂在 document.body 下的 flyout: 此时父链没有 transform/overflow,
   position:fixed 真正按 viewport 定位 (JS 已填 left/top). 强制 display:flex 因为
   它已经脱离 .dt-um-group.open 的级联作用域. z-index 顶到 999 防止被任何
   .dt-overlay / modal-mask 之类盖住. */
.dt-um-group-body-portal {
  display: flex !important;
  z-index: 9999;
}
.dt-um-sub {
  /* 在 flyout 里所有子项都是顶级条目, 不缩进; 即便 fallback 不走 fixed,
     轻微缩进 8px 也能保留"我属于上面那个分组"的视觉线索. */
  padding-left: 18px;
}

/* -- Main Feed (Desktop) -- */
.dt-main {
  flex: 1;
  height: 100vh; /* 旧浏览器兜底 */
  height: 100dvh; /* 折叠屏/移动工具栏: 用动态视口高度, 避免内容被截 */
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* 2026-04-27 .dt-topbar 已从 index.html 移除:
     原因 = 仅放一个搜索框, 与 action-bar 的 #actionNavSearch 功能重复; 且打开游戏时
     被 .game-fullscreen 盖住, 用户实际只能用 #actionNavSearch. 见 index.html 中的
     注释. 移动端搜索走独立 .top-bar / #searchInput 不受影响. */

/* Desktop Feed — TikTok Web scroll */
.dt-feed {
  flex: 1;
  overflow-y: auto;
  scroll-snap-type: y mandatory;
  scrollbar-width: none;
}
.dt-feed::-webkit-scrollbar { display: none; }

/* Desktop 收藏 / 历史 网格视图 — 点击左侧"收藏" / "历史"后在 #dtFeed
   内渲染。覆盖默认 scroll-snap 行为，改成普通可滚动网格列表。
   注意 historygrid 必须和 favgrid 共用同一规则，否则历史视图会沿用
   .dt-feed 默认 scroll-snap-type: y mandatory，导致 dt-fav-header
   被强制对齐到下一个 snap 点（视觉上"返回按钮和标题都消失了"）。 */
.dt-feed[data-view="favgrid"],
.dt-feed[data-view="historygrid"] {
  scroll-snap-type: none;
  display: block;
}
/* 收藏 / 历史 grid 容器：以 sidebar 右边缘为基准向右排列，不再 max-width+居中。
   旧实现 max-width:1280px + margin:0 auto 在宽屏（>1280+sidebar）下会让 grid
   居中悬空，第一列卡片离 sidebar 很远，体验上"看起来 sidebar 跟卡片没关系"。
   改成 width:100% 后，grid 跟随 dt-main 满宽，padding 控制与 sidebar / 视口右
   边缘的安全间距，无论窗口怎么拉伸卡片都从左侧 sidebar 边贴齐。 */
.dt-fav-wrap {
  width: 100%;
  padding: 28px 32px 80px;
  color: #fff;
  box-sizing: border-box;
}
/* dt-fav-header 用 sticky 贴顶：滚动列表时返回按钮始终在顶部，
   避免滚下去之后找不到返回入口。背景给一层渐变 + blur，让卡片
   滚到下方不会"穿透"显得乱。 */
.dt-fav-header {
  display: flex; align-items: center;
  margin: -28px -32px 18px;
  padding: 18px 32px 14px;
  gap: 14px;
  position: sticky;
  top: 0;
  z-index: 5;
  background: linear-gradient(180deg, rgba(18,18,18,.96) 0%, rgba(18,18,18,.85) 80%, rgba(18,18,18,0) 100%);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
.dt-fav-back {
  display: inline-flex; align-items: center; gap: 4px;
  background: rgba(255,255,255,.06);
  border: 1px solid rgba(255,255,255,.1);
  color: rgba(255,255,255,.85);
  padding: 6px 12px 6px 8px;
  border-radius: 18px;
  font-size: 13px; font-weight: 600;
  cursor: pointer;
  flex-shrink: 0;
  transition: background .15s ease, color .15s ease, transform .1s ease;
}
.dt-fav-back:hover {
  background: rgba(254,44,85,.15);
  border-color: rgba(254,44,85,.4);
  color: #FE2C55;
}
.dt-fav-back:active { transform: scale(.96); }
.dt-fav-back svg { display: block; }
/* 2026-05-01 用户反馈"收藏和历史记录的文字需要纯色, 不要彩色不要渐变"
   → 去掉原 linear-gradient + background-clip:text 的彩色描边,
   改成站点主文字色 var(--text). dark 下显示为 #fff, light 下深色. */
.dt-fav-header h3 {
  font-size: 22px; font-weight: 800; letter-spacing: .5px;
  color: var(--text, #fff);
  margin: 0;
}
.dt-fav-count {
  font-size: 13px; color: rgba(255,255,255,.55);
  margin-left: auto;
}
.dt-fav-grid {
  display: grid;
  /* min(180px, 100%) 避免容器宽度不足 180px 时卡片溢出导致图标被截断；
     例如 sidebar 折叠 + 窗口拉到很窄时 dt-main 内可用宽度 < 180px，
     原来的 minmax(180px, 1fr) 会强行 180px 宽，卡片溢出到 sidebar 后面 */
  grid-template-columns: repeat(auto-fill, minmax(min(180px, 100%), 1fr));
  gap: 16px;
}
.dt-fav-loading,
.dt-fav-empty {
  grid-column: 1 / -1;
  text-align: center; padding: 80px 16px;
  font-size: 14px; color: rgba(255,255,255,.5);
}

/* 2026-04-29: feed 空状态 (没有符合条件的游戏 / 试试切换分类...).
   旧版用 inline rgba(255,255,255,.4) 在 light 白底直接看不见, 现在
   走 class + CSS 变量 (--text-soft / --text-mute), light/dark 两边
   都可读. */
.feed-empty {
  text-align: center;
  color: var(--text-soft, rgba(255,255,255,.5));
  padding: 80px 20px;
}
.feed-empty-title {
  font-size: 15px; line-height: 1.5;
  color: var(--text-soft, rgba(255,255,255,.55));
  margin-bottom: 8px;
}
.feed-empty-hint {
  font-size: 13px; line-height: 1.5;
  color: var(--text-mute, rgba(255,255,255,.4));
}
.feed-empty-mobile {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: 92%;
  padding: 0 12px;
}
.dt-fav-card {
  background: rgba(255,255,255,.04);
  border: 1px solid rgba(255,255,255,.06);
  border-radius: 12px;
  overflow: hidden;
  cursor: pointer;
  transition: transform .18s ease, border-color .18s ease, box-shadow .18s ease;
  display: flex; flex-direction: column;
}
.dt-fav-card:hover {
  transform: translateY(-3px);
  border-color: rgba(254,44,85,.55);
  box-shadow: 0 10px 24px rgba(0,0,0,.35), 0 0 0 1px rgba(254,44,85,.25) inset;
}
.dt-fav-cover {
  position: relative;
  width: 100%;
  aspect-ratio: 4/3;
  background: #1a1a22;
  overflow: hidden;
}
.dt-fav-cover img {
  width: 100%; height: 100%; object-fit: cover;
  transition: transform .25s ease;
}
.dt-fav-card:hover .dt-fav-cover img { transform: scale(1.04); }
.dt-fav-fallback {
  width: 100%; height: 100%;
  display: flex; align-items: center; justify-content: center;
  font-size: 36px; font-weight: 900; color: #fff;
}
.dt-fav-play {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  color: rgba(255,255,255,.95);
  background: rgba(0,0,0,.32);
  opacity: 0; transition: opacity .18s ease;
  pointer-events: none;
}
.dt-fav-card:hover .dt-fav-play { opacity: 1; }
.dt-fav-del {
  position: absolute; top: 8px; right: 8px;
  width: 28px; height: 28px; border-radius: 50%;
  border: none; padding: 0; cursor: pointer;
  background: rgba(0,0,0,.6); color: #fff;
  display: flex; align-items: center; justify-content: center;
  z-index: 3; opacity: 0;
  transition: opacity .15s, background .15s, transform .12s;
}
.dt-fav-card:hover .dt-fav-del { opacity: 1; }
.dt-fav-del:hover { background: #FE2C55; }
.dt-fav-del:active { transform: scale(.9); }
.dt-fav-meta {
  padding: 10px 12px 12px;
}
.dt-fav-name {
  font-size: 14px; font-weight: 700;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  color: #fff;
}
.dt-fav-provider {
  font-size: 12px; color: rgba(255,255,255,.5);
  margin-top: 3px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
@media (max-width: 1024px) {
  .dt-fav-wrap { padding: 20px 18px 80px; }
  .dt-fav-header { margin: -20px -18px 16px; padding: 14px 18px 12px; }
  .dt-fav-grid { grid-template-columns: repeat(auto-fill, minmax(min(150px, 100%), 1fr)); gap: 12px; }
  .dt-fav-name { font-size: 13px; }
}

/* Desktop Game Card — TikTok Web Style */
.dt-game-card {
  scroll-snap-align: start;
  height: 100vh; /* 旧浏览器兜底 */
  height: 100dvh; /* 折叠屏/移动工具栏: 用动态视口高度, 避免内容被截 */
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
}

.dt-card-inner {
  width: 420px;
  max-width: 90%;
  height: calc(100vh - 80px); /* 旧浏览器兜底 */
  height: calc(100dvh - 80px);
  max-height: 800px;
  border-radius: 12px;
  overflow: hidden;
  position: relative;
  cursor: pointer;
  /* 卡片永远浮在视频海报之上, 视频背景永远暗色, 内部文字必须白色.
     在根容器显式 color:#fff, 让 .dt-card-name / .dt-card-prov-name /
     .dt-card-rtp 等只设 font-size 没设 color 的子元素继承白色, 不再
     从 body { color: var(--text) } 漏下来 (light 下 var(--text) 是
     深色, 会让卡片名在暗色视频上不可见 - 用户反馈 2026-04-28). */
  color: #fff;
  box-shadow: 0 8px 40px rgba(0,0,0,.5);
}

.dt-card-bg {
  position: absolute;
  top: 0; left: 0;
  width: 100%; height: 100%;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}
.dt-card-bg-img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}
.dt-card-bg-video {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
  /* 默认透明：未 active 的卡片 video 没 src，让底层海报 <img> 露出来；
     仅 active 卡（.is-playing）才上黑底防止视频解码出第一帧前透出底图 */
  background: transparent;
  pointer-events: none;
  position: absolute;
  top: 0; left: 0;
  z-index: 1;
}
.dt-game-card.is-playing .dt-card-bg-video {
  background: #000;
}
/* 海报底图：永远位于 video 之下、其他叠层之上 */
.dt-card-bg-img-poster {
  position: absolute;
  top: 0; left: 0;
  z-index: 0;
}
/* 桌面卡片无 bg_url 时：image 模糊放大铺底，与中央 LOGO 拉开层次 */
.dt-card-bg-img-blur {
  width: 130%; height: 130%;
  margin-left: -15%; margin-top: -15%;
  filter: blur(28px) brightness(.55) saturate(1.3);
  -webkit-filter: blur(28px) brightness(.55) saturate(1.3);
}

.dt-card-gradient {
  position: absolute;
  top: 0; left: 0;
  width: 100%; height: 100%;
  background: linear-gradient(0deg, rgba(0,0,0,.8) 0%, rgba(0,0,0,.1) 35%, rgba(0,0,0,.0) 55%, rgba(0,0,0,.3) 100%);
  pointer-events: none;
}

.dt-card-center {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -55%);
  z-index: 2;
  text-align: center;
  width: 80%;
}

.dt-card-logo {
  width: 100px; height: 100px;
  border-radius: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 36px;
  font-weight: 900;
  color: #fff;
  margin: 0 auto 14px;
  box-shadow: 0 8px 30px rgba(0,0,0,.5);
  overflow: hidden;
  animation: iconFloat 3s ease-in-out infinite;
}
.dt-card-logo img {
  width: 100%; height: 100%;
  object-fit: contain;
  border-radius: 20px;
}
.dt-card-logo .dt-card-logo-fallback {
  width: 100%; height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 36px;
  font-weight: 900;
  color: #fff;
  border-radius: 20px;
}

@keyframes iconFloat {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-6px); }
}

.dt-card-name {
  font-size: 24px;
  font-weight: 900;
  text-shadow: 0 2px 12px rgba(0,0,0,.7);
  margin-bottom: 6px;
}

.dt-card-rtp {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: rgba(254,44,85,.85);
  padding: 4px 14px;
  border-radius: 20px;
  font-size: 13px;
  font-weight: 700;
  margin-top: 8px;
}

.dt-card-provider-tag {
  margin-top: 6px;
  font-size: 13px;
  color: rgba(255,255,255,.7);
}

/* LOGO 下方的醒目徽章行（HOT / NEW / LIVE / 维护中），
   与移动端 .game-card-badges 居中布局保持一致 */
.dt-card-badges {
  margin-top: 10px;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  justify-content: center;
}

/* Desktop card bottom info */
.dt-card-bottom {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  padding: 24px 20px;
  z-index: 3;
}

.dt-card-prov-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 6px;
}

.dt-card-prov-icon {
  width: 32px; height: 32px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: 900;
  color: #fff;
}

.dt-card-prov-name {
  font-size: 14px;
  font-weight: 700;
}

.dt-card-follow {
  background: #FE2C55;
  border: none;
  color: #fff;
  font-size: 11px;
  padding: 3px 10px;
  border-radius: 4px;
  cursor: pointer;
  margin-left: 6px;
}

.dt-card-desc {
  font-size: 13px;
  color: rgba(255,255,255,.85);
  line-height: 1.4;
  margin-bottom: 6px;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.dt-card-tag-row {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  margin-bottom: 10px;
}
.dt-card-tag-row span {
  font-size: 12px;
  color: rgba(255,255,255,.7);
}

.dt-card-play-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: linear-gradient(135deg, #FE2C55, #ff6b81);
  border: none;
  color: #fff;
  padding: 8px 22px;
  border-radius: 24px;
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
  box-shadow: 0 4px 16px rgba(254,44,85,.4);
  transition: transform .2s;
}
.dt-card-play-btn:hover { transform: scale(1.05); }

/* Desktop right action column - matching mobile */
.dt-card-actions {
  position: absolute;
  right: -60px;
  bottom: 100px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
  z-index: 4;
}

.dt-action-avatar {
  width: 44px; height: 44px;
  border-radius: 50%;
  overflow: hidden;
  cursor: pointer;
  position: relative;
  margin-bottom: 6px;
  border: 2px solid #fff;
  box-shadow: 0 2px 8px rgba(0,0,0,.3);
}
.dt-action-avatar img {
  width: 100%; height: 100%;
  object-fit: contain;
  background: #1a1a2e;
}
.dt-action-avatar-text {
  width: 100%; height: 100%;
  display: flex; align-items: center; justify-content: center;
  font-size: 14px; font-weight: 900; color: #fff;
}
/* TikTok 风格：+ 角标始终显示，未登录点击会拉起登录窗 */

/* 未登录时隐藏"收藏"入口（桌面侧栏 + 移动端下拉菜单） */
body:not(.is-logged-in) .dt-mode[data-mode="favorites"],
body:not(.is-logged-in) .cat-dd-item[data-mode="favorites"] { display: none !important; }

.dt-action-avatar .avatar-plus {
  position: absolute; bottom: -4px; left: 50%; transform: translateX(-50%);
  width: 20px; height: 20px; border-radius: 50%;
  background: #FE2C55; color: #fff; font-size: 14px; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
  border: 1.5px solid #fff;
  cursor: pointer;
  padding: 0;
  transition: background .25s ease, transform .2s cubic-bezier(.175,.885,.32,1.275);
  z-index: 2;
}
.dt-action-avatar .avatar-plus:hover { transform: translateX(-50%) scale(1.1); }
.dt-action-avatar .avatar-plus:active { transform: translateX(-50%) scale(.85); }
.dt-action-avatar .avatar-plus .ap-check { display: none; vertical-align: middle; }
.dt-action-avatar .avatar-plus.followed {
  background: rgba(0,0,0,.65);
  box-shadow: 0 2px 6px rgba(0,0,0,.45);
  animation: pfbPop .35s cubic-bezier(.175,.885,.32,1.275);
}
.dt-action-avatar .avatar-plus.followed .ap-text { display: none; }
.dt-action-avatar .avatar-plus.followed .ap-check { display: block; }

.dt-action {
  display: flex;
  flex-direction: column;
  align-items: center;
  cursor: pointer;
  transition: transform .15s;
}
.dt-action:hover { transform: scale(1.15); }
.dt-action svg {
  width: 32px; height: 32px;
  filter: drop-shadow(0 2px 6px rgba(0,0,0,.5));
}
.dt-action span {
  font-size: 12px;
  margin-top: 3px;
  color: rgba(255,255,255,.9);
  text-shadow: 0 1px 4px rgba(0,0,0,.6);
}
.dt-action.liked svg { fill: #FE2C55; stroke: #FE2C55; }

/* ======================================================
   MOBILE — TikTok App Style (existing)
   ====================================================== */

/* -- Top Bar (sits outside mobileLayout for z-index isolation) -- */
.top-bar {
  position: fixed; top: 0; left: 0; right: 0;
  z-index: 300;
  display: flex; align-items: center;
  height: 54px;
  padding: 0 8px;
  /* feed 模式下半透明叠在视频上, 主题反白时也要兼顾;
     light 下 video/卡片可能是浅色, 用 var(--topbar-bg) 而非渐变 */
  background: linear-gradient(180deg, rgba(0,0,0,.7) 0%, transparent 100%);
  transition: background .3s;
  pointer-events: auto;
}
:root[data-theme="light"] .top-bar {
  background: linear-gradient(180deg, rgba(255,255,255,.85) 0%, rgba(255,255,255,0) 100%);
}
body.game-playing .top-bar {
  background: var(--surface);
}
.top-bar-right {
  flex-shrink: 0;
  width: 36px;
  display: flex; align-items: center; justify-content: center;
}
.search-btn {
  background: none; border: none; color: var(--text); cursor: pointer; opacity: .85;
}

/* 顶部 tab 条：左侧「推荐 ▾」cat-dropdown 把 mode 收成紧凑下拉，右侧 cat tab
   平铺并支持手指横向滑动浏览。配合 #mobileCatTabs { display:contents }
   把 cat-tab 提升为 .category-tabs 的直接 flex child，避免 inline span 子节点
   被默认 inline-block 自动换行（截图中"老虎机/真人/体育"换行的根因）。
   主 feed 区还有左右滑手势 → 直接切到上/下个 cat tab（参照 TikTok）。 */
.category-tabs {
  flex: 1;
  display: flex; align-items: center; gap: 0;
  overflow-x: auto; overflow-y: visible;
  padding: 0 2px;
  scrollbar-width: none;
  -ms-overflow-style: none;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: contain;
  scroll-behavior: smooth;
  flex-wrap: nowrap;
  min-width: 0;
}
.category-tabs::-webkit-scrollbar { display: none; }

/* 关键：让 #mobileCatTabs 自身从布局树消失，里面的 .cat-tab 直接成为
   #categoryTabs 的 flex child，自动 flex-shrink:0 + nowrap，不再换行。 */
#mobileCatTabs { display: contents; }

/* 2026-04-27 第 6 轮: dropdown 提升到 .top-bar 直接子节点 (HTML 已改),
   不再受 .category-tabs overflow-x:auto 滚动影响, 不需要 sticky 也永远可见.
   保留 flex-shrink:0 防止 cat-tabs 内容多时把 dropdown 压扁.
   登录/未登录态行为完全一致 (无 body class 限制), 仅下拉菜单内"收藏"项
   通过 body:not(.is-logged-in) .cat-dd-item[data-mode="favorites"] 隐藏. */
.cat-dropdown {
  position: relative;
  flex-shrink: 0;
  z-index: 2;
}
.cat-dropdown-btn {
  background: none; border: none;
  /* 第 5 轮: 之前 .5 太暗, 切到 cat 后用户以为下拉消失了, 提到 .85.
     active (mode 选中态) 提到 #fff 仍清晰区分. */
  color: rgba(255,255,255,.85);
  font-size: 15px; font-weight: 500;
  padding: 8px 8px; cursor: pointer;
  position: relative;
  transition: color .25s;
  white-space: nowrap;
  display: flex; align-items: center; gap: 2px;
}
.cat-dropdown-btn.active {
  color: #fff; font-weight: 700; font-size: 15px;
}
.cat-dropdown-btn.active::after {
  content: '';
  position: absolute;
  bottom: 2px; left: 50%; transform: translateX(-50%);
  width: 20px; height: 2.5px;
  background: #FE2C55; border-radius: 2px;
}
.cat-dd-arrow {
  transition: transform .25s;
}
.cat-dropdown.open .cat-dd-arrow {
  transform: rotate(180deg);
}
/* 关键：用 position: fixed 而不是 absolute，避免被父级 .category-tabs 的
   overflow-x:auto 自动裁切（CSS 规范 overflow-x/y 不能一裁一不裁，会强制
   都变 auto）。打开时由 JS 把按钮 bounding rect 写入 inline style top/left。
   z-index 必须高于 .top-bar (300) 让 dropdown 不被搜索栏 / 卡片遮挡。 */
.cat-dropdown-menu {
  display: none;
  position: fixed;
  top: 0; left: 0;
  background: rgba(30,30,30,.96);
  border-radius: 10px;
  padding: 6px 0;
  min-width: 90px;
  box-shadow: 0 8px 24px rgba(0,0,0,.5);
  z-index: 999;
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
}
.cat-dropdown.open .cat-dropdown-menu {
  display: block;
  animation: catDdFadeIn .2s ease;
}
@keyframes catDdFadeIn {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: translateY(0); }
}
.cat-dd-item {
  display: flex; align-items: center; gap: 9px; width: 100%;
  background: none; border: none;
  color: rgba(255,255,255,.7);
  font-size: 14px; font-weight: 500;
  padding: 8px 18px 8px 14px;
  text-align: left;
  cursor: pointer;
  transition: color .2s, background .2s;
  white-space: nowrap;
}
.cat-dd-item:hover { background: rgba(255,255,255,.08); }
.cat-dd-item.active {
  color: #FE2C55; font-weight: 700;
}
/* 下拉项图标 + trigger 图标: 与左侧栏 .dt-mode 导航 SVG 统一 */
.cat-dd-ico, .cat-dd-trigger-ico {
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.cat-dd-ico { width: 18px; height: 18px; }
.cat-dd-ico svg { width: 18px; height: 18px; }
.cat-dd-trigger-ico { width: 16px; height: 16px; margin-right: 1px; }
.cat-dd-trigger-ico svg { width: 16px; height: 16px; }

.cat-tab-divider {
  display: none;
}

/* 2026-04-27 第 4 轮: 平铺改回下拉 (cat-dropdown / .cat-dd-item 在前面已定义).
   原 .mode-tabs-inline / .mode-tab / .mode-tabs-divider 已废弃, JS/HTML 都不再引用. */

/* Category tabs */
.cat-tab {
  flex-shrink: 0;
  background: none; border: none;
  color: rgba(255,255,255,.5);
  font-size: 15px; font-weight: 500;
  padding: 8px 8px; cursor: pointer;
  position: relative;
  transition: color .25s;
  white-space: nowrap;
}
.cat-tab.active {
  color: #fff; font-weight: 700; font-size: 15px;
}
.cat-tab.active::after {
  content: '';
  position: absolute;
  bottom: 2px; left: 50%; transform: translateX(-50%);
  width: 20px; height: 2.5px;
  background: #FE2C55; border-radius: 2px;
}
.cat-tab.disabled {
  color: rgba(255,255,255,.25);
}
.cat-tab.disabled::after { display: none; }
/* 用户反馈：滑到「彩票/其他」（无游戏 → .disabled）时也要看到切换动作。
   active 时强制恢复白字 + 红条，让 disabled tab 也能高亮显示当前选中状态。 */
.cat-tab.disabled.active { color: #fff; }
.cat-tab.disabled.active::after { display: block; }

/* -- Feed Container -- */
.feed-container {
  position: fixed;
  top: 54px; left: 0; right: 0;
  bottom: calc(60px + env(safe-area-inset-bottom, 0px));
  overflow: hidden; z-index: 1;
  overscroll-behavior: none;
  touch-action: none;
}

.game-card {
  position: absolute; top: 0; left: 0;
  width: 100%; height: 100%;
  display: flex; align-items: center; justify-content: center;
  will-change: transform, opacity;
  overflow: hidden;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  transform: translate3d(0,0,0);
  /* 同 .dt-card-inner: 移动端游戏卡永远是视频背景, 强制白字, 与主题切换解耦. */
  color: #fff;
}
.game-card.animating {
  transition: transform .38s cubic-bezier(.22,.68,0,1.0), opacity .38s ease-out;
}

.game-card-bg {
  position: absolute; top: 0; left: 0;
  width: 100%; height: 100%;
  background-size: cover; background-position: center;
}
.game-card-img {
  width: 100%; height: 100%;
  object-fit: cover;
  position: absolute; top: 0; left: 0;
}
.game-card-video-bg {
  width: 100%; height: 100%;
  object-fit: cover;
  position: absolute; top: 0; left: 0;
  /* 关键：默认透明而非纯黑，否则相邻卡片 video 没 src 时
     会盖住底层海报图，上下滑动只看到一片黑（丢 TikTok 预览效果）。
     仅当卡片成为 active（is-playing）时再上不透明黑底，避免视频
     还没解码出第一帧时透出底图导致闪烁。 */
  background: transparent;
  pointer-events: none;
}
.game-card.is-playing .game-card-video-bg {
  background: #000;
}
/* 海报底图：和视频同位，永远可见，被 video 盖住时也不影响显示 */
.game-card-video-poster {
  z-index: 0;
}
.game-card-video-bg {
  z-index: 1;
}
/* 没有 bg_url 时：把 image 模糊放大铺满，避免和中央 LOGO 视觉重复 */
.game-card-bg-blur {
  overflow: hidden;
}
.game-card-img-blur {
  width: 130%; height: 130%;
  left: -15%; top: -15%;
  filter: blur(28px) brightness(.55) saturate(1.3);
  -webkit-filter: blur(28px) brightness(.55) saturate(1.3);
  transform: scale(1.05);
}
.game-card-gradient {
  position: absolute; top: 0; left: 0;
  width: 100%; height: 100%;
  background: linear-gradient(0deg, rgba(0,0,0,.85) 0%, rgba(0,0,0,.15) 25%, rgba(0,0,0,.05) 50%, rgba(0,0,0,.15) 75%, rgba(0,0,0,.65) 100%);
  z-index: 1;
}

.game-card-content {
  position: relative; z-index: 2;
  text-align: center; padding: 20px;
}

.game-card-logo {
  width: 120px; height: 120px;
  border-radius: 24px;
  display: flex; align-items: center; justify-content: center;
  font-size: 42px; font-weight: 900; color: #fff;
  box-shadow: 0 8px 40px rgba(0,0,0,.5);
  margin: 0 auto 16px;
  animation: iconFloat 3s ease-in-out infinite;
  overflow: hidden;
}
.game-card-logo img {
  width: 100%; height: 100%; object-fit: cover;
}
.game-card-logo-fallback {
  width: 100%; height: 100%;
  display: flex; align-items: center; justify-content: center;
  font-size: 42px; font-weight: 900; color: #fff;
  border-radius: 24px;
}
/* 中央 LOGO 可点击：增加触控反馈与高亮，提示这里能点 */
.game-card-logo-clickable {
  cursor: pointer;
  -webkit-tap-highlight-color: rgba(255,255,255,.18);
  transition: transform .12s ease-out, box-shadow .2s;
  position: relative;
}
.game-card-logo-clickable:active {
  transform: scale(.94);
  box-shadow: 0 4px 18px rgba(0,0,0,.55);
}
.game-card-logo-clickable:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 4px;
}
.game-card-name {
  font-size: 28px; font-weight: 900;
  text-shadow: 0 2px 12px rgba(0,0,0,.6);
  margin-bottom: 8px;
}
.game-card-rtp {
  display: inline-flex; align-items: center; gap: 6px;
  background: rgba(254,44,85,.9);
  padding: 4px 14px; border-radius: 20px;
  font-size: 13px; font-weight: 700;
}
.game-card-provider {
  margin-top: 10px; font-size: 13px;
  color: rgba(255,255,255,.7); font-weight: 500;
}
.card-badge {
  display: inline-block;
  padding: 2px 10px; border-radius: 10px;
  font-size: 10px; font-weight: 700; color: #fff;
  margin-top: 8px; margin-right: 4px;
}
.badge-hot {
  background: linear-gradient(135deg, #FE2C55, #ef4444);
  box-shadow: 0 2px 8px rgba(254,44,85,.45);
  letter-spacing: 1px;
  animation: hotPulse 2s infinite;
}
@keyframes hotPulse {
  0%, 100% { box-shadow: 0 2px 8px rgba(254,44,85,.45); }
  50%      { box-shadow: 0 2px 14px rgba(254,44,85,.7); }
}
.badge-new {
  background: linear-gradient(135deg, #22c55e, #16a34a);
  box-shadow: 0 2px 8px rgba(34,197,94,.4);
}
.badge-maintenance {
  background: linear-gradient(135deg, #f59e0b, #d97706);
  box-shadow: 0 2px 8px rgba(245,158,11,.4);
}
.badge-live {
  background: linear-gradient(135deg, #ef4444, #b91c1c);
  box-shadow: 0 2px 8px rgba(239,68,68,.5);
  letter-spacing: 1.5px;
  position: relative; padding-left: 18px;
}
.badge-live::before {
  content: '';
  position: absolute; left: 8px; top: 50%; transform: translateY(-50%);
  width: 6px; height: 6px; border-radius: 50%;
  background: #fff; box-shadow: 0 0 6px #fff;
  animation: liveBlink 1.4s infinite;
}
@keyframes liveBlink {
  0%, 100% { opacity: 1; }
  50%      { opacity: .35; }
}
.game-card-badges {
  margin-top: 10px;
  display: flex; flex-wrap: wrap;
  gap: 6px; justify-content: center;
}
.game-card.is-table-game .game-card-logo {
  border-radius: 28px;
  background: linear-gradient(180deg, rgba(255,255,255,.18), rgba(255,255,255,.06));
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}

.dt-card-maintenance {
  position: absolute; top: 0; left: 0; right: 0; bottom: 0;
  z-index: 5; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 8px;
  background: rgba(0,0,0,.55);
  font-size: 14px; font-weight: 700; color: #FFA500;
  pointer-events: none;
}

/* -- Action Bar (Douyin Style) -- */
.action-bar {
  position: fixed;
  right: 4px;
  top: 0;
  bottom: calc(60px + env(safe-area-inset-bottom, 0px));
  z-index: 50;
  display: flex; flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  gap: 4px;
  pointer-events: none;
  padding-bottom: 10px;
}
.action-bar > * { pointer-events: auto; }
body.game-playing .action-bar {
  z-index: 200;
}

/* === actionBar 收起 / 展开 === */
/* 收起：整条 actionBar 右移到屏幕外；同时显示 #actionBarHandle 小拉手。
   桌面端 actionBar 是 width:96px 的 fixed sidebar，translateX(100%) 同样能滑出。
   游戏 iframe 在底层不受影响，用户可以看到完整游戏 UI。 */
.action-bar {
  transition: transform .25s ease, opacity .2s;
}
body.action-bar-collapsed .action-bar {
  transform: translateX(110%);
  opacity: 0;
  pointer-events: none !important;
}
body.action-bar-collapsed .action-bar > * {
  pointer-events: none !important;
}

/* 2026-05-04 actionBar 收起时同步把它原本占的 96px 槽位让出去, 否则 actionBar
   translateX(110%) 滑出后, .dt-main padding-right (line 192) 与 .game-fullscreen
   right (line 5734) 仍然给它预留 96px, 在浅色主题下表现为右侧白边 (用户反馈
   截图: 桌面游戏页右边出现一条白条). 仅桌面生效, 移动端 .dt-main /
   .game-fullscreen 都另有规则不受影响.

   .game-fullscreen[data-fs="1"] 的全屏态自带 right:0!important, 这里 .25s
   过渡动画与 .action-bar transform 同步, 视觉上 actionBar 滑出 + 游戏区扩边
   一并完成, 无突兀跳变. */
@media (min-width: 768px) {
  body:not(.is-mobile-device) .dt-main,
  body:not(.is-mobile-device) .game-fullscreen {
    transition: padding-right .25s ease, right .25s ease;
  }
  body:not(.is-mobile-device).action-bar-collapsed .dt-main {
    padding-right: 0;
  }
  body:not(.is-mobile-device).action-bar-collapsed .game-fullscreen {
    right: 0;
  }
}

/* actionCollapseBtn 收起按钮：作为 .action-bar 内 flex 流的第一个子元素，
   自然紧贴 actionBar 顶端（移动端 flex-end 堆栈最顶 / 桌面 flex-start 第一项），
   随 actionBar transform 一起滑出，无需 fixed 定位。
   - 用 nova39 / TikTok 主色 #FE2C55 + 脉动光晕 → 醒目
   - 仅在游戏中（body.game-playing）显示，首页 feed 不需要 */
/* providerBadge 作为 collapse-btn 的锚点容器 */
.action-bar .provider-avatar { position: relative; }

/* collapse-btn —— 小拉手 ›› 折叠样式（与右边缘 #actionBarHandle 风格呼应，
   方向相反：>> 表示「把这条 actionBar 向右收起」）。
   锚定在 providerBadge 紧邻上方 6px。 */
.action-collapse-btn {
  display: flex;
  position: absolute;
  bottom: calc(100% + 6px);
  left: 50%;
  transform: translateX(-50%);
  width: 44px; height: 22px;
  border-radius: 11px;
  background: rgba(0,0,0,.55);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid rgba(255,255,255,.18);
  color: #fff;
  cursor: pointer;
  align-items: center; justify-content: center;
  padding: 0;
  flex-shrink: 0;
  -webkit-tap-highlight-color: transparent;
  transition: background .15s;
  pointer-events: auto !important;
  z-index: 3;
}
.action-collapse-btn:hover { background: rgba(0,0,0,.75); }
.action-collapse-btn:active { transform: translateX(-50%) scale(.92); background: rgba(0,0,0,.85); }
.action-collapse-btn svg { display: block; pointer-events: none; }
/* 全屏模式下 actionBar 仍然可访问 (2026-04-22 改造), 不再无条件隐藏 collapse-btn —
   用户在全屏中点小拉手展开后, 这个按钮要显示出来才能再次收起 actionBar. */
/* 移动端首页 feed（无遮挡问题）隐藏；进入游戏后显示 */
body.is-mobile-device:not(.game-playing) .action-collapse-btn { display: none; }
/* 个人中心 / 优惠中心 / 签到中心 也允许收起 actionBar (用户报告: 进入这些页面
   后看不到 ›› 收起按钮, 只能切回主页才出现). profile-active / ci-overlay-open
   两个 body class 由 JS 在打开/关闭页面时切换. */
body.is-mobile-device.profile-active   .action-collapse-btn,
body.is-mobile-device.ci-overlay-open  .action-collapse-btn { display: flex; }

/* 扩大 ›› 收起按钮 / 小拉手 的有效点击区域 (用户报告: 偶尔点不到, 局部
   区域不响应). 视觉尺寸不变, 通过透明 ::before 把 hit-area 上下左右各扩
   12px / 8px, 拇指点在边缘也能稳触发. svg 已 pointer-events:none, click
   依然冒泡到按钮本身, 不影响原有 click handler. */
.action-collapse-btn { position: absolute; }
.action-collapse-btn::before {
  content: '';
  position: absolute;
  inset: -14px;
  border-radius: inherit;
}
.action-bar-handle::before {
  content: '';
  position: absolute;
  inset: -12px -8px -12px -16px; /* 左侧多扩 16px, 拇指容易从屏幕外滑入命中 */
  border-radius: inherit;
}
/* actionBar 收起后右边缘的小拉手 */
.action-bar-handle {
  display: none;
  position: fixed;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 22px; height: 56px;
  border-radius: 12px 0 0 12px;
  background: rgba(0,0,0,.55);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid rgba(255,255,255,.18);
  border-right: none;
  color: #fff;
  cursor: pointer;
  align-items: center;
  justify-content: center;
  z-index: 9998;
  -webkit-tap-highlight-color: transparent;
  padding: 0;
  transition: background .15s, transform .12s;
}
.action-bar-handle:hover { background: rgba(0,0,0,.7); }
.action-bar-handle:active { transform: translateY(-50%) scale(.9); }
body.action-bar-collapsed .action-bar-handle { display: flex; }

/* ---- 个人中心 / 优惠中心 / 签到中心 打开时的 actionBar 层级 ----
   背景: 这些「全屏覆盖页」分别为 .profile-page (z-index:150) 与
   .ci-overlay (z-index:1000), 默认会盖住 actionBar (z-index:50). 现象:
   小拉手 (z-index:9998) 仍可见, 但点开后 actionBar 整列被覆盖页吞没,
   用户看不到右侧导航. 解法: 临时把 actionBar / 小拉手提到这些覆盖页之上.
   注意: 早期版本用 :not(.game-playing) 想严格保护游戏页, 但用户常常
   是「游戏中→点底部 nav 进个人中心 / 活动中心」的场景, body.game-playing
   仍在, 移动端 .action-bar 此时 z-index:200 仍 < .ci-overlay z-index:1000,
   actionBar 仍被盖. 所以这里取消 :not(.game-playing) 限制 ——
   覆盖页本身就是「全屏遮住游戏」的语义, 提升 actionBar 不会影响游戏可见性
   (游戏 iframe 在底层被覆盖页全屏盖住, 用户看不到也碰不到).
   全屏 body.game-fs-landscape 与 ci-overlay-open 互斥: 进 ci-overlay 入口
   都不在全屏游戏的 UI 路径上, 所以 100000+ 全屏层级不会被这些规则误覆盖. */
body.profile-active   .action-bar         { z-index: 160; }
body.profile-active   .action-bar-handle  { z-index: 161; }
body.ci-overlay-open  .action-bar         { z-index: 1010; }
body.ci-overlay-open  .action-bar-handle  { z-index: 1011; }

/* 2026-05-01 用户反馈: "商城, 优惠活动页面 个人主页, 不显示右侧菜单".
   覆盖页 (个人中心 / 活动中心-PromoHub 含商城/优惠/活动/成就/签到) 与
   主 feed 不同, 用户视线已离开游戏卡, 右侧 actionBar (点赞/客服/收藏/转发)
   都是绑当前游戏的, 上下文断了点了也跳错位; 此前虽用 site-logo + visibility
   占位"半隐"过, 但用户依旧觉得是冗余视觉噪点. 直接 display:none 移除,
   桌面 + 移动均生效. action-bar-handle 同步隐藏避免拉手孤儿出现.
   注: 不影响 .action-bar 在主 feed / 厂商页 / 游戏页 的正常显示. */
body.profile-active   .action-bar,
body.profile-active   .action-bar-handle,
body.ci-overlay-open  .action-bar,
body.ci-overlay-open  .action-bar-handle { display: none !important; }

/* 覆盖页 (个人中心 / 活动中心 / 签到中心) 中, actionBar 上「厂商 LOGO」与
   「下一个游戏预览」两块依赖「当前游戏」上下文 —— 此时已离开游戏视图,
   头像 / 预览停留在最后一次的厂商或游戏, 点了也跳错位.
   策略: 布局完全保留 (尺寸 / 间距 / 边框 / 阴影都不动), 内容做替换:
     - 头像位: 隐藏 #providerAvatar, 显示 .actionbar-site-logo (网站 LOGO)
     - follow + 角标: visibility:hidden 保留位置不影响布局
     - nextGamePreview: 默认 inline style="display:none", 这里用
       display:flex !important 强制显出占位, 内部 visibility:hidden 隐形,
       并禁用 cursor / 默认动画, 避免 hover 出指示
   actionCollapseBtn 是 providerBadge 的实体子元素, 不受影响. */
.actionbar-site-logo {
  display: none;
  filter: drop-shadow(0 1px 3px rgba(0,0,0,.45));
}
body.profile-active   #providerBadge .avatar-placeholder,
body.profile-active   #providerBadge .avatar-ring img,
body.ci-overlay-open  #providerBadge .avatar-placeholder,
body.ci-overlay-open  #providerBadge .avatar-ring img {
  display: none !important;
}
body.profile-active   #providerBadge .actionbar-site-logo,
body.ci-overlay-open  #providerBadge .actionbar-site-logo {
  display: block;
}
body.profile-active   #providerFollowBadge,
body.ci-overlay-open  #providerFollowBadge {
  visibility: hidden;
}
body.profile-active   #nextGamePreview,
body.ci-overlay-open  #nextGamePreview {
  display: flex !important;
  visibility: hidden;
  cursor: default !important;
  animation: none !important;
  pointer-events: none !important;
}
.action-item {
  display: flex; flex-direction: column;
  align-items: center; cursor: pointer;
}
.action-item.provider-avatar {
  margin-top: auto;
  margin-bottom: 6px;
}
.action-btn-wrap {
  width: 40px; height: 40px;
  display: flex; align-items: center; justify-content: center;
  transition: transform .2s cubic-bezier(.175,.885,.32,1.275);
}
.action-item:active .action-btn-wrap { transform: scale(.8); }
.action-icon {
  width: 30px; height: 30px;
  fill: #fff; stroke: none;
  filter: drop-shadow(0 2px 8px rgba(0,0,0,.5));
  transition: fill .2s, transform .2s;
}
.action-count {
  font-size: 11px; margin-top: -3px; font-weight: 700;
  text-shadow: 0 1px 4px rgba(0,0,0,.7);
  color: #fff;
  letter-spacing: .3px;
}
#btnLiveChat, #btnFavorite, #btnShare { margin-top: -4px; }
.action-item.liked .action-icon {
  fill: #FE2C55; stroke: none;
  animation: tikLike .5s cubic-bezier(.175,.885,.32,1.275);
}
#btnFavorite.liked .action-icon {
  fill: #FACD00; stroke: none;
}
@keyframes tikLike {
  0% { transform: scale(1); }
  30% { transform: scale(1.4); }
  60% { transform: scale(.9); }
  100% { transform: scale(1); }
}

.provider-avatar { position: relative; }
.avatar-ring {
  width: 48px; height: 48px; border-radius: 50%;
  border: 2.5px solid #fff; overflow: hidden;
  background: linear-gradient(135deg, #FE2C55, #25F4EE);
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 3px 14px rgba(0,0,0,.4);
}
.avatar-placeholder {
  width: 42px; height: 42px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 16px; font-weight: 900; color: #fff;
}

/* TikTok 风格：厂商头像下方的关注 +/✓ 角标 */
.provider-follow-badge {
  position: absolute;
  bottom: -8px;
  left: 50%;
  transform: translateX(-50%);
  width: 20px; height: 20px;
  border-radius: 50%;
  background: #FE2C55;
  color: #fff;
  border: none;
  padding: 0;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  box-shadow: 0 2px 8px rgba(254,44,85,.45);
  transition: background .25s ease, transform .25s cubic-bezier(.175,.885,.32,1.275), box-shadow .25s ease;
  z-index: 2;
}
.provider-follow-badge:active { transform: translateX(-50%) scale(.85); }
.provider-follow-badge .pfb-plus {
  font-size: 18px; font-weight: 900; line-height: 1;
  margin-top: -1px;
}
.provider-follow-badge .pfb-check { display: none; }
.provider-follow-badge.followed {
  background: rgba(0,0,0,.55);
  box-shadow: 0 2px 6px rgba(0,0,0,.35);
  animation: pfbPop .35s cubic-bezier(.175,.885,.32,1.275);
}
.provider-follow-badge.followed .pfb-plus { display: none; }
.provider-follow-badge.followed .pfb-check { display: block; }
@keyframes pfbPop {
  0%   { transform: translateX(-50%) scale(.6); }
  60%  { transform: translateX(-50%) scale(1.25); }
  100% { transform: translateX(-50%) scale(1); }
}

/* -- Next Game Preview -- */
.next-game-preview {
  display: flex; flex-direction: column; align-items: center;
  margin-top: 2px;
  cursor: pointer;
  animation: nextFadeIn .4s ease;
}
.next-game-arrow {
  font-size: 10px; color: rgba(255,255,255,.6);
  animation: nextBounce 1.5s ease infinite;
  margin-bottom: 2px;
}
@keyframes nextBounce {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(3px); }
}
@keyframes nextFadeIn {
  from { opacity: 0; transform: translateY(-8px); }
  to { opacity: 1; transform: translateY(0); }
}
.next-game-thumb {
  width: 48px; height: 48px; border-radius: 10px;
  overflow: hidden;
  border: 2px solid rgba(255,255,255,.35);
  box-shadow: 0 3px 12px rgba(0,0,0,.5);
  background: #222;
  display: flex; align-items: center; justify-content: center;
}
.next-game-thumb img {
  width: 100%; height: 100%; object-fit: cover;
  display: block;
}
.next-game-thumb .next-fallback {
  width: 100%; height: 100%;
  display: flex; align-items: center; justify-content: center;
  font-size: 18px; font-weight: 900; color: #fff;
}
.next-game-name {
  font-size: 9px; color: rgba(255,255,255,.7);
  max-width: 54px; text-align: center;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  margin-top: 2px;
  text-shadow: 0 1px 3px rgba(0,0,0,.6);
}

.spinning-disc { margin-top: 4px; }
.disc-outer {
  width: 44px; height: 44px; border-radius: 50%;
  background: conic-gradient(from 0deg, #333, #666, #333);
  display: flex; align-items: center; justify-content: center;
  animation: discSpin 4s linear infinite;
}
.disc-inner {
  width: 20px; height: 20px; border-radius: 50%;
  background: #1a1a1a; border: 2px solid #444;
}
@keyframes discSpin { to { transform: rotate(360deg); } }

/* -- Game Info Overlay -- */
.game-info-overlay {
  position: fixed;
  bottom: calc(60px + env(safe-area-inset-bottom, 0px) + 12px);
  left: 12px; right: 80px;
  z-index: 50; padding-bottom: 8px;
  /* "主题豁免": 这层浮在 .feed-container 视频卡之上, 永远是暗色视觉环境.
     子元素 .game-provider-name span / .game-title 只设 font-size + text-shadow
     没设 color, 不显式兜底就会从 body { color: var(--text) } 漏下来; light
     下变成深字 + 深阴影 = "@AFBGAMING / 超级火焰" 模糊不可见 (用户反馈
     2026-04-28 截图). 在容器层强制白字, 与 .dt-card-inner / .game-card
     同样的"永远 color:#fff"设计原则. */
  color: #fff;
}
body.game-playing .game-info-overlay { display: none; }
body.game-playing .double-tap-heart { display: none; }
/* 游戏 iframe 打开时，把卡片 feed 容器从渲染树里摘掉。
   1. 避免浏览器继续 layout/paint 几十张卡片（已隐藏但还在 DOM）。
   2. 配合 JS 里的 pauseAllCardVideos() 卸载 src，硬件解码器能彻底
      让出来给游戏 iframe 用，避免老虎机/直播桌台画面卡顿掉帧。
   关闭 iframe 后 closeGameIframe() 会移除 game-playing 类并 syncCardVideos() 恢复。 */
body.game-playing #feedContainer,
body.game-playing #dtFeed { visibility: hidden; }

/* === 桌面端「游戏中浏览大厅」模式 ===
   游戏中点左侧 sidebar 任一导航 → body 加 .dt-feed-overlay。
   dt-feed 浮在 game-fullscreen (z=90) 之上，让用户看到 buildFeed/收藏页
   重建出的新内容；游戏 iframe 仍在底层运行，不打断 session。
   返回入口：sidebar LOGO 点击，或收藏/历史 grid 内自带的「返回」按钮。 */
@media (min-width: 768px) {
  body:not(.is-mobile-device).game-playing.dt-feed-overlay #dtFeed {
    visibility: visible !important;
  }
  body:not(.is-mobile-device).game-playing.dt-feed-overlay .dt-main {
    position: relative;
    z-index: 100;
    /* 2026-05-02 用户反馈 dark 模式下右侧主区是 #000 纯黑跟 sidebar #121212
       灰黑撕裂. 改用 var(--sidebar-bg) 让主区与 sidebar 同色, 视觉拼接更自然.
       dark: #121212, light: #ffffff, 双主题自动跟随. */
    background: var(--sidebar-bg);
    /* 关键：游戏中 sidebar 被提到 position:fixed，已经离开 flex 流，
       dt-main 会贴到 viewport 左边 → 第一列卡片被 fixed sidebar 盖住。
       这里手动补一个等同 sidebar 宽度的 padding-left，把内容推到 sidebar 之外。
       --dt-sidebar-w 在 ≤1024px 折叠时会自动变成 64px，与 sidebar 同步缩。 */
    padding-left: var(--dt-sidebar-w, 240px);
    /* 让 dt-main 占满 sidebar 与 actionBar 之间整块，避免透出底层 iframe */
    padding-right: 96px;
  }
}
.game-provider-name {
  display: flex; align-items: center; gap: 10px; margin-bottom: 8px;
}
.game-provider-name span {
  font-size: 16px; font-weight: 700;
  text-shadow: 0 1px 6px rgba(0,0,0,.5);
}
.follow-btn {
  background: rgba(254,44,85,.9);
  border: none; color: #fff;
  font-size: 12px; font-weight: 600;
  padding: 3px 10px; border-radius: 4px; cursor: pointer;
}
.follow-btn.followed { background: rgba(255,255,255,.15); }
.game-title {
  font-size: 15px; font-weight: 500;
  margin-bottom: 6px;
  text-shadow: 0 1px 6px rgba(0,0,0,.5);
}
.game-desc { margin-bottom: 6px; overflow: hidden; }
.desc-text {
  font-size: 13px; color: rgba(255,255,255,.85);
  line-height: 1.4;
  display: -webkit-box; -webkit-line-clamp: 2;
  -webkit-box-orient: vertical; overflow: hidden;
}
.game-tags { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 8px; }
.tag { font-size: 12px; color: rgba(255,255,255,.75); font-weight: 500; }

.play-now-btn {
  display: inline-flex; align-items: center; gap: 6px;
  background: linear-gradient(135deg, #FE2C55, #ff6b81);
  border: none; color: #fff;
  font-size: 14px; font-weight: 700;
  padding: 8px 20px; border-radius: 24px; cursor: pointer;
  box-shadow: 0 4px 20px rgba(254,44,85,.5);
  transition: transform .2s;
}
.play-now-btn:hover { transform: scale(1.05); }

/* -- Bottom Nav -- */
.bottom-nav {
  position: fixed;
  bottom: 0; left: 0; right: 0;
  z-index: 200;
  height: calc(60px + env(safe-area-inset-bottom, 0px));
  background: var(--bottomnav-bg);
  border-top: 1px solid var(--border);
  display: flex; align-items: flex-start; justify-content: space-around;
  padding-top: 6px;
  padding-bottom: env(safe-area-inset-bottom, 0px);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  pointer-events: auto;
  transition: background .25s ease, border-color .25s ease;
}
.nav-item {
  display: flex; flex-direction: column;
  align-items: center; gap: 1px;
  background: none; border: none;
  color: var(--text-mute);
  font-size: 10px; cursor: pointer;
  transition: color .2s; padding: 4px 10px;
  position: relative;
}
.nav-balance {
  font-size: 9px; font-weight: 700;
  color: #FACD00;
  text-shadow: 0 1px 2px rgba(0,0,0,.5);
  margin-top: -1px;
}
.nav-item.active { color: var(--text); }
.nav-icon { width: 24px; height: 24px; }

.nav-sub-label {
  font-size: 8px;
  color: rgba(254,44,85,.8);
  margin-top: -1px;
  font-weight: 500;
  white-space: nowrap;
  max-width: 50px;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 首页按钮：去掉文字标签，整圆按钮在底部栏内上下居中 */
.nav-home-btn {
  /* 让此按钮自身在 .bottom-nav 的 align-items:flex-start 之外居中 */
  align-self: center;
  justify-content: center;
  /* 抵消 .bottom-nav 的 padding-top:6px 偏移，做到真正的视觉居中 */
  margin-top: -6px;
}
.nav-home-btn .home-btn-wrap {
  width: 44px; height: 44px; border-radius: 50%;
  background: linear-gradient(135deg, #25F4EE, #FE2C55);
  display: flex; align-items: center; justify-content: center;
  position: relative; overflow: hidden;
  box-shadow: 0 2px 10px rgba(0,0,0,.35);
}
.nav-home-btn .home-btn-wrap::before {
  content: ''; position: absolute;
  top: 2px; left: 2px; right: 2px; bottom: 2px;
  background: #161823; border-radius: 50%;
}
.nav-home-btn .home-btn-wrap .home-logo-svg {
  position: relative; z-index: 1;
}
.nav-home-btn .home-btn-wrap .home-currency-icon {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 1;
  font-size: 20px;
  line-height: 1;
  color: #FACD00;
  font-weight: 700;
  white-space: nowrap;
  /* 深度检查：使用 absolute + translate 居中，并移除多余偏移 (2026-06-16) */
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
}
/* 隐藏首页按钮下方的文字（"首页" 或 余额），无论登录与否 */
.nav-home-btn .nav-home-label {
  display: none !important;
}

/* ===== Shared: Panels & Overlays ===== */
.overlay {
  position: fixed; top: 0; left: 0; right: 0; bottom: 0;
  z-index: 200;
  background: rgba(0,0,0,.5);
  opacity: 0; pointer-events: none;
  transition: opacity .3s;
}
.overlay.active { opacity: 1; pointer-events: auto; z-index: 310; }

/* 搜索 overlay 例外：桌面 game-playing 时由 #actionNavSearch 触发（不关 iframe），
   而 body.game-fs-landscape/portrait 会把 .action-bar 提到 z:100000(!important)
   覆盖默认 overlay z:310，造成 actionBar 上的搜索/上下按钮反过来盖住搜索面板
   右侧（"热门搜索"标签和搜索输入框被遮挡，2026-04-21 用户反馈截图）。
   这里把 #searchOverlay.active 拔到 100050，确保 overlay 永远在 actionBar 之上，
   且不影响其它 overlay (provider/comment/share/login/finance) 的层级。 */
#searchOverlay.active { z-index: 100050; }

/* 登录面板必须永远在所有 overlay 之上 — 默认 .overlay.active 只有 z:310,
   而 .ci-overlay (PromoHub / 商城 / 签到) 是 z:1000, 在商城点"我的订单"等
   入口触发 promptLogin() 时, 登录面板会被 ci-overlay 整个盖住 → 用户看到
   一闪 toast 但登录窗不可见 (2026-05-01 用户反馈: "点击之后看不到登录窗口").
   100060 比 #searchOverlay (100050) 还高一点, 确保用户在搜索页内被踢出
   401 时, 登录面板也压在搜索之上. */
#loginOverlay.active,
#registerOverlay.active { z-index: 100060; }

.provider-panel, .comment-panel {
  position: absolute;
  bottom: 0; left: 0; right: 0;
  border-radius: 16px 16px 0 0;
  display: flex; flex-direction: column;
  transform: translateY(100%);
  transition: transform .35s cubic-bezier(.32,.72,.37,1.12);
}
/* .provider-panel: 跟随主题 (2026-04-28 用户要求"选择厂商页面也要日夜模式") */
.provider-panel {
  /* 2026-05-25: 70vh → 82vh — 用户反馈"选择厂商时显示不完整, 厂商显示
     不完整". 根因有两个叠加:
       (a) 70vh 在中等手机 (vh≈700) 上仅 ~490px, 抽屉里要装 panel-header
           (~52) + provider-search (~58) + provider-grid; 厂商 13+ 家分 6
           组时, grid 实高 600+px, 一开始就被剪掉一半, 第一屏看上去厂商
           列表"莫名缺最后几家";
       (b) 即便用户滑到底, 最后一行卡片还会被 iPhone home indicator /
           Android 手势条覆盖 → 见下面 .provider-grid 的 padding-bottom 修.
     82vh 留 18vh 给上方背景 (用户仍能感知是底部抽屉而非全屏),
     再配合 max-height: calc(...) 在小屏上额外让出 safe-area-inset-top
     防止 panel-header 撞到状态栏. */
  max-height: calc(82vh - env(safe-area-inset-top, 0px));
  background: var(--surface);
  color: var(--text);
}
/* .comment-panel: TikTok 风格固定深色 (评论 UI 内部子元素全是白字 + 半透明
   白分隔线 + 渐变头像, 改用主题成本高且影响 UX, 暂保留主题豁免) */
.comment-panel {
  height: 65vh;
  background: #1e1e1e;
  color: #fff;
}
.overlay.active .provider-panel,
.overlay.active .comment-panel { transform: translateY(0); }

.panel-header {
  display: flex; align-items: center;
  justify-content: space-between;
  padding: 16px 20px;
  border-bottom: 1px solid var(--border);
}
.panel-header h3 { font-size: 16px; font-weight: 700; color: var(--text); }

/* ======================================================
   Unified overlay header buttons (2026-05-06)
   ------------------------------------------------------
   把 .panel-close (× 关闭, 17 处底部抽屉用) 和 .ci-back / .ci-close
   (← 返回 / × 关闭, 全屏 ci-overlay 用: 优惠活动 / 签到 / 签到历史)
   的视觉统一: 都是 36×36 圆形 hover 高亮 + 20×20 SVG 描边图标 + .7→1
   opacity. 解决用户反馈"优惠活动页面要和快捷设置页面统一, 返回/关闭
   按钮都要统一".
   ====================================================== */
.panel-close,
.ci-back,
.ci-close,
.side-menu-close,
.lang-picker-close,
.theme-picker-close {
  appearance: none;
  background: transparent;
  border: none;
  width: 36px; height: 36px;
  padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%;
  color: var(--text);
  cursor: pointer;
  font-size: 0;
  line-height: 1;
  opacity: .7;
  transition: opacity .15s ease, background .15s ease;
}
.panel-close:hover,
.ci-back:hover,
.ci-close:hover,
.side-menu-close:hover,
.lang-picker-close:hover,
.theme-picker-close:hover {
  opacity: 1;
  background: rgba(127, 127, 127, .12);
}

/* 2026-05-07 用户反馈"优惠活动 / 商城弹窗 顶部 X 关闭按钮 外面要套个
   可见的圆"(image-d5a600b4-...): 之前 .panel-close / .ci-close 默认
   background:transparent, 圆形仅 hover 才显. 移动端没 hover, 看上去
   就是一个孤零零的细 X, 缺少"按钮"的视觉识别度. 这里给所有 × 关闭
   按钮 (.panel-close / .ci-close / .side-menu-close / .lang-picker-close /
   .theme-picker-close) 加常驻的浅灰圆底, hover 时再加深. 不动 .ci-back
   返回箭头 (← 通常不需要圆框, 与 X 关闭语义层级不同). */
.panel-close,
.ci-close,
.side-menu-close,
.lang-picker-close,
.theme-picker-close {
  background: rgba(127, 127, 127, .14);
  opacity: 1;
}
.panel-close:hover,
.ci-close:hover,
.side-menu-close:hover,
.lang-picker-close:hover,
.theme-picker-close:hover {
  background: rgba(127, 127, 127, .26);
  opacity: 1;
}
.panel-close svg,
.ci-back svg,
.ci-close svg,
.side-menu-close svg,
.lang-picker-close svg,
.theme-picker-close svg {
  width: 20px; height: 20px;
  stroke: currentColor;
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-linejoin: round;
  fill: none;
}

.provider-search { padding: 12px 20px; }
.provider-search input {
  width: 100%; background: var(--input-bg);
  border: 1px solid var(--input-border); color: var(--text);
  padding: 10px 16px; border-radius: 8px;
  font-size: 14px; outline: none;
}
.provider-search input::placeholder { color: var(--text-mute); }

.provider-grid {
  display: grid;
  /* minmax(0,1fr) 让 grid item 能正确收缩，避免长文字（如 AFB Gaming / Pragmatic Play）撑爆列宽 */
  grid-template-columns: repeat(4, minmax(0, 1fr));
  /* 2026-05-25: padding-bottom 加 env(safe-area-inset-bottom) — 之前固定
     30px, 在 iPhone (home indicator ~34px) / Android 手势条上, 滑到底时
     最后一行 .provider-card 会被指示条盖住 50% 以上, 视觉上像"厂商列表
     底部缺一截". 现在保底 30px 之上, 再加设备 safe-area 高度, 确保最后
     一行整张卡都在可视范围内. overscroll-behavior:contain 防止 grid 到
     上下边界时手势冒泡到 body / .overlay 触发关抽屉. */
  gap: 12px;
  padding: 12px 20px calc(30px + env(safe-area-inset-bottom, 0px));
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* 2026-05-23: 厂商选择浮层按分类分组. header 横跨 4 列, 与 .provider-card
   位于同一 grid 中, 这样 gap/对齐都自动跟卡片一致, 不必另套容器. 紧凑设计,
   只在标题下面一条细线分隔, 不堆砌图标 — 与 panel-header 视觉层级保持区分. */
.provider-group-header {
  grid-column: 1 / -1;
  display: flex; align-items: baseline; gap: 8px;
  padding: 14px 2px 6px;
  margin-top: 4px;
  font-size: 13px; font-weight: 700;
  color: var(--text);
  border-bottom: 1px solid var(--input-border);
}
.provider-group-header:first-child {
  margin-top: 0;
  padding-top: 4px;
}
.provider-group-title { line-height: 1.25; }
.provider-group-count {
  font-size: 11px; font-weight: 500;
  color: var(--text-mute);
  padding: 1px 7px;
  border-radius: 10px;
  background: var(--surface-2);
}
/* 2026-05-25 用户反馈"丢失游戏名称, 游戏数量, 等信息":
   旧实现把 .provider-card 限定 padding 12px 4px + .provider-card-name 用
   display:-webkit-box / -webkit-line-clamp:2 / overflow:hidden 三联. 这套
   在内容明确非空时正常截断, 但只要任意一个 vendor (在某些 i18n / 数据缺失
   场景下) 拿到空白 vendor_name / 空白 alias / undefined total_games, 整条
   文本节点会塌成 0 高度, 此时整张卡只剩 padding 包裹 48px 图标 (≈72px),
   看起来"只剩图标". 用户截图刚好命中这一态.

   修复策略 (防御式, 不依赖数据百分百干净):
     1. 卡片整体 min-height: 同一行卡片高度强对齐, 不会因为某张卡名字缺失
        就高度塌缩 — 顺带保证整列对齐美观.
     2. .provider-card-name / -count 都给 min-height + 显式 font-size, 即便
        textContent 完全为空, 也撑住 1 行高度占位, 不会"消失";
     3. -webkit-line-clamp 段保留 (长名仍然 2 行截断), 但 min-height 把
        webkit-box 收缩为 0 的情况硬挡掉.
   字号同步上调 11→12 / 10→11, 改善 472px JPEG/低清屏可读性. */
.provider-card {
  display: flex; flex-direction: column;
  align-items: center; gap: 6px;
  padding: 12px 6px 14px; border-radius: 12px;
  background: var(--surface-2);
  cursor: pointer;
  transition: background .2s, transform .2s;
  border: 1px solid transparent;
  overflow: hidden;
  min-width: 0;
  min-height: 116px; /* 12 + 48 + 6 + 30 (name 2 行) + 4 + 14 (count) + 14 ≈ 110 */
}
.provider-card:hover { background: var(--surface-3); }
.provider-card.selected {
  background: rgba(254,44,85,.15);
  border-color: rgba(254,44,85,.5);
}
.provider-card > img {
  width: 48px; height: 48px; border-radius: 12px;
  object-fit: contain;
  background: var(--surface-3);
  flex-shrink: 0;
}
.provider-card-icon {
  width: 48px; height: 48px; border-radius: 12px;
  display: flex; align-items: center; justify-content: center;
  font-size: 20px; font-weight: 900; color: #fff;
  flex-shrink: 0;
}
.provider-card-name {
  font-size: 12px; color: var(--text);
  text-align: center; font-weight: 600;
  width: 100%;
  line-height: 1.3;
  /* 限两行省略，长英文单词允许任意位置换行 */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  word-break: break-word;
  overflow-wrap: anywhere;
  hyphens: auto;
  /* min-height: 1 行兜底 — 即使 vendor_name 异常空白也保持卡片纵向一致 */
  min-height: 16px;
}
.provider-card-count {
  font-size: 11px; color: var(--text-mute);
  width: 100%; text-align: center;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  line-height: 1.3;
  min-height: 14px;
}

/* 2026-05-04 维护中的厂商卡片
   - 后端 wpl.status='maintenance' → renderProviderGrid 加 .is-maint + data-maint=1
   - 视觉: 整体降饱和 + 名字下方一条橙色"维护中"小标
   - 不动 background/hover 颜色, 让用户依旧能看清是哪家厂商, 但语义明确"不可用"
   - 取消 wiggle (维护厂商图标晃来晃去会暗示"可点", 与禁点语义冲突) */
.provider-card.is-maint {
  filter: grayscale(.85);
  opacity: .72;
  cursor: not-allowed;
}
.provider-card.is-maint:hover { background: var(--surface-2); }
.provider-card.is-maint:hover > img,
.provider-card.is-maint:hover > .provider-card-icon,
.provider-card.is-maint:focus > img,
.provider-card.is-maint:focus > .provider-card-icon,
.provider-card.is-maint:focus-within > img,
.provider-card.is-maint:focus-within > .provider-card-icon { animation: none; }
.provider-card-maint {
  margin-top: 2px;
  font-size: 10px;
  font-weight: 600;
  color: #f59e0b;
  background: rgba(245, 158, 11, .14);
  border: 1px solid rgba(245, 158, 11, .35);
  border-radius: 6px;
  padding: 1px 6px;
  line-height: 1.3;
  letter-spacing: .5px;
}

/* 厂商 ICON 悬停 / 聚焦时无限左右摇摆。
   - 仅作用在图标本身（img / .provider-card-icon），不带动卡片整体，
     卡片仍走原 transition 高亮，互不干扰。
   - 0% / 50% / 100% 都回到 0deg，确保 animation-iteration 平滑无回弹卡顿。
   - 用 transform 触发 GPU 合成，避免 layout/paint，移动端不发烫。
   - 尊重系统的 prefers-reduced-motion，关闭动画。 */
@keyframes nv39-icon-wiggle {
  0%   { transform: rotate(0deg); }
  25%  { transform: rotate(-14deg); }
  50%  { transform: rotate(0deg); }
  75%  { transform: rotate(14deg); }
  100% { transform: rotate(0deg); }
}
.provider-card > img,
.provider-card > .provider-card-icon {
  transform-origin: 50% 60%;
  will-change: transform;
}
.provider-card:hover > img,
.provider-card:hover > .provider-card-icon,
.provider-card:focus > img,
.provider-card:focus > .provider-card-icon,
.provider-card:focus-within > img,
.provider-card:focus-within > .provider-card-icon {
  animation: nv39-icon-wiggle 1.1s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) {
  .provider-card:hover > img,
  .provider-card:hover > .provider-card-icon,
  .provider-card:focus > img,
  .provider-card:focus > .provider-card-icon,
  .provider-card:focus-within > img,
  .provider-card:focus-within > .provider-card-icon { animation: none; }
}

.comment-list { flex: 1; overflow-y: auto; padding: 12px 20px; }
.comment-item {
  display: flex; gap: 12px; padding: 12px 0;
  border-bottom: 1px solid rgba(255,255,255,.05);
}
.comment-avatar {
  width: 36px; height: 36px; border-radius: 50%;
  background: linear-gradient(135deg, #FE2C55, #25F4EE);
  display: flex; align-items: center; justify-content: center;
  font-size: 14px; font-weight: 700; flex-shrink: 0;
}
.comment-body { flex: 1; }
.comment-user { font-size: 13px; color: rgba(255,255,255,.5); font-weight: 500; margin-bottom: 4px; }
.comment-text { font-size: 14px; line-height: 1.4; color: rgba(255,255,255,.9); }
.comment-time { font-size: 11px; color: rgba(255,255,255,.3); margin-top: 4px; }

.comment-input-wrap {
  display: flex; gap: 8px; padding: 12px 20px;
  border-top: 1px solid rgba(255,255,255,.08);
  background: #1e1e1e;
}
.comment-input-wrap input {
  flex: 1; background: rgba(255,255,255,.08);
  border: none; color: #fff;
  padding: 10px 16px; border-radius: 20px;
  font-size: 14px; outline: none;
}
.comment-input-wrap input::placeholder { color: rgba(255,255,255,.4); }
.send-btn {
  background: #FE2C55; border: none; color: #fff;
  padding: 8px 18px; border-radius: 20px;
  font-size: 14px; font-weight: 600; cursor: pointer;
}

.share-panel {
  position: absolute;
  bottom: 0; left: 0; right: 0;
  background: #1e1e1e;
  border-radius: 16px 16px 0 0;
  transform: translateY(100%);
  transition: transform .35s cubic-bezier(.32,.72,.37,1.12);
  padding-bottom: 30px;
}
.overlay.active .share-panel { transform: translateY(0); }
.share-grid {
  display: flex; gap: 20px; padding: 20px 24px; overflow-x: auto;
}
.share-item {
  display: flex; flex-direction: column;
  align-items: center; gap: 8px; cursor: pointer;
}
.share-icon {
  width: 52px; height: 52px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 18px; font-weight: 700; color: #fff;
}
.share-icon.telegram { background: #0088cc; }
.share-icon.whatsapp { background: #25D366; }
.share-icon.facebook { background: #1877F2; }
.share-icon.twitter { background: #000; }
.share-icon.line { background: #06C755; }
.share-icon.link { background: #555; font-size: 22px; }
.share-item span { font-size: 11px; color: rgba(255,255,255,.7); }
.share-game-info {
  padding: 12px 24px 0;
  font-size: 13px; color: rgba(255,255,255,.6);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.share-url-box {
  display: flex; align-items: center; gap: 8px;
  margin: 10px 24px 6px; padding: 8px 12px;
  background: rgba(255,255,255,.08); border-radius: 8px;
}
.share-url-box input {
  flex: 1; background: none; border: none; color: #fff;
  font-size: 13px; outline: none;
}
.share-copy-btn {
  background: #FE2C55; border: none; color: #fff;
  padding: 6px 14px; border-radius: 6px;
  font-size: 12px; font-weight: 600; cursor: pointer;
  white-space: nowrap;
}

.search-panel {
  position: absolute;
  top: 0; left: 0; right: 0; bottom: 0;
  /* 主题化 (2026-04-28 用户要求"白天模式下搜索页面背景色也要修改") */
  background: var(--surface);
  color: var(--text);
  /* flex column: search-bar / search-hot 自然撑开, search-results 用 flex:1
     吃掉剩余空间. 之前是 normal flow + .search-results 写死
     max-height:calc(100vh - 160px), 在 iOS Safari 上 100vh 包含浏览器 chrome,
     当热门搜索 tags 多到 3-4 行时三块加起来超过实际可视高度, 第一项搜索结果
     就被浏览器底栏挡住(2026-04-21 用户反馈). */
  display: flex; flex-direction: column;
  transform: translateX(100%);
  transition: transform .3s cubic-bezier(.32,.72,.37,1.12);
}
.overlay.active .search-panel { transform: translateX(0); }

.search-bar {
  flex: none;
  display: flex; align-items: center; gap: 8px;
  padding: 10px 12px;
  border-bottom: 1px solid var(--border);
}
.back-btn {
  background: none; border: none;
  color: var(--text); cursor: pointer; opacity: .7;
}
.back-btn:hover { opacity: 1; }
.search-bar input {
  flex: 1; background: var(--input-bg);
  border: 1px solid var(--input-border); color: var(--text);
  padding: 10px 16px; border-radius: 8px;
  font-size: 15px; outline: none;
}
.search-bar input::placeholder { color: var(--text-mute); }
.search-hot { flex: none; padding: 20px; }
.search-hot h4 { font-size: 15px; font-weight: 600; margin-bottom: 14px; color: var(--text); }
.hot-tags { display: flex; flex-wrap: wrap; gap: 10px; }
.hot-tag {
  background: var(--surface-2);
  padding: 6px 14px; border-radius: 16px;
  font-size: 13px; color: var(--text-soft);
  cursor: pointer;
  transition: background .15s, color .15s;
}
.hot-tag:hover { background: var(--surface-3); color: var(--text); }
.search-results {
  /* 改用 flex 布局后, results 自动吃掉 panel 剩余高度, 不再依赖 100vh 计算,
     iOS Safari 浏览器 chrome 占位也不会再把最后一项挤出可见区. */
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 0 20px calc(16px + env(safe-area-inset-bottom, 0px));
}
.search-result-item {
  display: flex; align-items: center; gap: 14px;
  padding: 14px 0;
  border-bottom: 1px solid var(--divider);
  cursor: pointer;
}
.search-result-icon {
  position: relative;
  width: 52px; height: 52px; border-radius: 12px;
  display: flex; align-items: center; justify-content: center;
  font-size: 22px; font-weight: 900; color: #fff; flex-shrink: 0;
  overflow: hidden;
}
.search-result-icon .sri-img {
  width: 100%; height: 100%;
  object-fit: cover;
  border-radius: 12px;
  display: block;
}
.search-result-icon .sri-fallback {
  width: 100%; height: 100%;
  align-items: center; justify-content: center;
  font-size: 22px; font-weight: 900; color: #fff;
}
/* 桌号角标：D02 / D03 / S1 等，区分同系列实景桌的相同缩略图 */
.search-result-tag {
  position: absolute;
  right: 3px; bottom: 3px;
  min-width: 26px;
  padding: 2px 5px;
  border-radius: 6px;
  background: rgba(0,0,0,.78);
  color: #FFE25C;
  font-size: 10px; font-weight: 800;
  letter-spacing: .3px;
  line-height: 1.1;
  text-align: center;
  border: 1px solid rgba(255,255,255,.18);
  box-shadow: 0 1px 4px rgba(0,0,0,.4);
  pointer-events: none;
}
.search-result-info { flex: 1; min-width: 0; }
.search-result-info .name {
  font-size: 15px; font-weight: 600; margin-bottom: 2px; color: var(--text);
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.search-result-info .meta { font-size: 12px; color: var(--text-mute); }

/* ───── 搜索结果状态 badge — 2026-05-25 ─────
   ngapi /games/slots?include_disabled=true 会把"关闭"和"维护中"的游戏
   一并返回, 前端在卡片名旁边贴一个小圆角 badge:
     · 维护中: 橙底 — 与全站维护视觉 (#FFA500 系) 一致
     · 已关闭: 红底 — 用品牌红 #FE2C55 系, 与禁用/关闭语义匹配
   整张卡 .is-maint / .is-closed 时降饱和 + 文字偏灰, 提示"不可玩",
   click 在 JS 侧拦下来弹 toast, 这里只负责视觉. */
.search-result-status {
  display: inline-flex; align-items: center;
  padding: 2px 8px;
  font-size: 10px; font-weight: 700;
  line-height: 1.3;
  border-radius: 8px;
  letter-spacing: .3px;
  flex: 0 0 auto;
}
.search-result-status.status-maint {
  background: rgba(255,165,0,.16);
  color: #FFA500;
  border: 1px solid rgba(255,165,0,.4);
}
.search-result-status.status-closed {
  background: rgba(254,44,85,.14);
  color: #FE2C55;
  border: 1px solid rgba(254,44,85,.4);
}
.search-result-item.is-maint,
.search-result-item.is-closed {
  cursor: not-allowed;
}
.search-result-item.is-maint .search-result-icon,
.search-result-item.is-closed .search-result-icon {
  filter: grayscale(.7);
  opacity: .75;
}
.search-result-item.is-maint .search-result-info .name,
.search-result-item.is-closed .search-result-info .name {
  color: var(--text-mute);
}

/* -- Double Tap Heart (only on feed, not during game play) -- */
.double-tap-heart {
  position: fixed; z-index: 150; pointer-events: none; opacity: 0;
}
.double-tap-heart svg {
  width: 100px; height: 100px;
  filter: drop-shadow(0 4px 16px rgba(254,44,85,.6));
}
.double-tap-heart.show { animation: heartBurst .8s ease-out forwards; }
@keyframes heartBurst {
  0% { transform: scale(0) rotate(-15deg); opacity: 1; }
  30% { transform: scale(1.2) rotate(5deg); opacity: 1; }
  60% { transform: scale(1); opacity: 1; }
  100% { transform: scale(1.3) translateY(-40px); opacity: 0; }
}

/* -- Toast -- */
.toast {
  position: fixed;
  /* 避开游戏顶栏/刘海; 长文案换行居中, 避免「文字偏移」贴边裁切 */
  top: max(72px, calc(env(safe-area-inset-top, 0px) + 56px));
  left: 50%; transform: translateX(-50%) translateY(-20px);
  background: rgba(50,50,50,.95);
  color: #fff;
  padding: 12px 18px;
  border-radius: 10px;
  font-size: 13px;
  font-weight: 500;
  line-height: 1.45;
  text-align: center;
  white-space: normal;
  word-break: break-word;
  max-width: min(92vw, 420px);
  box-sizing: border-box;
  /* 2026-05-01 z-index 提到 200000: 之前 300 被 .ci-overlay (1000) /
     finance-overlay (1500) / login-overlay (11000) / 全屏游戏 (99999~100002)
     等所有 overlay 完全盖住, 用户在 PromoHub / 充值 / 提现 / 商城 / 游戏内
     操作时 toast 反馈完全不可见, 误以为"点击没反应". 200000 高于所有已知
     overlay (含 #qrImagePreviewOverlay 5200 / theme-picker 100200 / lang-picker
     100300 / game-fs-landscape 100000+1/+2), 任何场景下 toast 均可见. */
  z-index: 200000; opacity: 0; pointer-events: none;
  transition: opacity .3s, transform .3s, background .2s, box-shadow .2s;
  backdrop-filter: blur(10px);
}
.toast.show {
  opacity: 1; transform: translateX(-50%) translateY(0);
}
/* 成功反馈：品牌色高亮 + 强阴影 + 微微放大，比普通灰色 toast 更醒目，
   常用于"链接已复制 / 收藏成功 / 操作成功"等正向反馈 */
.toast.toast-success {
  background: linear-gradient(135deg, #FE2C55 0%, #ff5577 100%);
  color: #fff;
  font-size: 15px;
  font-weight: 700;
  padding: 12px 28px;
  border-radius: 24px;
  box-shadow: 0 8px 24px rgba(254,44,85,.5), 0 0 0 1px rgba(255,255,255,.08) inset;
  letter-spacing: .5px;
}
.toast.toast-success.show {
  transform: translateX(-50%) translateY(0) scale(1.04);
}
.toast.toast-error {
  background: linear-gradient(135deg, #c0392b 0%, #e74c3c 100%);
  color: #fff;
  font-weight: 700;
  box-shadow: 0 6px 20px rgba(192,57,43,.4);
}
.toast.toast-warning {
  background: linear-gradient(135deg, #d35400 0%, #f39c12 100%);
  color: #fff;
  font-weight: 700;
  box-shadow: 0 6px 20px rgba(211,84,0,.4);
}

/* ===== Desktop panels override ===== */
@media (min-width: 768px) {
  body:not(.is-mobile-device) .overlay .provider-panel,
  body:not(.is-mobile-device) .overlay .comment-panel,
  body:not(.is-mobile-device) .overlay .share-panel {
    max-width: 480px;
    margin: 0 auto;
  }
  body:not(.is-mobile-device) .overlay .search-panel {
    max-width: 480px;
    left: auto; right: 0;
  }
}

/* ======================================================
   PROFILE PAGE — TikTok Style
   ====================================================== */
.profile-page {
  position: fixed; top: 0; left: 0; right: 0; bottom: 0;
  background: var(--panel-bg);
  /* z-index 150：盖在 game-fullscreen(z=90) 之上、bottom-nav(z=200) 之下，
     这样进入个人中心时游戏 iframe 仍存活，退出后游戏继续，无需重连。 */
  z-index: 150;
  overflow-y: auto; overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  color: var(--text);
}

.profile-topbar {
  position: sticky; top: 0; z-index: 10;
  display: flex; align-items: center; justify-content: center;
  height: 48px; background: var(--panel-bg);
  border-bottom: 1px solid var(--border);
}
.profile-topbar-title {
  font-size: 17px; font-weight: 700;
}
.profile-back-btn {
  position: absolute; left: 12px; top: 50%; transform: translateY(-50%);
  background: none; border: none; cursor: pointer;
  color: #FE2C55; display: flex; align-items: center;
  font-size: 14px; gap: 2px; padding: 4px;
}
.profile-topbar-btn {
  position: absolute; right: 12px; top: 50%; transform: translateY(-50%);
  background: none; border: none; cursor: pointer;
  color: var(--text);
}

/* Guest State */
.profile-guest {
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  padding: 120px 40px 40px; text-align: center;
}
.profile-guest-avatar {
  margin-bottom: 20px; opacity: .5;
}
.profile-guest-text {
  font-size: 15px; color: var(--text-mute); margin-bottom: 24px;
}
.profile-login-btn {
  width: 280px; max-width: 80%;
  padding: 14px 0; border: none;
  border-radius: 50px;
  background: #FE2C55; color: #fff;
  font-size: 17px; font-weight: 700;
  cursor: pointer; margin-bottom: 16px;
}
.profile-register-link {
  background: none; border: none;
  color: #FE2C55; font-size: 14px;
  cursor: pointer; font-weight: 500;
}

/* Logged In Header */
.profile-header {
  text-align: center;
  padding: 20px 20px 0;
}
.profile-avatar-wrap {
  position: relative; display: inline-block; margin-bottom: 12px;
}
.profile-avatar {
  width: 80px; height: 80px; border-radius: 50%;
  background: linear-gradient(135deg, #FE2C55, #25F4EE);
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
}
.profile-avatar img {
  width: 100%; height: 100%; object-fit: cover;
}
.profile-avatar-camera {
  position: absolute; bottom: 0; right: -4px;
  width: 28px; height: 28px; border-radius: 50%;
  background: #FE2C55; border: 2px solid #fff;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
}
.profile-name-row {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  margin-bottom: 4px;
}
.profile-nickname {
  font-size: 20px; font-weight: 800;
}
.profile-edit-btn {
  padding: 4px 14px; border: 1px solid var(--input-border);
  border-radius: 4px; background: var(--surface);
  font-size: 13px; font-weight: 600; cursor: pointer;
  color: var(--text);
}
.profile-username {
  font-size: 14px; color: var(--text-mute); margin-bottom: 16px;
  /* 2026-06-01 问题9: 长账号在个人中心也要能完整看到, 允许换行. */
  word-break: break-all;
  overflow-wrap: anywhere;
  /* 用户名统一大写 (与桌面 sidebar .dt-user-name 一致, 用户偏好 2026-04-28). */
  text-transform: uppercase;
  letter-spacing: .3px;
}

.profile-stats {
  display: flex; justify-content: center; gap: 32px;
  margin-bottom: 14px;
}
.profile-stat {
  display: flex; flex-direction: column; align-items: center;
}
.profile-stat-num {
  font-size: 18px; font-weight: 800;
}
.profile-stat-label {
  font-size: 12px; color: var(--text-mute);
}

.profile-bio {
  font-size: 13px; color: var(--text-mute);
  padding: 0 20px 16px; text-align: center;
  border-bottom: 1px solid var(--border);
}

/* Balance Card */
.profile-balance-card {
  position: relative;
  margin: 16px; padding: 18px 20px 16px;
  background: linear-gradient(135deg, #1a1a2e, #16213e);
  border-radius: 16px; color: #fff;
  overflow: hidden;
}
/* 顶部装饰光斑，提升视觉层次 */
.profile-balance-card::before {
  content: '';
  position: absolute;
  top: -40px; right: -30px;
  width: 160px; height: 160px;
  background: radial-gradient(circle, rgba(255,215,0,.18), transparent 60%);
  pointer-events: none;
}
.balance-main {
  position: relative;
  display: flex; flex-direction: row; align-items: baseline;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 14px;
}
.balance-label {
  font-size: 12px;
  color: rgba(255,255,255,.55);
  letter-spacing: .3px;
}
.balance-main .balance-label {
  flex: 0 0 auto;
}
.balance-amount {
  /* 2026-05-25: 28px/900 + 渐变金 在卡片里显得过重 (用户反馈"太大不协调") —
     与右下"奖金余额 0.00"(18px) 主从关系太悬殊, 与卡片自身高度 (~120px)
     比例也失衡. 降到 22px/800 仍是卡片视觉焦点, 但能给副信息留呼吸空间;
     line-height 收紧到 1, 避免大额带千位分隔符 (1,234,567.89) 撑成两行. */
  font-size: 22px; font-weight: 800; line-height: 1;
  background: linear-gradient(135deg, #FFD700, #FFA500);
  -webkit-background-clip: text; -webkit-text-fill-color: transparent;
  font-variant-numeric: tabular-nums;
  flex: 1 1 auto;
  min-width: 0;
  text-align: right;
}
/* 奖金余额 + 积分：双列副信息卡，紧凑、有分隔 */
.balance-sub-grid {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1fr;
  margin-bottom: 14px;
  padding: 12px 4px;
  background: rgba(255,255,255,.04);
  border: 1px solid rgba(255,255,255,.06);
  border-radius: 12px;
}
/* 2026-05-25 站点 (website 6.9) 开通余额宝时, app.js loadProfile 给 grid
   加 .with-savings → 切到三列 (奖金 / 积分 / 余额宝). 未开通保持双列, 不留空格. */
.balance-sub-grid.with-savings {
  grid-template-columns: 1fr 1fr 1fr;
}
.balance-sub-item {
  display: flex; flex-direction: column; align-items: center;
  gap: 4px;
  padding: 0 12px;
}
.balance-sub-item + .balance-sub-item {
  border-left: 1px solid rgba(255,255,255,.08);
}
.balance-sub-item .balance-label {
  font-size: 11px;
}
.balance-amount-sm {
  font-size: 18px; font-weight: 800; color: #25F4EE;
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}
/* 积分用暖色与余额区分 */
.balance-amount-sm.balance-points {
  color: #FFC857;
}
/* 2026-05-25 余额宝本金: 用品牌色 (= 转入/转出按钮的渐变金) 与主余额呼应,
   但比 .balance-amount 小一档 (18px) — 它是副信息, 不抢"主钱包余额"焦点.
   .balance-sub-savings 整列加 transition + active 态, 暗示可点击进余额宝面板. */
.balance-amount-sm.balance-savings {
  color: #FFD700;
}
.balance-sub-savings {
  position: relative;
  transition: background .15s;
  border-radius: 8px;
}
.balance-sub-savings:active {
  background: rgba(255,215,0,.08);
}
.balance-actions {
  display: flex; gap: 8px;
}
.balance-action-btn {
  flex: 1;
  display: flex; align-items: center; justify-content: center;
  gap: 4px;
  padding: 11px 0;
  border: none;
  border-radius: 10px;
  font-size: 13px; font-weight: 700;
  cursor: pointer;
  transition: transform .1s, filter .15s, background .15s;
}
.balance-action-btn:active {
  transform: scale(0.97);
}
.balance-action-btn.deposit {
  background: linear-gradient(135deg, #FE2C55, #ff5274);
  color: #fff;
  box-shadow: 0 4px 14px rgba(254, 44, 85, .3);
}
.balance-action-btn.deposit:hover { filter: brightness(1.05); }
.balance-action-btn.withdraw,
.balance-action-btn.transfer {
  background: rgba(255,255,255,.1);
  color: #fff;
  border: 1px solid rgba(255,255,255,.1);
}
.balance-action-btn.withdraw:hover,
.balance-action-btn.transfer:hover {
  background: rgba(255,255,255,.18);
}

/* Profile Tabs */
.profile-tabs {
  display: flex; border-bottom: 1px solid var(--border);
  position: sticky; top: 48px; background: var(--panel-bg); z-index: 5;
}
.profile-tab {
  flex: 1; display: flex; align-items: center; justify-content: center;
  padding: 12px 0; background: none; border: none;
  border-bottom: 2px solid transparent;
  cursor: pointer; color: var(--text-mute); transition: all .2s;
}
.profile-tab.active {
  color: var(--text); border-bottom-color: var(--text);
}
.profile-tab svg { stroke: currentColor; }

.profile-tab-content { padding: 16px; min-height: 300px; padding-bottom: 80px; }
.profile-section-header {
  display: flex; justify-content: space-between;
  align-items: center; margin-bottom: 12px;
}
.profile-section-header h4 { font-size: 15px; font-weight: 700; }

.profile-games-grid {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: 4px;
}
.profile-game-card {
  aspect-ratio: 3/4; border-radius: 4px; overflow: hidden;
  position: relative; cursor: pointer; background: var(--surface-2);
}
.profile-game-card img {
  width: 100%; height: 100%; object-fit: cover;
}
.profile-game-card .game-overlay-info {
  position: absolute; bottom: 0; left: 0; right: 0;
  padding: 4px 6px; font-size: 10px; color: #fff;
  background: linear-gradient(transparent, rgba(0,0,0,.7));
  display: flex; align-items: center; gap: 3px;
}
.profile-game-fallback {
  width: 100%; height: 100%;
  display: flex; align-items: center; justify-content: center;
  font-size: 24px; font-weight: 900; color: var(--text-soft);
}
.profile-empty {
  grid-column: 1 / -1; text-align: center;
  color: var(--text-faint); font-size: 14px; padding: 60px 0;
}

/* 收藏卡片右上角的删除按钮 */
.profile-game-card .profile-game-del {
  position: absolute; top: 4px; right: 4px;
  width: 24px; height: 24px; border-radius: 50%;
  border: none; padding: 0; cursor: pointer;
  background: rgba(0,0,0,.55); color: #fff;
  display: flex; align-items: center; justify-content: center;
  z-index: 3; opacity: 0; transition: opacity .15s, background .15s;
}
.profile-game-card:hover .profile-game-del,
.profile-game-card:focus-within .profile-game-del { opacity: 1; }
.profile-game-card .profile-game-del:hover { background: #ff3b30; }
.profile-game-card .profile-game-del:active { transform: scale(.92); }
/* 触屏环境（无 hover）下始终显示删除按钮 */
@media (hover: none) {
  .profile-game-card .profile-game-del { opacity: .92; }
}

/* 个人中心 → 我关注的厂商：卡片右上角"取消关注"按钮 */
.followed-vendor-card { position: relative; }
.followed-vendor-card .followed-vendor-unfollow {
  position: absolute; top: 6px; right: 6px;
  width: 22px; height: 22px; border-radius: 50%;
  border: none; padding: 0; cursor: pointer;
  background: rgba(0,0,0,.45); color: #fff;
  display: flex; align-items: center; justify-content: center;
  z-index: 3; transition: background .15s, transform .15s;
}
.followed-vendor-card .followed-vendor-unfollow:hover { background: #ff3b30; }
.followed-vendor-card .followed-vendor-unfollow:active { transform: scale(.9); }

/* Records */
.profile-records-tabs {
  display: flex; gap: 8px; margin-bottom: 12px;
  /* 2026-06-04 (doc#7): 报表 tab 增至 6 个(结算/投注/充值/提现/邀请有礼/锦标赛),
     窄抽屉里 flex 行会挤压或把末尾 tab 裁切遮挡。改为横向滚动 + tab 不收缩,
     保证所有 tab 都能完整显示并可滑动访问。 */
  flex-wrap: nowrap;
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  padding-bottom: 2px;
}
.profile-records-tabs::-webkit-scrollbar { display: none; }
.rec-tab {
  padding: 6px 14px; border-radius: 20px;
  background: var(--surface-2); border: none;
  font-size: 13px; font-weight: 500; cursor: pointer;
  color: var(--text-soft);
  flex: 0 0 auto;
  white-space: nowrap;
}
.rec-tab.active { background: var(--text); color: var(--bg); }

/* 投注记录"快捷范围按钮组" (今天/昨天/本周/上周): 列表上方常驻,
   只在 #recordsList / #recordsOverlayList 的投注 tab 里出现, 切到充值/提现自动消失.
   样式比 .rec-tab 更轻量, 视觉是次级筛选器, 不抢主 tab 焦点. */
.bet-range-tabs {
  display: flex; gap: 6px; margin-bottom: 10px;
  flex-wrap: wrap;
}
.bet-range-tab {
  padding: 5px 12px; border-radius: 14px;
  background: #f5f5f7; border: 1px solid transparent;
  font-size: 12px; color: #555; cursor: pointer;
  transition: all .15s;
}
.bet-range-tab:hover { background: #ececef; }
.bet-range-tab.active {
  background: #fff5f7; color: #FE2C55;
  border-color: #FE2C55; font-weight: 600;
}
.bet-range-list { display: flex; flex-direction: column; gap: 8px; }

/* 投注记录顶部统计条: 区域时间按钮下方常驻一行, 显示当前时段总下注 / 总输赢.
   - 空容器 (:empty) 不占空间, 避免加载/空数据时残留空白条 */
.bet-range-summary {
  display: flex;
  gap: 8px;
  margin-bottom: 10px;
}
.bet-range-summary:empty { display: none; }
.bet-summary-cell {
  flex: 1;
  background: #f8f9fa;
  border: 1px solid #eee;
  border-radius: 10px;
  padding: 8px 12px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.bet-summary-label {
  font-size: 11px;
  color: #999;
  font-weight: 500;
}
.bet-summary-value {
  font-size: 16px;
  font-weight: 700;
  color: #161823;
  letter-spacing: 0.2px;
}
.bet-summary-value.positive { color: #00c853; }
.bet-summary-value.negative { color: #ff3b30; }
.bet-summary-value.neutral  { color: #888; }

.profile-records-list {
  display: flex; flex-direction: column; gap: 8px;
}
.record-item {
  display: flex; justify-content: space-between;
  align-items: center; padding: 14px 16px;
  background: var(--surface-2); border-radius: 10px;
}
.record-left {
  display: flex; flex-direction: column; gap: 2px;
}
.record-title { font-size: 14px; font-weight: 600; color: var(--text); }
.record-time { font-size: 11px; color: var(--text-mute); }
.record-amount { font-size: 15px; font-weight: 700; }
.record-amount.positive { color: #22c55e; } /* 赢钱: 绿 */
.record-amount.negative { color: #FE2C55; } /* 输钱: 红 */
.record-amount.neutral  { color: var(--text-mute); }    /* 持平: 灰 */
/* 充值/提现记录右侧: 金额 + 取消按钮 (status=0 待审核才显示) */
.record-right {
  display: flex; flex-direction: column; align-items: flex-end; gap: 6px;
  flex-shrink: 0;
}
.record-cancel-btn {
  border: 1px solid #FE2C55; background: var(--surface); color: #FE2C55;
  font-size: 12px; font-weight: 600; padding: 4px 12px;
  border-radius: 14px; cursor: pointer;
  transition: background .15s, color .15s;
}
.record-cancel-btn:hover:not(:disabled) { background: #FE2C55; color: #fff; }
.record-cancel-btn:disabled { opacity: .5; cursor: not-allowed; }

/* 投注记录按游戏聚合行: 三行布局 (标题 / 末次时间·笔数 / 总下注) */
.record-bet-grp .record-bet-sub { color: var(--text-faint); font-size: 11px; }
.record-bet-grp .record-sub { color: var(--text-faint); font-weight: 400; font-size: 12px; }
.record-bet-grp .record-left { gap: 3px; min-width: 0; flex: 1; }
.record-bet-grp .record-title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.record-bet-grp { gap: 12px; }

/* bet_kind 徽章: 渲染在投注记录第二行 (跟时间+笔数同行), 标记
   "购买免费旋转" (bonus_buy 橙) / "打赏" (tip 紫) 等特殊聚合分组.
   2026-05-28 从 .record-title 内挪出: 标题设了 nowrap+ellipsis, 长标题会
   把徽章一起吃掉造成"样式丢失". 现在放到 .record-time 行不会被截断,
   且位置跟普通转动行的时间信息对齐, 视觉更清爽. */
.bet-kind-badge {
  display: inline-block; margin-right: 6px; padding: 1px 6px;
  font-size: 10px; font-weight: 600; line-height: 1.4;
  border-radius: 6px; vertical-align: middle;
}
.bet-kind-badge.bet-kind-bonusbuy {
  background: #fff7ed; color: #c2410c; border: 1px solid #fdba74;
}
.bet-kind-badge.bet-kind-tip {
  background: #faf5ff; color: #7e22ce; border: 1px solid #d8b4fe;
}
/* 2026-05-27 ViA Casino 打赏 (TIP / Donation) 接入: 紫色徽章, 跟橙色 bonus_buy
   颜色分桶清晰. 后端 mod_<short>_tips 表 UNION 进 GetBetHistory, bet_kind='tip' */
.bet-kind-badge.bet-kind-tip {
  background: #faf5ff; color: #7e22ce; border: 1px solid #d8b4fe;
}

/* Settings */
.settings-menu {
  display: flex; flex-direction: column;
}
.settings-item {
  display: flex; align-items: center; gap: 14px;
  padding: 16px 4px; cursor: pointer;
  border-bottom: 1px solid var(--divider);
  transition: background .15s;
}
.settings-item:active { background: var(--surface-2); }
.settings-item span { flex: 1; font-size: 15px; font-weight: 500; }
.settings-arrow { color: var(--text-faint); margin-left: auto; }
.settings-divider { height: 8px; background: var(--surface-2); margin: 0 -16px; }

/* 2026-05-04 侧栏「我的消息」行内 badge: 把 .msg-badge 默认的角标样式
   完全反转 — 用户要求"只显示红色数字, 没有背景色", 所以这里强制干掉
   .msg-badge 的红底/白字/圆角胶囊, 只留下 14px 红色加粗数字, 行内对齐
   到 settings-arrow 左侧. */
.settings-msg-badge {
  position: static !important;
  display: inline-flex !important;
  align-items: center; justify-content: center;
  margin-left: 6px; margin-right: 4px;
  flex: 0 0 auto;
  background: transparent !important;
  color: #FE2C55 !important;
  font-size: 14px !important;
  font-weight: 700 !important;
  padding: 0 !important;
  min-width: 0 !important;
  height: auto !important;
  line-height: 1 !important;
  border-radius: 0 !important;
  box-shadow: none !important;
}
.settings-msg-badge:empty { display: none !important; }

/* Profile Side Menu — slide from right */
.profile-side-backdrop {
  position: fixed; top: 0; left: 0; right: 0; bottom: 0;
  background: rgba(0,0,0,.45);
  z-index: 200; opacity: 0;
  pointer-events: none;
  transition: opacity .3s;
}
.profile-side-backdrop.open { opacity: 1; pointer-events: auto; }

.profile-side-menu {
  position: fixed; top: 0; right: 0; bottom: 0;
  width: 280px; max-width: 80vw;
  background: var(--panel-bg); z-index: 201;
  transform: translateX(100%);
  transition: transform .3s cubic-bezier(.32,.72,.37,1.0);
  display: flex; flex-direction: column;
  box-shadow: var(--shadow-lg);
}
.profile-side-menu.open { transform: translateX(0); }

.side-menu-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 16px 20px;
  border-bottom: 1px solid var(--border);
  font-size: 17px; font-weight: 700;
  color: var(--text);
}
/* 2026-05-06: 视觉已并入 "Unified overlay header buttons" (panel-close 等
   一组), 这里不再单独设 font-size/color, 统一规则会接管 SVG × 渲染. */
.side-menu-close {
  /* legacy declaration kept hollow for max specificity safety */
}
.profile-side-menu .settings-menu {
  flex: 1; overflow-y: auto;
  padding: 8px 16px;
  -webkit-overflow-scrolling: touch;
  /* 2026-05-25: 阻止滚动链 (scroll chaining). 用户反馈"上下滑动时底层 feed
     在滚动, 设置抽屉自己不动" 的根因 — iOS Safari / Chrome 在 overflow:auto
     容器到达上下边界时, 触摸事件会继续传给 body, 把后面的 .feed-container /
     #dtFeed 卷起来. overscroll-behavior:contain 在边界处吸收余下手势, 不让
     它逃出当前容器, 同时配合 body.side-menu-open { overflow:hidden } 双保险. */
  overscroll-behavior: contain;
}
.profile-side-menu .settings-item {
  padding: 14px 4px;
}
.profile-side-menu .settings-divider {
  margin: 0 -16px;
}

/* ───── 设置分组 (foldable) — 2026-05-25 ─────
   HTML 早在 2026-05-16 就铺好了 .settings-section / -header / -icon /
   -title / -caret / -body 的 DOM, 但配套 CSS + 点击 JS 一直缺位, 导致:
     · header 没样式, 与普通正文字一样大小/颜色, 看起来像"项目说明"
     · is-open 类切换没人触发, 永远展开
   现在补齐: header 16px 主色字体 + 14px 副 caret, .is-open 时 caret 旋转
   180° (视觉提示展开态), :not(.is-open) 隐藏 body 实现折叠. 内部 item 加
   8px 左缩进, 让用户感知"这几个是这个分组的". */
.profile-side-menu .settings-section {
  margin: 2px -4px;
}
.profile-side-menu .settings-section-header {
  display: flex; align-items: center; gap: 12px;
  width: 100%;
  padding: 14px 4px;
  background: transparent;
  border: 0;
  cursor: pointer;
  color: var(--text);
  font-size: 15px; font-weight: 600;
  text-align: left;
  -webkit-tap-highlight-color: transparent;
}
.profile-side-menu .settings-section-header:active { opacity: .65; }
.profile-side-menu .settings-section-icon {
  flex: 0 0 18px;
  width: 18px; height: 18px;
  color: var(--text-mute);
}
.profile-side-menu .settings-section-title {
  flex: 1;
  font-size: 15px; font-weight: 600;
  color: var(--text);
}
.profile-side-menu .settings-section-caret {
  flex: 0 0 14px;
  width: 14px; height: 14px;
  color: var(--text-mute);
  transition: transform .2s ease;
}
/* 展开态: caret/title/icon 全部换成品牌红 (#FE2C55), 让用户一眼看出
   "当前展开的是哪一组" — 用户明确要求"向下箭头用其他的颜色显示". */
.profile-side-menu .settings-section.is-open .settings-section-caret {
  transform: rotate(180deg);
  color: #FE2C55;
}
.profile-side-menu .settings-section.is-open .settings-section-title {
  color: #FE2C55;
}
.profile-side-menu .settings-section.is-open .settings-section-icon {
  color: #FE2C55;
}
.profile-side-menu .settings-section-body {
  /* 内嵌项左缩进, 用视觉层级表达"属于该分组" */
  padding-left: 12px;
}
.profile-side-menu .settings-section:not(.is-open) .settings-section-body {
  display: none;
}

/* ───── body 滚动锁 (侧菜单打开时) — 2026-05-25 ─────
   v1 用 overflow:hidden + touch-action:none, 在桌面 / Android 可以, 但 iOS
   Safari 上即使 body{overflow:hidden} 仍会响应 touchmove 把页面拉动 (尤其
   触摸落点在 backdrop / 侧菜单 header 等不可滚区域时, 手势会"漏"给 body).
   v2 (现在) 改用 position:fixed + top=-scrollY 模式 — 把 body 整个钉死在
   视口里, scrollY 由 JS 保存, 关菜单时再 window.scrollTo 还原. 这是 iOS 上
   公认最稳的 scroll lock 套路.
     · width:100% 配合 left/right:0 防止 fixed 后 body 收缩;
     · overflow:hidden touch-action:none 留作 desktop/Android 的"廉价"兜底;
     · overscroll-behavior:contain (上面 .settings-menu 上) 处理菜单内部
       到顶/到底的滚动链.
   关闭时 JS 还原 (见 app.js _setSideMenuOpen). */
body.side-menu-open {
  position: fixed !important;
  width: 100%;
  left: 0; right: 0;
  overflow: hidden !important;
  touch-action: none;
}
/* backdrop 自身: 不允许任何方向滚动手势 (用户用品 touch 落在 backdrop 那
   片半透明遮罩上时, 默认手势会冒泡到 body. 这里直接 touch-action:none
   配合 JS preventDefault 双保险). */
.profile-side-backdrop { touch-action: none; }
/* 侧菜单顶部 header 区域 (LOGO / 关闭 ×): 同样不滚, 把垂直手势让给
   .settings-menu (.settings-menu 自己声明了 touch-action:pan-y, 见上). */
.profile-side-menu .side-menu-header { touch-action: none; }
.profile-side-menu .settings-menu { touch-action: pan-y; }

/* ======================================================
   FOLLOWS PAGE — TikTok-style "Following" full-screen page
   关注厂商 / 收藏游戏 / 最近玩 三合一全屏页
   ------------------------------------------------------
   z-index 160 高于 .profile-page(150) 与 .game-fullscreen(90),
   保证从个人主页点开"关注"stat 时能盖住 profile 页面;
   被 body.game-fs-landscape 兜底规则 display:none, 不影响游戏全屏。
   ====================================================== */
.follows-page {
  position: fixed; top: 0; left: 0; right: 0; bottom: 0;
  background: var(--panel-bg); color: var(--text);
  z-index: 160;
  overflow-y: auto; overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  display: flex; flex-direction: column;
}

.follows-topbar {
  position: sticky; top: 0; z-index: 11;
  display: flex; align-items: center;
  height: 48px; padding: 0 12px;
  background: var(--panel-bg); border-bottom: 1px solid var(--border);
}
.follows-back-btn {
  width: 36px; height: 36px; border: none; background: none;
  display: flex; align-items: center; justify-content: center;
  color: var(--text); cursor: pointer; padding: 0;
}
.follows-topbar-title {
  flex: 1; text-align: center;
  font-size: 17px; font-weight: 700; color: var(--text);
  /* 让标题视觉居中：右侧补一个等宽 spacer */
}
.follows-topbar-spacer { width: 36px; height: 36px; }

/* 头部信息条: 关注厂商总数 + 一句简介, 取代旧的 stats+tabs */
.follows-summary {
  padding: 18px 16px 14px;
  background: var(--panel-bg);
  border-bottom: 1px solid var(--border);
  display: flex; flex-direction: column; gap: 4px;
}
.follows-summary-num {
  font-size: 18px; font-weight: 800; color: var(--text);
}
.follows-summary-num span { color: #FE2C55; font-size: 22px; }
.follows-summary-hint {
  font-size: 12px; color: var(--text-mute);
}

.follows-body {
  flex: 1; padding: 6px 12px calc(20px + env(safe-area-inset-bottom, 0px));
}

.follows-empty {
  text-align: center; color: var(--text-faint);
  font-size: 14px; padding: 60px 16px;
  white-space: pre-line;
}

/* —— TikTok 风格关注厂商行 —— */
.follows-vendor-list {
  display: flex; flex-direction: column;
  gap: 0;
}
.follows-vendor-row {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 4px;
  border-bottom: 1px solid var(--divider);
  cursor: pointer; transition: background .15s;
}
.follows-vendor-row:active { background: var(--surface-2); }
/* 厂商 logo 通常是横幅 PNG/WebP（如 AFBGAMING、JILI 自带文字标），
   用 border-radius:50% + object-fit:cover 会把两侧文字裁掉, 完全看不出
   是哪家。这里采用：圆角方形容器 + object-fit:contain + 内 padding,
   保留 logo 原始比例与全部文字; 同时叠一个 fallback 文字占位,
   仅在 img 加载失败时才显露出来 (img 自己 remove). */
.follows-vendor-row .fv-logo {
  position: relative;
  width: 56px; height: 56px;
  border-radius: 12px;
  background: #1a1a2e; flex-shrink: 0;
  overflow: hidden;
}
.follows-vendor-row .fv-logo-fallback {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: 18px; font-weight: 800; color: #fff;
  letter-spacing: .5px;
  text-transform: uppercase;
}
.follows-vendor-row .fv-logo-img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: contain;
  padding: 6px;
  box-sizing: border-box;
  background: #1a1a2e;
  border-radius: inherit;
}
.follows-vendor-row .fv-info {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column; gap: 3px;
}
.follows-vendor-row .fv-name {
  font-size: 15px; font-weight: 700; color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.follows-vendor-row .fv-meta {
  font-size: 12px; color: var(--text-mute);
}
.follows-vendor-row .fv-action {
  flex-shrink: 0;
  padding: 7px 18px;
  border: 1px solid #FE2C55;
  border-radius: 6px;
  background: #FE2C55;
  color: #fff; font-size: 13px; font-weight: 700;
  cursor: pointer; transition: background .15s, color .15s, border-color .15s;
}
.follows-vendor-row .fv-action.followed {
  background: var(--surface); color: var(--text-soft); border-color: var(--input-border);
}
.follows-vendor-row .fv-action:active { transform: scale(.96); }

/* 全屏时彻底隐藏，确保不挡游戏 */
body.game-fs-landscape .follows-page { display: none !important; }

@media (min-width: 768px) {
  /* 桌面下让"关注"也是一个抽屉式 modal，宽度受限居中 */
  .follows-page {
    top: 54px;
    bottom: 0;
    left: 50%; right: auto;
    transform: translateX(-50%);
    width: min(720px, 92vw);
    border-radius: 16px 16px 0 0;
    box-shadow: 0 -8px 40px rgba(0,0,0,.28);
  }
}

/* ======================================================
   VENDOR PROFILE PAGE — TikTok Creator Style
   ====================================================== */
.vendor-profile-page {
  position: fixed; top: 54px; left: 0; right: 0;
  bottom: calc(60px + env(safe-area-inset-bottom, 0px));
  z-index: 150; background: var(--panel-bg); color: var(--text);
  overflow-y: auto; -webkit-overflow-scrolling: touch;
}
.vendor-profile-topbar {
  display: flex; align-items: center; justify-content: space-between;
  padding: 8px 16px;
  position: sticky; top: 0; z-index: 10; background: var(--panel-bg);
  border-bottom: none;
  height: 44px;
}
.vendor-back-btn {
  background: none; border: none; padding: 4px;
  cursor: pointer; color: var(--text); line-height: 0;
}
.vendor-topbar-title {
  font-size: 17px; font-weight: 700;
  position: absolute; left: 50%; transform: translateX(-50%);
  max-width: calc(100% - 100px);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  text-align: center;
}
.vendor-topbar-spacer { width: 32px; }

/* 2026-06-17: 厂商关注 + LOGO 头部从纵向大卡片改为紧凑横向布局,
   高度从 ~260px 压到 ~76px, 把腾出的空间留给下方游戏网格, 尽量多显示游戏. */
.vendor-profile-header {
  display: grid;
  grid-template-columns: auto 1fr auto;
  grid-template-areas:
    "avatar name   follow"
    "avatar code   follow"
    "avatar stats  follow";
  align-items: center;
  column-gap: 12px; row-gap: 1px;
  padding: 10px 16px; text-align: left;
}
.vendor-profile-avatar {
  grid-area: avatar;
  width: 54px; height: 54px; border-radius: 50%;
  overflow: hidden; display: flex; align-items: center; justify-content: center;
  font-size: 20px; font-weight: 900; color: #fff;
  margin-bottom: 0; box-shadow: 0 2px 8px rgba(0,0,0,.12);
  background: #666;
}
.vendor-profile-avatar img {
  width: 100%; height: 100%; object-fit: contain; border-radius: 50%;
  background: var(--surface-3);
}
.vendor-profile-name {
  grid-area: name;
  font-size: 17px; font-weight: 800; margin: 0;
  max-width: 100%;
  word-break: break-word; overflow-wrap: anywhere;
  text-align: left; line-height: 1.2;
  align-self: end;
}
.vendor-profile-code {
  grid-area: code;
  font-size: 12px; color: var(--text-mute); margin: 0;
  max-width: 100%;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  align-self: start;
}
.vendor-profile-follow {
  grid-area: follow;
  appearance: none;
  border: none;
  outline: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 76px;
  height: 32px;
  padding: 0 16px;
  margin: 0;
  font-size: 13px;
  font-weight: 700;
  color: #fff;
  background: #FE2C55;
  border-radius: 16px;
  transition: background .2s, color .2s, transform .1s;
}
.vendor-profile-follow:active {
  transform: scale(0.97);
}
.vendor-profile-follow.followed {
  background: var(--surface-2);
  color: var(--text);
}
.vendor-profile-stats {
  grid-area: stats;
  display: flex; gap: 18px; margin-top: 3px;
}
.vendor-stat {
  display: flex; flex-direction: row; align-items: baseline; gap: 4px;
}
.vendor-stat strong {
  font-size: 14px; font-weight: 800;
}
.vendor-stat span {
  font-size: 11px; color: var(--text-mute);
}

.vendor-profile-tabs {
  display: flex; border-bottom: 1px solid var(--border);
  position: sticky; top: 44px; z-index: 9; background: var(--panel-bg);
  overflow-x: auto; scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.vendor-profile-tabs::-webkit-scrollbar { display: none; }
.vendor-tab {
  flex: 1 1 0; min-width: 56px;
  display: flex; flex-direction: column; align-items: center; justify-content: flex-end;
  padding: 6px 8px 7px; background: none; border: none;
  border-bottom: 2px solid transparent;
  color: var(--text-mute); cursor: pointer; transition: all .2s;
  font-size: 13px; font-weight: 500; white-space: nowrap; gap: 3px;
}
.vendor-tab.active {
  color: var(--text); border-bottom-color: #FE2C55; font-weight: 700;
}
/* 游戏类型 tab 的图标 (emoji), 下方再叠加分类名文字 */
.vendor-tab .vt-ico {
  font-size: 19px; line-height: 1;
  filter: grayscale(0.15);
}
.vendor-tab.active .vt-ico { filter: none; }
/* 图标下方的分类名文字 (与图标同时显示) */
.vendor-tab .vt-label {
  font-size: 12px; line-height: 1.2;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis;
}
.vendor-tab .vt-count {
  font-size: 11px; color: var(--text-faint); font-weight: 400;
}

.vendor-games-grid {
  display: grid;
  /* minmax(0,1fr) 确保 grid item 能正常收缩，避免长内容撑爆列宽 */
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1px; padding: 0;
}
.vendor-game-card {
  aspect-ratio: 1/1; position: relative; overflow: hidden;
  cursor: pointer;
  /* 主题化: light 浅灰底 / dark 深色底; 内部 .vg-name 通过 currentColor
     继承容器 color (var(--text)), 跟随主题变化.
     2026-04-28: 用户要求"厂商页面要跟随日夜模式而变化", 撤销之前的
     "主题豁免 color:#fff", 改用变量. */
  background: var(--surface-2);
  color: var(--text);
  min-width: 0;
  /* contain: layout 进一步隔离子元素布局，防止溢出影响相邻卡片 */
  contain: layout paint;
}
/* 旧浏览器若不支持 aspect-ratio，给一个保底高度 */
@supports not (aspect-ratio: 1) {
  .vendor-game-card { padding-top: 100%; }
  .vendor-game-card > * { position: absolute; top: 0; left: 0; right: 0; bottom: 0; }
}
.vendor-game-card img {
  width: 100%; height: 100%;
  /* AFB 等厂商 LOGO 是 200x200/250x250 正方形，contain 完整显示，cover 会裁掉边缘文字 */
  object-fit: contain;
  background: var(--surface-3);
  display: block;
}
.vendor-game-card .vg-fallback {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  display: flex; align-items: center; justify-content: center;
  flex-direction: column; gap: 6px;
  font-weight: 700; color: var(--text);
  overflow: hidden;
  padding: 8px;
  box-sizing: border-box;
}
.vendor-game-card .vg-name {
  font-size: 11px; text-align: center;
  line-height: 1.3;
  /* text-shadow 仅在 dark 主题有意义 (深底白字防边缘融化), light 下取消 */
  text-shadow: 0 1px 3px rgba(0,0,0,.5);
  /* 限制 3 行省略，长英文单词允许任意位置换行 */
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  word-break: break-word;
  overflow-wrap: anywhere;
  max-width: 100%;
}
.vendor-game-card .vg-icon {
  font-size: 36px; line-height: 1;
  filter: drop-shadow(0 2px 4px rgba(0,0,0,.3));
  flex-shrink: 0;
}
.vendor-game-card .vg-initial {
  font-size: 28px; font-weight: 900;
}
.vendor-game-card .vg-overlay {
  position: absolute; bottom: 0; left: 0; right: 0;
  padding: 18px 6px 6px;
  background: linear-gradient(transparent, rgba(0,0,0,.78));
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 6px;
  pointer-events: none;
  box-sizing: border-box;
  max-width: 100%;
}
.vendor-game-card .vg-title {
  font-size: 11px; color: #fff; font-weight: 600;
  /* min-width:0 + flex:1 是 ellipsis 在 flex 容器中生效的关键 */
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.vendor-game-card .vg-badge {
  font-size: 9px; color: #FE2C55; font-weight: 700;
  background: rgba(255,255,255,.9); padding: 1px 4px;
  border-radius: 3px;
  flex-shrink: 0;
  white-space: nowrap;
}
.vendor-games-empty {
  grid-column: 1 / -1; text-align: center;
  color: #bbb; font-size: 14px; padding: 60px 0;
}
.vendor-games-loading {
  grid-column: 1 / -1; text-align: center;
  color: #999; font-size: 13px; padding: 32px 0;
}

/* Desktop 端把 vendor 页面变成居中 modal */
.vendor-page-backdrop {
  display: none;
  position: fixed; inset: 0;
  background: rgba(0, 0, 0, .65);
  -webkit-backdrop-filter: blur(6px);
          backdrop-filter: blur(6px);
  z-index: 999;
}

@media (min-width: 768px) {
  /* 桌面下整个 modal 自身可滚动；不使用内部 flex column，否则会把 grid 高度
     固定为剩余空间，aspect-ratio:1/1 失效，卡片被压成横条.
     2026-04-29: 之前 background / border-bottom 硬编码 #fff / #f0f0f0,
     dark 模式下 modal 上半部分仍是白底白字 (vendor name / tabs / counts
     全部不可见). 改用 var(--panel-bg) / var(--border) 跟随主题. */
  body:not(.is-mobile-device) .vendor-profile-page {
    position: fixed;
    top: 50%;
    left: 50%;
    right: auto;
    bottom: auto;
    transform: translate(-50%, -50%);
    width: 560px;
    max-width: calc(100vw - 40px);
    height: 82vh;
    max-height: 780px;
    border-radius: 16px;
    overflow-y: auto;
    overflow-x: hidden;
    box-shadow: 0 24px 80px rgba(0, 0, 0, .5);
    z-index: 1000;
    background: var(--panel-bg);
    color: var(--text);
    -webkit-overflow-scrolling: touch;
  }
  body:not(.is-mobile-device) .vendor-profile-topbar {
    position: sticky;
    top: 0;
    z-index: 5;
    background: var(--panel-bg);
    border-bottom: 1px solid var(--border);
    height: 48px;
  }
  body:not(.is-mobile-device) .vendor-profile-tabs {
    position: sticky;
    top: 48px;
    z-index: 4;
    background: var(--panel-bg);
    border-bottom: 1px solid var(--border);
  }
  body:not(.is-mobile-device) .vendor-profile-header {
    padding: 14px 20px;
  }
  /* 卡片网格：保持 3 列、正方形，让 modal 滚动而不是压缩 grid 高度 */
  body:not(.is-mobile-device) .vendor-games-grid {
    grid-auto-rows: auto;
    padding: 8px;
    gap: 8px;
  }
  body:not(.is-mobile-device) .vendor-game-card {
    border-radius: 8px;
  }
}

/* Login/Register Panels — shared base */
.login-panel {
  background: var(--panel-bg); color: var(--text);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
.login-panel .panel-header {
  border-bottom: 1px solid var(--border);
}
.login-panel .panel-header h3 { color: var(--text); }
.login-panel .panel-close { color: var(--text); }

.login-panel-logo {
  display: flex; align-items: center; justify-content: center;
  gap: 10px;
  padding: 24px 0 8px;
}
.login-panel-logo svg { width: 48px; height: 40px; flex-shrink: 0; }
.login-panel-brand {
  font-size: 20px; font-weight: 800; color: var(--text);
  letter-spacing: .5px;
}

/* 注: 上一轮 (2026-04-28 P2) 把 .login-panel-logo svg 在 light 下做成
   "渐变圆环 + 浅灰内圆 + ∞" 双环托盘. 用户复盘 (2026-04-28 P3): 登录页面
   不要双环托盘, 直接绿色 ∞ 即可 (圆环只在底部首页按钮 .nav-home-btn 上保留).
   → 已撤回, 这里不再写 light 覆盖, login-panel-logo svg 跨主题保持原 48×40
   透明背景的绿色 ∞ stroke 原样. */
/* 站点名为空（site_name 还没注入或后端没配）时，自动隐藏 span 并让 ∞ 完全居中 */
.login-panel-brand:empty { display: none; }

.login-form {
  padding: 24px 20px;
  display: flex; flex-direction: column; gap: 14px;
}
.login-field input, .login-field select {
  width: 100%; padding: 14px 16px;
  border: 1px solid var(--input-border); border-radius: 8px;
  font-size: 16px; outline: none; color: var(--text);
  background: var(--input-bg);
  -webkit-appearance: none;
  appearance: none;
  box-sizing: border-box;
}
.login-field select {
  background: var(--input-bg) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%23999' stroke-width='1.5' fill='none'/%3E%3C/svg%3E") no-repeat right 14px center;
  padding-right: 36px;
}
.login-field input:focus, .login-field select:focus {
  border-color: #FE2C55; background: var(--surface);
}
.login-submit-btn {
  width: 100%; padding: 14px 0;
  border: none; border-radius: 50px;
  background: #FE2C55; color: #fff;
  font-size: 16px; font-weight: 700; cursor: pointer;
  margin-top: 4px;
  transition: opacity .2s;
}
.login-submit-btn:hover { opacity: .88; }
.login-submit-register { background: #25F4EE; color: #161823; }
.login-submit-register:hover { opacity: .88; }

/* Quick Register */
.quick-reg-divider {
  display: flex; align-items: center; gap: 12px;
  color: var(--text-faint); font-size: 13px; margin: 2px 0;
}
.quick-reg-divider::before,
.quick-reg-divider::after {
  content: ''; flex: 1; height: 1px; background: var(--divider);
}
.quick-reg-btn {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: #fff;
  position: relative;
  overflow: hidden;
}
.quick-reg-btn:hover { opacity: .9; }

/* Quick Register Result */
.quick-reg-result {
  padding: 8px 24px 28px; text-align: center;
}
.quick-reg-icon { font-size: 48px; margin-bottom: 4px; }
.quick-reg-title {
  font-size: 20px; font-weight: 700; color: var(--text); margin-bottom: 6px;
}
.quick-reg-warn {
  font-size: 12px; color: #e74c3c; margin-bottom: 18px;
  background: rgba(231,76,60,.08); border-radius: 6px; padding: 8px 12px;
  line-height: 1.5;
}
.quick-reg-credentials {
  background: var(--surface-2); border-radius: 12px; padding: 16px 20px;
  margin-bottom: 18px; text-align: left;
}
.quick-reg-row {
  display: flex; justify-content: space-between; align-items: center;
  padding: 8px 0;
  /* 2026-06-01 问题9: 注册结果弹窗里账号较长时允许标签与值分两行, 避免被挤窄/溢出. */
  flex-wrap: wrap; gap: 4px 10px;
}
.quick-reg-row + .quick-reg-row { border-top: 1px solid var(--divider); }
.quick-reg-label { font-size: 13px; color: var(--text-mute); flex-shrink: 0; }
.quick-reg-value {
  font-size: 16px; font-weight: 700; color: var(--text);
  font-family: 'Courier New', monospace; letter-spacing: .5px;
  /* 长账号完整换行展示, 不截断 */
  word-break: break-all; overflow-wrap: anywhere;
  text-align: right; min-width: 0;
}
/* 2026-06-01 问题10: 引导一键注册会员设置好记登录名 */
.quick-reg-rename-tip {
  font-size: 12px; color: var(--text-mute); line-height: 1.5;
  margin: 4px 0 10px; text-align: left;
}
.quick-reg-rename-btn {
  background: rgba(102,126,234,.10); color: #667eea;
  border: 1.5px dashed #667eea !important;
  margin-bottom: 8px;
}
.quick-reg-rename-btn:hover { background: rgba(102,126,234,.16); opacity: 1; }
.quick-reg-copy-btn {
  background: var(--surface); color: #667eea;
  border: 2px solid #667eea !important;
  margin-bottom: 8px;
}
.quick-reg-copy-btn:hover { background: rgba(102,126,234,.08); opacity: 1; }
.quick-reg-save-img-btn {
  background: var(--surface); color: #4eebc8;
  border: 2px solid #4eebc8 !important;
  margin-bottom: 8px;
}
.quick-reg-save-img-btn:hover { background: rgba(78,235,200,.08); opacity: 1; }

#qrImagePreviewOverlay { z-index: 5200; }
.qr-img-preview-panel {
  position: relative;
  width: min(92vw, 420px);
  max-height: 92vh;
  background: var(--panel-bg, #1c1c1e);
  border: 1px solid var(--border, rgba(255,255,255,.08));
  border-radius: 18px;
  box-shadow: 0 24px 60px rgba(0,0,0,.55);
  overflow: hidden;
  display: flex; flex-direction: column;
}
.qr-img-preview-panel .panel-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 18px;
  border-bottom: 1px solid var(--border, rgba(255,255,255,.08));
}
.qr-img-preview-panel .panel-header h3 {
  margin: 0; font-size: 16px; color: var(--text, #fff); font-weight: 600;
}
/* 2026-05-06: panel-close 视觉已统一, 这里只保留 color 微调以匹配预览面板
   略柔的 tone; 尺寸/形状/hover 走全局规则. */
.qr-img-preview-panel .panel-close { color: var(--text-mute, rgba(255,255,255,.6)); }
.qr-img-preview-body {
  padding: 16px 18px 20px;
  overflow-y: auto;
  display: flex; flex-direction: column; align-items: stretch; gap: 12px;
}
.qr-img-preview-hint {
  margin: 0;
  font-size: 13px;
  color: var(--text-mute, rgba(255,255,255,.65));
  text-align: center;
  line-height: 1.5;
}
.qr-img-preview-wrap {
  background: rgba(0,0,0,.25);
  border-radius: 14px;
  padding: 8px;
  display: flex; justify-content: center;
  -webkit-touch-callout: default;
}
.qr-img-preview-wrap img {
  display: block;
  width: 100%;
  max-width: 320px;
  height: auto;
  border-radius: 10px;
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: default;
}
#qrImagePreviewDownload { margin-top: 4px; }
.login-footer {
  text-align: center; padding: 0 20px 24px;
  font-size: 14px; color: var(--text-mute);
}
.login-to-register {
  background: none; border: none; color: #FE2C55;
  font-size: 14px; font-weight: 600; cursor: pointer;
}
.login-to-register:hover { text-decoration: underline; }

/* ── Mobile: bottom sheet ── */
@media (max-width: 767px) {
  .login-panel {
    position: absolute;
    bottom: 0; left: 0; right: 0;
    border-radius: 16px 16px 0 0;
    transform: translateY(100%);
    transition: transform .35s cubic-bezier(.32,.72,.37,1.12);
    padding-bottom: env(safe-area-inset-bottom, 20px);
    max-height: 92vh;
  }
  .overlay.active .login-panel { transform: translateY(0); }
  .login-panel-logo { padding: 16px 0 4px; }
}

/* ── Desktop: centered modal ── */
@media (min-width: 768px) {
  body:not(.is-mobile-device) .login-panel {
    position: absolute;
    top: 50%; left: 50%;
    transform: translate(-50%, -50%) scale(.9);
    opacity: 0;
    width: 420px;
    max-width: 90vw;
    border-radius: 12px;
    box-shadow: 0 12px 48px rgba(0,0,0,.25);
    transition: transform .3s cubic-bezier(.32,.72,.37,1.12), opacity .3s ease;
  }
  body:not(.is-mobile-device) .overlay.active .login-panel {
    transform: translate(-50%, -50%) scale(1);
    opacity: 1;
  }
  body:not(.is-mobile-device) .login-form { padding: 28px 32px; gap: 16px; }
  body:not(.is-mobile-device) .login-field input,
  body:not(.is-mobile-device) .login-field select {
    padding: 15px 18px;
    border-radius: 10px;
  }
  body:not(.is-mobile-device) .login-submit-btn {
    padding: 15px 0;
    font-size: 16px;
    margin-top: 8px;
  }
  body:not(.is-mobile-device) .login-footer { padding: 0 32px 28px; font-size: 14px; }
  body:not(.is-mobile-device) .login-panel .panel-header { padding: 20px 28px; }
}

.profile-bottom-nav {
  background: var(--panel-bg);
  border-top: 1px solid var(--border);
  backdrop-filter: none;
}
.profile-bottom-nav .nav-item { color: var(--text-mute); }
.profile-bottom-nav .nav-item.active { color: var(--text); }
.profile-bottom-nav .nav-item svg { stroke: currentColor; }
.profile-bottom-nav .nav-home-btn .home-btn-wrap::before { background: var(--surface-2); }
.profile-bottom-nav .nav-home-btn .home-btn-wrap .home-logo-svg { stroke: #43A047; fill: none; }
.profile-bottom-nav .nav-home-btn .home-btn-wrap .home-currency-icon { color: var(--text); }

@media (min-width: 768px) {
  body:not(.is-mobile-device) .profile-page { display: none !important; }
}

/* ======================================================
   FINANCE PANELS (Deposit / Withdraw / Transfer)
   ====================================================== */
.finance-overlay { z-index: 250; }
.finance-panel {
  background: #fff; border-radius: 16px 16px 0 0;
  position: absolute; bottom: 0; left: 0; right: 0;
  /* 移动端: 充值/提现/转账/记录 等抽屉统一 2/3 屏高 (≈66.66vh),
     避免每个抽屉根据内容自适应导致大小忽高忽低、用户视觉混乱.
     - height 固定; max-height 兜底极小屏 (例如 iPhone SE 横屏)
     - 内容超出由 .finance-body 内部滚动 */
  height: 66vh;
  max-height: 92vh;
  min-height: 420px;
  display: flex; flex-direction: column;
  transform: translateY(100%);
  transition: transform .35s cubic-bezier(.32,.72,.37,1.12);
}
.overlay.active .finance-panel {
  transform: translateY(0);
}
.finance-panel .panel-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 16px 8px; border-bottom: 1px solid #f0f0f0;
  flex-shrink: 0;
}
.finance-panel .panel-header h3 {
  font-size: 17px; font-weight: 700; color: #161823; margin: 0;
}
/* 2026-05-06: 之前这里给 .finance-panel .panel-close 单独覆盖了 24px 文字 ×
   + #999 颜色, 与全局 .panel-close 不一致. 现在 .panel-close 已经在
   "Unified overlay header buttons" 里统一为 SVG × + 36×36 圆形 hover, 这条
   单独覆盖反而会破坏统一, 所以移除. 原大小通过通用规则承袭即可. */
.finance-body {
  padding: 12px 16px 16px; overflow-y: auto; -webkit-overflow-scrolling: touch;
  flex: 1; min-height: 0;
}
.finance-loading {
  text-align: center; padding: 40px 0; color: #999; font-size: 14px;
}
.msg-tabs {
  display: flex; gap: 0; border-bottom: 1px solid #f0f0f0;
  padding: 0 20px;
}
.msg-tab {
  background: none; border: none; border-bottom: 2px solid transparent;
  padding: 10px 12px; font-size: 13px; font-weight: 600;
  color: #999; cursor: pointer; white-space: nowrap;
  transition: color .2s, border-color .2s;
}
.msg-tab.active { color: #161823; border-bottom-color: #FE2C55; }

/* 2026-05-23 消息中心 tab 胶囊 (.msg-filter*) — 之前 HTML 已经把 button 的
   class 改成了 .msg-filter 但 CSS 完全没规则, 导致截图里的"全部 未读 财务
   活动 返水 登录 系统"挤在一起、没间距、没视觉胶囊 (用户反馈图1).
   设计与 promo / category 胶囊统一: 灰底圆胶囊 + active 红底白字, gap 间距,
   横向溢出可滑动 (-webkit-overflow-scrolling 让 iOS 顺滑). divider 在
   "全部/未读" 与业务类别之间画一道竖线区隔, 强化"通用入口 vs 业务大类"分组. */
.msg-filter-bar {
  display: flex; align-items: center; gap: 8px;
  /* 2026-06-08 问题12: 在 .finance-panel 这个 flex 列里筛选栏必须 flex-shrink:0,
     否则窄屏/固定高度时被压扁; 末尾留 padding-right 给"系统"胶囊滚动余量,
     避免最后一项被裁切/看似被遮挡. */
  padding: 10px 24px 4px 16px;
  flex-shrink: 0;
  position: relative; z-index: 1;
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.msg-filter-bar::-webkit-scrollbar { display: none; }
/* 桌面端抽屉宽度有限(420px)放不下8个胶囊, 允许换行让"系统"等末项完整可见;
   移动端仍保持单行横滑. (问题12) */
body:not(.is-mobile-device) .msg-filter-bar {
  flex-wrap: wrap; overflow-x: visible;
}
.msg-filter {
  background: #f3f4f6;
  color: #4b5563;
  border: 1px solid transparent;
  border-radius: 999px;
  padding: 6px 14px;
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  flex: 0 0 auto;
  transition: background .15s, color .15s, border-color .15s, transform .1s;
}
.msg-filter:hover:not(.active) { background: #e5e7eb; color: #111827; }
.msg-filter:active { transform: scale(.96); }
.msg-filter.active {
  background: #FE2C55;
  color: #fff;
  border-color: #FE2C55;
  box-shadow: 0 2px 6px rgba(254,44,85,.25);
}
.msg-filter-divider {
  display: inline-block;
  width: 1px; height: 14px;
  background: #e5e7eb;
  margin: 0 2px;
  flex: 0 0 auto;
}
:root[data-theme="dark"] .msg-filter {
  background: rgba(255,255,255,.06); color: rgba(255,255,255,.72);
}
:root[data-theme="dark"] .msg-filter:hover:not(.active) {
  background: rgba(255,255,255,.10); color: #fff;
}
:root[data-theme="dark"] .msg-filter.active {
  background: #FE2C55; color: #fff; border-color: #FE2C55;
}
:root[data-theme="dark"] .msg-filter-divider { background: rgba(255,255,255,.12); }

/* 移动端：消息中心面板固定为屏幕 2/3 高度，切 tab（系统消息 / 存款 / 提款）
   时整体高度不变 — 列表多则 .finance-body 内部滚动，列表少则下方留白；
   避免出现"系统消息高、存取款低"导致抽屉跳来跳去的不稳定观感。
   桌面端走 body:not(.is-mobile-device) .finance-panel 抽屉规则，不受此影响。 */
body.is-mobile-device #messagesOverlay .finance-panel {
  height: 66.6667vh !important;
  max-height: 66.6667vh !important;
  min-height: 66.6667vh !important;
}
.msg-item {
  display: flex; gap: 12px; padding: 12px 0;
  border-bottom: 1px solid #f5f5f5;
}
.msg-item-icon {
  width: 36px; height: 36px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0; font-size: 16px;
}
.msg-item-icon.sys { background: #e3f2fd; color: #1976d2; }
.msg-item-icon.deposit { background: #e8f5e9; color: #388e3c; }
.msg-item-icon.withdraw { background: #fff3e0; color: #f57c00; }
.msg-item-body { flex: 1; min-width: 0; }
.msg-item-title { font-size: 13px; font-weight: 600; color: #333; }
.msg-item-desc { font-size: 12px; color: #999; margin-top: 2px; }
.msg-item-time { font-size: 11px; color: #bbb; margin-top: 4px; }
.msg-empty { text-align: center; padding: 40px 0; color: #bbb; font-size: 13px; }

/* 系统消息：未读高亮 + 行内「标为已读」按钮、顶部「全部已读」工具条
   后端 GetMessages 返回 is_read=false 的项时打 .msg-unread，行内按钮调
   POST /member/messages/:id/read，工具条按钮调 /messages/read-all */
.msg-item.msg-unread {
  background: #fffafb;
  border-bottom-color: #fde2e7;
  position: relative;
  padding-left: 8px;
}
.msg-item.msg-unread::before {
  content: '';
  position: absolute;
  left: 0; top: 16px;
  width: 4px; height: 4px; border-radius: 50%;
  background: #FE2C55;
  box-shadow: 0 0 6px rgba(254,44,85,.55);
}
.msg-item-actions {
  margin-top: 8px;
  display: flex; gap: 8px; flex-wrap: wrap;
}
.msg-read-btn {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 5px 10px;
  background: #fff; color: #FE2C55;
  border: 1px solid #FE2C55; border-radius: 6px;
  font-size: 12px; font-weight: 600;
  cursor: pointer;
  transition: background .15s, color .15s, transform .1s;
}
.msg-read-btn:hover:not(:disabled) { background: #FE2C55; color: #fff; }
.msg-read-btn:active:not(:disabled) { transform: scale(.95); }
.msg-read-btn:disabled { opacity: .5; cursor: not-allowed; }
.msg-read-btn svg { display: block; }

.msg-toolbar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px;
  padding: 10px 0 8px;
  margin-bottom: 4px;
  border-bottom: 1px solid #f0f0f0;
}
.msg-toolbar-info { font-size: 12px; color: #666; }
.msg-toolbar-info b { font-weight: 700; }
.msg-readall-btn {
  padding: 6px 12px;
  background: linear-gradient(135deg, #FE2C55, #ff5274);
  color: #fff; border: 0; border-radius: 8px;
  font-size: 12px; font-weight: 700;
  cursor: pointer;
  box-shadow: 0 2px 8px rgba(254,44,85,.25);
  transition: transform .1s, box-shadow .15s;
}
.msg-readall-btn:hover:not(:disabled) { box-shadow: 0 4px 14px rgba(254,44,85,.35); }
.msg-readall-btn:active:not(:disabled) { transform: scale(.96); }
.msg-readall-btn:disabled { opacity: .6; cursor: not-allowed; }

/* === 提现 - 洗码未达标拦截面板 ===
   /finance/turnover-check 返回 can_withdraw=false 时渲染，列出每条
   未完成的洗码要求 + 进度条 + 还需流水。让用户在填表前就知道情况。 */
.fin-turnover-block { padding: 4px 0 12px; }
.fin-turnover-banner {
  display: flex; flex-direction: column; align-items: center;
  background: linear-gradient(135deg, #fff5f7 0%, #ffe4ea 100%);
  border: 1px solid #ffd2da;
  border-radius: 12px;
  padding: 14px 16px;
  margin-bottom: 14px;
  text-align: center;
}
.fin-turnover-icon {
  width: 36px; height: 36px;
  border-radius: 50%;
  background: #FE2C55;
  color: #fff;
  font-size: 22px; font-weight: 800; line-height: 36px;
  margin-bottom: 8px;
}
.fin-turnover-title { font-size: 15px; font-weight: 700; color: #333; margin-bottom: 4px; }
.fin-turnover-subtitle { font-size: 13px; color: #666; }
.fin-turnover-subtitle b { color: #FE2C55; font-weight: 700; font-variant-numeric: tabular-nums; }
.fin-turnover-list { display: flex; flex-direction: column; gap: 10px; margin-bottom: 14px; }
.fin-turnover-item {
  background: #fafafa;
  border: 1px solid #eee;
  border-radius: 10px;
  padding: 10px 12px;
}
.fin-turnover-row {
  display: flex; justify-content: space-between; align-items: center;
  font-size: 13px;
}
.fin-turnover-name { font-weight: 600; color: #333; }
.fin-turnover-progress-text { color: #FE2C55; font-weight: 700; font-variant-numeric: tabular-nums; }
.fin-turnover-meta { font-size: 11px; color: #999; margin-top: 2px; }
.fin-turnover-bar {
  height: 6px; border-radius: 3px;
  background: #eee;
  overflow: hidden;
  margin: 8px 0 6px;
}
.fin-turnover-bar-fill {
  height: 100%;
  background: linear-gradient(90deg, #FE2C55, #ff6b85);
  border-radius: 3px;
  transition: width .3s;
}
.fin-turnover-amounts { font-size: 12px; color: #666; }
.fin-turnover-remaining { color: #FE2C55; font-weight: 600; font-variant-numeric: tabular-nums; }
.fin-submit-btn-secondary {
  background: linear-gradient(135deg, #444, #666) !important;
  color: #fff !important;
}

/* Channel grid (旧布局, 暂保留以防其他地方引用) */
.fin-section-title { font-size: 13px; font-weight: 500; color: #333; margin: 0 0 6px; }
/* 2026-05-01 优惠区移到提交按钮下方时, 跟按钮拉开间距 + 给标题加上"温和"提示色 */
.fin-promo-section-title {
  margin-top: 18px !important;
  font-weight: 500 !important;
  color: #6b7280 !important;
}
.fin-channel-grid {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; margin-bottom: 8px;
}
.fin-channel-card {
  border: 2px solid #eee; border-radius: 8px; padding: 6px 4px;
  text-align: center; cursor: pointer; transition: all .2s; background: #fafafa;
}
.fin-channel-card.active { border-color: #FE2C55; background: #fff5f7; }
.fin-channel-card-name { font-size: 12px; font-weight: 500; color: #333; margin-bottom: 2px; }
.fin-channel-card-limit { font-size: 10px; color: #999; }

/* 充值新布局 (2026-04-23 v2 满屏版):
   ┌──────────────────────────────────────────┐
   │ 通道列表 (左)  │  银行信息 (右)            │  ← .fin-channel-bank, 仅顶部
   ├──────────────────────────────────────────┤
   │ 优惠 / 金额 / 备注 / 凭证 / 提交 (全宽)    │  ← .fin-form-area, 满宽单列
   └──────────────────────────────────────────┘
   - 通道列固定宽 (手机 96px / 桌面 140px), 内部纵向滚动
   - 银行信息占满剩余宽度
   - 表单区从下面起单列全宽, 输入框/上传框拉到最大
   - 通道列里的 .fin-channel-card 改成"窄横条 / 左对齐", 区别于旧 grid 模式 */
.fin-deposit-layout {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.fin-channel-bank {
  display: flex;
  gap: 10px;
  align-items: stretch;
  margin-bottom: 0;
}
.fin-channel-list {
  flex: 0 0 96px;
  display: flex; flex-direction: column; gap: 6px;
  max-height: 280px; overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
.fin-channel-list .fin-channel-card {
  text-align: left;
  padding: 8px 8px;
}
.fin-bank-area {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column;
}
.fin-bank-area .fin-bank-info { margin-bottom: 0; height: 100%; box-sizing: border-box; }
.fin-bank-empty {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; gap: 4px;
  color: #999; font-size: 12px;
}
.fin-bank-empty-title { font-size: 13px; font-weight: 500; color: #555; }
.fin-bank-empty-sub   { font-size: 12px; color: #999; }
.fin-form-area {
  display: flex; flex-direction: column;
}

/* Bank info display */
.fin-bank-info {
  background: #f8f9fa; border-radius: 8px; padding: 6px 10px; margin-bottom: 8px;
  border: 1px solid #eee;
}
.fin-bank-row { display: flex; justify-content: space-between; padding: 3px 0; font-size: 12px; }
.fin-bank-label { color: #999; }
.fin-bank-value { color: #333; font-weight: 500; }
.fin-bank-value.copyable { color: #FE2C55; cursor: pointer; }
.fin-bank-value.copyable:active { opacity: .6; }

/* 三方在线收银台通道: 在线支付说明卡片 (替代银行账户区) */
.fin-bank-online {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; gap: 4px; height: 100%; box-sizing: border-box;
  background: #fff5f7; border: 1px solid #ffd7e0;
}
.fin-online-icon { font-size: 26px; line-height: 1; }
.fin-online-title { font-size: 13px; font-weight: 700; color: #FE2C55; }
.fin-online-sub   { font-size: 11px; color: #888; line-height: 1.5; }

/* 三方在线收银台通道: 支付方法选择器 (单选卡片) */
.fin-method-list { display: flex; flex-wrap: wrap; gap: 8px; }
.fin-method-card {
  flex: 0 0 auto; padding: 7px 12px; border: 1px solid #e5e7eb; border-radius: 8px;
  background: #fff; font-size: 12px; font-weight: 500; color: #333; cursor: pointer;
  user-select: none; transition: border-color .15s, background .15s, color .15s;
}
.fin-method-card.active { border-color: #FE2C55; background: #fff5f7; color: #FE2C55; }
.fin-method-card:active { opacity: .8; }

/* Form elements */
.fin-form-group { margin-bottom: 8px; }
.fin-form-label { display: block; font-size: 12px; font-weight: 500; color: #333; margin-bottom: 3px; }
.fin-form-hint { font-size: 10px; color: #999; margin-top: 2px; }
/* 充值表单"金额 + 备注"两列布局, 节省垂直空间, 让提交按钮在不滚动情况下尽量可见. */
.fin-form-row {
  display: grid; grid-template-columns: 1fr 1fr; gap: 8px;
}
.fin-form-row .fin-form-group { margin-bottom: 8px; }
.fin-input {
  width: 100%; padding: 8px 10px; border: 1.5px solid #e8e8e8; border-radius: 8px;
  font-size: 14px; background: #fafafa; outline: none; transition: border-color .2s;
  box-sizing: border-box;
}
.fin-input:focus { border-color: #FE2C55; background: #fff; }
.fin-select {
  width: 100%; padding: 10px 12px; border: 1.5px solid #e8e8e8; border-radius: 8px;
  font-size: 14px; background: #fafafa; outline: none; appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23999' stroke-width='2'%3E%3Cpolyline points='6,9 12,15 18,9'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 12px center;
  box-sizing: border-box;
}

/* 文件上传:
   - 占位状态: input 透明覆盖整框, 点哪都能弹文件选择
   - 预览状态: input 隐藏, 改由"移除"按钮回到占位态, 避免误触又弹文件选择 */
.fin-file-upload {
  border: 2px dashed #ddd; border-radius: 10px; padding: 12px;
  text-align: center; cursor: pointer; transition: border-color .2s;
  position: relative; overflow: hidden; min-height: 56px;
}
.fin-file-upload:hover { border-color: #FE2C55; }
.fin-file-upload input[type="file"] {
  position: absolute; top: 0; left: 0; width: 100%; height: 100%;
  opacity: 0; cursor: pointer; z-index: 1;
}
.fin-file-placeholder { padding: 12px 0; }
.fin-file-upload-text { font-size: 13px; color: #999; }
.fin-file-upload-name { font-size: 12px; color: #FE2C55; margin-top: 4px; word-break: break-all; }
/* 凭证预览缩略图: 选好图片后立刻在虚线框内显示.
   max 高度限制避免超长截图把整个表单顶下去, 内容超出由父容器滚动. */
.fin-file-preview-wrap {
  position: relative;
}
.fin-file-preview {
  display: block;
  width: 100%;
  max-height: 180px;
  object-fit: contain;
  border-radius: 8px;
  background: #f8f9fa;
}
.fin-file-clear {
  position: absolute;
  top: 6px; right: 6px;
  background: rgba(0, 0, 0, 0.6);
  color: #fff;
  border: none;
  font-size: 12px;
  padding: 4px 10px;
  border-radius: 14px;
  cursor: pointer;
  z-index: 5;
}
.fin-file-clear:hover { background: rgba(0, 0, 0, 0.8); }

/* 提交按钮 sticky 贴底: 滚动时始终可见, 不必再拉到底部找按钮. */
.fin-submit-bar {
  position: sticky;
  bottom: -1px;  /* -1 抵消 finance-body 底部 padding 抗锯齿缝隙 */
  background: linear-gradient(to bottom, rgba(255,255,255,0) 0%, #fff 30%, #fff 100%);
  padding: 10px 0 4px;
  margin-top: 8px;
  z-index: 4;
}
.fin-submit-btn {
  width: 100%; padding: 12px; border: none; border-radius: 10px;
  background: linear-gradient(135deg, #FE2C55, #ff6b81);
  color: #fff; font-size: 15px; font-weight: 600; cursor: pointer;
  transition: opacity .2s;
}
.fin-submit-btn:disabled { opacity: .5; cursor: not-allowed; }
.fin-submit-btn:not(:disabled):active { opacity: .8; }
/* 2026-05-01 inline 版本: 优惠区改放按钮下方, 不能再 sticky 贴底
   (会盖住下面的优惠卡), 用普通块级排版即可. */
.fin-submit-btn-inline { margin-top: 10px; margin-bottom: 4px; }

/* 提现页"洗码状态"卡片: 提现按钮上方常驻显示总洗码值/已完成/还需 + 进度条,
   整卡可点击 → 弹出 showTurnoverCheckModal 看明细. */
.fin-turnover-card {
  margin: 14px 0 6px;
  padding: 12px 14px;
  border: 1px solid #ffd2da;
  border-radius: 12px;
  background: linear-gradient(135deg, #fff8f9 0%, #fff0f3 100%);
  cursor: pointer;
  transition: box-shadow .2s, transform .1s;
}
.fin-turnover-card:hover { box-shadow: 0 4px 12px rgba(254, 44, 85, 0.12); }
.fin-turnover-card:active { transform: scale(0.995); }
.fin-turnover-card[data-state="done"] {
  border-color: #bbf7d0;
  background: linear-gradient(135deg, #f0fdf4 0%, #dcfce7 100%);
}
.fin-turnover-card[data-state="empty"] {
  border-color: #e5e7eb;
  background: #fafafa;
}
.fin-turnover-card-head {
  display: flex; justify-content: space-between; align-items: center;
  margin-bottom: 10px;
}
.fin-turnover-card-title { font-size: 13px; font-weight: 700; color: #333; }
.fin-turnover-card-link { font-size: 12px; color: #FE2C55; font-weight: 600; }
.fin-turnover-card[data-state="done"] .fin-turnover-card-link { color: #16a34a; }
.fin-turnover-card-grid {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-bottom: 10px;
}
.fin-turnover-card-label { font-size: 11px; color: #888; margin-bottom: 2px; }
.fin-turnover-card-val {
  font-size: 15px; font-weight: 700; color: #333;
  font-variant-numeric: tabular-nums;
}
.fin-turnover-card-val-done { color: #16a34a; }
.fin-turnover-card-val-pending { color: #FE2C55; }
.fin-turnover-card-bar {
  height: 6px; border-radius: 3px;
  background: rgba(0, 0, 0, 0.06);
  overflow: hidden; margin-bottom: 8px;
}
.fin-turnover-card-bar-fill {
  height: 100%; border-radius: 3px;
  transition: width .3s ease;
}
.fin-turnover-card-status {
  font-size: 12px; font-weight: 600; text-align: center;
}
.fin-turnover-card-status-ok { color: #16a34a; }
.fin-turnover-card-status-pending { color: #FE2C55; }
.fin-turnover-card-empty { text-align: center; padding: 4px 0; }
.fin-turnover-card-ok { color: #16a34a; font-size: 13px; font-weight: 600; }

/* 提现金额输入框下方的 VIP 限额 chip 行 (单笔上限 / 今日剩余次数 / 今日剩余金额).
   后台 2.2「会员类型管理」配的限额, GET /finance/withdraw-limits 拉取后渲染.
   chip 自带圆角灰底, 超限态 .over 飘红 + 加粗, 让用户填金额时一眼能看到拦截原因. */
.fin-wd-limits {
  display: flex; flex-wrap: wrap; gap: 6px;
  margin-top: 6px;
}
.fin-wd-limits:empty { display: none; }
.fin-wd-chip {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 4px 10px;
  background: #f4f5f7;
  border: 1px solid #e5e7eb;
  border-radius: 999px;
  font-size: 11px;
  color: #555;
  font-variant-numeric: tabular-nums;
  line-height: 1.3;
  transition: background .15s, color .15s, border-color .15s;
}
.fin-wd-chip em {
  font-style: normal;
  color: #888;
  font-weight: 500;
}
.fin-wd-chip.over {
  background: #fff1f0;
  border-color: #fda4af;
  color: #dc2626;
  font-weight: 700;
}
.fin-wd-chip.over em { color: #dc2626; }

/* "实际到账"预览块: 仅当 fee_rate > 0 且会员填了金额时显示, 大字号绿色突出最终
   银行收到的金额, 小字标注被扣的手续费金额 + 费率. 与 ngapi 后端 round 同口径. */
.fin-wd-fee-preview {
  margin-top: 8px;
  padding: 10px 12px;
  border: 1px solid #bbf7d0;
  border-radius: 10px;
  background: linear-gradient(135deg, #f0fdf4 0%, #dcfce7 100%);
}
.fin-wd-fee-preview:empty { display: none; }
.fin-wd-fee-row {
  display: flex; justify-content: space-between; align-items: baseline;
}
.fin-wd-fee-label { font-size: 12px; color: #15803d; font-weight: 600; }
.fin-wd-fee-real {
  font-size: 18px; font-weight: 800; color: #15803d;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.2px;
}
.fin-wd-fee-sub {
  font-size: 11px; color: #6b7280;
  margin-top: 2px;
  font-variant-numeric: tabular-nums;
}

/* ===== 洗码检查弹窗 (showTurnoverCheckModal) =====
   设计参考 nova31, 适配 nova39 finance-panel 亮色主题.
   独立于 .overlay 体系, 用 fixed 自管 z-index, 避免与现有
   _OVERLAY_KEEP_OPEN / _closeAllSecondaryPanels 互斥逻辑冲突
   (它本身就是从 #withdrawOverlay 之上弹出的"二级弹窗"). */
.tc-modal-overlay {
  position: fixed; inset: 0; z-index: 11000;
  display: flex; align-items: center; justify-content: center;
  background: rgba(0, 0, 0, .5);
  opacity: 0; transition: opacity .24s ease;
  padding: 16px;
}
.tc-modal-overlay.tc-modal-show { opacity: 1; }
.tc-modal {
  background: #fff; border-radius: 16px;
  width: min(500px, 100%); max-height: 88vh;
  display: flex; flex-direction: column;
  box-shadow: 0 16px 48px rgba(0, 0, 0, .25);
  overflow: hidden;
}
.tc-modal-head {
  display: flex; align-items: center; gap: 12px;
  padding: 14px 18px;
  border-bottom: 1px solid #e5e7eb;
  flex-shrink: 0;
}
.tc-head-icon {
  width: 36px; height: 36px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  color: #fff; font-size: 16px; font-weight: 800;
  flex-shrink: 0;
}
.tc-head-text { flex: 1; min-width: 0; }
.tc-head-title { font-size: 16px; font-weight: 700; color: #111827; }
.tc-head-sub { font-size: 12px; font-weight: 600; margin-top: 2px; }
.tc-modal-close {
  background: none; border: none; padding: 4px 8px;
  font-size: 22px; line-height: 1; color: #9ca3af; cursor: pointer;
}
.tc-modal-banner {
  padding: 8px 18px; font-size: 13px; font-weight: 600;
  border-bottom: 1px solid #e5e7eb; flex-shrink: 0;
}
.tc-modal-body {
  flex: 1; overflow-y: auto;
  padding: 14px 18px;
  -webkit-overflow-scrolling: touch;
}
.tc-modal-foot {
  padding: 12px 18px; border-top: 1px solid #e5e7eb;
  flex-shrink: 0;
}
.tc-modal-ok { color: #fff; }

.tc-card {
  border: 1px solid #e5e7eb; border-radius: 12px;
  margin-bottom: 12px; overflow: hidden; background: #fff;
}
.tc-card:last-child { margin-bottom: 0; }
.tc-card-head {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 14px 8px;
  background: #f9fafb; border-bottom: 1px solid #e5e7eb;
}
.tc-pill {
  font-size: 11px; font-weight: 600;
  padding: 2px 8px; border-radius: 4px;
  background: #f3f4f6; color: #374151;
}
.tc-pill-bonus { background: #fef9c3; color: #854d0e; }
.tc-pill-deposit { background: #eff6ff; color: #1e40af; }
.tc-pill-promo_record { background: #f3e8ff; color: #6b21a8; }
.tc-status {
  margin-left: auto;
  font-size: 11px; font-weight: 700;
  padding: 2px 10px; border-radius: 999px;
}
.tc-status-done { background: #dcfce7; color: #15803d; }
.tc-status-pending { background: #fee2e2; color: #b91c1c; }
.tc-card-name {
  padding: 8px 14px 4px;
  font-size: 14px; font-weight: 700; color: #111827;
}
.tc-grid {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: 1px; background: #e5e7eb;
  margin: 4px 0;
}
.tc-grid > div {
  background: #fff; padding: 8px 4px; text-align: center;
}
.tc-grid-label { font-size: 11px; color: #6b7280; margin-bottom: 2px; }
.tc-grid-val {
  font-size: 14px; font-weight: 700; color: #374151;
  font-variant-numeric: tabular-nums;
}
.tc-grid-val-done { color: #16a34a; }
.tc-bar {
  margin: 8px 14px 4px;
  height: 6px; background: #e5e7eb; border-radius: 999px; overflow: hidden;
}
.tc-bar-fill { height: 100%; transition: width .3s ease; }
.tc-progress-text {
  padding: 0 14px 8px;
  text-align: right; font-size: 11px; color: #6b7280;
  font-variant-numeric: tabular-nums;
}
.tc-meta {
  border-top: 1px dashed #e5e7eb;
  padding: 8px 14px 12px;
}
.tc-meta-row {
  display: flex; justify-content: space-between;
  padding: 3px 0;
  font-size: 12px;
}
.tc-meta-row span:first-child { color: #6b7280; }
.tc-meta-row span:last-child { color: #374151; font-weight: 600; }

/* 移动端: 操作行竖排, 弹窗占满 */
@media (max-width: 480px) {
  .fin-turnover-card-grid { gap: 6px; }
  .fin-turnover-card-val { font-size: 14px; }
  .tc-modal { width: 100%; max-height: 90vh; }
}

/* Wallet cards (transfer) */
.fin-wallet-list { display: flex; flex-direction: column; gap: 10px; }
.fin-wallet-card {
  background: #f8f9fa; border-radius: 10px; padding: 14px;
  display: flex; align-items: center; justify-content: space-between;
  border: 1px solid #eee;
}
.fin-wallet-card.main { background: linear-gradient(135deg, #fff5f7, #fff); border-color: #FE2C55; }
.fin-wallet-name { font-size: 14px; font-weight: 600; color: #333; }
.fin-wallet-balance { font-size: 16px; font-weight: 700; color: #FE2C55; }
.fin-wallet-transfer-btn {
  padding: 6px 14px; border: none; border-radius: 6px;
  background: #FE2C55; color: #fff; font-size: 12px; font-weight: 600;
  cursor: pointer; transition: opacity .2s;
}
.fin-wallet-transfer-btn:disabled { opacity: .5; cursor: not-allowed; }

/* Promo cards */
.fin-promo-list { display: flex; flex-direction: column; gap: 6px; margin-bottom: 10px; }
.fin-promo-card {
  border: 1.5px solid #eee; border-radius: 8px; padding: 10px 12px; cursor: pointer;
  transition: all .2s; display: flex; align-items: center; gap: 10px;
}
.fin-promo-card.active { border-color: #FE2C55; background: #fff5f7; }
.fin-promo-radio {
  width: 18px; height: 18px; border: 2px solid #ccc; border-radius: 50%;
  flex-shrink: 0; position: relative;
}
.fin-promo-card.active .fin-promo-radio {
  border-color: #FE2C55;
}
.fin-promo-card.active .fin-promo-radio::after {
  content: ''; position: absolute; top: 3px; left: 3px;
  width: 8px; height: 8px; border-radius: 50%; background: #FE2C55;
}
.fin-promo-text { flex: 1; min-width: 0; }
.fin-promo-name { font-size: 13px; color: #333; font-weight: 500; }
.fin-promo-desc { font-size: 11px; color: #999; margin-top: 2px; }
.fin-promo-bonus {
  flex-shrink: 0;
  font-size: 13px; font-weight: 600; color: #FE2C55;
  padding: 4px 10px; border-radius: 999px;
  background: linear-gradient(135deg, rgba(254,44,85,.12), rgba(254,44,85,.04));
  border: 1px solid rgba(254,44,85,.18);
  font-variant-numeric: tabular-nums;
}

/* 2026-05-01 充值页 active_bonus 横幅 — 用户已有进行中的优惠时,
   提示放弃才能换新优惠. 跟 nova31 同款红色警示卡, 自适应 light/dark 主题. */
.fin-active-bonus {
  background: rgba(254,44,85,.08);
  border: 1px solid rgba(254,44,85,.25);
  border-radius: 10px;
  padding: 10px 12px;
  margin-bottom: 12px;
}
.fin-ab-title {
  font-size: 11px; font-weight: 500; color: #FE2C55;
  text-transform: uppercase; letter-spacing: .5px; margin-bottom: 4px;
}
.fin-ab-name {
  font-size: 13px; font-weight: 500; color: var(--text, #161823);
  margin-bottom: 4px; word-break: break-all;
}
.fin-ab-meta {
  font-size: 11px; color: var(--text-muted, #6b7280);
  font-variant-numeric: tabular-nums;
}
.fin-ab-bar {
  margin-top: 6px;
  height: 5px; border-radius: 3px; background: rgba(0,0,0,.08); overflow: hidden;
}
.fin-ab-fill { height: 100%; background: linear-gradient(90deg, #FE2C55, #FF6B81); }
.fin-ab-hint {
  margin-top: 6px;
  font-size: 11px; color: rgba(217,42,80,.85);
  line-height: 1.5;
}
:root[data-theme="dark"] .fin-active-bonus { background: rgba(254,44,85,.12); }
:root[data-theme="dark"] .fin-ab-bar       { background: rgba(255,255,255,.08); }
:root[data-theme="dark"] .fin-ab-meta      { color: rgba(255,255,255,.6); }

/* Bank card management */
.fin-card-list { display: flex; flex-direction: column; gap: 8px; margin-bottom: 16px; }
.fin-bank-card-item {
  border: 1.5px solid #eee; border-radius: 10px; padding: 12px;
  display: flex; align-items: center; gap: 10px; cursor: pointer; transition: all .2s;
}
.fin-bank-card-item.active { border-color: #FE2C55; background: #fff5f7; }
.fin-bank-card-icon {
  width: 36px; height: 36px; border-radius: 8px; background: #f0f0f0;
  display: flex; align-items: center; justify-content: center;
  font-size: 16px; font-weight: 700; color: #666;
}
.fin-bank-card-info { flex: 1; }
.fin-bank-card-name { font-size: 13px; font-weight: 500; color: #333; }
.fin-bank-card-num { font-size: 12px; color: #999; }
.fin-add-card-btn {
  width: 100%; padding: 12px; border: 2px dashed #ddd; border-radius: 10px;
  background: none; cursor: pointer; font-size: 14px; color: #999;
  transition: all .2s; margin-bottom: 16px;
}
.fin-add-card-btn:hover { border-color: #FE2C55; color: #FE2C55; }

/* Add card form */
.fin-add-card-form { margin-bottom: 16px; padding: 14px; background: #f8f9fa; border-radius: 10px; }
.fin-bank-search-wrap { position: relative; }
.fin-bank-suggestions {
  position: absolute; top: 100%; left: 0; right: 0; z-index: 10;
  background: #fff; border: 1px solid #ddd; border-radius: 0 0 8px 8px;
  max-height: 160px; overflow-y: auto; box-shadow: 0 4px 12px rgba(0,0,0,.12);
}
.fin-bank-suggestion {
  padding: 10px 14px; font-size: 13px; cursor: pointer;
  border-bottom: 1px solid #f0f0f0; color: #333;
}
.fin-bank-suggestion:hover { background: #f0f0f0; color: #000; }

/* Desktop — 个人中心相关弹窗改成"左侧抽屉"，贴左侧导航栏右边显示，
   不遮盖游戏画面，玩家可继续看/操作游戏 */
@media (min-width: 768px) {
  /* overlay 不再做整屏黑色 mask，也不拦截事件；仅靠抽屉本体提供视觉聚焦 */
  body:not(.is-mobile-device) .finance-overlay,
  body:not(.is-mobile-device) .finance-overlay.active {
    background: transparent;
    pointer-events: none;
  }

  body:not(.is-mobile-device) .finance-panel {
    position: fixed;
    top: 0; bottom: 0;
    left: var(--dt-sidebar-w, 240px);
    right: auto;
    width: 420px;
    max-height: none;
    height: 100vh; /* 旧浏览器兜底 */
    height: 100dvh; /* 折叠屏/移动工具栏: 用动态视口高度, 避免内容被截 */
    border-radius: 0 14px 14px 0;
    box-shadow: 8px 0 28px rgba(0,0,0,.35);
    transform: translateX(-100%);
    opacity: 1;
    transition: transform .32s cubic-bezier(.32,.72,.37,1.12);
    /* ★ 关键 fix：默认 pointer-events:none —— 抽屉收起后虽然 transform:translateX(-100%)
       视觉上移出，但起点 left:240px + width:420px 后实际占据 (-180, 240)，
       右边缘正好覆盖 sidebar (0~240)。pointer-events:auto 会让收起的抽屉静默吞掉
       sidebar 上所有 click。改为 .active 时才 auto，彻底放过 sidebar。 */
    pointer-events: none;
  }
  body:not(.is-mobile-device) .overlay.active .finance-panel {
    transform: translateX(0);
    pointer-events: auto;
  }
  body:not(.is-mobile-device) .finance-body {
    max-height: none;
    flex: 1; min-height: 0;
  }
  body:not(.is-mobile-device) .fin-channel-grid { grid-template-columns: repeat(3, 1fr); }

  /* 桌面端: 充值面板与提款保持同款 420px 抽屉 (用户决策 2026-04-24).
     420px 内放不下"通道|银行"左右并排, 故改成上下堆叠:
       ┌──────────────┐
       │ 通道 (横排 grid) │
       │ 银行信息 (全宽) │
       │ 表单 (全宽)    │
       └──────────────┘ */
  body:not(.is-mobile-device) #depositOverlay .fin-channel-bank {
    flex-direction: column;
    gap: 8px;
  }
  body:not(.is-mobile-device) #depositOverlay .fin-channel-list {
    flex: 0 0 auto;
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 6px;
    max-height: none;
    overflow: visible;
  }
  body:not(.is-mobile-device) #depositOverlay .fin-channel-list .fin-channel-card {
    text-align: center;
    padding: 8px 6px;
  }
  body:not(.is-mobile-device) #depositOverlay .fin-bank-area {
    flex: 1 1 auto;
  }

  /* 抽屉模式下, panel-header 与 sidebar LOGO header 严格等高 + 共用 --dt-header-h.
     2026-05-15(2): 由 min-height 改为 height —— svg(22px) 与 h3 行高基线不同,
     min-height + content 撑开会出现 1~6px 差距, 强制 height 才能 100% 对齐. */
  body:not(.is-mobile-device) .finance-panel .panel-header {
    padding: 0 20px;
    height: var(--dt-header-h, 56px);
    flex-shrink: 0;
  }
  /* "我关注的厂商"抽屉同样用 finance-panel 抽屉外观, 但不带 .finance-panel 类,
     单独同步 header 高度防止再出现错位. */
  body:not(.is-mobile-device) #followedProvidersOverlay .provider-panel .panel-header {
    padding: 0 20px;
    height: var(--dt-header-h, 56px);
    flex-shrink: 0;
  }

  /* "我关注的厂商"也用同款抽屉样式（默认是底部弹起） */
  body:not(.is-mobile-device) #followedProvidersOverlay,
  body:not(.is-mobile-device) #followedProvidersOverlay.active {
    background: transparent;
    pointer-events: none;
  }
  body:not(.is-mobile-device) #followedProvidersOverlay .provider-panel {
    position: fixed;
    top: 0; bottom: 0;
    left: var(--dt-sidebar-w, 240px);
    right: auto;
    width: 420px;
    max-width: 420px;
    max-height: none;
    height: 100vh; /* 旧浏览器兜底 */
    height: 100dvh; /* 折叠屏/移动工具栏: 用动态视口高度, 避免内容被截 */
    margin: 0;
    border-radius: 0 14px 14px 0;
    box-shadow: 8px 0 28px rgba(0,0,0,.35);
    transform: translateX(-100%);
    transition: transform .32s cubic-bezier(.32,.72,.37,1.12);
    /* 同 finance-panel：默认 pointer-events:none 避免抽屉收起后还吞 sidebar 点击 */
    pointer-events: none;
  }
  body:not(.is-mobile-device) #followedProvidersOverlay.active .provider-panel {
    transform: translateX(0);
    pointer-events: auto;
  }
}

/* Settings detail panel height override */
.settings-detail-panel .finance-body { max-height: calc(90vh - 56px); }
@media (min-width: 768px) {
  body:not(.is-mobile-device) .settings-detail-panel {
    max-height: none; height: 100vh; height: 100dvh; width: 420px;
  }
  body:not(.is-mobile-device) .settings-detail-panel .finance-body { max-height: none; }
}

/* KYC status badges */
.kyc-status-badge {
  display: inline-block; padding: 3px 10px; border-radius: 12px;
  font-size: 12px; font-weight: 600;
}
.kyc-status-badge.pending { background: #fff3cd; color: #856404; }
.kyc-status-badge.approved { background: #d4edda; color: #155724; }
.kyc-status-badge.rejected { background: #f8d7da; color: #721c24; }

/* VIP progress bar */
.vip-progress-wrap { margin: 12px 0; }
.vip-progress-bar {
  height: 8px; background: #eee; border-radius: 4px; overflow: hidden;
}
.vip-progress-fill {
  height: 100%; background: linear-gradient(90deg, #FE2C55, #ff6b81);
  border-radius: 4px; transition: width .5s ease;
}
.vip-level-card {
  background: linear-gradient(135deg, #1a1a2e, #16213e);
  border-radius: 12px; padding: 16px; color: #fff; margin-bottom: 16px;
}
.vip-level-card .vip-star { color: #ffd700; font-size: 20px; }
.vip-level-name { font-size: 22px; font-weight: 800; margin: 4px 0; }
.vip-level-table { width: 100%; border-collapse: collapse; margin-top: 12px; font-size: 13px; }
.vip-level-table th { text-align: left; padding: 8px 6px; color: #999; border-bottom: 1px solid #f0f0f0; font-weight: 500; }
.vip-level-table td { padding: 8px 6px; border-bottom: 1px solid #f5f5f5; }
.vip-level-table tr.current { background: #fff5f7; }

/* ===== Daily Checkin — full-screen dark theme ===== */
/* z-index 1000：必须高于 .top-bar (300)，否则 ci-header 顶部 54px 会被 top-bar
   完全遮挡，返回按钮 + 标题 + 签到记录全部不可见，用户无法关掉签到页面回到游戏。
   这是用户报告 "添加返回按钮、不可以遮挡其他游戏" 的根因。 */
.ci-overlay {
  position: fixed; inset: 0; z-index: 1000;
  background: var(--overlay-bg);
  display: none; flex-direction: column;
  color: var(--text);
  transition: background .25s ease, color .25s ease;
}
.ci-overlay.open { display: flex; }

/* 桌面端：ci-overlay（活动中心 / 签到 / 签到历史）默认 inset:0 会盖住
   左侧 sidebar，导致 sidebar 整列被吞、ph-tabs 头部「优惠 / 活动 / 签到」
   被 viewport 左边遮（用户报告"左边的部分看不到"）。
   解决：与 dt-feed-overlay 模式（收藏/历史 grid 浮层）对齐 —— 让 ci-overlay
   从 --dt-sidebar-w 开始，sidebar 仍完整可见可点（点 LOGO / 其他 mode/cat
   都能瞬间切走，不必先关掉活动中心）。 */
@media (min-width: 768px) {
  body:not(.is-mobile-device) .ci-overlay {
    left: var(--dt-sidebar-w, 240px);
  }
  /* 2026-04-29: 桌面端活动中心 (PromoHub / 签到 / 历史) 内容横向居中并限宽.
     之前 inset:0 + width:100% 让成就/优惠卡片在宽屏 (≥1280px) 下一直拉到
     右侧 actionBar 边缘, 单列卡片越拉越长, 视觉很空. 880px 是单列阅读
     舒适上限 (与抖音/小红书 web 端一致), 同时保留两侧空白让 actionBar
     不被遮. .ci-header / .ph-tabs / .ci-body 三段都需要 (header 是 flex
     justify-between, 居中后返回箭头与"签到记录"按钮也回到 880px 视觉
     框内, 不再贴在屏幕左右两端). */
  body:not(.is-mobile-device) .ci-overlay > .ci-header,
  body:not(.is-mobile-device) .ci-overlay > .ph-tabs,
  body:not(.is-mobile-device) .ci-overlay > .ci-body {
    max-width: 880px;
    margin-left: auto;
    margin-right: auto;
    width: 100%;
    box-sizing: border-box;
  }
}
.ci-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 16px; padding-top: calc(12px + env(safe-area-inset-top, 0px));
  flex-shrink: 0;
}
/* 2026-05-06: .ci-back / .ci-close 的 background/border/size/hover 已经被
   "Unified overlay header buttons" 那条统一规则覆盖, 这里不再单独写样式.
   .ci-back 旧的 36px 宽度也由通用规则保留 (36×36). */
.ci-title { font-size: 17px; font-weight: 700; }
/* checkinOverlay 头部右侧把"签到记录"按钮 + × 关闭按钮放一组里, 一起靠右 */
.ci-header-right {
  display: flex; align-items: center; gap: 6px;
}
.ci-history-btn {
  background: none; border: 1px solid rgba(255,255,255,.2); border-radius: 14px;
  color: rgba(255,255,255,.7); font-size: 12px; padding: 4px 12px; cursor: pointer;
}
.ci-body {
  flex: 1; overflow-y: auto; -webkit-overflow-scrolling: touch;
  padding: 0 16px 24px;
  /* 2026-04-29: 之前底部仅 24px, 桌面右下"客服"浮窗 / promo 右侧浮标
     会盖住"签到奖励详情"末尾几行 (用户截图: 第7天的奖励文字被压到屏外).
     拉到 100px + safe-area, 给浮窗留出安全距离. */
  padding-bottom: calc(100px + env(safe-area-inset-bottom, 0px));
}

/* 2026-05-06: PromoHub (二级菜单 — 优惠/活动/成就/签到/商城) 在移动端
   保持全屏 .ci-overlay 模式 (← 返回 + 标题 + × 关闭), 与 checkin / 签到历史
   一致. 一级菜单 (promoActionSheet 上拉) 仍然是底部抽屉. */

/* Stats row */
.ci-stats {
  display: flex; gap: 8px; margin-bottom: 20px;
}
.ci-stat-card {
  flex: 1; background: rgba(255,255,255,.06); border-radius: 12px;
  padding: 14px 10px; text-align: center;
  border: 1px solid rgba(255,255,255,.06);
}
.ci-stat-num {
  font-size: 26px; font-weight: 800;
  background: linear-gradient(135deg, #FE2C55, #ff6b81);
  -webkit-background-clip: text; -webkit-text-fill-color: transparent;
  background-clip: text; line-height: 1.2;
}
.ci-stat-num.green {
  background: linear-gradient(135deg, #43A047, #66BB6A);
  -webkit-background-clip: text; background-clip: text;
}
.ci-stat-num.gold {
  background: linear-gradient(135deg, #FFB300, #FFCA28);
  -webkit-background-clip: text; background-clip: text;
}
.ci-stat-label {
  font-size: 11px; color: rgba(255,255,255,.45); margin-top: 4px; font-weight: 500;
}

/* 7-day reward strip */
.ci-week-strip {
  display: flex; gap: 6px; margin-bottom: 20px; overflow-x: auto;
  scrollbar-width: none; -ms-overflow-style: none;
  /* align-items: stretch (默认) 让 7 张卡片等高, 这样无论某张是否有
     "今天"标签都视觉对齐. */
}
.ci-week-strip::-webkit-scrollbar { display: none; }
.ci-week-card {
  flex: 0 0 calc((100% - 36px) / 7); min-width: 44px;
  background: rgba(255,255,255,.05); border-radius: 10px;
  padding: 10px 4px 8px; text-align: center;
  border: 1px solid rgba(255,255,255,.06);
  position: relative; transition: all .25s ease;
  display: flex; flex-direction: column; align-items: stretch;
}
.ci-week-card.done {
  background: rgba(254,44,85,.12);
  border-color: rgba(254,44,85,.25);
}
.ci-week-card.today {
  border-color: #FE2C55;
  box-shadow: 0 0 12px rgba(254,44,85,.3);
}
/* 2026-04-29: "今天"标签从绝对定位(bottom:-8px 浮到卡片外, 跨过卡片
   边框, 视觉上"跑下来"且其它卡片该位置空白不对齐)改成卡片内首行的
   inline-block pill, 居中显示在"第N天"下方. 同步所有 .ci-week-day
   减一行高度补偿 (margin-top: 4px), 这样有 today / 没 today 的卡片
   首段视觉总高度一致, 7 张卡片底部线齐. */
.ci-week-today-tag {
  display: inline-block;
  margin: 4px auto 6px;
  font-size: 9px; background: #FE2C55; color: #fff; padding: 1px 6px;
  border-radius: 6px; white-space: nowrap;
  align-self: center;
  pointer-events: none;
}
.ci-week-card.milestone {
  border-color: rgba(255,179,0,.4);
  background: rgba(255,179,0,.08);
}
.ci-week-day {
  font-size: 10px; color: rgba(255,255,255,.4); margin-bottom: 6px; font-weight: 600;
}
.ci-week-icon {
  font-size: 22px; line-height: 1.1; margin-bottom: 4px;
}
/* 2026-05-01 用户反馈"签到完成就完成了, 不要显示√号 对号":
   原来 .done 卡片会在 .ci-week-icon 之后追加一个绿色 ✓, 跟 emoji 重叠
   显得拥挤. 完成态由 .ci-week-card.done 的红粉底色 + 边框已经表达,
   这里去掉 ::after 对号. */
.ci-week-bonus {
  font-size: 9px; line-height: 1.3; color: rgba(255,255,255,.55); font-weight: 600;
  /* 奖励文案里像 "1.00~2.00" 这种无空格连续 token 比格子宽, 默认不在 ~/. 处断行
     会横向冲破格子边框 (用户反馈"文本超出边框"). 这里强制允许任意位置断行 + 收紧
     字号/行高, 让文案始终留在 .ci-week-card 内. */
  overflow-wrap: anywhere; word-break: break-word; hyphens: none;
  width: 100%; max-width: 100%;
}

/* Calendar grid */
.ci-cal-header {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 12px;
}
.ci-cal-title { font-size: 15px; font-weight: 700; }
.ci-cal-nav {
  background: none; border: none; color: rgba(255,255,255,.5); padding: 4px 8px;
  cursor: pointer; font-size: 16px;
}
.ci-cal-grid {
  display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px;
  margin-bottom: 20px;
}
.ci-cal-label {
  text-align: center; font-size: 11px; color: rgba(255,255,255,.3);
  font-weight: 600; padding: 4px 0;
}
.ci-cal-day {
  aspect-ratio: 1; display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  border-radius: 10px; font-size: 13px; font-weight: 500;
  color: rgba(255,255,255,.35); position: relative;
  transition: all .2s ease;
}
.ci-cal-day.checked {
  background: rgba(254,44,85,.15); color: #FE2C55; font-weight: 700;
}
.ci-cal-day.checked::after {
  content: '✓'; position: absolute; top: 2px; right: 4px;
  font-size: 8px; color: #43A047; font-weight: 800;
}
.ci-cal-day.today {
  background: rgba(254,44,85,.08);
  border: 1.5px solid #FE2C55; font-weight: 700; color: #FE2C55;
}
.ci-cal-day.empty { visibility: hidden; }

/* Big CTA button */
.ci-action-btn {
  width: 100%; padding: 16px; border: none; border-radius: 14px;
  font-size: 17px; font-weight: 800; cursor: pointer;
  color: #fff; position: relative; overflow: hidden;
  background: linear-gradient(135deg, #FE2C55 0%, #ff4070 50%, #ff6b81 100%);
  box-shadow: 0 4px 20px rgba(254,44,85,.35);
  transition: transform .15s ease, box-shadow .15s ease;
}
.ci-action-btn:active { transform: scale(.97); box-shadow: 0 2px 10px rgba(254,44,85,.3); }
.ci-action-btn:disabled {
  opacity: .5; cursor: not-allowed; box-shadow: none;
  background: rgba(255,255,255,.1);
}

/* Reward table */
.ci-reward-section {
  background: rgba(255,255,255,.04); border-radius: 14px;
  padding: 14px; margin-top: 16px;
  border: 1px solid rgba(255,255,255,.06);
}

/* 2026-04-29: 签到主页内 inline 历史段, 复用 .ci-reward-section 卡片骨架,
   让"签到记录"标题 + 历史列表融入主页, 不再需要单独"签到记录"按钮跳转. */
.ci-history-inline {
  background: rgba(255,255,255,.04); border-radius: 14px;
  padding: 14px; margin-top: 16px;
  border: 1px solid rgba(255,255,255,.06);
}
.ci-history-inline .ci-history-month:first-child { padding-top: 0; }
.ci-history-inline .ci-history-empty {
  text-align: center; padding: 24px 0; font-size: 13px;
  color: rgba(255,255,255,.4);
}
.ci-reward-title {
  font-size: 14px; font-weight: 700; margin-bottom: 10px;
  color: rgba(255,255,255,.8);
}
.ci-reward-row {
  display: flex; justify-content: space-between; align-items: center;
  padding: 8px 0; border-bottom: 1px solid rgba(255,255,255,.04);
  font-size: 13px;
}
.ci-reward-row:last-child { border-bottom: none; }
.ci-reward-day { color: rgba(255,255,255,.5); }
.ci-reward-val { color: #FFB300; font-weight: 700; }

/* History page */
.ci-history-month {
  font-size: 15px; font-weight: 700; color: rgba(255,255,255,.7);
  padding: 12px 0 8px; border-bottom: 1px solid rgba(255,255,255,.06);
  margin-bottom: 8px;
}
.ci-history-item {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 0; border-bottom: 1px solid rgba(255,255,255,.04);
}
.ci-history-dot {
  width: 36px; height: 36px; border-radius: 50%;
  background: rgba(254,44,85,.12); color: #FE2C55;
  display: flex; align-items: center; justify-content: center;
  font-size: 14px; font-weight: 800; flex-shrink: 0;
}
.ci-history-dot.makeup { background: rgba(255,179,0,.12); color: #FFB300; }
.ci-history-info { flex: 1; }
.ci-history-date { font-size: 14px; font-weight: 600; color: rgba(255,255,255,.8); }
.ci-history-detail { font-size: 12px; color: rgba(255,255,255,.4); margin-top: 2px; }
.ci-history-reward {
  font-size: 14px; font-weight: 700; color: #43A047; text-align: right;
}
.ci-history-empty {
  text-align: center; padding: 60px 0; color: rgba(255,255,255,.3); font-size: 14px;
}
.ci-history-load-more {
  display: block; width: 100%; padding: 12px; margin-top: 12px;
  background: rgba(255,255,255,.06); border: 1px solid rgba(255,255,255,.08);
  border-radius: 10px; color: rgba(255,255,255,.5); font-size: 13px;
  text-align: center; cursor: pointer;
}
.ci-history-load-more:hover { background: rgba(255,255,255,.1); }

/* ===========================================================
   2026-05-01 签到历史"报表化"重构: .ci-rpt-*
   用户反馈"页面太随意了, 每天需要类似报表的方式显示". 弃用旧的
   ci-history-item 自由 stack 排版, 改成月份 section + 表头 + 行
   grid 报表, 7 列等宽对齐 (状态点 / 日期 / 类型 / 天数 / 现金 /
   积分 / 抽奖). dark / light 双主题适配, 880px 限宽容器内不溢出.
   =========================================================== */
.ci-rpt-section { margin-bottom: 18px; }
.ci-rpt-section:last-child { margin-bottom: 4px; }
.ci-rpt-section-head {
  display: flex; justify-content: space-between; align-items: baseline;
  padding: 4px 2px 8px;
}
.ci-rpt-month {
  font-size: 14px; color: var(--text);
  letter-spacing: .2px;
}
.ci-rpt-summary {
  font-size: 12px; color: var(--text-mute, rgba(255,255,255,.45));
}
.ci-rpt-table {
  border: 1px solid rgba(255,255,255,.08);
  border-radius: 10px;
  overflow: hidden;
  background: rgba(255,255,255,.03);
}
.ci-rpt-row {
  display: grid;
  grid-template-columns: 36px minmax(96px, 1.5fr) minmax(72px, 1.3fr) minmax(60px, .9fr) minmax(64px, 1fr) minmax(56px, .9fr) minmax(56px, .9fr);
  align-items: center;
  gap: 6px;
  padding: 9px 10px;
  border-bottom: 1px solid rgba(255,255,255,.05);
  font-size: 13px;
  color: var(--text-soft, rgba(255,255,255,.7));
}
.ci-rpt-row:last-child { border-bottom: none; }
.ci-rpt-row.ci-rpt-thead {
  background: rgba(255,255,255,.04);
  color: var(--text-mute, rgba(255,255,255,.45));
  font-size: 11px;
  letter-spacing: .3px;
  text-transform: uppercase;
  padding: 7px 10px;
}
.ci-rpt-cell {
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  min-width: 0;
}
.ci-rpt-c-state { text-align: center; }
.ci-rpt-c-date { color: var(--text); font-variant-numeric: tabular-nums; }
.ci-rpt-c-type, .ci-rpt-c-day { color: var(--text-soft, rgba(255,255,255,.7)); }
.ci-rpt-c-cash, .ci-rpt-c-points, .ci-rpt-c-spin {
  text-align: right;
  font-variant-numeric: tabular-nums;
  color: var(--text-mute, rgba(255,255,255,.4));
}
.ci-rpt-c-cash.has-val   { color: #43A047; }
.ci-rpt-c-points.has-val { color: #FFB300; }
.ci-rpt-c-spin.has-val   { color: #4A90E2; }
.ci-rpt-thead .ci-rpt-c-cash,
.ci-rpt-thead .ci-rpt-c-points,
.ci-rpt-thead .ci-rpt-c-spin { color: inherit; }
.ci-rpt-dot {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; border-radius: 50%;
  background: rgba(254,44,85,.14); color: #FE2C55;
  font-size: 11px;
}
.ci-rpt-dot.makeup { background: rgba(255,179,0,.14); color: #FFB300; }

/* light 主题 — 报表骨架翻成深色描边 + 浅灰底, 防止白底白纸效果 */
:root[data-theme="light"] .ci-rpt-table {
  border-color: rgba(22,24,35,.1);
  background: rgba(22,24,35,.02);
}
:root[data-theme="light"] .ci-rpt-row {
  border-bottom-color: rgba(22,24,35,.06);
}
:root[data-theme="light"] .ci-rpt-row.ci-rpt-thead {
  background: rgba(22,24,35,.04);
}

/* 移动端 (<480px): 5+ 列在窄屏太挤, 隐藏"类型 / 天数"两列让金额列保留可读宽度 */
@media (max-width: 480px) {
  .ci-rpt-row {
    grid-template-columns: 30px minmax(80px, 1.4fr) minmax(56px, .9fr) minmax(50px, .85fr) minmax(50px, .85fr);
    gap: 4px;
    padding: 9px 8px;
  }
  .ci-rpt-c-type, .ci-rpt-c-day { display: none; }
}

/* ===== Promo Hub (活动中心) — directory tabs + section cards ===== */
.ph-tabs {
  display: flex; gap: 6px; padding: 4px 16px 12px; flex-shrink: 0;
  overflow-x: auto; scrollbar-width: none; -ms-overflow-style: none;
}
.ph-tabs::-webkit-scrollbar { display: none; }
.ph-tab {
  flex: 0 0 auto; padding: 8px 16px; border-radius: 18px;
  background: var(--chip-bg); color: var(--text-soft);
  border: 1px solid var(--border-soft);
  font-size: 13px; font-weight: 600; cursor: pointer;
  transition: all .2s ease; white-space: nowrap;
}
.ph-tab:active { transform: scale(.96); }
.ph-tab.active {
  background: linear-gradient(135deg, #FE2C55, #ff6b81);
  color: #fff; border-color: transparent;
  box-shadow: 0 2px 10px rgba(254,44,85,.3);
}
.ph-card {
  background: var(--surface-2); border: 1px solid var(--border-soft);
  border-radius: 14px; padding: 14px 14px;
  margin-bottom: 10px; cursor: pointer;
  transition: all .2s ease; display: flex; align-items: center; gap: 12px;
}
.ph-card:active { transform: scale(.98); background: var(--surface-3); }
.ph-card-icon {
  width: 44px; height: 44px; flex-shrink: 0; border-radius: 12px;
  display: flex; align-items: center; justify-content: center;
  font-size: 22px;
  background: linear-gradient(135deg, rgba(254,44,85,.2), rgba(255,179,0,.15));
}
.ph-card-body { flex: 1; min-width: 0; }
.ph-card-title { font-size: 14px; font-weight: 700; color: var(--text); margin-bottom: 3px; }
.ph-card-desc { font-size: 12px; color: var(--text-mute); line-height: 1.4; }
.ph-card-tag {
  font-size: 11px; padding: 2px 8px; border-radius: 8px;
  background: rgba(255,179,0,.15); color: #FFB300; font-weight: 700;
  flex-shrink: 0; align-self: flex-start;
}
.ph-empty {
  text-align: center; padding: 80px 20px; color: var(--text-faint);
  font-size: 13px; line-height: 1.6;
}
.ph-empty-icon { font-size: 44px; margin-bottom: 12px; opacity: .5; }
.ph-empty-title { font-size: 15px; color: var(--text-soft); margin-bottom: 6px; font-weight: 600; }

/* ============================================================
   Task Center (任务中心) — website 10.7 会员侧
   配套 JS: member-panels.js / loadPromoSectionTask.
   样式风格与 Achievement 一致, 区别在于"周期性可重复" + 进度条 + 领取按钮.
   ============================================================ */
.tc-cat-bar {
  display: flex; gap: 6px; flex-wrap: wrap;
  padding: 0 4px 12px; align-items: center;
}
.tc-cat-chip {
  padding: 6px 12px; border-radius: 16px;
  background: var(--chip-bg, rgba(255,255,255,.08));
  color: var(--text-soft, rgba(255,255,255,.65));
  border: 1px solid var(--border-soft, rgba(255,255,255,.1));
  font-size: 12px; font-weight: 600; cursor: pointer;
  transition: all .2s ease; white-space: nowrap;
  display: inline-flex; align-items: center; gap: 4px;
}
.tc-cat-chip:active { transform: scale(.96); }
.tc-cat-chip.active {
  background: linear-gradient(135deg, #FF6B35, #F7931E);
  color: #fff; border-color: transparent;
  box-shadow: 0 2px 10px rgba(255,107,53,.3);
}
.tc-cat-count {
  font-size: 10px; padding: 1px 6px; border-radius: 8px;
  background: rgba(0,0,0,.18); color: inherit; font-weight: 700;
}
.tc-cat-chip.active .tc-cat-count { background: rgba(255,255,255,.25); }

.tc-summary {
  background: var(--surface-2, rgba(255,255,255,.04));
  border: 1px solid var(--border-soft, rgba(255,255,255,.08));
  border-radius: 12px; padding: 10px 14px; margin-bottom: 12px;
  font-size: 13px; color: var(--text-soft, rgba(255,255,255,.65));
  font-weight: 500;
}
.tc-summary-active {
  background: linear-gradient(135deg, rgba(255,107,53,.16), rgba(247,147,30,.1));
  border-color: rgba(255,107,53,.35);
  color: #FF8C5A; font-weight: 700;
}

.tc-list { display: flex; flex-direction: column; gap: 10px; }

.tc-card {
  background: var(--surface-2, rgba(255,255,255,.04));
  border: 1px solid var(--border-soft, rgba(255,255,255,.08));
  border-radius: 14px; padding: 14px;
  transition: all .2s ease;
}
.tc-card-claimable {
  background: linear-gradient(135deg, rgba(255,107,53,.1), rgba(247,147,30,.05));
  border-color: rgba(255,107,53,.4);
  box-shadow: 0 0 0 1px rgba(255,107,53,.18), 0 4px 14px rgba(255,107,53,.15);
}
.tc-card-done { opacity: .7; }

.tc-card-head {
  display: flex; align-items: flex-start; gap: 12px; margin-bottom: 10px;
  /* 重置洗码弹窗 .tc-card-head(4765) 的浅色底/边框/内边距泄漏, 否则夜间模式下
     任务卡头部出现浅灰底+白字, 对比度不足看不清 (测试报告问题1) */
  background: transparent; border-bottom: none; padding: 0;
}
.tc-card-icon {
  width: 44px; height: 44px; flex-shrink: 0; border-radius: 12px;
  display: flex; align-items: center; justify-content: center;
  background: linear-gradient(135deg, rgba(255,107,53,.2), rgba(247,147,30,.15));
  overflow: hidden;
}
.tc-icon-emoji { font-size: 22px; line-height: 1; }
.tc-icon-img { width: 28px; height: 28px; object-fit: contain; }

.tc-card-meta { flex: 1; min-width: 0; }
.tc-card-title-row {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 4px;
}
.tc-card-title {
  font-size: 14px; font-weight: 700;
  color: var(--text, #fff); line-height: 1.3;
}
.tc-card-desc {
  font-size: 12px; color: var(--text-mute, rgba(255,255,255,.55));
  line-height: 1.4; margin-bottom: 4px;
}
.tc-card-cond {
  font-size: 11px; color: var(--text-soft, rgba(255,255,255,.6));
  font-weight: 600;
}

.tc-cat-badge {
  font-size: 10px; padding: 2px 7px; border-radius: 8px;
  color: #fff; font-weight: 700; line-height: 1.4;
  flex-shrink: 0;
}

.tc-card-reward { flex-shrink: 0; align-self: flex-start; }
.tc-reward-chip {
  font-size: 11px; padding: 3px 10px; border-radius: 10px;
  background: rgba(255,179,0,.15); color: #FFB300;
  font-weight: 700; white-space: nowrap;
}

.tc-card-progress {
  display: flex; align-items: center; gap: 10px;
  margin: 8px 0 12px;
}
.tc-progress-bar {
  flex: 1; height: 8px; border-radius: 4px;
  background: rgba(255,255,255,.08); overflow: hidden;
}
.tc-progress-fill {
  height: 100%; border-radius: 4px;
  background: linear-gradient(90deg, #FF6B35, #F7931E);
  transition: width .35s ease;
}
.tc-progress-text {
  font-size: 11px; color: var(--text-soft, rgba(255,255,255,.6));
  white-space: nowrap; font-weight: 600;
}

.tc-card-actions { display: flex; justify-content: flex-end; }
.tc-btn {
  padding: 8px 22px; border-radius: 18px;
  border: none; font-size: 13px; font-weight: 700;
  cursor: pointer; transition: all .15s ease;
}
.tc-btn-claim {
  background: linear-gradient(135deg, #FF6B35, #F7931E);
  color: #fff; box-shadow: 0 2px 8px rgba(255,107,53,.35);
}
.tc-btn-claim:hover { transform: translateY(-1px); box-shadow: 0 4px 12px rgba(255,107,53,.45); }
.tc-btn-claim:active { transform: scale(.97); }
.tc-btn-claim:disabled { opacity: .6; cursor: not-allowed; transform: none; }
.tc-btn-progress {
  background: rgba(255,255,255,.08);
  color: var(--text-soft, rgba(255,255,255,.55));
  cursor: not-allowed;
}
.tc-btn-claimed {
  background: rgba(46,200,104,.15);
  color: #2EC868; cursor: not-allowed;
}

/* 桌面浅色主题适配 (与 Achievement 一致, 用 body[data-theme=light] 覆盖) */
body[data-theme="light"] .tc-summary { background: #fff; border-color: #e8e8e8; color: #555; }
body[data-theme="light"] .tc-card { background: #fff; border-color: #e8e8e8; }
body[data-theme="light"] .tc-card-title { color: #1a1a1a; }
body[data-theme="light"] .tc-card-desc { color: #666; }
body[data-theme="light"] .tc-progress-bar { background: #f0f0f0; }
body[data-theme="light"] .tc-cat-chip { background: #f5f5f5; color: #555; border-color: #e8e8e8; }

/* ============================================================
   Achievement Panel (2026-04-28 重写)
   游戏化成就 UI: 等级徽章 + 进度条 + 状态分组 + 领取按钮
   配套 JS: member-panels.js / loadPromoSectionAchievement.
   ============================================================ */
.ach-loading {
  text-align: center; padding: 60px 0; color: rgba(255,255,255,.4); font-size: 13px;
}

/* 顶部 summary 行: 总览 + 排行榜入口 */
.ach-summary {
  display: flex; align-items: center; gap: 12px;
  background: linear-gradient(135deg, rgba(254,44,85,.12), rgba(255,179,0,.08));
  border: 1px solid rgba(255,179,0,.18);
  border-radius: 14px; padding: 12px 14px; margin-bottom: 12px;
}
.ach-summary-icon { font-size: 32px; line-height: 1; flex-shrink: 0; }
.ach-summary-text { flex: 1; min-width: 0; }
.ach-summary-title { font-size: 14px; font-weight: 700; color: #fff; }
.ach-summary-sub { font-size: 12px; color: rgba(255,255,255,.6); margin-top: 2px; }
.ach-leaderboard-btn {
  flex-shrink: 0; padding: 6px 12px; border-radius: 16px; border: 1px solid rgba(255,179,0,.4);
  background: rgba(255,179,0,.12); color: #FFB300; font-size: 12px; font-weight: 600;
  cursor: pointer; transition: all .15s ease;
}
.ach-leaderboard-btn:hover { background: rgba(255,179,0,.2); }

/* 分组标题 */
.ach-group { margin-bottom: 14px; }
.ach-group-title {
  font-size: 12px; color: rgba(255,255,255,.5); text-transform: uppercase;
  letter-spacing: .8px; font-weight: 700; padding: 0 4px 8px;
}
.ach-group-count { color: rgba(255,255,255,.35); font-weight: 500; }

/* 卡片基础布局 */
.ach-card {
  position: relative;
  background: rgba(255,255,255,.04); border: 1px solid rgba(255,255,255,.06);
  border-radius: 14px; padding: 0; margin-bottom: 8px;
  transition: transform .2s ease, box-shadow .2s ease, border-color .2s ease;
  overflow: hidden;
}
/* 2026-04-29 (v2): head 是固定高度 banner, 所有卡视觉一致.
     [badge] [title + 简要进度+奖励 (单行省略)] [pending 角标 + 领取小按钮 + caret]
   折叠态隐藏 .ach-card-body (desc / metric / roadmap / 大按钮);
   展开态 (data-collapsed=0) 显示 body. 点 head 任意位置切换 (mini 领奖
   按钮 + status 角标 自己 stopPropagation). */
.ach-card-head {
  display: flex; align-items: center; gap: 12px; position: relative;
  width: 100%; padding: 12px 14px; background: transparent; border: 0;
  color: inherit; text-align: left; cursor: pointer; font: inherit;
  min-height: 72px;
  -webkit-tap-highlight-color: transparent;
}
.ach-card-head:focus-visible { outline: 2px solid rgba(254,44,85,.5); outline-offset: -2px; border-radius: 14px; }
.ach-card-head-right {
  margin-left: auto;
  display: flex; align-items: center; gap: 8px;
  flex-shrink: 0;
}

/* 2026-05-05 head 右侧动作组 (+1 角标 / 领取 mini / 详情按钮) 在 JS 里
   显式包了一层 .ach-card-head-actions (见 _renderAchievementCard).
   之前 3 个元素是 head 的独立 flex 子元素, 依赖 .ach-card-title-wrap
   { flex:1 } 把它们顶到右端. 但桌面版 ci-body 880px 居中下出现过失衡:
   title-wrap 内部 (.ach-card-title-row + .ach-card-mini) 都是 block 不显式
   占宽, flex 余量算出来后 head 把右侧 3 个挤回 title-wrap 紧邻的位置,
   "+1" 因 .ach-status absolute 定位备份继续贴卡片右上角, 整张卡视觉
   成了 "头像+标题在左 / 领取详情挤中下 / +1 单独飘右上 / 中间大片空白"
   (用户反馈 2026-05-04 截图: "活动中心 -> 成就 -> 可立即领取 desposit").

   2026-05-05 v2: flex 方案 (margin-left:auto) 在用户实测仍未生效, 改用
   CSS Grid 强制三列布局, 完全脱离 flex 容器对子元素 "顺序 + 余量分配"
   的依赖. 三列分别承载 badge / title-wrap / actions-wrap, align-items:center
   保证三者垂直居中, gap 14px 与 head padding 视觉一致. !important 兜底
   覆盖任何后续 / @media 内的 display:flex 重设. */
/* 2026-05-05 v4: 放弃 grid + :has() 兜底方案 (用户实测: 旧 JS 缓存 + 3 列
   grid 把 5 个 direct child auto-flow 成 2 行 → "+1/24% 单飞右上, 领取/详情
   挤左下". :has() 在部分浏览器下 :not(:has(...)) 行为有差异, 5 列兜底没触发).
   重新用纯 flex 方案, 完全不依赖 JS 是否生成 .ach-card-head-actions wrapper:
     - head 是 flex row, nowrap, 一行排所有 child
     - title-wrap (flex:1, min-width:0) 吃掉中间所有余量, 把所有右侧元素
       (无论是 wrapper 还是散排的 status/claim/detail) 推到右端
     - 右侧所有元素 (.ach-card-head-actions / .ach-status / .ach-pending-badge
       / .ach-claim-mini / .ach-card-detail-btn) 显式 flex-shrink:0,
       不被 title-wrap 抢宽度
   这样新 JS (3 child) / 旧 JS (5 child) 都正确. */
.ach-card-head {
  display: flex !important;
  flex-direction: row !important;
  flex-wrap: nowrap !important;
  align-items: center !important;
  gap: 12px !important;
}
.ach-card-head > .ach-card-title-wrap {
  flex: 1 1 0% !important;
  min-width: 0 !important;
  overflow: hidden;
}
.ach-card-head > .ach-card-head-actions {
  display: flex !important;
  align-items: center;
  gap: 8px;
  flex-shrink: 0 !important;
  flex-wrap: nowrap;
  margin-left: auto;
}
/* 旧 JS 兜底: 散排的 5 个 direct child 中, 右侧 3 个分别声明 flex-shrink:0
   防止被 title-wrap 挤压. 不需要 margin-left:auto, 因为 title-wrap 的 flex:1
   已经把它们顶到右边. */
.ach-card-head > .ach-status,
.ach-card-head > .ach-pending-badge,
.ach-card-head > .ach-claim-mini,
.ach-card-head > .ach-card-detail-btn {
  flex-shrink: 0 !important;
}

/* ──────────────────────────────────────────────────────────────────
   2026-05-06 用户反馈"成就卡 红框 (领取 / 详情) 要放到箭头位置
   (= 25% 角标所在的右上角)". 之前用 flex margin-left:auto 让
   .ach-card-head-actions 贴右, 但移动端窄屏 + title-wrap 内 mini 进度
   长字串 (51/200 · 25% · +10 现金 +10 积分) 会把 head-actions 挤到下一
   行 (浏览器对 nowrap + min-width:0 + 巨长 mini 文本 的处理不一致).

   本次彻底用 absolute 定位 把 head-actions 钉在 head 容器右上角, 完全
   脱离 flex 余量算式, 不再受 mini 文本 / 标题宽度 / 折叠态 影响. 同时
   给 head 加 padding-right 避免标题 / mini 滑到角标下面被遮.
   ─────────────────────────────────────────────────────────────────── */
.ach-card-head {
  position: relative !important;
  flex-wrap: nowrap !important;
  padding-right: 14px !important;
}
.ach-card-head > .ach-card-head-actions {
  position: absolute !important;
  top: 50% !important;
  right: 0 !important;
  transform: translateY(-50%) !important;
  margin-left: 0 !important;
  display: inline-flex !important;
  align-items: center !important;
  gap: 8px !important;
  flex-shrink: 0 !important;
  flex-wrap: nowrap !important;
  white-space: nowrap !important;
  z-index: 1;
}
.ach-card-head > .ach-card-head-actions > * {
  flex-shrink: 0 !important;
}
.ach-card-head .ach-status,
.ach-card-head .ach-pending-badge {
  position: static !important;
  width: auto !important;
  height: auto !important;
  transform: none !important;
}
/* head-actions 是 absolute, 不再占 flex 余量, 标题/mini 文本可能整段
   滑到 head-actions 下面被遮. 给 title-wrap 留出 head-actions 大概的
   右侧 padding (~150px 容纳 25% + 领取 + 详情, 各类按钮空间足够). */
.ach-card-head > .ach-card-title-wrap {
  padding-right: 150px !important;
}
.ach-card-caret {
  flex-shrink: 0;
  width: 20px; height: 20px; display: flex; align-items: center; justify-content: center;
  color: rgba(255,255,255,.45);
  transition: transform .2s ease, color .2s ease;
}
.ach-card[data-collapsed="1"] .ach-card-caret { transform: rotate(-90deg); }
.ach-card[data-collapsed="0"] .ach-card-caret { transform: rotate(0deg); color: rgba(255,255,255,.7); }
.ach-card-body {
  padding: 0 14px 14px;
  border-top: 1px solid rgba(255,255,255,.06);
  padding-top: 12px;
  display: block;
}
.ach-card[data-collapsed="1"] .ach-card-body { display: none; }

/* head 内左侧 title-wrap: 单行省略, 最大宽度受 head 自适应 flex 限制 */
.ach-card .ach-card-title-wrap { flex: 1; min-width: 0; }
.ach-card .ach-card-head .ach-card-title {
  font-size: 14px; color: var(--text);
  margin-bottom: 2px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  display: block;
}
/* 2026-05-01 标题 + 星级 + 阶段进度 同一行 (head 内) */
.ach-card .ach-card-head .ach-card-title-row {
  display: flex; align-items: center; gap: 8px;
  min-width: 0; margin-bottom: 2px;
}
.ach-card .ach-card-head .ach-card-title-row .ach-card-title {
  margin-bottom: 0; flex: 0 1 auto;
  max-width: 100%;
}
/* 1~5 颗星 (achievement_level → bronze=1..diamond=5), on=金色, off=灰 */
.ach-stage-stars {
  display: inline-flex; align-items: center; gap: 1px;
  flex-shrink: 0;
  line-height: 1;
}
.ach-star { font-size: 11px; line-height: 1; }
.ach-star-on  { color: #FFB300; }
.ach-star-off { color: rgba(255,255,255,.18); }
/* 多阶段成就才有的 "x/y 阶" 紧凑标签 */
.ach-stage-frac {
  flex-shrink: 0;
  font-size: 11px; font-weight: 600;
  padding: 1px 6px; border-radius: 8px;
  background: rgba(255,179,0,.14); color: #FFB300;
  font-variant-numeric: tabular-nums;
}
/* "详情" 按钮 — 替代纯 caret, 让点击意图明确, 文字 + caret 一组 */
.ach-card-detail-btn {
  flex-shrink: 0;
  display: inline-flex; align-items: center; gap: 3px;
  padding: 4px 8px; border-radius: 999px;
  background: rgba(255,255,255,.05);
  color: rgba(255,255,255,.65);
  font-size: 11px; font-weight: 600;
  pointer-events: none;
}
.ach-card-detail-btn .ach-card-caret {
  width: 14px; height: 14px; color: inherit;
}
.ach-card-head:hover .ach-card-detail-btn { background: rgba(255,255,255,.09); color: rgba(255,255,255,.85); }
.ach-card[data-collapsed="0"] .ach-card-detail-btn {
  background: rgba(254,44,85,.16); color: #FE5B7B;
}
/* 折叠态简要进度 (L11 · 1100/1200 · 92% · +10 现金), 单行省略 */
.ach-card-mini {
  font-size: 12px;
  color: rgba(255,255,255,.65);
  letter-spacing: .2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ach-card-mini-locked { color: rgba(255,255,255,.4); }

/* head 右侧紧凑领奖按钮 — pending>0 时直接出现, 不必展开 */
.ach-claim-mini {
  flex-shrink: 0;
  border: 0; cursor: pointer;
  background: linear-gradient(135deg, #FE2C55, #FF6B81);
  color: #fff; font-size: 12px;
  padding: 6px 12px; border-radius: 999px;
  display: inline-flex; align-items: center; gap: 4px;
  box-shadow: 0 2px 8px rgba(254,44,85,.32);
  transition: transform .15s ease, box-shadow .15s ease;
  -webkit-tap-highlight-color: transparent;
}
.ach-claim-mini:hover { transform: translateY(-1px); box-shadow: 0 4px 12px rgba(254,44,85,.4); }
.ach-claim-mini:active { transform: translateY(0); }
.ach-claim-mini-n { font-size: 11px; opacity: .92; }

/* 2026-05-02 head 内 .ach-claim-mini 的 disabled 灰化态: 用户要求"红框
   位置始终显示领取按钮, 未达成时灰化, 达成时亮起". 这里覆盖默认的
   红渐变, 改成中性灰底 + 弱字色, 关掉 hover 阴影 + 阻断点击. */
.ach-claim-mini:disabled,
.ach-claim-mini.ach-claim-mini-disabled {
  background: rgba(127,127,127,.18);
  color: var(--text-mute, rgba(255,255,255,.45));
  box-shadow: none;
  cursor: not-allowed;
  pointer-events: none;
  transform: none;
  opacity: 1;
}
:root[data-theme="light"] .ach-claim-mini:disabled,
:root[data-theme="light"] .ach-claim-mini.ach-claim-mini-disabled {
  background: rgba(22,24,35,.06);
  color: rgba(22,24,35,.42);
}

/* 调小 head 内 status / pending 角标, 与新 banner 高度匹配, 改为相对定位
   (而不是脱离布局的 absolute), 让它们和 mini 按钮 / caret 排成右侧一行. */
.ach-card-head .ach-status,
.ach-card-head .ach-pending-badge {
  position: static;
  width: auto; height: auto;
  padding: 2px 8px; border-radius: 999px;
  font-size: 11px;
  display: inline-flex; align-items: center; justify-content: center;
}

/* 等级徽章: 左侧的圆角框 */
.ach-badge {
  width: 56px; flex-shrink: 0; padding: 8px 4px 6px;
  border-radius: 12px; text-align: center;
  background: linear-gradient(135deg, rgba(255,255,255,.06), rgba(255,255,255,.02));
  border: 1px solid rgba(255,255,255,.08);
}
.ach-badge-icon { display: block; font-size: 26px; line-height: 1; margin-bottom: 4px; }
.ach-badge-label { display: block; font-size: 10px; font-weight: 700; color: rgba(255,255,255,.7); letter-spacing: .5px; }
.ach-badge-bronze   { background: linear-gradient(135deg, rgba(205,127,50,.25), rgba(205,127,50,.08));  border-color: rgba(205,127,50,.4); }
.ach-badge-bronze   .ach-badge-label { color: #CD7F32; }
.ach-badge-silver   { background: linear-gradient(135deg, rgba(192,192,192,.25), rgba(192,192,192,.08)); border-color: rgba(192,192,192,.4); }
.ach-badge-silver   .ach-badge-label { color: #d8d8d8; }
.ach-badge-gold     { background: linear-gradient(135deg, rgba(255,215,0,.3), rgba(255,179,0,.08));    border-color: rgba(255,215,0,.45); }
.ach-badge-gold     .ach-badge-label { color: #FFD700; }
.ach-badge-platinum { background: linear-gradient(135deg, rgba(229,228,226,.25), rgba(180,180,255,.08)); border-color: rgba(229,228,226,.4); }
.ach-badge-platinum .ach-badge-label { color: #e0eaff; }
.ach-badge-diamond  { background: linear-gradient(135deg, rgba(180,82,255,.3), rgba(57,176,255,.15));   border-color: rgba(180,82,255,.45); }
.ach-badge-diamond  .ach-badge-label { color: #ffd9ff; }

/* 卡标题区 */
.ach-card-title-wrap { flex: 1; min-width: 0; }
.ach-card-title {
  font-size: 14px; font-weight: 700; color: #fff; margin-bottom: 2px;
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
}
.ach-stage-tag {
  font-size: 10px; font-weight: 700; padding: 1px 6px; border-radius: 8px;
  background: rgba(254,44,85,.18); color: #FF6B81;
}
.ach-card-desc { font-size: 12px; color: rgba(255,255,255,.55); line-height: 1.45; margin-bottom: 4px; }
.ach-metric { font-size: 12px; color: rgba(255,255,255,.7); font-weight: 600; }

/* 右上角状态标识 */
.ach-status {
  position: absolute; right: 0; top: 0;
  width: 24px; height: 24px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 14px; font-weight: 700;
}
.ach-status-claimable {
  background: rgba(254,44,85,.18); color: #FE2C55;
  animation: ach-pulse 1.4s ease-in-out infinite;
}
.ach-status-claimed  { background: rgba(33,208,122,.18); color: #21D07A; }
.ach-status-locked   { background: rgba(255,255,255,.06); color: rgba(255,255,255,.4); }
.ach-status-progress { background: rgba(74,144,226,.18); color: #4A90E2; font-variant-numeric: tabular-nums; }
:root[data-theme="light"] .ach-status-progress { background: rgba(74,144,226,.16); color: #2F6FB8; }

@keyframes ach-pulse {
  0%, 100% { transform: scale(1);   box-shadow: 0 0 0 0 rgba(254,44,85,.45); }
  50%      { transform: scale(1.1); box-shadow: 0 0 0 8px rgba(254,44,85,0); }
}

/* 进度条 */
.ach-progress-row { margin-top: 10px; }
.ach-progress-bar {
  width: 100%; height: 8px; border-radius: 4px;
  background: rgba(255,255,255,.06); overflow: hidden; position: relative;
}
.ach-progress-fill {
  height: 100%; border-radius: 4px;
  background: linear-gradient(90deg, #FE2C55 0%, #FFB300 100%);
  transition: width .5s ease;
  position: relative; overflow: hidden;
}
.ach-progress-fill::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent 0%, rgba(255,255,255,.25) 50%, transparent 100%);
  animation: ach-shimmer 2s linear infinite;
}
@keyframes ach-shimmer { 0% { transform: translateX(-100%); } 100% { transform: translateX(100%); } }

.ach-progress-text {
  display: flex; justify-content: space-between; align-items: center;
  font-size: 11px; color: rgba(255,255,255,.6); margin-top: 4px;
}
.ach-progress-pct { color: #FFB300; font-weight: 700; }

/* ────────────────────────────────────────────────────────────
   阶梯路线图 (剑侠情缘式) — JS 渲染 .ach-roadmap > .ach-stage-chip * N
   每个 chip 内部纵向排 4 行: icon / num "L10" / target "1000.00" / reward "+5.00"
   chip 之间用 .ach-stage-link 横线连接.
   2026-04-29: 之前 CSS 缺这段, 默认 div block 堆叠 → 用户截图所见
   "L10/1000.00/+5.00" 各自独立成行. 补全.
   ──────────────────────────────────────────────────────────── */
.ach-roadmap {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 10px;
  padding: 4px 2px 8px;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
}
.ach-roadmap::-webkit-scrollbar { height: 4px; }
.ach-roadmap::-webkit-scrollbar-thumb { background: rgba(255,255,255,.15); border-radius: 2px; }
.ach-stage-chip {
  flex: 0 0 auto;
  min-width: 72px;
  display: flex; flex-direction: column; align-items: center;
  gap: 3px;
  padding: 8px 6px;
  border-radius: 10px;
  background: rgba(255,255,255,.04);
  border: 1px solid rgba(255,255,255,.06);
  text-align: center;
  transition: background .15s, border-color .15s, transform .12s;
}
.ach-stage-chip:hover { transform: translateY(-1px); }
.ach-stage-icon {
  width: 28px; height: 28px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 14px; font-weight: 700;
  background: rgba(255,255,255,.06);
  color: rgba(255,255,255,.45);
  flex-shrink: 0;
}
.ach-stage-num {
  font-size: 12px; font-weight: 800;
  color: rgba(255,255,255,.85);
  letter-spacing: .3px;
}
.ach-stage-target {
  font-size: 11px;
  color: rgba(255,255,255,.55);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.ach-stage-reward {
  font-size: 10px; font-weight: 700;
  color: #FFB300;
  white-space: nowrap;
  line-height: 1.2;
}
/* 状态修饰 */
.ach-stage-claimed {
  background: rgba(33,208,122,.1);
  border-color: rgba(33,208,122,.25);
}
.ach-stage-claimed .ach-stage-icon { background: rgba(33,208,122,.2); color: #21D07A; }
.ach-stage-claimed .ach-stage-num  { color: rgba(33,208,122,.95); }

.ach-stage-claimable {
  background: rgba(254,44,85,.12);
  border-color: rgba(254,44,85,.4);
  animation: ach-pulse 1.6s ease-in-out infinite;
}
.ach-stage-claimable .ach-stage-icon { background: rgba(254,44,85,.22); color: #FE2C55; }
.ach-stage-claimable .ach-stage-num  { color: #FE2C55; }

.ach-stage-next {
  background: rgba(255,179,0,.08);
  border-color: rgba(255,179,0,.32);
}
.ach-stage-next .ach-stage-icon { background: rgba(255,179,0,.18); color: #FFB300; }

.ach-stage-locked {
  opacity: .55;
}
.ach-stage-locked .ach-stage-icon { background: rgba(255,255,255,.04); }

/* 终点封顶阶段 (cap) — 加金边突出 */
.ach-stage-cap {
  border-color: rgba(255,215,0,.45);
  box-shadow: 0 0 0 1px rgba(255,215,0,.25) inset;
}

/* 阶段连接条: 横向短线, 颜色按"下一阶段"状态 */
.ach-stage-link {
  flex: 0 0 16px;
  height: 2px;
  background: rgba(255,255,255,.1);
  border-radius: 1px;
}
.ach-stage-link-claimed { background: rgba(33,208,122,.5); }
.ach-stage-link-claimable { background: linear-gradient(90deg, rgba(33,208,122,.5), rgba(254,44,85,.6)); }
.ach-stage-link-next { background: linear-gradient(90deg, rgba(254,44,85,.5), rgba(255,179,0,.4)); }
.ach-stage-link-locked { background: rgba(255,255,255,.08); }

/* light 模式微调: 把半透明白边/底翻成半透明深灰底, 让 chip 在白底
   ach-card 上仍能看到边界 */
:root[data-theme="light"] .ach-stage-chip {
  background: rgba(22,24,35,.04);
  border-color: rgba(22,24,35,.08);
}
:root[data-theme="light"] .ach-stage-icon  { background: rgba(22,24,35,.06); color: rgba(22,24,35,.5); }
:root[data-theme="light"] .ach-stage-num   { color: var(--text); }
:root[data-theme="light"] .ach-stage-target { color: var(--text-soft); }
:root[data-theme="light"] .ach-stage-link  { background: rgba(22,24,35,.08); }

/* 卡片底部: 奖励 chips + 元数据 */
.ach-card-foot {
  margin-top: 12px; padding-top: 10px;
  border-top: 1px dashed rgba(255,255,255,.08);
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  justify-content: space-between;
}
.ach-rewards { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.ach-rewards-label {
  font-size: 11px; color: rgba(255,255,255,.45); margin-right: 4px;
}
.ach-chip {
  display: inline-block; padding: 3px 8px; border-radius: 8px;
  font-size: 11px; font-weight: 700; line-height: 1.4;
  background: rgba(255,255,255,.06); color: rgba(255,255,255,.85);
}
.ach-chip-pts  { background: rgba(255,179,0,.15); color: #FFB300; }
.ach-chip-cash { background: rgba(33,208,122,.15); color: #21D07A; }
.ach-chip-coup { background: rgba(57,176,255,.15); color: #39B0FF; }
.ach-chip-none { background: rgba(255,255,255,.04); color: rgba(255,255,255,.4); font-weight: 500; }

.ach-foot-meta {
  display: flex; align-items: center; gap: 8px;
  font-size: 10px; color: rgba(255,255,255,.4);
}
.ach-claimed-times { padding: 2px 6px; border-radius: 6px; background: rgba(33,208,122,.1); color: #21D07A; font-weight: 600; }
.ach-ends-tag      { padding: 2px 6px; border-radius: 6px; background: rgba(255,179,0,.1); color: #FFB300; font-weight: 600; }

/* 底部动作行 (领取/已领取/锁定) */
.ach-action-row { margin-top: 12px; }
.ach-claim-btn {
  display: block; width: 100%;
  padding: 10px 16px; border: none; border-radius: 12px;
  background: linear-gradient(135deg, #FE2C55, #ff6b81);
  color: #fff; font-size: 14px; font-weight: 700;
  cursor: pointer; transition: transform .15s ease, box-shadow .15s ease;
  box-shadow: 0 4px 14px rgba(254,44,85,.35);
}
.ach-claim-btn:hover:not(:disabled) { transform: translateY(-1px); box-shadow: 0 6px 18px rgba(254,44,85,.45); }
.ach-claim-btn:active:not(:disabled) { transform: scale(.98); }
/* 2026-05-02 灰化态 (未满足条件): 背景从红渐变换成中性灰, 字色压低, 阴影去掉.
   合并 :disabled 与显式 .ach-claim-disabled 两个选择器, 走同一套灰外观. */
.ach-claim-btn:disabled,
.ach-claim-btn.ach-claim-disabled {
  background: rgba(255,255,255,.06);
  color: rgba(255,255,255,.42);
  box-shadow: none;
  cursor: not-allowed;
  opacity: 1;
  pointer-events: none;
}
:root[data-theme="light"] .ach-claim-btn:disabled,
:root[data-theme="light"] .ach-claim-btn.ach-claim-disabled {
  background: rgba(0,0,0,.05);
  color: rgba(0,0,0,.42);
}
.ach-claim-done {
  text-align: center; padding: 8px; border-radius: 10px;
  background: rgba(33,208,122,.1); color: #21D07A;
  font-size: 13px; font-weight: 600;
}
.ach-locked-reason {
  text-align: center; padding: 8px; border-radius: 10px;
  background: rgba(255,255,255,.04); color: rgba(255,255,255,.5);
  font-size: 12px; font-weight: 500;
}

/* 卡片状态色 */
.ach-card-claimable {
  border-color: rgba(254,44,85,.35);
  background: linear-gradient(135deg, rgba(254,44,85,.08), rgba(255,179,0,.04));
  box-shadow: 0 0 0 0 rgba(254,44,85,.2);
  animation: ach-card-glow 2s ease-in-out infinite;
}
@keyframes ach-card-glow {
  0%, 100% { box-shadow: 0 0 0 0 rgba(254,44,85,.18); }
  50%      { box-shadow: 0 0 0 6px rgba(254,44,85,0); }
}
.ach-card-locked {
  opacity: .6; filter: grayscale(.4);
}
.ach-card-claimed {
  opacity: .75;
}
.ach-card-claimed .ach-card-title { color: rgba(255,255,255,.7); }

/* ===== Achievement Leaderboard Sheet ===== */
.ach-lb-overlay {
  position: fixed; inset: 0; z-index: 1500;
  display: none; align-items: flex-end; justify-content: center;
  pointer-events: none;
}
.ach-lb-overlay.open { display: flex; pointer-events: auto; }
.ach-lb-mask {
  position: absolute; inset: 0; background: rgba(0,0,0,.6);
  opacity: 0; transition: opacity .22s ease;
}
.ach-lb-overlay.open .ach-lb-mask { opacity: 1; }
.ach-lb-panel {
  position: relative; width: 100%; max-width: 480px;
  max-height: 75vh; background: #1a1a2e;
  border-radius: 18px 18px 0 0;
  transform: translateY(100%); transition: transform .25s cubic-bezier(.18,.7,.4,1);
  display: flex; flex-direction: column; overflow: hidden;
}
body:not(.is-mobile-device) .ach-lb-panel {
  border-radius: 18px;
  align-self: center;
  margin-bottom: 5vh;
}
.ach-lb-overlay.open .ach-lb-panel { transform: translateY(0); }
.ach-lb-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 18px; border-bottom: 1px solid rgba(255,255,255,.06);
}
.ach-lb-title { font-size: 15px; font-weight: 700; color: #fff; }
.ach-lb-close {
  width: 28px; height: 28px; border-radius: 50%; border: none;
  background: rgba(255,255,255,.08); color: #fff; font-size: 18px;
  cursor: pointer; line-height: 1;
}
.ach-lb-body { padding: 8px 12px 18px; overflow-y: auto; flex: 1; }
.ach-lb-empty { text-align: center; padding: 40px 0; color: rgba(255,255,255,.4); font-size: 13px; }
.ach-lb-row {
  display: grid; grid-template-columns: 36px 1fr auto; gap: 8px;
  align-items: center; padding: 10px 12px; margin-bottom: 6px;
  border-radius: 10px; background: rgba(255,255,255,.04);
}
.ach-lb-row:nth-child(1) { background: linear-gradient(135deg, rgba(255,215,0,.12), rgba(255,179,0,.04)); }
.ach-lb-row:nth-child(2) { background: linear-gradient(135deg, rgba(229,228,226,.1), rgba(192,192,192,.04)); }
.ach-lb-row:nth-child(3) { background: linear-gradient(135deg, rgba(205,127,50,.12), rgba(205,127,50,.04)); }
.ach-lb-rank { font-size: 18px; font-weight: 700; text-align: center; }
.ach-lb-name { font-size: 13px; color: #fff; font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ach-lb-cnt  { font-size: 12px; color: #FFB300; font-weight: 700; padding: 2px 8px; background: rgba(255,179,0,.1); border-radius: 8px; }
.ach-lb-cash { font-size: 12px; color: #21D07A; font-weight: 700; padding: 2px 8px; background: rgba(33,208,122,.1); border-radius: 8px; }

/* ===== Promo Action Sheet (优惠 入口"上拉菜单")
   移动端: 全屏 fixed + sheet 从底部上滑 (translateY 100% → 0)。
   桌面端 (body:not(.is-mobile-device)): 改为居中弹层, 与 dt-user-menu / overlay 风格统一。
   z-index 1200 高于 ci-overlay (1000), 因为 action sheet 是 PromoHub / Checkin 的入口,
   理论上会在它们关闭后再打开下一个；但为保险起见仍排在上层防止被任何老 overlay 残留遮挡。 */
.pas-overlay {
  position: fixed; inset: 0; z-index: 1200;
  display: none;
  align-items: flex-end; justify-content: center;
  pointer-events: none;
}
.pas-overlay.open { display: flex; pointer-events: auto; }
.pas-mask {
  position: absolute; inset: 0;
  background: rgba(0, 0, 0, .55);
  opacity: 0; transition: opacity .25s ease;
}
.pas-overlay.open .pas-mask { opacity: 1; }
/* 2026-04-29: .pas-* "优惠中心"上拉菜单 base 全部 var() 化, 跟主题走.
   之前硬编码 linear-gradient(#1a1b2e → #161823) + 半透明白边/底 + 白字,
   light 模式下整片仍黑灰, 跟登录/profile/vendor 风格不一致, 用户报"优惠
   中心整片还是黑灰色, 跟住主题走". 这里把 sheet/title/item/cancel 全部
   翻 var, dark 自动 #1c1c1e (panel-bg), light 自动 #fff. 蒙层 .pas-mask
   两主题共用 rgba(0,0,0,.55). */
.pas-sheet {
  position: relative;
  width: 100%; max-width: 520px;
  background: var(--panel-bg);
  border-radius: 18px 18px 0 0;
  padding: 0 0 calc(14px + env(safe-area-inset-bottom, 0px));
  color: var(--text);
  border-top: 1px solid var(--border);
  box-shadow: 0 -8px 32px var(--shadow);
  transform: translateY(100%);
  transition: transform .28s cubic-bezier(.2,.8,.2,1);
}
.pas-sheet .panel-header {
  padding: 14px 16px 12px;
  border-bottom: 1px solid var(--divider, var(--border));
}
.pas-sheet .panel-header h3 {
  font-size: 17px; font-weight: 700; color: var(--text); margin: 0;
}
.pas-overlay.open .pas-sheet { transform: translateY(0); }
.pas-handle {
  width: 40px; height: 4px; border-radius: 2px;
  background: var(--border);
  margin: 6px auto 10px;
}
.pas-title {
  font-size: 14px; font-weight: 700; color: var(--text);
  text-align: center; margin-bottom: 10px;
}
.pas-list {
  display: flex; flex-direction: column; gap: 6px;
  padding: 12px 14px 4px;
}
.pas-item {
  display: flex; align-items: center; gap: 12px;
  width: 100%;
  padding: 12px 12px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 14px;
  color: var(--text);
  font-family: inherit;
  cursor: pointer;
  transition: transform .15s, background .15s;
  text-align: left;
}
.pas-item:active { transform: scale(.98); background: var(--surface-3); }
.pas-item-icon {
  width: 40px; height: 40px; flex-shrink: 0;
  border-radius: 12px;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 20px;
  color: #fff;
}
.pas-item-body {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column; gap: 2px;
}
.pas-item-title {
  font-size: 15px; font-weight: 700; color: var(--text); line-height: 1.2;
}
.pas-item-desc {
  font-size: 12px; color: var(--text-mute); line-height: 1.3;
}
.pas-item-chev {
  flex-shrink: 0;
  font-size: 22px; color: var(--text-mute); font-weight: 300;
  line-height: 1;
}
.pas-cancel {
  width: 100%;
  padding: 12px 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  color: var(--text);
  font-size: 14px; font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  transition: background .15s;
}
.pas-cancel:hover { background: var(--surface-2); }
.pas-cancel:active { transform: scale(.98); }

/* 桌面端: 不当作底部上拉菜单, 而是居中弹层 (与 dt-user-menu 风格保持统一)。
   sheet 不再贴底, 而是从中央略微下方淡入上滑。 */
@media (min-width: 768px) {
  body:not(.is-mobile-device) .pas-overlay {
    align-items: center;
  }
  body:not(.is-mobile-device) .pas-sheet {
    width: 380px;
    max-width: 92vw;
    border-radius: 18px;
    padding: 10px 14px 14px;
    transform: translateY(20px);
    opacity: 0;
    transition: transform .22s ease, opacity .22s ease;
    box-shadow: 0 18px 48px var(--shadow);
    border: 1px solid var(--border);
  }
  body:not(.is-mobile-device) .pas-overlay.open .pas-sheet {
    transform: translateY(0);
    opacity: 1;
  }
  body:not(.is-mobile-device) .pas-handle { display: none; }
}

/* Rebate table */
.rebate-config-table { width: 100%; border-collapse: collapse; font-size: 13px; margin-bottom: 16px; }
.rebate-config-table th { text-align: left; padding: 8px 6px; background: #f8f9fa; color: #666; font-weight: 600; }
.rebate-config-table td { padding: 8px 6px; border-bottom: 1px solid #f5f5f5; }

/* Referral */
.referral-code-box {
  background: #f8f9fa; border: 2px dashed #FE2C55; border-radius: 12px;
  padding: 20px; text-align: center; margin-bottom: 16px;
}
.referral-code { font-size: 28px; font-weight: 900; color: #FE2C55; letter-spacing: 4px; margin: 8px 0; }
.referral-copy-btn {
  padding: 8px 24px; border: none; border-radius: 8px;
  background: #FE2C55; color: #fff; font-size: 14px; font-weight: 600; cursor: pointer;
}
.referral-stat { display: flex; gap: 16px; margin-bottom: 16px; }
.referral-stat-item {
  flex: 1; background: #f8f9fa; border-radius: 10px; padding: 14px; text-align: center;
}
.referral-stat-num { font-size: 22px; font-weight: 800; color: #FE2C55; }
.referral-stat-label { font-size: 12px; color: #999; margin-top: 4px; }

/* Messages */
.msg-header {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 12px; padding-bottom: 10px; border-bottom: 1px solid #f0f0f0;
}
.msg-header-count { font-size: 13px; color: #666; }
.msg-read-all-btn {
  background: none; border: 1px solid #FE2C55; color: #FE2C55;
  font-size: 12px; padding: 4px 12px; border-radius: 14px; cursor: pointer;
  transition: all .2s;
}
.msg-read-all-btn:active { background: #FE2C55; color: #fff; }
.msg-list { display: flex; flex-direction: column; gap: 8px; }
.msg-item {
  padding: 12px 14px; border-radius: 10px; background: #f8f9fa; cursor: pointer;
  border: 1px solid #eee; transition: all .2s;
}
.msg-item:active { background: #f0f0f0; }
.msg-item.unread { background: #fff5f7; border-color: #fed7dc; }
.msg-item.unread::before {
  content: ''; display: inline-block; width: 6px; height: 6px;
  border-radius: 50%; background: #FE2C55; position: absolute;
  top: 16px; left: 6px;
}
.msg-item { position: relative; padding-left: 14px; }
.msg-item-row {
  display: flex; align-items: center; gap: 8px; margin-bottom: 6px;
}
.msg-type-badge {
  font-size: 11px; font-weight: 600; padding: 1px 8px; border-radius: 10px;
  flex-shrink: 0;
}
.msg-item-title {
  font-size: 14px; font-weight: 600; color: #333;
  flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.msg-item-time { font-size: 11px; color: #bbb; flex-shrink: 0; }
.msg-item-preview { font-size: 13px; color: #888; line-height: 1.5; }
.msg-item-full-text {
  font-size: 13px; color: #555; line-height: 1.7; white-space: pre-wrap;
  word-break: break-word; padding: 8px 0 4px;
}
.msg-item-expand {
  font-size: 11px; color: #bbb; text-align: center; margin-top: 6px;
}
.msg-pager {
  display: flex; align-items: center; justify-content: center;
  gap: 12px; margin-top: 16px; padding-top: 12px; border-top: 1px solid #f0f0f0;
}
.msg-pager-btn {
  background: none; border: 1px solid #ddd; padding: 6px 14px;
  border-radius: 6px; font-size: 13px; cursor: pointer; color: #333;
}
.msg-pager-btn:disabled { opacity: .4; cursor: not-allowed; }
.msg-pager-info { font-size: 12px; color: #999; }
.msg-badge {
  position: absolute; top: -4px; right: -4px;
  min-width: 16px; height: 16px; padding: 0 4px;
  background: #FE2C55; border-radius: 8px;
  font-size: 10px; color: #fff; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
}
/* 2026-04-28 修复: 桌面端用户菜单里的 .msg-badge 同时挂了 .dt-um-badge,
   原本 .msg-badge 的 position:absolute + top/right:-4px 会因为父按钮
   .dt-user-menu-item 没有 position:relative, 跑到 .dt-user-menu 这个
   定位祖先的右上角, 视觉上叠到第一项「存款」上, 看起来像存款有红点.
   这里恢复 static 让 .dt-um-badge 的 inline-flex 生效, badge 自然出现
   在「我的消息」文字右侧 (flex 布局 + .dt-um-text:flex:1 推到末尾). */
.dt-user-menu-item .msg-badge {
  position: static;
  top: auto;
  right: auto;
}

/* WS toast */
.ws-toast {
  position: fixed; top: 60px; right: 16px; z-index: 600;
  background: #fff; border-radius: 12px; padding: 14px 18px;
  box-shadow: 0 4px 20px rgba(0,0,0,.15); min-width: 260px; max-width: 340px;
  animation: wsSlideIn .3s ease; border-left: 4px solid #FE2C55;
}
.ws-toast.admin { border-left-color: #3b82f6; }
.ws-toast-title { font-size: 14px; font-weight: 700; color: #333; margin-bottom: 4px; }
.ws-toast-body { font-size: 13px; color: #666; }
@keyframes wsSlideIn {
  from { opacity: 0; transform: translateX(100%); }
  to { opacity: 1; transform: translateX(0); }
}
@keyframes notifyProgress {
  from { width: 100%; }
  to { width: 0; }
}

/* ======================================================
   GAME IFRAME (inline with nav visible)
   ====================================================== */
.game-fullscreen {
  position: fixed;
  top: 54px;
  left: 0; right: 0;
  bottom: calc(60px + env(safe-area-inset-bottom, 0px));
  z-index: 90;
  background: #000;
  display: flex; flex-direction: column;
  isolation: isolate;
  will-change: transform;
  touch-action: auto;
}
/* 进入全屏的判定：toggleGameFs() 设 .game-fullscreen[data-fs="1"]
   并在 body 上加 .game-fs-landscape 类。下面所有「全屏后」的样式
   都用 [data-fs="1"] 锚定，避免之前 .fs-true 死选择器的问题。 */
.game-fullscreen[data-fs="1"] {
  top: 0 !important; bottom: 0 !important; left: 0 !important; right: 0 !important;
  z-index: 99999 !important;
}
/* 全屏后：隐藏整个 .game-fs-topbar，让游戏 iframe 真正占满
   .game-fullscreen 区域 (top:0~bottom:0)，不再被 40px 标题栏占位。
   退出全屏的入口由浮动按钮 .game-fs-exit-btn 提供（在游戏右上角悬浮）。
   .game-shield 也要把 top:40px 顶到 0，否则全屏后 shield 起点错位。 */
.game-fullscreen[data-fs="1"] .game-fs-topbar { display: none !important; }
.game-fullscreen[data-fs="1"] .game-shield { top: 0; }

/* === 全屏模式下取消所有遮罩 / 覆盖层 ===
   用户进入全屏（toggleGameFs → data-fs=1 + body.game-fs-landscape）时，
   彻底放开游戏 iframe，让玩家在真人 / 捕鱼 / 老虎机等任意游戏中都能
   正常操作（确认下注、点击桌台、拖拉转盘等），不被任何前端浮层拦截。
   退出全屏时 body 上的 .game-fs-landscape 自动移除 → 所有规则失效，
   恢复原状，无需额外 JS。
*/

/* 1. 加载遮罩 / TikTok 滑切手势区 / 桌面滚轮切游戏 zone：全屏时彻底关闭。
      这些都是为非全屏体验设计的，全屏后必须让位给游戏本身。 */
body.game-fs-landscape .game-shield,
body.game-fs-landscape .game-swipe-edge,
body.game-fs-landscape .game-wheel-edge {
  display: none !important;
}

/* 2. 全屏模式下 actionBar 处理 (2026-04-22 用户需求改造):
      原本会把右侧 actionBar 整列 + 小拉手都强制 display:none, 让 iframe 完全独占.
      新需求: 全屏时 actionBar 仍可访问, 但默认收起为小拉手, 用户点拉手能展开.
      → 不再无条件隐藏 .action-bar / .action-bar-handle / .action-collapse-btn,
        改由 toggleGameFs 在 JS 里强制加 body.action-bar-collapsed class 进入"小拉手"形态.
      → next-game-preview (actionBar 下方"下一张游戏"预览图) 全屏不需要, 仍隐藏. */
body.game-fs-landscape .next-game-preview {
  display: none !important;
}

/* 全屏时 #gameFullscreen 容器 inline z-index=99999 会盖住默认 9998/200 的
   小拉手 + actionBar, 导致看不见. 把它们提到容器之上让用户能操作. */
body.game-fs-landscape .action-bar-handle { z-index: 100001 !important; }
body.game-fs-landscape .action-bar         { z-index: 100000 !important; }
body.game-fs-landscape .action-collapse-btn { z-index: 100002 !important; }

/* 3. 浮动按钮：红包雨入口、客服 FAB、其它 ng-fab-* 类悬浮按钮全部藏起。
      游戏内已经有自己的菜单按钮，再叠浮层只会挡画面或抢点击。 */
body.game-fs-landscape #rp-float-btn,
body.game-fs-landscape .ng-lc-fab,
body.game-fs-landscape .ng-fab,
body.game-fs-landscape .ng-fab-cs {
  display: none !important;
}

/* 4. 移动端顶部 / 底部导航条：全屏自然不该出现。 */
body.is-mobile-device.game-fs-landscape #topBar,
body.is-mobile-device.game-fs-landscape #bottomNav,
body.is-mobile-device.game-fs-landscape .game-info-overlay {
  display: none !important;
}

/* 5. 桌面 sidebar：全屏时游戏要完全占满，sidebar 滑出屏幕外让位。 */
@media (min-width: 768px) {
  body:not(.is-mobile-device).game-fs-landscape .dt-sidebar {
    display: none !important;
  }
  body:not(.is-mobile-device).game-fs-landscape .dt-main {
    padding-right: 0 !important;
  }
}

/* 6. iframe 自身确保接管所有指针事件，避免任何残留 z-index 较高的
      overlay（如 toast / 下拉菜单等）默认情况下拦截游戏点击。 */
body.game-fs-landscape .game-fs-iframe {
  pointer-events: auto !important;
  touch-action: auto !important;
}

/* 7. 终极兜底：全屏时 .game-fullscreen 容器内除了 iframe 和退出按钮，
      其余任何子元素（左右两边 swipe-edge / wheel-edge / shield / 自定义
      浮层 / 未来新加的元素）一律隐藏 + 关闭点击。这样不必再针对每个
      具体 class 维护白名单，新增覆盖物默认就被屏蔽。 */
body.game-fs-landscape .game-fullscreen > *:not(#gameIframe):not(.game-fs-exit-btn) {
  display: none !important;
  pointer-events: none !important;
  visibility: hidden !important;
}

/* 8. iframe 容器本身放最低层：保证 iframe 占满（top:0;left:0;right:0;bottom:0），
      退出按钮独立浮在最上层（z-index:20，已在 .game-fs-exit-btn 中定义）。 */
body.game-fs-landscape .game-fs-iframe {
  position: absolute !important;
  inset: 0 !important;
  width: 100% !important;
  height: 100% !important;
  z-index: 1 !important;
}

/* 浮动「退出全屏」按钮：仅在全屏 (data-fs="1") 时显示，
   悬浮于游戏右上角，不占据布局空间。 */
.game-fs-exit-btn {
  display: none;
  position: absolute;
  top: calc(8px + env(safe-area-inset-top, 0px));
  right: calc(8px + env(safe-area-inset-right, 0px));
  z-index: 20;
  width: 36px; height: 36px;
  border-radius: 50%;
  background: rgba(0,0,0,.55);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid rgba(255,255,255,.22);
  color: #fff;
  cursor: pointer;
  align-items: center; justify-content: center;
  padding: 0;
  -webkit-tap-highlight-color: transparent;
  transition: background .15s, transform .12s;
}
.game-fs-exit-btn:hover { background: rgba(0,0,0,.75); }
.game-fs-exit-btn:active { transform: scale(.9); }
.game-fs-exit-btn svg { display: block; pointer-events: none; }
.game-fullscreen[data-fs="1"] .game-fs-exit-btn { display: flex; }
/* 全平台隐藏左上角 ← 返回按钮：
   - 桌面端：sidebar 上的 LOGO 已经是返回大厅入口，且任意 dt-nav 项进入
     dt-feed-overlay 模式（游戏不打断）；
   - 移动端：底部 #bottomNav 的「游戏大厅」+ 浏览器原生后退键已经能返回；
   多一个 ← 容易和浏览器顶部「后退」重叠造成误触。 */
/* 用 visibility:hidden 而不是 display:none —— 仍占 44px 宽度, 与右侧
   .game-fs-fullscreen 视觉对称, 这样中间的 .game-fs-title 才能在屏幕正中
   居中显示 (2026-04-21 用户反馈: title 偏左). pointer-events:none 防误点. */
.game-fs-back {
  visibility: hidden !important;
  pointer-events: none !important;
}

.game-fs-topbar {
  /* 与按钮触控区统一 44px，避免标题相对按钮垂直「偏移」 */
  height: 44px; min-height: 44px; flex-shrink: 0;
  background: #161823;
  display: flex; align-items: center;
  padding: 0 8px; gap: 8px;
  z-index: 10;
  position: relative;
}
.game-fs-back, .game-fs-fullscreen, .game-fs-nav {
  background: none; border: none; color: #fff;
  cursor: pointer; padding: 6px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  transition: background .2s;
  width: 36px; height: 36px;
  min-width: 36px; min-height: 36px;
  box-sizing: border-box;
  -webkit-tap-highlight-color: rgba(255,255,255,.15);
}
.game-fs-back:hover, .game-fs-fullscreen:hover, .game-fs-nav:hover { background: rgba(255,255,255,.1); }
.game-fs-nav:active { background: rgba(255,255,255,.18); transform: scale(.92); }
.game-fs-nav { display: none; }  /* 默认隐藏：移动端走 swipe 手势 */
@media (min-width: 768px) {
  body:not(.is-mobile-device) .game-fs-nav { display: flex; }
}
.game-fs-title {
  flex: 1; color: #fff; font-size: 15px; font-weight: 600;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  text-align: center;
}
.game-fs-iframe {
  flex: 1; width: 100%; border: none; background: #000;
  touch-action: auto;
}
.game-swipe-edge {
  position: absolute;
  top: 30%; bottom: 30%;
  left: 50px; right: 50px;
  z-index: 3;
  background: transparent;
  pointer-events: auto;
  touch-action: none;
}
.game-swipe-edge.passthrough {
  pointer-events: none;
}
.game-swipe-right { display: none; }
.game-shield {
  position: absolute;
  top: 40px; left: 0; right: 0; bottom: 0;
  z-index: 2;
  background: transparent;
  touch-action: auto;
}

@media (min-width: 768px) {
  body:not(.is-mobile-device) .game-fullscreen {
    top: 0; bottom: 0;
    /* left/right 用 CSS 变量，与 .dt-sidebar/.action-bar 同步折叠 */
    left: var(--dt-sidebar-w, 240px); right: 96px;
    z-index: 90;
  }
  body:not(.is-mobile-device) .game-fullscreen[data-fs="1"] { left: 0 !important; right: 0 !important; top: 0 !important; bottom: 0 !important; z-index: 99999 !important; }
  /* 桌面端没有触摸，不需要 TikTok 滑动手势区。
     若不禁用，这层透明 div 会盖在 iframe 上吃掉所有鼠标点击 → 游戏无法操作。 */
  body:not(.is-mobile-device) .game-swipe-edge { display: none; }
  /* gameShield 用于 loading 阶段引导用户点击解锁音频；桌面端不需要遮罩，
     load 完成前万一未及时隐藏，也不要拦截鼠标 */
  body:not(.is-mobile-device) .game-shield { pointer-events: none; }
  /* 2026-06-10 用户要求: 桌面版彻底取消游戏左右两侧(及四周)的透明遮罩层
     (.game-wheel-edge 滚轮热区). 这些透明层会盖在游戏左右两侧、吃掉鼠标点击,
     遮挡厂商左右两侧的 UI. 桌面端不再需要这套"任意位置滚轮切游戏"的热区,
     滚轮/中键切游戏仍由顶栏 (.game-fs-topbar) 与右侧 actionBar 接管, 不影响功能.
     ⚠️ 仅桌面端 (body:not(.is-mobile-device)); 手机端的滑动遮罩 (.game-swipe-edge)
     完全不动, 该需求只针对桌面版. */
  body:not(.is-mobile-device) .game-wheel-edge { display: none !important; }
}

/* 桌面端 wheel zone：透明覆盖在 iframe 四边（除右边由 actionBar 接管），
   学 TikTok"任意地方都能滚轮切下一个"的体验。游戏中心区域不被遮挡。
   移动端默认隐藏（用 swipe-edge 即可） */
.game-wheel-edge {
  display: none;
  position: absolute;
  z-index: 4;
  background: transparent;
  pointer-events: auto;
  cursor: ns-resize;
}
.game-wheel-edge-left {
  top: 40px; bottom: 0;
  left: 0;
  width: 60px;
}
.game-wheel-edge-top {
  top: 40px;
  left: 0; right: 0;
  height: 60px;
}
/* 用户反馈 (2026-04-22, AFB GGCS 体育): top wheel zone 透明覆盖在 iframe
   顶部 40~100px 全宽, pointer-events:auto 会吞掉点击 → 厂商页面常把
   "Bet List / BetSlip / Score / Settings / Day / Info / English" 等控制条
   放在该区域 (AFB / JILI / PGSoft 都有), iframe 里完全点不到.
   解法: 桌面端直接隐藏 top zone, 保留 left + bottom 两条 zone 已经够实现
   "任意位置滚轮切游戏"; 同时 topbar 自身也带滚轮切游戏 handler. */
body:not(.is-mobile-device) .game-wheel-edge-top { display: none !important; }
/* 用户反馈 (2026-04-23, JILI iRich Bingo 横屏游戏): left wheel zone 60px 宽
   覆盖 iframe 左侧 0~60px, pointer-events:auto + cursor:ns-resize 会吞掉
   厂商左侧的设置齿轮 / Logo / 历史 / 浮窗按钮的点击, 鼠标也无法 hover 到
   游戏 UI (cursor 变成上下箭头). 16:9 游戏在比例 < 16:9 的 iframe 中按宽度
   缩放, 左右贴边, 左侧按钮正好落进这 60px 热区; 窗口拉宽到 > 16:9 后游戏
   被居中、左侧出现黑边, 按钮才离开热区, 因此"窗口拉很大就能点".
   解法: 与 top zone 对称, 桌面端直接隐藏 left zone; topbar / actionBar /
   bottom zone 仍然能接管"任意位置滚轮切游戏". 移动端不受影响, 仍走 swipe-edge. */
body:not(.is-mobile-device) .game-wheel-edge-left { display: none !important; }
.game-wheel-edge-bottom {
  /* 底部只留 20px，避免遮挡游戏内的 BUY FEATURE / BALANCE / TOTAL BET 等按钮 */
  bottom: 0;
  left: 0; right: 0;
  height: 20px;
}

/* ============================================================
   2026-06-10 桌面端彻底放开游戏点击 —— 不再有任何遮罩层拦截
   ------------------------------------------------------------
   用户反馈: 桌面版游戏左右/四周仍有透明遮罩, 鼠标落在游戏上(尤其右上角
   厂商设置面板的 ×)点不动. 根因: .game-shield / .game-swipe-edge /
   .game-wheel-edge 等都是 #gameIframe 的兄弟浮层, 它们的"桌面端隐藏 / 关指针"
   规则散落在 @media(min-width:768px) 里, 一旦命中不到(窗口宽度临界、加载态
   inline display:block、未来新增浮层…)就会盖在 iframe 上吃掉点击.

   这里照搬"全屏取消所有遮罩"(见上方 body.game-fs-landscape 第 7 条)的思路,
   对【桌面端 + 游戏中】做同样的兜底: game-fullscreen 容器内除 iframe / 顶栏 /
   退出按钮外, 所有子元素一律 pointer-events:none, 并强制 iframe 接管指针.
   不依赖媒体查询、不必逐个维护浮层白名单, 新增浮层默认就不会拦截游戏.
   ⚠️ 仅 body:not(.is-mobile-device); 手机端的 .game-swipe-edge 滑动遮罩
   完全不受影响, 该需求只针对桌面版. */
body:not(.is-mobile-device).game-playing
  .game-fullscreen > *:not(#gameIframe):not(.game-fs-topbar):not(.game-fs-exit-btn) {
  pointer-events: none !important;
}
body:not(.is-mobile-device).game-playing .game-fs-iframe {
  pointer-events: auto !important;
}

/* ===== Landscape Lock =====
   2026-05-04 文案 + 动画升级:
     - 文案改为「请关闭手机自动旋转功能」, 副标题指引用户去控制中心关闭.
     - 动画用「持续摆动的手机 + 圆弧虚线箭头 + 红色禁止图标」, 让用户秒懂
       为什么要关闭自动旋转, 配 cubic-bezier 弹性回弹更生动. */
.landscape-lock {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 99999;
  background: radial-gradient(circle at 50% 35%, #1a1a26 0%, #0a0a14 80%);
  align-items: center;
  justify-content: center;
  flex-direction: column;
  touch-action: none;
  pointer-events: auto;
  padding: 20px;
}
.landscape-lock-inner {
  text-align: center;
  color: rgba(255,255,255,.85);
  max-width: 320px;
}
.landscape-anim {
  position: relative;
  width: 120px; height: 120px;
  margin: 0 auto 28px;
  display: flex; align-items: center; justify-content: center;
}
.landscape-phone {
  color: rgba(255,255,255,.92);
  transform-origin: 50% 50%;
  animation: landscape-phone-rock 2.4s cubic-bezier(.68,-.55,.27,1.55) infinite;
  filter: drop-shadow(0 4px 12px rgba(255,255,255,.12));
}
.landscape-arc {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  color: rgba(255,255,255,.6);
  animation: landscape-arc-fade 2.4s ease-in-out infinite;
}
.landscape-forbidden {
  position: absolute;
  top: -2px; right: 8px;
  width: 30px; height: 30px;
  background: #fff;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 4px 12px rgba(255,59,106,.45);
  animation: landscape-forbid-pop 2.4s ease-in-out infinite;
}
.landscape-title {
  font-size: 17px;
  font-weight: 600;
  letter-spacing: .5px;
  margin: 0 0 10px;
  color: #fff;
}
.landscape-sub {
  font-size: 13px;
  line-height: 1.6;
  color: rgba(255,255,255,.6);
  margin: 0;
}

@keyframes landscape-phone-rock {
  0%   { transform: rotate(0deg); }
  20%  { transform: rotate(-90deg); }
  45%  { transform: rotate(-90deg); }
  65%  { transform: rotate(0deg); }
  85%  { transform: rotate(0deg); }
  100% { transform: rotate(0deg); }
}
@keyframes landscape-arc-fade {
  0%, 20%   { opacity: 0; }
  35%       { opacity: 1; }
  55%, 100% { opacity: .35; }
}
@keyframes landscape-forbid-pop {
  0%, 55%   { transform: scale(0); opacity: 0; }
  65%       { transform: scale(1.25); opacity: 1; }
  80%, 100% { transform: scale(1); opacity: 1; }
}

body.is-mobile-device.is-landscape .landscape-lock { display: flex; }
body.is-mobile-device.is-landscape.game-fs-landscape .landscape-lock { display: none; }

/* ===== Scrollbar ===== */
::-webkit-scrollbar { width: 4px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: rgba(255,255,255,.15); border-radius: 2px; }

/* ============================================
 * Daily check-in prompt modal
 * 登录后/已登录刷新页面后, 未签到则居中弹出此小弹窗.
 * 每账号每日仅弹 1 次 (localStorage _ckdismiss_<mid>_<date>).
 * 同时支持移动端与桌面端, 用 z-index 9999 浮在所有 overlay 之上.
 * ============================================ */
.ck-modal-mask {
  position: fixed; inset: 0; z-index: 9999;
  background: rgba(0, 0, 0, .55);
  display: flex; align-items: center; justify-content: center;
  opacity: 0; transition: opacity .22s ease;
  -webkit-tap-highlight-color: transparent;
}
.ck-modal-mask.show { opacity: 1; }
.ck-modal {
  position: relative;
  width: 88%; max-width: 340px;
  background: #fff;
  border-radius: 16px;
  padding: 28px 22px 20px;
  text-align: center;
  box-shadow: 0 20px 60px rgba(0, 0, 0, .25);
  /* 出场用轻微弹跳; mask.show 触发后 transform 归位 */
  transform: translateY(12px) scale(.96);
  transition: transform .25s cubic-bezier(.34, 1.56, .64, 1);
}
.ck-modal-mask.show .ck-modal { transform: translateY(0) scale(1); }
.ck-modal-close {
  position: absolute; top: 8px; right: 12px;
  width: 30px; height: 30px;
  background: transparent; border: 0;
  font-size: 22px; color: #999; cursor: pointer; line-height: 1;
}
.ck-modal-close:hover { color: #555; }
.ck-modal-icon { font-size: 44px; line-height: 1; margin-bottom: 8px; }
.ck-modal-title {
  font-size: 18px; font-weight: 700; color: #222; margin-bottom: 6px;
}
.ck-modal-sub {
  font-size: 13px; color: #666; line-height: 1.5; margin-bottom: 14px;
}
.ck-modal-sub b { color: #ff5b6e; font-weight: 700; }
.ck-modal-reward {
  display: inline-block;
  padding: 8px 16px; margin-bottom: 18px;
  background: linear-gradient(135deg, #fff7e8, #ffe4c4);
  color: #d97706; font-weight: 700; font-size: 15px;
  border-radius: 999px;
}
.ck-modal-actions {
  display: flex; gap: 10px;
}
.ck-modal-btn-secondary,
.ck-modal-btn-primary {
  flex: 1;
  height: 42px;
  border: 0; border-radius: 10px;
  font-size: 15px; font-weight: 600;
  cursor: pointer;
  transition: opacity .15s, transform .12s, background .15s;
}
.ck-modal-btn-secondary {
  background: #f1f3f5; color: #555;
}
.ck-modal-btn-secondary:hover { background: #e7eaee; }
.ck-modal-btn-primary {
  background: linear-gradient(90deg, #ff4d6d, #ff8c5a);
  color: #fff;
  box-shadow: 0 6px 16px rgba(255, 77, 109, .35);
}
.ck-modal-btn-primary:hover { transform: translateY(-1px); }
.ck-modal-btn-primary:disabled { opacity: .6; cursor: not-allowed; transform: none; }

/* ============================================================
   I18N — Language Switcher
   ------------------------------------------------------------
   1. .lang-trigger      : 登录/注册 panel-header 右上角的小按钮 (旗+语种缩写+▾)
   2. .lang-picker-*     : 居中模态语言选择器, 由 #langPickerOverlay 唤起
   3. .settings-lang*    : profile 侧菜单中 "语言" 的折叠面板 (展开式列表)
   ============================================================ */

/* ---- Desktop sidebar footer trigger (深色侧栏专用) ----
   2026-04-27: 桌面端常驻语言切换按钮, 无论登录/未登录都显示 (在 .dt-sidebar-footer 顶部).
   命中 [data-lang-trigger="dt-sidebar"], 共享 i18n/index.js 的 _refreshTriggerLabels +
   _openPicker, 不需要单独 JS. 折叠态 (≤1024px) 收成方块图标.
   2026-04-28: 主题变量化, 与 .dt-sidebar-theme-btn 共用骨架. */
.dt-sidebar-lang-btn,
.dt-sidebar-theme-btn {
  width: 100%;
  display: flex; align-items: center; gap: 10px;
  padding: 9px 12px;
  background: var(--chip-bg);
  border: 1px solid var(--border);
  color: var(--text-soft);
  border-radius: 10px;
  font-size: 13px; font-weight: 500;
  cursor: pointer;
  transition: background .15s, border-color .15s, color .15s, transform .1s;
  line-height: 1;
  margin-bottom: 8px;
}
.dt-sidebar-lang-btn:hover,
.dt-sidebar-theme-btn:hover {
  background: var(--surface-2);
  border-color: var(--border);
  color: var(--text);
}
.dt-sidebar-lang-btn:active,
.dt-sidebar-theme-btn:active { transform: scale(.985); }
.dt-sidebar-lang-icon,
.dt-sidebar-theme-svg {
  width: 22px; height: 22px;
  display: flex; align-items: center; justify-content: center;
  color: var(--text-mute);
  flex-shrink: 0;
}
.dt-sidebar-lang-btn:hover  .dt-sidebar-lang-icon,
.dt-sidebar-theme-btn:hover .dt-sidebar-theme-svg { color: var(--text-soft); }
.dt-sidebar-lang-btn .lang-trigger-flag,
.dt-sidebar-theme-btn .theme-trigger-icon {
  font-size: 16px; line-height: 1;
  flex-shrink: 0;
}
.dt-sidebar-lang-btn .lang-trigger-name,
.dt-sidebar-theme-btn .theme-trigger-name {
  flex: 1; min-width: 0;
  text-align: left;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  letter-spacing: .2px;
}
.dt-sidebar-lang-caret,
.dt-sidebar-theme-caret {
  color: var(--text-faint);
  flex-shrink: 0;
}
.dt-sidebar-lang-btn:hover  .dt-sidebar-lang-caret,
.dt-sidebar-theme-btn:hover .dt-sidebar-theme-caret { color: var(--text-soft); }
.dt-sidebar-lang-divider {
  height: 1px;
  background: var(--divider);
  margin: 0 -4px 12px;
}

/* 折叠态: 仅显示图标 (旗+名+caret 全收起), 与下方 dt-user-trigger 视觉对齐 */
@media (max-width: 1024px) {
  .dt-sidebar-lang-btn,
  .dt-sidebar-theme-btn {
    flex-direction: column;
    justify-content: center;
    padding: 8px 4px;
    gap: 0;
    margin-bottom: 6px;
  }
  .dt-sidebar-lang-btn .lang-trigger-flag,
  .dt-sidebar-lang-btn .lang-trigger-name,
  .dt-sidebar-lang-caret,
  .dt-sidebar-theme-btn .theme-trigger-icon,
  .dt-sidebar-theme-btn .theme-trigger-name,
  .dt-sidebar-theme-caret { display: none; }
  .dt-sidebar-lang-icon,
  .dt-sidebar-theme-svg { width: 24px; height: 24px; }
  .dt-sidebar-lang-divider { margin: 0 0 8px; }
}

/* ---- Login/Register panel-header inline trigger ----
   .lang-trigger 与 .theme-trigger 同骨架, 只是子元素不同 (旗 vs 图标). */
.lang-trigger,
.theme-trigger {
  /* margin-left:auto 把第一个 trigger 推到 close 按钮旁边, 形成右对齐组. */
  display: inline-flex; align-items: center; gap: 6px;
  /* 背景从 4% 黑 → 7% 黑, 边框从 6% 黑 → 14% 黑: 在 .login-panel 白底上
     原配色几乎透明 (用户反馈 2026-04-28 截图: 移动端只看到月亮/旗 emoji,
     胶囊背景看不见, 文字 "夜间"/"简体中文" 显示也不够醒目). 加深后视觉
     与 .panel-close 一致, 移动端拇指可点区域更清晰. */
  background: rgba(0,0,0,.07);
  border: 1px solid rgba(0,0,0,.14);
  color: #161823;
  padding: 6px 10px; border-radius: 999px;
  font-size: 12px; font-weight: 600;
  cursor: pointer;
  transition: background .15s, border-color .15s, transform .12s;
  line-height: 1;
}
.theme-trigger { margin-left: auto; margin-right: 6px; }
.lang-trigger  { margin-right: 10px; }
/* 同时存在 (登录注册页) 时只让最左那个吃 margin-left:auto */
.theme-trigger + .lang-trigger { margin-left: 0; }
.panel-header > .lang-trigger:first-of-type:not(.theme-trigger + .lang-trigger) { margin-left: auto; }
/* 2026-07-18: 经典模式按钮 (#loginClassicMode/#registerClassicMode) 也带 .theme-trigger,
   于是它和其后的主题按钮各自吃到 margin-left:auto → 两段 auto 平分剩余空间, 经典模式
   按钮被卡在标题与主题组中间, 形成过长空隙 (用户反馈截图). 让经典模式按钮独吃 auto,
   取消其后主题按钮的 auto, 使 经典模式+主题+语言+关闭 紧凑右对齐成同一组. */
.panel-header .ng-mode-trigger + .theme-trigger { margin-left: 0; }

.lang-trigger:hover, .theme-trigger:hover  { background: rgba(0,0,0,.12); border-color: rgba(0,0,0,.22); }
.lang-trigger:active, .theme-trigger:active { transform: scale(.97); }
.lang-trigger-flag, .theme-trigger-icon { font-size: 16px; line-height: 1; }
.lang-trigger-name, .theme-trigger-name { letter-spacing: .2px; }

/* ---- 经典模式入口: 仅移动版显示 (2026-07-10) ----
   登录/注册面板右上角的 "经典模式" (#loginClassicMode / #registerClassicMode)
   切换按钮只面向移动端 (App 化体验才提供经典皮肤). 桌面版不需要, 默认隐藏,
   仅在移动视口 (max-width:767px) 或已判定为移动设备 (body.is-mobile-device) 时显示. */
.panel-header .ng-mode-trigger { display: none; }
@media (max-width: 767px) {
  .panel-header .ng-mode-trigger { display: inline-flex; }
}
body.is-mobile-device .panel-header .ng-mode-trigger { display: inline-flex; }

/* ---- Mobile panel-header trigger (登录/注册 panel 弹起时用) ----
   桌面 panel-header 是横向胶囊 (emoji + 文字 + caret), 在 mobile 上挤
   出 panel 宽度且文字小到看不清 (用户反馈 2026-04-28 截图: 只看到孤立
   月亮/中国旗, 没胶囊没文字). 改成圆形按钮: 仅 emoji, 视觉与 .panel-close
   (28px ×) 平衡, 拇指可点区域 36×36, 浅灰底有明显视觉边界. */
body.is-mobile-device .panel-header .lang-trigger,
body.is-mobile-device .panel-header .theme-trigger {
  width: 36px; height: 36px;
  padding: 0;
  border-radius: 50%;
  gap: 0;
  justify-content: center;
  background: rgba(0,0,0,.06);
  border-color: rgba(0,0,0,.1);
}
body.is-mobile-device .panel-header .lang-trigger-name,
body.is-mobile-device .panel-header .theme-trigger-name,
body.is-mobile-device .panel-header .lang-trigger > svg,
body.is-mobile-device .panel-header .theme-trigger > svg {
  display: none;
}
body.is-mobile-device .panel-header .lang-trigger-flag,
body.is-mobile-device .panel-header .theme-trigger-icon {
  font-size: 18px;
}
body.is-mobile-device .panel-header .lang-trigger:hover,
body.is-mobile-device .panel-header .theme-trigger:hover {
  background: rgba(0,0,0,.1);
}
.lang-trigger svg, .theme-trigger svg { opacity: .6; }
/* dark surface fallback: login panel 在 light 下是白底 (硬编码), 在 dark 下需要反白 trigger */
@media (prefers-color-scheme: dark) {
  .lang-trigger, .theme-trigger {
    background: rgba(255,255,255,.08); border-color: rgba(255,255,255,.18); color: #fff;
  }
}
:root[data-theme="dark"] .lang-trigger,
:root[data-theme="dark"] .theme-trigger {
  background: rgba(255,255,255,.08); border-color: rgba(255,255,255,.18); color: #fff;
}
/* 修正 specificity: 上面 mobile 圆形规则 (3 classes) 比 dark override (2 classes + attr)
   高, 在 dark 下 mobile login panel-header trigger 仍会用 light 配色 (黑底黑边几乎不可见,
   2026-04-28 用户反馈截图). 加一条 4-class 规则强制覆盖. */
:root[data-theme="dark"] body.is-mobile-device .panel-header .lang-trigger,
:root[data-theme="dark"] body.is-mobile-device .panel-header .theme-trigger {
  background: rgba(255,255,255,.08);
  border-color: rgba(255,255,255,.18);
  color: #fff;
}
:root[data-theme="dark"] body.is-mobile-device .panel-header .lang-trigger:hover,
:root[data-theme="dark"] body.is-mobile-device .panel-header .theme-trigger:hover {
  background: rgba(255,255,255,.14);
}

/* .panel-close (X 按钮) 视觉与 .lang-trigger / .theme-trigger 对齐, 加灰色胶囊
   外框, 让 panel-header 一组按钮看起来是同一族. mobile 下也给 36×36 圆形. */
body.is-mobile-device .panel-header .panel-close {
  width: 36px; height: 36px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: rgba(0,0,0,.06);
  border: 1px solid rgba(0,0,0,.1);
  font-size: 22px;  /* 之前 28px 在 36×36 圆里有点紧, 缩到 22 */
  opacity: 1;
  transition: background .15s, border-color .15s;
}
body.is-mobile-device .panel-header .panel-close:hover {
  background: rgba(0,0,0,.1);
}
:root[data-theme="dark"] body.is-mobile-device .panel-header .panel-close {
  background: rgba(255,255,255,.08);
  border-color: rgba(255,255,255,.18);
}
:root[data-theme="dark"] body.is-mobile-device .panel-header .panel-close:hover {
  background: rgba(255,255,255,.14);
}

/* ---- Centered picker modal (shared by lang & theme) ----
   2026-04-27: z-index 从 1300 → 100200, 高于 .dt-sidebar 在 game-playing 时的
   z=9999 / .action-bar 在 game-fs 时的 100000 / #searchOverlay.active 100050.
   原本 1300 会被 sidebar 覆盖, 导致游戏中打开 picker 后再点侧栏 Promosi 等其他
   nav: 点击穿过 mask 命中 sidebar (9999>1300) 触发底层 ci-overlay (z=1000) 打开,
   但 ci-overlay 又在 picker(1300) 之下, 用户看到的是 picker 仍盖在最上, 底下
   "promosi 没显示". 现在 picker 提到全站最高, 视觉绝对最顶.
   配合下方 _bindPickerInteractions 改造: overlay+mask 改 pointer-events:none,
   只有 .lang-picker-panel 接收点击 → 用户点 panel 之外任意区域时, click
   穿透到底下原始目标 (例如 sidebar nav), 同时 JS 监听到这次外部点击会
   _closePicker(), 实现"点哪都自动关 picker + 仍能立即跳转目标".
   2026-04-28: theme-picker 与 lang-picker 共用骨架, 主题变量化, 在 light 模式
   下自动反白; 唯一独立的是 list 部分的图标 (旗 vs emoji icon). */
.lang-picker-overlay,
.theme-picker-overlay {
  position: fixed; inset: 0; z-index: 100200;
  display: none;
  align-items: center; justify-content: center;
  pointer-events: none;
}
.lang-picker-overlay.open,
.theme-picker-overlay.open { display: flex; }
.lang-picker-mask,
.theme-picker-mask {
  position: absolute; inset: 0;
  background: var(--mask);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  opacity: 0; transition: opacity .2s;
  pointer-events: none;
}
.lang-picker-overlay.open .lang-picker-mask,
.theme-picker-overlay.open .theme-picker-mask { opacity: 1; }
.lang-picker-panel,
.theme-picker-panel {
  pointer-events: auto;
  position: relative;
  width: min(92vw, 360px);
  background: var(--picker-bg);
  border-radius: 16px;
  border: 1px solid var(--border);
  box-shadow: var(--shadow-lg);
  color: var(--text);
  overflow: hidden;
  transform: scale(.95) translateY(8px);
  opacity: 0;
  transition: opacity .22s, transform .22s cubic-bezier(.2,.9,.3,1.1);
}
.lang-picker-overlay.open .lang-picker-panel,
.theme-picker-overlay.open .theme-picker-panel { transform: scale(1) translateY(0); opacity: 1; }
.lang-picker-header,
.theme-picker-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 16px;
  font-size: 15px; font-weight: 700;
  border-bottom: 1px solid var(--divider);
}
/* 2026-05-06: 视觉已并入 "Unified overlay header buttons", 这里只保留 color
   微调 (text-soft 让 picker 弹窗里的 × 比 panel-close 略柔, 与 picker 整体
   tone 一致); 大小/形状/hover 圆形高亮均由统一规则接管. */
.lang-picker-close,
.theme-picker-close { color: var(--text-soft); }
.lang-picker-close:hover,
.theme-picker-close:hover { color: var(--text); }
.lang-picker-list,
.theme-picker-list {
  max-height: 70vh; overflow-y: auto;
  padding: 6px 0;
  -webkit-overflow-scrolling: touch;
}
.lang-picker-item,
.theme-picker-item {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 18px;
  cursor: pointer;
  transition: background .12s;
  border: none; background: transparent; color: inherit; width: 100%;
  text-align: left; font-size: 15px;
  -webkit-tap-highlight-color: transparent;
}
.lang-picker-item:hover,
.theme-picker-item:hover { background: var(--surface-2); }
.lang-picker-item .lpi-flag,
.theme-picker-item .tpi-icon { font-size: 22px; line-height: 1; width: 26px; text-align: center; }
.lang-picker-item .lpi-name,
.theme-picker-item .tpi-name { flex: 1; font-weight: 500; }
.lang-picker-item .lpi-check,
.theme-picker-item .tpi-check {
  color: var(--success); font-size: 18px; opacity: 0;
  transform: scale(.6); transition: opacity .15s, transform .15s;
}
.lang-picker-item.active .lpi-check,
.theme-picker-item.active .tpi-check { opacity: 1; transform: scale(1); }
.lang-picker-item.active,
.theme-picker-item.active { background: rgba(67,160,71,.1); }

/* ---- profileSideMenu language & theme collapse (共用骨架) ---- */
.settings-item.settings-lang,
.settings-item.settings-theme { position: relative; }
.settings-lang-current,
.settings-theme-current {
  flex: 0 0 auto !important;
  font-size: 13px !important;
  font-weight: 500 !important;
  color: #999;
  margin-left: auto; margin-right: 4px;
  max-width: 100px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.settings-item.settings-lang .settings-arrow,
.settings-item.settings-theme .settings-arrow {
  margin-left: 0;
  transition: transform .2s;
}
.settings-item.settings-lang[aria-expanded="true"] .settings-arrow,
.settings-item.settings-theme[aria-expanded="true"] .settings-arrow {
  transform: rotate(90deg);
}
.settings-lang-list,
.settings-theme-list {
  display: none;
  background: #fafafa;
  border-bottom: 1px solid #f0f0f0;
  margin: 0 -16px;
  padding: 4px 0;
}
.settings-lang-list.open,
.settings-theme-list.open { display: block; }
.settings-lang-list-item,
.settings-theme-list-item {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 36px;
  cursor: pointer;
  font-size: 14px; color: #333;
  transition: background .12s;
  border: none; background: transparent; width: 100%;
  text-align: left;
  -webkit-tap-highlight-color: transparent;
}
.settings-lang-list-item:hover,
.settings-theme-list-item:hover { background: #f0f0f0; }
.settings-lang-list-item .sll-flag,
.settings-theme-list-item .stl-icon { font-size: 18px; width: 22px; text-align: center; }
.settings-lang-list-item .sll-name,
.settings-theme-list-item .stl-name { flex: 1; }
.settings-lang-list-item .sll-check,
.settings-theme-list-item .stl-check { color: #43A047; opacity: 0; transition: opacity .15s; }
.settings-lang-list-item.active,
.settings-theme-list-item.active { color: #43A047; font-weight: 600; background: rgba(67,160,71,.06); }
.settings-lang-list-item.active .sll-check,
.settings-theme-list-item.active .stl-check { opacity: 1; }

/* ============================================================
   2026-05-04 通用「胶囊式 iOS 开关」(toggle switch)
   ------------------------------------------------------------
   .ng-switch     — 圆角 pill 滑轨 + 圆形 .ng-switch-knob 滑块,
                    [data-on="true"] 激活态把 knob 平移到右侧并染色滑轨.
   .ng-toggle     — 主题双段开关包装: 左标签 + .ng-switch + 右标签,
                    点任一标签也会触发对应方向, 视觉上类似分段控件.
   .ng-switch-solo— 单独使用 (滑动开关里 提示/开关 两个独立 toggle).

   - 主题: theme.js 读 [data-theme-toggle] 与 .ngt-side[data-theme-side];
   - 滑动: app.js  读 [data-swipe-toggle] (hint / enabled), 各自 on/off.
   ============================================================ */
.settings-toggle-row {
  flex-wrap: nowrap;
}
.settings-toggle-row .settings-toggle-label {
  flex: 1; font-size: 15px; font-weight: 500;
}

/* 主题双标签胶囊: ☀️ 日间 [○──] 🌙 夜间 */
.ng-toggle {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex: 0 0 auto;
  -webkit-tap-highlight-color: transparent;
}
.ng-toggle .ngt-side {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px 6px;
  border-radius: 6px;
  font-size: 13px;
  font-weight: 500;
  color: var(--text-mute, #999);
  cursor: pointer;
  transition: color .2s;
  user-select: none;
  white-space: nowrap;
}
.ng-toggle .ngt-side .ngt-icon { font-size: 14px; line-height: 1; }
.ng-toggle[data-active-side="light"] .ngt-side-l,
.ng-toggle[data-active-side="dark"]  .ngt-side-r {
  color: var(--text, #222);
  font-weight: 600;
}
:root[data-theme="dark"] .ng-toggle[data-active-side="light"] .ngt-side-l,
:root[data-theme="dark"] .ng-toggle[data-active-side="dark"]  .ngt-side-r {
  color: #fff;
}

/* iOS-风开关本体: 圆角 pill 轨道 + 圆形 knob 滑块 */
.ng-switch {
  position: relative;
  width: 46px;
  height: 26px;
  background: #d8d8de;
  border-radius: 999px;
  border: 0;
  padding: 0;
  cursor: pointer;
  transition: background .25s ease;
  flex: 0 0 auto;
  -webkit-tap-highlight-color: transparent;
  box-shadow: inset 0 0 0 1px rgba(0,0,0,.04);
}
:root[data-theme="dark"] .ng-switch {
  background: rgba(255,255,255,.18);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.06);
}
.ng-switch[data-on="true"] {
  background: #43A047;
}
:root[data-theme="dark"] .ng-switch[data-on="true"] {
  background: #66BB6A;
}
.ng-switch .ng-switch-knob {
  position: absolute;
  top: 2px; left: 2px;
  width: 22px; height: 22px;
  background: #fff;
  border-radius: 50%;
  box-shadow: 0 2px 5px rgba(0,0,0,.18), 0 0 1px rgba(0,0,0,.1);
  transition: transform .25s cubic-bezier(.4,.2,.2,1);
  pointer-events: none;
}
.ng-switch[data-on="true"] .ng-switch-knob {
  transform: translateX(20px);
}
.ng-switch:active .ng-switch-knob {
  transform: scale(1.05);
}
.ng-switch[data-on="true"]:active .ng-switch-knob {
  transform: translateX(20px) scale(1.05);
}

/* 单独使用的开关 (滑动 提示/开关) — 与右侧描述并排 */
.ng-switch-solo { margin-left: 12px; }

/* 2026-05-04 v3 主题专用加宽开关:
   - 80px 宽 (普通 ng-switch 是 46px), 留出两边空白用来显示 "日间" / "夜间" 标签;
   - 标签 absolute 在轨道内, 与 knob 互斥显示 — knob 在左 (light) 时, 右半空白
     显示 "日间" 作为状态确认; knob 在右 (dark) 时, 左半空白显示 "夜间";
   - 这样用户既能看到当前模式名, 又能直观看到"按一下就跳到对面"的可操作性. */
.ng-switch-theme {
  width: 80px;
  margin-left: auto;
}
.ng-switch-theme .ng-switch-label {
  position: absolute;
  top: 0; bottom: 0;
  display: flex; align-items: center; justify-content: center;
  width: 50px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .5px;
  color: rgba(255,255,255,.95);
  pointer-events: none;
  white-space: nowrap;
  opacity: 0;
  transition: opacity .2s ease;
  text-shadow: 0 1px 1px rgba(0,0,0,.15);
}
.ng-switch-theme .ng-switch-label-l { left: 0; }
.ng-switch-theme .ng-switch-label-r { right: 0; }
/* 日间 (light, data-on=false): knob 在左, 右侧空白显示 "日间" */
.ng-switch-theme[data-on="false"] .ng-switch-label-r {
  opacity: 1;
  color: #6b7280; /* 浅灰色, 在浅灰轨道上有对比度 */
  text-shadow: none;
}
/* 夜间 (dark, data-on=true): knob 在右, 左侧空白显示 "夜间" */
.ng-switch-theme[data-on="true"] .ng-switch-label-l {
  opacity: 1;
  color: #fff;
}
/* 80 - 22(knob) - 4(2x padding) = 54px 平移距离 */
.ng-switch-theme[data-on="true"] .ng-switch-knob {
  transform: translateX(54px);
}
.ng-switch-theme[data-on="true"]:active .ng-switch-knob {
  transform: translateX(54px) scale(1.05);
}
:root[data-theme="dark"] .ng-switch-theme[data-on="false"] .ng-switch-label-r {
  color: rgba(255,255,255,.55);
  text-shadow: none;
}

/* ============================================================
   2026-05-04 快捷设置 overlay (Quick Settings)
   底部 nav 「快捷设置」按钮唤起, 复用 .finance-panel 抽屉 UI;
   内部 3 个 .qs-row, 行布局比 settings-item 更宽松, 强调「单项一段开关」.
   ============================================================ */
/* 2026-05-04 #quickSettingsOverlay 内容只有 3 个小行, 不需要默认 .finance-panel
   的 66vh 高度. 这里把高度收到 auto, 最小高度也降下来, 保持底部 sheet 随内容
   自适应; 在矮屏 (iPhone SE) 上仍然预留滑动空间. */
#quickSettingsOverlay .finance-panel {
  height: auto;
  min-height: 0;
  max-height: 80vh;
  padding-bottom: env(safe-area-inset-bottom, 0px);
}
.qs-body {
  padding: 8px 16px 24px !important;
}
.qs-row {
  padding: 14px 0;
  border-bottom: 1px solid var(--divider);
}
.qs-row:last-child {
  border-bottom: 0;
}
.qs-row-head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 10px;
  color: var(--text);
}
.qs-row-head svg {
  flex: 0 0 auto;
  color: var(--text-mute);
}
.qs-row-title {
  flex: 1;
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
}
.qs-row-value {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 13px; color: var(--text-mute);
  font-weight: 500;
}
.qs-row-chev {
  color: var(--text-faint, #bbb);
  flex: 0 0 auto;
}
.qs-row-clickable {
  cursor: pointer;
  transition: background .15s;
  border-radius: 8px;
  margin: 0 -8px;
  padding: 14px 8px;
}
.qs-row-clickable:active { background: var(--surface-2); }
.qs-row-clickable .qs-row-head { margin-bottom: 0; }
.qs-row-desc {
  margin: 8px 0 0;
  font-size: 12px;
  color: var(--text-mute);
  line-height: 1.5;
}
/* 主题胶囊在 qs 面板里居中, 标题独占一行 */
/* 2026-05-04 v3 已弃用 — 主题改用 .ng-switch-theme 单开关; 保留空规则避免
   旧文档/截图引用残骸. 没有元素挂这个 class 了. */
.qs-ng-toggle { /* deprecated */ }

/* 主题行 (qs-row 第一行) 内部布局: 让 .ng-switch-theme 顺势贴右,
   并让头部不再吃下方 margin (本行没有附加描述). */
.qs-row.qs-row-theme .qs-row-head { margin-bottom: 0; }
.qs-row .ng-switch-theme { margin-left: auto; }

/* 滑动开关里的子项行: 左 (名称 + 描述) 右 (toggle), 行内对齐 */
.qs-sub-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 0;
  border-top: 1px dashed var(--divider);
}
.qs-sub-row:first-of-type {
  border-top: 0;
  padding-top: 4px;
}
.qs-sub-text {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column; gap: 2px;
}
.qs-sub-name {
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
}
.qs-sub-desc {
  font-size: 12px;
  color: var(--text-mute);
  line-height: 1.5;
}

/* ============================================================
   2026-05-04 v4 滑动「提示」模式 — 三段式闪烁遮罩 (中间 + 左右两侧)
   ------------------------------------------------------------
   #swipeHintOverlay 是 body 末尾的 fixed 元素 (不嵌在 .game-fullscreen 里),
   feed 页 / 游戏页 / 任何 overlay 都能看到提示, 由 _flashSwipeHint() 控制
   2 秒自动归零, 不写 localStorage.

   三段可视化 — 这是关键: 把"中间实际拦截区"和"屏幕两侧的物理边缘"同时点亮,
   既照顾用户对 .game-swipe-edge 真实位置的认知 (中间一条横向带), 又照顾
   "TikTok 风的两侧滑动印象". 用户口径: "中间位置不明显" → 加 .shi-mid;
   "两侧都要控制" → 用 body.swipe-disabled 做整体灰化, 让用户看到一关全关.

   状态:
     - 默认 opacity:0 + pointer-events:none, 完全无感.
     - body.swipe-hint              → 红色高亮 + 闪烁, 表示 "可以滑这里";
     - body.swipe-hint.swipe-disabled→ 整体降饱和 + 灰化 + "已关闭" 徽章弹出,
                                       表示 "这就是滑动区, 但目前已被开关关掉".
   ============================================================ */
.swipe-hint-overlay {
  position: fixed;
  inset: 0;
  z-index: 9998;
  pointer-events: none;
  opacity: 0;
  transition: opacity .25s ease;
}
body.swipe-hint .swipe-hint-overlay {
  opacity: 1;
}
/* 桌面端不存在 .game-swipe-edge 这一拦截层 (display:none), 滑动是用滚轮替代,
   所以即便在桌面 click 提示, 也用不上这套可视化, 直接隐藏避免误导. */
body:not(.is-mobile-device) .swipe-hint-overlay {
  display: none;
}

/* —— 左右物理边缘红条 —— */
.shi-bar {
  position: absolute;
  top: 12vh;
  bottom: 12vh;
  width: 56px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  padding: 14px 0;
  color: #fff;
  background: linear-gradient(
    to right,
    rgba(254,44,85,.78) 0%,
    rgba(254,44,85,.55) 55%,
    rgba(254,44,85,.18) 92%,
    rgba(254,44,85,0) 100%
  );
  box-shadow:
    0 0 32px rgba(254,44,85,.55),
    inset 6px 0 14px rgba(254,44,85,.55);
  animation: swipe-hint-flash .55s ease-in-out infinite alternate;
}
/* 2026-05-04 v6 给两侧也补上"虚线描边"——和中间 .shi-mid 的 dashed 边框
   保持视觉语言一致, 让用户知道这三段是同一个滑动区. 用 ::before 内嵌
   一个 inset 6px 的伪元素画 dashed 边, 避免直接给 .shi-bar 加 border 时
   左/右边贴着屏幕被裁掉一半的尴尬. */
.shi-bar::before {
  content: '';
  position: absolute;
  inset: 6px;
  border: 2px dashed rgba(255,255,255,.78);
  border-radius: 14px;
  pointer-events: none;
}
.shi-bar-left {
  left: 0;
  border-radius: 0 18px 18px 0;
}
.shi-bar-right {
  right: 0;
  background: linear-gradient(
    to left,
    rgba(254,44,85,.78) 0%,
    rgba(254,44,85,.55) 55%,
    rgba(254,44,85,.18) 92%,
    rgba(254,44,85,0) 100%
  );
  box-shadow:
    0 0 32px rgba(254,44,85,.55),
    inset -6px 0 14px rgba(254,44,85,.55);
  border-radius: 18px 0 0 18px;
}

/* —— 中间横向带 —— 与 .game-swipe-edge 实际拦截区位置一致 (top:30% bottom:30%,
   左右各 50px 缓冲), 让用户看到"中间这一片才是真正会切游戏的地方".
   .55s 闪烁动画与两侧同步 (相同 keyframes), 视觉成一体. */
.shi-mid {
  position: absolute;
  top: 30%;
  bottom: 30%;
  left: 50px;
  right: 50px;
  border-radius: 18px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  padding: 18px 0;
  color: #fff;
  background: radial-gradient(
    ellipse at center,
    rgba(254,44,85,.55) 0%,
    rgba(254,44,85,.32) 55%,
    rgba(254,44,85,.10) 100%
  );
  box-shadow:
    0 0 36px rgba(254,44,85,.45),
    inset 0 0 22px rgba(254,44,85,.5);
  border: 2px dashed rgba(255,255,255,.7);
  animation: swipe-hint-flash-mid .55s ease-in-out infinite alternate;
}
.shi-mid-text {
  font-size: 16px;
  font-weight: 800;
  letter-spacing: 2px;
  text-shadow: 0 2px 4px rgba(0,0,0,.5);
  background: rgba(0,0,0,.35);
  padding: 6px 16px;
  border-radius: 999px;
}

/* —— 箭头小动效 —— */
.shi-arrow {
  filter: drop-shadow(0 1px 2px rgba(0,0,0,.35));
  animation: swipe-hint-arrow-bob .9s ease-in-out infinite alternate;
}
.shi-arrow-down {
  animation-delay: .45s;
}
@keyframes swipe-hint-flash {
  0%   { opacity: .45; transform: scaleX(.85); }
  100% { opacity: 1;   transform: scaleX(1.05); }
}
@keyframes swipe-hint-flash-mid {
  0%   { opacity: .55; transform: scale(.97); }
  100% { opacity: 1;   transform: scale(1.02); }
}
@keyframes swipe-hint-arrow-bob {
  0%   { transform: translateY(-3px); opacity: .65; }
  100% { transform: translateY(3px);  opacity: 1; }
}

/* —— "已关闭" 徽章 —— 仅在 swipe-disabled + swipe-hint 同时成立时弹出, 让用户
   看到"提示和开关协同": 提示告诉你这里是滑动区, 但开关已经把它关了. —— */
.shi-disabled-badge {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%) scale(.7);
  display: flex; align-items: center; gap: 10px;
  padding: 12px 22px;
  background: rgba(34,34,38,.92);
  color: #fff;
  border-radius: 999px;
  font-size: 15px;
  font-weight: 700;
  box-shadow: 0 8px 28px rgba(0,0,0,.45);
  border: 1px solid rgba(255,255,255,.18);
  opacity: 0;
  transition: opacity .25s ease, transform .25s ease;
  z-index: 1;
}
body.swipe-disabled.swipe-hint .shi-disabled-badge {
  opacity: 1;
  transform: translate(-50%, -50%) scale(1);
}
.shi-disabled-badge svg { color: #FE2C55; flex: 0 0 auto; }

/* —— 关闭态可视化 —— body.swipe-disabled 时, 三段一起翻成"灰色禁用"配色,
   不再用 filter:grayscale (它管不到 box-shadow 红色光晕, 用户反映"只有
   中间看起来关了, 两侧还红的"). 这里直接重写 background / box-shadow /
   border-color 把 #FE2C55 红 → #888 灰, 让用户清楚看到"中间和两侧一起
   被开关关掉了". —— */
body.swipe-disabled.swipe-hint .shi-bar-left {
  background: linear-gradient(
    to right,
    rgba(140,140,140,.55) 0%,
    rgba(140,140,140,.32) 55%,
    rgba(140,140,140,.10) 92%,
    rgba(140,140,140,0) 100%
  );
  box-shadow:
    0 0 18px rgba(140,140,140,.30),
    inset 6px 0 12px rgba(140,140,140,.45);
}
body.swipe-disabled.swipe-hint .shi-bar-right {
  background: linear-gradient(
    to left,
    rgba(140,140,140,.55) 0%,
    rgba(140,140,140,.32) 55%,
    rgba(140,140,140,.10) 92%,
    rgba(140,140,140,0) 100%
  );
  box-shadow:
    0 0 18px rgba(140,140,140,.30),
    inset -6px 0 12px rgba(140,140,140,.45);
}
body.swipe-disabled.swipe-hint .shi-mid {
  background: radial-gradient(
    ellipse at center,
    rgba(140,140,140,.50) 0%,
    rgba(140,140,140,.28) 55%,
    rgba(140,140,140,.08) 100%
  );
  box-shadow:
    0 0 28px rgba(140,140,140,.32),
    inset 0 0 20px rgba(140,140,140,.45);
}
/* 虚线描边在关闭态也调灰, 与背景统一节奏 */
body.swipe-disabled.swipe-hint .shi-bar::before,
body.swipe-disabled.swipe-hint .shi-mid {
  border-color: rgba(255,255,255,.4);
}
/* 关闭态闪烁慢一点, 弱化"邀请滑动"暗示, 同时让"已关闭"徽章文字稳定可读 */
body.swipe-disabled.swipe-hint .shi-bar,
body.swipe-disabled.swipe-hint .shi-mid {
  animation-duration: 1.2s;
}
/* 关闭态箭头/中间文字也调灰, 不再像启用态那样亮白 */
body.swipe-disabled.swipe-hint .shi-arrow {
  color: rgba(255,255,255,.55);
}
body.swipe-disabled.swipe-hint .shi-mid-text {
  color: rgba(255,255,255,.6);
  background: rgba(0,0,0,.25);
}

/* body.swipe-disabled 仍然控制 .game-swipe-edge 的实际拦截:
   pointer-events:none, 不再"吃 tap". 不操作 display, 让 .game-swipe-edge
   一直保持原尺寸/位置, 开 / 关滑动状态稳定. */
body.swipe-disabled .game-swipe-edge {
  pointer-events: none !important;
}

/* ============================================================
   2026-05-04 夜间模式对比度修复 — 快捷设置 / finance-panel 抽屉
   ------------------------------------------------------------
   .finance-panel 老规则把 background / 标题色 / 关闭按钮色都硬写成
   light 配色 (#fff / #161823 / #999), 在夜间模式下表现为"白底黑字"
   板子直接糊在抖音黑背景上, 对比度极差. 这里用 [data-theme="dark"]
   覆盖, 让所有 finance-panel 抽屉 (含快捷设置) 在夜间走深色卡片色.
   - 标题用 --text (白)
   - 容器用 --panel-bg (#1c1c1e 抖音 dark 卡片色)
   - 关闭 X 用 --text-mute (高 mute, 但够辨)
   - 分割线交给 .finance-body 使用 --divider 自然过渡
   ============================================================ */
:root[data-theme="dark"] .finance-panel {
  background: var(--panel-bg);
  color: var(--text);
}
:root[data-theme="dark"] .finance-panel .panel-header {
  border-bottom-color: var(--divider);
}
:root[data-theme="dark"] .finance-panel .panel-header h3 {
  color: var(--text);
}
:root[data-theme="dark"] .finance-panel .panel-close {
  color: var(--text-mute);
}
:root[data-theme="dark"] .finance-panel .panel-close:hover {
  color: var(--text);
}
:root[data-theme="dark"] .finance-loading {
  color: var(--text-mute);
}
/* 2026-06-09 推荐 / 邀请有礼面板 dark 修复 (v2):
   该组件 (renderReferral / _renderInvitationSection) 全程浅色硬编码 (白卡 / #333 文字
   / #f8fafd 底). v1 曾把整块当浅色卡片渲染 → 夜间整块白, 用户反馈"这边显示是白色".
   v2 改为真正深色: 容器透明跟随 --panel-bg, 默认浅字; 再用属性选择器把组件里有限的
   几种内联「浅底 / 深字 / 浅边框」翻成深色版, 强调色(红/蓝/绿/紫/橙)保留. 仅 dark
   且本作用域生效, 不影响 light 与其它面板. */
:root[data-theme="dark"] .rp-referral-scope {
  background: transparent;
  color: var(--text-soft);
}
/* 浅底容器 → 深色卡片. 注意 [style*="background:#fff"] 会同时命中 #fff7ed,
   故 #fff7ed (邀请有礼暖卡) 规则放后面覆盖回暖色调. */
:root[data-theme="dark"] .rp-referral-scope [style*="background:#fff"],
:root[data-theme="dark"] .rp-referral-scope [style*="background:#f8fafd"],
:root[data-theme="dark"] .rp-referral-scope .referral-stat-item {
  background: #2a2a2c !important;
  border-color: rgba(255, 255, 255, .10) !important;
}
/* 邀请码框: 只换底色, 保留标志性红色虚线边框 */
:root[data-theme="dark"] .rp-referral-scope .referral-code-box {
  background: #2a2a2c !important;
}
:root[data-theme="dark"] .rp-referral-scope [style*="background:#fff7ed"] {
  background: #2a2018 !important;
  border-color: rgba(251, 146, 60, .30) !important;
}
/* QR 码必须保持白底, 否则深底融掉扫不出 (id 选择器特异性高于属性选择器, 稳压回白) */
:root[data-theme="dark"] .rp-referral-scope #refQRImg { background: #fff !important; }
/* 深色文字 → 浅色 */
:root[data-theme="dark"] .rp-referral-scope [style*="color:#333"],
:root[data-theme="dark"] .rp-referral-scope [style*="color:#1f2937"],
:root[data-theme="dark"] .rp-referral-scope .fin-section-title,
:root[data-theme="dark"] .rp-referral-scope .fin-form-label { color: var(--text) !important; }
:root[data-theme="dark"] .rp-referral-scope [style*="color:#666"],
:root[data-theme="dark"] .rp-referral-scope [style*="color:#888"] { color: rgba(255, 255, 255, .72) !important; }
:root[data-theme="dark"] .rp-referral-scope [style*="color:#999"],
:root[data-theme="dark"] .rp-referral-scope [style*="color:#9ca3af"],
:root[data-theme="dark"] .rp-referral-scope [style*="color:#bbb"] { color: rgba(255, 255, 255, .45) !important; }
/* 邀请有礼暖色文字 → 提亮暖色, 深底上可读 */
:root[data-theme="dark"] .rp-referral-scope [style*="color:#9a3412"],
:root[data-theme="dark"] .rp-referral-scope [style*="color:#92400e"] { color: #fdba74 !important; }
/* 输入框 / 表格表头 / 行分隔线 */
:root[data-theme="dark"] .rp-referral-scope .fin-input {
  background: #232325 !important; color: var(--text) !important; border-color: rgba(255, 255, 255, .12) !important;
}
:root[data-theme="dark"] .rp-referral-scope table thead tr { background: #232325 !important; }
:root[data-theme="dark"] .rp-referral-scope table tr { border-color: rgba(255, 255, 255, .08) !important; }
/* QuickSettings 子项虚线分隔在 dark 下偏深, 给一层稍亮的 divider 让分隔可见 */
:root[data-theme="dark"] .qs-sub-row {
  border-top-color: rgba(255,255,255,.08);
}
:root[data-theme="dark"] .qs-row-clickable:active {
  background: rgba(255,255,255,.06);
}
/* messages 中心 (从「我的消息」进入) 在 dark 下也整体反白, 避免硬白底糊在
   黑底页面上. tabs 选中色 / 列表条目色 / 时间戳色都用 var(--text*) 取值. */
:root[data-theme="dark"] .msg-tabs {
  border-bottom-color: var(--divider);
}
:root[data-theme="dark"] .msg-tab {
  color: var(--text-mute);
}
:root[data-theme="dark"] .msg-tab.active {
  color: var(--text);
}
:root[data-theme="dark"] .msg-item {
  /* 2026-06-08 问题21: 已读消息在 .msg-item(6445) 的 #f8f9fa 浅底上叠夜间半透明
     白字, 对比度崩溃看不清. 夜间统一改深色面板底, 覆盖浅底泄漏. */
  background: var(--surface-2);
  border-color: var(--divider);
  border-bottom-color: var(--divider);
}
:root[data-theme="dark"] .msg-item:active { background: var(--surface-3); }
:root[data-theme="dark"] .msg-item-title { color: var(--text); }
:root[data-theme="dark"] .msg-item-desc  { color: var(--text-soft); }
:root[data-theme="dark"] .msg-item-preview { color: var(--text-soft); }
:root[data-theme="dark"] .msg-item-full-text { color: var(--text-soft); }
:root[data-theme="dark"] .msg-item-time  { color: var(--text-mute); }
:root[data-theme="dark"] .msg-empty      { color: var(--text-mute); }
:root[data-theme="dark"] .msg-toolbar-info { color: var(--text-soft); }
:root[data-theme="dark"] .msg-toolbar-info b { color: var(--text); }
:root[data-theme="dark"] .msg-item.msg-unread {
  background: rgba(254,44,85,.08);
  border-color: rgba(254,44,85,.22);
  border-bottom-color: rgba(254,44,85,.18);
}
:root[data-theme="dark"] .msg-item.unread {
  background: rgba(254,44,85,.08);
  border-color: rgba(254,44,85,.22);
}
/* 2026-05-04 v7: 移动端 actionBar 上下切换按钮原来按 light/dark 分别给色, 但
   game-playing 时 actionBar 直接覆盖在游戏 iframe 上 (老虎机/百家乐/Crash 各种
   背景色都可能), 跟着主题色走在浅色游戏画面上仍然糊成一片. 改成不分主题统一用
   "深色玻璃 + 白边" 的高对比胶囊 (规则统一写在 main.css ~248 行 action-nav-btn).
   这里清空主题特化, 避免被 !important 同时覆盖造成的级联混乱. */

/* ============================================================
   抖音商城风 (Mall) — 日夜双主题
   挂载在 #promoHubBody 内, 由 member-panels.js 渲染。
   主题机制: .dy-mall-root 自封一套 --dy-* 变量, 由 .dy-theme-light /
   .dy-theme-dark 提供两套取值; 子元素全部走 var(--dy-*), 切换时 JS 仅
   重渲一次根类名即可。详情弹层 .dy-pdp-mask 也带相同 .dy-theme-* 类,
   独立 portal 在 body 末尾, 因此变量声明同时挂在 .dy-mall-root /
   .dy-pdp-mask 上, 两处都能取到。

   设计原则:
   - 横幅 .dy-points-hdr 是品牌红渐变 (TikTok 红 #FE2C55), 两主题都不变,
     保持 "积分商城" 的品牌识别。
   - 横幅之外的 surface (banner / 分类 / 卡片 / 详情) 随主题反白, light
     模式整体白底接近抖音 App, dark 模式与外层 ci-overlay 风格一致。
   - .dy-mall-root 用负 margin 拉满 .ci-body 的左右 padding, 让 light
     模式下整页是浅色卡片, 不被外层深色遮罩 "夹" 出深色边。
   ============================================================ */

/* -- 变量: 默认 (light) -- */
.dy-mall-root,
.dy-pdp-mask {
  --dy-bg:        #f6f7fb;
  --dy-surface:   #ffffff;
  --dy-surface-2: #f1f2f6;
  --dy-text:      #161823;
  --dy-text-soft: rgba(22,24,35,.72);
  --dy-text-mute: rgba(22,24,35,.45);
  --dy-border:    rgba(22,24,35,.08);
  --dy-divider:   rgba(22,24,35,.06);
  --dy-shadow:    0 4px 14px rgba(22,24,35,.06);
  --dy-shadow-lg: 0 12px 36px rgba(22,24,35,.18);
  --dy-accent:    #FE2C55;
  --dy-accent-2:  #00B8B8;
  --dy-warn:      #F59E0B;
  --dy-bg-a:      linear-gradient(135deg, #ffe2e8 0%, #ffd0db 100%);
  --dy-bg-b:      linear-gradient(135deg, #d6f4f4 0%, #bfeaea 100%);
  --dy-bg-c:      linear-gradient(135deg, #fff0d6 0%, #ffe2b3 100%);
  --dy-bg-d:      linear-gradient(135deg, #e2e6ff 0%, #cfd5ff 100%);
  --dy-bg-e:      linear-gradient(135deg, #f3e2ff 0%, #e6caff 100%);
}

/* -- 变量: dark 覆盖 (2026-04-28: 用户决策"商城无论是黑夜, 都只有白天的模式".
       即使 JS 仍会给商城根加上 .dy-theme-dark, 这里强制把所有 dark 变量值
       回填成 light 取值, 商城始终显示浅色 mall. 不动 JS 是为了少改代码面 + 留
       后路: 后续若要恢复 dark 商城只要把这块 dark 取值改回去即可.
       与全站日夜模式独立) */
.dy-mall-root.dy-theme-dark,
.dy-pdp-mask.dy-theme-dark {
  --dy-bg:        #f6f7fb;
  --dy-surface:   #ffffff;
  --dy-surface-2: #f1f2f6;
  --dy-text:      #161823;
  --dy-text-soft: rgba(22,24,35,.72);
  --dy-text-mute: rgba(22,24,35,.45);
  --dy-border:    rgba(22,24,35,.08);
  --dy-divider:   rgba(22,24,35,.06);
  --dy-shadow:    0 4px 14px rgba(22,24,35,.06);
  --dy-shadow-lg: 0 12px 36px rgba(22,24,35,.18);
  --dy-bg-a:      linear-gradient(135deg, #ffe2e8 0%, #ffd0db 100%);
  --dy-bg-b:      linear-gradient(135deg, #d6f4f4 0%, #bfeaea 100%);
  --dy-bg-c:      linear-gradient(135deg, #fff0d6 0%, #ffe2b3 100%);
  --dy-bg-d:      linear-gradient(135deg, #e2e6ff 0%, #cfd5ff 100%);
  --dy-bg-e:      linear-gradient(135deg, #f3e2ff 0%, #e6caff 100%);
}

/* light 模式时强制覆盖 (以防默认值被某层级吃掉) */
.dy-mall-root.dy-theme-light,
.dy-pdp-mask.dy-theme-light {
  --dy-bg:        #f6f7fb;
  --dy-surface:   #ffffff;
  --dy-surface-2: #f1f2f6;
  --dy-text:      #161823;
  --dy-text-soft: rgba(22,24,35,.72);
  --dy-text-mute: rgba(22,24,35,.45);
  --dy-border:    rgba(22,24,35,.08);
  --dy-divider:   rgba(22,24,35,.06);
}

/* -- 根容器: 拉满 ci-body 左右 padding, 整页淡灰底 (匹配抖音商城) -- */
.dy-mall-root {
  margin: 0 -16px;
  padding: 0 0 24px;
  background: var(--dy-bg);
  color: var(--dy-text);
  border-radius: 0;
  min-height: 100%;
  transition: background .25s ease, color .25s ease;
}

/* ============================================================
   ① 顶栏: 搜索 (圆角胶囊, 带 camera + 红色搜索按钮) + 购物车
   ============================================================ */
.dy-mall-topbar {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px 8px;
  background: var(--dy-bg);
}
.dy-mall-search {
  flex: 1; min-width: 0;
  display: flex; align-items: center;
  height: 38px; padding: 0 4px 0 12px;
  background: var(--dy-surface);
  border: 1.5px solid var(--dy-accent);
  border-radius: 999px;
  position: relative;
  gap: 6px;
  -webkit-tap-highlight-color: transparent;
  cursor: pointer;
}
.dy-mall-search-icon { color: var(--dy-text-mute); flex-shrink: 0; }
.dy-mall-search-ph {
  flex: 1; min-width: 0;
  font-size: 13px; color: var(--dy-text-soft);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.dy-mall-search-input {
  flex: 1; min-width: 0;
  height: 100%;
  border: none; outline: none; background: transparent;
  font-size: 14px; color: var(--dy-text);
  padding: 0 4px;
  -webkit-tap-highlight-color: transparent;
}
.dy-mall-search-input::placeholder { color: var(--dy-text-soft); }
.dy-mall-search-clear {
  width: 22px; height: 22px;
  background: transparent; border: none; cursor: pointer;
  color: var(--dy-text-mute);
  font-size: 18px; line-height: 1;
  display: inline-flex; align-items: center; justify-content: center;
  padding: 0; flex-shrink: 0; margin-right: 4px;
  -webkit-tap-highlight-color: transparent;
}
.dy-mall-search-clear:hover { color: var(--dy-accent); }
.dy-mall-search-cam {
  width: 30px; height: 30px;
  background: transparent; border: none; cursor: pointer;
  color: var(--dy-text-soft);
  display: inline-flex; align-items: center; justify-content: center;
  padding: 0; flex-shrink: 0;
  -webkit-tap-highlight-color: transparent;
  transition: color .15s, transform .12s;
}
.dy-mall-search-cam:hover  { color: var(--dy-accent); }
.dy-mall-search-cam:active { transform: scale(.92); }
.dy-mall-search-btn {
  background: var(--dy-accent); color: #fff;
  height: 30px; padding: 0 16px;
  border: none; border-radius: 999px;
  font-size: 13px; font-weight: 700;
  cursor: pointer; flex-shrink: 0;
  -webkit-tap-highlight-color: transparent;
  transition: transform .12s, opacity .15s;
}
.dy-mall-search-btn:hover  { opacity: .92; }
.dy-mall-search-btn:active { transform: scale(.96); }
.dy-mall-cart {
  width: 36px; height: 36px;
  background: transparent; border: none; cursor: pointer;
  color: var(--dy-text);
  display: inline-flex; align-items: center; justify-content: center;
  padding: 0; flex-shrink: 0;
  -webkit-tap-highlight-color: transparent;
  transition: color .15s, transform .12s;
}
.dy-mall-cart:hover  { color: var(--dy-accent); }
.dy-mall-cart:active { transform: scale(.92); }

/* ============================================================
   ② 5 格快捷入口 (我的订单 / 充值中心 / 券红包 / 订单报销 / 天天抽券)
      下方两个分页小点 (mock, 表示可滚)
   ============================================================ */
.dy-entry-row {
  display: grid; grid-template-columns: repeat(5, 1fr);
  gap: 4px; padding: 6px 12px 4px;
  position: relative;
}
.dy-entry-item {
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  padding: 8px 0 4px;
  background: transparent; border: none; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform .12s;
}
.dy-entry-item:active { transform: scale(.95); }
.dy-entry-icon {
  position: relative;
  width: 36px; height: 36px;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--dy-surface);
  border-radius: 10px;
  box-shadow: 0 1px 2px rgba(22,24,35,.04);
}
.dy-entry-emoji { font-size: 20px; line-height: 1; }
.dy-entry-badge {
  position: absolute; top: -8px; right: -10px;
  font-size: 10px; font-weight: 700; line-height: 1;
  padding: 2px 5px; border-radius: 8px 8px 8px 2px;
  background: var(--dy-accent); color: #fff;
  white-space: nowrap;
  box-shadow: 0 1px 3px rgba(254,44,85,.35);
}
.dy-entry-label {
  font-size: 12px; color: var(--dy-text);
  font-weight: 500; line-height: 1.2;
}
.dy-entry-dots {
  grid-column: 1 / -1;
  display: flex; justify-content: center; align-items: center;
  gap: 4px; margin-top: 2px; padding: 4px 0 0;
}
.dy-entry-dots i {
  width: 12px; height: 3px; border-radius: 2px;
  background: var(--dy-divider);
  display: block;
}
.dy-entry-dots i.is-on { background: var(--dy-text-mute); }

/* ============================================================
   ③ 双促销卡 (超值购 / 低价秒杀)
      左右各占 50%, 内部 head (标题 + 副标题) + 2 个商品缩略
   ============================================================ */
.dy-promo-row {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: 8px;
  padding: 4px 12px 8px;
}
.dy-promo-card {
  position: relative;
  padding: 10px 10px 10px;
  border-radius: 14px;
  background:
    linear-gradient(180deg, rgba(255,255,255,0) 60%, rgba(255,255,255,.85) 100%),
    linear-gradient(135deg, rgba(255,224,200,.95) 0%, rgba(255,200,180,.85) 100%);
  cursor: pointer;
  overflow: hidden;
  -webkit-tap-highlight-color: transparent;
  transition: transform .12s, box-shadow .15s;
  --accent: var(--dy-accent);
}
.dy-promo-card[data-mall-promo="flash"] {
  background:
    linear-gradient(180deg, rgba(255,255,255,0) 60%, rgba(255,255,255,.85) 100%),
    linear-gradient(135deg, rgba(255,210,210,.95) 0%, rgba(255,180,210,.9) 100%);
}
.dy-promo-card:active { transform: scale(.98); }
.dy-promo-head {
  display: flex; align-items: baseline; gap: 6px;
  margin-bottom: 8px;
}
.dy-promo-title {
  font-size: 16px; font-weight: 900;
  color: var(--accent); line-height: 1.1;
  font-style: italic;
  letter-spacing: -.3px;
}
.dy-promo-sub {
  font-size: 10px; font-weight: 700;
  background: var(--accent); color: #fff;
  padding: 1px 5px; border-radius: 4px;
  letter-spacing: .2px;
}
.dy-promo-card[data-mall-promo="value"] .dy-promo-sub {
  background: linear-gradient(90deg, #FFB300, #FF7A00);
}
.dy-promo-items {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: 6px;
}
.dy-promo-item { text-align: center; }
.dy-promo-img {
  aspect-ratio: 1 / 1;
  background: rgba(255,255,255,.7);
  border-radius: 8px;
  display: flex; align-items: center; justify-content: center;
  margin-bottom: 4px;
  overflow: hidden;
}
.dy-promo-img span { font-size: 30px; line-height: 1; }
.dy-promo-save {
  display: inline-block;
  font-size: 10px; font-weight: 700;
  color: #fff; background: var(--accent);
  padding: 1px 5px; border-radius: 4px;
  margin-bottom: 2px;
}
.dy-promo-price {
  font-size: 11px; color: var(--accent); font-weight: 600;
}
.dy-promo-price b { font-size: 13px; font-weight: 800; }

/* ============================================================
   ④ 文字分类 tab — 横滚, 选中加红色下划线 (替代旧的图标宫格)
   ============================================================ */
.dy-cat-bar {
  display: flex; gap: 16px;
  padding: 6px 16px 8px;
  overflow-x: auto;
  scrollbar-width: none; -ms-overflow-style: none;
  -webkit-overflow-scrolling: touch;
  background: var(--dy-bg);
  position: sticky; top: 0; z-index: 5;
}
.dy-cat-bar::-webkit-scrollbar { display: none; }
.dy-cat-tab {
  flex: 0 0 auto;
  position: relative;
  background: transparent; border: none; cursor: pointer;
  padding: 6px 0 8px;
  font-size: 14px; font-weight: 500;
  color: var(--dy-text-soft);
  -webkit-tap-highlight-color: transparent;
  transition: color .15s;
  display: inline-flex; align-items: center; gap: 3px;
}
.dy-cat-tab:hover { color: var(--dy-text); }
.dy-cat-tab.is-active {
  color: var(--dy-text);
  font-weight: 800;
  font-size: 16px;
}
.dy-cat-tab.is-active::after {
  content: '';
  position: absolute; left: 50%; bottom: 2px;
  width: 18px; height: 3px; border-radius: 2px;
  background: var(--dy-accent);
  transform: translateX(-50%);
}
.dy-cat-tag {
  font-size: 10px; font-weight: 700;
  background: var(--dy-accent); color: #fff;
  padding: 1px 4px; border-radius: 4px 4px 4px 1px;
  margin-left: -1px;
  letter-spacing: .2px;
}

/* ============================================================
   ⑤ 抖音风瀑布流 — 双列, 大图 + 品牌 + 卖点 + 红价 + 店铺销量
   ============================================================ */
.dy-grid {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: 8px;
  padding: 0 8px;
}
.dy-card {
  background: var(--dy-surface);
  border-radius: 12px;
  overflow: hidden;
  cursor: pointer;
  display: flex; flex-direction: column;
  -webkit-tap-highlight-color: transparent;
  transition: transform .12s, box-shadow .15s;
  box-shadow: 0 1px 3px rgba(22,24,35,.05);
}
.dy-card:active { transform: scale(.98); }
.dy-card-img {
  position: relative;
  aspect-ratio: 1 / 1.05;
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
}
.dy-card.is-featured .dy-card-img { aspect-ratio: 1 / 1.18; }
.dy-card-emoji { font-size: 76px; line-height: 1; }
.dy-card.is-featured .dy-card-emoji { font-size: 96px; }
/* 2026-04-29 接入 ng_gift_items.image_url: 真实图填满卡片图区, object-fit cover
   兜底裁剪保证不留白; onerror 时把 img 隐藏并展示 emoji 兜底. */
.dy-card-img-real {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}
/* promo 卡内嵌商品图小一圈 */
.dy-promo-img img {
  width: 100%; height: 100%;
  object-fit: cover;
  border-radius: 8px;
  display: block;
}
.dy-card-tag {
  position: absolute; top: 8px; left: 8px;
  font-size: 10px; font-weight: 700;
  padding: 2px 7px; border-radius: 4px;
  color: #fff; letter-spacing: .3px;
}
.dy-card-badge-new {
  position: absolute; bottom: 8px; left: 8px;
  font-size: 10px; font-weight: 700;
  padding: 2px 6px; border-radius: 4px;
  color: #fff; background: rgba(0,0,0,.55);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  letter-spacing: .3px;
}
.dy-card-body {
  padding: 8px 10px 10px;
  display: flex; flex-direction: column; gap: 4px;
  flex: 1;
}
.dy-card-brand-row {
  font-size: 13px; color: var(--dy-text);
  line-height: 1.35;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
  font-weight: 500;
}
.dy-card-brand {
  display: inline-flex; align-items: center; gap: 2px;
  font-size: 11px; font-weight: 700;
  color: #fff; background: #161823;
  padding: 1px 5px; border-radius: 3px;
  margin-right: 4px;
  vertical-align: 2px;
  white-space: nowrap;
}
.dy-mall-root.dy-theme-dark .dy-card-brand {
  background: #fff; color: #161823;
}
.dy-card-brand svg { color: #fff; }
.dy-mall-root.dy-theme-dark .dy-card-brand svg { color: #161823; }
.dy-card-name {
  font-weight: 500;
}
.dy-card-name-only {
  font-size: 13px; color: var(--dy-text);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; line-height: 1.35;
}
.dy-card-sub {
  font-size: 12px; color: var(--dy-text-mute);
  line-height: 1.3;
  display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical;
  overflow: hidden;
}
.dy-card-coupon-row { margin-top: 2px; }
.dy-card-coupon {
  display: inline-block;
  font-size: 10px; font-weight: 700;
  color: var(--dy-accent);
  background: rgba(254,44,85,.08);
  padding: 1px 5px; border-radius: 3px;
  border: 1px solid rgba(254,44,85,.22);
}
.dy-card-foot {
  display: flex; align-items: flex-end; justify-content: space-between;
  margin-top: auto; padding-top: 4px;
  gap: 8px;
}
.dy-card-price {
  display: inline-flex; align-items: baseline; gap: 4px;
  color: var(--dy-accent);
  flex: 1; min-width: 0;
}
.dy-yuan { font-size: 12px; font-weight: 700; line-height: 1; }
.dy-card-price b {
  font-size: 18px; font-weight: 900; line-height: 1;
  font-feature-settings: 'tnum' 1;
}
.dy-card-original {
  font-size: 11px; color: var(--dy-text-mute);
  text-decoration: line-through;
  font-weight: 400;
}
.dy-card-shop-sold {
  font-size: 11px; color: var(--dy-text-mute);
  white-space: nowrap;
  text-align: right;
}

/* -- 底部说明 -- */
.dy-mall-foot {
  text-align: center;
  padding: 20px 16px 4px;
  color: var(--dy-text-mute);
}
.dy-mall-foot-line  { font-size: 12px; line-height: 1.5; }
.dy-mall-foot-rules { font-size: 11px; margin-top: 4px; opacity: .8; }

/* ============================================================
   2026-04-29 v5 — 商城统一样式 (全局, 同时覆盖商品列表 + PDP + 兑换弹层):
   1) 所有文字一律 normal 字重
   2) 主字号 14px, 辅 13px
   3) chip 全部去除彩色背景, 仅保留:
      - 库存 (绿字, 无背景)
      - V+ 可兑 (紫色 chip — 唯一保留, 强调门槛)
      - 限购 / 已兑 (灰字 · 分隔, 无背景)
   4) PDP "兑换价" 大字红色 (无红色实底胶囊)
   ============================================================ */
.dy-mall-root, .dy-mall-root *,
.dy-pdp-mask, .dy-pdp-mask *,
.dy-pdp-exchange-mask, .dy-pdp-exchange-mask * {
  font-weight: normal !important;
}

/* 共用的 库存/V+/限购 样式 — 列表卡 + PDP 价格条 都通过这几个 class 取样 */
.mall-meta-stock   { color: #27ae60 !important; font-size: 13px !important; background: transparent !important; }
.mall-meta-soldout { color: #999    !important; font-size: 13px !important; background: transparent !important; }
.mall-meta-sub     { color: #888    !important; font-size: 13px !important; background: transparent !important; }
.mall-meta-vip {
  display: inline-block;
  font-size: 13px !important;
  color: #7b3fe4 !important;          /* 紫色文字, 无背景 (用户 2026-04-29 反馈) */
  background: transparent !important;
  padding: 0 !important;
  border-radius: 0 !important;
  line-height: 1.6 !important;
  white-space: nowrap;
}
.mall-meta-line {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  margin: 2px 0;
}

/* PDP 兑换价: 不要红色背景胶囊, 直接 红字大数字 (与"取消"按钮平级) */
.dy-pdp-pricebar {
  display: flex; align-items: flex-start; justify-content: space-between;
  padding: 12px 14px; gap: 14px;
  background: var(--dy-surface);
}
.dy-pdp-pricebar-left { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.dy-pdp-pricebar-right{ display: flex; flex-direction: column; align-items: flex-end; gap: 4px; }
.dy-pdp-price-from { color: #888 !important; font-size: 13px !important; }
.dy-pdp-price-main {
  color: #FE2C55 !important;
  font-size: 20px !important;
  background: transparent !important;
  padding: 0 !important;
  border-radius: 0 !important;
}
.dy-mall-root .dy-card-name,
.dy-mall-root .dy-card-sub,
.dy-mall-root .dy-card-price,
.dy-mall-root .dy-card-meta-row,
.dy-mall-root .dy-cat-text,
.dy-mall-root .dy-entry-label,
.dy-mall-root .dy-mall-search-ph,
.dy-mall-root .dy-mall-search-btn,
.dy-mall-root .dy-mall-foot-line,
.dy-mall-root .dy-mall-foot-rules {
  font-size: 14px !important;
  letter-spacing: 0 !important;
}
.dy-mall-root .dy-card-meta-row,
.dy-mall-root .dy-mall-foot-rules,
.dy-mall-root .dy-card-sub {
  font-size: 13px !important;
  color: var(--dy-text-mute) !important;
}
.dy-mall-root .dy-card-price {
  color: #FE2C55 !important;
}
/* chip / tag 背景全部清掉, 只保留文字 (避免红/黄/绿色块) */
.dy-mall-root .dy-card-meta-chip,
.dy-mall-root .dy-card-tag,
.dy-mall-root .dy-card-badge-new,
.dy-mall-root .dy-card-soldout {
  background: transparent !important;
  color: var(--dy-text-mute) !important;
  box-shadow: none !important;
  padding: 0 !important;
  border-radius: 0 !important;
}
/* 已抢光浮层依然要醒目, 但用文字而非半透明黑底 */
.dy-mall-root .dy-card-soldout {
  position: absolute; inset: auto 0 8px 0;
  text-align: center;
  color: #999 !important;
  background: transparent !important;
  font-size: 14px !important;
}
/* 5 格入口的 emoji 不属于"文字", 保留 */
.dy-mall-root .dy-entry-emoji { font-size: 24px !important; }
.dy-mall-root .dy-card-emoji  { font-size: 56px !important; }
/* 顶栏搜索按钮原本是红色实底, 用户说不要背景, 也清掉 */
.dy-mall-root .dy-mall-search-btn {
  background: transparent !important;
  color: var(--dy-accent) !important;
  padding: 0 8px !important;
}
/* 分类 tab 选中态: 之前用 字加粗 + 红下划线; 现在不加粗, 只保留下划线 + 红色 */
.dy-mall-root .dy-cat-tab.is-active .dy-cat-text { color: var(--dy-accent) !important; }

/* ============================================================
   桌面版商城布局 (2026-04-29 v3): 不再 mobile-first 拉满
   - .dy-mall-wrap 居中, 限制 max-width 1100px (1024px 屏也不顶边)
   - grid 改成响应式 (4 列 ≥ 920px / 5 列 ≥ 1200px)
   - 入口 / 分类 / 商品卡 间距加大, 卡片图区限高度 (避免桌面巨型 emoji)
   ============================================================ */
.dy-mall-wrap {
  width: 100%;
  margin: 0 auto;
}
@media (min-width: 768px) {
  .dy-mall-root { margin: 0; padding-top: 8px; }
  .dy-mall-wrap { max-width: 1100px; padding: 0 8px; }
  .dy-mall-topbar { padding: 12px 8px 10px; }
  .dy-entry-row {
    gap: 8px;
    padding: 14px 12px;
    background: var(--dy-surface);
    border-radius: 12px;
    margin: 0 8px 14px;
    box-shadow: 0 1px 3px rgba(22,24,35,.04);
  }
  .dy-entry-icon { width: 44px; height: 44px; }
  .dy-entry-emoji { font-size: 24px; }
  .dy-entry-label { font-size: 12px; }
  .dy-cat-bar { padding: 6px 8px; margin-bottom: 8px; }
  .dy-grid {
    grid-template-columns: repeat(4, 1fr);
    gap: 14px;
    padding: 0 8px;
  }
  .dy-card { box-shadow: 0 2px 8px rgba(22,24,35,.06); }
  .dy-card:hover { transform: translateY(-2px); box-shadow: 0 6px 18px rgba(22,24,35,.10); }
  .dy-card-img { aspect-ratio: 1 / 1; }
  .dy-card.is-featured .dy-card-img { aspect-ratio: 1 / 1; }
  .dy-card-emoji { font-size: 56px; }
  .dy-card.is-featured .dy-card-emoji { font-size: 64px; }
  .dy-mall-foot { padding-top: 32px; }
}
@media (min-width: 960px) {
  .dy-grid { grid-template-columns: repeat(5, 1fr); }
}
/* 移动端被 .is-mobile-device 标记的 body 即使视口大于 768 也走移动布局 (避免桌面浏览器
   开 dev tool 模拟手机时被桌面规则误打). */
body.is-mobile-device .dy-mall-wrap { max-width: none; padding: 0; }
body.is-mobile-device .dy-grid { grid-template-columns: 1fr 1fr; gap: 8px; padding: 0 8px; }
body.is-mobile-device .dy-mall-root { margin: 0 -16px; }

/* ============================================================
   v8 mall 新样式 (2026-04-29) — 对照截图回归"之前的 UI":
   - 顶部不要积分大字横幅
   - 搜索框用细描边胶囊, 红边一致 (用户截图)
   - 5 入口包在一个圆角白卡里
   - 分类 tab 是纯文字 + 红色下划线 (没有 emoji / 没有黑底胶囊)
   - 商品卡左上角小标签 (热销 / 精品 / 新品 / 限量)
   ============================================================ */
.dy-mall-root .dy-mall-topbar {
  display: block;
  width: 100%;
  box-sizing: border-box;
  padding: 12px 14px 6px;
}
.dy-mall-root .dy-mall-search-wrap {
  position: relative;
  display: flex; align-items: center;
  width: 100%;
  box-sizing: border-box;
  background: var(--dy-surface);
  border: 1px solid var(--dy-accent);
  border-radius: 24px;
  padding: 0 14px;
  height: 38px;
  margin-bottom: 12px;
}
.dy-mall-root .dy-mall-search-ic {
  color: var(--dy-text-mute); flex-shrink: 0;
  margin-right: 8px;
}
.dy-mall-root .dy-mall-search-wrap .dy-mall-search-input {
  flex: 1;
  border: none !important;
  background: transparent !important;
  outline: none;
  font-size: 13px !important;
  color: var(--dy-text);
  padding: 0 !important;
  height: 100%;
  width: 100%;
  box-sizing: border-box;
}
.dy-mall-root .dy-mall-search-wrap .dy-mall-search-input::placeholder {
  color: var(--dy-text-mute);
}
.dy-mall-root .dy-mall-search-clear {
  border: none; background: transparent;
  color: var(--dy-text-mute);
  width: 22px; height: 22px;
  border-radius: 50%;
  font-size: 18px; line-height: 1;
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  margin-left: 6px;
}
.dy-mall-root .dy-mall-search-clear:hover { color: var(--dy-accent); }

/* 5 入口卡片化 (用户截图) — 一整块圆角矩形 撑满宽度, 5 个入口大间距均分 */
.dy-mall-root .dy-quick-card {
  display: flex; align-items: stretch; justify-content: space-around;
  width: 100%;
  box-sizing: border-box;
  background: var(--dy-surface);
  border: 1px solid var(--dy-line, rgba(0,0,0,.06));
  border-radius: 14px;
  padding: 18px 12px;
  margin: 0 0 14px;
  box-shadow: 0 1px 2px rgba(22,24,35,.03);
}
.dy-mall-root .dy-quick-item {
  flex: 1 1 0;
  min-width: 0;
  border: none; background: transparent;
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  padding: 4px;
  cursor: pointer;
  color: var(--dy-text);
  -webkit-tap-highlight-color: transparent;
}
.dy-mall-root .dy-quick-item:active { transform: scale(.96); }
.dy-mall-root .dy-quick-emoji {
  font-size: 26px !important;
  line-height: 1;
  display: block;
}
.dy-mall-root .dy-quick-label {
  font-size: 13px !important;
  color: var(--dy-text-mute) !important;
  line-height: 1.2;
  text-align: center;
  /* 5 个入口各占 1/5 宽 (~50px). 原 white-space:nowrap 会让英文/越泰等长标签
     (Redemption Details / Shipping Address …) 单行放不下而横向溢出, 叠到相邻格
     (用户反馈"文本重叠"). 改为允许换行 + 长词强制断行, 始终留在各自格子内. */
  white-space: normal;
  overflow-wrap: anywhere;
  word-break: break-word;
  width: 100%;
}

/* 文字分类 tab (无 emoji, 选中红色下划线) */
.dy-mall-root .dy-cat-text-bar {
  display: flex;
  gap: 18px;
  padding: 4px 14px 10px;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  white-space: nowrap;
  border-bottom: 1px solid var(--dy-line, rgba(0,0,0,.05));
  margin-bottom: 12px;
}
.dy-mall-root .dy-cat-text-bar::-webkit-scrollbar { display: none; }
.dy-mall-root .dy-cat-text-tab {
  position: relative;
  flex: 0 0 auto;
  border: none !important;
  background: transparent !important;
  color: var(--dy-text-mute) !important;
  font-size: 14px !important;
  padding: 6px 0;
  cursor: pointer;
  white-space: nowrap;
}
.dy-mall-root .dy-cat-text-tab:hover { color: var(--dy-text) !important; }
.dy-mall-root .dy-cat-text-tab.is-active {
  color: var(--dy-accent) !important;
}
.dy-mall-root .dy-cat-text-tab.is-active::after {
  content: '';
  position: absolute;
  left: 50%; bottom: -1px;
  width: 18px; height: 2px;
  background: var(--dy-accent);
  border-radius: 2px;
  transform: translateX(-50%);
}

/* 商品卡左上角小标签 — 不同状态不同色 */
.dy-mall-root .dy-card-badge {
  position: absolute; top: 6px; left: 6px;
  font-size: 11px !important;
  font-weight: 500 !important;
  padding: 2px 7px;
  border-radius: 4px;
  color: #fff;
  letter-spacing: .3px;
  z-index: 2;
  background: rgba(0,0,0,.55);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.dy-mall-root .dy-card-badge.is-hot   { background: var(--dy-accent); }
.dy-mall-root .dy-card-badge.is-feat  { background: #8e44ad; }
.dy-mall-root .dy-card-badge.is-new   { background: #2e86de; }
.dy-mall-root .dy-card-badge.is-limit { background: #e67e22; }

/* 商品卡: 用户截图的卡片图区是 大色块 + 居中 emoji, 桌面 5 列布局也要保证图片高度合理 */
.dy-mall-root .dy-card-img { aspect-ratio: 1 / 1; }
.dy-mall-root .dy-card-emoji { font-size: 64px !important; }
@media (max-width: 767px) {
  .dy-mall-root .dy-card-emoji { font-size: 48px !important; }
  .dy-mall-root .dy-quick-emoji { font-size: 22px !important; }
  .dy-mall-root .dy-cat-text-bar { gap: 14px; }
}

/* 桌面端 — 搜索框 + 5 入口卡片 都撑满 .dy-mall-wrap (max-width 1100px), 上下排列 */
@media (min-width: 768px) {
  .dy-mall-root .dy-mall-topbar { padding: 14px 0 8px; }
  .dy-mall-root .dy-mall-search-wrap {
    height: 42px;
    padding: 0 18px;
    margin-bottom: 14px;
    max-width: none;
  }
  .dy-mall-root .dy-mall-search-wrap .dy-mall-search-input { font-size: 14px !important; }
  .dy-mall-root .dy-quick-card {
    padding: 22px 24px;
    margin-bottom: 16px;
    border-radius: 16px;
  }
  .dy-mall-root .dy-quick-item { gap: 10px; padding: 4px 8px; }
  .dy-mall-root .dy-quick-emoji { font-size: 30px !important; }
  .dy-mall-root .dy-quick-label { font-size: 14px !important; }
}

/* ============================================================
   PDP 底部兑换栏 — 必须贴合 .dy-pdp-sheet 卡片本身的宽度
   (旧版用 position:absolute 但 sheet 没设 position:relative,
    导致桌面端 红色 bar 飘出 sheet, 占满整个 mask 宽度)
   现统一用 flex 自然子元素, 桌面/移动 都跟随 sheet 宽
   ============================================================ */
.dy-pdp-sheet .dy-pdp-footer {
  flex: 0 0 auto;
  display: flex;
  align-items: stretch;
  gap: 10px;
  padding: 12px 14px calc(12px + env(safe-area-inset-bottom));
  background: var(--dy-bg, #fff);
  border-top: 1px solid rgba(0,0,0,.06);
}
.dy-pdp-sheet .dy-pdp-cancel-btn {
  flex: 0 0 96px;
  border: none;
  background: rgba(0,0,0,.04) !important;
  color: var(--dy-text-mute, #666) !important;
  border-radius: 24px;
  font-size: 14px !important;
  cursor: pointer;
  padding: 12px 0;
  font-weight: normal !important;
}
.dy-pdp-sheet .dy-pdp-cancel-btn:hover { background: rgba(0,0,0,.08) !important; }
.dy-pdp-sheet .dy-pdp-exchange-btn {
  flex: 1;
  border: none;
  background: linear-gradient(135deg, #FE2C55, #FF6A00);
  color: #fff !important;
  border-radius: 24px;
  cursor: pointer;
  padding: 8px 14px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  line-height: 1.2;
  transition: opacity .15s, transform .1s;
  font-weight: normal !important;
}
.dy-pdp-sheet .dy-pdp-exchange-btn:hover  { opacity: .92; }
.dy-pdp-sheet .dy-pdp-exchange-btn:active { transform: scale(.985); }
.dy-pdp-sheet .dy-pdp-exchange-num {
  font-size: 16px !important;
  color: #fff !important;
  font-weight: 600 !important;
}
.dy-pdp-sheet .dy-pdp-exchange-sub {
  font-size: 11px !important;
  color: rgba(255,255,255,.92) !important;
  margin-top: 1px;
}

/* 桌面: 卡片化的 sheet 让 footer 也变成"卡片底部" 视觉, 加点呼吸 */
@media (min-width: 768px) {
  body:not(.is-mobile-device) .dy-pdp-sheet .dy-pdp-footer {
    padding: 14px 16px;
  }
  body:not(.is-mobile-device) .dy-pdp-sheet .dy-pdp-cancel-btn,
  body:not(.is-mobile-device) .dy-pdp-sheet .dy-pdp-exchange-btn {
    padding: 10px 0;
  }
  body:not(.is-mobile-device) .dy-pdp-sheet .dy-pdp-exchange-num { font-size: 15px !important; }
}

/* -- 商品图 5 种渐变底 (a..e), 由 mock 数据 bgKey 决定 -- */
.dy-bg-a { background: var(--dy-bg-a); }
.dy-bg-b { background: var(--dy-bg-b); }
.dy-bg-c { background: var(--dy-bg-c); }
.dy-bg-d { background: var(--dy-bg-d); }
.dy-bg-e { background: var(--dy-bg-e); }

/* ============================================================
   PDP 商品详情 — 全屏覆盖式 (抖音商城风, 严格对齐截图)
   .dy-pdp-fullscreen 模式: 直接 100vw / 100vh, 不带遮罩, 无圆角
   ============================================================ */
.dy-pdp-mask {
  position: fixed; inset: 0; z-index: 100300;
  background: rgba(0,0,0,.5);
  display: flex; align-items: flex-end; justify-content: center;
  opacity: 0; pointer-events: none;
  transition: opacity .26s ease;
  -webkit-tap-highlight-color: transparent;
}
.dy-pdp-mask.open { opacity: 1; pointer-events: auto; }

/* 全屏 PDP: 整张商品页占满屏幕, 弹出从右侧滑入更接近"页面跳转"语义 */
.dy-pdp-fullscreen {
  background: var(--dy-bg);
  align-items: stretch;
}
.dy-pdp-fullscreen .dy-pdp-sheet {
  width: 100%; max-width: none;
  max-height: 100vh; height: 100vh; max-height: 100dvh; height: 100dvh;
  border-radius: 0;
  transform: translateX(20px);
  transition: transform .26s cubic-bezier(.2,.9,.3,1.1), opacity .26s ease;
  padding-bottom: 0;
  background: var(--dy-bg);
  display: flex; flex-direction: column;
  overflow: hidden;
}
.dy-pdp-mask.open.dy-pdp-fullscreen .dy-pdp-sheet { transform: translateX(0); }

/* 桌面端 PDP 收窄, 居中显示 (像 detail page 在右半屏) */
@media (min-width: 768px) {
  body:not(.is-mobile-device) .dy-pdp-fullscreen {
    align-items: center; justify-content: center;
  }
  body:not(.is-mobile-device) .dy-pdp-fullscreen .dy-pdp-sheet {
    width: 480px; height: 88vh; max-height: 88vh;
    border-radius: 18px;
    transform: translateY(20px);
  }
  body:not(.is-mobile-device) .dy-pdp-mask.open.dy-pdp-fullscreen .dy-pdp-sheet {
    transform: translateY(0);
  }
}

/* —— ① 顶栏 (透明叠在大图上) */
.dy-pdp-topbar {
  position: absolute; top: 0; left: 0; right: 0; z-index: 5;
  display: flex; align-items: center; justify-content: space-between;
  padding: 8px 12px;
  padding-top: calc(8px + env(safe-area-inset-top, 0px));
  pointer-events: none;
}
.dy-pdp-topbar > * { pointer-events: auto; }
.dy-pdp-top-actions { display: flex; align-items: center; gap: 8px; }
.dy-pdp-top-btn {
  width: 32px; height: 32px;
  display: inline-flex; align-items: center; justify-content: center;
  border: none; padding: 0;
  background: rgba(255,255,255,.92);
  color: #161823;
  border-radius: 50%;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background .15s, transform .12s;
  box-shadow: 0 1px 3px rgba(0,0,0,.08);
}
.dy-pdp-top-btn:hover  { background: #fff; }
.dy-pdp-top-btn:active { transform: scale(.92); }

/* PDP 主滚动区 (不含底部 sticky CTA) */
.dy-pdp-scroll {
  flex: 1; overflow-y: auto; -webkit-overflow-scrolling: touch;
  background: var(--dy-bg);
}
.dy-pdp-scroll::-webkit-scrollbar { display: none; }

/* —— ② 大图区: 主图 (2 栏) + 缩略图 (1 栏) + 各种 overlay */
.dy-pdp-gallery {
  position: relative;
  background: var(--dy-surface);
  padding: 6px 6px 8px;
}
.dy-pdp-gallery-grid {
  display: grid;
  grid-template-columns: 2fr 1fr;
  gap: 6px;
  height: 320px;
}
@media (min-width: 768px) {
  body:not(.is-mobile-device) .dy-pdp-gallery-grid { height: 280px; }
}
.dy-pdp-main-img {
  position: relative;
  border-radius: 14px;
  overflow: hidden;
  display: flex; align-items: center; justify-content: center;
}
.dy-pdp-main-img .dy-pdp-emoji {
  font-size: 130px; line-height: 1;
  filter: drop-shadow(0 6px 24px rgba(0,0,0,.18));
}
.dy-pdp-thumb-col {
  display: grid; grid-template-rows: 1fr 1fr; gap: 6px;
}
.dy-pdp-thumb {
  border-radius: 10px;
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
}
.dy-pdp-thumb span { font-size: 50px; line-height: 1; opacity: .9; }

.dy-pdp-browsing {
  position: absolute; top: 10px; left: 10px;
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 11px; color: #fff; font-weight: 500;
  background: rgba(0,0,0,.45); backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  padding: 3px 8px 3px 4px;
  border-radius: 999px;
  z-index: 2;
}
.dy-pdp-browsing-avatar {
  width: 18px; height: 18px;
  border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: linear-gradient(135deg,#43A047,#66BB6A);
  font-size: 9px; font-weight: 700; color: #fff;
}

.dy-pdp-play {
  position: absolute; left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  width: 56px; height: 56px;
  background: transparent; border: none; cursor: pointer;
  padding: 0; z-index: 3;
  -webkit-tap-highlight-color: transparent;
  transition: transform .15s;
}
.dy-pdp-play:active { transform: translate(-50%, -50%) scale(.92); }

.dy-pdp-find-same {
  position: absolute; left: 14px; bottom: 14px;
  display: inline-flex; align-items: center; gap: 4px;
  background: rgba(0,0,0,.55); color: #fff;
  border: none; cursor: pointer;
  padding: 4px 10px;
  border-radius: 999px;
  font-size: 11px; font-weight: 500;
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  -webkit-tap-highlight-color: transparent;
  transition: background .15s, transform .12s;
}
.dy-pdp-find-same:hover  { background: rgba(0,0,0,.7); }
.dy-pdp-find-same:active { transform: scale(.96); }

.dy-pdp-media-toggle {
  position: absolute; right: 14px; bottom: 14px;
  display: inline-flex;
  background: rgba(0,0,0,.55); color: rgba(255,255,255,.7);
  padding: 3px;
  border-radius: 999px;
  font-size: 11px; font-weight: 600;
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  gap: 0;
}
.dy-pdp-media-toggle span {
  padding: 3px 10px;
  border-radius: 999px;
  cursor: pointer;
  transition: background .15s, color .15s;
}
.dy-pdp-media-toggle .is-on {
  background: rgba(255,255,255,.95);
  color: #161823;
}

/* —— ③ 价格条 */
.dy-pdp-pricebar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px;
  padding: 12px 14px;
  background: var(--dy-surface);
  margin-top: 0;
  border-bottom: 1px solid var(--dy-divider);
}
.dy-pdp-pricebar-left {
  display: flex; align-items: center; gap: 6px;
  flex: 1; min-width: 0;
}
.dy-pdp-price-from {
  display: inline-flex; align-items: baseline;
  font-size: 13px; color: var(--dy-text);
  font-weight: 600;
}
.dy-pdp-price-from b {
  font-size: 22px; font-weight: 800; line-height: 1;
  font-feature-settings: 'tnum' 1;
  margin: 0 1px;
}
.dy-pdp-coupon-pill {
  display: inline-flex; align-items: stretch;
  border: 1.5px solid #FF7A00;
  border-radius: 999px;
  overflow: hidden;
  background: #fff7ed;
  font-feature-settings: 'tnum' 1;
}
.dy-pdp-coupon-pill-label {
  font-size: 11px; font-weight: 700;
  color: #fff; background: linear-gradient(90deg, #FF9500, #FF7A00);
  padding: 3px 7px;
  display: inline-flex; align-items: center;
  letter-spacing: .2px;
}
.dy-pdp-coupon-pill-amt {
  display: inline-flex; align-items: baseline;
  color: #FF7A00;
  font-size: 12px; font-weight: 700;
  padding: 2px 8px 2px 6px;
}
.dy-pdp-coupon-pill-amt b { font-size: 16px; font-weight: 900; line-height: 1; }

.dy-pdp-pricebar-right {
  display: flex; flex-direction: column; align-items: flex-end;
  gap: 2px;
  cursor: pointer; flex-shrink: 0;
  min-width: 78px;
  -webkit-tap-highlight-color: transparent;
  transition: opacity .15s;
}
.dy-pdp-pricebar-right:active { opacity: .7; }
.dy-pdp-shop-line {
  display: inline-flex; align-items: center; gap: 1px;
  font-size: 13px; font-weight: 700; color: var(--dy-text);
}
.dy-pdp-shop-sub {
  font-size: 10px; color: var(--dy-text-mute);
}

/* —— ④ 款式 chip 行 */
.dy-pdp-sku-row {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 14px;
  background: var(--dy-surface);
  margin-top: 6px;
  border-radius: 0;
}
.dy-pdp-sku-chips {
  display: flex; gap: 6px;
}
.dy-pdp-sku-chip {
  width: 36px; height: 36px;
  border-radius: 8px;
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
  border: 1.5px solid transparent;
  cursor: pointer;
  transition: border-color .15s, transform .12s;
}
.dy-pdp-sku-chip:active { transform: scale(.96); }
.dy-pdp-sku-chip.is-active { border-color: var(--dy-accent); }
.dy-pdp-sku-chip span { font-size: 22px; line-height: 1; }
.dy-pdp-sku-more {
  display: inline-flex; align-items: center; gap: 1px;
  font-size: 13px; color: var(--dy-text-soft);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.dy-pdp-sku-more:active { opacity: .7; }

/* —— ⑤ 商品标题 */
.dy-pdp-title {
  padding: 8px 14px 12px;
  background: var(--dy-surface);
  font-size: 15px; line-height: 1.4;
  color: var(--dy-text); font-weight: 700;
}
.dy-pdp-title-tag {
  display: inline-block;
  font-size: 11px; font-weight: 700;
  background: linear-gradient(90deg, #38BDF8, #2563EB);
  color: #fff;
  padding: 1px 6px; border-radius: 4px;
  margin-right: 6px;
  vertical-align: 2px;
}
.dy-pdp-title-text { font-weight: 700; }

/* —— ⑥ 品牌认证行 */
.dy-pdp-brand-row {
  display: flex; align-items: center; gap: 10px;
  width: 100%;
  padding: 10px 14px;
  background: var(--dy-surface);
  margin-top: 6px;
  border: none; cursor: pointer;
  text-align: left;
  -webkit-tap-highlight-color: transparent;
  transition: background .15s;
  color: var(--dy-text);
}
.dy-pdp-brand-row:hover { background: var(--dy-surface-2); }
.dy-pdp-brand-logo {
  width: 32px; height: 32px;
  border-radius: 8px;
  background: linear-gradient(135deg, #161823, #2c2e44);
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  color: #fff;
}
.dy-pdp-brand-logo span { font-size: 18px; line-height: 1; }
.dy-pdp-brand-meta { flex: 1; min-width: 0; }
.dy-pdp-brand-name {
  font-size: 13px; font-weight: 700; color: var(--dy-text);
  margin-bottom: 1px;
}
.dy-pdp-brand-cert {
  font-size: 11px; color: var(--dy-text-mute);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.dy-pdp-brand-row svg { color: var(--dy-text-mute); flex-shrink: 0; }

/* —— ⑦ 服务标签 chip 行 */
.dy-pdp-chips-row {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  padding: 10px 14px;
  background: var(--dy-surface);
}
.dy-pdp-chip {
  display: inline-flex; align-items: center; gap: 3px;
  font-size: 11px; font-weight: 500;
  color: var(--dy-text-soft);
  background: var(--dy-surface-2);
  padding: 3px 7px;
  border-radius: 4px;
  white-space: nowrap;
  line-height: 1.3;
}
.dy-pdp-chip-green {
  color: #22C55E;
  background: rgba(34,197,94,.08);
}
.dy-pdp-chip-green svg { color: #22C55E; }
.dy-pdp-chip-meta {
  font-size: 11px; color: var(--dy-text-mute);
  margin-left: auto;
}

/* —— ⑧ 排行榜 */
.dy-pdp-rank {
  display: flex; align-items: center; gap: 8px; width: 100%;
  padding: 10px 14px;
  background:
    linear-gradient(90deg, rgba(255,200,100,.18) 0%, rgba(255,235,200,.05) 100%),
    var(--dy-surface);
  border: none; border-top: 1px solid var(--dy-divider);
  cursor: pointer; text-align: left;
  -webkit-tap-highlight-color: transparent;
  color: var(--dy-text);
}
.dy-pdp-rank:hover { filter: brightness(.98); }
.dy-pdp-rank-icon { font-size: 16px; line-height: 1; flex-shrink: 0; }
.dy-pdp-rank-text {
  flex: 1; min-width: 0;
  font-size: 13px; font-weight: 600;
  color: #C2410C;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.dy-pdp-rank svg { color: #C2410C; flex-shrink: 0; }
.dy-mall-root.dy-theme-dark .dy-pdp-rank-text,
.dy-pdp-mask.dy-theme-dark .dy-pdp-rank-text,
.dy-pdp-mask.dy-theme-dark .dy-pdp-rank svg { color: #FFB066; }

/* —— ⑨ 服务行 */
.dy-pdp-svc-list {
  background: var(--dy-surface);
  margin-top: 6px;
  display: flex; flex-direction: column;
}
.dy-pdp-svc-row {
  display: flex; align-items: center; gap: 8px;
  width: 100%;
  padding: 10px 14px;
  background: var(--dy-surface);
  border: none; border-bottom: 1px solid var(--dy-divider);
  cursor: pointer; text-align: left;
  font-size: 13px; color: var(--dy-text-soft);
  -webkit-tap-highlight-color: transparent;
  transition: background .15s;
}
.dy-pdp-svc-row:last-child { border-bottom: none; }
.dy-pdp-svc-row:hover { background: var(--dy-surface-2); }
.dy-pdp-svc-icon { color: var(--dy-text-mute); flex-shrink: 0; }
.dy-pdp-svc-row > span:not(.dy-pdp-svc-pre) {
  flex: 1; min-width: 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.dy-pdp-svc-pre {
  display: inline-block;
  font-size: 10px; font-weight: 700;
  background: rgba(254,44,85,.1);
  color: var(--dy-accent);
  padding: 1px 5px; border-radius: 3px;
  flex-shrink: 0;
  letter-spacing: .2px;
}
.dy-pdp-svc-chev { color: var(--dy-text-mute); flex-shrink: 0; }

/* —— 宝贝详情区 (替代旧的"兑换说明"折叠区) */
.dy-pdp-detail {
  margin-top: 8px;
  padding: 14px 14px 24px;
  background: var(--dy-surface);
}
.dy-pdp-detail-title {
  display: flex; align-items: center; justify-content: center;
  gap: 10px;
  font-size: 13px; font-weight: 700;
  color: var(--dy-text);
  margin-bottom: 10px;
}
.dy-pdp-detail-bar {
  width: 28px; height: 1px;
  background: var(--dy-divider);
  display: inline-block;
}
.dy-pdp-detail-stat {
  text-align: center;
  font-size: 12px; color: var(--dy-text-mute);
  margin-bottom: 10px;
}
.dy-pdp-rules {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-direction: column; gap: 6px;
}
.dy-pdp-rules li {
  position: relative; padding-left: 14px;
  font-size: 12px; color: var(--dy-text-soft); line-height: 1.5;
}
.dy-pdp-rules li::before {
  content: ''; position: absolute; left: 4px; top: 8px;
  width: 4px; height: 4px; border-radius: 50%;
  background: var(--dy-accent); opacity: .65;
}

/* —— ⑩ 底部 sticky 操作栏 (旗舰店 / 客服 / 购物车 / 加购 / 立即抢购) */
.dy-pdp-cta-bar {
  display: flex; align-items: center; gap: 4px;
  padding: 8px 12px;
  padding-bottom: calc(8px + env(safe-area-inset-bottom, 0px));
  background: var(--dy-surface);
  border-top: 1px solid var(--dy-divider);
  flex-shrink: 0;
}
.dy-pdp-cta-mini {
  position: relative;
  width: 50px;
  display: inline-flex; flex-direction: column; align-items: center; gap: 2px;
  background: transparent; border: none; cursor: pointer;
  color: var(--dy-text-soft);
  padding: 4px 0;
  font-size: 11px; line-height: 1.1;
  -webkit-tap-highlight-color: transparent;
  transition: color .15s, transform .12s;
}
.dy-pdp-cta-mini:hover  { color: var(--dy-accent); }
.dy-pdp-cta-mini:active { transform: scale(.94); }
.dy-pdp-cta-mini svg    { display: block; }
.dy-pdp-cta-cart-badge {
  position: absolute; top: -2px; right: 4px;
  font-size: 10px; font-weight: 700; color: #fff;
  background: var(--dy-accent);
  padding: 1px 5px; border-radius: 999px;
  line-height: 1.1;
  box-shadow: 0 1px 3px rgba(254,44,85,.36);
}

.dy-pdp-cta-add {
  width: 44px; height: 44px;
  border: none; cursor: pointer;
  background: linear-gradient(135deg, #FFB300 0%, #FF8A00 100%);
  color: #fff;
  border-radius: 999px 0 0 999px;
  display: inline-flex; align-items: center; justify-content: center;
  margin-left: 4px;
  -webkit-tap-highlight-color: transparent;
  transition: transform .12s, box-shadow .15s;
  box-shadow: 0 4px 12px rgba(255,138,0,.32);
}
.dy-pdp-cta-add:active { transform: scale(.96); }

.dy-pdp-cta-buy {
  flex: 1;
  height: 44px;
  border: none; cursor: pointer;
  background: linear-gradient(135deg, #FE2C55 0%, #ff5e8a 100%);
  color: #fff;
  border-radius: 0 999px 999px 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: 0 14px;
  -webkit-tap-highlight-color: transparent;
  transition: transform .12s, box-shadow .15s;
  box-shadow: 0 4px 12px rgba(254,44,85,.36);
  line-height: 1;
}
.dy-pdp-cta-buy:hover  { box-shadow: 0 6px 18px rgba(254,44,85,.45); }
.dy-pdp-cta-buy:active { transform: scale(.98); }
.dy-pdp-cta-buy-price {
  font-size: 13px; font-weight: 600; line-height: 1.1;
  display: inline-flex; align-items: baseline;
}
.dy-pdp-cta-buy-price b {
  font-size: 17px; font-weight: 900; line-height: 1;
  font-feature-settings: 'tnum' 1;
  margin-left: 1px;
}
.dy-pdp-cta-buy-tag {
  font-size: 10px; font-weight: 600; opacity: .9;
  margin-top: 2px;
  white-space: nowrap;
}

/* ============================================================
   日间模式 - 文字色全局反色覆盖 (防"白底白字")
   ----------------------------------------------------------------
   背景: main.css 全文 ~190 处硬编码白色文字 (color:#fff /
   rgba(255,255,255,*)). 在 light 模式下, 三个子树的容器从深色
   反成浅色, 内部白字会瞬间不可见; 这里集中按子树批量反色.
   设计原则:
   - 只覆盖 light 模式 (:root[data-theme="light"]); dark 完全不影响.
   - 容器固定深色 (.profile-balance-card 渐变 / .provider-panel #1e1e1e
     / .toast / 视频卡 .game-card .dt-card / livechat / redpacket /
     game-fs-* 等) 的白字一律保留, 不在此覆盖.
   - 品牌色按钮 (.dt-register-btn 红 / .ach-claim-btn 红 /
     .login-submit-btn 红 / .dy-card-cta 红 等) 也保留白字.
   - 覆盖目标: dt-sidebar 子树 + ci-overlay 子树 + 桌面侧栏化的
     action-bar + cat-tab.disabled (top-bar 内). 这是 light 下用户
     视野最密集的浅色区域.
   ============================================================ */

/* ---- dt-sidebar 子树 (桌面专用, 移动端 desktop-layout display:none) ---- */
:root[data-theme="light"] .dt-sidebar { color: var(--text); }

:root[data-theme="light"] .dt-sidebar .dt-nav-item:hover,
:root[data-theme="light"] .dt-sidebar .dt-user-trigger:hover,
:root[data-theme="light"] .dt-sidebar .dt-user-trigger.open,
:root[data-theme="light"] .dt-sidebar .dt-user-name,
:root[data-theme="light"] .dt-sidebar .dt-user-logout,
:root[data-theme="light"] .dt-fav-back,
:root[data-theme="light"] .dt-fav-count,
:root[data-theme="light"] .dt-fav-name {
  color: var(--text);
}
/* 2026-05-01 light mode 下"收藏 / 历史记录"页头返回按钮在原暗色样式
   (rgba(255,255,255,.06) 底 + 半透明白边) 在浅底完全看不见 →
   重写浅灰底 + 灰边, hover 转粉. 同时把整个 .dt-fav-header 的暗色
   渐变背景换成 light-friendly 的白→透明渐变, 避免白页里突然黑一条. */
:root[data-theme="light"] .dt-fav-header {
  background: linear-gradient(180deg, var(--surface, #fff) 0%, var(--surface, #fff) 80%, rgba(255,255,255,0) 100%);
}
:root[data-theme="light"] .dt-fav-back {
  background: rgba(0,0,0,.04);
  border: 1px solid var(--border, rgba(0,0,0,.12));
  color: var(--text);
}
:root[data-theme="light"] .dt-fav-back:hover {
  background: rgba(254,44,85,.08);
  border-color: rgba(254,44,85,.4);
  color: #FE2C55;
}
/* 2026-05-01 light 模式下收藏 / 历史卡片本体: 暗色样式用了 rgba(255,255,255,.04)
   半透白底 + 半透白边, 在白底页面上完全看不见; .dt-fav-cover 兜底 #1a1a22 (游戏
   缩略图加载完会被图片盖住, 但加载中露出大块深色). 这里 light 改:
   * .dt-fav-card → 浅灰底 + 灰边, hover 仍粉边粉光.
   * .dt-fav-cover → 浅灰兜底 (符合白页), 图片加载后照常被盖住.
   * .dt-fav-loading → 文字跟主文字色, 不再 50% 白. */
:root[data-theme="light"] .dt-fav-card {
  background: var(--surface-2, #f4f4f6);
  border-color: var(--border, rgba(0,0,0,.08));
}
:root[data-theme="light"] .dt-fav-card:hover {
  border-color: rgba(254,44,85,.55);
  box-shadow: 0 6px 18px rgba(0,0,0,.08), 0 0 0 1px rgba(254,44,85,.2) inset;
}
:root[data-theme="light"] .dt-fav-cover {
  background: var(--surface-2, #ececef);
}
:root[data-theme="light"] .dt-fav-loading {
  color: var(--text-soft);
}
/* .dt-user-menu-item 不再放进反色组: 它已经在 .dt-user-menu 主题化里
   用 var(--text), light 自动深字, dark 自动白字, 不用单独覆盖.
   .dt-um-icon 是渐变彩色按钮 (24x24 圆角图标), 内部 SVG color #fff 在
   彩色渐变背景上是设计稿要的高亮白, light 下也保留, 不反色. */
:root[data-theme="light"] .dt-sidebar .dt-user-caret,
:root[data-theme="light"] .dt-sidebar .dt-user-trigger.open .dt-user-caret,
:root[data-theme="light"] .dt-fav-empty,
:root[data-theme="light"] .dt-fav-provider,
:root[data-theme="light"] .dt-action span {
  color: var(--text-soft);
}
/* 桌面 dt-card-* 在 dt-feed 内, 卡片本体有视频/海报背景 (永远暗色),
   所以 .dt-card-logo / .dt-card-desc 等白字在视频上可读 → 不动. */
/* dt-user-avatar / dt-fav-fallback 等是渐变彩色头像 / 占位, 内部文字色
   在彩色渐变上仍清晰 → 不动. */

/* ---- ci-overlay 子树 (优惠/活动/签到/成就/钱包/提现等所有 hub) ---- */
:root[data-theme="light"] .ci-overlay { color: var(--text); }
:root[data-theme="light"] .ci-overlay .ci-back,
:root[data-theme="light"] .ci-overlay .ci-title { color: var(--text); }
/* 2026-04-29: .ci-reward-title (签到奖励详情) / .ci-history-month (历史月份)
   是分组标题, light 下用主文字色 var(--text), 不要降到 --text-soft 否则
   仍偏淡看不清. 其它弱信息 (label / nav / day / detail) 维持 --text-soft. */
:root[data-theme="light"] .ci-overlay .ci-reward-title,
:root[data-theme="light"] .ci-overlay .ci-history-month {
  color: var(--text);
}
:root[data-theme="light"] .ci-overlay .ci-history-btn,
:root[data-theme="light"] .ci-overlay .ci-stat-label,
:root[data-theme="light"] .ci-overlay .ci-cal-nav,
:root[data-theme="light"] .ci-overlay .ci-cal-label,
:root[data-theme="light"] .ci-overlay .ci-cal-day,
:root[data-theme="light"] .ci-overlay .ci-reward-day,
:root[data-theme="light"] .ci-overlay .ci-history-date,
:root[data-theme="light"] .ci-overlay .ci-history-detail,
:root[data-theme="light"] .ci-overlay .ci-history-empty,
:root[data-theme="light"] .ci-overlay .ci-history-load-more {
  color: var(--text-soft);
}
/* 右上角"签到记录"按钮: 边框 + 文字, 默认是白底白边白字, light 翻深色 */
:root[data-theme="light"] .ci-overlay .ci-history-btn {
  border-color: rgba(22,24,35,.18);
  background: rgba(22,24,35,.02);
}
:root[data-theme="light"] .ci-overlay .ci-history-btn:hover {
  background: rgba(22,24,35,.06);
}

/* 成就 ach-* (在 ci-overlay 内) */
:root[data-theme="light"] .ach-summary-title,
:root[data-theme="light"] .ach-card-title,
:root[data-theme="light"] .ach-card-claimed .ach-card-title,
:root[data-theme="light"] .ach-lb-title,
:root[data-theme="light"] .ach-lb-name { color: var(--text); }

/* 2026-05-01 用户反馈"白天模式下, 显示的这个样式不对" — 成就排行榜
   弹窗 (.ach-lb-panel) 在 light 主题下仍是 #1a1a2e 深底, 跟周围白
   底列表对比强烈, 用户名/排名也是浅字几乎看不见. 这里把 panel /
   head / row / mask 换成 light 配色 (用 --surface / --border 而非
   硬编码白, 跟其它卡片同变量驱动). */
:root[data-theme="light"] .ach-lb-mask  { background: rgba(0,0,0,.35); }
:root[data-theme="light"] .ach-lb-panel {
  background: var(--surface, #fff);
  color: var(--text, #161823);
  box-shadow: 0 -8px 28px rgba(22,24,35,.18);
}
:root[data-theme="light"] .ach-lb-head  {
  border-bottom-color: var(--border, rgba(22,24,35,.08));
}
:root[data-theme="light"] .ach-lb-close {
  background: rgba(22,24,35,.06);
}
:root[data-theme="light"] .ach-lb-close:hover {
  background: rgba(22,24,35,.12);
}
:root[data-theme="light"] .ach-lb-row {
  background: rgba(22,24,35,.04);
}
:root[data-theme="light"] .ach-lb-row:nth-child(1) {
  background: linear-gradient(135deg, rgba(255,179,0,.18), rgba(255,179,0,.05));
}
:root[data-theme="light"] .ach-lb-row:nth-child(2) {
  background: linear-gradient(135deg, rgba(140,140,140,.16), rgba(180,180,180,.05));
}
:root[data-theme="light"] .ach-lb-row:nth-child(3) {
  background: linear-gradient(135deg, rgba(205,127,50,.16), rgba(205,127,50,.05));
}
:root[data-theme="light"] .ach-lb-rank { color: var(--text); }
:root[data-theme="light"] .ach-lb-cnt  {
  color: #B17600;
  background: rgba(255,179,0,.16);
}
:root[data-theme="light"] .ach-lb-cash {
  color: #0E8C4F;
  background: rgba(33,208,122,.14);
}
:root[data-theme="light"] .ach-summary-sub,
:root[data-theme="light"] .ach-group-title,
:root[data-theme="light"] .ach-group-count,
:root[data-theme="light"] .ach-card-desc,
:root[data-theme="light"] .ach-card-mini,
:root[data-theme="light"] .ach-metric,
:root[data-theme="light"] .ach-status-locked,
:root[data-theme="light"] .ach-progress-text,
:root[data-theme="light"] .ach-rewards-label,
:root[data-theme="light"] .ach-foot-meta,
:root[data-theme="light"] .ach-locked-reason,
:root[data-theme="light"] .ach-lb-empty { color: var(--text-soft); }
:root[data-theme="light"] .ach-card-caret { color: var(--text-mute); }
/* 2026-05-01 成就等级显示 / 详情按钮 light 主题适配 */
:root[data-theme="light"] .ach-star-off { color: rgba(22,24,35,.16); }
:root[data-theme="light"] .ach-stage-frac {
  background: rgba(255,179,0,.18);
  color: #B17600;
}
:root[data-theme="light"] .ach-card-detail-btn {
  background: rgba(22,24,35,.05);
  color: rgba(22,24,35,.6);
}
:root[data-theme="light"] .ach-card-head:hover .ach-card-detail-btn {
  background: rgba(22,24,35,.1);
  color: rgba(22,24,35,.82);
}
:root[data-theme="light"] .ach-card[data-collapsed="0"] .ach-card-detail-btn {
  background: rgba(254,44,85,.14);
  color: #C92A50;
}
:root[data-theme="light"] .ach-badge-label,
:root[data-theme="light"] .ach-chip,
:root[data-theme="light"] .ach-chip-none,
:root[data-theme="light"] .ach-lb-close { color: var(--text-soft); }
/* .ach-claim-btn 是品牌红渐变按钮, 保留白字; 不动. */

/* 2026-04-29: ci-overlay 内的卡片层 (.ach-card / .ci-stat-card /
   .ach-card-foot / .ach-progress-bar) 之前 base 用了
   rgba(255,255,255,.04~.06) 半透明白做底/边/虚线,
   在 dark 下能从深底上看出隐约的玻璃感, 但在 light 纯白底上
   完全消失 → "优惠中心"卡片堆叠成一锅白雾. 集中翻成
   半透明深灰, 在白底上仍能勾出卡片轮廓. */
:root[data-theme="light"] .ach-card,
:root[data-theme="light"] .ci-stat-card,
:root[data-theme="light"] .ci-reward-section,
:root[data-theme="light"] .ci-history-inline,
:root[data-theme="light"] .ci-week-card {
  background: rgba(22,24,35,.04);
  border-color: rgba(22,24,35,.08);
}
:root[data-theme="light"] .ach-card-foot {
  border-top-color: rgba(22,24,35,.1);
}
:root[data-theme="light"] .ach-progress-bar {
  background: rgba(22,24,35,.08);
}
/* 签到奖励详情: 行间分隔线 / 第N天弱信息 / 右侧奖励金色文字
   - 分隔线在白底上原本 rgba(255,255,255,.04) 几乎透明 → 翻深色描边
   - 右侧 .ci-reward-val 默认 #FFB300 在白底上对比度不足 → light 下加深 */
:root[data-theme="light"] .ci-reward-row {
  border-bottom-color: rgba(22,24,35,.06);
}
:root[data-theme="light"] .ci-reward-val {
  color: #B07000;
}
/* 7 天奖励 strip 的次级文字 (.ci-week-day / .ci-week-bonus) 默认是
   半透明白, 在 light 白底下完全看不见 → 翻 --text-soft / --text-mute */
:root[data-theme="light"] .ci-week-day { color: var(--text-mute); }
:root[data-theme="light"] .ci-week-bonus { color: var(--text-soft); }
/* milestone / done / today 状态的薄色玻璃底也整体翻深色, 否则白底淡黄/淡红
   再叠白色, 视觉上"等于没标". today 描边和 ::after 标签本身已是品牌红, 不动. */
:root[data-theme="light"] .ci-week-card.done {
  background: rgba(254,44,85,.08);
  border-color: rgba(254,44,85,.25);
}
:root[data-theme="light"] .ci-week-card.milestone {
  background: rgba(255,179,0,.1);
  border-color: rgba(255,179,0,.35);
}
/* 顶部三大统计数字 (.ci-stat-num) 是品牌渐变填字, 在白底上红/绿色还行,
   但金色 (gold) 对比度差; light 下改用更深的金色渐变, 仍走品牌色系. */
:root[data-theme="light"] .ci-stat-num.gold {
  background: linear-gradient(135deg, #C77800, #E69500);
  -webkit-background-clip: text; background-clip: text;
}
/* .ach-card-claimable / .ach-summary 自己有彩色渐变底 + 彩色边, 在 light
   下识别度本身够, 不动; 只把它们的 .ach-card-foot 虚线随上面规则一起翻. */

/* 消息中心 msg-* (在 ci-overlay 内) */
:root[data-theme="light"] .msg-readall-btn,
:root[data-theme="light"] .msg-read-btn:hover:not(:disabled) { color: var(--text-soft); }
/* .msg-badge 是红 dot, 保留白字 */

/* 推荐人 referral-* */
:root[data-theme="light"] .referral-copy-btn { color: var(--text); }
/* .referral-claim 等红色按钮保留白字 */

/* ---- 桌面侧栏化的 action-bar (light 下半透明白, mobile 浮在视频上不动) ----
   原设计是 mobile 浮在视频之上 (黑色背景), 所有图标/文字大量使用:
   - .action-icon { fill: #fff; filter: drop-shadow(0 2px 8px rgba(0,0,0,.5)); }
   - .action-count { color: #fff; text-shadow: 0 1px 4px rgba(0,0,0,.7); }
   - .action-nav-btn { background: rgba(255,255,255,.08); border: rgba(255,255,255,.18); color: #fff; }
   - .next-game-name { color: rgba(255,255,255,.7); text-shadow: ...; }
   切到 light 桌面侧栏后, .action-bar 背景变成半透明白 (var(--topbar-bg)),
   白色填充/白字 + 深色阴影 = 内容消失只剩"模糊投影轮廓" (用户反馈
   2026-04-28 截图: actionBar 整片图标都很糊, 看不清).
   下面集中反色: 实色填充 + 取消所有阴影, 让图标/文字在浅底上扎实可读. */
:root[data-theme="light"] body:not(.is-mobile-device) .action-bar { color: rgba(22,24,35,.6); }

/* SVG 实色 fill 用中性灰 (用户反馈 2026-04-28: 纯深字太重, 改浅色),
   hover 加深到 var(--text) 提供交互反馈 */
:root[data-theme="light"] body:not(.is-mobile-device) .action-bar .action-icon {
  fill: rgba(22,24,35,.55);
  filter: none;
  transition: fill .15s;
}
:root[data-theme="light"] body:not(.is-mobile-device) .action-bar .action-item:hover .action-icon {
  fill: var(--text);
}
:root[data-theme="light"] body:not(.is-mobile-device) .action-bar .action-item.liked .action-icon { fill: #FE2C55; }
:root[data-theme="light"] body:not(.is-mobile-device) .action-bar #btnFavorite.liked .action-icon { fill: #FACD00; }

/* 文字色: 中性灰 (count + label), 取消 text-shadow */
:root[data-theme="light"] body:not(.is-mobile-device) .action-bar .action-count,
:root[data-theme="light"] body:not(.is-mobile-device) .action-bar .action-label {
  color: rgba(22,24,35,.55);
  text-shadow: none;
  transition: color .15s;
}
:root[data-theme="light"] body:not(.is-mobile-device) .action-bar .action-item:hover .action-count,
:root[data-theme="light"] body:not(.is-mobile-device) .action-bar .action-item:hover .action-label {
  color: var(--text);
}

/* 上下切换/搜索按钮: 浅色透明胶囊, 边框/icon 都用淡灰 */
:root[data-theme="light"] body:not(.is-mobile-device) .action-bar .action-nav-btn {
  background: rgba(22,24,35,.04);
  border-color: rgba(22,24,35,.08);
  color: rgba(22,24,35,.6);
}
:root[data-theme="light"] body:not(.is-mobile-device) .action-bar .action-nav-btn:hover {
  background: rgba(22,24,35,.08);
  color: var(--text);
}
:root[data-theme="light"] body:not(.is-mobile-device) .action-bar .action-nav-btn:active {
  background: rgba(22,24,35,.12);
}

/* 收起 ›› 按钮 / 小拉手: 浅灰胶囊 (之前 .6 太黑) */
:root[data-theme="light"] body:not(.is-mobile-device) .action-collapse-btn,
:root[data-theme="light"] .action-bar-handle {
  background: rgba(22,24,35,.32);
  border-color: rgba(22,24,35,.1);
  color: #fff;
}
:root[data-theme="light"] body:not(.is-mobile-device) .action-collapse-btn:hover { background: rgba(22,24,35,.5); }

/* 下一个游戏预览 (next-game-*) - 同步淡灰 */
:root[data-theme="light"] body:not(.is-mobile-device) .next-game-name {
  color: rgba(22,24,35,.55);
  text-shadow: none;
}
:root[data-theme="light"] body:not(.is-mobile-device) .next-game-arrow { color: var(--text-mute); }
:root[data-theme="light"] body:not(.is-mobile-device) .next-game-thumb {
  border-color: var(--border);
  box-shadow: 0 2px 8px rgba(22,24,35,.08);
}
/* .next-game-thumb .next-fallback 是 fallback 字母, 在 #222 深底上, 保留白字 */

/* ---- top-bar 内 cat-tab/dropdown (light 下半透明白) ---- */
:root[data-theme="light"] .cat-dropdown-btn,
:root[data-theme="light"] .cat-tab,
:root[data-theme="light"] .cat-tab.disabled { color: var(--text-soft); }
:root[data-theme="light"] .cat-dropdown-btn.active,
:root[data-theme="light"] .cat-tab.active,
:root[data-theme="light"] .cat-tab.disabled.active { color: var(--text); }
/* .cat-dd-item 在 dropdown menu 内, dropdown menu 自带固定深色背景, 不动 */

/* ---- search-btn (移动端顶栏, light 下半透明白) ---- */
:root[data-theme="light"] .search-btn { color: var(--text); }

/* ---- 固定深色 panel 的继承文字色强制白色 ----
   仍保留豁免的 panel: 评论面板 (TikTok 头像渐变 + 半透明白文本风格),
   分享面板, toast, landscape-lock, balance-card 渐变, vip-level-card.
   .search-panel / .provider-panel 已主题化 (var(--surface) + var(--text)),
   不再列入. */
:root[data-theme="light"] .comment-panel,
:root[data-theme="light"] .share-panel,
:root[data-theme="light"] .toast,
:root[data-theme="light"] .landscape-lock,
:root[data-theme="light"] .profile-balance-card,
:root[data-theme="light"] .vip-level-card {
  color: #fff;
}

/* ======================================================
   厂商页 / 登录页 / 个人中心 light 模式微调
   ------------------------------------------------------
   2026-04-28 用户要求: "厂商页面, 个人登录页面, 个人中心页面,
   都要跟随日夜模式而变化". 容器层已改用 var(--bg/text), 这里
   只补几个会"漏视觉"的细节修复.
   ====================================================== */

/* 1) .vendor-game-card .vg-name 自带 text-shadow 0 1px 3px rgba(0,0,0,.5),
      在 light 下 (深字+深影) 会显得脏/糊, 取消 */
:root[data-theme="light"] .vendor-game-card .vg-name { text-shadow: none; }

/* 2) .vg-icon 自带 drop-shadow, light 下取消防糊 */
:root[data-theme="light"] .vendor-game-card .vg-icon { filter: none; }

/* 3) 桌面 login 模态阴影改成 light 友好版 */
:root[data-theme="light"] body:not(.is-mobile-device) .login-panel {
  box-shadow: 0 12px 48px rgba(22,24,35,.18);
}

/* 4) follows-page 桌面态容器阴影同步 */
:root[data-theme="light"] body:not(.is-mobile-device) .follows-page {
  box-shadow: 0 -8px 40px rgba(22,24,35,.18);
}

/* 5) "我关注的厂商" 抽屉 (#followedProvidersOverlay 内的 .provider-panel)
      桌面 light 下阴影 8px 0 28px rgba(0,0,0,.35) 在白底上过重, 替换 */
:root[data-theme="light"] body:not(.is-mobile-device) #followedProvidersOverlay .provider-panel {
  box-shadow: 8px 0 28px rgba(22,24,35,.16);
  border-right: 1px solid var(--border);
}

/* 6) provider-panel 内 placeholder 在 light 下要够明显 */
:root[data-theme="light"] .provider-panel .provider-search input::placeholder {
  color: rgba(22,24,35,.42);
}

/* 7) .nav-home-btn (底部 nav 中央 ∞ 按钮) 在 light 下内圆改 var(--surface-2) 浅灰
      ------------------------------------------------------
      用户口径 (2026-04-28): "白天模式, 无论怎么按, logo 都要和图一一样" — 即
      跟个人中心底部首页按钮 (.profile-bottom-nav 内已用 var(--surface-2))
      视觉一致. 全局规则 .nav-home-btn .home-btn-wrap::before { background: #161823 }
      (深底) 在 light 主页底部 nav 上变成"白底 + 黑内圆"很突兀, 这里在 light 下
      统一覆盖成浅灰内圆.
      dark 不动: 主页 .bottom-nav 仍 #161823 黑内圆 (与图3 dark 视频 feed 一致),
      个人中心 .profile-bottom-nav 仍走自己的 var(--surface-2) 规则. */
:root[data-theme="light"] .nav-home-btn .home-btn-wrap::before {
  background: var(--surface-2);
}

/* ============================================================
   Achievement v2 — 字号 / 间距 / 段落统一 (2026-04-29)
   用户反馈: "字体不统一, 上下段落间距太小, 不协调"
   规则:
   - 主字号 14, 副字号 12; 标题 15; 角标 11; 行高 1.55
   - 同卡内 段与段之间 至少 14px 垂直间距
   - 卡片之间 至少 14px 垂直间距
   - 不再用 font-weight:800 大粗字, 统一 normal/600
   ============================================================ */
.ach-summary {
  padding: 14px 16px !important;
  margin-bottom: 16px !important;
  gap: 14px !important;
}
.ach-summary-title { font-size: 15px !important; font-weight: 600 !important; line-height: 1.4 !important; }
.ach-summary-sub   { font-size: 13px !important; margin-top: 4px !important; line-height: 1.5 !important; }
.ach-leaderboard-btn { font-size: 12px !important; padding: 6px 14px !important; }

.ach-group { margin-bottom: 22px !important; }
.ach-group-title {
  font-size: 13px !important;
  letter-spacing: .4px !important;
  text-transform: none !important;
  padding: 0 4px 10px !important;
  font-weight: 600 !important;
  color: rgba(255,255,255,.7) !important;
}
.ach-group-count { font-size: 12px !important; }

.ach-card { margin-bottom: 14px !important; }
.ach-card-head { padding: 14px 16px !important; gap: 14px !important; min-height: 76px !important; }
.ach-card-head .ach-card-title { font-size: 15px !important; font-weight: 600 !important; line-height: 1.4 !important; }
.ach-card-mini  { font-size: 12.5px !important; line-height: 1.5 !important; margin-top: 2px !important; }

.ach-card-body { padding: 14px 16px 16px !important; padding-top: 14px !important; }
.ach-card-body > * + * { margin-top: 14px !important; }

.ach-card-desc {
  font-size: 13px !important;
  color: rgba(255,255,255,.65) !important;
  line-height: 1.6 !important;
  margin-bottom: 0 !important;
}
.ach-metric {
  font-size: 13px !important;
  color: rgba(255,255,255,.78) !important;
  font-weight: 500 !important;
  line-height: 1.5 !important;
}

.ach-roadmap { gap: 8px !important; padding: 4px 2px 10px !important; margin-top: 0 !important; }
.ach-stage-chip { padding: 10px 8px !important; gap: 4px !important; min-width: 78px !important; }
.ach-stage-num    { font-size: 12px !important; font-weight: 600 !important; }
.ach-stage-target { font-size: 11px !important; }
.ach-stage-reward { font-size: 11px !important; font-weight: 600 !important; }

.ach-next-block,
.ach-pending-summary {
  margin-top: 0 !important;
  padding: 12px 14px !important;
  border-radius: 12px !important;
}
.ach-next-head { gap: 10px !important; margin-bottom: 8px !important; }
.ach-next-label,
.ach-pending-summary-label {
  font-size: 11px !important;
  letter-spacing: .3px !important;
  font-weight: 600 !important;
  padding: 3px 8px !important;
}
.ach-next-text { font-size: 13px !important; line-height: 1.5 !important; font-weight: 500 !important; }
.ach-next-rewards { gap: 8px !important; margin-top: 10px !important; }

.ach-chip { font-size: 12px !important; padding: 4px 10px !important; font-weight: 600 !important; line-height: 1.4 !important; }
.ach-chip-bold { font-size: 12px !important; padding: 4px 10px !important; }

.ach-card-foot-meta {
  margin-top: 0 !important;
  font-size: 11px !important;
  gap: 10px !important;
  flex-wrap: wrap !important;
}
.ach-ends-tag      { font-size: 11px !important; padding: 3px 8px !important; font-weight: 600 !important; }
.ach-claimed-times { font-size: 11px !important; padding: 3px 8px !important; }

.ach-action-row { margin-top: 0 !important; }
.ach-action-dual { margin-top: 0 !important; gap: 10px !important; }
.ach-claim-btn { padding: 11px 16px !important; font-size: 14px !important; font-weight: 600 !important; }

.ach-badge       { padding: 10px 4px 8px !important; }
.ach-badge-icon  { font-size: 24px !important; margin-bottom: 6px !important; }
.ach-badge-label { font-size: 10px !important; letter-spacing: .4px !important; font-weight: 600 !important; }

:root[data-theme="light"] .ach-card-desc { color: rgba(22,24,35,.65) !important; }
:root[data-theme="light"] .ach-metric    { color: rgba(22,24,35,.78) !important; }
:root[data-theme="light"] .ach-next-text { color: rgba(22,24,35,.85) !important; }
:root[data-theme="light"] .ach-card-foot-meta { color: rgba(22,24,35,.55) !important; }
:root[data-theme="light"] .ach-summary-title { color: rgba(22,24,35,.92) !important; }
:root[data-theme="light"] .ach-summary-sub   { color: rgba(22,24,35,.6) !important; }
:root[data-theme="light"] .ach-group-title   { color: rgba(22,24,35,.65) !important; }
:root[data-theme="light"] .ach-group-count   { color: rgba(22,24,35,.45) !important; }
:root[data-theme="light"] .ach-card-mini     { color: rgba(22,24,35,.62) !important; }

/* ─────────────────────────────────────────────────────────────────
   2026-05-01  PromoHub → 优惠 tab → 卡片点击后的"优惠详情弹窗"
   .pdo-* (Promo Detail Overlay)
   z-index 100050: 高于 PromoHub (1000), 低于 loginOverlay (100060)
   ───────────────────────────────────────────────────────────────── */
.pdo-overlay {
  position: fixed; inset: 0; z-index: 100050;
  background: rgba(10,10,16,.55);
  display: flex; align-items: flex-end; justify-content: center;
  opacity: 0; pointer-events: none;
  transition: opacity .22s ease;
  padding: 0;
}
.pdo-overlay.open { opacity: 1; pointer-events: auto; }
.pdo-card {
  position: relative;
  width: 100%; max-width: 520px;
  max-height: 86vh; overflow-y: auto;
  background: var(--surface, #1a1c25);
  border: 1px solid var(--border, rgba(255,255,255,.08));
  border-radius: 18px 18px 0 0;
  padding: 22px 18px 18px;
  transform: translateY(24px);
  transition: transform .22s ease;
  color: var(--text, #fff);
}
.pdo-overlay.open .pdo-card { transform: translateY(0); }
@media (min-width: 720px) {
  .pdo-overlay { align-items: center; padding: 24px; }
  .pdo-card { border-radius: 18px; transform: translateY(0) scale(.96); }
  .pdo-overlay.open .pdo-card { transform: translateY(0) scale(1); }
}
.pdo-close {
  position: absolute; top: 10px; right: 12px;
  width: 32px; height: 32px;
  border: none; background: transparent;
  color: var(--text, rgba(255,255,255,.7));
  font-size: 22px; line-height: 1; cursor: pointer;
  border-radius: 50%;
}
.pdo-close:hover { background: rgba(255,255,255,.08); }
.pdo-head {
  display: flex; align-items: center; gap: 12px;
  padding: 4px 36px 14px 4px;
  border-bottom: 1px solid var(--border, rgba(255,255,255,.06));
  margin-bottom: 12px;
}
.pdo-icon {
  width: 44px; height: 44px; flex: 0 0 44px;
  display: flex; align-items: center; justify-content: center;
  font-size: 26px;
  background: linear-gradient(135deg, rgba(254,44,85,.18), rgba(254,44,85,.06));
  border-radius: 12px;
}
.pdo-head-text { flex: 1; min-width: 0; }
.pdo-title {
  font-size: 16px; font-weight: 600; line-height: 1.3;
  color: var(--text, #fff);
  word-break: break-all;
}
.pdo-subtag {
  display: inline-block; margin-top: 6px;
  font-size: 11px; padding: 2px 8px; border-radius: 10px;
  background: rgba(255,179,0,.16); color: #FFB300;
}
.pdo-rows {
  display: flex; flex-direction: column; gap: 0;
  margin-bottom: 14px;
}
.pdo-row {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 12px;
  padding: 10px 4px;
  border-bottom: 1px dashed var(--border, rgba(255,255,255,.06));
  font-size: 13px;
}
.pdo-row:last-child { border-bottom: none; }
.pdo-k {
  flex: 0 0 auto; min-width: 80px;
  color: var(--text-muted, rgba(255,255,255,.55));
}
.pdo-v {
  flex: 1; text-align: right;
  color: var(--text, rgba(255,255,255,.92));
  word-break: break-word;
  font-variant-numeric: tabular-nums;
}
.pdo-desc-title {
  font-size: 12px; color: var(--text-muted, rgba(255,255,255,.55));
  margin: 6px 4px 6px;
}
.pdo-desc {
  font-size: 13px; line-height: 1.6;
  color: var(--text, rgba(255,255,255,.85));
  background: rgba(255,255,255,.03);
  border: 1px solid var(--border, rgba(255,255,255,.05));
  border-radius: 10px;
  padding: 10px 12px;
  margin-bottom: 14px;
  white-space: pre-wrap;
}
.pdo-actions {
  display: flex; gap: 10px;
  padding-top: 4px;
}
.pdo-cancel, .pdo-cta {
  flex: 1; height: 40px;
  border: none; border-radius: 10px;
  font-size: 14px; font-weight: 600;
  cursor: pointer;
}
.pdo-cancel {
  background: rgba(255,255,255,.06);
  color: var(--text, rgba(255,255,255,.85));
  border: 1px solid var(--border, rgba(255,255,255,.08));
}
.pdo-cancel:hover { background: rgba(255,255,255,.1); }
.pdo-cta {
  background: linear-gradient(135deg, #FE2C55, #FF5470);
  color: #fff;
}
.pdo-cta:hover { filter: brightness(1.05); }

/* light 主题 */
:root[data-theme="light"] .pdo-overlay { background: rgba(0,0,0,.35); }
:root[data-theme="light"] .pdo-card    { background: #fff; border-color: rgba(22,24,35,.08); color: #161823; }
:root[data-theme="light"] .pdo-close   { color: rgba(22,24,35,.6); }
:root[data-theme="light"] .pdo-close:hover { background: rgba(22,24,35,.06); }
:root[data-theme="light"] .pdo-head    { border-bottom-color: rgba(22,24,35,.08); }
:root[data-theme="light"] .pdo-title   { color: #161823; }
:root[data-theme="light"] .pdo-row     { border-bottom-color: rgba(22,24,35,.08); }
:root[data-theme="light"] .pdo-k       { color: rgba(22,24,35,.55); }
:root[data-theme="light"] .pdo-v       { color: rgba(22,24,35,.88); }
:root[data-theme="light"] .pdo-desc-title { color: rgba(22,24,35,.55); }
:root[data-theme="light"] .pdo-desc    { background: rgba(22,24,35,.03); border-color: rgba(22,24,35,.08); color: rgba(22,24,35,.82); }
:root[data-theme="light"] .pdo-cancel  { background: rgba(22,24,35,.05); border-color: rgba(22,24,35,.1); color: rgba(22,24,35,.85); }
:root[data-theme="light"] .pdo-cancel:hover { background: rgba(22,24,35,.08); }

/* ═══════════════════════════════════════════════════════════════════════════════
 * 2026-05-26  代理会员 (website 3.X 的 ng_member.agent_type='agent') 入口屏蔽
 *
 * 触发: app.js 在 init / login / loadProfile 后 给 <body> 挂 .is-agent-member 类.
 * 业务: 这类会员的资金由后台手工上下分, 因此前端必须把 资金类 + 福利类 + 优惠类
 *      入口一并隐藏. 只保留 报表 / 关注厂商 / 安全中心 + 系统功能 (语言/主题/消息/登出).
 * 双层防御: CSS 隐藏 + JS 内 _agentBlock() 拦截 (见 app.js / member-panels.js).
 * 不用 :not / [data-role=agent] 这类组合是因为某些 entry 没有稳定 data 属性,
 * 直接列 id / 数据属性最稳, 也方便后续扩展 (加一条 selector 就多屏一个入口).
 * ═══════════════════════════════════════════════════════════════════════════════ */

/* —— 移动端底部 nav 的"优惠"按钮 (主 + 个人中心两份, 都是 [data-nav="promotion"]) —— */
body.is-agent-member #bottomNav         [data-nav="promotion"],
body.is-agent-member #profileBottomNav  [data-nav="promotion"] { display: none !important; }

/* —— 个人中心余额卡:
 *    a) 充值/提现/奖金 三联 action 按钮整行 .balance-actions 屏蔽
 *    b) 余额宝副条目本身 (#profileSavingsItem) JS 控制 display, 这里再加 !important 兜底
 *       不让 app.js _loadProfileSavings 后又被 display:flex 翻出来. —— */
body.is-agent-member .profile-balance-card .balance-actions { display: none !important; }
body.is-agent-member #profileSavingsItem                    { display: none !important; }

/* —— 移动端"设置"抽屉里两个折叠分组整组屏蔽 (header + body 一起没): —— */
body.is-agent-member #profileSideMenu .settings-section[data-section="finance"],
body.is-agent-member #profileSideMenu .settings-section[data-section="benefits"] { display: none !important; }

/* —— 桌面端用户下拉 (#dtUserMenu) 同样两个分组屏蔽: —— */
body.is-agent-member #dtUserMenu .dt-um-group[data-group="finance"],
body.is-agent-member #dtUserMenu .dt-um-group[data-group="benefits"] { display: none !important; }

/* —— 主页 / dt-feed / 各 overlay 入口里可能漂出来的优惠/PromoHub/红包/转盘/任务 类
 *    按钮一并屏蔽. 用 data-action 或 [data-nav] 兜底, 与现有 DOM 命名一致.
 *    若日后新增同类入口, 加一条 selector 即可, 不必动 JS. —— */
body.is-agent-member [data-action="deposit"],
body.is-agent-member [data-action="withdraw"],
body.is-agent-member [data-action="transfer"],
body.is-agent-member [data-action="bankCards"],
body.is-agent-member [data-action="savings"],
body.is-agent-member [data-action="vip"],
body.is-agent-member [data-action="rebate"],
body.is-agent-member [data-action="referral"],
body.is-agent-member [data-action="affiliate"],
body.is-agent-member [data-action="tasks"] { display: none !important; }

/* —— 2026-06-01 问题8: 红包雨悬浮按钮 + 飘落层兜底屏蔽.
 *    主拦截在 ngapi-redpacket.js (checkActive/resume/boot 都查 _agentSilent),
 *    这里再用 CSS 兜底, 即使 JS 漏判或 WS 直推也不会让代理会员看到红包雨. —— */
body.is-agent-member #rp-float-btn,
body.is-agent-member #rp-rain-field { display: none !important; }


/* 2026-06-15: 支付通道维护状态样式 */
.fin-maint-box {
  padding: 40px 20px;
  text-align: center;
  background: #fffafa;
  border: 1px dashed #ffccc7;
  border-radius: 12px;
  margin: 10px 0 20px;
}
.fin-maint-icon {
  font-size: 48px;
  margin-bottom: 16px;
}
.fin-maint-text {
  font-size: 15px;
  color: #ff4d4f;
  font-weight: 500;
  line-height: 1.6;
}



/* === light ci-overlay contrast fix 20260724 === */
/* 日间模式: ci-overlay 为纯白底, 原先按暗色写的白半透明字/边框会肉眼难见 */
:root[data-theme="light"] .ci-history-btn {
  border-color: rgba(22,24,35,.18);
  color: var(--text-mute, rgba(22,24,35,.55));
}
:root[data-theme="light"] .ci-stat-card {
  background: rgba(22,24,35,.04);
  border-color: rgba(22,24,35,.08);
}
:root[data-theme="light"] .ci-stat-label,
:root[data-theme="light"] .ci-week-day,
:root[data-theme="light"] .ci-week-bonus {
  color: var(--text-mute, rgba(22,24,35,.55)) !important;
}
:root[data-theme="light"] .ci-overlay .finance-loading {
  color: var(--text-mute, rgba(22,24,35,.55)) !important;
}
