/* ============================================================
   MUSIC CUP · 音乐世界杯
   深色 · 玻璃拟态 · 紫粉品牌色
   ============================================================ */

/* 自托管字体（拉丁子集，中文使用系统字体：苹方 / MiSans / 雅黑） */
@font-face {
  font-family: "Anton";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/anton-400.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Space Grotesk";
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url("../fonts/space-grotesk.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  --bg: #08080d;
  --panel: rgba(255, 255, 255, .045);
  --panel-2: rgba(255, 255, 255, .08);
  --line: rgba(255, 255, 255, .1);
  --line-soft: rgba(255, 255, 255, .06);
  --txt: #f4f4f8;
  --dim: rgba(235, 235, 245, .58);
  --dim2: rgba(235, 235, 245, .34);
  --acc1: hsl(258 84% 64%);
  --acc2: hsl(304 78% 66%);
  --acc1-soft: hsl(258 84% 64% / .34);
  --acc2-soft: hsl(304 84% 64% / .26);
  --grad: linear-gradient(135deg, var(--acc1), var(--acc2));
  --r-lg: 26px;
  --r-md: 18px;
  --r-sm: 12px;
  --font-cn: -apple-system, "PingFang SC", "Noto Sans SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
  --font-en: "Space Grotesk", "SF Pro Display", -apple-system, sans-serif;
  --font-display: "Anton", "Space Grotesk", "Arial Narrow", sans-serif;
  --shadow-card: 0 18px 50px -18px rgb(0 0 0 / .65);
  --topbar-h: 58px;
}

* { margin: 0; padding: 0; box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

html { color-scheme: dark; }

html { overflow-x: clip; }
body {
  background: var(--bg);
  color: var(--txt);
  font-family: var(--font-cn);
  font-size: 16px;
  line-height: 1.5;
  min-height: 100vh;
  min-height: 100dvh;
  overflow-x: clip;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
input { font: inherit; color: inherit; }
img { display: block; max-width: 100%; }
svg { display: block; }
::selection { background: var(--acc1-soft); }

.en { font-family: var(--font-en); }

/* ---------- 语言切换（仅首页左上角：🌐 + 当前语言名，点击弹语言列表） ---------- */
/* 与首页搜索框左缘严格对齐：内容列左缘 = 50% − 列宽/2 + .screen 的 20px 内边距。
   列宽分三档（.home 基础 520 / ≥760 是 560 / ≥1100 被 .screen 的 720 覆盖），
   三档的 left 因此写在各自的媒体查询里；移动端列宽=视口，左缘就是那 20px 内边距。 */
.lang-switch {
  position: fixed;
  top: calc(env(safe-area-inset-top) + 14px);
  left: max(20px, calc(50% - 240px));
  z-index: 50;
  display: inline-flex; align-items: center; gap: 6px;
  /* 透明的等高内衬：与右上角排行榜胶囊（padding 7 + 边框 1）同高，
     两颗按钮共用同一个 top 时中线才对齐 */
  padding: 8px 0;
  font-size: 12px; font-weight: 500; letter-spacing: .04em;   /* 字重与首页歌手 chip 一致 */
  color: rgba(244, 244, 250, .72);
  transition: transform .15s, color .2s;
  user-select: none; -webkit-user-select: none;
}
.lang-switch svg { width: 15px; height: 15px; }
.lang-switch:active { transform: scale(.92); }
[dir="rtl"] .lang-switch { left: auto; right: max(20px, calc(50% - 240px)); }

/* 语言选择弹窗 */
.lang-box { width: min(88vw, 320px); }
.lang-list { display: grid; grid-template-columns: 1fr 1fr; gap: 9px; margin-top: 16px; max-height: min(58vh, 470px); overflow-y: auto; -webkit-overflow-scrolling: touch; }
.lang-item {
  min-height: 46px;
  padding: 0 10px;
  border-radius: 13px;
  background: var(--panel);
  border: 1px solid var(--line);
  font-size: 14px; font-weight: 600;
  color: var(--dim);
  transition: transform .15s, border-color .2s, color .2s;
}
.lang-item:active { transform: scale(.95); }
.lang-item.on {
  color: var(--txt);
  border-color: transparent;
  background: linear-gradient(var(--panel-2), var(--panel-2)) padding-box, var(--grad) border-box;
}

/* ---------- 氛围背景：极光渐变 + 颗粒 ---------- */
.ambient { position: fixed; inset: 0; z-index: -2; overflow: hidden; }
.blob {
  position: absolute;
  width: 72vmax; height: 72vmax;
  border-radius: 50%;
  filter: blur(70px);
  opacity: .5;
  transition: background 1.2s ease;
}
.b1 {
  top: -32vmax; left: -18vmax;
  background: radial-gradient(circle at 35% 35%, var(--acc1-soft), transparent 62%);
  animation: drift1 26s ease-in-out infinite alternate;
}
.b2 {
  bottom: -36vmax; right: -20vmax;
  background: radial-gradient(circle at 60% 60%, var(--acc2-soft), transparent 62%);
  animation: drift2 32s ease-in-out infinite alternate;
}
@keyframes drift1 { to { transform: translate(9vmax, 7vmax) rotate(24deg); } }
@keyframes drift2 { to { transform: translate(-8vmax, -6vmax) rotate(-18deg); } }

.grain {
  position: fixed; inset: 0; z-index: 90;
  pointer-events: none; opacity: .05;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='.6'/%3E%3C/svg%3E");
}

/* ---------- 顶栏 ---------- */
.topbar[hidden] { display: none; } /* display:flex 会盖过 hidden 属性的默认隐藏，需显式声明 */
.topbar {
  position: fixed; top: 0; left: 0; right: 0; z-index: 40;
  height: calc(var(--topbar-h) + env(safe-area-inset-top));
  padding: env(safe-area-inset-top) 10px 0;
  display: flex; align-items: center; gap: 4px;
  background: rgb(10 10 16 / .68);
  backdrop-filter: blur(20px) saturate(1.4);
  -webkit-backdrop-filter: blur(20px) saturate(1.4);
  border-bottom: 1px solid var(--line-soft);
}
.tb-btn {
  width: 42px; height: 42px;
  display: grid; place-items: center;
  border-radius: 50%;
  color: var(--dim);
  transition: color .2s, background .2s, transform .15s;
}
.tb-btn svg { width: 21px; height: 21px; }
.tb-btn:active { transform: scale(.9); background: var(--panel-2); color: var(--txt); }
.tb-btn.off { opacity: .25; pointer-events: none; }
.tb-mid { flex: 1; min-width: 0; text-align: center; line-height: 1.25; }
.tb-artist {
  display: block; font-weight: 700; font-size: 14px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tb-phase { display: block; font-size: 11px; color: var(--dim); letter-spacing: .04em; }
.tb-prog {
  position: absolute; left: 0; right: 0; bottom: -2px; height: 2px;
  background: rgb(255 255 255 / .06);
}
.tb-prog i {
  display: block; height: 100%;
  background: var(--grad);
  border-radius: 2px;
  transition: width .5s cubic-bezier(.2, .8, .2, 1);
  box-shadow: 0 0 12px var(--acc1-soft);
}

/* ---------- 布局骨架 ---------- */
#app { min-height: 100vh; min-height: 100dvh; display: flex; flex-direction: column; }
.screen {
  width: 100%; max-width: 520px;
  margin: 0 auto;
  padding: 20px 20px calc(40px + env(safe-area-inset-bottom));
  flex: 1; display: flex; flex-direction: column;
  /* 注意：.screen 自身只做透明度动画——transform 会把内部 fixed 元素变成相对它定位 */
  animation: screenFade .4s ease both;
}
.screen.with-topbar { padding-top: calc(var(--topbar-h) + env(safe-area-inset-top) + 18px); }
.screen.with-cta { padding-bottom: calc(120px + env(safe-area-inset-bottom)); }
@keyframes screenFade { from { opacity: 0; } }
@keyframes screenIn { from { opacity: 0; transform: translateY(14px); } }
.phase-head, .draw-head, .stat-row { animation: screenIn .45s cubic-bezier(.2, .8, .2, 1) both; }

/* ---------- 通用元件 ---------- */
.pill {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 13px;
  border-radius: 999px;
  font-size: 12px; font-weight: 700; letter-spacing: .12em;
  color: var(--txt);
  background: var(--panel-2);
  border: 1px solid var(--line);
}
.pill.grad {
  background: var(--grad);
  border: 0;
  box-shadow: 0 4px 18px -6px var(--acc1-soft);
}
.grad-text {
  background: var(--grad);
  -webkit-background-clip: text; background-clip: text;
  color: transparent;
}
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 54px;
  padding: 0 28px;
  border-radius: 999px;
  font-size: 17px; font-weight: 700;
  transition: transform .16s, box-shadow .25s, opacity .2s, filter .2s;
  user-select: none; -webkit-user-select: none;
}
.btn svg { width: 20px; height: 20px; }
.btn:active { transform: scale(.96); }
.btn.primary {
  background: var(--grad);
  color: #fff;
  box-shadow: 0 10px 32px -10px var(--acc1-soft), inset 0 1px 0 rgb(255 255 255 / .25);
}
.btn.primary:disabled {
  opacity: .38; filter: saturate(.4);
  pointer-events: none;
  box-shadow: none;
}
.btn.ghost {
  background: var(--panel);
  border: 1px solid var(--line);
  color: var(--txt);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}
.btn.sm { min-height: 44px; padding: 0 20px; font-size: 15px; }

/* 底部固定操作条 */
.cta-bar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 30;
  padding: 14px 20px calc(16px + env(safe-area-inset-bottom));
  display: flex; justify-content: center; gap: 12px;
  background: linear-gradient(to top, rgb(8 8 13 / .96) 55%, transparent);
}
.cta-bar .btn { flex: 1; max-width: 480px; }

/* ============================================================
   首页
   ============================================================ */
/* margin-auto 居中：空间充足时垂直居中，内容超高时可正常从顶部滚动 */
.home {
  gap: 24px;
  min-height: 100vh; min-height: 100dvh;
  padding-bottom: calc(12px + env(safe-area-inset-bottom)); /* 推荐区贴近屏幕底缘 */
}
.home > .hero { margin-top: auto; }
.home > .home-foot { margin-bottom: auto; } /* 推荐区被推到屏幕最底部 */
.hero { text-align: center; padding-top: 10px; }
@keyframes heroFloat { 50% { transform: translateY(-7px) rotate(-3deg); } }

/* 组合字标：MUSIC 匀排 + CUP 巨字渐变 + 奖杯徽章叠角 + 整体斜切 */
.logo-lockup {
  position: relative;
  display: inline-block;
  margin: 0 auto;
  direction: ltr;   /* 品牌字标恒为 LTR：阿语 RTL 下逐字母 <i> 会被镜像成 CISUM */
  transform: skewX(-6deg);
  font-family: var(--font-display);
  font-weight: 400;
  text-transform: uppercase;
  line-height: 1;
  filter: drop-shadow(0 28px 70px var(--acc1-soft));
}
.logo-music {
  display: flex; justify-content: space-between;
  font-size: clamp(23px, 6.4vw, 30px);
  color: var(--txt);
  padding: 0 .12em;
  margin-bottom: 5px;
}
.logo-music i { font-style: normal; }
.logo-cup {
  display: block;
  font-size: clamp(94px, 25vw, 122px);
  line-height: .9;
  letter-spacing: .015em;
  padding-right: .05em;
  background: var(--grad);
  -webkit-background-clip: text; background-clip: text;
  color: transparent;
}
.logo-badge {
  position: absolute; top: -34px; left: 50%;
  font-size: 36px; line-height: 1;
  transform: skewX(6deg) translateX(-50%);
  filter: drop-shadow(0 12px 26px rgb(0 0 0 / .55));
  animation: badgeFloat 5s ease-in-out infinite;
}
@keyframes badgeFloat {
  0%, 100% { transform: skewX(6deg) translateX(-50%) rotate(0deg); }
  50% { transform: skewX(6deg) translateX(-50%) rotate(-6deg) translateY(-4px); }
}
.slogan {
  margin-top: 24px;
  font-size: clamp(20px, 5.6vw, 24px);
  font-weight: 900;
  letter-spacing: .22em;
  padding-left: .22em; /* 抵消末字字距，保持视觉居中 */
}
/* .22em 大字距只适合方块字短句；拉丁/西里尔/天城文长句按常规标题字距收紧 */
html[lang="en"] .slogan,
html[lang="es"] .slogan,
html[lang="fr"] .slogan,
html[lang="pt-BR"] .slogan,
html[lang="ru"] .slogan,
html[lang="id"] .slogan,
html[lang="de"] .slogan,
html[lang="hi"] .slogan {
  letter-spacing: .03em;
  padding-left: .03em;
}
/* 阿拉伯文是连写文字；泰文含上下组合音标，两者都不适合额外字距 */
html[lang="ar"] .slogan,
html[lang="th"] .slogan {
  letter-spacing: 0;
  padding-left: 0;
}
.tagline { margin-top: 8px; color: var(--dim); font-size: 14px; letter-spacing: .02em; }

.searchbox { position: relative; }
.search-field {
  display: flex; align-items: center; gap: 10px;
  height: 60px;
  padding: 0 20px;
  border-radius: 20px;
  background: var(--panel-2);
  border: 1px solid var(--line);
  /* 不加 backdrop-filter：WebKit 在毛玻璃容器内首次聚焦时光标会错位 */
  transition: border-color .25s, box-shadow .25s;
}
.searchbox.open .search-field,
.search-field:focus-within {
  border-color: var(--acc1-soft);
  box-shadow: 0 0 0 4px hsl(from var(--acc1) h s l / .12), 0 14px 40px -18px var(--acc1-soft);
}
.search-field svg { width: 21px; height: 21px; color: var(--dim); flex: none; }
.search-field input {
  flex: 1; min-width: 0;
  background: none; border: 0; outline: 0;
  font-size: 17px;
}
.search-field input::placeholder { color: var(--dim2); }
.sug {
  position: absolute; top: calc(100% + 10px); left: 0; right: 0; z-index: 20;
  border-radius: 20px;
  background: rgb(21 21 31 / .97);
  border: 1px solid var(--line);
  backdrop-filter: blur(24px) saturate(1.4);
  -webkit-backdrop-filter: blur(24px) saturate(1.4);
  box-shadow: var(--shadow-card);
  overflow: hidden;
  animation: sugIn .22s cubic-bezier(.2, .8, .2, 1) both;
}
@keyframes sugIn { from { opacity: 0; transform: translateY(-6px) scale(.985); } }
.sug:empty { display: none; }
.sug-item {
  display: flex; align-items: center; gap: 13px;
  width: 100%;
  padding: 14px 18px;
  text-align: left;
  transition: background .15s;
}
.sug-item:not(:last-child) { border-bottom: 1px solid var(--line-soft); }
.sug-item:active, .sug-item:hover { background: var(--panel-2); }
.sug-meta { min-width: 0; text-align: left; }
.sug-name { display: block; font-weight: 700; font-size: 15px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sug-genre { display: block; font-size: 12px; color: var(--dim); }
.sug-empty { padding: 18px; text-align: center; color: var(--dim); font-size: 14px; }

.chips-wrap { text-align: center; }
.chips-label { font-size: 12px; color: var(--dim2); letter-spacing: .16em; margin-bottom: 12px; }
/* 阿拉伯/天城文是连写文字，泰文含组合音标；.16em 字距会破坏字形 → 归零 */
html[lang="ar"] .chips-label,
html[lang="hi"] .chips-label,
html[lang="th"] .chips-label { letter-spacing: 0; }
.chips { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; }
.chip {
  padding: 7px 14px;
  border-radius: 999px;
  font-size: 12px; font-weight: 500;
  background: var(--panel);
  border: 1px solid var(--line);
  transition: transform .16s, background .2s, border-color .2s;
}
.chip:active { transform: scale(.94); }
.chip:hover { background: var(--panel-2); border-color: var(--acc1-soft); }

/* 曲库模式开关（纯文字，低调）：选中字亮 + 前置紫色勾，紧贴搜索框 */
.mode-pick { display: flex; justify-content: center; align-items: center; gap: 22px; margin-top: -12px; }
.mode-btn {
  padding: 3px 2px; border: 0; background: none;
  color: var(--dim2); font: inherit; font-size: 12px; cursor: pointer;
  transition: color .18s;
}
.mode-btn.on { color: var(--txt); }
.mode-btn.on::before { content: "✓"; margin-right: 4px; color: var(--acc1); font-size: 10px; }

.home-foot { text-align: center; font-size: 12px; color: var(--dim2); }

/* 首页底部：关于 / 玩法 / 隐私（弱化：纯文字、低对比） */
.home-links {
  width: 100%;
  /* gap 24 而不是原来的 40：三个入口并排，40 的话两条间隙就吃掉 80px，实测日 / 西 /
     法 / 葡 / 俄 / 印尼六种语言在 375px 上放不下。配合底部专用短标签（见 app.js 的
     tplHome），14 种语言在 320px 都排得下；wrap 仍留着兜更极端的字号放大。 */
  display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 4px 24px;
}
.home-link {
  padding: 6px 2px;
  font: inherit; font-size: 12px; color: var(--dim2);
  text-decoration: none;
  background: none; border: 0; cursor: pointer;
  transition: color .18s;
}
.home-link:hover { color: var(--dim); }
.home-link:active { color: var(--txt); }

/* 三个面板 .brand-btn 里的文字只有这一档：标题 14px/700、副标题 11px。原先第一层
   名片是 13 + 10.5、二级面板的社交按钮是 15，同一类按钮两套字号。跟 .brand-ico
   一样，面板级别不要再各调各的。整行 CTA（.dl-btn）是另一档，见那边。 */
.f-meta { min-width: 0; text-align: start; }
.f-meta b {
  display: block;
  font-size: 14px; font-weight: 700; color: var(--txt);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.f-meta i {
  font-style: normal;
  font-size: 11px; font-weight: 400; color: var(--dim); line-height: 1.35;
  margin-top: 1px;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}

/* 泽卿聊AI 关注面板 */
.zeqing-panel {
  position: relative;
  width: min(90vw, 360px);
  padding: 24px 22px 22px;
  border-radius: var(--r-lg);
  background: rgb(19 19 28 / .98);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-card);
  animation: riPop .35s cubic-bezier(.2, .9, .3, 1.15) both;
}
.zeqing-panel .modal-close { position: absolute; top: 10px; right: 10px; }
.zeqing-head { display: flex; align-items: center; gap: 13px; padding-right: 40px; }
.zeqing-head img { flex: none; width: 52px; height: 52px; border-radius: 15px; object-fit: cover; }
.zeqing-head b { font-size: 20px; font-weight: 900; }
.zeqing-desc {
  margin: 14px 0 20px;
  font-size: 13px; line-height: 1.7;
  color: var(--dim);
}
.zeqing-links { display: flex; gap: 11px; margin-bottom: 20px; }
/* 三个面板里的卡片（名片 / 社交入口 / App 下载）共用这一套盒子，间距与内边距跟
   .dl-btn 保持一致，面板级别只覆盖对齐方式与栅格，不再各调各的 gap 和 padding。 */
.brand-btn {
  flex: 1;
  display: flex; flex-direction: row; align-items: center; justify-content: center; gap: 10px;
  padding: 12px 12px;
  border-radius: 15px;
  background: var(--panel-2);
  border: 1px solid var(--line);
  text-decoration: none; color: var(--txt);
  transition: transform .16s, background .2s, border-color .2s;
}
.brand-btn:active { transform: scale(.95); }
.brand-btn:hover { background: rgb(255 255 255 / .12); border-color: var(--line); }
.brand-btn > span:last-child { font-size: 14px; font-weight: 700; }   /* 与 .f-meta b 同一档 */
/* 面板内容区的品牌与社交图标尺寸。顶部头图是另一档，见 .zeqing-head img。 */
.brand-ico {
  flex: none;
  width: 36px; height: 36px;
  border-radius: 10px;
  display: grid; place-items: center;
  color: #fff;
}
/* 各品牌图形的密度不同，svg 占容器的比例分别调过，让视觉大小看齐：小红书 .71
   （方块字最实）、Threads .65、X .53（细长字母，留白多才不显得比别的重）。
   改 .brand-ico 尺寸时这三个数要按比例一起改，否则视觉重量就散了。 */
.brand-img { object-fit: cover; } /* 抖音用真实 app 图标（自带黑底彩色音符） */
.brand-ico.xhs { background: #ff2442; }
.brand-ico.xhs svg { width: 25px; height: 25px; }
.brand-ico.threads { background: #000; }
.brand-ico.threads svg { width: 23px; height: 23px; }
.brand-ico.x { background: #000; }
.brand-ico.x svg { width: 19px; height: 19px; }

/* 玩法介绍的正文源：在服务端 HTML 里就存在（给爬虫读），页面上不显示，
   点击底部入口时由 app.js 搬进弹窗。别给它设 display，否则会盖掉 [hidden]。 */
.howto-source[hidden] { display: none; }

/* 玩法介绍的四步：序号交给 <ol>，译文里不带数字（各语言的序号写法不一样） */
.howto-steps {
  margin: 0; padding: 0 0 0 1.35em;
  display: grid; gap: 10px;
  font-size: 13px; line-height: 1.65; color: var(--dim);
}
[dir="rtl"] .howto-steps { padding: 0 1.35em 0 0; }
.howto-steps li::marker { color: var(--acc1); font-weight: 700; }

/* 可滚动面板：玩法介绍较长时允许纵向滚动，关于我们已移至外部链接 */
.about-panel { max-height: 100%; padding: 20px 22px; overflow-y: auto; -webkit-overflow-scrolling: touch; }
.about-panel .zeqing-desc { margin: 13px 0 16px; }

/* ---------- 加载 ---------- */
.screen.loading { align-items: center; gap: 26px; min-height: 100vh; min-height: 100dvh; text-align: center; }
.screen.loading > .spinner { margin-top: auto; }
.screen.loading > div:last-child { margin-bottom: auto; }
.spinner { position: relative; width: 86px; height: 86px; }
.spinner::before, .spinner::after {
  content: ""; position: absolute; inset: 0;
  border-radius: 50%;
  border: 3px solid transparent;
}
.spinner::before {
  border-top-color: var(--acc1); border-right-color: var(--acc2);
  animation: spin 1s linear infinite;
}
.spinner::after {
  inset: 12px;
  border-bottom-color: var(--acc2);
  opacity: .55;
  animation: spin 1.6s linear infinite reverse;
}
.spinner .note { position: absolute; inset: 0; display: grid; place-items: center; }
.spinner .note svg { width: 30px; height: 30px; color: var(--txt); animation: heroFloat 2.6s ease-in-out infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
.loading-artist { font-size: 22px; font-weight: 900; }
.loading-tip { color: var(--dim); font-size: 14px; min-height: 22px; transition: opacity .3s; }

/* ============================================================
   抽签结果
   ============================================================ */
.draw-head { text-align: center; margin-bottom: 24px; }
.draw-head h2 { font-size: 30px; font-weight: 900; margin: 12px 0 6px; }
.draw-head .sub { color: var(--dim); font-size: 14px; }
.stat-row {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px;
  margin-bottom: 24px;
}
/* 纯淘汰赛的名单页没有「小组」这一格，两格均分 */
.stat-row.two { grid-template-columns: repeat(2, 1fr); }

/* 名单页：赛事规模切换 + 歌名过滤（自选模式曲库可达 200 首，靠滚动找歌不现实） */
.size-pick { display: flex; justify-content: center; flex-wrap: wrap; gap: 8px; margin-bottom: 18px; }
.size-btn {
  padding: 7px 15px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--panel);
  color: var(--dim2); font: inherit; font-size: 13px; cursor: pointer;
  transition: color .18s, border-color .18s;
}
.size-btn.on { color: var(--txt); border-color: var(--acc1); }
/* 放在页面最顶、并粘住顶栏下方。位置是关键：iOS 键盘弹出时会把被遮住的输入框顶上来，
   搜索框若排在标题/统计条之后（屏幕 60% 处）必被遮住，整页就会跳一下；放在最顶端
   则一直在键盘上方，浏览器无需滚动。底色必须不透明，否则滚动时卡片会透上来。 */
.lineup-search {
  position: sticky;
  top: calc(var(--topbar-h) + env(safe-area-inset-top) + 6px);
  z-index: 6;
  display: flex; align-items: center; gap: 9px;
  height: 44px; padding: 0 10px 0 16px; margin-bottom: 20px;
  border-radius: 14px;
  background-color: var(--bg);
  background-image: linear-gradient(var(--panel-2), var(--panel-2));
  border: 1px solid var(--line);
  box-shadow: 0 10px 22px -14px #000;
  transition: border-color .25s;
}
.lineup-search:focus-within { border-color: var(--acc1-soft); }
.lineup-search > svg { width: 18px; height: 18px; color: var(--dim); flex: none; }
.lineup-search input {
  flex: 1; min-width: 0;
  background: none; border: 0; outline: 0;
  /* 必须 ≥16px：iOS Safari / 微信 webview 对更小的输入框会自动放大整页，
     放大后页面比视口宽（能横向滚动）且不会自动还原，退回首页仍是放大状态。 */
  font-size: 16px; color: inherit;
}
.lineup-search input::placeholder { color: var(--dim2); }
/* 键盘打开时收起底部按钮：iOS 的 visual viewport 缩小后，fixed 元素仍按原视口算
   bottom: 0，滚动时会飘到内容中间。搜索时那颗按钮本来也用不上。 */
body.kb-open .cta-bar { display: none; }
/* iOS 原生清除按钮在 webview 里时有时无，自己画一个 */
.lineup-search input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }
.lq-clear {
  flex: none; width: 28px; height: 28px; padding: 0;
  display: flex; align-items: center; justify-content: center;
  border: 0; border-radius: 50%;
  background: var(--panel-2); color: var(--dim);
  cursor: pointer;
}
.lq-clear[hidden] { display: none; }
.lq-clear svg { width: 14px; height: 14px; }
.lq-clear:active { background: var(--line); color: var(--txt); }
.lineup-note { margin: -6px 0 14px; text-align: center; font-size: 12.5px; color: var(--dim2); }
.lineup-note.busy::after {
  content: ""; display: inline-block; vertical-align: -1px; margin-left: 6px;
  width: 10px; height: 10px; border-radius: 50%;
  border: 1.5px solid var(--line); border-top-color: var(--acc1);
  animation: spin .7s linear infinite;
}
.stat {
  padding: 16px 8px 13px;
  text-align: center;
  border-radius: var(--r-md);
  background: var(--panel);
  border: 1px solid var(--line-soft);
}
.stat b {
  display: block;
  font-family: var(--font-display);
  font-size: 32px; font-weight: 400; line-height: 1.1;
  letter-spacing: .02em;
}
.stat span { font-size: 12px; color: var(--dim); }
.group-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.gcard {
  min-width: 0;
  border-radius: var(--r-md);
  background: var(--panel);
  border: 1px solid var(--line-soft);
  padding: 13px 13px 11px;
  animation: screenIn .5s cubic-bezier(.2, .8, .2, 1) both;
}
.gcard-head {
  display: flex; align-items: baseline; gap: 7px;
  margin-bottom: 10px;
}
.gcard-head b {
  font-family: var(--font-display);
  font-size: 22px; font-weight: 400; font-style: italic;
}
.gcard-head span { font-size: 11px; color: var(--dim2); letter-spacing: .1em; }
.gsong { display: flex; align-items: center; gap: 9px; padding: 4.5px 0; min-width: 0; }
.gsong img, .gsong .noart {
  flex: none;
  width: 30px; height: 30px;
  border-radius: 8px;
  object-fit: cover;
  background: var(--panel-2);
}
.gsong .noart { display: grid; place-items: center; color: var(--dim2); }
.gsong .noart svg { width: 14px; height: 14px; }
.gsong span {
  flex: 1; min-width: 0;
  font-size: 12.5px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* ============================================================
   阶段公共头部
   ============================================================ */
.phase-head { text-align: center; margin-bottom: 22px; }
.phase-head h2 {
  font-size: 34px; font-weight: 900;
  margin: 13px 0 5px;
  letter-spacing: .01em;
}
.phase-head h2 .en {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 1.12em;
  /* 合成斜体会让字形溢出行内盒、被 background-clip:text 截断，改用 transform 斜切 */
  display: inline-block;
  transform: skewX(-8deg);
  padding: 0 .06em;
}
.phase-head .sub { color: var(--dim); font-size: 14px; }
.phase-head .count {
  font-family: var(--font-en);
  color: var(--dim);
  font-size: 13px; letter-spacing: .1em;
  margin-top: 5px;
}

/* ============================================================
   小组赛：2×2 选歌卡
   ============================================================ */
.pick-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 13px; }
.scard {
  position: relative;
  min-width: 0;
  border-radius: var(--r-md);
  background: var(--panel);
  border: 1.5px solid var(--line-soft);
  overflow: hidden;
  cursor: pointer;
  transition: transform .18s cubic-bezier(.2, .8, .2, 1), border-color .2s, box-shadow .25s, background .2s;
  animation: screenIn .45s cubic-bezier(.2, .8, .2, 1) both;
}
.scard:active { transform: scale(.96); }
.scard .art { position: relative; background: var(--panel-2); }
/* 用 padding 撑正方形，不依赖 aspect-ratio：老 webview 会拿图片本身像素高度撑高卡片 */
.scard .art::before { content: ""; display: block; padding-top: 100%; }
.scard .art img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.scard .art .noart { position: absolute; inset: 0; display: grid; place-items: center; color: var(--dim2); }
.scard .art .noart svg { width: 34px; height: 34px; }
.scard .meta { padding: 10px 12px 12px; }
.scard .tname {
  font-size: 14.5px; font-weight: 700; line-height: 1.3;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
  min-height: 2.6em;
}
.scard .talbum {
  margin-top: 3px;
  font-size: 11.5px; color: var(--dim2);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.play-btn {
  position: absolute; right: 8px; bottom: 8px; z-index: 3;
  width: 38px; height: 38px;
  display: grid; place-items: center;
  border-radius: 50%;
  color: #fff;
  background: rgb(12 12 18 / .55);
  border: 1px solid rgb(255 255 255 / .22);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  transition: transform .16s, background .2s;
}
.play-btn svg { width: 17px; height: 17px; }
.play-btn:active { transform: scale(.88); }
.play-btn.playing { background: var(--grad); border-color: transparent; }
/* 纯 CSS 圆环加载器（iOS 对 svg 元素做旋转动画会出现拉伸残影） */
.ldr {
  display: block;
  width: 15px; height: 15px;
  border-radius: 50%;
  border: 2.5px solid rgb(255 255 255 / .28);
  border-top-color: #fff;
  animation: spin .8s linear infinite;
}
.check {
  position: absolute; top: 9px; right: 9px; z-index: 3;
  width: 28px; height: 28px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--grad);
  color: #fff;
  font-size: 15px; font-weight: 900;
  opacity: 0; transform: scale(.4);
  transition: opacity .18s, transform .22s cubic-bezier(.34, 1.56, .64, 1);
  box-shadow: 0 4px 14px -4px var(--acc1-soft);
}
.scard.picked { border-color: transparent; box-shadow: 0 0 0 2px var(--acc1), 0 14px 38px -14px var(--acc1-soft); }
.scard.picked .check { opacity: 1; transform: scale(1); }
.scard.picked .art img { filter: saturate(1.12); }

/* ============================================================
   遗珠复活赛：3 列小卡
   ============================================================ */
/* 名单页排序切换：纯文字开关（按热度 | 按专辑），不做成胶囊标签——
   页面顶部已经有一排「32/16/8/4 强」的胶囊，再来一排会分不清哪个是赛制哪个是排序 */
.lineup-sort { display: flex; align-items: center; margin: -8px 0 14px; padding-left: 2px; }
.sort-switch { display: flex; align-items: center; gap: 9px; }
.sort-link {
  padding: 7px 2px;   /* 纯文字本身热区太小，靠上下留白把可点高度撑到 34px */
  border: 0; background: none;
  color: var(--dim2); font: inherit; font-size: 13px; cursor: pointer;
  transition: color .18s;
}
.sort-link.on { color: var(--txt); font-weight: 700; }
.sort-sep { color: var(--line); font-size: 12px; user-select: none; }
/* 抽签方式勾选，贴这行最右（RTL 下自动翻到最左） */
.sort-rand {
  margin-inline-start: auto;
  display: flex; align-items: center; gap: 6px;
  padding: 7px 2px;
  border: 0; background: none;
  color: var(--dim2); font: inherit; font-size: 13px; cursor: pointer;
  transition: color .18s;
}
.sort-rand .rbox {
  width: 15px; height: 15px;
  display: grid; place-items: center;
  border: 1.5px solid var(--line); border-radius: 5px;
  font-size: 10px; line-height: 1; color: transparent;
  transition: background .18s, border-color .18s, color .18s;
}
.sort-rand.on { color: var(--txt); }
.sort-rand.on .rbox { background: var(--grad); border-color: transparent; color: #fff; }

.wild-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
/* 专辑分组标题：占满整行网格 */
.wgroup {
  grid-column: 1 / -1;
  display: flex; align-items: baseline; gap: 8px;
  margin: 10px 2px 0;
  padding-bottom: 7px;
  border-bottom: 1px solid var(--line-soft);
}
.wgroup:first-child { margin-top: 0; }
.wgroup[hidden] { display: none; }
.wg-name {
  flex: 1; min-width: 0;
  font-size: 13px; font-weight: 700; line-height: 1.35;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.wg-year { flex: none; font-size: 11.5px; color: var(--dim2); letter-spacing: .04em; }
.wg-count {
  flex: none;
  min-width: 18px; padding: 1px 6px;
  border-radius: 999px;
  background: var(--panel);
  font-size: 10.5px; color: var(--dim2); text-align: center;
}
.wcard {
  position: relative;
  min-width: 0;
  border-radius: 14px;
  background: var(--panel);
  border: 1.5px solid var(--line-soft);
  overflow: hidden;
  cursor: pointer;
  transition: transform .16s, border-color .2s, box-shadow .2s;
  animation: screenIn .4s cubic-bezier(.2, .8, .2, 1) both;
}
.wcard:active { transform: scale(.94); }
/* 受邀场的名单不可改（见 app.js lineupCard），按压反馈也要一并撤掉，别暗示能点 */
.wcard.locked:active { transform: none; }
.wcard .art { position: relative; background: var(--panel-2); }
.wcard .art::before { content: ""; display: block; padding-top: 100%; }
.wcard .art img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.wcard .art .noart { position: absolute; inset: 0; display: grid; place-items: center; color: var(--dim2); }
.wcard .art .noart svg { width: 22px; height: 22px; }
.wcard .wname {
  padding: 7px 8px 9px;
  font-size: 11.5px; font-weight: 500; line-height: 1.3;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
  min-height: 2.9em;
}
.gbadge {
  position: absolute; top: 6px; left: 6px; z-index: 2;
  min-width: 20px; height: 20px;
  padding: 0 5px;
  display: grid; place-items: center;
  border-radius: 7px;
  font-family: var(--font-en);
  font-size: 11px; font-weight: 700; font-style: italic;
  color: rgb(255 255 255 / .88);
  background: rgb(12 12 18 / .58);
  border: 1px solid rgb(255 255 255 / .16);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
.wcard .check { width: 24px; height: 24px; font-size: 13px; top: 6px; right: 6px; }
.wcard .play-btn { width: 32px; height: 32px; right: 6px; bottom: 6px; }
.wcard .play-btn svg { width: 14px; height: 14px; }
.wcard.picked { border-color: transparent; box-shadow: 0 0 0 2px var(--acc1), 0 12px 30px -12px var(--acc1-soft); }
.wcard.picked .check { opacity: 1; transform: scale(1); }
.wild-counter {
  font-family: var(--font-en);
  font-weight: 700; font-size: 15px;
  transition: transform .2s;
}
.wild-counter.bump { animation: bump .3s; }
@keyframes bump { 40% { transform: scale(1.25); } }

/* ============================================================
   淘汰赛：对决
   ============================================================ */
.duel-wrap { flex: 1; display: flex; flex-direction: column; justify-content: center; }
.duel {
  position: relative;
  display: grid; grid-template-columns: 1fr 1fr; gap: 14px;
  align-items: stretch;
}
.dcard {
  position: relative;
  min-width: 0;
  border-radius: var(--r-lg);
  background: var(--panel);
  border: 1.5px solid var(--line-soft);
  overflow: hidden;
  cursor: pointer;
  transition: transform .22s cubic-bezier(.2, .8, .2, 1), border-color .2s, box-shadow .3s, opacity .3s, filter .3s;
  animation: duelIn .5s cubic-bezier(.2, .8, .2, 1) both;
}
.dcard:nth-child(3) { animation-delay: .08s; }
@keyframes duelIn { from { opacity: 0; transform: translateY(22px) scale(.96); } }
.dcard:active { transform: scale(.965); }
.dcard .art { position: relative; background: var(--panel-2); }
.dcard .art::before { content: ""; display: block; padding-top: 100%; }
.dcard .art img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.dcard .art .noart { position: absolute; inset: 0; display: grid; place-items: center; color: var(--dim2); }
.dcard .art .noart svg { width: 44px; height: 44px; }
.dcard .meta { padding: 12px 13px 15px; }
.dcard .tname {
  font-size: 15.5px; font-weight: 900; line-height: 1.3;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
  min-height: 2.6em;
}
.dcard .talbum {
  margin-top: 4px;
  font-size: 11.5px; color: var(--dim2);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.dcard.winner {
  border-color: transparent;
  box-shadow: 0 0 0 2.5px var(--acc1), 0 22px 60px -18px var(--acc1-soft);
  transform: scale(1.035);
  z-index: 2;
}
.dcard.loser { opacity: .32; filter: saturate(.15) brightness(.75); transform: scale(.94); }
.vs-badge {
  position: absolute; left: 50%; top: 50%; z-index: 5;
  transform: translate(-50%, -50%);
  width: 54px; height: 54px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: rgb(14 14 21 / .88);
  border: 1px solid var(--line);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  box-shadow: 0 10px 34px -8px rgb(0 0 0 / .7), 0 0 0 5px rgb(255 255 255 / .03);
  pointer-events: none;
}
.vs-badge b {
  font-family: var(--font-display);
  font-weight: 400; font-size: 18px;
  letter-spacing: .03em;
  display: inline-block;
  transform: skewX(-8deg);
  padding: 0 .06em;
  background: var(--grad);
  -webkit-background-clip: text; background-clip: text;
  color: transparent;
}
.duel-hint { text-align: center; color: var(--dim2); font-size: 12.5px; margin-top: 22px; letter-spacing: .06em; }

/* ---------- 站点字标 mobanduoduo.com ----------
   页面被截图/录屏分享出去时认得出来源。画法与分享图 share.js drawWordmark2 一致 */
.wordmark {
  direction: ltr;   /* 品牌字标恒为 LTR：阿语 RTL 下不镜像成 PPA.PUCCISUM */
  text-align: center;
  font-family: var(--font-display);
  font-weight: 400;
  line-height: 1;
  letter-spacing: .04em;
  user-select: none; -webkit-user-select: none;
}
/* 合成斜体会让字形溢出行内盒、被 background-clip:text 截断，与分享图一样改用斜切 */
.wordmark b, .wordmark i {
  display: inline-block;
  font-weight: 400; font-style: normal;
  transform: skewX(-8deg);
}
.wordmark b {
  /* 横向渐变而不是全站 --grad 的 135deg：字标很扁，斜切渐变在这里只会让色带走位，
     且分享图 canvas 侧同样是横跨文字的水平渐变，两边要对得上 */
  background: linear-gradient(90deg, var(--acc1), var(--acc2));
  -webkit-background-clip: text; background-clip: text;
  color: transparent;
}
.wordmark i { color: var(--txt); }

/* 对战页底部：绝对定位在 .screen 已有的 40px 下内边距里——对战页要求一屏放得下，
   字标不能占据布局高度，否则矮机型（iPhone SE 那档）会被顶出滚动条 */
.duel-screen { position: relative; }   /* transform 会让内部 fixed 元素改基准，这里只用 relative */
.duel-brand {
  position: absolute;
  left: 0; right: 0;
  bottom: calc(11px + env(safe-area-inset-bottom));
  font-size: 15px;
  opacity: .85;
  pointer-events: none;   /* 不抢卡片的点击 */
}

/* 轮次过场 */
.round-intro {
  position: fixed; inset: 0; z-index: 70;
  display: grid; place-items: center;
  background: rgb(6 6 10 / .82);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  animation: fadeIn .25s both;
}
.round-intro.out { animation: fadeOut .3s both; }
@keyframes fadeIn { from { opacity: 0; } }
@keyframes fadeOut { to { opacity: 0; } }
.ri-box { text-align: center; animation: riPop .55s cubic-bezier(.2, .9, .3, 1.2) both; }
@keyframes riPop { from { opacity: 0; transform: scale(.7) translateY(16px); } }
.ri-box .pill { margin-bottom: 18px; }
.ri-title {
  font-size: clamp(44px, 13vw, 66px);
  font-weight: 900; line-height: 1.05;
  letter-spacing: .02em;
}
.ri-sub { margin-top: 12px; color: var(--dim); font-size: 15px; }

/* ============================================================
   冠军页
   ============================================================ */
.champ { align-items: center; text-align: center; }
/* 冠军页顶部用站点字标而不是皇冠：这一页是最常被截图外发的一屏 */
.champ-brand { font-size: 25px; margin-bottom: 12px; filter: drop-shadow(0 10px 30px var(--acc1-soft)); }
.champ-label { letter-spacing: .3em; font-size: 13px; color: var(--dim); margin-bottom: 18px; }
.champ-art-wrap { position: relative; width: min(64vw, 300px); margin-bottom: 22px; }
.champ-art-wrap::before {
  content: ""; position: absolute; inset: -14%;
  background: var(--grad);
  filter: blur(48px); opacity: .4;
  border-radius: 40px;
  z-index: -1;
  animation: glowPulse 3.6s ease-in-out infinite;
}
/* 只做透明度呼吸，不缩放——缩放 blur 元素会强制每帧重算模糊，拖垮帧率 */
@keyframes glowPulse { 50% { opacity: .62; } }
/* 礼花期间临时关掉封面光晕，减轻整页合成负担 */
.champ-art-wrap.mc-celebrating::before { display: none; }
.champ-art-wrap img, .champ-art-wrap .noart {
  width: 100%; aspect-ratio: 1;
  border-radius: 30px;
  object-fit: cover;
  border: 1px solid rgb(255 255 255 / .18);
  box-shadow: 0 30px 80px -20px rgb(0 0 0 / .8);
  animation: champIn .7s cubic-bezier(.2, .9, .3, 1.1) both;
}
.champ-art-wrap .noart { display: grid; place-items: center; color: var(--dim2); background: var(--panel-2); }
.champ-art-wrap .noart svg { width: 70px; height: 70px; }
/* 冠军封面右下角试听键：等封面入场动画走完再淡入 */
.champ-art-wrap .play-btn {
  right: 12px; bottom: 12px;
  width: 46px; height: 46px;
  animation: fadeIn .5s .45s both;
}
.champ-art-wrap .play-btn svg { width: 19px; height: 19px; }
/* 礼花期间同样卸掉按钮的毛玻璃（又一层每帧重算的 blur） */
.champ-art-wrap.mc-celebrating .play-btn {
  backdrop-filter: none; -webkit-backdrop-filter: none;
  background: rgb(12 12 18 / .72);
}
@keyframes champIn { from { opacity: 0; transform: scale(.82) rotate(-3deg); } }
.champ-title {
  font-size: clamp(28px, 8vw, 38px); font-weight: 900; line-height: 1.2;
  /* 双语连写名可能很长：两行截断加省略号 */
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; max-width: 92%;
}
.champ-album { color: var(--dim); font-size: 14px; margin: 8px 0 26px; }
.podium {
  width: 100%;
  display: grid; grid-template-columns: 1fr 1fr; gap: 11px;
  margin-bottom: 28px;
}
.pod {
  display: flex; align-items: center; gap: 11px;
  padding: 11px;
  border-radius: var(--r-md);
  background: var(--panel);
  border: 1px solid var(--line-soft);
  text-align: left;
  min-width: 0;
}
.pod.silver { grid-column: 1 / -1; background: linear-gradient(120deg, rgb(255 255 255 / .09), var(--panel) 60%); border-color: var(--line); }
.pod-art {
  position: relative; flex: none;
  display: block; padding: 0;
  width: 46px; height: 46px;
  border-radius: 11px; overflow: hidden;
  background: var(--panel-2);
  transition: transform .16s;
}
button.pod-art:active { transform: scale(.92); }
.pod img, .pod .noart { width: 100%; height: 100%; object-fit: cover; }
.pod .noart { display: grid; place-items: center; color: var(--dim2); }
.pod .noart svg { width: 20px; height: 20px; }
/* 小图整块即播：常驻半透明遮罩 + 播放图标，明示可点 */
.play-ico {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  color: #fff;
  background: rgb(8 8 14 / .36);
  transition: background .2s;
}
/* 亮色封面上光靠白图标会糊掉，补一层投影 */
.play-ico svg { width: 16px; height: 16px; filter: drop-shadow(0 1px 3px rgb(0 0 0 / .55)); }
.play-ico .ldr { width: 13px; height: 13px; border-width: 2px; }
.play-ico.playing { background: rgb(8 8 14 / .26); }
.pod-meta { min-width: 0; }
.pod-rank { font-size: 10.5px; letter-spacing: .14em; color: var(--dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pod-name { font-size: 13.5px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.champ-actions { width: 100%; display: flex; flex-direction: column; gap: 11px; }
/* 「再来一场」与「和好友一起玩」并排同款（同色同高同字号），但**不对半分宽**：
   后者在 14 种语言里都更长（"Mit Freunden spielen" / "Играть с друзьями"…），
   对半分时实测 7 种语言要折成两行；按 .8 : 1.2 分配后 375px 屏上全部单行。
   span 仍留两行的 line-clamp 兜底，将来新增语言最坏也只是折行，不会溢出或撑高按钮。 */
.champ-more { display: flex; gap: 11px; }
.champ-more .btn { min-width: 0; padding: 0 8px; font-size: 14px; gap: 5px; }
.champ-more .btn:first-child { flex: .8; }
.champ-more .btn:last-child { flex: 1.2; }
.champ-more .btn svg { flex: none; width: 16px; height: 16px; }
.champ-more .btn span {
  min-width: 0; text-align: center; line-height: 1.2;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
/* 320~359px 的老机型（iPhone SE 一代等）横排怎么调都塞不下法/德/俄，直接竖排 */
@media (max-width: 359px) {
  .champ-more { flex-direction: column; }
  .champ-more .btn:first-child, .champ-more .btn:last-child { flex: none; }
}

/* ============================================================
   分享图弹窗
   ============================================================ */
.modal {
  position: fixed; inset: 0; z-index: 80;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  /* 顶部为关闭按钮预留独立区域，避免与图片重叠 */
  padding: calc(68px + env(safe-area-inset-top)) 20px 20px;
  background: rgb(5 5 9 / .88);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  animation: fadeIn .25s both;
}
/* 分享弹窗：关闭按钮改为悬浮在分享图上（它自带底色 + 描边，压在图上依然看得清），
   顶部因此不再为它整块留白，省下的高度全给对阵图——带小红书气泡时可用高度更紧张，
   上方那块空白格外显眼。其余弹窗（关于我们、玩法、确认框）仍走上面的 68px 留白。 */
.modal.share-modal { padding-top: calc(30px + env(safe-area-inset-top)); padding-bottom: 0; }
/* 按钮行贴底的口径对齐小组赛的底部操作条 .cta-bar（16px + 安全区）：弹窗自己那 20px
   下内边距叠上按钮行的 10px 后比小组赛多出 14px，看着浮在半空 */
.share-modal .share-actions { padding-bottom: calc(16px + env(safe-area-inset-bottom)); }
/* 弹窗打开时锁住背后正文的滚动：.modal 只是 fixed 覆盖层，页面本身照旧能滚，
   iOS 上滚动条会从遮罩后面透出来（还能隔着模糊层看到正文在动）。
   不支持 :has 的老内核退回现状，锁不住而已，不影响功能。 */
html:has(#overlays .modal), html:has(#overlays .modal) body { overflow: hidden; }
.modal-close {
  position: absolute; top: calc(14px + env(safe-area-inset-top)); right: 14px;
  z-index: 10;
  width: 42px; height: 42px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--panel-2);
  border: 1px solid var(--line);
  color: var(--txt);
}
.modal-close svg { width: 19px; height: 19px; }
[dir="rtl"] .modal-close { right: auto; left: 14px; }
[dir="rtl"] .zeqing-panel .modal-close { left: 10px; }
[dir="rtl"] .zeqing-head { padding-right: 0; padding-left: 40px; }
.share-stage {
  width: 100%; max-width: 400px;
  flex: 1; min-height: 0;
  display: flex; align-items: center; justify-content: center;
}
.share-stage img {
  max-width: 100%; max-height: 100%;
  border-radius: 18px;
  border: 1px solid var(--line);
  box-shadow: 0 30px 90px -20px rgb(0 0 0 / .9);
  animation: champIn .5s cubic-bezier(.2, .9, .3, 1.05) both;
}
.share-loading { text-align: center; color: var(--dim); font-size: 14px; display: grid; gap: 18px; justify-items: center; }
.share-actions {
  position: relative;   /* 小红书引导气泡（.xhs-tip）的定位上下文 */
  flex: none;
  width: 100%; max-width: 400px;
  display: flex; gap: 11px;
  padding: 18px 0 calc(10px + env(safe-area-inset-bottom));
}
/* 两个按钮严格等高：显式锁 44（= 分享按钮 sm 高度），避免 ghost 的 1px border + min-height
   在微信/iOS webview 里被当作 content-box 而多出 2px 高，与分享按钮不齐 */
.share-actions .btn { flex: 1; height: 44px; box-sizing: border-box; }
.share-actions .btn.ghost { flex: 0 0 auto; padding: 0 22px; }
/* 小红书分享入口（仅简体+移动端，见 app.js openShare）：
   红色小红书圆钮 + 安卓的圆形下载钮，与 44px 的分享长条等高 */
.btn-circle {
  flex: none;
  width: 44px; height: 44px;
  border-radius: 50%;
  display: grid; place-items: center;
  color: #fff;
  transition: transform .16s;
}
.btn-circle:active { transform: scale(.92); }
.btn-circle.xhs { background: #ff2442; }   /* 小红书品牌红，与 .brand-ico.xhs 同色 */
.btn-circle.xhs svg { width: 30px; height: 30px; }   /* 字标横排三字，画得比通用图标大才够清楚 */
.btn-circle.dim { background: var(--panel); border: 1px solid var(--line); color: var(--txt); }
.btn-circle.dim svg { width: 20px; height: 20px; }
/* 微信/国产内核的简体分支：长按提示紧贴图片下方，下一行小红书圆钮 + 内联气泡
   （气泡在这里改为流内布局并常驻，复制后不关闭，见 app.js copyXhsTopic） */
.wx-hint.mid { padding: 14px 0 0; color: var(--txt); }   /* 与下方气泡文字同为白色 */
.share-actions.inline-tip { align-items: center; }
.share-actions.inline-tip .xhs-tip { position: static; flex: 1; }
/* 简体标准分支（iOS Safari / Chrome 等）：气泡改流内排布、独占按钮行上方一行，
   按钮行因此变高，flex 的分享图（.share-stage 让出高度）自动缩小上移，不再被气泡压住下缘。
   上方留白比 row-gap 大，让气泡靠按钮行、离分享图远一点；气泡移除时 JS 会摘掉 has-tip，
   布局回到无气泡时的原样。只在带气泡时开 wrap——其余语言的保存/分享长按钮不受影响。 */
.share-actions.has-tip { flex-wrap: wrap; row-gap: 16px; padding-top: 18px; }
.share-actions.has-tip .xhs-tip { position: static; order: -1; flex: 0 0 100%; }
/* 引导气泡：微信分支内联在按钮行内，标准分支独占上方一行；常驻，点击整条复制话题，
   复制成功切「已复制」动画后由 JS 移除 */
.xhs-tip {
  position: absolute;
  bottom: calc(100% + 4px);
  left: 0; right: 0;   /* 撑满按钮行宽度 */
  box-sizing: border-box;
  display: flex; align-items: center; gap: 10px;
  padding: 10px 14px;
  border-radius: 14px;
  background: rgb(16 16 24 / .92);
  border: 1px solid var(--line);
  color: var(--txt);
  font-size: 13px; line-height: 1.6; text-align: left;
  opacity: 0; transform: translateY(6px);
  transition: opacity .35s, transform .35s;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  z-index: 5;
}
.xhs-tip.show { opacity: 1; transform: none; }
.xhs-tip:active { transform: scale(.98); }
.xhs-tip svg { flex: none; width: 17px; height: 17px; opacity: .75; }
.xhs-tip.copied { justify-content: center; cursor: default; }
.xhs-tip .xhs-copied {
  display: inline-flex; align-items: center; gap: 6px;
  font-weight: 700;
  animation: xhsPop .32s cubic-bezier(.2, .9, .3, 1.45) both;
}
@keyframes xhsPop {
  from { transform: scale(.6); opacity: 0; }
  to { transform: none; opacity: 1; }
}
.wx-hint {
  flex: none;
  color: var(--dim);
  font-size: 13.5px;
  padding: 18px 0 calc(14px + env(safe-area-inset-bottom));
}
.share-actions:has(+ .save-hint) { padding-bottom: 8px; }
.save-hint {
  flex: none;
  color: var(--dim2);
  font-size: 12.5px;
  padding-bottom: calc(14px + env(safe-area-inset-bottom));
}

/* ---------- 确认弹窗 ---------- */
.confirm-box {
  width: min(88vw, 340px);
  padding: 26px 22px 20px;
  border-radius: var(--r-lg);
  background: rgb(19 19 28 / .96);
  border: 1px solid var(--line);
  text-align: center;
  animation: riPop .35s cubic-bezier(.2, .9, .3, 1.15) both;
}
.confirm-box h4 { font-size: 18px; font-weight: 900; margin-bottom: 8px; }
/* 新功能告知：蒙层比其它弹窗淡得多——公告不该把首页整个盖住，让人看得见背后的站 */
#newsModal {
  background: rgb(5 5 9 / .5);
  backdrop-filter: blur(5px);
  -webkit-backdrop-filter: blur(5px);
}
.news-box { width: min(88vw, 360px); }
.news-item {
  display: flex; align-items: flex-start; gap: 11px;
  padding: 14px;
  margin-bottom: 14px;
  border-radius: 12px;
  background: var(--panel);
  border: 1px solid var(--line-soft);
  text-align: left;
}
.news-ico { flex: none; font-size: 19px; line-height: 1.35; }
/* 必须比 .confirm-box p 更具体：那条在本段之后定义、同优先级，会把 margin 覆盖回 22px，
   于是每块下方凭空多出一行空白 */
.news-box .news-item p { margin: 0; font-size: 13.5px; line-height: 1.65; color: var(--dim); }
.news-box .row { margin-top: 20px; }
.confirm-box p { color: var(--dim); font-size: 14px; margin-bottom: 22px; }
.confirm-box .row { display: flex; gap: 10px; }
/* 左右内边距比通用 .btn 小得多：并排两颗按钮宽度由 flex 决定，28px 的留白只会挤掉文字空间，
   长译文（俄/法/德等）因此被折成两行 */
.confirm-box .btn { flex: 1; min-height: 48px; font-size: 15px; padding: 0 12px; }

/* ---------- 和好友一起玩：漂浮按钮 / 邀请弹窗 / 受邀横幅 ---------- */
/* 只用在抽签、名单页：悬在 cta-bar 上方靠右（冠军页改成 .champ-more 里的实体按钮）。
   右缘与小组卡片严格对齐 = 50% + 列宽/2 − .screen 的 20px 内边距，列宽跟着
   .screen 的 max-width 分三档（520 / ≥760 是 640 / ≥1100 是 720）；
   移动端列宽=视口，右缘就是那 20px 内边距。 */
.fab-invite {
  position: fixed; right: max(20px, calc(50% - 240px)); bottom: calc(84px + env(safe-area-inset-bottom)); z-index: 31;
  display: inline-flex; align-items: center; gap: 7px;
  padding: 10px 15px;
  border-radius: 999px;
  background: rgb(16 16 24 / .88);
  border: 1px solid var(--line);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  font-size: 13px; font-weight: 700;
  color: var(--txt);
  box-shadow: var(--shadow-card);
  transition: transform .15s;
  animation: fabIn .4s cubic-bezier(.2, .9, .3, 1.15) .25s both;
}
.fab-invite svg { width: 17px; height: 17px; }
.fab-invite:active { transform: scale(.94); }
/* 名单没选满时置灰不可点：还没有可分享的开局 */
.fab-invite:disabled { opacity: .4; pointer-events: none; }
[dir="rtl"] .fab-invite { right: auto; left: max(20px, calc(50% - 240px)); }
@media (min-width: 760px) {
  .fab-invite { right: calc(50% - 300px); }                       /* .screen 640 → 640/2 − 20 */
  [dir="rtl"] .fab-invite { right: auto; left: calc(50% - 300px); }
  .lang-switch { left: calc(50% - 260px); }                       /* .home  560 → 560/2 − 20 */
  [dir="rtl"] .lang-switch { left: auto; right: calc(50% - 260px); }
  /* .rank-fab 的同款分档写在它自己那节（本段之后定义，写这里会被基础规则覆盖） */
}
@media (min-width: 1100px) {
  /* 这一档 .home 的 max-width 也被 .screen 的 720px 覆盖，两者列宽相同 */
  .fab-invite { right: calc(50% - 340px); }
  [dir="rtl"] .fab-invite { right: auto; left: calc(50% - 340px); }
  .lang-switch { left: calc(50% - 340px); }
  [dir="rtl"] .lang-switch { left: auto; right: calc(50% - 340px); }
}
body.kb-open .fab-invite { display: none; }   /* 名单页键盘弹起时随 cta-bar 一起让位 */
@keyframes fabIn { from { opacity: 0; transform: translateY(10px) scale(.9); } }

/* 邀请弹窗复用 news-box 的卡片排版与 .news-ico emoji（设计稿里的灰色圆点辨识度太低） */
.invite-box { position: relative; }
.invite-box .modal-close { position: absolute; top: 12px; right: 12px; width: 36px; height: 36px; }
[dir="rtl"] .invite-box .modal-close { right: auto; left: 12px; }
.invite-box h4 { margin: 6px 0 16px; padding: 0 30px; }
.invite-fb-hint { color: var(--dim); font-size: 12.5px; margin-bottom: 8px; }
.invite-fallback {
  width: 100%;
  margin-bottom: 4px;
  padding: 10px 12px;
  border-radius: 12px;
  background: var(--panel);
  border: 1px solid var(--line);
  color: var(--dim);
  /* 必须 ≥16px：复制失败后这个框会被 focus，iOS 对更小的可聚焦控件自动放大整页
     且不还原，放大后全站 fixed 元素（顶栏 / cta-bar / fab）拖动时都会飘（同
     .lineup-search input 的教训） */
  font-size: 16px; line-height: 1.5;
  resize: none;
  -webkit-user-select: text; user-select: text;
}

/* 受邀落地页顶栏：仍是常规 flex 三段式（左返回 / 中横幅 / 右重开），只换背景与中间文案，
   品牌字走展示字体渐变。别改回 display:block——好友在落地第一屏也需要退出入口。 */
.topbar.tb-invite {
  /* 与页面底部主按钮同一条渐变，两端呼应；不透明底色下不需要毛玻璃与分隔线 */
  background: var(--grad);
  backdrop-filter: none; -webkit-backdrop-filter: none;
  border-bottom-color: transparent;
}
/* 渐变底上 var(--dim) 系的灰会发浑，图标与副标题改用带透明度的白 */
.topbar.tb-invite .tb-btn { color: rgb(255 255 255 / .82); }
.topbar.tb-invite .tb-btn:active { background: rgb(255 255 255 / .16); color: #fff; }
/* 375px 屏减去左右各 42px 的按钮只剩约 270px：德语等长译文必须省略，不许把顶栏撑高 */
.ib-title, .ib-sub { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ib-title { display: block; font-size: 12.5px; font-weight: 800; letter-spacing: .01em; color: #fff; }
.ib-brand {
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 400;
  letter-spacing: .05em;
  padding-inline: 2px;
  color: #fff;
}
.ib-sub { display: block; margin-top: 1px; font-size: 11px; color: rgb(255 255 255 / .78); }

/* ---------- Toast ---------- */
.toast {
  position: fixed; left: 50%; bottom: calc(96px + env(safe-area-inset-bottom)); z-index: 99;
  transform: translate(-50%, 16px);
  max-width: 82vw;
  padding: 11px 20px;
  border-radius: 999px;
  background: rgb(24 24 34 / .95);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-card);
  font-size: 14px; font-weight: 500;
  opacity: 0;
  transition: opacity .3s, transform .35s cubic-bezier(.2, .8, .2, 1);
  pointer-events: none;
  text-align: center;
}
.toast.show { opacity: 1; transform: translate(-50%, 0); }

/* ============================================================
   桌面端适配
   ============================================================ */
@media (min-width: 760px) {
  .screen { max-width: 640px; }
  .home, .loading { max-width: 560px; }
  .pick-grid { grid-template-columns: repeat(4, 1fr); gap: 14px; }
  .scard .tname { font-size: 13.5px; }
  .wild-grid { grid-template-columns: repeat(4, 1fr); }
  .group-grid { grid-template-columns: repeat(3, 1fr); }
  .duel { gap: 26px; }
  .duel-wrap { max-width: 620px; margin: 0 auto; width: 100%; }
  .vs-badge { width: 62px; height: 62px; }
  .vs-badge b { font-size: 19px; }
  .dcard .tname { font-size: 17px; }
  .champ-actions { flex-direction: row; }
  .champ-actions > .btn { flex: 1; }
  /* 三段并排时 champ-more 里挤了两颗按钮，等分会比手机上还窄（760px 档实测 294px，
     法/德/俄又要折行），多给一点 */
  .champ-actions > .champ-more { flex: 1.4; }
  .podium { grid-template-columns: 1.2fr 1fr 1fr; }
  .pod.silver { grid-column: auto; }
  .cta-bar .btn { max-width: 400px; }
  .scard:hover { border-color: var(--line); transform: translateY(-3px); }
  .dcard:hover:not(.winner):not(.loser) { transform: translateY(-4px); border-color: var(--line); }
  .wcard:hover:not(.locked) { border-color: var(--line); transform: translateY(-2px); }
}

@media (min-width: 1100px) {
  .screen { max-width: 720px; }
  .pick-grid { gap: 16px; }
}

/* ============================================================
   排行榜页（rank.html）+ 首页入口
   ============================================================ */
/* 首页排行榜入口（用户定）：位置在右上角，样式是歌手 chip 同款金边胶囊——
   padding / 圆角 / 字号字重与 .chip 一致，金色描边 + 微金底 + 纯白字突出入口。 */
/* 与首页搜索框右缘严格对齐（胶囊描边对齐搜索框描边）：内容列右缘 = 50% + 列宽/2
   − .screen 的 20px 内边距，取值与左上角 .lang-switch 逐档镜像（.home 基础 520 /
   ≥760 是 560 / ≥1100 被 .screen 的 720 覆盖）；移动端列宽=视口，右缘就是那 20px。 */
.rank-fab {
  position: fixed;
  top: calc(env(safe-area-inset-top) + 14px);
  right: max(20px, calc(50% - 240px));
  z-index: 50;
  display: inline-flex; align-items: center; gap: 5px;
  padding: 7px 14px;
  border-radius: 999px;
  font-size: 12px; font-weight: 500; letter-spacing: .04em;   /* 字重与语言切换、首页歌手 chip 一致 */
  color: var(--txt);   /* 比左侧语言切换更亮：纯白字，突出入口 */
  background: rgba(255, 214, 116, .07);
  border: 1px solid rgba(255, 214, 116, .4);
  text-decoration: none;
  transition: transform .15s, color .2s;
  user-select: none; -webkit-user-select: none;
}
.rank-fab:active { transform: scale(.92); }
[dir="rtl"] .rank-fab { right: auto; left: max(20px, calc(50% - 240px)); }
/* 分档必须写在基础规则之后：上面「桌面端适配」那两段媒体查询在本节之前，
   同优先级下会被 .rank-fab 的基础 right 覆盖回去 */
@media (min-width: 760px) {
  .rank-fab { right: calc(50% - 260px); }                         /* .home 560 → 560/2 − 20 */
  [dir="rtl"] .rank-fab { right: auto; left: calc(50% - 260px); }
}
@media (min-width: 1100px) {
  .rank-fab { right: calc(50% - 340px); }                         /* .screen 720 → 720/2 − 20 */
  [dir="rtl"] .rank-fab { right: auto; left: calc(50% - 340px); }
}

/* 底部固定分享条要占一行高度，内容列多留出这段 padding 才不会被盖住尾巴
   （26px 渐隐区 + 48px 按钮 + 14px 底距 + 视觉缓冲，实测 116px 瓷砖行不再被压） */
.rk { max-width: 560px; padding-top: 0; padding-bottom: calc(116px + env(safe-area-inset-bottom)); }   /* 顶部 safe-area 由常驻的 .rk-head 自己扛 */

/* 榜单页固定底部的「分享」长条（设计稿：渐变胶囊贴内容列宽度，居中悬浮）。
   渐变下衬一层页底色渐隐，滚动经过的内容不会跟按钮直接打架。 */
.rk-share-bar {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 40;
  display: flex; justify-content: center;
  padding: 26px 20px calc(14px + env(safe-area-inset-bottom));
  background: linear-gradient(to top, rgba(8, 8, 13, .92) 55%, transparent);
  pointer-events: none;               /* 渐隐层不挡列表点击，按钮自己恢复交互 */
}
.rk-share-btn {
  pointer-events: auto;
  width: min(520px, 100%);
  height: 48px;
  font-size: 15px;
}
/* 顶栏常驻（用户定）：下滑时钉在页顶不消失，样式**照抄主应用小组抽签页的
   .topbar**（上面 147 行那套半透明底 + 毛玻璃 + 细底边），不另创视觉。
   区别仅在定位：这里用 sticky 留在 .rk 的布局流里，与内容列对齐。 */
.rk-head {
  display: flex; align-items: center; gap: 8px;
  position: sticky;
  top: 0;
  z-index: 45;                     /* 在列表之上、分享弹窗(1000+)之下 */
  margin: 0 -20px;                 /* 铺满容器左右 padding，行内容不被边缘切断 */
  padding: calc(env(safe-area-inset-top) + 8px) 20px 8px;
  background: rgb(10 10 16 / .68);            /* ↓ 四行与 .topbar 逐字一致 */
  backdrop-filter: blur(20px) saturate(1.4);
  -webkit-backdrop-filter: blur(20px) saturate(1.4);
  border-bottom: 1px solid var(--line-soft);
}
/* 返回键图标与下方内容左缘对齐（抵消按钮内边距） */
.rk-back { flex: none; color: var(--dim); margin-left: -11px; }
[dir="rtl"] .rk-back { margin-left: 0; margin-right: -11px; }
.rk-title { flex: 1; min-width: 0; display: flex; align-items: baseline; gap: 10px; }
.rk-logo {
  font-family: var(--font-display);
  font-size: 21px; letter-spacing: .06em;
  display: inline-block;
  transform: skewX(-8deg);
  background: var(--grad);
  -webkit-background-clip: text; background-clip: text;
  color: transparent;
  white-space: nowrap;
}
/* Anton 字面高（21px 时上伸 18.2px、几乎无下伸），基线对齐后中文字块视觉偏低 → 上移 2px 做视觉居中 */
.rk-title h1 { position: relative; top: -2px; font-size: 19px; font-weight: 800; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* 数据截止时间：与 h1「排行榜」同色（继承 --txt），字号取其 50%（19px→9.5px）。
   底部与「MUSIC CUP 排行榜」视觉对齐（用户要求）：三者共用 .rk-title 的基线对齐，
   但 h1 为了配合 Anton 字标做了 top:-2px 的光学上移，这段小字没跟上，于是字形下缘
   反而比标题低出来一点。实测（PingFang SC / Anton，2026-07-26，逻辑像素）：
   字标 37.91、「排行榜」37.94、本行 38.58 —— 中文界面下沉 0.6px；拉丁界面的 h1
   没有下伸部，同样的 -2px 全额生效，下沉扩大到 1.9px。
   -1px 是两种字系的折中（中文剩 0.4px 上浮、拉丁剩 0.9px 下沉，都在半像素级）；
   要做到逐字系精确得按 h1 文本有无 CJK 下伸部分别取值，只有 JS 能判断，不值当。 */
.rk-cutoff { position: relative; top: -1px; font-size: 9.5px; font-weight: 400; white-space: nowrap; flex: none; }

/* 文字型 Tab（歌曲/歌手）+ 语言区下拉 */
.rk-topbar { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin: 16px 0 14px; }
.rk-tabs2 { display: flex; gap: 20px; min-width: 0; }
.rk-tab2 {
  font-size: 24px; font-weight: 900; line-height: 1.2;
  color: var(--dim2);
  padding: 2px 0;
  transition: color .2s;
  white-space: nowrap;
}
.rk-tab2.on { color: var(--txt); }
.rk-region-wrap { position: relative; flex: none; }
.rk-region {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 7px 12px 7px 15px;
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 13px; font-weight: 600;
  color: var(--txt);
  transition: background .2s, transform .15s;
}
.rk-region:active { transform: scale(.95); }
.rk-region svg { width: 14px; height: 14px; color: var(--dim); }
.rk-menu {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 30;
  min-width: 132px;
  padding: 5px;
  background: #15151f;
  border: 1px solid var(--line);
  border-radius: 14px;
  box-shadow: var(--shadow-card);
  animation: sugIn .18s cubic-bezier(.2, .8, .2, 1) both;
  /* 语区可能有十几个，超高就在菜单内滚动，不把页面顶长 */
  max-height: min(56vh, 380px);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;   /* 滚到底不带着整页一起滚（微信 webview 尤其明显） */
}
[dir="rtl"] .rk-menu { right: auto; left: 0; }
.rk-menu-item {
  display: block; width: 100%;
  padding: 10px 13px;
  border-radius: 9px;
  text-align: left;
  font-size: 14px;
  color: var(--dim);
}
[dir="rtl"] .rk-menu-item { text-align: right; }
.rk-menu-item.on { color: var(--txt); font-weight: 700; background: var(--panel); }
.rk-menu-item:active, .rk-menu-item:hover { background: var(--panel-2); }

.rk-search { margin-bottom: 8px; }
.rk-search .search-field { height: 48px; border-radius: 14px; background: var(--panel); }
/* 必须 ≥16px：iOS Safari / 微信 webview 对更小的输入框会在聚焦时自动放大整页，
   放大后页面比视口宽（能横向滚动）且不会自动还原，退回首页仍是放大状态。 */
.rk-search .search-field input { font-size: 16px; }

/* 扁平行列表：无容器底色、无分隔线，间距分行 */
.rk-row {
  display: flex; align-items: center; gap: 12px;
  padding: 9px 4px;
  cursor: pointer;
}
.rk-num {
  flex: none;
  min-width: 22px;
  text-align: center;
  font-size: 14px; font-weight: 600;
  color: var(--dim2);
}
.rk-num.top { font-weight: 800; }
.rk-num.t1 { color: #ffd166; }
.rk-num.t2 { color: #cfd6e4; }
.rk-num.t3 { color: #e8a87c; }
.rk-art {
  flex: none;
  width: 46px; height: 46px;
  border-radius: 10px;
  overflow: hidden;
  background: var(--panel-2);
  display: block;
}
.rk-art img { width: 100%; height: 100%; object-fit: cover; }
.rk-art .noart { width: 100%; height: 100%; display: grid; place-items: center; color: var(--dim2); }
.rk-art .noart svg { width: 18px; height: 18px; }
.rk-main { flex: 1; min-width: 0; }
.rk-main > b {
  display: block;
  font-size: 15px; font-weight: 700;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.rk-main > i {
  display: block;
  font-style: normal;
  font-size: 12px; color: var(--dim);
  margin-top: 1px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* 歌手行右侧：检索量条形图（log 缩放，纯视觉不标数） */
.rk-bar { flex: 0 0 32%; height: 9px; display: block; }
.rk-bar i {
  display: block; height: 100%;
  border-radius: 999px;
  background: var(--acc1);
  min-width: 10px;
  transition: width .4s cubic-bezier(.2, .8, .2, 1);
}
/* 扁平试听键：描边圆 */
.play-btn.rk-play {
  position: static;
  flex: none;
  width: 36px; height: 36px;
  background: transparent;
  border: 1.5px solid rgb(255 255 255 / .32);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
.play-btn.rk-play svg { width: 14px; height: 14px; }
.play-btn.rk-play.playing { background: var(--acc1); border-color: var(--acc1); }

.rk-empty { padding: 44px 20px; text-align: center; color: var(--dim); font-size: 14px; }
.rk-loading { padding: 60px 0; display: grid; gap: 18px; justify-items: center; color: var(--dim); font-size: 14px; }

/* 无限滚动底部：.on 三点跳动；.done 自然到底彻底隐藏；.capped 到 150 上限显示文案 */
.rk-more { display: none; padding: 20px 0 30px; justify-content: center; align-items: center; }
.rk-more.on, .rk-more.capped { display: flex; }
.rk-more.done { display: none; }
.rk-more.on .rk-more-cap { display: none; }         /* 加载中只显示三点 */
.rk-more.capped .rk-more-dots { display: none; }    /* 到上限只显示文案 */
.rk-more-cap { display: none; font-size: 12px; letter-spacing: .04em; color: var(--dim2); }
.rk-more.capped .rk-more-cap { display: inline; }
.rk-more-dots { display: inline-flex; gap: 6px; }
.rk-more-dots i {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--acc1, #e8a87c);
  animation: rkDot 1s ease-in-out infinite both;
}
.rk-more-dots i:nth-child(2) { animation-delay: .16s; }
.rk-more-dots i:nth-child(3) { animation-delay: .32s; }
@keyframes rkDot {
  0%, 80%, 100% { transform: scale(.5); opacity: .4; }
  40% { transform: scale(1); opacity: 1; }
}

/* ---------- 歌曲详情页（沿用冠军页视觉：大封面光晕 + 大标题） ---------- */
.rk-song { display: flex; flex-direction: column; align-items: center; text-align: center; padding-top: 22px; }
/* 歌手名：与专辑·年份同款字体样式，位于其下方 */
.rk-s-artist { color: var(--dim); font-size: 13.5px; margin-bottom: 20px; cursor: pointer; }
.rk-s-artist:active { color: var(--txt); }
.rk-s-art { position: relative; width: min(61vw, 285px); margin-bottom: 16px; }   /* 用户定：封面缩 5%，瓷砖上移 */
.rk-s-art::before {
  content: ""; position: absolute; inset: -14%;
  background: var(--grad);
  filter: blur(48px); opacity: .38;
  border-radius: 40px;
  z-index: -1;
}
.rk-s-art .rk-art {
  width: 100%; height: auto; aspect-ratio: 1;
  border-radius: 30px;
  border: 1px solid rgb(255 255 255 / .18);
  box-shadow: 0 30px 80px -20px rgb(0 0 0 / .8);
}
.rk-s-art .rk-art .noart svg { width: 60px; height: 60px; }
.rk-s-art .play-btn.rk-play {
  position: absolute; right: 12px; bottom: 12px;
  width: 48px; height: 48px;
  background: rgb(12 12 18 / .55);
  border: 1px solid rgb(255 255 255 / .25);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}
.rk-s-art .play-btn.rk-play svg { width: 19px; height: 19px; }
.rk-s-art .play-btn.rk-play.playing { background: var(--acc1); border-color: var(--acc1); }
[dir="rtl"] .rk-s-art .play-btn.rk-play { right: auto; left: 12px; }
.rk-s-title { font-size: clamp(26px, 7.5vw, 34px); font-weight: 900; line-height: 1.2; }
.rk-s-album { color: var(--dim); font-size: 13.5px; margin: 8px 0 2px; min-height: 20px; }
.rk-s-stats { width: 100%; display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; }
.rk-s-stats .stat b { font-size: 26px; }
.rk-s-stats .stat span {
  display: block;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  padding: 0 4px;
}

/* ---------- 歌手详情页 ---------- */
.rk-artistv { padding-top: 8px; }
.rk-a-head { display: flex; align-items: center; gap: 16px; margin: 10px 0 16px; }
.rk-a-head .rk-art { width: 96px; height: 96px; border-radius: 22px; }
.rk-a-head .rk-art .noart svg { width: 34px; height: 34px; }
.rk-a-meta { min-width: 0; }
.rk-a-meta h2 {
  font-size: 26px; font-weight: 900; line-height: 1.25;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.rk-a-meta p { color: var(--dim); font-size: 12.5px; margin-top: 4px; }

@media (min-width: 760px) {
  .rk { max-width: 640px; }
  .rk-bar { flex-basis: 36%; }
}

/* ---------- 无障碍 ---------- */
:focus-visible { outline: 2px solid var(--acc1); outline-offset: 3px; border-radius: 6px; }
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; }
}

/* ---------- 排行榜实体页的服务端正文（SEO） ----------
   爬虫与无 JS 环境可见；JS 启动后 render() 整体重绘 #app 原地接管。 */
.rk-seo{max-width:640px;margin:0 auto;padding:28px 20px;color:var(--txt)}
.rk-seo h1{font-size:24px;margin:0 0 10px}
.rk-seo p{opacity:.75;line-height:1.6;margin:0 0 14px}
.rk-seo-nav{display:flex;flex-wrap:wrap;gap:6px 10px;margin-bottom:18px}
.rk-seo-nav a,.rk-seo-list a{color:var(--txt);text-decoration:none;border-bottom:1px solid rgba(255,255,255,.25)}
.rk-seo-list{margin:0;padding-left:1.5em;line-height:1.9}
