/* ==========================================================================
   AI伴途（H5 / 安卓 WebView）—— 品牌标识见 brand/ 与 pages.js 的 BRAND_MARK
   设计系统 token 与小程序端 app.wxss 保持一致；
   换算规则：html 字号 = 100vw / 7.5 → 1rpx = 0.01rem（32rpx = 0.32rem）
   ========================================================================== */

:root {
  --c-primary: #0E6B57;
  --c-primary-deep: #0A4F41;
  --c-primary-soft: #E6F0ED;
  --c-accent: #E08A2E;
  --c-accent-soft: #FBF0E0;
  --c-bg: #F6F7F4;
  --c-surface: #FFFFFF;
  --c-surface-2: #F0F2EE;
  --c-ink: #16211E;
  --c-ink-2: #5C6B66;
  --c-ink-3: #93A19C;
  --c-line: #E4E7E3;
  --c-danger: #C4453B;
  --c-warn: #D99A2B;
  /* 全局底部导航「药丸自身」的高度（**不含**它与屏幕底边之间的间距）。
     只是兜底默认值：app.js 启动时会用实测高度覆盖成 px，以适配不同机型的字体缩放。
     约定：药丸顶边距屏幕底 = --tabbar-gap + --tabbar-h + 安全区。 */
  --tabbar-h: 1.12rem;
  /* 悬浮药丸与屏幕底边之间的间距（与左右边距同档） */
  --tabbar-gap: 0.24rem;
}

html {
  font-size: calc(100vw / 7.5);
  -webkit-text-size-adjust: 100%;
}
@media (min-width: 560px) {
  html { font-size: 74.66px; }
}

* { margin: 0; padding: 0; box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html, body { height: 100%; }

body {
  font-family: "Noto Sans SC", -apple-system, BlinkMacSystemFont, "PingFang SC", "Helvetica Neue", Arial, sans-serif;
  font-size: 0.3rem;
  color: var(--c-ink);
  background-color: #F6F7F4;
  overscroll-behavior: none;
}

#app {
  position: relative;
  max-width: 560px;
  margin: 0 auto;
  min-height: 100%;
  background-color: var(--c-bg);
  color: var(--c-ink);
  overflow-x: hidden;
}

/* —— 夜间主题（**已下线，勿用**）——
   全 App 固定日间（浅色）：根类名恒为 .theme-day（见 core.js Theme）。
   以下 .theme-night 规则为历史遗留，现已无任何代码会挂上这个类；
   保留仅为记录演进 + 万一将来要恢复双主题时有现成对照。
   ⚠️ 新增样式请一律写成「浅色为默认」，不要再往这层加覆盖。 */
.theme-night {
  --c-bg: #0E1513;
  --c-surface: #17201D;
  --c-surface-2: #1E2926;
  --c-ink: #EDF2F0;
  --c-ink-2: #9DAAA5;
  --c-ink-3: #6B7873;
  --c-line: #263230;
  --c-primary-soft: #14261F;
  --c-accent-soft: #2A2114;
}

img { display: block; }
button, input { font-family: inherit; }

/* —— 通用布局 —— */
.page-root { min-height: 100vh; background-color: var(--c-bg); color: var(--c-ink); }
.row { display: flex; flex-direction: row; align-items: center; }
.row-between { display: flex; flex-direction: row; align-items: center; justify-content: space-between; }
.col { display: flex; flex-direction: column; }
.center { display: flex; align-items: center; justify-content: center; }
.flex-1 { flex: 1; }
.safe-bottom { padding-bottom: calc(0.24rem + env(safe-area-inset-bottom)); }
.safe-top { padding-top: env(safe-area-inset-top); }
.divider { height: 1px; background-color: var(--c-line); }

/* —— 文本 —— */
.t-hero { font-size: 0.52rem; font-weight: 700; line-height: 1.25; }
.t-title { font-size: 0.4rem; font-weight: 700; line-height: 1.3; }
.t-subtitle { font-size: 0.34rem; font-weight: 600; line-height: 1.4; }
.t-body { font-size: 0.3rem; line-height: 1.6; }
.t-caption { font-size: 0.26rem; line-height: 1.5; color: var(--c-ink-2); }
.t-tiny { font-size: 0.22rem; line-height: 1.4; color: var(--c-ink-3); }
.ellipsis { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }

/* —— 卡片 —— */
.card { background-color: var(--c-surface); border-radius: 0.2rem; padding: 0.32rem; }

/* —— 按钮 —— */
.btn {
  display: flex; align-items: center; justify-content: center;
  height: 0.96rem; border-radius: 999px;
  font-size: 0.3rem; font-weight: 600; line-height: 1;
  padding: 0 0.48rem; border: none; cursor: pointer;
  transition: opacity .15s ease;
}
.btn:active { opacity: .85; }
.btn-primary { background-color: var(--c-primary); color: #FFFFFF; }
.btn-ghost { background-color: transparent; color: var(--c-primary); border: 1px solid var(--c-primary); }
.btn-disabled { background-color: var(--c-surface-2); color: var(--c-ink-3); }

/* —— 标签 / 状态点 —— */
.tag { display: inline-flex; align-items: center; padding: 0.08rem 0.2rem; border-radius: 999px; font-size: 0.26rem; background-color: var(--c-primary-soft); color: var(--c-primary); }
.dot { width: 0.14rem; height: 0.14rem; border-radius: 50%; flex-shrink: 0; }
.dot-live { background-color: var(--c-accent); }
.dot-ok { background-color: var(--c-primary); }
.dot-warn { background-color: var(--c-warn); }
.dot-bad { background-color: var(--c-ink-3); }

@keyframes breathe { 0% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.35); opacity: .45; } 100% { transform: scale(1); opacity: 1; } }
.breathe { animation: breathe 1.6s ease-in-out infinite; }

/* —— 图标（内联 SVG data URI，与小程序端 icons.wxss 同源）—— */
.ico { width: 0.4rem; height: 0.4rem; background-repeat: no-repeat; background-position: center; background-size: contain; flex-shrink: 0; }
.ico-location { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%230E6B57' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 21.5s7-6.1 7-11.6a7 7 0 1 0-14 0c0 5.5 7 11.6 7 11.6z'/%3E%3Ccircle cx='12' cy='9.6' r='2.4'/%3E%3C/svg%3E"); }
.ico-history { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235C6B66' stroke-width='1.8' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='8.4'/%3E%3Cpath d='M12 7.4V12l3.2 2.1'/%3E%3C/svg%3E"); }
.ico-user { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235C6B66' stroke-width='1.8' stroke-linecap='round'%3E%3Ccircle cx='12' cy='8.4' r='3.9'/%3E%3Cpath d='M4.6 20.2a7.6 7.6 0 0 1 14.8 0'/%3E%3C/svg%3E"); }
.ico-arrow { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2393A19C' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 5.5l7 6.5-7 6.5'/%3E%3C/svg%3E"); width: 0.32rem; height: 0.32rem; }
.ico-back { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2316211E' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M15 5.5L8 12l7 6.5'/%3E%3C/svg%3E"); }
.ico-close { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235C6B66' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M6 6l12 12M18 6L6 18'/%3E%3C/svg%3E"); }
.ico-warn { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23D99A2B' stroke-width='1.8' stroke-linecap='round'%3E%3Cpath d='M12 4.2l8.4 15H3.6z'/%3E%3Cpath d='M12 9.6v3.6'/%3E%3Ccircle cx='12' cy='16.2' r='.9' fill='%23D99A2B' stroke='none'/%3E%3C/svg%3E"); }
.ico-check { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23FFFFFF' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.6l4.6 4.6L19 7.4'/%3E%3C/svg%3E"); width: 0.3rem; height: 0.3rem; }
.ico-volume { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235C6B66' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4.8 9.2h3.4L13 5.6v12.8l-4.8-3.6H4.8z'/%3E%3Cpath d='M16.4 9.4a3.6 3.6 0 0 1 0 5.2'/%3E%3C/svg%3E"); }
.ico-settings { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235C6B66' stroke-width='1.7' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='3.1'/%3E%3Cpath d='M12 3.4v2.2M12 18.4v2.2M4.9 4.9l1.6 1.6M17.5 17.5l1.6 1.6M3.4 12h2.2M18.4 12h2.2M4.9 19.1l1.6-1.6M17.5 6.5l1.6-1.6'/%3E%3C/svg%3E"); }
.ico-trash { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235C6B66' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 7h16M9 7V5.2A1.2 1.2 0 0 1 10.2 4h3.6A1.2 1.2 0 0 1 15 5.2V7M6.5 7l.8 12.2A1.6 1.6 0 0 0 8.9 20.6h6.2a1.6 1.6 0 0 0 1.6-1.4L17.5 7'/%3E%3Cpath d='M10 11v5M14 11v5'/%3E%3C/svg%3E"); }
/* 夜态下图标描边改为浅色 */
.theme-night .ico-history,
.theme-night .ico-user,
.theme-night .ico-volume,
.theme-night .ico-settings,
.theme-night .ico-back { filter: invert(1) brightness(1.6); }
.theme-night .ico-arrow { filter: invert(1) brightness(1.2); }

/* ==========================================================================
   通用：顶部导航条（网页端自绘，替代小程序原生导航栏）
   ========================================================================== */
.navbar {
  position: sticky; top: 0; z-index: 20;
  display: flex; align-items: center;
  height: calc(0.88rem + env(safe-area-inset-top));
  padding: env(safe-area-inset-top) 0.24rem 0;
  background-color: var(--c-bg);
}
.navbar-back { width: 0.6rem; height: 0.6rem; display: flex; align-items: center; justify-content: center; }
.navbar-title { flex: 1; text-align: center; font-size: 0.32rem; font-weight: 600; color: var(--c-ink); }
.navbar-right { width: 0.6rem; }

/* ==========================================================================
   Toast / Modal
   ========================================================================== */
.toast {
  position: fixed; left: 50%; bottom: 20vh; transform: translateX(-50%) translateY(0.3rem);
  max-width: 80vw; padding: 0.2rem 0.32rem; border-radius: 0.16rem;
  background: rgba(10, 20, 18, .9); color: #fff; font-size: 0.26rem; line-height: 1.5;
  opacity: 0; pointer-events: none; transition: opacity .2s ease, transform .2s ease;
  z-index: 3000; text-align: center;
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

.mask { position: fixed; inset: 0; background: rgba(8, 18, 15, .55); display: flex; align-items: flex-end; z-index: 2500; }
.modal { width: 100%; max-width: 560px; margin: 0 auto; background-color: var(--c-surface); border-radius: 0.32rem 0.32rem 0 0; padding: 0.48rem 0.4rem calc(0.4rem + env(safe-area-inset-bottom)); }
.modal-title { display: block; font-size: 0.4rem; font-weight: 700; margin-bottom: 0.24rem; }
.modal-body { max-height: 55vh; overflow-y: auto; font-size: 0.26rem; line-height: 1.8; color: var(--c-ink-2); white-space: pre-wrap; }
.modal-btns { display: flex; margin-top: 0.4rem; }
.modal-btn-reject { flex: 1; background-color: var(--c-surface-2); color: var(--c-ink-2); margin-right: 0.2rem; }
.modal-btn-agree { flex: 2; }

/* —— 点位卡片（点地图上「当天讲解过」的标注弹出）—— */
.pcard-head { display: flex; align-items: center; margin-bottom: 0.12rem; }
.pcard-dot { width: 0.18rem; height: 0.18rem; border-radius: 50%; flex: none; margin-right: 0.16rem; }
.pcard-name { flex: 1; min-width: 0; font-size: 0.4rem; font-weight: 700; color: var(--c-ink); }
.pcard-time { flex: none; margin-left: 0.16rem; font-size: 0.22rem; color: var(--c-ink-3);
  font-variant-numeric: tabular-nums; }
.pcard-meta { font-size: 0.24rem; color: var(--c-primary); margin-bottom: 0.24rem; }
.pcard-body { max-height: 42vh; overflow-y: auto; font-size: 0.28rem; line-height: 1.85;
  color: var(--c-ink-2); white-space: pre-wrap; }

/* ==========================================================================
   启动页
   ========================================================================== */
.launch { min-height: 100vh; display: flex; flex-direction: column; justify-content: space-between; padding: 1.6rem 0.56rem 0; background-color: var(--c-bg); }
.brand { display: flex; flex-direction: column; align-items: center; }
/* 品牌标识：AI伴途 / BANTU —— 圆角率 22.5%，与 brand/app-icon.svg 一致 */
.logo { width: 1.68rem; height: 1.68rem; border-radius: 22.5%; background: linear-gradient(145deg, #0E6B57 0%, #0A4F41 100%); position: relative; margin-bottom: 0.44rem; display: flex; align-items: center; justify-content: center; }
.logo-sm { width: 1.32rem; height: 1.32rem; margin-bottom: 0.28rem; }
.mark-svg { width: 100%; height: 100%; display: block; }
.wordmark { font-size: 0.68rem; font-weight: 700; letter-spacing: 0.08rem; line-height: 1.1; }
.wordmark-sub { font-size: 0.24rem; font-weight: 600; letter-spacing: 0.32rem; text-indent: 0.32rem; color: var(--c-primary); margin-top: 0.12rem; }
.tagline { margin-top: 0.3rem; font-size: 0.26rem; color: var(--c-ink-3); text-align: center; }

.panel { background-color: var(--c-surface); border-radius: 0.32rem; padding: 0.08rem 0.32rem; margin: 0 0 0.4rem; }
.panel-item { display: flex; padding: 0.28rem 0; }
.panel-body { margin-left: 0.22rem; flex: 1; }
.panel-title { display: block; font-size: 0.3rem; font-weight: 600; margin-bottom: 0.08rem; }
.panel-desc { font-size: 0.26rem; color: var(--c-ink-2); line-height: 1.55; }
.actions { padding-bottom: 0.6rem; }
.text-row { display: flex; justify-content: center; margin-top: 0.26rem; }
.agree-text { font-size: 0.22rem; color: var(--c-primary); text-decoration: underline; }
/* 「安装到桌面」——只在浏览器里可安装时出现 */
.install-row { display: flex; align-items: center; justify-content: center; gap: 0.12rem; margin-top: 0.24rem;
  padding: 0.22rem 0.32rem; border-radius: 999px; font-size: 0.26rem; font-weight: 600;
  color: var(--c-primary); border: 1px solid var(--c-primary); }
.install-row:active { background-color: var(--c-primary-soft); }
.install-ico { width: 0.28rem; height: 0.28rem; border-radius: 0.08rem;
  border: 0.04rem solid currentColor; position: relative; }
.install-ico::after { content: ''; position: absolute; left: 50%; top: 100%; width: 0.04rem; height: 0.16rem;
  background-color: currentColor; transform: translateX(-50%); }
.tip { display: block; text-align: center; margin-top: 0.18rem; font-size: 0.22rem; color: var(--c-ink-3); line-height: 1.5; }

/* ==========================================================================
   登录页
   ========================================================================== */
.login { min-height: 100vh; display: flex; flex-direction: column; padding: 1rem 0.56rem 0; background-color: var(--c-bg); }
.login .head { margin-bottom: 0.9rem; }
.head-sub { display: block; margin-top: 0.2rem; font-size: 0.3rem; color: var(--c-ink-2); line-height: 1.6; }
.main-block { margin-bottom: 0.7rem; }
.wx-btn { height: 1.08rem; }
.wx-mark { width: 0.36rem; height: 0.3rem; border-radius: 50% 50% 46% 46%; background: #FFFFFF; position: relative; margin-right: 0.18rem; }
.wx-mark::after { content: ''; position: absolute; left: 0.06rem; bottom: -0.07rem; width: 0; height: 0; border-left: 0.09rem solid transparent; border-right: 0.09rem solid transparent; border-top: 0.11rem solid #FFFFFF; }
.wx-btn-text { color: #FFFFFF; font-size: 0.34rem; font-weight: 600; }
.wx-tip { display: block; text-align: center; margin-top: 0.22rem; font-size: 0.22rem; color: var(--c-ink-3); }
/* 微信可用时的次要入口「使用本机账号登录」：刻意做成弱化的文字链，不与主按钮抢视线 */
.dev-row { display: block; text-align: center; margin-top: 0.3rem; font-size: 0.26rem; color: var(--c-ink-2); }
.alt-block { background-color: var(--c-surface); border-radius: 0.2rem; padding: 0 0.32rem; margin-bottom: 0.4rem; }
/* 登录页说明条（无短信验证码时的替代区块） */
.alt-note { display: flex; align-items: flex-start; padding: 0.28rem 0.32rem; }
.alt-note-ico { width: 0.3rem; height: 0.3rem; flex-shrink: 0; margin-top: 0.04rem; margin-right: 0.16rem; }
.alt-note-text { font-size: 0.24rem; line-height: 1.66; color: var(--c-ink-2); }
.alt-head { display: flex; align-items: center; justify-content: space-between; height: 1.08rem; }
.alt-title { font-size: 0.3rem; font-weight: 500; }
.alt-arrow { transform: rotate(90deg); transition: transform .2s ease; }
.alt-arrow-up { transform: rotate(-90deg); }
.phone-form { padding-bottom: 0.36rem; }
.field { display: flex; align-items: center; height: 1.04rem; border-bottom: 1px solid var(--c-line); }
.field-label { width: 1.3rem; font-size: 0.26rem; color: var(--c-ink-2); }
.field-input { flex: 1; font-size: 0.3rem; color: var(--c-ink); background: transparent; border: none; outline: none; }
.field-input::placeholder { color: var(--c-ink-3); font-size: 0.26rem; }
.send-code { font-size: 0.26rem; color: var(--c-primary); font-weight: 600; padding-left: 0.2rem; }
.send-code-off { color: var(--c-ink-3); font-weight: 400; }
.phone-btn { margin-top: 0.36rem; }
.guest-block { margin-top: auto; padding-bottom: 0.6rem; display: flex; flex-direction: column; align-items: center; }
.guest-link { font-size: 0.3rem; color: var(--c-primary); font-weight: 500; }
.guest-desc { margin-top: 0.16rem; font-size: 0.22rem; color: var(--c-ink-3); text-align: center; line-height: 1.6; padding: 0 0.4rem; }

/* ==========================================================================
   偏好页
   ========================================================================== */
.pref { min-height: 100vh; display: flex; flex-direction: column; padding: 0.4rem 0.4rem 0; background-color: var(--c-bg); }
.pref .head { margin-bottom: 0.48rem; }
.grid { display: flex; flex-wrap: wrap; justify-content: space-between; }
.cell { width: 48.6%; min-height: 1.96rem; background-color: var(--c-surface); border: 1px solid var(--c-line); border-radius: 0.2rem; padding: 0.26rem 0.26rem 0.22rem; margin-bottom: 0.22rem; display: flex; flex-direction: column; justify-content: space-between; transition: border-color .18s ease, background-color .18s ease; }
.cell-on { border-color: var(--c-primary); background-color: var(--c-primary-soft); }
.cell-top { display: flex; align-items: flex-start; justify-content: space-between; margin-bottom: 0.14rem; }
.cell-label { font-size: 0.34rem; font-weight: 600; flex: 1; margin-right: 0.12rem; }
.cell-check { width: 0.36rem; height: 0.36rem; border-radius: 50%; border: 1px solid var(--c-line); display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.cell-on .cell-check { background-color: var(--c-primary); border-color: var(--c-primary); }
.cell-desc { font-size: 0.22rem; color: var(--c-ink-2); line-height: 1.55; }
.cell-on .cell-desc { color: var(--c-primary); }
.foot { margin-top: auto; padding: 0.32rem 0 0.48rem; }
.foot-count { display: block; text-align: center; font-size: 0.22rem; color: var(--c-ink-3); margin-bottom: 0.22rem; }
.foot-btn { width: 100%; }

/* ==========================================================================
   语音与方言（2.0）—— 对应设计稿 08
   换算：设计稿 390 宽 → 1px = 1/52 rem（与全站一致）
   注意本页配色与其它页相反：**页面白底、卡片浅灰**（设计稿如此），
   因为选中态用品牌浅绿、未选中用浅灰，只有在白底上才分得出层次。
   ========================================================================== */
.voice { min-height: 100vh; background-color: var(--c-surface); }
.vc-body { display: flex; flex-direction: column; gap: 0.346rem; padding: 0.115rem 0.385rem 0.423rem; }
.vc-sec { font-size: 0.25rem; font-weight: 600; color: var(--c-ink); }

/* —— 云端生效音色（2026-10-12）——
   决定合成音色的是服务端那份，本机选择只是「我点了哪个」。
   两者不一致 = 点了却听不出变化。这一行把服务端实际用的音色摊开，
   不一致时整条变红，用户与排查者一眼可见，不用再猜。 */
.vc-cloud {
  display: flex; align-items: baseline; gap: 0.115rem;
  padding: 0.135rem 0.192rem;
  border-radius: 0.154rem;
  background-color: #F1F5F3;
  font-size: 0.212rem; line-height: 1.45;
  color: var(--c-ink-2);
}
.vc-cloud-k {
  flex: none;
  font-weight: 600;
  color: var(--c-ink-3);
}
.vc-cloud-bad {
  background-color: #FDECEC;
  color: #B3261E;
}
.vc-cloud-bad .vc-cloud-k { color: #B3261E; }
.vc-cloud-warn {
  background-color: #FFF6E5;
  color: #8A5A00;
}
.vc-cloud-warn .vc-cloud-k { color: #8A5A00; }

/* —— 讲解音色：分组列表 ——
   V2.1 起有 39 个音色，原来的 2 列大卡片撑不下；改成「小组标题 + 行列表」，
   每行右侧一个试听键：点行=选中，点键=只试听不改设置。 */
.vc-tag {
  margin-top: 0.308rem; margin-bottom: 0.115rem;
  font-size: 0.212rem; font-weight: 600; letter-spacing: .02em;
  color: var(--c-ink-3);
}
.vc-list {
  display: flex; flex-direction: column; gap: 0.115rem;
  border-radius: 0.231rem; overflow: hidden;
}
.vc-row {
  display: flex; align-items: center; gap: 0.192rem;
  height: 1.077rem; padding: 0 0.269rem;
  background-color: var(--c-bg); color: var(--c-ink);
  transition: background-color .16s ease;
}
.vc-row:active { opacity: .82; }
.vc-row-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0.038rem; }
.vc-row-on { background-color: var(--c-primary-soft); }
.vc-row-on .vc-name { color: var(--c-primary); }
.vc-row-on .vc-desc { color: var(--c-primary); opacity: .75; }
/* 试听键：命中区域单独放大，手指不必精确戳小图标（行车场景宁可做大） */
.vc-row-play {
  flex: none; width: 0.692rem; height: 0.692rem; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background-color: var(--c-line); color: var(--c-ink-2);
}
.vc-row-on .vc-row-play { background-color: var(--c-primary); color: #FFFFFF; }
.vc-row-play-on { background-color: var(--c-primary); color: #FFFFFF; }

/* —— 方言：胶囊 —— */
.vc-chips { display: flex; flex-wrap: wrap; gap: 0.192rem; }
.vc-chip {
  display: flex; align-items: center; height: 0.75rem; padding: 0 0.308rem;
  border-radius: 999px; font-size: 0.25rem; font-weight: 500;
  background-color: var(--c-bg); color: var(--c-ink-2);
  transition: background-color .16s ease, color .16s ease;
}
.vc-chip-on { background-color: var(--c-primary); color: #FFFFFF; }
/* 当前音色不具备方言能力时的禁用态：置灰且不可点（点了服务端会合成失败） */
.vc-chip-off { opacity: .38; }
.vc-note { font-size: 0.212rem; line-height: 1.6; color: var(--c-ink-3); }
.vc-note b { color: var(--c-primary); font-weight: 600; }

/* —— 语速 / 语调滑块 —— */
.vc-slider { display: flex; flex-direction: column; gap: 0.192rem; }
.vc-slider-head { display: flex; align-items: center; justify-content: space-between; }
.vc-slider-label { font-size: 0.25rem; font-weight: 500; color: var(--c-ink); }
.vc-slider-value { font-size: 0.231rem; font-weight: 500; color: var(--c-primary); font-variant-numeric: tabular-nums; }
/* 自绘滑块：原生 range 在各内核下做不出「绿色已选段 + 白底描边手柄」这套一致的观感
   手柄圆心 = (轨道宽 − 手柄宽) × ratio + 手柄半径，与 JS 里的取值公式严格同源 */
.vc-range { position: relative; height: 0.385rem; touch-action: pan-y; }
.vc-track, .vc-fill { position: absolute; left: 0; top: 50%; transform: translateY(-50%); height: 0.115rem; border-radius: 0.058rem; }
.vc-track { width: 100%; background-color: var(--c-line); }
.vc-fill { width: calc((100% - 0.346rem) * var(--vc-ratio, 0) + 0.173rem); background-color: var(--c-primary); }
.vc-knob {
  position: absolute; top: 50%; margin-top: -0.173rem;
  left: calc((100% - 0.346rem) * var(--vc-ratio, 0) + 0.173rem);
  transform: translateX(-50%);
  width: 0.346rem; height: 0.346rem; border-radius: 50%;
  background-color: #FFFFFF; border: 0.048rem solid var(--c-primary);
  box-shadow: 0 0.02rem 0.06rem rgba(16,50,42,.18);
}

/* —— 试听 —— */
.vc-try {
  display: flex; align-items: center; justify-content: center; gap: 0.173rem;
  height: 1rem; border-radius: 999px;
  background-color: var(--c-primary); color: #FFFFFF;
  font-size: 0.288rem; font-weight: 500; cursor: pointer;
}
.vc-try:active { opacity: .88; }

/* 夜间：品牌深绿在暗底上做文字/描边对比度不足，统一换成提亮绿（与地图朝向标记同一处理） */
.theme-night .vc-row-on .vc-name,
.theme-night .vc-row-on .vc-desc,
.theme-night .vc-note b,
.theme-night .vc-slider-value { color: #7FC8AD; }
.theme-night .vc-fill { background-color: #7FC8AD; }
.theme-night .vc-knob { border-color: #7FC8AD; background-color: #EDF2F0; }

/* ==========================================================================
   导游主页
   ========================================================================== */
.guide { position: relative; min-height: 100vh; background-color: var(--c-bg); overflow: hidden; }
.map { position: absolute; left: 0; top: 0; width: 100%; height: 100vh; background:
  radial-gradient(120% 80% at 20% 10%, rgba(14,107,87,.18) 0%, rgba(14,107,87,0) 55%),
  radial-gradient(100% 70% at 85% 90%, rgba(224,138,46,.12) 0%, rgba(224,138,46,0) 60%),
  linear-gradient(180deg, #0C1412 0%, #101A17 55%, #0B1210 100%);
}
.theme-day .map { background:
  radial-gradient(120% 80% at 20% 10%, rgba(14,107,87,.10) 0%, rgba(14,107,87,0) 55%),
  radial-gradient(100% 70% at 85% 90%, rgba(224,138,46,.10) 0%, rgba(224,138,46,0) 60%),
  linear-gradient(180deg, #EDF1EE 0%, #E6EBE7 100%);
}
.map-grid { position: absolute; inset: 0; z-index: 1; background-image: linear-gradient(rgba(255,255,255,.045) 1px, transparent 1px), linear-gradient(90deg, rgba(255,255,255,.045) 1px, transparent 1px); background-size: 0.8rem 0.8rem; }
.theme-day .map-grid { background-image: linear-gradient(rgba(10,30,26,.05) 1px, transparent 1px), linear-gradient(90deg, rgba(10,30,26,.05) 1px, transparent 1px); }
/* 底图：腾讯位置服务静态图，由云函数代取（Key 不下发客户端）后淡入，覆盖网格占位。
   图片按 160% 超采样铺放（四周各留 30% 余量），拖动时直接平移已有像素，松手才重新取图。
   ⚠️ 这里的 160% 只是 JS 还没接管时的兜底：导航态下整张图要绕中心旋转，
      尺寸必须够到容器对角线（否则转到 45° 就露白），所以实际宽高由
      `_layoutMapImg()` 按「对角线 vs 160%」取大者后写成 px 覆盖掉这两行。 */
.map-canvas { position: absolute; inset: 0; z-index: 0; }
.map-img { position: absolute; left: -30%; top: -30%; width: 160%; height: 160%; object-fit: cover;
  opacity: 0; transition: opacity .45s ease; z-index: 0; transform-origin: 50% 50%; will-change: transform; }
.map-scrim {
  position: absolute; inset: 0; z-index: 1; opacity: 0; transition: opacity .45s ease;
  background: linear-gradient(180deg, rgba(8,14,12,.86) 0%, rgba(8,14,12,.34) 26%, rgba(8,14,12,.18) 48%, rgba(8,14,12,.74) 100%);
}
.theme-day .map-scrim {
  background: linear-gradient(180deg, rgba(246,247,244,.90) 0%, rgba(246,247,244,.46) 26%, rgba(246,247,244,.24) 48%, rgba(246,247,244,.82) 100%);
}
.map-attrib { position: absolute; right: 0.24rem; bottom: 0.24rem; z-index: 1; padding: 0.06rem 0.16rem; border-radius: 999px;
  font-size: 0.18rem; color: var(--c-ink-2); background-color: rgba(255,255,255,.74); opacity: 0; transition: opacity .45s ease; }
.theme-night .map-attrib { background-color: rgba(23,32,29,.74); color: var(--c-ink-3); }
.map.has-map .map-img,
.map.has-map .map-scrim,
.map.has-map .map-attrib { opacity: 1; }
.map.has-map .map-grid { display: none; }

/* 地图要能吃掉拖动/捏合手势，否则浏览器会拿去滚页面 */
.map { touch-action: none; }

/* —— 简约底图（V2.1 过渡方案）——
   设计稿（画布 734463845407684）是「米白陆地 + 白色路网 + 低饱和绿地水系」的
   简约风；矢量底图的真正换肤要走腾讯位置服务控制台的「个性化地图样式」
   （样式 ID 由 guide 云函数环境变量 MAP_STYLE_ID 下发，见 mapConfig）。
   在拿到正式样式 ID 之前，先给画布上一层轻度去饱和+提亮，观感先向设计稿靠拢。
   ⚠️ 滤镜放在 canvas 上而不是容器上：容器上叠 filter 会生成新的合成层，
      把 `.map-img`（静态图兜底）一起盖住导致双层地图闪烁。 */
.map-canvas canvas { filter: saturate(0.62) brightness(1.05) contrast(0.98); }
/* 盖在地图之上的遮罩/网格/角标/底图/定位胶囊一律不吃手势。
   ⚠️ .map-img 必须在内：它与 .map-canvas 同为 z-index:0 但在 DOM 后面，
      实际压在 TMap 画布之上，会吞掉全部 touch/pointer 事件 —— 表现为
      「矢量地图看得见、拖不动、也不能双指缩放」。 */
.map-img, .map-scrim, .map-grid, .map-attrib, .map-heading { pointer-events: none; }
/* touch-action 不继承，必须显式给到画布及其内部节点，否则浏览器会把手势抢去滚页面 */
.map-canvas, .map-canvas * { touch-action: none; }

/* 缩放 / 回到当前位置 */
.map-tools { position: absolute; right: 0.24rem; top: 50%; transform: translateY(-50%); z-index: 4;
  display: flex; flex-direction: column; gap: 0.16rem; }
.map-tool { width: 0.78rem; height: 0.78rem; border-radius: 0.24rem; display: flex; align-items: center; justify-content: center;
  font-size: 0.42rem; line-height: 1; font-weight: 300; color: var(--c-ink);
  background-color: rgba(255,255,255,.94); box-shadow: 0 0.04rem 0.18rem rgba(10,30,26,.16);
  user-select: none; -webkit-user-select: none; }
.map-tool:active { background-color: rgba(255,255,255,.78); transform: scale(.94); }
.theme-night .map-tool { background-color: rgba(23,32,29,.94); color: var(--c-ink); box-shadow: 0 0.04rem 0.18rem rgba(0,0,0,.34); }
.map-tool-home { display: flex; }
.map-tool-home .ico { width: 0.36rem; height: 0.36rem; }
/* 「自由浏览」橘色胶囊已按用户要求移除（自由浏览态只保留「回到当前位置」按钮） */

/* 顶部胶囊要避让状态栏/刘海：原生侧已把状态栏改透明并让内容延伸到其下方，
   这里用 env(safe-area-inset-top) 把内容顶到状态栏之下，地图本身仍全屏铺满。 */
.guide .statusbar { position: relative; display: flex; align-items: center; justify-content: space-between; padding: calc(0.2rem + env(safe-area-inset-top)) 0.28rem 0; z-index: 5; }
.status-chip { display: flex; align-items: center; height: 0.68rem; padding: 0 0.26rem; border-radius: 999px; background-color: rgba(255,255,255,.92); box-shadow: 0 0.04rem 0.2rem rgba(10,30,26,.10); }
.theme-night .status-chip { background-color: rgba(23,32,29,.92); }
.status-text { font-size: 0.26rem; font-weight: 600; font-variant-numeric: tabular-nums; margin-left: 0.12rem; }
.status-gps { font-weight: 400; color: var(--c-ink-2); }
.status-sep { width: 1px; height: 0.26rem; background-color: var(--c-line); margin: 0 0.18rem; }
.status-actions { display: flex; }
.icon-btn { width: 0.72rem; height: 0.68rem; display: flex; align-items: center; justify-content: center; border-radius: 999px; background-color: rgba(255,255,255,.92); margin-left: 0.16rem; box-shadow: 0 0.04rem 0.2rem rgba(10,30,26,.10); }
.theme-night .icon-btn { background-color: rgba(23,32,29,.92); }

.notice { position: relative; z-index: 5; display: flex; align-items: center; margin: 0.22rem 0.28rem 0; padding: 0.2rem 0.26rem; border-radius: 0.2rem; background-color: rgba(217,154,43,.14); border: 1px solid rgba(217,154,43,.32); }
.notice-dim { background-color: rgba(255,255,255,.88); border-color: var(--c-line); }
.theme-night .notice-dim { background-color: rgba(23,32,29,.9); }
.notice-ico { width: 0.32rem; height: 0.32rem; margin-right: 0.14rem; }
.notice-text { flex: 1; font-size: 0.22rem; color: var(--c-ink-2); line-height: 1.5; }
/* —— 「请保持在前台」这类起步提示：启动讲解后缓缓淡出 ——
   只用 opacity 会让空出来的位置留一块空白，所以把高度/内边距/边框一起过渡到 0，
   收起过程是「淡出 + 收拢」同时发生，版面上不会留下空洞。 */
.notice-auto { max-height: 2.4rem; overflow: hidden;
  transition: opacity 1.4s ease, max-height 1.4s ease, margin-top 1.4s ease,
              padding-top 1.4s ease, padding-bottom 1.4s ease, border-width 1.4s ease; }
.notice-auto.is-gone { opacity: 0; max-height: 0; margin-top: 0;
  padding-top: 0; padding-bottom: 0; border-width: 0; }

.idle { position: relative; z-index: 4; margin: 1.2rem 0.6rem 0; padding: 0.48rem 0.4rem; border-radius: 0.32rem; background-color: rgba(255,255,255,.94); box-shadow: 0 0.1rem 0.5rem rgba(10,30,26,.10); }
.theme-night .idle { background-color: rgba(23,32,29,.94); }
.idle-title { display: block; font-size: 0.4rem; font-weight: 700; margin-bottom: 0.18rem; }
.idle-desc { display: block; font-size: 0.26rem; color: var(--c-ink-2); line-height: 1.7; }
.idle-block { display: block; margin-top: 0.22rem; font-size: 0.22rem; color: var(--c-danger); line-height: 1.6; }

/* 底部面板是全宽容器（含内边距、空占位），它本身不吃手势 —— 否则整条底部横带
   都变成「地图拖不动」的死区；只有真正可点的子元素（卡片/字幕/音量/标签栏）才接收事件。 */
.guide .bottom { position: absolute; left: 0; right: 0; bottom: 0; z-index: 6; padding: 0 0.24rem;
  pointer-events: none; }
.guide .bottom > * { pointer-events: auto; }
.preparing { display: flex; align-items: center; margin-bottom: 0.16rem; padding: 0.2rem 0.26rem; border-radius: 0.2rem; background-color: var(--c-primary-soft); border: 1px solid rgba(14,107,87,.16); }
.preparing-dot { width: 0.16rem; height: 0.16rem; margin-right: 0.16rem; border-radius: 50%; background-color: var(--c-primary); animation: prep-pulse 1.2s ease-in-out infinite; }
.preparing-text { flex: 1; font-size: 0.22rem; color: var(--c-primary); line-height: 1.5; }
@keyframes prep-pulse { 0%,100% { opacity: .35; transform: scale(.8); } 50% { opacity: 1; transform: scale(1.1); } }

/* —— 顶部状态胶囊（设计稿：湖州·南浔段 | 62 km/h | 讲解中） —— */
/* 同 .guide .statusbar：整体让开状态栏（用 margin 而非 padding，胶囊才不会被撑歪） */
.navpill { position: relative; z-index: 5; display: flex; align-items: center; margin: calc(0.2rem + env(safe-area-inset-top)) 0.24rem 0; padding: 0.12rem 0.12rem 0.12rem 0.26rem; background-color: rgba(255,255,255,.96); border-radius: 999px; box-shadow: 0 0.08rem 0.36rem rgba(10,30,26,.14); }
.theme-night .navpill { background-color: rgba(255,255,255,.96); }
/* 设计稿顶栏是一体白卡：夜间主题也保持白底，文字用固定深色（夜间变量是浅色，会白底白字） */
.theme-night .navpill-loc { color: #17211E; }
.theme-night .navpill-speed { color: #5C6B66; }
.navpill-pin { width: 0.34rem; height: 0.34rem; flex-shrink: 0; background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%230E6B57'%3E%3Cpath d='M21 3.6L3.8 10.4c-.9.35-.84 1.63.09 1.9l6.1 1.8 1.8 6.1c.27.93 1.55 1 1.9.09L20.4 3a.75.75 0 0 0-.96-.96z'/%3E%3C/svg%3E") center/contain no-repeat; }
.navpill-loc { flex: 1; min-width: 0; margin: 0 0.16rem 0 0.12rem; font-size: 0.27rem; font-weight: 600; color: var(--c-ink); }
.navpill-speed { flex-shrink: 0; font-size: 0.25rem; color: var(--c-ink-2); margin-right: 0.22rem; font-variant-numeric: tabular-nums; }
.navpill-toggle { display: flex; align-items: center; flex-shrink: 0; padding: 0.16rem 0.3rem; border-radius: 999px; background-color: var(--c-surface-2); color: var(--c-ink-2); font-size: 0.25rem; font-weight: 600; letter-spacing: 0.02rem; }
.navpill-toggle.is-live { background-color: var(--c-primary); color: #FFFFFF; box-shadow: 0 0.06rem 0.2rem rgba(14,107,87,.32); }
.navpill-toggle.btn-disabled { opacity: .55; }
.navpill-speaker { width: 0.32rem; height: 0.32rem; margin-right: 0.1rem; background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235C6B66' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4.8 9.2h3.4L13 5.6v12.8l-4.8-3.6H4.8z'/%3E%3Cpath d='M16.4 9.4a3.6 3.6 0 0 1 0 5.2'/%3E%3C/svg%3E") center/contain no-repeat; }
.navpill-toggle.is-live .navpill-speaker { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23FFFFFF' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4.8 9.2h3.4L13 5.6v12.8l-4.8-3.6H4.8z'/%3E%3Cpath d='M16.4 9.4a3.6 3.6 0 0 1 0 5.2'/%3E%3C/svg%3E"); }

/* —— 底部标签条（设计稿：导览 / 足迹 / 我的） —— */
.tabbar { display: flex; align-items: center; margin-top: 0.2rem; padding: 0.12rem; background-color: rgba(255,255,255,.96); border-radius: 999px; box-shadow: 0 0.08rem 0.36rem rgba(10,30,26,.14); }
.theme-night .tabbar { background-color: rgba(23,32,29,.96); }
.tab-item { flex: 1; display: flex; flex-direction: column; align-items: center; padding: 0.14rem 0 0.12rem; border-radius: 999px; font-size: 0.2rem; color: var(--c-ink-3); }
.tab-item .ico { margin-bottom: 0.05rem; }
.tab-active { background-color: var(--c-primary); color: #FFFFFF; font-weight: 600; }
.tab-active .ico { filter: brightness(0) invert(1); }
.ico-compass { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235C6B66' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='8.6'/%3E%3Cpath d='M15.6 8.4l-2 5.2-5.2 2 2-5.2z'/%3E%3C/svg%3E"); }
.ico-heart { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235C6B66' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 20s-7.2-4.6-9-9a4.7 4.7 0 0 1 9-2 4.7 4.7 0 0 1 9 2c-1.8 4.4-9 9-9 9z'/%3E%3C/svg%3E"); }

/* —— 讲解卡（设计稿驾驶卡：正在播报徽标 + 大标题 + 波形进度 + 全文链接） —— */
.acard { background-color: var(--c-surface); border-radius: 0.32rem; padding: 0.3rem 0.32rem 0.28rem; box-shadow: 0 0.1rem 0.44rem rgba(10,30,26,.14); }
.acard-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 0.16rem; }
.acard-badge { display: inline-flex; align-items: center; font-size: 0.22rem; font-weight: 600; color: var(--c-accent); background-color: var(--c-accent-soft); padding: 0.07rem 0.2rem; border-radius: 999px; }
.acard-badge::before { content: ''; width: 0.12rem; height: 0.12rem; border-radius: 50%; background-color: var(--c-accent); margin-right: 0.1rem; animation: prep-pulse 1.2s ease-in-out infinite; }
.acard-badge-dim { color: var(--c-ink-3); background-color: var(--c-surface-2); }
.acard-badge-dim::before { background-color: var(--c-ink-3); animation: none; }
.acard-dist { font-size: 0.22rem; color: var(--c-ink-3); font-variant-numeric: tabular-nums; }
.acard-title { font-size: 0.44rem; font-weight: 700; margin-bottom: 0.1rem; }
.acard-meta { font-size: 0.22rem; color: var(--c-ink-3); margin-bottom: 0.24rem; }
.acard-player { display: flex; align-items: center; margin-bottom: 0.24rem; }
.acard-playbtn { width: 0.8rem; height: 0.8rem; border-radius: 50%; background-color: var(--c-primary); display: flex; align-items: center; justify-content: center; flex-shrink: 0; box-shadow: 0 0.06rem 0.22rem rgba(14,107,87,.3); }
.acard-playbtn:active { transform: scale(.94); }
.acard-playbtn svg { width: 0.34rem; height: 0.34rem; }
.wave { flex: 1; min-width: 0; display: flex; align-items: center; gap: 0.035rem; height: 0.6rem; margin: 0 0.2rem; }
.wave i { flex: 1; min-width: 0.03rem; border-radius: 999px; background-color: var(--c-line); transition: background-color .18s linear; }
.wave i.on { background-color: var(--c-primary); }
.theme-night .wave i.on { background-color: var(--c-accent); }
.acard-time { flex-shrink: 0; font-size: 0.2rem; color: var(--c-ink-3); font-variant-numeric: tabular-nums; }
.acard-vol { flex-shrink: 0; width: 0.44rem; height: 0.44rem; margin-left: 0.14rem; display: flex; align-items: center; justify-content: center; }
.acard-vol .ico { width: 0.34rem; height: 0.34rem; }
.acard-link { display: inline-flex; align-items: center; font-size: 0.24rem; font-weight: 600; color: var(--c-primary); padding: 0.04rem 0; }
.acard-link-arrow { margin-left: 0.08rem; transform: rotate(90deg); background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%230E6B57' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 5.5l7 6.5-7 6.5'/%3E%3C/svg%3E"); }

/* —— 开启导游：**纯手动** ——
   原「进入页面 N 秒后自动开启 + 右侧暂停倒计时」已按产品要求整体移除
   （自动倒计时相关的 .idle-cd / .idle-hold / .is-counting 一并删除）。
   现在开始与结束都由用户亲手控制，每一段行程的起止时间才是用户的真实意图。 */
.idle-start-row { display: flex; align-items: center; gap: 0.2rem; margin-top: 0.3rem; }
.idle-start { flex: 1; min-width: 0; position: relative; overflow: hidden;
  margin-top: 0; text-align: center; }
.idle-start-text { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* —— 字幕面板 —— */
.sub { background-color: var(--c-surface); border-radius: 0.2rem; overflow: hidden; margin-top: 0.16rem; }
.sub-bar { display: flex; align-items: center; justify-content: space-between; padding: 0.22rem 0.28rem; }
.sub-label { font-size: 0.26rem; font-weight: 600; letter-spacing: 0.01rem; }
.sub-hint { font-size: 0.22rem; color: var(--c-ink-3); margin-left: 0.14rem; }
.sub-toggle { display: flex; align-items: center; }
.sub-toggle-text { font-size: 0.22rem; color: var(--c-ink-3); margin-right: 0.06rem; }
.sub-arrow { transform: rotate(90deg); transition: transform .2s ease; }
.sub-arrow-up { transform: rotate(-90deg); }
.sub-body { max-height: 4.2rem; overflow-y: auto; padding: 0 0.28rem 0.26rem; }
.sub-line { font-size: 0.34rem; line-height: 1.7; color: var(--c-ink-3); padding: 0.1rem 0; transition: color .25s ease, transform .25s ease; transform-origin: left center; }
.sub-line-done { color: var(--c-ink-3); opacity: .55; }
.sub-line-active { color: var(--c-ink); font-weight: 600; transform: scale(1.02); }
.sub-collapsed .sub-body { display: none; }

/* —— 控制条 —— */
.ctrl { display: flex; align-items: center; justify-content: space-between; padding: 0.28rem 0.08rem 0.4rem; }
.ctrl-vol, .ctrl-settings { width: 0.88rem; height: 0.88rem; border-radius: 50%; background-color: rgba(255,255,255,.94); display: flex; align-items: center; justify-content: center; box-shadow: 0 0.06rem 0.24rem rgba(10,30,26,.12); }
.theme-night .ctrl-vol, .theme-night .ctrl-settings { background-color: rgba(23,32,29,.94); }
.ctrl-main { flex: 1; height: 1rem; margin: 0 0.22rem; border-radius: 999px; background-color: var(--c-primary); display: flex; align-items: center; justify-content: center; box-shadow: 0 0.1rem 0.3rem rgba(14,107,87,.28); }
.ctrl-main-stop { background-color: var(--c-accent); box-shadow: 0 0.1rem 0.3rem rgba(224,138,46,.30); }
.ctrl-main-dot { width: 0.16rem; height: 0.16rem; border-radius: 50%; background-color: #FFFFFF; margin-right: 0.16rem; }
.ctrl-main-text { font-size: 0.34rem; font-weight: 600; color: #FFFFFF; letter-spacing: 0.02rem; }
.ctrl-main.btn-disabled { background-color: var(--c-surface-2); box-shadow: none; }
.ctrl-main.btn-disabled .ctrl-main-text { color: var(--c-ink-3); }
/* 音量 + 声音自检面板 */
.vol-panel { margin: 0 0.24rem 0.18rem; padding: 0.22rem 0.28rem; border-radius: 0.2rem; background-color: rgba(255,255,255,.96); box-shadow: 0 0.06rem 0.24rem rgba(10,30,26,.10); }
.theme-night .vol-panel { background-color: rgba(23,32,29,.96); }
.vol-row { display: flex; align-items: center; }
.vol-label { font-size: 0.26rem; color: var(--c-ink-2); margin-right: 0.2rem; flex-shrink: 0; }
.vol-panel input[type=range] { flex: 1; accent-color: #0E6B57; }
.vol-acts { margin-top: 0.18rem; justify-content: space-between; gap: 0.16rem; }
.vol-test { flex-shrink: 0; padding: 0.14rem 0.28rem; border-radius: 0.32rem; font-size: 0.25rem; color: #FFFFFF; background-color: var(--c-primary); }
.vol-hint { flex: 1; text-align: right; font-size: 0.2rem; line-height: 1.5; color: var(--c-ink-3); }
/* 音量自检面板里的「语音与方言」快捷入口（声音不合适的下一步就是它） */
.vol-more { margin-top: 0.16rem; padding-top: 0.2rem; border-top: 1px solid var(--c-line); justify-content: space-between; }
.vol-more-label { font-size: 0.26rem; color: var(--c-primary); }
.vol-more .ico-arrow { width: 0.28rem; height: 0.28rem; }
.vol-diag { margin-top: 0.18rem; padding-top: 0.16rem; border-top: 1px solid var(--c-line); }
.vd-line { display: flex; align-items: center; justify-content: space-between; padding: 0.05rem 0; font-size: 0.24rem; }
.vd-k { color: var(--c-ink-3); }
.vd-v { color: var(--c-ink-2); font-weight: 600; }
.vd-v.ok { color: var(--c-primary); }
.vd-v.bad { color: var(--c-danger); }
.vd-concl { margin-top: 0.14rem; padding: 0.14rem 0.18rem; border-radius: 0.14rem; font-size: 0.23rem; line-height: 1.6; color: var(--c-ink-2); background-color: var(--c-surface-2); }
.theme-night .vd-concl { background-color: rgba(255,255,255,.06); }
/* 被自动播放策略拦下：徽标写成动作指令，让用户一眼知道该点哪 */
.acard-wait .acard-playbtn { background-color: var(--c-accent); animation: pulse-btn 1.4s ease-in-out infinite; }
@keyframes pulse-btn {
  0%, 100% { box-shadow: 0 0 0 0 rgba(224,138,46,.55); }
  50% { box-shadow: 0 0 0 0.14rem rgba(224,138,46,0); }
}
/* idle 页的「听不到声音」入口 */
.idle-audio { display: flex; align-items: center; justify-content: center; gap: 0.1rem; margin-top: 0.2rem; font-size: 0.24rem; color: var(--c-primary); }
.idle-audio .ico-volume { width: 0.3rem; height: 0.3rem; }

/* ==========================================================================
   足迹 / 播放记录页（对齐 UI 稿 Screen 05）
   换算：设计稿 390px 宽 → 本端 rem，系数 1/52（即 1px = 0.0192rem，与全局
   1rpx = 0.01rem 同源）。所有字号/间距/圆角都直接取自设计稿标注。
   ========================================================================== */
.trips {
  min-height: 100vh;
  background-color: var(--c-bg);
  /* 页面内 token：只在足迹页生效，日/夜两套，避免污染全局变量 */
  --tv-ink: #0E1A17;
  --tv-sub: #8C948F;
  --tv-card: #F5F7F4;
  --tv-chip-bg: #E6F2EE;
  --tv-chip-fg: #0E6B57;
  --tv-chip-wait-bg: #FCEFDD;
  --tv-chip-wait-fg: #9A5F14;
}
.theme-night .trips {
  --tv-ink: #EDF2F0;
  --tv-sub: #7E8B86;
  --tv-card: #1E2926;
  --tv-chip-bg: #14261F;
  --tv-chip-fg: #7FC8AD;
  --tv-chip-wait-bg: #2E2415;
  --tv-chip-wait-fg: #E0AE62;
}

/* 主体：左右 22px、上 8px（另叠状态栏安全区）、下 12px，段间距 18px */
.tv-body {
  display: flex; flex-direction: column; gap: 0.346rem;
  padding: calc(0.154rem + env(safe-area-inset-top)) 0.423rem 0.231rem;
}

/* —— 标题行 —— */
.tv-head { display: flex; align-items: center; justify-content: space-between; }
.tv-title { font-size: 0.462rem; font-weight: 700; color: var(--tv-ink); }
.tv-range { display: flex; align-items: center; font-size: 0.231rem; font-weight: 500; color: var(--c-primary); }

/* 小三角/箭头：范围标签朝下，分组头朝右（展开时转向上） */
.tv-caret { display: inline-block; width: 0; height: 0; }
.tv-range .tv-caret {
  margin-left: 0.077rem;
  border-left: 0.077rem solid transparent; border-right: 0.077rem solid transparent;
  border-top: 0.09rem solid var(--c-primary);
}
.tv-group-head .tv-caret {
  border-top: 0.077rem solid transparent; border-bottom: 0.077rem solid transparent;
  border-left: 0.09rem solid var(--c-ink-3);
  transition: transform .2s ease;
}
.tv-group-head .tv-caret-up { transform: rotate(-90deg); }

/* —— 三宫格统计：卡高 78px、圆角 16px、底色 #F5F7F4 —— */
.tv-stats { display: flex; gap: 0.192rem; }
.tv-stat {
  flex: 1; min-width: 0; height: 1.5rem;
  padding: 0.269rem 0.192rem 0 0.269rem;
  display: flex; flex-direction: column; gap: 0.135rem;
  border-radius: 0.308rem;
  background-color: var(--tv-card);
}
.tv-stat-v { font-size: 0.365rem; font-weight: 700; line-height: 1; color: var(--tv-ink); font-variant-numeric: tabular-nums; }
.tv-stat-v-em { color: var(--c-primary); }
.tv-stat-u { font-size: 0.212rem; line-height: 1.25; color: var(--tv-sub); }

/* —— 「点位 / 足迹」两个标签（默认落在足迹＝轨迹） —— */
.tv-tabs {
  display: flex; gap: 0.154rem;
  padding: 0.077rem;
  border-radius: 999px;
  background-color: var(--tv-card);
}
.tv-tab {
  flex: 1;
  display: flex; align-items: center; justify-content: center;
  height: 0.692rem;
  border-radius: 999px;
  font-size: 0.269rem; font-weight: 600;
  color: var(--tv-sub);
}
.tv-tab.is-on {
  background-color: #FFFFFF;
  color: var(--c-primary);
  box-shadow: 0 0.019rem 0.077rem rgba(16, 40, 32, .08);
}

/* —— 足迹标签：轨迹小地图 —— */
.tv-map {
  position: relative;
  height: 4.615rem;
  border-radius: 0.308rem;
  overflow: hidden;
  background-color: var(--tv-card);
}
.tv-map-mask {
  position: absolute; inset: 0; z-index: 2;
  display: flex; align-items: center; justify-content: center;
  font-size: 0.231rem; color: var(--tv-sub);
  background-color: var(--tv-card);
}
.tv-frows { display: flex; flex-direction: column; gap: 0.154rem; }
.tv-frow {
  display: flex; align-items: center; gap: 0.192rem;
  padding: 0.231rem 0.269rem;
  border: 1px solid transparent;
  border-radius: 0.231rem;
  background-color: var(--tv-card);
}
.tv-frow.is-on { border-color: var(--c-primary); background-color: var(--c-primary-soft); }
.tv-fmain { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0.077rem; }
.tv-fdate { font-size: 0.269rem; font-weight: 600; color: var(--tv-ink); }
.tv-fmeta { font-size: 0.212rem; color: var(--tv-sub); font-variant-numeric: tabular-nums; }
.tv-fgo {
  flex: none;
  display: flex; align-items: center;
  height: 0.577rem; padding: 0 0.231rem;
  border-radius: 999px;
  background-color: var(--c-primary-soft);
  color: var(--c-primary);
  font-size: 0.212rem; font-weight: 600;
}

/* —— 记录列表 —— */
.tv-records { display: flex; flex-direction: column; gap: 0.038rem; }
.tv-rec {
  display: flex; align-items: center; gap: 0.231rem;
  padding: 0.192rem 0;
  border-radius: 0.231rem;
  transition: background-color .15s ease;
}
.tv-rec.is-playing { background-color: var(--c-primary-soft); }
.tv-thumb {
  width: 1.077rem; height: 1.077rem; flex-shrink: 0;
  border-radius: 0.269rem;
  display: flex; align-items: center; justify-content: center;
}
.tv-thumb svg { width: 0.538rem; height: 0.538rem; display: block; }
/* 六类分类色：低饱和纸感色，与主体山水青绿同一家族 */
.tv-thumb-humanity { background-color: #E6F0ED; color: #0E6B57; }
.tv-thumb-architecture { background-color: #F7EDE0; color: #9A5F14; }
.tv-thumb-nature { background-color: #E4F1EB; color: #2F7D62; }
.tv-thumb-product { background-color: #F8E9E4; color: #B0553F; }
.tv-thumb-town { background-color: #E8EFF4; color: #3A6B8A; }
.tv-thumb-business { background-color: #EDF0F3; color: #5B6B7A; }
.theme-night .tv-thumb-humanity { background-color: #14261F; color: #7FC8AD; }
.theme-night .tv-thumb-architecture { background-color: #2E2415; color: #E0AE62; }
.theme-night .tv-thumb-nature { background-color: #14261F; color: #8FD3B8; }
.theme-night .tv-thumb-product { background-color: #2B1B17; color: #E09A82; }
.theme-night .tv-thumb-town { background-color: #17262F; color: #8FB4CC; }
.theme-night .tv-thumb-business { background-color: #1E262B; color: #A3B3BF; }

.tv-info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0.096rem; }
.tv-name { font-size: 0.269rem; font-weight: 600; color: var(--tv-ink); }
.tv-meta { font-size: 0.212rem; color: var(--tv-sub); font-variant-numeric: tabular-nums; }

/* 完播状态胶囊：已完播（绿）/ 未完播（暖橙）/ 播放中（强调色） */
.tv-chip {
  flex-shrink: 0;
  padding: 0.096rem 0.173rem;
  border-radius: 999px;
  font-size: 0.192rem; font-weight: 500;
  background-color: var(--tv-chip-bg); color: var(--tv-chip-fg);
}
/* 讲解全文面板：没有文字稿时压成次要色，别看起来像加载失败 */
.ds-body.is-none { color: var(--c-ink-3); }

/* 点位行的三个动作：播放 / 看文字 / 导航 */
.tv-acts { display: flex; align-items: center; gap: 0.115rem; flex: none; }
.tv-act {
  width: 0.615rem; height: 0.615rem; flex: none;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background-color: var(--tv-card);
  color: var(--tv-sub);
}
.tv-act svg { width: 0.3rem; height: 0.3rem; display: block; }
.tv-act.is-on { background-color: var(--c-primary-soft); color: var(--c-primary); }
.tv-act:active { transform: scale(.92); }
.tv-chip-live { background-color: var(--c-accent-soft); color: var(--c-accent); }

/* —— 分组（全部记录视图） —— */
.tv-group + .tv-group { margin-top: 0.154rem; }
/* 分组头与记录行左对齐（都从 22px 版面边距起排），只保留上下内边距 */
.tv-group-head { display: flex; align-items: center; justify-content: space-between; padding: 0.231rem 0; }
.tv-group-info { display: flex; flex-direction: column; gap: 0.058rem; min-width: 0; }
.tv-group-date { font-size: 0.269rem; font-weight: 600; color: var(--tv-ink); }
.tv-group-meta { font-size: 0.212rem; color: var(--tv-sub); font-variant-numeric: tabular-nums; }

.tv-note { padding: 0.6rem 0.2rem; text-align: center; font-size: 0.231rem; line-height: 1.6; color: var(--tv-sub); }
.tv-note-in { padding: 0.3rem 0; }
.tv-more { display: flex; align-items: center; justify-content: center; height: 0.9rem; font-size: 0.25rem; color: var(--c-primary); }

/* 统计范围选择（复用全局 modal 外壳） */
.tv-opts { display: flex; flex-direction: column; }
/* 左右不留额外内边距：让选项文字与弹层标题、右侧勾选图标同一条竖线上 */
.tv-opt {
  display: flex; align-items: center; justify-content: space-between;
  padding: 0.32rem 0; font-size: 0.3rem; color: var(--c-ink);
  border-top: 1px solid var(--c-line);
}
.tv-opt:first-child { border-top: none; }
.tv-opt.is-on { color: var(--c-primary); font-weight: 600; }
.tv-opt-check { width: 0.3rem; height: 0.3rem; border-radius: 50%; background-color: var(--c-primary); }

.empty { display: flex; flex-direction: column; align-items: center; padding-top: 1.8rem; }
.empty-ico { width: 1.4rem; height: 1.4rem; border-radius: 50%; background-color: var(--c-surface); border: 2px dashed var(--c-line); margin-bottom: 0.36rem; }
.empty-title { font-size: 0.34rem; font-weight: 600; margin-bottom: 0.14rem; }
.empty-desc { font-size: 0.26rem; color: var(--c-ink-3); line-height: 1.6; text-align: center; padding: 0 0.6rem; margin-bottom: 0.48rem; }
.empty-btn { width: 3.2rem; }

/* ==========================================================================
   个人中心 / 关于
   ========================================================================== */
.profile { min-height: 100vh; padding: 0.28rem 0.28rem 0; background-color: var(--c-bg); }
.user-card { display: flex; align-items: center; background-color: var(--c-surface); border-radius: 0.32rem; padding: 0.36rem 0.32rem; margin-bottom: 0.4rem; }
.avatar { width: 1.08rem; height: 1.08rem; border-radius: 50%; background: linear-gradient(145deg, #0E6B57, #0A4F41); color: #FFFFFF; font-size: 0.4rem; font-weight: 600; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
/* 微信头像：铺满色块圆底。缺图时露出的仍是品牌绿底，不会出现破图白块 */
.avatar-img { width: 100%; height: 100%; border-radius: 50%; object-fit: cover; display: block; }
.user-info { flex: 1; margin: 0 0.24rem; min-width: 0; }
.user-name { display: block; font-size: 0.4rem; font-weight: 700; margin-bottom: 0.1rem; }
.user-sub { display: block; font-size: 0.22rem; color: var(--c-ink-3); line-height: 1.5; }
.login-btn { font-size: 0.26rem; font-weight: 600; color: #FFFFFF; background-color: var(--c-primary); border-radius: 999px; padding: 0.14rem 0.32rem; flex-shrink: 0; }
.group { margin-bottom: 0.36rem; }
.group-title { display: block; font-size: 0.22rem; color: var(--c-ink-3); letter-spacing: 0.01rem; margin: 0 0 0.14rem 0.12rem; }
.pcell { display: flex; align-items: center; background-color: var(--c-surface); border-radius: 0.2rem; padding: 0.3rem 0.28rem; margin-bottom: 0.16rem; }
.pcell-ico { margin-right: 0.22rem; }
.pcell-label { flex: 1; font-size: 0.3rem; font-weight: 500; }
.pcell-value { font-size: 0.22rem; color: var(--c-ink-3); margin-right: 0.12rem; max-width: 3.2rem; }
/* —— 「导航地图 → 地图朝向」分段选择 ——
   两个选项都带一句说明：这不是一个「当前值不明」的开关，而是一次显式选择，
   用户看得到自己在选什么、以及两种模式各自的副作用。 */
.pcell-col { display: block; padding: 0.3rem 0.28rem 0.26rem; }
.pcell-col-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 0.24rem; }
.mm-seg { display: flex; gap: 0.18rem; }
.mm-opt { flex: 1; min-width: 0; padding: 0.24rem 0.24rem 0.22rem; border-radius: 0.24rem;
  background-color: var(--c-surface-2); border: 1px solid transparent; }
.mm-opt-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 0.1rem; }
.mm-opt-label { font-size: 0.28rem; font-weight: 600; color: var(--c-ink); }
.mm-opt-desc { font-size: 0.2rem; line-height: 1.5; color: var(--c-ink-3); }
.mm-radio { width: 0.32rem; height: 0.32rem; border-radius: 50%; flex: none;
  border: 1px solid var(--c-line); background-color: var(--c-surface); }
.mm-on { background-color: var(--c-primary-soft); border-color: var(--c-primary); }
.mm-on .mm-opt-label { color: var(--c-primary); }
.mm-on .mm-radio { border-color: var(--c-primary); background-color: var(--c-primary);
  box-shadow: inset 0 0 0 0.07rem var(--c-surface); }

.about { min-height: 100vh; padding: 0.9rem 0.4rem 0; background-color: var(--c-bg); display: flex; flex-direction: column; align-items: center; }
.brand-name { font-size: 0.4rem; font-weight: 700; letter-spacing: 0.02rem; }
.brand-version { margin-top: 0.1rem; font-size: 0.22rem; color: var(--c-ink-3); }
.brand-slogan { margin-top: 0.26rem; font-size: 0.26rem; color: var(--c-ink-2); letter-spacing: 0.04rem; margin-bottom: 0.7rem; }
.about .group { width: 100%; background-color: var(--c-surface); border-radius: 0.2rem; padding: 0 0.28rem; margin-bottom: 0; }
.acell { display: flex; align-items: center; justify-content: space-between; height: 1.08rem; border-bottom: 1px solid var(--c-line); }
.acell:last-child { border-bottom: none; }
.acell-label { font-size: 0.3rem; }
.copyright { margin-top: auto; padding: 0.6rem 0 0.4rem; font-size: 0.22rem; color: var(--c-ink-3); text-align: center; }

/* 诊断浮层（临时） */
.diag { position: fixed; left: 0.16rem; right: 0.16rem; bottom: 0.6rem; background: rgba(13,20,17,.94); border: 1px solid rgba(126,226,195,.35); border-radius: 0.14rem; padding: 0.18rem 0.22rem; z-index: 4000; font-size: 0.2rem; color: #eef7f2; line-height: 1.55; word-break: break-all; }
.diag-title { color: #7ee2c3; font-weight: 600; margin-bottom: 0.08rem; }

/* ================= 机头朝向标记（核心导航页） ================= */
/* 位置固定在地图中心：跟随模式下用户永远居中（TMap setCenter / 静态图以人为中心取图）。
   pointer-events 必须为 none —— 否则这块会挡住中心区域的拖动与双指缩放（老坑重灾区）。 */
/* ---- 用户位置标记（高德样式：圆形头像 + 顶部小三角朝向） ----
   容器 = 头像圆（0.8rem），圆心对准定位点；小三角装在 .mh-rotor 里，
   由 rAF 绕头像圆心旋转表达机头朝向（transform-origin: 圆心）。 */
.map-heading {
  position: absolute;
  left: 0; top: 0;
  width: 0.8rem; height: 0.8rem;
  z-index: 3;
  pointer-events: none;
}
/* 白描边 + 投影的头像圆 */
.mh-avatar {
  position: absolute; inset: 0; border-radius: 50%; overflow: hidden;
  border: 0.045rem solid #FFFFFF; background-color: var(--c-primary);
  box-shadow: 0 0.06rem 0.22rem rgba(10, 30, 26, .30);
  display: flex; align-items: center; justify-content: center;
  font-size: 0.3rem; font-weight: 700; color: #FFFFFF;
  animation: mhIn .38s cubic-bezier(.22, .9, .26, 1.18);
}
.mh-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.mh-initial { letter-spacing: 0; }
/* 头像底下的一圈呼吸光环（高级感：缓慢往复，不抢注意力） */
.mh-halo {
  position: absolute; inset: -0.12rem; border-radius: 50%;
  border: 0.025rem solid rgba(14, 107, 87, .45);
  animation: mhHalo 2.6s ease-in-out infinite;
  pointer-events: none;
}
/* 朝向小三角：随 rotor 绕头像圆心旋转（机头朝上时恒指屏幕上方） */
.mh-rotor {
  position: absolute; inset: 0; z-index: 1;
  transform-origin: 50% 50%;
  will-change: transform;
  pointer-events: none;
}
.mh-tri {
  position: absolute; top: -0.17rem; left: 50%; margin-left: -0.1rem;
  width: 0; height: 0;
  border-left: 0.1rem solid transparent; border-right: 0.1rem solid transparent;
  border-bottom: 0.17rem solid #14A05F;
  filter: drop-shadow(0 0.02rem 0.08rem rgba(10, 30, 26, .3));
}
@keyframes mhIn {
  from { transform: scale(.4); opacity: 0; }
  to   { transform: scale(1); opacity: 1; }
}
@keyframes mhHalo {
  0%   { transform: scale(.92); opacity: .85; }
  70%  { transform: scale(1.22); opacity: 0; }
  100% { transform: scale(1.22); opacity: 0; }
}

/* ---- 正在讲解的点位标注（气泡 + 引线 + 落点） ----
   讲解期间贴在该点位的地理坐标上，位置由 JS 逐帧换算写入 left/top：
   外层只负责「整体锚点」——translate(-50%, -100%) 让最下方的落点正好压住坐标，
   内层负责上下翻转、气泡负责弹出动画，三者互不干扰（都写在同一个 transform 上会打架）。
   ⚠️ 必须与 .map-heading 同列在 pointer-events:none 名单里，否则地图中心拖不动。 */
.map-poi {
  position: absolute;
  left: 0; top: 0;
  z-index: 3;
  pointer-events: none;
  transform: translate(-50%, -100%);
  will-change: transform;
}
.map-poi-inner { display: flex; flex-direction: column; align-items: center; }
.map-poi-bubble {
  display: block;
  max-width: 3.6rem; min-width: 2.9rem;
  padding: 0.2rem 0.24rem 0.24rem; border-radius: 0.26rem;
  background-color: rgba(255, 255, 255, .97);
  box-shadow: 0 0.06rem 0.3rem rgba(10, 30, 26, .24);
  font-size: 0.24rem; line-height: 1.32; color: #17211E;
}
/* 设计稿气泡恒为白卡：夜间主题不再改黑（文字用固定深色） */
.map-poi-stem { width: 0.02rem; height: 0.14rem; background-color: rgba(14, 107, 87, .38); }
.map-poi-dot {
  width: 0.16rem; height: 0.16rem; border-radius: 50%;
  /* 落点用强调橙，与矢量图上的沿途点位图钉（POI_PIN_STYLE）同色：
     蓝点=你在哪，橙点=正在讲哪，两个语义一眼分得开 */
  background-color: #E08A2E; border: 0.03rem solid #FFFFFF;
  /* 负底距把落点圆心顶到锚点上（半个直径），否则标注整体会偏高一个点 */
  margin-bottom: -0.08rem;
}
/* 点位贴近屏幕顶部时把气泡翻到落点下方，免得被状态栏/导航条压住 */
.map-poi.is-flip { transform: translate(-50%, 0); }
.map-poi.is-flip .map-poi-inner { flex-direction: column-reverse; }
.map-poi.is-flip .map-poi-dot { margin-bottom: 0; margin-top: -0.08rem; }
@keyframes poiPop {
  from { opacity: 0; transform: translateY(0.14rem) scale(.88); }
  to { opacity: 1; transform: none; }
}
.map-poi.is-pop .map-poi-bubble { animation: poiPop 0.26s cubic-bezier(.2, .9, .3, 1.2); }

/* ---- 当天讲解过的点位（常驻标注：分类色点 + 点位名称） ----
   与「正在讲解」的落点标注是两件事：那个只活一次讲解，这个是全天累积的足迹。
   用 DOM 覆盖层而不是地图要素：矢量图（MultiMarker）与静态图两条底图路径都能共用
   同一套定位（_poiScreen），不必为两种底图各写一遍标注代码。
   容器 pointer-events:none（不挡地图拖动），只有标签本体 auto（可点击弹卡片）。 */
.map-played { position: absolute; inset: 0; z-index: 3; pointer-events: none; overflow: hidden; }
.mp-item {
  position: absolute; left: 0; top: 0;
  display: flex; align-items: center; gap: 0.08rem;
  max-width: 2.9rem; padding: 0.07rem 0.18rem 0.07rem 0.12rem;
  border-radius: 999px;
  background-color: rgba(255, 255, 255, .94);
  box-shadow: 0 0.04rem 0.18rem rgba(10, 30, 26, .20);
  font-size: 0.22rem; line-height: 1.3; color: var(--c-ink);
  pointer-events: auto;
  /* 标签中心压在坐标上：位置由逐帧写 left/top，缩放/旋转交给这里的 transform */
  transform: translate(-50%, -50%);
  will-change: transform;
}
.theme-night .mp-item { background-color: rgba(23, 32, 29, .94); }
.mp-dot { width: 0.13rem; height: 0.13rem; border-radius: 50%; flex: none;
  border: 0.02rem solid rgba(255, 255, 255, .9); }
.mp-name { min-width: 0; max-width: 2.5rem; }
/* 正在播的那条：同色描边 + 轻微放大，一眼看出「讲到这儿了」 */
.mp-item.mp-on { box-shadow: 0 0 0 0.03rem var(--c-primary), 0 0.06rem 0.24rem rgba(10, 30, 26, .26); font-weight: 600; }

/* ============ 全局底部导航（导览 / 足迹 / 我的）—— V2.1 已移除「收藏」 ============ */

/* —— 保活页（V2.1）——
   讲解跑着的时候去逛别的页面，导览页不能被销毁，否则回来要重开一遍。
   这里用「盖住 + 不可见 + 不吃事件」把它留在文档里：
     · 留在文档里 → 地图 SDK、布局测量、#app 内的事件委托全部照常可用；
     · visibility:hidden 而不是 display:none → 布局尺寸不塌，
       回前台时地图不会因为量到 0 宽而错位。 */
.app-parked {
  position: fixed;
  left: 0; top: 0;
  width: 100%; height: 100%;
  visibility: hidden;
  pointer-events: none;
  z-index: -1;
}
/* 悬浮药丸：与屏幕左右、底部都留出间距（不再贴死在最底边），圆角胶囊风格。 */
.global-tabbar {
  position: fixed;
  left: 50%;
  transform: translateX(-50%);
  width: calc(100% - 0.48rem);
  max-width: 560px;
  bottom: calc(var(--tabbar-gap) + env(safe-area-inset-bottom));
  z-index: 50;
  display: flex; align-items: center;
  padding: 0.1rem 0.12rem;
  background-color: rgba(255,255,255,.96);
  border-radius: 999px;
  box-shadow: 0 0.1rem 0.4rem rgba(10,30,26,.16);
}
/* 设计稿底栏恒为白卡：夜间主题也不改黑；文字/图标用固定色（夜间变量是浅色） */
.global-tabbar .tab-item { flex: 1; display: flex; flex-direction: column; align-items: center; padding: 0.1rem 0 0.08rem; border-radius: 999px; font-size: 0.2rem; color: #9AA6A0; }
.global-tabbar .tab-item .ico { width: 0.42rem; height: 0.42rem; margin-bottom: 0.05rem; }
/* 选中态 = 浅绿胶囊 + 绿字 + 绿图标（设计稿样式） */
.global-tabbar .tab-active { background-color: rgba(14, 107, 87, .12); color: var(--c-primary); font-weight: 600; }
.global-tabbar .tab-active .ico { filter: invert(30%) sepia(62%) saturate(1195%) hue-rotate(126deg) brightness(93%) contrast(92%); }

/* 主页面底部给全局导航留出空间，避免内容被悬浮底栏遮住 */
.trips, .profile { padding-bottom: calc(var(--tabbar-gap) + var(--tabbar-h) + env(safe-area-inset-bottom) + 0.3rem); }

/* 导览页底部播报卡片上移，让出悬浮底栏并留出间隙。
   ⚠️ 必须同时计入三项，少任何一项卡片都会被底栏压住：
     ① 底栏自身的底距 var(--tabbar-gap) —— .global-tabbar 的 bottom 就是 calc(--tabbar-gap + 安全区)，
        卡片定位若不加这一项，底边会沉到比底栏顶边还低；
     ② 底栏高度 var(--tabbar-h)（app.js 启动时按实测值写成 px）；
     ③ 安全区 env(safe-area-inset-bottom)。
   末尾再留 0.24rem 视觉间隙（与卡片左右边距 0.24rem 同一档，观感统一）。
   实测：旧写法漏了 ① 且无间隙，卡片底边比底栏顶边低 0.254rem —— 底栏正好压住卡片下缘。 */
.guide .bottom {
  bottom: calc(var(--tabbar-gap) + var(--tabbar-h) + env(safe-area-inset-bottom) + 0.24rem);
}

/* 用动态视口单位规避移动端地址栏 / 全面屏造成的 100vh 偏差 */
.guide, .map, .page-root, .trips, .profile, .about, .launch, .login, .pref { min-height: 100vh; min-height: 100dvh; }
.map { height: 100vh; height: 100dvh; }


/* ==================================================================
   V2.1 · Screen 03 / 03c / 04 改版
   ------------------------------------------------------------------
   03  顶部「讲解中」胶囊 = 播报控制唯一入口（底部 Now Playing Card 已移除）
   03c 导航应用选择（底部弹层）
   04  讲解详情 / 正在播报（足迹页点点位弹出的底部大面板）
   ================================================================== */

/* ---------- 顶部「讲解中」胶囊（设计稿：深绿按钮 + 白喇叭 + 白字） ---------- */
.livepill {
  display: flex; align-items: center; gap: 0.1rem; flex: none; margin-left: auto;
  height: 0.58rem; padding: 0 0.22rem; border-radius: 999px;
  background-color: #EEF3F0; color: #5C6B66;
  font-size: 0.24rem; font-weight: 600; cursor: pointer; user-select: none;
}
.livepill.is-live {
  background-color: var(--c-primary); color: #FFFFFF;
  box-shadow: 0 0.06rem 0.2rem rgba(14, 107, 87, .32);
}
/* 喇叭图标：待命=灰绿，讲解中=白。替换原先的「呼吸点」（设计稿无此元素） */
.livepill-speaker {
  width: 0.3rem; height: 0.3rem; flex: none;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235C6B66' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4.8 9.2h3.4L13 5.6v12.8l-4.8-3.6H4.8z'/%3E%3Cpath d='M16.4 9.4a3.6 3.6 0 0 1 0 5.2'/%3E%3C/svg%3E") center/contain no-repeat;
}
.livepill.is-live .livepill-speaker {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23FFFFFF' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4.8 9.2h3.4L13 5.6v12.8l-4.8-3.6H4.8z'/%3E%3Cpath d='M16.4 9.4a3.6 3.6 0 0 1 0 5.2'/%3E%3C/svg%3E");
}

/* ---------- 播报控制面板（点胶囊展开；点面板外收起） ---------- */
.lp-scrim { position: fixed; inset: 0; z-index: 1150; }
.livepanel {
  position: fixed; right: 0.24rem; top: calc(1.12rem + env(safe-area-inset-top));
  z-index: 1200; width: 5rem; max-width: calc(100% - 0.48rem);
  padding: 0.26rem; border-radius: 0.28rem;
  background-color: rgba(255, 255, 255, .98);
  box-shadow: 0 0.16rem 0.5rem rgba(10, 30, 26, .26);
}
.theme-night .livepanel { background-color: rgba(23, 32, 29, .98); box-shadow: 0 0.16rem 0.5rem rgba(0, 0, 0, .5); }

.lp-row { display: flex; align-items: center; gap: 0.18rem; }
.lp-btn {
  width: 0.84rem; height: 0.84rem; border-radius: 50%; flex: none;
  display: flex; align-items: center; justify-content: center;
  background-color: var(--c-primary); box-shadow: 0 0.06rem 0.18rem rgba(14, 107, 87, .28);
}
.lp-btn:active { transform: scale(.94); }
.lp-stop { background-color: var(--c-surface-2); color: var(--c-ink-2); box-shadow: none; }
.lp-mid { flex: 1; min-width: 0; }
.lp-t { font-size: 0.26rem; font-weight: 600; color: var(--c-ink); }
.lp-time { margin-top: 0.04rem; font-size: 0.22rem; color: var(--c-ink-3); font-variant-numeric: tabular-nums; }

.lp-vol { margin-top: 0.22rem; display: flex; align-items: center; gap: 0.14rem; }
.lp-vol-ico { width: 0.3rem; height: 0.3rem; flex: none; }
.lp-range {
  flex: 1; -webkit-appearance: none; appearance: none; outline: none;
  height: 0.08rem; border-radius: 0.04rem; background-color: var(--c-line);
}
.lp-range::-webkit-slider-thumb {
  -webkit-appearance: none; width: 0.3rem; height: 0.3rem; border-radius: 50%;
  background-color: var(--c-primary); box-shadow: 0 0.04rem 0.12rem rgba(10, 30, 26, .2);
}
.lp-volnum { width: 0.72rem; text-align: right; flex: none; font-size: 0.22rem; color: var(--c-ink-2); font-variant-numeric: tabular-nums; }

.lp-foot {
  margin-top: 0.18rem; padding-top: 0.14rem; border-top: 1px solid var(--c-line);
  display: flex; align-items: center; justify-content: space-between;
}
.lp-link { font-size: 0.22rem; color: var(--c-ink-3); }
.lp-link-go { color: var(--c-primary); font-weight: 600; }

/* ---------- 地图上的「正在讲解」气泡（设计稿：白卡 + 红点状态 + 大标题 + 通栏绿钮） ---------- */
.map-poi-bubble {
  display: block; max-width: 3.6rem; min-width: 2.9rem;
  padding: 0.2rem 0.24rem 0.24rem; border-radius: 0.26rem;
}
.map-poi-live {
  display: flex; align-items: center; gap: 0.09rem;
  font-size: 0.2rem; font-weight: 500; color: #8A968F; letter-spacing: .01rem;
}
.map-poi-live i {
  width: 0.12rem; height: 0.12rem; border-radius: 50%; flex: none;
  background-color: #E5483F; animation: prep-pulse 1.4s ease-in-out infinite;
}
.map-poi-title {
  margin-top: 0.08rem; font-size: 0.3rem; font-weight: 700;
  color: #17211E; max-width: 3.1rem; min-width: 0;
}
/* ⚠️ 只给 CTA 开 pointer-events：气泡整体跟着点位在地图上飘，
   如果整块吃点击，手指在这块区域就拖不动地图了。 */
.map-poi-cta {
  pointer-events: auto; margin-top: 0.18rem; height: 0.68rem; border-radius: 0.18rem;
  display: flex; align-items: center; justify-content: center; gap: 0.1rem;
  font-size: 0.26rem; font-weight: 600; color: #FFFFFF; background-color: var(--c-primary);
}
.map-poi-cta:active { background-color: var(--c-primary-deep); }
.map-poi-cta-ico {
  width: 0.26rem; height: 0.26rem; flex: none;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23FFFFFF'%3E%3Cpath d='M21 3.6L3.8 10.4c-.9.35-.84 1.63.09 1.9l6.1 1.8 1.8 6.1c.27.93 1.55 1 1.9.09L20.4 3a.75.75 0 0 0-.96-.96z'/%3E%3C/svg%3E") center/contain no-repeat;
}
/* 「已讲解」查看气泡（#g-playedtag）：绿点绿字，与「正在讲解」的红点区分 */
.map-poi-live.is-done { color: #5C6B66; }
.map-poi-live.is-done i { background-color: #14A05F; animation: none; }
.map-poi-dot-done { background-color: #14A05F; }
.map-poi-dot-done i { border-color: rgba(20, 160, 95, .9); }
.map-poi-dot { position: relative; }
.map-poi-dot i {
  position: absolute; inset: 0; border-radius: 50%;
  border: 0.02rem solid rgba(224, 138, 46, .9);
  animation: poiRing 2s cubic-bezier(.2, .7, .3, 1) infinite;
}
.map-poi-dot i:nth-child(2) { animation-delay: .7s; }
.map-poi-dot i:nth-child(3) { animation-delay: 1.4s; }
@keyframes poiRing {
  0%   { transform: scale(1); opacity: .7; }
  100% { transform: scale(3.2); opacity: 0; }
}

/* ---------- 03c · 导航应用选择（底部弹层） ---------- */
.navsheet, .detsheet { padding: 0.28rem 0.32rem calc(0.32rem + env(safe-area-inset-bottom)); position: relative; }
.ns-grip, .ds-grip {
  width: 0.72rem; height: 0.08rem; border-radius: 0.04rem;
  background-color: var(--c-line); margin: 0 auto 0.24rem;
}
.ns-head { margin-bottom: 0.16rem; }
.ns-t { font-size: 0.3rem; font-weight: 700; color: var(--c-ink); }
.ns-s { font-size: 0.24rem; color: var(--c-ink-3); margin-top: 0.06rem; }
.nrow { display: flex; align-items: center; gap: 0.2rem; padding: 0.2rem 0; border-bottom: 1px solid var(--c-line); }
.nrow:active { opacity: .7; }
.nico { width: 0.56rem; height: 0.56rem; border-radius: 0.16rem; flex: none; }
.nbody { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.nname { font-size: 0.27rem; font-weight: 600; color: var(--c-ink); }
.ndesc { font-size: 0.21rem; color: var(--c-ink-3); margin-top: 0.03rem; }
.nrow-arrow { width: 0.26rem; height: 0.26rem; flex: none; }
.ns-cancel {
  margin-top: 0.26rem; height: 0.84rem; border-radius: 0.22rem;
  display: flex; align-items: center; justify-content: center;
  font-size: 0.27rem; color: var(--c-ink-2); background-color: var(--c-surface-2);
}

/* ---------- 04 · 讲解详情 / 正在播报 ---------- */
.ds-head { display: flex; gap: 0.24rem; align-items: flex-start; }
.ds-thumb {
  width: 0.96rem; height: 0.96rem; border-radius: 0.24rem; flex: none;
  /* 点位类型图标（2026-10-13 用户要求「左边正方形框改成点位类型图标」）。
     ⚠️ 必须 flex 居中：图标是内联 SVG，不居中就顶在方块左上角。 */
  display: flex; align-items: center; justify-content: center;
}
/* 方块里的白图标。0.5rem 是在 0.96rem 方块里「看得出形状、又不顶边」的尺寸 */
.ds-pico { width: 0.5rem; height: 0.5rem; display: block; }
.ds-hinfo { flex: 1; min-width: 0; }
.ds-badges { display: flex; flex-wrap: wrap; gap: 0.1rem; }
.ds-chip {
  font-size: 0.2rem; font-weight: 600; color: var(--c-accent);
  background-color: var(--c-accent-soft); padding: 0.06rem 0.16rem; border-radius: 999px;
}
/* 点位类型（「教堂」「博物馆」）。
   ⚠️ 刻意**不跟「优质点位」同色**：那颗橙的是**档位**（优质），这颗绿的是**类型** ——
   同色会让人以为「教堂」也是一种「优质」。绿色＝品牌色，与主按钮同一套语言。 */
.ds-chip-type { color: var(--c-primary); background-color: var(--c-primary-soft); }
.ds-chip-none { color: var(--c-ink-3); background-color: var(--c-surface-2); }
.ds-name { margin-top: 0.12rem; font-size: 0.4rem; font-weight: 700; color: var(--c-ink); line-height: 1.26; }
.ds-meta { margin-top: 0.06rem; font-size: 0.22rem; color: var(--c-ink-3); }
/* 地址（腾讯 POI 的完整串，如「广东省珠海市香洲区梅华街道」）：
   **最多两行**再截断 —— 只给一行会把「XX路XX号」这个最有用的部分切掉。 */
.ds-addr {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  overflow: hidden; line-height: 1.45;
}
.ds-player { display: flex; align-items: center; gap: 0.2rem; margin-top: 0.26rem; }
.ds-btn {
  width: 0.92rem; height: 0.92rem; border-radius: 50%; flex: none;
  display: flex; align-items: center; justify-content: center; background-color: var(--c-primary);
}
.ds-btn:active { transform: scale(.94); }
.ds-pgroup { flex: 1; min-width: 0; }
.ds-wave { display: flex; align-items: flex-end; gap: 0.04rem; height: 0.5rem; }
.ds-wave i { flex: 1; min-height: 0.06rem; background-color: var(--c-line); border-radius: 0.03rem; }
.ds-ptime { display: flex; justify-content: space-between; margin-top: 0.06rem; font-size: 0.21rem; color: var(--c-ink-3); }
.ds-body {
  margin-top: 0.24rem; max-height: 32vh; overflow-y: auto;
  font-size: 0.26rem; line-height: 1.85; color: var(--c-ink-2);
}
.ds-acts { display: flex; gap: 0.14rem; margin-top: 0.28rem; }
.ds-btn2 {
  height: 0.84rem; border-radius: 0.22rem;
  /* ⚠️ `flex: 1 1 auto`（基础宽度＝**内容宽度**）而不是 `flex: 1`（按键数平分）：
     平分时「看卫星图」「到此点位去」这种四五个字的按钮会被挤爆 ——
     原来写的是「看照片」（三个字），改名后多了一个字的宽度，375px 屏上就放不下了。
     按内容定基础宽度、再用 flex-grow 微调，宽度自然跟着字数走。 */
  flex: 1 1 auto;
  display: flex; align-items: center; justify-content: center;
  font-size: 0.24rem; font-weight: 600; white-space: nowrap;
}
.ds-photo { flex-grow: 1.15; }
.ds-go { flex-grow: 1.35; color: #FFFFFF; background-color: var(--c-primary); }
/* 窄屏（320~350px CSS）兜底：按钮的「内容宽度」加起来刚好会顶破卡片 */
@media (max-width: 350px) {
  .ds-acts { gap: 0.1rem; }
  .ds-btn2 { font-size: 0.22rem; }
}

/* ---------- 04b · 点位详情卡片：固定在页面底部、高约 1/3 屏 ---------- */
/*
 * 2026-10-13 用户口径（附图）：「就按照这个截图来设置，固定在页面底部，
 * 高度占手机屏幕的三分之一，页面左边显示卫星图」。
 *
 * 位置其实**本来就是底部**（`.mask` 是 `align-items: flex-end` + `.modal` 顶部圆角），
 * 这里补的是**固定高度**：原来高度由内容撑，点位名一长、地址一多，
 * 卡片就会自己长高，把地图压得只剩一条缝。
 *
 * ⚠️ 高度写 `vh` 不写 `rem`：用户口径是「占**手机屏幕**的三分之一」，
 *    是屏占比、不是某个固定尺寸 —— 小屏手机上也该是三分之一。
 * ⚠️ 布局改成纵向 flex：上半截是「左图 + 右文」，按钮行 `margin-top: auto` 贴底。
 *    这样地址再长也只会挤中间那栏，不会把按钮顶出屏幕外。
 */
.vpd-sheet {
  height: 33.33vh;
  min-height: 4.6rem;
  display: flex; flex-direction: column;
  overflow: hidden;
}
/* 关闭：右上角一颗圆钮（用户要求第 5 条「用一个图标表示关闭窗口」）。
   原来是一颗占 1/3 宽的「关闭」文字按钮 —— 底部面板的通用语言是右上角 ×。 */
.ds-x {
  position: absolute; top: 0.22rem; right: 0.26rem; z-index: 2;
  width: 0.62rem; height: 0.62rem; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  color: var(--c-ink-3); background-color: var(--c-surface-2);
}
.ds-x:active { transform: scale(.92); }
.ds-x svg { width: 0.3rem; height: 0.3rem; display: block; }
/* 右上角有 × ⇒ 标题区留出它的宽度，免得长点位名顶到图标底下 */
.detsheet .ds-hinfo { padding-right: 0.72rem; }

/* 左方块：**卫星图当底、类型图标叠在上面**。
   ⚠️ 比原来（0.96rem）放大到 1.6rem：卫星图缩到指甲盖大小就看不出是哪儿了，
      而它存在的意义正是「一眼看出这个点位长什么样」。 */
.vpd-sheet .ds-thumb {
  width: 1.6rem; height: 1.6rem; border-radius: 0.26rem;
  background-size: cover; background-position: center;
  position: relative; overflow: hidden;
}
/* 卫星影像是照片，白图标直接压上去会糊在亮处 —— 铺一层暗罩把对比度压出来。
   ⚠️ 只在**真有图**时铺：没图时方块是纯主色底，再压暗就成了「脏绿色」。 */
.vpd-sheet .ds-thumb.has-img::after {
  content: ''; position: absolute; inset: 0;
  background: rgba(6, 18, 15, .34);
}
.ds-thumb-ico { position: relative; z-index: 1; display: flex; }
/* 图标在 1.6rem 方块里放到 0.62rem：比原来（0.5rem）大一圈，压在图上也认得出 */
.vpd-sheet .ds-thumb-ico svg { width: 0.62rem; height: 0.62rem; }
/* 按钮行贴底 */
.vpd-sheet .ds-acts { margin-top: auto; padding-top: 0.2rem; }
.vpd-sheet .ds-acts .ds-btn2 { flex: 1 1 0; }
/* 高度是**固定的 1/3 屏**，而内容（一行标签 + 名称 + 两行地址）撑不满 ——
   若不处理，空白会全堆在地址下面，按钮孤零零贴着底边，看着像「内容没加载完」。
   让头部在「把手」与「按钮行」之间平分剩余空间即可：留白摊到上下两侧，
   视觉上变成刻意的留白。⚠️ 必须配合 `.ds-acts { margin-top: auto }` ——
   两者都是「吃掉剩余空间」，flex 会平分，正好是我们要的效果。 */
.vpd-sheet .ds-head { margin: auto 0; }

/* ---------- 03b · 导览启动（圆形倒计时 + 无文字圆钮） ---------- */
.boot { position: fixed; inset: 0; z-index: 1400; display: flex; flex-direction: column;
  align-items: center; justify-content: center; }
.boot-mask { position: absolute; inset: 0; background-color: rgba(10, 20, 18, .52); }
.boot-core { position: relative; z-index: 1; margin-top: auto; }
.boot-ring { position: relative; width: 3.2rem; height: 3.2rem; }
.boot-ring svg { width: 100%; height: 100%; transform: rotate(-90deg); }
.boot-ring-bg { fill: none; stroke: rgba(255, 255, 255, .28); stroke-width: 8; }
.boot-ring-fg {
  fill: none; stroke: #FFFFFF; stroke-width: 8; stroke-linecap: round;
  transition: stroke-dashoffset .95s linear;
}
.boot-ring-in {
  position: absolute; inset: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center; color: #FFFFFF;
}
.boot-num { font-size: 1.1rem; font-weight: 700; line-height: 1; font-variant-numeric: tabular-nums; }
.boot-cap { margin-top: 0.1rem; font-size: 0.24rem; opacity: .88; }

.boot-acts { position: relative; z-index: 1; display: flex; gap: 0.4rem; margin-top: 0.6rem; margin-bottom: auto; }
.boot-rbtn {
  width: 1.1rem; height: 1.1rem; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background-color: rgba(255, 255, 255, .2); color: #FFFFFF;
}
.boot-rbtn:active { transform: scale(.94); }
.boot-go { background-color: var(--c-primary); box-shadow: 0 0.1rem 0.3rem rgba(14, 107, 87, .4); }
.boot-sub { margin-top: 0.06rem; font-size: 0.2rem; color: rgba(255, 255, 255, .52); }

/* ==========================================================================
   行程轨迹回看页（足迹 → 某次行程 → 「轨迹」）
   ========================================================================== */
/* 全屏地图 + 底部信息卡。
   ⚠️ 地图必须拿到确定高度（flex:1 配 min-height:0）：矢量地图是量容器高度来建
   canvas 的，容器高 0 时它安静地渲染出一片空白，没有任何报错 —— 这是 GL 地图最经典的坑。 */
.page-root.track { display: flex; flex-direction: column; height: 100vh; overflow: hidden; }
.tk-wrap { flex: 1; display: flex; flex-direction: column; min-height: 0; }
.tk-map { flex: 1; position: relative; overflow: hidden; background-color: var(--c-surface-2); }
.tk-mask {
  position: absolute; left: 0; right: 0; top: 0; bottom: 0; z-index: 2;
  display: flex; align-items: center; justify-content: center;
  font-size: 0.26rem; color: var(--c-ink-3); background-color: var(--c-bg);
}
.tk-card {
  flex: none;
  padding: 0.32rem 0.32rem calc(0.36rem + env(safe-area-inset-bottom));
  background-color: var(--c-surface);
  border-top: 0.014rem solid var(--c-line);
}
.tk-stats { display: flex; }
.tk-stat { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 0.077rem; }
.tk-v {
  font-size: 0.42rem; font-weight: 700; line-height: 1; color: var(--c-ink);
  font-variant-numeric: tabular-nums;
}
.tk-u { font-size: 0.212rem; color: var(--c-ink-3); }
.tk-when { margin-top: 0.231rem; text-align: center; font-size: 0.231rem; color: var(--c-ink-3); }

/* —— 足迹页：行程组头里的「轨迹」入口 —— */
.tv-group-act { display: flex; align-items: center; gap: 0.192rem; flex: none; }
.tv-track {
  display: inline-flex; align-items: center; height: 0.5rem; padding: 0 0.231rem;
  border-radius: 999px; font-size: 0.212rem; font-weight: 500;
  background-color: var(--c-primary-soft); color: var(--c-primary);
}

/* ==========================================================================
   V2.3 · 手动开始 / 长按 3 秒结束 / 点位照片
   ========================================================================== */

/* —— 播报面板：结束按钮改成「长按 3 秒」——
   结束是不可逆的（这一段行程就此封口），点一下太容易被误触，
   所以按钮里嵌一圈进度环，按住才走，松手归零。 */
.lp-btn.lp-stop { position: relative; }
.lp-stop-ico { position: relative; z-index: 1; display: flex; align-items: center; justify-content: center; }
/* SVG 36×36、r=15.5 → 周长 2π·15.5 ≈ 97.4；dasharray/dashoffset 由 _paintHold 每帧写死，
   这里只给初值与配色（别加 transition：逐帧改的属性和过渡叠加会打架）。 */
.lp-ring { position: absolute; inset: 0; width: 100%; height: 100%; transform: rotate(-90deg); pointer-events: none; }
.lp-ring-bg { fill: none; stroke: var(--c-line); stroke-width: 2.6; }
.lp-ring-fg {
  fill: none; stroke: var(--c-accent); stroke-width: 2.6; stroke-linecap: round;
  stroke-dasharray: 97.4; stroke-dashoffset: 97.4;
  opacity: 0; transition: opacity .12s ease;
}
.lp-stop.is-holding .lp-ring-fg { opacity: 1; }
.lp-stop.is-holding { background-color: var(--c-accent-soft); transform: scale(.96); }
.lp-hint { margin-top: 0.16rem; font-size: 0.2rem; line-height: 1.5; color: var(--c-ink-3); }

/* —— 全屏长按反馈层（#g-boot 复用为 hold 层）——
   结束按钮只有 0.4rem 宽，手指按住时完全看不到进度，
   这层给一个大圆环告诉用户「还要按多久 / 松手会不会白按」。 */
.boot-hold .boot-core { margin-top: 0; }          /* 基础 .boot-core 是给底部按钮组留位的，这层要正居中 */
.boot-hold .boot-ring-fg { transition: none; }    /* 进度逐帧驱动，不能有 .95s 过渡 */
@media (prefers-reduced-motion: reduce) {
  .lp-stop.is-holding { transform: none; }
}

/* —— 气泡里的「看卫星图」入口 ——
   ⚠️ 必须单独开 pointer-events：气泡整体跟着点位在地图上飘，
   整块吃点击手指就拖不动地图了（与 .map-poi-cta 同一条铁律）。 */
.map-poi-row { margin-top: 0.18rem; display: flex; align-items: center; gap: 0.12rem; }
.map-poi-row .map-poi-cta { margin-top: 0; flex: 1; }
.map-poi-photo {
  pointer-events: auto; flex: none;
  height: 0.68rem; padding: 0 0.22rem; border-radius: 0.18rem;
  display: flex; align-items: center; gap: 0.08rem;
  font-size: 0.24rem; font-weight: 600;
  color: var(--c-primary); background-color: var(--c-primary-soft);
}
.map-poi-photo:active { opacity: .68; }
.mpp-ico {
  width: 0.26rem; height: 0.26rem; flex: none;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%230E6B57' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z'/%3E%3Ccircle cx='12' cy='13' r='4'/%3E%3C/svg%3E") center/contain no-repeat;
}
/* 详情面板里的第三颗按钮（看卫星图）：次级样式，不与「到此点位去」抢视觉 */
.ds-photo { color: var(--c-primary); background-color: var(--c-primary-soft); }

/* —— 足迹页：缩略图兼作「看卫星图」入口 ——
   缩略图本来就是设计稿里的照片位，服务端补上真实照片后回车位即可。 */
.tv-thumb-tap { position: relative; }
.tv-thumb-tap:active { transform: scale(.94); }
.tv-thumb-cam {
  position: absolute; right: -0.06rem; bottom: -0.06rem;
  width: 0.38rem; height: 0.38rem; border-radius: 50%;
  border: 0.024rem solid var(--c-surface);
  background-color: var(--c-primary);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23FFFFFF' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z'/%3E%3Ccircle cx='12' cy='13' r='4'/%3E%3C/svg%3E");
  background-size: 0.22rem 0.22rem; background-position: center; background-repeat: no-repeat;
}

/* —— 全屏照片查看层 ——
   刻意「点开才看」：开车盯屏幕不安全（字幕当初也是这个理由砍的），
   照片只在用户主动要求时出现，默认不占任何版面。
   深底色是为了让照片里的浅色天空不出戏，也顺便把「这是看图模式」说清楚。 */
.photosheet {
  padding: 0; overflow: hidden; background-color: #0C1513;
  border-radius: 0.32rem 0.32rem 0 0;
}
.ph-stage {
  position: relative; width: 100%; aspect-ratio: 4 / 3; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  background-color: #0C1513;
}
.ph-img { display: block; width: 100%; height: 100%; object-fit: cover; opacity: 0; transition: opacity .3s ease; }
.ph-img.on { opacity: 1; }
.ph-wait {
  position: absolute; inset: 0; padding: 0.4rem;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 0.18rem;
  font-size: 0.24rem; line-height: 1.6; color: rgba(255, 255, 255, .66); text-align: center;
}
.ph-spin {
  width: 0.52rem; height: 0.52rem; border-radius: 50%;
  border: 0.05rem solid rgba(255, 255, 255, .16); border-top-color: var(--c-primary);
  animation: phSpin .9s linear infinite;
}
@keyframes phSpin { to { transform: rotate(360deg); } }
.ph-err { font-size: 0.26rem; color: rgba(255, 255, 255, .72); }
.ph-retry {
  display: inline-flex; align-items: center; height: 0.68rem; padding: 0 0.5rem;
  border-radius: 999px; font-size: 0.26rem; font-weight: 600;
  color: #FFFFFF; background-color: var(--c-primary);
}
.ph-retry:active { opacity: .82; }
.ph-bar {
  display: flex; align-items: center; gap: 0.24rem;
  padding: 0.26rem 0.36rem calc(0.3rem + env(safe-area-inset-bottom));
  background-color: #0C1513;
}
.ph-info { flex: 1; min-width: 0; }
.ph-name { font-size: 0.3rem; font-weight: 600; color: #FFFFFF; }
.ph-src { margin-top: 0.06rem; font-size: 0.21rem; color: rgba(255, 255, 255, .5); }
.ph-close {
  flex: none; height: 0.72rem; padding: 0 0.4rem; border-radius: 999px;
  display: flex; align-items: center; font-size: 0.26rem; color: #FFFFFF;
  background-color: rgba(255, 255, 255, .14);
}
.ph-close:active { background-color: rgba(255, 255, 255, .26); }
@media (prefers-reduced-motion: reduce) {
  .ph-spin { animation: none; }
}

/* ==========================================================================
   V2.1 · 动效层（高级感 / 丝滑感）
   原则：只在「出现」的瞬间播一次（display:none → 显示时动画自动重放），
   逐帧跟随的东西（气泡定位、小三角旋转）依旧纯 transform，绝不用动画做。
   ========================================================================== */
@keyframes popIn {
  from { opacity: 0; transform: scale(.9) translateY(-0.06rem); }
  to   { opacity: 1; transform: none; }
}
@keyframes sheetUp {
  from { opacity: 0; transform: translateY(14%); }
  to   { opacity: 1; transform: none; }
}
@keyframes bootIn {
  from { opacity: 0; transform: scale(.86); }
  to   { opacity: 1; transform: none; }
}
@keyframes chipIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* 顶部控制面板：从胶囊一侧轻弹出 */
.livepanel { transform-origin: 100% 0; animation: popIn .22s cubic-bezier(.22, .9, .26, 1); }
/* 底部弹层（03c 导航选择 / 04 讲解详情 / 点位照片）：上滑入场 */
.navsheet, .detsheet, .photosheet { animation: sheetUp .3s cubic-bezier(.22, .9, .26, 1); }
/* 03b 倒计时层：核心环 + 按钮组先后浮入 */
.boot-core { animation: bootIn .34s cubic-bezier(.22, .9, .26, 1); }
.boot-acts { animation: bootIn .34s cubic-bezier(.22, .9, .26, 1) .06s backwards; }
/* 胶囊与底栏 tab：状态切换有过渡而不是硬切 */
.livepill { transition: background-color .25s ease, box-shadow .25s ease, color .25s ease; }
.global-tabbar .tab-item { transition: background-color .2s ease, color .2s ease; }
/* 03b 圆钮按压反馈更跟手 */
.boot-rbtn { transition: transform .15s ease; }
/* 当天已讲解的足迹标签：出现时轻淡入 */
.mp-item { animation: chipIn .25s ease; }

/* 用户系统开了「减弱动态效果」就全部让位：一切动画瞬时完成 */
@media (prefers-reduced-motion: reduce) {
  .livepanel, .navsheet, .detsheet, .photosheet, .boot-core, .boot-acts, .mp-item,
  .mh-avatar { animation: none; }
  .mh-halo { animation: none; opacity: 0; }
}
