:root {
  --void: #0d0e0d;
  --night: #171714;
  --ink: #25241f;
  --bone: #eee7d7;
  --quiet: #b8ab91;
  --gold: #cba15e;
  --gold-pale: #e4c582;
  --display: STKaiti, "Kaiti SC", "Songti SC", serif;
  --body: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
}

* { box-sizing: border-box; }

html,
body {
  width: 100%;
  min-height: 100%;
  margin: 0;
  overflow: hidden;
  background: var(--void);
}

body {
  color: var(--bone);
  font-family: var(--body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  -webkit-tap-highlight-color: transparent;
}

button { font: inherit; }

button:focus-visible {
  outline: 1px solid var(--gold-pale);
  outline-offset: 4px;
}

img { display: block; }

.immersive-stage img {
  -webkit-user-drag: none;
  user-select: none;
}

[hidden] { display: none !important; }

.app-shell {
  position: relative;
  width: 100%;
  min-width: 320px;
  height: 100dvh;
  min-height: 560px;
  overflow: hidden;
  isolation: isolate;
  background: var(--void);
  --camera-x: 19%;
  --camera-offset-x: -19%;
  --scene-zoom: 1;
  --scene-y: 63%;
  --world-pan-x: 0px;
  --world-pan-y: 0px;
  --role-focus-tile-width: min(22dvh, 180px);
  --role-focus-tile-half-height: min(22.25dvh, 182px);
  --focus-tile-width: var(--role-focus-tile-width);
  --focus-tile-half-height: var(--role-focus-tile-half-height);
  --text-card-gap: -36px;
  --text-card-width: min(360px, calc(100vw - var(--role-focus-tile-width) - var(--text-card-gap) - 16px));
  --reading-top: calc(55% - var(--role-focus-tile-half-height));
  --reading-left: max(
    12px,
    calc(50vw - (var(--text-card-width) + var(--text-card-gap) + var(--role-focus-tile-width)) / 2 - clamp(22px, 5vw, 42px))
  );
  --reading-right: min(
    calc(100vw - 12px),
    calc(50vw + (var(--text-card-width) + var(--text-card-gap) + var(--role-focus-tile-width)) / 2 - clamp(18px, 4vw, 36px))
  );
  --sanyue-card-gap: 24px;
  --text-card-ink-left: 0.248;
  --sanyue-card-ink-right: 0.891;
  --text-card-content-offset-y: -16.75%;
  --sanyue-card-content-offset-y: -3.4%;
}

.immersive-stage {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  touch-action: none;
  background: var(--void);
}

.immersive-stage::before {
  position: absolute;
  z-index: 11;
  inset: 0;
  content: "";
  pointer-events: none;
  opacity: 0.16;
  background-image: radial-gradient(rgba(233, 206, 154, 0.28) 0.45px, transparent 0.72px);
  background-size: 5px 5px;
}

.stage-camera {
  position: absolute;
  z-index: 1;
  top: 0;
  left: 50%;
  width: calc(100dvh * 2.332);
  height: 100%;
  transform: translateX(var(--camera-offset-x));
  will-change: transform;
  backface-visibility: hidden;
  transition: transform 940ms cubic-bezier(0.16, 1, 0.3, 1);
}

.stage-world {
  position: relative;
  width: 100%;
  height: 100%;
  transform: translate3d(var(--world-pan-x), var(--world-pan-y), 0) scale(var(--scene-zoom));
  transform-origin: var(--camera-x) var(--scene-y);
  will-change: transform;
  backface-visibility: hidden;
  transition: transform 940ms cubic-bezier(0.16, 1, 0.3, 1);
}

.stage-world__background {
  width: 100%;
  height: 100%;
  object-fit: fill;
  user-select: none;
}

.stage-world__veil {
  --sight-x: 50%;
  --sight-y: 58%;
  --sight-radius: 188px;
  position: absolute;
  z-index: 5;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  background: rgba(2, 3, 2, 0.86);
  transition: opacity 420ms ease;
}

.figure-set {
  position: absolute;
  z-index: 3;
  pointer-events: none;
}

/* 底图实测校准：六梃五格窗，x 28.53%–37.24%；高度取线稿原比例(900×386)避免纵向拉伸 */
.figure-set--zaju {
  top: 59.7%;
  left: 28.53%;
  width: 8.71%;
  height: 8.71%;
}

/* 散乐窗：竖梃 x 51.29%–59.82%，窗身与杂剧同一水平线、同一窗高 */
.figure-set--sanyue {
  top: 59.7%;
  left: 51.29%;
  width: 8.53%;
  height: 8.71%;
  opacity: 0.12;
  transition: opacity 700ms ease;
}

/* 贴近散乐窗时，五人作为整体一同浮现并可被照见。 */
.app-shell[data-mode="explore"].is-near-sanyue .figure-set--sanyue {
  opacity: 0.82;
}

/* 线稿五片段：每格独立切图，与底图窗格立柱严格对齐 */
.figure-slice {
  position: absolute;
  top: 2%;
  height: 96%;
  width: 20%;
  background-repeat: no-repeat;
  background-size: 500% 100%;
  filter: invert(77%) sepia(18%) saturate(1020%) hue-rotate(359deg) brightness(100%) contrast(88%);
  mix-blend-mode: screen;
}

.figure-slice--sanyue { background-image: url("../assets/diagrams/sanyue-five-outline.png"); }
.figure-slice--sanyue:nth-child(1) { left: 0; background-position: 0 50%; }
.figure-slice--sanyue:nth-child(2) { left: 20%; background-position: 25% 50%; }
.figure-slice--sanyue:nth-child(3) { left: 40%; background-position: 50% 50%; }
.figure-slice--sanyue:nth-child(4) { left: 60%; background-position: 75% 50%; }
.figure-slice--sanyue:nth-child(5) { left: 80%; background-position: 100% 50%; }

.sanyue-hotspot {
  position: absolute;
  z-index: 4;
  inset: 0;
  padding: 0;
  cursor: pointer;
  pointer-events: auto;
  background: transparent;
  border: 0;
}

/* 砖下积光：靠近时暖光落在整组砖下沿，替代圆圈符号 */
.sanyue-hotspot::after {
  position: absolute;
  bottom: -5%;
  left: 50%;
  width: 88%;
  height: 10px;
  content: "";
  opacity: 0;
  background: radial-gradient(ellipse at center, rgba(255, 216, 146, 0.6), rgba(255, 216, 146, 0) 68%);
  transform: translateX(-50%) scaleX(0.7);
  transition: opacity 300ms ease, transform 480ms cubic-bezier(0.16, 1, 0.3, 1);
  pointer-events: none;
}

.app-shell[data-mode="explore"].is-near-sanyue .sanyue-hotspot::after {
  opacity: 0.75;
  transform: translateX(-50%) scaleX(1);
}

.sanyue-hotspot.is-visited::after { opacity: 0.18; }

.sanyue-hotspot.is-active::after { opacity: 1; }

.figure-set__evidence {
  position: absolute;
  z-index: 1;
  top: 50%;
  left: 50%;
  width: 118%;
  height: auto;
  opacity: 0;
  transform: translate(-50%, -50%);
  transition: opacity 700ms ease;
}

.role-evidence-layer {
  position: absolute;
  z-index: 3;
  inset: 0;
}

.role-evidence {
  position: absolute;
  top: 50%;
  width: auto;
  height: 94%;
  max-width: none;
  opacity: 0;
  transform: translate(-50%, -50%) scale(0.9);
}

.role-evidence--fumo { left: 90%; }
.role-evidence--yinxi { left: 70%; }
.role-evidence--zhuanggu { left: 50%; }
.role-evidence--fujing { left: 30%; }
.role-evidence--moni { left: 10%; }

.role-hotspot-layer {
  position: absolute;
  z-index: 6;
  top: 59.7%;
  left: 28.53%;
  width: 8.71%;
  height: 8.71%;
}

.role-hotspot {
  position: absolute;
  z-index: 1;
  top: 0;
  width: 20%;
  height: 100%;
  padding: 0;
  cursor: pointer;
  background: transparent;
  border: 0;
  border-radius: 1px;
  transform: translateX(-50%);
}

/* 每个热点格内切显示线稿对应人物，天然与窗格对齐 */
.role-hotspot::before {
  position: absolute;
  inset: 2% 0;
  content: "";
  pointer-events: none;
  background: url("../assets/diagrams/zaju-five-outline.png") no-repeat;
  background-size: 500% 100%;
  background-position: var(--slice, 50%) 50%;
  filter: invert(77%) sepia(18%) saturate(1020%) hue-rotate(359deg) brightness(100%) contrast(88%);
  mix-blend-mode: screen;
  opacity: 0.15;
  transition: opacity 380ms ease;
}

/* 砖下积光：靠近时暖光落在每个人物砖下沿，替代圆圈符号 */
.role-hotspot::after {
  position: absolute;
  bottom: -5%;
  left: 50%;
  width: 78%;
  height: 9px;
  content: "";
  opacity: 0;
  background: radial-gradient(ellipse at center, rgba(255, 216, 146, 0.6), rgba(255, 216, 146, 0) 68%);
  transform: translateX(-50%) scaleX(0.7);
  transition: opacity 300ms ease, transform 480ms cubic-bezier(0.16, 1, 0.3, 1);
  pointer-events: none;
}

.role-hotspot.is-visited::after { opacity: 0.18; }

.role-hotspot.is-active::after { opacity: 1; }

.role-hotspot--fumo { left: 90%; --slice: 100%; }
.role-hotspot--yinxi { left: 70%; --slice: 75%; }
.role-hotspot--zhuanggu { left: 50%; --slice: 50%; }
.role-hotspot--fujing { left: 30%; --slice: 25%; }
.role-hotspot--moni { left: 10%; --slice: 0%; }

.entry-screen {
  position: absolute;
  z-index: 12;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  opacity: 0;
  background: #eee7d7;
  transform: translateZ(0);
  will-change: opacity;
  transition: opacity 800ms ease;
}

.entry-screen__image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

.paper-back {
  position: absolute;
  z-index: 11;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  visibility: hidden;
  opacity: 0;
  background: #17120e;
  transform: translateZ(0);
  will-change: opacity;
  transition: opacity 320ms ease, visibility 0s linear 320ms;
}

.paper-back__image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

.app-shell[data-mode="threshold"] .paper-back,
.app-shell[data-mode="opening"] .paper-back,
.app-shell[data-mode="playbill"] .paper-back,
.app-shell.is-returning .paper-back {
  visibility: visible;
  opacity: 1;
  transition: opacity 320ms ease, visibility 0s linear;
}

.app-shell[data-mode="explore"] .paper-back,
.app-shell[data-mode="reading"] .paper-back,
.app-shell[data-mode="leaving"] .paper-back,
.app-shell[data-mode="closing"] .paper-back,
.app-shell[data-mode="playbill-dissolving"] .paper-back {
  visibility: hidden;
  opacity: 0;
  transition: none;
}

.playbill-screen {
  position: absolute;
  z-index: 12;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  visibility: hidden;
  opacity: 0;
  background: #070807;
  transform: translateZ(0);
  will-change: opacity;
  transition: opacity 1200ms ease, visibility 0s linear 1200ms;
}

.playbill-screen__image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  opacity: 1;
  will-change: opacity;
}

.app-shell.is-playbill-visible .playbill-screen {
  visibility: visible;
  opacity: 1;
  transition: opacity 1200ms ease 1600ms, visibility 0s linear;
}

.playbill-screen__enter {
  position: absolute;
  z-index: 2;
  inset: 0;
  display: grid;
  place-items: end center;
  padding: 0 0 max(64px, 12vh, calc(env(safe-area-inset-bottom) + 40px));
  border: 0;
  background: transparent;
  color: rgba(58, 48, 35, 0.78);
  cursor: pointer;
  font-family: "Songti SC", STSong, SimSun, serif;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.18em;
  opacity: 0;
  pointer-events: none;
  transition: opacity 480ms ease;
}

.playbill-screen__enter:focus-visible {
  outline: 1px solid rgba(244, 221, 165, 0.72);
  outline-offset: -12px;
}

.app-shell.is-playbill-ready .playbill-screen__enter {
  opacity: 1;
  pointer-events: auto;
}

.app-shell.is-playbill-dissolving .playbill-screen {
  opacity: 0;
  transition: opacity 1200ms ease;
}

.app-shell.is-playbill-dissolving .playbill-screen__enter {
  opacity: 0;
  pointer-events: none;
}

.entry-field {
  position: absolute;
  z-index: 13;
  inset: 0;
  display: grid;
  padding: 0 0 max(64px, 12vh, calc(env(safe-area-inset-bottom) + 40px));
  place-items: end center;
  color: rgba(58, 48, 35, 0.78);
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  background: transparent;
  border: 0;
  transition: opacity 480ms ease;
}

.entry-field__copy {
  font-family: "Songti SC", STSong, SimSun, serif;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.18em;
}

.app-shell.is-entry-screen-ready .entry-screen { opacity: 1; }

.app-shell.is-entry-ready .entry-field {
  opacity: 1;
  pointer-events: auto;
}

.app-shell.is-entering .entry-screen {
  animation: paper-fade-away 1600ms ease both;
}

@keyframes paper-fade-away {
  0% { opacity: 1; }
  100% { opacity: 0; }
}

.app-shell.is-entering .entry-field {
  opacity: 0;
  pointer-events: none;
}

.app-shell.is-returning .entry-screen {
  transition: opacity 1200ms ease 1600ms;
}

.departure-dimmer {
  position: absolute;
  z-index: 14;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  background: rgba(2, 3, 2, 0.98);
  transition: opacity 1200ms ease;
}

.app-shell.is-leaving .departure-dimmer {
  opacity: 1;
  transition: opacity 1200ms ease;
}

.app-shell.is-returning .departure-dimmer {
  opacity: 0;
  transition: none;
}

.closing-screen {
  position: absolute;
  z-index: 24;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  visibility: hidden;
  background: #0f0e0c;
  transition: visibility 0s linear;
}

.closing-screen__image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  opacity: 0;
  transition: opacity 1200ms ease;
}

.closing-screen__return {
  position: absolute;
  left: 50%;
  bottom: max(64px, 12vh, calc(env(safe-area-inset-bottom) + 40px));
  padding: 7px 0 6px 8px;
  color: rgba(58, 48, 35, 0.78);
  font-family: "Songti SC", STSong, SimSun, serif;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.18em;
  cursor: pointer;
  opacity: 0;
  background: transparent;
  border: 0;
  transform: translateX(-50%);
  transition: opacity 420ms ease 1220ms, color 220ms ease;
}

.closing-screen__return:enabled:hover { color: rgba(34, 29, 22, 0.98); }

.app-shell.is-closing .closing-screen {
  pointer-events: auto;
  visibility: visible;
  transition: visibility 0s linear;
}

.app-shell.is-closing .closing-screen__image {
  opacity: 1;
}

.app-shell.is-closing .closing-screen__return { opacity: 1; }

.app-shell.is-returning .closing-screen {
  background: transparent;
}

.app-shell.is-returning .closing-screen__image {
  opacity: 0;
  transition: opacity 1600ms ease;
}

.app-shell.is-returning .closing-screen__return {
  opacity: 0;
  transition: opacity 180ms ease;
}

.explore-hint {
  position: absolute;
  z-index: 10;
  bottom: max(30px, env(safe-area-inset-bottom));
  left: 24px;
  margin: 0;
  color: rgba(225, 200, 152, 0.82);
  font-family: "Songti SC", STSong, SimSun, serif;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.1em;
  opacity: 0;
  pointer-events: none;
  transform: translateY(8px);
  transition: opacity 420ms ease, transform 520ms cubic-bezier(0.16, 1, 0.3, 1);
}

.explore-hint.is-visible { opacity: 1; transform: translateY(0); }

.exit-tab {
  position: absolute;
  z-index: 10;
  right: 20px;
  /* 按钮含 8px 下内边距，22+8=30，使文字基线与探索提示（bottom 30px）共线 */
  bottom: max(22px, calc(env(safe-area-inset-bottom) - 8px));
  padding: 8px 0 8px 10px;
  color: rgba(225, 200, 152, 0.82);
  font-family: "Songti SC", STSong, SimSun, serif;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.1em;
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  background: transparent;
  border: 0;
  transform: translateY(8px);
  transition: opacity 380ms ease, transform 480ms cubic-bezier(0.16, 1, 0.3, 1), color 280ms ease, text-shadow 280ms ease;
}

.exit-tab.is-visible {
  opacity: 1;
  pointer-events: auto;
  transform: translateY(0);
}

.app-shell.has-long-exit-copy .explore-hint.is-visible {
  opacity: 0;
}

.exit-tab.is-complete {
  color: rgba(238, 204, 130, 0.96);
  text-shadow: 0 0 7px rgba(190, 138, 52, 0.5), 0 0 20px rgba(190, 138, 52, 0.22);
}

.exit-tab.is-awaiting-sanyue {
  color: rgba(228, 194, 128, 0.82);
  text-shadow: 0 0 6px rgba(176, 122, 38, 0.3);
}

.exit-tab:enabled:hover {
  color: rgba(246, 216, 156, 1);
  text-shadow: 0 0 8px rgba(190, 138, 52, 0.55), 0 0 22px rgba(190, 138, 52, 0.26);
}

.reading-dimmer {
  position: absolute;
  z-index: 5;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  background: radial-gradient(ellipse 40% 45% at 60% 62%, rgba(9, 10, 9, 0.42), rgba(4, 5, 4, 0.9) 82%);
  transition: opacity 500ms ease;
}

.reading-dimmer.is-visible { opacity: 1; }

.focus-tile {
  position: absolute;
  z-index: 8;
  top: 55%;
  left: 50%;
  width: var(--focus-tile-width);
  aspect-ratio: 135 / 273;
  pointer-events: none;
  transform: translate3d(-50%, -50%, 0);
  transform-origin: center;
  contain: strict;
}

.focus-tile__image {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  opacity: 0;
  visibility: hidden;
  transform: translate3d(0, 0, 0) scale3d(0.72, 0.72, 1);
  will-change: transform, opacity;
  transition: transform 650ms cubic-bezier(0.4, 0, 1, 1), visibility 0s linear 650ms;
}

.focus-tile__image.is-visible {
  opacity: 1;
  visibility: visible;
  transform: translate3d(0, 0, 0) scale3d(1, 1, 1);
  transition: transform 1650ms cubic-bezier(0.16, 1, 0.3, 1), opacity 0s;
}

.focus-tile__image.is-exiting {
  opacity: 0;
  visibility: visible;
  transform: translate3d(0, 0, 0) scale3d(1, 1, 1);
  transition: opacity 650ms ease-out;
}

.app-shell.has-sanyue-text-card {
  --sanyue-visible-width: calc(var(--reading-right) - var(--reading-left));
  --sanyue-visible-height: calc(var(--sanyue-visible-width) * 234 / 612);
  --focus-tile-width: calc(var(--sanyue-visible-width) * 633 / 612);
  --focus-tile-half-height: calc(var(--focus-tile-width) * 127 / 633);
  --sanyue-reading-top: max(
    56px,
    min(
      var(--reading-top),
      calc(
        100dvh -
        var(--sanyue-visible-height) -
        var(--sanyue-card-gap) -
        var(--text-card-width) * 1.36 -
        16px
      )
    )
  );
}

.focus-tile.is-sanyue { aspect-ratio: 633 / 254; }

.role-text-card {
  position: absolute;
  z-index: 7;
  top: 55%;
  left: clamp(12px, 4vw, 44px);
  width: var(--text-card-width);
  aspect-ratio: 800 / 1132;
  pointer-events: none;
  transform: translateY(-50%);
}

.app-shell.has-text-card .focus-tile {
  top: calc(var(--reading-top) + var(--focus-tile-half-height));
  left: calc(var(--reading-right) - var(--focus-tile-width) / 2);
}

.app-shell.has-text-card .role-text-card {
  top: var(--reading-top);
  left: calc(var(--reading-left) - var(--text-card-width) * var(--text-card-ink-left));
  transform: none;
}

/* 引戏砖原图 135×262 比砖框 135:273 略宽，object-fit 上下留白；卡片同步下移补偿量 (273/135 − 262/135) / 2 × 砖宽 */
.app-shell[data-active-role="yinxi"].has-text-card .role-text-card {
  top: calc(var(--reading-top) + var(--focus-tile-width) * 11 / 270);
}

.app-shell.has-sanyue-text-card .focus-tile {
  top: calc(var(--sanyue-reading-top) + var(--focus-tile-width) * 117 / 633);
  left: calc(var(--reading-left) + var(--focus-tile-width) * 0.4826);
}

.app-shell.has-sanyue-text-card .role-text-card {
  top: calc(
    var(--sanyue-reading-top) +
    var(--sanyue-visible-height) +
    var(--sanyue-card-gap)
  );
  left: calc(var(--reading-right) - var(--text-card-width) * var(--sanyue-card-ink-right));
  width: var(--text-card-width);
  transform: none;
}

.app-shell.has-sanyue-text-card .role-text-card__image {
  transform: translate3d(0, var(--sanyue-card-content-offset-y), 0);
}

@media (max-width: 640px) {
  .app-shell {
    --role-focus-tile-width: min(42vw, 220px);
    --role-focus-tile-half-height: min(42.5vw, 222px);
    --focus-tile-width: var(--role-focus-tile-width);
    --focus-tile-half-height: var(--role-focus-tile-half-height);
    --text-card-gap: 16px;
    --text-card-width: min(68vw, 310px);
    --reading-top: clamp(168px, 23dvh, 200px);
    --reading-left: 16px;
    --reading-right: calc(100vw - 16px);
  }

  /* 窄屏阅读页：仅杂剧文字卡整体右移 8px，墨迹左缘 16px→24px，与探索提示左轨一致；散乐卡右对齐不动（2026-08-12 真机反馈） */
  .app-shell.has-text-card:not(.has-sanyue-text-card) .role-text-card {
    left: calc(var(--reading-left) + 8px - var(--text-card-width) * var(--text-card-ink-left));
  }
}

.role-text-card__image {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  opacity: 0;
  transform: translate3d(0, var(--text-card-content-offset-y), 0);
  will-change: opacity;
  transition: opacity 650ms ease-out;
}

.role-text-card__image.is-visible {
  opacity: 1;
  transform: translate3d(0, var(--text-card-content-offset-y), 0);
  transition: opacity 1650ms ease 1050ms;
}

.role-text-card__image.is-exiting {
  opacity: 0;
  transform: translate3d(0, var(--text-card-content-offset-y), 0);
  transition: opacity 650ms ease-out;
}

.role-annotation {
  --annotation-width: min(30vw, 260px);
  --focus-half-height: min(22.24dvh, 182px);
  --focus-height: min(44.48dvh, 364px);
  position: absolute;
  z-index: 10;
  top: calc(55% - var(--focus-half-height));
  left: clamp(24px, 7vw, 72px);
  display: flex;
  flex-direction: column;
  width: var(--annotation-width);
  height: var(--focus-height);
  margin: 0;
  padding: 1px 14px 2px 0;
  opacity: 0;
  text-wrap: pretty;
  background: transparent;
  transform: translateY(10px);
  transition: opacity 420ms ease 1000ms, transform 600ms cubic-bezier(0.16, 1, 0.3, 1) 1000ms;
}

.role-annotation.is-visible { opacity: 1; transform: translateY(0); }

.role-annotation__index {
  display: inline-block;
  align-self: flex-start;
  margin: 0 0 10px;
  padding: 2px 6px 1px;
  color: rgba(228, 191, 118, 0.9);
  font-size: 9px;
  letter-spacing: 0.13em;
  border: 1px solid rgba(218, 177, 102, 0.26);
}

.role-annotation h1 {
  margin: 0;
  color: var(--bone);
  font-family: var(--display);
  font-size: clamp(23px, 6.3vw, 30px);
  font-weight: 500;
  letter-spacing: 0.06em;
  line-height: 1.08;
  text-shadow: 0 2px 18px rgba(0, 0, 0, 0.85);
}

.role-annotation blockquote {
  position: relative;
  margin: 13px 0 0;
  padding-left: 11px;
  color: #f3e7cd;
  font-family: var(--display);
  font-size: clamp(16px, 4.2vw, 21px);
  font-weight: 500;
  line-height: 1.58;
  letter-spacing: 0.025em;
  white-space: pre-line;
  text-shadow: 0 2px 15px rgba(0, 0, 0, 0.76);
}

.role-annotation blockquote::before {
  position: absolute;
  top: 7px;
  bottom: 7px;
  left: 0;
  width: 1px;
  content: "";
  background: linear-gradient(rgba(228, 191, 118, 0.85), rgba(228, 191, 118, 0.08));
}

.role-annotation__detail {
  margin: 6px 0 0;
  color: rgba(202, 186, 156, 0.92);
  font-size: 11px;
  line-height: 1.58;
}

.role-annotation__detail:nth-of-type(2) {
  margin-top: auto;
  padding-top: 10px;
  border-top: 1px solid rgba(218, 177, 102, 0.16);
}

.role-annotation__detail::before {
  color: rgba(226, 185, 108, 0.75);
  letter-spacing: 0.05em;
}

.role-annotation__detail:nth-of-type(2)::before { content: "身段 · "; }
.role-annotation__detail:last-child::before { content: "行当 · "; }

/* 纸页交接期间，墓壁始终留在完整黑场之后，避免从底层闪出。 */
.app-shell[data-mode="threshold"] .stage-world__veil,
.app-shell[data-mode="opening"] .stage-world__veil,
.app-shell[data-mode="playbill"] .stage-world__veil,
.app-shell[data-mode="playbill-dissolving"] .stage-world__veil {
  opacity: 1;
  background: rgb(2, 3, 2);
  transition: opacity 1200ms ease;
}

/* 纸页交接时连同墓室的金色人物提示一并停绘；探索开始后才恢复。 */
.app-shell[data-mode="threshold"] .figure-set,
.app-shell[data-mode="opening"] .figure-set,
.app-shell[data-mode="playbill"] .figure-set,
.app-shell[data-mode="playbill-dissolving"] .figure-set,
.app-shell[data-mode="threshold"] .role-hotspot-layer,
.app-shell[data-mode="opening"] .role-hotspot-layer,
.app-shell[data-mode="playbill"] .role-hotspot-layer,
.app-shell[data-mode="playbill-dissolving"] .role-hotspot-layer {
  visibility: hidden;
}

.app-shell.is-returning .stage-world__veil {
  opacity: 1 !important;
  -webkit-mask-image: none;
  mask-image: none;
  transition: none !important;
}

/* explore：暗幕中留下随指尖移动的微光。 */
.app-shell[data-mode="explore"] .stage-world__veil,
.app-shell[data-mode="leaving"] .stage-world__veil {
  opacity: 1;
  transition: opacity 1400ms ease 0ms;
  -webkit-mask-image: radial-gradient(
    circle var(--sight-radius) at var(--sight-x) var(--sight-y),
    transparent 0%,
    transparent 25%,
    rgba(0, 0, 0, 0.12) 41%,
    rgba(0, 0, 0, 0.64) 72%,
    #000 100%
  );
  mask-image: radial-gradient(
    circle var(--sight-radius) at var(--sight-x) var(--sight-y),
    transparent 0%,
    transparent 25%,
    rgba(0, 0, 0, 0.12) 41%,
    rgba(0, 0, 0, 0.64) 72%,
    #000 100%
  );
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
}

/* 灯光全开：暗幕退至 0，线稿组图全部显现并带烛晕 */
.app-shell.is-lit .stage-world__veil {
  opacity: 0 !important;
  transition: opacity 600ms ease !important;
}
.app-shell.is-lit .figure-set--sanyue { opacity: 1; }
.app-shell.is-lit .role-hotspot::before {
  opacity: 0.85;
  filter: invert(77%) sepia(18%) saturate(1020%) hue-rotate(359deg) brightness(100%) contrast(88%) drop-shadow(0 0 6px rgba(255, 205, 118, 0.5));
}
.app-shell.is-lit .figure-slice {
  filter: invert(77%) sepia(18%) saturate(1020%) hue-rotate(359deg) brightness(100%) contrast(88%) drop-shadow(0 0 6px rgba(255, 205, 118, 0.5));
}

.app-shell[data-mode="explore"].is-near-zaju .role-hotspot::before {
  opacity: 0.95;
  filter: invert(77%) sepia(18%) saturate(1020%) hue-rotate(359deg) brightness(100%) contrast(88%) drop-shadow(0 0 6px rgba(255, 205, 118, 0.55));
}

.app-shell[data-mode="explore"].is-near-zaju .role-hotspot::after {
  opacity: 0.75;
  transform: translateX(-50%) scaleX(1);
}

.app-shell[data-mode="explore"].is-near-sanyue .figure-slice {
  filter: invert(77%) sepia(18%) saturate(1020%) hue-rotate(359deg) brightness(100%) contrast(88%) drop-shadow(0 0 6px rgba(255, 205, 118, 0.55));
}

/* 逐人响应：悬停的人物线稿增亮、砖下积光加强，其余四位压暗退后，以回应本身提示可点 */
.role-hotspot-layer:has(.role-hotspot:hover) .role-hotspot:not(:hover)::before {
  opacity: 0.45;
  filter: invert(77%) sepia(18%) saturate(1020%) hue-rotate(359deg) brightness(100%) contrast(88%);
}

.role-hotspot-layer:has(.role-hotspot:hover) .role-hotspot:not(:hover)::after { opacity: 0.25; }

.app-shell[data-mode="explore"] .role-hotspot:hover::before {
  opacity: 1;
  filter: invert(77%) sepia(18%) saturate(1020%) hue-rotate(359deg) brightness(105%) contrast(88%) drop-shadow(0 0 9px rgba(255, 210, 128, 0.75));
}

.app-shell[data-mode="explore"] .role-hotspot:hover::after {
  opacity: 1;
  transform: translateX(-50%) scaleX(1.06);
}

.app-shell[data-mode="explore"] .sanyue-hotspot:hover::after { opacity: 1; }

.app-shell[data-mode="reading"] .stage-world__veil {
  opacity: 0;
  transition: opacity 160ms ease-out;
}
.app-shell[data-mode="reading"] .role-hotspot::before { opacity: 0.4; }

/* 阅读中被照见的那一位在暗幕上保持微亮，其余退至 0.4 */
.app-shell[data-mode="reading"] .role-hotspot.is-active::before {
  opacity: 0.85;
  filter: invert(77%) sepia(18%) saturate(1020%) hue-rotate(359deg) brightness(100%) contrast(88%) drop-shadow(0 0 6px rgba(255, 205, 118, 0.5));
}

.app-shell.is-dragging .stage-camera { transition: none; }

/* 灯光开关位于右上角、容器原生图标行（返回/转发，约 44pt）之下，仅在探索与近看时可见。 */
.light-toggle {
  position: absolute;
  z-index: 18;
  top: calc(max(18px, env(safe-area-inset-top)) + 52px);
  right: 20px;
  display: flex;
  align-items: center;
  padding: 8px 6px;
  color: rgba(225, 200, 152, 0.82);
  font-family: "Songti SC", STSong, SimSun, serif;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.1em;
  cursor: pointer;
  background: transparent;
  border: 0;
  opacity: 0;
  transition: opacity 400ms ease, color 260ms ease, text-shadow 260ms ease;
  pointer-events: none;
}

.app-shell[data-mode="explore"] .light-toggle,
.app-shell[data-mode="reading"] .light-toggle {
  opacity: 1;
  pointer-events: auto;
}

.light-toggle:hover {
  color: rgba(246, 216, 156, 1);
  text-shadow: 0 0 8px rgba(190, 138, 52, 0.5);
}

/* 全室亮度开关为纯文字签：状态由“点亮/熄灯”文案与文字暖光强弱表达，不使用几何符号。 */
.app-shell.is-lit .light-toggle {
  color: rgba(238, 204, 130, 0.95);
  text-shadow: 0 0 7px rgba(190, 138, 52, 0.45), 0 0 18px rgba(190, 138, 52, 0.2);
}

/* 音乐开关与灯光开关同款文字签，位于其正下方，同在探索与近看时可见。 */
.music-toggle {
  position: absolute;
  z-index: 18;
  top: calc(max(18px, env(safe-area-inset-top)) + 90px);
  right: 20px;
  display: flex;
  align-items: center;
  padding: 8px 6px;
  color: rgba(225, 200, 152, 0.82);
  font-family: "Songti SC", STSong, SimSun, serif;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.1em;
  cursor: pointer;
  background: transparent;
  border: 0;
  opacity: 0;
  transition: opacity 400ms ease, color 260ms ease, text-shadow 260ms ease;
  pointer-events: none;
}

.app-shell[data-mode="explore"] .music-toggle,
.app-shell[data-mode="reading"] .music-toggle {
  opacity: 1;
  pointer-events: auto;
}

.music-toggle:hover {
  color: rgba(246, 216, 156, 1);
  text-shadow: 0 0 8px rgba(190, 138, 52, 0.5);
}

/* 息乐状态仅以文字微暗表达，不加几何符号。 */
.music-toggle[aria-pressed="true"] {
  color: rgba(225, 200, 152, 0.45);
}

@media (max-width: 360px) {
  .explore-hint { left: 20px; }
}

@media (max-height: 680px) {
  .role-annotation blockquote { margin-top: 10px; margin-bottom: 10px; }
  .role-annotation__detail { font-size: 10px; line-height: 1.45; }
}

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