/* ============================================================
   mv.css —— 16:9 舞台（1920 × 1080）
   正式页面与分镜缩略图共用这套样式，缩略图只是 transform: scale()
   ============================================================ */

.stage {
  position: relative;
  width: 1920px;
  height: 1080px;
  overflow: hidden;
  flex: none;

  background: var(--stage-bg, #E7F0FA);
  color: var(--ink);
  font-family: var(--f-cn);
  font-weight: 400;

  /* 可被 inline style 覆盖 */
  --u: 220px;      /* 主标题基准字号 */
  --s: 1;          /* 字号档（0.62 / 0.7 / 0.85 / 1 / 1.15 / 1.2 …） */
  --dot: 8;        /* 点阵间距 px */
}

/* 点阵纸 */
.stage .dots {
  position: absolute;
  inset: 0;
  background-image: radial-gradient(circle at 1px 1px, var(--dot-cor, #C6D8EC) 1.2px, transparent 0);
  background-size: calc(var(--dot) * 1px) calc(var(--dot) * 1px);
  pointer-events: none;
}

/* ---------- 文字区 ---------- */
.stage .body {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  /* ⚠️ padding 的百分比是相对「包含块宽度」算的（1920），不是高度！
     所以这里必须用 px：22% × 1080 = 237.6px */
  padding: 238px 6% 0;
  text-align: center;
}

/* 行数越少，文字块整体越往下（视觉重心更居中）；eng / code 在流里会自动跟随 */
.stage[data-lines="1"] .body { padding-top: 300px; }
.stage[data-lines="2"] .body { padding-top: 258px; }

.stage[data-align="left"] .body {
  align-items: flex-start;
  text-align: left;
  padding: 281px 6% 0;          /* 26% × 1080 */
}

.stage[data-align="left"][data-lines="1"] .body { padding-top: 330px; }
.stage[data-align="left"][data-lines="2"] .body { padding-top: 290px; }

/* 右侧有字符画、且主句很长时：把文字区收窄，别和黑色字符画撞在一起 */
.stage.has-right-deco .body {
  padding-right: 28%;
}

.stage[data-align="left"].has-right-deco .body {
  padding-right: 28%;
}

.stage .hero {
  font-family: var(--f-cn);
  font-weight: 700;              /* 只有正片用 Bold */
  font-size: calc(var(--u) * var(--s));
  line-height: 1.08;
  letter-spacing: -0.015em;
  color: var(--ink);
}

.stage .hero .line { display: block; }

/* 行内强调（数据里用 <em class="o|b|g">） */
.stage em.o { color: var(--orange); font-style: normal; }
.stage em.b { color: var(--blue);   font-style: normal; }
.stage em.g { color: var(--green);  font-style: normal; }

/* 英文副标题：永远压在中文主标题下方 */
.stage .eng {
  margin-top: 0.18em;
  font-family: var(--f-mono);
  font-size: calc(var(--u) * var(--s) * 0.2);
  line-height: 1.3;
  letter-spacing: 0.01em;
  color: var(--sub);
}

/* ---------- 代码金句 ---------- */
.stage .code {
  margin-top: 0.38em;
  padding: 0;
  font-family: var(--f-mono);
  font-size: calc(var(--u) * 0.19 * var(--cs, 1));
  line-height: 1.5;
  color: #33414F;              /* plain token 的底色：深灰蓝，好和紫/蓝/绿/橙拉开 */
  white-space: pre;
  text-align: left;
  align-self: center;          /* 代码块整体居中，别在左侧飘着 */
}

.stage[data-align="left"] .code {
  align-self: flex-start;   /* 左对齐镜头里，代码也跟着文字靠左 */
}

.stage .code .cn {
  font-family: var(--f-cn);
  font-weight: 700;              /* 中文比符号粗，是混排的关键 */
  color: var(--ink);
}

/* ---------- 语法高亮配色（不追求标准，只求结构可分） ---------- */
.stage .code .key  { color: var(--blue); }                  /* JSON 键名   蓝 */
.stage .code .str  { color: var(--green); }                 /* 字符串      绿 */
.stage .code .kw   { color: #7C3AED; }                      /* 关键字/布尔 紫 */
.stage .code .fn   { color: var(--blue); }                  /* 函数名      蓝 */
.stage .code .num  { color: var(--orange); }                /* 数字        橙 */
.stage .code .pun  { color: #93A6B8; }                      /* 标点        灰 */
.stage .code .cmt  { color: #7A8B9A; font-style: italic; }  /* 注释        灰斜 */
.stage .code .tag  { color: var(--blue); }                  /* XML 标签    蓝 */
.stage .code .attr { color: #7C3AED; }                      /* XML 属性名  紫 */

/* "刚滑入"的片段：底色 + 左侧竖线，像编辑器里刚插入的一段 */
.stage .code .ins {
  background: rgba(34, 197, 94, .16);
  box-shadow: inset 2px 0 0 var(--green);
  border-radius: 2px;
  padding: 0 2px 0 4px;
}

/* 整段代码里"注释当标题用"时的强调色（8-1 的 // 幸福永远） */
.stage .code.accent .cmt,
.stage .code.accent .cmt .cn {
  color: var(--orange);
  font-style: normal;
  font-weight: 400;
}

/* zoomLine：被点名的那一行单独缩放，不改变其余行的排版 */
.stage .code .zoom {
  display: inline-block;
  transform-origin: center center;
  will-change: transform;
}

/* ---------- 同学留言：语音条 + 逐字字幕 ---------- */

/* 页面标题 */
.stage .voicetitle {
  position: absolute;
  left: 0;
  right: 0;
  top: 6%;
  text-align: center;
  z-index: 3;
}

.stage .voicetitle .vt-cn {
  display: block;
  font-size: calc(var(--u) * 0.32);
  font-weight: 700;
  letter-spacing: .04em;
  color: var(--ink);
}

.stage .voicetitle .vt-sub {
  display: block;
  margin-top: .72em;
  font-size: calc(var(--u) * 0.11);
  font-weight: 400;
  color: var(--sub);
  letter-spacing: .22em;
}

.stage .voicetitle .vt-en {
  display: block;
  margin-top: .62em;
  font-family: var(--f-mono);
  font-size: calc(var(--u) * 0.062);
  color: var(--deco);
  letter-spacing: .16em;
}

/* 左侧：语音条 */
.stage .voicelist {
  position: absolute;
  left: 6%;
  top: 24%;
  width: 37%;
  display: flex;
  flex-direction: column;
  align-items: flex-start;      /* 关键：胶囊宽度由内容决定，而不是撑满整栏 */
  gap: 22px;
  z-index: 3;
  /* 条数多时 JS 写 --vs 整块等比缩小；从左上方缩放，不会顶到标题和字幕框 */
  transform-origin: left top;
  transform: scale(var(--vs, 1));
}

/* 一组 = 人名在上 + 语音条在下 */
.stage .vstack {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.stage .vname {
  padding-left: 10px;
  font-family: var(--f-mono);
  font-size: 27px;
  color: var(--sub);
  letter-spacing: .1em;
  transition: color .2s;
}

.stage .vstack:has(.voice.is-on) .vname {
  color: var(--orange);
}

/* 条数多时自动压一点，保证字幕还在下方待得住 */
/* 条数多时靠 --vs 整体缩放，这里只微调间距 */
.stage .voicelist[data-n="4"] { gap: 18px; }

.voice {
  display: flex;
  align-items: center;
  gap: 18px;
  height: 84px;
  padding: 0 26px 0 12px;
  border-radius: 42px;
  background: #FFFFFF;
  box-shadow: 0 2px 0 rgba(11, 14, 18, .06), 0 10px 28px rgba(11, 14, 18, .07);
  cursor: pointer;
  transition: transform .18s ease, box-shadow .18s ease;
  user-select: none;
}

.voice:hover {
  transform: translateX(4px);
  box-shadow: 0 2px 0 rgba(11, 14, 18, .06), 0 10px 28px rgba(11, 14, 18, .12);
}

.voice.is-on {
  background: #FFFFFF;
  box-shadow: 0 0 0 2px var(--orange), 0 10px 28px rgba(11, 14, 18, .12);
}

/* 播放键 */
.voice .vp {
  flex: none;
  width: 58px;
  height: 58px;
  border-radius: 50%;
  border: 0;
  background: #F2F5F9;
  position: relative;
  cursor: pointer;
  transition: background .18s;
}

.voice .vp::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-38%, -50%);
  border-style: solid;
  border-width: 10px 0 10px 16px;
  border-color: transparent transparent transparent var(--ink);
}

.voice.is-on .vp::after {
  transform: translate(-50%, -50%);
  border: 0;
  width: 20px;
  height: 24px;
  border-left: 7px solid var(--ink);
  border-right: 7px solid var(--ink);
}

/* 波形：条细、间距小、整体矮——高低差才看得出来 */
.voice .vw {
  display: flex;
  align-items: center;
  gap: 3px;
  height: 30px;
}

.voice .vw i {
  display: block;
  width: 3px;
  height: var(--h, 20px);
  border-radius: 2px;
  background: var(--ink);
  opacity: .84;
  transform-origin: center;
}

/* 已播过的部分变成橙色（像 Audacity 那样，不做假跳动） */
.voice .vw i.played {
  background: var(--orange);
  opacity: 1;
}

.voice.is-on .vw i {
  opacity: .95;
}

/* 时长 */
.voice .vd {
  flex: none;
  font-family: var(--f-mono);
  font-size: 22px;
  color: var(--ink);
  letter-spacing: .02em;
}

/* 右侧：字幕框（圆角矩形，内容自动滚动） */
.stage .voicesub {
  position: absolute;
  left: 43%;
  right: 5%;
  top: 28%;
  bottom: 14%;
  padding: 42px 44px;
  border-radius: 32px;
  background: rgba(255, 255, 255, .78);
  box-shadow: 0 2px 0 rgba(11, 14, 18, .04), 0 14px 40px rgba(11, 14, 18, .06);
  overflow: hidden;
  z-index: 3;
}

.stage .voicesub .vscroll {
  transition: transform .55s cubic-bezier(.22, .61, .36, 1);
  will-change: transform;
}

.stage .voicesub .vline {
  display: block;
  margin-bottom: .22em;
  font-size: calc(var(--u) * 0.19);
  line-height: 1.36;
  color: #A8B6C4;                 /* 还没读到的句子：浅灰 */
  letter-spacing: .01em;
  transition: color .3s;
}

.stage .voicesub .vline.is-done {
  color: var(--sub);
}

.stage .voicesub .vline.is-cur {
  color: var(--ink);
  font-weight: 700;
}

.stage .voicesub .vc {
  opacity: 0;
  transition: opacity .16s linear;
}

.stage .voicesub .vc.on {
  opacity: 1;
}

/* 没播放时的占位 */
.stage .voicesub .vscroll:empty::before {
  content: "点击左侧语音条，听听同学们说了什么";
  display: block;
  padding-top: 34%;
  text-align: center;
  font-size: calc(var(--u) * 0.098);
  font-weight: 400;
  color: var(--deco);
  letter-spacing: .12em;
}
.stage .deco {
  position: absolute;
  transform: translate(-50%, -50%);
  font-family: var(--f-mono);
  font-size: calc(var(--u) * 0.12 * var(--ds, 1));
  line-height: 1.02;
  color: var(--ink);          /* 字符画用黑色：和主文字同一支笔，才有存在感 */
  white-space: pre;
  pointer-events: none;
}

.stage .deco pre {
  margin: 0;
  font: inherit;
  color: inherit;
}

/* 装饰里的 1–3 个强调字符 */
.stage .deco em.w { color: var(--orange-l); font-style: normal; }  /* 火苗 */
.stage .deco em.g { color: var(--green-l);  font-style: normal; }  /* 机器人天线 */
.stage .deco em.h { color: var(--orange-l); font-style: normal; }  /* 日历高亮 */
.stage .deco em.r { color: #E5484D; font-style: normal; }           /* 红心：情绪高潮 */
/* 花：花瓣 / 花蕊 / 茎叶 三色分工 */
.stage .deco em.fp { color: var(--orange);             font-style: normal; }  /* 花瓣 橙 */
.stage .deco em.fc { color: #D9A200;                   font-style: normal; }  /* 花蕊 黄 */
.stage .deco em.fs { color: var(--green);              font-style: normal; }  /* 茎叶 绿 */

/* ---------- emoji ---------- */
.stage .emoji {
  position: absolute;
  transform: translate(-50%, -50%);
  /* 直接命中 emoji 字体，别让浏览器先去试等宽字体再回退——那会让第一个 emoji 明显慢一拍 */
  font-family: "Segoe UI Emoji", "Apple Color Emoji", "Noto Color Emoji",
               "Segoe UI Symbol", sans-serif;
  font-size: calc(var(--u) * 0.42 * var(--ds, 1));
  line-height: 1;
  pointer-events: none;
  filter: saturate(1.06);
}

/* 留言页四角的彩带 / 蛋糕：轻轻上下浮
   错峰延迟由 JS 直接写 animation-delay（nth-of-type 在混着别的 div 时不可靠） */
.stage .emoji.corner {
  animation: cornerFloat 4.2s ease-in-out infinite;
}

@keyframes cornerFloat {
  0%, 100% { transform: translate(-50%, -50%); }
  50%      { transform: translate(-50%, calc(-50% - 12px)); }
}

/* emoji 人群矩阵（一排排学生） */.stage .deco.crowd {
  font-family: "Segoe UI Emoji", "Apple Color Emoji", "Noto Color Emoji", sans-serif;
  font-size: calc(var(--u) * 0.2 * var(--ds, 1));
  line-height: 1;
  white-space: normal;
  color: var(--ink);
}

.stage .deco.crowd .crowd-row {
  display: flex;
  justify-content: center;
  gap: 0.42em;
  margin-bottom: 0.55em;
}

.stage .deco.crowd .crowd-row:last-child {
  margin-bottom: 0;
}

.stage .deco.crowd .crowd-item {
  display: block;
  width: 1.15em;
  line-height: 1.15;
  text-align: center;
}

/* ---------- 音符 / 波形 / 进度条（渲染器生成的碎片） ---------- */
.stage .deco .note {
  display: inline-block;
  color: var(--ink);
  font-size: calc(var(--u) * 0.2 * var(--ds, 1));
  margin: 0 0.35em;
}

.stage .deco .wave {
  color: var(--ink);
  letter-spacing: 0.28em;
}

.stage .deco .bar {
  color: var(--ink);
}

.stage .deco .bar .fill {
  color: var(--green);
}

.stage .deco .checks i {
  font-style: normal;
  color: var(--green);
  margin-right: 0.4em;
}

.stage .deco .row {
  color: var(--sub);
  letter-spacing: 0.18em;
}

/* 静止 / 缩略图里不做动画；正式页由 js/mv.js 加 .is-live 再启用 */
.stage .fade-50 { opacity: 0.5; }
