/* ════════════════════════════════════════════════════════════════
   剧场视图（theater）：一张圆桌 + 所有人围坐 + 实时字幕。
   纯 CSS 布景：不加载任何外部图片/CDN，离线可用（仓库铁律）。
   布局：桌面铺满主舞台；窄屏铺满剩余高度，字幕与席位等比缩放。
   ════════════════════════════════════════════════════════════════ */

.theater {
  position: relative;
  flex: 1;
  min-height: 0;
  margin: 6px 0 0;
  border-radius: 14px;
  overflow: hidden;
  border: 1px solid rgba(255, 214, 148, .16);
  box-shadow: 0 18px 60px rgba(0, 0, 0, .55), inset 0 0 60px rgba(0, 0, 0, .6);
  background: var(--panel);
}
.theater[hidden] { display: none !important; }

/* 画面本体：暗色书房 + 顶部灯光的径向渐变，再叠一层书架竖纹 */
.th-scene {
  position: absolute;
  inset: 0;
  overflow: hidden;
  background-color: var(--panel);
  background-image: url('/assets/theater/room.jpg');
  background-size: cover;
  /* 垂直位置由 theater.js 按窗口宽高比动态设置（保证桌沿总落在画面 62% 附近），
     这里给一个 16:9 下的等价缺省值。 */
  background-position: 50% 50%;
}
/* 顶部压暗 + 底部让字幕区更干净：用两层渐变盖在照片上，别让照片细节抢人 */
.th-scene::before {
  content: '';
  position: absolute;
  inset: 0;
  background:
    linear-gradient(180deg, rgba(4, 6, 9, .55) 0%, rgba(4, 6, 9, 0) 26%, rgba(4, 6, 9, 0) 66%, rgba(4, 6, 9, .62) 100%),
    radial-gradient(120% 90% at 50% 42%, transparent 46%, rgba(0, 0, 0, .45) 100%);
  pointer-events: none;
}
/* 极轻的胶片颗粒（CSS 噪点，不用外部纹理） */
.th-scene::after {
  content: '';
  position: absolute;
  inset: 0;
  opacity: .05;
  pointer-events: none;
  background-image:
    repeating-radial-gradient(circle at 17% 32%, rgba(23,20,15,.6) 0 1px, transparent 1px 3px),
    repeating-radial-gradient(circle at 71% 63%, rgba(23,20,15,.5) 0 1px, transparent 1px 4px);
  mix-blend-mode: overlay;
}
.th-vignette { position: absolute; inset: 0; pointer-events: none; background: radial-gradient(130% 100% at 50% 45%, transparent 55%, rgba(0,0,0,.55) 100%); }

/* 背景照片里已经有桌子，这层只保留一层极淡的"桌面反光"作为视觉锚点 */
/* 席位：按百分比定位在椭圆四周，近大远小由 JS 的 --scale 控制 */
.th-seats { position: absolute; inset: 0; }
/* 人数超过上限时的"还有 N 位在座"提示（不影响坐在桌边的人） */
.th-more {
  position: absolute;
  left: 16px;
  bottom: 64px;
  z-index: 80;
  padding: 5px 10px;
  border-radius: 999px;
  background: rgba(8, 11, 15, .72);
  border: 1px solid rgba(200,68,42, .32);
  color: #cfd8e2;
  font-size: var(--fs-1);
  letter-spacing: .02em;
  backdrop-filter: none;
  pointer-events: none;
}
.th-more[hidden] { display: none !important; }
.th-seat {
  position: absolute;
  /* 尺寸不再由宽度百分比决定：每个人物的像素高度由 JS 按"桌沿 + 透视"算好写进 height，
     aspect-ratio:1 让宽度自动等于高度（抠图是正方形）。原来的整圈椭圆布局已废弃。 */
  width: auto;
  height: 22%;
  aspect-ratio: 1;
  transform: translateX(-50%);
  transition: transform .28s cubic-bezier(.2, .8, .2, 1), filter .28s, left .35s, top .35s;
  display: flex;
  flex-direction: column;
  align-items: center;
  pointer-events: none;
}
.th-avatar {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  overflow: hidden;
  border: 2px solid rgba(230, 197, 138, .5);
  background: var(--panel-2);
  /* 环境光 + 接触阴影：让人物像"坐"在椅子上，而不是贴在画面上 */
  box-shadow:
    0 10px 26px rgba(0, 0, 0, .7),
    0 2px 6px rgba(0, 0, 0, .8),
    0 0 0 6px rgba(8, 10, 13, .35);
  display: grid;
  place-items: center;
}
.th-avatar > img { width: 100%; height: 100%; object-fit: cover; display: block; }
.th-emoji { font-size: clamp(18px, 4.2vw, 44px); line-height: 1; }
.th-nameplate {
  position: absolute;
  top: calc(100% + 4px);
  min-width: 84%;
  max-width: 170%;
  padding: 1px 7px;
  border-radius: 4px;
  /* 铜色铭牌：与书房的黄铜灯/皮椅同一套材质语言 */
  background: linear-gradient(180deg, rgba(52, 38, 22, .94), rgba(26, 19, 12, .94));
  border: 1px solid rgba(200,68,42, .45);
  box-shadow: 0 4px 12px rgba(0, 0, 0, .55), inset 0 1px 0 rgba(255, 226, 168, .18);
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.th-name { font-size: clamp(9px, 1.05vw, 13px); color: var(--text); font-weight: 600; }
.th-role { font-size: clamp(8px, .86vw, 11px); color: var(--muted); margin-left: 4px; }

/* ══════════════ 人物"坐进椅子"（transparent cutout）══════════════
   用户原话：「他要坐到椅子上，和背景融合到一起，而不是还是一个头像。」
   做法：透明人物层按桌沿透视摆放，统一压暗 + 暖棕色调融入书房灯光，
   桌沿处用人物自带的 alpha 淡出 + 一层接触阴影做"落座"的接地感。 */
.th-person {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 2;
  /* 统一色调：压暗、加暖棕、降低一点饱和度 —— 和书房的黄铜灯/皮椅融成一张照片 */
  filter: brightness(.84) contrast(1.08) saturate(.82) sepia(.19)
    drop-shadow(0 12px 22px rgba(0, 0, 0, .55));
  transform-origin: 50% 100%;
}
/*
 * 注意：环境光**不能**用 .th-person::after 画渐变 —— 那层元素不跟着人物 alpha 走，
 * 会在透明区域露出一块矩形暗带（实测像给桌面糊了半透明黑方块）。
 * 暖光/压暗放到 canvas 里用 source-atop 只作用在人物像素上（见 render.js）。
 */
.th-person {
  /* 桌沿遮挡：--cut-at 由 JS 按每个人坐在哪张椅子算出来（人物图内的相对高度） */
  -webkit-mask-image: linear-gradient(to bottom,
    #000 calc(var(--cut-at, 120%) - 1.2%),
    rgba(0, 0, 0, 0) calc(var(--cut-at, 120%) + 1.2%));
  mask-image: linear-gradient(to bottom,
    #000 calc(var(--cut-at, 120%) - 1.2%),
    rgba(0, 0, 0, 0) calc(var(--cut-at, 120%) + 1.2%));
}
.th-person > img,
.th-person > canvas {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: contain;
}
/* contain 模式下不要再做"脸部取景缩放"（living.css 的 --liv-z 变量这里不存在） */
.th-person.liv-host > img { transform: none; }
.th-cutout { object-fit: contain; pointer-events: none; }

/* 落座阴影：压在人物下半身与桌沿之间，让人"坐实"而不是浮在桌面上 */
.th-shadow {
  position: absolute;
  left: 50%;
  /* 落座阴影贴在"身体底边"（由 JS 写入 --body-bottom），不是方图底边 */
  top: calc(var(--body-bottom, 78%) - 6%);
  width: 84%;
  height: 20%;
  transform: translateX(-50%);
  background: radial-gradient(ellipse at 50% 45%, rgba(0, 0, 0, .62), rgba(0, 0, 0, 0) 72%);
  filter: blur(7px);
  z-index: 1;
  pointer-events: none;
}

/* 坐落的人物：铭牌变成桌上的"名牌"，声波条收起（有聚光就够了） */
.th-seat.is-seated .th-nameplate {
  /* 坐在桌边时的名牌 = 桌上的黄铜姓名卡：贴在"桌沿遮挡线"下面一点，离本人更近 */
  top: calc(var(--cut-at, 80%) + 0.6%);
  width: max-content;
  min-width: 0;
  max-width: 190px;
  padding: 2px 9px 2px;
  border-radius: 3px;
  /* 深胡桃木 + 黄铜描边的卡片：在暗书房里不抢脸，但一眼能读出名字 */
  transform: perspective(420px) rotateX(18deg) scale(.97);
  transform-origin: 50% 100%;
  background: linear-gradient(180deg, rgba(52, 39, 23, .97), rgba(22, 16, 9, .97));
  border: 1px solid rgba(226, 188, 124, .58);
  box-shadow:
    0 7px 13px rgba(0, 0, 0, .62),
    0 1px 0 rgba(255, 236, 190, .26) inset,
    0 -2px 3px rgba(0, 0, 0, .4) inset;
}
.th-seat.is-seated .th-role { display: none; }
.th-seat.is-seated .th-name {
  font-size: clamp(10px, 1vw, 12px);
  letter-spacing: .04em;
  color: #f4e6c4;
  text-shadow: 0 1px 2px rgba(0, 0, 0, .65);
}
.th-seat.is-seated .th-speaking-bars { display: none !important; }
.th-seat.is-seated .th-avatar { display: none; }
.th-seat.is-seated .th-mic { display: none; }

/* 说话中：人物背后一层暖色光斑（像有一束光打在座位上） */
.th-seat.is-seated.is-speaking::before {
  content: '';
  position: absolute;
  left: 50%;
  top: 42%;
  width: 190%;
  height: 100%;
  transform: translate(-50%, -50%);
  background: radial-gradient(ellipse at 50% 48%, rgba(166,106,31, .22), rgba(166,106,31, 0) 66%);
  filter: blur(8px);
  z-index: 0;
  pointer-events: none;
}

/* 说话中：人物被暖色聚光"点亮"，但不要有圆形外框 */
.th-seat.is-seated.is-speaking .th-person {
  transform: scale(1.015);
  filter: brightness(1.04) contrast(1.05) saturate(1.02) sepia(.06)
    drop-shadow(0 0 26px rgba(255, 186, 84, .55))
    drop-shadow(0 12px 20px rgba(0, 0, 0, .5));
}
.th-seat.is-seated.is-speaking .th-nameplate {
  border-color: rgba(255, 240, 200, .95);
  box-shadow: 0 0 20px rgba(255, 184, 72, .5), 0 7px 12px rgba(0, 0, 0, .55);
}
.th-seat.is-seated.is-speaking .th-shadow {
  background: radial-gradient(ellipse at 50% 45%, rgba(255, 178, 76, .22), rgba(0, 0, 0, .5) 52%, rgba(0, 0, 0, 0) 76%);
}

/* 「我」= 右下角自己的小窗（不占桌边座位） */
.th-seat.is-self {
  border-radius: 12px;
}
.th-self-figure {
  width: 100%;
  height: 100%;
  display: grid;
  place-items: center;
  color: var(--text-2);
  opacity: .82;
  padding: 16%;
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, .5));
}
.th-self-figure .self-figure-svg { width: 100%; height: 100%; }
/* 自视视频（剧场右下角小窗）：与宫格共用一个流，镜像显示 */
.th-seat.is-self .th-avatar { position: relative; }
.th-self-video {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  border-radius: 12px;
  transform: scaleX(-1);
  background: #000;
}
.th-seat.is-self[data-camera="live"] .th-self-figure { display: none; }
.th-seat.is-self .th-avatar {
  border: 2px solid rgba(120, 168, 255, .6);
  border-radius: 12px;
  box-shadow:
    0 0 0 3px rgba(8, 10, 13, .55),
    0 0 22px rgba(96, 148, 255, .18),
    0 12px 30px rgba(0, 0, 0, .65);
  background: linear-gradient(180deg, var(--panel-3), var(--panel-2));
}
.th-seat .th-nameplate { z-index: 6; }
.th-seat .th-mic { z-index: 7; }
.th-seat .th-speaking-bars { z-index: 6; }
.th-seat.is-self .th-nameplate {
  top: calc(100% + 3px);
  min-width: 0;
  max-width: none;
  padding: 1px 9px;
  white-space: nowrap;
}
.th-seat.is-self .th-role { display: none; }

/* 说话中：暖色聚光 + 呼吸环 + 声波条 */
.th-seat.is-speaking { z-index: 90 !important; }
.th-seat.is-speaking .th-avatar {
  border-color: var(--warn);
  box-shadow: 0 0 0 2px rgba(255, 214, 140, .28);
}
.th-seat.is-speaking .th-name { color: var(--warn); }
.th-speaking-bars {
  position: absolute; bottom: -12px; left: 50%; transform: translateX(-50%);
  display: none; gap: 3px; align-items: flex-end; height: 12px;
}
.th-seat.is-speaking .th-speaking-bars { display: flex; }
.th-speaking-bars i {
  width: 3px; border-radius: 2px; background: var(--warn); height: 40%;
  animation: th-bar .9s ease-in-out infinite;
}
.th-speaking-bars i:nth-child(2) { animation-delay: .15s; }
.th-speaking-bars i:nth-child(3) { animation-delay: .3s; }
.th-speaking-bars i:nth-child(4) { animation-delay: .45s; }
.th-mic {
  position: absolute; right: -4px; top: -4px;
  font-size: clamp(10px, 1.2vw, 15px);
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, .8));
}
@keyframes th-breathe {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.035); }
}
@keyframes th-bar {
  0%, 100% { height: 30%; }
  50% { height: 100%; }
}

/* HUD：左上议题 + 元信息 */
.th-hud {
  position: absolute; left: 18px; top: 14px; right: 18px;
  display: flex; flex-direction: column; gap: 4px;
  pointer-events: none;
}
.th-topic-line { display: flex; align-items: center; gap: 8px; min-width: 0; }
.th-live-dot {
  width: 7px; height: 7px; border-radius: 50%; background: var(--danger);
  box-shadow: 0 0 10px rgba(255, 95, 86, .8); flex: none;
  animation: th-pulse 1.8s ease-in-out infinite;
}
.th-topic-line > span:last-child {
  font-size: clamp(12px, 1.35vw, 16px); font-weight: 650; color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  text-shadow: 0 2px 12px rgba(0, 0, 0, .8);
}
.th-meta { font-size: clamp(10px, 1vw, 12px); color: var(--muted); font-variant-numeric: tabular-nums; }
@keyframes th-pulse { 0%, 100% { opacity: .35; } 50% { opacity: 1; } }

/* 字幕条：底部居中，像视频字幕 */
.th-subtitle {
  position: absolute; left: 50%; bottom: 6px; transform: translateX(-50%);
  width: min(66%, 760px);
  padding: 8px 16px 9px;
  border-radius: 8px;
  background: linear-gradient(180deg, rgba(9, 11, 14, .78), rgba(9, 11, 14, .9));
  border: 1px solid rgba(200,68,42, .28);
  backdrop-filter: none;
  box-shadow: 0 12px 34px rgba(0, 0, 0, .5);
  cursor: help;
}
.th-sub-head { display: flex; align-items: center; gap: 8px; margin-bottom: 3px; }
.th-sub-name { font-size: clamp(10px, 1vw, 12px); color: var(--warn); font-weight: 650; }
.th-sub-hint { font-size: var(--fs-1); color: var(--faint); letter-spacing: .04em; }
.th-sub-text {
  font-size: clamp(12px, 1.2vw, 16px); line-height: 1.45; color: var(--text-2);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; min-height: 1.5em;
}
.th-subtitle[data-live="1"] .th-sub-hint { color: var(--warn); }

.th-foot {
  position: absolute; left: 18px; right: 18px; bottom: 12px;
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
}
.th-foot-hint { font-size: var(--fs-1); color: var(--faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.th-back { min-height: 34px; font-size: var(--fs-2); }

/* ── 视图模式：切到剧场时，主舞台只留画面（发言流暂时收起，按 T/返回宫格回来） ── */
#app[data-view="theater"] #seats,
#app[data-view="theater"] #btn-seats-expand,
#app[data-view="theater"] #table-hub,
#app[data-view="theater"] #floor-queue,
#app[data-view="theater"] #mode-hint,
#app[data-view="theater"] #metrics-bar,
#app[data-view="theater"] #present-stage { display: none !important; }
#app[data-view="theater"] .stage { grid-template-columns: minmax(0, 1fr); grid-template-rows: minmax(0, 1fr); }
#app[data-view="theater"] .room-pane { display: flex; flex-direction: column; min-height: 0; height: 100%; }
#app[data-view="theater"] #theater { flex: 1 1 auto; min-height: 0; }
#app[data-view="theater"] .stream-pane { display: none !important; }
#app[data-view="theater"] .room-pane { border-right: 0; padding: 8px 10px 6px; }
#app[data-view="theater"] #theater { display: block !important; }
/* 影院模式下 toast 让出字幕位（否则会盖住正在说的那句话）。
   ⚠️ #toasts 是 body 的子元素、和 #app 是兄弟关系，不是 #app 的后代 ——
   原来写 `#app[data-view=theater] #toasts` 根本匹配不到（死规则），toast 一直压在字幕上。 */
#app[data-view="theater"] ~ #toasts {
  top: auto;
  bottom: calc(var(--dock-h, 84px) + 170px);
}
#app[data-view="theater"] .th-foot { bottom: 8px; }
#app[data-view="grid"] .theater { display: none !important; }

/* 窄屏：剧场铺满剩余高度，席位/字幕按视口缩一点 */
@media (max-width: 760px) {
  /* 手机：席位由 JS 的桌沿布局算出高度，这里只收紧铭牌字号 */

  .th-nameplate { padding: 1px 4px; }
  .th-name { font-size: var(--fs-1); }
  .th-role { display: none; }
  .th-table { top: 52%; width: 78%; height: 30%; }
  .th-subtitle { bottom: 4px; width: 94%; padding: 6px 10px 8px; }
  .th-sub-text { font-size: var(--fs-2); -webkit-line-clamp: 2; }
  /* 手机上「返回宫格」挪到右上（底部空间要留给字幕） */
  .th-foot { top: 46px; right: 10px; left: auto; bottom: auto; }
  .th-foot-hint { display: none; }
  .th-back { min-height: 40px; }
  .th-hud { left: 12px; right: 12px; top: 10px; }
  .th-meta { font-size: var(--fs-1); }
}
