/* 个人站样式 */

/* ------------------------------ 令牌 ------------------------------ */
/* 站点只有深色一套 */
:root {
  color-scheme: dark;   /* 滚动条、表单控件这类原生 UI 也跟着变深 */

  --bg:         #0e1110;
  --surface:    #141817;
  --ink:        #ece9e2;
  --ink-soft:   #b5b8b3;
  --muted:      #a3a7a1;
  --line:       #272c2b;
  --edge:       #6d726b;   /* 有意义的控件边界（进度条未播段、输入框），对比度 >= 3:1 */
  --accent:     #63c9b7;
  --accent-ink: #0e1110;

  /* 毛玻璃：面板完全不带底色，只靠 backdrop-filter 把背后的东西糊掉。 */
  --glass:        transparent;
  --glass-line:   rgba(255, 255, 255, .18);
  --glass-hi:     rgba(255, 255, 255, .075);   /* 顶边高光，让玻璃有厚度 */
  --glass-halo:   rgba(0, 0, 0, .65);          /* 玻璃上文字的光晕，替代底色保可读性 */
  --glass-blur:   10px;   /* 模糊越小越"透"（看得见背后）；越大越干净但越像实心板 */
  --glass-shadow: 0 12px 32px -20px rgba(0, 0, 0, .85);   /* 浮在正文上面，要一点阴影才分得开 */

  /* 动态壁纸的纱罩：压在 <video> 上面，把画面压到文字能读的亮度。 */
  --veil:         rgba(14, 17, 16, .74);
  /* 开场遮罩只在"封面"那一屏用：那时没有任何正文需要压，可以让视频亮出来。 */
  --veil-intro:   rgba(14, 17, 16, .38);

  /* 玻璃面板内部用到的交互底色，必须是半透明的，不能糊一块实色上去 */
  --tint:         rgba(236, 233, 226, .08);
  --field:        rgba(14, 17, 16, .4);

  --r:    10px;
  --r-sm: 7px;
  /* 组件栏的宽度随视口伸缩：正文列是居中的固定宽度，固定宽度的组件栏在宽屏上 */
  --dock-w: clamp(360px, 50% - 200px, 470px);

  /* 组件栏从底部往上占多高（bottom + 栏高 + 呼吸）——栏里内容变了要同步改 */
  --dock-clear: 310px;

  /* 排版的两把尺子。--label-w 是"标签列"的宽度：碎碎念的日期、关于页的 dt 都用它。 */
  --label-w: 92px;
  --gap-col: 22px;           /* 标签列与正文列之间的距离 */

  --font-sans:  -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", "Yu Gothic UI", "Yu Gothic", "Meiryo", "Helvetica Neue", Arial, sans-serif;
  --font-serif: "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, "Songti SC", "STSong", "SimSun", serif;
  --font-mono:  "SF Mono", "Cascadia Mono", Consolas, "JetBrains Mono", ui-monospace, monospace;
  /* 花体：只为左下角那句装饰性的 Welcome 服务，全是系统字体、零依赖。 */
  --font-script: "Vivaldi", "Monotype Corsiva", "Lucida Calligraphy", "Edwardian Script ITC",
                 "Kunstler Script", "Palace Script MT", "Apple Chancery", "Snell Roundhand",
                 "Segoe Script", cursive;
}

/* ------------------------------ 基础 ------------------------------ */
*, *::before, *::after { box-sizing: border-box; }

/* [hidden] 必须真的藏住。 */
[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  /* 背景保持纯色不透明 —— 半透明只做在小组件和顶栏上 */
  background: var(--bg);
  color: var(--ink);
  font: 16px/1.68 var(--font-sans);
  -webkit-font-smoothing: antialiased;
  transition: background-color .2s ease, color .2s ease;
}

img { display: block; max-width: 100%; }
button { font: inherit; color: inherit; cursor: pointer; }

a {
  color: var(--accent);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}
a:hover { text-decoration-thickness: 2px; }

code {
  font-family: var(--font-mono);
  font-size: .875em;
  background: var(--tint);
  padding: .1em .35em;
  border-radius: 5px;
}

::selection { background: var(--accent); color: var(--accent-ink); }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }

.panel {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
}

/* ------------------------------ 动态壁纸 ------------------------------ */
/* 两层都放在负 z-index：根 stacking context 里负层级先于正文块绘制， */
.bgvideo {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: -2;
  pointer-events: none;
  background: var(--bg);        /* 视频没加载出来时也不露白 */
}
.veil {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: var(--veil);
}
/* 动态壁纸和纱罩都是纯装饰，不参与交互 */
.bgvideo,
.veil { user-select: none; }

/* 封面那一屏纱罩变薄，把视频亮出来；点掉之后再压回 --veil */
.veil { transition: background-color .8s ease; }
.js.is-intro .veil { background: var(--veil-intro); }

/* ------------------------------ 开场遮罩 ------------------------------ */
/* 默认不可见 —— 没有 JS 时封面必须消失（否则整站被一张点不掉的遮罩挡死）， */
.intro {
  position: fixed;
  inset: 0;
  z-index: 200;              /* 高于顶栏(60)和组件栏(50) */
  display: grid;
  place-items: center;
  text-align: center;
  visibility: hidden;
  opacity: 0;
  pointer-events: none;
  transition: opacity .6s ease, visibility 0s linear .6s;
}
.js.is-intro .intro {
  visibility: visible;
  opacity: 1;
  pointer-events: auto;
  transition: opacity .6s ease;
}

/* 整屏都是可点区域，用 button 换来自带的键盘可达性（Enter / Space 都能进站） */
.intro-go {
  display: block;
  padding: 22px 30px;
  background: none;
  border: 0;
  color: #fff;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.intro-go:focus-visible { outline: 2px solid rgba(255, 255, 255, .75); outline-offset: 6px; border-radius: 6px; }

.intro-title {
  display: block;
  font-family: var(--font-sans);      /* 明确要无衬线，所以不走标题的衬线栈 */
  font-weight: 300;
  font-size: clamp(34px, 8vw, 104px);
  line-height: 1.08;
  letter-spacing: .01em;
  color: #fff;
  text-shadow: 0 2px 26px rgba(0, 0, 0, .5);
}

.intro-hint {
  display: block;
  margin-top: 16px;
  font-family: var(--font-mono);
  font-size: 11.5px;
  letter-spacing: .34em;
  text-indent: .34em;                 /* 抵掉末字后面多出来的字距，视觉上才是居中 */
  color: rgba(255, 255, 255, .85);
  text-shadow: 0 1px 14px rgba(0, 0, 0, .6);
  animation: hint 2.6s ease-in-out infinite;
}
@keyframes hint {
  0%, 100% { opacity: .45; }
  50%      { opacity: .95; }
}

/* 开场的这一屏里，页面控件全部收起来；点掉封面后再"浮"出来。 */
.rail,
.dock,
.stage { transition: opacity .55s ease, transform .55s ease; }

.stage { transition-delay: .08s; }
.dock  { transition-delay: .2s; }
.rail  { transition-delay: .32s; }

.js.is-intro .rail,
.js.is-intro .dock,
.js.is-intro .stage {
  opacity: 0;
  visibility: hidden;        /* 顺便从无障碍树里摘掉，读屏不会念到被藏起来的控件 */
  pointer-events: none;
}
.js.is-intro .rail  { transform: translateY(16px); }
.js.is-intro .dock  { transform: translateY(16px); }
.js.is-intro .stage { transform: translateY(10px); }

/* ------------------------------ 右下角导航 ------------------------------ */
/* 三个图标竖排在右下角，鼠标悬停（或键盘聚焦）时向左"展开"出文字说明。 */
.rail {
  position: fixed;
  right: 24px;
  bottom: 24px;
  z-index: 60;
  display: flex;
  flex-direction: column;
  align-items: flex-end;     /* 展开时向左长，右边缘始终对齐 */
  gap: 8px;
}

/* 收起时正好是个圆：padding 13 + 图标 19 + padding 13 ≈ 45，圆角拉满 */
.rail-link {
  display: flex;
  align-items: center;
  height: 44px;
  padding: 0 13px;
  border-radius: 999px;
  background: var(--surface);
  border: 1px solid var(--line);
  color: var(--ink-soft);
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
  transition: color .18s ease, background-color .18s ease, border-color .18s ease;
}
.rail-link:hover,
.rail-link:focus-visible { color: var(--ink); background: var(--tint); }

.rail-ico { display: block; flex: none; line-height: 0; }

/* 展开原理：grid 的 0fr → 1fr 过渡，宽度会跟到文字的自然宽度。 */
.rail-txt {
  display: grid;
  grid-template-columns: 0fr;
  margin-left: 0;
  opacity: 0;
  transition: grid-template-columns .34s cubic-bezier(.22, .7, .3, 1),
              margin-left .34s cubic-bezier(.22, .7, .3, 1),
              opacity .2s ease;
}
.rail-txt > span {
  overflow: hidden;          /* 0fr 时把文字裁掉，收起状态才是真的"零宽" */
  white-space: nowrap;
  font-size: 14px;
  letter-spacing: .02em;
}

.rail-link:hover .rail-txt,
.rail-link:focus-visible .rail-txt {
  grid-template-columns: 1fr;
  margin-left: 9px;
  opacity: 1;
}

.rail-link.is-active,
.rail-link.is-active:hover,
.rail-link.is-active:focus-visible {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
}

/* 主题切换按钮已经去掉（站点只有深色一套），相关样式一并撤掉 */

/* ------------------------------ 内容区 ------------------------------ */

/* 只给读屏看的标题。小游戏页的报头按用户要求去掉了，但页面不能没有 h1 —— */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  border: 0;
  white-space: nowrap;
}

.stage {
  max-width: 760px;
  margin: 0 auto;
  padding: 80px 24px 470px;   /* 顶部不必再让开顶栏了（导航已挪到右下角） */
}

/* 首页的正文全删了，只剩一句铺满的英雄字 —— 上面那条 760px 的内容列对它没有意义， */
.js[data-route="home"] .stage {
  max-width: none;
  padding: 0;
}

/* ---------------------- 首页英雄字 ---------------------- */
/* 一句大号花体 Welcome，占视口左边三分之二：.hero 决定"地盘"，.hero-word 决定大小。 */
.hero {
  /* 用 svh 而不是 dvh：svh 是"浏览器工具栏全都在"时的最小高度， */
  min-height: 100vh;
  min-height: 100svh;
  width: 66.6667%;
  display: grid;
  place-items: center;
  padding: 24px 0 0;         /* 顶部留一点余量，矮窗口下字不至于贴到边 */
}

/* ≥1100px 时组件栏才浮在左下角，垂直居中会撞上去，所以为它预留底部空间； */
@media (min-width: 1100px) {
  .hero { padding-bottom: var(--dock-clear); }
}

/* 这个宽度下首页就是一屏落地：禁掉滚动。 */
@media (min-width: 1100px) and (min-height: 620px) {
  .js[data-route="home"] { overflow: hidden; }
}

.hero-word {
  margin: 0;
  font-family: var(--font-script);
  font-weight: 400;
  font-size: clamp(56px, 18.6vw, 380px);
  line-height: 1.1;
  letter-spacing: .01em;
  color: var(--ink);
  /* 字跨在视频上，光晕要够大才托得住细笔画 */
  text-shadow: 0 4px 60px var(--glass-halo), 0 1px 6px rgba(0, 0, 0, .45);
  padding: 0 .04em;          /* 花体收笔的连写会探出字身框，两侧留点位置 */
  user-select: none;
}

.js .view { display: none; }
.js .view.is-active {
  display: block;
  animation: rise .3s cubic-bezier(.22, .7, .3, 1) both;
}
@keyframes rise {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

.eyebrow {
  margin: 0 0 14px;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--muted);
}

/* 内容页的报头：上下各拉一条细线把它框住。 */
.mast {
  margin: 0 0 34px;
  padding: 12px 0 28px;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}
.mast .eyebrow { margin: 0 0 16px; }
.mast h1       { margin: 0 0 14px; }
.mast .lede    { margin: 0; }

h1 {
  margin: 0 0 18px;
  font-family: var(--font-serif);
  font-weight: 600;
  font-size: clamp(34px, 5.2vw, 50px);
  line-height: 1.14;
  letter-spacing: .005em;
  color: var(--ink);
  text-wrap: balance;        /* 中英混排时别把末尾两个字挤成一行孤字 */
}
/* 句号单独染薄荷绿。标题整体从薄荷绿改回墨白 —— */
h1 .dot { color: var(--accent); }
.hl { color: var(--accent); }

/* 小标题：走等宽栈、字号小、字距大 —— 靠"上方细线 + 留白"分层，不靠加大字号。 */
h2 {
  margin: 0 0 18px;
  font-family: var(--font-mono);
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: .14em;
  color: var(--ink-soft);
}

p { margin: 0 0 16px; }

/* 导语比正文亮一档、大一号 —— 层次靠字号和明度差出来。 */
.lede {
  margin: 0 0 18px;
  font-size: 17.5px;
  line-height: 1.62;
  color: var(--ink);
}
/* 正文可能不止一段。.body 本身 margin-bottom: 0（这样最后一段不会在 */
.body { margin-bottom: 0; color: var(--ink-soft); }
.body + .body { margin-top: 18px; }

.block {
  margin: 46px 0 0;
  padding-top: 24px;
  border-top: 1px solid var(--line);
}

/* 首页正文（连同「最近」列表 .mini-* / .more）已整体删除，只剩一句英雄字。 */

/* 定义列表：标签列宽度走全站统一的 --label-w，和碎碎念的日期列同宽 */
.facts { margin: 0; }
.facts > div {
  display: grid;
  grid-template-columns: var(--label-w) 1fr;
  gap: var(--gap-col);
  padding: 12px 0;
  border-bottom: 1px solid var(--line);
}
.facts > div:first-child { padding-top: 0; }
.facts > div:last-child { border-bottom: 0; }   /* 最后一行不留一条悬空的线 */
.facts dt {
  padding-top: 2px;
  font-family: var(--font-mono);
  font-size: 12.5px;
  letter-spacing: .04em;
  color: var(--muted);
}
.facts dd { margin: 0; font-size: 15px; line-height: 1.62; color: var(--ink-soft); }

/* ------------------------------ 社交账号按钮 ------------------------------ */
/* 图标用两家的官方 mark（内联 SVG，不引外链）。hover 反白成强调色， */
.social { display: flex; flex-wrap: wrap; gap: 10px; }

.social-btn {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 9px 16px 9px 14px;
  border: 1px solid var(--edge);
  border-radius: 999px;
  background: var(--tint);
  color: var(--ink);
  font-size: 13.5px;
  text-decoration: none;
  transition: color .2s ease, background-color .2s ease, border-color .2s ease;
}
.social-btn:hover {
  color: var(--accent-ink);
  background: var(--accent);
  border-color: transparent;
}
.social-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.social-ico { flex: none; }

/* 分享页：博客式列表。一条一篇，日期挂左边标签列（宽度走全站的 --label-w）， */
.post-list { margin: 0; }

.post {
  display: grid;
  grid-template-columns: var(--label-w) 1fr;
  gap: var(--gap-col);
  padding: 24px 0;
  border-bottom: 1px solid var(--line);
}
.post:first-child { padding-top: 4px; }
.post:last-child { border-bottom: 0; }        /* 收尾那一条线交给下面的页脚注 */

.post-side { display: flex; flex-direction: column; gap: 6px; }
.post-date {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 12.5px;
  letter-spacing: .03em;
  color: var(--muted);
  font-variant-numeric: tabular-nums;   /* 日期等宽，竖列才对得齐 */
}

.post-main { min-width: 0; }            /* 网格子项默认 min-width:auto，长英文会撑破 */

/* 标题走衬线 —— 和站里其它 h1/h2 一致，博客的"文章名"该有的分量 */
.post-title {
  margin: 0 0 8px;
  font-family: var(--font-serif);
  font-size: 19.5px;
  font-weight: 500;
  line-height: 1.38;
  color: var(--ink);
}
.post-title a {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: color .2s ease, border-color .2s ease;
}
.post-title a:hover { color: var(--accent); border-bottom-color: var(--accent); }
.post-title a:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.post-excerpt {
  margin: 0;
  font-size: 15px;
  line-height: 1.7;
  color: var(--ink-soft);
}

.post-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  margin: 11px 0 0;
  font-family: var(--font-mono);
  font-size: 11.5px;
  color: var(--muted);
}
.post-tags { color: var(--accent); }
.post-read { color: var(--muted); }
.post-out { color: var(--muted); }

/* 页脚注：和正文之间拉一条线，让它读起来是"注解"， */
.hint {
  margin: 40px 0 0;
  padding-top: 14px;
  border-top: 1px solid var(--line);
  font-family: var(--font-mono);
  font-size: 12.5px;
  line-height: 1.75;
  color: var(--muted);
}
.empty { padding: 16px 0; font-size: 14px; color: var(--muted); }

/* 注释：悬浮组件栏只在 ≥1100px 生效，见「响应式」一节 */
.dock {
  position: fixed;
  left: 24px;
  bottom: 24px;
  width: var(--dock-w);
  max-height: calc(100dvh - 110px);
  overflow: auto;
  overscroll-behavior: contain;
  display: flex;
  flex-direction: column;
  gap: 10px;
  z-index: 50;
}

.dock-row { display: flex; gap: 10px; align-items: stretch; }

/* 长条：时间 + 天气 */
.nowbar {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 11px 14px;
}

.clock { min-width: 0; }
.clock-time {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 23px;
  line-height: 1.05;
  letter-spacing: -.01em;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}
.clock-sec { margin-left: 4px; font-size: 12px; letter-spacing: .02em; color: var(--muted); }
.clock-date {
  margin: 5px 0 0;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: .02em;
  color: var(--muted);
  white-space: nowrap;
}

.wx {
  flex: none;
  display: grid;
  grid-template-columns: auto auto;
  align-items: center;
  gap: 1px 7px;
  justify-items: end;
}
.wx-ico { grid-column: 1; line-height: 0; color: var(--accent); }
.wx-temp { grid-column: 2; font-family: var(--font-mono); font-size: 16px; color: var(--ink); }
.wx-desc {
  grid-column: 1 / -1;
  font-size: 11.5px;
  color: var(--muted);
  white-space: nowrap;
}

/* ------------------------------ 小框：跳转按键 ------------------------------ */
/* 这里只放一个"去小游戏页"的按键，棋盘本体搬到 #view-game 了。 */
.jump {
  flex: 0 0 auto;
  width: 104px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 7px;
  padding: 10px 8px;
  color: var(--ink-soft);
  text-decoration: none;
  transition: color .2s ease, border-color .2s ease;
}
.jump-ico { display: block; color: var(--accent); }
.jump-ico svg { display: block; }
.jump-t {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: .02em;
  white-space: nowrap;
}
.jump:hover { color: var(--ink); border-color: var(--edge); }
.jump:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  color: var(--ink);
  border-color: var(--edge);
}

/* ------------------------------ 小游戏页 ------------------------------ */
/* 棋盘 10×20、每格 20px = 200×400（数值在 js/tetris.js 的 CELL / NCELL 里）。 */
.gamewrap {
  display: flex;
  flex-wrap: wrap;
  gap: 30px;
  align-items: flex-start;
}

.game {
  flex: none;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px;
}

.game-hud,
.game-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.game-name,
.game-lv {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: .03em;
  color: var(--muted);
  white-space: nowrap;
}
.game-lv { color: var(--ink-soft); }
.game-lv b { font-weight: 500; color: var(--accent); }

.game-stage { position: relative; }

#gBoard {
  display: block;
  border-radius: 5px;
  background: rgba(14, 17, 16, .42);   /* 棋盘底比面板再暗一档，格子线才读得出来 */
  outline: none;
  cursor: pointer;
  touch-action: none;                   /* 手机上在棋盘里滑动＝操作，别带着页面一起滚 */
}
#gBoard:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.game-cover {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 9px;
  border-radius: 5px;
  background: rgba(14, 17, 16, .76);
  text-align: center;
}
.game-cover[hidden] { display: none; }
.game-cover-t { margin: 0; font-size: 13px; color: var(--ink); }

.game-btn {
  padding: 6px 16px;
  border: 1px solid var(--edge);
  border-radius: 999px;
  background: var(--tint);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: 12.5px;
  cursor: pointer;
  transition: color .2s ease, background-color .2s ease, border-color .2s ease;
}
.game-btn:hover { color: var(--accent-ink); background: var(--accent); border-color: transparent; }
.game-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.game-score {
  overflow: hidden;
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--ink-soft);
  text-overflow: ellipsis;
  white-space: nowrap;
}
.game-score b { font-weight: 500; color: var(--accent); }
/* 尺寸由 js/tetris.js 的 fit() 按 NCELL 写内联样式，这里别写死，否则两边会打架 */
.game-next { display: block; flex: none; }

/* 按键操作提示。左边键位、右边动作，本来就是名值对，所以用 <dl> 而不是 <ul>。 */
.keys { flex: 1 1 300px; min-width: 240px; }
.keys h2 {
  margin: 0 0 12px;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .08em;
  color: var(--muted);
}
.keys h2 ~ .keylist { margin-bottom: 26px; }

.keylist { display: grid; gap: 10px; margin: 0; }
.keylist > div { display: flex; align-items: center; gap: 14px; }
.keylist dt { flex: none; display: flex; gap: 5px; width: var(--label-w); }
.keylist dd { margin: 0; font-size: 13.5px; color: var(--ink-soft); }

kbd {
  display: inline-block;
  min-width: 24px;
  padding: 4px 7px;
  border: 1px solid var(--line);
  border-bottom-color: var(--edge);
  border-radius: 5px;
  background: var(--tint);
  color: var(--ink);
  font-family: var(--font-mono);
  font-size: 11px;
  line-height: 1;
  text-align: center;
  white-space: nowrap;
}

.keys .hint { margin-top: 22px; }

@media (max-width: 720px) {
  .keylist dt { width: auto; min-width: 74px; }
}

/* ------------------------------ 播放器 ------------------------------ */
.player {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 14px;
}

.player-head { display: flex; align-items: center; gap: 12px; }

.cover {
  position: relative;
  flex: none;
  width: 52px;
  height: 52px;
  border-radius: 8px;
  overflow: hidden;
  background: var(--tint);
  border: 1px solid var(--line);
  color: var(--muted);
}
.cover-ph { position: absolute; inset: 0; margin: auto; }
.cover img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

.now { flex: 1 1 auto; min-width: 0; }
.now-title {
  margin: 0;
  font-size: 14.5px;
  font-weight: 500;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.now-artist {
  margin: 2px 0 0;
  font-family: var(--font-mono);
  font-size: 11.5px;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 播放器右上角的两个小按钮：先在网易云打开这个歌单、展开/收起播放列表 */
.pl-toggle,
.pl-src {
  flex: none;
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  background: transparent;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  color: var(--muted);
  text-decoration: none;
  transition: color .16s ease, border-color .16s ease, background-color .16s ease;
}
.pl-toggle:hover,
.pl-src:hover,
.pl-toggle[aria-expanded="true"] { color: var(--accent); border-color: var(--accent); }
.pl-src:hover { background: var(--tint); }

/* 三条横线收成一个叉：展开时上下两条向中线并拢再各转 ±45°，中间那条淡出让位。 */
.pl-ico path {
  transform-box: view-box;
  transform-origin: 12px 12px;
  transition: transform .32s cubic-bezier(.22, .7, .3, 1), opacity .18s ease;
}
.pl-toggle[aria-expanded="true"] .b1 { transform: translateY(5px) rotate(45deg); }
.pl-toggle[aria-expanded="true"] .b2 { opacity: 0; transform: scaleX(.35); }
.pl-toggle[aria-expanded="true"] .b3 { transform: translateY(-5px) rotate(-45deg); }

/* 进度条 / 音量条 */
.scrub { display: flex; flex-direction: column; gap: 5px; }

input[type="range"].seek {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 16px;
  margin: 0;
  background:
    linear-gradient(to right, var(--accent) var(--p, 0%), var(--edge) var(--p, 0%))
    center / 100% 3px no-repeat;
  cursor: pointer;
}
input[type="range"].seek:disabled { cursor: default; opacity: .55; }
input[type="range"].seek::-webkit-slider-runnable-track {
  height: 3px;
  border: 0;
  background: transparent;
}
input[type="range"].seek::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 12px;
  height: 12px;
  margin-top: -4.5px;
  border: 0;
  border-radius: 50%;
  background: var(--accent);
}
input[type="range"].seek::-moz-range-track {
  height: 3px;
  border: 0;
  border-radius: 2px;
  background: transparent;
}
input[type="range"].seek::-moz-range-thumb {
  width: 12px;
  height: 12px;
  border: 0;
  border-radius: 50%;
  background: var(--accent);
}
input[type="range"].seek:focus-visible { outline: none; }
input[type="range"].seek:focus-visible::-webkit-slider-thumb {
  box-shadow: 0 0 0 3px var(--line);
}

.times {
  display: flex;
  justify-content: space-between;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: .04em;
  color: var(--muted);
}

.controls { display: flex; align-items: center; gap: 8px; }

.ctrl {
  width: 32px;
  height: 32px;
  display: grid;
  place-items: center;
  padding: 0;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  color: var(--ink-soft);
  transition: color .16s ease, border-color .16s ease;
}
.ctrl:hover { color: var(--accent); border-color: var(--line); }

.ctrl.play {
  width: 38px;
  height: 38px;
  border: 0;
  border-radius: 50%;
  background: var(--accent);
  color: var(--accent-ink);
}
.ctrl.play:hover { opacity: .88; color: var(--accent-ink); border-color: transparent; }

.ico-pause { display: none; }
.player[data-playing="true"] .ico-play  { display: none; }
.player[data-playing="true"] .ico-pause { display: block; }

.vol {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: auto;
  flex: 0 1 116px;
  min-width: 78px;
}
.vol input { flex: 1 1 auto; min-width: 0; }
.vol-btn {
  flex: none;
  width: 22px;
  height: 22px;
  display: grid;
  place-items: center;
  padding: 0;
  background: none;
  border: 0;
  color: var(--muted);
}
.vol-btn:hover { color: var(--accent); }

/* ---------------------- 播放列表的展开 / 收起 ---------------------- */
/* .fold 只管高度：grid-template-rows 从 0fr 过渡到 1fr，高度会跟到内容的自然高度。 */
.fold {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows .38s cubic-bezier(.22, .7, .3, 1);
}
.fold.is-open { grid-template-rows: 1fr; }

/* .fold-body 是被"压扁"的那一项。 */
.fold-body {
  position: relative;
  min-height: 0;
  overflow: hidden;
  visibility: hidden;
  padding-top: 0;
  transition: visibility 0s linear .38s,
              padding-top .38s cubic-bezier(.22, .7, .3, 1);
}
.fold.is-open > .fold-body {
  visibility: visible;
  padding-top: 10px;
  transition: visibility 0s, padding-top .38s cubic-bezier(.22, .7, .3, 1);
}

/* 上边线用绝对定位画，不参与布局（border 会实打实占 1px）； */
.fold-body::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 1px;
  background: var(--line);
  opacity: 0;
  transition: opacity .3s ease;
}
.fold.is-open > .fold-body::before { opacity: 1; }

/* 内容比高度晚一点起跑：先让空间打开、字再浮上来。 */
.fold-body > * {
  opacity: 0;
  transform: translateY(-6px);
  transition: opacity .26s ease, transform .32s cubic-bezier(.22, .7, .3, 1);
}
.fold.is-open .fold-body > * {
  opacity: 1;
  transform: none;
  transition-delay: .1s;
}

.playlist { display: flex; flex-direction: column; gap: 8px; }

#plSearch {
  width: 100%;
  padding: 7px 10px;
  font: inherit;
  font-size: 13px;
  color: var(--ink);
  background: var(--field);
  border: 1px solid var(--edge);
  border-radius: var(--r-sm);
}
#plSearch::placeholder { color: var(--muted); }

.pl-list {
  position: relative;
  max-height: 168px;
  margin: 0;
  padding: 0;
  overflow: auto;
  overscroll-behavior: contain;
  list-style: none;
}

.pl-item {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 7px 8px;
  border-radius: 6px;
  font-size: 13px;
  color: var(--ink-soft);
  cursor: pointer;
  content-visibility: auto;
  contain-intrinsic-size: auto 32px;
}
.pl-item:hover { background: var(--tint); color: var(--ink); }
.pl-item.is-cur { background: var(--tint); color: var(--accent); }
.pi-name { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.pi-artist {
  flex: none;
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--muted);
}
.pl-empty {
  padding: 14px 8px;
  font-family: var(--font-mono);
  font-size: 12.5px;
  color: var(--muted);
}

/* ---------------------- 半透明玻璃 · 按页隐藏组件栏 ---------------------- */

/* 支持 backdrop-filter 就上玻璃效果；不支持的浏览器保持上面的不透明版本。 */
@supports ((backdrop-filter: blur(4px)) or (-webkit-backdrop-filter: blur(4px))) {
  .panel,
  .rail-link {
    background: var(--glass);          /* 透明：没有底色，只有模糊 */
    border-color: var(--glass-line);
    box-shadow: inset 0 1px 0 var(--glass-hi), var(--glass-shadow);
    /* 没有底色托着，文字对比度全靠"背后是什么"。给字补一圈极淡的光晕， */
    text-shadow: 0 1px 2px var(--glass-halo);
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(1.2);
    backdrop-filter: blur(var(--glass-blur)) saturate(1.2);
  }
}

/* 左下角那组小组件只在首页出现。碎碎念页和关于页整条收起来， */
.js:not([data-route="home"]) .dock { display: none; }

/* ------------------------------ 切页后的迷你播放条 ------------------------------ */
/* 只出现在首页以外，占的还是首页组件栏那个角 —— 读起来像"整条栏收成了一小条"。 */
.mini {
  position: fixed;
  left: 24px;
  bottom: 24px;
  z-index: 50;

  display: flex;
  align-items: center;
  gap: 10px;
  max-width: min(290px, calc(100vw - 108px));
  padding: 7px 9px 7px 7px;
  border: 1px solid var(--glass-line);
  border-radius: 999px;
  background: var(--glass);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(1.2);
  backdrop-filter: blur(var(--glass-blur)) saturate(1.2);
  box-shadow: 0 6px 22px var(--glass-halo);

  /* 显隐不走 display，走 visibility + opacity —— display 是切不出过渡的， */
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  /* 从组件栏那个角落长出来：origin 定在左下角，起点略小略低 */
  transform: translateY(14px) scale(.9);
  transform-origin: 0 100%;
  transition: opacity .3s ease,
              transform .34s cubic-bezier(.22, .7, .3, 1),
              visibility 0s linear .34s;
}

/* 只出现在首页以外。进、出两个方向都有过渡： */
.js:not([data-route="home"]) .mini {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transform: none;
  transition: opacity .34s ease,
              transform .4s cubic-bezier(.22, .7, .3, 1),
              visibility 0s;
}

/* 封面 + 歌名 + 竖条这一整块是"回首页"的链接；播放键在它外面， */
.mini-go {
  display: flex;
  flex: 1 1 auto;
  align-items: center;
  gap: 10px;
  min-width: 0;
  border-radius: 999px;
  color: inherit;
  text-decoration: none;
}
.mini-go:hover .mini-title { color: var(--accent); }
.mini-go:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.mini-cover {
  position: relative;
  flex: none;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  overflow: hidden;
  background: var(--tint);
  border: 1px solid var(--line);
  color: var(--muted);
}
.mini-ph { position: absolute; inset: 0; margin: auto; }
.mini-cover img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

.mini-text { display: flex; flex-direction: column; min-width: 0; line-height: 1.28; }
.mini-title,
.mini-artist {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.mini-title  { font-size: 12.5px; color: var(--ink); transition: color .2s ease; }
.mini-artist { font-size: 10.5px; color: var(--muted); }
.mini-artist:empty { display: none; }

/* 三根小竖条：在放的时候跳，暂停时沉成静止的短条。 */
.mini-bars { display: flex; flex: none; align-items: flex-end; gap: 2px; height: 13px; }
.mini-bars i {
  width: 2.5px;
  height: 4px;
  border-radius: 1px;
  background: var(--muted);
  animation: none;
}
.mini[data-playing="true"] .mini-bars i {
  background: var(--accent);
  animation: mini-eq .86s ease-in-out infinite;
}
.mini[data-playing="true"] .mini-bars i:nth-child(2) { animation-delay: .17s; }
.mini[data-playing="true"] .mini-bars i:nth-child(3) { animation-delay: .34s; }
@keyframes mini-eq {
  0%, 100% { height: 4px; }
  50%      { height: 13px; }
}

.mini-btn {
  flex: none;
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  padding: 0;
  border: 1px solid var(--edge);
  border-radius: 50%;
  background: var(--tint);
  color: var(--ink);
  cursor: pointer;
  transition: color .2s ease, background-color .2s ease, border-color .2s ease;
}
.mini-btn:hover { color: var(--accent-ink); background: var(--accent); border-color: transparent; }
.mini-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.mini .ico-pause { display: none; }
.mini[data-playing="true"] .ico-play  { display: none; }
.mini[data-playing="true"] .ico-pause { display: block; }

@media (prefers-reduced-motion: reduce) {
  .mini { transition: none; transform: none; }
  /* 不跳了，但用固定高度差把"在放"和"暂停"区分开 */
  .mini[data-playing="true"] .mini-bars i { animation: none; height: 11px; }
}

/* 碎碎念 / 关于页没有那组小组件，底部就不需要为它留白了。 */
.js:not([data-route="home"]) .stage { padding-bottom: 140px; }

/* 小游戏页的留白另外算：报头按用户要求去掉了（视觉全部让给棋盘）， */
.js:not([data-route="home"])[data-route="game"] .stage {
  padding: 40px 24px 96px;
}

/* ------------------------------ 响应式 ------------------------------ */

/* ≥1100px 时组件栏悬浮在左下角，正文**从它后面穿过去**，不再为它让出那一列。 */
@media (min-width: 1100px) {
  .stage { padding: 80px 24px 470px; }

  /* 宽屏下组件栏是 position:fixed，不占流式空间 —— 所以可以真的做过渡。 */
  .js:not([data-route="home"]) .dock {
    display: flex;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transform: translateY(12px) scale(.97);
    transform-origin: 0 100%;
    transition: opacity .3s ease,
                transform .36s cubic-bezier(.22, .7, .3, 1),
                visibility 0s linear .36s;
    transition-delay: 0s;
  }
}

/* 窄一点就把小组件栏放到正文下面，改成静态流式，彻底不会重叠 */
@media (max-width: 1099px) {
  .stage { padding: 72px 24px 28px; }
  /* 窄屏下这条迷你播放条也是固定的，占底部约 96px（48 高 + 24 边距）。 */
  .js:not([data-route="home"]) .stage { padding-bottom: 112px; }
  .dock {
    position: static;
    width: auto;
    max-width: 760px;
    max-height: none;
    overflow: visible;
    /* 底部留 88px：右下角导航是 fixed 的，滚到页面底部时它会压在组件栏右下角上， */
    margin: 10px auto 88px;
    padding: 0 24px;
  }
  .dock-row { flex-wrap: wrap; }
  .nowbar { flex: 1 1 220px; }
  .jump { flex: 1 1 auto; }
}

@media (max-width: 560px) {
  .rail { right: 14px; bottom: 14px; gap: 6px; }
  .rail-link { height: 40px; padding: 0 11px; }
  .facts > div { grid-template-columns: 1fr; gap: 2px; }
  .facts dt { padding-top: 0; }
  /* 窄屏放不下两列，标签回到正文上方 */
  .post { grid-template-columns: 1fr; gap: 8px; }
  .vol { flex: 0 1 96px; }
}

/* ------------------------------ 无障碍 / 打印 ------------------------------ */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    transition-delay: 0s !important;   /* 延迟也要归零，否则"入场错峰"会让人干等 .32 秒 */
  }
  .js .view.is-active { animation: none; }
}

@media print {
  .rail, .dock, .bgvideo, .veil, .intro { display: none !important; }
  .js .view { display: block !important; }
  .js.is-intro .stage { opacity: 1 !important; visibility: visible !important; }
  .stage { max-width: none; padding: 0; }
}
