:root {
  --paper: #e4d5bb;
  --ink: #1a1410;
  --soot: #070605;
  --cinnabar: #9c2b1a;
  --lamp: #d7a15a;
  --copper: #8a6a3d;
  --moss: #7d9a6a;
  --ease: cubic-bezier(.16, .84, .28, 1);
}

* { box-sizing: border-box; }
html, body {
  margin: 0;
  height: 100%;
  background: var(--soot);
  color: var(--paper);
  font-family: "Noto Serif SC", serif;
  overflow: hidden;
  user-select: none;
  -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
}

.void {
  height: 100%;
  display: grid;
  place-items: center;
  background: #050403;
}

/* ============ 舞台 ============
   横版：1536×1024 背景图，左右两侧墙上各挂一个画框（画面里只露出约 1/4）。
   竖版：1024×1536 背景图，坐标另算。所有关键矩形都由背景图像素测量而来。 */
.stage {
  --fw: 1536;
  --fh: 1024;

  /* 中央金框的内窗 */
  --slot-x: 35.68%;
  --slot-y: 16.21%;
  --slot-w: 28.32%;
  --slot-h: 52.34%;

  /* 左右侧墙上画框「可见」的那部分内窗 */
  --wing-y: 26.07%;
  --wing-h: 34.28%;
  --wing-w: 3.13%;

  /* 金框画出来的边比内窗宽一截（横版实测单边 23px），量的时候别只算内窗 */
  --frame-pad: 23px;

  /* 「询问记录」面板：导航箭头要躲开它，所以两边共用同一组数 */
  --dossier-right: 3.2%;
  --dossier-w: 18.2%;

  /* 导航箭头 */
  --nav-size: 46px;
  --nav-gap: 40px;

  position: relative;
  width: min(100vw, calc(100vh * var(--fw) / var(--fh)));
  height: min(100vh, calc(100vw * var(--fh) / var(--fw)));
  overflow: hidden;
  cursor: grab;
  box-shadow: 0 0 80px rgba(0, 0, 0, .8);
  touch-action: none;
}
.stage.dragging { cursor: grabbing; }
.stage.listening { cursor: none; }

.hall {
  position: absolute;
  inset: 0;
  background-image: url("./images/hall-plate.png");
  background-image: image-set(
    url("./images/hall-plate.webp") type("image/webp"),
    url("./images/hall-plate.png") type("image/png")
  );
  background-position: center;
  background-size: 100% 100%;
  background-repeat: no-repeat;
  pointer-events: none;
  z-index: 1;
}

/* ---- 竖屏（手机）：换竖版背景，舞台吃满整屏 ---- */
.stage.tall {
  --fw: 1024;
  --fh: 1536;
  width: 100vw;
  height: 100vh;
  height: 100dvh;
  box-shadow: none;

  /* 竖版图 1024×1536，按屏宽铺满 => 图高 = 150vw */
  --slot-x: 31.05vw;
  --slot-y: 35.156vw;
  --slot-w: 37.99vw;
  --slot-h: 47.363vw;

  --wing-y: 36.621vw;
  --wing-h: 43.652vw;
  --wing-w: 5.273vw;
}
.stage.tall .hall {
  background-image: url("./images/hall-plate-portrait.png");
  background-image: image-set(
    url("./images/hall-plate-portrait.webp") type("image/webp"),
    url("./images/hall-plate-portrait.png") type("image/png")
  );
  background-position: top center;
  background-size: 100% auto;
  background-repeat: no-repeat;
}
/* 竖版图只到 150vw，下面用暗色接上，免得露出一截硬边 */
.stage.tall .hall::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 149.4vw;
  bottom: 0;
  background: linear-gradient(180deg, #0d0906 0%, #060403 55%, #050403 100%);
}

/* ============ 中央画框 ============ */
.frame-window {
  position: absolute;
  left: var(--slot-x);
  top: var(--slot-y);
  width: var(--slot-w);
  height: var(--slot-h);
  overflow: hidden;
  z-index: 2;
  background: #050505;
  box-shadow: inset 0 0 34px rgba(0, 0, 0, .85);
}
.strip {
  display: flex;
  height: 100%;
  width: 300%;
  will-change: transform;
  backface-visibility: hidden;
}
.slide {
  flex: 0 0 33.333%;
  width: 33.333%;
  height: 100%;
  object-fit: cover;
  object-position: center 62%;
  pointer-events: none;
  filter: saturate(.88) contrast(1.06);
  backface-visibility: hidden;
}

/* ============ 左右侧墙画框（预览上一卷 / 下一卷） ============ */
.wing {
  position: absolute;
  z-index: 2;
  overflow: hidden;
  background: #050505;
  cursor: pointer;
  pointer-events: auto;
}
.wing.left { left: 0; top: var(--wing-y); width: var(--wing-w); height: var(--wing-h); }
.wing.right { right: 0; top: var(--wing-y); width: var(--wing-w); height: var(--wing-h); }
.wing::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  box-shadow: inset 0 0 26px rgba(0, 0, 0, .92);
}
/* 画框内壁的暖光，让侧墙的图和背景的射灯连成一片 */
.wing::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  mix-blend-mode: soft-light;
  opacity: .9;
}
.wing.right::before {
  background: linear-gradient(90deg, rgba(255, 190, 110, .5), rgba(120, 80, 40, .2) 60%, rgba(0, 0, 0, .4));
}
.wing.left::before {
  background: linear-gradient(270deg, rgba(255, 190, 110, .5), rgba(120, 80, 40, .2) 60%, rgba(0, 0, 0, .4));
}
.wing img {
  position: absolute;
  top: 0;
  height: 100%;
  /* 只露画框可见的那一条：整幅画按 4 倍宽渲染，再让容器裁掉外面 */
  width: 400%;
  object-fit: cover;
  object-position: center 62%;
  display: block;
  opacity: 0;
  transition: opacity .46s ease, transform .55s cubic-bezier(.16, .84, .28, 1);
  filter: brightness(.6) saturate(.74);
  will-change: transform, opacity;
}
.wing.left img { right: 0; left: auto; }
.wing.right img { left: 0; right: auto; }
.wing img.on { opacity: 1; }
.wing:hover img { filter: brightness(.82) saturate(.9); }

.stamp {
  position: absolute;
  left: 50%;
  top: 42%;
  z-index: 3;
  border: 4px solid var(--cinnabar);
  color: var(--cinnabar);
  padding: .12em .28em .18em;
  font-family: "ZCOOL XiaoWei", serif;
  font-size: clamp(42px, 6.2vw, 92px);
  letter-spacing: .18em;
  transform: translate(-50%, -50%) rotate(-14deg);
  background: rgba(20, 8, 6, .12);
  text-shadow: 0 0 1px rgba(156, 43, 26, .4);
  pointer-events: none;
  animation: chop .3s cubic-bezier(.2, 1.4, .3, 1);
}
.stamp[hidden] { display: none; }
.stamp.yes { color: var(--lamp); border-color: var(--lamp); }
.stamp.close, .stamp.partial { color: #c45c3e; border-color: #c45c3e; }
.stamp.solved { color: var(--moss); border-color: var(--moss); }
.stamp.irrelevant, .stamp.unanswerable, .stamp.refuse { color: #b9a07a; border-color: #b9a07a; }

@keyframes chop {
  0% { transform: translate(-50%, -50%) rotate(-14deg) scale(1.35); opacity: 0; }
  70% { transform: translate(-50%, -50%) rotate(-14deg) scale(.96); opacity: 1; }
  100% { transform: translate(-50%, -50%) rotate(-14deg) scale(1); }
}

.reveal {
  position: absolute;
  inset: 0;
  z-index: 12;
  display: grid;
  place-items: center;
  pointer-events: none;
  background: radial-gradient(circle at 50% 42%, rgba(0, 0, 0, .18), transparent 58%);
}
.reveal[hidden] { display: none; }
.reveal-plate {
  min-width: 28%;
  text-align: center;
  padding: 22px 28px 18px;
  background: linear-gradient(180deg, rgba(24, 16, 10, .88), rgba(10, 8, 6, .72));
  border: 1px solid #c4a36a;
  box-shadow:
    inset 0 0 0 1px #5a4424,
    inset 0 0 0 4px rgba(196, 163, 106, .22),
    0 24px 60px rgba(0, 0, 0, .55);
  animation: plateIn .5s var(--ease);
}
.reveal-kicker {
  font-family: "IBM Plex Mono", monospace;
  letter-spacing: .42em;
  font-size: 11px;
  color: #c45c3e;
  margin-bottom: 8px;
}
.reveal-title {
  font-family: "ZCOOL XiaoWei", serif;
  font-size: clamp(36px, 4.6vw, 64px);
  letter-spacing: .28em;
  color: #f7ead0;
  text-shadow: 0 8px 24px rgba(0, 0, 0, .6);
}
@keyframes plateIn {
  from { transform: scale(1.12); opacity: 0; }
  to { transform: scale(1); opacity: 1; }
}

.seal {
  position: absolute;
  left: 2.4%;
  top: 3.2%;
  z-index: 6;
  writing-mode: vertical-rl;
  font-family: "ZCOOL XiaoWei", serif;
  letter-spacing: .35em;
  font-size: clamp(18px, 2.1vw, 28px);
  color: #f3e2c8;
  background: var(--cinnabar);
  padding: .55em .28em;
  pointer-events: none;
  box-shadow: 0 8px 18px rgba(0, 0, 0, .35);
}

/* 声音开关：挂在印章正下方，不能压到「问」字。
   印章高 ≈ 3.79em、宽 ≈ 1.57em，字号是 clamp(18px,2.1vw,28px)，
   这里用同一支 clamp 折算（×3.79→clamp(68px,7.96vw,106px)），换屏幕也不会重新压回去。 */
.sound {
  position: absolute;
  left: 2.4%;
  top: calc(3.2% + clamp(68px, 7.96vw, 106px) + 12px);
  z-index: 8;
  width: clamp(28px, 3.3vw, 44px);
  height: clamp(28px, 3.3vw, 44px);
  display: grid;
  place-items: center;
  border: 1px solid rgba(196, 163, 106, .5);
  background: rgba(10, 8, 6, .5);
  color: #d7c09a;
  cursor: pointer;
  padding: 0;
  transition: color .2s, border-color .2s, background .2s, opacity .22s;
}
.sound:hover { color: #f7ead0; border-color: #c4a36a; }
.sound.off { color: #6b5c48; border-color: rgba(196, 163, 106, .22); }
.sound svg { width: 19px; height: 19px; fill: currentColor; }
.sound .slash { opacity: 0; }
.sound.off .slash { opacity: 1; }

.nav {
  position: absolute;
  top: 37.4%;
  z-index: 5;
  width: var(--nav-size);
  height: var(--nav-size);
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid rgba(196, 163, 106, .44);
  border-radius: 50%;
  background: rgba(10, 8, 6, .52);
  color: rgba(224, 174, 104, .78);
  font-size: 30px;
  line-height: 1;
  cursor: pointer;
  font-family: "IBM Plex Mono", monospace;
  backdrop-filter: blur(2px);
  transition: color .2s, border-color .2s, background .2s, transform .2s, opacity .22s;
}
.nav > span { display: block; transform: translateY(-2px); }
.nav:hover {
  color: rgba(215, 161, 90, .95);
  border-color: rgba(196, 163, 106, .8);
  background: rgba(22, 16, 10, .66);
  transform: scale(1.06);
}
/* 箭头贴着中央金框的外侧对称站，不再贴舞台边。
   贴边的时候右边那枚会被「询问记录」面板压住——面板底色是半透明的，
   箭头会在下面透出半个影子，看着就像坏了。 */
.nav.prev {
  left: calc(var(--slot-x) - var(--frame-pad) - var(--nav-gap) - var(--nav-size));
  right: auto;
}
.nav.next {
  left: min(
    calc(var(--slot-x) + var(--slot-w) + var(--frame-pad) + var(--nav-gap)),
    calc(100% - var(--dossier-right) - var(--dossier-w) - var(--nav-size) - 14px)
  );
  right: auto;
}
.nav:active { transform: scale(.94); }

/* 排行榜是全屏遮罩弹层，浮起来的时候把舞台浮标一起收走，
   不然箭头会在暗罩后面透出半个影子，看着像坏了。 */
.stage.boarded .nav,
.stage.boarded .sound { opacity: 0; visibility: hidden; }
.stage.boarded .hint { display: none; }

.plaque {
  position: absolute;
  left: 50%;
  top: 68.8%;
  transform: translateX(-50%);
  z-index: 5;
  min-width: 28%;
  text-align: center;
  pointer-events: none;
}
.plaque .no {
  font-family: "IBM Plex Mono", monospace;
  font-size: 12px;
  letter-spacing: .5em;
  color: #f0c9a0;
  margin-bottom: 6px;
  text-shadow: 0 1px 8px #000;
}
.plaque h1 {
  margin: 0;
  font-family: "ZCOOL XiaoWei", serif;
  font-weight: 400;
  font-size: clamp(34px, 4.2vw, 56px);
  letter-spacing: .34em;
  color: #f7ead0;
  text-shadow:
    0 0 1px #1a1208,
    0 2px 0 #3a2a14,
    0 8px 24px rgba(0, 0, 0, .9),
    0 0 18px rgba(215, 161, 90, .35);
}

.read {
  position: absolute;
  left: 50%;
  top: 77.6%;
  transform: translateX(-50%);
  z-index: 5;
  width: min(46%, 560px);
  max-height: 11.2%;
  overflow-y: auto;
  overscroll-behavior: contain;
  pointer-events: auto;
  padding-right: 4px;
  mask-image: linear-gradient(#000 70%, transparent 100%);
}
.read::-webkit-scrollbar { width: 4px; }
.read::-webkit-scrollbar-thumb { background: #6e5a3a; }
.surface {
  margin: 0;
  text-align: center;
  font-size: 15px;
  font-weight: 700;
  line-height: 1.9;
  color: #f0e2c4;
  text-shadow: 0 2px 10px #000, 0 0 12px rgba(0, 0, 0, .8);
  transition: color .3s;
}
.surface.bottom { color: #f0e2c8; text-align: left; }

.heard, .status {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  z-index: 6;
  margin: 0;
  text-align: center;
  pointer-events: none;
}
.heard {
  bottom: 12.8%;
  font-size: 16px;
  font-weight: 700;
  letter-spacing: .12em;
  color: #fff4dc;
  min-height: 1.2em;
  text-shadow: 0 2px 16px #000;
}
.status {
  bottom: 1.8%;
  font-family: "IBM Plex Mono", monospace;
  font-size: 11px;
  letter-spacing: .38em;
  color: #8a7760;
}

.dock {
  position: absolute;
  left: 50%;
  bottom: 4.6%;
  transform: translateX(-50%);
  z-index: 8;
  width: min(48%, 620px);
  display: grid;
  grid-template-columns: 1fr 56px;
  gap: 10px;
  align-items: center;
}
.mic {
  position: relative;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  border: 2px solid #c4a36a;
  background: radial-gradient(circle at 50% 40%, #2a231b, #0c0a08 70%);
  color: #e8d3a8;
  cursor: pointer;
  display: grid;
  place-items: center;
  box-shadow: 0 0 0 1px #3a2c1c, 0 10px 24px rgba(0, 0, 0, .55);
  touch-action: none;
}
.mic svg { width: 28px; height: 28px; fill: currentColor; }
/* 浏览器没有 SpeechRecognition（比如 Firefox / 老版 Safari）：麦克风置灰，引导打字 */
.mic.unsupported {
  border-color: rgba(196, 163, 106, .3);
  color: #6b5c48;
  cursor: not-allowed;
  box-shadow: none;
}
.mic .rings {
  position: absolute;
  inset: -18px;
  border-radius: 50%;
  pointer-events: none;
  opacity: 0;
}
.stage.listening .mic {
  border-color: var(--cinnabar);
  color: #f4d2c4;
  box-shadow: 0 0 0 1px #5a2018, 0 0 24px rgba(156, 43, 26, .45);
}
.stage.listening .mic .rings {
  opacity: 1;
  background:
    radial-gradient(circle, transparent 54%, rgba(156, 43, 26, .0) 55%, rgba(156, 43, 26, .55) 56%, transparent 57%),
    radial-gradient(circle, transparent 70%, rgba(156, 43, 26, .0) 71%, rgba(156, 43, 26, .35) 72%, transparent 73%);
  animation: pulse 1.6s linear infinite;
}
.mic-cap {
  position: absolute;
  left: 50%;
  bottom: 1.6%;
  transform: translateX(-50%);
  z-index: 7;
  font-family: "IBM Plex Mono", monospace;
  font-size: 11px;
  letter-spacing: .28em;
  color: #d7c09a;
  pointer-events: none;
  text-shadow: 0 2px 8px #000;
  white-space: nowrap;
}

.dossier {
  position: absolute;
  right: var(--dossier-right);
  top: 8%;
  width: var(--dossier-w);
  max-height: 62%;
  z-index: 6;
  pointer-events: auto;
  background: linear-gradient(180deg, rgba(22, 16, 10, .82), rgba(10, 8, 6, .55));
  border: 1px solid #c4a36a;
  box-shadow:
    inset 0 0 0 1px #5a4424,
    inset 0 0 0 3px rgba(196, 163, 106, .28),
    0 16px 40px rgba(0, 0, 0, .45);
  padding: 12px 12px 10px;
  overflow: auto;
}
.dossier::before {
  content: "";
  position: absolute;
  inset: 5px;
  border: 1px solid rgba(240, 201, 160, .18);
  pointer-events: none;
}
.player {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
  font-family: "IBM Plex Mono", monospace;
  font-size: 11px;
  color: #d7c09a;
}
.player input {
  flex: 1;
  min-width: 0;
  background: transparent;
  border: 0;
  border-bottom: 1px solid #6e5a3a;
  color: #f7ead0;
  font-family: "Noto Serif SC", serif;
  font-size: 14px;
  outline: none;
}
.meter {
  display: flex;
  justify-content: space-between;
  gap: 6px;
  font-family: "IBM Plex Mono", monospace;
  font-size: 11px;
  letter-spacing: .12em;
  color: #f0c9a0;
  padding-bottom: 8px;
  border-bottom: 1px solid rgba(196, 163, 106, .22);
  text-shadow: 0 1px 6px #000;
}
.keys {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  margin: 8px 0 6px;
}
.keys[hidden] { display: none; }
.key-chip {
  font-family: "IBM Plex Mono", monospace;
  font-size: 10px;
  letter-spacing: .08em;
  padding: 3px 7px;
  border: 1px solid var(--lamp);
  color: #f0c9a0;
  background: rgba(215, 161, 90, .14);
  box-shadow: inset 0 0 0 1px rgba(90, 68, 36, .55);
  animation: chipIn .4s var(--ease);
}
@keyframes chipIn {
  from { transform: scale(.8); opacity: 0; }
  to { transform: scale(1); opacity: 1; }
}
.ledger {
  list-style: none;
  margin: 8px 0 0;
  padding: 0;
  max-height: 22vh;
  overflow: auto;
}
.board-open {
  margin-top: 12px;
  width: 100%;
  background: transparent;
  border: 1px solid #c4a36a;
  color: #f0c9a0;
  font-family: "ZCOOL XiaoWei", serif;
  letter-spacing: .28em;
  padding: 7px 0;
  cursor: pointer;
}
.board-layer {
  position: absolute;
  inset: 0;
  z-index: 14;
  background: rgba(6, 4, 3, .62);
  display: grid;
  place-items: center;
  animation: fadeIn .25s ease;
}
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
.board-layer[hidden] { display: none; }
.board-sheet {
  width: min(52%, 560px);
  max-height: 72%;
  overflow: auto;
  background: linear-gradient(180deg, rgba(24, 16, 10, .94), rgba(10, 8, 6, .9));
  border: 1px solid #c4a36a;
  box-shadow:
    inset 0 0 0 1px #5a4424,
    inset 0 0 0 4px rgba(196, 163, 106, .2),
    0 24px 70px rgba(0, 0, 0, .55);
  padding: 18px 20px;
}
.board-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-family: "ZCOOL XiaoWei", serif;
  letter-spacing: .32em;
  font-size: 28px;
  color: #f7ead0;
}
.board-head button {
  background: transparent;
  border: 1px solid #6e5a3a;
  color: #d7c09a;
  cursor: pointer;
  padding: 4px 10px;
  font-family: "IBM Plex Mono", monospace;
}
.board-sub {
  margin: 8px 0 12px;
  font-family: "IBM Plex Mono", monospace;
  font-size: 12px;
  letter-spacing: .16em;
  color: #8a7760;
}
.board {
  list-style: none;
  margin: 6px 0 0;
  padding: 0;
}
.board li {
  display: grid;
  grid-template-columns: 1.2em 1fr auto;
  gap: 6px;
  font-size: 12px;
  color: #d8c7a6;
  margin: 0 0 4px;
}
.board .me { color: var(--lamp); }
.ledger li {
  margin: 0 0 9px;
  padding: 0;
  line-height: 1.45;
  animation: rowIn .4s var(--ease);
}
@keyframes rowIn {
  from { transform: translateY(-6px); opacity: 0; }
  to { transform: translateY(0); opacity: 1; }
}
.ledger .q {
  color: #f4ead4;
  font-size: 13px;
  font-weight: 700;
  text-shadow: 0 1px 6px #000;
}
.ledger .a {
  margin-top: 2px;
  font-family: "ZCOOL XiaoWei", serif;
  letter-spacing: .2em;
  font-size: 16px;
  color: var(--lamp);
}
.ledger .a.no, .ledger .a.irrelevant { color: #d8c7a6; }
.ledger .a.close, .ledger .a.partial { color: #e07a58; }
.ledger .a.solved { color: var(--moss); }
.ledger .ms {
  font-family: "IBM Plex Mono", monospace;
  font-size: 10px;
  color: #8a7760;
  letter-spacing: .08em;
}
.stage.listening .mic-cap { color: #c45c3e; }

@keyframes pulse {
  from { transform: scale(.92); opacity: .9; }
  to { transform: scale(1.12); opacity: 0; }
}

.type-line {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 8px;
  align-items: center;
}
.type-line input {
  width: 100%;
  background: rgba(10, 8, 6, .55);
  border: 1px solid #6e5a3a;
  color: var(--paper);
  font-family: "Noto Serif SC", serif;
  font-size: 16px;
  text-align: left;
  outline: none;
  padding: 8px 12px;
  transition: border-color .2s, background .2s;
}
.type-line input:focus { border-color: #c4a36a; background: rgba(14, 11, 8, .78); }
.ask-btn {
  background: transparent;
  border: 1px solid #c4a36a;
  color: #f0c9a0;
  font-family: "ZCOOL XiaoWei", serif;
  letter-spacing: .2em;
  padding: 0 12px;
  height: 40px;
  cursor: pointer;
  transition: background .2s, color .2s;
}
.ask-btn:hover { background: rgba(215, 161, 90, .16); color: #f7ead0; }
.stage.busy .ask-btn { opacity: .45; pointer-events: none; }
.stage.busy .type-line input { opacity: .6; }

.grain {
  pointer-events: none;
  position: fixed;
  inset: 0;
  opacity: .07;
  z-index: 9;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='.6'/%3E%3C/svg%3E");
}

/* ============ 空气里的浮尘 ============
   十几颗慢慢上浮的光点，成本极低但整个厅立刻"有人在呼吸" */
.motes {
  position: absolute;
  inset: 0;
  z-index: 4;
  pointer-events: none;
  overflow: hidden;
}
.motes i {
  position: absolute;
  border-radius: 50%;
  opacity: 0;
  background: radial-gradient(circle, rgba(255, 222, 168, .95), rgba(255, 198, 118, 0) 70%);
  animation-name: drift;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
  will-change: transform, opacity;
}
@keyframes drift {
  0% { transform: translate3d(0, 0, 0) scale(.55); opacity: 0; }
  14% { opacity: var(--o, .4); }
  78% { opacity: var(--o, .4); }
  100% { transform: translate3d(var(--dx, 18px), var(--dy, -130px), 0) scale(1.05); opacity: 0; }
}
.stage.listening .motes i { animation-play-state: paused; }

/* 盖章那一下整幅画面跟着沉一下 */
.stage.quake { animation: quake .34s ease-out; }
@keyframes quake {
  0% { transform: translate3d(0, 0, 0); }
  16% { transform: translate3d(-3px, 2px, 0); }
  34% { transform: translate3d(3px, -2px, 0); }
  52% { transform: translate3d(-2px, -1px, 0); }
  72% { transform: translate3d(2px, 1px, 0); }
  100% { transform: translate3d(0, 0, 0); }
}

/* 结案 / 新线索时，一道暖光斜着扫过去 */
.reveal::after {
  content: "";
  position: absolute;
  inset: -10%;
  pointer-events: none;
  background: linear-gradient(104deg, transparent 36%, rgba(255, 219, 158, .15) 50%, transparent 64%);
  transform: translateX(-62%);
  animation: sweep 1.15s cubic-bezier(.3, .5, .3, 1);
}
@keyframes sweep {
  to { transform: translateX(62%); }
}

/* 开场遮罩 */
.boot {
  position: fixed;
  inset: 0;
  z-index: 40;
  display: grid;
  place-items: center;
  background: #050403;
  transition: opacity .7s ease, visibility .7s;
}
.boot.done { opacity: 0; visibility: hidden; }
.boot-inner { text-align: center; }
.boot-seal {
  font-family: "ZCOOL XiaoWei", serif;
  font-size: 46px;
  letter-spacing: .5em;
  color: var(--cinnabar);
  border: 2px solid var(--cinnabar);
  padding: .2em .34em .3em;
  display: inline-block;
  animation: bootPulse 1.8s ease-in-out infinite;
}
@keyframes bootPulse {
  0%, 100% { opacity: .5; }
  50% { opacity: 1; }
}
.boot-cap {
  margin-top: 18px;
  font-family: "IBM Plex Mono", monospace;
  font-size: 11px;
  letter-spacing: .42em;
  color: #8a7760;
}

/* 键盘/手势提示，几秒后自己退场 */
.hint {
  position: absolute;
  left: 50%;
  top: 10.6%;
  transform: translateX(-50%);
  z-index: 7;
  font-family: "IBM Plex Mono", monospace;
  font-size: 12px;
  letter-spacing: .3em;
  color: #c9b48d;
  text-shadow: 0 2px 10px #000;
  pointer-events: none;
  opacity: 0;
  transition: opacity .8s ease;
  white-space: nowrap;
}
.hint.show { opacity: .85; }

.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }

/* ============ 手机 / 窄屏 ============ */
@media (max-width: 720px) {
  .read { width: 86%; max-height: 16%; }
  .nav { display: none; }
  .mic { width: 48px; height: 48px; }
  .dossier { width: 42%; max-height: 36%; }
  .dock { width: 88%; }
}

/* 竖屏：整套重排。背景图铺满屏宽，UI 落在画面下方的暗区 */
.stage.tall .seal {
  left: 4vw;
  top: 3vw;
  font-size: 17px;
  padding: .5em .26em;
}
.stage.tall .sound {
  left: auto;
  right: 4vw;
  top: 4vw;
  width: 34px;
  height: 34px;
}
.stage.tall .frame-window {
  box-shadow: inset 0 0 22px rgba(0, 0, 0, .85);
}
.stage.tall .wing { cursor: pointer; }

.stage.tall .nav {
  display: grid;
  place-items: center;
  top: 55vw;
  bottom: auto;
  width: 42px;
  height: 42px;
  font-size: 26px;
  line-height: .8;
  border: 1px solid rgba(196, 163, 106, .5);
  border-radius: 50%;
  background: rgba(10, 8, 6, .58);
  color: rgba(224, 174, 104, .88);
}
/* 竖版另算：记录面板挪到屏幕下方居中，左右两侧没有面板跟箭头抢位置，
   所以这里仍然按侧墙画框的外沿来留气口（见上面 --wing-w 的说明）。 */
.stage.tall .nav.prev { left: calc(var(--wing-w) + 8.5vw); right: auto; }
.stage.tall .nav.next { left: auto; right: calc(var(--wing-w) + 8.5vw); }

.stage.tall .plaque {
  top: 85vw;
  min-width: 0;
  width: 90vw;
}
.stage.tall .plaque .no { font-size: 10px; letter-spacing: .42em; margin-bottom: 3px; }
.stage.tall .plaque h1 {
  font-size: clamp(22px, 7.2vw, 34px);
  letter-spacing: .22em;
}
.stage.tall .read {
  top: 102vw;
  width: 88vw;
  max-height: min(30vw, 24vh);
}
.stage.tall .surface {
  font-size: 13px;
  line-height: 1.75;
}
.stage.tall .dossier {
  left: 50%;
  right: auto;
  transform: translateX(-50%);
  top: auto;
  bottom: 10.5vh;
  width: 90vw;
  max-height: 24vh;
  background: linear-gradient(180deg, rgba(16, 12, 8, .72), rgba(8, 6, 4, .5));
  padding: 9px 10px 8px;
}
.stage.tall .player { margin-bottom: 6px; }
.stage.tall .ledger { max-height: 12vh; }
.stage.tall .ledger .q { font-size: 12px; }
.stage.tall .ledger .a { font-size: 14px; }
.stage.tall .board-open { margin-top: 8px; padding: 6px 0; font-size: 13px; }
.stage.tall .board-sheet { width: 88vw; max-height: 66vh; }

.stage.tall .dock {
  bottom: 4vh;
  width: 86vw;
  grid-template-columns: 1fr 48px;
  gap: 8px;
}
.stage.tall .type-line input { font-size: 15px; padding: 7px 10px; }
.stage.tall .ask-btn { height: 36px; padding: 0 10px; }
.stage.tall .mic { width: 48px; height: 48px; }
.stage.tall .mic svg { width: 23px; height: 23px; }

.stage.tall .heard {
  bottom: 25vh;
  font-size: 14px;
  width: 88vw;
}
.stage.tall .status { bottom: 0.8vh; font-size: 10px; letter-spacing: .3em; }
.stage.tall .mic-cap { bottom: 0.8vh; font-size: 10px; }
.stage.tall .mic-cap { display: none; }
.stage.tall .hint { top: auto; bottom: 34vh; font-size: 11px; letter-spacing: .22em; }

.stage.tall .stamp { font-size: clamp(30px, 11vw, 54px); top: 45%; }
.stage.tall .reveal-plate { min-width: 62vw; padding: 16px 18px 14px; }
.stage.tall .reveal-title { font-size: clamp(26px, 8vw, 40px); }
.stage.tall .reveal-kicker { font-size: 10px; }

/* 矮屏（横过来的窄窗口）别把元素叠在一起 */
@media (max-height: 560px) {
  .stage.tall .dossier { display: none; }
  .stage.tall .heard { bottom: 20vh; }
}

/* ---------------- 滚动条：跟界面同一套材质 ----------------
   默认的白轨道＋灰滑块在这套暗金里太跳，改成一条窄的暗金细轨。
   Chrome/Edge/Safari 走 ::-webkit-scrollbar；Firefox 没有这套伪元素，
   只能靠 scrollbar-color（两者互斥，所以用 @supports 隔开）。 */
.stage ::-webkit-scrollbar { width: 8px; height: 8px; }
.stage ::-webkit-scrollbar-track {
  background: rgba(8, 6, 4, .72);
  border-radius: 4px;
}
.stage ::-webkit-scrollbar-thumb {
  border-radius: 4px;
  background: linear-gradient(180deg, rgba(215, 176, 113, .62), rgba(140, 110, 66, .5));
  box-shadow: inset 0 0 0 1px rgba(196, 163, 106, .28);
}
.stage ::-webkit-scrollbar-thumb:hover {
  background: linear-gradient(180deg, #d7b071, rgba(196, 163, 106, .8));
}
.stage ::-webkit-scrollbar-corner { background: transparent; }

@supports not selector(::-webkit-scrollbar) {
  .stage, .stage * {
    scrollbar-width: thin;
    scrollbar-color: rgba(196, 163, 106, .55) rgba(8, 6, 4, .72);
  }
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}
