/* ============================================================
   page-visual.css —— 独立页面的图示化组件库

   为什么需要这一层：
   独立 HTML 页存在的唯一理由，是表达 Markdown 表达不了的东西——
   概念对比、结构示意、分组关系。如果一个页面只剩 h2 + ul + table，
   它就该写成知识库里的 Markdown，而不是独立页。

   但富视觉不等于堆装饰。此前这些页面出过的真实问题是：单页 79 处
   渐变、83 个「每标题配一个」的图标、13 个色相轮着用。那些颜色不
   承载任何信息，只是在填空。

   所以这套组件遵循一条硬规则：**视觉差异必须承载信息差异。**
   同级区块一律同色，层级靠留白、字重、边框粗细区分；颜色只用主色
   与中性灰两套，主色留给「需要被指认的那一个」。

   所有取值走 page-shell.css 的 --page-* 令牌。页面主色由 page-themes.css
   的 .page-theme-* 决定，不要在页面里写内联 style 覆盖主色。

   独立页只有浅色一套，不做深色模式——理由见 tools/generate-tailwind-palette.js
   的文件头注释。
   ============================================================ */

/* ===== 宽版容器 =====
   .page-prose（44rem）是长文的栏宽；图示化页面以卡片网格为主，
   需要整个 shell 宽度。

   选择器必须带上 body.page-shell > main：page-shell.css 里的
   `body.page-shell > main { width: 100% }` 特指度是 (0,1,2)，
   单写 .page-wide 的 (0,1,0) 压不过它，容器会铺满整个视口。
   page-article.css 在 .page-prose 上踩过同一个坑。 */

body.page-shell > main.page-wide,
.page-wide {
  width: min(100% - 2rem, var(--page-shell-max));
  margin-inline: auto;
}

/* hero 与面包屑本身就限宽到 shell 宽度并居中；放进 page-wide 后
   会再减一次 2rem，比下面的卡片网格窄一圈，左边界对不齐。 */
.page-wide > .page-breadcrumb,
.page-wide > .page-hero,
.page-wide > .page-source {
  width: 100%;
}

.page-wide > section {
  margin-bottom: 4rem;
}

.page-wide > section:last-of-type {
  margin-bottom: 2rem;
}

@media (max-width: 640px) {
  body.page-shell > main.page-wide,
  .page-wide {
    width: min(100% - 1.25rem, var(--page-shell-max));
  }

  .page-wide > section {
    margin-bottom: 3rem;
  }
}

/* ===== 主色 hero =====
   页面的视觉锚点。一个页面只有这一处主色实底，它把主题色立住，
   下面的卡片才敢保持克制——满页都想抢眼，等于没有重点。

   page-shell.css 的 .page-hero h1 写死了 slate-900，压在主色上
   读不出来，必须显式改回 --page-on-accent。 */

.page-hero--accent {
  border-color: var(--page-accent-strong);
  border-top: 4px solid var(--page-accent-strong);
  background: var(--page-accent);
  color: var(--page-on-accent);
}

.page-hero--accent h1 {
  color: var(--page-on-accent);
}

/* hero 里的文字一律不透明。曾经用 opacity 0.85–0.88 拉层次，在紫底上
   还够（约 4.9–5.2:1），换成色板里较亮的橙（5.18:1）就掉到 4.2 了，
   最暗的金（4.93:1）更是任何折损都过不了线。

   层次改用字号、字重和间距——本来也该这么做，那是组件的基本原则。 */
.page-hero--accent .page-hero__eyebrow,
.page-hero--accent .page-hero__summary,
.page-hero--accent .page-hero__meta {
  color: var(--page-on-accent);
}

/* ===== 区块标题 =====
   替代过去的渐变 banner。主色胶囊 eyebrow + 中性色标题 + 主色调
   的底线，与知识库正文的 h2 处理保持同一语言。 */

.pv-head {
  margin: 3.5rem 0 1.5rem;
  padding-bottom: 0.875rem;
  border-bottom: 1px solid color-mix(in srgb, var(--page-accent) 32%, var(--page-border));
}

.pv-head:first-child {
  margin-top: 0;
}

.pv-head__eyebrow {
  display: inline-block;
  margin: 0 0 0.625rem;
  padding: 0.25rem 0.75rem;
  border-radius: 999px;
  background: var(--page-accent-soft);
  color: var(--page-accent-strong);
  font-size: var(--page-text-sm);
  font-weight: 600;
  letter-spacing: 0.04em;
}

.pv-head__title {
  margin: 0;
  color: var(--page-text);
  font-size: var(--page-text-xl);
  font-weight: 700;
  line-height: 1.35;
}

.pv-head__summary {
  max-width: 42rem;
  margin: 0.5rem 0 0;
  color: var(--page-muted);
  font-size: var(--page-text-base);
  line-height: 1.7;
}

/* ===== 网格 ===== */

.pv-grid {
  display: grid;
  gap: 1.25rem;
  grid-template-columns: 1fr;
}

@media (min-width: 40rem) {
  .pv-grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .pv-grid--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 60rem) {
  .pv-grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .pv-grid--sidebar { grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr); }
}

/* ===== 卡片 =====
   过去每张卡片自带一个色相的边框、阴影和角落光晕。现在统一：
   细边框 + 极轻阴影，hover 时边框转主色。区分靠内容，不靠颜色。 */

.pv-card {
  display: flex;
  flex-direction: column;
  padding: 1.5rem;
  /* 边框带一点主色，整页才有统一的色调倾向。纯中性灰边框配白底，
     页面会读起来像未上色的线框稿。 */
  border: 1px solid color-mix(in srgb, var(--page-accent) 22%, var(--page-border));
  border-radius: var(--page-radius-lg, 1rem);
  background: var(--page-surface);
  box-shadow: var(--page-shadow-sm);
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.pv-card:hover {
  border-color: var(--page-accent);
  box-shadow: 0 10px 30px color-mix(in srgb, var(--page-accent) 18%, transparent);
}

/* 需要被指认出来的那一张——正例、推荐项、当前选择。
   全页最多用一次，用多了就退化成「又一种颜色」。 */
.pv-card--accent {
  border-color: var(--page-accent);
  background: var(--page-accent-soft);
}

.pv-card__head {
  display: flex;
  align-items: flex-start;
  gap: 0.875rem;
  margin-bottom: 1rem;
}

/* 字母/序号徽章。主色实底，字色走 --page-on-accent 而不是写死白，
   换主题色时才不会失守。 */
.pv-card__badge {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: var(--page-radius-md, 0.75rem);
  background: var(--page-accent);
  color: var(--page-on-accent);
  font-size: var(--page-text-lg);
  font-weight: 700;
  line-height: 1;
}

.pv-card__badge--quiet {
  background: var(--page-accent-soft);
  color: var(--page-accent);
}

.pv-card__title {
  margin: 0;
  color: var(--page-text);
  font-size: var(--page-text-lg);
  font-weight: 700;
  line-height: 1.4;
}

.pv-card__label {
  display: block;
  margin-top: 0.125rem;
  color: var(--page-muted);
  font-size: var(--page-text-sm);
  font-weight: 500;
}

.pv-card__body {
  margin: 0;
  color: var(--page-muted);
  font-size: var(--page-text-md);
  line-height: 1.75;
}

.pv-card__body + .pv-card__body {
  margin-top: 0.75rem;
}

.pv-card__body strong {
  color: var(--page-text);
  font-weight: 600;
}

/* 把标签/脚注压到卡片底部，让等高网格里的卡片底部对齐 */
.pv-card__foot {
  margin-top: auto;
  padding-top: 1rem;
}

/* ===== 标签 ===== */

.pv-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.pv-tag {
  padding: 0.25rem 0.75rem;
  border-radius: 999px;
  background: var(--page-accent-soft);
  /* 用加深版而不是主色本身：标签常常落在 .pv-card--accent 的淡色底上，
     两层淡底叠加后主色只剩 3.85:1。加深版留得住余量。 */
  color: var(--page-accent-strong);
  font-size: var(--page-text-sm);
  font-weight: 500;
}

.pv-tag--quiet {
  background: rgb(var(--page-muted-rgb, 100 116 139) / 0.1);
  color: var(--page-muted);
}

/* ===== 示意图 =====
   这是整套组件里最该保留的东西：用图形演示概念本身。
   「左对齐/右对齐/居中」三张示意图，比任何文字描述都直观，
   把它压成表格等于把内容删了。 */

.pv-demo {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding: 1rem;
  border-radius: var(--page-radius-md, 0.75rem);
  background: var(--page-bg-subtle, rgb(148 163 184 / 0.1));
}

.pv-demo--start { align-items: flex-start; }
.pv-demo--end { align-items: flex-end; }
.pv-demo--center { align-items: center; }

/* 代表一行文字的色块。中性灰是「普通行」，加 --accent 表示被强调的行。 */
.pv-bar {
  height: 0.5rem;
  border-radius: 999px;
  background: rgb(var(--page-muted-rgb, 100 116 139) / 0.35);
}

.pv-bar--accent { background: var(--page-accent); }
.pv-bar--head { height: 0.75rem; }

.pv-bar--w25 { width: 25%; }
.pv-bar--w33 { width: 33%; }
.pv-bar--w50 { width: 50%; }
.pv-bar--w66 { width: 66%; }
.pv-bar--w75 { width: 75%; }
.pv-bar--w85 { width: 85%; }
.pv-bar--full { width: 100%; }

.pv-demo__caption {
  margin: 0.75rem 0 0;
  color: var(--page-muted);
  font-size: var(--page-text-sm);
  line-height: 1.6;
}

/* ===== 链接列表 =====
   外部资源清单。preflight 清掉了 list-style 和 text-decoration，
   两个都要显式声明，否则符号消失、链接看不出是链接。 */

.pv-links {
  margin: 0;
  padding: 0;
  list-style: none;
}

.pv-links > li + li {
  margin-top: 0.625rem;
}

.pv-links a {
  color: var(--page-accent-strong);
  font-size: var(--page-text-md);
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.pv-links a:hover {
  text-decoration-thickness: 2px;
}

/* ===== 图示容器 =====
   包住内联 SVG 示意图。给一层淡底把图和卡片正文分开，并让 SVG 里的
   currentColor 有一个确定的继承来源。 */

.pv-figure-frame {
  padding: 1rem;
  border-radius: var(--page-radius-md, 0.75rem);
  background: var(--page-bg-subtle);
  color: var(--page-text);
}

.pv-figure-frame svg {
  display: block;
  width: 100%;
  height: auto;
}

/* ===== 卡片内的引用与代码 =====
   page-article.css 的 blockquote / code 样式挂在 .page-prose 下，
   图示页不走那个容器，需要在这里单独给一份。 */

.pv-quote {
  margin: 0;
  padding: 0.625rem 0.875rem;
  border-left: 3px solid var(--page-accent);
  border-radius: 0 var(--page-radius-sm, 0.5rem) var(--page-radius-sm, 0.5rem) 0;
  background: var(--page-bg-subtle);
  color: var(--page-text);
  font-size: var(--page-text-md);
  font-style: italic;
  line-height: 1.65;
}

.pv-card code,
.pv-points code {
  padding: 0.1em 0.35em;
  border-radius: 0.3rem;
  background: var(--page-bg-subtle);
  color: var(--page-accent-strong);
  font-family: var(--page-font-mono);
  font-size: 0.925em;
  font-style: normal;
}

/* ===== 金字塔 =====
   自上而下收敛的层级结构（结论 → 论点 → 论据）。层宽和层色一起
   表达收敛：越往上越窄、越实，塔尖是唯一的主色实底。

   第 2、3 层用主色与卡片底色的低比例混合，配深色正文；只有塔尖是
   实底配 --page-on-accent。别把中间层也做成实底——三层实底压在一起，
   「收敛」这个信息就没了，只剩三条彩色横杠。 */

.pv-pyramid {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
}

.pv-pyramid__tier {
  display: grid;
  place-items: center;
  padding: 0.875rem 1rem;
  border-radius: var(--page-radius-md, 0.75rem);
  text-align: center;
}

.pv-pyramid__tier--1 {
  width: 50%;
  background: var(--page-accent);
  color: var(--page-on-accent);
}

.pv-pyramid__tier--2 {
  width: 75%;
  background: color-mix(in srgb, var(--page-accent) 26%, var(--page-surface));
  color: var(--page-text);
}

.pv-pyramid__tier--3 {
  width: 100%;
  background: color-mix(in srgb, var(--page-accent) 11%, var(--page-surface));
  color: var(--page-text);
}

.pv-pyramid__label {
  font-size: var(--page-text-md);
  font-weight: 700;
  line-height: 1.35;
}

/* 不加 opacity：塔尖压在主色实底上，白字任何折损都可能掉到 AA 线下。
   与正标题的层次靠字号和字重区分。 */
.pv-pyramid__note {
  margin-top: 0.125rem;
  font-size: var(--page-text-sm);
  font-weight: 500;
}

@media (max-width: 40rem) {
  .pv-pyramid__tier--1 { width: 70%; }
  .pv-pyramid__tier--2 { width: 88%; }
}

/* ===== 正反例对照 =====
   判定色是这套组件里唯一允许的第二组颜色，因为它承载信息：
   绿 = 该这么做，红 = 别这么做。沿用知识库既有语义色。 */

.pv-verdict {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  margin-top: 0.75rem;
  font-size: var(--page-text-sm);
  font-weight: 600;
}

.pv-verdict svg {
  width: 1rem;
  height: 1rem;
}

.pv-verdict--good { color: var(--page-ok, #15843e); }
.pv-verdict--bad { color: var(--page-bad, #b3261e); }
.pv-verdict--warn { color: var(--page-warn, #8a6100); }

.pv-card--good { border-color: rgb(21 132 62 / 0.35); }
.pv-card--bad { border-color: rgb(179 38 30 / 0.35); }

/* ===== 编号要点 =====
   .page-steps 是正文里的有序步骤；这个是卡片网格里的要点，
   编号与文字并排而不是悬挂，适合放进 grid。 */

.pv-points {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: pv-point;
}

.pv-points > li {
  display: flex;
  align-items: flex-start;
  gap: 0.875rem;
  padding: 0.875rem 1rem;
  border-radius: var(--page-radius-md, 0.75rem);
  background: var(--page-bg-subtle, rgb(148 163 184 / 0.1));
  counter-increment: pv-point;
}

.pv-points > li::before {
  content: counter(pv-point);
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 0.5rem;
  background: var(--page-accent);
  color: var(--page-on-accent);
  font-size: var(--page-text-sm);
  font-weight: 700;
  line-height: 1;
}

.pv-points__title {
  margin: 0 0 0.125rem;
  color: var(--page-text);
  font-size: var(--page-text-md);
  font-weight: 600;
}

.pv-points__body {
  margin: 0;
  color: var(--page-muted);
  font-size: var(--page-text-sm);
  line-height: 1.65;
}

/* ===== 色板 / 字体样例 =====
   演示配色与字体时，样例本身就是内容，必须看得见。 */

.pv-swatches {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.pv-swatch {
  flex: 1 1 5rem;
  min-width: 5rem;
}

.pv-swatch__chip {
  height: 3.5rem;
  border-radius: var(--page-radius-md, 0.75rem);
  border: 1px solid rgb(0 0 0 / 0.06);
}

.pv-swatch__label {
  display: block;
  margin-top: 0.5rem;
  color: var(--page-muted);
  font-size: var(--page-text-sm);
}

/* 字体样例：这里的 font-family 是被演示的对象，不是页面排版，
   所以显式写死，不走 --page-font。 */
.pv-specimen {
  margin: 0;
  color: var(--page-text);
  font-size: 1.75rem;
  line-height: 1.4;
}

.pv-specimen--serif { font-family: Georgia, "Times New Roman", "Songti SC", serif; }
.pv-specimen--sans { font-family: Inter, "PingFang SC", "Helvetica Neue", sans-serif; }
.pv-specimen--mono { font-family: "SF Mono", Menlo, Consolas, monospace; }

/* ===== 组件自有令牌 =====
   独立页只有浅色一套，取值即最终值。 */

/* 挂在 body 而不是 :root：主题色由 body 上的 .page-theme-* 提供，
   :root 在它之上，那里的 var(--page-accent) 只能取到默认值——示意图
   底色会永远是紫的，不跟随页面主题。 */
body.page-shell {
  /* 示意图与要点条的底色。带一点主色而不是中性灰——这些小色块在页面上
     出现的次数最多，它们的色调决定了整页读起来是暖是冷、有没有主题。 */
  --page-bg-subtle: color-mix(in srgb, var(--page-accent) 8%, transparent);
}

:root {
  --page-muted-rgb: 100 116 139;

  /* 判定色，沿用知识库语义：绿 = 该这么做，红 = 别这么做，金 = 需留意。
     取的是各色的加深版，不是知识库正文里那一档：判定标记常常落在
     .pv-demo / .pv-card--accent 的淡色底上，正文档（绿 4.77、金 4.62）
     叠一层淡底就掉到 4.3 以下。加深后白底 6.3 / 6.8 / 6.2，留得住余量。 */
  --page-ok: #116931;
  --page-bad: #9f1c15;
  --page-warn: #6f4e00;
}
