/*
 * purple 基础层
 *
 * 加载顺序：tokens.css（变量） → style.css（继承自 blue 的基线） → base.css（本文件）
 * 本文件排最后，职责是压过两样东西：
 *   1. core/css/dark.css 的 17981 行底妆（两个老主题共用，不能改）
 *   2. style.css 里继承自 blue、与 purple 观感冲突的部分
 * style.css 保持 blue 原样不动，P3/P4 再逐页替换；本文件里的每一条都是 purple 自己的决定。
 *
 * ⚠️ 作用域规则：
 *   - 主题 DOM 内的元素 → 写 .theme-purple X（.theme-purple 是主题根节点的类）
 *   - sweetalert / contextmenu / toastr 这类挂在 <body> 上、在主题根节点之外的组件
 *     → 不能加 .theme-purple 前缀，否则选不中。本文件只在 purple 主题下被加载，
 *       不写前缀也不会污染 blue/icafemenu。
 */

/* ============================================================
   1. 中和 CP 的 Theme color 六档配置
   ============================================================
   CP 的 settings-cafe.htm 有个 Theme color 设置（default/green/sea/fire/shadow/
   customized），main.js 会把选中的颜色以内联样式写到 document.documentElement 上：
     --client_themes_front_color / _90 / _75
     --client_themes_back_color  / _90 / _75
   blue 的 style.css 有 10 处直接引用这两组变量。purple 要的是固定的洋红观感，
   而 CP 的默认前景色是 #49d149（绿），跟着走的话开箱即绿。

   这里在 .theme-purple 上重新定义这 6 个变量：自定义属性按元素继承，主题根节点自己
   的声明会覆盖从 :root 继承下来的值（哪怕 :root 上那份是内联样式——内联优先级只作用
   于它所在的那个元素，管不到后代元素自己的声明）。于是 style.css 里那 10 处引用
   自动解析成 purple 的颜色，一处都不用改。

   代价：purple 下 CP 的 Theme color 不再生效（blue/icafemenu 不受影响）。这是刻意的，
   要改回跟随，把下面这段删掉即可。 */
.theme-purple {
	--client_themes_front_color:    var(--purple-accent);
	--client_themes_front_color_90: var(--purple-accent-to);
	--client_themes_front_color_75: var(--purple-accent-from);
	--client_themes_back_color:     var(--purple-ground);
	--client_themes_back_color_90:  var(--purple-surface);
	--client_themes_back_color_75:  var(--purple-panel);
}

/* ============================================================
   2. 软件渲染禁用项
   ============================================================
   客户端 CEF 以 --disable-gpu --disable-gpu-compositing 启动，全部走软件渲染：
     - backdrop-filter / filter: blur()：每帧对全部像素做高斯运算，开销极高
     - mix-blend-mode：同样要逐像素合成
     - will-change：GPU 合成已禁用，只会多造一个软件合成层
   blue 基线里有 41 处生效的 backdrop-filter、3 处 filter: blur()、1 处 will-change，
   这里统一按主题作用域关掉。第 3 节负责把因此失去毛玻璃的半透明容器补成不透明。 */
.theme-purple *,
.theme-purple *::before,
.theme-purple *::after,
.sweet-alert,
.context-menu-list {
	backdrop-filter: none !important;
	-webkit-backdrop-filter: none !important;
	will-change: auto !important;
}

/* 电光边框的辉光层：blur 换成 box-shadow（软渲染下开销远低于高斯模糊），
   叠加模式一并去掉 */
.theme-purple .electro-border-overlay .glow-layer-1,
.theme-purple .electro-border-overlay .glow-layer-2,
.theme-purple .electro-border-overlay .background-glow,
.theme-purple .electro-border-overlay .overlay-1,
.theme-purple .electro-border-overlay .overlay-2 {
	filter: none !important;
	mix-blend-mode: normal !important;
}
.theme-purple .electro-border-overlay .background-glow {
	box-shadow: 0 0 24px 6px var(--purple-accent-from);
	opacity: 0.35;
}

/* ============================================================
   3. 半透明容器转不透明
   ============================================================
   blue 基线里这些容器都是「半透明背景 + backdrop-filter 毛玻璃」的组合，
   第 2 节关掉模糊之后，只剩半透明，底下内容会直接穿透上来。按层级补成不透明：
     rgba(14,18,29,0.95) 这类站在内容之上的（弹窗/菜单） → --purple-panel
     rgba(14,18,29,0.25) 这类页面区块                      → --purple-surface */

/* 3.1 弹窗层 */
.theme-purple .modal-content,
.theme-purple .myModalOrderList .modal-content-order,
.theme-purple .myModalPrint .modal-content,
.theme-purple .myModalBalanceHistory .modal-content-order,
.theme-purple .header-section .header-area .dropdown-menu,
.theme-purple .header-section .header-area .header-menu,
.sweet-alert,
.context-menu-list {
	background: var(--purple-panel) !important;
	border: 1px solid var(--purple-border) !important;
}

/* 3.2 页面区块层 */
.theme-purple .header-section .header-area,
.theme-purple #page_login .home-cafeid-form-div,
.theme-purple .home-promoted,
.theme-purple .home-news,
.theme-purple #page-shop .shop-category-menu,
.theme-purple .event-card,
.theme-purple .event-detail-container .bd-highlight,
.theme-purple .event-detail-container .rounded-top > .container:last-child,
.theme-purple .rank-table-container {
	background: var(--purple-surface) !important;
}

/*
 * 有意保持半透明、不在上面两组里的三个：
 *   .hover-overlay          —— rgba(0,0,0,0.4) 是刻意的压暗遮罩，半透明是它的功能本身
 *   .event-detail-winners-card —— 背景是图片
 *   .bottom-section         —— 背景是渐变
 * 它们只在第 2 节被去掉了模糊，背景不动。
 */

/* ============================================================
   4. 底色与文字
   ============================================================ */
/* 底色必须放在 body 上，不能放在 .theme-purple：视频背景（layout.htm 的 .url-video）是
   position:fixed + z-index:-1，画在根层叠上下文的负层。.theme-purple 是普通流里的 div，
   它的不透明底色会整块盖住视频，登录页选「Video」时只看到一片 #171720。
   body 的背景会传播到画布最底层，视频画在它上面，blue 就是这个层次。
   !important 是为了压过顶层 client/main.htm 里 <body style="background-color: black">
   （启动阶段防闪白用的内联样式，不能删）。 */
body {
	background-color: var(--purple-ground) !important;
}
.theme-purple {
	background-color: transparent;
	color: var(--purple-text);
	font-family: var(--purple-font);
}

/* 注意：主文字不是纯白（取样得 #919FBF）。纯白留给需要强调的数字——
   时间、金额、倒计时。这是参考界面的层次做法，全白会把层次压平。 */
.theme-purple .text-white,
.theme-purple .purple-strong {
	color: var(--purple-text-strong) !important;
}
.theme-purple .text-muted,
.theme-purple .purple-muted {
	color: var(--purple-text-muted) !important;
}
.theme-purple a {
	color: var(--purple-accent-text);
}

/* ============================================================
   5. 按钮
   ============================================================ */
/* 主按钮：水平渐变（左紫右洋红），不是对角 */
.theme-purple .btn-primary,
.theme-purple .purple-btn-primary {
	background: var(--purple-gradient-primary) !important;
	border: none !important;
	color: var(--purple-text-strong) !important;
	border-radius: var(--purple-r-btn) !important;
	font-family: var(--purple-font);
}
/* 悬停/按下只动 opacity —— 软渲染下 opacity 有快速路径，
   换 background 会触发整块重绘 */
.theme-purple .btn-primary:hover,
.theme-purple .purple-btn-primary:hover { opacity: 0.88; }
.theme-purple .btn-primary:active,
.theme-purple .purple-btn-primary:active { opacity: 0.75; }
.theme-purple .btn-primary:disabled,
.theme-purple .purple-btn-primary:disabled { opacity: 0.45; }

/* 顶栏 Lucky Spin 图标（layout.htm，音量图标前面）。按 Yao 的反馈：右上角、紫色图标。
   圆钮底色/尺寸跟旁边几个图标同一套（.header-right-info > div > a.lang），这里只把图标染成主题紫。
   ⚠️ 演进：会员卡下面一整条按钮 → 会员卡右上角圆钮（渐变底+细线图标，发糊）→ 现在的顶栏。 */
/* 顶栏右侧每一项都是 flex 居中。不能在 HTML 上用 Bootstrap 的 .d-flex（display:flex !important），
   它会压过 v-show 写的内联 display:none，条件判断全部失效：
     Lucky Spin（lucky_spin_enable / 今日资格）、Ask help（menuButton.assist）、
     Logout（menuButton.logout）、Chat（未登录会员）、机器号——关了照样显示。
   blue 里 Ask help / Logout 是下拉菜单项、没带 d-flex，所以没这个问题；purple 把它们
   提到顶栏做成方片时带上了 d-flex，判断就丢了。这里统一不带 !important 地给 flex。 */
.theme-purple .header-right-info > div {
	display: flex;
	align-items: center;
	justify-content: center;
}
.theme-purple .header-right-info .purple-header-spin i {
	color: var(--purple-accent-text);
	font-size: 16px;
}
/* 右上角小圆点：提示「今天还能抽」。
   闪烁不用 CSS 动画：只要有 infinite 动画在跑，浏览器每帧都会醒来，软件渲染下哪怕只动这 8px
   的 opacity，主页静置 CPU 也从约 3% 涨到约 12%；换成 steps() 硬切仍有约 4.5%。
   改由 js/app.js 定时切 .is-off（亮 1.2s、灭 0.4s），每个周期只有两次画面变化，实测跟不显示小红点没有区别。
   灭的时候完全隐藏而不是半透明：橙点叠在深色底上降到 0.35 会变成灰褐色，像坏掉的指示灯。 */
.theme-purple .purple-spin-dot {
	position: absolute;
	top: 0;
	right: 0;
	width: 8px;
	height: 8px;
	border-radius: 50%;
	background: var(--purple-warning);
	box-shadow: 0 0 0 2px var(--purple-surface);
}
.theme-purple .purple-spin-dot.is-off {
	opacity: 0;
}

/* 次级按钮：实心深底，不描边 */
.theme-purple .btn-secondary,
.theme-purple .btn-default,
.theme-purple .purple-btn-secondary {
	background: var(--purple-elevated) !important;
	border: none !important;
	color: var(--purple-text) !important;
	border-radius: var(--purple-r-btn) !important;
}
.theme-purple .btn-secondary:hover,
.theme-purple .btn-default:hover,
.theme-purple .purple-btn-secondary:hover { opacity: 0.85; }

.theme-purple .btn:focus,
.theme-purple .btn.focus {
	box-shadow: 0 0 0 2px var(--purple-accent) !important;
	outline: none !important;
}

/* ============================================================
   6. 表单控件
   ============================================================ */
.theme-purple .form-control,
.theme-purple input[type="text"],
.theme-purple input[type="password"],
.theme-purple input[type="number"],
.theme-purple input[type="email"],
.theme-purple select,
.theme-purple textarea {
	background: var(--purple-elevated) !important;
	border: 1px solid transparent !important;
	border-radius: var(--purple-r-btn) !important;
	color: var(--purple-text-strong) !important;
	font-family: var(--purple-font);
}
.theme-purple .form-control:focus,
.theme-purple input:focus,
.theme-purple select:focus,
.theme-purple textarea:focus {
	border-color: var(--purple-accent) !important;
	box-shadow: none !important;
	outline: none !important;
}
.theme-purple .form-control::placeholder,
.theme-purple input::placeholder,
.theme-purple textarea::placeholder {
	color: var(--purple-text-muted) !important;
}

/* ============================================================
   7. 弹窗
   ============================================================ */
.theme-purple .modal-content {
	border-radius: var(--purple-r-card) !important;
}
.theme-purple .modal-header,
.theme-purple .modal-footer {
	border-color: var(--purple-border) !important;
}
/* 遮罩：不用模糊，只压暗 */
.theme-purple .modal-backdrop,
.modal-backdrop {
	background: #000 !important;
	opacity: 0.6 !important;
}

/* ============================================================
   8. 卡片
   ============================================================ */
.theme-purple .card,
.theme-purple .purple-card {
	background: var(--purple-surface);
	border: 1px solid var(--purple-border);
	border-radius: var(--purple-r-card);
}
/* 选中态用洋红描边，不改背景——参考界面的做法 */
.theme-purple .purple-card.is-selected {
	border-color: var(--purple-border-selected);
}

/* ============================================================
   9. 胶囊与状态
   ============================================================
   参考界面的订单状态用「左侧 4px 色条 + 同色文字」，不是整块着色。
   这里给出基类，具体页面在 P3/P4 里套用。 */
.theme-purple .purple-chip {
	display: inline-block;
	padding: 2px 10px;
	border-radius: var(--purple-r-pill);
	font-size: 12px;
	line-height: 18px;
}
.theme-purple .purple-chip-info    { background: var(--purple-info-chip-bg); color: var(--purple-info-chip-fg); }
.theme-purple .purple-chip-success { background: rgba(85, 255, 70, 0.14);  color: var(--purple-success); }
.theme-purple .purple-chip-warning { background: rgba(220, 169, 41, 0.16); color: var(--purple-warning); }
.theme-purple .purple-chip-accent  { background: var(--purple-accent);       color: var(--purple-text-strong); }

.theme-purple .purple-status { border-left: 4px solid transparent; padding-left: 12px; }
.theme-purple .purple-status-new      { border-left-color: var(--purple-info);    color: var(--purple-info); }
.theme-purple .purple-status-progress { border-left-color: var(--purple-warning); color: var(--purple-warning); }
.theme-purple .purple-status-done     { border-left-color: var(--purple-success); color: var(--purple-success); }
.theme-purple .purple-status-canceled { border-left-color: var(--purple-text-muted); color: var(--purple-text-muted); }

/* ============================================================
   10. 滚动条
   ============================================================ */
.theme-purple ::-webkit-scrollbar { width: 8px; height: 8px; }
.theme-purple ::-webkit-scrollbar-track { background: transparent; }
.theme-purple ::-webkit-scrollbar-thumb {
	background: var(--purple-elevated);
	border-radius: var(--purple-r-pill);
}
.theme-purple ::-webkit-scrollbar-thumb:hover { background: var(--purple-accent-from); }

/* ============================================================
   11. dark.css 里带 !important 的工具类
   ============================================================
   .text-gray 在 core/css/dark.css:16329 是 `color:#adb5bd !important`，
   同等 specificity 下 !important 永远赢，第 4 节那条普通声明压不过它。
   主题根节点自己就带 text-gray（见 main.htm 的 class），所以要同时写
   复合选择器（.theme-purple.text-gray，同一个元素）和后代选择器。 */
.theme-purple.text-gray,
.theme-purple .text-gray {
	color: var(--purple-text) !important;
}

/* ============================================================
   13. 游戏卡片 —— 对齐参考界面形态
   ============================================================
   参考界面的卡片：竖版 2:3 海报 + 常驻的底部标题带（全大写、小字号、字距略放开）
   + 右上角收藏星。blue 基线是 168x240（7:10）、标题浮在海报上、收藏用红心。 */

/* 游戏网格：固定 168x240 卡片，从左往右排，不拉伸。
   168x240（7:10）是我们海报的素材规格（CP games.htm 上传提示就是这个尺寸，
   default-poster.png 也是），也是 blue 基线的尺寸——按原图 1:1 显示，不裁不缩。
   ⚠️ 之前这里是 repeat(auto-fill, minmax(168px, 1fr)) + aspect-ratio 3:4，卡片按窗口宽度
      平分拉伸：1366 屏 203px、1920 屏 184px、2560 屏 187px，不同机器/窗口截图卡片大小不一，
      3:4 还会把 7:10 的海报上下裁掉一截、放大后发糊。现在固定尺寸，多出来的宽度留在行尾。
   间距 16 对齐 Senet 实测（卡片间距 15~16px）；game.htm 容器上内联写的 gap:20px 是 blue 基线的，
   内联样式压不过 !important，这里覆盖掉。
   ⚠️ 再次调整（方案 C）：固定 168 时剩余宽度全堆在行尾，右侧空白 20~164px 不等，
      最后一张卡对不齐上面的搜索框。改成 minmax(150px, 1fr)：列数按宽度自动选，
      卡片在 150 上下微调、正好铺满一行，右边线跟搜索框右侧对齐；高度按 7:10 跟着宽度走
      （下面 #page-game .game-item 那条）。实测 1280~2560 屏卡片宽 150~177，
      多数时候比 168 略小，海报是缩小不是放大，不会发虚。
      代价：不同分辨率之间卡片不再是严格的 168；同一窗口下各筛选页大小仍然一致。
      首页那排仍是固定 168x240（横向滚动的一行，不需要铺满）。 */
.theme-purple #page-game .d-flex.flex-wrap {
	display: grid !important;
	grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
	gap: 16px !important;
	justify-content: start;
	align-content: start;
}
.theme-purple :is(#page-game, #page-home) .game-item {
	width: 168px;
	height: 240px;              /* 7:10，海报素材原尺寸 */
	border-radius: 8px;
	background-color: var(--purple-surface);
	/* 这里必须保留 will-change: transform（跟 blue 一致），第 2 节的全局 will-change:auto 对卡片不适用。
	   悬停上浮 translateY(-4px) 时，没有独立合成层的卡片会连同背后缩放铺满的壁纸一起重新光栅化；
	   有独立层只是整层平移。实测鼠标连续划过卡片 CPU 约 36% → 25%（纯鼠标移动的下限约 17%），
	   静止时没有额外开销。!important 用来压过第 2 节 .theme-purple * 那条。 */
	will-change: transform !important;
}
/* Games 页：宽度由网格列决定，高度按 7:10 跟随。必须写在上面那条之后——
   两条 specificity 都是 (1,2,0)（:is 取最高的 #page-game），同级后声明的赢。 */
.theme-purple #page-game .game-item {
	width: auto;
	height: auto;
	aspect-ratio: 7 / 10;
}

/* 悬停：洋红描边取代原来的绿色外发光。
   box-shadow 做描边比 border 好——不占布局、不引起重排 */
.theme-purple :is(#page-game, #page-home) .game-item:hover {
	box-shadow: 0 0 0 2px var(--purple-accent) !important;
	transform: translateY(-4px) !important;
}

/* 卡片内一律不做过渡，悬停效果瞬间切换。
   继承自 blue 的规则里，悬停一张卡会同时跑约 12 个过渡（上浮、描边、边框色、
   遮罩背景、角标背景和 padding、收藏图标 width……），其中 padding/width 每帧都重排。
   软件渲染下每帧整张卡重绘，鼠标划过一排卡片时移入移出的卡同时在动，
   实测连续划动 CPU 约 70% → 35%（icafemenu 约 40%）。 */
.theme-purple :is(#page-game, #page-home) .game-item,
.theme-purple :is(#page-game, #page-home) .game-item::before,
.theme-purple :is(#page-game, #page-home) .game-item::after,
.theme-purple :is(#page-game, #page-home) .game-item *,
.theme-purple :is(#page-game, #page-home) .game-item *::before,
.theme-purple :is(#page-game, #page-home) .game-item *::after {
	transition: none !important;
}

/* 底部标题带：常驻，不随 hover 位移。
   渐变要够高才压得住海报——参考界面量下来，淡出从卡片高度的约 72% 处开始、
   到底部收成近黑，整条占卡片高度 27% 上下；原来只给了 7px 内边距、带子总高 30px
   （卡片 275 高的 11%），而且 42% 处就到顶不透明度了，等于一条窄窄的硬边，
   压在 Fortnite / GTA / PUBG 这种满幅花哨海报上，字几乎糊在画面里。
   padding-top 用百分比不用 px：百分比内边距是按「宽度」算的，卡片是 3:4，
   24% 宽 = 18% 高，加上文字和下边距正好落在 27% 左右，而且跟着卡片缩放走。 */
.theme-purple :is(#page-game, #page-home) .game-item .game-name-label {
	left: 0 !important;
	right: 0 !important;
	bottom: 0 !important;
	max-width: 100% !important;
	transform: none !important;
	transition: none !important;
	padding: 24% 8px 8px;
	background: linear-gradient(180deg,
		rgba(18, 18, 26, 0) 0%,
		rgba(18, 18, 26, 0.55) 42%,
		rgba(18, 18, 26, 0.92) 80%,
		rgba(18, 18, 26, 0.96) 100%);
	color: var(--purple-text-oncard);
	font-family: var(--purple-font);
	/* 11px 比左栏分类项（14px）小一大截，参考界面里两者差不多齐 */
	font-size: 13px;
	font-weight: 500;
	line-height: 16px;
	/* 长名字换行排两行，超过两行才截断——参考界面
	   「Counter-Strike: Global Offensive」就是排两行的。
	   基线那条写的是 nowrap + text-overflow:ellipsis，一律压成一行，
	   于是变成「Counter-Strike Global O...」「PlayerUnknown's Battl...」。
	   line-clamp 需要 -webkit-box 这一套，纯 CSS，CEF 内核支持。 */
	white-space: normal !important;
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	overflow: hidden;
	/* 真机是普通大小写、不加字距（Discord / Google Chrome / GTA Vice City），
	   全大写+letter-spacing 是营销渲染图里的写法，已撤掉 */
	text-align: center;
	text-shadow: none;
}
/* hover 时标题带不动——基线那条 bottom:18px→16px 的位移会让文字抖一下 */
.theme-purple :is(#page-game, #page-home) .game-item:hover .game-name-label {
	bottom: 0 !important;
}

/* 收藏星：参考界面用白色星标（描边=未收藏，实心=已收藏），不是红心 */
.theme-purple .game-item .badge-container .icon-favorite {
	color: var(--purple-text-strong) !important;
	font-size: 15px;
}
.theme-purple .game-item .badge-container .icon-favorite.is-on {
	color: var(--purple-text-strong) !important;
}

/* 角标容器：参考界面里收藏星常驻可见，不是 hover 才出现 */
.theme-purple .game-item .badge-container:not(.has-license):not(.has-favorite) {
	opacity: 1 !important;
}

/* ============================================================
   14. 左侧分类栏
   ============================================================
   参考界面：无图标、无背景块，激活项直接用洋红文字，不用左边框+底色 */
.theme-purple .game-category-menu .dropdown-item {
	color: var(--purple-text);
	font-family: var(--purple-font);
	font-size: 13px;
	border-left: none !important;
	background: transparent !important;
}
.theme-purple .game-category-menu .dropdown-item-active,
.theme-purple .game-category-menu .dropdown-item:hover {
	color: var(--purple-accent-text) !important;
	background: transparent !important;
}

/* --- 14.1 左侧分类栏：对齐参考界面的纯文本列表 ---
   blue 基线给了 3x16px 侧边指示条 + 激活项渐变底；参考界面没有这两样，
   激活态只是文字变洋红。
   注意选择器权重：基线那几条是 :is(#page-game,#page-shop) > ... 带 ID 的
   (1,2,0)，且都带 !important。要压过必须自己也含 ID 且权重更高，
   注意 :is() 的权重取参数里最高的那个（#page-game），
	   所以还要把 .d-flex.flex-column.flex-shrink-0 这条类链一并补上，
	   否则是 (1,2,0) < (1,4,0) 压不过。 */
.theme-purple :is(#page-game, #page-shop) > .d-flex.flex-column.flex-shrink-0 .dropdown-item::before {
	display: none !important;
}
.theme-purple :is(#page-game, #page-shop) > .d-flex.flex-column.flex-shrink-0 .dropdown-item {
	color: var(--purple-text) !important;
	font-family: var(--purple-font) !important;
	background: transparent !important;
}
.theme-purple :is(#page-game, #page-shop) > .d-flex.flex-column.flex-shrink-0 .dropdown-item:hover {
	color: var(--purple-text-strong) !important;
	background: transparent !important;
}
.theme-purple :is(#page-game, #page-shop) > .d-flex.flex-column.flex-shrink-0 .dropdown-item.dropdown-item-active {
	color: var(--purple-accent-text) !important;
	background: transparent !important;
}

/* --- Games / Shop 左侧分类栏：跟 My account 页同一套轨道线 ---
   参考界面这三个页面的左栏是同一种形态：标题（图标+文字）在上，下面一列
   分类项左边挂一条贯通的竖轨道线，激活项是线上那一段变主题色 + 文字变色，
   没有填充色块。度量也一致（按 1920 屏折算）：标题图标 x=48、轨道线 x=72、
   项文字 x=88。

   列宽维持 252px 不动——改它会连带把右边的卡片网格整体推走，不在这次范围里。

   权重：基线那几条是 :is(#page-game,#page-shop) > .d-flex.flex-column.flex-shrink-0
   .dropdown-item 的 (1,4,0)!important，这里沿用同一条链。 */
.theme-purple :is(#page-game, #page-shop) > .d-flex.flex-column.flex-shrink-0 {
	padding-left: 48px !important;
}
/* Shop 左栏在 style.css:4143 被写成 height:fit-content（只有内容那么高），
   轨道线跟着到不了底。Games 那边没有这条，两边统一放开。 */
.theme-purple #page-shop .shop-category-menu {
	height: auto !important;
	max-height: none !important;
}
/* 页面标题前的图标：原来是 images/game.svg / shop.svg 两张图片，
   跟顶栏、widget 头各是一套，三处粗细风格都不一样。现在统一成 FA light。
   尺寸跟标题（20px）配，略小一点，跟参考界面一致。 */
.theme-purple :is(#page-game, #page-shop) .menu-header .menu-header-icon {
	margin-right: 10px;
	font-size: 18px;
	line-height: 1;
	color: var(--purple-text);
}
/* 标题自带 pl-3，容器已经给了 48，去掉它免得叠加成 64 */
.theme-purple :is(#page-game, #page-shop) > .d-flex.flex-column.flex-shrink-0 .menu-header {
	padding-left: 0 !important;
}
/* 轨道线挂在包裹层（span.dropdown）上并撑满整列——参考界面那条线一直通到
   页面底部，不是只有分类项那么高。各分类项用 margin-left:-2px 把自己的
   2px 边框正好压在这条线上，激活项只是把压住的那一段改成主题色。
   （之前是每项各画一段线拼起来，列表多高线就多高，到不了底。） */
.theme-purple :is(#page-game, #page-shop) > .d-flex.flex-column.flex-shrink-0 > .dropdown {
	display: block;
	flex: 1 1 auto;
	margin-left: 24px;
	border-left: 2px solid var(--purple-border);
}
.theme-purple :is(#page-game, #page-shop) > .d-flex.flex-column.flex-shrink-0 .dropdown-item {
	/* 圆角和上下外边距都要清掉：基线的 border-radius:8px 会让压上去的那段带弧，
	   margin:4px 0 会让激活段跟线错位。高度改用 padding 补回来。 */
	margin: 0 0 0 -2px !important;
	padding: 9px 14px !important;
	border-radius: 0 !important;
	border-left: 2px solid transparent !important;
}
.theme-purple :is(#page-game, #page-shop) > .d-flex.flex-column.flex-shrink-0 .dropdown-item:hover {
	border-left-color: var(--purple-text-muted) !important;
}
/* 子分类（Shop 的二级分组，外层套了 .pl-4）：自己画一段缩进的线，读成子树。
   必须排在 .dropdown-item-active 之前，否则会把二级分类激活态的主题色盖掉 */
.theme-purple :is(#page-game, #page-shop) > .d-flex.flex-column.flex-shrink-0 .pl-4 .dropdown-item {
	margin-left: 0 !important;
	border-left-color: var(--purple-border) !important;
}
.theme-purple :is(#page-game, #page-shop) > .d-flex.flex-column.flex-shrink-0 .dropdown-item.dropdown-item-active {
	border-left-color: var(--purple-accent) !important;
}

/* 分类栏标题（GAMES）：参考界面里是普通小标题，不加粗到 700 */
.theme-purple .game-category-menu .header-label {
	font-family: var(--purple-font);
	font-weight: 500;
	letter-spacing: 0.04em;
}

/* ============================================================
   15. 会员面板 —— 参考界面的信息编排
   ============================================================
   排布照搬参考界面：头像+名字+等级进度 → 分隔线 → Time left / My passes
   → Rate → 分隔线 → 余额 + Top up → 硬币/Bonus → Offer 轮播。
   数据全部沿用我们原有的绑定，没有新增字段：
     等级        vueHome.memberCurrentGroup / vueHome.memberGroup.length
     Time left   当前生效 offer 的 remaining（time_type 为 offer 或 balance）
     My passes   vueAvailableOffers.items.length（参考界面的 passes 即我们的 offer）
     Rate        memberInfo.price_per_hour
     余额        memberInfo.member_balance_realtime
     硬币/Bonus  我们特有，参考界面没有这两项，放在余额下方保留
   参考界面的 Favorites 海报行没有做——收藏数据在 theGame/thePCStatus 上，
   两者都不是 PetiteVue.reactive 对象，绑上去收藏变更后不会重渲；要做成
   响应式得改 core/js（功能层），不在本次范围。 */

/* 分隔线是个空 div，三件事都得写，少一件就看不见：
   width/align-self —— 父容器是 d-flex flex-column align-items-start，
                       空元素会收缩成 0 宽（之前一直是这个情况，线从来没显示过）
   flex-shrink:0   —— 侧栏内容超高时 flex 会把 1px 的项压成 0 高 */
.theme-purple .purple-divider {
	width: 100%;
	align-self: stretch;
	flex-shrink: 0;
	height: 1px;
	background: var(--purple-border);
	margin: var(--purple-sp-4) 0;
}

/* --- 等级进度 --- */
.theme-purple .purple-level { margin-top: var(--purple-sp-2); }
.theme-purple .purple-level-head { margin-bottom: 6px; }
/* 等级名用强调文字色（主色向白提亮）。
   曾按 v4.3.0 参考图改成主色 55% 透明度的暗紫，换成洋红主色后在深色面板上几乎看不清，
   文字的可读性优先，暗色只留给进度条这类非文字的大块元素 */
.theme-purple .purple-level-name {
	color: var(--purple-accent-text);
	font-size: 13px;
	font-weight: 500;
}
.theme-purple .purple-level-pct {
	color: var(--purple-text-muted);
	font-size: 12px;
}
.theme-purple .purple-level-bar {
	height: 3px;
	border-radius: var(--purple-r-pill);
	background: var(--purple-elevated);
	overflow: hidden;
}
/* 参考图进度条已完成段是暗紫 #330F8D（= --purple-accent-dim），不是亮色渐变。
   大面积铺最亮的主色在广色域屏上会明显发艳 */
.theme-purple .purple-level-fill {
	height: 100%;
	border-radius: var(--purple-r-pill);
	background: var(--purple-accent-dim);
}

/* --- Time left / My passes --- */
.theme-purple .purple-session { width: 100%; }
.theme-purple .purple-label {
	color: var(--purple-text-muted);
	font-size: 12px;
	line-height: 16px;
	margin-bottom: 2px;
}
/* 关键数字用纯白——参考界面把白色留给时间和金额，正文是 #919FBF 的蓝灰 */
.theme-purple .purple-time {
	color: var(--purple-text-strong);
	font-size: 28px;
	font-weight: 500;
	line-height: 34px;
	letter-spacing: 0.01em;
}
.theme-purple .purple-passes {
	color: var(--purple-text);
	font-size: 28px;
	font-weight: 500;
	line-height: 34px;
}

/* --- Rate 行 --- */
.theme-purple .user-price-info {
	color: var(--purple-text-muted);
	font-size: 12px;
}

/* --- 余额 + Top up --- */
.theme-purple .user-stat-wallet .member_balance_realtime {
	color: var(--purple-text-strong);
	font-size: 17px;
	font-weight: 500;
	margin-left: var(--purple-sp-2);
}
/* Top up 在参考界面是实心洋红渐变按钮，不是一个加号加一行字 */
.theme-purple .btn-topup {
	background: var(--purple-gradient-primary) !important;
	border-radius: var(--purple-r-btn) !important;
	padding: 7px 14px !important;
	gap: 6px !important;
}
.theme-purple .btn-topup:hover { opacity: 0.88; }
.theme-purple .btn-topup span {
	color: var(--purple-text-strong) !important;
	background: transparent !important;
	border: none !important;
}

/* --- 硬币 / Bonus 小行 --- */
.theme-purple .purple-mini-stats {
	gap: var(--purple-sp-4);
	margin-top: var(--purple-sp-3);
	color: var(--purple-text);
	font-size: 13px;
}
.theme-purple .purple-mini-stats .user-stat-item { gap: 6px; }

/* --- 面板整体 --- */
.theme-purple .user-info-card {
	background: var(--purple-panel);
	border-radius: var(--purple-r-card);
	padding: var(--purple-sp-5) var(--purple-sp-4);
}
.theme-purple .user-name {
	color: var(--purple-text-strong);
	font-size: 15px;
	font-weight: 500;
	margin-bottom: 0;
}

/* ============================================================
   16. purple-* 组件字体
   ============================================================
   这些类原名 blue-*，是 blue 主题登录页自带的组件（主卡片、快捷入口、
   行式入口等），P4 已统一改名为 purple-*。style.css 里它们各自硬编码了
   font-family: "Rubik"，这里统一收敛到 token。
   （P2 时期那条针对 [class^="blue-"] 的临时兼容规则已随改名一并删除） */
.theme-purple [class^="purple-"],
.theme-purple [class*=" purple-"] {
	font-family: var(--purple-font) !important;
}
/* ⚠️ 例外：元素同时是 Font Awesome 图标时不能换字体，否则字形取不到、变成豆腐块。
   踩过一次——<i class="fa fa-solid fa-key purple-segment-icon"> 被上面那条命中，
   字体换成 Poppins，钥匙就成了 ▯。给 purple- 前缀的类名配 fa 图标时都会中招。 */
.theme-purple [class^="purple-"].fa,
.theme-purple [class*=" purple-"].fa {
	font-family: "Font Awesome 6 Pro" !important;
}

/* ============================================================
   17. 登录页 —— 参考界面的手风琴入口列
   ============================================================
   参考界面：屏幕左上角一列等宽卡片自上而下堆叠——机器号卡片，
   然后每个登录入口各占一张卡（图标方块 + 文字一行），点谁谁就地
   向下展开表单，其余的保持一行收起。管理员入口不在卡片列里，
   是列下方一行居中的下划线文字。
   我们把原来的“整卡切换 + 圆形快捷图标”改成同一套手风琴，
   功能一个没动：还是 vueLoginMode.active_tab 那套 tab 值。 */

/* 列靠左靠上（参考界面贴着屏幕左上角，不是垂直居中）。
   入口全开时这一列会比较高，留 overflow 兜底，免得矮屏被裁掉。 */

.theme-purple #page_login .loginDiv > section {
	justify-content: flex-start !important;
	align-items: flex-start !important;
	/* 垂直位置：参考界面原生是 638 高，面板占了大半屏，钉在左上角看着刚好。
	   但网吧实机是 1325 高这种大屏，同样钉 28px 就变成“浮在最上面、下面空一大截”。
	   这里用 max()：矮屏保持 28px 贴顶（不然会被截），屏越高越向垂直居中靠。
	   760 是面板实测高度 733 + 上下各留一点。不用 align-items:center：
	   面板比视口还高时 center 会把顶部截掉且滑不到。 */
	padding: max(28px, calc((100vh - 760px) / 2)) 0 28px 28px;
	overflow-y: auto;
}
.theme-purple #page_login .purple-card-container {
	/* 宽度按参考界面的【占屏比】算，不是照搬它的像素值。
	   参考图那块面板 245px / 图宽 1090 = 0.225；原先写死 320px，在 2000 宽的屏上
	   只有 0.16，比参考窄了四成——内容挤在窄柱里只能往下堆，矮屏时底部的 Admin
	   就被顶出视口了，而右边还空着 1600 多 px。
	   下限 360 是给多语言长标签留的（Username/Password 的俄语、西语译文更长）；
	   上限 480 防止超宽屏上这一柱宽得失衡。 */
	/* 上限压到 400：登录表单不该跟着屏幕无限变宽。
	   之前按「参考图左栏占屏 0.225」做成纯比例，2360 宽的屏上就涨到 543px，
	   一个登录框宽成这样很怪。那 0.225 是在 1090 宽的图上量的，而那张图按字号看
	   明显是缩小过的截图，它的 245px 更可能是固定宽度而不是比例。
	   下限 300 给窄窗口，23vw 只在 1300~1750 这段起作用，再宽就钉在 400。 */
	width: clamp(280px, 21vw, 360px);
	max-width: 360px;
	padding: 0;
	gap: 8px;
}

/* --- 机器号卡片 --- */
.theme-purple .purple-pc-card {
	background: var(--purple-surface);
	border-radius: var(--purple-r-card);
	padding: 22px var(--purple-sp-5);
	text-align: center;
}
/* .pc_name 原本是绝对定位在屏幕左上角（top:50px;left:25px），
   收进卡片列之后要改回常规流 */
.theme-purple .purple-pc-card .pc_name {
	position: static !important;
	top: auto !important;
	left: auto !important;
	padding: 0 !important;
	/* 参考界面这个号码是绿的（实测 #049550），语义是「这台机可用」，
	   所以用 --purple-success 而不是普通文字色。 */
	color: var(--purple-success) !important;
	font-family: var(--purple-font);
	line-height: 1.1;
	text-align: center !important;
}

/* --- 手风琴列 --- */
.theme-purple .purple-accordion {
	display: flex;
	flex-direction: column;
	/* 参考界面这几行几乎是贴着的（7–9px），视觉上是一根连续的柱，
	   不是四张分开的卡。原来 12px 散成了四块。 */
	gap: 8px;
	width: 100%;
}

/* 单个入口：一张独立卡片，收起时只有 head，展开时下面接 body */
.theme-purple .purple-acc-section {
	background: var(--purple-surface);
	border: none;
	border-radius: var(--purple-r-card);
	/* 不能 overflow:hidden——Amount/Minutes 的预设下拉要从卡片里溢出来 */
	overflow: visible;
}

/* 入口行本体 */
.theme-purple .purple-acc-head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	padding: 0 16px;
}
/* 可点区域：整行左半边（右边的副按钮不在里面，天然不会被冒泡带上） */
.theme-purple .purple-acc-head-main {
	flex: 1 1 auto;
	display: flex;
	align-items: center;
	gap: 12px;
	min-height: 48px;
	cursor: pointer;
	min-width: 0;
}
.theme-purple .purple-acc-head-main:hover { opacity: 0.85; }
.theme-purple .purple-acc-head-main:focus {
	outline: none;
}
.theme-purple .purple-acc-head-main:focus .purple-acc-title {
	color: var(--purple-text-strong) !important;
	text-decoration: underline;
}

/* 图标方块：参考界面是每个入口一个专属配色的圆角方片 */
/* 参考界面的图标是 22x22，我们用 24 ——图标本身是现成的 SVG 素材，
   缩到 22 里面的小细节会糊，24 刚好。 */
.theme-purple .purple-acc-icon {
	width: 24px;
	height: 24px;
	flex-shrink: 0;
	display: inline-flex;
	align-items: center;
	justify-content: center;
}
.theme-purple .purple-acc-icon img {
	width: 24px;
	height: 24px;
	display: block;
}

.theme-purple .purple-acc-title {
	margin: 0 !important;
	color: var(--purple-text-oncard) !important;
	font-size: 14px !important;
	font-weight: 500 !important;
	line-height: 1.2;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
.theme-purple .purple-acc-section.is-open .purple-acc-title {
	color: var(--purple-text-strong) !important;
}

/* 行右侧的副按钮（注册）：参考界面是个浅色小药丸 */
.theme-purple .purple-acc-action {
	flex-shrink: 0;
	display: inline-block;
	padding: 7px 12px;
	background: var(--purple-elevated);
	border-radius: var(--purple-r-chip);
	color: var(--purple-text-oncard) !important;
	font-size: 12px;
	font-weight: 500;
	text-decoration: none !important;
	line-height: 1.1;
	cursor: pointer;
}
.theme-purple .purple-acc-action:hover {
	color: var(--purple-text-strong) !important;
}

/* 展开区：沿用 .purple-card-body 那套表单样式，只改内边距
   （head 已经给了上边距，body 顶部不再重复留白） */
.theme-purple .purple-acc-body.purple-card-body {
	padding: 0 14px 14px 14px !important;
}

/* “Forgot password?” 参考界面是靠右的下划线小字 */
.theme-purple .purple-acc-body .reset-password-link {
	text-align: right !important;
}
.theme-purple .purple-acc-body .reset-password-link a {
	text-decoration: underline !important;
}

/* 输入框配色：同一张表单里两个框颜色不一样，是两条 !important 规则打架的结果——
   未聚焦时命中 base.css 的 .theme-purple input[type="password"]（0,2,1）拿到
   --purple-elevated，一聚焦又被 style.css 的 .purple-card-body .form-control:focus
   （0,3,0）拉成 #1F2430。这里在登录卡范围内把两种状态统一成主题的输入框色
   （--purple-elevated，跟商城/弹窗里的输入框一致），聚焦只改描边。
   权重：.theme-purple .purple-acc-body input[type="password"] 是 (0,3,1)，
   带 :focus 是 (0,4,1)，两条都压得过上面那两个。 */
.theme-purple .purple-acc-body .form-control,
.theme-purple .purple-acc-body .login-input,
.theme-purple .purple-acc-body input[type="text"],
.theme-purple .purple-acc-body input[type="tel"],
.theme-purple .purple-acc-body input[type="password"],
.theme-purple .purple-acc-body input[type="number"],
.theme-purple .purple-acc-body input[type="email"],
.theme-purple .purple-acc-body select,
.theme-purple .purple-acc-body textarea {
	background: var(--purple-elevated) !important;
	border: 1px solid transparent !important;
}
.theme-purple .purple-acc-body .form-control:focus,
.theme-purple .purple-acc-body .login-input:focus,
.theme-purple .purple-acc-body input[type="text"]:focus,
.theme-purple .purple-acc-body input[type="tel"]:focus,
.theme-purple .purple-acc-body input[type="password"]:focus,
.theme-purple .purple-acc-body input[type="number"]:focus,
.theme-purple .purple-acc-body input[type="email"]:focus,
.theme-purple .purple-acc-body select:focus,
.theme-purple .purple-acc-body textarea:focus {
	background: var(--purple-elevated) !important;
	border-color: var(--purple-accent) !important;
}

/* --- 登录表单控件收紧 ---
   参考界面的输入框只有 24px、按钮 25px，标签贴着框上沿。
   我们没敲到那么矮：网吧客户端不少是触摸屏，24px 的点击目标按不准。
   32/36 是折中：比原来的 46/44 紧凑很多，又还能指头点。
   权重：基线 style.css 的 .purple-card-body .form-control 是 (0,2,0)!important，
   这里多一个 .theme-purple 是 (0,3,0)!important，压得过。 */
.theme-purple .purple-acc-body .form-control,
.theme-purple .purple-acc-body .login-input {
	height: 32px !important;
	font-size: 13px !important;
}
.theme-purple .purple-acc-body .form-label {
	font-size: 11px !important;
	margin-bottom: 3px !important;
}
.theme-purple .purple-acc-body .form-group {
	margin-bottom: 8px !important;
}
.theme-purple .purple-acc-body .purple-btn-primary,
.theme-purple .purple-acc-body .btn-primary {
	height: 36px !important;
	padding-top: 0 !important;
	padding-bottom: 0 !important;
	font-size: 13px !important;
	/* 基线这个按钮的 line-height 是 44px（配当时 44px 的按钮高）。
	   高度改成 36 后 line-height 没跟着改，44 的行盒装进 36 的框里，
	   文字就偏下 3.5px。改用 flex 居中，以后再改高度也不用动这里。 */
	display: inline-flex !important;
	align-items: center !important;
	justify-content: center !important;
	line-height: 1 !important;
}
/* 机器号卡片也跟着收一点，否则它一个就占 99px */
.theme-purple .purple-pc-card {
	padding: 14px var(--purple-sp-4) !important;
}

/* --- 管理员入口：卡片列外面的一行居中下划线文字 --- */
.theme-purple .purple-tech-user {
	display: flex;
	justify-content: center;
	padding: 6px 0 2px 0;
}
.theme-purple .purple-tech-user-link {
	color: var(--purple-text-strong) !important;
	font-size: 13px;
	font-weight: 500;
	text-decoration: underline !important;
	cursor: pointer;
}
.theme-purple .purple-tech-user-link:hover {
	color: var(--purple-accent-text) !important;
}


/* ============================================================
   19. 顶栏机器号 + 侧栏底部工具条
   ============================================================
   依据 v94.2 真机截图补的两块，用的都是我们已有的数据和功能：
     机器号        vueGlobal.pcName（真机那条还带绿点+分区名，客户端拿不到
                   pc_group_name，没有的不做）
     语言          theSystemMenu.open_language_modal()
     反馈          vueGlobal.modals.feedback
     聊天          window.theChat.open()
     版本号        vueGlobal.versionDate
   这三个入口原来散在顶栏和设置弹窗里，这里按参考界面的位置补一份入口，
   不改任何功能。 */

.theme-purple .header-pcname {
	color: var(--purple-text);
	font-size: 13px;
}

.theme-purple .purple-sidebar-footer {
	/* 侧栏是 flex column + overflow-y:auto，内容（会员卡+促销+新闻）
	   本来就超高，margin-top:auto 没有空白可吸收，会被顶出视口。
	   参考界面这条是常驻可见的，所以在滚动容器内吸底；
	   sticky 需要不透明背景，否则内容会从它下面透出来。
	   margin-top:auto 保留：内容短时仍然贴底 */
	margin-top: auto;
	position: sticky;
	bottom: 0;
	z-index: 2;
	background: var(--purple-ground);
	padding: var(--purple-sp-3) var(--purple-sp-4) var(--purple-sp-4);
	border-top: 1px solid var(--purple-border);
}
.theme-purple .purple-footer-row {
	gap: var(--purple-sp-2);
}
/* 参考界面底栏分两档：上面这行（语言 / 反馈 / 聊天）是正文色，
   下面版本号那行更暗一档。原来两行同色，看着是一片糊的。 */
.theme-purple .purple-footer-lang,
.theme-purple .purple-footer-icon {
	color: var(--purple-text);
	font-size: 12px;
	text-decoration: none;
}
.theme-purple .purple-footer-lang:hover,
.theme-purple .purple-footer-icon:hover {
	color: var(--purple-text);
	text-decoration: none;
}
/* 聊天按钮：参考界面里是个实心深底胶囊，不是洋红主按钮——
   洋红留给 Top up 那种主操作 */
.theme-purple .purple-chat-btn {
	background: var(--purple-elevated);
	color: var(--purple-text) !important;
	border-radius: var(--purple-r-btn);
	padding: 6px 12px;
	font-size: 12px;
	text-decoration: none !important;
	white-space: nowrap;
}
.theme-purple .purple-chat-btn:hover { opacity: 0.85; }
.theme-purple .purple-footer-version {
	margin-top: var(--purple-sp-2);
	color: var(--purple-text-muted);
	font-size: 11px;
}

/* ============================================================
   20. 顶栏排布与侧栏面板 —— 对齐 v94.2 真机
   ============================================================
   真机顶栏的排布是：logo → 紧邻的图标导航（图标在上、文字在下）→ 大片留白
   → 搜索框（靠右）→ 机器号/状态 → 图标组。
   blue 基线是 logo 绝对定位 + nav margin-left:305px + search margin-left:191px，
   结果搜索框悬在正中间、nav 和 logo 之间空一大块。 */

/* 搜索框靠右，紧邻右侧状态区。
   .header-area 是 flex + justify-content-start，margin-left:auto 会把它推到
   内容区右端；内容区右边界由 .header-area 自己的 padding-right 决定（见
   layout.htm 里那个内联值，右侧状态区是绝对定位的，不占 flex 位置，必须手工留） */
.theme-purple .header-search {
	margin-left: auto !important;
	margin-right: 0 !important;
}

/* 右侧状态区是绝对定位的、不占 flex 位置，所以要在这里手工留出它的宽度，
   搜索框（margin-left:auto）才停在正确的位置。
   432 = 400（侧栏宽）+ 32（内容区到侧栏的间距），这样搜索框的右边缘正好落在
   Games / Shop / Offers 三页内容区的右边缘上。
   原来是写在 layout.htm 里的内联 450px，那个值让搜索框停在 1550，
   比内容区的 1568 靠左 18px，三页一致地错开。
   顶栏加了 Lucky Spin 一格（layout.htm，音量图标前面）后右侧状态区宽到 420px，曾把这里
   调成 464、让搜索框右边缘错开内容区 32px；后来把状态区右边多余的 35px 收掉
   （见 .header-right-info 那几条），就又回到 432、重新对齐了。
   注意：搜索框右边缘是被这个 padding 钉住的，缩搜索框宽度只会让它的左边缘往里收，让不出位置。 */
.theme-purple .purple-header-area {
	padding-right: 432px !important;
}

/* 导航项：真机是图标在上、文字在下 */
.theme-purple .menu-icon-link {
	display: inline-flex;
	flex-direction: column;
	align-items: center;
	gap: 2px;
	padding: 4px 10px;
	text-decoration: none !important;
}
.theme-purple .menu-icon-label {
	font-size: 11px;
	line-height: 13px;
	color: var(--purple-text-muted);
}
.theme-purple .menu-icon-link.active .menu-icon-label {
	color: var(--purple-accent-text);
}

/* 侧栏：真机是一整块实底面板通到底边。实底画在外层 #purple-sidebar 上（第 39 节），
   .member-sidebar 本身背景透明，这里只把圆角去掉，让它和外层贴合 */
.theme-purple .member-sidebar {
	border-radius: 0 !important;
}
/* 页脚钉在屏幕右下角，宽度跟 #purple-sidebar 一致（400px，right:0）。
   用 fixed：侧栏内容区是滚动容器，页脚要始终停在视口底，不跟着内容滚走。
   #purple-sidebar 链路上没有 transform/filter/will-change，fixed 不会被困住。 */
.theme-purple .purple-sidebar-footer {
	position: fixed !important;
	right: 0;
	bottom: 0;
	width: 400px;
	z-index: 3;
	background: var(--purple-surface);   /* 与侧栏同色，参考图里底栏不单独提亮 */
}

/* --- 20.1 导航项形态：对齐真机 ---
   blue 基线把导航做成一个深色胶囊容器（.header-menu 有 rgba 底 + 50px 圆角），
   激活项还带洋红边框 + 外发光。真机两样都没有：导航直接坐在顶栏上，
   激活项只是图标和文字变洋红。
   权重说明：基线那几条是 .header-section .header-area .header-menu... 的
   (0,5,0)，前面加 .theme-purple 才压得过。 */
.theme-purple .header-section .header-area .header-menu {
	background: transparent !important;
	/* P2 第 3.1 节把 .header-menu 一起归进了「弹窗层」转不透明 + 描边，
	   这里背景改透明后那条描边还留着，顶栏会出现一圈框。参考界面没有。 */
	border: none !important;
	border-radius: 0 !important;
	height: auto !important;
	padding: 0 !important;
	gap: 10px !important;
}
.theme-purple .header-section .header-area .header-menu .menu-icon-link {
	height: auto !important;
	min-width: 0 !important;
	padding: 2px 10px !important;
	border: none !important;
}
.theme-purple .header-section .header-area .header-menu .menu-icon-link.active {
	background: transparent !important;
	border: none !important;
	box-shadow: none !important;
}
/* 悬停也不要底片：基线在 :hover 上挂了 rgba(255,255,255,0.05) + 50px 圆角，
   鼠标划过会冒出一个圆形灰底。参考界面的导航项悬停只是图标/文字变色，没有底。
   这里只压背景，图标变浅那条（style.css 的 :not(.active):hover .menu-icon）留着当反馈。
   权重：基线那条是 (0,5,0)，加 .theme-purple 成 (0,6,0) 才压得过。 */
.theme-purple .header-section .header-area .header-menu .menu-icon-link:hover {
	background: transparent !important;
}
/* 激活项的图标：基线写死成白色，真机是洋红 */
.theme-purple .header-section .header-area .header-menu.text-white .menu-icon.header-menu-active {
	color: var(--purple-accent) !important;
}

/* ============================================================
   21. 卡片角标 / 头像 / 左栏标题 —— 对齐 v94.2 真机
   ============================================================ */

/* --- 21.1 license 角标移到左上 ---
   真机是收藏星右上、平台标识左上，两边分开；blue 基线把两个挤在右上同一个容器里 */
.theme-purple .game-item .game-image .badge-container-left,
.theme-purple :is(#page-game, #page-shop, #page-rank, #page-event, #page-home, #page-account, #purple-sidebar) .game-item .badge-container-left {
	left: 0 !important;
	right: auto !important;
	border-radius: 0 0 6px 0 !important;
	/* 基类的 padding/height 没落到这个新容器上（实测 padding 为 0、宽度塌成 9px），
	   这里显式补齐，比去追查哪条选择器没命中更稳 */
	padding: 0 8px !important;
	height: 28px !important;
	background: var(--purple-surface) !important;
	display: flex !important;
	align-items: center !important;
}

/* --- 21.2 头像：圆角方形，去掉进度环 ---
   真机的头像是圆角方形 + 左下角一枚徽标，没有圆环。
   我们那圈进度环表达的是等级进度，而 P3b 已经在名字下面加了
   "Level N + 百分比 + 线性条"，环是重复信息，这里隐藏掉。
   ⚠️ 只是 CSS 隐藏，member-sidebar.htm 里的 <svg class="progress-ring">
      结构原样保留，想要环回来把这条删掉即可。 */
.theme-purple .user-avatar .progress-ring {
	display: none !important;
}
.theme-purple .user-avatar .cafe_info_member_logo {
	border-radius: var(--purple-r-card) !important;
	width: 100% !important;
	height: 100% !important;
	object-fit: cover;
}
.theme-purple .user-avatar {
	border-radius: var(--purple-r-card);
	overflow: visible;
}
/* 等级数字徽标挪到左下角，对应真机头像左下那枚 */
.theme-purple .user-avatar .user-level {
	transform: none !important;   /* 基线带了 translateX(-12px)，会把徽标推出头像 */
	top: auto !important;
	bottom: -4px !important;
	left: -4px !important;
	right: auto !important;
	background: var(--purple-accent-from) !important;   /* 参考图角标是深一档的紫（实测 #35089C） */
	color: var(--purple-text-strong) !important;
	border-radius: var(--purple-r-chip) !important;
}

/* --- 21.3 左栏标题轻量化 ---
   真机是一行轻量小标题；我们带了 Bootstrap 的 .text-white + .font-weight-bold，
   两个都是 !important，必须同等重量才压得过 */
.theme-purple .game-category-menu .header-label,
.theme-purple .game-category-menu .header-label.font-weight-bold,
.theme-purple .shop-category-menu .header-label,
.theme-purple .shop-category-menu .header-label.font-weight-bold {
	color: var(--purple-text) !important;
	font-weight: 500 !important;
	/* 13px 比旁边分类项（14px）还小，读起来像个小标签不像页标题；
	   参考界面里它明显大于分类项。字距也跟着收紧，字大了不需要那么疏 */
	font-size: 20px !important;
	letter-spacing: 0.02em !important;
}

/* ============================================================
   22. 顶栏图标尺寸统一 + 侧栏底栏收紧
   ============================================================ */

/* --- 22.1 导航图标 ---
   参考界面用的就是 Font Awesome light（实测它的 Games / Goodies / Passes / News
   分别是 gamepad-modern / burger-soda / ticket / newspaper）。我们也改成 FA，
   同一个概念在顶栏/widget 头/页面标题三处用同一个图标。
   Shop 没有照抄 burger-soda：那是 Senet 叫 Goodies、专做餐饮才用汉堡，
   我们叫 Shop、卖的是通用商品，用同一套里的 basket-shopping。

   改成字体图标后，原来那套「每个 SVG 各自算墨迹占比、再用 transform
   缩到 24px」的补偿（33/25/29/29/32 + scale 0.998/0.759/0.873/0.873/0.970）
   全部不需要了——同一套字体的字形视觉尺寸本来就是均匀的，
   一个 font-size 就够，文字基线也不会再散。

   ⚠️ 类名里必须带 fa（这里是 fal），否则会被
   .theme-purple [class*=" purple-"] 那条 font-family !important 抢成豆腐块；
   这里的 <i> 没带 purple- 类名，暂时不会中招，但别随手加。 */
/* 基线那条 .header-section .header-area .header-menu.text-white .menu-icon
   是 (0,5,0)!important，不带 !important 压不过（实测被压回 20x20） */
.theme-purple .header-section .header-menu .menu-icon-link .menu-icon {
	display: block !important;
	width: 33px !important;
	height: 24px !important;
	font-size: 22px !important;
	line-height: 24px !important;
	text-align: center;
}

/* 激活态：由父级 .active 驱动（petite-vue 给 SVG 写 className 会写坏，
   当初就是为此把绑定移到父级的；现在是 <i> 了，继续沿用这个写法） */
.theme-purple .header-menu .menu-icon-link .menu-icon { color: var(--purple-text-muted); }
.theme-purple .header-menu .menu-icon-link.active .menu-icon { color: var(--purple-accent) !important; }

/* --- 22.2 右侧图标 ---
   实测框是 18/18/18/18/20，最后一个明显大一圈；墨迹 15x13 / 15x15 /
   15x10 / 14x14 / 17x16。先把框统一到 18，去掉那个 20 的离群值。 */
.theme-purple .header-right-info svg {
	width: 18px !important;
	height: 18px !important;
}
/* 文字与图标基线对齐，字号统一 */
.theme-purple .header-right-info {
	font-size: 13px;
}

/* --- 22.3 侧栏底栏收紧 ---
   真机那条比我们紧凑：字更小、上下留白更少。同时把底部空白压下来。 */
.theme-purple .purple-sidebar-footer {
	padding: 10px var(--purple-sp-4) 10px;
}

/* 语言下拉展开时把整条页脚抬到下拉层。
   页脚是 position:fixed + z-index:3，本身就是一个层叠上下文，里面那个
   .purple-lang-menu 写多大的 z-index 都只在页脚内部排序，对外仍然只有 3。
   而侧栏里 .rank-header / .section-tabs 是 20、.carousel-indicators 是 15、
   .news-qr 是 999 —— 全都压在下拉上面，于是弹出来的语言列会被
   「ACTUALITÉS / RANG」那行字穿透显示。
   只在展开时抬，不常驻：常驻的话页脚会盖住侧栏里所有 z-index < 1000 的东西，
   影响面比这个 bug 本身还大。
   1000 是 Bootstrap 的 dropdown 层级，低于 modal 的 1050，所以弹窗仍然盖得住页脚。 */
.theme-purple .purple-sidebar-footer.is-lang-open {
	z-index: 1000;
}
.theme-purple .purple-footer-lang,
.theme-purple .purple-footer-icon {
	font-size: 11px;
}

.theme-purple .purple-chat-btn {
	padding: 5px 10px;
	font-size: 11px;
}
.theme-purple .purple-footer-version {
	margin-top: 4px;
	color: var(--purple-text-muted);
	font-size: 10px;
}
/* 规则入口：参考界面是条下划线链接，跟版本号同一档暗色。
   display 不写 !important —— v-show 要靠内联 display:none 生效。 */
.theme-purple .purple-footer-rules {
	color: var(--purple-text-muted);
	font-size: 10px;
	text-decoration: underline;
}
.theme-purple .purple-footer-rules:hover {
	color: var(--purple-text);
	text-decoration: underline;
}

/* ============================================================
   23. 顶栏右侧图标做成方片 + 去掉底栏图标的边线
   ============================================================
   真机 Senet 顶栏右侧是「机器号 + 分区」后面跟 4 个圆角方片按钮
   （购物车/提示/锁屏/退出），图标坐在有底色的方片里，不是裸图标。
   我们这一排是 PC号 / 时钟 / 音量 / 聊天 / 余额 / 积分 / 头像，
   其中音量和聊天是按钮，做成方片；其余是文字读数，保持原样。 */
.theme-purple .header-right-info > div > a.lang:not(.dropdown-item) {
	width: 30px;
	height: 30px;
	border-radius: var(--purple-r-btn);
	background: var(--purple-elevated);
	color: var(--purple-text);
	flex-shrink: 0;
}
.theme-purple .header-right-info > div > a.lang:not(.dropdown-item):hover {
	opacity: 0.85;
}
/* 方片自己有尺寸了，外层不用再撑宽 */
.theme-purple .header-right-info .header-sound {
	width: auto !important;
}

/* --- 23.1 侧栏底栏的反馈入口 ---
   之前给它加了一圈 1px 边框做成圆环，真机没有这条线：平时只有一个描边气泡图标，
   鼠标移上去才出现一块圆角底（参考截图里那个方框是 hover 态，光标正压在上面）。
   ⚠️ 这个类在上面 §21 / §22.3 还各写过一次，三处会互相覆盖（最后一处赢）。
      尺寸相关的只留这一处，别再往前面加。 */
.theme-purple .purple-footer-icon {
	border: none !important;
	width: 26px;
	height: 26px;
	border-radius: var(--purple-r-chip);
	flex-shrink: 0;
}
.theme-purple .purple-footer-icon svg {
	width: 18px;
	height: 18px;
}
.theme-purple .purple-footer-icon:hover {
	background: var(--purple-elevated);
	color: var(--purple-text-strong);
}

/* --- 23.2 侧栏订单/收据入口去掉圆形底片 ---
   它的内联样式带 background: rgba(255,255,255,0.08) + border-radius:50%，
   虽然不是 border，但那圈浅色圆底在面板上看就是一条边线。真机没有。
   内联样式要用 !important 才压得过。 */
.theme-purple .member-sidebar a[href*="checklist"] {
	background: transparent !important;
	border-radius: 0 !important;
	color: var(--purple-text) !important;
}
.theme-purple .member-sidebar a[href*="checklist"]:hover {
	color: var(--purple-text-strong) !important;
}

/* --- 23.3 顶栏右侧去掉余额与积分读数 ---
   真机 Senet 顶栏右侧只有「机器号 + 分区」和几个方片按钮，没有金额读数；
   我们这两项（余额 / 积分）在右侧会员面板里已经各显示了一遍，顶栏是重复。
   用 display:none 而不是删 DOM：只在 purple 作用域内生效，blue/icafemenu
   不受影响，想恢复删掉这一条即可，绑定和数据都还在。 */
.theme-purple .header-right-info .header-balance {
	display: none !important;
}

/* --- 23.4 顶栏去掉时钟 ---
   真机 Senet 顶栏右侧没有时钟，只有机器号+分区和方片按钮。
   同样用 display:none，只在 purple 作用域内生效，想恢复删掉这条即可。 */
.theme-purple .header-right-info .header-time {
	display: none !important;
}

/* ============================================================
   24. Home 页 widget 仪表盘
   ============================================================
   按 Senet Shell 参考图重排：上面一行 Games 横滑卡片，下面并排
   Shop / Offers / News（+ 我们独有的 Rank），右侧会员面板。
   命名用我们自己的，不跟参考图的 Goodies/Passes 走。 */

/* 内边距不能加在这一层：它会连右侧会员面板一起往里缩，Home 的侧栏就比
   Games/Shop 矮 32px、左偏 16px、顶部低 16px。留白挪到左边的 widget 列上，
   侧栏保持贴边贴顶，三个页面的侧栏位置和高度就一致了。
   gap 同样归零——Games/Shop 的侧栏是紧贴内容区的，没有缝。 */
.theme-purple .purple-home {
	gap: 0;
	padding: 0;
	overflow: hidden;
}
.theme-purple .purple-home-widgets {
	gap: var(--purple-sp-4);
	padding: var(--purple-sp-4);
	min-width: 0;          /* 允许 flex 子项收缩，否则横滑行会把父容器撑破 */
}
.theme-purple .purple-widget-cols {
	gap: var(--purple-sp-4);
	min-height: 0;
}

/* --- widget 外框 --- */
.theme-purple .purple-widget {
	background: var(--purple-surface);
	border-radius: var(--purple-r-card);
	padding: var(--purple-sp-4);
	display: flex;
	flex-direction: column;
	min-width: 0;
	min-height: 0;
}
.theme-purple .purple-widget-head {
	color: var(--purple-text);
	font-family: var(--purple-font);
	font-size: 14px;
	font-weight: 500;
	margin-bottom: var(--purple-sp-3);
	flex-shrink: 0;
}
.theme-purple .purple-widget-body {
	flex: 1 1 auto;
	min-height: 0;
	overflow: hidden;
}

/* --- Games：横向一行，超出横向滚动 --- */
/* 高度固定 320px：刚好放下一排 168x240 的卡片（跟 Games 页同一尺寸）。
   widget 高 = 卡片 240 + 行上下各 6px 留白 + 标题行和 widget 内边距共 68px。
   ⚠️ 之前是 clamp(296px, 30%, 372px)、卡片 height:100% + 3:4 推宽度，卡片随屏高变：
      1366~1920 屏 162x216，2560 屏 219x292，跟 Games 页不是一个尺寸。 */
.theme-purple .purple-widget-games { flex: 0 0 320px; }
/* 箭头定位层：原来只有 position:relative，高度由内容决定，
   widget 长高了它不跟着长，卡片的 height:100% 就无从参照 */
.theme-purple .purple-games-wrap {
	flex: 1 1 auto;
	min-height: 0;
	display: flex;
	flex-direction: column;
}
.theme-purple .purple-games-row {
	display: flex;
	flex-direction: row;
	gap: var(--purple-sp-4);   /* 16px，跟 Games 页网格同一个间距 */
	overflow-x: auto;
	overflow-y: hidden;
	/* hover 要 translateY(-4px) 再加 2px 描边。overflow-x:auto 会让 overflow-y
	   也变成滚动值（两轴不能一个 auto 一个 visible），所以四边都会剪：
	   顶上不留就剪掉上边线，左右不留就剪掉首/末卡的侧边线。
	   四周留 6px，左右再用负 margin 拉回去，
	   卡片起点仍然跟 widget 标题对齐，只是剪裁区向外撑了 6px。 */
	padding: 6px;
	margin-left: -6px;
	margin-right: -6px;
}
/* 卡片本体的尺寸/角标/标题带全走 Games 页那套（选择器已扩到 #page-home），
   这里只管行内排列。#games .game-item 的 float+margin-right 是 blue 基线留的，
   在 flex 行里 float 无效、margin 又会叠到 gap 上，一并清掉。 */
.theme-purple #games .purple-games-row .game-item {
	flex: 0 0 auto;
	float: none;
	margin-right: 0;
	/* 必须显式给一个 z-index，否则左/右箭头上会 hover 闪烁：
	   .game-image 是 z-index:3，跟箭头一样大。卡片未 hover 时自身没堆叠上下文，
	   .game-image 直接跟箭头比，同为 3 则按文档顺序——行在箭头之后，卡片赢；
	   一 hover，transform: translateY(-4px) 造出堆叠上下文，.game-image 的 3 被关在里面，
	   卡片整体掉到 0，箭头反过来赢——于是 hover 又掉了。两个状态来回振荡。
	   显式 z-index 让卡片任何时候都有堆叠上下文，层级不再随 hover 翻转。 */
	z-index: 0;
	/* 尺寸不在这里写，走上面 :is(#page-game, #page-home) .game-item 那条的 168x240，
	   两个页面的游戏卡片始终同一个大小 */
}
/* hover 的那张抬一层，让洋红描边压在邻卡之上；1 仍低于箭头的 3 */
.theme-purple #games .purple-games-row .game-item:hover { z-index: 1; }

/* --- Shop：跟 Shop 页同一套卡片尺寸 --- */
/* 原来是 1fr × 1fr 的 2x2，行高被可用空间均分——屏越高卡片被拉得越大，
   实测 1366 屏 128x137、1920 屏 221x293、2559 屏 327x384，是 Shop 页卡片的 1.9 倍，
   连宽高比都在飘。Shop 页那边是固定的：
     .shop-item-wrapper  170px 宽（含 p-3 的 16px 内边距），总高 228px
     .shop-image         138x138，圆角 12px
   卡片不再随屏高变形；多出来的空间改成多排几张，
   装不下的交给头部那对箭头翻页（每页几张由 purpleSyncShopPageSize() 按实际格子数算）。 */
.theme-purple .purple-widget-shop { flex: 1 1 0; }
.theme-purple .purple-shop-grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, 170px);
	grid-auto-rows: 228px;
	gap: var(--purple-sp-3);
	/* 不拉伸：行列都靠起始端堆，剩下的空位就空着 */
	align-content: start;
	justify-content: start;
}
/* Senet 的 Goodies 卡：图片铺满整张卡、四边不留白，名称+价格压在底部一条
   半透明深色带上（实测原图 218x200，带高约占卡高 27%）。风格照抄，
   尺寸用我们自己的：商品图 CP 那边裁的是 256x256（store-products.htm:197 的 canvas），
   Shop 页显示 138 方块，这里也用 138 方块——既是我们的比例，又永远不会把图放大变糊。
   （早先那版 grid-auto-rows:1fr 会把卡拉到 327x384，图就是那么糊的） */
.theme-purple .purple-shop-card {
	position: relative;
	width: 100%;
	height: 100%;
	border-radius: 12px;
	overflow: hidden;
	background: var(--purple-panel);
	min-height: 0;
}
.theme-purple .purple-shop-card-img {
	width: 100%;
	height: 100%;             /* 铺满整张卡 */
	background-size: cover;
	background-position: center;
	background-repeat: no-repeat;
}
/* 底部半透明带：Senet 那条是均匀的半透深色（能看到商品透出来），
   不是渐变。高度靠内容擑，实测跟原图的 27% 差不多。 */
.theme-purple .purple-shop-card-meta {
	position: absolute;
	left: 0; right: 0; bottom: 0;
	padding: 5px 8px 6px;
	background: rgba(23, 23, 32, 0.72);
}
.theme-purple .purple-shop-card-name {
	color: var(--purple-text-oncard);
	font-size: 11px;
	line-height: 14px;
	/* 长名字截断，不让带子撑高——否则一排里几张卡的带一高一低，
	   参考界面那条带是等高的 */
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}
.theme-purple .purple-shop-card-price {
	color: var(--purple-text-strong);
	font-size: 12px;
	font-weight: 500;
}

/* --- Offers（参考图里的 Passes）--- */
.theme-purple .purple-widget-offers { flex: 0 0 220px; }
.theme-purple .purple-offer-list {
	display: flex;
	flex-direction: column;
	gap: var(--purple-sp-2);
}
.theme-purple .purple-offer-card {
	background: var(--purple-panel);
	border-radius: var(--purple-r-btn);
	padding: 10px 12px;
}
.theme-purple .purple-offer-card:hover { opacity: 0.88; }
.theme-purple .purple-offer-price {
	color: var(--purple-text-strong);
	font-size: 15px;
	font-weight: 500;
	margin-top: 2px;
}

/* --- News --- */
.theme-purple .purple-widget-news { flex: 1 1 0; }

/* --- Rank：沿用原有 .home-leaderboard，套上 widget 外观 --- */
.theme-purple .purple-widget-cols .home-leaderboard {
	background: var(--purple-surface) !important;
	border-radius: var(--purple-r-card) !important;
	flex: 0 0 240px;
	min-width: 0;
}


/* --- 24.1 Home 页的修正 ---
   原有两条用来解开自制会员块外层 Bootstrap col-3 栅格约束的规则，
   会员块已改用共享侧栏容器，随之删除。 */

/* 底部标题带是 z-index:3，比 .overlay（z-index:2）高，
   而右下角那个「发密码/取授权」小图标就在 overlay 里、位置恰好压在标题带上——
   实测点不动，playwright 报 label intercepts pointer events。
   标题带是纯装饰，直接不收事件，点击穿透到下面的按钮/整卡。 */
.theme-purple :is(#page-game, #page-home) .game-item .game-name-label {
	pointer-events: none;
}

/* Top N 热度角标：基线是常规流元素，会把海报挤到右边。
   参考界面没有这个标记，但它是我们自己的功能（widget 就是 Top 5），不能丢；
   左上已经给了 license 钥匙、右上是收藏星，所以放左下角。 */
.theme-purple .purple-games-row .game-image .game-heat {
	position: absolute;
	left: 6px;
	bottom: 42px;         /* 让开底部标题带的文字（13px 两行 = 32，加 8 下边距） */
	z-index: 4;
	font-size: 10px;
	line-height: 14px;
	padding: 1px 6px;
	border-radius: var(--purple-r-chip);
	background: rgba(23, 23, 32, 0.82);
	pointer-events: none;
}

/* Rank：基线用 justify-content-between + h-100，行会被拉得很散 */
.theme-purple .purple-widget-cols .home-leaderboard #home_rank {
	justify-content: flex-start !important;
	gap: var(--purple-sp-2);
}
.theme-purple .purple-widget-cols .home-leaderboard h4 {
	font-size: 13px !important;
	font-weight: 500 !important;
}

/* --- 23.5 顶栏方片改成描边样式 ---
   参考图里那 4 个方片是「浅描边 + 近乎透明的底」，不是实底色块。 */
.theme-purple .header-right-info > div > a.lang:not(.dropdown-item) {
	background: rgba(145, 159, 191, 0.06);
	border: 1px solid var(--purple-border);
}
.theme-purple .header-right-info > div > a.lang:not(.dropdown-item):hover {
	background: var(--purple-elevated);
	opacity: 1;
}

/* ============================================================
   25. 单品详情弹窗
   ============================================================
   对照 Senet 官方下单流程的详情弹窗：标题 + 关闭，图在左、名称在右，
   分隔线，Total + 数量步进 + 总价，底部 Add to cart / Buy now 两个按钮。
   参考图里还有商品描述和「加料」单选，我们没有对应字段，未做。 */

.theme-purple .purple-pd .modal-header {
	border-bottom: 1px solid var(--purple-border) !important;
}
.theme-purple .purple-pd .modal-title {
	color: var(--purple-text-strong);
	font-family: var(--purple-font);
}
/* 标题和内容要在同一条竖线上（参考界面如此，我们的结算弹窗也是 24）。
   必须带 !important：通用那条 .modal-body 在 style.css 里写死了
   padding: 20px 40px !important，不加的话再高的 specificity 也压不过它，
   这条规则原本就是这么被架空的。 */
.theme-purple .purple-pd .modal-body {
	padding: 20px 24px !important;
}

.theme-purple .purple-pd-top {
	gap: var(--purple-sp-4);
	margin-bottom: var(--purple-sp-5);
}
.theme-purple .purple-pd-img {
	width: 148px;
	height: 148px;
	object-fit: cover;
	border-radius: var(--purple-r-card);
	flex-shrink: 0;
}
/* --- offer 时长卡的精简版（侧栏 OFFERS tab 用） ---
   侧栏那个槽位只有 96 见方，把详情弹窗那张 213 宽的卡原样缩进去会挤爆
   （实测内容总高 128，槽位只有 96），所以砍掉「Starts in」徽标和底部价格带，
   只留斜纹底 + 表盘水印 + 大号时长。信息没丢：条目下面本来就有名称和价格。
   ⚠️ start-session 的 offer 卡试过同样的做法，撤掉了：那张卡自己的底色就是暖褐渐变
      （--electric-border-color: #dd8448），暖褐的时长卡压上去几乎融进背景，
      对比度反而不如原来那个紫色图标。要再试的话记得先解决对比度。
   材质（斜纹/柔光/渐变）直接复用 .purple-offer-card，两个 class 一起挂。 */
.theme-purple .purple-offer-mini {
	position: relative;
	display: flex;
	/* 这三条都得带 !important：.purple-offer-card 那条（§27.2 附近）跟这条同为
	   (0,2,0) 的 specificity，但声明在后面，不加就压不过它的
	   flex-direction:column + justify-content:space-between + min-height:96px，
	   时长会被顶到卡片顶部。 */
	flex-direction: row !important;
	align-items: center !important;
	justify-content: center !important;
	overflow: hidden;
	flex-shrink: 0;
	padding: 0 !important;
	min-height: 0 !important;
}
.theme-purple .purple-offer-mini .purple-offer-clock {
	left: 2%;
	top: 50%;
	width: 42%;
	height: 42%;
	opacity: 0.09;
}
.theme-purple .purple-offer-mini .purple-offer-dur { margin: 0; }

/* 侧栏 OFFERS tab 的 hover 翻转。
   整套 3D 直接复用首页 Offers widget 那几条（§36.3 的 .purple-offer-flip / -inner /
   :hover / -face / -face-back / -back-label / -back-value），这里只改尺寸和背面排版，
   主题里就只有一套翻转机制。
   外壳尺寸对齐原来 <img> 的可视区域：那张图是 96x96 的盒子 + padding 2px 2px 0 2px，
   净可视 92x94，所以翻转壳就是 92x94 + 同样的 margin —— 布局盒跟改之前完全一致，
   切 tab 和翻转全程都不会有位移。 */
.theme-purple .shop-item .purple-offer-flip {
	width: 92px;
	height: 94px;
	margin: 2px 2px 0 2px;
	flex-shrink: 0;
	/* 首页那条是 perspective:700px 配 167px 宽的卡，比值 0.24。这里卡只有 92 宽，
	   沿用 700 的话比值掉到 0.13、透视太平、翻起来不像 3D，按同样比值折算到 385。 */
	perspective: 385px;
}
/* 翻转触发点放在整个条目上，不是只有卡片那一块：条目本身就是点击区，
   鼠标移到下面的名称/价格上时也该翻，不然手感割裂。
   （首页那条 .purple-offer-flip:hover 仍然管首页，两边互不影响。） */
.theme-purple .shop-item:hover .purple-offer-flip-inner {
	transform: rotateY(180deg);
}
.theme-purple .shop-item .purple-offer-face {
	border-radius: 10px;
	overflow: hidden;
}
/* 正面的时长卡现在就是那张 face 本身，尺寸交给 inset:0，别再自己定宽高和外边距 */
.theme-purple .shop-item .purple-offer-mini {
	width: auto;
	height: auto;
	margin: 0;
	border-radius: 10px !important;
}
.theme-purple .shop-item .purple-offer-mini .purple-offer-dur-v { font-size: 20px; line-height: 23px; }
.theme-purple .shop-item .purple-offer-mini .purple-offer-dur-u { font-size: 10px; }
/* 背面：92px 宽（减内边距只剩 76px）放不下首页那三行，只留「Starts in」和有效时段。
   每一项单独占一行、都不换行——混排让浏览器自己折会折出
   "Starts in: Wed" / "15:00" 这种读不通的断点。实测各行最宽 71px，都放得下。 */
.theme-purple .shop-item .purple-offer-face-back {
	padding: 8px;
	box-sizing: border-box;
	gap: 0;
	white-space: nowrap;
}
.theme-purple .shop-item .purple-offer-face-back > div {
	overflow: hidden;
	text-overflow: ellipsis;
}
.theme-purple .shop-item .purple-offer-face-back .purple-offer-back-label {
	font-size: 10px;
	line-height: 13px;
}
.theme-purple .shop-item .purple-offer-back-when {
	font-size: 11px;
	line-height: 14px;
	margin-bottom: 6px;
}
.theme-purple .shop-item .purple-offer-face-back .purple-offer-back-value {
	font-size: 11px;
	line-height: 14px;
}

/* offer 详情：左边那格用时长卡代替商品图（offer 没有真实照片，
   走 <img> 只会显示 default-offer.jpg 那张通用图章）。
   .purple-offer-card 提供材质（渐变+斜纹）和 flex column space-between 的骨架，
   这里只定尺寸和那条价格带。
   尺寸按参考图量的：卡宽占【内容区】宽的 49.6%（136/274），宽高比 1.417（136/96）——
   是横的，不是正方形；原来做成 148 见方是错的。
   注意百分比是相对 .purple-pd-top 这个内容盒，不是弹窗外框：参考图里卡宽占弹窗宽 43%，
   但弹窗左右各有 21px 内边距，换算到内容盒是 49.6%，直接写 43% 会小一圈。 */
.theme-purple .purple-pd-offer {
	position: relative;
	width: 49.6%;
	aspect-ratio: 1.417;
	flex-shrink: 0;
	border-radius: var(--purple-r-card) !important;
	overflow: hidden;
	padding: 10px 12px 0 !important;   /* 底部留给价格带自己铺满 */
}
/* 复用 §27.2 的 .purple-offer-clock。表盘尺寸/位置是把官方图那张卡做局部中值背景
   相减、再取残差亮环的外接框量出来的：环占 x 42..95、y 86..149，卡是 136x96 起点
   (41,84) —— 直径约卡宽的 40%（= 卡高的 57%，是个正圆），圆心在卡宽 20% / 卡高 35%
   处，也就是偏左偏上，左缘基本贴着卡边。用百分比跟着卡一起缩放。 */
.theme-purple .purple-pd-offer .purple-offer-clock {
	left: 0;
	top: 35%;
	width: 40%;
	height: 57%;
	opacity: 0.07;
}
/* 徽标在这张大卡上要比首页那张亮一档，官方图里「Starts in:」接近白色 */
.theme-purple .purple-pd-offer .purple-offer-badge {
	font-size: 12px;
	color: rgba(255, 255, 255, 0.78);
}
/* 官方图里「5 h」的中心落在卡宽 54% 处，不是顶到右边；居中最接近 */
.theme-purple .purple-pd-offer .purple-offer-dur { margin: 0 auto; }
.theme-purple .purple-pd-offer .purple-offer-dur-v { font-size: 34px; line-height: 38px; }
.theme-purple .purple-pd-offer .purple-offer-dur-u { font-size: 14px; }
/* 底部价格带：参考图里是一条压暗的横条，占卡高约 29%（28/96），价格靠左。
   压暗程度也是量的：条内亮度 31、卡身 55，比值 0.56，等于盖一层 alpha≈0.45 的黑。
   原来给的 0.26 太浅、padding 也太小（只有卡高的 22%），所以那条带子不明显。 */
.theme-purple .purple-pd-offer-foot {
	position: relative;
	z-index: 1;
	margin: 0 -12px;
	padding: 12px 12px 13px;
	background: rgba(0, 0, 0, 0.45);
}
.theme-purple .purple-pd-offer-foot .purple-offer-price {
	color: var(--purple-text-strong);
	font-size: 14px;
	font-weight: 500;
	margin-top: 0;
}

/* offer 专属的几行信息（有效时段） */
.theme-purple .purple-pd-label {
	margin-top: 14px;
	color: var(--purple-text-muted);
	font-size: 12px;
}
.theme-purple .purple-pd-value {
	margin-top: 2px;
	color: var(--purple-text);
	font-size: 13px;
}
/* 打折时总价左边那段划掉的原价 */
.theme-purple .purple-pd-was {
	margin-right: 8px;
	color: var(--purple-text-muted);
	font-size: 13px;
	font-weight: 400;
	text-decoration: line-through;
}

.theme-purple .purple-pd-name {
	color: var(--purple-text-strong);
	font-family: var(--purple-font);
	font-size: 20px;
	line-height: 26px;
	font-weight: 600;
}

/* Total 行：上方一条分隔线，跟参考图一致 */
.theme-purple .purple-pd-total {
	border-top: 1px solid var(--purple-border);
	padding-top: var(--purple-sp-4);
	margin-bottom: var(--purple-sp-4);
}
.theme-purple .purple-pd-total-label {
	color: var(--purple-text-muted);
	font-size: 13px;
}
/* 步进器和总价贴成一组靠右，中间只留一个 sp-3 */
.theme-purple .purple-pd-total-right {
	gap: var(--purple-sp-3);
}
.theme-purple .purple-pd-stepper {
	background: var(--purple-elevated);
	border-radius: var(--purple-r-btn);
	padding: 2px;
	gap: 2px;
}
.theme-purple .purple-pd-step {
	width: 30px;
	height: 30px;
	border: none;
	background: transparent;
	color: var(--purple-text);
	border-radius: var(--purple-r-chip);
}
.theme-purple .purple-pd-step:hover { color: var(--purple-text-strong); }
.theme-purple .purple-pd-qty {
	min-width: 34px;
	text-align: center;
	color: var(--purple-text-strong);
	font-size: 15px;
}
.theme-purple .purple-pd-price {
	color: var(--purple-text-strong);
	font-size: 18px;
	font-weight: 500;
}

.theme-purple .purple-pd-actions { gap: var(--purple-sp-3); }
.theme-purple .purple-pd-btn svg { flex-shrink: 0; }
/* 两颗按钮要等宽（参考界面如此）。padding 必须写在这里显式拉平：
   flex-basis:0 配 box-sizing:border-box 时，边框盒被压到 0，内边距撑不下，
   于是这一项的最小主尺寸被抬成「左右内边距之和」。Buy now 那颗被
   .purple-btn-primary 设成 padding:0，Add to cart 那颗吃的是按钮的 UA 默认
   1px 6px —— 12px 的差额先被扣掉、剩下的才平分，结果就差了 12px。
   min-width:0 是顺带的：文案长到放不下时别把 flex-basis:0 顶开。 */
.theme-purple .purple-pd-btn {
	flex: 1 1 0;
	min-width: 0;
	padding: 0 var(--purple-sp-3);
	height: 44px;
	border-radius: var(--purple-r-btn);
	font-size: 14px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
}

/* --- 23.6 顶栏右侧的间距收紧 ---
   基线给每一项都挂了 Bootstrap 的 mr-3（16px），而方片本身才 30px 宽，
   排出来一个个孤零零的。参考界面那几个方片是紧挨成一簇的，
   只有「机器号 → 方片簇」之间留一段明显间距。 */
.theme-purple .header-right-info > div {
	margin-right: 6px !important;
}
/* 最右那个方片（退出）右边原来空着 51px：绝对定位层 right:30px（.r-8）+ 它自己 15px 内边距
   （.col-auto）+ 最后一项 6px 外边距，比下面侧栏内容的 16px 右边距多出 35px。
   收成跟侧栏内容右边缘对齐（视口右边 16px），省下的 35px 正好还给搜索框，
   搜索框右边缘重新跟内容区对齐（见 .purple-header-area 的 padding-right）。 */
.theme-purple .purple-header-area > .position-absolute.r-8 {
	right: 16px !important;
	padding-right: 0 !important;
}
.theme-purple .header-right-info > div:last-child {
	margin-right: 0 !important;
}
/* 真正撑开间距的是 style.css:1870 的 gap:24px!important —— 上面把 mr-3 收到 6px
   之后，方片之间仍然隔着 24+6=30px，跟方片本身一样宽（参考界面这个比值约 0.58）。
   压到 11px，加上那 6px 外边距，方片间距 17px ≈ 30×0.57。
   权重：基线那条是 .header-section .header-area .header-right-info (0,3,0)!important，
   这里带上 .theme-purple 成 (0,4,0) 才压得过。 */
.theme-purple .header-section .header-area .header-right-info {
	gap: 11px !important;
}
.theme-purple .header-right-info .header-pcname {
	margin-right: 18px !important;
}
/* 头像跟方片簇之间也留开一点，避免贴在一起 */
.theme-purple .header-right-info .header-avatar-dropdown {
	margin-left: 10px;
}

/* ============================================================
   26. Home widget 补齐：翻页箭头 / Offers 卡片 / 收藏行
   ============================================================ */

/* --- 26.1 widget 头部的翻页箭头 --- */
.theme-purple .purple-widget-nav { gap: 4px; }
.theme-purple .purple-widget-arrow {
	width: 26px;
	height: 26px;
	border: none;
	background: transparent;
	color: var(--purple-text-muted);
	border-radius: var(--purple-r-chip);
	font-size: 12px;
	line-height: 1;
}
.theme-purple .purple-widget-arrow:hover {
	background: var(--purple-elevated);
	color: var(--purple-text-strong);
}

/* --- 26.2 Offers 卡片 ---
   参考界面是一行两张的宽卡，不是窄条。列宽跟着放开。 */
.theme-purple .purple-widget-offers { flex: 1 1 0; min-width: 300px; }
.theme-purple .purple-offer-list {
	display: grid;
	grid-template-columns: 1fr 1fr;
	grid-auto-rows: min-content;
	gap: var(--purple-sp-3);
}
.theme-purple .purple-offer-card {
	position: relative;
	background: var(--purple-panel);
	border-radius: var(--purple-r-card);
	padding: var(--purple-sp-3) var(--purple-sp-4) var(--purple-sp-4);
	min-height: 96px;
	display: flex;
	flex-direction: column;
	justify-content: space-between;
	overflow: hidden;
}
.theme-purple .purple-offer-card:hover { opacity: 0.88; }
.theme-purple .purple-offer-badge {
	color: var(--purple-text-muted);
	font-size: 11px;
	text-align: right;
}
/* 「Now」用绿色，跟参考界面一致——这里绿是状态语义（立即可用），不是品牌色 */
.theme-purple .purple-offer-now { color: var(--purple-success); }
.theme-purple .purple-offer-price {
	color: var(--purple-text);
	font-size: 13px;
}

/* --- 26.3 侧栏收藏行 --- */
/* 收藏行：对照参考界面是 5 个一行、撑满侧栏宽、超过就换行。
   ⚠️ 必须显式撑满：父容器 .user-info-card 带 align-items-start，
      不写 width/align-self 的话整行会收缩成内容宽（实测只有 254px，
      而侧栏可用宽是 332~380），海报也就跟着挤成小方块。 */
.theme-purple .purple-fav {
	margin-top: var(--purple-sp-4);
	width: 100%;
	align-self: stretch;
}
.theme-purple .purple-fav-title {
	color: var(--purple-text-muted);
	font-size: 12px;
	margin-bottom: var(--purple-sp-2);
}
/* 用 Grid 而不是 flex 五等分：flex-basis 写百分比时，容器主轴尺寸被判为
   「不确定」，浏览器会回退到图片的固有宽度（实测每张变成 168px，一行只放得下
   1~2 张）。Grid 的 1fr 直接按容器宽度分，不吃这个亏。 */
.theme-purple .purple-fav-row {
	display: grid;
	grid-template-columns: repeat(5, 1fr);
	gap: 8px;
	width: 100%;
}
/* 高度交给长宽比，Home（窄）和 Games（宽）两种侧栏宽度下都是 5 个一行。
   比例取自参考界面 105:167。 */
.theme-purple .purple-fav-item,
.theme-purple .purple-fav-empty {
	width: 100%;
	height: auto;
	aspect-ratio: 105 / 167;
	border-radius: 6px;
}
.theme-purple .purple-fav-item {
	object-fit: cover;
}
/* 空位：参考界面用虚线框占位 */
.theme-purple .purple-fav-empty {
	border: 1px dashed var(--purple-border);
}

/* --- 26.4 Top up 按钮：对照参考界面 ---
   参考图是实心渐变按钮、左侧一枚卡片图标、文字白色、圆角约 9px，
   渐变方向左深右浅（取样 #3D15B7 → #657DDD，我们用自己的洋红同方向）。
   markup 里的内联样式已清除，这里是唯一的外观来源。 */
.theme-purple .btn-topup {
	display: inline-flex !important;
	align-items: center;
	gap: 8px;
	margin-left: auto;
	padding: 8px 16px !important;
	border: none !important;
	border-radius: var(--purple-r-btn) !important;
	background: var(--purple-gradient-primary) !important;
	color: var(--purple-text-strong) !important;
	font-family: var(--purple-font);
	font-size: 13px;
	font-weight: 500;
	cursor: pointer;
	outline: none;
	white-space: nowrap;
}
.theme-purple .btn-topup:hover  { opacity: 0.88; }
.theme-purple .btn-topup:active { opacity: 0.75; }
.theme-purple .btn-topup svg    { flex-shrink: 0; }
.theme-purple .btn-topup span   { color: var(--purple-text-strong) !important; }

/* ============================================================
   27. Games 侧边箭头 / Offers 卡片材质
   ============================================================ */

/* --- 27.1 Games 列表的左右箭头 ---
   参考界面把这对箭头压在列表左右边缘、竖直居中，不在 widget 头部
   （Shop 和 News 才是头部箭头）。 */
.theme-purple .purple-games-wrap { position: relative; }
.theme-purple .purple-row-arrow {
	position: absolute;
	top: 50%;
	transform: translateY(-50%);
	z-index: 3;
	width: 34px;
	height: 34px;
	border: none;
	border-radius: 50%;
	background: rgba(23, 23, 32, 0.72);
	color: var(--purple-text);
	font-size: 14px;
	line-height: 1;
}
.theme-purple .purple-row-arrow:hover {
	background: var(--purple-elevated);
	color: var(--purple-text-strong);
}
.theme-purple .purple-row-arrow-left  { left: -6px; }
.theme-purple .purple-row-arrow-right { right: -6px; }

/* --- 27.2 Offers 卡片材质 ---
   参考界面的 Pass 卡是暖褐渐变 + 一层细斜纹 + 一个大号时钟水印，
   跟周围的冷色面板拉开区分。色值取自官方图：左上 #554341 → 右下 #3B342D。
   斜纹的走向和疏密是从官方图算出来的：取卡内一块干净区域，按行、列各自去均值
   （等于扣掉底色渐变），再分别按 x+y 和 x-y 分组求组间标准差。
   ⚠️ 这里的坐标系 y 是【向下】增长的，所以：
        x+y 为常数的那族线 = 向右上走 = 视觉上的 /
        x-y 为常数的那族线 = 向右下走 = 视觉上的 \
      组间标准差大的那一族，就是条纹本身的走向。
      官方图四个取样区块一致给出 x+y 更大（3.95 / 5.26 / 4.94 / 3.22，
      对应的 x-y 是 0.76 / 3.63 / 4.27 / 2.70），所以条纹是 / ，对应 135deg。
      实测确认过映射：45deg 渲染出来是 \ ，135deg 是 / 。
   周期：沿 x+y 方向做自相关，峰值 lag=4~5（这是对角线步长，真实周期还要除以 √2）
      → 3.2px，那张卡宽 136，折合卡宽的 2.4%；我们的卡 167~213 宽，取 5px 一道。
   明暗幅度官方图约 ±5/55 ≈ 9%。
   纯 CSS 渐变，不引图片，软渲染下只是一次平铺填充，代价可以忽略。 */
.theme-purple .purple-offer-card {
	background:
		/* 边缘柔光。官方卡的低频亮度是个 U 形：中间最暗（约 54），往左右两边升到
		   80 上下，不是单向渐变。右缘那侧没有表盘干扰，拿它标定：
		   (83-54)/(255-54) ≈ 0.14 的白。这里保守取 0.10 —— 那张图是 GIF，
		   边缘多少带点压缩振铃，不宜全额照抄。 */
		linear-gradient(90deg,
			rgba(255, 255, 255, 0.06) 0%, rgba(255, 255, 255, 0) 26%,
			rgba(255, 255, 255, 0) 74%, rgba(255, 255, 255, 0.10) 100%),
		/* 左上那团柔光（表盘那一侧整体偏亮，不只是表盘线本身） */
		radial-gradient(90% 75% at 16% 20%,
			rgba(255, 255, 255, 0.055) 0%, rgba(255, 255, 255, 0) 62%),
		repeating-linear-gradient(135deg,
			rgba(255, 255, 255, 0.055) 0px, rgba(255, 255, 255, 0.055) 1px,
			rgba(255, 255, 255, 0) 1px, rgba(255, 255, 255, 0) 5px),
		linear-gradient(135deg, #554341 0%, #3B342D 100%) !important;
}
.theme-purple .purple-offer-clock {
	position: absolute;
	left: -18px;
	top: 50%;
	transform: translateY(-50%);
	width: 104px;
	height: 104px;
	color: #ffffff;
	opacity: 0.07;
	pointer-events: none;
}
/* 卡内文字要压在水印之上 */
.theme-purple .purple-offer-badge,
.theme-purple .purple-offer-price { position: relative; z-index: 1; }

/* --- 27.3 排行块的标题与表头 ---
   原来 home.htm 的排行块有「Last 30 days」标题和 RANK/PLAYER/SCORE 三列表头，
   搬进侧栏时丢了，只剩一个 RANK 标签和几行数据，看着空。这里补回来。 */
.theme-purple .purple-rank-period {
	color: var(--purple-text-muted);
	font-size: 11px;
}
.theme-purple .purple-rank-head {
	background: transparent !important;
	padding-bottom: 4px;
	margin-bottom: 2px;
	border-bottom: 1px solid var(--purple-border);
}
/* 权重说明：基线那条是 :is(#page-game,...) .rank-name (1,2,0)，
   而且带 text-transform:uppercase。选择器要含 ID 且更高才压得过，
   这里 .theme-purple + :is(#id...) + 两个类 = (1,3,0)。 */
.theme-purple :is(#page-game, #page-shop, #page-rank, #page-event, #page-home, #page-account, #purple-sidebar) .purple-rank-head .rank-number,
.theme-purple :is(#page-game, #page-shop, #page-rank, #page-event, #page-home, #page-account, #purple-sidebar) .purple-rank-head .rank-name,
.theme-purple :is(#page-game, #page-shop, #page-rank, #page-event, #page-home, #page-account, #purple-sidebar) .purple-rank-head .rank-score {
	text-transform: uppercase !important;   /* 三个词统一大写，不再一半大写一半不大写 */
	color: var(--purple-text-muted) !important;
	font-size: 11px !important;
	font-weight: 500 !important;
	letter-spacing: 0.04em;
}

/* --- 27.4 钱包行重排 ---
   对照参考界面：一整行 = 左边图标块 + 中间「余额 / bonus·硬币」两行叠放 + 右边 Top up。
   原来 bonus 和硬币是另起一行的独立区块（.purple-mini-stats），与参考排版不符，已并入。 */
.theme-purple .user-stat-wallet {
	gap: var(--purple-sp-3);
}
/* 参考界面的钱包图标坐在一个圆角方块底衬里，不是裸图标 */
.theme-purple .purple-wallet-icon {
	width: 34px;
	height: 34px;
	flex-shrink: 0;
	border-radius: var(--purple-r-btn);
	background: var(--purple-elevated);
	color: var(--purple-text);
}
.theme-purple .purple-wallet-icon svg { width: 18px; height: 18px; }

.theme-purple .purple-wallet-values { min-width: 0; line-height: 1.2; }
.theme-purple .purple-wallet-values .member_balance_realtime {
	margin-left: 0 !important;
	color: var(--purple-text-strong);
	font-size: 17px;
	font-weight: 500;
}
/* 第二行：bonus 和硬币并排，字号压小，跟主余额拉开层次 */
.theme-purple .purple-wallet-sub {
	gap: var(--purple-sp-3);
	margin-top: 2px;
}
.theme-purple .purple-wallet-sub .user-stat-item { gap: 4px; }
.theme-purple .purple-wallet-sub svg { width: 13px; height: 13px; }
.theme-purple .purple-wallet-sub span {
	font-size: 12px;
	color: var(--purple-text-muted);
}
/* bonus 用琥珀色，跟参考界面一致（那里 bonus 是金色的） */
.theme-purple .purple-wallet-sub .member_balance_bonus_realtime { color: var(--purple-warning); }

/* ============================================================
   28. 侧栏「Last order」行
   ============================================================
   参考界面钱包行下面还有一行：[图标块] Last order:  N items  [状态]。
   图标块沿用钱包那颗（.purple-wallet-icon），保持两行同一种节奏；
   右半边「条目数 + 状态药丸」用 margin-left:auto 推到最右。
   数据由 js/app.js 的 vueGlobal.lastOrder 提供。 */
.theme-purple .purple-last-order {
	/* 必须撑满一行：否则行宽按内容收缩，右半边的 margin-left:auto 推不到边 */
	width: 100%;
	gap: 10px;
	padding: 6px 0;
	cursor: pointer;
}
.theme-purple .purple-last-order:hover { opacity: 0.85; }

.theme-purple .purple-last-order-label {
	color: var(--purple-text-muted) !important;
	font-size: 13px;
	font-weight: 400;
	white-space: nowrap;
}

/* 条目数：推到右边，跟状态药丸挨着 */
.theme-purple .purple-last-order-count {
	margin-left: auto;
	color: var(--purple-text-strong) !important;
	font-size: 13px;
	font-weight: 600;
	white-space: nowrap;
}
/* 「—」占位（没有订单时）后面没有药丸，右边补一点内边距对齐 */
.theme-purple .purple-last-order-count + .purple-last-order-status { margin-left: 0; }

/* 状态药丸。display 不写 !important：v-show 隐藏靠的是内联 display:none，
   加了 !important 会把它压掉，没有订单时药丸也会露出来。 */
.theme-purple .purple-last-order-status {
	display: inline-flex;
	align-items: center;
	padding: 4px 10px;
	background: var(--purple-elevated);
	border-radius: var(--purple-r-chip);
	font-size: 12px;
	font-weight: 500;
	line-height: 1.2;
	white-space: nowrap;
	color: var(--purple-text-oncard) !important;
}
.theme-purple .purple-last-order-status.is-paid      { color: var(--purple-success) !important; }
.theme-purple .purple-last-order-status.is-cancelled { color: var(--purple-text-muted) !important; }
.theme-purple .purple-last-order-status.is-pending,
.theme-purple .purple-last-order-status.is-process   { color: var(--purple-warning) !important; }

/* ============================================================
   29. 底栏语言弹出列表
   ============================================================
   参考界面的语言切换是贴着按钮上方弹出的一列语言代码，选中项高亮，
   点一下直接生效——不是我们原来那个「开弹窗 → 选下拉 → 点 Apply」。
   列表用 absolute 挂在按钮上方；侧栏是 overflow-y:auto 的滚动容器，
   底栏又是 sticky bottom:0，所以向上展开正好落在可视区内，不会被裁掉。 */
.theme-purple .purple-footer-lang-wrap {
	position: relative;
	display: flex;
	align-items: center;
}

.theme-purple .purple-lang-menu {
	position: absolute;
	left: 0;
	bottom: calc(100% + 8px);
	z-index: 30;
	min-width: 58px;
	/* 跟视口走：现在 13 种语言一屏放得下，矮屏/语言更多时自动滚动 */
	max-height: 60vh;
	overflow-y: auto;
	padding: 4px;
	background: var(--purple-elevated);
	border: 1px solid var(--purple-border);
	border-radius: var(--purple-r-btn);
	/* 软件渲染下不用 filter/blur 做投影，box-shadow 便宜得多 */
	box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45);
}

/* display 不写 !important：v-show 隐藏靠的是内联 display:none */
.theme-purple .purple-lang-option {
	display: block;
	width: 100%;
	padding: 5px 10px;
	background: transparent;
	border: none;
	border-radius: var(--purple-r-chip);
	color: var(--purple-text);
	font-family: var(--purple-font);
	font-size: 12px;
	font-weight: 500;
	line-height: 1.3;
	text-align: center;
	cursor: pointer;
}
.theme-purple .purple-lang-option:hover { background: var(--purple-panel); color: var(--purple-text-strong); }
.theme-purple .purple-lang-option:focus { outline: none; }
.theme-purple .purple-lang-option.is-active {
	background: var(--purple-accent);
	color: #FFFFFF;
}

/* 列表展开时按钮本身也提亮，表示当前在选 */
.theme-purple .purple-footer-lang.is-open { color: var(--purple-text-strong); }

/* ============================================================
   30. My account 页面
   ============================================================
   对照 Senet：点头像进这个页面，左边一列子导航，中间内容，右边仍是会员面板。

   顶栏原来那个头像下拉（17 项）已整个删除，去向：
     顶栏 4 个图标  Feedback / Lock PC / Logout（Language 在侧栏底部）
     Profile 页     Change Avatar（大头像）、Change password（Reset password 按钮）、
                    Convert to member、Bind app account、Join us
     子页           Order list → Order history、Balance history → Balance history
     Settings 子页  Mouse / Display / Sound settings、Checklist、Ask help、Refresh
   一项没丢。 */
.theme-purple .purple-account {
	min-width: 0;
}

/* --- 左侧子导航 --- */
/* 壁纸挂在 .theme-body 上、一直都在，这个页面内容稀疏，不铺底的话
   字段标签会压在壁纸上读不清。按主题 token 的分工铺：左栏用最底层色，
   内容区用主内容区色。右侧会员面板不碰——它的底由 layout.htm 里那层
   fixed 的 --purple-panel 垫层负责，这里铺满会把它盖掉。 */
/* 尺寸对照参考界面量出来的（原图 2484 宽，按 1920 屏折算）：
   标题图标 x=48、轨道线 x=72、导航文字 x=87、内容区起点 x=293。
   所以左内边距 48，列宽 292 + 1px 右边线 = 293。 */
.theme-purple .purple-account-nav {
	width: 292px;
	flex-shrink: 0;
	/* 下内边距归零，否则轨道线到不了底（参考界面那条一直通到底部） */
	padding: var(--purple-sp-5) var(--purple-sp-4) 0 48px;
	/* gap 会把各项的 border-left 切断，轨道线必须首尾相接 */
	gap: 0;
	background: var(--purple-ground);
	/* 与内容区之间的分隔线，跟 Games/Shop 页左栏的处理一致 */
	border-right: 1px solid var(--purple-border);
}
.theme-purple .purple-account-head {
	gap: 10px;
	margin-bottom: var(--purple-sp-5);
	color: var(--purple-text-strong);
}
.theme-purple .purple-account-head-text {
	font-size: 19px;
	font-weight: 500;
}
/* 参考界面这几项左边有一条贯通的竖轨道线，激活项是线上那一段变亮 +
   文字变主题色，没有填充色块。每项各带一段 border-left，连起来就是整条线。 */
/* 轨道线挂在包裹层上并撑满整列（跟 Games/Shop 左栏同一套做法）。
   线的 x 对齐标题「My account」文字的起点，比图标再缩进一个图标宽。 */
.theme-purple .purple-account-navlist {
	margin-left: 24px;
	border-left: 2px solid var(--purple-border);
}
.theme-purple .purple-account-navitem {
	display: block;
	margin-left: -2px;
	padding: 9px 14px;
	border-radius: 0;
	border-left: 2px solid transparent;
	color: var(--purple-text) !important;
	font-size: 14px;
	text-decoration: none !important;
}
.theme-purple .purple-account-navitem:hover {
	color: var(--purple-text-strong) !important;
	border-left-color: var(--purple-text-muted);
}
.theme-purple .purple-account-navitem.is-active {
	color: var(--purple-accent-text) !important;
	border-left-color: var(--purple-accent);
}
/* 参考界面导航列表下面没有横线——之前我照着一张低清截图误加了一条，已去掉 */

/* --- 内容区 --- */
.theme-purple .purple-account-body {
	min-width: 0;
	padding: var(--purple-sp-5);
	overflow-y: auto;
	background: var(--purple-surface);
}
.theme-purple .purple-account-pane-title {
	margin: 0 0 var(--purple-sp-4);
	color: var(--purple-text-strong);
	font-size: 17px;
	font-weight: 500;
}
.theme-purple .purple-account-empty {
	padding: var(--purple-sp-5);
	color: var(--purple-text-muted);
	font-size: 13px;
	text-align: center;
}

/* --- Profile --- */
.theme-purple .purple-profile { gap: 40px; }
.theme-purple .purple-profile-side { width: 240px; }
.theme-purple .purple-profile-avatar {
	position: relative;
	width: 230px;
	height: 230px;
	border-radius: var(--purple-r-card);
	overflow: hidden;
	background: var(--purple-surface);
}
.theme-purple .purple-profile-avatar img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}
/* 可上传时右下角压一枚相机角标，提示这块能点 */
.theme-purple .purple-profile-avatar-edit {
	position: absolute;
	right: 10px;
	bottom: 10px;
	width: 32px;
	height: 32px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	border-radius: 50%;
	background: var(--purple-elevated);
	color: var(--purple-text-oncard);
	font-size: 13px;
}
.theme-purple .purple-profile-stat {
	margin-top: var(--purple-sp-4);
	padding-top: var(--purple-sp-3);
	border-top: 1px solid var(--purple-border);
}
.theme-purple .purple-profile-stat-label {
	color: var(--purple-text-muted);
	font-size: 12px;
}
.theme-purple .purple-profile-stat-value {
	margin-top: 2px;
	color: var(--purple-text-strong);
	font-size: 20px;
	font-weight: 500;
}
.theme-purple .purple-profile-stat-sub {
	color: var(--purple-warning);
	font-size: 12px;
}

.theme-purple .purple-profile-name {
	margin: 0;
	color: var(--purple-text-strong);
	font-size: 28px;
	font-weight: 500;
}
.theme-purple .purple-profile-actions {
	gap: 10px;
	margin: var(--purple-sp-4) 0 var(--purple-sp-5);
}
.theme-purple .purple-profile-btn {
	padding: 9px 16px;
	background: var(--purple-elevated);
	border: none;
	border-radius: var(--purple-r-btn);
	color: var(--purple-text-oncard);
	font-family: var(--purple-font);
	font-size: 13px;
	cursor: pointer;
}
.theme-purple .purple-profile-btn:hover { color: var(--purple-text-strong); }

/* 只读字段：参考界面是三列栅格，标签在上、值在下，底下一条细线 */
.theme-purple .purple-profile-grid {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: var(--purple-sp-4) var(--purple-sp-5);
}
.theme-purple .purple-profile-field {
	padding-bottom: var(--purple-sp-3);
	border-bottom: 1px solid var(--purple-border);
	min-width: 0;
}
.theme-purple .purple-profile-field-label {
	color: var(--purple-text-muted);
	font-size: 12px;
}
.theme-purple .purple-profile-field-value {
	margin-top: 4px;
	color: var(--purple-text-strong);
	font-size: 15px;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

/* --- My offers --- */
.theme-purple .purple-acct-offer-row {
	gap: 12px;
	padding: 14px 16px;
	margin-bottom: 10px;
	background: var(--purple-surface);
	border-radius: var(--purple-r-card);
}
.theme-purple .purple-acct-offer-name {
	color: var(--purple-text-strong);
	font-size: 14px;
	font-weight: 500;
}
.theme-purple .purple-acct-offer-badge {
	padding: 3px 9px;
	background: var(--purple-elevated);
	border-radius: var(--purple-r-chip);
	color: var(--purple-success);
	font-size: 11px;
}
.theme-purple .purple-acct-offer-remaining {
	margin-left: auto;
	color: var(--purple-text-strong);
	font-size: 14px;
	font-weight: 500;
}
.theme-purple .purple-acct-offer-bar {
	width: 160px;
	height: 6px;
	flex-shrink: 0;
	background: var(--purple-elevated);
	border-radius: var(--purple-r-pill);
	overflow: hidden;
}
.theme-purple .purple-acct-offer-fill {
	height: 100%;
	background: var(--purple-accent);
}

/* --- Settings --- */
.theme-purple .purple-setting-row {
	gap: 14px;
	padding: 14px 16px;
	margin-bottom: 10px;
	background: var(--purple-surface);
	border-radius: var(--purple-r-card);
	color: var(--purple-text) !important;
	font-size: 14px;
	text-decoration: none !important;
}
.theme-purple .purple-setting-row:hover { color: var(--purple-text-strong) !important; }
.theme-purple .purple-setting-icon {
	width: 34px;
	height: 34px;
	flex-shrink: 0;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	border-radius: var(--purple-r-btn);
	background: var(--purple-elevated);
	color: var(--purple-text-oncard);
}
.theme-purple .purple-setting-arrow {
	margin-left: auto;
	color: var(--purple-text-muted);
	font-size: 20px;
	line-height: 1;
}

/* --- 30.1 从弹窗搬过来的两张表：补回失效的样式 ---
   style.css 里有 24 条规则的作用域绑死在 .myModalOrderList / .myModalBalanceHistory
   上（列宽、单元格底线、容器内边距），弹窗一删这些全部失效，表现为列宽塌掉、
   表头横向溢出。这里按 .purple-account-pane 原样重挂一遍，数值与原规则一致。 */
.theme-purple .purple-account-pane .table-responsive {
	margin: 0 !important;
	padding: 0 !important;
	overflow: visible;
}
.theme-purple .purple-account-pane .order-table-container,
.theme-purple .purple-account-pane .balance-table-container {
	max-height: none !important;
}
.theme-purple .purple-account-pane .table th,
.theme-purple .purple-account-pane .table td {
	border-bottom: 1px solid #313452;
}
.theme-purple .purple-account-pane .order-table tbody tr:last-child td {
	border-bottom: none !important;
}
/* 列宽（原 .myModalOrderList .order-table th/td:nth-child(N)） */
.theme-purple .purple-account-pane .order-table th:first-child,
.theme-purple .purple-account-pane .order-table td:first-child { width: 80px; padding-left: 16px; }
.theme-purple .purple-account-pane .order-table th:nth-child(2),
.theme-purple .purple-account-pane .order-table td:nth-child(2) { width: 150px; }
.theme-purple .purple-account-pane .order-table th:nth-child(3),
.theme-purple .purple-account-pane .order-table td:nth-child(3) { width: 100px; }
.theme-purple .purple-account-pane .order-table th:nth-child(4),
.theme-purple .purple-account-pane .order-table td:nth-child(4) { width: 300px; }
.theme-purple .purple-account-pane .order-table th:nth-child(5),
.theme-purple .purple-account-pane .order-table td:nth-child(5) { width: 100px; text-align: right; }
.theme-purple .purple-account-pane .order-table th:nth-child(6),
.theme-purple .purple-account-pane .order-table td:nth-child(6) { width: 100px; }
.theme-purple .purple-account-pane .order-table th:nth-child(7),
.theme-purple .purple-account-pane .order-table td:nth-child(7) { width: 100px; padding-right: 16px; }

/* --- 30.2 My account 页的滚动 ---
   纵向：#page-account 原来没有高度约束，内容区 .purple-account-body 虽然写了 overflow-y:auto，
   却跟着表格一起长高（20 行订单就 3000+px），外层 #page_games 是 overflow:hidden，
   超出屏幕的部分直接被裁掉、滚不动。跟 #page-game 同一个做法（style.css 的 #page-game.d-flex）：
   页面容器 overflow:hidden，flex 子项的 min-height 就按 0 算、被压回屏幕高度，
   内容区才真正在自己内部滚动。
   横向：两张表的容器原来是 overflow:hidden，窄屏下列被压扁、日期折成两行，
   放不下的直接裁掉。改成容器内横向滚动，表格给一个最小宽度（= 各列宽之和），
   列不再被挤压，宽屏下表格照常撑满、不出现滚动条。 */
.theme-purple #page-account.d-flex {
	overflow: hidden;
	min-height: 0;
}
.theme-purple .purple-account,
.theme-purple .purple-account-body {
	min-height: 0;
}
.theme-purple .purple-account-pane .order-table-container,
.theme-purple .purple-account-pane .balance-table-container {
	overflow-x: auto !important;
	overflow-y: hidden !important;
}
/* 订单表 7 列宽之和：80 + 150 + 100 + 300 + 100 + 100 + 100 */
.theme-purple .purple-account-pane .order-table { min-width: 930px; }
.theme-purple .purple-account-pane .balance-table { min-width: 760px; }

/* 搜索框：.order-search-input 只有 (0,1,0)，压不过第 6 节那条
   .theme-purple input[type="text"] (0,2,1)!important，于是输入框自己带上了
   --purple-elevated 底色和圆角，在外层那个本来就有底色的胶囊里又套了一层。
   这个冲突在弹窗时代就存在，搬到页面上更显眼。用 (0,4,0) 压回透明。 */
.theme-purple .purple-account-pane .order-search-input-group .order-search-input {
	background: transparent !important;
	border: none !important;
	border-radius: 0 !important;
	height: auto !important;
}
/* 两张表的标题原来是弹窗里居中的大字，这里跟其它子页的标题统一成左对齐 */
.theme-purple .purple-account-pane .order-list-header,
.theme-purple .purple-account-pane .balance-history-header {
	align-items: flex-start !important;
}
.theme-purple .purple-account-pane .order-list-title,
.theme-purple .purple-account-pane .balance-history-title {
	text-align: left !important;
	width: 100%;
}

/* ============================================================
   31. Shop 顶部工具条（排序下拉）+ 顶栏购物车小圆点
   ============================================================
   参考界面 Shop 页顶部只有一个靠右的排序下拉；原来那条
   「N items in cart + Checkout + Reset」已删（两个功能分别由顶栏购物车图标
   和结算弹窗里的 Clear all 承接），数量提示收敛成顶栏图标上的小圆点。 */
/* 排序下拉要跟左边「SHOP」标题同处一行。
   标题那块 .menu-header 带 my-4：外边距 24 + 自身高 + 外边距 24，
   自身高就是标题的 line-height。工具条取同样的总高 + 垂直居中，
   两边中线自然对齐，而且不管排序按钮本身多高都成立。
   【改标题字号时这个数要跟着改】：标题 13px(lh 22) 时是 24+27+24=75；
   现在标题 20px(lh 34)，是 24+34+24=82。上次漏了这一步，两边差了 3px。 */
.theme-purple .shop-toolbar {
	height: 82px;
	padding: 0 16px;
	width: 100%;
	align-items: center;
}

.theme-purple .purple-sort {
	position: relative;
}
.theme-purple .purple-sort-trigger {
	gap: 8px;
	height: 36px;             /* 跟左边的分段控件取齐，不再由内容擑 */
	padding: 0 12px;
	background: var(--purple-elevated);
	border: none;
	border-radius: var(--purple-r-btn);
	color: var(--purple-text-oncard);
	font-family: var(--purple-font);
	font-size: 13px;
	cursor: pointer;
	white-space: nowrap;
}
.theme-purple .purple-sort-trigger:hover { color: var(--purple-text-strong); }
.theme-purple .purple-sort-trigger:focus { outline: none; }
.theme-purple .purple-sort-trigger svg { width: 14px; height: 14px; flex-shrink: 0; }

.theme-purple .purple-sort-menu {
	position: absolute;
	right: 0;
	top: calc(100% + 6px);
	z-index: 30;
	min-width: 170px;
	padding: 4px;
	background: var(--purple-elevated);
	border: 1px solid var(--purple-border);
	border-radius: var(--purple-r-btn);
	/* 软件渲染下不用 blur 做投影 */
	box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45);
}
/* display 不写 !important：v-show 隐藏靠内联 display:none */
.theme-purple .purple-sort-option {
	display: block;
	width: 100%;
	padding: 7px 10px;
	background: transparent;
	border: none;
	border-radius: var(--purple-r-chip);
	color: var(--purple-text);
	font-family: var(--purple-font);
	font-size: 13px;
	text-align: left;
	cursor: pointer;
	white-space: nowrap;
}
.theme-purple .purple-sort-option:hover { background: var(--purple-panel); color: var(--purple-text-strong); }
.theme-purple .purple-sort-option:focus { outline: none; }
.theme-purple .purple-sort-option.is-active { background: var(--purple-accent); color: #FFFFFF; }

/* 顶栏购物车小圆点。
   点是 absolute 的，必须给它的父级 <a> 一个 position:relative——否则它会去贴
   最近的定位祖先（顶栏本身），跑到屏幕最右边去。那个 <a> 在 layout.htm 里加了
   purple-cart-link 这个类名专门用来挂定位。 */
.theme-purple .purple-cart-link {
	position: relative;
}
.theme-purple .purple-cart-link .purple-cart-dot {
	position: absolute;
	top: -2px;
	right: -2px;
	width: 7px;
	height: 7px;
	border-radius: 50%;
	background: var(--purple-success);
}

/* 加进购物车时顶栏购物车闪两下（对照参考界面 04 号录屏 8.33s~10.00s）。
   逐帧量出来的时间轴：峰值 #E1E21F 亮黄绿 → 谷值 #2F6F4D 暗绿 → 第二个峰 → 衰减回常态，
   全程 1670ms，两个峰分别落在 0ms 和 780ms、各持续约 220ms。
   做法是叠两层伪元素、只动画 opacity，不在 keyframes 里改 background-color：
   客户端 libcef 是 --disable-gpu 跑的，改背景色要逐帧 repaint，改 opacity 有快速路径。
   ::before 是谷值那层暗绿，整段亮着、末尾淡出；::after 是峰值那层亮黄绿，闪两次。
   谷值单靠一层亮黄绿调 opacity 混不出来——#E1E21F 压在常态底色上偏黄，
   实测谷值是偏纯的绿，所以必须两层。 */
.theme-purple .purple-cart-link::before,
.theme-purple .purple-cart-link::after {
	content: '';
	position: absolute;
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	border-radius: inherit;
	opacity: 0;
	pointer-events: none;
}
.theme-purple .purple-cart-link::before { background: #2F6F4D; }
.theme-purple .purple-cart-link::after { background: #E1E21F; }
/* 图标和小圆点要压在两层色块之上。
   svg 是 static 的，光给 z-index 不生效，得先 position: relative；
   小圆点本来就是 absolute，给 z-index 就够，别在这里重写它的 position。 */
.theme-purple .purple-cart-link > svg {
	position: relative;
	z-index: 1;
}
.theme-purple .purple-cart-link .purple-cart-dot { z-index: 1; }

.theme-purple .purple-cart-link.is-cart-flash::before { animation: purple-cart-dim 1670ms ease-out 1; }
.theme-purple .purple-cart-link.is-cart-flash::after { animation: purple-cart-peak 1670ms ease-out 1; }

@keyframes purple-cart-dim {
	0%, 85% { opacity: 1; }
	100% { opacity: 0; }
}
@keyframes purple-cart-peak {
	0%, 8% { opacity: 1; }
	20%, 40% { opacity: 0; }
	46%, 54% { opacity: 1; }
	66%, 100% { opacity: 0; }
}
/* 高亮期间图标要压深。参考界面整段高亮里图标都比底色暗（实测 #254525~#102219，
   取中间的深绿），不是我们常态那个浅灰蓝——浅灰压在亮黄绿上几乎看不见。
   这里用 transition 不用 keyframes：参考界面图标在整段高亮里颜色基本不变，
   只在首尾各切换一次，transition 正好对应，比逐帧改 color 省得多。 */
.theme-purple .purple-cart-link > svg {
	transition: color 220ms ease;
}
.theme-purple .purple-cart-link.is-cart-flash > svg {
	color: #16301E;
}

/* Games 页内容区跟 Shop 对齐。
   Games 的工具条外面套了两层 Bootstrap .container，每层带 15px 左右内边距，
   一共让内容区比 Shop 窄了 30px——Shop 那层是 px-0。侧栏左边在 1600，
   Shop 的内容右边界 1584（留 16px），Games 是 1554，白多出一截。
   :not(.p-4) 是为了放过第三层——那层是卡片区自己的 24px 内边距，不能一起清掉。 */
/* 卡片区那层的左右内边距收成 16，跟 Shop 那边卡片的 p-3 一致。
   它原本是 p-4（24px），会让 Games 的内容右边缘比 Shop/Offers 缩进 8px。
   上下仍保持 24，只动左右。 */
.theme-purple #page-game .container.p-4 {
	padding-left: 16px !important;
	padding-right: 16px !important;
}

.theme-purple #page-game .container:not(.p-4) {
	padding-left: 0 !important;
	padding-right: 0 !important;
}

/* --- 31.1 Games 页工具条：授权筛选分段按钮 + 排序 ---
   排序下拉复用 Shop 那套 .purple-sort（两页共用同一份样式）。
   工具条高度同样取 75px，好跟左栏「GAMES」标题中线对齐。 */
.theme-purple .game-toolbar {
	/* 跟 .shop-toolbar 同一个算法：24 + 标题 line-height 34 + 24 */
	height: 82px;
	padding: 0 16px;
	width: 100%;
}

/* 分段按钮：参考界面是三段连体，激活段填主题色 */
/* 高度跟右边的排序下拉对齐。原来高度是内容擑出来的：
   内按钮 25.6 + 上下各 3px = 31.6，而 .purple-sort-trigger 是 36.1，差 4.5px，
   两个控件上下边对不齐。这里两边都写死 36px。
   内边距 3 → 4：激活那个洋红块原来四周只剩 3px，贴得太紧。
   内圆角随之改成 5px（= 外圆角 9 − 内边距 4），这样嵌套的弧才同心。 */
.theme-purple .purple-segment {
	background: var(--purple-elevated);
	border-radius: var(--purple-r-btn);
	height: 36px;
	padding: 4px;
	gap: 2px;
}
.theme-purple .purple-segment-btn {
	height: 28px;             /* 36 − 上下各 4 */
	padding: 0 12px;
	/* 改用 flex 居中：以后再调高度或行高，文字和钥匙图标都不会跑偏 */
	display: inline-flex;
	align-items: center;
	justify-content: center;
	background: transparent;
	border: none;
	border-radius: 5px;
	color: var(--purple-text);
	font-family: var(--purple-font);
	font-size: 12px;
	line-height: 1.3;
	white-space: nowrap;
	cursor: pointer;
}
.theme-purple .purple-segment-btn:hover { color: var(--purple-text-strong); }
.theme-purple .purple-segment-btn:focus { outline: none; }
.theme-purple .purple-segment-btn.is-active {
	background: var(--purple-accent);
	color: #FFFFFF;
}
/* License 那一档前面的钥匙，跟卡片左上角授权角标同一个字形（fa-key），
   这样「按 License 筛出来的」和「卡片上带钥匙的」对得上 */
.theme-purple .purple-segment-icon {
	margin-right: 6px;
	font-size: 11px;
}

/* --- 31.2 侧栏会话块合并后的补充样式 ---
   原来「Time left 大字」和「offer 轮播里的 remaining」显示的是同一个数（在用
   那个 offer 的剩余时间），两块还被 Favorites 隔开。现在轮播并进会话块，
   在用那一屏不再重复时间，改显一个 In use 标签。 */

/* 时间前的时钟图标（对照参考界面） */
.theme-purple .purple-time-icon {
	flex-shrink: 0;
	margin-right: 8px;
	color: var(--purple-text-muted);
	/* 时间大字是 28px/34px，图标的圆环要跟数字高度差不多，
	   原来那个 18px 的 SVG（可见圆环只有 15.5px）明显偏小 */
	font-size: 24px;
	line-height: 1;
}
/* 「· hh:mm」格式提示跟标签同色同字号，靠 .purple-label 自己的样式即可 */

/* My offers 数字旁边的切换计费按钮（从原轮播行挪过来） */
.theme-purple .purple-offer-switch {
	margin-left: 8px;
	width: 24px;
	height: 24px;
	flex-shrink: 0;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	background: rgba(var(--purple-accent-rgb), 0.10);
	border: 1px solid var(--purple-border);
	border-radius: 5px;
	color: var(--purple-accent);
	font-size: 14px;
	font-weight: 700;
	line-height: 1;
	cursor: pointer;
}
.theme-purple .purple-offer-switch:hover { background: rgba(var(--purple-accent-rgb), 0.18); }
.theme-purple .purple-offer-switch:focus { outline: none; }

/* 在用标记：占住那一屏右侧，避免跟其它屏一有时间一没时间、参差不齐。
   display 不写 !important——v-show 靠内联 display:none 生效 */
.theme-purple .purple-offer-inuse {
	display: inline-flex;
	align-items: center;
	padding: 2px 8px;
	background: var(--purple-elevated);
	border-radius: var(--purple-r-chip);
	color: var(--purple-success);
	font-size: 11px;
	line-height: 1.3;
	white-space: nowrap;
}

/* 轮播并进会话块后，上面不再需要自己的上外边距 */
.theme-purple .purple-session-merged-offers {
	margin-top: var(--purple-sp-3);
}

/* --- 31.3 会话块压缩 ---
   原来这块 172px：费率独占一行（22 + 上下留白 = 32px），翻页箭头跟进度条同行
   把那行撑到按钮高度 28px（条本身只有 6px）。
   费率并进时间行、箭头挪到名称行之后，进度条行只剩细条。 */

/* 费率跟在大字时间后面当小字 */
.theme-purple .purple-time .user-price-info {
	margin-left: 10px;
	color: var(--purple-text-muted);
	font-size: 12px;
	line-height: 1;
	flex-shrink: 0;
}
.theme-purple .purple-time .user-price-info label {
	margin: 0 2px 0 0;
	font-size: 12px;
	font-weight: 400;
}
.theme-purple .purple-time .user-price-info .currency {
	margin-right: 2px;
}

/* 名称行：左箭头 → 名称 → 时间/In use → 右箭头 */
.theme-purple .vip-info-row {
	gap: 8px;
}
.theme-purple .vip-info-row .vip-arrow {
	flex-shrink: 0;
}
.theme-purple .vip-info-row .vip-label {
	flex: 1 1 auto;
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	/* 原来是从父级继承来的居中——那是这块还是独立一栏时的样子。
	   现在并进会话块，上面 Time left / 大字时间全是左对齐，它必须跟齐 */
	text-align: left;
}

/* 进度条行：箭头挪走之后只剩细条，高度按条本身算 */
.theme-purple .vip-progress-row {
	min-height: 0;
}
.theme-purple .vip-progress-row .vip-progress-bar-container {
	flex: 1 1 auto;
	margin: 0;
}
/* offers 区跟上面的时间行贴近一点；同时清掉左右内边距——
   style.css:2659 给了 padding:8px 12px!important，导致 offer 名称和进度条
   比上面的 Time left / My offers 整体内缩 16px，左右都对不齐。
   权重上有两条要压，第二条是坑：
     :is(#page-game,...) .vip-progress-section        (1,1,0)!important  padding 8px 12px
     :is(#page-game,...) #offers_div                  (2,0,0)!important  padding 0 16px 12px 16px
   后者才是那 16px 的真凶——:is() 的权重取参数里最高的那个（这里是 ID），
   再加上 #offers_div 就是两个 ID。所以必须自己也带上那串 :is() 才压得过。 */
.theme-purple #offers_div.vip-progress-section,
.theme-purple :is(#page-game, #page-shop, #page-rank, #page-event, #page-home, #page-account, #purple-sidebar) #offers_div {
	margin: 6px 0 0 0 !important;
	padding: 0 !important;
}

/* ============================================================
   32. 游戏详情页
   ============================================================
   对照参考界面：标题行（返回 + 名称 + 授权钥匙）→ 左海报 + 右操作区，
   操作按钮带文字，下面一条分隔线，再下面是分类 chip。
   原来是钥匙/收藏星叠在海报右上角、右边一排只有图标的小圆钮。 */
/* 详情页不套卡片底：参考界面的详情是平铺在页面底色上的，没有一块浅色圆角面板。
   而且同一个页面的列表态本来也没有卡片底（游戏卡直接铺在背景上），
   只有详情态多出这么一块，两态切换时会看到一块面板凭空出现。
   左右内边距归零（模板上的 p-5 只保留上下）—— 外层几层 container 已经垫出 70px，
   再加 48 就是 118，比参考界面的留白宽一倍。 */
.theme-purple .purple-detail {
	background: transparent;
	border-radius: 0;
	padding-left: 0 !important;
	padding-right: 0 !important;
	padding-top: var(--purple-sp-5) !important;
}
.theme-purple .purple-detail-head {
	gap: 12px;
}
.theme-purple .purple-detail-title {
	color: var(--purple-text-strong);
	font-family: var(--purple-font);
	font-size: 22px;
	font-weight: 500;
}
/* 授权钥匙：跟列表卡片左上角那枚同色同字形，只是挪到标题后面 */
.theme-purple .purple-detail-key {
	width: 26px;
	height: 26px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	border-radius: var(--purple-r-chip);
	background: var(--purple-accent);
	color: #FFFFFF;
	font-size: 12px;
}

.theme-purple .purple-detail-poster {
	width: 240px;
	flex-shrink: 0;
	border-radius: var(--purple-r-card);
	object-fit: cover;
	aspect-ratio: 7 / 10;   /* 跟列表卡片一样按海报素材 168x240 的比例，不裁海报 */
}
.theme-purple .purple-detail-main {
	padding-left: var(--purple-sp-5);
	min-width: 0;
}
.theme-purple .purple-detail-actions {
	gap: 10px;
}

/* 动作按钮：主操作实心，其余描边 */
.theme-purple .purple-detail-btn {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	padding: 10px 18px;
	background: transparent;
	border: none;
	border-radius: var(--purple-r-btn);
	color: var(--purple-text-oncard);
	font-family: var(--purple-font);
	font-size: 14px;
	line-height: 1.2;
	white-space: nowrap;
	cursor: pointer;
}
.theme-purple .purple-detail-btn:hover { color: var(--purple-text-strong); }
.theme-purple .purple-detail-btn:focus { outline: none; }
.theme-purple .purple-detail-btn.is-primary {
	background: var(--purple-accent);
	color: #FFFFFF;
}
.theme-purple .purple-detail-btn.is-primary:hover { opacity: 0.9; color: #FFFFFF; }
.theme-purple .purple-detail-btn.is-danger { color: var(--purple-warning); }
.theme-purple .purple-detail-btn .fa-star.is-on { color: var(--purple-accent); }

.theme-purple .purple-detail-divider {
	margin: var(--purple-sp-4) 0;
	height: 1px;
	background: var(--purple-border);
}
/* 分类 chip */
.theme-purple .purple-detail-tags {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
}
.theme-purple .purple-detail-tag {
	padding: 6px 14px;
	background: var(--purple-elevated);
	border-radius: var(--purple-r-chip);
	color: var(--purple-text);
	font-size: 13px;
}

/* --- 32.1 游戏卡片 hover 操作区 ---
   曾经把居中的两个圆钮收成右下角一个小图标（主操作改成整卡可点），
   用户要求按 blue 主题的原样子保留 Play + 发密码两个按钮，已整段撤回。
   现在这块完全走基线 style.css（.overlay .btn 的洋红圆钮），没有主题覆盖。 */


/* ============================================================
   33. 顶栏与下方内容区的分层
   ============================================================
   参考界面里顶栏是一条平的、略亮的面，下方内容区明显更暗，
   两者之间有干净的色阶。我们原来顶栏确实是 --purple-surface(#1C202A)，
   但下方直接露出网吧壁纸原图（core.js 把 cafe_info_cafe_login 写成
   .theme-body 的内联 background-image），壁纸亮的地方比顶栏还亮，
   色阶就没了，顶栏与内容区糊在一起。

   为什么落在 #games 而不是 .theme-body：
   ① 壁纸是内联样式，CSS 改不动（也拿不到那个动态 URL）；
   ② 用 ::before/::after 做浮层行不通——.theme-body 不是堆叠上下文，
      z-index:-1 的伪元素会归到根堆叠上下文的负层，反而跑到壁纸下面去（实测无效），
      改成 z-index:0 又会把非定位的子元素盖住；
   ③ inset box-shadow 是元素自己背景绘制的一部分，画在背景图之上、内容之下，
      不碰堆叠顺序；而 #games 又只在登录后的 layout 里，登录页不受影响
      （网吧自己选的登录背景图不该被我们压暗）。
   顶栏的 .header-area 是 position:relative，画在定位层，不会被这层盖到。
   软件渲染下这是一块纯色实心矩形（blur 为 0），开销跟一个背景色一样。 */
.theme-purple #games {
	box-shadow: inset 0 0 0 100vmax rgba(18, 18, 26, 0.62);
}

/* ============================================================
   34. News widget 的新闻卡
   ============================================================
   改前：图片 h-100 m-auto 居中浮在卡里，不擑宽；图下面什么都没有，
   widget 下半截空白。参考界面是一张完整的卡：上半媒体擑满宽，
   下半一块深色文字区，标题在上、日期钉在底。
   注：参考界面标题下还有两行正文，我们 table_icafe_news 没这个字段，没做。 */
.theme-purple .purple-widget-news .purple-widget-body {
	display: flex;
}
/* 基线在 HTML 上带了 mr-5 / py-4 / col-12，把卡挤得比 widget 窄一大截 */
.theme-purple .purple-widget-news .home-news {
	flex: 1 1 auto;
	min-height: 0;
	width: 100% !important;
	max-width: 100% !important;
	margin: 0 !important;
	padding: 0 !important;
	background: transparent !important;
	border: none !important;
	display: flex;
}
.theme-purple .purple-widget-news .carousel,
.theme-purple .purple-widget-news .carousel-inner,
.theme-purple .purple-widget-news .carousel-item.active {
	flex: 1 1 auto;
	min-height: 0;
	width: 100%;
	height: 100%;
}
.theme-purple .purple-news-card {
	display: flex;
	flex-direction: column;
	height: 100%;
	border-radius: var(--purple-r-card);
	overflow: hidden;
	background: var(--purple-panel);
}
/* 媒体区：固定 16:9，宽度擑满卡片 */
.theme-purple .purple-news-media {
	position: relative;
	flex: 0 0 auto;
	width: 100%;
	/* 不是 16:9：CP 的新闻图是用 <canvas width=500 height=260> 裁出来的（settings-news.htm:147），
	   按 16:9 会把上下各裁掉一截；用原比例就不会裁 */
	aspect-ratio: 500 / 260;
	overflow: hidden;
	background: var(--purple-elevated);
}
.theme-purple .purple-news-media .purple-news-img,
.theme-purple .purple-news-media iframe,
.theme-purple .purple-news-media .video-box {
	width: 100% !important;
	height: 100% !important;
	object-fit: cover;
	margin: 0 !important;
	display: block;
}
/* 文字区：吃掉剩余高度，日期靠 margin-top:auto 钉在底部 */
.theme-purple .purple-news-meta {
	flex: 1 1 auto;
	min-height: 0;
	display: flex;
	flex-direction: column;
	padding: var(--purple-sp-4);
}
.theme-purple .purple-news-title {
	/* 父层带了 text-center，参考界面是左对齐 */
	text-align: left;
	color: var(--purple-text-strong);
	font-family: var(--purple-font);
	font-size: 15px;
	font-weight: 600;
	line-height: 20px;
	/* 长标题最多两行，再长省略 */
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}
.theme-purple .purple-news-date {
	text-align: left;
	margin-top: auto;
	padding-top: var(--purple-sp-3);
	color: var(--purple-text-muted);
	font-size: 12px;
	line-height: 16px;
}
/* 轮播点：原来在卡下方占一行，看着像条分割线；改成压在媒体右下角 */
.theme-purple .purple-widget-news .carousel-indicators {
	top: auto;
	bottom: 14px;
	left: auto;
	right: 16px;
	margin: 0;
	z-index: 3;
}

/* ============================================================
   35. 左下角电源/重启按钮
   ============================================================
   运行中游戏条（.bottom-section，60px）改成没游戏时不占位后，
   内容区伸到了视口底，这对按钮就压在内容上了（它们一直是
   position:fixed + z-index:9999 的悬浮层，只是以前恰好落在那条空带里）。
   基线背景是 rgba(23,23,32,0.25)，压在亮底的商品图上基本看不清，
   改成不透明实底 + 描边，跟列表那对翻页箭头同一种处理。 */
.theme-purple .feedback-icon a.power-button,
.theme-purple .feedback-icon a.reboot-button {
	background: var(--purple-surface);
	border: 1px solid var(--purple-border);
	border-radius: var(--purple-r-btn);
}
.theme-purple .feedback-icon a.power-button:hover,
.theme-purple .feedback-icon a.reboot-button:hover {
	background: var(--purple-elevated);
	/* 基线这里是 scale(1.1)，软件渲染下静态 transform 没问题，保留 */
}

/* ============================================================
   34. 手写图标（Games / Shop）
   ============================================================
   定义在 layout.htm 开头的 <symbol>，这里只管尺寸和颜色。
   因为两个图标用同一个 24x24 画布、墨迹已在 SVG 里对齐，
   所以这里只需给一个尺寸，不再需要像以前那样逐个 transform: scale() 修正。 */
.theme-purple .purple-ico {
	display: inline-block;
	flex-shrink: 0;
	color: inherit;
	vertical-align: middle;
}
/* 顶栏：原来 .menu-icon 是 33x24 的字形框，换成 SVG 后直接给正方形 */
.theme-purple .header-section .header-menu .menu-icon-link .purple-ico.menu-icon {
	width: 26px !important;
	height: 26px !important;
}
/* 页面标题旁的图标，跟 20px 的标题字号配 */
.theme-purple .purple-ico.menu-header-icon {
	width: 24px;
	height: 24px;
}
/* 首页 widget 头部，跟 14px 标题配 */
.theme-purple .purple-ico.purple-widget-ico {
	width: 18px;
	height: 18px;
}

/* ============================================================
   35. 顶栏高度与搜索框位置
   ============================================================
   两边都按 1918 宽量的：
     顶栏高   参考 57   我们 68
     搜索框   参考 x1325→1540（69%→80%）215x30
               我们 x1018→1318（53%→69%）300x40  —— 偏左、偏大
   参考界面的搜索框是紧贴右侧状态区的，不是悬在中间。 */
.theme-purple .header-section .header-area {
	height: var(--purple-topbar-h) !important;
	/* 右侧状态区是绝对定位的、不占 flex 位，要手工给它留出宽度。
	   实测右侧区距右边缘 403，再给搜索框留 ~47 的间隙 → 450。
	   【值写在 layout.htm 的内联 style 里】：那里是 inline !important，
	   比样式表的 !important 还高一级，写在这里压不过它。 */
}
/* 顶栏是 fixed，内容区靠这个 padding 让位 */
.theme-purple #games {
	padding-top: var(--purple-topbar-h) !important;
}
/* 搜索框收窄收矮，向参考界面的 215x30 靠 */
.theme-purple .header-search > .position-relative {
	width: 240px !important;
}
.theme-purple .header-search .header-search-input {
	height: 32px !important;
	font-size: 13px !important;
}

/* ============================================================
   36. Offers 页：列表
   ============================================================
   参考界面这一页是「一行一条」的列表，不是卡片网格。一行五段：
   时长缩略卡 | 名称 + 起始 | 有效时段 | 价格 | 购买按钮。
   （之前做成了带 hover 翻转的卡片网格——那是首页 Offers widget 的样式，
     已挪回 §36.3，这里不再有翻转。） */

/* 左侧分类栏整列收起：参考界面 Offers 页没有分类栏，内容从最左开始。
   inline style 的 width:252px 没有 !important，这里的 !important 压得住。 */
/* 整列收起。两处在用：Offers 模式的商品分类栏、游戏详情页的游戏分类栏。
   选择器要写得比 §22 那条 `:is(#page-game, #page-shop) > .d-flex.flex-column.flex-shrink-0`
   更specific：`:is()` 取参数里最高的那一个（ID），那条是 (1,4,0) 且带 !important，
   只写 `.shop-category-menu.purple-col-collapsed`(0,3,0) 压不住它的 padding-left:48px。
   border-box 下 width 不会小于 padding，那 48px 就是收不干净的原因。
   这里同样套一层 :is()，算出来是 (1,5,0)，刚好压过它。 */
.theme-purple :is(#page-game, #page-shop) > .d-flex.flex-column.flex-shrink-0.purple-col-collapsed {
	width: 0 !important;
	/* flex 子项的 min-width 默认 auto（= min-content），只写 width:0 一样收不干净 */
	min-width: 0 !important;
	padding: 0 !important;
	overflow: hidden;
}

/* --- 36.1 页头：标题 + 两个 tab --- */
.theme-purple .purple-offers-head {
	display: flex;            /* 不写 !important：v-show 要靠内联 display:none 生效 */
	flex-direction: column;
	justify-content: center;
	gap: var(--purple-sp-2);
	margin-right: auto;       /* 把页头顶到左边，右边的排序下拉不动 */
}
.theme-purple .purple-offers-title {
	display: flex;
	align-items: center;
	gap: var(--purple-sp-2);
	color: var(--purple-text-strong);
	font-size: 20px;
	line-height: 24px;
	letter-spacing: 0.02em;
}
.theme-purple .purple-offers-title .purple-ico { width: 24px; height: 24px; }
.theme-purple .purple-offers-tabs { display: flex; gap: var(--purple-sp-2); }
.theme-purple .purple-offers-tab {
	height: 28px;
	padding: 0 14px;
	border: 0;
	border-radius: var(--purple-r-chip);
	background: var(--purple-panel);
	color: var(--purple-text-muted);
	font-size: 12px;
	line-height: 1;
	cursor: pointer;
}
.theme-purple .purple-offers-tab:focus { outline: none; }
.theme-purple .purple-offers-tab:hover { color: var(--purple-text); }
.theme-purple .purple-offers-tab.is-active {
	background: var(--purple-elevated);
	color: var(--purple-text-strong);
}

/* --- 36.2 列表本体 --- */
/* 外层是一块带描边的面板，里面一行一条，行之间靠 gap 分开（参考界面就是这样，
   不是表格线）。display 不写 !important——v-show 要压得住。 */
/* 左右留白：内容列本身离窗口边 / 离右侧栏各 16px，这里再加 32，合计 48 ——
   跟 Shop / Games 页标题图标的 x=48 取齐（那两页的左栏 padding-left 就是 48），
   参考界面的 Offers 页留白也是这个量级，而且左右对称。
   只写 16 的话左边只有 32，比别的页窄一截，右边看着也比左边宽。
   选择器要带 #product-list：blue 继承下来的 `#product-list>div{padding-right:15px}`
   是 (1,0,1)，`.theme-purple .purple-offers-page`(0,2,0) 压不住，右边会少 1px 且跟标题错开。 */
.theme-purple #product-list > .purple-offers-page {
	display: block;
	/* #product-list 在商品模式下是 Grid（见 style.css 的 auto-fill 那条），
	   Offers 这块是整宽面板、不是卡片，不跨列的话会被当成一列、宽度被压到
	   minmax 的下限。grid-column 在非 grid 的父容器下是惰性的，所以两种模式都安全。 */
	grid-column: 1 / -1;
	/* 左右内边距跟商品卡的 p-3 对齐（16px），原来是 sp-6=32px，
	   会让 offer 行的右边缘比商品卡缩进 16px、两页对不齐 */
	padding: 0 16px;
}
/* 不再套一层外框：参考界面就是一排行卡直接铺在页面底色上，
   没有「外层面板 + 内层卡」两级。这里只保留纵向排布和行间距。 */
.theme-purple .purple-offers-panel {
	display: flex;
	flex-direction: column;
	gap: var(--purple-sp-2);
}
/* 一行 = 一个五列网格。
   缩略卡固定宽；名称和时段两列可伸缩；价格列右对齐、宽度跟内容走；按钮固定。
   ⚠️ minmax(0, …) 是必需的：grid 列默认 min-width:auto，长名称会把列撑开、
      把右侧价格挤出容器，text-truncate 也就失效了。 */
.theme-purple .purple-offer-row {
	display: grid;
	/* 六列：缩略卡 | 名称 | 有效时段 | 弹性空隙 | 价格 | 按钮。
	   前三列给固定上限而不是 fr —— 参考界面里名称/分区/有效时段是往左挤在一起的，
	   富余宽度全留在价格前面。写成 fr 的话名称列会按比例摊开（2149px 宽时实测
	   撑到 733px），有效时段被推到行正中，跟参考界面差很多。
	   第 4 列那个 1fr 就是那段空隙，没有对应的子元素，所以价格和按钮要显式指定列号。
	   价格写死 130px 是为了让各行的前几列对齐（auto 的话每行价格字数不同就错位）。 */
	grid-template-columns: 76px minmax(0, 220px) minmax(0, 280px) 1fr 130px 36px;
	align-items: center;
	gap: var(--purple-sp-4);
	/* 参考界面一行约 60px 高，12px 的上下内边距会做到 70 */
	padding: 10px var(--purple-sp-4);
	background: var(--purple-surface);
	border-radius: 10px;
}
.theme-purple .purple-offer-row:hover { background: var(--purple-panel); }

/* 时长缩略卡：跟首页 Offers widget 同一套暖褐渐变 + 时钟水印，缩小版 */
.theme-purple .purple-offer-thumb {
	position: relative;
	display: flex;
	align-items: baseline;
	justify-content: center;
	gap: 3px;
	width: 76px;
	height: 40px;
	border-radius: var(--purple-r-chip);
	background: linear-gradient(135deg, #554341 0%, #3B342D 100%);
	overflow: hidden;
}
/* 复用 §27.2 的 .purple-offer-clock，但那套尺寸是给大卡的，这里压小并居左 */
.theme-purple .purple-offer-thumb .purple-offer-clock {
	left: -10px;
	width: 52px;
	height: 52px;
	opacity: 0.10;
}
.theme-purple .purple-offer-thumb-v {
	position: relative;
	z-index: 1;
	color: var(--purple-text-strong);
	font-size: 18px;
	line-height: 1;
	font-weight: 500;
}
.theme-purple .purple-offer-thumb-u {
	position: relative;
	z-index: 1;
	color: var(--purple-text-oncard);
	font-size: 10px;
	line-height: 1;
}
/* My offers 那栏放的是 hh:mm，20px 太挤 */
.theme-purple .purple-offer-thumb-time { font-size: 15px; }

.theme-purple .purple-offer-cell { min-width: 0; }
.theme-purple .purple-offer-rname {
	color: var(--purple-text-strong);
	font-size: 14px;
	line-height: 18px;
	font-weight: 500;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}
.theme-purple .purple-offer-rsub {
	margin-top: 3px;
	color: var(--purple-text-muted);
	font-size: 11px;
	line-height: 14px;
	white-space: nowrap;
}
/* 「Now」用绿色，跟首页卡和参考界面一致——绿是状态语义（立即可用），不是品牌色 */
.theme-purple .purple-offer-rsub .purple-offer-now { color: var(--purple-success); }
/* 只有「现在就能用」那档全大写（参考界面就是 NOW）；换成具体时刻时不大写 */
.theme-purple .purple-offer-now.is-now { text-transform: uppercase; }
.theme-purple .purple-offer-rclock {
	width: 12px;
	height: 12px;
	margin-left: 4px;
	vertical-align: -1px;
	color: var(--purple-warning);
}
.theme-purple .purple-offer-rlabel {
	color: var(--purple-text-muted);
	font-size: 11px;
	line-height: 14px;
}
.theme-purple .purple-offer-rvalue {
	margin-top: 3px;
	color: var(--purple-text-oncard);
	font-size: 13px;
	line-height: 16px;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}
.theme-purple .purple-offer-cell-price {
	grid-column: 5;
	text-align: right;
}
.theme-purple .purple-offer-buy { grid-column: 6; }
.theme-purple .purple-offer-rprice {
	color: var(--purple-text-strong);
	font-size: 14px;
	line-height: 18px;
	font-weight: 500;
	white-space: nowrap;
}
/* 划掉的原价。参考界面是暗红色，比正文更弱 */
.theme-purple .purple-offer-rwas {
	margin-top: 2px;
	color: var(--purple-danger);
	font-size: 11px;
	line-height: 14px;
	text-decoration: line-through;
	opacity: 0.75;
	white-space: nowrap;
}
.theme-purple .purple-offer-buy {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 36px;
	height: 36px;
	padding: 0;
	border: 0;
	border-radius: var(--purple-r-btn);
	background: var(--purple-gradient-primary);
	/* 图标用的是 currentColor，这里不给白色就会继承外面的深色文字色。
	   原先那张 cart.png 是白色位图、不吃 color，换成内联 SVG 后才暴露出来。 */
	color: #FFFFFF;
	cursor: pointer;
}
.theme-purple .purple-offer-buy:focus { outline: none; }
.theme-purple .purple-offer-buy:hover { filter: none; opacity: 0.88; }
.theme-purple .purple-offer-buy svg { width: 18px; height: 18px; flex-shrink: 0; }

/* My offers 沿用「可购买」那套 6 列，不再另开一套 —— 两个 tab 切换时
   缩略卡和名称列不会跳。参考界面这两栏的第 3、4 列是「作用分区 / 有效时段」，
   我们拿不到分区名，那块空间给剩余时间进度条用。 */
.theme-purple .purple-offer-row-mine .purple-offer-cell-bar { grid-column: 3 / 5; }
/* 启用按钮里的播放三角 */
.theme-purple .purple-offer-play { width: 16px; height: 16px; }

/* My offers 那栏的剩余时间条 */
.theme-purple .purple-offer-cell-bar { display: flex; align-items: center; }
.theme-purple .purple-offer-bar {
	width: 100%;
	height: 6px;
	border-radius: var(--purple-r-pill);
	background: var(--purple-elevated);
	overflow: hidden;
}
.theme-purple .purple-offer-bar > i {
	display: block;
	height: 100%;
	border-radius: var(--purple-r-pill);
	background: var(--purple-gradient-primary);
}

.theme-purple .purple-offers-empty {
	padding: var(--purple-sp-5) 0;
	color: var(--purple-text-muted);
	font-size: 13px;
	text-align: center;
}

/* ============================================================
   36.3 首页 Offers widget：hover 翻面
   ============================================================
   参数是从官方 GIF（verified-player-shell/…-03，1920x910，10fps）逐帧量的：
   翻面发生在**首页的 Passes widget**上（不是 Offers 页），过渡只占 2 帧 ≈ 200ms，
   中间帧有透视压缩 —— 是绕 Y 轴的真 3D 旋转，不是淡入淡出。
   正面：大号时长 + 右上 Starts in + 左下价格；背面：名称 + 有效时段。

   软件渲染（CEF --disable-gpu）下这是一次性的 200ms transition，只在 hover
   的那一张卡上跑，不是循环 keyframes，开销有界；不加 will-change —— GPU 合成
   已禁用，它只会多造一个软件合成层。 */
/* 高度写死：两个面都是 absolute，不参与父元素高度计算，父元素不给高就塌成 0。
   120 是量出来的最坏情况——窗口窄时正面的「Starts in: Thu 23:00」会折成两行，
   104 装不下，价格那行会被 .purple-offer-card 的 overflow:hidden 切掉。
   真机 2559 宽时这一行不折行，多出来的空间由 space-between 分掉。 */
.theme-purple .purple-offer-flip {
	position: relative;
	height: 120px;
	perspective: 700px;
}
.theme-purple .purple-offer-flip-inner {
	position: relative;
	width: 100%;
	height: 100%;
	transform-style: preserve-3d;
	transition: transform 0.2s ease;
}
.theme-purple .purple-offer-flip:hover .purple-offer-flip-inner {
	transform: rotateY(180deg);
}
.theme-purple .purple-offer-face {
	position: absolute;
	inset: 0;
	backface-visibility: hidden;
	-webkit-backface-visibility: hidden;
}
/* 整张卡在翻，内层不要再跟着变透明（§26.2 那条 hover 降不透明度在这儿多余） */
.theme-purple .purple-offer-flip .purple-offer-card:hover { opacity: 1; }
/* 背面：参考界面是平底深色、没有纹理，要盖掉正面那条暖褐渐变 */
.theme-purple .purple-offer-face-back {
	transform: rotateY(180deg);
	/* 用 panel 不用 surface：surface 跟 widget 底色相同，翻过去就看不出是张卡了 */
	background: var(--purple-panel) !important;
	display: flex;
	flex-direction: column;
	justify-content: center;
	gap: var(--purple-sp-1);
}
.theme-purple .purple-offer-back-title {
	color: var(--purple-text-strong);
	font-size: 14px;
	font-weight: 500;
	line-height: 17px;
}
.theme-purple .purple-offer-back-label {
	color: var(--purple-text-muted);
	font-size: 11px;
	line-height: 14px;
}
.theme-purple .purple-offer-back-value {
	color: var(--purple-text-oncard);
	font-size: 13px;
	line-height: 16px;
}
/* 正面的大号时长（参考界面卡面主体就是它，不是名称）。
   单位小一号、跟数字基线对齐。 */
.theme-purple .purple-offer-dur {
	position: relative;
	z-index: 1;
	display: flex;
	align-items: baseline;
	gap: 5px;
	color: var(--purple-text-strong);
	margin: 2px 0 6px;
}
.theme-purple .purple-offer-dur-v { font-size: 26px; line-height: 30px; font-weight: 500; }
/* 单位用中性白：官方图里「5 h」的 h 是淡灰白，不带蓝；
   --purple-text-oncard 是 #C9D9FF，放在暖褐卡上偏蓝，跟数字割裂 */
.theme-purple .purple-offer-dur-u { font-size: 12px; color: rgba(255, 255, 255, 0.72); }
/* 卡面价格：折后价在上，原价划掉在下 */
.theme-purple .purple-offer-was {
	position: relative;
	z-index: 1;
	margin-top: 2px;
	color: var(--purple-danger);
	font-size: 11px;
	line-height: 14px;
	text-decoration: line-through;
	opacity: 0.75;
}

/* ============================================================
   37. 锁屏遮罩
   ============================================================
   #page_lock 本来就铺满全屏、z-index 999，挡得住点击，但它自己没有底色
   （.formDiv 全项目只有一条响应式规则，不带 background），
   底下那一整页登录表单会原样透出来 —— 看得见、点不动。
   给它一层半透明压暗底就够了：登录页还在（一片全黑更吓人），但一眼能看出是
   被锁住的不可用状态，锁屏文案也才压得住底下的内容。

   0.70 是比出来的：0.82 以上登录面板几乎看不见，跟直接隐藏没区别；
   0.60 以下压不住底下的按钮，锁屏文案读起来费劲。
   尺寸保持铺满全屏不变 —— 它同时负责拦点击（elementFromPoint 在输入框位置
   返回的是这一层），只盖右半边的话左边那些按钮就真能点了。 */
.theme-purple #page_lock {
	background: rgba(10, 11, 16, 0.70);
}

/* ============================================================
   38. 侧栏纵向密度
   ============================================================
   窗口矮一点侧栏就出滚动条。逐块量下来，空白不在内容上，在分隔和内外边距：
     · member-sidebar 里 5 条 .purple-divider，每条 = 1px 线 + 上下各 16px 外边距 = 33px，
       光分隔线就占掉 165px
     · 会员卡自身上下各 24px 内边距
     · 钱包行 8px 上外边距 + 8px 上下内边距（来自 style.css:3017，带 !important）
     · 订单行 6px 上下内边距
   这里统一收一档。不动任何内容尺寸 —— 字号、图标、头像、进度条都没碰，
   只是把留白压薄。 */
.theme-purple .purple-divider {
	margin: 10px 0;
}
.theme-purple .user-info-card {
	padding: var(--purple-sp-4);
}
/* style.css:3017 的 `.user-info-card > .user-stat-wallet` 带 !important、(0,2,1)，
   这里多带一个类提到 (0,3,0) 才压得住 */
/* 横向归零：这一行背景是透明的（style.css 那条注释写「全宽深色背景条」，但实际没设
   background），12px 只会让钱包图标比下面 Last order 的图标右 12px，跟左边对不齐 */
.theme-purple .user-info-card > .user-stat-wallet {
	padding: 4px 0 !important;
	margin-top: 0 !important;
}
.theme-purple .purple-last-order {
	padding: 3px 0;
}
/* 再往下压就不是留白的事了：.shop-section 有 min-height:256px（促销轮播那张图的
   尺寸决定的），rank-section 是 flex:1 会自己吃掉剩余空间 —— 改它们里面的外边距
   只是把空白在框内挪位置，侧栏总高一点不变（试过，撤回了）。 */

/* --- 38.1 侧栏第一屏要能看到 News ---
   2K 屏开 125% / 150% 缩放时，客户端实际可用高度只有 1152 / 960，News 被挤出第一屏
   （150% 时差 174px）。除了把 Lucky Spin 改成图标、去掉一条分割线（约 81px），还有两处：
   ① 底栏 .purple-sidebar-footer 是 position:fixed 钉在视口底部的（约 71px 高），
      滚动容器却没给它留位置，最下面那段内容一直被它盖着。容器底部留出同样的高度。
      原规则是 style.css 的 :is(...) > .bd-highlight.rounded.p-4.border-block.flex-shrink-0
      { padding: 0 !important }，权重 (1,5,0)，这里带上全部类名才压得过。
   ② News 图片原来固定 200px 高（316 宽，比例 1.58，比原图 1.92 高，左右被裁）。
      改成吃掉剩余空间，并且始终保持原图比例 500:260（CP settings-news.htm 用 canvas 裁成这个尺寸）：
      高度在 100~160px 之间随可用空间伸缩，宽度按比例跟着变、居中显示，图片永远完整不裁切。
      160 ≈ 满宽 316 ÷ 1.923 再留几像素余量，再高宽度就放不下、会被 max-width 截成非原比例。矮窗口下图会变小、两侧留空，
      比「铺满宽度、上下裁掉 40%」好——新闻图多是网吧自己做的宣传图，字常贴着边。 */
.theme-purple #purple-sidebar > .member-sidebar.bd-highlight.rounded.p-4.border-block.flex-shrink-0 {
	padding-bottom: 72px !important;
}
.theme-purple #purple-sidebar .sidebar-section.rank-section {
	flex: 1 1 auto;
	min-height: 0;
}
.theme-purple #purple-sidebar .news-content.active {
	flex: 1 1 auto;
	min-height: 0;
}
.theme-purple #purple-sidebar .news-carousel-wrapper {
	flex: 1 1 0;
	min-height: 100px;
	max-height: 160px;
	align-items: stretch !important;   /* 让轮播容器被拉伸到 wrapper 的高度，百分比高度才有参照 */
	justify-content: space-between !important;   /* 箭头贴两边，图片在中间 */
}
.theme-purple #purple-sidebar .news-carousel-wrapper .news-arrow {
	align-self: center;
}
.theme-purple #purple-sidebar .news-carousel-container,
.theme-purple #purple-sidebar #game_carousel_news {
	height: auto !important;
	/* 高度由 wrapper 拉伸决定，宽度按原图比例反推；只有一条新闻（没有箭头）时靠 margin 居中 */
	flex: 0 0 auto;
	width: auto !important;
	aspect-ratio: 500 / 260;
	max-width: 100%;
	margin: 0 auto !important;
}
/* ③ 分割线上下留白 20 → 12。侧栏里 4 条分割线每条连留白占 41px，收紧后共省 64px。
   客户端窗口不最大化时（带标题栏）可用高度只有 ~925，光靠 ①② 不够。
   ④ 新闻指示点上方 20 → 10。 */
.theme-purple #purple-sidebar .purple-divider {
	margin-top: 2px !important;
	margin-bottom: 2px !important;
}
.theme-purple #purple-sidebar .rank-section .news-indicators {
	margin-top: 10px !important;
}

/* ============================================================
   39. 独立的右侧会员面板 #purple-sidebar
   ============================================================
   全局只有一份（layout.htm 的 <aside id="purple-sidebar">），不再嵌在各页面里。
   原来每页各一份，高度受页面容器摆布：只有 #page-game/#page-shop 带
   overflow:hidden（flex 子项的 min-height 因此按 0 算，被压在 #games 里），
   Event/Rank/Account/Home 的容器按内容撑开，侧栏跟着撑高，
   overflow-y:auto 永远不触发 —— 窗口一矮这几页的侧栏就滚不动。

   现在侧栏钉在视口右侧，自己定高、自己滚，跟当前页无关。
   它替代了 layout.htm 里原来那两块 fixed 垫层（实底面板 + 左边 1px 分隔线）。 */
.theme-purple #purple-sidebar {
	position: fixed;
	top: var(--purple-topbar-h);
	right: 0;
	bottom: 0;
	width: 400px;
	/* 低于顶栏（1000），高于内容区；页脚的语言下拉在侧栏自己的层叠上下文里抬高 */
	z-index: 1;
	/* 参考图右侧面板与顶栏同色（v9.4.2 实测都是 #1C202B），所以用 surface 而不是 panel */
	background: var(--purple-surface);
	/* 左边 1px 分隔线：画在侧栏外侧，不占宽度，位置与原来那条 fixed 线相同（right:400px）。
	   面板改成与顶栏同色后，原来用 surface 画的线就看不见了，换成参考图那条竖线的颜色 */
	box-shadow: -1px 0 0 var(--purple-elevated);
}
/* 滚动容器是 .member-sidebar 本身（style.css 的 :is(...) > .bd-highlight... 那条给了
   overflow-y:auto 并藏掉滚动条），这里给它定高 */
.theme-purple #purple-sidebar > .member-sidebar {
	height: 100%;
}
/* 内容区在右边让出侧栏的宽度。
   Games/Shop 原来在内容和侧栏之间有 16px 的 flex gap，侧栏移走后 gap 没了，
   用 padding-right 补回，内容宽度与改前一致 */
.theme-purple #games {
	padding-right: 400px;
}
.theme-purple :is(#page-game, #page-shop).d-flex {
	padding-right: 16px;
}
