/* ============================================================
 * 日常小镇 · 样式
 * 移动优先；暖色系延续站内体系，但整体更明亮柔和
 * ============================================================ */

:root {
  --lt-grass:    #a8d98a;
  --lt-grass-2:  #9acf7b;
  --lt-grass-3:  #8ec46f;
  --lt-road:     #efe0bd;
  --lt-road-2:   #d9c39a;
  --lt-wall:     #fdf1e0;
  --lt-wood:     #c9955f;
  --lt-ink:      #4a4033;
  --lt-ink-2:    #6b5d4a;
  --lt-sky:      #cfe8f5;
  --lt-panel:    #fffaf2;
  --lt-panel-2:  #f6ead8;
  --lt-line:     #e2d3bd;
  --lt-accent:   #e07a5f;
  --lt-accent-2: #7fb069;
  --lt-gold:     #f2b134;
  --lt-text:     #4a4033;
  --lt-muted:    #8a7a66;
  --lt-shadow:   0 10px 26px rgba(74, 64, 51, .16);
  --lt-radius:   16px;
  --lt-radius-sm:10px;
  --lt-top-h:    56px;
  --lt-dock-h:   68px;

  /* ── UI 视觉系统 v2 追加的令牌（2026-09-24）────────────────────
     规则：纸面（--lt-paper）+ 统一描边（--lt-stroke，2px 墨棕）
           + 底边（--lt-edge，盒子的"厚度"）+ 柔和投影。
     层次只用这三样做，不叠大面积 blur（手机上会掉帧）。 */
  --lt-paper:    #fffaf2;
  --lt-paper-2:  #f7ecdb;
  --lt-paper-3:  #f0e3cf;
  --lt-ink-3:    #8a7f6a;
  --lt-moss:     #7fb069;
  --lt-moss-d:   #5f8f4c;
  --lt-moss-l:   #a8d98a;
  --lt-stroke:   #4a4033;
  --lt-edge:     rgba(74, 64, 51, .26);
  --lt-r-xs:     8px;
  --lt-r-md:     14px;
  --lt-r-lg:     20px;
  --lt-tap:      44px;                     /* 触摸目标下限 */
  --lt-sh-1:     0 1px 0 rgba(74, 64, 51, .10);
  --lt-sh-2:     0 6px 16px rgba(74, 64, 51, .14);
  --lt-sh-press: 0 3px 0 var(--lt-edge), 0 8px 18px rgba(74, 64, 51, .16);
  --lt-safe-t:   env(safe-area-inset-top, 0px);
  --lt-safe-b:   env(safe-area-inset-bottom, 0px);
  --lt-top-full: calc(var(--lt-top-h) + env(safe-area-inset-top, 0px));
  --lt-dock-full:calc(var(--lt-dock-h) + env(safe-area-inset-bottom, 0px));
  /* 夜晚：HUD 换成暖深色纸面，夜里不刺眼但仍然有描边可读 */
  --lt-night-paper:  rgba(38, 34, 30, .90);
  --lt-night-line:   rgba(255, 238, 210, .34);
  --lt-night-text:   #fdf3e2;
  --lt-font: -apple-system, BlinkMacSystemFont, "PingFang SC", "Noto Sans CJK SC",
             "Microsoft YaHei", system-ui, sans-serif;
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

/* 排版分层
   —— 站内传统是零外部资源（不引 CDN、不引字体文件），所以 display 层不靠换字体，
      而靠字重 + 字距 + 字号做出明确对比：display 更重更紧，正文更松更轻。 */
.lt-brand b, .lt-sheet-head h2, .lt-stat b, .lt-empty b, .lt-timer .lt-clock {
  font-weight: 800;
  letter-spacing: -0.015em;
}
.lt-title, .lt-house-label, .lt-dock-btn b { letter-spacing: -0.005em; }
body { letter-spacing: 0.01em; }
.lt-stat b, .lt-timer .lt-clock, .lt-pill b { font-variant-numeric: tabular-nums; }

html, body {
  margin: 0; padding: 0; height: 100%;
  overflow: hidden;
  background: var(--lt-sky);
  color: var(--lt-text);
  font-family: var(--lt-font);
  font-size: 15px;
  line-height: 1.6;
  overscroll-behavior: none;
}

body { display: flex; flex-direction: column; }

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

/* ---------------- 顶部栏 ---------------- */
.lt-top {
  flex: 0 0 auto;
  height: var(--lt-top-h);
  display: flex; align-items: center; gap: 10px;
  padding: 0 12px;
  background: var(--lt-panel);
  border-bottom: 2px solid var(--lt-line);
  position: relative; z-index: 30;
}
.lt-brand { display: flex; align-items: center; gap: 7px; font-size: 16px; white-space: nowrap; }
.lt-brand b { letter-spacing: .02em; }
.lt-logo { display: flex; }

.lt-stats { display: flex; gap: 6px; margin-left: auto; }
.lt-pill {
  display: inline-flex; align-items: center; gap: 3px;
  background: var(--lt-panel-2);
  border: 1.5px solid var(--lt-line);
  border-radius: 999px;
  padding: 3px 9px;
  font-size: 12.5px;
  white-space: nowrap;
}
.lt-pill i { font-style: normal; font-size: 12px; }
.lt-pill b { font-variant-numeric: tabular-nums; }
.lt-pill em { font-style: normal; color: var(--lt-muted); font-size: 11px; }

.lt-tools { display: flex; gap: 4px; }
.lt-ico {
  width: 34px; height: 34px; border-radius: 10px;
  display: grid; place-items: center;
  color: var(--lt-ink-2);
  border: 1.5px solid transparent;
  transition: background .15s, border-color .15s;
}
.lt-ico:hover, .lt-ico:focus-visible { background: var(--lt-panel-2); border-color: var(--lt-line); }
.lt-ico:active { transform: scale(.94); }

/* 窄屏：顶栏必须能完整放下三个按钮 + 三个数据胶囊 */
@media (max-width: 430px) {
  .lt-top { gap: 5px; padding: 0 8px; }
  .lt-brand b { font-size: 15px; }
  .lt-pill { padding: 2px 6px; font-size: 12px; gap: 2px; }
  .lt-pill i svg { width: 13px; height: 13px; }
  .lt-pill em { display: none; }        /* 顶栏加语音按钮后，为它让出空间 */
  .lt-ico { width: 28px; height: 28px; }
  .lt-tools { gap: 1px; }
}
@media (max-width: 375px) {
  .lt-brand b { display: none; }
}

/* ---------------- 小镇视图 ---------------- */
.lt-world-wrap {
  flex: 1 1 auto;
  position: relative;
  overflow: hidden;
  background: var(--lt-grass);
  touch-action: manipulation;
}
.lt-world {
  position: absolute; top: 0; left: 0;
  transform-origin: 0 0;
  will-change: transform;
}
.lt-world.lt-cam-anim { transition: transform .55s cubic-bezier(.4, .1, .2, 1); }

/* 地面纹理 */
.lt-ground { position: absolute; inset: 0; }
.lt-tile { position: absolute; }

/* 房屋 / 工作台 / 装饰 / 道具：统一用绝对定位 */
.lt-obj { position: absolute; transform-origin: 50% 100%; }
.lt-house { filter: drop-shadow(0 3px 0 rgba(74, 64, 51, .10)); transition: transform .18s; }
.lt-house-hit {
  position: absolute; cursor: pointer;
  border-radius: 12px;
  transition: transform .18s, filter .18s;
}
.lt-house-hit:active { transform: scale(.97); }
.lt-house-hit.lt-locked { cursor: not-allowed; filter: grayscale(.75) brightness(1.04); opacity: .72; }
.lt-house-label {
  position: absolute; left: 50%; transform: translateX(-50%);
  background: rgba(255, 250, 242, .94);
  border: 1.5px solid var(--lt-line);
  border-radius: 999px;
  padding: 1px 9px; font-size: 11.5px; white-space: nowrap;
  color: var(--lt-ink-2);
  pointer-events: none;
}
.lt-house-label b { color: var(--lt-text); }
.lt-pct { color: var(--lt-accent); font-weight: 700; font-size: 10.5px; }
.lt-lock-badge {
  position: absolute; left: 50%; top: -6px; transform: translateX(-50%);
  background: var(--lt-ink); color: #fff;
  font-size: 10.5px; padding: 2px 8px; border-radius: 999px; white-space: nowrap;
}

/* 建设度气泡（房子右上角） */
.lt-prog {
  position: absolute; left: 50%; transform: translateX(-50%);
  width: 62px; height: 7px; border-radius: 999px;
  background: rgba(255, 255, 255, .72);
  border: 1.5px solid var(--lt-ink);
  overflow: hidden; pointer-events: none;
}
.lt-prog i { display: block; height: 100%; background: var(--lt-accent); transition: width .5s cubic-bezier(.3, 1.2, .5, 1); }

/* 道路 */
.lt-roads { position: absolute; inset: 0; pointer-events: none; }
/* 装饰层：不吃点击，避免挡住房屋热区 */
.lt-decor { position: absolute; inset: 0; pointer-events: none; }

/* 小人 */
.lt-char-wrap {
  position: absolute; transform-origin: 50% 100%;
  transition: transform .1s linear;
  pointer-events: none;
  z-index: 20;
}
.lt-char-wrap svg { display: block; width: 38px; height: auto; }
.lt-char-shadow { position: absolute; left: 50%; bottom: -3px; transform: translateX(-50%); }

/* 交互提示气泡 */
.lt-bubble {
  position: absolute; left: 50%; transform: translateX(-50%);
  bottom: calc(var(--lt-dock-h) + 14px);
  max-width: min(86vw, 420px);
  background: rgba(255, 250, 242, .97);
  border: 2px solid var(--lt-ink);
  border-radius: 14px;
  padding: 9px 14px;
  font-size: 13.5px; line-height: 1.5;
  box-shadow: var(--lt-shadow);
  z-index: 25;
  animation: lt-pop .3s cubic-bezier(.3, 1.4, .5, 1);
}
.lt-bubble::after {
  content: ''; position: absolute; left: 50%; bottom: -8px; transform: translateX(-50%) rotate(45deg);
  width: 12px; height: 12px; background: rgba(255, 250, 242, .97);
  border-right: 2px solid var(--lt-ink); border-bottom: 2px solid var(--lt-ink);
}
.lt-bubble b { color: var(--lt-accent); }

.lt-hint {
  position: absolute; left: 50%; bottom: 12px; transform: translateX(-50%);
  background: rgba(74, 64, 51, .74); color: #fff;
  padding: 5px 13px; border-radius: 999px; font-size: 12px;
  white-space: nowrap; pointer-events: none;
  transition: opacity .4s;
  max-width: 92vw; overflow: hidden; text-overflow: ellipsis;
}
.lt-hint.lt-gone { opacity: 0; }

/* ---------------- 底部快捷栏 ---------------- */
.lt-dock {
  flex: 0 0 auto;
  height: var(--lt-dock-h);
  display: flex; align-items: center; gap: 8px;
  padding: 0 10px;
  background: var(--lt-panel);
  border-top: 2px solid var(--lt-line);
  overflow-x: auto; overflow-y: hidden;
  scrollbar-width: none;
  position: relative; z-index: 30;
}
.lt-dock::-webkit-scrollbar { display: none; }
.lt-dock-btn {
  flex: 0 0 auto;
  display: flex; flex-direction: column; align-items: center; gap: 1px;
  min-width: 62px; padding: 6px 8px;
  border-radius: var(--lt-radius-sm);
  border: 1.5px solid var(--lt-line);
  background: var(--lt-panel-2);
  font-size: 11.5px; line-height: 1.2;
  transition: transform .14s, background .14s, border-color .14s;
}
.lt-dock-btn b { font-size: 12.5px; }
.lt-dock-btn:active { transform: scale(.95); }
.lt-dock-btn.lt-on { background: #eaf6df; border-color: var(--lt-accent-2); }
.lt-dock-btn.lt-locked { opacity: .55; }
.lt-dock-btn .lt-dot { font-size: 15px; line-height: 1; }
.lt-dock-btn .lt-badge {
  position: absolute; margin-top: -34px; margin-left: 26px;
  background: var(--lt-accent); color: #fff;
  font-size: 10px; padding: 0 5px; border-radius: 999px; min-width: 16px; text-align: center;
}

/* ---------------- 浮层面板 ---------------- */
.lt-sheet { position: fixed; inset: 0; z-index: 100; display: flex; align-items: flex-end; }
.lt-sheet[hidden] { display: none; }
.lt-sheet-backdrop { position: absolute; inset: 0; background: rgba(40, 34, 26, .42); animation: lt-fade .2s; }
.lt-sheet-body {
  position: relative; width: 100%;
  max-height: 88vh; overflow-y: auto;
  background: var(--lt-panel);
  border-radius: 22px 22px 0 0;
  border-top: 2.5px solid var(--lt-ink);
  padding: 0 0 calc(20px + env(safe-area-inset-bottom));
  animation: lt-slide .28s cubic-bezier(.25, .9, .3, 1);
  -webkit-overflow-scrolling: touch;
}

.lt-sheet-head {
  position: sticky; top: 0; z-index: 2;
  display: flex; align-items: center; gap: 10px;
  padding: 14px 16px 12px;
  background: var(--lt-panel);
  border-bottom: 2px solid var(--lt-line);
}
.lt-sheet-head h2 { margin: 0; font-size: 17px; }
.lt-sheet-head .lt-sub { font-size: 12px; color: var(--lt-muted); }
.lt-sheet-head .lt-spacer { flex: 1; }
.lt-x {
  width: 32px; height: 32px; border-radius: 9px; display: grid; place-items: center;
  background: var(--lt-panel-2); border: 1.5px solid var(--lt-line); font-size: 17px; line-height: 1;
}
.lt-x:active { transform: scale(.94); }

.lt-sheet-body > *:not(.lt-sheet-head) { margin-left: 16px; margin-right: 16px; }
.lt-sec { margin-top: 16px; }
.lt-sec-title {
  display: flex; align-items: center; gap: 8px;
  font-size: 12.5px; color: var(--lt-muted); font-weight: 700; letter-spacing: .06em;
  margin: 18px 16px 8px;
}
.lt-sec-title::after { content: ''; flex: 1; height: 1px; background: var(--lt-line); }

/* 建设度条 */
.lt-bar {
  height: 12px; border-radius: 999px; overflow: hidden;
  background: var(--lt-panel-2); border: 2px solid var(--lt-ink);
  margin: 10px 0 4px;
}
.lt-bar i { display: block; height: 100%; background: linear-gradient(90deg, var(--lt-accent-2), #a8d98a); transition: width .6s cubic-bezier(.3, 1.1, .4, 1); }
.lt-bar-note { font-size: 12px; color: var(--lt-muted); }
.lt-bar-note b { color: var(--lt-text); font-variant-numeric: tabular-nums; }

/* ---------------- 按钮 ---------------- */
.lt-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  padding: 10px 16px; border-radius: 12px;
  border: 2px solid var(--lt-ink);
  background: var(--lt-panel);
  font-size: 14px; font-weight: 600;
  box-shadow: 0 2px 0 var(--lt-ink);
  transition: transform .12s, box-shadow .12s, background .12s;
}
.lt-btn:active { transform: translateY(2px); box-shadow: 0 0 0 var(--lt-ink); }
.lt-btn.lt-primary { background: var(--lt-accent-2); color: #fff; }
.lt-btn.lt-warm { background: var(--lt-accent); color: #fff; }
.lt-btn.lt-ghost { box-shadow: none; border-width: 1.5px; border-color: var(--lt-line); background: var(--lt-panel-2); font-weight: 500; }
.lt-btn.lt-ghost:active { transform: scale(.97); }
.lt-btn:disabled { opacity: .5; box-shadow: none; transform: none; }
.lt-btn.lt-block { width: 100%; }
.lt-btn.lt-sm { padding: 6px 11px; font-size: 12.5px; border-width: 1.5px; box-shadow: 0 1.5px 0 var(--lt-ink); }

/* ---------------- 任务卡片 ---------------- */
.lt-task {
  border: 2px solid var(--lt-line); border-radius: var(--lt-radius);
  background: #fff; padding: 12px 13px; margin-bottom: 10px;
  transition: border-color .2s, background .2s;
}
.lt-task.lt-done { background: #f0f8ea; border-color: var(--lt-accent-2); }
.lt-task.lt-running { border-color: var(--lt-gold); background: #fffaf0; }
.lt-task-top { display: flex; align-items: flex-start; gap: 10px; }
.lt-check {
  flex: 0 0 auto; width: 26px; height: 26px; border-radius: 9px;
  border: 2px solid var(--lt-ink); background: #fff;
  display: grid; place-items: center; font-size: 15px; color: #fff;
  transition: background .18s, transform .12s;
}
.lt-check:active { transform: scale(.9); }
.lt-task.lt-done .lt-check { background: var(--lt-accent-2); }
.lt-task-main { flex: 1; min-width: 0; }
.lt-title { font-weight: 600; font-size: 15px; word-break: break-word; }
.lt-task.lt-done .lt-title { text-decoration: line-through; color: var(--lt-muted); }
.lt-task-meta { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 5px; font-size: 11.5px; color: var(--lt-muted); }
.lt-chip {
  display: inline-flex; align-items: center; gap: 3px;
  background: var(--lt-panel-2); border: 1px solid var(--lt-line);
  border-radius: 999px; padding: 1px 8px; font-size: 11px;
}
.lt-chip.lt-fire { background: #fff0e6; border-color: #f0b48f; color: #b4592f; }
.lt-task-acts { display: flex; gap: 6px; align-items: center; }

/* 子项 */
.lt-subs { margin: 10px 0 2px; padding-left: 4px; border-left: 2px dashed var(--lt-line); }
.lt-sub { display: flex; align-items: center; gap: 9px; padding: 5px 0 5px 10px; font-size: 13.5px; }
.lt-sub .lt-check { width: 21px; height: 21px; border-radius: 7px; font-size: 12px; }
.lt-sub.lt-done { color: var(--lt-muted); text-decoration: line-through; }
.lt-sub-name { flex: 1; min-width: 0; word-break: break-word; }

/* 计时器 */
.lt-timer {
  display: flex; align-items: center; gap: 10px;
  margin-top: 10px; padding: 8px 10px;
  background: #fff8e8; border: 1.5px dashed var(--lt-gold); border-radius: 12px;
}
.lt-timer .lt-clock { font-variant-numeric: tabular-nums; font-size: 20px; font-weight: 700; letter-spacing: .03em; }
.lt-timer .lt-tmode { font-size: 11px; color: var(--lt-muted); }
.lt-timer .lt-spacer { flex: 1; }

/* ---------------- 空状态 ---------------- */
.lt-empty { text-align: center; padding: 26px 16px; color: var(--lt-muted); }
.lt-empty .lt-face { font-size: 40px; line-height: 1; margin-bottom: 10px; }
.lt-empty b { display: block; color: var(--lt-text); font-size: 15px; margin-bottom: 4px; }

/* ---------------- 表单 ---------------- */
.lt-field { margin: 12px 0; }
.lt-field label { display: block; font-size: 12.5px; color: var(--lt-muted); margin-bottom: 5px; font-weight: 600; }
.lt-input, .lt-select, .lt-area {
  width: 100%; padding: 11px 12px;
  border: 2px solid var(--lt-line); border-radius: 11px;
  background: #fff; font: inherit; font-size: 14.5px; color: var(--lt-text);
}
.lt-area { min-height: 74px; resize: vertical; }
.lt-input:focus, .lt-select:focus, .lt-area:focus { outline: none; border-color: var(--lt-accent-2); }
.lt-row { display: flex; gap: 8px; flex-wrap: wrap; }
.lt-row > * { flex: 1; min-width: 110px; }

/* 选项按钮组 */
.lt-opts { display: flex; gap: 7px; flex-wrap: wrap; }
.lt-opt {
  padding: 7px 13px; border-radius: 999px;
  border: 2px solid var(--lt-line); background: #fff; font-size: 13px;
}
.lt-opt.lt-on { background: var(--lt-accent-2); border-color: var(--lt-ink); color: #fff; font-weight: 600; }

/* ---------------- 捏人 ---------------- */
.lt-avatar-stage {
  display: flex; flex-direction: column; align-items: center;
  background: linear-gradient(180deg, #dff0cd, #bde0a2);
  border: 2px solid var(--lt-ink); border-radius: var(--lt-radius);
  padding: 16px 0 10px; margin-top: 14px;
}
.lt-avatar-stage svg { width: 118px; height: auto; }
.lt-avatar-name { font-size: 12px; color: var(--lt-ink-2); }
.lt-swatches { display: flex; gap: 8px; flex-wrap: wrap; }
.lt-sw {
  width: 34px; height: 34px; border-radius: 10px;
  border: 2px solid var(--lt-line);
}
.lt-sw.lt-on { border-color: var(--lt-ink); box-shadow: 0 0 0 2px #fff inset, 0 0 0 3px var(--lt-accent-2); }

/* ---------------- 日历热力图 ---------------- */
.lt-cal-head, .lt-cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 5px; }
.lt-cal-head div { text-align: center; font-size: 11px; color: var(--lt-muted); }
.lt-cal-cell {
  aspect-ratio: 1 / 1; border-radius: 7px;
  background: var(--lt-panel-2); border: 1.5px solid var(--lt-line);
  display: grid; place-items: center; font-size: 10.5px; color: var(--lt-muted);
}
.lt-cal-cell.lt-out { opacity: .35; }
.lt-cal-cell.lt-future { opacity: .45; border-style: dashed; }
.lt-cal-cell.lt-l1 { background: #dcefcb; border-color: #b7d9a0; color: #4a6b3a; }
.lt-cal-cell.lt-l2 { background: #b7dda0; border-color: #8fc072; color: #33512a; }
.lt-cal-cell.lt-l3 { background: #8fc072; border-color: #6aa353; color: #fff; }
.lt-cal-cell.lt-l4 { background: #5f9a48; border-color: #47772f; color: #fff; }

/* ---------------- 统计格 ---------------- */
.lt-stats-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 9px; }
.lt-stat {
  background: var(--lt-panel-2); border: 2px solid var(--lt-line);
  border-radius: 13px; padding: 12px 6px; text-align: center;
}
.lt-stat b { display: block; font-size: 21px; line-height: 1.2; font-variant-numeric: tabular-nums; }
.lt-stat span { font-size: 11px; color: var(--lt-muted); }

/* ---------------- 仓库 / 商店 ---------------- */
.lt-grid2 { display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); gap: 10px; }
.lt-item {
  background: #fff; border: 2px solid var(--lt-line); border-radius: 13px;
  padding: 8px 6px 6px; text-align: center; position: relative;
}
.lt-item svg { display: block; margin: 0 auto; max-height: 56px; width: auto; }
.lt-item .lt-iname { font-size: 11.5px; margin-top: 3px; }
.lt-item .lt-n {
  position: absolute; top: 5px; right: 5px;
  background: var(--lt-ink); color: #fff; font-size: 10.5px;
  border-radius: 999px; padding: 0 6px;
}
.lt-item .lt-price { font-size: 11px; color: var(--lt-gold); font-weight: 700; }
.lt-item.lt-cant { opacity: .5; }
.lt-item button { width: 100%; }

/* 摆放模式 */
.lt-placing .lt-world-wrap { cursor: crosshair; }
.lt-placing .lt-house-hit { pointer-events: none; }
.lt-placing-bar {
  position: absolute; left: 50%; transform: translateX(-50%);
  bottom: calc(var(--lt-dock-h) + 12px);
  background: var(--lt-ink); color: #fff;
  padding: 7px 14px; border-radius: 999px; font-size: 12.5px;
  z-index: 26; white-space: nowrap;
}

/* ---------------- Toast / 粒子 ---------------- */
.lt-toast {
  position: fixed; left: 50%; bottom: calc(var(--lt-dock-h) + 24px);
  transform: translateX(-50%);
  background: var(--lt-ink); color: #fff;
  padding: 9px 16px; border-radius: 999px; font-size: 13.5px;
  z-index: 200; max-width: 88vw; text-align: center;
  animation: lt-pop .25s cubic-bezier(.3, 1.4, .5, 1);
}
.lt-toast[hidden] { display: none; }

.lt-fx { position: fixed; inset: 0; pointer-events: none; z-index: 150; }
.lt-fx span {
  position: absolute; font-size: 20px;
  animation: lt-float 1.05s ease-out forwards;
}

/* ---------------- 动画 ---------------- */
@keyframes lt-pop { from { transform: translateX(-50%) scale(.9); opacity: 0; } to { transform: translateX(-50%) scale(1); opacity: 1; } }
@keyframes lt-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes lt-slide { from { transform: translateY(24px); opacity: .6; } to { transform: translateY(0); opacity: 1; } }
@keyframes lt-float {
  0%   { transform: translate(-50%, 0) scale(.7); opacity: 0; }
  25%  { opacity: 1; }
  100% { transform: translate(-50%, -70px) scale(1.15); opacity: 0; }
}
@keyframes lt-hop {
  0%, 100% { transform: translateY(0); }
  35%      { transform: translateY(-7px); }
  70%      { transform: translateY(0); }
}
.lt-char-wrap.lt-hop { animation: lt-hop .5s ease-out; }

/* ---------------- 桌面适配 ---------------- */
@media (min-width: 640px) {
  body { max-width: 100%; }
  .lt-sheet { align-items: center; justify-content: center; }
  .lt-sheet-body {
    width: min(560px, 94vw);
    border-radius: 22px;
    border: 2.5px solid var(--lt-ink);
    max-height: 84vh;
    padding-bottom: 22px;
  }
  .lt-bubble { bottom: 20px; }
}

/* ---------------- 无障碍 ---------------- */
.lt-visually-hidden {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap;
}
:focus-visible { outline: 3px solid var(--lt-accent-2); outline-offset: 2px; border-radius: 6px; }

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


/* ============================================================
 * 虚拟摇杆（手机操作）
 * 位置在左下、底栏之上；只在摇杆上按下才接管，不影响点地面走路。
 * ============================================================ */
.lt-stick {
  position: fixed;
  left: 18px;
  bottom: calc(var(--lt-dock-h, 58px) + 18px);
  width: 96px; height: 96px;
  border-radius: 50%;
  background: rgba(253, 241, 224, .30);
  border: 2px solid rgba(74, 64, 51, .28);
  box-shadow: 0 2px 10px rgba(0, 0, 0, .10);
  z-index: 30;                    /* 低于面板(40)，高于画布 */
  touch-action: none;
  -webkit-user-select: none; user-select: none;
  -webkit-tap-highlight-color: transparent;
}
.lt-stick-ring {
  position: absolute; inset: 12px;
  border-radius: 50%;
  border: 1.5px dashed rgba(74, 64, 51, .20);
  pointer-events: none;
}
.lt-stick-knob {
  position: absolute;
  left: 50%; top: 50%;
  width: 42px; height: 42px;
  margin: -21px 0 0 -21px;
  border-radius: 50%;
  background: var(--lt-accent-2, #f4a261);
  border: 2px solid rgba(74, 64, 51, .35);
  box-shadow: 0 2px 6px rgba(0, 0, 0, .18);
  pointer-events: none;
  will-change: transform;
}
/* 大屏（桌面）也能用，但把手感说明留给画面 —— 不额外加提示 */
@media (min-height: 500px) and (min-width: 700px) {
  .lt-stick { left: 26px; bottom: calc(var(--lt-dock-h, 58px) + 26px); width: 108px; height: 108px; }
}


/* ============================================================
 * 建筑浮动名牌
 * ------------------------------------------------------------
 * 上下跳动用 margin-top 而不是 transform —— 因为 JS 每帧要用 transform
 * 把名牌定位到投影坐标，两者写在同一个属性上会互相覆盖。
 * ============================================================ */
#ltLabels {
  position: fixed; inset: 0;
  pointer-events: none;          /* 不挡点地面 */
  z-index: 25;                   /* 高于画布，低于面板(40) */
  overflow: hidden;
}
.lt-label {
  position: absolute; left: 0; top: 0;
  transform: translate(-50%, -100%);
  display: flex; flex-direction: column; align-items: center; gap: 1px;
  padding: 3px 10px 4px;
  border-radius: 999px;
  background: rgba(253, 246, 234, .92);
  border: 1.5px solid rgba(74, 64, 51, .30);
  box-shadow: 0 3px 10px rgba(0, 0, 0, .14);
  white-space: nowrap;
  will-change: transform, opacity, margin-top;
  transition: opacity .18s;
  animation: lt-label-bob 2.6s ease-in-out infinite;
}
.lt-label b {
  font-size: 12.5px; font-weight: 700; line-height: 1.15;
  color: #3d3628; letter-spacing: .02em;
}
.lt-label i {
  font-style: normal; font-size: 9.5px; line-height: 1;
  color: #8a7f70;
}
/* 名称下方的小尖角，指向建筑 */
.lt-label::after {
  content: ''; position: absolute; left: 50%; bottom: -5px;
  width: 0; height: 0; margin-left: -4px;
  border: 4px solid transparent;
  border-top-color: rgba(74, 64, 51, .30);
}

@keyframes lt-label-bob {
  0%, 100% { margin-top: 0; }
  50%      { margin-top: -9px; }
}

/* 用户开了"减少动画"就停下 */
@media (prefers-reduced-motion: reduce) {
  .lt-label { animation: none; }
}


/* ============================================================
 * 室内标题栏
 * 进屋后出现在顶部，显示这是哪间屋、以及"出来"按钮。
 * 用 fixed 而不是塞进 lt-top：室内的顶栏和室外的不是一回事。
 * ============================================================ */
.lt-room {
  position: fixed;
  /* 🔴 必须让开顶栏（.lt-top 高 54px），否则屋名牌会压在金币/连续天数/今日完成
     那几个药丸上，连视角按钮都被盖住 —— 用户看到的就是"UI 都丢失了"。 */
  left: 50%; top: calc(var(--lt-top-h, 54px) + 8px); transform: translateX(-50%);
  display: flex; align-items: center; gap: 8px;
  padding: 7px 8px 7px 14px;
  border-radius: 999px;
  background: rgba(253, 246, 234, .96);
  border: 2px solid rgba(74, 64, 51, .30);
  box-shadow: 0 4px 14px rgba(0, 0, 0, .18);
  z-index: 42;                       /* 高于面板(40)，室内它是最上层 */
  /* 🔴 右侧是工具竖排（44px + 8 边距）——照满宽算会压住语音按钮。
     两侧各留 46px，既躲开工具条，又仍然居中。 */
  max-width: calc(100vw - 92px);
  animation: lt-room-in .22s ease-out;
}
.lt-room[hidden] { display: none; }
.lt-room-txt { display: flex; flex-direction: column; min-width: 0; line-height: 1.25; }
.lt-room-dot {
  width: 9px; height: 9px; border-radius: 50%;
  background: #7fb069;
  box-shadow: 0 0 0 3px rgba(127, 176, 105, .22);
  flex: 0 0 auto;
}
.lt-room b { font-size: 14px; color: #3d3628; white-space: nowrap; }
.lt-room i {
  font-style: normal; font-size: 11px; color: #8a7f70;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.lt-room-exit {
  flex: 0 0 auto;
  padding: 6px 12px; border-radius: 999px;
  border: 1.5px solid rgba(74, 64, 51, .3);
  background: var(--lt-accent-2, #f4a261);
  color: #fff; font-size: 12.5px; font-weight: 700;
  font-family: inherit; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.lt-room-exit:active { transform: scale(.94); }

@keyframes lt-room-in {
  from { opacity: 0; transform: translateX(-50%) translateY(-10px); }
  to   { opacity: 1; transform: translateX(-50%) translateY(0); }
}

/* 进屋按钮（在地点面板里，做成醒目的主按钮）*/
.lt-enter-btn {
  width: 100%;
  padding: 11px 14px;
  border-radius: var(--lt-radius-sm);
  border: 2px solid var(--lt-ink, #4a4033);
  background: var(--lt-accent-2, #f4a261);
  color: #fff; font-size: 14.5px; font-weight: 700;
  font-family: inherit; cursor: pointer;
  box-shadow: 0 3px 0 rgba(74, 64, 51, .35);
}
.lt-enter-btn:active { transform: translateY(1px); box-shadow: 0 1px 0 rgba(74, 64, 51, .35); }

/* 屋名牌里的操作提示：室内拖动可以环绕看 */
.lt-room-hint {
  font-size: 10.5px; color: #9a8f80;
  padding: 2px 7px; border-radius: 999px;
  background: rgba(74, 64, 51, .07);
  white-space: nowrap;
}
@media (max-width: 380px) { .lt-room-hint { display: none; } }   /* 太窄就不挤了 */

/* 活动点按钮：走到家具旁边才出现（"坐下看书" / "在灶台前炒菜"…）
   刻意做成贴底居中的胶囊，和摇杆、底栏都不打架 */
.lt-spot {
  position: fixed;
  left: 50%;
  transform: translateX(-50%);
  bottom: calc(var(--lt-dock-h, 64px) + 14px);
  z-index: 30;
  padding: 9px 18px;
  border: none;
  border-radius: 999px;
  background: rgba(46, 40, 34, 0.86);
  color: #ffe9c2;
  font-size: 14px;
  letter-spacing: 0.5px;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.3);
  animation: lt-spot-in 0.22s ease-out;
  cursor: pointer;
}
.lt-spot:active { transform: translateX(-50%) scale(0.94); }
@keyframes lt-spot-in {
  from { opacity: 0; transform: translateX(-50%) translateY(8px); }
  to   { opacity: 1; transform: translateX(-50%) translateY(0); }
}


/* ============================================================
 * UI 视觉系统 v2 —— 3D HUD（2026-09-24）
 * ------------------------------------------------------------
 * 气质取自场景：Kenney/KayKit 低多边形玩具 —— 暖木色描边、奶油纸面、
 * 苔绿/珊瑚/蜜黄点缀、圆角、有"厚度"的按钮。
 *
 * 六条硬规则（改这一节时别破）：
 *  ① 描边统一 2px var(--lt-stroke)，小件 1.5px；圆角只用 --lt-r-* 四档
 *  ② 层次 = 纸面 + 底边(box-shadow 0 Npx 0) + 柔和投影，最多两层
 *  ③ 动画只用 transform / opacity；不用大面积 backdrop-filter（手机上掉帧）
 *  ④ 主按钮高 >= 44px（--lt-tap），相邻间距 >= 8px
 *  ⑤ 浮层自带纸面 + 描边 → 无论背景是亮天空还是黑夜场景都可读；
 *     夜里再由 body.lt-night 整体转成暖深色（见本节末尾）
 *  ⑥ 图标一律 <i data-ic> + LT_ICON（js/icons3d.js），不用 emoji 混排
 * ============================================================ */

/* ---------- 0. 图标槽 + 3D 版基础布局 ---------- */
#ltCanvas { position: fixed; inset: 0; width: 100%; height: 100%; display: block; touch-action: none; }
.lt-top  { position: fixed; top: 0; left: 0; right: 0; }
.lt-dock { position: fixed; left: 0; right: 0; bottom: 0; }
#ltSheet { z-index: 40; }

.lt-ic { display: block; width: 22px; height: 22px; flex: 0 0 auto; }
[data-ic]:empty { display: block; }         /* 还没填图标时也占位，避免布局跳一下 */

/* ---------- 1. 顶部栏：只放"身份 + 状态" ---------- */
.lt-top {
  height: var(--lt-top-full);
  padding: 0 10px;
  padding-top: var(--lt-safe-t);
  display: flex; align-items: center; gap: 9px;
  background: linear-gradient(180deg, #fffdf8 0%, #fbf3e5 100%);
  border-bottom: 2px solid var(--lt-line);
  box-shadow: 0 5px 14px rgba(74, 64, 51, .10);
  z-index: 30;
}
.lt-brand { gap: 8px; font-size: 16px; }
.lt-brand b { font-weight: 800; font-size: 16.5px; letter-spacing: -.01em; color: var(--lt-ink); }
.lt-logo {
  width: 32px; height: 32px; border-radius: 11px;
  display: grid; place-items: center;
  background: linear-gradient(180deg, #bde49b, #8fcb6f);
  border: 2px solid var(--lt-stroke);
  box-shadow: 0 2px 0 var(--lt-edge);
  color: #3f5c2c;
}
.lt-logo .lt-ic { width: 19px; height: 19px; }
.lt-brand .lt-ver {
  font-size: 10.5px; font-weight: 800; letter-spacing: .04em;
  padding: 2px 6px; border-radius: 999px;
  background: var(--lt-moss); color: #fff; border: 1.5px solid var(--lt-stroke);
}

.lt-stats { display: flex; gap: 6px; margin-left: auto; }
.lt-pill {
  height: 30px; padding: 0 10px; gap: 5px;
  border-radius: 999px;
  border: 1.5px solid var(--lt-line);
  background: var(--lt-paper);
  box-shadow: var(--lt-sh-1);
  font-size: 13px; font-weight: 800;
  color: var(--lt-ink);
}
.lt-pill .lt-ic { width: 16px; height: 16px; }
.lt-pill i { display: flex; align-items: center; line-height: 1; }
.lt-pill b { font-variant-numeric: tabular-nums; }
.lt-pill em { font-style: normal; color: var(--lt-muted); font-size: 11px; font-weight: 700; }
.lt-pill.p-coins i  { color: #dfa32a; }
.lt-pill.p-streak i { color: var(--lt-accent); }
.lt-pill.p-today i  { color: var(--lt-moss-d); }

/* ---------- 2. 工具条：改成右侧竖排（拇指够得着，不挤顶栏） ----------
   原来 5 个按钮塞在顶栏里，390px 竖屏上算出来是 496px 宽 →
   最右边的"存档与设置"直接被挤出屏幕外。现在竖排在右边缘，每个 44px。 */
.lt-tools {
  position: fixed; right: 8px;
  top: calc(var(--lt-top-full) + 8px);
  display: flex; flex-direction: column; gap: 6px;
  z-index: 22;
}
.lt-ico {
  width: var(--lt-tap); height: var(--lt-tap);
  border-radius: var(--lt-r-md);
  display: grid; place-items: center;
  color: var(--lt-ink-2);
  background: rgba(255, 250, 242, .94);
  border: 2px solid var(--lt-stroke);
  box-shadow: 0 2px 0 var(--lt-edge);
  transition: transform .12s ease, background .12s ease, color .12s ease, opacity .12s ease;
}
.lt-ico .lt-ic { width: 21px; height: 21px; }
.lt-ico:hover, .lt-ico:focus-visible { background: var(--lt-paper-2); }
.lt-ico:active { transform: translateY(2px) scale(.97); box-shadow: 0 0 0 var(--lt-edge); }
.lt-ico.on  { color: var(--lt-moss-d); border-color: var(--lt-moss); background: #f2f8ec; }
body.lt-night .lt-ico.on { color: #b7d79f; background: rgba(110, 163, 83, .22); }
.lt-ico.off { color: var(--lt-ink-3); opacity: .82; }
/* 📷 反馈按钮：故意比其余工具小一号、低对比 —— 它是"给作者的通道"，
   不是玩家每天要按的按钮，不该抢主按钮的注意力。 */
.lt-ico.lt-ico-shot { width: 38px; height: 38px; opacity: .88; }
.lt-ico.lt-ico-shot .lt-ic { width: 18px; height: 18px; }
.lt-ico.lt-ico-shot.busy { opacity: .40; }

/* ---------- 3. 底部地点栏 ---------- */
.lt-dock {
  height: var(--lt-dock-full);
  /* 🔴 5 个地点按钮要正好铺满一屏：fixed 最小宽度 68 + gap8 + padding10
     在 390px 竖屏上算出来 392px → 第 5 个按钮会被切掉 2px（横滚）。
     改成 flex:1 + min-width 兜底，宽度自适应；窄到 320px 才真的横滚。 */
  padding: 6px 8px calc(6px + var(--lt-safe-b));
  gap: 6px;
  background: linear-gradient(180deg, #fffdf8, #f8efe0);
  border-top: 2px solid var(--lt-line);
  box-shadow: 0 -6px 16px rgba(74, 64, 51, .10);
}
.lt-dock-btn {
  position: relative;
  flex: 1 1 0;
  min-width: 64px; min-height: 54px;
  padding: 5px 8px 4px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  border-radius: var(--lt-r-md);
  border: 2px solid var(--lt-line);
  background: var(--lt-paper);
  color: var(--lt-ink);
  box-shadow: 0 2px 0 rgba(74, 64, 51, .08);
  font-size: 12px; line-height: 1.1;
  transition: transform .14s ease, background .14s ease, border-color .14s ease, color .14s ease;
}
.lt-dock-btn .lt-ic { width: 23px; height: 23px; color: var(--lt-moss-d); }
.lt-mini .lt-ic { width: 14px; height: 14px; }
.lt-room-exit .lt-ic { width: 15px; height: 15px; }
.lt-enter-btn .lt-ic { width: 19px; height: 19px; }
.lt-sheet-head .lt-ic, .lt-x .lt-ic { width: 17px; height: 17px; }
.lt-dock-btn b { font-size: 12px; font-weight: 800; letter-spacing: -.005em; }
.lt-dock-btn:active { transform: translateY(2px) scale(.98); }
.lt-dock-btn.lt-on {
  background: linear-gradient(180deg, #8ec46f, #6ea353);
  border-color: var(--lt-stroke);
  color: #fff;
  box-shadow: 0 2px 0 rgba(74, 64, 51, .34);
}
.lt-dock-btn.lt-on .lt-ic { color: #fff; }
.lt-dock-btn.lt-locked { opacity: .55; filter: grayscale(.5); }
.lt-dock-btn .lt-dot { font-size: 15px; line-height: 1; }
/* 待办数徽标：绝对定位到卡片右上角（原来是负 margin 硬凑的，会跟着文字飘） */
.lt-dock-btn .lt-badge {
  position: absolute; top: -7px; right: -5px;
  margin: 0; min-width: 21px; height: 21px; padding: 0 5px;
  display: grid; place-items: center;
  border-radius: 999px;
  background: var(--lt-accent); color: #fff;
  border: 2px solid var(--lt-paper);
  font-size: 11px; font-weight: 800; font-variant-numeric: tabular-nums;
  box-shadow: 0 2px 5px rgba(74, 64, 51, .28);
}

/* ---------- 4. 虚拟摇杆 ---------- */
.lt-stick {
  left: 14px;
  bottom: calc(var(--lt-dock-full) + 12px);
  width: 104px; height: 104px;
  background: rgba(255, 250, 242, .40);
  border: 2px solid rgba(74, 64, 51, .40);
  box-shadow: inset 0 2px 10px rgba(74, 64, 51, .10), 0 3px 0 rgba(74, 64, 51, .14);
}
.lt-stick-ring { inset: 15px; border: 2px dashed rgba(74, 64, 51, .20); }
.lt-stick-knob {
  width: 46px; height: 46px; margin: -23px 0 0 -23px;
  background: radial-gradient(circle at 34% 28%, #b6e293, #7fb069 72%);
  border: 2px solid var(--lt-stroke);
  box-shadow: 0 3px 0 rgba(74, 64, 51, .30), 0 6px 12px rgba(0, 0, 0, .16);
}

/* ---------- 5. 活动点按钮（"坐下看书"） ---------- */
.lt-spot {
  bottom: calc(var(--lt-dock-full) + 16px);
  min-height: 48px;
  padding: 0 20px 0 17px;
  display: inline-flex; align-items: center; gap: 9px;
  border: 2px solid var(--lt-stroke);
  border-radius: 999px;
  background: linear-gradient(180deg, #fffdf8, #f6ead8);
  color: var(--lt-ink);
  font-size: 14.5px; font-weight: 800; letter-spacing: .01em;
  box-shadow: var(--lt-sh-press);
  z-index: 30;
}
.lt-spot::before {
  content: ''; width: 10px; height: 10px; border-radius: 50%;
  background: var(--lt-moss); box-shadow: 0 0 0 3px rgba(127, 176, 105, .28);
  flex: 0 0 auto;
}
.lt-spot:active { transform: translateX(-50%) translateY(2px) scale(.98); box-shadow: 0 1px 0 var(--lt-edge); }
.lt-spot[hidden] { display: none; }

/* ---------- 6. 对话 / 提示气泡 ---------- */
/* 🔴 提示气泡的位置是算过的：底栏 68 + 128 = 196px。
   为什么不是紧贴底栏 —— 左下角是摇杆（104px 高，顶到 dock+116），
   居中贴底的气泡（88vw 宽）必然压住摇杆。抬到摇杆上方，两边都完整。 */
#lt3dHint {
  position: fixed;             /* 🔴 忘了这条就变成文档流里的静态块，跑到页面顶上 */
  z-index: 18;
  bottom: calc(var(--lt-dock-full) + 128px);
  left: 50%;
  max-width: min(88vw, 420px);
  padding: 11px 16px 12px;
  border-radius: var(--lt-r-lg);
  background: rgba(255, 250, 242, .97);
  color: var(--lt-ink);
  border: 2px solid var(--lt-stroke);
  box-shadow: 0 3px 0 var(--lt-edge), 0 10px 22px rgba(74, 64, 51, .22);
  font-size: 14px; font-weight: 700; line-height: 1.5;
  text-align: center; white-space: normal;
  opacity: 0;
  transform: translateX(-50%) translateY(8px);
  transition: opacity .26s ease, transform .26s cubic-bezier(.2, 1.3, .4, 1);
}
#lt3dHint.on { opacity: 1; transform: translateX(-50%) translateY(0); }
/* 说话人（NPC 对话）：main3d 传的是 "名字：台词"，ui3d 拆出来放这一行 */
#lt3dHint b {
  display: block; margin-bottom: 3px;
  font-size: 11.5px; font-weight: 800; letter-spacing: .08em;
  color: var(--lt-accent);
}
#lt3dHint b::before { content: '· '; color: var(--lt-moss); }
#lt3dHint::after {
  content: ''; position: absolute; left: 50%; bottom: -8px;
  width: 13px; height: 13px;
  background: rgba(255, 250, 242, .97);
  border-right: 2px solid var(--lt-stroke); border-bottom: 2px solid var(--lt-stroke);
  border-radius: 0 0 4px 0;
  transform: translateX(-50%) rotate(45deg);
}

/* ---------- 7. 时段切换（昼夜）---------- */
.lt-timebar {
  position: fixed;
  display: flex;               /* 🔴 少了这条：按钮是 flex 子项，会一列竖下来 */
  left: 10px;
  top: calc(var(--lt-top-full) + 8px);
  gap: 3px; padding: 4px;
  background: rgba(255, 250, 242, .95);
  border: 2px solid var(--lt-stroke);
  border-radius: 999px;
  box-shadow: 0 3px 0 var(--lt-edge), 0 8px 18px rgba(74, 64, 51, .16);
  z-index: 19;
}
/* 屋里：屋名牌和时段按钮都是"顶栏下面那一层"，必须错开。
   屋名牌高约 50px + 8px 间距 → 时段按钮让到 +62。 */
body.lt-indoors .lt-timebar { top: calc(var(--lt-top-full) + 66px); }
.lt-timebtn {
  min-width: 48px; min-height: var(--lt-tap);
  padding: 4px 7px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  border-radius: 999px;
  color: var(--lt-ink-2);
  font-size: 10.5px; font-weight: 800; line-height: 1.1;
  text-shadow: none;
  transition: background .15s ease, color .15s ease, transform .12s ease;
}
.lt-timebtn i { font-style: normal; font-size: 18px; line-height: 1; }
.lt-timebtn .lt-ic { width: 19px; height: 19px; }
.lt-timebtn.on {
  background: linear-gradient(180deg, #8ec46f, #6ea353);
  color: #fff;
  box-shadow: inset 0 -2px 0 rgba(0, 0, 0, .10);
}
.lt-timebtn.on .lt-ic { color: #fff; }
.lt-timebtn:active { transform: scale(.94); }

/* 时段条【可收起】（第四阶段）：一排 5 个按钮在 390px 竖屏上约 260px 宽，
   横屏/小屏会挡住画面。左边那个小三角是"永远看得见的一格"，
   点了把 5 个按钮收掉（状态记 localStorage lt3d.timebar）。 */
.lt-timebtns { display: flex; gap: 3px; }
.lt-timebar.fold .lt-timebtns { display: none; }
.lt-timefold {
  width: 26px; min-height: var(--lt-tap);
  display: grid; place-items: center;
  border-radius: 999px;
  color: var(--lt-ink-2);
}
.lt-timefold::before {
  content: ''; width: 9px; height: 9px;
  border-left: 2.4px solid currentColor; border-bottom: 2.4px solid currentColor;
  transform: rotate(45deg) translate(1px, -1px);
  transition: transform .16s ease;
}
.lt-timebar.fold .lt-timefold::before { transform: rotate(-135deg) translate(-1px, -1px); }

/* ---------- 8. 建筑浮动名牌 ---------- */
.lt-label {
  padding: 3px 11px 4px;
  border-radius: 999px;
  background: rgba(255, 250, 242, .95);
  border: 2px solid var(--lt-stroke);
  box-shadow: 0 3px 0 var(--lt-edge), 0 6px 12px rgba(0, 0, 0, .12);
}
.lt-label b { font-size: 12.5px; font-weight: 800; color: var(--lt-ink); }
.lt-label i { font-size: 9.5px; color: var(--lt-ink-3); }
.lt-label::after { bottom: -5px; border-width: 5px; border-top-color: var(--lt-stroke); margin-left: -5px; }

/* ---------- 9. 室内标题栏 ---------- */
.lt-room {
  top: calc(var(--lt-top-full) + 8px);
  padding: 6px 8px 6px 13px;
  gap: 8px;
  /* 🔴 一行塞不下：圆点 + 屋名 + 副标题 + 拖动提示 + 出来按钮。
     原来是一行 flex，390px 竖屏上副标题被压成"今天还…"（用 grid 也一样压）。
     现在屋名/副标题收进一个纵向的 .lt-room-txt 里 —— 两行文字自己排，
     右侧按钮按内容吃宽度，谁都不用被截。 */
  display: flex;
  align-items: center;
  column-gap: 8px;
  background: rgba(255, 250, 242, .97);
  border: 2px solid var(--lt-stroke);
  box-shadow: 0 3px 0 var(--lt-edge), 0 8px 18px rgba(0, 0, 0, .16);
}
.lt-room b { font-size: 14px; font-weight: 800; color: var(--lt-ink); white-space: nowrap; }
.lt-room i { color: var(--lt-ink-3); font-size: 10.5px; }
.lt-room-exit {
  /* 🔴 图标 .lt-ic 是 display:block —— 按钮不加 flex 的话，图标会把文字挤到下一行 */
  white-space: nowrap;
  display: inline-flex; align-items: center; gap: 5px;
  min-height: 34px; padding: 6px 14px;
  border-radius: 999px;
  border: 2px solid var(--lt-stroke);
  background: linear-gradient(180deg, #8ec46f, #6ea353);
  box-shadow: 0 2px 0 rgba(74, 64, 51, .32);
  font-size: 12.5px; font-weight: 800;
}
.lt-room-exit:active { transform: translateY(1px); box-shadow: 0 0 0 rgba(74, 64, 51, .32); }
/* "拖动屏幕看四周" 这条提示在竖屏上把整条屋名牌撑爆（副标题被截成"今天还…"）。
   它是一次性的引导，隐藏掉换整条名牌的可读性 —— 元素保留在 DOM 里，随时能放回来。 */
.lt-room-hint { display: none; }

/* ---------- 10. 首屏加载页 ---------- */
#lt3dLoading {
  position: fixed; inset: 0; z-index: 60; overflow: hidden;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 20px; padding: 24px;
  padding-bottom: calc(24px + var(--lt-safe-b));
  background: linear-gradient(180deg, #9fd0e8 0%, #c6e6f4 42%, #e9f5e4 100%);
  color: var(--lt-ink);
  font: 15px/1.5 var(--lt-font);
  transition: opacity .4s ease;
}
/* 底部两道低多边形山脊：把渐变的"白底"收住，构图不至于下半屏发空 */
.lt-load-ground { position: absolute; left: 0; right: 0; bottom: 0; height: 24vh; pointer-events: none; }
.lt-load-ground svg { display: block; width: 100%; height: 100%; }
.lt-load-ground .g1 { fill: #9ac27b; }
.lt-load-ground .g2 { fill: #a8d98a; }
.lt-load-art { width: min(88vw, 380px); }
.lt-load-art svg { display: block; width: 100%; height: auto; overflow: visible; }
.lt-load-hill-far  { fill: #7fa863; }
.lt-load-hill-near { fill: #93cd72; }
.lt-load-sun  { fill: #f7d98c; }
.lt-load-sun-ring { fill: rgba(247, 217, 140, .38); }
.lt-load-cloud { fill: rgba(255, 255, 255, .9); }
.lt-load-cloud.c2 { fill: rgba(255, 255, 255, .62); }
.lt-load-wall { fill: #fdf1e0; stroke: var(--lt-stroke); stroke-width: 2; }
.lt-load-roof { stroke: var(--lt-stroke); stroke-width: 2; stroke-linejoin: round; }
.lt-load-window { fill: #cfe8f5; stroke: var(--lt-stroke); stroke-width: 1.4; }
/* 云只做 transform 平移动画（不触发重排，手机上不掉帧） */
.lt-load-cloud.c1 { animation: lt-cloud 26s linear infinite; }
.lt-load-cloud.c2 { animation: lt-cloud 38s linear infinite reverse; }
@keyframes lt-cloud {
  from { transform: translateX(-24px); }
  to   { transform: translateX(24px); }
}
/* 房子"一栋栋盖起来"：scaleY 从 0 到 1，错开时间 */
.lt-load-town > g { transform-box: fill-box; transform-origin: 50% 100%; animation: lt-build 1.1s cubic-bezier(.22, 1.2, .4, 1) both; }
.lt-load-town > g:nth-child(2) { animation-delay: .16s; }
.lt-load-town > g:nth-child(3) { animation-delay: .32s; }
.lt-load-town > g:nth-child(4) { animation-delay: .48s; }
.lt-load-town > g:nth-child(5) { animation-delay: .64s; }
@keyframes lt-build { from { transform: scaleY(.02); opacity: 0; } to { transform: scaleY(1); opacity: 1; } }

.lt-load-card {
  width: min(88vw, 380px);
  padding: 15px 18px 16px;
  border-radius: var(--lt-r-lg);
  background: rgba(255, 250, 242, .96);
  border: 2px solid var(--lt-stroke);
  box-shadow: 0 4px 0 var(--lt-edge), 0 14px 30px rgba(74, 64, 51, .22);
}
.lt-load-title {
  font-size: 16.5px; font-weight: 800; letter-spacing: -.01em;
  color: var(--lt-ink); margin-bottom: 10px;
}
.lt-load-bar {
  height: 14px; border-radius: 999px; overflow: hidden;
  background: var(--lt-paper-3);
  border: 2px solid var(--lt-stroke);
}
.lt-load-bar > i {
  display: block; height: 100%; width: 0;
  border-radius: 0 999px 999px 0;
  background: linear-gradient(90deg, var(--lt-moss-l), var(--lt-moss));
  transition: width .25s ease;
}
.lt-load-meta {
  display: flex; align-items: center; gap: 10px;
  margin-top: 9px; font-size: 12.5px; color: var(--lt-ink-3); font-weight: 700;
}
.lt-load-meta b {
  margin-left: auto; font-size: 14px; font-weight: 800;
  color: var(--lt-moss-d); font-variant-numeric: tabular-nums;
}
@media (prefers-reduced-motion: reduce) {
  .lt-load-cloud, .lt-load-town > g { animation: none !important; }
}

/* ---------- 11. 进房间加载层 ---------- */
#ltRoomLoading {
  position: fixed; inset: 0; z-index: 30; display: none;
  flex-direction: column; align-items: center; justify-content: center; gap: 12px;
  /* 纯渐变打底，不用 blur —— 软渲染/低端机上也几乎零成本 */
  background: radial-gradient(circle at 50% 46%, rgba(28, 23, 18, .34) 0%, rgba(20, 17, 14, .62) 100%);
  color: var(--lt-night-text);
  font: 14px/1.5 var(--lt-font);
  pointer-events: none;
}
#ltRoomLoading.on { display: flex; }
#ltRoomLoading .ring {
  position: relative;
  width: 46px; height: 46px; border-radius: 50%;
  border: 4px solid rgba(255, 250, 242, .26);
  border-top-color: var(--lt-moss-l);
  animation: ltSpin .8s linear infinite;
}
/* 圈底下一层静态柔光（也是纯色圆，不是 box-shadow 动画） */
#ltRoomLoading .ring::after {
  content: ''; position: absolute; inset: -10px; border-radius: 50%;
  background: rgba(168, 217, 138, .14);
}
#ltRoomLoading .txt {
  max-width: 84vw; text-align: center;
  background: rgba(255, 250, 242, .96); color: var(--lt-ink);
  border: 2px solid var(--lt-stroke);
  padding: 8px 16px; border-radius: 999px;
  font-weight: 800; font-size: 13.5px;
  box-shadow: 0 3px 0 var(--lt-edge), 0 10px 22px rgba(0, 0, 0, .28);
}
#ltRoomLoading .bar {
  width: 200px; height: 12px; border-radius: 999px; overflow: hidden;
  background: rgba(18, 15, 12, .52);            /* 槽要看得见，否则像一根浮空的绿条 */
  border: 2px solid rgba(255, 250, 242, .40);
}
#ltRoomLoading .bar > i { background: linear-gradient(90deg, var(--lt-moss-l), var(--lt-moss)); }
#ltRoomLoading .bar > i { display: block; height: 100%; width: 0; background: var(--lt-moss-l); transition: width .2s ease; }
@keyframes ltSpin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { #ltRoomLoading .ring { animation-duration: 2.4s; } }

/* ---------- 12. 浮层面板（地点 / 记录 / 形象 / 设置） ---------- */
.lt-sheet-body {
  background: var(--lt-paper);
  border-radius: 24px 24px 0 0;
  border-top: 2.5px solid var(--lt-stroke);
  padding-bottom: calc(22px + var(--lt-safe-b));
  box-shadow: 0 -10px 30px rgba(40, 34, 26, .28);
}
.lt-sheet-backdrop { background: rgba(40, 34, 26, .46); }
.lt-sheet-head {
  padding: 13px 16px 12px;
  gap: 9px;
  background: linear-gradient(180deg, #fffdf8, var(--lt-paper));
  border-bottom: 2px solid var(--lt-line);
}
.lt-sheet-head h2, .lt-sheet-head b { font-size: 17px; font-weight: 800; color: var(--lt-ink); }
.lt-sheet-head .lt-tag {
  background: var(--lt-moss); color: #fff;
  border: 1.5px solid var(--lt-stroke);
  font-size: 11px; font-weight: 800; padding: 2px 9px;
}
.lt-x {
  width: 34px; height: 34px; border-radius: var(--lt-r-xs);
  background: var(--lt-paper-2); border: 1.5px solid var(--lt-line);
  color: var(--lt-ink-2); display: grid; place-items: center;
}
.lt-x .lt-ic { width: 17px; height: 17px; }
.lt-x:active { transform: scale(.94); }

.lt-sec-title { font-size: 12.5px; font-weight: 800; color: var(--lt-ink-3); letter-spacing: .08em; }
.lt-sec-title::after { height: 1.5px; background: var(--lt-line); }

.lt-btn {
  min-height: var(--lt-tap);
  padding: 10px 18px;
  border-radius: var(--lt-r-md);
  border: 2px solid var(--lt-stroke);
  background: var(--lt-paper);
  color: var(--lt-ink);
  font-size: 14.5px; font-weight: 800;
  box-shadow: 0 3px 0 var(--lt-edge);
}
.lt-btn.lt-primary { background: linear-gradient(180deg, #8ec46f, #6ea353); color: #fff; box-shadow: 0 3px 0 rgba(74, 64, 51, .34); }
.lt-btn.lt-warm    { background: linear-gradient(180deg, #ec8f74, #d9694d); color: #fff; box-shadow: 0 3px 0 rgba(74, 64, 51, .34); }
.lt-btn.lt-ghost   { background: var(--lt-paper-2); border: 2px solid var(--lt-line); box-shadow: none; font-weight: 700; }
.lt-btn:disabled { opacity: .45; box-shadow: none; }
.lt-btn.lt-sm { min-height: 36px; padding: 6px 12px; font-size: 12.5px; box-shadow: 0 2px 0 var(--lt-edge); }

.lt-task {
  border: 2px solid var(--lt-line);
  border-radius: var(--lt-r-md);
  background: #fff;
  padding: 11px 12px;
  margin: 9px 0;
}
.lt-task.lt-done { background: #f2f8ec; border-color: #bcd9a8; }
.lt-task .lt-title { font-size: 14.5px; font-weight: 700; color: var(--lt-ink); }
.lt-check {
  width: 30px; height: 30px; border-radius: 10px;
  border: 2px solid var(--lt-stroke); background: #fff;
  font-size: 15px; color: #fff;
}
.lt-task.lt-done .lt-check, .lt-check.on { background: var(--lt-moss); }
.lt-chip {
  background: var(--lt-paper-2); border: 1.5px solid var(--lt-line);
  color: var(--lt-ink-3); font-size: 11px; font-weight: 700; padding: 2px 9px;
}
.lt-mini {
  display: inline-flex; align-items: center; gap: 5px;
  border: 1.5px solid var(--lt-line); background: var(--lt-paper);
  color: var(--lt-ink-2); font-size: 11.5px; font-weight: 700;
  padding: 5px 11px; border-radius: 999px;
}
.lt-mini:active { background: var(--lt-paper-2); }
.lt-enter-btn {
  /* 🔴 width:100% + 面板给的左右 16px 外边距 = 横向溢出 32px
     （面板因此出现横向滚动条，真机上也一样）。这里改成 auto，撑满中间那一段。 */
  width: auto;
  display: flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 50px;
  border-radius: var(--lt-r-md);
  border: 2px solid var(--lt-stroke);
  background: linear-gradient(180deg, #8ec46f, #6ea353);
  box-shadow: 0 3px 0 rgba(74, 64, 51, .34);
  font-size: 15px; font-weight: 800;
}
.lt-cell { background: var(--lt-paper-2); border: 2px solid var(--lt-line); border-radius: var(--lt-r-md); }
.lt-cell b { color: var(--lt-moss-d); font-weight: 800; }
.lt-roadrow { border-bottom: 1.5px dashed var(--lt-line); }
.lt-roadrow b { color: var(--lt-moss-d); font-weight: 800; }
.lt-note { font-size: 12.5px; line-height: 1.7; color: var(--lt-ink-2); }
.lt-note b { color: var(--lt-moss-d); }
.lt-input, .lt-select, .lt-area { border-radius: var(--lt-r-md); border: 2px solid var(--lt-line); font-size: 15px; }
.lt-opt { padding: 9px 15px; font-weight: 700; }
.lt-file { display: none; }

/* 形象面板的角色格 / 任务编辑器的表单行 / 记录面板的三列格
   —— 这几条原来写在 index.html 的内联 <style> 里（2D 版遗留），
   内联块删掉后必须在这里补回来，否则"形象"和"记录"两个面板会散掉。 */
.lt-chargrid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin-top: 10px; }
.lt-charbtn {
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  border: 2px solid var(--lt-line); border-radius: var(--lt-r-md);
  background: #fff; box-shadow: var(--lt-sh-1); padding: 8px 2px;
  font: 11.5px/1.3 var(--lt-font); font-weight: 700; color: var(--lt-ink-2);
  cursor: pointer; text-align: center;
}
.lt-charbtn.on { background: linear-gradient(180deg, #8ec46f, #6ea353); border-color: var(--lt-stroke); color: #fff; }
.lt-charbtn .lt-ic { width: 22px; height: 22px; }
.lt-charbtn:active { transform: scale(.96); }

.lt-editor {
  margin-top: 11px; padding-top: 11px;
  border-top: 2px dashed var(--lt-line);
  display: flex; flex-direction: column; gap: 9px;
}
.lt-editor label { display: flex; flex-direction: column; gap: 5px; font-size: 12.5px; font-weight: 700; color: var(--lt-ink-3); }

.lt-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 9px; }

/* ---------- 13. 夜晚：HUD 转暖深色 ----------
   main3d 进屋/时段切换时会给 body 打 .lt-night（见 daynight3d._syncButtons）。
   夜里场景很暗，白纸面会晃眼；换成暖深色纸 + 奶白描边，
   描边仍然是"实线"，所以对比度不靠 blur 也够。 */
body.lt-night { --lt-paper: #2e2a26; --lt-paper-2: #3a342e; --lt-paper-3: #443c34;
                --lt-line: rgba(255, 238, 210, .22); --lt-stroke: rgba(255, 238, 210, .42);
                --lt-ink: #fdf3e2; --lt-ink-2: #e8dcc6; --lt-ink-3: #bfae95;
                --lt-muted: #bfae95; --lt-edge: rgba(0, 0, 0, .40); }
body.lt-night .lt-top { background: linear-gradient(180deg, rgba(38, 34, 30, .96), rgba(30, 27, 24, .96)); }
body.lt-night .lt-dock { background: linear-gradient(180deg, rgba(38, 34, 30, .97), rgba(30, 27, 24, .97)); }
body.lt-night .lt-pill,
body.lt-night .lt-ico,
body.lt-night .lt-dock-btn,
body.lt-night .lt-timebar,
body.lt-night .lt-label,
body.lt-night .lt-room { background: rgba(46, 42, 38, .96); }
body.lt-night .lt-brand b { color: #fdf3e2; }
body.lt-night .lt-dock-btn.lt-on { background: linear-gradient(180deg, #6ea353, #55803f); color: #fff; }
body.lt-night .lt-dock-btn .lt-ic { color: #b7d79f; }
body.lt-night .lt-dock-btn.lt-on .lt-ic { color: #fff; }
body.lt-night .lt-dock-btn .lt-badge { border-color: #2e2a26; }
body.lt-night .lt-stick { background: rgba(30, 27, 24, .40); border-color: rgba(255, 238, 210, .40); }
body.lt-night .lt-stick-ring { border-color: rgba(255, 238, 210, .22); }
body.lt-night #lt3dHint { background: rgba(46, 42, 38, .97); color: #fdf3e2; border-color: rgba(255, 238, 210, .42); }
body.lt-night #lt3dHint::after { background: rgba(46, 42, 38, .97); border-color: rgba(255, 238, 210, .42); }
body.lt-night #lt3dHint b { color: #f0b48f; }
body.lt-night .lt-spot { background: linear-gradient(180deg, #3a342e, #2e2a26); color: #fdf3e2; border-color: rgba(255, 238, 210, .42); }
body.lt-night .lt-room-exit { color: #fff; }
body.lt-night .lt-sheet-body { background: #2e2a26; }
body.lt-night .lt-sheet-head { background: linear-gradient(180deg, #3a342e, #2e2a26); }
body.lt-night .lt-task { background: #35302a; }
body.lt-night .lt-task.lt-done { background: #2f3a2c; }
body.lt-night .lt-check { background: rgba(255, 238, 210, .12); }
body.lt-night .lt-input, body.lt-night .lt-select, body.lt-night .lt-area { background: #3a342e; color: #fdf3e2; }

/* ---------- 13b. 黄昏 / 阴天：给色调，但仍然是【亮底】----------
   第四阶段：原来只有"深夜"会换 HUD 配色，黄昏/阴天的 HUD 还是正午那张纯白纸面，
   和场景对不上。这里各给一档：
     · 黄昏 —— 偏暖（奶油橙纸面 + 焦糖描边），但**不反色**。黄昏场景还没暗到
       需要深色 HUD，白纸面也只是"有点跳"，用暖色纸面正好接住画面里的金橙。
     · 阴天 —— 偏冷灰（冷白纸面 + 石板描边），和低饱和的灰天一致。
   两者都只动纸面/描边/文字这几档令牌 + 顶栏底栏那两条写死的渐变。 */
body.lt-dusk { --lt-paper: #fff3e0; --lt-paper-2: #ffe9cd; --lt-paper-3: #ffdfba;
               --lt-stroke: #6d4526; --lt-line: rgba(109, 69, 38, .28);
               --lt-ink: #3b2415; --lt-ink-2: #5b3a22; --lt-ink-3: #8a6a4c;
               --lt-edge: rgba(109, 69, 38, .24); }
body.lt-dusk .lt-top { background: linear-gradient(180deg, #fff6ea 0%, #ffe9cf 100%); }
body.lt-dusk .lt-dock { background: linear-gradient(180deg, #fff6ea, #ffe4c6); }
body.lt-overcast { --lt-paper: #f2f5f7; --lt-paper-2: #e7ecef; --lt-paper-3: #dde4e8;
                   --lt-stroke: #46545e; --lt-line: rgba(70, 84, 94, .26);
                   --lt-ink: #26313a; --lt-ink-2: #3d4b55; --lt-ink-3: #6d7c86;
                   --lt-edge: rgba(70, 84, 94, .22); }
body.lt-overcast .lt-top { background: linear-gradient(180deg, #f6f9fb 0%, #e6ecf0 100%); }
body.lt-overcast .lt-dock { background: linear-gradient(180deg, #f6f9fb, #e2e9ee); }

/* ---------- 14. 安全区 / 窄屏兜底 ---------- */
/* ---------- 14b. 横屏：至少不要明显错位 ----------
   竖屏那套（顶栏 56 + 底栏 68 + 时段条 44 + 工具竖排 5×44）在横屏
   （常见 740×360 / 800×360）里几乎把画面吃光。这里只做"压缩 + 换排布"，
   不改任何尺寸令牌的语义：
     · 顶栏 / 底栏压矮，工具竖排改成贴右上角的横排（横屏右边是长的）
     · 时段条贴左上角（横屏不需要占一整行）
     · 摇杆和提示语留出中间的行动区，别压到地点栏
   用 orientation: landscape 而不是 max-width —— 横屏的宽度是够的，
   问题只出在高度。 */
@media (orientation: landscape) and (max-height: 560px) {
  :root { --lt-top-h: 46px; --lt-dock-h: 56px; }
  .lt-brand { font-size: 14px; gap: 6px; }
  .lt-brand b { font-size: 14.5px; }
  .lt-logo { width: 26px; height: 26px; border-radius: 9px; }
  .lt-logo .lt-ic { width: 16px; height: 16px; }
  .lt-pill { height: 26px; font-size: 12px; padding: 0 7px; }
  .lt-tools { flex-direction: row; top: calc(var(--lt-top-full) + 6px); right: 8px; gap: 6px; }
  .lt-ico { width: 38px; height: 38px; border-radius: 11px; }
  .lt-ico .lt-ic { width: 18px; height: 18px; }
  .lt-ico.lt-ico-shot { width: 34px; height: 34px; }
  .lt-timebar { top: calc(var(--lt-top-full) + 6px); left: 8px; padding: 3px; }
  .lt-timebtn { min-width: 40px; min-height: 36px; font-size: 9.5px; padding: 2px 5px; gap: 1px; }
  .lt-timebtn i { font-size: 15px; }
  .lt-timebtn .lt-ic { width: 15px; height: 15px; }
  .lt-timefold { min-height: 36px; }
  .lt-dock-btn { min-height: 42px; font-size: 11px; }
  .lt-stick { width: 88px; height: 88px; left: 12px; bottom: calc(var(--lt-dock-full) + 8px); }
  #lt3dHint { max-width: 54vw; font-size: 11.5px; }
  .lt-sheet-body { max-height: 94vh; }
  .lt-room { max-width: 46vw; }
}

@media (max-width: 430px) {
  .lt-top { gap: 6px; padding: 0 8px; padding-top: var(--lt-safe-t); }
  .lt-brand b { font-size: 15.5px; }
  .lt-pill { padding: 0 8px; font-size: 12.5px; gap: 4px; }
  .lt-pill em { display: none; }
  .lt-timebtn { min-width: 46px; }
}
@media (max-width: 360px) {
  .lt-brand b { display: none; }
  .lt-timebtn { min-width: 42px; font-size: 10px; }
}
@media (prefers-reduced-motion: reduce) {
  .lt-timebtn:active, .lt-ico:active, .lt-dock-btn:active, .lt-spot:active { transform: none; }
}


/* ============================================================
 * ?hud=0 —— 隐藏【整个 HUD】（宣传片抓帧用，2026-09-21 用户要求）
 * ------------------------------------------------------------
 * 为什么要它：要让电脑上的无头浏览器按 ?time=…&cam=…&hud=0 自己抓 3D 画面剪宣传片，
 * 而用户明确要求【片子里不许出现 2D 的 UI 画面】。
 *
 * 隐藏：顶栏/资源条、时段按钮排、右侧工具列、底栏地点按钮、摇杆、
 *       气泡/提示/toast、地点面板、进房间提示、首屏加载页（它也是 2D UI）。
 * 保留：**3D 场景本身** —— 包括三条石路、房子、以及 3D 里的悬浮名牌
 *       （名牌是场景里的 sprite，不是 DOM，属于"3D 场景"的一部分）。
 *
 * 🔴 用 `display: none` 而不是 `visibility: hidden` / `opacity: 0`：
 *    后两者仍会占位、仍可能被合成器画进一帧；抓帧要的是"这一帧里彻底没有它"。
 *    用 `display:none` 之后这些元素不再有布局盒 ⇒ 不会渲染、也不会响应指针。
 *    （摇杆被隐藏后 rect 为 0，但它同时收不到 pointer 事件，所以不会算出 NaN；
 *     相机/拾取用的是 canvas 的 rect，与 HUD 无关 —— 玩法与性能都不受影响。）
 * 开关在 index.html 的内联脚本里，解析期就挂到 <html> 上 ⇒ 第一帧就是干净的，
 * 不会"先闪一下 HUD 再消失"。
 * ============================================================ */
html.lt-hud-off .lt-top,
html.lt-hud-off .lt-tools,
html.lt-hud-off .lt-timebar,
html.lt-hud-off .lt-dock,
html.lt-hud-off .lt-sheet,
html.lt-hud-off .lt-bubble,
html.lt-hud-off .lt-hint,
html.lt-hud-off .lt-toast,
html.lt-hud-off .lt-stick,
html.lt-hud-off #ltStick,
html.lt-hud-off #lt3dHint,
html.lt-hud-off #ltRoomLoading,
html.lt-hud-off #lt3dLoading,
html.lt-hud-off #ltLabels,
html.lt-hud-off .lt-room,
html.lt-hud-off #ltRoom,
html.lt-hud-off .lt-perf,
html.lt-hud-off #ltPerf {
  display: none !important;
  pointer-events: none !important;
}

/* ============================================================
 * ④ CSS 暗角（第五阶段 ⑰）—— 抄 scene-demo 的做法：**纯 CSS 一层**，不进后处理链，
 * 所以零显存、零 draw call、零 pass。作用是把视线收到画面中心、给"小品感"收边。
 * ⚠️ pointer-events: none —— 绝不能挡住摇杆/按钮/点地面（玩法红线）。
 * ⚠️ z-index 压在所有 HUD 之下（HUD 是 100+），只在画布上方。
 * ?hud=0 录制时**保留**它（它是"画面"的一部分，不是 UI）；要关就加 ?nograd=1。
 * ============================================================ */
#ltVignette {
  position: fixed; inset: 0; z-index: 5; pointer-events: none;
  background:
    radial-gradient(ellipse 128% 108% at 50% 46%,
      rgba(0, 0, 0, 0) 52%, rgba(18, 14, 10, .10) 74%, rgba(12, 9, 6, .26) 100%);
  mix-blend-mode: multiply;
}
html.lt-nograd #ltVignette { display: none; }
