:root {
  --ink: #1e293b;
  --ink-dim: #64748b;
  --ink-faint: #94a3b8;
  --line: rgba(15, 23, 42, 0.10);
  --panel: rgba(255, 255, 255, 0.88);
  --panel-solid: #ffffff;
  --accent: #2563eb;
  --accent-soft: rgba(37, 99, 235, 0.12);
  --warn: #dc2626;
  --shadow: 0 12px 32px rgba(2, 6, 23, 0.30), 0 2px 6px rgba(2, 6, 23, 0.18);
  /* 界面自适应：--uiW 由屏幕宽度决定，--uiH 由屏幕高度决定，乘积即统一缩放系数 --ui。
     所有界面尺寸都乘以 --ui，于是整体随屏幕等比缩放，小屏不挤、大屏不空旷。 */
  --uiW: 1;
  --uiH: 1;
  --ui: calc(var(--uiW) * var(--uiH));
  --r: calc(14px * var(--ui));
  --tb-h: calc(58px * var(--ui));
  /* 卡片表头统一规格（v3.6）：所有浮窗表头共用同一套高度 / 内边距 / 主题标记 */
  --head-h: calc(38px * var(--ui));
  --hy: calc(9px * var(--ui));
  --hx: calc(14px * var(--ui));
  --accent-bar: linear-gradient(180deg, #2563eb, #22d3ee);
  /* 面板文字样式（v14.0）：--ui-font 字体 / --ui-fs 字号倍率 由 JS 写入；
     --ink / --ink-dim / --ink-faint 三个文字色变量同样由 JS 覆写（含透明度）。
     v21.0：面板文字「字重」真正生效 ——
       --ui-fw   基准字重（正文）
       --ui-fw-m 中粗（原先把标题 / 分组名写死的 600）
       --ui-fw-b 加粗（原先写死的 700 / 800）
     三者都由「面板文字样式 › 字重」按所选等级推算写入，因此面板里从正文到标题会
     整体跟着变粗 / 变细，而不只是正文那一行。 */
  --ui-fs: 1;
  --ui-fw: 400;
  --ui-fw-m: 600;
  --ui-fw-b: 700;
  /* 浮窗停靠高度：由 JS 依视图实测写入（三窗/综合视图需下移到窗格标题条之下）。
     这里给纯 CSS 兜底值，保证脚本未执行时浮窗也不会压住标题条。 */
  --dock-top: calc(var(--tb-h) + 12px * var(--ui));
}

* { box-sizing: border-box; }

html, body {
  margin: 0; padding: 0; height: 100%; overflow: hidden;
  background: #05070d;
  color: var(--ink);
  font-family: var(--ui-font, "PingFang SC", "Microsoft YaHei", "Segoe UI", system-ui, -apple-system, sans-serif);
  font-size: calc(13px * var(--ui) * var(--ui-fs));
  /* v21.0：面板文字基准字重（标题 / 分组名的中粗与加粗由 --ui-fw-m / --ui-fw-b 承担） */
  font-weight: var(--ui-fw, 400);
  -webkit-font-smoothing: antialiased;
}

#gl { position: fixed; inset: 0; width: 100%; height: 100%; display: block; touch-action: none; cursor: grab; }
#gl.grabbing { cursor: grabbing; }

/* ---------- 视窗框 ---------- */
#panes { position: fixed; inset: 0; pointer-events: none; z-index: 5; }
.pane {
  position: absolute; display: none; flex-direction: column; gap: 2px;
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 12px; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.18);
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.07), rgba(255, 255, 255, 0));
}
.pane.on { display: flex; }
.pane > span { position: absolute; }
/* 窗格表头：与综合视图子窗口表头（.ccell-h）同款 */
.pane .pane-h {
  height: 30px; display: flex; align-items: center; padding: 0 10px; flex: none;
  background: linear-gradient(180deg, rgba(255,255,255,.16), rgba(255,255,255,.05));
  border-bottom: 1px solid rgba(255,255,255,.12);
  border-radius: 11px 11px 0 0; user-select: none;
}
.pane .pane-h span {
  position: relative; padding-left: 9px;
  font-size: calc(15px * var(--ui-fs)); font-weight: var(--ui-fw-m, 600); color: #eaf2ff;
  letter-spacing: .4px;
}
/* 统一的表头语言：左侧一小段主题色竖条（浅色卡片与深色窗格共用） */
.pane .pane-h span::before, #comboUI .ccell-h span::before {
  content: ""; position: absolute; left: 0; top: 50%; transform: translateY(-50%);
  width: 2.5px; height: 12px; border-radius: 999px;
  background: linear-gradient(180deg, #60a5fa, #22d3ee);
}
/* 提示文字：与标题同处一行（不再单独占一行，浮窗可以紧贴表头下方停靠） */
.pane .p-hint {
  margin-left: 10px; font-size: calc(11px * var(--ui-fs)); font-style: normal; font-weight: var(--ui-fw, 400);
  color: rgba(226, 240, 255, 0.62); letter-spacing: 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0;
}

/* ---------- 可拖动分隔条 ---------- */
.splitter { position: fixed; z-index: 11; display: none; }
.splitter.on { display: block; }
.splitter i {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  border-radius: 999px; background: rgba(37, 99, 235, .45);
  box-shadow: 0 0 0 3px rgba(37, 99, 235, .12); transition: background .15s ease;
}
.splitter.vert { cursor: col-resize; width: 10px; }
.splitter.vert i { width: 4px; height: 46px; }
.splitter.horz { cursor: row-resize; height: 10px; }
.splitter.horz i { height: 4px; width: 46px; }
.splitter:hover i, .splitter.drag i { background: rgba(37, 99, 235, .9); box-shadow: 0 0 0 4px rgba(37, 99, 235, .18); }
body.resizing { user-select: none; cursor: grabbing; }

/* ---------- 面板通用 ---------- */
.card {
  position: fixed; z-index: 10;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--r);
  box-shadow: var(--shadow); backdrop-filter: blur(14px) saturate(1.25);
  -webkit-backdrop-filter: blur(14px) saturate(1.25);
}
#optsCard.collapsed .card-body { display: none; }

/* ---------- 卡片表头（v3.6 统一规格） ----------
   1) 满宽出血：用负外边距抵消卡片自身的内边距，表头横贯整张卡片，
      不再出现“白色表头浮在卡片里、右侧留一条缝”的观感；
   2) 顶部圆角跟随卡片内圆角，避免表头方角戳出卡片圆角；
   3) 统一构成：左侧主题色竖条 + 图标 + 标题 + 摘要胶囊 + 右侧折叠胶囊按钮。 */
.card > .card-head {
  position: relative; z-index: 2; flex: none;
  display: flex; align-items: center; gap: calc(9px * var(--ui));
  min-height: var(--head-h);
  margin: 0 calc(-1 * var(--pad-x, 0px)) 0;
  padding: var(--hy) var(--hx);
  border-radius: calc(var(--r) - 1px) calc(var(--r) - 1px) 0 0;
  background:
    radial-gradient(140% 190% at 0% 0%, rgba(37, 99, 235, .14), rgba(37, 99, 235, 0) 60%),
    linear-gradient(180deg, rgba(255, 255, 255, .99), rgba(244, 248, 255, .97));
  border-bottom: 1px solid rgba(15, 23, 42, .09);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .95);
  cursor: grab; user-select: none;
}
.card-head h2 {
  position: relative; margin: 0; padding-left: calc(11px * var(--ui));
  display: inline-flex; align-items: center; gap: calc(5px * var(--ui));
  font-size: calc(13px * var(--ui) * var(--ui-fs)); font-weight: var(--ui-fw-b, 700); letter-spacing: .3px;
  color: var(--ink); line-height: 1.25; white-space: nowrap;
}
.card-head h2::before {
  content: ""; position: absolute; left: 0; top: 50%; transform: translateY(-50%);
  width: calc(3px * var(--ui)); height: calc(15px * var(--ui)); border-radius: 999px;
  background: var(--accent-bar);
  box-shadow: 0 0 0 calc(2.5px * var(--ui)) rgba(37, 99, 235, .10);
}
.hd-ico { font-style: normal; font-size: calc(13px * var(--ui) * var(--ui-fs)); line-height: 1; }
/* 表头摘要（时间 / 观测点）：主题色浅胶囊，替代原来的灰色小字 */
.card-head > output {
  flex: 0 1 auto; min-width: 0;
  padding: calc(2px * var(--ui)) calc(9px * var(--ui));
  border: 1px solid rgba(37, 99, 235, .16); border-radius: 999px;
  background: rgba(37, 99, 235, .08); color: #1d4ed8;
  font-size: calc(11px * var(--ui) * var(--ui-fs)); font-weight: var(--ui-fw-m, 600);
  font-variant-numeric: tabular-nums; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
/* 折叠 / 展开：胶囊按钮 + 状态箭头（展开态朝上、折叠态朝下） */
.card-head .link {
  flex: none; margin-left: auto;
  display: inline-flex; align-items: center; gap: calc(5px * var(--ui));
  padding: calc(3px * var(--ui)) calc(10px * var(--ui));
  border: 1px solid rgba(37, 99, 235, .22); border-radius: 999px;
  background: rgba(37, 99, 235, .07); color: #1d4ed8;
  font-size: calc(11.5px * var(--ui) * var(--ui-fs)); font-weight: var(--ui-fw-m, 600); line-height: 1.3;
  transition: background .15s ease, border-color .15s ease, transform .12s ease;
}
.card-head .link::before {
  content: ""; width: calc(5.5px * var(--ui)); height: calc(5.5px * var(--ui));
  border-right: calc(1.8px * var(--ui)) solid currentColor;
  border-bottom: calc(1.8px * var(--ui)) solid currentColor;
  transform: rotate(-135deg) translate(-1px, -1px); transition: transform .18s ease;
}
.card-head .link:hover { background: rgba(37, 99, 235, .16); border-color: rgba(37, 99, 235, .38); }
.card-head .link:active { transform: translateY(1px); }
#optsCard.collapsed .card-head .link::before,
#timeCard.min .card-head .link::before,
#geoInfo.gi-min .card-head .link::before { transform: rotate(45deg) translate(-2px, -2px); }

/* ---------- 点标注列表 ---------- */
.pt-list { display: flex; flex-direction: column; gap: 3px; max-height: 168px; overflow-y: auto; }
.pt-row { display: flex; align-items: center; gap: 7px; padding: 3px 6px; border-radius: 7px; background: rgba(122,162,255,0.07); }
.pt-dot { flex: none; width: 9px; height: 9px; border-radius: 50%; box-shadow: 0 0 5px rgba(255,176,32,0.55); }
.pt-txt { flex: 1; font-size: calc(11.5px * var(--ui-fs)); color: var(--ink); white-space: nowrap; }
.pt-del { flex: none; }
.pt-empty { font-size: calc(11px * var(--ui-fs)); color: var(--ink-dim); padding: 2px 0; }

/* ---------- 顶部标题栏（v3.6：沉浸式横贯窗口顶端） ---------- */
#titleBar {
  position: fixed; top: 0; left: 0; right: 0; height: var(--tb-h); z-index: 15;
  display: flex; align-items: center; gap: 13px; padding: 0 20px;
  background:
    radial-gradient(140% 260% at 6% -60%, rgba(37, 99, 235, .26), rgba(37, 99, 235, 0) 62%),
    linear-gradient(90deg, rgba(255, 255, 255, .95) 0%, rgba(241, 246, 255, .92) 46%, rgba(255, 255, 255, .95) 100%);
  border-bottom: 1px solid rgba(15, 23, 42, .08);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .85), 0 6px 20px rgba(2, 6, 23, .22);
  backdrop-filter: blur(18px) saturate(1.45);
  -webkit-backdrop-filter: blur(18px) saturate(1.45);
  user-select: none;
}
/* 顶部高光：让标题栏“贴住”窗口最上沿 */
#titleBar::before {
  content: ""; position: absolute; left: 0; right: 0; top: 0; height: 1px; pointer-events: none;
  background: linear-gradient(90deg, rgba(255,255,255,0), rgba(255,255,255,.95) 20%, rgba(255,255,255,.95) 80%, rgba(255,255,255,0));
}
/* 底端主题渐变线：标题栏与场景之间的“沉浸”过渡 */
#titleBar::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -1px; height: 2px; opacity: .8; pointer-events: none;
  background: linear-gradient(90deg, rgba(37,99,235,0) 0%, rgba(37,99,235,.62) 16%, rgba(34,211,238,.68) 58%, rgba(37,99,235,0) 100%);
}
/* v20.0：左侧徽标由「自转」文字改为地球图片（内联 SVG，无外部资源依赖）。
   圆形底盘 + 主题色外发光；发光颜色随当前视图变化（自转=蓝 / 公转=琥珀 / 综合=紫），
   由 JS 写入 data-view 属性驱动，标题栏一眼可辨当前处于哪种视图。 */
.title-badge {
  width: 38px; height: 38px; flex: none; border-radius: 50%; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  background: radial-gradient(circle at 34% 28%, #16324f, #0b1d33 78%);
  box-shadow: 0 4px 14px rgba(37, 99, 235, .38), inset 0 0 0 1px rgba(255, 255, 255, .18);
  transition: box-shadow .22s ease;
}
.title-badge svg { width: 100%; height: 100%; display: block; }
.title-badge[data-view="revolve"] { box-shadow: 0 4px 14px rgba(245, 158, 11, .46), inset 0 0 0 1px rgba(255, 255, 255, .22); }
.title-badge[data-view="combo"]   { box-shadow: 0 4px 14px rgba(139, 92, 246, .46), inset 0 0 0 1px rgba(255, 255, 255, .22); }
/* 标题与制作者徽标同处一行（v20.0 删除标题下的小字副标题）。
   .tb-text 允许收缩（min-width:0）——窄屏下标题可换行，不会撑破标题栏。 */
.tb-text { min-width: 0; }
.tb-text h1 { margin: 0; font-size: calc(16.5px * var(--ui-fs)); font-weight: var(--ui-fw-b, 700); letter-spacing: .3px; white-space: nowrap; }
/* 单窗 / 三窗：只在“自转演示”视图显示（其余视图无此概念） */
#segMode { display: none; }
body[data-view="rotate"] #segMode { display: flex; }

/* ---------- 时间面板 ---------- */
#timeCard {
  right: 16px; top: var(--dock-top); width: 336px; padding: 0 16px 12px;
  display: flex; flex-direction: column; gap: 10px; transition: opacity .2s ease;
  /* 高度上限：不超过窗口下沿，且不越过下方窗格标题文字（--cap 由 JS 按综合视图
     里实际标题位置写入）；内容超高时面板内部滚动，标题始终可见 */
  /* 高度上限：不超过窗口下沿，且不越过下方窗格标题文字（--cap 由 JS 按综合视图
     里实际标题位置写入）；内容超高时面板内部滚动，标题始终可见。
     先写普通 calc() 兜底，再写 min() 版本 —— 不支持 min() 的内核会保留前一条 */
  max-height: calc(100vh - var(--dock-top) - 12px);
  max-height: min(var(--cap, 100vh), calc(100vh - var(--dock-top) - 12px));
  overflow-y: auto;
  /* 面板自身可滚动：触摸设备允许纵向原生滚动 */
  touch-action: pan-y; overscroll-behavior: contain; -webkit-overflow-scrolling: touch;
  --pad-x: calc(16px * var(--ui)); --hx: calc(16px * var(--ui));
}
#timeCard.fade { opacity: .28; }
/* 折叠态：只留标题行。宽度 auto → 收缩到内容（图标+标题+摘要胶囊+按钮）实际所需宽度，
   既不截断摘要，也不留多余空白（内容自适应排版） */
#timeCard.min { width: auto; }
#timeCard.min .t-block, #timeCard.min .terms,
#timeCard.min .term-note, #timeCard.min .sb, #timeCard.min .facts { display: none; }
/* 浮窗拖拽 */
.card.grabbing { cursor: grabbing; box-shadow: 0 10px 34px rgba(15, 23, 42, .22); }
.card.grabbing .card-head { cursor: grabbing; }
#timeCard.grabbing { opacity: 1 !important; }
.t-main { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
#tDate { font-size: calc(15px * var(--ui-fs)); font-weight: var(--ui-fw-b, 700); }
#tClock { font-size: calc(26px * var(--ui-fs)); font-weight: var(--ui-fw-b, 700); letter-spacing: 1px; font-variant-numeric: tabular-nums; line-height: 1.1; color: var(--ink); }
.t-sub { display: flex; justify-content: space-between; align-items: center; font-size: calc(11px * var(--ui-fs)); color: var(--ink-dim); }
.link {
  border: 0; background: none; color: var(--accent); font-size: calc(11.5px * var(--ui-fs)); cursor: pointer; padding: 2px 4px; border-radius: 6px;
  font-family: inherit;
}
.link:hover { background: var(--accent-soft); }

.terms { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; }
.term {
  border: 1px solid var(--line); background: rgba(255, 255, 255, .7); border-radius: 9px; padding: 5px 2px; cursor: pointer;
  text-align: center; font-family: inherit; transition: .15s;
}
.term .n { display: block; font-size: calc(12px * var(--ui-fs)); font-weight: var(--ui-fw-m, 600); color: var(--ink); }
.term .d { display: block; font-size: calc(10px * var(--ui-fs)); color: var(--ink-faint); margin-top: 1px; font-variant-numeric: tabular-nums; }
.term:hover { border-color: rgba(37, 99, 235, .45); background: #fff; }
.term.active { background: var(--accent); border-color: var(--accent); }
.term.active .n, .term.active .d { color: #fff; }
.term-note { font-size: calc(11px * var(--ui-fs)); color: var(--ink-dim); margin-top: -2px; }

.sb { display: flex; flex-direction: column; gap: 3px; }
.sb-head { display: flex; justify-content: space-between; align-items: baseline; font-size: calc(11.5px * var(--ui-fs)); }
.sb-head label { color: var(--ink-dim); }
.sb-head .dim { color: var(--ink-faint); }
.sb-head output { font-weight: var(--ui-fw-b, 700); font-size: calc(12.5px * var(--ui-fs)); font-variant-numeric: tabular-nums; }

.ticks { position: relative; height: 24px; margin-top: -1px; }
.ticks .tk { position: absolute; transform: translateX(-50%); font-size: calc(9.5px * var(--ui-fs)); color: var(--ink-faint); top: 0; white-space: nowrap; }
.ticks .tk::before {
  content: ""; position: absolute; left: 50%; top: -5px; width: 1px; height: 3px; background: rgba(100, 116, 139, .5);
}
.ticks .tk.t2 { top: 11px; }
.ticks .tk.t2::before { top: -4px; height: 3px; }
.ticks .tk.key { color: var(--accent); font-weight: var(--ui-fw-b, 700); font-size: calc(10.5px * var(--ui-fs)); }
.ticks .tk.key::before { background: var(--accent); height: 4px; width: 1.5px; }

.facts { display: grid; grid-template-columns: 1fr 1fr; gap: 7px 8px; border-top: 1px dashed var(--line); padding-top: 9px; }
.facts div { text-align: center; min-width: 0; }
.facts .fact-wide { grid-column: 1 / -1; }
.facts b { display: block; font-size: calc(13px * var(--ui-fs)); font-variant-numeric: tabular-nums; color: var(--ink); }
.facts i { display: block; font-style: normal; font-size: calc(10px * var(--ui-fs)); color: var(--ink-faint); margin-top: 1px; }

/* ---------- 显示设置 ---------- */
/* v3.6：滚动从卡片移到 .card-body，表头独立于滚动区 —— 表头不再被内容“穿透”，
   右侧也不会再被滚动条挤出一条缝。 */
#optsCard {
  left: 16px; top: var(--dock-top); width: 292px;
  /* --cap（JS 写入）＝ 下方窗格标题文字的上沿，保证铺满全窗时标题不被压住
     （同样先写 calc() 兜底、再写 min() 版本） */
  max-height: calc(100vh - var(--tb-h) - 130px);
  max-height: min(var(--cap, 100vh), calc(100vh - var(--tb-h) - 130px));
  display: flex; flex-direction: column; overflow: hidden; padding: 0;
  --pad-x: 0px; --hx: calc(14px * var(--ui));
}
#optsCard .card-body {
  flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden;
  /* 触摸设备上允许纵向原生滚动（此前被浮窗拖动逻辑劫持 → 无法滑动） */
  touch-action: pan-y; overscroll-behavior: contain; -webkit-overflow-scrolling: touch;
  padding: calc(8px * var(--ui)) calc(14px * var(--ui)) calc(12px * var(--ui));
  display: flex; flex-direction: column; gap: calc(4px * var(--ui));
}
/* 仅在虚线模式下可用的行（实线时置灰并禁用） */
.row.locked { opacity: .42; }
.row.locked input { pointer-events: none; }
.row select {
  flex: 1; border: 1px solid var(--line); border-radius: 7px; padding: 3px 6px; font-family: inherit; font-size: calc(11.5px * var(--ui-fs));
  background: #fff; color: var(--ink);
}
.row input[type=color] {
  width: 30px; height: 22px; padding: 0; border: 1px solid var(--line); border-radius: 6px; background: none; cursor: pointer;
}
.clr-hex { font-size: calc(10.5px * var(--ui-fs)); color: var(--ink-faint); font-variant-numeric: tabular-nums; }

.btn-row { display: flex; align-items: center; gap: 8px; padding: 4px 0 0; }
.dim { font-size: calc(10.5px * var(--ui-fs)); color: var(--ink-faint); }

/* 开关 */
.sw { display: flex; align-items: center; gap: 9px; padding: 4px 0; cursor: pointer; user-select: none; }
.sw input { display: none; }
.sw .track {
  width: 32px; height: 18px; border-radius: 10px; background: rgba(100, 116, 139, .32); position: relative; flex: none;
  transition: background .18s;
}
.sw .track::after {
  content: ""; position: absolute; width: 14px; height: 14px; border-radius: 50%; background: #fff; top: 2px; left: 2px;
  box-shadow: 0 1px 3px rgba(0,0,0,.28); transition: transform .18s;
}
.sw input:checked + .track { background: var(--accent); }
.sw input:checked + .track::after { transform: translateX(14px); }
.sw-label { font-size: calc(12px * var(--ui-fs)); }

/* 滑块 */
input[type=range] {
  -webkit-appearance: none; appearance: none; height: 18px; background: transparent; cursor: pointer;
}
input[type=range]::-webkit-slider-runnable-track {
  height: 4px; border-radius: 2px; background: linear-gradient(90deg, rgba(37,99,235,.55), rgba(37,99,235,.18));
}
input[type=range]::-webkit-slider-thumb {
  -webkit-appearance: none; width: 14px; height: 14px; border-radius: 50%; background: #fff; margin-top: -5px;
  border: 2px solid var(--accent); box-shadow: 0 1px 4px rgba(2,6,23,.25);
}
input[type=range]::-moz-range-track { height: 4px; border-radius: 2px; background: rgba(37,99,235,.4); }
input[type=range]::-moz-range-thumb {
  width: 12px; height: 12px; border-radius: 50%; background: #fff; border: 2px solid var(--accent);
}

/* ---------- 底部控制条 ---------- */
#controlBar {
  position: fixed; z-index: 12; left: 50%; bottom: 14px; transform: translateX(-50%);
  display: flex; align-items: center; gap: 12px; row-gap: 8px; padding: 10px 16px; border-radius: 16px;
  background: var(--panel); border: 1px solid var(--line); box-shadow: var(--shadow);
  backdrop-filter: blur(14px) saturate(1.25); -webkit-backdrop-filter: blur(14px) saturate(1.25);
  max-width: calc(100vw - 32px); flex-wrap: wrap; justify-content: center;
}
/* 折叠按钮：位于控制条窗口内右上角 */
.cb-toggle {
  position: absolute; top: 5px; right: 8px;
  border: 1px solid var(--line); background: rgba(255, 255, 255, .65); color: var(--ink-faint);
  border-radius: 999px; padding: 1px 9px; font-size: calc(10.5px * var(--ui-fs)); font-family: inherit; cursor: pointer;
  display: inline-flex; align-items: center; gap: 4px;
  transition: color .15s, border-color .15s; white-space: nowrap; flex: none;
}
.cb-toggle:hover { color: #1d4ed8; border-color: rgba(37, 99, 235, .45); }
.cb-toggle .arr { display: inline-block; transition: transform .25s; font-size: calc(9px * var(--ui-fs)); line-height: 1; }
#controlBar.min { padding: 6px 12px; }
#controlBar.min .cb-group, #controlBar.min .cb-sep { display: none; }
#controlBar.min .cb-toggle { position: static; }
#controlBar.min .cb-toggle .arr { transform: rotate(180deg); }
.cb-group { display: flex; align-items: center; gap: 8px; flex-wrap: nowrap; }
.cb-sep { width: 1px; height: 26px; background: var(--line); flex: none; }
.cb-cap { font-size: calc(11.5px * var(--ui-fs)); color: var(--ink-faint); flex: none; letter-spacing: .5px; }
.btn {
  border: 1px solid var(--line); background: #fff; color: var(--ink); border-radius: 9px; padding: 6px 13px;
  font-size: calc(12.5px * var(--ui-fs)); font-family: inherit; cursor: pointer; display: inline-flex; align-items: center; gap: 5px;
  height: 31px; transition: .15s; white-space: nowrap;
}
.btn:hover { border-color: rgba(37,99,235,.5); color: var(--accent); transform: translateY(-1px); }
.btn:active { transform: translateY(0); }
.btn.xs { height: 27px; padding: 4px 10px; font-size: calc(12px * var(--ui-fs)); }
.btn.on { background: var(--accent); border-color: var(--accent); color: #fff; }
.unit { font-size: calc(11px * var(--ui-fs)); color: var(--ink-dim); min-width: 22px; }
.btn.play { background: var(--accent); border-color: var(--accent); color: #fff; min-width: 88px; justify-content: center; }
.btn.play:hover { background: #1d4ed8; color: #fff; }
.btn.warn { color: var(--warn); }
.btn.warn:hover { border-color: rgba(220,38,38,.5); background: rgba(220,38,38,.06); color: var(--warn); }
.speed { display: flex; align-items: center; gap: 8px; }
.speed label { font-size: calc(11.5px * var(--ui-fs)); color: var(--ink-dim); white-space: nowrap; }
.speed input[type=range] { width: 110px; }
.speed output { font-size: calc(11.5px * var(--ui-fs)); min-width: 124px; color: var(--ink); font-variant-numeric: tabular-nums; }
.seg { display: flex; border: 1px solid var(--line); border-radius: 9px; overflow: hidden; background: #fff; flex: none; }
.seg button {
  border: 0; background: none; padding: 6px 14px; height: 29px; font-size: calc(12.5px * var(--ui-fs)); font-family: inherit;
  cursor: pointer; color: var(--ink-dim); white-space: nowrap; transition: .15s;
}
.seg button + button { border-left: 1px solid var(--line); }
.seg button:hover { color: var(--accent); background: rgba(37, 99, 235, .06); }
.seg button.on { background: var(--accent); color: #fff; }
.grp-tip { margin: 8px 0 0; font-size: calc(10.5px * var(--ui-fs)); line-height: 1.6; color: var(--ink-dim); }

/* ---------- loading ---------- */
#loading {
  position: fixed; z-index: 30; left: 50%; top: 50%; transform: translate(-50%, -50%);
  padding: 10px 18px; border-radius: 12px; background: rgba(15,23,42,.82); color: #e2e8f0; font-size: calc(13px * var(--ui-fs));
  letter-spacing: .5px; transition: opacity .4s; pointer-events: none;
}
#loading.hide { opacity: 0; }

/* 滚动条（滚动区已移至 .card-body，表头不再被滚动条挤窄） */
#optsCard .card-body::-webkit-scrollbar { width: 10px; }
#optsCard .card-body::-webkit-scrollbar-thumb { background: rgba(100,116,139,.45); border-radius: 5px; }
#optsCard .card-body::-webkit-scrollbar-track { background: transparent; }
#optsCard .card-body { scrollbar-width: thin; scrollbar-color: rgba(100,116,139,.4) transparent; }

/* ---------- 标题栏视图切换 ---------- */
#titleBar .title-views { margin-left: auto; }
#titleBar .seg { height: 30px; }
#titleBar .seg button { height: 28px; padding: 0 14px; font-size: calc(12px * var(--ui-fs)); }

/* ---------- 综合视图窗口管理器 ---------- */
#comboUI { position: fixed; inset: 0; z-index: 6; display: none; pointer-events: none; }
#comboUI.on { display: block; }
#comboUI .ccell {
  position: absolute; background: transparent; border: 1px solid rgba(255,255,255,.16);
  border-radius: 12px; overflow: hidden; pointer-events: none;
}
#comboUI .ccell-h {
  height: 30px; display: flex; align-items: center; justify-content: space-between; padding: 0 10px;
  background: linear-gradient(180deg, rgba(255,255,255,.16), rgba(255,255,255,.05));
  border-bottom: 1px solid rgba(255,255,255,.12); cursor: pointer; user-select: none; pointer-events: auto;
}
#comboUI .ccell-h span { position: relative; padding-left: 9px; font-size: calc(15px * var(--ui-fs)); font-weight: var(--ui-fw-b, 700); color: #eaf2ff; letter-spacing: .5px; }
#comboUI .ccell-x {
  border: 0; background: rgba(255,255,255,.14); color: #eaf2ff; border-radius: 6px; width: 22px; height: 20px;
  font-size: calc(13px * var(--ui-fs)); line-height: 1; cursor: pointer; font-family: inherit;
}
#comboUI .ccell-x:hover { background: rgba(255,255,255,.3); }
#comboUI .cdiv { position: absolute; z-index: 7; pointer-events: auto; }
#comboUI .cdiv:hover { background: rgba(37,99,235,.25); }
#comboUI .cdiv#spV, #comboUI .cdiv#spV2 { width: 8px; cursor: col-resize; }
#comboUI .cdiv#spL1, #comboUI .cdiv#spR1 { height: 8px; cursor: row-resize; }

/* ---------- 观测点数据面板（默认时间面板左侧；风格与其它浮窗一致，可折叠 / 拖动） ---------- */
#geoInfo {
  z-index: 20; display: none; width: 344px; max-width: 412px;
  padding: 0 14px 10px; font-size: calc(12.5px * var(--ui-fs)); line-height: 1.5;
  max-height: calc(100vh - var(--dock-top) - 12px);
  max-height: min(var(--cap, 100vh), calc(100vh - var(--dock-top) - 12px));
  overflow-y: auto;
  touch-action: pan-y; overscroll-behavior: contain;
  --pad-x: calc(14px * var(--ui)); --hx: calc(14px * var(--ui));
}
#geoInfo.on { display: block; }
/* 折叠态：只留标题行（宽度同上，保证表头摘要不被截断） */
#geoInfo.gi-min { width: auto; }
#geoInfo.gi-min .gi-body { display: none; }
#geoInfo .gi-body { display: flex; flex-direction: column; padding-top: 8px; }
#geoInfo .pi { display: flex; align-items: baseline; gap: 6px; padding: 3px 0; }
#geoInfo .pi-k { flex: none; min-width: 68px; color: var(--ink-dim); font-size: calc(11.5px * var(--ui-fs)); white-space: nowrap; }
/* 数值行一律不换行：面板宽度已按最长行（全年昼长 / 日出日落方位）预留 */
#geoInfo .pi-v { flex: 1; text-align: right; color: var(--ink); font-weight: var(--ui-fw-m, 600); white-space: nowrap; }
#geoInfo .pi.hero { flex-direction: column; align-items: center; gap: 1px; padding: 6px 0 4px;
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); margin: 3px 0; }
#geoInfo .pi.hero .pi-k { min-width: 0; }
#geoInfo .pi-big { font-size: calc(21px * var(--ui-fs)); font-weight: var(--ui-fw-b, 800); letter-spacing: 1px; color: #b45309; line-height: 1.2; }
#geoInfo .pi-cap { font-size: calc(11px * var(--ui-fs)); color: var(--ink-dim); }
#geoInfo .pi-curve { display: block; padding-top: 6px; }
/* 全年昼长曲线：高度固定、宽度自适应；画布内部分辨率由 JS 按实际显示尺寸 × devicePixelRatio
   重建（此前固定 464×156 内部尺寸 + CSS 拉伸，宽高比不一致导致文字被压扁） */
#geoInfo #cvYearCurve { width: 100%; height: 92px; display: block; }

/* =====================================================================
   自适应（v2.5）：整个界面随屏幕尺寸等比缩放
   ---------------------------------------------------------------------
   --uiW 由屏幕宽度断点决定、--uiH 由屏幕高度断点决定，二者相乘得到统一
   缩放系数 --ui。下面集中覆盖上文各处的固定像素值，使标题栏 / 时间面板 /
   显示设置 / 底部控制条 / 综合视图子窗口在笔记本小屏、低矮窗口、超宽大屏
   上都能完整显示、互不重叠。
   ===================================================================== */

/* --- 宽度断点：越宽的屏放得越大，越窄的屏收得越小（断点留有余量，避免窗口边框导致刚好卡在边界） --- */
@media (min-width: 2400px)                        { :root { --uiW: 1.26; } }
@media (min-width: 2000px) and (max-width: 2399px) { :root { --uiW: 1.16; } }
@media (min-width: 1760px) and (max-width: 1999px) { :root { --uiW: 1.06; } }
@media (min-width: 1560px) and (max-width: 1759px) { :root { --uiW: 1.00; } }
@media (max-width: 1559px)                        { :root { --uiW: 0.94; } }
@media (max-width: 1400px)                        { :root { --uiW: 0.88; } }
@media (max-width: 1240px)                        { :root { --uiW: 0.82; } }
@media (max-width: 1100px)                        { :root { --uiW: 0.75; } }
@media (max-width: 980px)                         { :root { --uiW: 0.68; } }
@media (max-width: 860px)                         { :root { --uiW: 0.60; } }
@media (max-width: 720px)                         { :root { --uiW: 0.52; } }

/* --- 高度断点：低矮窗口进一步收窄，避免面板超出屏幕 --- */
@media (max-height: 940px) { :root { --uiH: 0.97; } }
@media (max-height: 820px) { :root { --uiH: 0.92; } }
@media (max-height: 700px) { :root { --uiH: 0.86; } }
@media (max-height: 600px) { :root { --uiH: 0.78; } }
/* v23.8：手机横屏（高度常常只有 300~460px）再收一档，浮窗不会顶出屏幕 */
@media (max-height: 480px) { :root { --uiH: 0.70; } }
@media (max-height: 400px) { :root { --uiH: 0.62; } }

/* --- 顶部标题栏 --- */
#titleBar { padding: 0 calc(20px * var(--ui)); gap: calc(13px * var(--ui)); }
.title-badge {
  width: calc(38px * var(--ui)); height: calc(38px * var(--ui));
  border-radius: 50%;
}
.tb-text h1 { font-size: calc(16.5px * var(--ui) * var(--ui-fs)); }
#titleBar .seg { height: calc(30px * var(--ui)); }
#titleBar .seg button { height: calc(28px * var(--ui)); padding: 0 calc(14px * var(--ui)); font-size: calc(12px * var(--ui) * var(--ui-fs)); }

/* --- 右侧时间面板 --- */
#timeCard {
  right: calc(16px * var(--ui)); top: var(--dock-top);
  width: calc(336px * var(--ui));
  padding: 0 calc(16px * var(--ui)) calc(12px * var(--ui));
  gap: calc(10px * var(--ui));
  /* max-height 见上方主规则（min(--cap, 视口剩余高度)），此处不再覆盖 */
  --pad-x: calc(16px * var(--ui)); --hx: calc(16px * var(--ui));
}
/* 时间面板自身会滚动（窗口很矮时），表头保持吸附在顶部 */
#timeCard > .card-head { position: sticky; top: 0; }
#timeCard.min { width: auto; }
.t-main { gap: calc(8px * var(--ui)); }
#tDate { font-size: calc(15px * var(--ui) * var(--ui-fs)); }
#tClock { font-size: calc(26px * var(--ui) * var(--ui-fs)); }
.t-sub { font-size: calc(11px * var(--ui) * var(--ui-fs)); }
.link { font-size: calc(11.5px * var(--ui) * var(--ui-fs)); padding: calc(2px * var(--ui)) calc(4px * var(--ui)); border-radius: calc(6px * var(--ui)); }
.terms { gap: calc(6px * var(--ui)); }
.term { border-radius: calc(9px * var(--ui)); padding: calc(5px * var(--ui)) calc(2px * var(--ui)); }
.term .n { font-size: calc(12px * var(--ui) * var(--ui-fs)); }
.term .d { font-size: calc(10px * var(--ui) * var(--ui-fs)); margin-top: calc(1px * var(--ui)); }
.term-note { font-size: calc(11px * var(--ui) * var(--ui-fs)); }
.sb { gap: calc(3px * var(--ui)); }
.sb-head { font-size: calc(11.5px * var(--ui) * var(--ui-fs)); }
.sb-head output { font-size: calc(12.5px * var(--ui) * var(--ui-fs)); }
.ticks { height: calc(24px * var(--ui)); }
.ticks .tk { font-size: calc(9.5px * var(--ui) * var(--ui-fs)); }
.ticks .tk.t2 { top: calc(11px * var(--ui)); }
.ticks .tk.key { font-size: calc(10.5px * var(--ui) * var(--ui-fs)); }
.facts { gap: calc(7px * var(--ui)) calc(8px * var(--ui)); padding-top: calc(9px * var(--ui)); }
.facts b { font-size: calc(13px * var(--ui) * var(--ui-fs)); }
.facts i { font-size: calc(10px * var(--ui) * var(--ui-fs)); margin-top: calc(1px * var(--ui)); }

/* --- 左侧显示设置 --- */
#optsCard {
  left: calc(16px * var(--ui)); top: var(--dock-top);
  width: calc(292px * var(--ui));
  max-height: calc(100vh - var(--tb-h) - 130px * var(--ui));
  max-height: min(var(--cap, 100vh), calc(100vh - var(--tb-h) - 130px * var(--ui)));
}
.grp-tip { font-size: calc(10.5px * var(--ui) * var(--ui-fs)); margin: calc(8px * var(--ui)) 0 0; }
.dim { font-size: calc(10.5px * var(--ui) * var(--ui-fs)); }
.clr-hex { font-size: calc(10.5px * var(--ui) * var(--ui-fs)); }
.btn-row { gap: calc(8px * var(--ui)); padding: calc(4px * var(--ui)) 0 0; }

/* 设置项行：标签 + 控件 + 读数对齐排布（原来没有 flex，窄屏下容易错位） */
.row { display: flex; align-items: center; gap: calc(8px * var(--ui)); padding: calc(3px * var(--ui)) 0; }
.row > label { flex: none; width: auto; white-space: nowrap; font-size: calc(11.5px * var(--ui) * var(--ui-fs)); color: var(--ink-dim); max-width: 62%; }
.row input[type=range] { flex: 1 1 auto; min-width: 0; }
.row > output { flex: none; min-width: calc(46px * var(--ui)); text-align: right; font-size: calc(11.5px * var(--ui) * var(--ui-fs)); font-variant-numeric: tabular-nums; color: var(--ink); }
.row input[type=number] {
  flex: 1 1 auto; min-width: 0; border: 1px solid var(--line); border-radius: calc(7px * var(--ui));
  padding: calc(3px * var(--ui)) calc(6px * var(--ui)); font-family: inherit; font-size: calc(11.5px * var(--ui) * var(--ui-fs));
  background: #fff; color: var(--ink);
}
.row select { font-size: calc(11.5px * var(--ui) * var(--ui-fs)); padding: calc(3px * var(--ui)) calc(6px * var(--ui)); border-radius: calc(7px * var(--ui)); }
.row input[type=color] { width: calc(30px * var(--ui)); height: calc(22px * var(--ui)); border-radius: calc(6px * var(--ui)); }
.unit { font-size: calc(11px * var(--ui) * var(--ui-fs)); min-width: calc(22px * var(--ui)); }

/* 开关 */
.sw { gap: calc(9px * var(--ui)); padding: calc(4px * var(--ui)) 0; }
.sw .track { width: calc(32px * var(--ui)); height: calc(18px * var(--ui)); border-radius: calc(10px * var(--ui)); }
.sw .track::after { width: calc(14px * var(--ui)); height: calc(14px * var(--ui)); top: calc(2px * var(--ui)); left: calc(2px * var(--ui)); }
.sw input:checked + .track::after { transform: translateX(calc(14px * var(--ui))); }
.sw-label { font-size: calc(12px * var(--ui) * var(--ui-fs)); }

/* 滑块 */
input[type=range] { height: calc(18px * var(--ui)); }
input[type=range]::-webkit-slider-runnable-track { height: calc(4px * var(--ui)); border-radius: calc(2px * var(--ui)); }
input[type=range]::-webkit-slider-thumb { width: calc(14px * var(--ui)); height: calc(14px * var(--ui)); margin-top: calc(-5px * var(--ui)); border-width: calc(2px * var(--ui)); }
input[type=range]::-moz-range-track { height: calc(4px * var(--ui)); }

/* --- 底部控制条 --- */
#controlBar {
  bottom: calc(14px * var(--ui)); gap: calc(12px * var(--ui)); padding: calc(10px * var(--ui)) calc(16px * var(--ui));
  border-radius: calc(16px * var(--ui)); max-width: calc(100vw - 2 * 16px * var(--ui));
}
#controlBar.min { padding: calc(6px * var(--ui)) calc(12px * var(--ui)); }
.cb-toggle { font-size: calc(10.5px * var(--ui) * var(--ui-fs)); padding: calc(1px * var(--ui)) calc(9px * var(--ui)); top: calc(5px * var(--ui)); right: calc(8px * var(--ui)); }
.cb-group { gap: calc(8px * var(--ui)); }
.cb-sep { height: calc(26px * var(--ui)); }
.cb-cap { font-size: calc(11.5px * var(--ui) * var(--ui-fs)); }
.btn { border-radius: calc(9px * var(--ui)); padding: calc(6px * var(--ui)) calc(13px * var(--ui)); font-size: calc(12.5px * var(--ui) * var(--ui-fs)); height: calc(31px * var(--ui)); gap: calc(5px * var(--ui)); }
.btn.xs { height: calc(27px * var(--ui)); padding: calc(4px * var(--ui)) calc(10px * var(--ui)); font-size: calc(12px * var(--ui) * var(--ui-fs)); }
.btn.play { min-width: calc(88px * var(--ui)); }
.speed { gap: calc(8px * var(--ui)); }
.speed label { font-size: calc(11.5px * var(--ui) * var(--ui-fs)); }
.speed input[type=range] { width: calc(110px * var(--ui)); }
.speed output { font-size: calc(11.5px * var(--ui) * var(--ui-fs)); min-width: calc(124px * var(--ui)); }
.seg { border-radius: calc(9px * var(--ui)); }
.seg button { padding: calc(6px * var(--ui)) calc(14px * var(--ui)); height: calc(29px * var(--ui)); font-size: calc(12.5px * var(--ui) * var(--ui-fs)); }

/* --- 视窗框标题 --- */
.pane { border-radius: calc(12px * var(--ui)); }
.pane .pane-h { height: calc(30px * var(--ui)); padding: 0 calc(10px * var(--ui)); border-radius: calc(11px * var(--ui)) calc(11px * var(--ui)) 0 0; }
.pane .pane-h span { font-size: calc(15px * var(--ui) * var(--ui-fs)); }
.pane .p-hint { left: calc(12px * var(--ui)); top: calc(38px * var(--ui)); font-size: calc(11px * var(--ui) * var(--ui-fs)); }

/* --- 综合视图子窗口 --- */
#comboUI .ccell { border-radius: calc(12px * var(--ui)); }
#comboUI .ccell-h { height: calc(30px * var(--ui)); padding: 0 calc(10px * var(--ui)); }
#comboUI .ccell-h span { font-size: calc(15px * var(--ui) * var(--ui-fs)); }
#comboUI .ccell-x { width: calc(22px * var(--ui)); height: calc(20px * var(--ui)); font-size: calc(13px * var(--ui) * var(--ui-fs)); border-radius: calc(6px * var(--ui)); }

/* --- 观测点数据面板 / 加载提示 --- */
#geoInfo {
  width: calc(344px * var(--ui)); max-width: calc(412px * var(--ui));
  padding: 0 calc(14px * var(--ui)) calc(10px * var(--ui));
  font-size: calc(12.5px * var(--ui) * var(--ui-fs));
  --pad-x: calc(14px * var(--ui)); --hx: calc(14px * var(--ui));
}
#geoInfo.gi-min { width: auto; }
#geoInfo .gi-body { padding-top: calc(8px * var(--ui)); }
#geoInfo .pi-k { min-width: calc(68px * var(--ui)); font-size: calc(11.5px * var(--ui) * var(--ui-fs)); }
#geoInfo .pi-big { font-size: calc(21px * var(--ui) * var(--ui-fs)); }
#geoInfo .pi-cap { font-size: calc(11px * var(--ui) * var(--ui-fs)); }
#loading { padding: calc(10px * var(--ui)) calc(18px * var(--ui)); border-radius: calc(12px * var(--ui)); font-size: calc(13px * var(--ui) * var(--ui-fs)); }

/* --- 窄屏：压缩标题栏，保证三个视图切换按钮始终可点 --- */
@media (max-width: 1150px) {
  #titleBar { padding: 0 calc(10px * var(--ui)); gap: calc(9px * var(--ui)); }
  #titleBar .title-views.seg button { padding: 0 calc(9px * var(--ui)); }
  .tb-text h1 { white-space: normal; line-height: 1.15; }
}
@media (max-width: 920px) {
  .title-badge { display: none; }
}

/* ---------- v4.1 菜单化显示设置：主面板只列一级菜单，内容在右侧浮层展开 ---------- */
#optsCard { overflow: visible; }
#optsCard.collapsed .opt-fly { display: none; }
#optsCard .card-body { border-radius: var(--r); }

/* 一级菜单行 */
.opt-menu { display: flex; flex-direction: column; gap: calc(3px * var(--ui)); }
.opt-row {
  display: flex; align-items: center; gap: calc(8px * var(--ui)); width: 100%;
  padding: calc(7px * var(--ui)) calc(9px * var(--ui));
  border: 1px solid var(--line); border-radius: calc(10px * var(--ui));
  background: linear-gradient(180deg, rgba(37,99,235,.06), rgba(37,99,235,.015));
  cursor: pointer; text-align: left; font-family: inherit; color: var(--ink);
}
.opt-row:hover { background: linear-gradient(180deg, rgba(37,99,235,.14), rgba(37,99,235,.05)); }
.opt-row.on { background: #fff; border-color: rgba(37,99,235,.45); box-shadow: inset 0 0 0 1px rgba(37,99,235,.22); }
.opt-ico { font-size: calc(14px * var(--ui) * var(--ui-fs)); line-height: 1; flex: none; font-style: normal; }
.opt-txt { display: flex; flex-direction: column; min-width: 0; flex: 1 1 auto; gap: 1px; }
.opt-t { font-size: calc(12.5px * var(--ui) * var(--ui-fs)); font-weight: var(--ui-fw-b, 700); color: var(--ink); white-space: nowrap; }
.opt-sub { font-size: calc(10px * var(--ui) * var(--ui-fs)); color: var(--ink-faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.opt-row .chev { margin-left: auto; flex: none; color: var(--ink-faint); font-size: calc(13px * var(--ui) * var(--ui-fs)); font-style: normal; transition: transform .15s ease; }
.opt-row.on .chev { transform: translateX(2px); color: var(--accent); }

/* 右侧浮层（一级内容 / 二级菜单列表）：高度继承主面板的 JS 夹取值（max-height: inherit），
   内部自行滚动；鼠标移出整个菜单范围后由 JS 自动收起 */
.opt-fly {
  display: none; position: absolute; left: calc(100% + 8px); top: 0;
  width: calc(272px * var(--ui)); max-height: inherit;
  background: rgba(255,255,255,.97); border: 1px solid var(--line); border-radius: calc(12px * var(--ui));
  box-shadow: 0 12px 32px rgba(2,6,23,.22); padding: calc(8px * var(--ui)) calc(10px * var(--ui)) calc(10px * var(--ui));
  overflow-y: auto; overflow-x: hidden; z-index: 30;
  touch-action: pan-y; overscroll-behavior: contain; -webkit-overflow-scrolling: touch;
  scrollbar-width: thin; scrollbar-color: rgba(100,116,139,.4) transparent;
}
.opt-fly.on { display: block; }
/* 菜单被拖到右半屏时，浮层改为向左展开 */
#optsCard.fly-left .opt-fly { left: auto; right: calc(8px + 100%); }
/* 浮层与菜单之间的透明"桥"：鼠标穿过间隙不触发 pointerleave 的收起计时 */
.opt-fly::before, .opt-fly::after { content: ""; position: absolute; top: 0; bottom: 0; width: 10px; }
.opt-fly::before { left: -10px; }
.opt-fly::after { right: -10px; }
#optsCard.fly-left .opt-fly::before { left: auto; right: -10px; }
#optsCard.fly-left .opt-fly::after { right: auto; left: -10px; }

.fly-head {
  font-size: calc(12px * var(--ui) * var(--ui-fs)); font-weight: var(--ui-fw-b, 700); color: var(--ink);
  padding: calc(2px * var(--ui)) calc(2px * var(--ui)) calc(7px * var(--ui));
  border-bottom: 1px dashed var(--line); margin-bottom: calc(6px * var(--ui));
  /* v20.0：标题行可能还带一个「分组开关」复选框（如「全局文字大小样式统一」），
     故改为 flex-start + gap 布局：开关靠左、标题占满剩余宽度、关闭按钮靠右。 */
  display: flex; align-items: center; gap: calc(7px * var(--ui));
}
.fly-head .fly-t { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fly-head .sw { flex: none; padding: 0; gap: calc(7px * var(--ui)); }
.fly-close {
  flex: none; margin-left: auto; width: calc(22px * var(--ui)); height: calc(22px * var(--ui));
  line-height: 1; font-size: calc(16px * var(--ui) * var(--ui-fs)); color: var(--ink-faint);
  background: transparent; border: 0; border-radius: 4px; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.fly-close:hover { background: rgba(100,116,139,.12); color: var(--ink); }
/* 分组分割线：总开关/地理事物 与 文字注释 之间 */
.section-sep {
  height: 1px; background: var(--line); margin: calc(8px * var(--ui)) 0;
  border: 0;
}
.opt-fly .opt-row { margin: calc(3px * var(--ui)) 0; background: rgba(15,23,42,.03); }
.opt-fly::-webkit-scrollbar { width: 8px; }
.opt-fly::-webkit-scrollbar-thumb { background: rgba(100,116,139,.35); border-radius: 4px; }
.opt-fly::-webkit-scrollbar-track { background: transparent; }

/* ---------- v4.3 统一三级菜单 ---------- */
/* 一级菜单行（.lv1）下方的二级容器：点击一级行后在其下方内联展开 */
.opt-sec .lv2-wrap { display: none; }
.opt-sec.open .lv2-wrap {
  display: flex; flex-direction: column; gap: calc(2px * var(--ui));
  margin: calc(3px * var(--ui)) 0 calc(5px * var(--ui)) calc(14px * var(--ui));
  padding: calc(3px * var(--ui)) 0 calc(3px * var(--ui)) calc(8px * var(--ui));
  border-left: 2px solid rgba(37, 99, 235, .30);
}
.lv1 .chev { transition: transform .18s ease; }
.opt-sec.open > .lv1 .chev { transform: rotate(90deg); color: var(--accent); }

/* 二级菜单行（紧凑样式，位于二级容器内） */
.lv2-row { padding: calc(5px * var(--ui)) calc(8px * var(--ui)); border-radius: calc(8px * var(--ui)); background: rgba(15, 23, 42, .03); }
.lv2-row .opt-t { font-size: calc(11.5px * var(--ui) * var(--ui-fs)); }
.lv2-row .chev { font-size: calc(11px * var(--ui) * var(--ui-fs)); }
.lv2-row:hover { background: rgba(37, 99, 235, .10); }
.lv2-row.on { background: #fff; border-color: rgba(37, 99, 235, .45); box-shadow: inset 0 0 0 1px rgba(37, 99, 235, .22); }
.fly-head { color: #1e3a8a; }
/* ===== v15.0：菜单 DOM 由 MENU 数据渲染；三级及以下统一用 .nd（可嵌套到任意层） =====
   只有存在子级的节点才渲染 .nd-h + 展开箭头 .ar；没有子级时直接渲染成一行控件。 */
.nd {
  border: 1px solid var(--line); border-radius: calc(9px * var(--ui));
  margin: calc(4px * var(--ui)) 0; background: rgba(15, 23, 42, .025); overflow: hidden;
}
.nd.d4 { margin-left: calc(7px * var(--ui)); background: rgba(15, 23, 42, .015); }
.nd.d5 { margin-left: calc(14px * var(--ui)); background: transparent; }
.nd-h {
  display: flex; align-items: center; width: 100%; gap: calc(6px * var(--ui));
  padding: calc(6px * var(--ui)) calc(9px * var(--ui)); cursor: pointer; user-select: none;
  font-family: inherit; font-size: calc(11.5px * var(--ui) * var(--ui-fs)); font-weight: var(--ui-fw-b, 700); color: var(--ink);
  text-align: left; background: transparent; border: 0;
}
.nd-h:hover { color: #1d4ed8; }
.nd-t { flex: 0 1 auto; }
.nd-h .ar {
  margin-left: auto; flex: none; font-style: normal; color: var(--ink-faint);
  font-size: calc(10px * var(--ui) * var(--ui-fs)); transition: transform .18s ease;
}
.nd.open > .nd-h .ar { transform: rotate(180deg); color: var(--accent); }
.nd-b {
  display: none; padding: calc(2px * var(--ui)) calc(9px * var(--ui)) calc(8px * var(--ui));
  background: #fff; border-top: 1px dashed var(--line);
}
.nd.open > .nd-b { display: block; }
/* 标题行内嵌的控件（如「类型」下拉）：隐藏重复标签、贴右显示 */
.nd-h .inline-ctl { margin-left: auto; padding: 0; gap: calc(5px * var(--ui)); border: 0; background: transparent; }
.nd-h .inline-ctl > label { display: none; }
.nd-h .inline-ctl select { flex: none; min-width: calc(66px * var(--ui)); }
.nd-h .inline-ctl + .ar { margin-left: calc(2px * var(--ui)); }
/* 开关关闭：子级整体收起并置灰（未勾选 -> 不纳入菜单） */
.nd.off > .nd-b { display: none !important; }
.nd.off > .nd-h { opacity: .5; }
.nd.off > .nd-h .ar { opacity: .5; }
/* v21.0（需求③）：被「上级开关」压住的注释节点 —— 置灰并收起子级，
   仍可点击（点它会自动把缺的上级开关一并打开），保证「先总开关、再地理事物、最后注释」
   这个顺序在界面上看得见、也不会出现「点了没反应」。 */
.nd.gated > .nd-b { display: none !important; }
.nd.gated > .nd-h { opacity: .42; }
.nd.gated > .nd-h .ar { opacity: .42; }
.sw.gated { opacity: .42; }
.sw.gated .sw-label { text-decoration: none; }
.raw-blk { margin: calc(3px * var(--ui)) 0; }
.menu-global { margin: calc(8px * var(--ui)) 0 calc(2px * var(--ui)); display: flex; justify-content: center; }
.menu-global .btn { width: 100%; }

/* =========================================================================
   v18.0
   ========================================================================= */

/* ---------- v18.0-①：菜单行高收紧 ----------
   放在文件末尾，靠层叠顺序覆盖上面的默认间距（同为后写者胜）；数值统一在原基础上收约 25%~35%，
   只动「外边距 / 内边距 / 行高 / 间隙」，不动字号与控件尺寸 —— 更紧凑，但不会挤成一片。 */
.row { gap: calc(7px * var(--ui)); padding: calc(2px * var(--ui)) 0; }
.row > label, .row > output { line-height: 1.2; }
.grp-tip { margin: calc(6px * var(--ui)) 0 0; line-height: 1.45; }
.btn-row { gap: calc(7px * var(--ui)); padding: calc(3px * var(--ui)) 0 0; }
.sw { gap: calc(7px * var(--ui)); padding: calc(2px * var(--ui)) 0; }
.sw-label { line-height: 1.2; }

/* 一级 / 二级菜单行 */
.opt-row { gap: calc(7px * var(--ui)); padding: calc(5px * var(--ui)) calc(9px * var(--ui)); }
.opt-txt { gap: 0; }
.opt-sec.open .lv2-wrap {
  gap: calc(1px * var(--ui));
  margin: calc(2px * var(--ui)) 0 calc(3px * var(--ui)) calc(13px * var(--ui));
  padding: calc(2px * var(--ui)) 0 calc(2px * var(--ui)) calc(8px * var(--ui));
}
.lv2-row { padding: calc(4px * var(--ui)) calc(8px * var(--ui)); }

/* 右侧二级内容窗口 / 三级分组 */
.fly-head { padding: calc(2px * var(--ui)) calc(2px * var(--ui)) calc(5px * var(--ui)); margin-bottom: calc(5px * var(--ui)); line-height: 1.2; }
.section-sep { margin: calc(6px * var(--ui)) 0; }.nd { margin: calc(3px * var(--ui)) 0; }.nd-h { padding: calc(4.5px * var(--ui)) calc(9px * var(--ui)); }.nd-b { padding: calc(2px * var(--ui)) calc(9px * var(--ui)) calc(5px * var(--ui)); }.nd-b > .row:first-child { padding-top: calc(3px * var(--ui)); }
.raw-blk { margin: calc(2px * var(--ui)) 0; }
.menu-global { margin: calc(6px * var(--ui)) 0 calc(1px * var(--ui)); }

/* ---------- v18.0-②：「添加点」窗口可拖动 ---------- */
.opt-fly.fly-drag .fly-head { cursor: move; }
.opt-fly.fly-drag .fly-head:active { cursor: grabbing; }
.opt-fly.fly-drag .fly-close { cursor: pointer; }
.opt-fly.dragging { z-index: 80; box-shadow: 0 18px 44px rgba(2, 6, 23, .30); }
.opt-fly.dragging, .opt-fly.dragging * { user-select: none; -webkit-user-select: none; }

/* =========================================================================
   v19.0
   ========================================================================= */

/* ---------- v19.0-①：制作者徽章移到标题右侧（版本号取消） ---------- */
.tb-line { display: flex; align-items: center; gap: calc(9px * var(--ui)); min-width: 0; }
.tb-by {
  flex: none; display: inline-flex; align-items: center; gap: calc(4px * var(--ui));
  padding: calc(3px * var(--ui)) calc(9px * var(--ui));
  border-radius: 999px;
  background: linear-gradient(135deg, #fff6cf 0%, #ffe2ef 52%, #dbeaff 100%);
  border: 1px solid rgba(37, 99, 235, .20);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .95), 0 2px 7px rgba(2, 6, 23, .07);
  font-size: calc(10.5px * var(--ui) * var(--ui-fs)); color: #7a4a86; font-weight: var(--ui-fw-m, 600);
  line-height: 1; white-space: nowrap; cursor: default; user-select: none;
}
.tb-by .eg { font-style: normal; font-size: calc(11px * var(--ui) * var(--ui-fs)); display: inline-block; }
.tb-by:hover .eg { animation: tbEgg .75s ease; }
@keyframes tbEgg {
  0%, 100% { transform: translateY(0) rotate(0); }
  30% { transform: translateY(calc(-2px * var(--ui))) rotate(-14deg); }
  65% { transform: translateY(calc(-1px * var(--ui))) rotate(11deg); }
}

/* ---------- v19.0-③：标题栏内的「沉浸模式」进入按钮 ----------
   位置：紧贴「自转演示」左侧、并留出一段距离。做法是把原来给 .title-views 的
   margin-left:auto 交给这个按钮，再由它的 margin-right 让出间隔。 */
#titleBar .title-views { margin-left: 0; }
.tb-immersive {
  flex: none; margin-left: auto; margin-right: calc(26px * var(--ui));
  height: calc(30px * var(--ui)); padding: 0 calc(12px * var(--ui));
  border-radius: calc(10px * var(--ui)); gap: calc(5px * var(--ui));
  font-size: calc(12px * var(--ui) * var(--ui-fs));
  color: #1e3a8a; border-color: rgba(37, 99, 235, .28);
  background: linear-gradient(135deg, #eef4ff, #e6feff);
}
.tb-immersive:hover { color: #fff; background: linear-gradient(135deg, #2563eb, #22d3ee); border-color: transparent; }
.tb-immersive svg { flex: none; }

/* ---------- v19.0-②：底部控制条收进一行 ----------
   根因：控制条用 left:50% + translateX(-50%) 居中，绝对定位下 width:auto 走
   shrink-to-fit，可用宽度只有 50vw，内容一超就换行。这里显式给 width:max-content，
   让它先按「一行」的自然宽度撑开，再由 max-width 在窄屏兜底回退成换行。
   顺带把「收起/展开」按钮从绝对定位改成行内最后一项 —— 一行布局下它原来会压住
   右侧的按钮。 */
#controlBar {
  width: max-content;
  gap: calc(10px * var(--ui)); row-gap: calc(7px * var(--ui));
  padding: calc(9px * var(--ui)) calc(13px * var(--ui));
}
#controlBar .cb-toggle, #controlBar.min .cb-toggle {
  position: static; order: 99; align-self: center;
  padding: calc(2px * var(--ui)) calc(10px * var(--ui));
}
.cb-group { gap: calc(7px * var(--ui)); }
.cb-sep { height: calc(22px * var(--ui)); }
.cb-cap { font-size: calc(11px * var(--ui) * var(--ui-fs)); }
#controlBar .btn { padding: calc(6px * var(--ui)) calc(11px * var(--ui)); font-size: calc(12px * var(--ui) * var(--ui-fs)); }
#controlBar .btn.play { min-width: calc(82px * var(--ui)); }
#controlBar .seg button { padding: calc(6px * var(--ui)) calc(11px * var(--ui)); font-size: calc(12px * var(--ui) * var(--ui-fs)); }
.speed { gap: calc(7px * var(--ui)); }
.speed input[type=range] { width: calc(96px * var(--ui)); }
.speed output { min-width: calc(104px * var(--ui)); white-space: nowrap; }

/* ---------- v19.0-③：沉浸模式 ---------- */
/* 进入沉浸：隐藏所有面板 / 标题栏 / 控制条 / 窗格表头与分隔条，只留 3D 画面。
   注意：窗格（#panes .pane）与综合视图单元格（#comboUI .ccell）本身是渲染
   视口的承载盒，不能 display:none，只收掉它们的表头与边框观感。 */
body.immersive #titleBar,
body.immersive #timeCard,
body.immersive #optsCard,
body.immersive #controlBar,
body.immersive #geoInfo { display: none !important; }

body.immersive #panes .pane-h,
body.immersive #panes .p-hint,
body.immersive #comboUI .ccell-h,
body.immersive #comboUI .cdiv,
body.immersive .splitter { display: none !important; }
body.immersive #panes .pane,
body.immersive #comboUI .ccell { border-color: transparent; background: none; box-shadow: none; }

/* 退出按钮：右上角，默认隐形；鼠标靠近右上角（body.imm-hot）或键盘聚焦时淡入 */
.imm-exit {
  position: fixed; z-index: 60; top: calc(10px * var(--ui)); right: calc(12px * var(--ui));
  display: none; align-items: center; gap: calc(6px * var(--ui));
  height: calc(34px * var(--ui)); padding: 0 calc(14px * var(--ui));
  border-radius: 999px; border: 1px solid rgba(255, 255, 255, .22);
  background: rgba(15, 23, 42, .62); color: #e2e8f0;
  font-family: inherit; font-size: calc(12px * var(--ui) * var(--ui-fs)); font-weight: var(--ui-fw-m, 600);
  cursor: pointer; white-space: nowrap;
  backdrop-filter: blur(10px) saturate(1.3); -webkit-backdrop-filter: blur(10px) saturate(1.3);
  box-shadow: 0 8px 24px rgba(2, 6, 23, .38);
  opacity: 0; transform: translateY(calc(-8px * var(--ui))); pointer-events: none;
  transition: opacity .22s ease, transform .22s ease, background .15s, color .15s;
}
body.immersive #btnExitImm { display: inline-flex; }
body.immersive.imm-hot #btnExitImm,
body.immersive #btnExitImm:focus-visible { opacity: 1; transform: none; pointer-events: auto; }
#btnExitImm:hover { background: rgba(220, 38, 38, .82); color: #fff; border-color: rgba(255, 255, 255, .38); }

/* 进入沉浸时的短暂提示（3.5s 后自行移除） */
.imm-toast {
  position: fixed; z-index: 70; left: 50%; top: calc(14px * var(--ui)); transform: translateX(-50%);
  padding: calc(7px * var(--ui)) calc(16px * var(--ui)); border-radius: 999px;
  background: rgba(15, 23, 42, .66); color: #e2e8f0; border: 1px solid rgba(255, 255, 255, .18);
  font-size: calc(12px * var(--ui) * var(--ui-fs)); white-space: nowrap; pointer-events: none;
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  animation: immToast 3.4s ease forwards;
}
@keyframes immToast {
  0% { opacity: 0; transform: translateX(-50%) translateY(calc(-8px * var(--ui))); }
  12%, 78% { opacity: 1; transform: translateX(-50%) translateY(0); }
  100% { opacity: 0; transform: translateX(-50%) translateY(calc(-6px * var(--ui))); }
}

/* 窄屏：沉浸按钮只留图标，标题栏更紧凑 */
@media (max-width: 1150px) {
  .tb-immersive { margin-right: calc(14px * var(--ui)); padding: 0 calc(9px * var(--ui)); }
  .tb-immersive .txi { display: none; }
}

/* =========================================================================
   v20.0
   ========================================================================= */

/* ---------- v20.0-㉔：面板折叠态优化 ----------
   问题：折叠后只剩一行表头，但卡片仍是原来的「宽矩形 + 大圆角 + 表头下边框」，
   看起来像一个空盒子，既不紧凑也不美观。
   方案：三种可折叠浮窗（显示设置 / 时间 / 观测点）折叠后统一成「胶囊」——
     · 宽度收缩到内容实际所需（auto），不再是原来的固定死宽；
     · 整体改为全圆角（999px），表头与卡片同形，去掉表头下边框；
     · 内边距归零、阴影减弱、描边收紧，悬浮感更轻；
     · 表头去掉上下内边距，让图标/标题/摘要/按钮在胶囊内垂直居中；
     · 悬停时表头泛起主题色，暗示「点一下可再次展开」。 */
#optsCard.collapsed,
#timeCard.min,
#geoInfo.gi-min {
  width: auto;
  padding: 0;
  border-radius: 999px;
  overflow: hidden;
  background: var(--panel-solid);
  box-shadow: 0 8px 22px rgba(2, 6, 23, .24), 0 1px 3px rgba(2, 6, 23, .16);
  --pad-x: 0px;
}
#optsCard.collapsed > .card-head,
#timeCard.min > .card-head,
#geoInfo.gi-min > .card-head {
  gap: calc(10px * var(--ui));
  padding-top: 0;
  padding-bottom: 0;
  border-radius: 999px;
  border-bottom: 0;
  background: linear-gradient(180deg, #ffffff, #f1f6ff);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .95);
  transition: background .18s ease;
}
#optsCard.collapsed > .card-head:hover,
#timeCard.min > .card-head:hover,
#geoInfo.gi-min > .card-head:hover {
  background:
    radial-gradient(150% 230% at 0% 0%, rgba(37, 99, 235, .20), rgba(37, 99, 235, 0) 64%),
    linear-gradient(180deg, #ffffff, #eaf2ff);
}
/* 折叠态里摘要是唯一有信息量的一行：不参与收缩，优先保留完整读数 */
#optsCard.collapsed > .card-head > output,
#timeCard.min > .card-head > output,
#geoInfo.gi-min > .card-head > output { flex: 0 0 auto; }
/* 折叠态统一：折叠按钮不再抢眼，改为中性描边（展开态才用主题色强调） */
#optsCard.collapsed > .card-head .link,
#timeCard.min > .card-head .link,
#geoInfo.gi-min > .card-head .link {
  background: rgba(15, 23, 42, .04);
  border-color: rgba(15, 23, 42, .16);
  color: var(--ink-dim);
}
#optsCard.collapsed > .card-head .link:hover,
#timeCard.min > .card-head .link:hover,
#geoInfo.gi-min > .card-head .link:hover {
  background: rgba(37, 99, 235, .14);
  border-color: rgba(37, 99, 235, .38);
  color: #1d4ed8;
}

/* ---------- v20.0-㉔（续）：底部控制条收起态同样收成胶囊 ---------- */
#controlBar.min {
  padding: calc(5px * var(--ui)) calc(13px * var(--ui));
  border-radius: 999px;
  box-shadow: 0 8px 22px rgba(2, 6, 23, .22), 0 1px 3px rgba(2, 6, 23, .14);
}
#controlBar.min .cb-toggle {
  padding: calc(3px * var(--ui)) calc(12px * var(--ui));
  color: var(--ink-dim);
}
#controlBar.min .cb-toggle:hover { color: #1d4ed8; }

/* ---------- v20.0-㉓：标题栏左侧地球徽标随视图高亮 ----------
   徽标是内联 SVG 地球图片；这里只补充「非自转」视图下的一点点视觉区分，
   不改动标题文字（删除了标题下的小字副标题）。 */
.title-badge[data-view="revolve"] { background: radial-gradient(circle at 34% 28%, #3a2a12, #1b1206 78%); }
.title-badge[data-view="combo"]   { background: radial-gradient(circle at 34% 28%, #2a1f45, #150f24 78%); }

/* =========================================================================
   v23.8：触摸屏 / 移动端适配
   -------------------------------------------------------------------------
   1) 页面本身禁止「回弹 / 下拉刷新」——手机上的橡皮筋会干扰拖动与双指捏合；
   2) 三枚浮窗的宽度上限锚定视口，任何缩放档位都不会溢出屏幕或被切边；
   3) 无悬停设备（手机 / 平板 / 触摸屏一体机）没有 hover 反馈，这里补上「按下态」、
      并把菜单行 / 开关行的最小点击高度抬到一个手指够得着的尺寸；
      滚动容器明确交给原生触摸滚动（画布的双指捏合不会把它们卷进去）。
   ========================================================================= */
html, body { overscroll-behavior: none; }
#optsCard, #timeCard, #geoInfo { max-width: calc(100vw - 24px * var(--ui)); }

@media (hover: none) {
  /* 点击热区：菜单行 / 开关行 / 一级行至少保留一指的高度（原值在 ui≈0.5 时只有 ~15px） */
  .opt-row, .lv2-row, .nd-h, .sw { min-height: calc(32px * var(--ui)); }
  /* 按下反馈：替代桌面端的 hover 高亮，避免「点了没反应」的误判 */
  .opt-row:active, .lv2-row:active, .nd-h:active { background: rgba(37, 99, 235, .22); }
  .btn:active, .seg button:active, .link:active { border-color: rgba(37, 99, 235, .55); color: #1d4ed8; }
  /* 浮窗 / 菜单 / 三级容器的滚动：交给原生惯性滚动，且不把滚动继续传给画布 */
  .card-body, .opt-fly, #timeCard {
    -webkit-overflow-scrolling: touch; overscroll-behavior: contain;
  }
  /* 表头是拖动把手：明确禁止在其上触发浏览器的滑动手势 */
  .card > .card-head { touch-action: none; }
}

