/* 轨道式学科选择器
 * 结构：舞台(.orbit-stage) → 轨道线 + 中央核心 + N 颗小球(.orbit-node) + 确认面板
 * 小球的位置只由一个变量 --ring（轨道当前角度）决定，JS 每帧更新它，CSS 负责摆位。
 * 每颗小球都会反向自转，所以图标和文字永远是正的。
 */

.orbit-stage {
  /* 轨道半径：手机上尽量放大，让中央的空心装得下确认面板（上限是小球外圈的装饰不出屏幕） */
  --orbit-radius: clamp(108px, calc(36vw - 8px), 200px);
  --node-size: clamp(54px, 14.5vw, 72px);      /* 小球直径 */
  --deco-size: calc(var(--node-size) * 1.8);   /* 小球外圈留的空间（标签、选中时的光晕与涟漪） */
  --motif-ink: #3e4b52;                        /* 球里科目图案的墨线，和网站图标同色（--logo-ink） */
  --motif-paper: #ffffff;
  --motif-spark: #e9cf63;                      /* 原子的电子 */
  --ring: 0;                                   /* 轨道角度，由 JS 每帧写入 */
  position: relative;
  width: 100%;
  max-width: 640px;
  margin: 14px auto 0;
  height: calc(var(--orbit-radius) * 2 + var(--deco-size) + 54px);
  -webkit-user-select: none;
  user-select: none;
  touch-action: manipulation;
}

/* ---------- 轨道线与中央核心 ---------- */
.orbit-track {
  position: absolute; left: 50%; top: 50%;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  pointer-events: none;
}
.orbit-track.outer {
  width: calc(var(--orbit-radius) * 2); height: calc(var(--orbit-radius) * 2);
  border: 1px dashed rgba(5, 150, 105, 0.22);
}
.orbit-track.inner {
  width: calc(var(--orbit-radius) * 0.96); height: calc(var(--orbit-radius) * 0.96);
  border: 1px solid rgba(2, 132, 199, 0.12);
}

.orbit-core {
  position: absolute; left: 50%; top: 50%;
  width: clamp(62px, 16vw, 82px); height: clamp(62px, 16vw, 82px);
  transform: translate(-50%, -50%);
  border-radius: 50%;
  display: grid; place-items: center;
  /* 单色纸面＋细墨线，和网站图标同一套；指到哪一科，外框与外圈就染成那一科的颜色（JS 写 --core-deep／--core-soft） */
  background: #fffdf8;
  border: 1.5px solid var(--core-deep, rgba(62, 75, 82, .8));
  box-shadow: 0 0 0 8px var(--core-soft, rgba(62, 75, 82, .06)), 0 14px 30px -14px rgba(15, 23, 42, .5);
  transition: box-shadow .55s ease, border-color .55s ease, opacity .35s ease, transform .55s cubic-bezier(.22, 1, .36, 1);
  pointer-events: none;
}
.orbit-core .brand-logo { width: 86%; height: 86%; }
.orbit-stage.has-selection .orbit-core { opacity: 0; transform: translate(-50%, -50%) scale(.72); }

/* ---------- 小球 ---------- */
.orbit-node {
  position: absolute; left: 50%; top: 50%;
  width: var(--node-size); height: var(--node-size);
  margin: calc(var(--node-size) / -2) 0 0 calc(var(--node-size) / -2);
  padding: 0; border: 0; background: none; cursor: pointer;
  /* 先转到自己的角度 → 往外推一个半径 → 再反向自转，让内容保持正立 */
  transform:
    rotate(calc((var(--base) + var(--ring)) * 1deg))
    translateY(calc(var(--orbit-radius) * -1))
    rotate(calc((var(--base) + var(--ring)) * -1deg));
  transition: opacity .45s ease;
  /* 注意：transform 不加 transition —— 它由 JS 每帧驱动，加了会打架 */
}
/* 其他球退後，但只淡化球体：标签整颗淡到 .3 会掉到 1.5:1，而它们仍然可以点 */
.orbit-stage.has-selection .orbit-node:not(.is-selected) .node-disc { opacity: .3; }
.orbit-node[aria-disabled="true"] { cursor: default; }
/* 还没有题的科目：球淡一点，还是点得到（点开会说明整理中）。有题的科目自然成为第一眼 */
.orbit-node.is-empty:not(.is-selected) .node-disc { opacity: .62; }
.orbit-node.is-empty:not(.is-selected):hover .node-disc,
.orbit-node.is-empty:not(.is-selected):focus-visible .node-disc { opacity: 1; }

.node-disc {
  position: relative;
  display: grid; place-items: center;
  width: 100%; height: 100%;
  border-radius: 50%;
  background: color-mix(in oklab, var(--accent-color) 9%, #fff);   /* 单色：一点点科目色 */
  border: 1.5px solid rgba(62, 75, 82, .55);
  box-shadow: 0 8px 20px -10px rgba(15, 23, 42, .45);
  transition: transform .5s cubic-bezier(.22, 1, .36, 1), box-shadow .4s ease, border-color .4s ease, opacity .45s ease;
}
.orbit-node:hover .node-disc,
.orbit-node:focus-visible .node-disc { transform: scale(1.09); border-color: var(--accent-color); }
.orbit-node.is-selected .node-disc {
  transform: scale(1.22);
  border-color: var(--accent-color);
  box-shadow: 0 0 0 7px var(--accent-soft), 0 14px 30px -12px var(--accent-color);
}

/* 选中时向外扩散的涟漪 */
.orbit-node.is-selected .node-disc::after {
  content: ''; position: absolute; inset: -5px;
  border-radius: 50%; border: 2px solid var(--accent-color);
  animation: nodeRipple 1.8s ease-out infinite;
}
@keyframes nodeRipple {
  0%   { transform: scale(1);    opacity: .5; }
  100% { transform: scale(1.62); opacity: 0; }
}

.node-glyph {
  width: 64%; height: 64%; display: block;
  --m-deep: color-mix(in oklab, var(--accent-color) 78%, #000);   /* 图案里的深科目色 */
  --m-soft: color-mix(in oklab, var(--accent-color) 28%, #fff);   /* 图案里的浅科目色（车身、矩形的填色） */
}
.node-glyph svg { width: 100%; height: 100%; display: block; overflow: visible; }

/* ---------- 球里的科目图案（js/orbit-subjects.js 的 MOTIFS） ----------
 * 平常静止；指到、键盘移到、选中时才动起来（选中时更快），减少动态时不动 */
.m-strand { fill: none; stroke-width: 2.6; stroke-linecap: round; }
.m-a { stroke: var(--m-deep); }
.m-b { stroke: var(--m-soft); }
.m-rung { fill: none; stroke: var(--motif-ink); stroke-width: 1.6; stroke-linecap: round; opacity: .5; transform-box: fill-box; transform-origin: center; }
.m-orbit { transform-box: view-box; transform-origin: 24px 24px; }
.m-orbit ellipse { fill: none; stroke: var(--accent-color); stroke-width: 1.8; }
.m-e { fill: var(--motif-spark); stroke: var(--motif-ink); stroke-width: 1; }
.m-nucleus { fill: var(--accent-color); stroke: var(--motif-ink); stroke-width: 1.2; }
.m-wire { fill: none; stroke: var(--motif-ink); stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; opacity: .7; }
.m-current { fill: none; stroke: var(--accent-color); stroke-width: 1.9; stroke-linecap: round; stroke-dasharray: 1.6 3.2; opacity: 0; transition: opacity .3s ease; }
.m-battery { fill: none; stroke: var(--motif-ink); stroke-width: 1.8; stroke-linecap: round; }
.m-lamp { fill: var(--motif-paper); stroke: var(--motif-ink); stroke-width: 1.4; transition: fill .3s ease; }
.m-lamp-x { fill: none; stroke: var(--motif-ink); stroke-width: 1.1; stroke-linecap: round; }
.m-force { fill: none; stroke: var(--m-deep); stroke-width: 2.1; stroke-linecap: round; stroke-linejoin: round; transform-box: fill-box; transform-origin: left center; }
.m-f { fill: var(--m-deep); font: italic 700 6.5px Georgia, "Times New Roman", serif; }
.m-body { fill: var(--m-soft); stroke: var(--motif-ink); stroke-width: 1.8; stroke-linejoin: round; }
.m-window { fill: var(--motif-paper); stroke: var(--motif-ink); stroke-width: 1.4; stroke-linejoin: round; }
.m-wheel { transform-box: fill-box; transform-origin: center; }
.m-wheel circle { fill: var(--motif-ink); }
.m-wheel .m-hub { fill: var(--motif-paper); }
.m-rect { fill: var(--m-soft); stroke: var(--motif-ink); stroke-width: 1.6; }
.m-grid { fill: none; stroke: var(--motif-ink); stroke-width: 1; opacity: .5; }
.m-spiral { fill: none; stroke: var(--m-deep); stroke-width: 2.4; stroke-linecap: round; stroke-dasharray: 1; }

@keyframes mTwist { 0%, 100% { transform: scaleX(1); } 50% { transform: scaleX(.12); } }
@keyframes mSpin { to { transform: rotate(360deg); } }
@keyframes mDrive { 0%, 100% { transform: translateX(-1.2px); } 50% { transform: translateX(1.6px); } }
@keyframes mFlow { to { stroke-dashoffset: -4.8; } }
@keyframes mPull { 0%, 100% { transform: scaleX(.78); } 50% { transform: scaleX(1.08); } }
@keyframes mDraw { 0% { stroke-dashoffset: 1; } 55%, 100% { stroke-dashoffset: 0; } }

.orbit-node:hover .m-rung, .orbit-node:focus-visible .m-rung, .orbit-node.is-selected .m-rung { animation: mTwist 1.4s ease-in-out infinite; }
.orbit-node .m-rung:nth-of-type(2n) { animation-delay: -.7s; }
.orbit-node:hover .m-o0, .orbit-node:focus-visible .m-o0, .orbit-node.is-selected .m-o0 { animation: mSpin 3.2s linear infinite; }
.orbit-node:hover .m-o1, .orbit-node:focus-visible .m-o1, .orbit-node.is-selected .m-o1 { animation: mSpin 4.4s linear infinite reverse; }
.orbit-node:hover .m-o2, .orbit-node:focus-visible .m-o2, .orbit-node.is-selected .m-o2 { animation: mSpin 5.6s linear infinite; }
.orbit-node:hover .m-car, .orbit-node:focus-visible .m-car, .orbit-node.is-selected .m-car { animation: mDrive .7s ease-in-out infinite; }
.orbit-node:hover .m-wheel, .orbit-node:focus-visible .m-wheel, .orbit-node.is-selected .m-wheel { animation: mSpin .6s linear infinite; }
.orbit-node:hover .m-current, .orbit-node:focus-visible .m-current, .orbit-node.is-selected .m-current { opacity: 1; animation: mFlow .8s linear infinite; }
.orbit-node:hover .m-lamp, .orbit-node:focus-visible .m-lamp, .orbit-node.is-selected .m-lamp { fill: var(--motif-spark); }
.orbit-node:hover .m-force, .orbit-node:focus-visible .m-force, .orbit-node.is-selected .m-force { animation: mPull .7s ease-in-out infinite; }
.orbit-node:hover .m-spiral, .orbit-node:focus-visible .m-spiral, .orbit-node.is-selected .m-spiral { animation: mDraw 2.4s cubic-bezier(.22, 1, .36, 1) infinite; }
/* 点下去（选中）：同样的动作快一倍，当作「点中了」的反馈 */
.orbit-node.is-selected .m-rung { animation-duration: .8s; }
.orbit-node.is-selected .m-o0 { animation-duration: 1.4s; }
.orbit-node.is-selected .m-o1 { animation-duration: 1.9s; }
.orbit-node.is-selected .m-o2 { animation-duration: 2.4s; }
.orbit-node.is-selected .m-car { animation-duration: .4s; }
.orbit-node.is-selected .m-wheel { animation-duration: .3s; }
.orbit-node.is-selected .m-current { animation-duration: .4s; }
.orbit-node.is-selected .m-force { animation-duration: .4s; }
.orbit-node.is-selected .m-spiral { animation-duration: 1.4s; }

/* 进度圆弧（每颗球随时显示已掌握比例） */
.node-arc { position: absolute; inset: -4px; width: calc(100% + 8px); height: calc(100% + 8px); transform: rotate(-90deg); }
.node-arc circle { fill: none; stroke-width: 3.5; stroke-linecap: round; }
.node-arc .arc-bg { stroke: rgba(15, 23, 42, .07); }
.node-arc .arc-fg {
  stroke: var(--accent-color);
  stroke-dasharray: 282.74;           /* 2πr，r=45 */
  stroke-dashoffset: 282.74;          /* 由 JS 按百分比设定 */
  transition: stroke-dashoffset .9s cubic-bezier(.22, 1, .36, 1);
}

/* 标签跟著轨道转，会转到飘动的青绿光团上：用 --text-muted（#475569）不算白光晕实测最低 4.16:1，调深一档 */
.node-label {
  position: absolute; top: calc(100% + 8px); left: 50%;
  transform: translateX(-50%);
  white-space: nowrap; text-align: center;
  font-size: 12px; font-weight: 700; color: #334155;
  z-index: 2;
  text-shadow: 0 0 5px #fff, 0 0 5px #fff, 0 1px 2px rgba(255, 255, 255, .95);
  transition: color .35s ease, top .35s ease;
}
/* 选中的球放大 1.22 倍并加一圈光晕，标签会压在光晕上（实测 2.5:1）。给它一块白底，底下是什么颜色都站得住 */
/* 字用科目色压深一档：生物 #059669、物理、数学的原色在白底上都不到 4.5:1（小字） */
.orbit-node.is-selected .node-label {
  color: var(--text-main, #0f172a); color: color-mix(in oklab, var(--accent-color) 70%, #000); top: calc(100% + 18px);
  padding: 4px 10px; border-radius: 999px;
  background: rgba(255, 255, 255, .92); box-shadow: 0 2px 8px -4px rgba(15, 23, 42, .25);
}
/* 不认 color-mix 的旧浏览器：含 var() 的宣告不会退回上一条（会变成没设），要在规则之後另外补（同 css/night.css 最後一段） */
@supports not (color: color-mix(in oklab, red 50%, blue)) {
  .orbit-node.is-selected .node-label { color: var(--text-main, #0f172a); }
}
/* 首页预览水彩时，底部的山丘在标签後面：实测 4.24:1，调深一档 */
.has-scene .node-label { color: #1e293b; }
.node-label em { display: block; font-style: normal; font-size: 11px; font-weight: 500; }

/* ---------- 中央确认面板 ---------- */
.orbit-panel {
  position: absolute; left: 50%; top: 50%;
  /* 宽度跟著轨道的空心走：伸出去就会盖住左右两颗球的标签 */
  width: min(236px, calc(var(--orbit-radius) * 2 - var(--node-size) - 18px));
  padding: 16px 16px 12px;
  border-radius: 18px;
  background: rgba(255, 255, 255, .97);
  border: 1px solid var(--card-border, rgba(226, 232, 240, .95));
  box-shadow: 0 20px 44px -18px rgba(15, 23, 42, .45);
  text-align: center;
  z-index: 5;
  opacity: 0; visibility: hidden; pointer-events: none;
  transform: translate(-50%, -44%) scale(.88);
  transition: opacity .3s ease, transform .45s cubic-bezier(.22, 1, .36, 1), visibility .3s;
}
.orbit-panel.is-open {
  opacity: 1; visibility: visible; pointer-events: auto;
  transform: translate(-50%, -50%) scale(1);
}
.panel-title { font-family: var(--font-display, serif); font-size: 16px; font-weight: 700; color: var(--text-main, #0f172a); }
.panel-sub { font-size: 12px; color: var(--text-muted, #64748b); margin-top: 2px; }
.panel-bar { height: 7px; border-radius: 99px; background: rgba(15, 23, 42, .08); overflow: hidden; margin: 12px 0 6px; }
.panel-bar i { display: block; height: 100%; width: 0; border-radius: 99px; background: var(--accent-color); transition: width .9s cubic-bezier(.22, 1, .36, 1); }
.panel-stat { font-size: 12px; color: var(--text-muted, #64748b); }
.panel-stat strong { color: var(--accent-color); font-size: 14px; }
.panel-enter {
  margin-top: 12px; width: 100%;
  padding: 8px 14px; border: 0; border-radius: 11px; cursor: pointer;
  font-size: 14px; font-weight: 700; color: #fff;
  background: var(--accent-color);
  box-shadow: 0 8px 18px -8px var(--accent-color);
  transition: transform .15s ease, filter .2s ease;
}
.panel-enter:hover { transform: translateY(-1px); filter: brightness(1.06); }
.panel-enter:active { transform: translateY(0); }
.panel-enter[disabled] { background: #cbd5e1; box-shadow: none; cursor: not-allowed; }
.panel-enter.is-quiet { background: transparent; color: #334155; box-shadow: inset 0 0 0 1px rgba(51,65,85,.35); }
.panel-hint { margin-top: 8px; font-size: 11px; color: var(--text-muted, #64748b); }

/* 手机的空心比较小：面板收紧，章节预览只留一行，
   「点其他地方取消」也省下来——轨道上方的说明已经写了这句 */
@media (max-width: 560px) {
  .orbit-panel { padding: 12px 12px 12px; }
  .panel-sub { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .panel-bar { margin: 8px 0 4px; }
  .panel-enter { margin-top: 8px; padding: 8px 12px; }
  .panel-hint { display: none; }
  /* 选中那颗球的标签会被面板压住一半；面板上已经写了科目名，让它淡出 */
  .orbit-stage.has-selection .orbit-node.is-selected .node-label { opacity: 0; transition: opacity .25s ease; }
}
/* 320px：空心只剩 162px 高，标题和进度一折行就会压到下面那颗球。字级降一档、章节预览省略 */
@media (max-width: 340px) {
  .panel-title { font-size: 14px; }
  .panel-sub { display: none; }
  .panel-stat { font-size: 11px; }
  .panel-stat strong { font-size: 13px; }
}

/* ---------- 无障碍：尊重「减少动态效果」 ---------- */
@media (prefers-reduced-motion: reduce) {
  .node-glyph *, .orbit-node.is-selected .node-disc::after { animation: none !important; }
  .node-disc, .orbit-panel, .node-arc .arc-fg, .panel-bar i { transition-duration: .01ms !important; }
}

/* 不认 color-mix 的旧浏览器：含 var() 的宣告会整个变成「没设」（图案会变全黑），这里补上不混色的版本 */
@supports not (color: color-mix(in oklab, red 50%, blue)) {
  .node-disc { background: #fff; }
  .node-glyph { --m-deep: var(--accent-color); --m-soft: var(--accent-soft); }
}
