/* 学习路线（t-20261009-htuw route，替换时间轴）：S 形的关卡地图。
   t-20261026-wybz game：从顶栏的单元进度条长出来的轻量浮层（点进度条展开、再点 / Esc / 点外面收起），不替代计划窗口；左栏不再放路线。
   颜色只用设计语言里已有的：学完的关卡和它那段路是单元在知识地图里那一章的分支色（--br，同计划日程），
   正在学是「进行中」的浅蓝（--plan-current），外圈一道蓝弧是这一单元走到哪（同顶栏进度条）；没开始是灰的空心圈和虚线；
   勋章是路上的小圆章，落在它发生的时间位置，蓝绿是 T2、金是 T3；全部走完时终点的旗换成金奖杯。
   路上的一段 = 这个单元的学习分段，分段之间的停顿留一道小缝（learning-route.js pieceDashes）。 */

/* ---------- 浮层：从顶栏下沿拉下来的一张图，左右和正文栏对齐（两边各宽出 16px，被盖住的每一行整行盖住）；
   上沿紧贴顶栏（不留缝、不透出下面的正文），上沿是直的、下沿两个圆角，展开、收起只改它自己的高度（learning-route.js unroll）；
   手机上铺满整宽。下面一层很淡的纸色（roadmap-veil），正文退后一层；正对着浮层下沿垫一小段渐隐（roadmap-veil__edge，
   learning-route.js edgeVeil 摆位置），被下沿切开的那半行字在这里淡没，浮层自己的阴影照样画在它上面 ---------- */
.roadmap-veil { position: fixed; inset: 56px 0 0; z-index: calc(var(--z-menu) - 1); background: color-mix(in srgb, var(--canvas) 66%, transparent); }
.roadmap-veil[hidden] { display: none; }
.roadmap-veil__edge { position: absolute; top: 0; left: 0; height: 48px; pointer-events: none; background: linear-gradient(var(--canvas) 50%, color-mix(in srgb, var(--canvas) 0%, transparent)); }
.roadmap {
  --rm-top: 56px;
  position: fixed; top: var(--rm-top); z-index: var(--z-menu);
  display: flex; flex-direction: column; max-height: calc(100dvh - var(--rm-top) - 16px);
  border: 1px solid var(--border); border-top: 0; border-radius: 0 0 var(--r-md) var(--r-md); background: var(--surface); box-shadow: var(--shadow-modal);
  color: var(--ink);
}
.roadmap[hidden] { display: none; }
.roadmap.is-bleed { border-right: 0; border-left: 0; }
.roadmap:focus { outline: none; }
/* --rm-extra：浮层盖到学生气泡的右缘时，比正文那一栏多出来的那一截（learning-route.js place）；路线仍按正文那一栏排 */
.roadmap { --rm-extra: 0px; }
.rm-scroll { position: relative; min-height: 0; overflow-x: hidden; overflow-y: auto; padding: 4px calc(18px + var(--rm-extra)) 8px 18px; border-radius: inherit; overscroll-behavior: contain; }

/* ---------- 关卡圆圈 ---------- */
.lr-node {
  position: relative; z-index: 1; display: grid; flex: none; place-items: center; width: 22px; height: 22px; box-sizing: border-box;
  border: 2px solid var(--border-strong); border-radius: 50%; background: var(--surface); color: var(--faint);
  font-size: 11px; font-weight: 600; line-height: 1; font-variant-numeric: tabular-nums;
}
.lr-node svg { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 2.6; stroke-linecap: round; stroke-linejoin: round; }
.lr-stop.is-done .lr-node { border-color: var(--br); background: var(--br); color: var(--surface); }
.lr-stop.is-current .lr-node { border-color: var(--accent); background: var(--plan-current); color: var(--plan-current-ink); }
.lr-stop.is-skipped .lr-node { border-style: dashed; }
/* 学过没学完（开过头、不是当前单元）：分支色空心圈，序号也是分支色 */
.lr-stop.is-started .lr-node { border-color: var(--br); color: var(--br); }
/* 练习、模拟单元是圆角方块 */
.lr-stop.is-practice .lr-node { border-radius: 8px; }
.lr-stop.is-finish .lr-node { border: 0; background: none; color: var(--ink); }

/* ---------- S 形关卡地图 ---------- */
.lr-map { position: relative; width: 100%; }
.lr-map__path { position: absolute; top: 0; left: 0; display: block; overflow: visible; }
/* 路基是一条淡灰的宽路，学完的单元在上面画分支色的一截截，缝里露出路基 */
.lr-bed path { fill: none; stroke: var(--surface-subtle); stroke-width: 14; stroke-linecap: round; }
.lr-piece { fill: none; stroke: var(--br); stroke-width: 6; stroke-linecap: butt; }
.lr-ahead { fill: none; stroke: var(--border-strong); stroke-width: 2; stroke-dasharray: 2 7; stroke-linecap: round; }
.lr-passed { fill: none; stroke: var(--border-strong); stroke-width: 2; }
/* 关卡浮窗开着时，别的关卡、路和勋章退后一层，这一关自己和它路上的勋章照旧（learning-route.js focusLevel）：
   浮窗边上露出来的半截名字、半个圆圈也淡下去，不和浮窗抢 */
.lr-map > :is(.lr-map__path, .lr-stop, .rm-medal) { transition: opacity 140ms ease; }
.lr-map.has-pop > .lr-map__path { opacity: .4; }
.lr-map.has-pop > :is(.lr-stop, .rm-medal):not(.is-popped) { opacity: .28; }
.lr-stop {
  --br: var(--map-branch-1); --node: 34px; --label-w: 140px;
  position: absolute; display: flex; flex-direction: column; align-items: center; gap: 6px; width: var(--label-w);
  margin: calc(var(--node) / -2) 0 0 calc(var(--label-w) / -2); padding: 0; border: 0; background: none; color: var(--ink); font: inherit; text-align: center; cursor: pointer;
}
.lr-stop .lr-node { width: var(--node); height: var(--node); font-size: 13px; transition: transform var(--motion-t0) var(--ease-back); }
.lr-stop .lr-node svg { width: 18px; height: 18px; }
.lr-stop.is-current { --node: 40px; --up-p: 0; }
/* 正在学：外圈一道蓝弧是这一单元走到哪（--up-p，和顶栏进度条同一个数），看得到但不抢眼 */
.lr-stop.is-current .lr-node::before {
  content: ''; position: absolute; inset: -6px; border-radius: 50%;
  background: conic-gradient(var(--accent) calc(var(--up-p, 0) * 1turn), color-mix(in srgb, var(--accent) 14%, transparent) 0);
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 3px), #000 calc(100% - 2.5px));
  mask: radial-gradient(farthest-side, transparent calc(100% - 3px), #000 calc(100% - 2.5px));
}
.lr-stop.is-current.is-practice .lr-node::before { border-radius: 12px; }
.lr-stop:hover .lr-node { transform: scale(1.08); }
.lr-stop:active .lr-node { transform: scale(.94); }
.lr-stop:focus-visible { outline: none; }
.lr-stop:focus-visible .lr-node { outline: 2px solid var(--accent); outline-offset: 4px; }
.lr-stop.is-finish { cursor: default; }
.lr-stop.is-finish .lr-node svg { width: 24px; height: 24px; stroke-width: 2; }
/* 全部走完：终点是一只金奖杯 */
.lr-stop.is-finish.is-won .lr-node { border: 2px solid var(--reward-gold-deep); background: var(--reward-gold-soft); color: var(--reward-gold-deep); }
.lr-stop.is-finish.is-won .lr-node svg { width: 22px; height: 22px; }
.lr-trophy__cup { fill: var(--reward-gold); }
.lr-stop__label { display: grid; justify-items: center; gap: 2px; max-width: 100%; }
.lr-stop__title { display: -webkit-box; overflow: hidden; color: var(--ink); font-size: 13px; line-height: 1.4; overflow-wrap: anywhere; -webkit-box-orient: vertical; -webkit-line-clamp: 2; }
.lr-stop:is(.is-pending, .is-skipped) .lr-stop__title { color: var(--faint); }
.lr-stop.is-current .lr-stop__title { font-weight: 600; }
.lr-stop.is-finish .lr-stop__title { font-weight: 600; font-variant-numeric: tabular-nums; }
.lr-stop__meta { color: var(--faint); font-size: var(--fs-caption); line-height: 1.5; font-variant-numeric: tabular-nums; }

/* ---------- 路上的勋章：小圆章，悬停、聚焦或点一下（触屏）时上方出一行字；靠近两边时那行字往里挪（--tip-dx） ---------- */
.rm-medal {
  --tip-dx: 0px;
  position: absolute; z-index: 3; display: grid; place-items: center; width: 32px; height: 32px; margin: -18px 0 0 -16px; padding: 0;
  border: 0; border-radius: 50%; background: none; cursor: default;
}
.rm-medal .k-medal { --m-gap: var(--surface); width: 24px; height: 24px; transition: transform var(--motion-t0) var(--ease-back); }
.rm-medal.is-t3 { z-index: 4; }
.rm-medal.is-t3 .k-medal { width: 30px; height: 30px; }
/* 悬停只在真有指针悬停的设备上出（触屏点一下以后浏览器会把 :hover 一直留着，那行字就收不回去），触屏靠点一下的 .is-tipped */
@media (hover: hover) { .rm-medal:hover .k-medal { transform: scale(1.18); } }
.rm-medal:focus-visible .k-medal { transform: scale(1.18); }
.rm-medal:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.rm-medal__tip {
  position: absolute; bottom: calc(100% + 6px); left: 50%; padding: 3px 9px; border-radius: var(--r-pill);
  background: var(--ink); color: var(--canvas); font-size: var(--fs-caption); font-weight: 600; line-height: 1.4; white-space: nowrap;
  opacity: 0; visibility: hidden; pointer-events: none; transform: translate(calc(-50% + var(--tip-dx)), 3px);
  transition: opacity 120ms ease, transform 140ms ease, visibility 120ms;
}
.rm-medal:is(:focus-visible, .is-tipped) .rm-medal__tip { opacity: 1; visibility: visible; transform: translate(calc(-50% + var(--tip-dx)), 0); }
@media (hover: hover) { .rm-medal:hover .rm-medal__tip { opacity: 1; visibility: visible; transform: translate(calc(-50% + var(--tip-dx)), 0); } }
.rm-medal.is-tipped { z-index: 5; }
.rm-medal.is-tipped .k-medal { transform: scale(1.18); }

/* ---------- 关卡浮窗：知识地图节点浮窗（km-pop）的样子，行只读；叠在路线上，底色是实心纸面（不透出下面的路和勋章） ---------- */
.km-pop.lr-pop { z-index: calc(var(--z-menu) + 1); background: var(--surface); -webkit-backdrop-filter: none; backdrop-filter: none; }
.lr-pop__state { margin: 6px 0 0; color: var(--muted); font-size: var(--fs-caption); font-weight: 600; font-variant-numeric: tabular-nums; }
.lr-pop__state.is-current { justify-self: start; display: inline-block; padding: 0 8px; border-radius: var(--r-pill); background: var(--plan-current); color: var(--plan-current-ink); line-height: 20px; }
.lr-pop .lr-pop__row { cursor: default; }
.lr-pop .lr-pop__row:hover { background: none; color: var(--muted); }
/* 练过的题：一题一个小方格（同判分卡上那一排），对是绿、错是红框 */
.lr-pop__strip { gap: 3px; max-width: 100%; margin-top: 8px; }
.lr-pop__strip .ca-cell { width: 10px; height: 10px; border-radius: 2px; }
/* 进入这一关的单元：右下角一枚蓝色圆钮，「走进门」的箭头；浮窗里内容长、要滚动时它贴在浮窗底边，一直看得见 */
.lr-pop__go {
  position: sticky; bottom: 0; z-index: 1;
  display: grid; place-items: center; width: 40px; height: 40px; margin: 12px 0 0 auto; padding: 0;
  border: 0; border-radius: 50%; background: var(--accent); color: var(--on-accent); box-shadow: var(--shadow-pop); cursor: pointer;
  transition: background-color 120ms ease, scale var(--motion-t0) var(--ease-back);
}
.lr-pop__go svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; transition: transform 140ms ease; }
.lr-pop__go:hover { background: var(--accent-strong); box-shadow: 0 0 0 3px var(--surface), 0 0 0 5px var(--accent), var(--shadow-pop); }
.lr-pop__go:active { scale: .92; transition-duration: 80ms; }
.lr-pop__go:hover svg { transform: translateX(2px); }
.lr-pop__go:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
/* 悬停、聚焦：圆钮左边一行小提示（同顶栏进度条的单元名），字最后出现 */
.lr-pop__go-tip {
  position: absolute; right: calc(100% + 10px); top: 50%; padding: 4px 10px; border: 1px solid var(--border); border-radius: var(--r-sm);
  background: var(--surface); box-shadow: var(--shadow-pop); color: var(--ink); font-size: var(--fs-caption); font-weight: 600; line-height: 1.5; white-space: nowrap;
  opacity: 0; visibility: hidden; pointer-events: none; transform: translate(4px, -50%);
  transition: opacity 120ms ease, transform 140ms ease, visibility 120ms;
}
.lr-pop__go:is(:hover, :focus-visible) .lr-pop__go-tip { opacity: 1; visibility: visible; transform: translate(0, -50%); transition-delay: 200ms; }
/* 浮窗矮、要在里面滚动时，底边一小段渐隐，再往下浮窗的底边距是实心纸面（进入圆钮浮在这两层上面）：下沿不露出被切开的半行 */
.lr-pop .km-pop__scroll::after { content: ''; position: sticky; bottom: 0; display: block; height: 18px; margin-top: -18px; background: linear-gradient(color-mix(in srgb, var(--surface) 0%, transparent), var(--surface)); pointer-events: none; }
.lr-pop::after { content: ''; position: absolute; z-index: 0; left: 0; right: 0; bottom: 0; height: 18px; border-bottom-left-radius: inherit; border-bottom-right-radius: inherit; background: var(--surface); pointer-events: none; }
.lr-medals { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 4px 12px; margin: 0; padding: 0; list-style: none; }
.lr-medals__row { display: flex; align-items: center; gap: 8px; color: var(--ink); font-size: var(--fs-ui); line-height: 1.5; }
.lr-medals__row .k-medal { flex: none; width: 20px; height: 20px; }
/* 指针停上去看一眼：只有第几关、名字、状态和练过的题，窄一些，少挡路线；点一下钉住才展开勋章和知识点 */
.lr-pop:not(.is-pinned) { width: 280px; }
.lr-pop:not(.is-pinned) .km-pop__sec { display: none; }

@media (max-width: 559px) {
  .rm-scroll { padding: 2px calc(8px + var(--rm-extra)) 8px 8px; }
  .rm-medal { width: 26px; height: 26px; margin: -15px 0 0 -13px; }
  .rm-medal .k-medal { width: 21px; height: 21px; }
  .rm-medal.is-t3 .k-medal { width: 26px; height: 26px; }
}
@media (prefers-reduced-motion: reduce) { .lr-map > :is(.lr-map__path, .lr-stop, .rm-medal), .lr-stop .lr-node, .rm-medal .k-medal, .rm-medal__tip, .lr-pop__go, .lr-pop__go svg, .lr-pop__go-tip { transition: none; } }
