* { margin: 0; padding: 0; box-sizing: border-box; }

body {
  background: var(--bg-image);
  color: var(--ink);
  font-family: var(--font-ui);
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
}

#app { max-width: var(--maxw); margin: 0 auto; position: relative; z-index: 1; }

.hidden { display: none !important; }

/* 内边距下移到各 stage 与结果卡：导出长图的节点是 #resultCard，
   只有让内边距长在卡片自己身上，屏幕与长图才会有一致的内边距 */
.stage { padding: var(--pad); animation: fade .45s ease both; }
#stage-result { padding: 0; }                 /* 结果页内边距由卡片承担，避免屏幕出现双重内边距 */
/* 结果卡：屏幕与导出共用同一份内边距。
   卡片自己再画一遍 body 的背景渐变，导出长图才会带渐变（此前只有纯色 --bg，
   与屏幕不一致）——见 share.js 的 backgroundColor 只是兜底 */
#resultCard { padding: var(--pad); background: var(--bg-image); }
#resultActions { padding: 0 var(--pad) var(--pad); }  /* 按钮区在卡片之外，不进长图 */
@keyframes fade { from { opacity: 0; transform: translateY(12px); } }

/* 细金属线分隔 */
.rule { height: 1px; background: var(--line); margin: var(--gap) 0; }

/* 主按钮 */
.btn {
  display: block; width: 100%; padding: 18px;
  background: transparent; color: var(--ink);
  border: 1px solid var(--line); border-radius: 2px;
  font-size: 17px; letter-spacing: .08em; cursor: pointer;
  transition: border-color .2s, background .2s;
}
.btn:hover { border-color: var(--accent); background: var(--overlay); }
.btn:disabled { opacity: .35; cursor: not-allowed; }

/* 入口页与答题页 */
.kicker { font-size: 12px; letter-spacing: .22em; color: var(--ink-dim); text-transform: uppercase; }
.hero-title { font-family: var(--font-hero); font-size: 44px; line-height: 1.25; letter-spacing: .04em; margin: 20px 0; }
.lede { color: var(--ink-dim); font-size: 15px; line-height: 1.9; margin-bottom: 12px; }
.lede.dim { color: var(--ink-faint); }
.q-text { font-size: 26px; line-height: 1.6; margin: 24px 0 32px; font-weight: 600; }
.options { display: grid; gap: 12px; }
.opt {
  position: relative; overflow: hidden;
  padding: 20px 68px 20px 20px; text-align: left; font-size: 16px; line-height: 1.6;
  background: var(--overlay); color: var(--ink);
  border: 1px solid var(--line-soft); border-radius: 2px; cursor: pointer;
  transition: border-color .2s, background .2s;
}
/* 氛围底：右侧一层极淡的主题色，让每个选项静止时也有颜色倾向，
   而不是四块一模一样的灰板。 */
.opt::before {
  content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background: radial-gradient(60% 120% at 100% 50%, var(--opt-to, var(--accent-2)), transparent 70%);
  opacity: .06; transition: opacity .2s;
}
.opt-text { position: relative; z-index: 1; }
/* 主导维度英雄的徽记（见 ui.js 的 optionHtml）。
   装饰，不是提示：静态下是纹理，hover 亮起并把边框染成该英雄的主色，
   选中时进一步提亮。--opt-from / --opt-to 由选项内联挂上。 */
.opt-deco {
  position: absolute; right: 14px; top: 50%; z-index: 1;
  width: 44px; height: 44px; transform: translateY(-50%);
  pointer-events: none; opacity: .22; transition: opacity .2s;
}
.opt-deco .emblem { display: block; width: 100%; height: 100%; }
.opt:hover { border-color: var(--opt-from, var(--accent)); background: var(--overlay-2); }
.opt:hover::before { opacity: .11; }
.opt:hover .opt-deco { opacity: .5; }
.opt.picked::before { opacity: .16; }
.opt.picked .opt-deco { opacity: .8; }

/* 结果页 */
.hero-en { color: var(--ink-dim); letter-spacing: .3em; font-size: 13px; }
.hero-title { color: var(--ink); }
/* 注：--accent / --accent-2 由 renderResult 按英雄主题色就地覆盖，无需在此重复声明默认值 */
#stage-result .hero-title { color: var(--accent-2); }
.sec { font-size: 13px; letter-spacing: .16em; color: var(--accent); margin: 28px 0 10px; font-weight: 700; }
.para { color: var(--ink-dim); font-size: 16px; line-height: 2; }
.line {
  margin: 36px 0; padding: 28px 0; text-align: center;
  font-family: var(--font-hero); font-size: 26px; line-height: 1.6;
  color: var(--ink); border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
}
/* 下外边距交给 #resultCard 的内边距承担：卡片有内边距后 .rarity 的下外边距不再穿透折叠，
   若保留 28px 会让屏幕上的「稀有度 → 按钮」间距翻倍（28 → 56），破坏与旧版的视觉一致 */
.rarity { text-align: center; color: var(--accent-2); font-size: 14px; letter-spacing: .1em; margin: 28px 0 0; }
.ghost { margin-top: 12px; color: var(--ink-dim); }
/* ── 性格光谱雷达图（见 src/radar.js）────────────────────────────
   全 8 维，两条多边形叠在**同一套刻度**上：你（实心半透明）+ 匹配英雄（描边）。
   刻度固定 0–100，**不按数据自适应** —— 自适应会让两条形状"看起来像"，
   哪怕数值差很远，那这张图就不再是比较，而是装饰。
   英雄那条只由它自己的 vector 算出，谁来测都一样，是稳定的对比基准。 */
.radar-wrap { margin: 4px 0 10px; }
.radar { display: block; width: 100%; max-width: 340px; height: auto; margin: 0 auto; }
.radar-grid { fill: none; stroke: var(--line-soft); stroke-width: 1; }
.radar-spoke { stroke: var(--line-soft); stroke-width: 1; }
.radar-label { fill: var(--ink-dim); font-size: 13px; }
/* 「你」用固定的中性白，**不从英雄主题色派生** ——
   派生过一次，碰上主题色偏暗的英雄（雷神 from 就是深蓝）自己那条就又灰又细，
   而英雄那条反而更亮，主客颠倒。中性白在任何英雄卡上都是同一种存在感。
   英雄那条用虚线的理由：两条形状本来就该接近，实线叠一起就分不出谁是谁了。 */
.radar-user { fill: var(--ink); fill-opacity: .18; stroke: var(--ink); stroke-width: 3; stroke-linejoin: round; }
.radar-hero { fill: none; stroke: var(--accent-2); stroke-width: 2; stroke-linejoin: round; stroke-dasharray: 6 4; }

/* 图例。::before 里不放文字——字体子集脚本不扫 CSS，CSS 里的中文会变豆腐块 */
.radar-legend { display: flex; justify-content: center; gap: 22px; margin-top: 8px; }
.lg { font-size: 13px; color: var(--ink-dim); display: inline-flex; align-items: center; gap: 7px; }
.lg::before { content: ''; width: 12px; height: 12px; border-radius: 2px; }
.lg-user::before { background: var(--ink); opacity: .55; }
.lg-hero::before { border: 2px solid var(--accent-2); }

/* 得分最高的 3 维：雷达图看得出形状，看不出含义，另附一句文字 */
.radar-notes { display: grid; gap: 6px; }
.bar-name { font-size: 14px; color: var(--ink); }
.bar-desc { font-size: 13px; color: var(--ink-faint); }

/* ── 入口页 ───────────────────────────────────────────────────
   背景加一层细网格：只给"空"的地方一点结构。用径向遮罩自上而下淡出，
   整页铺满会显得吵。z-index 提到 1，压在网格之上。 */
body::before {
  content: '';
  position: fixed; inset: 0; pointer-events: none; z-index: 0;
  background-image:
    linear-gradient(var(--line-soft) 1px, transparent 1px),
    linear-gradient(90deg, var(--line-soft) 1px, transparent 1px);
  background-size: 46px 46px;
  opacity: .55;
  -webkit-mask-image: radial-gradient(120% 78% at 50% 0%, var(--mask-solid) 0%, transparent 72%);
          mask-image: radial-gradient(120% 78% at 50% 0%, var(--mask-solid) 0%, transparent 72%);
}

#stage-intro .hero-title { font-size: 52px; line-height: 1.15; margin: 26px 0 10px; }

/* 英雄阵容：两行反向滚动的人形。
   用的就是结果页那 34 个原创人形 —— 零图片请求、零新增风险，
   却能把"这是一个有 34 位人物的测试"直接摆在开始页上。
   两行方向相反错开，比同向更有"阵容在流动"的感觉。 */
.roster {
  margin: 48px calc(-1 * var(--pad)) 0;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, var(--mask-solid) 13%, var(--mask-solid) 87%, transparent);
          mask-image: linear-gradient(90deg, transparent, var(--mask-solid) 13%, var(--mask-solid) 87%, transparent);
}
.roster-title {
  text-align: center; font-size: 11px; letter-spacing: .24em;
  color: var(--ink-dim); margin-bottom: 18px;
}
.roster-row {
  display: flex; gap: 16px; width: max-content;
  animation: rosterSlide 72s linear infinite;
}
.roster-row + .roster-row { margin-top: 18px; animation-direction: reverse; animation-duration: 90s; }
/* 和封面同一套色调处理（见 .lineup img）：34 张画风差异大，不统一就会很跳 */
.roster img {
  flex: none; width: 58px; aspect-ratio: 3 / 4;
  object-fit: cover; object-position: center 22%;
  border-radius: 2px; opacity: .88;
  filter: grayscale(1) sepia(.95) saturate(1.5) brightness(.82) contrast(1.06);
}
@keyframes rosterSlide { to { transform: translateX(-50%); } }

/* 尊重系统的「减少动态效果」设置 */
@media (prefers-reduced-motion: reduce) {
  .roster-row { animation: none; }
}

/* ── 封面照片墙 ──────────────────────────────────────────────
   34 张图的画风差异很大（写实 / 插画 / 白底 / 暗底），直接并排会很跳。
   统一手段是三层叠加：
     1. 底部遮罩淡出  —— 让人物从暗处浮出来，而不是硬边贴图
     2. 整体压暗      —— 把风格差异压进同一个亮度区间
     3. 底部对齐 + 中间放大 —— 电影海报式排布，视线自然落在中间
   用的是缩略图（约 20KB），不是卡片上那张原图 —— 封面只是装饰，
   不该让首页多下几百 KB。 */
.lineup {
  display: flex; justify-content: center; align-items: flex-end;
  gap: 6px; margin-bottom: 30px;
}
/* 统一色调是这一步的关键。
   34 张图来自不同画师、不同画风，底色从纯白到深蓝都有 —— 直接并排就是
   一堆亮方块，看着很跳。去色后统一成暖调（琥珀），风格差异被抹平，
   同时和主题的金色强调色对上。
   这也是海报的常规做法：封面用风格化的单色做氛围，全彩照片留到结果页揭晓。 */
.lineup img {
  min-width: 0;
  aspect-ratio: 3 / 4; object-fit: cover; object-position: center 22%;
  border-radius: 3px; opacity: .92;
  filter: grayscale(1) sepia(.95) saturate(1.5) brightness(.82) contrast(1.06);
  -webkit-mask-image: linear-gradient(180deg, transparent 0%, var(--mask-solid) 15%, var(--mask-solid) 66%, transparent 100%);
          mask-image: linear-gradient(180deg, transparent 0%, var(--mask-solid) 15%, var(--mask-solid) 66%, transparent 100%);
}
/* 中间放大：两侧窄、中间宽，形成一条视线 */
.lineup img:nth-child(1), .lineup img:nth-child(5) { flex: 0.85 1 0; }
.lineup img:nth-child(2), .lineup img:nth-child(4) { flex: 1 1 0; }
.lineup img:nth-child(3) { flex: 1.3 1 0; opacity: .95; }

/* ── 答题页顶部的照片带 + 进度条 ──────────────────────────────
   8 张缩略图压成窄条铺满顶端，重度压暗只当氛围用；
   题目文字压在它下面的深色区域里，不影响阅读。
   负外边距是为了让它通栏 —— .stage 有内边距，不拉出来就会缩在中间。 */
.quiz-band {
  display: flex; gap: 2px; height: 70px; overflow: hidden;
  margin: calc(-1 * var(--pad)) calc(-1 * var(--pad)) 22px;
  opacity: .44;
  -webkit-mask-image: linear-gradient(180deg, var(--mask-solid) 28%, transparent 100%);
          mask-image: linear-gradient(180deg, var(--mask-solid) 28%, transparent 100%);
}
.quiz-band img {
  flex: 1 1 0; min-width: 0; height: 100%;
  object-fit: cover; object-position: center 18%;
  filter: grayscale(1) sepia(.95) saturate(1.5) brightness(.8) contrast(1.06);
}

/* 进度条。比「第 7 / 20 题」几个字更能让人知道还剩多少 */
.progress { height: 2px; background: var(--line-soft); margin: 10px 0 26px; }
.progress i { display: block; height: 100%; background: linear-gradient(90deg, var(--accent), var(--accent-2)); transition: width .3s ease; }
.preview { width: 100%; margin-top: 16px; border: 1px solid var(--line-soft); }

/* ── 英雄人形（原创抽象几何符号，见 src/icons.js）──────────────────
   内联 SVG，不是图片文件：34 位英雄因此不产生任何图片请求（不需要懒加载），
   导出长图时也天然清晰，不受设备像素比影响。
   描边用英雄自己的 theme 渐变，由 renderFigure 注入 <linearGradient>。
   姿态按签名维度变化，胸前是英雄自己的徽记。 */
.emblem-wrap { display: flex; justify-content: center; margin-bottom: 4px; }
.figure { width: 148px; height: 148px; opacity: .95; }

/* 人物图（可选，放 assets/heroes/<id>.jpg 才出现 —— 见该目录的 README）。
   画幅锁 3:4 并 object-fit: cover：无论你给什么比例，卡片上的观感一致，
   也保证导出的长图不会因为某张图特别高而被撑变形。
   底部用遮罩淡出，让照片化进卡片，而不是一块硬边的贴图。
   object-position 偏上，是因为人像的脸通常在上半部分，居中裁容易切到脸。 */
.hero-photo {
  display: block; width: 230px; aspect-ratio: 3 / 4;
  object-fit: cover; object-position: center 22%;
  border-radius: 3px;
  -webkit-mask-image: linear-gradient(180deg, var(--mask-solid) 74%, transparent);
          mask-image: linear-gradient(180deg, var(--mask-solid) 74%, transparent);
}
/* 图加载成功才隐藏人形 —— 失败时人形还在，不会出现空白 */
.emblem-wrap.has-photo .figure { display: none; }

/* ── 返回上一步 ──────────────────────────────────────────────
   选完立刻进入下一题（保持刷题手感），要改就按「上一题」回去。
   回去后必须能看出上次选的是哪个，否则等于在盲改 —— 故用三重标记：
   描边 + 底色 + 左侧内嵌色条（只靠描边太容易被 hover 态混淆）。 */
.btn.back-btn { margin-top: 28px; }
.opt.picked {
  border-color: var(--accent-2);
  background: var(--overlay-2);
  box-shadow: inset 3px 0 0 var(--accent-2);
}
