:root {
  --bg: #0b0f14;
  --panel: #0d1117;
  --line: #1e2836;
  --text: #e6edf3;
  --muted: #8b98a9;
  --dim: #5d6b7d;
  --accent: #4ade80;
  --accent-2: #38bdf8;
  --radius: 14px;
  --rc: #8b98a9;

  /* 跳过教学页「夺回属于我们的一切！」的高亮色（当前：橙） */
  --story-hl: #fb923c;

  /* v0.47 顶栏三档配色 */
  --ui-label: #a78bfa;   /* 养分 / 长度 / 下次进化 / 护盾 这些小标签 → 紫 */
  --ui-goal: #fb923c;    /* 目标养分（/1350、/消灭全部敌人） → 橙 */
}

* { box-sizing: border-box; }

html, body { height: 100%; }

body {
  margin: 0;
  height: 100dvh;
  overflow: hidden;
  display: grid;
  place-items: center;
  padding: 10px;
  background:
    radial-gradient(1100px 620px at 50% -10%, #16233a 0%, transparent 62%),
    radial-gradient(700px 480px at 100% 110%, #10261f 0%, transparent 60%),
    var(--bg);
  color: var(--text);
  font-family: "Segoe UI", system-ui, -apple-system, "PingFang SC", "Microsoft YaHei", sans-serif;
  -webkit-font-smoothing: antialiased;
}

/* 一屏布局：顶栏 + 自适应正方形棋盘 */
.app {
  width: min(96vw, calc(100dvh - 76px), 860px);
  height: 100%;
  max-height: 100dvh;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 4px 0;
}

.board-area {
  flex: 1 1 auto;
  min-height: 0;
  display: grid;
  place-items: center;
}

/* ---------- 顶栏 ---------- */
.topbar {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
  padding: 0 2px;
}

.brand {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.1em;
  color: var(--text);
  white-space: nowrap;
}

/* v0.47：「蛇之传承」标题提到纯白，压过顶栏其它文字 */
#brand-name { color: #ffffff; }

/* v0.47：关卡名跟在代数后面，弱一档（它是位置提示，不是数值） */
.brand .level-name {
  margin-left: 8px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--ui-label);
  opacity: 0.85;
}

.brand .level-name:empty { display: none; }

.brand em {
  font-style: normal;
  margin-left: 6px;
  padding: 2px 7px;
  border: 1px solid var(--line);
  border-radius: 6px;
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--accent-2);
}

.hud { display: flex; gap: 14px; transition: opacity 200ms ease; }

.is-idle .hud { opacity: 0; pointer-events: none; }

.stat { display: grid; gap: 2px; text-align: right; }

.stat .k {
  font-size: 10px;
  letter-spacing: 0.1em;
  /* v0.47：养分 / 长度 / 下次进化 / 护盾 的标签统一紫色 */
  color: var(--ui-label);
  white-space: nowrap;
}

.stat .v {
  font-size: 17px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  color: var(--text);
}

.stat .v b { font-weight: 700; }
/* v0.47：目标养分（/1000、／3 次进化、／消灭全部敌人）改橙色 */
.stat .v i { font-style: normal; font-size: 11px; color: var(--ui-goal); font-weight: 400; }

/* ---------- 棋盘 ---------- */
.stage {
  position: relative;
  width: 100%;
  aspect-ratio: 1 / 1;
  border-radius: var(--radius);
  overflow: hidden;
  border: 1px solid var(--line);
  background: var(--panel);
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5), inset 0 0 0 1px rgba(255, 255, 255, 0.02);
}

#board {
  display: block;
  width: 100%;
  height: 100%;
}

/* 护盾碎裂 / 死亡 / 传送 的屏幕反馈 */
.stage.is-hit::after,
.stage.is-dead::after,
.stage.is-portal::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  animation: hitpulse 420ms ease-out forwards;
}

.stage.is-hit::after { box-shadow: inset 0 0 70px 14px rgba(248, 113, 113, 0.55); }
.stage.is-dead::after { box-shadow: inset 0 0 90px 22px rgba(239, 68, 68, 0.7); }
.stage.is-portal::after { box-shadow: inset 0 0 60px 12px rgba(34, 211, 238, 0.45); }

/* HUD：剩余敌人（只在黑蛇关显示） */
.stat--hunt { transition: opacity 160ms ease; }
.stat--hunt.is-off { display: none; }
/* v0.47：这里显示的是"还剩几个"，属于目标类信息，跟目标养分同色 */
.stat--hunt .v { color: var(--ui-goal); font-weight: 700; }
.stat--hunt .v.is-alert { color: #fbbf24; }

@keyframes hitpulse {
  from { opacity: 1; }
  to { opacity: 0; }
}

/* ---------- 遮罩 / 面板 ---------- */
.overlay {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  justify-items: center;
  padding: 20px;
  background: rgba(8, 12, 18, 0.95);
  animation: fade 160ms ease-out;
}

.overlay.is-hidden { display: none; }

/* v0.17：进化/传承面板用半透明遮罩——能看到游戏画面，像暂停那样 */
.overlay.is-dim { background: rgba(8, 12, 18, 0.52); }

/* v0.22：暂停遮罩再淡一档（0.35）。暂停时玩家想看清棋盘处境，
   0.95 等于把画面糊死；文字对比度靠下面的局部补偿保住。 */
.overlay.is-pause { background: rgba(8, 12, 18, 0.35); }

.overlay.is-pause .hint,
.overlay.is-pause .flavor {
  color: rgba(232, 238, 248, 0.95);
  text-shadow: 0 1px 6px rgba(0, 0, 0, 0.9);
}

.overlay.is-pause .panel h2,
.overlay.is-pause .eyebrow {
  text-shadow: 0 2px 10px rgba(0, 0, 0, 0.85);
}

/* 半透明后，原本按"近黑底"设计的低对比辅助元素会被亮色地面洗掉——局部补偿 */
.overlay.is-dim .hint {
  color: rgba(226, 234, 244, 0.92);
  text-shadow: 0 1px 5px rgba(0, 0, 0, 0.85);
}

.overlay.is-dim .flavor {
  color: rgba(226, 234, 244, 0.88);
  text-shadow: 0 1px 5px rgba(0, 0, 0, 0.85);
}

/* v0.26：半透明底上的长段落正文。
   .story 原来用 --muted #8b98a9（低饱和灰蓝），压在 0.52 遮罩的草地上只有
   1.90:1，糊成一片；同背景下橙/蓝/紫虽然亮度比也只有 2.0~2.6，但靠色相就能认。
   所以正文要做的是"提亮到近白"（5.04:1），而不是换色相。
   阴影补的是草地格线的干扰——纯靠颜色在带纹理的底上总有一两处糊。 */
.overlay.is-dim .story {
  color: #eef4fb;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.8), 0 1px 9px rgba(0, 0, 0, 0.5);
}

/* 重点句的橙色（--story-hl）同样需要阴影：它的亮度比只有 2.46:1，
   全靠高饱和撑着，加一层深色背衬能让笔画边缘更锐。 */
.overlay.is-dim .story b {
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.85);
}

.overlay.is-dim .btn-quiet {
  color: rgba(240, 246, 252, 0.95);
  background: rgba(9, 15, 26, 0.82);
  border: 1px solid #33465f;
  border-radius: 6px;
}

.overlay.is-dim .btn-quiet:hover { color: #ffffff; }

/* v0.17：黑蛇击杀触发的进化，面板里常驻一行死因播报（选完才消失） */
.evolve-note {
  margin: 0;
  font-size: 12.5px;
  letter-spacing: 0.04em;
  color: #fbbf24;
  text-shadow: 0 1px 6px rgba(0, 0, 0, 0.8);
}

@keyframes fade { from { opacity: 0; } to { opacity: 1; } }

.panel {
  display: grid;
  justify-items: center;
  gap: 8px;
  width: min(100%, 780px);
  min-width: 0;
  text-align: center;
  /* v0.24：这里**不再**设 overflow-y: auto。
     v0.21 加它是为了卡面面板在小窗口能滚，但它对所有普通面板一视同仁——
     面板高度本来就由内容撑开（grid 的 auto 轨道），任何 1px 的滚动溢出
     （当时是 .btn:active 的 translateY(1px)）都会让浏览器画出系统滚动条，
     表现为「鼠标按住按钮时面板右侧闪一下」。卡面的滚动已经由
     .panel--cards .cards 独立承担，标题页有自己的规则，这里不需要。 */
}

/* 极矮屏（<460px 高）兜底：普通面板这时可能装不下，恢复滚动，
   否则 body 的 overflow:hidden 会把按钮直接裁掉且无法触达。 */
@media (max-height: 459px) {
  .panel {
    max-height: 100%;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding-right: 2px;
  }
}

/* v0.21：卡面面板（进化 / 传承）改用 flex 纵向排列，
   让 .cards 成为唯一可滚动区——标题、提示、底部按钮始终可见。
   小窗口（1080×600）下 2 列卡片会把 grid 版面板顶出可视区，
   按钮滚到屏幕外等于把玩家卡死。 */
.panel--cards {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}

.panel--cards .cards {
  flex: 0 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  /* 卡片下缘的滚动条不贴着边框图，留 2px */
  padding-right: 2px;
}

/* 矮屏（≤760px 窗口高）收紧卡面面板：目标是在 1080×600 这种窗口里
   2 行卡 + 提示 + 按钮全都放得下，而不是靠滚动。滚动只是兜底。
   选择器写成 .panel--cards .cards .card 是为了压过 .card.common（0,2,0）——
   边框那组规则更靠后，同权重会被它盖住。 */
@media (max-height: 760px) {
  .panel--cards { gap: 5px; }
  .panel--cards h2 { font-size: 19px; }
  .panel--cards .flavor { font-size: 11px; line-height: 1.35; }
  .panel--cards .cards { gap: 8px; }
  .panel--cards .cards .card { min-height: 104px; padding: 16px 14px 24px; }
  .panel--cards .cards .card-name { font-size: 14px; }
  .panel--cards .cards .card-desc { font-size: 11px; line-height: 1.4; }
}

.panel h2 {
  margin: 0;
  font-size: clamp(19px, 3.6vw, 26px);
  letter-spacing: 0.02em;
  line-height: 1.3;
}

.eyebrow {
  font-size: 11px;
  letter-spacing: 0.16em;
  color: var(--accent-2);
}

.eyebrow--legacy { color: #a78bfa; }

/* 跳过教学页：眉题升为全页最大的字 */
.eyebrow--big {
  font-size: clamp(18px, 2.8vw, 24px);
  letter-spacing: 0.2em;
  font-weight: 700;
  margin-bottom: 18px;
}

/* 跳过教学页：「获得天赋 ×」这行，黄色、第二大字 */
.stats-line--talent {
  margin: 6px 0 22px;
  justify-content: center;
  font-size: 13px;
}
.stats-line--talent b {
  color: #fbbf24;
  font-size: clamp(17px, 2.4vw, 21px);
  font-weight: 800;
  font-variant-numeric: normal;
}

/* 跳过教学页的故事：紧凑版 */
.story--compact {
  max-width: 480px;
  line-height: 1.8;
}

.flavor {
  margin: 0;
  font-size: 12.5px;
  color: var(--muted);
  max-width: 420px;
  line-height: 1.65;
  text-wrap: pretty;
}

/* v0.48：关卡预览的 flavor 行升级为「这一关的关键提示」——产品把重要信息
   写进了 level.js 的 flavor，所以这一行需要橙色高亮，压过普通说明文字。
   与 .hint--key 同色系，但保持 flavor 的排版（尺寸/间距不动）。
   橙在深底上亮度比只有 2.46:1，按本文件规范补一层深色投影锐化笔画。 */
.flavor--key {
  color: var(--story-hl);
  font-weight: 700;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.85);
}

.story {
  margin: 0;
  font-size: 13px;
  line-height: 1.9;
  color: var(--muted);
  max-width: 560px;
  text-wrap: pretty;
}

.story b {
  /* 跳过教学页「夺回属于我们的一切！」这一行的颜色。
     想换颜色只改这一个值（候选见文件末尾注释）。 */
  color: var(--story-hl);
  font-weight: 700;
}

.stats-line {
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
  justify-content: center;
  font-size: 12.5px;
  color: var(--muted);
}

.stats-line b {
  color: var(--text);
  font-variant-numeric: tabular-nums;
  font-size: 14.5px;
}

.hint {
  margin: 2px 0 0;
  font-size: 11px;
  color: var(--dim);
  letter-spacing: 0.02em;
}

/* 教学关预览：长者教导的那行规则 */
.hint--big {
  font-size: 13.5px;
  color: var(--text);
  line-height: 1.8;
  letter-spacing: 0.02em;
}

/* 狩猎关预览的关键规则行：比 flavor 大一号。
   v0.49：橙色改紫色——上一行 flavor 已经橙了，两行同色分不出主次；
   改成 --ui-label 紫之后，层级是「橙=这一关的氛围提示 / 紫=进入后的硬规则」。
   紫在深底上亮度比同样偏低，投影照旧保留。 */
.hint--key {
  margin: 6px 0 0;
  font-size: 15px;
  font-weight: 700;
  color: var(--ui-label);
  letter-spacing: 0.02em;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.85);
}

.btn {
  margin-top: 6px;
  padding: 10px 22px;
  border: 0;
  border-radius: 10px;
  font: inherit;
  font-weight: 700;
  color: #06120b;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  cursor: pointer;
  transition: filter 120ms ease;
}

.btn:hover { filter: brightness(1.08); }
/* v0.24：按下反馈改成只改绘制、不改几何。
   原来用 translateY(1px)，在 overflow-y:auto 的祖先里会被算进 scrollable
   overflow，面板高度临界时立刻画出系统滚动条（见 .panel 上的注释）。 */
.btn:active { filter: brightness(0.94); }

.btn-quiet {
  margin-top: 4px;
  padding: 6px 12px;
  border: 0;
  border-bottom: 1px dashed #33445c;
  background: transparent;
  color: var(--muted);
  font: inherit;
  font-size: 12px;
  letter-spacing: 0.03em;
  cursor: pointer;
}

.btn-quiet:hover {
  color: var(--text);
  border-bottom-color: #4a5f7a;
}

/* v0.25：侧模式结束面板的「回到标题」。
   默认的 .btn-quiet 是脚注式虚线字，和主按钮并排时像说明文字而不是选项；
   这里抬成有边框的次级按钮，但不上渐变，保住「再来一次」的主次。 */
.btn-quiet--boxed {
  margin-top: 8px;
  padding: 8px 20px;
  border: 1px solid #2b3b52;
  border-radius: 9px;
  font-size: 13px;
  color: #9fb0c4;
}

.btn-quiet--boxed:hover {
  border-color: #3d5573;
  color: var(--text);
}

/* 跳过教学：面板右下角的弱化按钮 */
.btn-skip {
  margin-top: 10px;
  font-size: 11.5px;
  opacity: 0.85;
}

/* 关卡选择（回忆 / 无尽） */
.level-pick {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
  width: 100%;
  margin: 8px 0 4px;
}

.level-pick .btn-quiet {
  margin-top: 0;
  padding: 8px 6px;
  border: 1px solid #2c3a4e;
  border-radius: 8px;
  border-bottom: 1px solid #2c3a4e;
  text-align: center;
  font-size: 12px;
}

.level-pick .btn-quiet:hover {
  border-color: #4a5f7a;
  background: rgba(74, 95, 122, 0.12);
}

/* ---------- 卡牌 ---------- */
.cards {
  display: grid;
  grid-template-columns: repeat(var(--cols, 3), minmax(0, 1fr));
  gap: 9px;
  width: 100%;
  /* v0.24：把原来的 margin-top 4px 换成 padding-top 4px——总占位不变，
     但容器内部多出 4px 空间吸收 .card:hover 的上浮 3px，
     否则这个位移会被算进 .cards 的 scrollable overflow，画出滚动条。 */
  margin: 0 0 2px;
  padding-top: 4px;
}

.cards--grid { width: 100%; }

.card {
  position: relative;
  width: 100%;
  min-height: 140px;
  display: grid;
  align-content: start;
  gap: 6px;
  padding: 12px 12px 24px;
  border-radius: 12px;
  border: 1px solid #24334a;
  border-top: 3px solid var(--rc);
  background: #131c28;
  color: var(--text);
  text-align: left;
  font: inherit;
  cursor: pointer;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04);
  transition: transform 110ms ease, border-color 110ms ease, box-shadow 110ms ease;
}

.cards--grid .card { min-height: 118px; }

.card:hover {
  transform: translateY(-3px);
  border-color: var(--rc);
  box-shadow: 0 10px 26px rgba(0, 0, 0, 0.45);
}

/* v0.24：按下同样只改绘制。hover 的 -3px 上浮保留（由 .cards 的
   padding-top 吸收），但按下不能再叠加位移，否则容器临界时会闪滚动条。 */
.card:active { filter: brightness(1.08); }

/* 传说卡：整张金色的卡，不只是顶边一条线（BUG-4） */
.card.legend {
  border-color: rgba(251, 191, 36, 0.42);
  border-top-color: #fbbf24;
  background: linear-gradient(180deg, #241a06 0%, #151009 100%);
  box-shadow: inset 0 1px 0 rgba(251, 191, 36, 0.16),
              0 0 18px rgba(251, 191, 36, 0.10);
}

.card.legend:hover {
  border-color: rgba(251, 191, 36, 0.75);
  box-shadow: 0 10px 26px rgba(0, 0, 0, 0.45), 0 0 22px rgba(251, 191, 36, 0.22);
}

.card.legend .card-name {
  color: #fde68a;
  text-shadow: 0 0 12px rgba(251, 191, 36, 0.35);
}

/* ---- v0.17 二轮：四角说明 ----
   稀有度左上、标签右上、本代/永久左下、无法传承右下，全部落在边框图上。
   深墨字 + 半透明米白底：白/紫/金三种框上都可读（不依赖框色）。 */
.card-corner {
  position: absolute;
  font-size: 10.5px;
  letter-spacing: 0.05em;
  font-weight: 500;
  color: #1f2733;
  background: rgba(255, 251, 240, 0.75);
  border-radius: 4px;
  padding: 1px 6px;
  white-space: nowrap;
}

/* ---- 角标钉在内角交界处（v0.17 方案 A：骑缝） ----
   绝对定位的基准是 padding 盒（黑区边缘），不是卡片外角。
   ±9px 让角标向外探进边框带 9px、其余留在黑区——钉在黑区与
   边框带的交界线上，即视觉上的"卡片内角"。米白底在框与黑两种
   底上都成立，所以骑缝不损可读性。 */
.card-corner--tl { top: -9px; left: -9px; }
.card-corner--tr { top: -9px; right: -9px; }
.card-corner--bl { bottom: -9px; left: -9px; }
.card-corner--br { bottom: -9px; right: -9px; }

.card-name {
  font-size: 15px;
  font-weight: 700;
  line-height: 1.2;
}

.card-desc {
  font-size: 12px;
  line-height: 1.5;
  color: #9fb0c4;
  text-wrap: pretty;
}

/* v0.21-b：数字键与底部角标同一条水平线。
   角标贴在内角交界处（bottom: -9px，骑缝），键也用 -9px；
   高度写死 16px 与角标一致（实测角标 16px），上下边都对齐，
   读成「本代 ×2/3 · [2] · 无法传承」一行。 */
.card-key {
  position: absolute;
  left: 50%;
  bottom: -9px;
  transform: translateX(-50%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 16px;
  padding: 0 9px;
  font-size: 12px;
  font-weight: 700;
  line-height: 1;
  color: #fde68a;
  background: rgba(9, 15, 26, 0.92);
  border: 1px solid rgba(251, 191, 36, 0.6);
  border-radius: 5px;
  white-space: nowrap;
}

/* 「无法传承」：给玩家的提前预警——这张卡带不进下一代。
   与其它角标同款深字米白底；12/26 张都不可继承，是常态而非异常。 */
.card-corner.is-no-legacy {
  color: #501313;
  background: rgba(252, 235, 235, 0.85);
}

/* 传承面板的卡：只保留"永久"的边框提示，底色交给稀有度。
   以前这里写死紫色渐变，会盖掉 common/rare/legend 的底色——
   结果非传说卡全是紫色（v0.8 修正）。 */
.card--permanent {
  border-color: #4c3f6e;
  box-shadow: inset 0 1px 0 rgba(167, 139, 250, 0.12), 0 0 0 1px rgba(167, 139, 250, 0.08);
}

/* 传承面板：左下角标是「永久/已传承」，底色偏紫以区分面板 */
.card--permanent .card-corner--bl {
  color: #2b2154;
  background: rgba(226, 217, 255, 0.85);
}

/* 传承面板里的传说卡：金色底 + 金色边框（稀有度优先） */
.card--permanent.legend {
  border-color: rgba(251, 191, 36, 0.5);
  border-top-color: #fbbf24;
  background: linear-gradient(180deg, #241a06 0%, #151009 100%);
  box-shadow: inset 0 1px 0 rgba(251, 191, 36, 0.16),
              0 0 0 1px rgba(251, 191, 36, 0.14),
              0 0 18px rgba(251, 191, 36, 0.10);
}

/* 传承面板里的稀有卡：紫色底 */
.card--permanent.rare {
  border-color: rgba(167, 139, 250, 0.45);
  background: linear-gradient(180deg, #1c1730 0%, #141020 100%);
}

/* 传承面板里的普通卡：灰蓝底 */
.card--permanent.common {
  border-color: rgba(139, 152, 169, 0.4);
  background: linear-gradient(180deg, #182230 0%, #131c28 100%);
}

/* ---------- 【传家宝】双选：已锁定的卡 ---------- */
/* 传承是承诺：锁定后不再响应点击，视觉上停在原位、金边收口。
   hover/active 一律复位，避免玩家以为还能改。 */
.card.is-picked,
.card.is-picked:hover,
.card.is-picked:active {
  transform: none;
  border-color: #fbbf24;
  border-top-color: #fbbf24;
  box-shadow: inset 0 0 0 1px rgba(251, 191, 36, 0.32),
              0 0 22px rgba(251, 191, 36, 0.20);
  cursor: default;
}

/* 左下角「永久」已被 JS 换成「已传承」，角标变实心金 */
.card.is-picked .card-corner--bl {
  color: #0c1420;
  background: #fbbf24;
}

/* 数字键：已锁定的卡再按也没用，改成实心金底勾 */
.card.is-picked .card-key {
  color: #0c1420;
  border-color: #fbbf24;
  background: #fbbf24;
  font-size: 0;
}

.card.is-picked .card-key::before {
  content: '✓';
  font-size: 14px;
  font-weight: 700;
}

/* ---------- buff 栏（叠在棋盘内，不占布局高度） ---------- */
.buffs {
  position: absolute;
  left: 8px;
  right: 8px;
  bottom: 8px;
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  /* 容器不挡棋盘，但 chip 自己要能点（v0.8 BUG-C：点击查看能力说明） */
  pointer-events: none;
}

.chip {
  pointer-events: auto;
  cursor: pointer;
  padding: 2px 7px;
  border-radius: 6px;
  border: 1px solid rgba(56, 189, 248, 0.25);
  background: rgba(10, 16, 24, 0.85);
  color: #a7d8f5;
  font-size: 10.5px;
  letter-spacing: 0.02em;
  backdrop-filter: blur(2px);
}

/* 传承过来的天赋：只保留一个边框上的提示，不参与颜色竞争。
   v0.8 BUG-D：颜色一律交给下面的稀有度规则。 */
.chip.legacy {
  border-style: dashed;
}

/* ---------- 颜色 = 稀有度（v0.8 BUG-D） ----------
   只有这一套配色。是否传承不再用颜色区分（玩家玩两轮自己就知道）。
   选择器写成 .chip.chip--xxx 是为了把权重提到 (0,2,0)，
   压过 .chip.legacy 与 .chip 的默认色。 */
.chip.chip--legend {
  border-color: rgba(251, 191, 36, 0.65);
  background: rgba(48, 33, 8, 0.92);
  color: #fde68a;
  font-weight: 600;
  text-shadow: 0 0 10px rgba(251, 191, 36, 0.45);
  box-shadow: 0 0 0 1px rgba(251, 191, 36, 0.18) inset;
}

.chip.chip--rare {
  border-color: rgba(167, 139, 250, 0.5);
  color: #c4b5fd;
}

.chip.chip--common {
  border-color: rgba(139, 152, 169, 0.4);
  color: #a9b6c6;
}

.chip.kill {
  border-color: rgba(248, 113, 113, 0.45);
  background: rgba(40, 12, 12, 0.9);
  color: #fca5a5;
  font-weight: 600;
}

/* 有面板打开时收起 chip 条（v0.21）。
   面板态下点击 chip 是被 showAbilityInfo 的 mode 守卫挡住的，留着等于摆一个
   点不动的按钮；何况遮罩本身近乎不透明，留着也看不见。
   注：v0.21-b 撤掉了暂停面板里的两栏清单，要看能力详情请回到游戏中点 chip。 */
.overlay:not(.is-hidden) ~ .buffs {
  display: none;
}

/* ---------- toast ---------- */
.toast {
  position: absolute;
  left: 50%;
  top: 14px;
  transform: translate(-50%, -8px);
  padding: 7px 15px;
  border-radius: 999px;
  background: rgba(74, 222, 128, 0.16);
  border: 1px solid rgba(74, 222, 128, 0.45);
  color: #c7f9d6;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.03em;
  opacity: 0;
  pointer-events: none;
  transition: opacity 180ms ease, transform 180ms ease;
  white-space: nowrap;
}

.toast.is-on {
  opacity: 1;
  transform: translate(-50%, 0);
}

@media (max-width: 620px) {
  /* 窄屏放不下两个徽章：隐藏「标签」（进度/生存/赌徒…），保住左下角。
     v0.21 起左下角带层数（本代 ×2 / 本代 ×1/3），信息量比标签高；
     稀有度在左上、「无法传承」在右下，两条关键信息都不受影响。 */
  .card-corner--tr {
    display: none;
  }
}

@media (max-width: 520px) {
  .hud { gap: 9px; }
  .stat .v { font-size: 14px; }
  .card { width: 100%; min-height: 128px; padding: 10px 10px 22px; }
  .card-name { font-size: 14px; }
  .card-desc { font-size: 11.5px; }
}

/* ============================================================
   【跳过教学页】「是时候回到那里去了，夺回属于我们的一切！」
   这一行的颜色候选 —— 改 :root 里的 --story-hl 一个值即可
   ------------------------------------------------------------
   候选                色值        观感
   橙（当前）          #fb923c    温暖、有号召力，和"出发"按钮同系
   黄                  #fbbf24    亮、喜庆，和传说卡同色
   紫                  #a78bfa    和"长者的嘱托"眉题同色，页面统一
   深白                #dbe7f3    接近原白色，但更柔和不刺眼
   普通白              #ffffff    最亮的纯白
   浅金                #fde68a    黄的柔和版，不扎眼
   珊瑚红              #f87171    有"战斗檄文"感，但偏警告
   青绿                #5eead4    和"出发"按钮一致，但语义偏"安全"
   ============================================================ */

/* ==========================================================================
   美术素材接入（批次 3 收尾）
   ========================================================================== */

/* ---- 长者肖像：挂在 eyebrow 上方，不动 DOM 结构 ----
   elder-portrait 是 512 方图、脸在上半部，用 background-size 放大后
   裁出脸部，比整张缩进去清楚得多 */
.eyebrow--elder::before {
  content: '';
  display: block;
  width: 86px;
  height: 86px;
  margin: 0 auto 12px;
  background: url('assets/art/elder-portrait.png') center 26% / 122% auto no-repeat;
  border-radius: 50%;
  border: 3px solid #3a2b28;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.45),
              inset 0 0 0 2px rgba(255, 255, 255, 0.14);
}

/* ---- 标题界面（v0.23 重排） ----
   封面 1536×1024 是 3:2。棋盘是 1:1，两者比例不同，所以"铺满"和"不裁"只能二选一：
     · 面板铺满棋盘 + cover → 左右各裁 17%，两个角色都会被切
     · 面板保持 3:2 + contain → 棋盘上下留黑边（旧版的问题）
   这里取第三条：面板**按 3:2 完整显示整幅画**，棋盘剩下的部分用同一张图的
   模糊放大版填底（.overlay.is-title::before）——图不裁、无黑边、零新素材。 */
.panel--title {
  position: relative;
  z-index: 1;                       /* 压在模糊底之上 */
  width: 100%;
  max-width: 720px;
  aspect-ratio: 3 / 2;              /* 与封面素材同比例 → cover 不裁切 */
  min-height: min-content;          /* 小窗口内容放不下时允许长高（此时左右略裁） */
  max-height: none;                 /* 不继承 .panel 的 100%：否则 4 按钮会被切掉 */
  padding: 30px 28px 24px;
  background: url('assets/art/title-bg.png') center / cover no-repeat;
  border-radius: 20px;
  box-shadow: 0 24px 64px rgba(0, 0, 0, 0.6);
  /* 不写 overflow:hidden——4 个按钮在小窗口会超出 3:2，留给 .panel 的
     max-height + overflow-y 兜底，宁可出滚动条也不能把按钮切掉。 */
  overflow-x: hidden;
  overflow-y: auto;
}

.panel--title::before {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(130% 95% at 50% 22%,
              rgba(8, 14, 24, 0.20) 0%,
              rgba(8, 14, 24, 0.56) 58%,
              rgba(8, 14, 24, 0.82) 100%);
  border-radius: inherit;
}

/* 内容区背后加一层柔和暗带（v0.23）：副题与按钮正压在大蛇的浅色身体上，
   纯靠 text-shadow 压不住，加一块无硬边的径向暗底。 */
.panel--title::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 48%;
  transform: translate(-50%, -50%);
  width: 90%;
  height: 78%;
  background: radial-gradient(60% 60% at 50% 50%, rgba(6, 10, 18, 0.60) 0%, rgba(6, 10, 18, 0.34) 62%, rgba(6, 10, 18, 0) 100%);
  pointer-events: none;
}

.panel--title > * { position: relative; z-index: 1; }

/* 封面态：整个棋盘铺同一张封面的模糊放大版，取代原来的 0.95 黑幕 */
.overlay.is-title {
  background: #0b0f14;
  /* 关键：overlay 是 place-content:center，1fr 轨道会被内容压成 max-content，
     封面卡片就只能长成"内容那么宽"。封面态单独把轨道钉成 100%。 */
  grid-template-columns: 100%;
}

.overlay.is-title::before {
  content: '';
  position: absolute;
  inset: -24px;
  background: url('assets/art/title-bg.png') center / cover no-repeat;
  filter: blur(26px) brightness(0.42) saturate(1.05);
  transform: scale(1.12);
}

/* 标题层级（v0.23 反转）：游戏名最大，副题退成一行小字 */
.eyebrow--title {
  font-size: clamp(22px, 3vw, 30px);
  letter-spacing: 0.2em;
  font-weight: 700;
  line-height: 1.2;
}

.title-sub {
  margin: 0;
  font-size: 14.5px;
  letter-spacing: 0.04em;
  color: rgba(240, 246, 253, 0.97);
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.95), 0 2px 12px rgba(0, 0, 0, 0.8);
}

/* 按钮列：一行一个，全部主按钮样式（v0.23 按产品要求取消主次区分） */
.title-actions {
  display: grid;
  gap: 10px;
  justify-items: center;
  width: 100%;
  margin-top: 14px;
}

.title-btn {
  width: min(100%, 320px);
  margin-top: 0;
}

.title-btn small {
  font-size: 12px;
  font-weight: 500;
  opacity: 0.82;
  margin-left: 2px;
}

.panel--title .eyebrow {
  color: #ffe9b8;
  text-shadow: 0 2px 8px rgba(0, 0, 0, 0.8);
}

/* 矮屏（≤760px 窗口高）：四按钮版式在 1080×620 下超出约 90px，
   收紧字号与间距把它压回 3:2 卡片内，滚动条只作兜底。 */
@media (max-height: 760px) {
  /* 矮屏放弃 3:2 画框：卡片改为内容高度（左右各裁掉一点封面边缘），
     否则四个按钮放不下。高屏仍保持 3:2，封面完整。 */
  .panel--title { padding: 22px 22px 16px; aspect-ratio: auto; }
  .eyebrow--title { font-size: 22px; letter-spacing: 0.16em; }
  .title-sub { font-size: 13px; }
  .title-actions { gap: 7px; margin-top: 10px; }
  .title-btn { padding: 8px 18px; }
  .title-btn small { font-size: 11px; }
  .panel--title .hint { margin-top: 8px; }
}

.panel--title .hint {
  color: rgba(232, 238, 248, 0.92);
  text-shadow: 0 1px 7px rgba(0, 0, 0, 0.95);
}

/* ---- 卡牌边框：按稀有度换整张边框图 ----
   素材是 512×512 的九宫格边框（中心透明），用 border-image 切片，
   这样卡片高度随内容变化时边框不会变形 */
.card.common,
.card.rare,
.card.legend {
  /* 关键：border-image-width 只影响绘制、不参与布局，
     必须用真的 transparent 边框把位置占出来，否则文字会被边框图盖住 */
  border: 32px solid transparent;
  border-radius: 0;
  border-image-slice: 130 fill;
  border-image-width: 32px;
  border-image-repeat: stretch;
  /* v0.21：172 → 140。2 列布局下卡片约 280px 宽，desc 最多 2 行，
     172 是给"4 张挤成一列、文案 5 行"的旧形态留的高度。 */
  min-height: 140px;
  padding: 22px 18px 26px;   /* 数字键骑在内角交界处，底部只需留 26px 防压行 */
  margin-bottom: 0;          /* 数字键已移进卡内，卡外不再需要空隙 */
}

.card.common { border-image-source: url('assets/art/frame-common.png'); }
.card.rare { border-image-source: url('assets/art/frame-rare.png'); }
.card.legend { border-image-source: url('assets/art/frame-legend.png'); }

/* ---- v0.17：幕布对齐素材黑心 ----
   slice 46 → 130：紫框、淡紫内环、黑区的圆角描边和底部"叠卡"装饰层
   全部划入边框区（切割线落在纯黑区内，不再从装饰层中间穿过——
   那是二轮"内边框被覆盖一半"的根因），fill 渲染的中心就是干净的纯黑幕布。 */
.card.common,
.card.rare,
.card.legend {
  border-image-slice: 130 fill;
}

/* v0.17 二轮：旧的 border-top:0 已删——那是给已废弃的 --rc 顶色线让位用的，
   它会让顶边布局边框归零，边框图和四角标位的定位基准全部错位。 */

.card.common:hover,
.card.rare:hover,
.card.legend:hover { border-image-width: 34px; border-width: 34px; }

/* ---------- v0.31 死亡屏：死因播报 + 战绩 ---------- */

/* 死因常驻在舞台顶部：死亡瞬间玩家视线还在蛇身上，面板居中且内容多，
   死因混在正文里会被"族群还有很多蛋"那类叙事淹没。
   放在 toast 下方（toast 占 top:14px），两者不会互相盖住。 */
.death-note {
  position: absolute;
  left: 50%;
  top: 58px;
  transform: translate(-50%, -8px);
  padding: 8px 18px;
  border-radius: 999px;
  background: rgba(127, 29, 29, 0.88);
  border: 1px solid rgba(248, 113, 113, 0.7);
  box-shadow: 0 6px 22px rgba(0, 0, 0, 0.55);
  color: #ffe9e9;
  font-size: 15px;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-shadow: 0 1px 6px rgba(0, 0, 0, 0.8);
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.18s ease, transform 0.18s ease;
  z-index: 3;
}

.death-note.is-on {
  opacity: 1;
  transform: translate(-50%, 0);
}

/* 战绩：两个数字块。原来和叙述同级（12.5px 灰字），打完一局看不到自己得了多少。 */
.record {
  display: flex;
  justify-content: center;
  align-items: flex-end;
  gap: 34px;
  margin: 2px 0 6px;
}

.record-item {
  display: grid;
  justify-items: center;
  gap: 3px;
}

.record-value {
  font-size: clamp(24px, 3.2vw, 30px);
  font-weight: 800;
  line-height: 1.05;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

.record-label {
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--dim);
}

/* 矮屏：面板顶边可能逼近顶部，播报收窄上移，避免压住内容 */
@media (max-height: 460px) {
  .death-note {
    top: 8px;
    padding: 6px 14px;
    font-size: 13px;
  }
}

/* 死亡屏那行小字叙事。用 --muted 而不是 --hint 的 --dim：
   11px + #5d6b7d 在近黑底上只有 3.5:1，比 v0.26 修过的正文还低。 */
.death-meta {
  margin: 0;
  font-size: 11.5px;
  letter-spacing: 0.03em;
  color: var(--muted);
}

/* ==========================================================================
   v1.1 移动端：横屏三栏 + 固定基点方向键
   --------------------------------------------------------------------------
   只在「横屏且屏高 ≤ 560px」时生效——这是手机 / 小平板横屏的特征尺寸。
   桌面端（竖屏窗口）完全不受影响，V1.0 的布局与观感保持不变。

   三栏几何：
     左栏 = 品牌 + 方向键    中栏 = 棋盘（受高度限制的正方形）    右栏 = HUD + 暂停/静音
   棋盘是正方形，横屏宽度必然富余，方向键正好落在左栏空白里，
   既不占用也不遮挡棋盘——这就是"独立栏"与"浮层"在这里会重合的原因。
   ========================================================================== */

.dpad,
.side-actions { display: none; }

/* ---- 移动端共用外观：横屏 / 竖屏两套布局只负责"摆放"，外观写在这里 ---- */
.dpad {
  position: relative;
  border-radius: 50%;
  border: 1px solid rgba(230, 237, 243, 0.14);
  background: rgba(230, 237, 243, 0.045);
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
}
.dpad svg { display: block; width: 100%; height: 100%; }
.dpad path { fill: rgba(230, 237, 243, 0.5); transition: fill 90ms ease; }
.dpad .dpad-dot { fill: rgba(230, 237, 243, 0.26); transition: fill 90ms ease; }
.dpad[data-dir="up"] .dpad-up,
.dpad[data-dir="down"] .dpad-down,
.dpad[data-dir="left"] .dpad-left,
.dpad[data-dir="right"] .dpad-right { fill: var(--accent); }
.dpad[data-dir] .dpad-dot { fill: rgba(74, 222, 128, 0.5); }

.side-actions { gap: 8px; }

.icon-btn {
  padding: 0;
  border-radius: 50%;
  border: 1px solid rgba(230, 237, 243, 0.16);
  background: rgba(13, 17, 23, 0.72);
  color: var(--text);
  font: inherit;
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}
.icon-btn:active { background: rgba(74, 222, 128, 0.22); }

@media (orientation: landscape) and (max-height: 560px) {
  :root { --side: clamp(128px, 19vw, 186px); }

  body {
    padding: 0;
    overscroll-behavior: none;          /* 禁掉下拉刷新 */
    -webkit-touch-callout: none;
    user-select: none;
    -webkit-user-select: none;
  }

  .app {
    position: relative;
    width: 100vw;
    height: 100dvh;
    max-height: none;
    gap: 0;
    display: grid;
    grid-template-columns: var(--side) minmax(0, 1fr) var(--side);
    grid-template-rows: auto minmax(0, 1fr);
    padding-top: env(safe-area-inset-top, 0px);
    padding-right: env(safe-area-inset-right, 0px);
    padding-bottom: env(safe-area-inset-bottom, 0px);
    padding-left: env(safe-area-inset-left, 0px);
  }

  /* 让 .brand / .hud 直接成为 .app 的网格子项，避免改动 DOM 层级 */
  .topbar { display: contents; }

  .brand {
    grid-column: 1;
    grid-row: 1;
    align-self: start;
    padding: 10px 6px 0 12px;
    font-size: 12px;
    letter-spacing: 0.06em;
  }
  .brand .level-name { margin-left: 4px; font-size: 11px; }
  .brand em { margin-left: 4px; padding: 1px 5px; font-size: 10px; }

  .hud {
    grid-column: 3;
    grid-row: 1 / span 2;
    flex-direction: column;
    align-items: flex-end;
    justify-content: flex-start;
    gap: 5px;
    padding: 10px 12px 64px 0;   /* 底部让位给暂停 / 静音按钮 */
  }
  .hud .stat { text-align: right; }
  .hud .stat .k { font-size: 9.5px; }
  .hud .stat .v { font-size: 15px; }

  /* 棋盘：由高度反推正方形边长。flex 之下 100% 才有确定的参照高度 */
  .board-area {
    grid-column: 2;
    grid-row: 1 / span 2;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 6px 0;
    min-width: 0;
  }
  .stage {
    flex: 0 0 auto;
    height: 100%;
    width: auto;
    max-width: 100%;
    aspect-ratio: 1 / 1;
    touch-action: none;
  }

  /* 面板改为覆盖整个屏幕：棋盘只有 340 来像素宽，三张卡塞进去会挤成一团 */
  .overlay {
    position: fixed;
    inset: 0;
    z-index: 60;
  }
  .panel { width: min(92vw, 780px); }

  /* ---- 方向键（固定基点）：只负责摆放，外观在共用区 ---- */
  .dpad {
    grid-column: 1;
    grid-row: 2;
    align-self: end;
    justify-self: center;
    display: block;
    width: clamp(132px, 17vw, 176px);
    height: clamp(132px, 17vw, 176px);
    margin-bottom: 12px;
  }

  /* ---- 暂停 / 静音 ---- */
  .side-actions {
    grid-column: 3;
    grid-row: 2;
    align-self: end;
    justify-self: end;
    display: flex;
    padding: 0 12px 12px 0;
  }
  .icon-btn { width: 44px; height: 44px; }
}

/* ==========================================================================
   V1.2 竖屏移动端：三行布局（顶栏 / 棋盘 / 方向键）
   --------------------------------------------------------------------------
   为什么不再要求横屏：棋盘是正方形，横屏只多 3px（348 vs 345），却要依赖
   orientation.lock 与全屏——浏览器一不给就玩不了。竖屏下棋盘由**宽度**决定，
   地址栏和状态栏吃掉的都是高度冗余，所以"全屏失败"从生死线降级为加分项。

   只在「竖屏且屏宽 ≤ 560px」生效；横屏仍走上面那套三栏（超集，不退步）。
   ========================================================================== */

@media (orientation: portrait) and (max-width: 560px) {
  body {
    padding: 0;
    overscroll-behavior: none;
    -webkit-touch-callout: none;
    user-select: none;
    -webkit-user-select: none;
  }

  .app {
    position: relative;
    width: 100vw;
    height: 100dvh;
    max-height: none;
    gap: 0;
    display: grid;
    grid-template-rows: auto minmax(0, 1fr) auto;
    padding-top: env(safe-area-inset-top, 0px);
    padding-right: env(safe-area-inset-right, 0px);
    padding-bottom: env(safe-area-inset-bottom, 0px);
    padding-left: env(safe-area-inset-left, 0px);
  }

  /* ---- 顶栏两行：品牌行 / 数值行 ---- */
  .topbar {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: center;
    row-gap: 4px;
    padding: 6px 10px 0;
  }
  .brand {
    grid-column: 1;
    grid-row: 1;
    font-size: 12px;
    letter-spacing: 0.06em;
    padding-right: 92px;      /* 给右上角两个圆按钮让位 */
  }
  .brand .level-name { margin-left: 4px; font-size: 11px; }
  .brand em { margin-left: 4px; padding: 1px 5px; font-size: 10px; }

  .hud {
    grid-column: 1 / -1;
    grid-row: 2;
    justify-content: space-between;
    gap: 6px;
    /* 右侧让出 96px 给暂停 / 静音：否则 space-between 会把最后一项（护盾）
       顶到最右边，正好被按钮压住 */
    padding: 0 96px 0 0;
  }
  .hud .stat { text-align: left; }
  .hud .stat .k { font-size: 9.5px; }
  .hud .stat .v { font-size: 13px; }

  /* ---- 棋盘：宽度撑满并保持正方形 ----
     min(100%, 100dvh - 290px) 里的 290 = 顶栏 52 + 方向键 188 + 上下安全区 ≈40，
     作用是在极矮屏（如 320×480）把棋盘压成正方形，而不是让 max-height 把它压扁。 */
  .board-area {
    grid-row: 2;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 4px 8px;
    min-height: 0;
  }
  .stage {
    flex: 0 0 auto;
    width: min(100%, calc(100dvh - 290px));
    max-width: 100%;
    aspect-ratio: 1 / 1;
    touch-action: none;
  }

  /* ---- 方向键：底部正中，单手拇指可及 ---- */
  .dpad {
    display: block;
    grid-row: 3;
    justify-self: center;
    width: clamp(132px, 44vw, 176px);
    height: clamp(132px, 44vw, 176px);
    margin: 0 auto 12px;
  }

  /* ---- 暂停 / 静音：右上角，不压棋盘也不挨着方向键 ---- */
  .side-actions {
    display: flex;
    position: absolute;
    top: calc(6px + env(safe-area-inset-top, 0px));
    right: calc(10px + env(safe-area-inset-right, 0px));
  }
  .icon-btn { width: 40px; height: 40px; }

  /* ---- 面板：覆盖全屏 + 卡片单列 ----
     棋盘只有 344 宽，三列会把卡挤成 110px。传承面板的列数是内联 --cols 写的，
     这里用 grid-template-columns 直接覆盖，比给变量加 !important 干净。 */
  .overlay {
    position: fixed;
    inset: 0;
    z-index: 60;
    padding: 12px;
  }
  /* 面板不再被棋盘框住，底下直接透出游戏画面，白字压黄地砖看不清。
     加一层压暗，让面板读起来像真正的弹窗。 */
  .overlay:not(.is-hidden):not(.is-pause) { background: rgba(8, 12, 18, 0.78); }
  .panel { width: 100%; max-width: 520px; }
  .panel .cards { grid-template-columns: 1fr; gap: 6px; }
  /* 单列之后每张卡横着有 336px，纵向不需要 128px——原 min-height 会让四张卡
     把面板顶到 793/800，按钮贴住屏幕下沿。压到 104 后四选一仍有富余。 */
  .panel .card { min-height: 104px; padding: 8px 12px 16px; }
  .panel .card-desc { font-size: 12px; }
}
