/* =========================================================================
   Music · 聆听房间
   -------------------------------------------------------------------------
   Music is not a player. It is a room for listening.

   这一页不是播放器。没有旋转唱片、没有频谱、没有粒子、没有 glow。
   它是一份个人聆听档案：左边是编号，中间是封面、曲名、艺人、专辑、年份、
   时长，中间用细线分开。页面默认是灰的——把指针停在某一行上，那首歌才
   亮起来。这和 Gallery 的「灰度 → 彩色」是同一个语言，只是这里的「颜色」
   换成了注意力和可读性。

   颜色：整页灰阶。只有一个强调色 --m-accent（暖铜），且只在
   「这首歌正在响」的时候出现。颜色必须有语义，不是装饰。

   动效：全部可以在不改结构的前提下删掉。删掉之后页面依然成立。

   这一页不加载 shared.css，和 Gallery 一样自包含——理由同 gallery.css：
   它只有自己一个使用者，整份样式独立就没有「覆盖不全」的风险。
   色值沿用 gallery.css 的 --g-* 数值，两页视觉连续。

   播放：全程只有一个 <audio> 元素，切歌只换 src。
   结构上就不可能出现两个音频同时响。
   ========================================================================= */

:root {
  /* 与 gallery.css 同源，保证两页是同一个网站的两次呼吸 */
  --m-bg: #08080a;
  --m-fg: #f4f4f2;
  --m-soft: rgba(244, 244, 242, 0.6);
  --m-faint: rgba(244, 244, 242, 0.36);
  --m-ghost: rgba(244, 244, 242, 0.2);
  --m-line: rgba(244, 244, 242, 0.13);
  --m-line-2: rgba(244, 244, 242, 0.3);

  /* 唯一的强调色。只在「正在播放」时出现 */
  --m-accent: #c8a06a;

  --m-x: clamp(20px, 5.4vw, 104px);
  --m-gap: clamp(16px, 2.6vw, 44px);

  --m-ease: cubic-bezier(0.22, 0.68, 0.24, 1);
  --m-ease-out: cubic-bezier(0.16, 1, 0.3, 1);
}

/* ------------------------------------------------------------------ 基础 */

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

html {
  color-scheme: dark;
  background: var(--m-bg);
  scroll-behavior: auto; /* 交给 Lenis，浏览器不要再平滑一次 */
  scrollbar-gutter: stable; /* 聆听状态锁滚动时不会横向抖动 */
}

body.music-page {
  margin: 0;
  overflow-x: hidden;
  background: var(--m-bg);
  color: var(--m-fg);
  font-family: Inter, Geist, "HarmonyOS Sans SC", "Source Han Sans SC", "Noto Sans SC", "Microsoft YaHei", sans-serif;
  font-size: 16px;
  font-weight: 400;
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

body.music-page p,
body.music-page dl,
body.music-page dt,
body.music-page dd,
body.music-page h1,
body.music-page h2,
body.music-page ol,
body.music-page li,
body.music-page figure {
  margin: 0;
  padding: 0;
}

body.music-page ol {
  list-style: none;
}

img {
  display: block;
  max-width: 100%;
}

a {
  color: inherit;
  text-decoration: none;
}

button {
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  cursor: pointer;
}

::selection {
  background: var(--m-fg);
  color: var(--m-bg);
}

:focus-visible {
  outline: 1px solid var(--m-fg);
  outline-offset: 3px;
}

/* 聆听状态打开时锁住页面滚动 */
html.m-locked,
html.m-locked body {
  overflow: hidden;
}

.music-main,
.site-footer {
  position: relative;
  z-index: 2;
}

/* -------------------------------------------------------------- 滚动进度 */

.scroll-progress {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 120;
  height: 1px;
  pointer-events: none;
}

.scroll-progress span {
  display: block;
  height: 100%;
  background: var(--m-fg);
  transform: scaleX(0);
  transform-origin: left;
}

/* ---------------------------------------------------------------- 页头 */

.site-header {
  position: sticky;
  top: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 28px;
  padding: 20px var(--m-x);
  border-bottom: 1px solid transparent;
  background: color-mix(in srgb, var(--m-bg) 80%, transparent);
  backdrop-filter: blur(16px);
  transition: border-color 0.5s var(--m-ease), transform 0.55s var(--m-ease);
}

.site-header.is-scrolled {
  border-color: var(--m-line);
}

.site-header.is-hidden {
  transform: translateY(-101%);
}

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

.brand-mark {
  width: 38px;
  height: 38px;
  overflow: hidden;
  border: 1px solid var(--m-line);
  border-radius: 50%;
}

.brand-mark img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* 头像保持原色，与首页一致。这里原本是 filter: grayscale(1)，
     结果是同一个头像在首页有颜色、在内页是黑白的。
     注意：本页封套/圆盘的灰度是 .m-sleeve img 那条，不受影响。 */
}

.brand-name {
  display: block;
  font-size: 17px;
  font-weight: 600;
  line-height: 1.1;
}

.brand-note {
  display: block;
  color: var(--m-faint);
  font-size: 10px;
  letter-spacing: 0.16em;
  line-height: 1.5;
  text-transform: uppercase;
}

.navbar {
  display: flex;
  align-items: center;
  gap: clamp(14px, 2vw, 30px);
  min-width: 0;
}

.navbar a {
  position: relative;
  padding: 4px 0;
  color: var(--m-soft);
  font-size: 14px;
  white-space: nowrap;
  transition: color 0.4s var(--m-ease);
}

.navbar a::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: right;
  transition: transform 0.5s var(--m-ease-out);
}

.navbar a:hover,
.navbar a.active {
  color: var(--m-fg);
}

.navbar a:hover::after,
.navbar a.active::after {
  transform: scaleX(1);
  transform-origin: left;
}

/* ================================================================== 序章
   结构与 Gallery 的 hero 一致（四行网格 + 固定高度），这是刻意的：
   两页的进页节奏应该一样。但内容与重心不同——Gallery 的重心是照片，
   Music 的重心是那句话和它周围的大片空白。
   ==================================================================== */

.m-hero {
  display: grid;
  grid-template-rows: auto 1fr auto auto;
  row-gap: clamp(16px, 2.4vh, 32px);
  /* 比 Gallery 略矮，好让档案的第一行在首屏露出来 */
  min-height: clamp(400px, 58svh, 640px);
  padding: clamp(48px, 6.5vh, 100px) var(--m-x) clamp(14px, 2.2vh, 28px);
}

.eyebrow {
  color: var(--m-faint);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.18em;
  line-height: 1.4;
  text-transform: uppercase;
}

.m-title {
  align-self: center;
  max-width: 16em;
  font-size: clamp(32px, 5.6vw, 84px);
  font-weight: 400;
  line-height: 1.1;
  letter-spacing: -0.01em;
}

.m-title .line {
  display: block;
  overflow: hidden;
}

.m-title .line i {
  display: block;
  font-style: normal;
}

.hero-foot {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: end;
  gap: clamp(24px, 4vw, 72px);
}

.m-lead {
  max-width: 40em;
  color: var(--m-soft);
  font-size: clamp(14px, 1.15vw, 17px);
  line-height: 1.85;
}

.hero-spec {
  display: flex;
  gap: clamp(20px, 3vw, 52px);
}

.hero-spec dt {
  color: var(--m-ghost);
  font-size: 10px;
  letter-spacing: 0.16em;
  line-height: 1.6;
  text-transform: uppercase;
}

.hero-spec dd {
  margin-top: 6px;
  color: var(--m-fg);
  font-size: 13px;
  line-height: 1.4;
  white-space: nowrap;
}

.hero-scroll {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: var(--m-ghost);
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.hero-scroll i {
  display: block;
  width: 34px;
  height: 1px;
  background: currentColor;
  transform-origin: left;
  animation: m-scan 2.6s var(--m-ease) infinite;
}

.hero-scroll em {
  font-style: normal;
}

@keyframes m-scan {
  0% { transform: scaleX(0); opacity: 0; }
  35% { transform: scaleX(1); opacity: 1; }
  70% { transform: scaleX(1); opacity: 1; }
  100% { transform: scaleX(1); opacity: 0; }
}

/* ============================================================ 展示台
   Archive 是索引，这里是舞台：索引回答「我有哪些音乐」，舞台回答
   「我现在正在看哪一张」。

   它钉在顶部，账本从它下面滚过去——索引在动，舞台不动。这样悬停
   第 7 行时舞台就在视野里，不必来回滚动。钉的范围由 .m-rail 决定，
   所以它到账本结束就松开，不会一路钉到结束语上去。

   物件是桌上的一张唱片，不是 3D 卡片：正方形封套 + 从背后滑出的
   圆盘 + 落在隐含平面上的影。没有做封套的厚度面——rotateY 只有
   ±5°，画出侧面也看不见，那点实体感交给圆盘和影去做，不硬凑。

   背景必须不透明：账本要从它后面经过。
   ==================================================================== */

.m-rail {
  position: relative;
}

/* 展示台已经把账本和序章分开了，账本自己那道 130px 的顶距就成了双份留白 */
.m-rail .m-archive {
  padding-top: clamp(24px, 3.4vh, 46px);
}

.m-showcase {
  position: sticky;
  top: 0;
  z-index: 40;
  background: var(--m-bg);
  /* 顶距必须高过页头（实测 79px）。页头向下滚时收起，向上滚时回来——
     回来的时候展示台还钉在 top:0，两者重叠的那几像素会正好切在
     「Now showing」的上沿上。多留的这点就是给它让位的。 */
  padding: clamp(72px, 9.2vh, 92px) var(--m-x) clamp(20px, 2.8vh, 34px);
}

.m-showcase-inner {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--m-gap);
  align-items: center;
}

.m-stage {
  grid-column: 1 / span 5;
}

.m-stage-label {
  margin-bottom: clamp(12px, 1.8vh, 20px);
}

/* ---------------------------------------------------------- 唱片物件 */

.m-object {
  position: relative;
  display: block;
  width: clamp(140px, 12vw, 186px);
  aspect-ratio: 1;
  perspective: 1000px;
  /* 状态阶梯：静止 5% → 被选中 15% → 正在响 23%
     圆盘探出的是自己的宽度百分比，所以这个数字就是「抽出多少」 */
  --dx: 5%;
  --dy: 1.5%;
  /* 入场幅度按 brief 走：rotateX ±3°、rotateY ±5°、scale 1.00–1.04。
     再大就不是「桌上的一张唱片」，是炫技了。 */
  --osc: 1;
}

.m-object.is-live { --dx: 15%; --dy: 3%; --osc: 1.02; }
.m-object.is-playing { --dx: 23%; --dy: 4.5%; --osc: 1.035; }

.m-object-stage {
  position: absolute;
  inset: 0;
  display: block;
  transform-style: preserve-3d;
  transform: rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg)) scale(var(--osc));
  transition: transform 0.8s var(--m-ease-out);
}

/* 视差要跟手，所以指针停在唱片上时换成短过渡；
   指针离开时这条被去掉，回正走的是上面那条 0.8s ——
   于是它慢慢归位，不是弹回去。 */
.m-object.is-tilting .m-object-stage {
  transition-duration: 0.16s;
}

/* 影：让物件落在某个平面上。深背景上「影子」不是黑块，是更深一档 */
.m-object-shadow {
  position: absolute;
  left: 8%;
  right: -10%;
  bottom: -6%;
  height: 9%;
  border-radius: 50%;
  background: #000;
  filter: blur(13px);
  opacity: 0.9;
  pointer-events: none;
}

/* 封套：正面。默认近黑白，被选中才恢复原色——
   和档案行的 hover 是同一件事，不是第二套语言 */
.m-sleeve {
  position: absolute;
  inset: 0;
  display: block;
  overflow: hidden;
  background: rgba(244, 244, 242, 0.04);
  border: 1px solid var(--m-line);
  transform: translateZ(0);
}

.m-sleeve img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(1) brightness(0.55) contrast(1.06);
  transition: filter 0.7s var(--m-ease);
}

.m-object.is-live .m-sleeve img,
.m-object.is-playing .m-sleeve img {
  filter: grayscale(0) brightness(1) contrast(1);
}

/* 圆盘：从封套背后滑出来。
   偏移在 .m-disc 上，旋转在内层 .m-disc i 上——两个 transform 必须
   属于两个元素，放一起会互相覆盖（Gallery 的视差层/缩放层同理）。 */
.m-disc {
  position: absolute;
  inset: 0;
  display: block;
  border-radius: 50%;
  overflow: hidden;
  background: radial-gradient(circle at 36% 30%, #1b1b20 0%, #101014 46%, #09090c 100%);
  box-shadow:
    inset 0 0 0 1px rgba(244, 244, 242, 0.09),
    0 16px 34px -16px rgba(0, 0, 0, 0.95);
  transform: translate3d(var(--dx), var(--dy), -14px);
  transition: transform 0.9s var(--m-ease-out);
}

.m-disc i {
  position: absolute;
  inset: 0;
  display: block;
  border-radius: 50%;
  /* 一道偏心的掠光 + 中心孔 + 标签环 + 极细的同心沟槽。
     掠光不对称，所以转起来看得见；沟槽是唱片的实体纹理，不是装饰纹样 */
  background:
    conic-gradient(from 0deg,
      rgba(244, 244, 242, 0) 0deg,
      rgba(244, 244, 242, 0.06) 56deg,
      rgba(244, 244, 242, 0) 98deg,
      rgba(244, 244, 242, 0) 360deg),
    radial-gradient(circle at 50% 50%, var(--m-bg) 0 5.5%, rgba(244, 244, 242, 0.07) 5.5% 6.2%, transparent 6.2%),
    radial-gradient(circle at 50% 50%, transparent 0 27%, rgba(244, 244, 242, 0.05) 27% 27.7%, transparent 27.7%),
    repeating-radial-gradient(circle at 50% 50%, rgba(244, 244, 242, 0.022) 0 1px, transparent 1px 4px);
  animation: m-spin 26s linear infinite;
  /* 不转的时候是「停住」，不是「回到原点」——
     暂停播放时唱片不该弹回起始角度 */
  animation-play-state: paused;
}

@keyframes m-spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

/* 只有真的在响才转。暂停是「停住」，不是「回到原点」——
   animation-play-state 让角度留在原地，符合「暂停」这个词的字面意思。
   不播放时唱片一直转是不对的：那会让「正在响」这件事失去唯一的信号。 */
.m-object.is-playing .m-disc i {
  animation-play-state: running;
}

/* ------------------------------------------------------------ 舞台文字
   这几个选择器必须带 body.music-page 前缀：重置写的是
   body.music-page h2 / dl / p（特异性 0,1,2），裸类名（0,1,0）压不过它，
   margin 会被吃掉。V1 的 .listening-facts 就踩了这个坑。          */

.m-showcase-meta {
  grid-column: 7 / span 6;
  min-width: 0;
}

.m-showcase-counter {
  color: var(--m-ghost);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.16em;
}

body.music-page .m-showcase-title {
  margin-top: 12px;
  color: var(--m-fg);
  font-size: clamp(22px, 2.6vw, 38px);
  font-weight: 400;
  line-height: 1.16;
  letter-spacing: -0.01em;
}

body.music-page .m-showcase-facts {
  display: flex;
  flex-wrap: wrap;
  gap: 6px clamp(18px, 2.6vw, 40px);
  margin-top: clamp(16px, 2.4vh, 26px);
  padding-top: clamp(14px, 2vh, 22px);
  border-top: 1px solid var(--m-line);
}

.m-showcase-facts dt {
  color: var(--m-ghost);
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.m-showcase-facts dd {
  margin-top: 5px;
  color: var(--m-soft);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
}

body.music-page .m-showcase-hint {
  margin-top: clamp(14px, 2vh, 20px);
  color: var(--m-ghost);
  font-size: 12px;
  line-height: 1.7;
}

.hint-coarse { display: none; }

/* 触屏没有 hover，提示语得说点按的规则；判断依据是指针类型，不是宽度 */
@media (pointer: coarse) {
  .hint-fine { display: none; }
  .hint-coarse { display: inline; }
}

/* 换一首时的极短淡入。真正的反馈是封面变色和圆盘滑出，
   这里只负责让文字不是硬切。 */
.m-showcase-meta.is-swapping {
  animation: m-swap 0.3s var(--m-ease-out);
}

@keyframes m-swap {
  from { opacity: 0.25; }
  to { opacity: 1; }
}

/* ============================================================ 聆听档案
   Archive 不是卡片瀑布流，是一本账：编号、封面、曲名、艺人、专辑、
   年份、时长，七列对齐，一行一首，中间用细线分隔。

   视觉节奏不做随机偏移——随机的对立面是「不该对齐的地方才不对齐」。
   这里不对齐的地方是两处、且都有理由：
     · 第 1 行（1980，档案里最早的一首）封面与曲名放大，作为开场
     · 第 10 行（2024，最新的一首）整行拉宽，作为收束
   其余 8 行严格同构。这是书挡，不是撒点。
   ==================================================================== */

.m-archive {
  padding: clamp(56px, 9vh, 130px) var(--m-x) clamp(48px, 8vh, 110px);
}

.m-archive-head {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--m-gap);
  margin-bottom: clamp(28px, 5vh, 64px);
}

.m-archive-head .eyebrow {
  grid-column: 1 / span 2;
}

.m-archive-note {
  grid-column: 4 / span 6;
  color: var(--m-soft);
  font-size: 14px;
  line-height: 1.8;
}

.m-archive-note b {
  color: var(--m-fg);
  font-weight: 400;
}

/* 列标题：像杂志表格的抬头，不是导航 */
.m-labels {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--m-gap);
  padding-bottom: 10px;
  border-bottom: 1px solid var(--m-line);
}

.m-labels span {
  color: var(--m-ghost);
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

/* 抬头的七列必须和每一行的七列逐列对齐，否则这个表头就是假的 */
.m-labels > span:nth-child(1) { grid-column: 1 / span 1; }
.m-labels > span:nth-child(2) { grid-column: 2 / span 1; }
.m-labels > span:nth-child(3) { grid-column: 3 / span 4; }
.m-labels > span:nth-child(4) { grid-column: 7 / span 2; }
.m-labels > span:nth-child(5) { grid-column: 9 / span 2; }
.m-labels > span:nth-child(6) { grid-column: 11 / span 1; }
.m-labels > span:nth-child(7) { grid-column: 12 / span 1; justify-self: end; }

/* --------------------------------------------------------------- 行 */

.m-row {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--m-gap);
  align-items: center;
  position: relative;
  width: 100%;
  padding: clamp(16px, 1.9vh, 24px) 0;
  border-bottom: 1px solid var(--m-line);
  text-align: left;
  transition: border-color 0.5s var(--m-ease);
}

.m-row:hover {
  border-bottom-color: var(--m-line-2);
}

/* 列位置：桌面是七列一行 */
.m-row > .c-num { grid-column: 1 / span 1; }
.m-row > .c-art { grid-column: 2 / span 1; }
.m-row > .c-title { grid-column: 3 / span 4; }
.m-row > .c-artist { grid-column: 7 / span 2; }
.m-row > .c-album { grid-column: 9 / span 2; }
.m-row > .c-year { grid-column: 11 / span 1; }
.m-row > .c-time { grid-column: 12 / span 1; justify-self: end; }

.c-num,
.c-art,
.c-title,
.c-artist,
.c-album,
.c-year,
.c-time {
  min-width: 0;
}

/* 编号：档案的骨架，字重很轻，颜色很淡，只在被注意时亮 */
.c-num {
  color: var(--m-ghost);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.06em;
  transition: color 0.5s var(--m-ease);
}

/* 封面：与 Gallery 完全同一套语言——默认近黑白，被注意时才恢复原色 */
.c-art {
  display: block;
  /* 封面是标记，不是内容本身——所以它比所在的列窄，
     并且随行的重要性分三级：普通 58 / 开场 72 / 收束 108（1440 下） */
  width: clamp(48px, 4vw, 64px);
  aspect-ratio: 1;
  overflow: hidden;
  background: rgba(244, 244, 242, 0.04);
  border: 1px solid var(--m-line);
  transition: border-color 0.5s var(--m-ease);
}

.c-art img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(1) brightness(0.55) contrast(1.06);
  transform: scale(1.001);
  transition: filter 0.65s var(--m-ease), transform 0.75s var(--m-ease);
}

.c-title {
  display: block;
  color: var(--m-soft);
  font-size: clamp(15px, 1.35vw, 20px);
  line-height: 1.35;
  transition: color 0.5s var(--m-ease);
}

.c-title > span {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.c-artist,
.c-album {
  display: block;
  color: var(--m-faint);
  font-size: 12.5px;
  line-height: 1.5;
  transition: color 0.5s var(--m-ease);
}

.c-artist > span,
.c-album > span {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.c-year,
.c-time {
  color: var(--m-ghost);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.04em;
  transition: color 0.5s var(--m-ease);
}

/* ---- 悬停：只做两件事。曲名与封面。
        这是 Gallery「照片恢复彩色」的对应物，核心感觉是
        「这首歌被注意到了」，不是「这个网页用了很多 CSS 动画」。 ---- */

.m-row:hover .c-title,
.m-row:focus-visible .c-title {
  color: var(--m-fg);
}

.m-row:hover .c-artist,
.m-row:hover .c-album,
.m-row:focus-visible .c-artist,
.m-row:focus-visible .c-album {
  color: var(--m-soft);
}

.m-row:hover .c-num,
.m-row:hover .c-year,
.m-row:hover .c-time,
.m-row:focus-visible .c-num,
.m-row:focus-visible .c-year,
.m-row:focus-visible .c-time {
  color: var(--m-faint);
}

.m-row:hover .c-art,
.m-row:focus-visible .c-art {
  border-color: var(--m-line-2);
}

.m-row:hover .c-art img,
.m-row:focus-visible .c-art img {
  filter: grayscale(0) brightness(1) contrast(1);
  transform: scale(1.045);
}

/* ---- 正在响的那一首：唯一的强调色出现在这里 ---- */

.m-row.is-playing {
  border-bottom-color: color-mix(in srgb, var(--m-accent) 55%, transparent);
}

.m-row.is-playing .c-num,
.m-row.is-playing .c-title,
.m-row.is-playing .c-year,
.m-row.is-playing .c-time {
  color: var(--m-accent);
}

.m-row.is-playing .c-art {
  border-color: color-mix(in srgb, var(--m-accent) 45%, transparent);
}

.m-row.is-playing .c-art img {
  filter: grayscale(0) brightness(1) contrast(1);
}

/* 停止后仍留在房间里：封面与曲名保持可读，但不占用强调色 */
.m-row.is-current .c-title {
  color: var(--m-fg);
}

.m-row.is-current .c-art img {
  filter: grayscale(0) brightness(0.92) contrast(1);
}

/* ---- 两处刻意的体量变化 ---- */

.m-row.is-open {
  padding-top: clamp(20px, 2.6vh, 34px);
  padding-bottom: clamp(20px, 2.6vh, 34px);
}

.m-row.is-open > .c-art {
  width: clamp(56px, 5vw, 76px);
}

.m-row.is-open > .c-title {
  font-size: clamp(18px, 1.9vw, 28px);
}

.m-row.is-wide {
  padding-top: clamp(24px, 3.4vh, 46px);
  padding-bottom: clamp(24px, 3.4vh, 46px);
}

.m-row.is-wide > .c-art {
  grid-column: 2 / span 2;
  width: clamp(72px, 7.5vw, 118px);
}

.m-row.is-wide > .c-title {
  grid-column: 4 / span 4;
  font-size: clamp(20px, 2.4vw, 36px);
}

.m-row.is-wide > .c-artist { grid-column: 8 / span 3; }
.m-row.is-wide > .c-album { grid-column: 11 / span 2; }

/* 拉宽的行放不下 12 列的年份与时长，让它们落到第二行 */
.m-row.is-wide > .c-year { grid-column: 8 / span 1; grid-row: 2; justify-self: start; }
.m-row.is-wide > .c-time { grid-column: 9 / span 1; grid-row: 2; justify-self: start; }

.m-row.is-wide > .c-num { align-self: start; }

.m-archive-foot {
  margin-top: clamp(20px, 3vh, 36px);
  color: var(--m-ghost);
  font-size: 12px;
  line-height: 1.8;
}

/* ---------------------------------------------------------------- 结束语 */

.m-endnote {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--m-gap);
  row-gap: 22px;
  padding: clamp(56px, 9vh, 130px) var(--m-x) clamp(72px, 11vh, 150px);
  border-top: 1px solid var(--m-line);
}

.m-endnote .eyebrow {
  grid-column: 1 / span 2;
}

.m-endnote p {
  grid-column: 4 / span 6;
  color: var(--m-soft);
  font-size: 14px;
  line-height: 1.9;
}

.link-underline {
  position: relative;
  display: inline-block;
  padding-bottom: 3px;
  color: var(--m-fg);
  font-size: 13px;
}

.link-underline::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 1px;
  background: currentColor;
  transform-origin: right;
  transition: transform 0.5s var(--m-ease-out);
}

.link-underline:hover::after {
  transform: scaleX(0);
  transform-origin: left;
}

.m-endnote .link-underline {
  grid-column: 4 / span 6;
  justify-self: start;
}

/* ---------------------------------------------------------------- 页脚 */

.site-footer {
  display: flex;
  justify-content: space-between;
  gap: 24px;
  padding: 34px var(--m-x);
  border-top: 1px solid var(--m-line);
  color: var(--m-faint);
  font-size: 12px;
}

.site-footer a {
  color: inherit;
  transition: color 0.3s var(--m-ease);
}

.site-footer a:hover {
  color: var(--m-fg);
}

/* ========================================================== 聆听状态
   对应 Gallery 的 View State：整屏只服务一首歌。
   结构也照搬（顶部 / 舞台 / 底部），因为那是这个网站「进入某一件东西」
   的固定姿势。区别是这里多了传输控件——Gallery 不需要，音乐需要。
   ==================================================================== */

.listening {
  position: fixed;
  inset: 0;
  z-index: 130;
  display: none;
  grid-template-rows: auto 1fr auto auto;
  row-gap: clamp(14px, 2.4vh, 30px);
  padding: clamp(16px, 2.4vh, 30px) var(--m-x) clamp(16px, 3vh, 34px);
  background: var(--m-bg);
}

.listening.is-open {
  display: grid;
}

.listening-bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(
    120% 90% at 50% 0%,
    rgba(244, 244, 242, 0.035) 0%,
    rgba(8, 8, 10, 0) 60%
  );
}

/* 必须排掉 .listening-bg：它是绝对定位的底纹，一旦被这条规则改成
   position: relative 就会变成一个真实的网格单元，把四行结构顶掉。
   用 :not() 而不是指望书写顺序，改顺序时不会再踩一次。 */
.listening > :not(.listening-bg) {
  position: relative;
  z-index: 1;
}

.listening-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
}

.listening-tag {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: var(--m-faint);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}

/* 三根极细的竖线，只在真正出声时起伏。不是频谱，是「在响」 */
.m-pulse {
  display: inline-flex;
  align-items: flex-end;
  gap: 2px;
  height: 11px;
}

.m-pulse i {
  display: block;
  width: 1px;
  height: 100%;
  background: var(--m-ghost);
  transform-origin: bottom;
  transition: background 0.4s var(--m-ease);
}

.listening.is-sounding .m-pulse i {
  background: var(--m-accent);
  animation: m-pulse 1.5s var(--m-ease) infinite;
}

.listening.is-sounding .m-pulse i:nth-child(2) { animation-delay: 0.24s; }
.listening.is-sounding .m-pulse i:nth-child(3) { animation-delay: 0.48s; }

@keyframes m-pulse {
  0% { transform: scaleY(0.3); }
  45% { transform: scaleY(1); }
  100% { transform: scaleY(0.3); }
}

.listening-close {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: var(--m-soft);
  font-size: 13px;
  transition: color 0.4s var(--m-ease);
}

.listening-close em {
  color: var(--m-ghost);
  font-size: 10px;
  font-style: normal;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.listening-close:hover {
  color: var(--m-fg);
}

/* ---------------------------------------------------------------- 舞台 */

.listening-stage {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--m-gap);
  align-items: center;
  min-height: 0;
}

/* 尺寸必须定在这一层，不能留在子元素上。
   justify-self: start 让网格项按 fit-content 定宽，而这个盒子里全是
   绝对定位的孩子——没有内在宽度，fit-content 就是 0；子元素的
   min(100%, …) 再对着 0 解析，aspect-ratio 把高度也乘成 0，整块消失。
   （V1 这里是 <img>，图片自带内在尺寸兜底，所以同一个写法在 V1 看得见。
   换成 div 拼的物件就塌了。）百分比在这一层是对着网格区解析的，有确定值。 */
.listening-object {
  grid-column: 1 / span 5;
  justify-self: start;
  display: block;
  width: min(100%, 40vh);
}

/* 这里是「正在听」，所以圆盘一直是抽出来的状态，
   不像展示台那样要等选中或播放才滑出。尺度和旧的封面一致。 */
.listening-object .m-object {
  width: 100%;
  --dx: 23%;
  --dy: 4.5%;
}

.listening-object .m-sleeve {
  background: rgba(244, 244, 242, 0.04);
}

/* 聆听状态里的封面是主角，不给它降亮度 */
.listening-object .m-sleeve img {
  filter: grayscale(0) brightness(0.98) contrast(1);
}

.listening-object .m-disc {
  box-shadow:
    inset 0 0 0 1px rgba(244, 244, 242, 0.09),
    0 26px 54px -22px rgba(0, 0, 0, 0.95);
}

.listening-meta {
  grid-column: 7 / span 6;
  display: block;
}

.listening-counter {
  color: var(--m-ghost);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.16em;
}

.listening-title {
  margin-top: 14px;
  color: var(--m-fg);
  font-size: clamp(24px, 3.2vw, 48px);
  font-weight: 400;
  line-height: 1.16;
  letter-spacing: -0.01em;
}

.listening-facts {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(20px, 3vw, 48px);
  margin-top: clamp(18px, 3vh, 34px);
  padding-top: clamp(16px, 2.4vh, 26px);
  border-top: 1px solid var(--m-line);
}

.listening-facts dt {
  color: var(--m-ghost);
  font-size: 10px;
  letter-spacing: 0.16em;
  line-height: 1.6;
  text-transform: uppercase;
}

.listening-facts dd {
  margin-top: 6px;
  color: var(--m-soft);
  font-size: 13px;
  line-height: 1.5;
}

/* -------------------------------------------------------------- 传输控件 */

.m-transport {
  width: min(100%, 680px);
  margin: 0 auto;
}

.m-scrub {
  display: flex;
  align-items: center;
  gap: 14px;
}

.m-time {
  color: var(--m-ghost);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.06em;
  min-width: 4.2em;
}

.m-time[data-total] {
  text-align: right;
}

.m-controls {
  display: flex;
  align-items: center;
  gap: clamp(16px, 2.4vw, 30px);
  margin-top: clamp(14px, 2.2vh, 24px);
}

.m-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  color: var(--m-soft);
  transition: color 0.35s var(--m-ease), transform 0.35s var(--m-ease);
}

.m-btn:hover {
  color: var(--m-fg);
  transform: translateY(-1px);
}

.m-btn svg {
  width: 15px;
  height: 15px;
  fill: currentColor;
}

.m-btn.m-play {
  width: 56px;
  height: 56px;
  border: 1px solid var(--m-line-2);
  border-radius: 50%;
  color: var(--m-fg);
}

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

.m-btn.m-play:hover {
  border-color: var(--m-fg);
}

.m-btn[disabled] {
  color: var(--m-ghost);
  cursor: default;
  transform: none;
}

.m-volume {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-left: auto;
  width: clamp(100px, 15vw, 168px);
}

.m-vol-label {
  color: var(--m-ghost);
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

/* 进度与音量：一条 1px 的线。滑块默认藏起来，指针靠近才出现 */
.m-range {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 18px;
  background: transparent;
  cursor: pointer;
  --fill: 0%;
}

.m-range::-webkit-slider-runnable-track {
  height: 1px;
  background: linear-gradient(
    to right,
    var(--m-accent) var(--fill),
    var(--m-line-2) var(--fill)
  );
}

.m-range::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 9px;
  height: 9px;
  margin-top: -4px;
  border-radius: 50%;
  background: var(--m-fg);
  opacity: 0;
  transition: opacity 0.3s var(--m-ease);
}

.m-range:hover::-webkit-slider-thumb,
.m-range:focus-visible::-webkit-slider-thumb {
  opacity: 1;
}

.m-range::-moz-range-track {
  height: 1px;
  background: var(--m-line-2);
}

.m-range::-moz-range-progress {
  height: 1px;
  background: var(--m-accent);
}

.m-range::-moz-range-thumb {
  width: 9px;
  height: 9px;
  border: 0;
  border-radius: 50%;
  background: var(--m-fg);
  opacity: 0;
  transition: opacity 0.3s var(--m-ease);
}

.m-range:hover::-moz-range-thumb,
.m-range:focus-visible::-moz-range-thumb {
  opacity: 1;
}

.m-range.m-range--vol::-webkit-slider-runnable-track {
  background: linear-gradient(
    to right,
    var(--m-soft) var(--fill),
    var(--m-line-2) var(--fill)
  );
}

.m-range.m-range--vol::-moz-range-progress {
  background: var(--m-soft);
}

/* 播不了的时候进度条是原生 disabled 的（见 js/music-flow.js 的 setSeekable）。
   颜色沿用 .m-btn[disabled] 那一套：暗到 --m-line（比没填满时的 --m-line-2
   还低一档），滑块永远不出现。这样「不能用」在视觉上也是成立的，
   而不只是键盘用户会发现 Tab 跳过了它。

   这段必须排在上面那两条 :hover 之后 —— disabled 的元素照样能匹配 :hover，
   两条规则特异性相同，靠的就是先后顺序。 */
.m-range[disabled] {
  cursor: default;
}

.m-range[disabled]::-webkit-slider-runnable-track {
  background: var(--m-line);
}

.m-range[disabled]::-moz-range-track {
  background: var(--m-line);
}

.m-range[disabled]::-moz-range-progress {
  background: var(--m-line);
}

.m-range[disabled]::-webkit-slider-thumb,
.m-range[disabled]::-moz-range-thumb {
  opacity: 0;
}

/* 播放状态：唯一一处文字反馈，播不了就直说 */
.m-status {
  min-height: 1.6em;
  margin-top: 12px;
  color: var(--m-faint);
  font-size: 12px;
  line-height: 1.6;
  text-align: center;
}

.m-status.is-error {
  color: var(--m-accent);
}

/* -------------------------------------------------------------- 曲目条 */

.listening-strip {
  display: flex;
  gap: 10px;
  overflow-x: auto;
  padding-bottom: 4px;
  scrollbar-width: none;
}

.listening-strip::-webkit-scrollbar {
  display: none;
}

.m-chip {
  position: relative;
  flex: 0 0 auto;
  width: clamp(40px, 4vw, 54px);
  aspect-ratio: 1;
  overflow: hidden;
  background: rgba(244, 244, 242, 0.04);
  border: 1px solid var(--m-line);
  transition: border-color 0.45s var(--m-ease);
}

.m-chip img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(1) brightness(0.5);
  transition: filter 0.5s var(--m-ease);
}

.m-chip:hover img,
.m-chip:focus-visible img {
  filter: grayscale(0) brightness(0.9);
}

.m-chip.is-current {
  border-color: var(--m-fg);
}

.m-chip.is-current img {
  filter: grayscale(0) brightness(1);
}

.m-chip.is-playing {
  border-color: var(--m-accent);
}

.m-chip.is-playing::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 2px;
  background: var(--m-accent);
}

/* ------------------------------------------------------- 揭示（可整段删掉） */

html.m-ready .m-hero .eyebrow,
html.m-ready .m-hero .hero-foot,
html.m-ready .m-hero .hero-scroll {
  opacity: 0;
  animation: m-in 0.7s var(--m-ease-out) forwards;
}

html.m-ready .m-hero .hero-foot { animation-delay: 0.18s; }
html.m-ready .m-hero .hero-scroll { animation-delay: 0.3s; }

html.m-ready .m-title .line i {
  opacity: 0;
  transform: translateY(0.9em);
  animation: m-line 0.85s var(--m-ease-out) forwards;
}

html.m-ready .m-row {
  opacity: 0;
}

html.m-ready .m-row.is-in {
  animation: m-in 0.55s var(--m-ease-out) forwards;
  animation-delay: calc(var(--i, 0) * 45ms);
}

html.m-ready .m-labels,
html.m-ready .m-archive-head {
  opacity: 0;
  animation: m-in 0.6s var(--m-ease-out) 0.05s forwards;
}

/* 展示台是钉住的，所以只淡入、不位移——位移会让它在滚动中「跳」一下 */
html.m-ready .m-showcase-inner {
  opacity: 0;
  animation: m-in 0.7s var(--m-ease-out) 0.12s forwards;
}

@keyframes m-in {
  from { opacity: 0; transform: translateY(14px); }
  to { opacity: 1; transform: translateY(0); }
}

@keyframes m-line {
  from { opacity: 0; transform: translateY(0.9em); }
  to { opacity: 1; transform: translateY(0); }
}

/* 音频元素不占布局，也不参与绘制，但保持可播放 */
.m-audio {
  position: absolute;
  width: 0;
  height: 0;
  opacity: 0;
  pointer-events: none;
}

/* ============================================================ 响应式 */

/* 和 Gallery 同一档：收一收导航的间距和字号，给页头留出余量 */
@media (max-width: 1100px) {
  .navbar {
    gap: 14px;
  }

  .navbar a {
    font-size: 13px;
  }
}

/* ------------------------------------------------------ 平板 834×1112
   不是把桌面压窄：账本从「七列一行」变成「两行」。
   曲名独占第一行，艺人 / 专辑 / 年份组成第二行，时长跨两行右对齐。
   信息一条不少，只是换了一种读法。                                    */

@media (max-width: 1023px) {
  .m-archive-head .eyebrow { grid-column: 1 / span 3; }
  .m-archive-note { grid-column: 4 / span 9; }

  /* 列标题在这个布局里已经不对应了，收掉比留着误导好 */
  .m-labels {
    display: none;
  }

  .m-row {
    row-gap: 5px;
    align-items: center;
  }

  .m-row > .c-num { grid-column: 1 / span 1; grid-row: 1 / span 2; }
  .m-row > .c-art { grid-column: 2 / span 1; grid-row: 1 / span 2; width: 48px; }
  .m-row > .c-title { grid-column: 3 / span 6; grid-row: 1; }
  .m-row > .c-artist { grid-column: 3 / span 3; grid-row: 2; }
  .m-row > .c-album { grid-column: 6 / span 4; grid-row: 2; }
  .m-row > .c-year { grid-column: 10 / span 2; grid-row: 2; }
  .m-row > .c-time { grid-column: 12 / span 1; grid-row: 1 / span 2; }

  .m-row.is-open > .c-art,
  .m-row.is-wide > .c-art {
    width: 58px;
  }

  .m-row.is-wide > .c-art { grid-column: 2 / span 2; }
  .m-row.is-wide > .c-title { grid-column: 4 / span 5; }
  .m-row.is-wide > .c-artist { grid-column: 4 / span 4; grid-row: 2; }
  .m-row.is-wide > .c-album { grid-column: 8 / span 3; grid-row: 2; }
  .m-row.is-wide > .c-year { grid-column: 11 / span 1; grid-row: 2; }
  .m-row.is-wide > .c-time { grid-column: 12 / span 1; grid-row: 1; }

  .m-endnote .eyebrow { grid-column: 1 / span 3; }
  .m-endnote p,
  .m-endnote .link-underline { grid-column: 4 / span 9; }

  /* 聆听状态：物件缩小，让出高度给传输控件。
     宽度同样定在网格项上（见上面 .listening-object 的说明）。 */
  .listening-object { grid-column: 1 / span 5; width: min(100%, 30vh); }
  .listening-meta { grid-column: 6 / span 7; }

  /* 展示台：账本在这里已经换成两行的读法，展示台跟着收一档，
     把高度让给账本——钉住的区域越高，能看到的行就越少。 */
  .m-showcase {
    padding-top: clamp(52px, 6.4vh, 68px);
    padding-bottom: clamp(16px, 2.2vh, 24px);
  }

  .m-stage { grid-column: 1 / span 4; }
  .m-object { width: clamp(108px, 13.5vw, 138px); }
  .m-showcase-meta { grid-column: 6 / span 7; }

  body.music-page .m-showcase-title { font-size: clamp(20px, 2.5vw, 28px); }
  body.music-page .m-showcase-facts { gap: 5px 22px; }
  body.music-page .m-showcase-hint { margin-top: 12px; }

  .site-header { padding-top: 16px; padding-bottom: 16px; }
}

/* ------------------------------------------------------ 手机 390×844
   也不是把平板压窄。账本变成「封面在左，信息在右」的条目：
   编号 + 封面占左边两列，右边第一行曲名与时长，下面两行元数据。
   hover 在触屏上不存在，所以点按的反馈由 :active 接管。            */

@media (max-width: 640px) {
  /* 页头：375px 下「ZHU + creative weblog + 六个导航项」放不进一行，
     实测溢出 73px，而且浏览器会为此把整页缩小，连正文一起变糊。
     处理方式和 Gallery 一致——副标题收掉、导航改为可横向滚，
     而不是让页头把整个视口撑破。 */
  .brand-note {
    display: none;
  }

  .navbar {
    overflow-x: auto;
    scrollbar-width: none;
  }

  .navbar::-webkit-scrollbar {
    display: none;
  }

  .m-hero {
    min-height: clamp(360px, 56svh, 520px);
    padding-top: clamp(32px, 5vh, 56px);
  }

  .m-title {
    max-width: none;
  }

  .hero-foot {
    grid-template-columns: minmax(0, 1fr);
    gap: 22px;
  }

  .hero-spec {
    gap: 22px;
  }

  .m-archive-head .eyebrow { grid-column: 1 / span 12; }
  .m-archive-note { grid-column: 1 / span 12; margin-top: 14px; }

  .m-row {
    grid-template-columns: 24px 50px minmax(0, 1fr) auto;
    column-gap: 12px;
    row-gap: 3px;
    padding: 15px 0;
  }

  .m-row > .c-num {
    grid-column: 1;
    grid-row: 1 / span 3;
    align-self: start;
    padding-top: 3px;
    font-size: 11px;
  }

  .m-row > .c-art,
  .m-row.is-open > .c-art,
  .m-row.is-wide > .c-art {
    grid-column: 2;
    grid-row: 1 / span 3;
    align-self: start;
    width: 50px;
  }

  .m-row > .c-title,
  .m-row.is-wide > .c-title {
    grid-column: 3;
    grid-row: 1;
    font-size: 16px;
  }

  .m-row > .c-artist,
  .m-row.is-wide > .c-artist {
    grid-column: 3;
    grid-row: 2;
    font-size: 12px;
  }

  .m-row > .c-album,
  .m-row.is-wide > .c-album {
    grid-column: 3;
    grid-row: 3;
    font-size: 12px;
  }

  .m-row > .c-year,
  .m-row.is-wide > .c-year {
    grid-column: 4;
    grid-row: 3;
    justify-self: end;
  }

  .m-row > .c-time,
  .m-row.is-wide > .c-time {
    grid-column: 4;
    grid-row: 1;
    justify-self: end;
  }

  /* 触屏没有 hover，用按下和常驻的可读性代替 */
  .m-row.is-playing .c-title,
  .m-row.is-current .c-title {
    color: var(--m-accent);
  }

  .m-row.is-current .c-title {
    color: var(--m-fg);
  }

  .m-row:active .c-title {
    color: var(--m-fg);
  }

  .m-row:active .c-art img {
    filter: grayscale(0) brightness(1);
  }

  /* 展示台：手机上改成「物件在左、文字在右」——和账本的行同一个读法，
     而且比上下堆叠矮将近一半。钉住的区域每高一寸，能看到的行就少一寸。
     物件不缩小到看不清：圆盘还要滑得出来，旋转还要看得出来。 */
  .m-showcase {
    padding: clamp(50px, 7.6vh, 62px) var(--m-x) clamp(14px, 2vh, 20px);
  }

  .m-showcase-inner {
    grid-template-columns: auto minmax(0, 1fr);
    /* 26px 只剩 3px 余量——圆盘最大时探出 23px，会贴到右边的字上。
       栏间距是拿宽度换的，这里多给 8px 买一点呼吸。 */
    column-gap: 34px;
    align-items: center;
  }

  /* 「Now showing」在这里是多余的——右边的 01 / 07 说的是同一件事 */
  .m-stage-label { display: none; }

  .m-stage { grid-column: 1; }
  .m-object { width: 92px; }
  .m-showcase-meta { grid-column: 2; }

  body.music-page .m-showcase-title {
    margin-top: 6px;
    font-size: 19px;
    line-height: 1.2;
  }

  body.music-page .m-showcase-facts {
    gap: 3px 16px;
    margin-top: 10px;
    padding-top: 9px;
  }

  .m-showcase-facts dt { font-size: 9px; }
  .m-showcase-facts dd { margin-top: 3px; font-size: 12px; }

  body.music-page .m-showcase-hint {
    margin-top: 9px;
    font-size: 11px;
    line-height: 1.6;
  }

  .m-endnote .eyebrow,
  .m-endnote p,
  .m-endnote .link-underline {
    grid-column: 1 / span 12;
  }

  .site-footer {
    flex-direction: column;
    gap: 6px;
    padding: 26px var(--m-x);
  }

  /* 聆听状态：单列。封面、曲名、控件、曲目条自上而下 */
  .listening {
    grid-template-rows: auto auto auto auto;
    row-gap: 16px;
    overflow-y: auto;
    padding-bottom: 20px;
  }

  .listening-stage {
    grid-template-columns: minmax(0, 1fr);
    row-gap: 18px;
    align-content: start;
  }

  /* 宽度同样定在网格项上：定在子元素上的话，父盒会比物件宽
     （它还会继承平板那档 clamp），justify-self: center 居中的是空盒子，
     物件被留在左边——看上去整块偏左。 */
  .listening-object {
    grid-column: 1;
    justify-self: center;
    width: min(52vw, 22vh);
  }

  .listening-object .m-object {
    width: 100%;
  }

  .listening-meta {
    grid-column: 1;
    text-align: left;
  }

  .listening-title {
    margin-top: 10px;
    font-size: 24px;
  }

  .listening-facts {
    gap: 20px;
    margin-top: 16px;
    padding-top: 14px;
  }

  .listening-facts dd {
    font-size: 12px;
  }

  .m-controls {
    position: relative;
    justify-content: center;
    gap: 14px;
    padding-bottom: 30px;
  }

  /* 音量在手机上不藏在右边角，摊到控件下方一整行 */
  .m-volume {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    width: auto;
    margin-left: 0;
  }

  .m-status {
    text-align: left;
    margin-top: 6px;
  }
}

/* 触屏：滑块一直可见，否则摸不到 */
@media (pointer: coarse) {
  .m-range::-webkit-slider-thumb {
    width: 13px;
    height: 13px;
    margin-top: -6px;
    opacity: 1;
  }

  .m-range::-moz-range-thumb {
    width: 13px;
    height: 13px;
    opacity: 1;
  }

  .m-range {
    height: 26px;
  }

  .c-art img {
    filter: grayscale(0.35) brightness(0.78) contrast(1.03);
  }

  /* 触屏没有 hover，展示台的封面不能一直停在「没被选中」的暗档上，
     否则第一眼看过去是一块黑。这是推流媒体常见的做法：
     触屏上默认就给一档可见的亮度，选中再恢复彩色。 */
  .m-object .m-sleeve img {
    filter: grayscale(0.35) brightness(0.78) contrast(1.03);
  }
}

/* ------------------------------------------------------- reduced motion */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }

  /* 动效关掉之后，靠动画「出现」的东西必须直接是可见的 */
  html.m-ready .m-hero .eyebrow,
  html.m-ready .m-hero .hero-foot,
  html.m-ready .m-hero .hero-scroll,
  html.m-ready .m-title .line i,
  html.m-ready .m-row,
  html.m-ready .m-labels,
  html.m-ready .m-archive-head,
  html.m-ready .m-showcase-inner {
    opacity: 1 !important;
    transform: none !important;
  }

  /* 唱片不转。其余照常：圆盘该滑出还是滑出，只是一步到位。
     展示台、封面、元数据、聆听状态都不依赖动效。 */
  .m-object.is-playing .m-disc i {
    animation: none;
  }

  /* 视差也一并取消——JS 那侧已经不问指针位置了，这里是兜底 */
  .m-object-stage {
    transform: scale(var(--osc)) !important;
  }

  .listening.is-sounding .m-pulse i {
    animation: none;
    transform: scaleY(0.7);
  }

  .hero-scroll i {
    animation: none;
    transform: scaleX(1);
  }

  .m-row:hover .c-art img,
  .m-row:focus-visible .c-art img {
    transform: none;
  }
}
