/* ============================================================================
   assets/site.css — ems-pdu / IDCPDU · 卡 2「钢与光 Steel & Light」
   Phase 1B 模板层产出。**共享版式与组件**（token 在 design-tokens.css）。

   &#9940; CSP：style-src 'self' —— 全文无 style="..." 内联属性、无内联事件、
      无第三方 URL。组件参数化一律走类名（见 §img-grid / §cert-wall 的 is-cN）。
   &#9940; 内容不得依赖 JS 才可见：全文不给正文/表格/图示加 opacity:0 入场动画。
      只有装饰层（光条、hover 抬升、位移）允许动效。
   &#9940; 反模式：一律 `background-color`，不用 `background:` 简写
      （简写会把 background-image 重置为 none，实测过）。
   ========================================================================= */

/* ============================ 0 · 布局原子 ================================ */
/* box-sizing 复位归这里 —— 它是**版式基础**，与 site.css 的其它 layout 规则同源。
   &#9940; 单一权威源（硬约束 54）：这条从 design-tokens.css 搬过来，两处都有会被
   check-css-conflicts.py 判 FAIL。
   为什么归 site.css 不归 design-tokens：design-tokens.css 只放 token 与 @font-face，
   不放**规则**（它的注释里也是这么声明的）。 */
*, *::before, *::after { box-sizing: border-box; }

.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.wrap--narrow { max-width: 1080px; }

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap; border: 0;
}
.skip {
  position: absolute; left: var(--s-md); top: -100px; z-index: 200;
  padding: 12px 18px; background-color: var(--brand); color: #fff;
  font-family: var(--f-mono); font-size: var(--fs-btn);
  letter-spacing: var(--ls-nav); text-transform: uppercase;
  transition: top var(--t-fast) var(--ease);
}
.skip:focus { top: var(--s-md); }

/* 段落与标题的通用节奏 */
.lede {
  color: var(--fg-3); font-size: var(--fs-body-s);
  line-height: var(--lh-copy); max-width: var(--measure);
}
.prose {
  color: var(--fg-3); font-size: var(--fs-body);
  line-height: var(--lh-copy); max-width: var(--measure);
}
.prose + .prose { margin-top: var(--s-md); }

/* ============================ 1 · 文字原子 =============================== */
/* mono 全大写标签：10px / ls .20em / tabular —— 设计语言 §五 */
.eyebrow {
  font-family: var(--f-mono); font-size: var(--fs-label);
  letter-spacing: var(--ls-label); text-transform: uppercase;
  color: var(--brand); font-variant-numeric: tabular-nums;
}
.cap, .label {
  font-family: var(--f-mono); font-size: var(--fs-label);
  letter-spacing: var(--ls-label); text-transform: uppercase;
  color: var(--fg-label); font-variant-numeric: tabular-nums;
}
.data, .mono {
  font-family: var(--f-mono); font-variant-numeric: tabular-nums;
  letter-spacing: .02em;
}
.data { font-size: var(--fs-data); color: var(--fg-2); }
.num  { font-family: var(--f-display); letter-spacing: .5px; color: var(--fg-1); }

.h1 {
  font-size: var(--fs-h1); line-height: var(--lh-display);
  letter-spacing: var(--ls-display); max-width: var(--measure-h1);
}
.h2 { font-size: var(--fs-h2); line-height: var(--lh-title); }
.h3 { font-size: var(--fs-h3); line-height: var(--lh-title); }
.h4 { font-size: var(--fs-h4); line-height: var(--lh-title); }
.lead { color: var(--fg-2); font-size: var(--fs-lead); line-height: var(--lh-body); max-width: 50ch; }

/* 亮段里的文字角色（第 4 屏 / 白承板）。
   &#9888;&#65039; 亮段上的 accent **文字**一律用 --brand-deep（5.20:1）。
   #E05020 落在 #EDEFF0 上只有 3.41:1、--brand-ink 只有 2.57:1 —— 都不达 AA，
   也都不达「大字 3:1」。装饰线（process 的 2px 顶线）仍用 --brand。 */
.is-light .h1, .is-light .h2, .is-light .h3, .is-light .h4 { color: var(--on-light); }
.is-light .lead, .is-light .prose { color: var(--ink); }
.is-light .lede { color: var(--steel-ink); }
.is-light .cap, .is-light .label { color: var(--steel-cap); }
.is-light .data, .is-light .mono { color: var(--steel-ink); }
.is-light .eyebrow { color: var(--brand-deep); }
/* 亮段里的焦点环要用深一档的橙 + 亮内环，否则橙环压在 #EDEFF0 上几乎看不见 */
.is-light :focus-visible { box-shadow: var(--focus-ring-on-light); }

/* ============================ 2 · 按钮（按钮形态 CTA）=====================
   形态由类名定：is-solid（实心 = 主转化）/ is-line（描边）/ is-ghost。
   实心按钮 = 橙色底 —— 全站唯一铺橙色的地方（设计语言 §二之一）。
   ========================================================================= */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: 9px; min-height: var(--s-touch); padding: 13px 22px;
  font-family: var(--f-mono); font-size: var(--fs-btn); font-weight: var(--w-regular);
  letter-spacing: var(--ls-nav); text-transform: uppercase;
  background-color: transparent; color: var(--fg-1);
  border: 1px solid var(--rule-strong); border-radius: var(--r-none);
  cursor: pointer; text-align: center;
  transition: var(--transition-ctl);
}
.btn:hover { border-color: var(--brand); color: var(--brand-ink); box-shadow: var(--e-1); }
.btn:active { transform: translateY(1px); }
/* 实心 CTA：底色是设计语言锁定的 #E05020，文字改暖调深色（4.94:1，达 AA）；
   hover 切到 --brand-deep + 白字（5.99:1）—— 状态变化同时体现在底色与字色上。 */
.btn.is-solid { background-color: var(--brand); border-color: var(--brand); color: var(--on-brand); }
.btn.is-solid:hover { background-color: var(--brand-deep); border-color: var(--brand-deep); color: var(--text); }
.btn.is-block { width: 100%; }
.btn.is-ghost { border-color: var(--hair-2); }
.btn.on-light { border-color: var(--hair-light); color: var(--ink); }
.btn.on-light:hover { border-color: var(--brand); color: var(--brand-deep); }
.btn-row { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; }

/* 文字型文档链接 —— &#9940; **不是**转化动作，不要加 data-modal-open
   （page-templates.md：正文里的文档引用小链接是导航，不是转化） */
.linkdoc {
  font-family: var(--f-mono); font-size: var(--fs-data);
  letter-spacing: .06em; color: var(--brand-ink);
  border-bottom: 1px solid var(--rule-strong);
  transition: var(--transition-ctl);
}
.linkdoc:hover { border-bottom-color: var(--brand-ink); }
/* &#9940; 不在这里加 `content:"\2192"` 后缀：U+2192 三个字族的 cmap 里都没有字形，
   会落到系统回退族（实测宽度 34.52px，非本站字体），视觉上不可控。
   方向感由下划线 + 目标页自身承担。（禁用字符表见 source/design-blueprint.md） */

/* ============================ 3 · 段与段底 =============================== */
.sec { padding-block: var(--s-section); border-bottom: 1px solid var(--rule); }
.sec--dark { background-color: var(--canvas); color: var(--fg-3); }
.sec--deep { background-color: var(--surface); color: var(--fg-3); }
.sec--void { background-color: var(--ink-void); color: var(--fg-3); }
.sec--light { background-color: var(--light); color: var(--ink); border-bottom-color: var(--hair-light-soft); }
.sec--flush { padding-block: 0; }
.sec--tight { padding-block: var(--s-xl); }
.hair { height: 1px; border: 0; margin: 0; background-color: var(--rule-strong); }
.hair--light { background-color: var(--hair-light); }

/* ============================ 4 · 页头（顶栏 + 移动端菜单）===============
   结构契约（Phase 3 必须照抄，否则 md5 一致性检查会红）：
     .site-head > .wrap > ( a.brand | button.menu-btn | nav.menu | .head-actions )
     active 态 = 页面自己给 <a> 加 .is-active；块里不写死当前页。
   ========================================================================= */
.site-head {
  position: fixed; inset: 0 0 auto 0; z-index: 60;
  background-image: var(--grad-nav);
  transition: var(--transition-ctl);
}
.site-head.is-stuck {
  background-color: rgba(8, 10, 11, .92);
  background-image: none;
  border-bottom: 1px solid var(--rule);
  box-shadow: var(--e-2);
  -webkit-backdrop-filter: blur(10px) saturate(120%);
  backdrop-filter: blur(10px) saturate(120%);
}
.site-head .wrap {
  display: flex; align-items: center; gap: var(--s-md);
  min-height: 80px; flex-wrap: wrap;
}
/* 品牌锁定：客户原图字标 + 一行小副标。
   &#9940; img 必须保留 width/height 属性（防抖动），CSS 只压高度、宽度 auto 等比。
   字标原图 169x30，导航给 24px 高 —— 这是客户素材的分辨率上限，不是可调项。 */
.brand {
  display: inline-flex; align-items: center; gap: 10px;
  font-family: var(--f-display); font-size: 22px;
  letter-spacing: var(--ls-brand); text-transform: uppercase; color: var(--fg-1);
}
.brand img { height: 24px; width: auto; }
.brand__name {
  font-family: var(--f-mono); font-size: var(--fs-label);
  letter-spacing: var(--ls-nav); text-transform: uppercase;
  color: var(--fg-label); white-space: nowrap;
}

.menu { flex: 1 1 auto; }
.menu ul {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 0; margin: 0; padding: 0; list-style: none;
}
.menu a {
  display: block; padding: 10px 14px;
  font-family: var(--f-mono); font-size: 10.5px;
  letter-spacing: var(--ls-nav); text-transform: uppercase;
  color: #D6DADC; transition: var(--transition-ctl);
}
.menu a:hover { color: var(--brand-ink); }
.menu a.is-active { color: var(--brand-ink); box-shadow: inset 0 -2px 0 var(--brand); }

.head-actions { display: flex; align-items: center; gap: var(--s-sm); margin-left: auto; }
.head-note {
  font-family: var(--f-mono); font-size: var(--fs-label);
  letter-spacing: var(--ls-nav); color: var(--fg-4); text-transform: uppercase;
}

/* 移动端菜单：CSP 禁内联事件 —— 用「隐藏 checkbox + label」纯 CSS 开关，
   JS 只是把 aria-expanded 与焦点同步过去；JS 全挂时菜单照样能开。 */
.menu-btn {
  display: none; align-items: center; gap: 8px;
  min-height: var(--s-touch); min-width: var(--s-touch);
  padding: 0 12px; margin-left: auto;
  background-color: transparent; color: var(--fg-1);
  border: 1px solid var(--rule-strong); border-radius: var(--r-none);
  cursor: pointer; transition: var(--transition-ctl);
}
.menu-btn:hover { border-color: var(--brand); }
.menu-btn__bars { display: block; width: 16px; height: 2px; background-color: currentColor; box-shadow: 0 5px 0 currentColor, 0 -5px 0 currentColor; }
.menu-btn__txt { font-family: var(--f-mono); font-size: var(--fs-label); letter-spacing: var(--ls-nav); text-transform: uppercase; }

.menu-toggle { position: absolute; opacity: 0; pointer-events: none; width: 0; height: 0; }

@media (max-width: 1080px) {
  .menu-btn { display: inline-flex; }
  .head-actions .head-note { display: none; }
  .menu {
    order: 5; flex: 1 1 100%;
    max-height: 0; overflow: hidden;
    transition: max-height var(--t-slow) var(--ease);
  }
  .menu-toggle:checked ~ .menu { max-height: 80vh; overflow-y: auto; }
  .menu ul { flex-direction: column; align-items: stretch; gap: 0; padding-block: var(--s-xs); }
  .menu a { padding: 14px 2px; border-bottom: 1px solid var(--hair-1); }
  .menu a.is-active { box-shadow: inset 3px 0 0 var(--brand); padding-left: 12px; }
  .menu-toggle:focus-visible ~ .menu-btn { box-shadow: var(--focus-ring); }
}

@media (max-width: 560px) {
  .brand { font-size: 18px; }
  .brand img { height: 22px; }
  .head-actions .btn { padding: 12px 14px; }
}

/* 页头是 fixed，首屏需要让位（hero 自己贴顶，内页用 .has-head 的 padding） */
.has-head { padding-top: 80px; }
.page-hero { padding-top: calc(80px + var(--s-section)); }

/* ============================ 5 · hero-scrim =============================
   变体（block_type hero-scrim）：is-raking-light / is-workbench-spot / is-open-rack-edge
   影像处理与遮罩逐字取自卡 2：object-position 62% 46%，saturate(.5) brightness(.62)。
   ========================================================================= */
.hero {
  position: relative; display: flex; align-items: flex-end;
  min-height: var(--hero-min); overflow: hidden;
  background-color: var(--ink-void);
  border-bottom: 1px solid var(--rule);
  padding-top: 80px;
}
.hero__bg { position: absolute; inset: 0; overflow: hidden; }
.hero__bg img {
  width: 100%; height: 100%; object-fit: cover;
  object-position: 62% 46%;
  filter: saturate(.5) brightness(.62) contrast(1.06);
  /* &#9940; 视口上限，防止「图片渲染盒超过视口高」这一类永远复发。
     成因：`.hero` 是 `min-height`（会被内容撑高），`.hero__bg` 是 `inset:0` 绝对铺满，
     `img` 又 `height:100%` —— 于是**内容一撑高，图片跟着超**。
     `check-layout-edges.js` 量的是**图片元素**，于是命中的是 hero 底图本身。
     加 `max-height` 后 img 最高只到一屏；`object-fit: cover` 仍在，
     图片不会被拉变形，超出部分露出的是 `.hero` 的 `--ink-void` 暗场（与设计语言一致）。
     内容本身不受影响：`.hero` 该多高还多高，正文不会被裁（`.hero` 的 `overflow:hidden`
     只裁装饰层；文案在 `.hero__inner` 里，随 `.hero` 正常增高）。 */
  max-height: 100svh;
}
.hero__scrim { position: absolute; inset: 0; background-image: var(--scrim-h), var(--scrim-v); }
.hero__lightbar {
  position: absolute; top: 0; left: 0;
  width: var(--lightbar-w); height: var(--lightbar-h);
  background-image: var(--grad-brand);
  z-index: 2; transition: width var(--t-slow) var(--ease);
}
.hero__inner { position: relative; z-index: 3; width: 100%; padding-bottom: var(--s-xl); }
.hero__grid {
  display: grid; grid-template-columns: var(--split);
  gap: var(--gap-split); align-items: end;
}
/* text-shadow 兜底：即使遮罩在某些素材上偏薄，标题仍然可读 */
.hero .h1 { margin-top: var(--s-md); text-shadow: var(--text-shadow-hero); }
.hero .lead { margin-top: var(--s-md); color: #C3CACD; text-shadow: var(--text-shadow-data); }
.hero .eyebrow { text-shadow: var(--text-shadow-data); }
.hero .btn-row { margin-top: var(--s-lg); }

/* 三种光照变体只改影像处理与遮罩权重，版式不动 */
.hero.is-raking-light .hero__bg img { object-position: 62% 46%; filter: saturate(.5) brightness(.62) contrast(1.06); }
.hero.is-workbench-spot .hero__bg img { object-position: 50% 42%; filter: saturate(.42) brightness(.66) contrast(1.04); }
.hero.is-workbench-spot .hero__scrim { background-image: var(--scrim-h), var(--scrim-v); }
.hero.is-open-rack-edge .hero__bg img { object-position: 68% 52%; filter: saturate(.55) brightness(.58) contrast(1.08); }
.hero.is-open-rack-edge .hero__scrim {
  background-image:
    linear-gradient(90deg, rgba(var(--scrim-base), .96) 0%, rgba(var(--scrim-base), .5) 52%, rgba(var(--scrim-base), .78) 100%),
    var(--scrim-v);
}
.hero--short { min-height: 62svh; }

/* 参数栏：右下角常驻 dl 5 行 —— 不是卡片、不是按钮组（设计语言 §四） */
.rail { border-top: 1px solid var(--hair-2); padding-top: 18px; margin: 0; }
.rail .kv {
  display: flex; justify-content: space-between; gap: var(--s-sm);
  padding: 9px 0; border-bottom: 1px solid var(--hair-1);
}
.rail dt {
  font-family: var(--f-mono); font-size: var(--fs-label);
  letter-spacing: .14em; text-transform: uppercase; color: var(--fg-4);
}
.rail dd { margin: 0; font-family: var(--f-mono); font-size: 13.5px; color: var(--fg-1); }
.rail dd em { font-style: normal; color: var(--brand-ink); }
@media (max-width: 900px) {
  .hero__grid { grid-template-columns: 1fr; gap: var(--s-lg); align-items: start; }
  .rail { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 var(--s-md); }
}
@media (max-width: 560px) { .rail { grid-template-columns: 1fr; } }

/* ============================ 6 · spec-band ==============================
   变体：is-dl-two-col / is-table-dense / is-mono-strip。签名 = 0px 直角参数表。
   ========================================================================= */
.specband {
  display: grid; grid-template-columns: var(--spec);
  gap: var(--gap-spec); align-items: start;
}
.specband__plate {
  background-color: var(--paper); border: 1px solid var(--rule);
  padding: var(--s-sm); box-shadow: var(--e-1);
}
.specband__plate img { width: 100%; aspect-ratio: 1 / 1; object-fit: contain; }
.specband__legend {
  font-family: var(--f-mono); font-size: var(--fs-label);
  letter-spacing: .06em; color: var(--fg-label);
  margin-top: 12px; line-height: var(--lh-body);
}
.speclist { width: 100%; border-collapse: collapse; margin-top: var(--s-md); }
.speclist caption { text-align: left; padding-bottom: 12px; }
.speclist th {
  font-family: var(--f-mono); font-size: var(--fs-label);
  letter-spacing: .14em; text-transform: uppercase; color: var(--fg-label);
  text-align: left; font-weight: var(--w-regular);
  padding: 0 14px 10px 0; border-bottom: 1px solid var(--rule-strong);
}
.speclist td {
  padding: 12px 14px 12px 0; border-bottom: 1px solid var(--rule);
  color: var(--fg-2); font-size: var(--fs-body-s); vertical-align: top;
}
.speclist td:first-child { color: var(--fg-1); font-weight: var(--w-regular); }
.speclist td.n { font-family: var(--f-mono); font-size: var(--fs-data); color: var(--fg-1); white-space: nowrap; }

/* is-dl-two-col：同一份 dl 排成两列（窄参数集） */
.specband.is-dl-two-col .speclist td { padding-block: 10px; }
.specband.is-dl-two-col .specband__dl {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0 var(--s-lg); margin: var(--s-md) 0 0;
}
.specband.is-dl-two-col .specband__dl > div {
  display: flex; justify-content: space-between; gap: var(--s-sm);
  padding: 11px 0; border-bottom: 1px solid var(--hair-1);
}
.specband.is-dl-two-col dt {
  font-family: var(--f-mono); font-size: var(--fs-label);
  letter-spacing: .12em; text-transform: uppercase; color: var(--fg-label);
}
.specband.is-dl-two-col dd { margin: 0; font-family: var(--f-mono); font-size: var(--fs-data); color: var(--fg-1); }

/* is-table-dense：更多行、更紧的行距 */
.specband.is-table-dense .speclist td { padding-block: 8px; }
.specband.is-table-dense .speclist th { padding-bottom: 8px; }

/* is-mono-strip：等宽数据条，横向铺开 */
.mono-strip {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  border-top: 1px solid var(--hair-light);
  margin-top: var(--s-lg);
}
.mono-strip > div { padding: 18px 20px 0 0; }
.mono-strip b {
  display: block; font-family: var(--f-mono); font-size: var(--fs-label);
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--fg-label); font-weight: var(--w-regular);
}
.mono-strip span { display: block; font-family: var(--f-display); font-size: 40px; color: var(--fg-1); margin-top: 4px; }
.mono-strip i { font-style: normal; font-family: var(--f-mono); font-size: 12px; color: var(--fg-label); }
.is-light .mono-strip { border-top-color: var(--hair-light); }
.is-light .mono-strip b, .is-light .mono-strip i { color: var(--steel-cap); }
.is-light .mono-strip span { color: var(--on-light); }

@media (max-width: 900px) {
  .specband { grid-template-columns: 1fr; gap: var(--s-lg); }
}

/* ============================ 7 · feature-split ==========================
   变体：is-image-left / is-image-right / is-full-bleed-quote。
   非对称 1.55fr : 1fr。用 CSS order 做左右互换（**不用 direction:rtl**）。
   ========================================================================= */
.split {
  display: grid; grid-template-columns: var(--split);
  gap: var(--gap-split); align-items: center;
}
.split__media { position: relative; }
.split__media img { width: 100%; object-fit: cover; }
.split__plate {
  background-color: var(--paper); border: 1px solid var(--rule);
  padding: var(--s-sm); box-shadow: var(--e-1);
}
.split__plate img { aspect-ratio: 1 / 1; object-fit: contain; }
.split__body > * + * { margin-top: var(--s-md); }
.split__body .h3 { margin-top: var(--s-md); }

.split.is-image-left .split__media { order: 1; }
.split.is-image-left .split__body { order: 2; }
.split.is-image-right .split__media { order: 2; }
.split.is-image-right .split__body { order: 1; }

@media (max-width: 900px) {
  .split { grid-template-columns: 1fr; gap: var(--s-lg); }
  .split.is-image-left .split__media,
  .split.is-image-left .split__body,
  .split.is-image-right .split__media,
  .split.is-image-right .split__body { order: 0; }
}

/* is-full-bleed-quote：全幅影像，引文压在左三分 */
.quote-band {
  position: relative; display: flex; align-items: center;
  min-height: var(--band-min); overflow: hidden;
  background-color: var(--ink-void); border-bottom: 1px solid var(--rule);
}
.quote-band__bg { position: absolute; inset: 0; }
.quote-band__bg img {
  width: 100%; height: 100%; object-fit: cover;
  object-position: 55% 50%;
  filter: saturate(.35) brightness(.5);
}
.quote-band__scrim {
  position: absolute; inset: 0;
  background-image: linear-gradient(90deg, rgba(var(--scrim-base), .94) 0%, rgba(var(--scrim-base), .5) 48%, rgba(var(--scrim-base), .88) 100%);
}
.quote-band__inner { position: relative; z-index: 3; width: 100%; padding-block: var(--s-xl); }
.quote-band blockquote {
  margin: 0; max-width: 34ch;
  font-family: var(--f-display); font-size: var(--fs-h3);
  line-height: var(--lh-tight); letter-spacing: var(--ls-title);
  text-transform: uppercase; color: var(--fg-1);
  text-shadow: var(--text-shadow-hero);
}
.quote-band cite {
  display: block; margin-top: var(--s-md); font-style: normal;
  font-family: var(--f-mono); font-size: var(--fs-label);
  letter-spacing: var(--ls-nav); text-transform: uppercase; color: var(--fg-4);
}
.quote-band__two {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s-lg); margin-top: var(--s-md); max-width: 1080px;
}
@media (max-width: 768px) { .quote-band__two { grid-template-columns: 1fr; } }

/* ============================ 8 · readout-wall (register-grid) ============ */
.readout {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 0; margin-top: var(--s-lg);
  border-top: 1px solid var(--hair-2);
}
.readout__cell {
  padding: var(--s-md) var(--s-md) var(--s-md) 0;
  border-bottom: 1px solid var(--hair-1);
  transition: var(--transition-ctl);
}
.readout__cell:hover { transform: var(--hover-lift); }
.readout__cell b {
  display: block; font-family: var(--f-mono); font-size: var(--fs-label);
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--fg-label); font-weight: var(--w-regular);
}
.readout__cell strong {
  display: block; margin-top: 6px;
  font-family: var(--f-display); font-weight: var(--w-display);
  font-size: clamp(30px, 3.2vw, 46px); letter-spacing: .5px;
  color: var(--fg-1); line-height: 1;
}
.readout__cell span { display: block; margin-top: 8px; font-size: var(--fs-body-s); color: var(--fg-3); }
.is-light .readout { border-top-color: var(--hair-light); }
.is-light .readout__cell { border-bottom-color: var(--hair-light-soft); }
.is-light .readout__cell b { color: var(--steel-cap); }
.is-light .readout__cell strong { color: var(--on-light); }
.is-light .readout__cell span { color: var(--steel-ink); }

/* ============================ 9 · cert-wall ==============================
   变体：is-plates（扫描件板）/ is-ledger（账册表）。
   证书墙只写**证名 + 持证主体**，不落编号（content-policy site_specific_rules）。
   ========================================================================= */
/* --- is-plates：6–12 张扫描件 --- */
.certwall {
  display: grid;
  grid-template-columns: repeat(var(--ig-cols), minmax(0, 1fr));
  gap: var(--s-sm);
  margin-top: var(--s-lg);
}
.certwall__item {
  display: flex; flex-direction: column;
  background-color: var(--surface-strong);
  border: 1px solid var(--rule);
  box-shadow: var(--e-1);
  transition: var(--transition-ctl);
}
.certwall__item:hover { border-color: var(--rule-strong); transform: var(--hover-lift); }
.certwall__scan { background-color: var(--paper); padding: var(--s-xs); }
.certwall__scan img { width: 100%; aspect-ratio: 3 / 4; object-fit: contain; }
.certwall__meta { padding: var(--s-sm); border-top: 1px solid var(--rule); }
.certwall__meta b { display: block; font-size: var(--fs-body-s); color: var(--fg-1); font-weight: var(--w-regular); }
.certwall__meta span { display: block; margin-top: 4px; font-family: var(--f-mono); font-size: var(--fs-micro); letter-spacing: .06em; color: var(--fg-label); }
.certwall--wide .certwall__scan img { aspect-ratio: 3 / 2; }

/* --- is-ledger：表格式账册 --- */
.ledger { width: 100%; border-collapse: collapse; margin-top: var(--s-lg); }
.ledger th {
  font-family: var(--f-mono); font-size: var(--fs-label);
  letter-spacing: .14em; text-transform: uppercase; color: var(--fg-label);
  text-align: left; font-weight: var(--w-regular);
  padding: 0 14px 10px 0; border-bottom: 1px solid var(--rule-strong);
}
.ledger td {
  padding: 13px 14px 13px 0; border-bottom: 1px solid var(--rule);
  color: var(--fg-2); font-size: var(--fs-body-s); vertical-align: top;
}
.ledger td:first-child { color: var(--fg-1); font-weight: var(--w-regular); }
.ledger td.n { font-family: var(--f-mono); font-size: var(--fs-data); color: var(--fg-1); white-space: nowrap; }

/* ============================ 10 · cta-band ==============================
   block_type cta-band（page-end-form，**同页唯一**）。
   表单只用 1px 边框 + 全大写 mono 标签，不通体铺色（设计语言 §六）。
   ========================================================================= */
.ctaband { display: grid; grid-template-columns: 1.35fr 1fr; gap: var(--gap-split); align-items: center; }
.ctaband__body > * + * { margin-top: var(--s-md); }
.ctaband__body .btn-row { margin-top: var(--s-lg); }

/* ============================ 11 · process-strip (numbered) ============== */
.process {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--s-lg); margin-top: var(--s-lg); counter-reset: step;
}
.process__step { position: relative; padding-top: var(--s-md); border-top: 2px solid var(--rule-strong); }
.process__step::before {
  counter-increment: step;
  content: counter(step, decimal-leading-zero);
  position: absolute; top: -2px; left: 0;
  padding-right: 8px;
  font-family: var(--f-mono); font-size: var(--fs-label);
  letter-spacing: .14em; color: var(--brand-ink);
  background-color: var(--canvas);
  box-shadow: 0 -2px 0 0 var(--brand);
}
.is-light .process__step { border-top-color: var(--on-light); }
.is-light .process__step::before { background-color: var(--light); color: var(--brand-deep); box-shadow: 0 -2px 0 0 var(--brand); }
.process__step h3 { font-size: var(--fs-h4); margin-top: var(--s-xs); }
.process__step p { margin: var(--s-xs) 0 0; font-size: var(--fs-body-s); color: var(--fg-3); line-height: var(--lh-copy); }
.is-light .process__step h3 { color: var(--on-light); }
.is-light .process__step p { color: var(--steel-ink); }
/* &#9940; 步骤条不显示时间数字（组件规范：Day 3-14 类标注用户已否决） */

/* ============================ 12 · industry-grid =========================
   变体：is-pain-solution / is-spec-first。6–7 张行业图 + 卡片。
   ========================================================================= */
.indgrid {
  display: grid; grid-template-columns: repeat(var(--ig-cols), minmax(0, 1fr));
  gap: var(--s-sm); margin-top: var(--s-lg);
}
.indgrid__item {
  display: flex; flex-direction: column;
  background-color: var(--surface-strong);
  border: 1px solid var(--rule); box-shadow: var(--e-1);
  transition: var(--transition-ctl);
}
.indgrid__item:hover { border-color: var(--rule-strong); transform: var(--hover-lift); }
.indgrid__shot { overflow: hidden; background-color: var(--ink-void); }
.indgrid__shot img { width: 100%; aspect-ratio: 3 / 2; object-fit: cover; filter: saturate(.55) brightness(.82); transition: filter var(--t-slow) var(--ease); }
.indgrid__item:hover .indgrid__shot img { filter: saturate(.75) brightness(.95); }
.indgrid__body { padding: var(--s-md); }
.indgrid__body .label { display: block; }
.indgrid__body h3 { font-size: var(--fs-h4); margin-top: var(--s-xs); }
.indgrid__body p { margin: var(--s-xs) 0 0; font-size: var(--fs-body-s); color: var(--fg-3); line-height: var(--lh-body); }
.indgrid__spec { margin: var(--s-sm) 0 0; padding: 0; list-style: none; }
.indgrid__spec li {
  display: flex; justify-content: space-between; gap: var(--s-sm);
  padding: 7px 0; border-top: 1px solid var(--hair-1);
  font-family: var(--f-mono); font-size: var(--fs-micro); color: var(--fg-label);
  letter-spacing: .06em;
}
.indgrid__spec li b { color: var(--fg-1); font-weight: var(--w-regular); }

/* ============================ 13 · 图片网格（标签位铺量）=================
   &#9940; 任务补充要求 2：全站平均 >=15 个 <img>/页，43 页 = 645 个标签位，
      而全站生图上限 215 张 —— 差额**必须靠多图网格 + source/materials 真实素材复用**补。
      所以这些网格是「必须用」的组件，不是可选装饰。

   列数与最小列宽**由类名控制**（CSP 下不能写 style="--ig-cols:3"）：
     is-c2 / is-c3 / is-c4 / is-c5 / is-c6 / is-c8  to 列数
     is-min120 / is-min180 / is-min240              to 自动折行的最小列宽
     窄屏另有 is-t2 / is-t3（<=768px）与 is-m1（<=480px）覆盖。
   走 @property 注册的 <number>，所以 var() 能被真正解析成数字。
   ========================================================================= */
.img-grid, .certwall, .indgrid {
  display: grid;
  grid-template-columns: repeat(var(--ig-cols), minmax(0, 1fr));
  gap: var(--s-sm);
}
.img-grid--auto { grid-template-columns: repeat(auto-fit, minmax(var(--ig-min), 1fr)); }

.img-grid.is-c2, .certwall.is-c2, .indgrid.is-c2 { --ig-cols: 2; }
.img-grid.is-c3, .certwall.is-c3, .indgrid.is-c3 { --ig-cols: 3; }
.img-grid.is-c4, .certwall.is-c4, .indgrid.is-c4 { --ig-cols: 4; }
.img-grid.is-c5, .certwall.is-c5, .indgrid.is-c5 { --ig-cols: 5; }
.img-grid.is-c6, .certwall.is-c6, .indgrid.is-c6 { --ig-cols: 6; }
.img-grid.is-c8, .certwall.is-c8, .indgrid.is-c8 { --ig-cols: 8; }
.img-grid.is-c12, .certwall.is-c12, .indgrid.is-c12 { --ig-cols: 12; }

.img-grid.is-min120 { --ig-min: 120px; }
.img-grid.is-min180 { --ig-min: 180px; }
.img-grid.is-min240 { --ig-min: 240px; }
.img-grid.is-min300 { --ig-min: 300px; }

.img-grid__item {
  display: flex; flex-direction: column;
  border: 1px solid var(--rule); background-color: var(--surface-strong);
  box-shadow: var(--e-1); transition: var(--transition-ctl);
}
.img-grid__item:hover { border-color: var(--rule-strong); transform: var(--hover-lift); }
.img-grid__item img { width: 100%; aspect-ratio: 1 / 1; object-fit: cover; }
.img-grid__item.is-contain img { object-fit: contain; background-color: var(--paper); }
.img-grid__item.is-wide img { aspect-ratio: 3 / 2; }
.img-grid__item.is-tall img { aspect-ratio: 3 / 4; }
.img-grid__meta { padding: 11px 13px; border-top: 1px solid var(--rule); }
.img-grid__meta b { display: block; font-size: var(--fs-data); color: var(--fg-1); font-weight: var(--w-regular); }
.img-grid__meta span { display: block; margin-top: 4px; font-family: var(--f-mono); font-size: var(--fs-micro); letter-spacing: .04em; color: var(--fg-label); word-break: break-word; }

/* 型号条：4–8 张一行，只给图与型号，无描述 —— feature-split 内的辅助图组 */
.modelstrip {
  display: grid; grid-template-columns: repeat(var(--ig-cols), minmax(0, 1fr));
  gap: var(--s-xs); margin-top: var(--s-md);
}
.modelstrip.is-c4 { --ig-cols: 4; }
.modelstrip.is-c5 { --ig-cols: 5; }
.modelstrip.is-c6 { --ig-cols: 6; }
.modelstrip.is-c8 { --ig-cols: 8; }
.modelstrip__item { border: 1px solid var(--rule); background-color: var(--paper); padding: var(--s-xxs); transition: var(--transition-ctl); }
.modelstrip__item:hover { border-color: var(--brand); }
.modelstrip__item img { width: 100%; aspect-ratio: 1 / 1; object-fit: contain; }
.modelstrip figcaption {
  margin-top: 6px; padding-top: 6px; border-top: 1px solid var(--rule);
  font-family: var(--f-mono); font-size: var(--fs-micro);
  letter-spacing: .04em; color: var(--fg-label); text-align: center;
}

/* 窄屏折行：375 / 768 必须可达（不得横向溢出） */
@media (max-width: 1080px) {
  .img-grid.is-c6, .certwall.is-c6, .indgrid.is-c6,
  .img-grid.is-c8, .certwall.is-c8,
  .img-grid.is-c12, .certwall.is-c12 { --ig-cols: 4; }
}
@media (max-width: 768px) {
  .img-grid, .certwall, .indgrid { --ig-cols: 2; }
  .img-grid.is-t3, .certwall.is-t3, .indgrid.is-t3 { --ig-cols: 3; }
  .img-grid.is-t2, .certwall.is-t2, .indgrid.is-t2 { --ig-cols: 2; }
  .img-grid.is-c2, .img-grid.is-c3, .img-grid.is-c4, .img-grid.is-c5, .img-grid.is-c6 {
    --ig-cols: 2;
  }
  .certwall.is-c2, .certwall.is-c3, .certwall.is-c4 { --ig-cols: 2; }
  .indgrid.is-c2, .indgrid.is-c3, .indgrid.is-c4 { --ig-cols: 2; }
  .modelstrip.is-c6, .modelstrip.is-c8 { --ig-cols: 4; }
}
@media (max-width: 560px) {
  .img-grid.is-m1, .certwall.is-m1, .indgrid.is-m1 { --ig-cols: 1; }
  .modelstrip.is-c4, .modelstrip.is-c5, .modelstrip.is-c6, .modelstrip.is-c8 { --ig-cols: 3; }
}

/* ============================ 14 · 页脚 ================================== */
.site-foot {
  background-color: var(--ink-void); color: var(--fg-3);
  padding-block: var(--s-xl) var(--s-lg);
}
.site-foot__cols { display: grid; grid-template-columns: 1.7fr repeat(4, minmax(0, 1fr)); gap: var(--s-lg); }
.site-foot h2 { font-family: var(--f-mono); font-size: var(--fs-label); letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--fg-1); font-weight: var(--w-regular); margin: 0 0 14px; }
.site-foot ul { margin: 0; padding: 0; list-style: none; }
.site-foot li { padding: 4px 0; font-size: 12px; }
.site-foot a { color: var(--fg-label); transition: var(--transition-ctl); }
.site-foot a:hover { color: var(--brand-ink); }
.site-foot__brand .site-foot__mark {
  font-family: var(--f-display); font-size: 24px; letter-spacing: var(--ls-brand);
  text-transform: uppercase; color: var(--brand-ink); margin: 0 0 14px;
}
.site-foot__brand p { margin: 0; max-width: 36ch; font-size: 12px; line-height: var(--lh-body); color: var(--fg-label); }
.site-foot__cta { margin-top: var(--s-md); }
.site-foot__legal {
  margin-top: var(--s-lg); padding-top: 18px;
  border-top: 1px solid var(--rule);
  font-size: 11.5px; line-height: var(--lh-body); color: var(--fg-label);
}
.site-foot__legal b { color: var(--fg-1); font-weight: var(--w-medium); }
/* 5 列页脚：1440 to 5 / <=1080 to 3 / <=768 to 2 / <=560 to 1。
   窄屏必须真的折行 —— 5 列在 375px 下每列只剩 ~47px，必然横向溢出。 */
@media (max-width: 1080px) { .site-foot__cols { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 768px) { .site-foot__cols { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .site-foot__cols { grid-template-columns: 1fr; } }

/* ============================ 15 · 询盘弹窗 ==============================
   契约见 references/page-templates.md「询盘弹窗（v21.5 · 强制形态）」，
   闸门 scripts/check-inquiry-modal.js。下面每条带 &#9940; 的都对应一次实测事故。
   ========================================================================= */
body.modal-open { overflow: hidden; }   /* &#9940; 锁背景滚动用类，不用内联 style */
body.modal-open .site-head { -webkit-backdrop-filter: none; backdrop-filter: none; }

/* 蜜罐：人看不见、机器人会填。不用 display:none / type=hidden —— 已知会被跳过 */
.hp-field { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.modal {
  position: fixed; inset: 0; z-index: 90;
  display: none; align-items: center; justify-content: center;
  padding: var(--s-md);
}
.modal.is-open { display: flex; }

/* 背幕用 <button>：点背景关闭不需额外绑定，键盘也能聚焦（契约第 2 条）。
   &#9940; 必须有 backdrop-filter —— 它是「高程 + 毛玻璃」体系的一部分。 */
.modal__scrim {
  position: absolute; inset: 0; width: 100%; height: 100%;
  padding: 0; border: 0; margin: 0;
  background-color: var(--scrim-deep);
  -webkit-backdrop-filter: blur(6px) saturate(80%);
  backdrop-filter: blur(6px) saturate(80%);
  cursor: pointer;
}

.modal__dialog {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  /* &#9940; 行必须显式写成可收缩的弹性轨道：默认 `auto` 只按内容算高，
     容器 max-height 压不住它，行会照内容撑到 949px 再被 overflow:hidden 无声切掉。
     光给子项 min-height:0 不够，**轨道本身**也要允许收缩。 */
  grid-template-rows: minmax(0, 1fr);
  width: 100%; max-width: 1040px; max-height: 92vh;
  background-color: var(--surface-strong);
  border: 1px solid var(--rule-strong);
  border-radius: var(--r-none);
  box-shadow: var(--e-3);
  overflow: hidden;
}
/* &#9940; 不是可选项。grid 子项 min-height 默认 auto（不许矮于内容），
   面板上的 overflow-y:auto 就永远不生效，提交按钮被切在视口外。
   min-width:0 同理，防止长邮箱把两栏撑歪。 */
.modal__shot, .modal__panel { min-width: 0; min-height: 0; }

/* 深色模式第 1 条：系统深色下强制浅色渲染，杜绝控件「黑底黑字」 */
.modal__dialog *, .modal__dialog *::before, .modal__dialog *::after { color-scheme: light; }

/* --- 图窗 --- */
.modal__shot { position: relative; min-height: 320px; background-color: var(--ink-void); overflow: hidden; }
.modal__shot img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 62% 46%; opacity: .9; }
.modal__copy {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: var(--s-lg) var(--s-md) var(--s-md);
  background-image: var(--scrim-img);
  color: var(--fg-1);
}
.modal__copy b {
  display: block;
  font-family: var(--f-display); font-weight: var(--w-display);
  font-size: 26px; line-height: var(--lh-tight); letter-spacing: var(--ls-title);
  text-transform: uppercase; margin-bottom: var(--s-xs);
  /* &#9940; 必须显式写 color。全局 `b{color:<深色>}` 会让压在照片上的标题掉到 1.1:1。
     本站 design-tokens.css 已把 b 设为 color:inherit，这里再显式一次做双保险。 */
  color: var(--text);
  text-shadow: var(--text-shadow-hero);
}
.modal__copy span { font-size: var(--fs-body-s); line-height: var(--lh-ui); color: var(--text-2); }
/* 窄屏要隐掉整块时得压过 `.modal__copy` 的 position/display ——
   属性选择器与单类选择器优先级同级，靠这里的位置（在后面）取胜。 */
.modal__copy[hidden] { display: none; }

/* --- 表单面板 --- */
.modal__panel {
  position: relative;
  padding: var(--s-lg) var(--s-lg) var(--s-md);
  /* 深色模式第 2 条：显式底色 + 字色，不靠继承。
     用 --canvas(#101315) 而不是 --surface-strong(#1E2427)：面板是**长文本 + 表单**，
     --steel 标签色在 --surface-strong 上只有 3.97:1（闸门的 3:1 过，AA 的 4.5:1 不过），
     在 --canvas 上是 5.36:1。弹窗是转化点，标签必须读得清。 */
  background-color: var(--canvas);
  color: var(--fg-2);
  overflow-y: auto;
}
.modal__close {
  position: absolute; top: var(--s-sm); right: var(--s-sm);
  display: flex; align-items: center; justify-content: center;
  width: var(--s-touch); height: var(--s-touch); padding: 0;
  background-color: transparent; color: var(--fg-1);
  border: 1px solid var(--rule-strong); border-radius: var(--r-none);
  cursor: pointer; transition: var(--transition-ctl);
}
.modal__close:hover { background-color: rgba(255, 255, 255, .08); border-color: var(--brand); box-shadow: var(--e-1); }
.modal__close svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
.modal__kicker { display: block; }
.modal__panel h2, .modal__panel h3 { margin-top: var(--s-xs); color: var(--fg-1); max-width: 24ch; font-size: 30px; line-height: var(--lh-tight); }
.modal__sub { margin: var(--s-xs) 0 var(--s-md); font-size: var(--fs-body-s); line-height: var(--lh-ui); color: var(--text-2); max-width: 46ch; }

/* --- 表单本体：1px 边框 + 全大写 mono 标签，不通体铺色 --- */
.iform { display: block; }
.iform__box { display: block; min-width: 0; }
.iform__row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-sm); }
.field { display: block; margin: 0 0 var(--s-sm); }
.field__label {
  display: block; margin-bottom: 7px;
  font-family: var(--f-mono); font-size: var(--fs-label);
  letter-spacing: .14em; text-transform: uppercase; color: var(--fg-label);
}
.field input[type="text"], .field input[type="email"], .field textarea, .field select {
  width: 100%; min-height: var(--s-touch); padding: 11px 13px;
  background-color: var(--paper); color: var(--ink);
  border: 1px solid var(--rule-strong); border-radius: var(--r-none);
  font-family: var(--f-body); font-size: var(--fs-body); font-weight: var(--w-regular);
  transition: var(--transition-ctl);
}
.field textarea { min-height: 110px; resize: vertical; }
.field input:hover, .field textarea:hover, .field select:hover { border-color: var(--brand); }
.field input:focus-visible, .field textarea:focus-visible, .field select:focus-visible {
  outline: none; border-color: var(--brand); box-shadow: var(--focus-ring);
}
.field__unit {
  display: block; margin-top: 6px;
  font-family: var(--f-mono); font-size: var(--fs-micro);
  letter-spacing: .06em; color: var(--fg-label);
}
/* &#9940; 深色模式第 3 条：select 的 option 显式给字色与底色 */
.field select option { color: var(--ink); background-color: var(--paper); }

/* 勾选行（勾选项不计入「文本字段 <=5」） */
.ticks { display: grid; gap: 0; margin: 0 0 var(--s-sm); }
.tick {
  display: flex; align-items: flex-start; gap: 11px;
  padding: 10px 0; border-bottom: 1px solid var(--hair-1);
  cursor: pointer; transition: var(--transition-ctl);
}
.tick:hover { color: var(--fg-1); }
.tick input { flex: 0 0 auto; width: 17px; height: 17px; margin: 2px 0 0; accent-color: var(--brand); }
.tick__txt { font-size: var(--fs-body-s); color: var(--fg-2); }
.tick__txt b { display: block; color: var(--fg-1); font-weight: var(--w-regular); }
.tick__txt span { display: block; margin-top: 3px; font-family: var(--f-mono); font-size: var(--fs-micro); letter-spacing: .04em; color: var(--fg-label); }

.iform__actions { display: flex; flex-wrap: wrap; gap: var(--s-xs); align-items: center; margin-top: var(--s-md); }
.iform__note { display: block; margin-top: var(--s-sm); font-size: 11.5px; line-height: var(--lh-body); color: var(--fg-label); }

/* 无 JS 回退：原生 POST 提交后落到 /contact/ 的成功锚点 */
.form-success { border: 1px solid var(--brand); background-color: rgba(224, 80, 32, .08); padding: var(--s-md); }
.form-success h3 { color: var(--fg-1); font-size: 24px; }
.form-success p { margin: var(--s-xs) 0 0; color: var(--fg-2); font-size: var(--fs-body-s); }

/* --- 窄屏：单栏，图窗压成横幅，整框滚 --- */
@media (max-width: 780px) {
  .modal { padding: var(--s-xs); }
  .modal__dialog {
    grid-template-columns: 1fr;
    grid-template-rows: auto auto;   /* 单栏时图窗 + 面板两行，各按内容高 */
    max-height: 94vh;
    overflow-y: auto;                /* 窄屏靠整框滚，不靠面板内部滚 */
  }
  .modal__shot { min-height: 132px; }
  /* 图窗上的文案与面板自己的标题+承诺语说的是同一件事，窄屏隐掉，
     否则图片被压得不够高、文案被边框裁掉（实测「上缘被切」）。 */
  .modal__copy { display: none; }
  .modal__panel { padding: var(--s-md) var(--s-md) var(--s-lg); overflow-y: visible; }
  .iform__row { grid-template-columns: 1fr; }
  .modal__panel h2, .modal__panel h3 { font-size: 24px; }
}

/* ============================ 16 · 404 / Ads 落地 / 文章框架 =============
   三个页型自己的版式由 Phase 3 写；这里只给**共用的骨架类**，
   省得它们再各自发明一遍（也保证「无内联 style」这条在这三页同样成立）。
   ========================================================================= */
.center-stage {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  min-height: 70svh; text-align: center; padding-block: var(--s-2xl);
}
.center-stage .h1 { font-size: clamp(88px, 12vw, 180px); max-width: none; }
.center-stage .lead { max-width: 44ch; margin-top: var(--s-md); }

/* Ads 落地页：无 header/footer，底部 sticky CTA 条（拇指可达） */
.sticky-cta {
  position: sticky; bottom: 0; z-index: 40;
  display: flex; align-items: center; justify-content: space-between; gap: var(--s-sm);
  padding: var(--s-sm) var(--s-md);
  background-color: rgba(8, 10, 11, .95);
  border-top: 1px solid var(--rule-strong);
  box-shadow: var(--e-2);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
}
.sticky-cta .cap { color: var(--fg-4); }
@media (max-width: 560px) {
  .sticky-cta { flex-direction: column; align-items: stretch; }
  .sticky-cta .cap { display: none; }
}

/* 文章框架（blog 列表/正文的最小骨架） */
.post-list { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-md); margin-top: var(--s-lg); }
.post-card {
  display: flex; flex-direction: column;
  background-color: var(--surface-strong); border: 1px solid var(--rule);
  box-shadow: var(--e-1); transition: var(--transition-ctl);
}
.post-card:hover { border-color: var(--rule-strong); transform: var(--hover-lift); }
.post-card img { width: 100%; aspect-ratio: 3 / 2; object-fit: cover; }
.post-card__body { padding: var(--s-md); }
.post-card__body h3 { font-size: var(--fs-h4); }
.post-card__body p { margin: var(--s-xs) 0 0; font-size: var(--fs-body-s); color: var(--fg-3); }
@media (max-width: 768px) { .post-list { grid-template-columns: 1fr; } }

/* FAQ 手风琴 —— &#9940; JS 必须随组件提供（site.js 里绑 .faq-q 互斥展开） */
.faq { margin-top: var(--s-lg); border-top: 1px solid var(--rule-strong); }
.faq__item { border-bottom: 1px solid var(--rule); }
.faq__q {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s-md);
  width: 100%; padding: var(--s-md) 0;
  background-color: transparent; border: 0; cursor: pointer; text-align: left;
  font-family: var(--f-body); font-size: var(--fs-body); font-weight: var(--w-regular);
  color: var(--fg-1); transition: var(--transition-ctl);
}
.faq__q:hover { color: var(--brand-ink); }
.faq__q::after { content: "+"; font-family: var(--f-mono); font-size: 16px; color: var(--brand-ink); flex: 0 0 auto; }
.faq__item.is-open .faq__q::after { content: "\2212"; }
/* &#9940; 用 grid-template-rows 0frto1fr 做展开，不用 max-height 猜数 */
.faq__a { display: grid; grid-template-rows: 0fr; transition: grid-template-rows var(--t-base) var(--ease); }
.faq__item.is-open .faq__a { grid-template-rows: 1fr; }
.faq__a > div { overflow: hidden; min-height: 0; }
.faq__a p { margin: 0 0 var(--s-md); font-size: var(--fs-body-s); color: var(--fg-3); line-height: var(--lh-copy); max-width: var(--measure); }
.faq__a p + p { margin-top: var(--s-xs); }

/* ============================ 17 · 计量单位与数值排版 ==================== */
.unit { color: var(--fg-label); font-family: var(--f-mono); font-size: .92em; letter-spacing: .04em; }
.kv-inline { display: inline-flex; align-items: baseline; gap: 6px; }
.nowrap { white-space: nowrap; }

/* 表格横向滚动兜底：窄屏不许把版心撑破（不许横向溢出） */
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.table-scroll > table { min-width: 560px; }

/* ============================ 18 · `hidden` 兜底（必须放在最后） =========
   组件类普遍写了 `display:flex/block`。`[hidden]` 的属性选择器与单类选择器
   优先级**同级**（都是 (0,1,0)），谁赢只看**出现顺序** —— 所以这一条必须排在
   全文所有 display 声明之后，否则 `hidden` 会被无声忽略
   （事故形态：用户提交后表单藏不住，成功提示和表单同时出现在弹窗里）。
   ========================================================================= */
[hidden] { display: none; }

/* ============================ 19 · 减少动效 ==============================
   &#9940; 这里**必须放在文件最后**，而且**不能用 `*, *::before, *::after` 这个选择器**。
   两块坑叠在一起会变成真事故（实测过）：
     ① `*{…!important}` 与 `@media(...){*{…!important}}` 是**同源、同重要性**的两个声明，
        `!important` 之间比的是**出现顺序** —— 谁在后面谁赢。
        所以这条媒体查询如果排在 `.btn{transition: var(--transition-ctl)}` 后面，
        它反而会把**所有人的**过渡都压成 1ms（没开 reduced-motion 也一样），
        而真正开着的用户因为「更长的时长写在前面」，拿不到减少动效的效果。方向正好反了。
     ② 选择器若写成 `*, *::before, *::after`，与 §0 的 box-sizing 复位**字符串相同**，
        check-css-conflicts.py 会判 FAIL（单一权威源）。
   现在：§0 是**普通声明**（box-sizing，与动效无关，不会被这条 !important 影响），
   本条用 `*` 单选择器，字符串不再重复，且作为最后一个 !important 声明真正生效。
   `*` 已覆盖元素本身；伪元素自己的过渡极少，且正文型内容不依赖伪元素承载。 */
@media (prefers-reduced-motion: reduce) {
  * {
    transition-duration: 1ms !important;
    animation-duration: 1ms !important;
  }
}
