/* learn.css — 学习页面共享样式：设计 tokens + 版式 + 图示 + 交互组件
   改风格只改 :root 的 tokens；页面自己的 CSS 只用这些 tokens。
   设计原则改编自 teaching-explainer (MIT, Rebecca Fordon) 与 visual-explainer (MIT, Nico Bailon)，见 THIRD-PARTY-NOTICES.md */

/* ---------- 0. 自带等宽字体：JetBrains Mono 5.3.0（可变字重，OFL 1.1，见 fonts/OFL.txt；来源 @fontsource-variable/jetbrains-mono）
   随 kit 分发，离线可用；不再依赖读者本机装了什么字体 ---------- */
@font-face {
  font-family: "LP Mono"; font-style: normal; font-display: swap; font-weight: 100 800;
  src: url(fonts/jetbrains-mono-latin-wght-normal.woff2) format("woff2-variations"), url(fonts/jetbrains-mono-latin-wght-normal.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "LP Mono"; font-style: normal; font-display: swap; font-weight: 100 800;
  src: url(fonts/jetbrains-mono-latin-ext-wght-normal.woff2) format("woff2-variations"), url(fonts/jetbrains-mono-latin-ext-wght-normal.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ---------- 1. Tokens（浅色） ---------- */
:root {
  color-scheme: light;
  /* 中性色只有一个色温（暖中性，R ≥ G > B）：底、线、次要文字同一家族，不混冷灰。数值由 scripts/tokens.mjs 校验 */
  --bg: #fbfaf8;
  --surface: #ffffff;
  --band: #f2f1ed;
  --text: #1a1917;          /* 15.5:1 以上 */
  --text-dim: #56524b;      /* ≥6.8:1 on bg/surface/band */
  --line: #e6e4de;          /* 仅装饰分隔线 */
  --line-strong: #807b73;   /* 有意义的轮廓，≥3.7:1 */
  --accent: var(--blue);    /* 默认 = blue；由 data-accent 覆盖 */
  --accent-ink: var(--blue-ink);
  --accent-tint: var(--blue-tint);
  --ok: #1b6e3a;   --ok-tint: #e6f3ea;
  --risk: #b42318; --risk-tint: #fbeae8;
  --warn: #8a5a00; --warn-tint: #faf1de;
  --focus: var(--accent);

  --f-sans: "Inter Variable", "PingFang SC", "Hiragino Sans GB", "Noto Sans CJK SC", "Noto Sans SC", "Source Han Sans SC", "Microsoft YaHei", system-ui, sans-serif;
  --f-serif: "Noto Serif CJK SC", "Noto Serif SC", "Source Han Serif SC", "Songti SC", "STSong", Georgia, serif;
  --f-mono: "LP Mono", "JetBrains Mono", "Cascadia Code", Consolas, "SF Mono", Menlo, "DejaVu Sans Mono", "Noto Sans Mono CJK SC", monospace;  /* 中文字符落到后面的 CJK 字体 */
  --f-display: var(--f-sans);

  --t-label: 13px; --t-small: 14px; --t-body: 17px; --t-h3: 20px; --t-h2: 27px; --t-h1: 40px;
  --s-1: 4px; --s-2: 8px; --s-3: 12px; --s-4: 16px; --s-5: 24px; --s-6: 32px; --s-7: 48px; --s-8: 72px;
  --r-1: 4px; --r-2: 8px;
  --measure: 40em;          /* 中文正文约 38–42 字/行 */
  --wide: 1120px;
  --fast: 120ms; --med: 220ms; --slow: 420ms; --ease: cubic-bezier(.2,.7,.2,1);
  --lift: 0 1px 2px rgb(0 0 0 / .06), 0 4px 12px rgb(0 0 0 / .06);
}


/* 色板：9 个色相。--X 画线条与色块（≥3:1），--X-ink 写文字（≥4.5:1，在 --bg、--surface、--X-tint 上都成立），
   --X-tint 作底色，--X-hi 是深色终端里的文字色（两种主题下相同）。浅/深两套均已验证。
   同一套色相有两种用法：data-accent（全页强调色，一页一个）与 data-c（概念色，正文 + 图 + 代码贯穿，一页 2–4 个）。 */
:root {
  --blue:#2f4fb0;   --blue-ink:#263f8f;   --blue-tint:#eaeefb;   --blue-hi:#b4c2ff;
  --sea:#0b6597;    --sea-ink:#09527a;    --sea-tint:#e3f1f9;    --sea-hi:#92d3f5;
  --teal:#0f6f68;   --teal-ink:#0b5550;   --teal-tint:#ddf1ee;   --teal-hi:#86e0d7;
  --forest:#2e6b3a; --forest-ink:#245530; --forest-tint:#e4f0e6; --forest-hi:#a6dfb1;
  --olive:#5c6510;  --olive-ink:#49500c;  --olive-tint:#eef0d8;  --olive-hi:#d5df95;
  --amber:#8a5300;  --amber-ink:#6e4200;  --amber-tint:#f8efdc;  --amber-hi:#f6ca7c;
  --copper:#9a4614; --copper-ink:#7c3810; --copper-tint:#f8e9df; --copper-hi:#f6b896;
  --plum:#7a3863;   --plum-ink:#632d51;   --plum-tint:#f5e6ef;   --plum-hi:#edc0dc;
  --slate:#475569;  --slate-ink:#334155;  --slate-tint:#eceff3;  --slate-hi:#c6cfdc;
}

/* ---------- 2. Tokens（深色）：跟随系统，或 data-theme 强制 ---------- */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --bg:#141413; --surface:#1c1c1a; --band:#191917; --text:#ebe9e4; --text-dim:#a9a59c;
    --line:#2d2c29; --line-strong:#77736b;
    --ok:#6fd394; --ok-tint:#16281d; --risk:#ff8a80; --risk-tint:#2d1716; --warn:#f0c060; --warn-tint:#2a2312;
    --lift: 0 1px 2px rgb(0 0 0 / .4), 0 4px 14px rgb(0 0 0 / .35);
    --blue:#93a7ff;   --blue-ink:#b4c2ff;   --blue-tint:#1d2340;
    --sea:#62bff0;    --sea-ink:#92d3f5;    --sea-tint:#13283a;
    --teal:#4fd1c5;   --teal-ink:#86e0d7;   --teal-tint:#10292a;
    --forest:#7fcf8f; --forest-ink:#a6dfb1; --forest-tint:#15281a;
    --olive:#c2cf6a;  --olive-ink:#d5df95;  --olive-tint:#24270f;
    --amber:#f0b44c;  --amber-ink:#f6ca7c;  --amber-tint:#2c2413;
    --copper:#f29a6b; --copper-ink:#f6b896; --copper-tint:#2e1c13;
    --plum:#e3a2cb;   --plum-ink:#edc0dc;   --plum-tint:#2c1a26;
    --slate:#a8b4c6;  --slate-ink:#c6cfdc;  --slate-tint:#1e232b;
  }
}
:root[data-theme="dark"] {
  color-scheme: dark;
  --bg:#141413; --surface:#1c1c1a; --band:#191917; --text:#ebe9e4; --text-dim:#a9a59c;
  --line:#2d2c29; --line-strong:#77736b;
  --ok:#6fd394; --ok-tint:#16281d; --risk:#ff8a80; --risk-tint:#2d1716; --warn:#f0c060; --warn-tint:#2a2312;
  --lift: 0 1px 2px rgb(0 0 0 / .4), 0 4px 14px rgb(0 0 0 / .35);
  --blue:#93a7ff;   --blue-ink:#b4c2ff;   --blue-tint:#1d2340;
  --sea:#62bff0;    --sea-ink:#92d3f5;    --sea-tint:#13283a;
  --teal:#4fd1c5;   --teal-ink:#86e0d7;   --teal-tint:#10292a;
  --forest:#7fcf8f; --forest-ink:#a6dfb1; --forest-tint:#15281a;
  --olive:#c2cf6a;  --olive-ink:#d5df95;  --olive-tint:#24270f;
  --amber:#f0b44c;  --amber-ink:#f6ca7c;  --amber-tint:#2c2413;
  --copper:#f29a6b; --copper-ink:#f6b896; --copper-tint:#2e1c13;
  --plum:#e3a2cb;   --plum-ink:#edc0dc;   --plum-tint:#2c1a26;
  --slate:#a8b4c6;  --slate-ink:#c6cfdc;  --slate-tint:#1e232b;
}

/* 全页强调色：<html data-accent="…">（学科默认值见 subjects.json）。只给交互与“此刻焦点”：按钮、当前步骤、链接、焦点框 */
[data-accent="blue"]   { --accent:var(--blue);   --accent-ink:var(--blue-ink);   --accent-tint:var(--blue-tint); }
[data-accent="sea"]    { --accent:var(--sea);    --accent-ink:var(--sea-ink);    --accent-tint:var(--sea-tint); }
[data-accent="teal"]   { --accent:var(--teal);   --accent-ink:var(--teal-ink);   --accent-tint:var(--teal-tint); }
[data-accent="forest"] { --accent:var(--forest); --accent-ink:var(--forest-ink); --accent-tint:var(--forest-tint); }
[data-accent="olive"]  { --accent:var(--olive);  --accent-ink:var(--olive-ink);  --accent-tint:var(--olive-tint); }
[data-accent="amber"]  { --accent:var(--amber);  --accent-ink:var(--amber-ink);  --accent-tint:var(--amber-tint); }
[data-accent="copper"] { --accent:var(--copper); --accent-ink:var(--copper-ink); --accent-tint:var(--copper-tint); }
[data-accent="plum"]   { --accent:var(--plum);   --accent-ink:var(--plum-ink);   --accent-tint:var(--plum-tint); }
[data-accent="slate"]  { --accent:var(--slate);  --accent-ink:var(--slate-ink);  --accent-tint:var(--slate-tint); }

/* 概念色：data-c="<色相>"。同一个概念（如“宿主机”）在正文、图、代码、终端里用同一个色相，让读者一眼对上号。 */
[data-c="blue"]   { --c:var(--blue);   --c-ink:var(--blue-ink);   --c-tint:var(--blue-tint);   --c-hi:var(--blue-hi); }
[data-c="sea"]    { --c:var(--sea);    --c-ink:var(--sea-ink);    --c-tint:var(--sea-tint);    --c-hi:var(--sea-hi); }
[data-c="teal"]   { --c:var(--teal);   --c-ink:var(--teal-ink);   --c-tint:var(--teal-tint);   --c-hi:var(--teal-hi); }
[data-c="forest"] { --c:var(--forest); --c-ink:var(--forest-ink); --c-tint:var(--forest-tint); --c-hi:var(--forest-hi); }
[data-c="olive"]  { --c:var(--olive);  --c-ink:var(--olive-ink);  --c-tint:var(--olive-tint);  --c-hi:var(--olive-hi); }
[data-c="amber"]  { --c:var(--amber);  --c-ink:var(--amber-ink);  --c-tint:var(--amber-tint);  --c-hi:var(--amber-hi); }
[data-c="copper"] { --c:var(--copper); --c-ink:var(--copper-ink); --c-tint:var(--copper-tint); --c-hi:var(--copper-hi); }
[data-c="plum"]   { --c:var(--plum);   --c-ink:var(--plum-ink);   --c-tint:var(--plum-tint);   --c-hi:var(--plum-hi); }
[data-c="slate"]  { --c:var(--slate);  --c-ink:var(--slate-ink);  --c-tint:var(--slate-tint);  --c-hi:var(--slate-hi); }

/* 版式风格（register）：paper = 概念/原理；blueprint = 系统/架构/协议 */
[data-register="paper"] { --f-display: var(--f-serif); }
[data-register="blueprint"] .lp-fig .lp-stage {
  --grid: color-mix(in srgb, var(--line) 70%, transparent);
  background-image: linear-gradient(var(--grid) 1px, transparent 1px), linear-gradient(90deg, var(--grid) 1px, transparent 1px);
  background-size: 24px 24px;
}

/* ---------- 3. 基础版式 ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0; background: var(--bg); color: var(--text);
  font: var(--t-body)/1.75 var(--f-sans); font-kerning: normal;
  text-rendering: optimizeLegibility;
}
a { color: var(--accent-ink); text-underline-offset: 3px; }
:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; border-radius: 2px; }
img, svg, canvas { max-width: 100%; }
code, kbd, samp { font-family: var(--f-mono); font-size: .9em; }
:not(pre) > code { background: var(--band); border: 1px solid var(--line); border-radius: var(--r-1); padding: 0 .3em; overflow-wrap: anywhere; }
pre { font: var(--t-small)/1.6 var(--f-mono); background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-2); padding: var(--s-4); overflow-x: auto; }

.lp-wrap { max-width: var(--wide); margin: 0 auto; padding: 0 var(--s-4); }
@media (min-width: 720px) { .lp-wrap { padding: 0 var(--s-6); } }

.lp-top { display: flex; align-items: center; gap: var(--s-4); justify-content: space-between; padding: var(--s-4) 0; font-size: var(--t-small); color: var(--text-dim); }
.lp-top a { color: var(--text-dim); text-decoration: none; }
.lp-top a:hover { color: var(--text); }
.lp-theme { font: inherit; color: var(--text-dim); background: none; border: 1px solid var(--line); border-radius: var(--r-1); padding: var(--s-1) var(--s-3); cursor: pointer; min-height: 32px; }

.lp-hero { padding: var(--s-7) 0 var(--s-6); border-bottom: 1px solid var(--line); }
.lp-kicker { font-size: var(--t-small); font-weight: 500; letter-spacing: .02em; color: var(--text-dim); margin: 0 0 var(--s-3); }
h1, h2, h3 { font-family: var(--f-display); line-height: 1.35; letter-spacing: 0; margin: 0; text-wrap: balance; }
h1 { font-size: clamp(30px, 5vw, var(--t-h1)); font-weight: 600; max-width: 22em; }
h2 { font-size: clamp(22px, 3.2vw, var(--t-h2)); font-weight: 600; margin: 0 0 var(--s-4); }
h3 { font-size: var(--t-h3); font-weight: 600; margin: var(--s-6) 0 var(--s-3); }
.lp-lede { font-size: 19px; color: var(--text-dim); max-width: var(--measure); margin: var(--s-4) 0 0; }
.lp-meta { font-size: var(--t-small); color: var(--text-dim); margin-top: var(--s-4); }

main > section { padding: var(--s-8) 0 0; scroll-margin-top: 56px; }
main > section:last-child { padding-bottom: var(--s-8); }
.lp-sec-label { font-size: var(--t-label); font-weight: 500; color: var(--text-dim); letter-spacing: .02em; margin: 0 0 var(--s-2); }
/* 小节编号：编号本身就是标记（不再加竖条、色块）。和目录同一套计数，读者在目录和正文之间对得上 */
main { counter-reset: lp-sec; }
main > section:has(> h2) { counter-increment: lp-sec; }
.lp-sec-label::before { content: counter(lp-sec, decimal-leading-zero); font: 500 var(--t-label)/1 var(--f-mono); font-variant-numeric: tabular-nums; color: var(--text); margin-right: .75em; }
.lp-prose, main > section > p, main > section > ul, main > section > ol { max-width: var(--measure); }
p { margin: 0 0 var(--s-4); }
li { margin: var(--s-1) 0; }
strong { font-weight: 600; }
.lp-band { background: var(--band); margin: var(--s-8) calc(50% - 50vw) 0; padding: var(--s-1) calc(50vw - 50%) var(--s-8); }

/* 目录（4 节以上才用）*/
.lp-toc { position: sticky; top: 0; z-index: 5; background: var(--bg); border-bottom: 1px solid var(--line); }
.lp-toc ol { list-style: none; display: flex; gap: var(--s-5); margin: 0 auto; padding: var(--s-1) var(--s-4); max-width: var(--wide); overflow-x: auto; scrollbar-width: none; counter-reset: toc; }
.lp-toc li { margin: 0; white-space: nowrap; font-size: var(--t-small); counter-increment: toc; }
.lp-toc a { display: inline-flex; align-items: center; min-height: 32px; color: var(--text-dim); text-decoration: none; }  /* 点击目标 ≥24px（WCAG 2.5.8） */
.lp-toc a::before { content: counter(toc, decimal-leading-zero); margin-right: .6em; font-family: var(--f-mono); font-size: var(--t-label); font-variant-numeric: tabular-nums; opacity: .7; }
.lp-toc a[aria-current="true"] { color: var(--accent-ink); font-weight: 600; }
@media (min-width: 720px) { .lp-toc ol { padding-inline: var(--s-6); } }  /* 目录条与正文左边缘对齐 */

/* 提示框、芯片、深入阅读 */
.lp-chip { display: inline-flex; align-items: center; gap: var(--s-1); font: 600 var(--t-label)/1.4 var(--f-sans); padding: 2px var(--s-2); border-radius: var(--r-1); background: var(--accent-tint); color: var(--accent-ink); }
.lp-chip[data-st="ok"] { background: var(--ok-tint); color: var(--ok); }
.lp-chip[data-st="risk"] { background: var(--risk-tint); color: var(--risk); }
.lp-chip[data-st="warn"] { background: var(--warn-tint); color: var(--warn); }
.lp-note { max-width: var(--measure); background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-2); padding: var(--s-4); margin: var(--s-5) 0; }
.lp-note > .lp-chip:first-child { margin-bottom: var(--s-2); }
.lp-note p:last-child { margin-bottom: 0; }
details.lp-deep { max-width: var(--measure); border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); padding: var(--s-3) 0; margin: var(--s-5) 0; }
details.lp-deep summary { cursor: pointer; font-weight: 600; color: var(--text); }
details.lp-deep[open] summary { margin-bottom: var(--s-3); }
.lp-remember { max-width: var(--measure); padding-left: 1.4em; }
.lp-remember li { margin: var(--s-2) 0; }
.lp-sources { font-size: var(--t-small); color: var(--text-dim); }
.lp-sources li { overflow-wrap: anywhere; }

/* 关联高亮：正文术语 ↔ 图中元素 */
[data-ref]:not(svg *) { cursor: help; }
span[data-ref] { border-bottom: 1.5px dashed var(--c, var(--accent)); }
span[data-ref].is-lit { background: var(--c-tint, var(--accent-tint)); }

/* 概念色在正文里：<span data-c="blue">宿主机</span>、<code data-c="blue">8080</code>。
   颜色只是“对上号”的提示，文字本身必须说清是什么（不只靠颜色）。 */
:is(span, b, strong, em, dfn)[data-c] { color: var(--c-ink); font-weight: 600; font-style: normal; }
:not(pre) > code[data-c] { color: var(--c-ink); background: var(--c-tint); border-color: color-mix(in srgb, var(--c) 35%, transparent); }
mark { background: var(--warn-tint); color: inherit; padding: 0 .15em; border-radius: 2px; }
mark[data-c] { background: var(--c-tint); color: var(--c-ink); font-weight: 600; }
/* 图例：本页用到的概念色，放在首屏图下或第一次用色之前 */
.lp-legend { display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-5); list-style: none; padding: 0; margin: var(--s-3) 0 0; font-size: var(--t-small); color: var(--text-dim); }
.lp-legend li { margin: 0; display: inline-flex; align-items: center; gap: var(--s-2); }
.lp-legend li[data-c]::before { content: ""; flex: none; width: 12px; height: 12px; border-radius: 3px; background: var(--c-tint); border: 2px solid var(--c); }
.lp-legend li b { color: var(--c-ink, var(--text)); font-weight: 600; }

/* 旁注：放在它所注释的段落之前。宽屏浮到右侧边栏，窄屏变成正文里的小注 */
.lp-side { max-width: var(--measure); margin: var(--s-4) 0; padding: var(--s-2) 0 0; border-top: 2px solid var(--c, var(--line-strong)); font-size: var(--t-small); line-height: 1.65; color: var(--text-dim); }
.lp-side > b:first-child, .lp-side > strong:first-child { display: block; color: var(--c-ink, var(--text)); margin-bottom: var(--s-1); }
.lp-side p { margin: 0 0 var(--s-2); }
.lp-side > :last-child { margin-bottom: 0; }
.lp-side .lp-fig { margin: var(--s-3) 0 0; }
@media (min-width: 1100px) {
  main > section > .lp-side, .lp-hero .lp-side { float: right; clear: right; width: 17.5em; margin: var(--s-1) 0 var(--s-5) var(--s-6); }
  main > section > :is(.lp-fig, .lp-term, pre, table, .lp-split, .lp-wide-block, h2, .lp-sec-label) { clear: right; }
}

/* 终端记录。data-title 写“在哪台机器、哪个 shell 运行”；data-untested 标出未实测 */
.lp-term { font: var(--t-small)/1.65 var(--f-mono); background: #15171b; color: #e8eaee; border-radius: var(--r-2); padding: var(--s-4); overflow-x: auto; margin: var(--s-5) 0; max-width: 100%; }
.lp-term[data-title]::before { content: attr(data-title); display: block; margin: calc(-1 * var(--s-2)) 0 var(--s-3); padding-bottom: var(--s-2); border-bottom: 1px solid #2c3038; color: #a3abb7; font: 600 var(--t-label)/1.4 var(--f-sans); letter-spacing: .02em; white-space: normal; }
.lp-term[data-title][data-untested]::before { content: attr(data-title) "  ·  未实测：只列命令，预期结果见正文"; }
.lp-term .p { color: #e8eaee; }            /* 命令行 */
.lp-term .p::before { content: "$ "; color: #9bd18f; }
.lp-term .p.root::before { content: "# "; color: #ff9e8f; }
.lp-term .o { color: #bfc5ce; }             /* 输出 */
.lp-term .c { color: #8b939e; }             /* 注释 */
.lp-term .f { color: #a9b1bd; }             /* 选项 -p --rm（弱化，让值更醒目） */
.lp-term mark { background: none; color: #ffd479; font-weight: 600; padding: 0; }
.lp-term [data-c] { color: var(--c-hi); background: none; border: 0; padding: 0; font-weight: 600; }
.lp-term > div { white-space: pre; }

/* 表格：默认就是干净的数据表 */
main table { border-collapse: collapse; width: 100%; font-size: var(--t-small); margin: var(--s-5) 0; font-variant-numeric: tabular-nums; }
main th, main td { text-align: left; vertical-align: top; padding: var(--s-2) var(--s-3); border-bottom: 1px solid var(--line); }
main thead th { font-weight: 600; color: var(--text-dim); border-bottom: 1.5px solid var(--line-strong); }
main caption { caption-side: top; text-align: left; font-size: var(--t-small); color: var(--text-dim); margin-bottom: var(--s-2); }
.lp-table-scroll { overflow-x: auto; max-width: 100%; }

/* 学习目标：首屏图之后，两栏紧凑排列 */
.lp-goals-label { font-size: var(--t-label); font-weight: 600; letter-spacing: .06em; color: var(--text-dim); margin: var(--s-6) 0 var(--s-2); }
.lp-goals { list-style: none; padding: 0; margin: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 19em), 1fr)); gap: var(--s-2) var(--s-6); }
.lp-goals li { margin: 0; padding-left: 1.1em; position: relative; }
.lp-goals li::before { content: ""; position: absolute; left: 0; top: .82em; width: .55em; height: 2px; background: var(--line-strong); }

/* 大号展示行：一条命令、一个公式、一个关键式子，各部分可用 data-c 上色 */
.lp-display { font: 600 clamp(18px, 2.6vw, 25px)/1.5 var(--f-mono); margin: 0 0 var(--s-3); white-space: nowrap; overflow-x: auto; color: var(--text); }
.lp-display .f { color: var(--text-dim); font-weight: 500; }

/* 小型多图：同一张小图画 N 次，只变差异处 */
.lp-multiples { display: grid; gap: var(--s-4); grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr)); }
.lp-multiples > * { min-width: 0; }
.lp-multiples h4 { font: 600 var(--t-small)/1.4 var(--f-sans); margin: 0 0 var(--s-2); }

/* 宽屏与窄屏各画一份图（横向版 / 纵向版），用这两个类切换 */
@media (max-width: 719.98px) { .lp-only-wide { display: none !important; } }
@media (min-width: 720px) { .lp-only-narrow { display: none !important; } }

/* 双栏：图 + 文字 */
.lp-split { display: grid; gap: var(--s-6); align-items: start; }
.lp-split > * { min-width: 0; }
@media (min-width: 900px) { .lp-split { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); } }

/* ---------- 4. 图示 figure ---------- */
.lp-fig { margin: var(--s-6) 0; }
.lp-fig .lp-stage { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-2); padding: var(--s-4); }
@media (max-width: 719px) { .lp-fig .lp-stage { padding: var(--s-3) var(--s-2); } }  /* 手机上给图让出宽度，图内字号不低于 11px */
.lp-fig .lp-stage:has(> svg.lp-wide) { overflow-x: auto; overscroll-behavior-x: contain; }
.lp-fig svg.lp-wide { min-width: 620px; }  /* 宽图在手机上保持可读字号，舞台内横向滚动 */
.lp-fig figcaption { font-size: var(--t-small); color: var(--text-dim); margin-top: var(--s-3); max-width: var(--measure); }
.lp-fig figcaption b { color: var(--text); font-weight: 600; }
.lp-fig svg { display: block; width: 100%; height: auto; overflow: visible; }
.lp-fig svg text { font-family: var(--f-sans); font-size: 15px; fill: var(--text); }
/* 图组高亮的描边不能继承到文字，否则字形会糊在一起。 */
.lp-fig svg text, .lp-fig svg tspan { stroke: none; }
.lp-fig svg .sub { font-size: 13px; fill: var(--text-dim); }
.lp-fig svg .mono { font-family: var(--f-mono); font-size: 14px; }
.lp-fig svg .lp-box { fill: var(--surface); stroke: var(--line-strong); stroke-width: 1.5; }
.lp-fig svg .lp-life { stroke: var(--line-strong); stroke-width: 1; stroke-dasharray: 3 4; }
.lp-fig svg .lp-edge { fill: none; stroke: var(--text-dim); stroke-width: 1.75; marker-end: url(#lp-arrow); }
.lp-fig svg .lp-edge.async { stroke-dasharray: 6 5; }
.lp-fig svg .lp-bnd { fill: none; stroke: var(--line-strong); stroke-dasharray: 5 4; }
.lp-fig svg .lp-state { fill: var(--band); stroke: var(--line-strong); }
.lp-fig svg .is-key, .lp-fig svg .is-now.lp-edge { stroke: var(--accent); stroke-width: 2.75; marker-end: url(#lp-arrow-accent); }
.lp-fig svg .lp-box.is-key, .lp-fig svg .lp-state.is-now { stroke: var(--accent); stroke-width: 2.5; fill: var(--accent-tint); }
.lp-fig svg text.is-now, .lp-fig svg .is-now text { fill: var(--accent-ink); font-weight: 600; }
.lp-fig svg .lp-tok { fill: var(--accent); }
.lp-fig svg .is-lit:not(text, tspan) { stroke: var(--accent) !important; }
.lp-fig svg text.is-lit, .lp-fig svg tspan.is-lit { fill: var(--accent-ink); stroke: none !important; font-weight: 600; }
.lp-fig svg .ok { stroke: var(--ok); } .lp-fig svg .risk { stroke: var(--risk); }
.lp-fig svg text.ok { fill: var(--ok); stroke: none; } .lp-fig svg text.risk { fill: var(--risk); stroke: none; }
/* 概念色在图里：给形状、区域、连线、文字加 data-c，和正文里同一概念用同一色相 */
.lp-fig svg .lp-box[data-c], .lp-fig svg [data-c] > .lp-box { stroke: var(--c); fill: var(--c-tint); }
.lp-fig svg .lp-bnd[data-c], .lp-fig svg [data-c] > .lp-bnd { stroke: var(--c); stroke-width: 1.5; fill: color-mix(in srgb, var(--c-tint) 55%, transparent); }
.lp-fig svg .lp-edge[data-c] { stroke: var(--c); marker-end: url(#lp-arrow-ctx); }
.lp-fig svg text[data-c], .lp-fig svg tspan[data-c], .lp-fig svg [data-c] > text { fill: var(--c-ink); }
.lp-fig svg .lp-dot[data-c] { fill: var(--c); }
/* 区域标签页：<g class="lp-tab" data-c="blue" transform="translate(x y)"><rect width="72" height="24" rx="4"/><text x="10" y="17">宿主机</text></g> */
.lp-fig svg .lp-tab > rect { fill: var(--c, var(--text-dim)); }
.lp-fig svg .lp-tab[data-c] > text, .lp-fig svg .lp-tab > text { fill: var(--surface); font-size: 13px; font-weight: 600; }
/* 端口/接口小芯片：放在区域边框上，像墙上的一扇门 */
.lp-fig svg .lp-port > rect { fill: var(--surface); stroke: var(--c, var(--line-strong)); stroke-width: 2; }
.lp-fig svg .lp-port > text { font-family: var(--f-mono); font-size: 14px; font-weight: 600; fill: var(--c-ink, var(--text)); text-anchor: middle; dominant-baseline: central; }
/* 数据包标签：一张小卡片写出包头里的关键字段 */
.lp-fig svg .lp-pkt > rect { fill: var(--surface); stroke: var(--text-dim); stroke-width: 1.25; }
.lp-fig svg .lp-pkt text { font-family: var(--f-mono); font-size: 13px; }
.lp-fig svg .lp-pkt .k { fill: var(--text-dim); }
.lp-fig svg .is-lit[data-c]:not(text, tspan) { stroke: var(--c) !important; stroke-width: 2.75; }
/* 编号标注 ① ② */
.lp-fig svg .lp-co circle { fill: var(--text); }
.lp-fig svg .lp-co text { fill: var(--bg); font-size: 12px; font-weight: 600; text-anchor: middle; dominant-baseline: central; }
/* 尺寸线 */
.lp-fig svg .lp-dim path { stroke: var(--text-dim); stroke-width: 1; fill: none; }
.lp-fig svg .lp-dim text { font-size: 13px; fill: var(--text-dim); text-anchor: middle; }

/* 分步播放器（data-lp="steps"） */
.lp-ready[data-lp="steps"] [data-s] { transition: opacity var(--med) var(--ease); }
.lp-ready[data-lp="steps"] [data-s].is-off { opacity: 0; pointer-events: none; }
.lp-ready[data-lp="steps"] [data-s].is-past:not(.lp-at) { opacity: .55; }
.lp-ready[data-lp="steps"] .lp-tok[data-s]:not(.is-now) { opacity: 0; }
.lp-cap { list-style: none; padding: 0; margin: var(--s-3) 0 0; max-width: var(--measure); }
.lp-cap li { margin: 0; }
.lp-ready .lp-cap li:not(.is-now) { display: none; }
.lp-cap .lp-ask { display: block; margin-top: var(--s-2); color: var(--accent-ink); font-weight: 600; }
.lp-player { display: flex; align-items: center; flex-wrap: wrap; gap: var(--s-2); margin-top: var(--s-3); }
.lp-player input[type=range] { flex: 1 1 160px; accent-color: var(--accent); min-height: 32px; }
.lp-count { font: var(--t-small)/1 var(--f-mono); color: var(--text-dim); font-variant-numeric: tabular-nums; min-width: 4.5em; text-align: right; }

/* 交互图（live figure）控件 */
.lp-controls { display: flex; flex-wrap: wrap; gap: var(--s-4) var(--s-6); margin: var(--s-4) 0; font-size: var(--t-small); }
.lp-controls label { display: grid; gap: var(--s-1); min-width: 200px; }
.lp-controls input[type=range] { accent-color: var(--accent); }
.lp-out { font-variant-numeric: tabular-nums; font-family: var(--f-mono); color: var(--accent-ink); font-weight: 600; }

/* 3D / canvas 容器 */
.lp-canvas { position: relative; aspect-ratio: 16 / 9; background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-2); overflow: hidden; }
.lp-canvas canvas { display: block; width: 100% !important; height: 100% !important; }
.lp-canvas .lp-reset { position: absolute; right: var(--s-3); top: var(--s-3); }

/* ---------- 5. 按钮 ---------- */
.lp-btn { font: 600 var(--t-small)/1.2 var(--f-sans); min-height: 40px; min-width: 40px; padding: var(--s-2) var(--s-4); border-radius: var(--r-1); cursor: pointer;
  border: 1.5px solid var(--accent); background: var(--accent); color: var(--bg); transition: filter var(--fast); }
.lp-btn:hover { filter: brightness(1.08); }
.lp-btn.ghost { background: transparent; color: var(--accent-ink); border-color: var(--line-strong); }
.lp-btn[disabled] { opacity: .45; cursor: not-allowed; filter: none; }

/* ---------- 6. 练习组件（共用外壳）---------- */
.lp-task { max-width: var(--measure); background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-2); padding: var(--s-5); margin: var(--s-6) 0; }
.lp-task-kind { display: block; font: 500 var(--t-label)/1.4 var(--f-sans); color: var(--text-dim); letter-spacing: .02em; margin-bottom: var(--s-2); }
.lp-q { font-weight: 600; margin: 0 0 var(--s-4); }
.lp-actions { display: flex; flex-wrap: wrap; gap: var(--s-2); margin-top: var(--s-4); }
.lp-fb { margin-top: var(--s-4); padding: var(--s-3) var(--s-4); border-radius: var(--r-1); background: var(--band); }
.lp-fb:empty { display: none; }
.lp-fb.is-ok { background: var(--ok-tint); }
.lp-fb.is-ok::before { content: "对。"; font-weight: 600; color: var(--ok); }
.lp-fb.is-no { background: var(--risk-tint); }
.lp-fb.is-no::before { content: "还不对。"; font-weight: 600; color: var(--risk); }
/* 解析块：浅底整块，不加左侧彩条（“圆角 + 左彩条”是最典型的模板味，见 visual.md §7） */
.lp-why, .lp-answer, .lp-model { margin-top: var(--s-4); padding: var(--s-3) var(--s-4); background: var(--band); border-radius: var(--r-1); }
.lp-why > :last-child, .lp-answer > :last-child, .lp-model > :last-child { margin-bottom: 0; }
.lp-ready .lp-why[hidden], .lp-ready .lp-answer[hidden], .lp-ready .lp-model[hidden], .lp-hint[hidden] { display: none; }
.lp-input, .lp-task textarea { display: block; width: 100%; min-height: 88px; font: inherit; color: var(--text); background: var(--bg); padding: var(--s-2) var(--s-3); border: 1px solid var(--line-strong); border-radius: var(--r-1); }

/* 选择题选项 */
.lp-opt { display: flex; gap: var(--s-3); align-items: flex-start; padding: var(--s-3); margin: var(--s-2) 0; border: 1px solid var(--line); border-radius: var(--r-1); cursor: pointer; min-height: 44px; }
.lp-opt:hover { border-color: var(--line-strong); }
.lp-opt input { margin-top: .45em; accent-color: var(--accent); flex: none; width: 18px; height: 18px; }
.lp-opt:has(input:checked) { border-color: var(--accent); background: var(--accent-tint); }
.lp-opt.is-right { border-color: var(--ok); background: var(--ok-tint); }
.lp-opt.is-wrong { border-color: var(--risk); }

/* 填空 */
.lp-blank { font: 600 1em/1.4 var(--f-mono); width: 7em; padding: 1px var(--s-2); margin: 0 2px; color: var(--accent-ink); background: var(--bg); border: none; border-bottom: 2px solid var(--line-strong); border-radius: 0; }
.lp-blank.is-ok { border-color: var(--ok); color: var(--ok); }
.lp-blank.is-no { border-color: var(--risk); color: var(--risk); }

/* 分类 */
.lp-items { list-style: none; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: var(--s-2); }
.lp-items li { margin: 0; }
.lp-item { font: 500 var(--t-small)/1.3 var(--f-sans); padding: var(--s-2) var(--s-3); min-height: 40px; border: 1.5px solid var(--line-strong); border-radius: var(--r-1); background: var(--bg); color: var(--text); cursor: pointer; }
.lp-item[aria-pressed="true"] { border-color: var(--accent); background: var(--accent-tint); outline: 2px solid var(--accent); outline-offset: 1px; }
.lp-item.is-done { border-color: var(--ok); color: var(--ok); cursor: default; }
.lp-cats { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: var(--s-3); margin-top: var(--s-4); }
.lp-cat { display: flex; flex-direction: column; align-items: stretch; gap: var(--s-2); text-align: left; font: 600 var(--t-small)/1.3 var(--f-sans); color: var(--text); padding: var(--s-3); min-height: 88px; border: 1.5px dashed var(--line-strong); border-radius: var(--r-2); background: var(--band); cursor: pointer; }
.lp-cat:hover { border-color: var(--accent); }
.lp-cat .lp-bin { display: flex; flex-wrap: wrap; gap: var(--s-1); font-weight: 500; }
.lp-cat .lp-bin span { font-size: var(--t-label); padding: 1px var(--s-2); border-radius: var(--r-1); background: var(--ok-tint); color: var(--ok); }

/* 自我解释：要点自评 */
.lp-points { list-style: none; padding: 0; margin: var(--s-3) 0 0; }
.lp-points label { display: flex; gap: var(--s-2); align-items: baseline; cursor: pointer; }
.lp-points input { accent-color: var(--accent); }

.lp-tally { font: 600 var(--t-small)/1 var(--f-mono); color: var(--text-dim); font-variant-numeric: tabular-nums; }

.lp-sr { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* ---------- 7. 无障碍与打印 ---------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; scroll-behavior: auto !important; }
}
@media print {
  .lp-toc, .lp-player, .lp-theme, .lp-actions, .lp-controls { display: none !important; }
  .lp-ready [data-s].is-off { opacity: 1 !important; }
  .lp-ready .lp-cap li { display: list-item !important; }
  .lp-ready .lp-why[hidden], .lp-ready .lp-answer[hidden], .lp-ready .lp-model[hidden] { display: block !important; }
}
