:root{
  /* 颜色令牌统一在 /shared/css/theme.css（三个端共用一份：深色 / 浅色 / 将来更多配色）。
     这里只留**尺寸**类令牌 —— 别把颜色再写回来，否则新配色漏掉 C 端。 */
  --radius:12px;
  /* 移动端底部导航的内容高度（不含 iOS 安全区）。短视频页算舞台高度要用它，
     所以底部栏自己也按这个值定高，避免两边各写一个魔数、改一处忘一处。 */
  --nav-h:60px;
}
*{box-sizing:border-box;margin:0;padding:0}
html,body{height:100%}
/* 关掉 iOS Safari 的「文本自动放大」（text autosizing）：
   它会在宽视口下按块宽度把正文字号**成倍放大**（典型表现就是"真机比 Chrome 模拟器大一圈、
   看着臃肿"），而且只在真机上发生、桌面模拟器复现不出来。全站字号由下面的刻度统一决定，
   不接受浏览器再插一手。 */
html{-webkit-text-size-adjust:100%;text-size-adjust:100%}
/* 页面底：基础色 +（可选）极淡的品牌 wash 渐变。
   --page-wash 在深色下就是 none（所以深色零变化），浅色/玫粉下给一层很淡的渐变 ——
   这是"氛围感"的主要来源（对标站的页底也是浅紫 wash 而不是纯色）。 */
body{background-color:var(--bg);background-image:var(--page-wash,none);background-repeat:no-repeat;
  background-attachment:fixed;background-size:100% 100%;color:var(--text);font-family:"Microsoft YaHei","PingFang SC",-apple-system,Segoe UI,Roboto,Arial,sans-serif;font-size:14px;line-height:1.6}
a{color:inherit;text-decoration:none}
img{display:block}
button{font-family:inherit;cursor:pointer}
input,textarea,select{font-family:inherit;font-size:14px;background:var(--bg2);color:var(--text);border:1px solid var(--line);border-radius:8px;padding:9px 12px;outline:none;width:100%}
input:focus,textarea:focus,select:focus{border-color:var(--brand)}
textarea{resize:vertical;min-height:80px}

/* 顶栏 */
.topbar{position:sticky;top:0;z-index:50;display:flex;align-items:center;gap:18px;height:60px;padding:0 20px;background:var(--glass);backdrop-filter:blur(10px);border-bottom:1px solid var(--line)}
.brand{display:flex;align-items:center;gap:8px;font-weight:800;font-size:18px;background:var(--grad-brand);-webkit-background-clip:text;background-clip:text;color:transparent;white-space:nowrap}
.brand .logo{font-size:22px;color:var(--brand2);-webkit-text-fill-color:var(--brand2)}
.nav{display:flex;gap:4px;flex:1;flex-wrap:wrap}
.nav a{padding:8px 14px;border-radius:9px;color:var(--muted);font-weight:600}
.nav a:hover{color:var(--text);background:var(--card)}
.nav a.active{color:#fff;background:var(--grad-brand);box-shadow:0 2px 10px var(--glow,transparent)}
/* margin-left:auto：移动端顶栏的导航是隐藏的（.nav 是唯一的 flex:1 元素），
   没有这一行的话「外观按钮 / 金币 / 头像」会紧贴在品牌名后面，而不是待在右上角。 */
.top-right{display:flex;align-items:center;gap:10px;white-space:nowrap;margin-left:auto}
.btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;border:none;border-radius:12px;padding:9px 16px;font-weight:700;background:var(--card2);color:var(--text);transition:.15s}
.btn:hover{filter:brightness(1.12)}
.btn.primary{background:linear-gradient(135deg,var(--brand-fill,var(--brand)),var(--brand2));color:#fff}
.btn.accent{background:var(--accent);color:#04231c}
.btn.danger{background:var(--danger);color:#fff}
.btn.ghost{background:transparent;border:1px solid var(--line);color:var(--muted)}
.btn.sm{padding:5px 10px;font-size:12px;border-radius:7px}
.btn:disabled{opacity:.5;cursor:not-allowed}

/* 布局 */
.layout{max-width:1200px;margin:0 auto;padding:20px}
.grid{display:grid;gap:18px}
.grid.videos{grid-template-columns:repeat(auto-fill,minmax(220px,1fr))}
.grid.topics{grid-template-columns:repeat(auto-fill,minmax(180px,1fr))}
.grid.team{grid-template-columns:repeat(auto-fill,minmax(240px,1fr))}
.card{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);overflow:hidden}
.card.pad{padding:18px}
.card.clickable{cursor:pointer;transition:.15s}
.card.clickable:hover{transform:translateY(-3px);border-color:var(--brand)}

/* 视频卡片 */
.vcard .thumb{position:relative;aspect-ratio:16/9;background:var(--card2)}
/* 封面加载失败（外链过期 / 防盗链 403）：JS 把 img 移除后给一块有辨识度的底，
   而不是留一个和「正在加载」分不清的纯色块。 */
.thumb.thumb-nocover{background:linear-gradient(135deg,var(--card2),#1a2030)}
.vcard .thumb img{width:100%;height:100%;object-fit:cover}
/* 网格卡片封面「两段式加载」：静态小图先铺满（本站几十 KB，秒到），动态封面（来源站的
   循环小视频 / GIF）随后在后台下载，加载完淡入盖上去 —— 速度与动感都要。
   动图元素由 views.js 的 coverAnim* 按「滚进视口 + 网络分档 + 一屏上限」懒建，没轮到
   或建不出来的卡片就停在静态封面，永远不会是一块黑。z-index:0 是刻意的：它压得住
   底下那张在正常流里的静态图，又压不过后面那层的播放键与时长标签（它们 z-index 是
   auto、按文档顺序排在动图之后）。 */
.thumb .thumb-anim{position:absolute;inset:0;z-index:0;display:block;pointer-events:none}
.thumb .thumb-anim video,.thumb .thumb-anim img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block;opacity:0;transition:opacity .45s ease}
.thumb .thumb-anim video.on,.thumb .thumb-anim img.on{opacity:1}
.vcard .meta{padding:10px 12px 12px}
.vcard .meta h3{font-size:14px;font-weight:700;margin-bottom:6px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
/* 信息行：任何机型都必须一行放完（小屏旧机也不折行）。
   整行 nowrap；信息段可收缩、溢出打省略号兜底；VIP 徽标固定在最右、不参与压缩。
   四个元素（类别 / 播放 / 点赞 / 会员）的占位都刻意收窄，其中会员徽标最轻。

   详情页 `.vt-row` 共用同一套排版 —— 详情页也只有这一行信息（分类 / 播放 / 点赞 / 时长），
   区别只在「没有 VIP 徽标同行、可用宽度更大」，所以只在字号和分类截断宽度上放宽一点。 */
.vcard .meta .row,.vt-row{display:flex;align-items:center;flex-wrap:nowrap;gap:6px;overflow:hidden;color:var(--muted);font-size:12px}
.vcard .meta .row .vrow-info,.vt-row .vrow-info{flex:1 1 auto;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.vcard .meta .row .vrow-info i,.vt-row .vrow-info i{font-style:normal;margin:0 3px;opacity:.5}
/* 分类名可截断（后台能自由新增长分类），但最长只占 3 个字宽 ——
   320px 老机型上信息行可用宽度只有约 98px（播放/点赞两个数字要占 ~67px），
   分类再宽就会把数字挤掉。生产分类都是 2 个字，这条只是长分类的兜底。 */
.vcard .meta .row .vcat,.vt-row .vcat{color:hsl(var(--cat-h,265) var(--cat-s,72%) var(--cat-l,74%));display:inline-block;max-width:3em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:bottom}
/* ---- 详情页信息行：比卡片行宽松，字号也提一档（它是这一屏的主信息） ---- */
.vt-row{margin-top:10px;gap:7px;font-size:13px}
/* 详情页整行独占屏宽，分类不必压到 3em；给到 8em 仍然保证三个数字留得住 */
.vt-row .vcat{max-width:8em}
/* 点赞：看着是普通文字，实际是个可点的内联控件（保留点赞这个真实功能） */
.vt-row .vlike{background:none;border:none;padding:0;margin:0;font:inherit;color:inherit;cursor:pointer;line-height:inherit}
.vt-row .vlike:hover{color:var(--text)}
/* 标题：从原先的大标题 + 副标题两段，压成「只有标题、最多两行」
   （副标题那一块已按需求撤下），字号也比原来小一档 */
.vt-title{font-size:17px;font-weight:700;line-height:1.45;margin:12px 0 0;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.tag{display:inline-block;padding:2px 8px;border-radius:20px;background:var(--brand);font-size:11px;color:#fff}
.badge{display:inline-block;padding:2px 8px;border-radius:20px;font-size:11px;font-weight:700}
.badge.vip{background:linear-gradient(135deg,#f7b733,#fc4a1a);color:var(--on-vip,#fff)}
.badge.free{background:linear-gradient(135deg,#34d399,var(--accent));color:var(--on-accent,#04231c)}
.badge.agent{background:var(--warn);color:#3a2300}
.badge.admin{background:var(--danger);color:#fff}
.badge.coin{background:linear-gradient(135deg,#ffd166,#ffab2e);color:#3a2b00}
.badge.off{background:var(--card2);color:var(--muted)}
/* 封面右下角的时长/人数胶囊：**白字**。
   原来是金色 #ffd166，问题有两个：
     ① 封面左上刚把会员角标改成金色，两个金色互相抢眼，金色就不再等于「VIP」了；
     ② 浅色封面（白底、雪景）上金色最吃亏 —— 实测对比度 6.0:1，白字 8.6:1，
        深色封面上则分别是 13.9:1 / 20.0:1。两者都过 AA，但白字在浅封面上高出一档半。
   对标站点（v7.mscmsx.com）的时长也是白字，改完这块与它一致。
   注：这条同时用于长视频时长与直播卡观看人数，两处都是中性数据，统一白字更整齐。 */
.thumb-badge{position:absolute;right:8px;bottom:8px;background:rgba(0,0,0,.7);color:#fff;padding:2px 8px;border-radius:6px;font-size:12px;font-weight:700}
/* 会员角标：压在封面**左上角**（对标站点就是这一枚）。
   金→橙渐变 + 白粗体；亮封面（白背景、雪景那类）上仍要看得清，
   所以额外给一层浅色描边 + 投影，而不是只靠渐变本身。
   位置从「信息行最右端」搬到封面：信息行因此腾出约 26px ——
   320px 老机型上分类名不再被挤成省略号（见 .vrow-info 那几条注释）。 */
.vcard .thumb-vip{position:absolute;left:8px;top:8px;z-index:2;padding:2px 7px;border-radius:6px;
  font-size:11px;font-weight:800;letter-spacing:.3px;line-height:1.35;
  background:linear-gradient(135deg,#f7b733,#fc4a1a);color:#fff;
  box-shadow:0 0 0 1px rgba(255,255,255,.55),0 1px 6px rgba(0,0,0,.32)}
.play{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:52px;height:52px;border-radius:50%;background:rgba(108,92,231,.9);display:flex;align-items:center;justify-content:center;font-size:20px;color:#fff;opacity:0;transition:.15s}
.vcard:hover .play{opacity:1}

/* 短视频信息流 */
/* 短视频页包裹层：桌面高度 = 视口 − 桌面顶栏(60px)；移动端在下面的媒体查询里
   让开底栏与安全区。包裹层负责**定高与居中**，舞台只管填满它。 */
.short-wrap{height:calc(100vh - 60px);display:flex;flex-direction:column;align-items:center;background:#000}
.short-stage{height:100%;display:flex;justify-content:center;background:#000}
.short-panel{position:relative;height:100%;max-width:420px;width:100%}
.short-item{position:relative;height:100%;width:100%}
/* 只认主角 <video>：预载用的隐藏 <video> 也挂在同一个容器里，不能让它一起铺满 */
.short-item video.sv-main{width:100%;height:100%;object-fit:cover}
.short-preload{position:absolute;left:-9999px;top:0;width:1px;height:1px;overflow:hidden;opacity:0;pointer-events:none}
.short-preload video{width:1px;height:1px}
/* 锁定态封面层：竖版短视频封面 / 16:9 长视频封面都用 cover 铺满各自的框。
   存在的唯一目的 —— 别让用户对着一块纯黑发呆，至少看得出这是什么片子。 */
.short-poster,.player-poster{position:absolute;inset:0;z-index:1;overflow:hidden;background:linear-gradient(160deg,#241a3d,#141021 55%,#07070b)}
.short-poster img,.player-poster img{position:absolute;inset:0;z-index:1;width:100%;height:100%;object-fit:cover;display:block}
/* 两段式封面：小图先顶上把画面填满，原图加载完成再淡入覆盖（速度 → 画质）。
   两张图叠在同一层里，后插的 .poster-full 天然压在小图之上；原图拿不到（外链
   签名过期 / 404）时 onerror 直接隐藏，留下的仍是一张有内容的封面而不是黑屏。 */
.short-poster .poster-full,.player-poster .poster-full{opacity:0;transition:opacity .35s ease}
.short-poster .poster-full.on,.player-poster .poster-full.on{opacity:1}
/* 覆盖层是「循环小视频」时（来源站的动态封面现在给 .mp4，不再给 gif）：
   视频放不进 <img>，得自己铺满并压在底图之上；静音与 playsinline 由标签属性负责。 */
.short-poster video.poster-full,.player-poster video.poster-full{position:absolute;inset:0;z-index:2;width:100%;height:100%;object-fit:cover;display:block}
.short-poster .ph,.player-poster .ph{position:absolute;inset:0;z-index:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;color:#b9b1d6;font-size:34px}
.short-poster .ph small,.player-poster .ph small{font-size:12px;letter-spacing:.05em;opacity:.85}
/* 底部信息区：控件常驻、标题起播 3 秒后**真正收起来**（高度也收掉，不再占位置）。
   底部留白要给固定定位的「上一条 / 下一条」让位，别让两者叠在一起。 */
.short-ui{color:#fff;position:absolute;left:0;right:0;bottom:0;z-index:3;padding:16px 16px 66px;display:flex;flex-direction:column;gap:10px}
/* 标题块：按需求去掉了原来那层半灰渐变遮罩，可读性改由文字投影保证 */
.short-meta{
  max-height:180px; overflow:hidden;
  transform-origin:left bottom;
  transition:max-height .38s cubic-bezier(.4,0,.2,1), opacity .26s ease,
             transform .38s cubic-bezier(.4,0,.2,1);
}
/* 收起态：不只是淡出 —— 高度收到 0，下面的控件顺势上移，不再有那块空位 */
.short-meta.hide{max-height:0; opacity:0; transform:translateY(12px); pointer-events:none}
.short-ui h3{margin-bottom:4px;text-shadow:0 1px 8px rgba(0,0,0,.7)}
.short-ui .short-meta .flex{text-shadow:0 1px 6px rgba(0,0,0,.65)}
/* 短视频播放控件：播放 / 暂停 + 进度 + 时间 */
.short-ctl{display:flex;align-items:center;gap:10px;padding:0 2px}
.short-ctl .ctl-btn{width:36px;height:36px;flex:0 0 36px;border:0;border-radius:50%;color:#fff;font-size:13px;display:flex;align-items:center;justify-content:center;background:rgba(255,255,255,.2);backdrop-filter:blur(6px);cursor:pointer}
.short-bar{position:relative;flex:1;height:4px;border-radius:2px;background:rgba(255,255,255,.28);overflow:hidden}
.short-bar i{display:block;height:100%;width:0;border-radius:2px;background:linear-gradient(90deg,#ffb020,#ff6b3d);transition:width .2s linear}
.short-ctl .ctl-time{font-size:12px;color:#e9e5f5;font-variant-numeric:tabular-nums;white-space:nowrap}
.short-actions{position:absolute;right:10px;bottom:120px;z-index:3;display:flex;flex-direction:column;gap:16px;align-items:center}
.short-actions button,
.short-actions .short-author{background:transparent;border:none;color:#fff;display:flex;flex-direction:column;align-items:center;gap:2px;font-size:12px}
.short-actions .ico{width:44px;height:44px;border-radius:50%;background:rgba(0,0,0,.4);display:flex;align-items:center;justify-content:center;font-size:20px}
/* 作者那一项的图标位放圆形头像：尺寸吃满 .ico，和上面三个圆形图标严格同宽同高、同一条中轴 */
.short-actions .ico-avatar{background:none;overflow:hidden}
.short-actions .ico-avatar .avatar{width:100%;height:100%;font-size:17px}
/* 作者的 @名字比「声音 / 分享」长得多：单行显示，放不下才省略号。
   68px 正好容下「@兰陵笑笑生」这个长度的名字，换个更长的也不会撑破操作栏。 */
.short-actions b{
  max-width:68px;font-size:11px;font-weight:600;text-align:center;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
/* 声音开关按下的状态：点亮成主色，一眼看出「现在是开着声音的」 */
.short-actions .ico.on{background:rgba(108,92,231,.9)}

/* 播放器 */
.player-wrap{position:relative;background:#000;border-radius:14px;overflow:hidden;aspect-ratio:16/9}
/* ---------- 旋转全屏（横版视频在竖屏手机上转 90° 铺满）----------
   为什么需要：内核自带的"全屏"只放大不旋转，横版视频在竖屏手机上必然上下大黑边。
   按钮只在横版视频上出现（见 views.js 的 landscapeOf）。
   三层策略见 views.js；这里是最底层（CSS 旋转）的样式：
   视频元素自己旋转 90°，所以用 left/top 50% + translate(-50%,-50%) 对齐屏幕中心；
   尺寸由 JS 按视口交换后写死（移动端 100vh/100vw 会被地址栏高度抖动影响，不能靠它）。 */
.pv-rot-btn{position:absolute;right:10px;top:10px;z-index:3;display:none;width:34px;height:34px;
  border:0;border-radius:50%;background:rgba(0,0,0,.45);color:#fff;cursor:pointer;
  align-items:center;justify-content:center;padding:0}
.pv-rot-btn.on{display:flex}
.pv-rot-btn:hover{background:rgba(0,0,0,.62)}
body.pv-rotating{overflow:hidden}
.pv-rotate{position:fixed;left:0;top:0;z-index:9999;background:#000;overflow:hidden}
.pv-rotate video{position:absolute;left:50%;top:50%;max-width:none;max-height:none;
  transform:translate(-50%,-50%) rotate(90deg);object-fit:contain;background:#000}
.pv-rotate .pv-rot-close{position:absolute;right:14px;top:14px;z-index:3;width:36px;height:36px;
  border:0;border-radius:50%;background:rgba(0,0,0,.5);color:#fff;cursor:pointer;
  display:flex;align-items:center;justify-content:center;padding:0}
.pv-rotate .pv-rot-bar{position:absolute;left:0;right:0;bottom:0;height:3px;z-index:3;background:rgba(255,255,255,.18)}
.pv-rotate .pv-rot-bar i{display:block;height:100%;width:0;background:var(--accent)}
.player-wrap video{width:100%;height:100%}
/* 遮罩从「整块死黑」改成中间深、边缘浅的径向渐变：文字区域够暗看得清，封面又能透出来 */
.player-overlay{position:absolute;inset:0;z-index:2;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:14px;background:radial-gradient(105% 70% at 50% 50%,rgba(6,4,12,.78),rgba(6,4,12,.46) 62%,rgba(6,4,12,.68));text-align:center;padding:24px;text-shadow:0 1px 4px rgba(0,0,0,.85)}
/* 锁定态文案压在任意封面上都要看得清：不用灰字（糊在亮封面上），改用浅白 + 阴影 */
.player-overlay .muted{color:#e9e5f5}
.player-overlay h2{font-size:22px}
.paywall{display:flex;gap:10px;flex-wrap:wrap;justify-content:center}
/* 锁定页的「分享赚金币」：低权重小链接，不跟主出口抢注意力（锁定页要够简洁） */
.lock-minor{color:var(--ink-soft);font-size:12.5px;text-decoration:none;opacity:.85}
.lock-minor:hover{opacity:1;text-decoration:underline}

/* 起播闸门：长视频与短视频共用同一套出口。
   可播放态也一样铺封面 —— <video> 拿到地址并不会自己画第一帧，没有封面就是一块纯黑
   （用户反馈的「线上详情页黑乎乎」就是这条路径）。整块闸门可点，点了才拉流起播。 */
.play-gate{position:absolute;inset:0;z-index:2;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;cursor:pointer}
.play-big{width:76px;height:76px;border:0;border-radius:50%;color:#fff;font-size:30px;line-height:1;display:flex;align-items:center;justify-content:center;cursor:pointer;
  background:linear-gradient(135deg,#ffb020,#ff6b3d);box-shadow:0 10px 30px rgba(255,120,40,.5);animation:gatePulse 2.2s ease-out infinite}
.play-big span{margin-left:5px}      /* 让三角在圆里视觉居中 */
.play-big:active{transform:scale(.94)}
.play-hint{color:#fff;font-size:13px;letter-spacing:.08em;text-shadow:0 1px 6px rgba(0,0,0,.8)}
@keyframes gatePulse{
  0%{box-shadow:0 10px 30px rgba(255,120,40,.5),0 0 0 6px rgba(255,255,255,.18)}
  70%{box-shadow:0 10px 30px rgba(255,120,40,.5),0 0 0 24px rgba(255,255,255,0)}
  100%{box-shadow:0 10px 30px rgba(255,120,40,.5),0 0 0 6px rgba(255,255,255,0)}
}
/* 播放真的开始 → 封面与闸门一起淡出，把画面和原生控件交还用户 */
.player-wrap .player-poster,.player-wrap .play-gate,
.short-item .short-poster,.short-item .play-gate{transition:opacity .3s ease}
.player-wrap.playing .player-poster,.player-wrap.playing .play-gate,
.short-item.playing .short-poster,.short-item.playing .play-gate{opacity:0;pointer-events:none}

/* 表单 */
.form-card{max-width:420px;margin:40px auto;background:var(--card);border:1px solid var(--line);border-radius:16px;padding:28px}
.form-card h1{font-size:22px;margin-bottom:20px;text-align:center}
.field{margin-bottom:14px}
.field label{display:block;margin-bottom:6px;color:var(--muted);font-size:13px}
.hint{color:var(--muted);font-size:12px;margin-top:6px}
.err{color:var(--danger);font-size:13px;min-height:18px}

/* 列表/表 */
.list-item{display:flex;align-items:center;gap:14px;padding:14px 16px;border-bottom:1px solid var(--line)}
.list-item:last-child{border-bottom:none}
.avatar{width:38px;height:38px;border-radius:50%;background:linear-gradient(135deg,var(--brand),var(--brand2));display:flex;align-items:center;justify-content:center;font-weight:800;color:#fff;flex-shrink:0}
.avatar.sm{width:30px;height:30px;font-size:13px}
table{width:100%;border-collapse:collapse}
th,td{padding:10px 12px;text-align:left;border-bottom:1px solid var(--line);font-size:13px}
th{color:var(--muted);font-weight:600;font-size:12px}

/* 统计卡 */
.stat-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:14px;margin-bottom:20px}
.stat{background:var(--card);border:1px solid var(--line);border-radius:12px;padding:16px}
.stat .num{font-size:26px;font-weight:800;margin-top:4px}
.stat .lbl{color:var(--muted);font-size:12px}

/* 社区 */
.post-card{margin-bottom:16px}
.post-body{padding:16px}
.post-images{display:grid;grid-template-columns:repeat(auto-fill,minmax(120px,1fr));gap:8px;margin-top:10px}
.post-images img{width:100%;aspect-ratio:1;object-fit:cover;border-radius:8px}
.post-actions{display:flex;gap:18px;margin-top:12px;color:var(--muted)}
.post-actions button{background:none;border:none;color:var(--muted);display:flex;align-items:center;gap:5px}
.post-actions button.liked{color:var(--danger)}
.comment{margin-top:12px}
.comment-item{display:flex;gap:10px;padding:10px 0;border-top:1px solid var(--line)}
.comment-item .cname{font-size:12px;color:var(--muted)}

/* 直播 */
.live-card .live-badge{position:absolute;left:8px;top:8px;background:var(--danger-fill,var(--danger));color:#fff;font-size:11px;padding:2px 8px;border-radius:6px;display:flex;align-items:center;gap:4px}
.live-dot{width:7px;height:7px;border-radius:50%;background:#fff;animation:pulse 1.2s infinite}
@keyframes pulse{50%{opacity:.3}}

/* 营销气泡 */
.bubble-ticker{position:fixed;left:20px;bottom:20px;z-index:60;max-width:320px}
.bubble{background:var(--bubble-bg);border:1px solid var(--line);border-radius:16px;padding:12px 16px;margin-bottom:8px;box-shadow:0 8px 24px var(--c-bubble-shadow,var(--bubble-shadow));animation:slidein .4s}
@keyframes slidein{from{transform:translateY(20px);opacity:0}}
.bubble .b-name{color:var(--accent-ink);font-weight:700}   /* 亮薄荷压白底只有 ~2.9:1，浅色下用 --accent-ink */

/* 转盘 */
.wheel{position:relative;width:280px;height:280px;margin:0 auto}
.wheel svg{width:100%;height:100%}
.wheel .spin-btn{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:76px;height:76px;border-radius:50%;background:linear-gradient(135deg,var(--brand),var(--brand2));color:#fff;font-weight:800;border:none;font-size:14px}

/* Toast
   z-index 必须高于任何遮罩层：否则提示会被压在蒙版 + backdrop-filter 模糊下面，看起来「糊成一团」。 */
#toast-root{position:fixed;left:50%;bottom:30px;transform:translateX(-50%);z-index:1300;display:flex;flex-direction:column;gap:8px;align-items:center;pointer-events:none}
.toast{background:var(--toast-bg);color:var(--toast-fg,#fff);padding:11px 18px;border-radius:10px;box-shadow:0 6px 20px var(--c-shadow,var(--shadow));animation:slidein .25s;font-size:14px;font-weight:600;line-height:1.5;max-width:min(600px,calc(100vw - 32px));border:1px solid var(--line-soft-16);pointer-events:auto}
/* 错误提示必须是「深红底 + 纯白粗体」，原因同后台端（旧写法白字压亮红底看不清） */
.toast.err{background:#b81723;color:#fff;border-color:rgba(255,255,255,.30)}
.toast.ok{background:var(--accent);color:#04231c;border-color:rgba(0,0,0,.12)}

.muted{color:var(--muted)}
.flex{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.between{justify-content:space-between}
.mt8{margin-top:8px}.mt12{margin-top:12px}.mt20{margin-top:20px}
.section-title{font-size:18px;font-weight:800;margin:22px 0 14px;display:flex;align-items:center;gap:10px;position:relative;padding-bottom:9px}
/* 区块标题下的品牌短横（对标目标站的做法）：绝对定位，所以不会破坏"图标 + 文字"的 flex 行 */
.section-title::after{content:"";position:absolute;left:0;bottom:0;width:18px;height:3px;border-radius:2px;background:var(--grad-brand)}
.chips{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:16px}
.chip{padding:6px 14px;border-radius:999px;background:var(--card);border:1px solid var(--line);color:var(--muted);cursor:pointer;font-size:13px}
.chip.active{background:var(--brand-fill,var(--brand));color:#fff;border-color:var(--brand-fill,var(--brand))}
/* 分类筛选条（C 端长视频列表）：分类会越加越多，窄屏下原来是「一行横滑」——后面的
   分类看不见、也没有任何提示。这里改成折行，最多 3 行，超出用「更多」展开 / 收起。
   .chips.cat-chips 的权重高于后面媒体查询里的 .chips，所以能压掉那条 nowrap 横滑。 */
.cat-fold{position:relative}
.chips.cat-chips{flex-wrap:wrap;overflow:hidden}
.chips.cat-chips.folded{margin-bottom:6px}
.chips-more{margin:0 0 16px;padding:5px 13px;border-radius:20px;background:transparent;
  border:1px dashed var(--line);color:var(--muted);font-size:12px;cursor:pointer;line-height:1.5}
.chips-more:hover{color:var(--text);border-color:var(--brand)}
.chips-more[hidden]{display:none}
.empty{text-align:center;color:var(--muted);padding:60px 20px}
.hero{background:var(--c-hero-bg);border-radius:18px;padding:34px;margin-bottom:8px;border:1px solid var(--hero-line);position:relative;overflow:hidden}
.hero h1{font-size:28px;margin-bottom:8px}
.hero p{color:var(--hero-fg);max-width:560px}
.hero .btn{margin-top:14px}

/* ================= 玫粉主题的动效（A 形态：只有光影，没有粒子） =================
   三条设计约束（照讨论里定的来）：
   ① 只给玫粉（[data-theme="rose"]）且用户没关（[data-fx="on"]）—— 深色/浅色保持完全静态；
   ② 尊重"减少动效"：系统开了 prefers-reduced-motion 就整段不生效（也顺带让逐像素回归
      拿到确定性的截图 —— 抓图工具正是模拟这个偏好）；
   ③ 只动 transform / opacity（走合成器，不重排不重绘），且都锁在**有界区域**里
      （hero / 会员卡 / 支付按钮），不做整屏铺满 —— 否则会和底栏毛玻璃叠着烧合成。
   另外零新增 DOM：三个效果全部用伪元素，所以不会给页面加节点、也不会撑高文档。 */
@media (prefers-reduced-motion: no-preference) {
  /* ① 首页 hero：两团品牌色柔光在里面缓慢漂移（只在玫粉 + 动效开启时出现） */
  :root[data-theme="rose"][data-fx="on"] .hero::before,
  :root[data-theme="rose"][data-fx="on"] .hero::after {
    content:""; position:absolute; width:64%; aspect-ratio:1; border-radius:50%;
    pointer-events:none; z-index:0; will-change:transform;
  }
  :root[data-theme="rose"][data-fx="on"] .hero::before {
    left:-14%; top:-36%;
    background:radial-gradient(circle at 50% 50%,var(--fx-glow-1),transparent 62%);
    animation:fxHeroA 21s ease-in-out infinite alternate;
  }
  :root[data-theme="rose"][data-fx="on"] .hero::after {
    right:-16%; bottom:-42%;
    background:radial-gradient(circle at 50% 50%,var(--fx-glow-2),transparent 62%);
    animation:fxHeroB 26s ease-in-out infinite alternate;
  }
  /* hero 里的文字与按钮要压在光影之上 */
  :root[data-theme="rose"][data-fx="on"] .hero > * { position:relative; z-index:1; }

  /* ②「我的」页会员卡：一层很淡的呼吸光晕（4.5s 一次，幅度很小，不抢注意力） */
  :root[data-theme="rose"][data-fx="on"] .me-vip { position:relative; overflow:hidden; }
  :root[data-theme="rose"][data-fx="on"] .me-vip::after {
    content:""; position:absolute; right:-18%; top:-70%; width:46%; aspect-ratio:1; border-radius:50%;
    background:radial-gradient(circle at 50% 50%,var(--fx-glow-1),transparent 66%);
    pointer-events:none; z-index:0; will-change:transform,opacity;
    animation:fxBreath 4.5s ease-in-out infinite;
  }
  :root[data-theme="rose"][data-fx="on"] .me-vip > * { position:relative; z-index:1; }

  /* ③ 会员页的支付按钮：一道品牌高光从左到右扫过（经典"按得下去"的暗示） */
  :root[data-theme="rose"][data-fx="on"] .plan-pay .btn { position:relative; overflow:hidden; }
  :root[data-theme="rose"][data-fx="on"] .plan-pay .btn::after {
    content:""; position:absolute; top:0; bottom:0; width:38%;
    background:linear-gradient(100deg,transparent,var(--fx-sheen),transparent);
    transform:translate3d(-160%,0,0); pointer-events:none;
    animation:fxSweep 3.4s ease-in-out infinite;
  }
}
@keyframes fxHeroA{from{transform:translate3d(0,0,0) scale(1)}to{transform:translate3d(9%,7%,0) scale(1.14)}}
@keyframes fxHeroB{from{transform:translate3d(0,0,0) scale(1.1)}to{transform:translate3d(-8%,-6%,0) scale(1)}}
@keyframes fxBreath{0%,100%{transform:scale(.86);opacity:.45}50%{transform:scale(1.06);opacity:.9}}
@keyframes fxSweep{0%{transform:translate3d(-160%,0,0)}55%,100%{transform:translate3d(300%,0,0)}}
/* 低端机降级：设备内存 ≤4GB 或 CPU 核 ≤4 时，会员卡与按钮的动效先去掉（只留 hero 那层）
   —— 阈值写在 CSS 里，靠 JS 在 <html> 上打 data-fx-lite 标记（见 theme.js） */
/* 注意：降级**不再**关掉会员卡光晕与支付按钮扫光 —— 这两处各只有一个元素，
   成本极低，却恰恰是用户最容易注意到的"精致感"。降级只削减大面积的层。 */

/* ---------- 整页背景动态光影（玫粉专属） ----------
   两轮迭代的结论：
   · 第 1 版只把光影锁在 hero 里 → 用户反馈"不明显"（动效只覆盖页面顶部一小块）；
   · 第 2 版铺到整页，但三团光斑的**位置是写死的**（左上粉 / 中间紫 / 下方橙）→
     用户反馈"看久了就是固定布局，希望像云朵/水彩那样无序流动，或像极光"。
   · 第 3 版（本段）：颜色与位置**解绑** ——
       ① 5 团大小不一的光斑，每团都沿一条**不规则多段路径**横穿整个视口，并互相穿插重叠，
          于是"哪里是粉、哪里是紫"每时每刻都在变，像水彩在纸上互相晕开；
       ② 2 道**极光幕**（竖向渐变 + 倾斜 + 横向漂移 + 透明度呼吸），是"极光"质感的主要来源；
       ③ 1 条**脉冲光带**：扫过的同时亮度做包络起伏（亮→暗→更亮→灭），而不是匀速划过。
       另外每团光斑的动画时长互质（23/29/37/41/53s），组合起来肉眼几乎看不出循环。
   性能前提（都实测过，别随便破）：
     · 只动 transform / opacity → 合成器路径，不重排不重绘；静止与滚动均 60fps、长任务 0；
     · 唯一真实开销是"毛玻璃每帧重新采样会动的背景"（顶栏/底栏 backdrop-filter）→
       动效开启时这两处换成略不透明的纯色底（见下面 .topbar/.bottom-nav 两条）；
     · 内容全部坐在**不透明卡片**上，背景再花也不影响可读性；
     · 光斑用 radial-gradient 的宽透明过渡做柔边，**不用 filter:blur()**（大层模糊是移动端卡顿头号来源）。
   层级：#fx-layer 是 z-index:0、#app 抬到 z-index:1 —— 光影在内容之下、页面底色之上，
   而且**不用改 body 的底色**，所以深/浅两套主题的渲染完全不受影响。
   强度/配色都在 theme.css 的 --fx-page-1..5、--fx-aurora-1/2、--fx-band 里。 */
@media (prefers-reduced-motion: no-preference) {
  :root[data-theme="rose"][data-fx="on"] #app { position: relative; z-index: 1; }
  :root[data-theme="rose"][data-fx="on"] #fx-layer {
    position: fixed; inset: 0; z-index: 0; pointer-events: none; overflow: hidden;
  }
  /* 粒子单独一层：压在内容之上（所以能飘过白卡片），但仍在顶栏/底栏之下 */
  :root[data-theme="rose"][data-fx="on"] #fx-dust-layer {
    position: fixed; inset: 0; z-index: 2; pointer-events: none; overflow: hidden;
  }
  :root[data-theme="rose"][data-fx="on"] #fx-layer > i {
    position: absolute; border-radius: 50%; pointer-events: none; will-change: transform;
  }
  /* 五团光斑：起点散布在四角与中间，路径互相穿过 —— 这就是"无序流动"的关键 */
  :root[data-theme="rose"][data-fx="on"] .fx-b1 {
    width: 92vw; height: 92vw; left: -30vw; top: -22vh;
    background: radial-gradient(circle at 50% 50%, var(--fx-page-1), transparent 66%);
    animation: fxDrift1 23s ease-in-out infinite;
  }
  :root[data-theme="rose"][data-fx="on"] .fx-b2 {
    width: 84vw; height: 84vw; right: -26vw; top: 26vh;
    background: radial-gradient(circle at 50% 50%, var(--fx-page-2), transparent 66%);
    animation: fxDrift2 29s ease-in-out infinite;
  }
  :root[data-theme="rose"][data-fx="on"] .fx-b3 {
    width: 76vw; height: 76vw; left: 12vw; bottom: -26vh;
    background: radial-gradient(circle at 50% 50%, var(--fx-page-3), transparent 66%);
    animation: fxDrift3 37s ease-in-out infinite;
  }
  :root[data-theme="rose"][data-fx="on"] .fx-b4 {
    width: 66vw; height: 66vw; left: 34vw; top: -14vh;
    background: radial-gradient(circle at 50% 50%, var(--fx-page-4), transparent 68%);
    animation: fxDrift4 41s ease-in-out infinite;
  }
  :root[data-theme="rose"][data-fx="on"] .fx-b5 {
    width: 58vw; height: 58vw; right: -12vw; bottom: -12vh;
    background: radial-gradient(circle at 50% 50%, var(--fx-page-5), transparent 68%);
    animation: fxDrift5 53s ease-in-out infinite;
  }
  /* 两道极光幕：竖向光帘 + 倾斜 + 横向漂移 + 透明度呼吸（"极光"质感的来源） */
  :root[data-theme="rose"][data-fx="on"] #fx-layer > .fx-a1,
  :root[data-theme="rose"][data-fx="on"] #fx-layer > .fx-a2 {
    border-radius: 0; height: 150vh; top: -25vh; will-change: transform, opacity;
  }
  :root[data-theme="rose"][data-fx="on"] .fx-a1 {
    width: 58vw; left: 6vw;
    background: linear-gradient(180deg, transparent 4%, var(--fx-aurora-1) 42%, transparent 96%);
    transform: skewX(-10deg) rotate(6deg);
    animation: fxAurora1 31s ease-in-out infinite;
  }
  :root[data-theme="rose"][data-fx="on"] .fx-a2 {
    width: 44vw; left: 44vw;
    background: linear-gradient(180deg, transparent 8%, var(--fx-aurora-2) 46%, transparent 94%);
    transform: skewX(-14deg) rotate(-5deg);
    animation: fxAurora2 43s ease-in-out infinite;
  }
  /* 脉冲光带：扫过 + 亮度包络（亮→暗→更亮→灭），不是匀速划过 */
  :root[data-theme="rose"][data-fx="on"] .fx-band {
    left: -60%; top: -22%; width: 220%; height: 64%; border-radius: 0;
    background: linear-gradient(100deg, transparent, var(--fx-band), transparent);
    transform: rotate(-18deg); will-change: transform, opacity;
    animation: fxBand 21s ease-in-out infinite;
  }
  /* ---------- B 形态：上浮粒子 ----------
     纯 CSS：每颗粒子是一个 <i>，靠 CSS 变量控制起点/横向漂移/时长/相位，共用一条上浮动画。
     为什么不做 canvas：26 颗点只需要 transform+opacity，CSS 就能跑在合成器上，
     一个 rAF 循环都不需要（省电、也不会和滚动抢主线程）。
     粒子放在**内容之上**（z-index:2，仍低于顶栏 50 / 底栏 80）：C 端页面几乎全是白卡片，
     放内容之下就只能从卡片缝隙里看到，等于白做。压字风险靠三点控制：
     点很小（3~6px）、透明度低（0.35~0.7）、稀疏（26 颗铺满整屏）。
     基础 opacity 是 0：只有在动画跑起来时才可见 —— 这样"减少动效"或降级时它们自然隐形，
     不需要额外的 display 规则。 */
  :root[data-theme="rose"][data-fx="on"] #fx-dust-layer .fx-dust {
    position: absolute; bottom: -8vh; width: 8px; height: 8px; border-radius: 50%;
    opacity: 0; pointer-events: none;
    /* 这里刻意**不写 will-change**：60 颗粒子各自 promote 一层会吃掉移动端的合成层预算
       （真机上可能整层不渲染），而动画元素本来就会被自动提升。 */
    background: radial-gradient(circle at 50% 50%, var(--fx-dust), var(--fx-dust-2) 58%, transparent 74%);
    /* 一圈柔光晕：白芯在浅色页面上本来很弱，靠这层色晕才"看得见"（bokeh 感） */
    box-shadow: 0 0 12px var(--fx-dust-2);
    animation-name: fxDust; animation-timing-function: linear; animation-iteration-count: infinite;
  }
  /* 三种颜色各一档光晕（粉 / 薄荷 / 紫罗兰）：三色混着飘才不单调 */
  :root[data-theme="rose"][data-fx="on"] #fx-dust-layer .fx-dust.mint {
    background: radial-gradient(circle at 50% 50%, var(--fx-dust), var(--fx-dust-3) 58%, transparent 74%);
    box-shadow: 0 0 12px var(--fx-dust-3);
  }
  :root[data-theme="rose"][data-fx="on"] #fx-dust-layer .fx-dust.violet {
    background: radial-gradient(circle at 50% 50%, var(--fx-dust), var(--fx-dust-4) 58%, transparent 74%);
    box-shadow: 0 0 12px var(--fx-dust-4);
  }
  /* 降级（只在大面积层上做减法）：去掉三团额外光斑与一道极光幕。
     刻意**保留**脉冲光带、粒子（由 JS 减量到 26 颗）、hero 光影、会员卡光晕与支付按钮扫光 ——
     它们都是小元素、走合成器、真机实测并不吃性能；早先版本把它们整类砍掉，
     结果用户在真机上以为"功能没了"（而桌面模拟环境正常，排查了很久）。 */
  :root[data-fx-lite="1"][data-theme="rose"][data-fx="on"] .fx-b3,
  :root[data-fx-lite="1"][data-theme="rose"][data-fx="on"] .fx-b4,
  :root[data-fx-lite="1"][data-theme="rose"][data-fx="on"] .fx-b5,
  :root[data-fx-lite="1"][data-theme="rose"][data-fx="on"] .fx-a1 { display: none; }
  /* 背景在动时不要再让顶栏/底栏做毛玻璃（每帧重新采样会很贵） */
  :root[data-theme="rose"][data-fx="on"] .topbar {
    background: rgba(255, 255, 255, .9);
    -webkit-backdrop-filter: none; backdrop-filter: none;
  }
  :root[data-theme="rose"][data-fx="on"] .bottom-nav {
    background: rgba(255, 255, 255, .92);
    -webkit-backdrop-filter: none; backdrop-filter: none;
  }
}
/* 光斑路径：多段、方向来回穿插（不是简单的直线来回），所以看上去像云在飘而不是在"左右晃" */
@keyframes fxDrift1{
  0%{transform:translate3d(0,0,0)}25%{transform:translate3d(46vw,34vh,0)}
  55%{transform:translate3d(18vw,72vh,0)}80%{transform:translate3d(-14vw,26vh,0)}
  100%{transform:translate3d(0,0,0)}}
@keyframes fxDrift2{
  0%{transform:translate3d(0,0,0)}22%{transform:translate3d(-40vw,-26vh,0)}
  48%{transform:translate3d(-64vw,30vh,0)}74%{transform:translate3d(-22vw,64vh,0)}
  100%{transform:translate3d(0,0,0)}}
@keyframes fxDrift3{
  0%{transform:translate3d(0,0,0)}30%{transform:translate3d(34vw,-58vh,0)}
  60%{transform:translate3d(-30vw,-40vh,0)}85%{transform:translate3d(20vw,-14vh,0)}
  100%{transform:translate3d(0,0,0)}}
@keyframes fxDrift4{
  0%{transform:translate3d(0,0,0)}28%{transform:translate3d(-52vw,44vh,0)}
  62%{transform:translate3d(10vw,86vh,0)}100%{transform:translate3d(0,0,0)}}
@keyframes fxDrift5{
  0%{transform:translate3d(0,0,0)}35%{transform:translate3d(-46vw,-52vh,0)}
  70%{transform:translate3d(-16vw,-84vh,0)}100%{transform:translate3d(0,0,0)}}
@keyframes fxAurora1{
  0%{transform:skewX(-10deg) rotate(6deg) translate3d(-14vw,0,0);opacity:.35}
  35%{transform:skewX(-10deg) rotate(6deg) translate3d(26vw,0,0);opacity:.85}
  70%{transform:skewX(-10deg) rotate(6deg) translate3d(58vw,0,0);opacity:.45}
  100%{transform:skewX(-10deg) rotate(6deg) translate3d(6vw,0,0);opacity:.7}}
@keyframes fxAurora2{
  0%{transform:skewX(-14deg) rotate(-5deg) translate3d(30vw,0,0);opacity:.5}
  40%{transform:skewX(-14deg) rotate(-5deg) translate3d(-22vw,0,0);opacity:.85}
  75%{transform:skewX(-14deg) rotate(-5deg) translate3d(-56vw,0,0);opacity:.35}
  100%{transform:skewX(-14deg) rotate(-5deg) translate3d(4vw,0,0);opacity:.6}}
/* 脉冲光带：位移是"扫过"，opacity 做包络 → 看起来是一道会呼吸的光脉冲 */
/* 粒子：从视口下方升到上方，两端淡入淡出；--dx 是每颗自己的横向漂移量（由 JS 随机给） */
@keyframes fxDust{
  0%{transform:translate3d(0,0,0) scale(.6);opacity:0}
  8%{opacity:.85}
  26%{opacity:.42}
  44%{opacity:.9}
  62%{opacity:.4}
  80%{opacity:.8}
  100%{transform:translate3d(var(--dx,0),-112vh,0) scale(1);opacity:0}}
@keyframes fxBand{
  0%{transform:rotate(-18deg) translate3d(-34%,0,0);opacity:0}
  12%{opacity:.85}
  34%{transform:rotate(-18deg) translate3d(4%,0,0);opacity:.25}
  52%{opacity:.95}
  78%{transform:rotate(-18deg) translate3d(54%,0,0);opacity:.35}
  100%{transform:rotate(-18deg) translate3d(70%,0,0);opacity:0}}
.side{display:grid;grid-template-columns:2fr 1fr;gap:18px;align-items:start}
@media(max-width:900px){.side{grid-template-columns:1fr}.nav a{padding:6px 9px;font-size:13px}}
/* 详情页「同类推荐」（固定 4 条）：桌面右栏竖排 1 列，窄屏折叠为 2 列 2×2 */
.related-grid{display:grid;gap:12px;grid-template-columns:1fr}
@media(max-width:900px){.related-grid{grid-template-columns:repeat(2,1fr);gap:10px}}
.coin-row{display:flex;align-items:center;gap:6px;color:var(--coin-ink);font-weight:700}
.section-head{display:flex;align-items:center;justify-content:space-between;margin:22px 0 14px}
/* h3 也走同一套：视图层有两处板块标题用的是 <h3>（同类推荐 / 中奖记录），
   以前只有 h2 有样式，h3 落到浏览器默认（约 16.4px + 默认 margin），
   于是同一页里两个板块标题层级不一致 —— 那是 bug，不是设计。 */
.section-head h2, .section-head h3 { font-size: 18px; font-weight: 800; }
.tabs{display:flex;gap:4px;border-bottom:1px solid var(--line);margin-bottom:16px}
.tabs button{background:none;border:none;color:var(--muted);padding:10px 16px;font-weight:700;border-bottom:2px solid transparent}
.tabs button.active{color:#fff;border-bottom-color:var(--brand)}
.toolbar{display:flex;gap:10px;flex-wrap:wrap;margin-bottom:16px}
.toolbar input{max-width:260px}
.toolbar .btn{white-space:nowrap}
.hidden{display:none!important}

/* ============================================================
   移动端适配 & App 化样式
   ============================================================ */

/* 底部导航栏（仅移动端显示） */
.bottom-nav { display: none; }

/* 平滑滚动 & 隐藏滚动条 */
html { -webkit-overflow-scrolling: touch; scroll-behavior: smooth; }
::-webkit-scrollbar { width: 0; height: 0; }

/* 全局触摸优化 */
a, button, .clickable { -webkit-tap-highlight-color: transparent; user-select: none; }
.btn:active { transform: scale(.96); filter: brightness(.9); }
.card.clickable:active { transform: scale(.98); }

@media (max-width: 768px) {
  /* ---------- 移动端排版刻度（唯一来源） ----------
     以前移动端的字号是一堆写死的 px（再加上 380px 一个硬断点），后果有两个：
       · 320px 到 440px 的手机长着一模一样的字，大屏手机白白多出宽度却**一点内容都不多**；
       · 想整体压一档密度就得满文件找几十处 font-size，改一处漏一处。
     现在只在这几个变量里定字号 / 间距，下面所有选择器都引用它们。

     两条原则（用户反馈"真机看着臃肿、缩到 75% 反而协调"之后的取舍）：
       ① **阅读性文字不缩水**：正文 / 卡片标题 / 信息行 / 详情页标题的上限就是原来的值
          （正文 14、卡片题 12、信息行 10），小屏也只降 0.4~0.8px —— 不能为了"看着瘦"牺牲可读性；
       ② **展示性文字与留白收一档**：hero 标题 20→18、板块标题 16→15、
          跑马灯 13→12、hero 说明 12→11.5，配合 hero 内边距 20/16→15/13、
          板块上下间距 16/10→13/8、跑马灯内边距 8→7。
         首屏因此多让出 ~25px（≈ 六分之一张卡片），且大屏不再把字放大。

     用 vw 让 320→440 连续过渡、上下限夹住：常见机型（320~410）基本取下限（小屏不糊），
     430/440 走上限（大屏不放大、多出来的宽度留给内容）。 */
  :root {
    --fs-body: clamp(13.5px, 3.2vw, 14px);             /* 正文 / 继承字号 */
    --fs-card-title: clamp(11.6px, 3.08vw, 12px);      /* 卡片标题（两行截断）：≥390 就是原来的 12 */
    --fs-meta: clamp(11px, 2.9vw, 12px);               /* 卡片信息行：中文低于 11px 辨识度明显下降 */
    --fs-nav: clamp(11px, 2.9vw, 12px);                /* 底栏标签：全站使用频率最高的控件，单独一档 */
    --fs-detail-meta: clamp(11.5px, 2.9vw, 12.2px);    /* 详情页信息行（比卡片行大一档） */
    --fs-detail-title: clamp(13.5px, 3.18vw, 14.2px);  /* 详情页标题 */
    --fs-sec: clamp(15px, 3.64vw, 16px);               /* 板块标题 */
    --fs-hero: clamp(18px, 4.43vw, 19.5px);            /* 首页 hero 主标题 */
    --fs-hero-p: clamp(11.5px, 2.85vw, 12px);          /* hero 说明 */
    --fs-marquee: clamp(12px, 2.91vw, 12.8px);         /* 公告跑马灯（用户点名偏大的那处） */
    --fs-toast: clamp(12.5px, 3.1vw, 13.2px);
    --pad-page: clamp(11px, 3.2vw, 14px);              /* 页面左右留白 */
    --gap-grid: clamp(8px, 2.27vw, 10px);              /* 卡片网格间距 */
    --gap-page: clamp(16px, 3.4vw, 20px);              /* 页面底部留白 */
    --pad-hero: clamp(15px, 3.9vw, 17px);              /* hero 内边距（上下） */
    --pad-hero-x: clamp(13px, 3.4vw, 15px);
    --sec-gap-top: clamp(13px, 3.4vw, 15px);           /* 板块标题上间距 */
    --sec-gap-bottom: clamp(8px, 2.27vw, 10px);
  }
  body { font-size: var(--fs-body); }

  /* ---------- 顶栏 ---------- */
  .topbar {
    height: calc(48px + env(safe-area-inset-top));
    padding: env(safe-area-inset-top) 14px 0;
    gap: 10px;
    background: var(--glass-strong);
    backdrop-filter: blur(16px) saturate(1.4);
  }
  .topbar .nav { display: none; }
  .top-right { gap: 6px; }
  .top-right .btn.ghost.sm, .top-right .coin-row { display: none; }
  .brand { font-size: 16px; gap: 6px; }
  .brand .logo { font-size: 19px; }

  /* ---------- 底部 Tab 栏（毛玻璃 + 胶囊指示器） ---------- */
  .bottom-nav {
    display: flex;
    position: fixed;
    bottom: 0; left: 0; right: 0;
    z-index: 80;
    background: var(--glass-nav);
    backdrop-filter: blur(20px) saturate(1.6);
    -webkit-backdrop-filter: blur(20px) saturate(1.6);
    border-top: 1px solid var(--line-soft);
    padding: 2px 8px calc(6px + env(safe-area-inset-bottom));
  }
  .bottom-nav a {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 1px;
    padding: 5px 0 3px;
    color: var(--muted);
    font-size: var(--fs-nav);
    font-weight: 600;
    text-decoration: none;
    border-radius: 12px;
    transition: color .2s, background .2s;
  }
  .bottom-nav a .ico {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    line-height: 0;
    transition: transform .2s, color .2s;
  }
  .bottom-nav a .ico svg { width: 22px; height: 22px; display: block; }
  /* 选中态：图标转品牌紫、文字转白加重。
     胶囊比原来收淡一档 —— 图标本身现在能表达选中了，背景再重就是重复强调。 */
  .bottom-nav a.active {
    color: var(--nav-active-fg, #fff);
    font-weight: 700;
    background: var(--nav-active-bg);
    box-shadow: 0 2px 10px var(--glow, transparent);
  }
  .bottom-nav a.active .ico { color: var(--nav-active-ico); transform: translateY(-1px) scale(1.06); }
  /* 这里曾有一个"抬起的圆形主操作（会员）"的样式（对标 v7 的中间 FAB）。
     用户实际看过之后判断"太别扭"，要求撤掉 —— 连同 JS 里的标记一起移除，底栏回到五个平铺入口。
     留一条经验给以后：底栏本身是 position:fixed，**不要**为了给子元素当包含块而给它加
     position:relative —— 那会把它从"固定贴底"变回普通流，整个底栏跑到文档末尾（踩过一次）；
     fixed 本身已经是绝对定位子元素的包含块。 */
  .bottom-nav a:active .ico { transform: scale(.88); }

  /* ---------- 页面主体 ---------- */
  /* 底栏高度统一走 --nav-h：以前各处的 60 / 64 / 72 / 78 都是手写的魔数，
     改一次底栏就要满文件找一遍。 */
  .bottom-nav { height: calc(var(--nav-h) + env(safe-area-inset-bottom)); }
  body { padding-bottom: calc(var(--nav-h) + 6px + env(safe-area-inset-bottom)); }

  /* 短视频页：底部导航**保留**，所以舞台高度要同时让开顶栏与底栏。
     以前外层包裹写死 height:calc(100vh - 60px)，移动端只能靠
     `#app div:has(> .short-stage)` 反向选中它再 `!important` 覆盖 —— 三个问题：
       · 样式层依赖 DOM 结构（#app > div > .short-stage），视图层一改结构就静默失效，
         而且失效方式是"底栏被顶掉 / 舞台撑破"，很难排查；
       · `:has()` 挂在 body 下属于样式重算最贵的一类选择器，而短视频是高频滚动页；
       · 两处 !important 互相打架，safe-area 在一层层 calc 里减了两次。
     现在由视图层直接给包裹层 `.short-wrap`（views.js 的 shortFeed），
     高度写在下面这一条里，标签里不再写内联高度 —— 不再需要 `:has()` 与覆盖式 !important。 */
  .short-wrap {
    height: calc(100dvh - 48px - var(--nav-h)
                  - env(safe-area-inset-top) - env(safe-area-inset-bottom));
  }
  /* 浮层让位：注意舞台底边已经正好落在导航顶边，所以舞台**内部**的绝对定位元素
     只需要再让开「上一条 / 下一条 + 计数」那一条，不能再减一次导航高度。
     实测：导航顶边之上 94px 处是上下条的顶边，所以文字层让出 102px 正好留 8px 缝。 */
  body.is-short .short-ui {
    padding: 16px 86px calc(102px + env(safe-area-inset-bottom)) 16px;
  }
  body.is-short .short-actions { bottom: calc(112px + env(safe-area-inset-bottom)); }
  .layout { padding: var(--pad-page) var(--pad-page) var(--gap-page); }

  /* ---------- 首页 Hero ---------- */
  /* 高度是首屏最贵的一段：内边距从 20/16 收到 15/13 上下，标题从 20 收到 18~19.5，
     说明从 12 收到 11.5~12.2 —— 省下来的 ~14px 正好多放小半张卡片。 */
  .hero {
    padding: var(--pad-hero) var(--pad-hero-x);
    border-radius: 16px;
    margin-bottom: 6px;
  }
  .hero h1 { font-size: var(--fs-hero) !important; line-height: 1.3; }
  .hero p { font-size: var(--fs-hero-p); line-height: 1.6; margin-top: 4px; }
  .hero .btn { padding: 7px 16px; font-size: 12.5px; margin-top: 9px; }

  /* ---------- 标题栏 ---------- */
  .section-head { margin: var(--sec-gap-top) 0 var(--sec-gap-bottom); }
  .section-head h2, .section-head h3 { font-size: var(--fs-sec); font-weight: 800; }
  .section-title { font-size: var(--fs-sec); margin: var(--sec-gap-top) 0 var(--sec-gap-bottom); }

  /* ---------- 视频卡片（大缩略图 + 圆角 + 阴影） ---------- */
  .grid.videos {
    grid-template-columns: repeat(2, 1fr) !important;
    gap: var(--gap-grid);
  }
  .vcard {
    border-radius: 12px;
    box-shadow: 0 2px 8px var(--c-card-shadow,var(--card-shadow));
  }
  .vcard .thumb { border-radius: 12px 12px 0 0; }
  .vcard .meta { padding: 7px 9px 9px; }
  .vcard .meta h3 { font-size: var(--fs-card-title); line-height: 1.4; -webkit-line-clamp: 2; }
  .vcard .meta .row { font-size: var(--fs-meta); gap: 4px; }
  /* 详情页信息行：窄屏也收一档，但仍比卡片行大 —— 它是正片下面的主信息 */
  .vt-row { font-size: var(--fs-detail-meta); gap: 5px; margin-top: 9px; }
  .vt-title { font-size: var(--fs-detail-title); margin-top: 10px; }
  /* 会员角标搬到封面左上角后，窄屏只需收一档尺寸（原来的"低调小标"规则已随之删除） */
  .vcard .thumb-vip { left: 6px; top: 6px; padding: 1px 6px; font-size: 10px; border-radius: 5px; }
  .vcard .play { width: 40px; height: 40px; font-size: 16px; opacity: 1; background: rgba(108,92,231,.75); }
  .thumb-badge { font-size: 10px; padding: 2px 6px; }
  .live-card .live-badge { font-size: 10px; padding: 2px 6px; }

  /* ---------- 短视频（沉浸式全屏） ---------- */
  /* 高度只由 .short-wrap 决定（见上面的注释）；舞台这里只改宽度上限，
     不要再写 height:100dvh —— 那会让舞台比包裹高，把底栏顶掉（这正是旧写法打架的地方）。 */
  .short-stage { max-width: 100vw !important; }
  .short-item video.sv-main { object-fit: contain; }
  .short-ui { padding: 16px 16px calc(78px + env(safe-area-inset-bottom)); }
  .short-actions { bottom: calc(120px + env(safe-area-inset-bottom)); gap: 18px; }
  .short-actions .ico { width: 46px; height: 46px; }

  /* ---------- 播放器 ---------- */
  .player-wrap { border-radius: 0 0 14px 14px; }
  .player-overlay h2 { font-size: 18px; }
  .paywall .btn { padding: 8px 16px; font-size: 13px; }

  /* ---------- 卡片 ---------- */
  .card { border-radius: 14px; }
  .card.pad { padding: 14px; }
  .card.pad h3 { font-size: 14px; }

  /* ---------- 表单 ---------- */
  .form-card {
    max-width: 100% !important;
    margin: 16px 12px !important;
    padding: 24px 18px;
    border-radius: 18px;
  }
  .form-card h1 { font-size: 20px; }
  input, textarea, select { padding: 12px 14px; font-size: 15px; border-radius: 10px; }
  .field { margin-bottom: 16px; }
  .btn { min-height: 40px; }
  .btn.sm { min-height: 32px; }

  /* ---------- 表格（横滑 + 首列固定感） ---------- */
  table { display: block; overflow-x: auto; -webkit-overflow-scrolling: touch; }
  th, td { padding: 10px 12px; font-size: 12px; white-space: nowrap; }

  /* ---------- 统计卡 ---------- */
  .stat-grid { grid-template-columns: repeat(2, 1fr) !important; gap: 10px; margin-bottom: 14px; }
  .stat { padding: 12px; border-radius: 12px; }
  .stat .num { font-size: 20px; }
  .stat .lbl { font-size: 11px; }

  /* ---------- 社区 ---------- */
  .post-body { padding: 12px 14px; }
  .post-images { grid-template-columns: repeat(3, 1fr) !important; }
  .list-item { padding: 12px 14px; gap: 10px; }

  /* ---------- 直播 ---------- */
  .grid.topics { grid-template-columns: repeat(2, 1fr) !important; gap: 10px; }
  .grid.topics .card .thumb { aspect-ratio: 4/3; }
  .grid.topics .card .meta h3 { font-size: 13px; }

  /* ---------- 抽奖转盘 ---------- */
  .wheel { width: 240px !important; height: 240px !important; }
  .wheel .spin-btn { width: 64px; height: 64px; font-size: 13px; }

  /* ---------- Toast（显示在底部导航上方） ---------- */
  #toast-root { bottom: calc(76px + env(safe-area-inset-bottom)); }
  .toast { padding: 10px 18px; font-size: var(--fs-toast); max-width: calc(100vw - 40px); }

  /* ---------- 营销气泡 ---------- */
  .bubble-ticker { left: 10px; bottom: calc(72px + env(safe-area-inset-bottom)); max-width: calc(100vw - 20px); }
  .bubble { padding: 8px 12px; font-size: 11.5px; }

  /* ---------- Chips ---------- */
  .chips { gap: 6px; margin-bottom: 10px; overflow-x: auto; flex-wrap: nowrap; padding-bottom: 4px; -webkit-overflow-scrolling: touch; }
  /* 分类胶囊收窄：后续分类会越来越多，靠横滑 + 小占位撑住 */
  .chip { flex-shrink: 0; padding: 5px 10px; font-size: 12px; line-height: 1.35; }
  /* 搜索与排序并成一行：原来 input 的 max-width:260px 顶到 select，白占一整行。
     这一行再收一档高度（上面那条通用控件规则是 12px/15px，对小屏偏大），
     并把宽度重新分一下：搜索框让出一截，排序框向左加宽（它原来只有两个字，
     却和输入框一样高，宽度全被搜索框吃了）。 */
  .toolbar { flex-wrap: nowrap; gap: 8px; margin-bottom: 12px; }
  .toolbar input, .toolbar select { padding: 8px 12px; font-size: 13.5px; border-radius: 9px; }
  .toolbar input { flex: 1 1 auto; min-width: 0; max-width: none; }
  .toolbar select { flex: 0 0 34%; max-width: 150px; }
  /* 折叠按钮在小屏也跟着收一档，别比分类胶囊还显眼 */
  .chips-more { padding: 4px 11px; font-size: 11.5px; margin-bottom: 12px; }

  /* ---------- 通用布局 ---------- */
  .side { display: block !important; }
  .layout.side > div + div { margin-top: 14px; }
  .flex { gap: 8px; }
  .mt20 { margin-top: 14px; }

  /* 隐藏桌面冗余元素 */
  .hero .flex .btn.ghost { display: none; }
}

/* 超小屏（<380px）：只再收「留白」，字号交给上面的流体刻度（它已经在小屏取下限）。
   以前这里还硬写了 h3 / 信息行 / hero 的字号 —— 那是"两个地方都管字号"，
   改一处忘一处就会出现 320 和 390 长得完全不一样的怪现象。 */
@media (max-width: 380px) {
  .layout { padding: 10px 10px 16px; }
  .grid.videos { gap: 8px; }
  .vcard .meta { padding: 6px 8px 8px; }
  .chip { padding: 5px 9px; font-size: 11.5px; }
  .stat .num { font-size: 18px; }
}

/* ---------- PWA / Standalone App 模式 ---------- */
@media (display-mode: standalone) {
  body {
    /* 防止 iOS bounce */
    overscroll-behavior-y: none;
  }
  .topbar { padding-top: env(safe-area-inset-top); }
  /* 更像原生 App：禁用文字选择 */
  body { -webkit-user-select: none; user-select: none; }
  input, textarea { -webkit-user-select: auto; user-select: auto; }
}

/* ---------- 横屏适配 ---------- */
@media (max-width: 768px) and (orientation: landscape) {
  .bottom-nav { flex-direction: row; }
}

/* 顶栏头像按钮 */
.topbar-avatar { display: inline-flex; align-items: center; }
.topbar-avatar .avatar { border: 2px solid var(--line); }

/* ---------- 访客临时身份 ---------- */
.modal-overlay{position:fixed;inset:0;z-index:1000;display:flex;align-items:center;justify-content:center;padding:18px;background:var(--modal-overlay);backdrop-filter:blur(8px);opacity:0;transition:opacity .18s}
.modal-overlay.show{opacity:1}
.identity-card-modal,.guest-modal{position:relative;width:100%;max-width:420px;max-height:min(92dvh,680px);overflow:auto;background:var(--dialog-bg);border:1px solid var(--line-soft-10);border-radius:22px;padding:24px;box-shadow:0 20px 60px var(--shadow);transform:translateY(14px) scale(.98);transition:transform .18s}
.modal-overlay.show .identity-card-modal,.modal-overlay.show .guest-modal{transform:translateY(0) scale(1)}
.modal-close,.gm-x{position:absolute;top:14px;right:14px;width:32px;height:32px;border:none;border-radius:50%;
  background:rgba(127,127,127,.14);color:var(--text);font-size:22px;line-height:1;cursor:pointer;
  display:grid;place-items:center;padding:0}
.modal-close:hover,.gm-x:hover{background:rgba(127,127,127,.26)}
.identity-badge{display:inline-flex;padding:5px 10px;border-radius:999px;background:rgba(0,212,170,.14);color:var(--accent);font-size:12px;font-weight:700}
.identity-card-modal h2,.guest-modal h2{margin:10px 0 6px;font-size:20px}
.identity-tip{margin:0 0 16px;color:var(--muted);font-size:12px}
.identity-panel{position:relative;overflow:hidden;background:#fff;border-radius:18px;padding:20px;text-align:center;color:#111827}
.identity-panel::after{content:"G318";position:absolute;right:-20px;bottom:24px;transform:rotate(-24deg);color:rgba(17,24,39,.08);font-weight:800;font-size:34px;pointer-events:none}
.identity-nick{font-weight:800;font-size:20px}
/* 身份卡面板恒为白底（设计如此、不跟主题），所以里面的身份码也必须固定深色：
   之前用 --brand-ink，深色主题下它是浅紫 #a79bfa，压白底只有 2.41:1（看不清）。 */
.identity-code{margin:4px 0 14px;font-family:ui-monospace,Consolas,monospace;font-size:24px;font-weight:800;letter-spacing:2px;color:#5b3bbd}
.identity-qr{margin:0 auto;display:block;border-radius:8px}
.identity-brand{margin-top:12px;color:#6b7280;font-size:12px;font-weight:600}
.identity-actions{display:flex;gap:10px;margin-top:16px}
.identity-actions .btn{flex:1}
.segmented{display:grid;grid-template-columns:1fr 1fr;margin:14px 0;background:var(--bg2);border:1px solid var(--line);border-radius:10px;padding:4px;gap:4px}
.segmented button{border:none;background:transparent;color:var(--muted);border-radius:7px;padding:8px 4px;font-weight:700}
.segmented button.active{background:linear-gradient(135deg,var(--brand-fill,var(--brand)),var(--brand2));color:#fff}
.restore-upload{display:flex;align-items:center;justify-content:center;height:52px;border:1px dashed var(--brand);border-radius:12px;background:var(--brand-soft-8);color:var(--brand-ink);font-weight:700}
.restore-upload input{display:none}
.divider{position:relative;height:1px;margin:18px 0;background:var(--line);text-align:center}
.divider span{position:relative;top:-10px;background:var(--surface-4);padding:0 10px;color:var(--muted);font-size:12px}
.guest-chip{display:inline-flex;align-items:center;gap:8px;margin-top:4px;padding:4px 8px;border-radius:999px;background:rgba(108,92,231,.12);border:1px solid var(--brand-line-35);color:var(--ink-violet);font-size:12px}
.guest-chip b{font-family:ui-monospace,Consolas,monospace;letter-spacing:1px}

@media (max-width:768px){
  /* 升级 / 识别身份是表单，保持底部抽屉（键盘弹出时不遮挡输入框） */
  .modal-overlay{align-items:flex-end;padding:0}
  .guest-modal{max-width:100%;margin:0;border-bottom-left-radius:0;border-bottom-right-radius:0;padding:20px 16px calc(20px + env(safe-area-inset-bottom))}
  .identity-actions{flex-direction:column}
  .identity-panel{padding:18px 14px}
  .identity-code{font-size:22px}

  /* ---------- 临时身份卡：改成「居中紧凑卡片」 ----------
     原来它和 guest-modal 共用一套底部抽屉样式：满宽、贴底、二维码 220px，
     实测基本占满整屏。首访用户第一眼看到的是「自己被打断了」，
     既看不清这个站点是干什么的，卡片本身也因为拉满而显得空。
     现在收窄到 340px、二维码缩到 140px（绘制仍按 220px 出图，缩小显示更清晰），
     操作按钮并排，上下留出页面可见区。 */
  #identity-card-overlay{align-items:center;padding:14px}
  #identity-card-overlay .identity-card-modal{
    max-width:340px;
    border-radius:18px;
    padding:16px 16px 14px;
    max-height:min(80dvh,540px);
  }
  #identity-card-overlay .identity-badge{font-size:11px;padding:4px 9px}
  #identity-card-overlay h2{font-size:16px;margin:8px 0 4px}
  #identity-card-overlay .identity-tip{font-size:11.5px;line-height:1.55;margin:0 0 10px}
  #identity-card-overlay .identity-panel{padding:12px;border-radius:14px}
  #identity-card-overlay .identity-panel::after{font-size:26px;right:-14px;bottom:16px}
  #identity-card-overlay .identity-nick{font-size:15px}
  #identity-card-overlay .identity-code{font-size:17px;letter-spacing:1.5px;margin:2px 0 8px}
  /* 二维码：canvas 仍按 220 出图（清晰），这里只缩小显示尺寸 */
  #identity-card-overlay .identity-qr{width:140px;height:140px}
  #identity-card-overlay .identity-brand{margin-top:8px;font-size:10.5px}
  #identity-card-overlay .identity-actions{flex-direction:row;gap:8px;margin-top:12px}
  #identity-card-overlay .identity-actions .btn{min-height:40px;font-size:13px}
  #identity-card-overlay .modal-close{width:30px;height:30px;font-size:17px;top:9px;right:9px}
}

/* ---------- 会员档次页 ---------- */
.plan-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:14px;margin-top:16px}
.card.plan{position:relative;padding:18px;cursor:pointer;transition:.15s;border:1px solid var(--line)}
.card.plan:hover{transform:translateY(-2px);border-color:var(--brand)}
.card.plan.active{border-color:var(--brand);background:linear-gradient(160deg,var(--brand-soft-16),var(--brand2-soft-6));box-shadow:0 0 0 1px var(--brand) inset}
.card.plan b{font-size:16px}
.plan-badge{position:absolute;top:12px;right:12px;padding:2px 8px;border-radius:20px;background:var(--grad-brand);color:#fff;font-size:11px;font-weight:700}
.plan-price{margin:8px 0 2px;font-size:26px;font-weight:800;color:var(--gold)}
.plan-price small{font-size:12px;font-weight:600;color:var(--muted)}
.card.plan.active .plan-price{color:var(--coin-ink)}
.plan-pay{position:sticky;bottom:0;padding:14px 0 calc(14px + env(safe-area-inset-bottom));margin-top:16px}
.plan-pay .btn{width:100%;height:46px;font-size:15px}

/* 锁定态里的金币提示：比正文更亮一档，避免用户漏看「差多少币 / 已达上限」 */
.coin-hint{margin:0;padding:8px 12px;border-radius:10px;background:var(--coin-soft-12);border:1px solid rgba(255,209,102,.35);color:#ffd166;font-size:12.5px;line-height:1.6}

/* ---------- 邀请好友赚金币 ---------- */
.invite-row{display:flex;align-items:center;justify-content:space-between;gap:10px}
.invite-row .lbl{color:var(--muted);font-size:12px}
.invite-code{font-family:ui-monospace,Consolas,monospace;font-size:20px;letter-spacing:2px;color:var(--brand2)}
.invite-link{margin:12px 0;padding:12px 14px;border-radius:10px;background:var(--bg2);border:1px dashed var(--line);font-size:12px;color:var(--muted);word-break:break-all;line-height:1.7}
.invite-qr{margin:16px auto 10px;max-width:220px;text-align:center}
.invite-qr canvas{width:100%;max-width:200px;height:auto;background:#fff;border-radius:12px;padding:8px;margin:0 auto}

@media (max-width:768px){
  .plan-grid{grid-template-columns:repeat(2,1fr);gap:10px;margin-top:12px}
  .card.plan{padding:14px 12px}
  .card.plan b{font-size:14px}
  .plan-price{font-size:20px}
  .plan-badge{font-size:10px;padding:2px 6px}
  .plan-pay{padding:12px 0 calc(12px + env(safe-area-inset-bottom) + 64px)}
}


/* ---------- 首页跑马灯公告（内容 / 速度 / 配色均由后台配置） ---------- */
.marquee { display: flex; align-items: center; gap: 10px; margin: 14px 0 4px; padding: 9px 14px;
  border-radius: 12px; border: 1px solid var(--line); background: var(--card); overflow: hidden; }
.marquee .mq-icon { flex: none; font-size: 15px; }
/* 两侧渐隐：文字进出屏幕时不会硬生生「切断」 */
.marquee .mq-view { flex: 1; overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 18px, #000 calc(100% - 18px), transparent);
  mask-image: linear-gradient(90deg, transparent, #000 18px, #000 calc(100% - 18px), transparent); }
.marquee .mq-track { display: flex; width: max-content; animation: mq-scroll var(--mq-duration, 30s) linear infinite; }
.marquee:hover .mq-track { animation-play-state: paused; }
.marquee .mq-item { white-space: nowrap; padding-right: 64px; font-size: 14px; }
.marquee .mq-item[aria-hidden="true"] { padding-right: 0; }
.marquee .mq-dot { margin: 0 14px; opacity: .55; }
@keyframes mq-scroll { from { transform: translateX(0); } to { transform: translateX(-50%); } }
.marquee.mq-gold { border-color: rgba(240,185,60,.36); background: linear-gradient(90deg, rgba(240,185,60,.14), rgba(240,185,60,.04)); }
.marquee.mq-gold .mq-item { color: var(--notice-ink); }
.marquee.mq-blue { border-color: rgba(91,140,255,.36); background: linear-gradient(90deg, rgba(91,140,255,.14), rgba(91,140,255,.04)); }
.marquee.mq-blue .mq-item { color: #8cb4ff; }
.marquee.mq-red { border-color: rgba(255,94,94,.34); background: linear-gradient(90deg, rgba(255,94,94,.13), rgba(255,94,94,.04)); }
.marquee.mq-red .mq-item { color: #ff9a9a; }
@media (max-width: 768px) {
  /* 跑马灯是用户点名"字有点大"的地方：字号跟着上面的刻度走（12~12.8px），
     纵向内边距再收 1px，条间距（.mq-item 的 padding-right）从 44 收到 30 ——
     间距太宽会让"这一条滚过去"的空白比文字还多，看着就更臃肿。
     断点原来写的是 760px：760~768px 这一段（iPad 竖屏 / 部分安卓平板）会撕裂 ——
     底栏与卡片已经是移动态，跑马灯却还是桌面尺寸。统一到 768。 */
  .marquee { margin: 8px 0 2px; padding: 7px 10px; border-radius: 10px; }
  .marquee .mq-icon { font-size: 14px; }
  .marquee .mq-item { font-size: var(--fs-marquee); padding-right: 30px; }
}

/* ---------- 站内弹窗（App.ask / App.askText，替代浏览器原生 confirm / alert / prompt） ----------
   原生弹窗在 iOS Safari、微信内置浏览器、部分 WebView 里是**系统级**的：
   白底灰框、按钮文案由系统给，和深色站点完全脱节（很突兀），还会阻塞主线程。
   这里给「确认 / 提示 / 输入」三种场景一套统一外观。 */
.app-dialog-overlay { z-index: 1100; }
.app-dialog {
  position: relative;
  width: 100%;
  max-width: 320px;
  background:var(--dialog-bg);
  border: 1px solid var(--line-soft-10);
  border-radius: 18px;
  padding: 20px 18px 16px;
  box-shadow: 0 20px 60px var(--c-shadow-lg,var(--shadow-lg));
  transform: translateY(12px) scale(.97);
  transition: transform .18s;
}
.modal-overlay.show .app-dialog { transform: translateY(0) scale(1); }
.app-dialog h3 { margin: 0 0 8px; font-size: 16px; font-weight: 800; }
/* 礼物菜单这类多行文本靠 pre-wrap 保留换行 */
.app-dialog p { margin: 0; color: var(--muted); font-size: 13px; line-height: 1.7; white-space: pre-wrap; }
.app-dialog input { margin-top: 12px; }
.app-dialog-actions { display: flex; gap: 8px; margin-top: 18px; }
.app-dialog-actions .btn { flex: 1; min-height: 42px; font-size: 14px; }

@media (max-width: 768px) {
  /* 手机上居中，不吃满宽度；底部留白给软键盘 */
  .app-dialog-overlay { align-items: center; padding: 18px; }
  .app-dialog { max-width: 300px; padding: 18px 16px 14px; }
}

/* ============================================================================
   直播广场 · 无真实房间时的预设占位卡（竖版彩色卡）
   设计要点：
     1) 竖版 3:4 —— 直播封面本身就是竖屏语境，横版 16:9 撑不起「广场」的存在感
     2) 每张一套双色渐变 + 顶部柔光 + 底部压暗，白字在任意色相上都够清楚
     3) 徽标 / 人数用半透明玻璃胶囊，不抢标题
     4) 全部装饰都是 CSS，不依赖任何图片资源
   ============================================================================ */
.live-ph-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 16px; }

.live-ph {
  position: relative;
  isolation: isolate;              /* 让下面的 -1 层伪元素只作用于本卡 */
  overflow: hidden;
  aspect-ratio: 3 / 4;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: 12px;
  border-radius: 16px;
  color: #fff;
  cursor: pointer;
  box-shadow: 0 10px 26px var(--c-tile-shadow,var(--tile-shadow)), inset 0 0 0 1px var(--line-soft-14);
  transition: transform .18s ease, box-shadow .18s ease;
}
.live-ph:active { transform: scale(.975); }
@media (hover: hover) and (pointer: fine) {
  .live-ph:hover { transform: translateY(-3px); box-shadow: 0 16px 34px var(--c-tile-shadow-hover,var(--tile-shadow-hover)), inset 0 0 0 1px rgba(255,255,255,.22); }
}

/* 顶部斜射柔光，让纯渐变不至于显得平 */
.live-ph::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: radial-gradient(120% 78% at 22% 0%, rgba(255,255,255,.30), rgba(255,255,255,0) 62%);
}
/* 底部压暗：标题与小字直接压在渐变上会糊，这层是给它们的地基 */
.live-ph::after {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(to top,
    rgba(6,8,14,.88) 0%, rgba(6,8,14,.62) 32%, rgba(6,8,14,.10) 58%, rgba(6,8,14,0) 78%);
}

.live-ph-rose  { background: linear-gradient(150deg, #8b5cf6, #ec4899); }
.live-ph-ocean { background: linear-gradient(150deg, #06b6d4, #4f46e5); }
.live-ph-amber { background: linear-gradient(150deg, #f59e0b, #ef4444); }
.live-ph-iris  { background: linear-gradient(150deg, #a78bfa, #6366f1); }

/* 大号 emoji 作海报式水印，不参与内容布局 */
.live-ph-art {
  position: absolute; top: 16%; left: 50%;
  transform: translateX(-50%);
  font-size: 46px; line-height: 1;
  opacity: .92; z-index: 0;
  filter: drop-shadow(0 8px 20px rgba(0,0,0,.35));
}

.live-ph-badge {
  position: absolute; top: 10px; left: 10px; z-index: 2;
  display: inline-flex; align-items: center; gap: 5px;
  padding: 4px 9px; border-radius: 999px;
  background: rgba(8,10,14,.46);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  border: 1px solid var(--line-soft-16);
  font-size: 11px; font-weight: 700;
}
.live-ph-badge .live-dot { width: 6px; height: 6px; background: #ff3b5c; box-shadow: 0 0 0 0 rgba(255,59,92,.7); animation: livePhPulse 1.6s infinite; }
@keyframes livePhPulse { 70% { box-shadow: 0 0 0 7px rgba(255,59,92,0); } 100% { box-shadow: 0 0 0 0 rgba(255,59,92,0); } }
.live-ph-badge.soon { background: rgba(255,255,255,.18); }

.live-ph-viewers {
  position: absolute; top: 10px; right: 10px; z-index: 2;
  padding: 3px 8px; border-radius: 999px;
  background: rgba(8,10,14,.42);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  border: 1px solid var(--line-soft-14);
  font-size: 10.5px; font-weight: 700; font-variant-numeric: tabular-nums;
}

.live-ph-body { position: relative; z-index: 1; display: flex; flex-direction: column; align-items: flex-start; gap: 5px; }
.live-ph-body h3 {
  margin: 0; font-size: 13.5px; font-weight: 800; line-height: 1.4;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  text-shadow: 0 1px 8px rgba(0,0,0,.55);
}
.live-ph-body p {
  margin: 0; font-size: 11px; line-height: 1.5; color: rgba(255,255,255,.80);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  text-shadow: 0 1px 6px rgba(0,0,0,.5);
}
.live-ph-time {
  padding: 3px 9px; border-radius: 8px;
  background: rgba(255,255,255,.18); border: 1px solid rgba(255,255,255,.26);
  font-size: 12px; font-weight: 800; font-variant-numeric: tabular-nums;
}
.live-ph-cta {
  margin-top: 3px;
  display: inline-flex; align-items: center; gap: 5px;
  padding: 6px 12px; border-radius: 999px;
  background: #fff; color: #2a1a5e;
  font-size: 11.5px; font-weight: 800;
  box-shadow: 0 4px 14px rgba(0,0,0,.28);
}

@media (max-width: 768px) {
  .live-ph-grid { grid-template-columns: repeat(2, 1fr); gap: 10px; }
  .live-ph { border-radius: 14px; padding: 10px; }
  .live-ph-art { top: 14%; font-size: 38px; }
  .live-ph-body h3 { font-size: 12.5px; }
  .live-ph-body p { font-size: 10.5px; }
  .live-ph-badge { font-size: 10px; padding: 3px 8px; }
  .live-ph-viewers { font-size: 10px; }
  .live-ph-time { font-size: 11px; }
  .live-ph-cta { font-size: 11px; padding: 5px 10px; }
}
@media (max-width: 380px) {
  .live-ph-art { font-size: 32px; }
  .live-ph-body h3 { font-size: 11.5px; }
  /* 老机型上说明文字只留一行，优先保证标题与徽标不挤 */
  .live-ph-body p { -webkit-line-clamp: 1; }
}

/* ============================================================================
   「我的」页
   设计要点：
     1) 身份码从「灰紫小胶囊」升为主角 —— 它是访客唯一的找回凭据，
        现在整行可点、字号提上去，右侧直接给「查看身份卡」入口
     2) 升级正式账号并进身份头卡：它和身份是同一件事，不该散在两处
     3) 会员从「统计卡」改成「价值条」：状态 + 一句价值 + CTA 在同一行
     4) 统计位只留两个真数字，等高对齐
     5) 订单 / 流水在 C 端是懒记录：空态一行、默认列最近三条、需要时展开
   ============================================================================ */
.me-page { max-width: 620px; }

/* ---------- 身份头卡 ---------- */
#me-info { padding: 0; }
.me-hero-top { display: flex; gap: 12px; align-items: flex-start; padding: 14px; }
.me-ident { flex: 1; min-width: 0; }
.me-nick { display: flex; align-items: center; gap: 6px; font-size: 16px; font-weight: 800; line-height: 1.35; }
.me-sub { margin-top: 4px; font-size: 12px; color: var(--muted); }

.me-code {
  margin-top: 9px; width: 100%;
  display: flex; align-items: center; gap: 8px;
  padding: 9px 11px; border-radius: 11px;
  background: var(--brand-soft-8, rgba(108,92,231,.12));
  border: 1px solid var(--brand-line-35, rgba(108,92,231,.34));
  color: inherit; font: inherit; text-align: left; cursor: pointer;
  transition: background .15s, border-color .15s;
}
.me-code:active { background: var(--brand-soft-16, rgba(108,92,231,.2)); }
.me-code-lbl { flex: none; font-size: 11.5px; color: var(--muted); }
.me-code b {
  font-family: ui-monospace, Consolas, monospace;
  font-size: 15.5px; font-weight: 800; letter-spacing: 1.6px;
  color: var(--brand-ink); font-variant-numeric: tabular-nums;   /* 浅底上用 --brand-ink 才达标（原来是 --ink-violet，玫瑰下只有 3.77:1） */
}
/* 「查看身份卡 ›」：原来是写死的浅紫 #c084fc，压浅底只有 2.26:1 */
.me-code-act { margin-left: auto; flex: none; font-size: 11.5px; font-weight: 700; color: var(--brand-ink); }
.me-tip {
  margin-top: 9px; display: flex; gap: 6px; align-items: flex-start;
  font-size: 11.5px; line-height: 1.5; color: var(--gold, #f0b429);
}

/* 正式会员的「身份卡」入口：与游客的临时身份码块视觉同级，但更轻（它不承担找回职责） */
.me-card-btn {
  margin-top: 9px; display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 11px; border-radius: 10px;
  background: rgba(108,92,231,.12); border: 1px solid rgba(108,92,231,.34);
  color: var(--ink-violet); font: inherit; font-size: 12.5px; font-weight: 700; cursor: pointer;
}
.me-card-btn:active { background: rgba(108,92,231,.2); }

/* 「永久入口」：所属代理的专属裸域名 —— 会员记着它就能随时回来，传出去业绩也算这位代理的。
   放在昵称块下方单独一行，域名用等宽大字（要能照着输），复制按钮在右侧。 */
.me-entry {
  display: flex; align-items: center; gap: 10px;
  margin: 0 14px 14px; padding: 11px 12px; border-radius: 12px;
  background: linear-gradient(135deg, rgba(124,92,255,.16), rgba(91,140,255,.12));
  border: 1px solid rgba(124,92,255,.34);
}
.me-entry-main { flex: 1; min-width: 0; }
.me-entry-lbl { font-size: 11.5px; color: var(--muted); }
.me-entry-domain {
  display: block; margin: 2px 0 3px;
  font-family: ui-monospace, Consolas, monospace;
  font-size: 17px; font-weight: 800; letter-spacing: .5px;
  color: var(--ink-violet-3); word-break: break-all;
}
.me-entry-tip { font-size: 11.5px; line-height: 1.5; color: var(--muted); }

/* 身份卡里的「永久入口」那一行：整行可点（提示"点击复制"），点击范围要大 */
.identity-entry {
  margin: 10px 0 2px; padding: 8px 10px; border-radius: 10px;
  background: rgba(108,92,231,.1); border: 1px dashed rgba(108,92,231,.5);
  font-size: 13px; color: #4a3fa8; cursor: pointer; user-select: none;
}
.identity-entry b { font-family: ui-monospace, Consolas, monospace; font-size: 15px; }
.identity-entry::after { content: " 点击复制"; font-size: 11px; color: #7b74a8; }

/* ---------- 升级正式账号（身份头卡的下半段） ---------- */
.me-upgrade {
  padding: 13px 14px 14px;
  border-top: 1px solid var(--line);
  background: rgba(108,92,231,.07);
}
.me-upgrade-title { font-size: 14px; font-weight: 800; margin-bottom: 4px; }
.me-upgrade-note { margin: 0 0 11px; font-size: 11.5px; line-height: 1.6; color: var(--muted); }
.me-upgrade-btns { display: flex; gap: 8px; }
.me-upgrade-btns .btn { flex: 1; }

/* ---------- 会员价值条 ---------- */
.me-vip { display: flex; align-items: center; gap: 12px; padding: 13px 14px; border-top: 1px solid var(--line); }
.me-vip-main { flex: 1; min-width: 0; }
.me-vip-title { font-size: 14px; font-weight: 800; }
.me-vip-sub { margin-top: 2px; font-size: 11.5px; line-height: 1.5; color: var(--muted); }
.me-vip .btn { flex: none; }

/* ---------- 资产（两张真统计，等高） ---------- */
.me-assets {
  display: grid; grid-template-columns: 1fr 1fr; gap: 10px;
  padding: 13px 14px; border-top: 1px solid var(--line);
}
.me-asset { background: var(--card2); border-radius: 12px; padding: 11px 12px; }
.me-asset-lbl { font-size: 11.5px; color: var(--muted); }
.me-asset-num {
  margin-top: 2px; font-size: 22px; font-weight: 800; line-height: 1.2;
  font-variant-numeric: tabular-nums;
}
.me-asset-num.gold { color: var(--gold, #f0b429); }
.me-asset-num small { margin-left: 3px; font-size: 12px; font-weight: 600; color: var(--muted); }

/* ---------- 行动区 ---------- */
.me-act { display: flex; padding: 0 14px 12px; }
.me-act .btn { flex: 1; }
/* 次级实心（tonal）：和品牌紫的实心主按钮同色系但轻一档，
   避免一屏里出现两种互相争抢的强调色 */
.btn.tonal {
  background: var(--brand-soft-16);
  border: 1px solid rgba(108,92,231,.42);
  color: var(--ink-violet-2);
}
.me-note { margin: 0; padding: 0 14px 14px; font-size: 11.5px; line-height: 1.65; color: var(--muted); }

/* ---------- 我的：两格数字条 + 永久入口细行 + 操作行 ----------
   重排理由（用户反馈「排版凌乱、入口卡不理想」）：原来「身份 / 永久入口 / 升级 / 会员 / 金币」
   是一串各自为政的大块，视觉重量全堆在顶部。现在收成三层：
     ① 两格数字（金币 · 会员）—— 一眼看到最常看的两个数；
     ② 永久入口降为一条细行（只有它真的需要"复制"这个动作）；
     ③ 操作行两等分（分享赚金币 · 外观主题），不再是两个宽度、两种风格各占一行。 */
/* ---------- 「我的」页：页头 + 7 张胶囊卡 ----------
   为什么改成"一卡一件事"：上一版把会员与金币挤在同一行的 3:1 格里，两张卡互相压着，
   金额与状态都只能挤成小字。现在会员、金币各自全宽成卡，每张卡用一个图标 + 一种色系
   表明它属于哪类事，整页读起来是"一排整齐的胶囊"，而不是一堆格子。

   配色语义（全部走主题 token，三套主题各自成立）：
     会员=品牌渐变（唯一可充值，唯一有动效）· 金币/入口=金色（裂变）· 主题/记录=中性 */
.me-id { display: flex; gap: 12px; align-items: flex-start; padding: 4px 2px 12px; }
.me-id-tip { display: flex; gap: 6px; align-items: center; margin: -4px 2px 12px;
  font-size: 11.5px; line-height: 1.5; color: var(--warn); }
.me-id-tip svg { flex: none; }
.me-caps { position: relative; display: block; width: 100%; text-align: left;
  margin-bottom: 10px; padding: 13px 14px; border-radius: 16px;
  background: var(--card); border: 1px solid var(--line); color: inherit;
  box-shadow: 0 1px 2px rgba(0, 0, 0, .04); }
button.me-caps, .me-caps--tap { cursor: pointer; font: inherit; }
button.me-caps:active, .me-caps--tap:active { transform: scale(.994); }
.me-caps--tap:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.me-caps-head { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.me-caps-head b { font-size: 13.5px; font-weight: 800; }
.me-caps-ico { width: 26px; height: 26px; flex: none; border-radius: 9px;
  display: inline-flex; align-items: center; justify-content: center; }
.me-caps-note { margin-left: auto; font-size: 11.5px; color: var(--muted); }
/* 小徽标（剩 N 天 / 差 N 个）：靠右的小药丸，不抢主信息 */
.me-caps-tag { margin-left: auto; padding: 1px 8px; border-radius: 999px;
  font-size: 11px; font-weight: 800; color: var(--text);
  background: rgba(246, 165, 60, .14); }
.me-caps-main { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.me-caps-row { display: flex; align-items: center; gap: 10px; }
.me-caps-big { font-size: 20px; font-weight: 800; line-height: 1.2; }
.me-caps-sub { font-size: 11.5px; color: var(--muted); }
/* ① 会员：品牌色系 + 呼吸光按钮 */
.me-caps--vip { border-color: var(--brand-weak, var(--line)); }
.me-caps--vip .me-caps-ico { background: linear-gradient(135deg, var(--brand), var(--brand2, var(--brand))); color: #fff; }
.me-cta { display: block; text-align: center; width: 100%; margin-top: 11px; padding: 10px;
  border: 0; border-radius: 11px; box-sizing: border-box;
  font-size: 13.5px; font-weight: 800; color: #fff; cursor: pointer;
  background: linear-gradient(135deg, var(--brand), var(--brand2, var(--brand))); }
.me-cta:active { transform: scale(.99); }
@media (prefers-reduced-motion: no-preference) {
  .me-cta { animation: meBreath 2.6s ease-in-out infinite; }
  @keyframes meBreath {
    0%, 100% { filter: drop-shadow(0 0 0 var(--brand)); }
    50% { filter: drop-shadow(0 0 9px var(--brand)); }
  }
}
/* ② 金币：金色系；分享按钮在卡内（全宽后终于放得下文字） */
.me-caps--coin .me-caps-ico { background: rgba(255, 209, 102, .18); color: var(--warn); }
.me-share { margin-left: auto; flex: none; display: inline-flex; align-items: center; gap: 6px;
  padding: 8px 12px; border-radius: 11px; font-size: 12.5px; font-weight: 800; cursor: pointer;
  color: var(--text); background: rgba(255, 209, 102, .14);
  border: 1px solid rgba(255, 209, 102, .38); }
.me-share svg { color: var(--warn); }
.me-share:active { transform: scale(.97); }
/* ③ 入口：金色虚线感 + 域名大字 */
.me-caps--entry { border-style: dashed; border-color: rgba(255, 209, 102, .45); }
.me-caps--entry .me-caps-ico { background: rgba(255, 209, 102, .14); color: var(--warn); }
/* 入口卡的域名是这张卡的主角：比正文大一档、品牌色、字距略松，扫一眼就能读出来 */
/* 一行放不下时让域名收缩省略，而不是把"点击复制"挤到第二行 */
.me-caps--entry .me-caps-head { flex-wrap: nowrap; gap: 6px; }
.me-entry-domain { font-size: 18px; font-weight: 800; letter-spacing: .3px; color: var(--brand);
  min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* 「点击复制」：整卡可点必须写出来 —— 用小药丸，不与域名抢主次 */
.me-entry-hint { margin-left: auto; flex: none; display: inline-flex; align-items: center;
  padding: 3px 9px; border-radius: 999px; font-size: 11px; font-weight: 800;
  color: var(--brand); background: var(--surface-2, rgba(255, 255, 255, .06));
  border: 1px solid var(--line); white-space: nowrap; }
/* 金币卡底部的提示：一条细虚线隔开，字号再小一号 —— 它是"说明"，不该和余额抢视线 */
.me-caps-foot { margin-top: 9px; padding-top: 9px; border-top: 1px dashed var(--line);
  font-size: 11px; line-height: 1.55; color: var(--muted); }
/* 金币卡：图标 + 金币 + 余额 + 动态小字 + 分享钮 全部同一行 */
.me-caps-head--coin { margin-bottom: 0; gap: 7px; flex-wrap: nowrap; }
.me-caps-head--coin .me-caps-big { font-size: 18px; }
.me-caps-head--coin .me-caps-sub { margin-left: 1px; }
.me-caps-head--coin .me-share { margin-left: auto; }
/* 入口卡压成一行后，域名紧跟在「永久入口」后面，靠右仍是复制图标 */
.me-caps--entry .me-caps-head b.me-entry-domain { margin-left: 8px; }
/* ④ 升级：品牌色系，两条利益点 */
.me-caps--up { border-color: var(--brand-weak, var(--line)); }
.me-caps--up .me-caps-ico { background: rgba(108, 92, 231, .14); color: var(--brand); }
.me-up-list { margin: 0 0 11px; padding-left: 17px; font-size: 11.5px; line-height: 1.8; color: var(--muted); }
.me-up-list b { color: var(--brand); font-size: 12.5px; }
.me-up-btns { display: flex; gap: 8px; }
.me-up-btns .btn { flex: 1; }
/* ⑤ 主题：中性，一行读完 */
.me-caps--theme .me-caps-ico { background: var(--surface-2, rgba(255, 255, 255, .06)); color: var(--muted); }
.me-theme-go { margin-left: 6px; color: var(--muted); }
/* ⑥⑦ 订单 / 流水：沿用 .me-block，但统一成同样的胶囊外观 */
.me-block { border-radius: 16px; margin-bottom: 10px; }
@media (max-width: 360px) {
  .me-caps { padding: 12px; border-radius: 14px; }
  .me-caps-big { font-size: 18px; }
  .me-cta { font-size: 12.5px; padding: 9px; }
  .me-share { padding: 7px 9px; font-size: 11.5px; }
}
.me-stat { position: relative; padding: 10px 12px; border-radius: 12px;
  background: var(--surface-2, rgba(255,255,255,.04)); border: 1px solid var(--line); }
.me-stat-lbl { font-size: 11.5px; color: var(--muted); }
.me-stat-num { margin-top: 2px; font-size: 17px; font-weight: 800; line-height: 1.25;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.me-stat-num.gold { color: var(--text); }   /* 数字用正文色：浅金在浅底上对比不足（装饰性的金色只留给图标/虚线） */
.me-stat-sub { margin-top: 2px; font-size: 11px; color: var(--muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.me-stat-sub small { font-size: 10.5px; }
.me-stat-btn { margin-top: 6px; padding: 2px 10px; border-radius: 999px; font-size: 11.5px;
  font-weight: 700; color: var(--accent); background: var(--accent-weak, rgba(0,212,170,.14));
  border: 0; cursor: pointer; }
.me-entry-row { display: flex; align-items: center; gap: 8px; width: calc(100% - 28px);
  margin: 0 14px 12px; padding: 9px 12px; border-radius: 12px; cursor: pointer; text-align: left;
  background: transparent; border: 1px dashed var(--line); color: inherit; }
.me-entry-row:active { background: var(--surface-2, rgba(255,255,255,.04)); }
.me-entry-row .me-entry-lbl { flex: none; font-size: 11.5px; color: var(--muted); }
.me-entry-row .me-entry-domain { flex: 1; min-width: 0; font-size: 13px; font-weight: 700;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.me-entry-row .me-entry-copy { flex: none; color: var(--muted); display: inline-flex; }
.me-actions { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; padding: 0 14px 10px; }
.me-act-btn { display: flex; align-items: center; justify-content: center; gap: 6px;
  padding: 10px 8px; border-radius: 12px; font-size: 13px; font-weight: 700; cursor: pointer;
  color: var(--text); background: var(--surface-2, rgba(255,255,255,.04));
  border: 1px solid var(--line); }
.me-act-btn b { font-weight: 600; font-size: 11.5px; color: var(--muted); }
.me-act-btn:active { transform: scale(.985); }
@media (max-width: 360px) {
  .me-stats { gap: 8px; }
  .me-stat-num { font-size: 17px; }
}

/* ---------- 明细区（我的订单 / 金币流水） ---------- */
.me-block { margin-top: 12px; padding: 14px; }
.me-sec { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 10px; }
.me-sec h3 { font-size: 14.5px; font-weight: 800; }
.me-more {
  border: none; background: none; padding: 0;
  color: #c084fc; font-size: 11.5px; font-weight: 700;
  font-family: inherit; cursor: pointer;
}
.me-empty { color: var(--muted); font-size: 12.5px; padding: 2px 0; }

.me-item { display: flex; gap: 10px; padding: 10px 0; border-bottom: 1px solid var(--line); }
.me-item:last-child { border-bottom: none; padding-bottom: 0; }
.me-item-main { flex: 1; min-width: 0; }
.me-item-title { font-size: 13px; font-weight: 700; }
.me-item-sub {
  margin-top: 2px; font-size: 10.5px; color: var(--muted);
  font-variant-numeric: tabular-nums;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.me-item-side { flex: none; text-align: right; }
.me-item-amt { font-size: 14px; font-weight: 800; font-variant-numeric: tabular-nums; }
.me-item-meta { margin-top: 3px; display: flex; gap: 6px; align-items: center; justify-content: flex-end; }
.me-item-time { flex: none; font-size: 10.5px; color: var(--muted); white-space: nowrap; }

.me-tx { display: flex; align-items: center; gap: 10px; padding: 9px 0; border-bottom: 1px solid var(--line); }
.me-tx:last-child { border-bottom: none; padding-bottom: 0; }
.me-tx-amt { flex: none; min-width: 54px; font-size: 13.5px; font-weight: 800; font-variant-numeric: tabular-nums; }
.me-tx-amt.in { color: var(--gold, #f0b429); }
.me-tx-amt.out { color: var(--muted); }
.me-tx-reason { flex: 1; min-width: 0; font-size: 12.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.avatar.lg { width: 52px; height: 52px; font-size: 20px; }

/* ============================================================================
   首页海报轮播（广告位 home_hero）
   用原生横向滚动 + scroll-snap 做滑动：手机上自带惯性滑动与吸附，
   不用自己写手势；自动播放只是定时 scrollTo。后台一条广告都没配时，
   #home-hero 里仍然是那个内置静态介绍卡，这块样式不会被用到。
   ============================================================================ */
.hero-carousel { position: relative; border-radius: 16px; overflow: hidden; margin-bottom: 8px; background: var(--card2); }
.hc-track {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.hc-track::-webkit-scrollbar { display: none; }
.hc-slide { flex: 0 0 100%; scroll-snap-align: start; display: block; aspect-ratio: 3 / 1; }
.hc-slide img { width: 100%; height: 100%; object-fit: cover; display: block; }
.hc-dots {
  position: absolute; left: 0; right: 0; bottom: 8px;
  display: flex; justify-content: center; gap: 5px; pointer-events: none;
}
.hc-dots i {
  width: 6px; height: 6px; border-radius: 999px;
  background: rgba(255,255,255,.42); box-shadow: 0 1px 3px rgba(0,0,0,.5);
  transition: width .22s ease, background .22s ease;
}
.hc-dots i.on { width: 16px; background: #fff; }
@media (max-width: 768px) {
  .hero-carousel { border-radius: 14px; }
}

/* ============================================================
   共享双色图标（/shared/js/dsh-icons.js）在 C 端的基样式
   C 端只引图标脚本、不引那份后台列表样式（dsh-ui.css），所以在这里补上尺寸规则。
   图标本身来自共享图标集：与两个后台同源、同风格，改一处三端一致。
   ============================================================ */
.ico { display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; flex: 0 0 18px; vertical-align: -4px; color: currentColor; }
.ico svg { width: 100%; height: 100%; display: block; }
h1 .ico, h2 .ico, h3 .ico, .section-head .ico, .section-title .ico { vertical-align: -3px; margin-right: 6px; }
/* 按钮里的图标要跟着按钮字号走，别把按钮顶高 */
.btn .ico, .btn-sm .ico { width: 15px; height: 15px; flex-basis: 15px; vertical-align: -3px; margin-right: 5px; }
.lock-minor .ico, .me-item-sub .ico, .me-tx-amt .ico, .muted .ico { width: 13px; height: 13px; flex-basis: 13px;
  vertical-align: -2px; margin-right: 3px; }
.coin-row .ico { width: 15px; height: 15px; flex-basis: 15px; vertical-align: -3px; margin-right: 4px; }
/* 点赞 / 收藏 / 声音这类「可点状态」：图标填色即"已激活"，不再靠字重或颜色差 */
.vlike .ico, .ctl-bar .ico { margin-right: 4px; }
.vlike[data-liked="1"] .ico, .ctl-bar .ico.on { color: var(--accent, #ff5b6a); }
/* 直播状态点（列表标题里的「直播中 / 未开播」）：原来用 🔴/⚫ emoji —— 各系统字形大小不一，
   会把标题行高顶开，改用 CSS 圆点。
   注意类名不能叫 .live-dot —— 那个名字在第 227 行已被「直播封面上的白色脉冲点」占用。 */
.live-state-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%;
  background: #6b7280; margin-right: 6px; vertical-align: 1px; }
.live-state-dot.on { background: #ff4d4f; box-shadow: 0 0 0 3px rgba(255, 77, 79, .18); }

/* ---------- 无障碍：尊重「减少动态效果」 ----------
   系统里常驻循环动效不少：跑马灯无限滚动、卡片封面循环小视频、起播键脉冲、
   直播红点脉冲、转盘旋转。对前庭功能敏感的用户，满屏循环动效是实打实的不适，
   而这是成本最低、收益最明确的一项适配。

   注意两点：
     · **保留内容**：跑马灯只是停住滚动（不是 display:none），公告信息不能因此丢失；
     · 动图元素由 views.js 的 coverAnim* 在创建前就查一次这个媒体查询（不创建最省事），
       这里再兜一层 —— 万一有元素已经建出来，也不能继续动。 */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  .marquee .mq-track { animation: none; transform: none; }
  .vcard:hover { transform: none; }
  .card.clickable:hover { transform: none; }
  .card.plan:hover { transform: none; }
}

/* 「我的 → 外观主题」入口：整行可点，右侧显示当前主题名。
   与顶栏那个圆形图标共用同一个抽屉（Theme.openPicker），所以两处状态天然一致。 */
.me-theme{display:flex;align-items:center;gap:9px;width:100%;margin-top:10px;padding:12px 13px;
  background:var(--card2);border:1px solid var(--line);border-radius:12px;color:var(--text);
  font-size:13.5px;cursor:pointer;text-align:left}
.me-theme:hover{border-color:var(--brand)}
.me-theme .ico{color:var(--brand-ink);flex:none}
.me-theme b{margin-left:auto;color:var(--muted);font-weight:600}
.me-theme-go{color:var(--muted);flex:none}

/* ---------- 升级正式账号弹窗（整改） ----------
   背景：旧版把关闭键做成滚动容器里的绝对定位元素，内容一滚就跟着滚走，
   小屏上用户找不到"返回"→ 被卡在这一页。现在头部固定，底部再给一个文字按钮。 */
.gm-head{display:flex;align-items:center;justify-content:space-between;gap:10px;
  position:sticky;top:-20px;z-index:2;margin:-20px -16px 10px;padding:14px 16px 10px;
  background:var(--card);border-bottom:1px solid var(--line-soft)}
.gm-head h2{font-size:17px;margin:0}
.gm-x{width:32px;height:32px;flex:none;border:none;border-radius:50%;background:var(--surface-4);
  color:var(--muted);font-size:19px;line-height:1;cursor:pointer}
.gm-x:active{background:var(--brand-soft-16);color:var(--brand-ink)}
.ferr{display:none;margin:6px 0 0;color:var(--danger-ink);font-size:12px;line-height:1.4}
.pwd{position:relative;display:flex;align-items:center}
.pwd input{flex:1;min-width:0;padding-right:52px}
.pwd-eye{position:absolute;right:6px;border:none;background:transparent;color:var(--brand-ink);
  font-size:12px;font-weight:600;padding:6px 8px;cursor:pointer}
.cred{border:1px solid var(--brand-line-35);background:var(--brand-soft-8);border-radius:12px;
  padding:10px 12px;margin:10px 0 14px}
.cred-row{display:flex;align-items:center;gap:8px;padding:5px 0}
.cred-row span{flex:none;width:46px;color:var(--muted);font-size:12px}
.cred-row b{flex:1;min-width:0;font-size:14px;word-break:break-all}

/* ---------- 低对比度整改（全站扫描后补的） ----------
   来源：浅色/玫粉主题下文字看不清的问题，用 _probe/audit-contrast.mjs 逐页逐主题扫出来的。 */
/* 「去注册/去登录」这类提示链接：--brand 当**文字**太浅（玫瑰 3.49、深色 3.32），换 --brand-ink */
.hint a, .form-card .hint a { color: var(--brand-ink); text-decoration: underline; }
/* 分类文字：浅色系主题把明度压到 36%（深色系保持 74%）—— 原来的 74% 压白卡片只有 1.42:1 */
:root[data-theme="light"] .vcat, :root[data-theme="rose"] .vcat,
:root[data-theme="light"] .cat-chip, :root[data-theme="rose"] .cat-chip { --cat-l: 30%; }
/* 短视频（压在全屏视频上）：次要文字用半透明白，别跟随主题 */
.short-ui .muted, .short-ui .short-meta .muted { color: rgba(255, 255, 255, .78); }
.short-ui h3, .short-ui .short-meta { color: #fff; }

/* ---------- 短视频：竖向滑动切换（本轮整改） ----------
   结构：.short-stage > .short-track > .short-slot × 3，中间那条正好对齐屏幕。
   恒定只渲染 3 条（上一条/当前/下一条），翻页靠回收节点 —— 所以"全部加载"也不会
   堆出几百个 <video>；而且当前这条的节点不被重建，视频不会划过去又从头播。 */
.short-stage{position:relative;overflow:hidden;background:#000;
  touch-action:none;                 /* 竖向手势自己处理，别让浏览器抢去做下拉刷新 */
  overscroll-behavior:contain}
.short-track{position:absolute;inset:0;display:flex;flex-direction:column;height:300%;
  will-change:transform;transform:translateY(0)}
.short-slot{position:relative;flex:0 0 33.3333%;height:33.3333%;width:100%;overflow:hidden}
.short-slot[data-idx="-1"]{background:#000}
/* 圆形半透明返回键（借鉴目标站：37px、rgba(255,255,255,.12)） */
.short-back{position:absolute;left:12px;top:12px;z-index:7;width:37px;height:37px;padding:0;
  border:0;border-radius:50%;background:rgba(255,255,255,.14);color:#fff;
  font-size:21px;line-height:35px;text-align:center;cursor:pointer;
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px)}
.short-back:active{background:rgba(255,255,255,.26)}
/* 首进提示：上滑看下一条（划一次就永远不再出现） */
.short-hint{position:absolute;left:0;right:0;bottom:30%;z-index:6;display:flex;
  flex-direction:column;align-items:center;gap:4px;color:#fff;pointer-events:none;
  opacity:0;transition:opacity .35s ease;text-shadow:0 1px 10px rgba(0,0,0,.65)}
.short-hint.on{opacity:.95;animation:shortHintUp 1.7s ease-in-out infinite}
.short-hint b{font-size:13.5px;font-weight:800;letter-spacing:.5px}
.short-hint span{font-size:11.5px;opacity:.86}
@keyframes shortHintUp{0%{transform:translateY(7px)}50%{transform:translateY(-7px)}100%{transform:translateY(7px)}}
/* 进度条：细轨 + 白色圆点滑块（借鉴目标站：轨 3px/22% 白，点 13px 白） */
.short-ctl .short-bar{overflow:visible;height:3px;background:rgba(255,255,255,.22)}
.short-ctl .short-bar i{position:relative;background:linear-gradient(90deg,#ffb020,#ff6b3d)}
.short-ctl .short-bar i::after{content:"";position:absolute;right:-6px;top:50%;width:13px;height:13px;
  margin-top:-6.5px;border-radius:50%;background:#fff;box-shadow:0 1px 5px rgba(0,0,0,.45)}
/* 动作栏：头像在最上（借鉴目标站排布），间距与规格对齐它的右侧栏 */
.short-actions{gap:15px}
.short-actions .short-author{display:flex;flex-direction:column;align-items:center;gap:4px}
.short-actions .short-author b{font-size:11px;max-width:60px;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}

/* ---------- 短视频起播反馈（用户反馈点了播放键没反应） ----------
   起播时要等网络：过去一点就立刻收掉闸门 → 用户以为没反应。
   现在闸门留到 playing 事件再收，等待期间在这里转圈。 */
.play-spin{display:none;width:32px;height:32px;margin:12px auto 0;border-radius:50%;
  border:3px solid rgba(255,255,255,.28);border-top-color:#fff;
  animation:shortSpin .85s linear infinite}
.short-item.loading .play-spin,.player-box.loading .play-spin{display:block}
.short-item.loading .play-big{opacity:.55}
@keyframes shortSpin{to{transform:rotate(360deg)}}

/* ---------- 身份卡弹窗（本轮）：正式账号标识 / 明显关闭 / 倒计时 ---------- */
#identity-card-overlay .modal-close { top: 10px; right: 10px; width: 34px; height: 34px;
  border-radius: 50%; font-size: 22px; line-height: 1;
  background: var(--surface-2, rgba(0, 0, 0, .06)); border: 1px solid var(--line);
  color: var(--text); display: inline-flex; align-items: center; justify-content: center; }
#identity-card-overlay .modal-close:active { transform: scale(.94); }
.identity-countdown { position: absolute; top: 48px; right: 12px; font-size: 10.5px;
  color: var(--muted); letter-spacing: .2px; }
/* 「正式账号」标识：与"临时身份码"一眼区分，不做成花哨徽章 */
.id-acc { margin-left: 8px; padding: 1px 7px; border-radius: 6px; vertical-align: 2px;
  font-size: 10.5px; font-weight: 800; letter-spacing: .3px;
  color: var(--brand); background: var(--surface-2, rgba(0, 0, 0, .05)); border: 1px solid var(--line); }

/* ---------- 视频流：到底提示 + 返回顶部 ---------- */
.vl-end { grid-column: 1 / -1; padding: 18px 0 6px; text-align: center;
  font-size: 11.5px; color: var(--muted); letter-spacing: .2px; }
/* 返回顶部：极简的圆形描边按钮，浮在内容右下、避开底部导航 */
.back-top { position: fixed; right: 14px; bottom: 74px; z-index: 40;
  width: 38px; height: 38px; display: inline-flex; align-items: center; justify-content: center;
  padding: 0; cursor: pointer; border-radius: 50%;
  color: var(--muted); background: var(--surface, rgba(20, 20, 24, .72));
  border: 1px solid var(--line); backdrop-filter: blur(6px);
  box-shadow: 0 4px 14px rgba(0, 0, 0, .18); }
.back-top:active { transform: scale(.94); }
.back-top[hidden] { display: none; }

/* 「我的」最底部：退出登录（弱化存在感，靠二次确认防误触） */
.me-logout{margin:22px 0 6px;text-align:center}
.me-logout-btn{border:none;background:transparent;padding:10px 16px;cursor:pointer;
  font-size:13px;color:var(--muted);border-radius:10px}
.me-logout-btn:hover{color:var(--text);background:var(--surface-4)}
.me-logout-btn:active{transform:scale(.98)}
