/* ============================================================================
   小米 MiSans 网页字体注册（客户 2026-11-05 第 7 条：
   「系统和打印 PDF 文件的字体全部使用小米字体」）

   ── 字体来源与署名 ──────────────────────────────────────────────────────
   字体：MiSans（小米，与汉仪字库合作开发），母版是 static/fonts/ 下的
   MiSans-Regular.ttf / MiSans-Bold.ttf。小米官方声明 MiSans 免费商用，
   所以把子集后的 woff2 下发到浏览器（属于二次分发）是允许的。
   子集产物里保留了 name 记录：0=版权、8=制造商(汉仪)、9=设计方、
   11=厂商网址 —— 署名信息不能因为「省几个 KB」被裁掉。
   注意：原始字体的 name 13/14（许可证描述/URL）本来就是空的，
   小米没有把许可证正文写进字体，所以许可证说明以本节文字为准。

   ── 为什么只有两个 @font-face ───────────────────────────────────────────
   客户批准只做 Regular(400) + Bold(700)。界面与 SOP 卡片只用到这两档
   （标题 700、正文 400），Medium(500) 没有任何地方引用，多做一份只是
   让首屏多下 0.86MB。
   ★ 这两个字重内部的 OS/2 usWeightClass 分别是 330 / 630（MiSans 的原始
     设定）。这里不去改它：浏览器匹配字重看的是下面的 font-weight 描述符，
     不是字体内码；写 400/700 才能和 CSS 里的 font-weight: 400/700 对上。
     看到 330/630 不要「顺手修正」成 400/700 —— 那要重跑子集脚本，而收益为零。

   ── 子集化范围（这是子集，不是全量字体）────────────────────────────────
   由 scripts/subset_fonts.py 生成，收录：
     · ASCII 可打印区 0x20-0x7E
     · GB2312 全部汉字与符号（6763 汉字 + 682 符号）
     · 打印常用补充符号 ×÷±°℃㎏㎎·—…“”‘’《》〈〉【】％／＃＆ 以及 ¥ − –
   实测每字重 7547 个码位；Regular 899,648 字节 / Bold 919,232 字节
   （母版各约 8MB，子集后约为源体积 11%）。
   超出范围的字符会回退到系统字体（已验证：生僻字宽度与回退字体一致，
   即正常回退，不会出现豆腐块）。要扩范围就改脚本重跑，别手工重做子集。

   ── 为什么 src 用绝对路径 /static/fonts/... ─────────────────────────────
   编辑页「导出 PDF」的做法是：window.open('', '_blank') 拿到一个空白窗口，
   再 document.write() 拼整页 HTML。那个新文档的 URL 是 about:blank，
   baseURI 继承自打开它的页面（实测 Chromium：baseURI = 打开者页面的 URL）。
   三种写法实测结果（Edge 156 / Chromium 内核，@font-face 在 about:blank
   文档里的 document.fonts 状态）：

     url("/static/fonts/x.woff2")                → loaded   ✅
     url(location.origin + "/static/fonts/x")    → loaded   ✅
     url("static/fonts/x.woff2")（相对路径）      → error    ❌
       相对路径按打开者页面所在目录（/static/app/）解析，
       实际请求 /static/app/static/fonts/... 必然 404，@font-face 静默失效，
       PDF 回落系统字体 —— 客户看到的仍是「两种字体」。

   所以绝对路径不是风格偏好，是 about:blank 文档里唯一可靠的写法。
   将来若导出改成 iframe/srcdoc 或拼接方式变化，这条结论要重新验证，
   不要假设它永远成立。

   ── 为什么 font-display: swap ───────────────────────────────────────────
   0.86MB 不算小，首次加载需要时间。swap 让文字先用系统字体立刻可见，
   字体到位后替换，避免首屏白字。
   ★ 打印侧不受 swap 影响的前提是：打印前等 document.fonts.ready。
     若不等，打印机可能在字体还没到位时就抓取版面，纸上就会出现系统字体。
     这一步在阶段二接入导出流程时处理，改这里解决不了。

   ── 为什么 url 带 ?v=<指纹>，而引本文件时却**不带** query ──────────────
   后端（app/main.py 的 _StaticCacheControl）对静态资源分档：
     · .woff2 带 ?v=非空 → public, max-age=31536000, immutable
     · .woff2 不带 ?v=   → 兜底档 public, max-age=86400
     · .css  带 ?v=      → immutable
     · .css  不带 ?v=    → no-cache（每次回源验证，内容没变只回 304，几十字节）

   ① 字体文件（woff2）必须 immutable：它 0.86MB，是最值得缓存的东西。
      immutable 的收益不是省掉这 0.86MB，而是省掉到期后的那趟条件往返。
   ② 但 `?v=` 的值是**算出来的**，不是人填的：`scripts/subset_fonts.py` 生成 woff2 后
      把 sha256 前 8 位写进下面两行。换字体只需跑一次脚本，忘记改版本号这件事
      在结构上不存在（手填的数字始终有"忘了改"这个失效方式，而它的后果是
      客户端拿着 immutable 的旧字体一年不更新、链路上零报错）。
   ③ 引用本文件时**故意不带 ?v=**：如果 <link href="/static/css/font.css?v=1">，
      那 font.css 自己也变成 immutable，于是"换字体"就要求两个版本号同进——
      改了字体文件却没改 CSS 链接，浏览器一年不重取 font.css，继续请求旧 woff2 地址，
      等于换字体这件事没发生。把外层 query 去掉（走 no-cache）之后，耦合消失：
      只剩一个数字，且由脚本维护。代价是每次导航多一趟 304，内网 RTT 个位数毫秒，
      用这个换掉"漏改一处静默失效一年"是划算的。
      ⇒ 所以 19 个页面的 <link> 一律写 `href="/static/css/font.css"`，不带任何 query。
         _verify/probe_font_wiring.js 有断言钉住这一点（带 query 就红）。
   ========================================================================== */

@font-face {
  font-family: "MiSans";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/static/fonts/MiSans-Regular.subset.woff2?v=b63ae57f") format("woff2");
}

@font-face {
  font-family: "MiSans";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("/static/fonts/MiSans-Bold.subset.woff2?v=63daa7de") format("woff2");
}
