/* ==========================================================================
   贪吃蛇 · 霓虹玻璃拟态主题
   设计原则：深色渐变底 + 柔和光晕，玻璃卡片靠 backdrop-filter 撑质感，
   所有装饰元素都不抢游戏画面的戏。
   ========================================================================== */

:root {
  --bg-0: #070b14;
  --bg-1: #0d1425;
  --bg-2: #131c33;

  --glass-bg: rgba(255, 255, 255, 0.055);
  --glass-bg-strong: rgba(255, 255, 255, 0.09);
  --glass-stroke: rgba(255, 255, 255, 0.14);
  --glass-stroke-soft: rgba(255, 255, 255, 0.08);

  --text-0: #eaf2ff;
  --text-1: #a8b6d4;
  /* 次级信息文本统一用此色：实测全站最差对比度 5.47:1（.hud-label），
     达 WCAG AA 4.5:1；同时与 --text-1 保留 0.1157 亮度差，层次不塌 */
  --text-2: #8fa0c4;

  --accent: #2fe6a8;
  --accent-2: #4d8bff;
  --accent-warm: #ffb648;
  --danger: #ff5d6c;

  --radius-lg: 22px;
  --radius-md: 14px;
  --radius-sm: 10px;

  --shadow-card: 0 24px 60px rgba(0, 0, 0, 0.55);
  --shadow-soft: 0 8px 24px rgba(0, 0, 0, 0.38);
  --blur-glass: blur(18px) saturate(140%);
}

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html,
body {
  height: 100%;
}

body {
  background:
    radial-gradient(120% 90% at 50% -10%, #1b2a4d 0%, rgba(27, 42, 77, 0) 55%),
    linear-gradient(160deg, var(--bg-0) 0%, var(--bg-1) 45%, var(--bg-2) 100%);
  background-attachment: fixed;
  color: var(--text-0);
  font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", -apple-system,
    BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
  min-height: 100%;
  overflow-x: hidden;
  /* 移动端手感：禁掉双击缩放与长按弹菜单（-webkit 前缀在 iOS Safari 仍必需） */
  touch-action: manipulation;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
  /* 禁止橡皮筋下拉刷新/上拉（iOS Safari 默认允许，会露出页面底色） */
  overscroll-behavior-y: none;
}

/* 背景光晕：纯装饰，pointer-events 全关 */
.bg-orbs {
  position: fixed;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  z-index: 0;
}

.orb {
  position: absolute;
  display: block;
  border-radius: 50%;
  filter: blur(90px);
  opacity: 0.5;
}

.orb-a {
  width: 46vmin;
  height: 46vmin;
  top: -12vmin;
  left: -8vmin;
  background: radial-gradient(circle, rgba(47, 230, 168, 0.55), rgba(47, 230, 168, 0));
}

.orb-b {
  width: 52vmin;
  height: 52vmin;
  top: 22vmin;
  right: -16vmin;
  background: radial-gradient(circle, rgba(77, 139, 255, 0.5), rgba(77, 139, 255, 0));
}

.orb-c {
  width: 38vmin;
  height: 38vmin;
  bottom: -14vmin;
  left: 28vmin;
  background: radial-gradient(circle, rgba(255, 182, 72, 0.28), rgba(255, 182, 72, 0));
}

/* ---------- 布局 ---------- */
.app {
  position: relative;
  z-index: 1;
  width: min(960px, calc(100% - 32px));
  margin: 0 auto;
  padding: 28px 0 22px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

/* iOS 刘海屏 / 底部 Home 指示条避让：env() 在不支持的浏览器上回退为 0，
   故桌面端完全无副作用。
   只补上下方向 —— 左右维持 .app 自身的居中宽度逻辑（width:min(960px,100%-32px)
   + margin:auto），若在此再加左右 padding 会与之重复计算，导致布局偏移。 */
@supports (padding: max(0px)) {
  .app {
    padding-top: max(28px, env(safe-area-inset-top));
    padding-bottom: max(22px, env(safe-area-inset-bottom));
  }
}

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}

.brand {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
}

.brand-mark {
  width: 42px;
  height: 42px;
  flex: none;
  border-radius: 13px;
  background: linear-gradient(145deg, var(--accent), var(--accent-2));
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.16) inset, 0 8px 22px rgba(47, 230, 168, 0.35);
  position: relative;
}

/* 品牌标记上的"小蛇眼"，让图标和游戏呼应 */
.brand-mark::after {
  content: "";
  position: absolute;
  top: 12px;
  right: 11px;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: #06210f;
  box-shadow: -9px 3px 0 -1px #06210f;
}

.brand-text {
  min-width: 0;
}

.brand-title {
  font-size: 22px;
  font-weight: 700;
  letter-spacing: 2px;
  line-height: 1.1;
}

.brand-sub {
  font-size: 11px;
  color: var(--text-2);
  letter-spacing: 1.4px;
  margin-top: 3px;
}

/* ---------- HUD ---------- */
.hud {
  display: flex;
  align-items: stretch;
  gap: 8px;
  padding: 8px;
  border-radius: var(--radius-md);
  background: var(--glass-bg);
  border: 1px solid var(--glass-stroke-soft);
  backdrop-filter: var(--blur-glass);
  -webkit-backdrop-filter: var(--blur-glass);
  box-shadow: var(--shadow-soft);
}

.hud-cell {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  min-width: 72px;
  padding: 6px 10px;
  border-radius: var(--radius-sm);
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.06);
}

.hud-label {
  font-size: 10px;
  letter-spacing: 1.5px;
  color: var(--text-2);
}

.hud-value {
  font-size: 18px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--text-0);
  text-shadow: 0 0 18px rgba(47, 230, 168, 0.35);
}

.hud-value-alt {
  color: var(--accent-warm);
  text-shadow: 0 0 18px rgba(255, 182, 72, 0.35);
}

.icon-btn {
  width: 40px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: var(--radius-sm);
  background: rgba(255, 255, 255, 0.04);
  color: var(--text-0);
  cursor: pointer;
  transition: background 0.18s ease, transform 0.12s ease, color 0.18s ease;
}

.icon-btn:hover {
  background: var(--glass-bg-strong);
  color: var(--accent);
}

.icon-btn:active {
  transform: scale(0.94);
}

/* 暂停键在菜单/结束态禁用（对局未开始，暂停无意义）。
   :disabled 会移出 Tab 序列，这里再给明确的视觉降级，避免玩家以为点了没反应。 */
.icon-btn:disabled {
  opacity: 0.32;
  cursor: default;
  pointer-events: none;
}

/* 扬声器图标：内联 SVG，用 currentColor 跟随主题，不引外部资源 */
.icon-sound {
  width: 20px;
  height: 20px;
  display: block;
  overflow: visible;
}

.icon-sound-body {
  fill: currentColor;
}

.icon-sound-wave {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
}

/* 静音斜杠默认隐藏，仅在 aria-pressed=true 时出现 */
.icon-sound-slash {
  stroke: var(--danger);
  stroke-width: 2;
  stroke-linecap: round;
  opacity: 0;
  transition: opacity 0.18s ease;
}

.icon-btn[aria-pressed="true"] {
  color: var(--text-2);
}

.icon-btn[aria-pressed="true"] .icon-sound-wave {
  opacity: 0.28;
}

.icon-btn[aria-pressed="true"] .icon-sound-slash {
  opacity: 1;
}

/* 背景音乐图标：内联 SVG，与扬声器图标同一模式（aria-pressed=true 显示斜杠=关闭） */
.icon-music {
  width: 20px;
  height: 20px;
  display: block;
  overflow: visible;
}

.icon-music-note {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.icon-music-dot {
  fill: currentColor;
}

.icon-music-slash {
  stroke: var(--danger);
  stroke-width: 2;
  stroke-linecap: round;
  opacity: 0;
  transition: opacity 0.18s ease;
}

.icon-btn[aria-pressed="true"] .icon-music-slash {
  opacity: 1;
}

/* 设置（滑块/调节）图标：内联 SVG，双轨 + 双旋钮，用 currentColor 跟随主题 */
.icon-gear {
  width: 20px;
  height: 20px;
  display: block;
  overflow: visible;
}

.icon-gear-track {
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
}

.icon-gear-knob {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
}

/* 暂停/播放图标：默认显示「暂停」双竖条，aria-pressed=true（已暂停）时切换为播放三角。
   与音效键同一模式：JS 只切 aria-pressed，图标显隐全交给 CSS。 */
.icon-pause {
  width: 20px;
  height: 20px;
  display: block;
  overflow: visible;
}

.icon-pause-bar {
  stroke: currentColor;
  stroke-width: 2.2;
  stroke-linecap: round;
  transition: opacity 0.18s ease;
}

.icon-pause-play {
  fill: currentColor;
  opacity: 0;
  transition: opacity 0.18s ease;
}

.icon-btn[aria-pressed="true"] .icon-pause-bar {
  opacity: 0;
}

.icon-btn[aria-pressed="true"] .icon-pause-play {
  opacity: 1;
}

/* ---------- 触屏方向键（D-pad） ----------
   仅在触屏设备显示（hover:none + pointer:coarse 双重判定，
   避免触屏笔记本同时满足 hover 而误隐藏）。
   绝对定位在舞台底部，不占据文档流，故不会把棋盘挤出视口。 */
.dpad {
  /* 放在 stage 之外的文档流里（见 HTML 结构），绝不能压住棋盘 ——
     canvas 的命中区域与视觉必须完全对应，压在上面会让底部几格点不到。 */
  width: 168px;
  height: 168px;
  margin: 0 auto;
  display: none;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 1fr);
  gap: 5px;
  /* 按钮响应 touchmove 才不会在滑动时连带滚动/缩放页面 */
  touch-action: none;
  /* 演示模式下方向键无意义（AI 接管），由 JS 加 is-hidden 隐藏 */
  flex-shrink: 0;
}

/* 触屏设备才显示方向键。必须位于 .dpad 基础规则之后：
   两者特异性相同(.dpad 为 0,1,0)，靠后者胜出 —— 写在前面会被基础规则里的
   display:none 覆盖，导致手机上按键完全不出现（我踩过：媒体查询 matched=true
   但 computed display 仍是 none）。
   用 hover:none + pointer:coarse 双条件：触屏笔记本同时满足 hover:hover，
   只用 pointer:coarse 会把它的实体键盘用户也一起藏掉。 */
@media (hover: none) and (pointer: coarse) {
  .dpad {
    display: grid;
  }
}

/* 演示中隐藏方向键。特异性 0,2,0 高于上面的 .dpad，故可稳定压过它。 */
.dpad.is-hidden {
  display: none;
}

.dpad-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--glass-stroke);
  border-radius: var(--radius-sm);
  background: var(--glass-bg);
  -webkit-backdrop-filter: var(--blur-glass);
  backdrop-filter: var(--blur-glass);
  color: var(--text-0);
  cursor: pointer;
  /* 半透明毛玻璃上的高光，延续整体质感 */
  box-shadow: var(--shadow-soft);
  -webkit-tap-highlight-color: transparent;
  touch-action: none;
  transition: background 0.12s ease, transform 0.12s ease;
}

.dpad-btn svg {
  width: 22px;
  height: 22px;
  fill: currentColor;
  pointer-events: none;
}

.dpad-btn:active {
  background: var(--glass-bg-strong);
  transform: scale(0.94);
}

.dpad-up    { grid-area: 1 / 2 / 2 / 3; }
.dpad-left  { grid-area: 2 / 1 / 3 / 2; }
.dpad-right { grid-area: 2 / 3 / 3 / 4; }
.dpad-down  { grid-area: 3 / 2 / 4 / 3; }

/* ---------- 游戏舞台 ---------- */
.stage {
  position: relative;
  width: 100%;
  /* 棋盘比例跟随设置（--board-aspect 由 JS 动态写入），保证棋盘铺满不留空；
     移动端媒体查询会以字面 1/1 覆盖此变量式声明 */
  aspect-ratio: var(--board-aspect, 4 / 3);
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: rgba(8, 12, 22, 0.55);
  border: 1px solid var(--glass-stroke);
  backdrop-filter: var(--blur-glass);
  -webkit-backdrop-filter: var(--blur-glass);
  box-shadow: var(--shadow-card), 0 0 0 1px rgba(0, 0, 0, 0.35);
}

/* 死亡瞬间的轻微镜头抖动，纯视觉反馈 */
.stage.is-dead {
  animation: shake 0.42s cubic-bezier(0.36, 0.07, 0.19, 0.97);
}

@keyframes shake {
  10%, 90% { transform: translate3d(-2px, 1px, 0); }
  30%, 70% { transform: translate3d(4px, -2px, 0); }
  50% { transform: translate3d(-6px, 2px, 0); }
}

.board {
  display: block;
  width: 100%;
  height: 100%;
  touch-action: none; /* 触屏滑动交给 JS 处理，禁止浏览器手势抢占 */
}

/* CRT 扫描线纹理，透明度极低，只加质感不加噪点 */
.scanlines {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: repeating-linear-gradient(
    to bottom,
    rgba(255, 255, 255, 0.028) 0px,
    rgba(255, 255, 255, 0.028) 1px,
    rgba(0, 0, 0, 0) 1px,
    rgba(0, 0, 0, 0) 3px
  );
  mix-blend-mode: overlay;
}

/* ---------- 遮罩 + 玻璃卡片 ---------- */
.overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: radial-gradient(120% 100% at 50% 0%, rgba(10, 16, 30, 0.72), rgba(4, 7, 14, 0.88));
  backdrop-filter: blur(10px) saturate(120%);
  -webkit-backdrop-filter: blur(10px) saturate(120%);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.28s ease, visibility 0.28s ease;
  z-index: 3;
}

/* 显示时 visibility 必须「立刻生效」——这是 H3 焦点失败的根因：
   base 规则里 visibility 也带 0.28s 过渡，而按 CSS 过渡规范 visibility 是离散插值，
   进度为 0（过渡刚创建的那一帧）取的是**起始值 hidden**，之后进度落入 (0,1) 才变 visible。
   于是「加 is-visible → 紧接着 focus()」时元素仍算 visibility:hidden，
   不可聚焦，focus() 静默失败；在过渡时钟不推进的环境（headless）里甚至会一直是 hidden。
   这里给 visibility 0s（时长为 0 不会生成过渡）→ 显示瞬间即 visible。
   隐藏方向仍走 base 的 0.28s，淡出效果不受影响。 */
.overlay.is-visible {
  opacity: 1;
  visibility: visible;
  transition: opacity 0.28s ease, visibility 0s;
}

.card {
  width: min(420px, 100%);
  max-height: 100%;
  overflow: auto;
  padding: 26px 24px 22px;
  text-align: center;
  border-radius: var(--radius-lg);
  background: linear-gradient(165deg, rgba(255, 255, 255, 0.11), rgba(255, 255, 255, 0.035));
  border: 1px solid var(--glass-stroke);
  backdrop-filter: var(--blur-glass);
  -webkit-backdrop-filter: var(--blur-glass);
  box-shadow: var(--shadow-card);
  transform: translateY(12px) scale(0.985);
  transition: transform 0.32s cubic-bezier(0.22, 1, 0.36, 1);
}

.card-sm {
  width: min(340px, 100%);
  padding: 24px 22px 20px;
}

.overlay.is-visible .card {
  transform: translateY(0) scale(1);
}

/* 设置面板层级高于演示横幅/停止按钮(z-index:4)，确保模态独占、不误触 */
#ov-settings {
  z-index: 5;
}

.card-kicker {
  font-size: 10px;
  letter-spacing: 3.2px;
  color: var(--accent);
  text-shadow: 0 0 16px rgba(47, 230, 168, 0.5);
}

.card-kicker.is-record {
  color: var(--accent-warm);
  text-shadow: 0 0 18px rgba(255, 182, 72, 0.6);
}

/* 通关态：金色庆祝配色，与失败态的青绿/死亡红形成区分 */
.overlay.is-win .card {
  border-color: rgba(255, 196, 84, 0.55);
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.55), 0 0 0 1px rgba(255, 196, 84, 0.25),
    0 0 60px rgba(255, 196, 84, 0.22);
}
.overlay.is-win .card-kicker,
.overlay.is-win .card-title {
  color: var(--accent-warm);
  text-shadow: 0 0 18px rgba(255, 182, 72, 0.6);
}

.card-title {
  font-size: 26px;
  font-weight: 700;
  letter-spacing: 1.5px;
  margin: 8px 0 10px;
}

.card-desc {
  font-size: 13px;
  line-height: 1.75;
  color: var(--text-1);
}

.keys {
  list-style: none;
  margin: 18px 0 4px;
  display: grid;
  gap: 8px;
  text-align: left;
}

.keys li {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--text-1);
}

.keys span {
  margin-left: 6px;
  color: var(--text-2);
}

kbd {
  min-width: 24px;
  height: 24px;
  padding: 0 6px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: inherit;
  font-size: 11px;
  color: var(--text-0);
  border-radius: 7px;
  background: rgba(255, 255, 255, 0.07);
  border: 1px solid rgba(255, 255, 255, 0.14);
  box-shadow: 0 2px 0 rgba(0, 0, 0, 0.35);
}

.kbd-wide {
  min-width: 58px;
  letter-spacing: 1px;
}

.result {
  margin: 16px 0 4px;
  display: grid;
  gap: 8px;
}

.result-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 14px;
  font-size: 12px;
  color: var(--text-1);
  border-radius: var(--radius-sm);
  background: rgba(255, 255, 255, 0.045);
  border: 1px solid rgba(255, 255, 255, 0.07);
}

.result-row b {
  font-size: 19px;
  font-variant-numeric: tabular-nums;
  color: var(--text-0);
}

.card-actions {
  margin-top: 20px;
  display: flex;
  gap: 10px;
  justify-content: center;
  flex-wrap: wrap;
}

.btn {
  appearance: none;
  border: 1px solid transparent;
  border-radius: 12px;
  padding: 11px 20px;
  font-family: inherit;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.6px;
  color: #04140d;
  cursor: pointer;
  transition: transform 0.14s ease, box-shadow 0.2s ease, background 0.2s ease;
}

.btn-primary {
  background: linear-gradient(140deg, #4ff5bd, #21c9d8);
  box-shadow: 0 10px 26px rgba(47, 230, 168, 0.3);
}

.btn-primary:hover {
  transform: translateY(-1px);
  box-shadow: 0 14px 32px rgba(47, 230, 168, 0.42);
}

.btn-primary:active {
  transform: translateY(1px);
}

.btn-ghost {
  background: rgba(255, 255, 255, 0.07);
  border-color: rgba(255, 255, 255, 0.14);
  color: var(--text-0);
}

.btn-ghost:hover {
  background: rgba(255, 255, 255, 0.12);
}

.btn:active {
  transform: translateY(1px);
}

.card-foot {
  margin-top: 14px;
  font-size: 11px;
  letter-spacing: 0.6px;
  color: var(--text-2);
}

.card-foot b {
  color: var(--accent-warm);
  font-variant-numeric: tabular-nums;
}

/* ---------- 暂停面板：本局进度对比条 ----------
   当前分 vs 该规格最高分。填色用蓝→绿渐变呼应 HUD 最高分(暖)与分数(绿)两端。 */
.progress {
  margin-top: 16px;
}

.progress-track {
  height: 10px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.07);
  border: 1px solid rgba(255, 255, 255, 0.08);
  overflow: hidden;
}

.progress-fill {
  height: 100%;
  width: 0%;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--accent-2), var(--accent));
  box-shadow: 0 0 12px rgba(47, 230, 168, 0.5);
  transition: width 0.4s ease;
}

.progress-text {
  margin-top: 8px;
  text-align: center;
  font-size: 11px;
  letter-spacing: 0.6px;
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
}

/* ---------- 结束页：本地图 Top5 排行榜 ---------- */
.lb {
  margin-top: 16px;
  padding: 12px 14px;
  border-radius: var(--radius-md);
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.07);
}

.lb-title {
  font-size: 11px;
  letter-spacing: 1.2px;
  color: var(--text-2);
  margin-bottom: 8px;
}

.lb-list {
  display: grid;
  gap: 6px;
}

.lb-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 10px;
  border-radius: var(--radius-sm);
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.05);
}

/* 本局分数所在行高亮，让玩家一眼看到自己排第几 */
.lb-row.is-current {
  background: rgba(47, 230, 168, 0.12);
  border-color: rgba(47, 230, 168, 0.4);
}

.lb-rank {
  width: 18px;
  text-align: center;
  font-size: 12px;
  font-weight: 700;
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
}

/* 第一名名次用暖色点一下，传统但不抢戏 */
.lb-row:first-child .lb-rank {
  color: var(--accent-warm);
}

.lb-val {
  margin-left: auto;
  font-size: 16px;
  color: var(--text-0);
  font-variant-numeric: tabular-nums;
}

.lb-row.is-current .lb-val {
  color: var(--accent);
}

.lb-empty {
  font-size: 11px;
  color: var(--text-2);
  text-align: center;
  padding: 8px 0;
}

/* ---------- 结束页：AI 演示统计（仅演示局显示） ---------- */
.demo-stats {
  margin-top: 12px;
  display: grid;
  gap: 8px;
}

/* 通用隐藏：演示统计 / 排行榜空态等按状态切换显隐 */
.is-hidden {
  display: none !important;
}

/* ---------- 页脚 ---------- */
.foot {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  flex-wrap: wrap;
  font-size: 12px;
  letter-spacing: 0.6px;
  /* 页脚是全站唯一落在底部暖光晕(.orb-c)上的文字，单独提亮一档做兜底。
     逐行亮度剖面实测：文字行背景 L=0.0053~0.0079（96% 像素落在该暗区），
     本色实测对比度 8.18:1（最严口径）/ 7.81:1（背景最亮处），达 AA 4.5:1；
     不改动全局 --text-2，避免连带拉平 .brand-sub/.keys span/.card-foot 的层次。
     与 --text-1 保留 0.0632 亮度差，层次不塌。 */
  color: #9aabc9;
}

.foot .dot {
  opacity: 0.5;
}

/* ---------- 设置面板 ---------- */
.card-settings {
  width: min(440px, 100%);
}

.settings-list {
  margin: 18px 0 4px;
  display: grid;
  gap: 16px;
  text-align: left;
}

.setting-row {
  display: grid;
  gap: 8px;
}

.setting-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
}

.setting-head label {
  font-size: 13px;
  color: var(--text-0);
  letter-spacing: 0.4px;
}

.setting-val {
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: var(--accent);
  text-shadow: 0 0 14px rgba(47, 230, 168, 0.4);
}

/* 自定义 range 滑杆：玻璃风轨道 + 霓虹旋钮 */
input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 6px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.12);
  border: 1px solid rgba(255, 255, 255, 0.12);
  outline: none;
  cursor: pointer;
}

input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: linear-gradient(140deg, #4ff5bd, #21c9d8);
  border: 1px solid rgba(255, 255, 255, 0.7);
  box-shadow: 0 0 0 4px rgba(47, 230, 168, 0.18), 0 4px 10px rgba(0, 0, 0, 0.4);
  transition: transform 0.12s ease;
}

input[type="range"]::-webkit-slider-thumb:active {
  transform: scale(1.12);
}

input[type="range"]::-moz-range-thumb {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: linear-gradient(140deg, #4ff5bd, #21c9d8);
  border: 1px solid rgba(255, 255, 255, 0.7);
  box-shadow: 0 0 0 4px rgba(47, 230, 168, 0.18), 0 4px 10px rgba(0, 0, 0, 0.4);
}

input[type="range"]::-moz-range-track {
  height: 6px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.12);
}

/* ---------- 恢复默认设置：按钮 / 行内提示 / 二次确认弹窗 ---------- */

/* 重置区：与底部「完成」主按钮之间用分割线 + 说明文案隔开。
   既保证显眼（不被当成隐藏高级选项），又避免与「完成」连排导致误触。 */
.settings-reset {
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--glass-stroke-soft);
  text-align: center;
}

.settings-reset-note {
  margin-top: 8px;
  font-size: 11px;
  line-height: 1.7;
  color: var(--text-2);
}

/* 重置按钮：幽灵底 + 危险色描边 —— 语义上「不是主操作」但足够显眼。
   min-height 44px：移动端最小可点击尺寸，避免和滑杆一起被误触。 */
.btn-danger-ghost {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  min-height: 44px;
  background: rgba(255, 93, 108, 0.12);
  border-color: rgba(255, 93, 108, 0.42);
  /* 半透明红底上实测对比度 7:1 以上；与项目青绿主色明确区分，不会被当成主按钮 */
  color: #ffb3ba;
}

.btn-danger-ghost:hover {
  background: rgba(255, 93, 108, 0.2);
}

/* 重置图标：内联 SVG 回环箭头，stroke 走 currentColor 跟随按钮文字色 */
.icon-reset {
  width: 15px;
  height: 15px;
  flex: none;
  display: block;
  overflow: visible;
}

.icon-reset-arc,
.icon-reset-arrow {
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* 行内提示：用 max-height 过渡做「展开 / 收起」，隐藏时不占任何空间，
   出现时也不会把下方「完成」按钮顶出可视区（比 display:none 少一次跳动）。 */
.settings-toast {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  max-height: 0;
  margin-top: 0;
  padding: 0 12px;
  overflow: hidden;
  opacity: 0;
  font-size: 12px;
  line-height: 1.6;
  letter-spacing: 0.3px;
  text-align: left;
  border-radius: var(--radius-sm);
  border: 1px solid rgba(47, 230, 168, 0);
  background: rgba(47, 230, 168, 0.12);
  color: var(--text-0);
  transition: max-height 0.26s ease, margin-top 0.26s ease, opacity 0.26s ease,
    padding 0.26s ease, border-color 0.26s ease;
}

.settings-toast.is-visible {
  max-height: 90px;
  margin-top: 12px;
  padding: 9px 12px;
  opacity: 1;
  border-color: rgba(47, 230, 168, 0.45);
}

/* 「已是默认」这类中性提示改用暖色，避免和「恢复成功」混淆 */
.settings-toast.is-info {
  background: rgba(255, 182, 72, 0.12);
  border-color: rgba(255, 182, 72, 0.45);
}

.toast-icon {
  width: 14px;
  height: 14px;
  flex: none;
  display: block;
  overflow: visible;
}

.toast-icon-ok path {
  fill: none;
  stroke: var(--accent);
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.toast-icon-info {
  display: none;
}

.toast-icon-info circle,
.toast-icon-info line {
  fill: none;
  stroke: var(--accent-warm);
  stroke-width: 2;
  stroke-linecap: round;
}

.settings-toast.is-info .toast-icon-ok {
  display: none;
}

.settings-toast.is-info .toast-icon-info {
  display: block;
}

/* 二次确认弹窗：fixed 定位脱离 .stage 的 overflow:hidden 与 max-height 约束，
   保证矮屏 / 横屏下也不被裁切；z-index 高于设置面板(5)以维持模态独占。 */
.overlay-modal {
  position: fixed;
  z-index: 40;
}

.card-confirm {
  text-align: center;
}

.card-confirm .card-title {
  font-size: 21px;
}

.confirm-warn {
  color: var(--danger);
}

/* 作用范围清单：把「重置什么 / 不重置什么」直接摆出来，
   避免玩家误以为最高分会跟着一起被清掉。 */
.confirm-scope {
  margin: 14px 0 2px;
  display: grid;
  gap: 8px;
  text-align: left;
}

.confirm-scope-title {
  font-size: 11px;
  letter-spacing: 1px;
  color: var(--text-2);
}

.confirm-list {
  list-style: none;
  display: grid;
  gap: 5px;
}

.confirm-list li {
  display: flex;
  align-items: flex-start;
  gap: 7px;
  font-size: 12px;
  line-height: 1.6;
  color: var(--text-1);
}

.confirm-list li::before {
  content: "";
  width: 6px;
  height: 6px;
  margin-top: 6px;
  flex: none;
  border-radius: 50%;
}

.confirm-list.is-reset li::before {
  background: var(--danger);
  box-shadow: 0 0 8px rgba(255, 93, 108, 0.6);
}

.confirm-list.is-keep li::before {
  background: var(--accent);
  box-shadow: 0 0 8px rgba(47, 230, 168, 0.6);
}

/* 危险操作按钮：红渐变 + 白字。最亮端 #d8324c 实测对比度 4.69:1（达 WCAG AA），
   与青绿主色强区分，不会和「主要操作」混淆。 */
.btn-danger {
  min-height: 44px;
  background: linear-gradient(140deg, #d8324c, #a8142c);
  color: #fff;
  box-shadow: 0 10px 26px rgba(255, 93, 108, 0.3);
}

.btn-danger:hover {
  transform: translateY(-1px);
  box-shadow: 0 14px 32px rgba(255, 93, 108, 0.42);
}

.card-kicker.is-danger {
  color: var(--danger);
  text-shadow: 0 0 18px rgba(255, 93, 108, 0.55);
}

/* 键盘可见焦点：outline 不占布局，不会影响既有排布 */
.btn-danger-ghost:focus-visible,
.card-confirm .btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ---------- 演示标识 + 停止按钮 ---------- */
.demo-banner {
  position: absolute;
  top: 14px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 4;
  padding: 6px 14px;
  font-size: 12px;
  letter-spacing: 1.2px;
  color: var(--text-0);
  border-radius: 999px;
  background: rgba(77, 139, 255, 0.18);
  border: 1px solid rgba(77, 139, 255, 0.5);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.35);
  backdrop-filter: var(--blur-glass);
  -webkit-backdrop-filter: var(--blur-glass);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.28s ease, visibility 0.28s ease;
  pointer-events: none;
}

.demo-stop {
  position: absolute;
  right: 14px;
  bottom: 14px;
  z-index: 4;
  padding: 9px 16px;
  font-family: inherit;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.6px;
  color: #fff;
  border-radius: 12px;
  border: 1px solid rgba(255, 93, 108, 0.6);
  background: rgba(255, 93, 108, 0.22);
  cursor: pointer;
  backdrop-filter: var(--blur-glass);
  -webkit-backdrop-filter: var(--blur-glass);
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.4);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.28s ease, visibility 0.28s ease, transform 0.14s ease, background 0.2s ease;
}

.demo-stop:hover {
  background: rgba(255, 93, 108, 0.36);
}

.demo-stop:active {
  transform: translateY(1px);
}

/* .stage.is-demo 时才展示横幅与停止按钮 */
.stage.is-demo .demo-banner,
.stage.is-demo .demo-stop {
  opacity: 1;
  visibility: visible;
}

/* ---------- 响应式 ---------- */
@media (max-width: 720px) {
  .app {
    width: calc(100% - 20px);
    padding: 16px 0 18px;
    gap: 12px;
  }

  /* 覆盖上方 .app 的简写 padding：否则这里的 16px/18px 会把安全区避让抹掉 */
  @supports (padding: max(0px)) {
    .app {
      padding-top: max(16px, env(safe-area-inset-top));
      padding-bottom: max(18px, env(safe-area-inset-bottom));
    }
  }

  .topbar {
    gap: 10px;
  }

  .brand-mark {
    width: 36px;
    height: 36px;
    border-radius: 11px;
  }

  .brand-mark::after {
    top: 10px;
    right: 9px;
  }

  .brand-title {
    font-size: 18px;
  }

  .brand-sub {
    font-size: 9.5px;
  }

  .hud {
    width: 100%;
    justify-content: space-between;
    padding: 6px;
  }

  .hud-cell {
    flex: 1;
    min-width: 0;
    padding: 5px 4px;
  }

  .hud-value {
    font-size: 15px;
  }

  /* 竖屏时棋盘太扁会挤，改为按高度约束比例。
     320x568 这类矮屏上，1:1 棋盘(≈300px) + 方向键(138px) + 顶栏 + 页脚
     会超过视口高度（实测 dh=656 > ih=568），故按视口高度给棋盘封顶。
     双声明降级：dvh（地址栏变化时正确）在前，vh 兜底在后覆盖。 */
  .stage {
    aspect-ratio: 1 / 1;
    max-height: calc(100vh - 250px);
    max-height: calc(100dvh - 250px);
  }

  .card {
    padding: 20px 16px 18px;
  }

  .card-title {
    font-size: 21px;
  }

  .card-desc {
    font-size: 12px;
  }

  .keys li {
    font-size: 11px;
  }

  .btn {
    padding: 10px 15px;
    font-size: 12px;
  }

  .foot {
    font-size: 11px;
  }
}

@media (max-width: 380px) {
  .hud-label {
    font-size: 9px;
    letter-spacing: 0.6px;
  }

  /* 矮屏（iPhone SE 320x568 这类）：纵向要同时装下顶栏 + 棋盘 + 方向键 + 页脚，
   默认排布会溢出（实测 scrollHeight 656 > innerHeight 568）。
   逐项压缩非游戏内容，把每一像素都让给棋盘与操作区。 */
@media (max-height: 700px) and (orientation: portrait) {
  .app {
    gap: 8px;
    padding-top: max(8px, env(safe-area-inset-top));
    padding-bottom: max(8px, env(safe-area-inset-bottom));
  }

  .topbar {
    gap: 6px;
  }

  .brand-mark {
    width: 28px;
    height: 28px;
    border-radius: 9px;
  }

  .brand-mark::after {
    top: 8px;
    right: 7px;
  }

  .brand-title {
    font-size: 15px;
  }

  /* 副标题在矮屏是纯装饰，直接隐藏（顶栏高度立刻降一行） */
  .brand-sub {
    display: none;
  }

  .hud {
    padding: 4px;
    gap: 4px;
  }

  /* 极窄竖屏：去掉 HUD 小标题行（label）直接降低 HUD 高度，把空间让给棋盘；
     value 强制单行不换行，配合 overflow:hidden 防止窄幅下文字折行把 HUD 撑高。
     数值信息（得分/最高/规格/速度）全部保留，仅不显示「得分」等小标题字。 */
  .hud-label { display: none; }
  .hud-value { white-space: nowrap; }
  .hud-cell { overflow: hidden; }
  .icon-btn { width: 34px; }

  .hud-value {
    font-size: 14px;
  }

  .foot {
    display: none;
  }

  .dpad {
    width: 132px;
    height: 132px;
  }
}

  .dpad-btn svg {
    width: 19px;
    height: 19px;
  }
}

/* 横屏时可用高度被压得很扁，方向键必须收窄，
   否则棋盘 + 方向键 + 顶栏一起超出视口，页面出现纵向滚动。 */
@media (orientation: landscape) and (max-height: 520px) {
  .dpad {
    width: 124px;
    height: 124px;
    gap: 4px;
  }

  .dpad-btn svg {
    width: 17px;
    height: 17px;
  }

  /* 横屏的核心矛盾：竖屏时「棋盘 1:1 + 方向键竖排」正好填满一屏，
     横过来后同样的排布会高出视口 500px 以上（实测 dh=921 vs ih=390）。
     解法：方向键移到棋盘右侧，两者并排 —— 竖向只剩「棋盘高度」一项，
     由 max-height 把它压进视口。 */
  .app {
    gap: 8px;
    padding-top: max(8px, env(safe-area-inset-top));
    padding-bottom: max(8px, env(safe-area-inset-bottom));
  }

  .stage,
  .dpad {
    display: none;   /* 先统一隐藏，下方按触屏与否分别恢复 */
  }

  .topbar .brand-sub {
    display: none;    /* 横屏本就窄，副标题是首个被挤没的内容 */
  }

  .foot {
    display: none;    /* 提示信息在横屏优先让位给可玩区域 */
  }
}

/* 横屏 + 触屏：棋盘与方向键并排 */
@media (orientation: landscape) and (max-height: 520px) and (hover: none) and (pointer: coarse) {
  .app {
    display: grid;
    grid-template-columns: 1fr auto;
    grid-template-areas:
      "topbar topbar"
      "stage  dpad";
    align-items: center;
  }

  .topbar {
    grid-area: topbar;
  }

  .stage {
    grid-area: stage;
    display: block;
    /* 横屏按宽度铺开，但高度必须压住，否则仍会溢出 */
    aspect-ratio: auto;
    /* 双声明：先给不支持 dvh 的旧浏览器兜底，再用 dvh 覆盖。
       dvh = 动态视口高度，地址栏收起/展开时会变，正是我们要的；
       vh 在移动端会偏大，导致按它算出的棋盘高过实际可视区。 */
    height: min(calc(100vh - 108px), 100vw);
    height: min(calc(100dvh - 108px), 100vw);
    max-height: calc(100vh - 108px);
    max-height: calc(100dvh - 108px);
  }

  .dpad {
    grid-area: dpad;
    display: grid;
    width: 120px;
    height: 120px;
  }
}

/* 横屏 + 非触屏（桌面窄窗口）：方向键不显示，棋盘独占并按高度约束 */
@media (orientation: landscape) and (max-height: 520px) and (hover: hover) {
  .app {
    display: block;
  }

  .stage {
    display: block;
    aspect-ratio: auto;
    height: min(calc(100vh - 108px), 100vw);
    height: min(calc(100dvh - 108px), 100vw);
    max-height: calc(100vh - 108px);
    max-height: calc(100dvh - 108px);
  }
}

/* 矮屏（横屏 844x390 这类）：确认弹窗必须整体压进视口，
   否则「取消 / 确认恢复」两个按钮会被顶到卡片滚动区外面、点不到。
   主要省高度的办法是把「将被重置」的 4 项排成两列。 */
@media (max-height: 520px) {
  .card-confirm {
    padding: 14px 14px 12px;
  }

  .card-confirm .card-title {
    font-size: 18px;
    margin: 6px 0 8px;
  }

  .card-confirm .card-desc {
    font-size: 12px;
    line-height: 1.6;
  }

  .confirm-scope {
    margin-top: 8px;
    gap: 4px;
  }

  .confirm-list {
    gap: 4px;
  }

  .confirm-list.is-reset {
    grid-template-columns: 1fr 1fr;
  }

  .card-confirm .card-actions {
    margin-top: 12px;
  }
}

/* 矮屏：设置卡片改成「头部 + 滑杆滚动区 + 常驻底部区」三段式布局。

   背景（缺陷 2）：320x568 下卡片可视区只有 256px、内容却有 516px，
   「恢复默认设置」按钮被挤到 top=486/bottom=529 —— 首屏完全看不见，必须下滑。
   而需求明确要求按钮放在「显眼」位置，首屏不可见就不算显眼。

   思路：把唯一可牺牲的滑杆区做成独立滚动区，头部与底部（重置按钮 + 完成）常驻，
   这样无论内容多高，重置按钮都稳定落在首屏。
   有富余高度时（如 375x667）滑杆区会被 flex 自动撑开，不会产生滚动，
   所以这个改动只在真正挤不下的时候才生效。

   断点沿用项目既有词汇：移动端 (max-width:720px) + 矮横屏 (max-height:520px)。
   - 不能只写 max-height:700px：那会把「1366x680 这类矮而宽的桌面窗口」也卷进来，
     而那种情况卡片其实很宽裕，属于无谓降级。
   - 也不能只写 max-height:700px + portrait：实测 390x844（当下最常见的手机尺寸）
     卡片可视区只有 326px、内容 477px，按钮同样掉到首屏外，光按高度判定会漏掉它。
     按项目既有的移动端断点（与 720px 以下棋盘改 1:1 是同一条线）判定才覆盖得住。 */
@media (max-width: 720px),
       (orientation: landscape) and (max-height: 520px) {
  /* 遮罩留白压到 8px，直接把这部分高度让给卡片 */
  #ov-settings {
    padding: 8px;
  }

  .card-settings {
    display: flex;
    flex-direction: column;
    overflow: hidden;       /* 卡片整体不再滚动，滚动交给 .settings-list */
    padding-top: 8px;
    padding-bottom: 8px;
  }

  /* 装饰性小标题与「即时生效」说明在矮屏让位：
     它们不参与操作，而滑杆、重置按钮、完成按钮都是必须露出来的。 */
  .card-settings .card-kicker,
  .card-settings .card-desc {
    display: none;
  }

  .card-settings .card-title {
    font-size: 16px;
    margin: 0;
  }

  .card-settings .settings-list {
    flex: 1 1 auto;
    /* 关键：flex 子项默认 min-height:auto，不置 0 它不会收缩、
       overflow-y 也就永远不会生效（滚动区会直接把卡片撑破） */
    min-height: 0;
    overflow-y: auto;
    /* 滑杆区滚到底时不要把滚动继续传给整页 */
    overscroll-behavior: contain;
    margin: 4px 0 0;
    gap: 8px;
    /* 给滑杆旋钮留一点余量，避免贴边被裁 */
    padding: 2px 2px 2px;
  }

  .card-settings .setting-row {
    gap: 3px;
  }

  /* 重置区与完成按钮是「必须常驻」的部分，禁止被 flex 压缩 */
  .card-settings .settings-reset,
  .card-settings .card-actions {
    flex: none;
  }

  .card-settings .settings-reset {
    margin-top: 4px;
    padding-top: 5px;
  }

  .card-settings .settings-reset-note {
    margin-top: 8px;
    font-size: 11px;
    line-height: 1.5;
  }

  /* 18px 不是随手定的：间距 = note 上边距 8 + note 一行 16.5 + 本值，
     要保证 844x390（note 只占一行）下「重置↔完成」仍 >= 40px 防误触。 */
  .card-settings .card-actions {
    margin-top: 18px;
  }
}

/* 矮屏横屏（844x390 这类）：高度极端紧缺、宽度却很富余，
   把滑杆排成两列 —— 4 项变 2 行，滚动区高度需求直接减半。 */
@media (orientation: landscape) and (max-height: 520px) {
  .card-settings .settings-list {
    grid-template-columns: 1fr 1fr;
    gap: 8px 14px;
  }
}

@media (prefers-reduced-motion: reduce) {
  /* .overlay.is-visible 也要列进来：它单独声明了 transition，
     特异性比 .overlay 高，不覆盖的话减弱动效对它无效 */
  .overlay,
  .overlay.is-visible,
  .card,
  .btn,
  .settings-toast,
  .icon-btn,
  .icon-sound-slash {
    transition: none;
  }

  .stage.is-dead {
    animation: none;
  }
}
