/* ==========================================================
   type-tokens.css — 排版 token 层 (Backlog #157 新建)
   ------------------------------------------------------------

   加载序: CSS 第 1 / 37 (index.html <head> 第 1 个 <link>; 后加载的覆盖先加载的)
   ★ 全站 37 个 CSS 的完整加载序 + 职责表见 index.html 头注释「📂 文件结构速查」
     (单一事实源 —— 旧版 19 个文件各抄一份清单, 且停在 25/26/28/31 四个旧版本;
      加一个 CSS 要改 19 处, 编号还是"分组号"而非真实加载位, 现已收敛)
   物理分层原则: 不使用 CSS @import, 直接在 index.html
   最前面用 <link> 引入 (保证 file:// 协议下零 CORS 错误运行)

   加载顺序: 本文件必须是 **第一个** CSS <link> (早于 base.css),
             因为后续所有文件都在用这里的变量。

   ------------------------------------------------------------
   【本文件解决什么】
   审计 (Backlog #156) 实测: 31 个 CSS 共 **438 条** font-size 声明、
   **98 个不同声明值**, 其中 42% 只出现一次 —— 每个区块各自调自己的
   字号, 没有任何共享轨道。

   本文件建立 6 级 × 2 变体 = 12 个排版 token, 作为**唯一**的字号来源。

   ------------------------------------------------------------
   【铁律 · 不可 token 化的三类值】
   本轮迁移**故意跳过**以下三类, 任何后续轮次也不许动:

     1. clamp(...)  — 12 处, 全在 scene.css (hero 标题) + portfolio-entry.css
                      (卡面水印)。**固化会杀死视口响应式**:
                      例如 clamp(1.5rem, 2.8vw, 2.2rem) 在 1440px 下算出
                      35.2px, 但那是「vw 解析到上限」的结果, 不是作者意图
                      的定值。换成 var(--type-xxx) 后整个 clamp 语义消失。

     2. calc(...)   — 5 处, 全在 resume-experience.css
                      (calc(1em * var(--resume-cn-scale)))。它是**按父级
                      字号等比缩放**的双语简历逻辑, 一旦换成绝对 token
                      就会破坏中英缩放关系。

     3. em 单位     — 9 处 (0.95em / 0.78em / 0.5em ...)。em 相对**父元素**
                      字号, 与 rem/px 不同源, 换 token 即语义变更。

   → 这三类共 26 条, 占 6%, 是**有意保留的例外**, 不是遗漏。

   ------------------------------------------------------------
   【12 个 token 的取值依据】
   全部取自**实测的实际渲染值** (Playwright 多视口采样, 见
   .trash/_b157b_baseline.json), 不是凭空设计的比例尺。理由:
   本轮目标是「归位」不是「重设计」—— token 的值必须等于现值,
   替换后计算样式零差异, 视觉不变。

   后续轮次若要真正拉平长尾 (8.5 / 9.5 / 10.5 / 11.5 / 12.5 / 12.8 /
   13.6 / 14.4 / 14.72 ... 共 73 条), 那属于**视觉变更**, 必须单独立项 +
   截图逐条确认, 不能混进本轮。

   ------------------------------------------------------------
   【非排版角色 — 不属于 type scale】
   字号阶梯管的是「文字」。以下三个是**图标尺寸**与**装饰尺寸**,
   跟着文字的 token 走会在换字号时把图标一起改坏, 所以单列:
     --icon-collage    .collage-card-icon  (emoji, 42px)
     --icon-entry      .entry-emoji        (emoji, 36px)
     --decor-watermark .card-watermark     (字母水印, 192px)
   ========================================================== */

:root {

  /* ══════════════════════════════════════════════════════
     排版层级 · 6 级 × 2 变体 = 12 个值
     变体命名 -sm = 同层级内的次级信息 (比主值小一档)
     ══════════════════════════════════════════════════════ */

  /* ── display · 页面级大标题 ── */
  --type-display:       3rem;        /* 48px   h2.section-title */
  --type-display-sm:    2.8rem;      /* 44.8px h2.life-collage-main-title */

  /* ── title · 区块 / 卡片主标题 ── */
  --type-title:         1.8rem;      /* 28.8px 模态标语 / 分类标题 */
  --type-title-sm:      1.4rem;      /* 22.4px 小节内标题 */

  /* ── section · 小节标题 ── */
  --type-section:       1.3rem;      /* 20.8px h3.collage-card-title */
  --type-section-sm:    1.05rem;     /* 16.8px .about-me-card-subtitle */

  /* ── body · 正文 ── */
  --type-body:          0.95rem;     /* 15.2px 首屏副标题 / 全站最高频非 micro 值 */
  --type-body-sm:       0.8125rem;   /* 13px   h3.project-title */

  /* ── caption · 说明 / 副标 ── */
  --type-caption:       0.75rem;     /* 12px   .entry-title-cn */
  --type-caption-sm:    0.6875rem;   /* 11px   .floater-name / .resume-module-tag (全站第 2 高频) */

  /* ── micro · 元信息 ── */
  --type-micro:         0.625rem;    /* 10px   .entry-meta-* (全站最高频) */
  --type-micro-sm:      0.5625rem;   /* 9px    .floater-sub */

  /* ══════════════════════════════════════════════════════
     非排版角色 · 图标 / 装饰尺寸
     (不随 type token 联动, 见文件头注【非排版角色】)
     ══════════════════════════════════════════════════════ */
  --icon-collage:       2.625rem;    /* 42px  .collage-card-icon */
  --icon-entry:         2.25rem;     /* 36px  .entry-emoji */
  --decor-watermark:    12rem;       /* 192px .card-watermark */
}


/* ==========================================================
   ── 间距阶梯 (Backlog #159) ──
   ------------------------------------------------------------
   实测 (matchAll 口径, 排除本文件): margin / padding / gap 共
   731 个 px 取值, 分布在 36 个不同值上。

   本阶梯取其中能被**精确命中**的 14 档 —— 只做「值 → token」的
   等价替换, **不吸附**。实际替换 571 处。

   剩下的是 1 / 3 / 5 / 7 / 9 / 11 / 13 / 14 / 15 / 18 / 21 / 22 / 26 /
   28 / 30 / 36 / 38 / 42 / 44 / 50 / 60 / 70 / 80px, 吸附它们会改
   视觉, 需单独立项 (与 198 条长尾字号同批)。

   为什么是 14 档而不是 8 档: 8 档只能精确覆盖 60%, 14 档才到 67%。
   宁可 token 多几个, 也不在「token 化」的名义下偷偷改视觉。
   ──────────────────────────────────────────────────────── */
:root {
  --space-1: 2px;
  --space-2: 4px;
  --space-3: 6px;
  --space-4: 8px;
  --space-5: 10px;
  --space-6: 12px;
  --space-7: 16px;
  --space-8: 20px;
  --space-9: 24px;
  --space-10: 32px;
  --space-11: 40px;
  --space-12: 48px;
  --space-13: 56px;
  --space-14: 64px;
}

/* ==========================================================
   ── 字体族 (Backlog #159) ──
   ------------------------------------------------------------
   实测: font-family 共 174 条声明 / 36 种不同写法。

   之所以是「36 种」而不是「几个字体」, 是因为**同族不同序**:
   'Cinzel','Playfair Display',serif 与
   'Cinzel','Playfair Display','PingFang SC',…,serif 的回退链不同,
   渲染结果可能不同。

   铁律: 本层**只收逐字符完全相同的整条栈**。任何顺序调整、
   增删回退项都属于视觉变更, 不在本轮。覆盖 130 / 174 = 75%,
   剩余 44 条零散写法 (含 inherit / var() / 单字体) 保持原样。
   ──────────────────────────────────────────────────────── */
:root {
  --font-display: 'Cinzel', 'Playfair Display', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, 'PingFang SC', sans-serif;
  --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, 'PingFang SC', sans-serif;
  --font-mono: 'JetBrains Mono', 'SF Mono', Consolas, monospace;
  --font-serif-tnr: 'Cinzel', 'Times New Roman', serif;
  --font-serif-cjk: 'Cinzel', 'Playfair Display', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'Noto Sans CJK SC', Georgia, serif;
  --font-serif: 'Cinzel', 'Playfair Display', serif;
  --font-sans-latin: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;
  --font-cjk: 'PingFang SC', -apple-system, BlinkMacSystemFont, sans-serif;
  /* [Backlog #286 · 2026-10-25] 正文衬线(**真小写**): Playfair Display 打头。
     为什么不能复用 --font-serif / --font-display / --font-serif-cjk:
       那三个**都以 Cinzel 开头**, 而 Cinzel 的小写字母是**小型大写**(small caps)
       字形 ⇒ 拿它写英文正文, 无论加不加 text-transform:uppercase,
       读起来都是一串大写字母(§286 的实测痛点就是这个)。
     这个 token 是「正文可读性」与「站点的 Cinzel 声音」之间的分工点:
       模块名/标语 → Cinzel(--font-display) · 英文散文 → 本 token */
  --font-serif-body: 'Playfair Display', Georgia, 'Times New Roman', serif;
}

/* ==========================================================
   ── 语义色 (Backlog #159) ──
   ------------------------------------------------------------
   实测: 颜色属性共 620 条声明 / 74 种不同 hex。

   **刻意不收敛**: 这 74 个 hex 绝大多数是各模块自己的调色
   (紫 6b4d8a / 铜 b87333 / 洋红 e44693 / 青 00f2fe …),
   塞进 3 个 role 等于抹掉设计。

   本层只做一件事: 把两个**贯穿全站**的主色提成 role token,
   给换肤留一个入口:
     --role-paper  #f7f1e1  米白   替换 21 处
     --role-sea    #006478  海青   替换 24 处

   ⚠ **没有 --role-diver**: #156 审计提的「米白 / 海青 / 潜水员
   三色」里, 「潜水员」不是单一颜色 —— 它是 14 块卡纸拼贴
   (躯干 #b53a25 暗红 / 金黄腰带 #f5c542 / 浅青镜片 #b0e0e6 …)。
   实测这四个部件色在全部 CSS **和** JS 里各 0 次, 没有可 token 化的
   单一色值。PROJECT_NOTES §潜水员 的部件表与代码不同源,
   不可据此造 token。

   ⚠ **#e8e2d3 与 #f7f1e1 是两个不同的米白** (base.css --paper-bg
   vs --role-paper), 不要合并。
   ──────────────────────────────────────────────────────── */
:root {
  --role-paper: #f7f1e1;
  --role-sea: #006478;
}


/* ==========================================================
   ── 图标 / 装饰尺寸 (Backlog #159) ──
   ------------------------------------------------------------
   198 条长尾拉平时分出的一类: 这些声明写在 `font-size` 上, 但
   尺寸对象是**图标字形** (emoji / 关闭按钮 / 缩放按钮 / 占位符),
   不是文字。归到 `--type-*` 在语义上是错的 —— 它们有自己的档位。

   本层把它们提成 `--icon-*`, 与 #157 已有的
   `--icon-collage` / `--icon-entry` 同族。
   ──────────────────────────────────────────────────────── */
:root {
  --icon-modal: 1.5rem;   /* .collage-modal-icon 原 24px */
  --icon-reading: 0.9375rem;   /* .reading-col-icon 原 15px */
  --icon-emoji: 0.875rem;   /* .tooltip-marathon-emoji 原 14px */
  --icon-entry-lg: 1.75rem;   /* .entry-emoji 原 28px */
  --icon-close: 1.375rem;   /* .image-lightbox-close 原 22px */
  --icon-zoom: 0.875rem;   /* .zoom-controls button 原 14px */
  --icon-footer: 1rem;   /* .site-footer-symbol 原 16px */
}

/* ── #159 补充: 其余图标尺寸 (原为 --type-*, 尺寸对象是字形不是文字) ── */
:root {
  --icon-x1-card: 1.25rem;   /* .x1-card-icon 原 20px */
}

/* ── #159 补充: 关闭按钮 / 缩放标签 / emoji / 占位图标 ──
   尺寸对象是字形不是文字, 归 --type-* 在语义上是错的, 提为 --icon-*。
   值 = 原 --type-* 的值, 因此**视觉零变化**。 */
:root {
  --icon-close-modal: 1.3rem;   /* 强制覆盖任何遮挡层 悬停: 红色背景 + 边框 + 文字 (强调"危险操作"语义 原 --type-section */
  --icon-reading-now: 0.75rem;   /* .reading-reading-now__icon 原 --type-caption */
  --icon-journey: 0.8125rem;   /* .travel-journey-emoji 原 --type-body-sm */
  --icon-city: 0.6875rem;   /* .travel-city-emoji 原 --type-caption-sm */
  --icon-logo-placeholder: 2.8rem;   /* .project-logo-wrapper:empty::before 原 --type-display-sm */
  --icon-close-pdf: 1.4rem;   /* .pdf-close-button 原 --type-title-sm */
  --icon-zoom-label: 0.75rem;   /* 8. PDF 缩放等级 + 控件 (右下角浮窗) =============== 原 --type-caption */
  --icon-x1-card: 1.3rem;   /* .x1-elegant-text .x1-card-icon 原 --type-section */
  --icon-close-resume: 1.4rem;   /* .resume-modal-close 原 --type-title-sm */
  --icon-race: 1rem;   /* [Backlog #226] .mc-race-emoji 赛事卡的标识 emoji; 与标题(15px)同量级 */
}


/* ==========================================================
   ── 层叠契约 (Backlog #161) ──
   ------------------------------------------------------------
   `#156` 审计实测: 全站 657 个 position:absolute + 20 个 fixed,
   z-index 从 0 一路散到 2147483647, 跨 9 个数量级, **没有任何分带**。
   后果实测: 简历区 floater 文字 ("2024-26 / CUHK / M.Arch") 矩形内部,
   4 个装饰层**全部**在绘制 (clip 像素 diff 20/20 命中)。

   本层把层叠关系**成文**, 四个平面:

   ┌ 浮层平面   z ≥ 100      模态 / 抽屉 / 灯箱 (全是 6-7 位数, 天然在内)
   ├ 混合层     99998/99999  body::before / ::after 纸纹  ← **例外**
   ├ 内容平面   z 10 / 20     .content-section / .seaweed-label-layer
   └ 背景平面   z -5 … -2     点阵 / 海草 / 潜水员 / 焦散

   ⚠ **为什么需要第四个「混合层」**: 纸纹两层用
   mix-blend-mode: screen / overlay。它们必须**高于内容**才能对内容
   做混合着色; 压到 z < 1 会让它们只与 body 背景混合, 卡纸纹理整体失效。
   这是 `#156` 的三平面提案没覆盖的情况 —— 实施时发现, 补为第四平面。

   铁律: 新增装饰层一律进**背景平面**; 想让装饰压住内容必须先改这份契约。
   ──────────────────────────────────────────────────────── */
:root {
  /* 背景平面 —— 装饰, 永远在内容之下 */
  --z-bg-deep: -5;        /* #dotMatrixCanvas   八边点阵 (SHELVED) */
  --z-bg-seaweed: -4;     /* #seaweedCanvas     远/中景海草 + 光柱 + 粒子 */
  --z-bg-diver: -3;       /* #diverOverlayCanvas 前景潜水员 */
  --z-bg-caustics: -2;    /* #causticsCanvas    顶部水面焦散 */

  /* 内容平面 —— 卡片与文字 */
  --z-content: 10;        /* .content-section   所有 section 容器 */
  --z-content-label: 20;  /* .seaweed-label-layer 全站 section 索引 */

  /* 浮层平面 —— 模态 / 抽屉 / 灯箱, 现有值全是 6-7 位数, 天然满足 ≥100 */
  --z-float: 100;

  /* 混合层 —— 纸纹, 见上面的例外说明 */
  --z-blend-fiber-light: 99998;
  --z-blend-fiber-dark: 99999;
}
