/* ==========================================================================
   谷素军 · 个人简历网站
   结构：顶部姓名+导航 → 简历（左经历 / 右档案）→ 作品集 → 设计研究 → 联系我
   风格：B 瑞士网格 + 柔光玻璃（玻璃用于项目卡与联系区，简历区保持纯净排版）
   栅格：1440 容器 / 边距 80 / 内容 1280 / 12 栏 / 间距 24
   ========================================================================== */

/* ---------- tokens ---------- */
:root{
  --canvas:#F4F6F8;
  --surface:#FFFFFF;
  --ink:#111111;
  --ink-2:#3B434F;      /* 次级深灰：右栏档案 / 荣誉用，比 --ink 收敛 */
  --sub:#5F6774;        /* 描述性正文：canvas 上 5.27:1，兼顾「弱于标题」与 WCAG AA */
  --mute:#68717E;       /* 标签 / 图注 / 小字：canvas 上 4.56:1，AA 下限之上 */
  --line:#E6E8EC;
  --line-2:#C9CFD8;     /* 结构线：图（结构图 / 曲线 / 行为地图）的连线，比 --line 清楚一档 */
  --accent:#FF4D2D;
  --accent-ink:#C63116; /* 强调色的「文字版」：#FF4D2D 当文字只有 3.05:1，这个 5.03:1 */
  --on-accent:#FFFFFF;  /* 强调色块上的文字/图标：图标按 3:1 过；文字 3.31:1，仅限大字号粗体 */
  --glow1:#7C9CFF;
  --glow2:#A78BFA;
  --glow3:#67E8F9;

  --gutter:24px;
  --margin:80px;
  --content:1280px;
  --wrap:min(var(--content), calc(100% - var(--margin) * 2));
  --measure:960px;      /* 正文阅读栏宽：单句陈述句不折行所需的宽度，与图行右边缘对齐 */

  /* 字号阶：L1–L4 是主阶（锁定的 4 档），L2b/L2c/L3b/L4b 是字阶的辅助级，
     用来收编原先散落在各处的写死 px —— 全部登记在 design-spec.md 与 design-tokens.json */
  --t1:clamp(38px, 6.6vw, 96px);      /* L1   Hero 主标题 */
  --t2:clamp(22px, 2.8vw, 40px);      /* L2   区块标题 */
  --t2b:clamp(22px, 2.2vw, 28px);     /* L2b  页头姓名 */
  --t2c:clamp(26px, 2.5vw, 34px);     /* L2c  详情页二级标题 h2（v7 从 24 提到 34：章节头是版面唯一的层级抓手） */
  --t2d:clamp(20px, 1.6vw, 22px);     /* L2d  块内主张：小节里那句被放大来压住整块的话 */
  --t3:clamp(16px, 1.25vw, 18px);     /* L3   正文 / 条目标题 / 小节 h3 */
  --t3b:15px;                         /* L3b  简历正文：信息密度例外，按原设计不缩放 */
  --t4:clamp(13px, .97vw, 14px);      /* L4   标签 / 说明 / 页脚 */
  --t4b:12px;                         /* L4b  图注 / 等宽小字 */
  --t-stat:clamp(30px, 3.4vw, 48px);  /*      指标数字 */

  --r-card:24px;
  --r-thumb:14px;
  --r-pill:999px;
  --r-stage:32px;

  --sec:clamp(72px, 8.6vw, 136px);
  --block:clamp(36px, 5vw, 72px);

  --glass-fill:linear-gradient(180deg,rgba(255,255,255,.70),rgba(255,255,255,.52));
  --glass-blur:32px;
  --glass-sat:180%;
  --glass-line:rgba(255,255,255,.9);
  --glass-shadow:0 12px 32px rgba(18,23,38,.10);
  --glass-shadow-lift:0 26px 60px rgba(18,23,38,.17);
  --glass-inner:inset 0 1px 0 rgba(255,255,255,.95), inset 0 0 0 1px rgba(255,255,255,.34);

  /* 字体栈：西文走自托管 Inter，中文走自托管 Noto Sans SC（按本站用字子集化），
     系统字体只作兜底 —— 保证 macOS / Windows / 安卓三端字形一致。
     中国大陆不引入任何外部字体域名，详见 assets/fonts.css 顶部说明 */
  --font:'Inter','Noto Sans SC','PingFang SC','HarmonyOS Sans SC','Microsoft YaHei',system-ui,-apple-system,sans-serif;
  --mono:'JetBrains Mono','Noto Sans SC',ui-monospace,SFMono-Regular,Menlo,Consolas,'PingFang SC','Microsoft YaHei',monospace;
}

/* ---------- reset ---------- */
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth;overflow-x:clip}
body{
  margin:0;background:var(--canvas);color:var(--ink);
  font-family:var(--font);font-size:var(--t3);line-height:1.7;
  -webkit-font-smoothing:antialiased;overflow-x:clip;
}
img{max-width:100%;display:block}
a{color:inherit;text-decoration:none}
h1,h2,h3,h4,p,ul,ol,figure{margin:0}
ul,ol{padding:0;list-style:none}
:focus-visible{outline:2px solid var(--accent);outline-offset:3px;border-radius:4px}
::selection{background:rgba(255,77,45,.16)}

/* ---------- grid ---------- */
.wrap{width:var(--wrap);margin-inline:auto}
.grid{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:var(--gutter)}

/* ---------- type ---------- */
.l1{font-size:var(--t1);font-weight:700;line-height:1.06;letter-spacing:-.03em}
.l2{font-size:var(--t2);font-weight:600;line-height:1.2;letter-spacing:-.01em}
.l3{font-size:var(--t3);font-weight:400;line-height:1.7}
.l4{font-size:var(--t4);font-weight:400;line-height:1.6}
.mono{font-family:var(--mono);font-weight:500}
.eyebrow{
  font-family:var(--mono);font-weight:500;font-size:var(--t4);
  letter-spacing:.08em;text-transform:uppercase;color:var(--mute);
}
/* 橙色当文字用时统一走 --accent-ink；纯色块 / 图标仍用 --accent */
.accent{color:var(--accent-ink)}
.sub{color:var(--sub)}

/* ---------- ambient glow ---------- */
.ambient{position:absolute;top:0;left:0;right:0;height:900px;overflow:hidden;pointer-events:none;z-index:0}
.ambient .glow{position:absolute;border-radius:50%;filter:blur(150px)}
.glow-1{width:640px;height:640px;background:var(--glow1);top:-400px;right:-150px;opacity:.24}
.glow-2{width:520px;height:520px;background:var(--glow2);top:-410px;right:1%;opacity:.15}
.glow-3{width:420px;height:420px;background:var(--glow3);top:-320px;right:19%;opacity:.10}
main,footer{position:relative;z-index:1}

/* ---------- glass ---------- */
.glass{
  background:var(--glass-fill);
  -webkit-backdrop-filter:blur(var(--glass-blur)) saturate(var(--glass-sat));
  backdrop-filter:blur(var(--glass-blur)) saturate(var(--glass-sat));
  border:1px solid var(--glass-line);
  border-radius:var(--r-card);
  box-shadow:var(--glass-inner), var(--glass-shadow);
}

/* ---------- 手机端浮动「联系我」 ---------- */
.fab{
  display:none;
  position:fixed;
  right:18px;
  bottom:calc(18px + env(safe-area-inset-bottom,0px));
  z-index:70;
  width:56px;height:56px;
  align-items:center;justify-content:center;
  border-radius:var(--r-pill);
  background:var(--accent);color:var(--on-accent);
  box-shadow:0 10px 26px rgba(255,77,45,.34);
  transition:transform .24s cubic-bezier(.22,.7,.3,1),opacity .3s ease,box-shadow .24s ease;
}
.fab svg{display:block}
.fab:hover{box-shadow:0 14px 32px rgba(255,77,45,.42)}
.fab:active{transform:scale(.96)}
.fab:focus-visible{outline:2px solid var(--ink);outline-offset:3px}
/* 联系区进入视口后收起，避免和区块内的 CTA 重复 */
.fab.is-hidden{opacity:0;transform:translateY(14px);pointer-events:none}

/* ---------- masthead ---------- */
.masthead{
  position:sticky;top:0;z-index:60;
  padding:24px 0 20px;
  background:transparent;
  border-bottom:1px solid transparent;
  transition:
    background-color .3s ease,
    border-color .3s ease,
    padding .5s cubic-bezier(.4,0,.2,1);
}
.masthead.stuck{
  padding:17px 0 14px;
  background:rgba(246,247,250,.74);
  -webkit-backdrop-filter:blur(20px) saturate(180%);
  backdrop-filter:blur(20px) saturate(180%);
  border-bottom-color:var(--line);
}
.masthead .row{display:flex;align-items:flex-start;justify-content:space-between;gap:32px}
.masthead .who{display:flex;flex-direction:column;min-width:0}
.masthead .name{font-size:var(--t2b);font-weight:700;letter-spacing:-.02em;line-height:1.25}
.masthead .tag{
  color:var(--sub);font-size:var(--t3b);margin-top:4px;overflow:hidden;
  max-height:30px;opacity:1;
  transform:translateY(0);filter:blur(0);
  will-change:opacity,transform,max-height;
  transition:
    opacity .42s cubic-bezier(.4,0,.2,1),
    filter .42s cubic-bezier(.4,0,.2,1),
    transform .52s cubic-bezier(.22,.7,.3,1),
    max-height .52s cubic-bezier(.4,0,.2,1),
    margin-top .52s cubic-bezier(.4,0,.2,1);
}
/* 吸顶后收起定位语：淡出 + 微微上移 + 极轻失焦，避免生硬地「啪」一下消失 */
.masthead.stuck .tag{opacity:0;filter:blur(5px);transform:translateY(-7px);max-height:0;margin-top:0}
/* 右栏与姓名共用一条中心线：容器高度取姓名行高（--t2b × 行高 1.25），
   内部各项 align-items:center 后，锚点文字与「下载简历」按钮的中线都落在姓名中线上 */
.masthead .menu{display:flex;align-items:center;gap:36px;padding-top:0;height:calc(var(--t2b) * 1.25);flex:none}
.masthead .menu a{font-size:var(--t3b);color:var(--sub);white-space:nowrap;transition:color .18s ease}
.masthead .menu a:hover{color:var(--ink)}
.masthead .menu a[aria-current="true"]{color:var(--accent-ink)}

/* 页头右上角「下载简历」：与四个锚点同排，落在「联系我」右侧 */
.masthead .menu a.dl{
  display:inline-flex;align-items:center;gap:7px;
  padding:9px 17px;border-radius:var(--r-pill);
  background:var(--accent);color:var(--on-accent);
  font-size:var(--t4);font-weight:500;letter-spacing:-.01em;
  box-shadow:0 6px 16px rgba(255,77,45,.26);
  transition:transform .18s ease,box-shadow .18s ease;
}
.masthead .menu a.dl:hover{color:var(--on-accent);transform:translateY(-1px);box-shadow:0 10px 22px rgba(255,77,45,.34)}
.masthead .menu a.dl:active{transform:scale(.97)}
.masthead .menu a.dl svg{display:block;flex:none}

/* ---------- buttons ---------- */
.btn{
  display:inline-flex;align-items:center;gap:8px;
  padding:14px 26px;border-radius:var(--r-pill);
  font-size:var(--t3);font-weight:500;letter-spacing:-.01em;
  border:1px solid transparent;cursor:pointer;
  transition:transform .18s ease,box-shadow .18s ease,background .18s ease;
}
.btn:hover{transform:translateY(-2px)}
.btn-primary{background:var(--accent);color:var(--on-accent);box-shadow:0 8px 20px rgba(255,77,45,.28)}
.btn-primary:hover{box-shadow:0 12px 28px rgba(255,77,45,.36)}
.btn-ghost{background:transparent;color:var(--ink);border-color:var(--ink)}
.btn-ghost:hover{background:rgba(17,17,17,.04)}
.btn-sm{padding:10px 18px;font-size:var(--t4)}

/* ---------- section head ---------- */
.sec{padding-top:var(--sec);position:relative}
.sec-head,.sec .projects{position:relative;z-index:1}
.sec-head{display:flex;align-items:baseline;gap:20px;margin-bottom:var(--block)}
.sec-head .no{font-family:var(--mono);font-size:var(--t3);color:var(--accent);font-weight:500}
.sec-head .titles{display:flex;flex-direction:column;gap:2px}
.sec-head h2{font-size:var(--t2);font-weight:700;letter-spacing:-.03em;line-height:1.12}
.sec-head .rule{flex:1;height:1px;background:var(--line);align-self:center}

/* ---------- 柔光场：给玻璃卡一层可透的背景，玻璃才读得出来 ---------- */
.sec .field{
  position:absolute;left:50%;transform:translateX(-50%);bottom:0;z-index:0;
  width:min(1520px,100vw);height:520px;pointer-events:none;
  filter:blur(100px);opacity:.5;
}
#portfolio .field{
  background:
    radial-gradient(58% 62% at 16% 48%,rgba(124,156,255,.22),transparent 70%),
    radial-gradient(52% 58% at 50% 22%,rgba(167,139,250,.16),transparent 72%),
    radial-gradient(56% 64% at 86% 58%,rgba(255,138,102,.18),transparent 72%);
}
#research .field{
  background:
    radial-gradient(54% 62% at 20% 56%,rgba(103,232,249,.20),transparent 72%),
    radial-gradient(56% 58% at 66% 24%,rgba(124,156,255,.18),transparent 72%),
    radial-gradient(50% 58% at 92% 68%,rgba(167,139,250,.16),transparent 72%);
}
#contact .field{
  opacity:.68;
  background:
    radial-gradient(58% 66% at 26% 52%,rgba(255,138,102,.26),transparent 72%),
    radial-gradient(52% 60% at 74% 42%,rgba(167,139,250,.18),transparent 72%);
}

/* ==========================================================================
   简历区：左栏经历 / 右栏档案
   ========================================================================== */
.resume{padding-top:clamp(40px,4.6vw,76px)}
.resume-grid{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:var(--gutter)}
.resume-main{grid-column:1 / span 8}
.resume-facts{grid-column:10 / span 3}

/* 简历区大标题：横跨整宽，左右两栏自其下方同一水平线起排，
   使右栏首行与左栏首条经历的日期（2019.08-至今）对齐 */
.resume-h{
  font-size:var(--t3);font-weight:700;letter-spacing:-.015em;
  margin-bottom:clamp(28px,3vw,44px);
}

/* 一条经历：左日期 / 右正文 */
/* 两行两列：日期 / 机构名 同一行，「主要工作」/ 正文首行 同一行 —— 左侧标签因此
   天然对齐右侧第一条分组标题或要点，不依赖手算偏移 */
.entry{
  display:grid;
  grid-template-columns:126px 1fr;
  column-gap:28px;row-gap:16px;
  align-items:start;
}
.entry + .entry{margin-top:clamp(46px,4.8vw,76px)}
.entry .when{grid-area:1 / 1;color:var(--sub);font-size:var(--t3b);line-height:1.75;padding-top:1px;white-space:nowrap}
.entry .head{grid-area:1 / 2;display:flex;flex-wrap:wrap;gap:0 12px;align-items:baseline}
.entry .lbl{grid-area:2 / 1;color:var(--mute);font-size:var(--t4);line-height:1.7;padding-top:2px}
.entry .body{grid-area:2 / 2;display:flex;flex-direction:column;gap:16px;min-width:0}
.entry .org{font-weight:400;font-size:var(--t3);letter-spacing:-.005em;color:var(--ink)}
.entry .role{color:var(--sub);font-size:var(--t3b)}
.entry .sub-h{font-weight:400;font-size:var(--t3b);color:var(--ink);margin-top:2px}
.entry .para{color:var(--sub);font-size:var(--t3b);line-height:1.9}

/* 编号要点 */
.entry ol{counter-reset:n;display:flex;flex-direction:column;gap:14px;margin-top:2px}
.entry ol li{counter-increment:n;position:relative;padding-left:26px;color:var(--sub);font-size:var(--t3b);line-height:1.9}
.entry ol li::before{content:counter(n) "、";position:absolute;left:0;color:var(--mute)}

/* 右栏档案 */
.facts{display:flex;flex-direction:column;gap:clamp(20px,2vw,30px)}
.fact{display:grid;grid-template-columns:76px 1fr;gap:14px;align-items:baseline}
.fact .k{color:var(--mute);font-size:var(--t4)}
.fact .v{font-size:var(--t4);color:var(--ink-2);word-break:break-word}
.fact .v a{border-bottom:1px solid var(--line);transition:border-color .18s ease,color .18s ease}
.fact .v a:hover{border-bottom-color:var(--ink-2);color:var(--ink-2)}

/* 右栏子模块（个人荣誉）：与档案之间留白 + 发丝分隔线 */
.aside-blk{
  margin-top:clamp(34px,3.4vw,48px);
  padding-top:clamp(26px,2.6vw,36px);
  border-top:1px solid var(--line);
}
.aside-blk > h2{
  font-size:var(--t4);font-weight:600;letter-spacing:.01em;color:var(--ink-2);
  margin-bottom:clamp(16px,1.7vw,22px);
}

/* 荣誉：窄栏内按公司纵向分组（右栏统一克制：小字号、灰阶、不用强调色） */
.honor + .honor{margin-top:clamp(18px,1.8vw,24px)}
.honor{display:grid;grid-template-columns:1fr;gap:clamp(7px,0.8vw,10px)}
.honor .org{color:var(--ink-2);font-weight:400;font-size:var(--t4);letter-spacing:0;margin-bottom:1px}
.honor ul{display:flex;flex-direction:column;gap:clamp(7px,0.8vw,10px)}
.honor li{display:grid;grid-template-columns:68px 1fr;gap:12px;font-size:var(--t4);color:var(--sub);line-height:1.75}
.honor .yr{font-family:var(--mono);font-size:var(--t4b);color:var(--mute);font-weight:500;letter-spacing:.01em}

/* ---------- 项目卡 ---------- */
.projects{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--gutter)}
.card{
  display:flex;flex-direction:column;gap:20px;padding:18px;cursor:pointer;
  transition:transform .34s cubic-bezier(.22,.7,.3,1),box-shadow .34s cubic-bezier(.22,.7,.3,1);
}
.card:hover{transform:translateY(-6px);box-shadow:var(--glass-inner),var(--glass-shadow-lift)}
.card:focus-visible{outline:2px solid var(--accent);outline-offset:4px}
.card .thumb{
  aspect-ratio:4/3;border-radius:var(--r-thumb);overflow:hidden;position:relative;
  background:linear-gradient(140deg,#1A1D24,#4C5566);
}
.card .thumb img{display:block;width:100%;height:100%;object-fit:cover;object-position:center}
.card h3{font-size:var(--t3);font-weight:700;letter-spacing:-.02em}
.card .kicker{font-family:var(--mono);font-size:var(--t4b);letter-spacing:.14em;color:var(--mute);text-transform:uppercase}
.card .desc{font-size:var(--t4);color:var(--sub);line-height:1.85}
.card .more{margin-top:auto;font-size:var(--t4);color:var(--accent-ink);font-weight:500}
/* 作品集：系统分享 / 全局批注 / 手写笔记 */
.projects .card:nth-child(1) .thumb{background:linear-gradient(140deg,#141B2B 0%,#2F5F86 100%)}
.projects .card:nth-child(2) .thumb{background:linear-gradient(140deg,#1A1D24 0%,#4A3A56 100%)}
.projects .card:nth-child(3) .thumb{background:linear-gradient(140deg,#211A17 0%,#9C4A32 100%)}
/* 设计研究：规范沉淀 / Pad OS / 人因 */
.projects.research .card:nth-child(1) .thumb{background:linear-gradient(140deg,#0F2226 0%,#2C7C8C 100%)}
.projects.research .card:nth-child(2) .thumb{background:linear-gradient(140deg,#1B1630 0%,#59439C 100%)}
.projects.research .card:nth-child(3) .thumb{background:linear-gradient(140deg,#1A2118 0%,#4F7A46 100%)}

/* ---------- 联系 ---------- */
.contact{padding:clamp(40px,4.4vw,72px)}
/* 联系我的大字：不再吃满 --t1（Hero 主阶 96px 放在这里压得太满），
   单列一档 —— 下要压住 --t2 区块标题（40px），上要低于 Hero，比例 1.65× */
.contact .statement{font-size:clamp(30px, 4.6vw, 66px);margin-bottom:clamp(28px,2.8vw,44px);letter-spacing:-.035em;text-wrap:balance}
.contact .acts{display:flex;flex-wrap:wrap;gap:14px;align-items:center}
.contact .acts a.line{font-family:var(--mono);font-size:var(--t3b);color:var(--sub);padding:15px 0;transition:color .18s ease}
.contact .acts a.line:hover{color:var(--accent-ink)}

/* ---------- footer ---------- */
footer{padding:56px 0 72px;color:var(--mute);font-size:var(--t4)}
.foot-row{
  display:flex;justify-content:space-between;gap:24px;flex-wrap:wrap;
  border-top:1px solid var(--line);padding-top:28px;
}

/* ---------- reveal ---------- */
.reveal{opacity:0;transform:translateY(20px);transition:opacity .7s cubic-bezier(.22,.7,.3,1),transform .7s cubic-bezier(.22,.7,.3,1)}
.reveal.in{opacity:1;transform:none}

/* ---------- 项目详情 ---------- */
/* 详情页不再有吸顶导航栏，首屏留白由这一层自己给 */
.detail-hero{padding:clamp(56px,6vw,92px) 0 0}
.detail-hero .glass{padding:clamp(28px,3.4vw,52px);display:flex;flex-direction:column;gap:22px}
.detail-meta{display:flex;flex-wrap:wrap;gap:12px 36px;color:var(--sub);font-size:var(--t4)}
/* 首屏这张名片只有三行字，1280 的卡里右半边空着四成 —— 看着像没排完。
   桌面端把它当两栏网格用：左栏「返回 / 标题 / 一句话」，右栏档案竖排、与正文底对齐。
   档案从「标题后面拖出来的一条尾巴」变成卡片的第二条腿，横向空间也用满了。
   960 以下退回原来的一行横排 —— 窄屏横排省高度，竖排反而把首屏撑长。 */
@media (min-width:960px){
  .detail-hero .glass{
    display:grid;grid-template-columns:minmax(0,1fr) clamp(272px,26vw,352px);
    column-gap:clamp(32px,4vw,72px);row-gap:clamp(14px,1.5vw,20px);
  }
  .detail-hero .glass > .eyebrow{grid-column:1;grid-row:1}
  .detail-hero .glass > h1{grid-column:1;grid-row:2}
  .detail-hero .glass > .l3{grid-column:1;grid-row:3}
  .detail-hero .glass > .detail-meta{
    grid-column:2;grid-row:1 / span 3;align-self:end;justify-self:stretch;
    /* 列方向 + wrap 会让这一栏缩到最窄那条 flex line 的宽度（截出来只有 114px，
       四条档案全折成三行）。这里关掉 wrap、改成 stretch，栏宽才是轨道宽。 */
    flex-direction:column;flex-wrap:nowrap;align-items:flex-start;gap:8px;min-width:0;
  }
}
.detail-body{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:var(--gutter);padding-top:var(--block)}
.detail-body .main{grid-column:span 12;display:flex;flex-direction:column;gap:56px}
/* 章与章之间再松一档，段落和配图之间保持常规间距 —— 杂志式节奏 */
.detail-body .main > section + section:has(> h2){margin-top:26px}
/* reset 把 p 的 margin 归零，段与段原本贴在一起；统一给章节内部一个 22px 的节奏 */
.detail-body .main > section{display:flex;flex-direction:column;gap:22px}
/* 单栏后正文不宜跟着拉满 1280px：文本限宽、图与组图仍占满整栏 */
.detail-body .main > section > h2,
.detail-body .main > section > h3,
.detail-body .main > section > h4,
.detail-body .main > section > p{max-width:var(--measure)}
.detail-body h2{font-size:var(--t2c);font-weight:600}
.detail-body p{color:var(--sub);line-height:1.85}
/* 有序清单：与首页「工作经历」的编号语言一致，编号悬挂、正文左对齐 */
.detail-body .main > section > ol{max-width:var(--measure);counter-reset:n;display:flex;flex-direction:column;gap:10px}
.detail-body ol li{counter-increment:n;position:relative;padding-left:26px;color:var(--sub);font-size:var(--t3);line-height:1.85}
.detail-body ol li::before{content:counter(n) '、';position:absolute;left:0;color:var(--mute)}
.detail-body .fig{
  border-radius:var(--r-card);overflow:hidden;aspect-ratio:3/2;position:relative;
  display:flex;align-items:center;justify-content:center;color:var(--mute);
  font-family:var(--mono);font-size:var(--t4b);letter-spacing:.06em;
  background:
    radial-gradient(120% 120% at 10% 0%,rgba(124,156,255,.24),transparent 62%),
    radial-gradient(110% 110% at 90% 100%,rgba(167,139,250,.22),transparent 60%),
    linear-gradient(160deg,#F8FAFD,#E7EDF7);
  box-shadow:0 10px 26px rgba(18,23,38,.07);
}
.detail-body .fig img{display:block;width:100%;height:100%;object-fit:cover;object-position:center}
/* 比例悬殊的图（如宽幅示意）不裁切，按原比例显示；透明底导出直接落在画布上，不加渐变底和投影。
   宽幅图跟着整栏拉到 1280px 会显得过大，收进正文的阅读栏宽（--measure），与上方段落左对齐 */
.detail-body .fig.nat{aspect-ratio:auto;background:none;box-shadow:none;border-radius:0;max-width:var(--measure)}
.detail-body .fig.nat img{height:auto}
/* 窄幅图（如四个手势示意）：原图只有 678px 宽，放到整栏会放大到 1.4 倍而发虚 */
.detail-body .fig.nat.sm{max-width:520px}
/* 结构图一类的大图：整栏会高到近 900px，把页面节奏压垮，收一档 */
.detail-body .fig.nat.md{max-width:720px}
/* 本身就是「整行图带」的宽幅图（如三屏联动的演示条）：跟着整栏走，不收到 --measure */
.detail-body .fig.nat.full{max-width:none;border-radius:var(--r-card);overflow:hidden;background:var(--surface)}

/* ---------- 详情页：内容块（沿用现有 token，不引入新的视觉语言） ---------- */
/* 描述性文字 D1 · 正文：成段说明，含区块开篇的结论句（.lead）。
   正文只有一种形态 —— 不因为句子重要就换字号、字重或颜色 */
.detail-body .blk{display:flex;flex-direction:column;gap:22px}
.detail-body h3{font-size:var(--t3);font-weight:600;color:var(--ink)}
/* 条目标题降两档，与 h3 小节标题（--t3 16–18px）拉开层级 */
.detail-body h4{font-size:var(--t4);font-weight:600;color:var(--ink)}
.detail-body .cap{font-size:var(--t4);color:var(--sub);line-height:1.8}

/* 图片行 */
.fig-row{display:grid;gap:var(--gutter)}
.fig-row.c2{grid-template-columns:repeat(2,minmax(0,1fr))}
.fig-row.c3{grid-template-columns:repeat(3,minmax(0,1fr))}
.fig-row.c4{grid-template-columns:repeat(4,minmax(0,1fr))}
.fig-row.c5{grid-template-columns:repeat(5,minmax(0,1fr))}
/* 同组两张图源比例差得多、又要求等高时：列宽按图源比例给（内联 style 会盖住
   手机端的单栏规则，所以做成类），手机端由下面的 media query 退回一栏 */
.fig-row.ratio-23{grid-template-columns:2fr 3fr}
/* 手写助手的两张图源比例是 2.296 与 1.422：列宽按这两个比例给（1.615fr 1fr），
   两图自然撑开后高度正好相等 —— 图注才落得回同一条基线 */
.fig-row.ratio-85{grid-template-columns:1.615fr 1fr}
.fig-row .item{display:flex;flex-direction:column;gap:14px}
.fig-row img{width:100%;height:auto;border-radius:var(--r-thumb);display:block}
/* 同组两张图宽度不同、但要等高时：列宽按图源比例给（内联 style 传 fr），
   图片按自身比例自然撑开，就既不留白也不错位。
   必须带上 .c2/.c3/.c4 提高权重 —— 下面的「.fig-row.c2 img{aspect-ratio:3/2}」
   同样只有两个类，写在后面就会把 natural 盖掉，图注又错开 */
.fig-row.natural img,
.fig-row.c2.natural img,
.fig-row.c3.natural img,
.fig-row.c4.natural img{aspect-ratio:auto;object-fit:fill}

/* 机位图：一台设备一个 .item，说明紧贴其下并居中 —— 让文字明确「说的是这一张」，
   而不是在图片下方横排成一行（横排时读者没法把文字和某一台设备对上）。

   设备宽度统一取值「五列布局的自然宽度」：列数少的组不去放大设备来填满行宽，
   而是把多出来的空间交给间距。否则同样是手机截图，五列组 236px、三列组 411px，
   大小不一致，三列组还会因为放大而发虚。 */
.fig-row.shots{
  --shot-w:calc((100% - 4 * var(--gutter)) / 5);
  display:flex;flex-wrap:wrap;justify-content:space-between;align-items:flex-start;
  gap:var(--gutter);
}
.fig-row.shots .item{flex:0 0 var(--shot-w);min-width:0;gap:18px;text-align:center}
/* 五组设备的长宽比略有差异（高宽比 2.129 ～ 2.216，来自各自页面的画框不同）。
   让图片自然撑开时高度就不一样，图注基线最夸张会差 13px，横向读不齐。
   这里按最高的那组锁定统一比例、顶部对齐，多出来的高度留白 ——
   设备顶部齐、图注也齐，与原始页面的排法一致 */
.fig-row.shots .item img{
  border-radius:0;
  aspect-ratio:570/1263;
  object-fit:contain;object-position:top center;
}
.fig-row.shots .item .cap{line-height:1.7}
/* 图注里的粗体是「这条说明说的是哪张图」的标签，单独占行 */
.fig-row .item .cap b{display:block;font-weight:500;color:var(--ink-2)}
/* 功能清单：一个功能一张图，图注第一行是功能名（窄图/宽图都适用） */
.detail-body .cap b{display:block;font-weight:500;color:var(--ink-2)}
/* 同一行的两张实拍图比例不同，统一裁成 3:2，让下方的标题/说明对齐 */
.fig-row.c2 img{aspect-ratio:3/2;object-fit:cover;object-position:center}
/* 图片比例不一致时（同组最高与最矮相差可达 17%），下方的标题/说明会落在不同高度。
   .eq 按组统一比例、contain 缩放、底部对齐 —— 图注横向能读齐。
   比例由每行用内联 --eq 传入，因为每一组的图源比例本就不同 */
.fig-row.eq img{aspect-ratio:var(--eq,1.5);object-fit:contain;object-position:center bottom}
/* 同一组里视频和图片混排时也要等高，否则下方的标题会错开 */
.fig-row.eq video{
  width:100%;aspect-ratio:var(--eq,1.5);object-fit:cover;
  display:block;border-radius:var(--r-thumb);background:#0E1116;color:#C7D0DC;
}
.fig-row .item .hd{display:flex;align-items:baseline;gap:12px}
.fig-row .item .hd h3,.fig-row .item .hd h4{margin:0}

/* 「最终选择」标记：叠在图片左上角，不烘焙进图片，保证缩放后依然清晰、颜色走 token */
.fig-row .shot{position:relative;border-radius:var(--r-thumb);overflow:hidden}
.fig-row .pick{
  position:absolute;top:7.5%;left:8%;z-index:1;
  display:inline-flex;align-items:center;
  padding:.42em 1em .46em;border-radius:var(--r-pill);
  background:var(--accent);color:var(--on-accent);
  font-size:var(--t4);font-weight:600;letter-spacing:.04em;line-height:1.3;
}
.fig-row .item .n,.quad .item .n{font-family:var(--mono);font-size:var(--t4);letter-spacing:.06em;color:var(--accent)}

/* 两栏对照 */
.cmp{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));border-top:1px solid var(--line)}
.cmp > *{padding:24px 24px 24px 0;border-bottom:1px solid var(--line);font-size:var(--t4);line-height:1.85;color:var(--sub)}
.cmp > *:nth-child(even){padding-left:32px;padding-right:0;border-left:1px solid var(--line)}
/* 两栏对照的列表头：比正文大一档、颜色更实，明确是「标题」而不是小标签 */
.cmp .th{font-family:var(--mono);font-size:var(--t4);font-weight:500;letter-spacing:.06em;color:var(--ink-2);text-transform:uppercase;padding-bottom:14px}

/* 规格对标表：维度 × 五家公开规范的建议值 + 说明。
   七列在桌面上才排得开（1280px 整栏），窄屏整表转成「一个维度一张卡」，
   表头隐藏、靠 data-k 把列名回填到每个值前面 —— 表格数据在手机上不靠缩略图看 */
.tbl{width:100%;border-collapse:collapse;table-layout:fixed}
.tbl th,.tbl td{text-align:left;vertical-align:top;padding:20px 18px 20px 0;border-bottom:1px solid var(--line)}
.tbl thead th{font-family:var(--mono);font-size:var(--t4);font-weight:500;letter-spacing:.02em;color:var(--ink-2);padding-bottom:12px}
.tbl thead tr:first-child th{padding-bottom:8px}
/* 子表头紧跟「建议值」这一行，不再重复一遍上边距 */
.tbl thead tr:last-child th{padding-top:6px}
.tbl tbody th{font-size:var(--t3b);font-weight:600;color:var(--ink);letter-spacing:.02em}
.tbl td{font-size:var(--t4);line-height:1.85;color:var(--sub)}
.tbl td small{display:block;margin-top:4px;font-size:var(--t4b);line-height:1.85;color:var(--mute)}

/* 四宫格 */
.quad{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:var(--gutter)}
.quad .item{display:flex;flex-direction:column;gap:14px}
.quad .item svg{width:38px;height:38px;color:var(--accent)}
.quad .item p{font-size:var(--t4);line-height:1.85}

/* 枚举清单（11 项硬件）：最轻的标签形态，只为把「覆盖了多少项」讲清楚，
   不引入新的视觉语言 —— 描边、圆角、字号都复用现有 token */
.chips{display:flex;flex-wrap:wrap;gap:10px;max-width:var(--measure)}
.chips span{
  display:inline-flex;align-items:baseline;gap:8px;
  padding:7px 16px 8px;border-radius:var(--r-pill);
  border:1px solid var(--line);background:var(--surface);
  font-size:var(--t4);line-height:1.6;color:var(--ink-2);
}
.chips span i{font-family:var(--mono);font-style:normal;font-size:var(--t4b);color:var(--mute)}

/* 指标 */
.stats{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--gutter)}
.stats .item .num{font-size:var(--t-stat);font-weight:700;letter-spacing:-.03em;line-height:1;color:var(--ink)}
.stats .item .num small{font-size:var(--t3);font-weight:400;color:var(--mute);margin-left:6px;letter-spacing:0}
.stats .item .t{font-size:var(--t4);font-weight:500;color:var(--ink);margin-top:16px}
.stats .item .d{font-size:var(--t4);color:var(--sub);margin-top:8px;line-height:1.85}

/* 用户行为地图（旅程图）：沿用作品集原页的表格骨架，补齐行业标准行，
   左侧行标签与顶部阶段名做成深色轴带，中间是「图标 + 箭头」的行为流程与情绪曲线 */
.stage{
  display:grid;grid-template-columns:140px repeat(3,minmax(0,1fr));
  column-gap:0;row-gap:0;
  border:1px solid var(--line);border-radius:var(--r-card);overflow:hidden;background:var(--surface);
}
.stage > *{padding-top:26px;padding-bottom:24px}
.stage .lb{
  padding:24px 20px 24px 24px;background:var(--ink);color:var(--surface);
  font-size:var(--t3);font-weight:600;line-height:1.5;
}
.stage .th{
  padding:18px 12px;background:var(--ink);color:var(--surface);
  text-align:center;font-size:var(--t3b);font-weight:600;line-height:1.5;
}
/* 栏间距用单元格自身的 padding 来留（column-gap 为 0，分隔线才能左右连成一条）。
   最后一列不单独去掉 padding —— 正文左对齐，右侧少 24px 不影响观感，
   却省掉了「按序号排除最后一列」这种一加行就错位的写法 */
.stage .cell{padding-left:20px;padding-right:20px;border-bottom:1px solid var(--line)}
.stage > :nth-last-child(-n+4){border-bottom:0}
.stage .cell ul,.stage .cell ol{display:flex;flex-direction:column;gap:8px;font-size:var(--t4);line-height:1.9;color:var(--sub)}
/* counter 要在本表内重置，否则会接着上一个列表继续编号 */
.stage .cell ol{counter-reset:n}
.stage .cell ol li{counter-increment:n;position:relative;padding-left:22px;color:var(--sub);font-size:var(--t4);line-height:1.9}
.stage .cell ol li::before{content:counter(n) '、';position:absolute;left:0;color:var(--mute)}

/* 「行为」行：图标 + 文案的流程，步与步之间用箭头连起来 */
.stage .flow{display:flex;align-items:flex-start}
.stage .flow .step{flex:1 1 0;min-width:0;display:flex;flex-direction:column;align-items:center;gap:10px;text-align:center}
.stage .flow .ic{
  width:36px;height:36px;border-radius:50%;border:1px solid var(--line);background:var(--canvas);
  display:grid;place-items:center;color:var(--ink-2);
}
.stage .flow .ic svg{width:19px;height:19px;display:block}
.stage .flow .tx{font-size:var(--t4b);line-height:1.5;color:var(--sub)}
.stage .flow .arrow{flex:0 0 16px;height:1px;background:var(--mute);margin-top:18px;position:relative;opacity:.55}
.stage .flow .arrow::after{
  content:'';position:absolute;right:0;top:-2.5px;
  border-left:5px solid var(--mute);border-top:3px solid transparent;border-bottom:3px solid transparent;
}

/* 情绪曲线：整条曲线跨三列，表情落在点位上 */
.stage .chart{grid-column:2 / -1;padding-top:20px;padding-right:20px}
.stage .chart svg{display:block;width:100%;height:auto}
.stage .chart .base{fill:none;stroke:var(--line);stroke-width:1;stroke-dasharray:4 7}
.stage .chart .area{fill:var(--accent);fill-opacity:.07}
.stage .chart .line{fill:none;stroke:var(--ink-2);stroke-width:2;stroke-linecap:round}
.stage .chart .face > circle:first-child{fill:var(--surface);stroke:var(--ink-2);stroke-width:2}
.stage .chart .face .eye{fill:var(--ink-2)}
.stage .chart .face .mouth{fill:none;stroke:var(--ink-2);stroke-width:2;stroke-linecap:round}
/* 苦脸（.low）只是「这一格偏低」，仍走墨色；强调色只给全局最低的那一个点（.min） */
.stage .chart .face.min > circle:first-child{stroke:var(--accent)}
.stage .chart .face.min .eye{fill:var(--accent)}
.stage .chart .face.min .mouth{stroke:var(--accent)}
.stage .chart .axis{font-family:var(--mono);font-size:11px;letter-spacing:.06em;fill:var(--mute)}
/* 表情在曲线上，这一行的情绪词要落到各列中线，才能和上方的表情对位 */
.stage .emo{display:flex;align-items:center;justify-content:center;gap:12px}
.stage .emo span{font-size:var(--t4);line-height:1.6;color:var(--sub)}
/* 桌面上表情已经画在曲线上了，这一行只留情绪词 */
.stage .emo svg{display:none}

/* 图标卡：自绘线性图标 + 标题 + 说明（与「三个关键决策」同一套图标语言） */
.fig-row.icons .item .pic{width:40px;height:40px;color:var(--accent)}

/* 三列四宫格（三个关键决策） */
.quad.q3{grid-template-columns:repeat(3,minmax(0,1fr))}
/* 五列四宫格（研究的执行流程）：编号 + 标题 + 一句说明，横向读成一条流程 */
.quad.q5{grid-template-columns:repeat(5,minmax(0,1fr))}
.quad.q5 .item{gap:10px}
.quad.q5 .item .n{font-size:var(--t4b)}

/* 编号条目 */
.steps{display:flex;flex-direction:column;gap:32px}
.steps .row{display:grid;grid-template-columns:40px minmax(0,1fr);column-gap:16px;align-items:baseline}
.steps .row .n{font-family:var(--mono);font-size:var(--t4);color:var(--accent);line-height:1.9}
.steps .row p{font-size:var(--t4);line-height:1.9;margin-top:10px}

/* 清单里的「已上线」标记 */
.star{color:var(--accent)}

/* 汇报稿扫码卡：左侧说明，右侧两个二维码 */
.scan{
  display:grid;grid-template-columns:minmax(0,1fr) auto auto;
  gap:clamp(32px,4vw,72px);align-items:center;
  padding:clamp(28px,2.6vw,40px);
  border-radius:var(--r-card);border:1px solid var(--line);background:var(--surface);
}
.scan .t{font-size:var(--t3);font-weight:600;color:var(--ink)}
.scan .d{font-size:var(--t4);color:var(--sub);margin-top:10px;line-height:1.8}
.scan figure{margin:0;text-align:center}
.scan img{display:block;width:104px;height:104px;border-radius:8px}
.scan figcaption{font-size:var(--t4);color:var(--sub);margin-top:12px;line-height:1.6}

/* 视频 */
.vid{display:flex;flex-direction:column;gap:12px;align-items:center}
/* 片源 1180×1280（近 1:1）：铺满整栏会过高。限宽 680px 且不超过 68vh，取小值，原比例不裁切 */
.vid video{
  width:100%;max-width:min(680px,68vh);aspect-ratio:1180/1280;
  border-radius:var(--r-card);display:block;background:#0E1116;color:#C7D0DC;
}
/* 图注是文字，宽度只能受阅读栏宽约束 —— 之前误用了视频的 min(680px,68vh)
   （那是按视口高度算的，窗口一矮就把这句话压到 449px，明明有宽度却折行） */
.vid figcaption{width:100%;max-width:var(--measure);text-align:center;font-size:var(--t4);color:var(--sub)}

/* ---------- responsive ---------- */
@media (max-width:1100px){
  .resume-main{grid-column:1 / span 12}
  .resume-facts{grid-column:1 / span 12;margin-top:clamp(40px,4vw,56px)}
  .facts{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:24px 32px}
  .aside-blk{margin-top:clamp(40px,4vw,56px)}
  .honors{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:28px 32px}
  .honor + .honor{margin-top:0}
  .honor li{grid-template-columns:72px 1fr}
  .projects{grid-template-columns:repeat(2,minmax(0,1fr))}
  .detail-body .main{grid-column:span 12}
  .fig-row.c3{grid-template-columns:repeat(2,minmax(0,1fr))}
  .fig-row.c4{grid-template-columns:repeat(2,minmax(0,1fr))}
  .quad{grid-template-columns:repeat(2,minmax(0,1fr));gap:28px 24px}
  .quad.q3{grid-template-columns:repeat(2,minmax(0,1fr))}
  .quad.q5{grid-template-columns:repeat(3,minmax(0,1fr));gap:28px 24px}
}
@media (max-width:900px){
  .grid .span-3,.grid .span-4,.grid .span-5,
  .grid .span-6,.grid .span-7,.grid .span-8{grid-column:span 12}
}
@media (max-width:820px){
  :root{--margin:24px}
  .fab{display:inline-flex}
  .masthead{padding:16px 0 14px}
  /* 手机端页头：第一行「姓名 ←→ 下载简历」（按姓名中线对齐），
     定位语整行铺在下面。who 用 display:contents 让姓名与定位语直接落进网格，
     这样按钮能和姓名同排，定位语又不会被挤成两行。 */
  .masthead .row{display:grid;grid-template-columns:1fr auto;column-gap:12px;row-gap:4px;align-items:center}
  .masthead .who{display:contents}
  .masthead .name{grid-column:1;grid-row:1}
  .masthead .tag{grid-column:1 / -1;grid-row:2;margin-top:0}
  /* 手机端不显示顶部切换 tab（单页滚动即可到达各区块），只留「下载简历」 */
  .masthead .menu{grid-column:2;grid-row:1;justify-self:end;height:auto;padding-top:0}
  .masthead .menu a:not(.dl){display:none}
  .entry{grid-template-columns:1fr;column-gap:0;row-gap:10px}
  .entry .when{grid-area:auto;order:1;padding-top:0;white-space:normal}
  .entry .lbl{grid-area:auto;order:2;padding-top:0}
  .entry .head{grid-area:auto;order:3}
  .entry .body{grid-area:auto;order:4}
  /* 手机端只保留右栏的个人荣誉；档案信息（邮箱 / 电话 / 求职意向）由文末「联系我」承担 */
  .facts{display:none}
  .aside-blk{margin-top:0;padding-top:0;border-top:0;align-self:start}
  .projects{grid-template-columns:1fr}
  .sec-head{gap:12px}
  .honors{grid-template-columns:1fr;gap:0}
  .honor + .honor{margin-top:30px}
  .honor li{grid-template-columns:72px 1fr;gap:12px}
  .contact .statement br.br-lg{display:none}
  /* 详情页内容块：全部落成单列 */
  .fig-row.c2,.fig-row.c3,.fig-row.c4,.fig-row.ratio-23,.fig-row.ratio-85{grid-template-columns:1fr}
  /* 阶段表在单列下会变成「标签 / 三列内容」交替，读不出对应关系：
     改成 标签当小标题 + 每个内容块自带阶段名前缀 */
  .stage{grid-template-columns:1fr}
  .stage .lb:first-child,.stage .th{display:none}
  .stage{border-radius:var(--r-card)}
  .stage .lb{padding:22px 20px}
  .stage .cell{padding-left:20px}
  .stage .cell::before{
    content:attr(data-stage);display:block;margin-bottom:12px;
    font-family:var(--mono);font-size:var(--t4);font-weight:500;letter-spacing:.06em;color:var(--ink-2);
  }
  .stage .lb-empty,.stage .chart{display:none}
  .stage .emo{padding-top:18px;border-bottom:0;justify-content:flex-start}
  .stage .emo svg{display:block;width:30px;height:30px;flex:0 0 auto;color:var(--ink-2)}
  .stage .emo.min svg{color:var(--accent)}
  .stage .cell{padding-right:0;padding-top:18px;padding-bottom:0;border-bottom:0}
  .stage .cell::before{
    content:attr(data-stage);display:block;margin-bottom:10px;
    font-family:var(--mono);font-size:var(--t4);font-weight:500;letter-spacing:.06em;color:var(--ink-2);
  }
  .fig-row.join{column-gap:0}
  /* 机位图在手机上退到两列：单列会让一台设备占满整行、页面被拉得很长，
     横排一行又缩到几十像素看不出内容。--shot-w 同步改成两列的自然宽度 */
  .fig-row.shots{--shot-w:calc((100% - var(--gutter)) / 2)}
  /* 对照表保持两栏：左右配对才是它的意义，落成单列会读不出对应关系 */
  .cmp > *{padding:14px 12px 14px 0}
  .cmp > *:nth-child(even){padding-left:14px}
  /* 规格对标表：七列在手机上排不下，整表转成「一个维度一张卡」。
     表头隐藏，列名由 data-k 回填到每个值前面（同 .stage 的做法） */
  .tbl,.tbl tbody,.tbl tr,.tbl th,.tbl td{display:block}
  .tbl colgroup,.tbl thead{display:none}
  .tbl tr{padding:24px 0;border-bottom:1px solid var(--line)}
  .tbl th,.tbl td{border:0;padding:0}
  .tbl tbody th{margin-bottom:12px}
  .tbl tbody tr:first-child{padding-top:0}
  .tbl td[data-k]{display:grid;grid-template-columns:104px minmax(0,1fr);gap:10px;margin-top:12px}
  .tbl td[data-k]::before{content:attr(data-k);font-size:var(--t4b);line-height:1.9;color:var(--mute)}
  /* 值和它自己的注解贴紧（3px），条目之间拉开（12px），分组关系才读得出来 */
  .tbl td[data-k] > small{grid-column:2;margin-top:3px}
  .quad,.quad.q3,.quad.q5{grid-template-columns:1fr;gap:26px}
  .stats{grid-template-columns:1fr;gap:24px}
  .steps .row{grid-template-columns:1fr}
  .steps .row .n{line-height:1.4}
  .scan{grid-template-columns:1fr;gap:28px;justify-items:start}
  .scan figure{text-align:left}
}

/* 系统开启「降低透明度」时，玻璃退化为近实色，保证可读性 */
@media (prefers-reduced-transparency:reduce){
  :root{--glass-fill:linear-gradient(180deg,rgba(255,255,255,.95),rgba(255,255,255,.92));--glass-blur:0px;--glass-sat:100%}
  .masthead.stuck{background:rgba(246,247,250,.97)}
}

@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *{animation:none!important;transition:none!important}
  .reveal{opacity:1;transform:none}
}
@media print{
  .masthead,.ambient,.contact .acts,.sec .field,.fab{display:none}
  body{background:#fff}
  .glass{box-shadow:none;background:#fff;backdrop-filter:none}
}

/* ---------- 详情页：「写 / 唤 / 控」三组体验 ---------- */
/* 一章里要放三组并列的体验，用发丝线分组 —— 不新增颜色、字号与圆角，
   线取表格分割线同一支 token（--line），与右栏「个人荣誉」的分组语言一致 */
.detail-body .group{
  display:flex;flex-direction:column;gap:22px;
  padding-top:clamp(24px,2.6vw,36px);border-top:1px solid var(--line);
}
.detail-body .group > h3,
.detail-body .group > p,
.detail-body .group > .cap,
.detail-body .group > .fig-row,
.detail-body .group > .fig{max-width:var(--measure)}

/* ---------- 功能结构图：每个「定义」下面先给一张层级地图 ---------- */
/* 一个定义下面挂着 3–10 张并列的功能卡，单看卡片会散。先按「定义 → 方向 → 功能」三层把关系画出来，
   再往下读卡片：根节点实心（--ink），方向是标题，功能复用 .chips 的标签形态，连线只用 --line。 */
.map{--cols:3;position:relative;max-width:var(--measure);margin:34px 0 46px}
.map.c2{--cols:2}
.map .root{
  position:relative;display:table;padding:9px 20px 10px;border-radius:var(--r-pill);
  background:var(--ink);color:#fff;font-size:var(--t4);font-weight:500;line-height:1.6;letter-spacing:.01em;
}
/* 根 → 总线的竖线，挂在定义胶囊自己的中线上（胶囊多长都对齐） */
.map .root::after{content:"";position:absolute;left:50%;bottom:-26px;width:1px;height:26px;background:var(--line-2)}
.map .branch{
  position:relative;display:grid;grid-template-columns:repeat(var(--cols),minmax(0,1fr));
  gap:var(--gutter);margin-top:26px;padding-top:24px;
}
/* 总线：从第一列的分支线拉到最后一列的分支线 */
/* 总线：从第一列的分支线拉到最后一列的分支线。
   最后一列的左边缘 = (100% + gutter) × (cols-1) / cols，
   早先写成 right:calc(100% / cols) 会短 0.67 个 gutter（三列时 16px），线接不上第三个分支 */
.map .branch::before{content:"";position:absolute;top:0;left:0;width:calc((100% + var(--gutter)) * (var(--cols) - 1) / var(--cols));height:1px;background:var(--line-2)}
.map .col{position:relative}
/* 每列的分支线 */
.map .col::before{content:"";position:absolute;top:-24px;left:0;width:1px;height:24px;background:var(--line-2)}
.map .hd{font-size:var(--t4);font-weight:600;color:var(--ink);letter-spacing:.01em}
.map .gl{display:block;margin-top:16px;font-size:var(--t4b);color:var(--mute);letter-spacing:.04em}
.map .chips{margin-top:12px;gap:8px}
.map .chips span{padding:6px 14px 7px}

/* ---------- 功能结构图（.map.cols）：三个定义横着排，方向先用图形立起来 ---------- */
/* 竖排的三段带子像目录：一屏只装得下一段，三段之间的关系要靠滚才能看到。改成三列并排，
   「一支笔的定义」才一眼同框。每列里：定义是一枚深色胶囊，从胶囊垂下一根主轴，
   轴上钉着方向节点 —— 节点是圆形 + 线性图标，功能项是节点旁边的小字。
   图形负责结构，文字只做说明；图标是 24 格里的线性图标，线宽 1.5，与站内插画同一支笔。 */
.map.cols{
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  gap:0 clamp(28px,3.6vw,64px);max-width:none;margin:0;
}
.map.cols .col{display:flex;flex-direction:column;min-width:0}
/* 这里不用「总线 + 分叉」那套线：列首的短分叉线会孤零零地悬在胶囊上方 */
.map.cols .col::before{display:none}
/* 定义胶囊：三列等宽，胶囊撑满一列，三顶帽子对齐 */
.map.cols .root{
  display:flex;align-items:baseline;justify-content:space-between;gap:14px;
  padding:11px 20px 12px;
}
/* 颜色要显式写：详情页的 .detail-body h3 会把颜色按正文的墨色压回来 */
.map.cols .root h3{font-size:var(--t3b);font-weight:600;letter-spacing:.005em;color:#fff}
/* 方向数用半透明白：深色胶囊上的次级信息，不再借第三支灰 */
.map.cols .root .n{
  font-family:var(--mono);font-size:var(--t4b);letter-spacing:.04em;
  color:rgba(255,255,255,.62);white-space:nowrap;
}
/* 胶囊垂下来的主轴：与节点圆心、列内左基线同在一条线上（圆心 = 列左 + 30） */
.map.cols .root::after{left:30px;bottom:-22px;height:22px}
.map.cols .subs{display:flex;flex-direction:column;margin-top:22px;padding-left:60px}
/* 方向节点：圆形图标 + 名称，节点之间留一档气口，主轴分段画以免越过最后一个节点 */
.map.cols .sub{position:relative;padding-top:26px}
.map.cols .sub:first-child{padding-top:0}
.map.cols .sub::before{content:"";position:absolute;left:-30px;top:0;height:100%;width:1px;background:var(--line-2)}
.map.cols .sub:last-child::before{height:18px}
.map.cols .sub .gl{
  position:relative;display:flex;align-items:center;min-height:40px;
  margin-top:0;
  font-size:var(--t3b);font-weight:600;color:var(--ink);letter-spacing:.01em;
}
/* 圆用白底压在主轴交点上，线穿过去被圆截断，节点才立得住；图标取强调色的文字版 */
.map.cols .sub .ic{
  position:absolute;left:-50px;top:0;display:grid;place-items:center;
  width:40px;height:40px;border-radius:50%;
  background:var(--surface);border:1px solid var(--line);color:var(--accent-ink);
  box-shadow:0 2px 8px rgba(18,23,38,.05);
}
.map.cols .sub .ic svg{display:block;width:21px;height:21px}
.map.cols .sub .caps{
  display:flex;flex-wrap:wrap;gap:2px 16px;margin-top:6px;
  font-size:var(--t4);line-height:1.9;color:var(--sub);
}

/* ---------- 复用关系图（.map.reuse）：一份能力分给四个模块 ---------- */
/* 上一版是「一顶深色帽子 + 一条长横线 + 四个词」：四个模块只有名字，图本身没讲出
   「同一份能力」这件事，胶囊的垂线还落在总线的偏左处，接不上。
   这一版把关系画出来：源头居中（深色胶囊 + 工具栏图标），总线对称分到四颗圆形节点，
   节点里是模块图标，名字与一句短注在圆下。节点语言完全沿用 .map.cols ——
   圆 + 线性图标 + 文字，全页只有这一套结构图语法。
   列内居中是这张图需要的：四列的圆心正好落在 12.5% / 37.5% / 62.5% / 87.5%，
   总线（圆心中点到圆心中点）的中点因此正好是 50%，与胶囊的垂线对齐。 */
.map.reuse{--cols:4;max-width:none}
.map.reuse .col{display:flex;flex-direction:column;align-items:center;text-align:center}
.map.reuse .root{display:flex;align-items:center;gap:11px;width:max-content;margin:0 auto;padding:11px 22px 12px}
.map.reuse .root .ric{display:block;width:21px;height:21px;flex:0 0 auto}
.map.reuse .root .ric svg{display:block;width:21px;height:21px}
.map.reuse .root .rt{font-size:var(--t3);font-weight:600;letter-spacing:.005em;color:#fff}
/* 总线：从第一列的圆心拉到最后一列的圆心（圆心 = 列宽的一半） */
.map.reuse .branch::before{left:calc(12.5% - var(--gutter) * .375);width:calc((100% + var(--gutter)) * .75)}
/* 分叉线落在列中线上，从总线垂到圆顶 */
.map.reuse .col::before{left:50%}
.map.reuse .nic{
  display:grid;place-items:center;width:54px;height:54px;border-radius:50%;
  background:var(--surface);border:1px solid var(--line);color:var(--accent-ink);
  box-shadow:0 2px 8px rgba(18,23,38,.05);
}
.map.reuse .nic svg{display:block;width:25px;height:25px}
.map.reuse .tx{margin-top:16px}
.map.reuse .hd{font-size:var(--t3);font-weight:600;color:var(--ink);letter-spacing:-.005em}
.map.reuse .ds{margin-top:6px;font-size:var(--t4);line-height:1.7;color:var(--mute)}

@media (max-width:820px){
  /* 手机端不再画连线：三层改成一条竖排的清单，靠缩进与字号分层 */
  .map{margin:26px 0 34px}
  .map .root{margin-left:0}
  .map .branch{grid-template-columns:1fr;gap:24px;padding-top:0;margin-top:18px}
  .map .branch::before,.map .branch::after,.map .col::before,.map .root::after{display:none}
  .map .col{padding-left:0}
  /* 结构图：三列落成一列，但主轴与图形节点保留 —— 图形是这张图的主角，
     不因为屏窄就退回成一份文字清单 */
  .map.cols{grid-template-columns:1fr;gap:32px}
  .map.cols .root::after{display:block;left:30px}
  /* 复用关系图：连线收掉之后，四颗节点竖排成一份清单，圆在左、文字在右；
     胶囊也从居中退回左基线，和这一列其它文字同一条线 */
  .map.reuse .root{margin:0}
  .map.reuse .col{flex-direction:row;align-items:center;gap:16px;text-align:left}
  .map.reuse .tx{margin-top:0}
  .map.reuse .nic{width:46px;height:46px;flex:0 0 auto}
  .map.reuse .nic svg{width:22px;height:22px}
}

/* 详情页里的外链（如「结果」里的 vivo HIG 规范）：用强调色的文字版，与卡片上的「查看详情」同一支 token */
.detail-body .cap a,
.detail-body p a[target]{
  color:var(--accent-ink);text-decoration:underline;text-underline-offset:3px;
  text-decoration-thickness:1px;transition:color .18s ease;
}
.detail-body .cap a:hover,
.detail-body p a[target]:hover{color:var(--ink)}

/* ==========================================================================
   详情页版式 v2 · 画廊式版面
   诊断：旧版面里「章节标题 / 大图 / 组图 / 图注」都压在同一条左基线与同一个
   960px 尺度上，尺寸层级扁平 → 读起来是一条匀速的流水线，图也提不起来。
   改法只做三件事，不新增颜色、圆角与字号阶：
     1. 章节头 —— mono 序号 + 放大的标题 + 顶部发丝线，把「章」立起来；
     2. 图片分级 —— 主角图放开到整栏，章节首图加圆角投影，组图统一画布；
     3. 竖向节奏 —— 统一 gap 换成 12 / 18 / 38 / 68 / 100 的分层留白。
   横向规则不动：所有文字与所有图的左边缘仍在同一条线上，图注仍贴着它的图。
   ========================================================================== */

/* ---------- 1 · 章节头 ---------- */
.detail-body .sec-hd{padding-top:clamp(28px,3.4vw,48px);border-top:1px solid var(--line)}
.detail-body .sec-hd .n{
  display:block;font-family:var(--mono);font-size:var(--t4b);font-weight:500;
  letter-spacing:.2em;line-height:1;color:var(--mute);
}
.detail-body .sec-hd h2{
  max-width:var(--measure);margin-top:clamp(10px,1.2vw,16px);
  font-size:var(--t2c);line-height:1.18;letter-spacing:-.022em;font-weight:600;
}
.detail-body .sec-hd .lead{max-width:var(--measure);margin-top:clamp(10px,1.1vw,14px)}

/* ---------- 1.5 · 小节标题：补上「章」与「条目」中间缺的那一级 ---------- */
/* 旧版 h3 用的是 --t3，和正文、条目标题同号（都是 18px）—— 全页二十来个小节标题
   扫过去读不出层级，只有「34px 章标题 / 18px 其他」两档。
   现在只把「小节级」的 h3（.blk 或 .group 的直接子级）提到 --t2b，
   行内条目标题（.hd 里的、.item 里的）仍走 .detail-body h3 的 --t3 ——
   它们本来就是条目，不该跟着放大。
   于是字阶落成：34 章 / 28 小节 / 22 块内主张 / 18 条目与正文 / 14 图注，五级单调递减。 */
.detail-body .blk > h3,
.detail-body .group > h3{
  font-size:var(--t2b);font-weight:600;line-height:1.28;letter-spacing:-.02em;
}

/* ---------- 2 · 竖向节奏 ---------- */
.detail-body .main{gap:0}
/* .main 是纵向 flex，默认 align-items:stretch 会把结尾这颗胶囊拉成整栏宽的一条 ——
   它是按钮，按内容宽就够 */
.detail-body .main > .btn{margin-top:clamp(48px,5vw,80px);align-self:flex-start}
.detail-body .main > section,
.detail-body .blk{display:flex;flex-direction:column;gap:0}
.detail-body .main > section + section{margin-top:clamp(72px,8vw,120px)}
/* 块与块之间的大留白；图注是图的一部分，单独收紧到 18px */
.detail-body .blk > * + *{margin-top:clamp(38px,4.4vw,68px)}
.detail-body .blk > .cap,
.detail-body .blk > .fig + .cap,
.detail-body .blk > .fig-row + .cap,
.detail-body .blk > .gal + .cap{margin-top:18px}
.detail-body .blk > .group{margin-top:clamp(56px,6.4vw,100px)}
.detail-body .blk > .stats{margin-top:clamp(30px,3.4vw,48px)}
/* 68px 是「块与块」之间的留白，标题与它的正文、以及同一段思路里的上下两句，
   都不该用这一档 —— 否则标题和内容被拆成两块，读起来是断的。
   这一条只收「标题/段落紧邻」的组合；跨块的 .group / .stats / .fig-row 仍走上面。
   h2 也要收：其它五张详情页的章节标题直接就是 .blk > h2（没有 .sec-hd），
   标题和它下面那句话之间同样是 68px，读起来像两个块。 */
.detail-body .blk > h3 + *,
.detail-body .blk > h2 + *,
.detail-body .blk > h4 + *,
.detail-body .blk > p + p,
.detail-body .blk > .lead + p{margin-top:clamp(14px,1.5vw,20px)}
.detail-body .group > h3 + *{margin-top:clamp(16px,1.8vw,26px)}

/* ---------- 3 · 图片分级 ---------- */
/* 整栏单图（.nat.full，如划掉即删、涂鸦工具栏分区、记忆胶带）：给上卡片投影，
   与组图落在同一种「白卡」语言上 */
.detail-body .fig.nat.full{background:var(--surface);box-shadow:0 14px 36px rgba(18,23,38,.10)}
/* 正文栏单图（960）：唯一一处「主图降到 960」的例外，给的是 §1 ——
   它的图源只有 816px 宽，拉到 1280 就是 1.57 倍放大，边缘明显发虚。
   圆角与投影照样给足，尺度小一档但仍是「作品」而不是「贴图」。
   图源换成 ≥1600px 之后，把这个类改成 .stage 即可。 */
.detail-body .fig.nat.card{
  border-radius:var(--r-card);overflow:hidden;background:var(--surface);
  box-shadow:0 18px 44px rgba(18,23,38,.13);
}
/* 章节主图：放开到整栏（960 → 1280），32 圆角 + 大投影，是这一章的视觉锚点。
   图片尺度只分三级 —— 主图 1280 / 组图按整栏分栏 / 细节图 520，
   不按当前图源像素临时缩水：图源是要被换掉的，版面尺度不该跟着它走。 */
.detail-body .fig.nat.stage{max-width:none;border-radius:var(--r-stage);overflow:hidden;box-shadow:0 28px 68px rgba(18,23,38,.15)}
/* 横带主图（书写手感）：2.5 那版是把机身缩在中间、两侧留 240px 白底换来的矮，
   卡片里左右两块空白看着就是「图没填满」。图源已按机身外框重裁（1154×634），
   容器比例跟着走 1.82，宽度收到 960 —— 机身正好铺满卡片，四周不留底。
   cover 是兜底：同比例下不裁内容。 */
.detail-body .fig.nat.band{aspect-ratio:1.82;max-width:960px}
.detail-body .fig.nat.band img{height:100%;object-fit:cover;object-position:center}
/* 结构图、指标自己带外边距会破坏上面的节奏，交回去统一管 */
.detail-body .map{margin:0}
/* 但「章节标题 → 结构图」这一档不能跟着归零：01 节里 h2 与三顶定义胶囊原本贴在一起，
   标题和它的图被读成一块。这一条按 .blk > * + * 的同一档留白补回来。 */
.detail-body .blk > .sec-hd + .map,
.detail-body .blk > h2 + .map,
.detail-body .group > .sec-hd + .map,
.detail-body .group > h3 + .map{margin-top:clamp(28px,3.4vw,48px)}

/* 组图统一到整栏：原先「组里的图行被收到 960、章节级的图行是 1280」，
   同一页里两列图一处在 468、一处在 628，尺寸说了两套话。现在一律跟着整栏走，
   两列 628、三列 411 —— 图才是这一页的主角。
   列宽保持等分：试过按图源像素分 2:3，列宽一不等两图高度就跟着不等，
   图注会落到两条基线上；图注横向读齐是这套版面的硬规则，不能破。 */
.detail-body .group > .fig-row{max-width:none}
/* 组图的统一画布：透明 PNG 原本落在灰底画布上、白底截图是另一种底，一组图两种底。
   统一压到白卡上，一组图看起来才是一组。 */
.fig-row .item > img{
  background:var(--surface);border-radius:var(--r-card);
  box-shadow:0 8px 22px rgba(18,23,38,.06);
}
.detail-body .group > * + *{margin-top:clamp(28px,3.2vw,46px)}
.detail-body .group > .cap,
.detail-body .group > .fig + .cap,
.detail-body .group > .fig-row + .cap,
.detail-body .group > .gal + .cap{margin-top:16px}

/* 循环演示视频：和组图落在同一张白卡上，比例按原片放进去，不裁切、
   不放大 —— 小V圈搜的演示要看得到「圈选 → 出结果」的全过程 */
.fig-row .item > video{
  display:block;width:100%;height:auto;aspect-ratio:var(--eq,1.5);
  object-fit:contain;background:var(--surface);border-radius:var(--r-card);
  box-shadow:0 8px 22px rgba(18,23,38,.06);
}

/* ---------- 3.5 · 图集：同一格里的多张同源图，切换查看 ---------- */
/* 同一件事的几个瞬间（呼出入口 → 划框 → 出工具条 → 取字）不该并排铺成四张小图 ——
   并排会把每一张挤小，也读不出先后。图集占原来那一格，换图不换版面：
   容器沿用 .fig-row 的等高约束（--eq），切换后这一格的高度不变，
   所以同一行两张图的图注基线不会被撑开。白卡、圆角、投影与 .fig-row .item > img
   完全一致，切换前后都还是「同一组图里的成员」。 */
.gal{
  position:relative;min-width:0;
  aspect-ratio:var(--eq,1.5);
  border-radius:var(--r-card);overflow:hidden;
  background:var(--surface);box-shadow:0 8px 22px rgba(18,23,38,.06);
  touch-action:pan-y;   /* 只接管横向手势，页面纵向滚动照旧 */
}
/* 章节级图集：和 .fig.nat.stage 同一个尺度与投影 */
.gal.stage{border-radius:var(--r-stage);box-shadow:0 28px 68px rgba(18,23,38,.15)}
/* 两张超长图集（涂鸦工具栏 7 张、全局摘录 8 张）：满栏 1280 下要占 800–850px 高，
   一屏里连图注都看不到。缩到 90%——1152 宽、高跟着掉到 720 / 768，
   图注回到一屏内；左边缘仍与正文同一条线，不做居中。 */
.gal.stage.fit90{max-width:90%}
/* 四张图源比例一致（都是 3:2），contain 让它们严丝合缝；
   若是混比例的一组，contain 会留边，也不会把图裁掉 */
.fig-row .gal > img,
.gal > img,
.gal > video{
  position:absolute;inset:0;
  width:100%;height:100%;
  object-fit:contain;object-position:center bottom;
  opacity:0;transition:opacity .3s ease;
  pointer-events:none;
}
.fig-row .gal > img.is-on,
.gal > img.is-on,
.gal > video.is-on{opacity:1}
/* 默认 contain：图集里混着不同比例（笔身手势那组还夹着一段视频）时，留边好过裁掉演示内容。
   整组都是截屏、要让图铺满卡片时，换成 .gal.fill —— 多出来的那一点裁掉，卡片里不留底。
   裁的量由 --eq 决定：随手写那四张比例在 1.42~1.60 之间，--eq:1.56 时每边最多只吃掉 2.5%，
   正好落在状态栏、页面留白这些没有信息的地方。 */
.gal.fill > img{object-fit:cover}
/* 切换控件：圆点常驻（触屏点它、也能左右划），指针设备悬停时两侧再给箭头。
   底座用玻璃胶囊 —— 图片深浅不定，裸圆点会时隐时现 */
.gal-dots{
  position:absolute;left:50%;bottom:14px;z-index:2;transform:translateX(-50%);
  display:flex;align-items:center;gap:8px;
  margin:0;padding:7px 11px;border-radius:var(--r-pill);
  /* 用近乎实心的白：截图底部常是浅色 dock，半透明玻璃会让圆点糊在底图里认不出来 */
  background:rgba(255,255,255,.94);
  -webkit-backdrop-filter:blur(16px) saturate(170%);
  backdrop-filter:blur(16px) saturate(170%);
  box-shadow:0 4px 16px rgba(18,23,38,.18),0 0 0 1px rgba(18,23,38,.06);
}
.gal-dot{
  width:6px;height:6px;padding:0;border:0;border-radius:var(--r-pill);
  background:rgba(18,23,38,.28);cursor:pointer;
  transition:width .24s ease,background-color .24s ease;
}
.gal-dot.is-on{width:18px;background:var(--accent)}
.gal-dot:focus-visible{outline:2px solid var(--ink);outline-offset:3px}
.gal-btn{
  position:absolute;top:50%;z-index:2;transform:translateY(-50%);
  display:grid;place-items:center;width:34px;height:34px;padding:0;
  border:0;border-radius:var(--r-pill);cursor:pointer;color:var(--ink-2);
  background:rgba(255,255,255,.72);
  -webkit-backdrop-filter:blur(16px) saturate(170%);
  backdrop-filter:blur(16px) saturate(170%);
  box-shadow:0 4px 16px rgba(18,23,38,.16);
  opacity:0;transition:opacity .2s ease,color .2s ease;
}
.gal-btn svg{display:block;width:15px;height:15px}
.gal-btn.prev{left:12px}
.gal-btn.next{right:12px}
.gal:hover .gal-btn,.gal:focus-within .gal-btn{opacity:1}
.gal-btn:hover{color:var(--ink)}

/* ---------- 3.6 · 手势双栏：说明在左、演示在右 ---------- */
/* 参考官方同一节的排法：左栏一句话主张压住整块的重量，底下一排三个手势，
   图标在上、名称与短注在下；右栏一张演示图。
   三个手势同时兼任切换控件 —— 点哪一条、点圆点、或者横向划一下，右边的演示都跟着换。
   三张素材本来就是同一件事的三个瞬间，摊成三张并排卡反而读不出先后。
   图标沿用参考图的实心色块（不是本页的线性图标）：交叠双圆＝轻捏、单圆＝双击、
   实心圆加一圈涟漪＝长捏。色块恒为强调色的深浅两档，激活态只提饱和度，不引入新色。 */
.gesture{
  display:grid;grid-template-columns:minmax(0,.86fr) minmax(0,1fr);
  gap:clamp(28px,3.6vw,64px);align-items:center;
}
.gesture .g-title{
  font-size:var(--t2d);line-height:1.35;letter-spacing:-.02em;font-weight:600;color:var(--ink);
}
.gesture .g-desc{margin-top:16px;font-size:var(--t4);line-height:1.85;color:var(--sub);max-width:32em}
.gesture .g-list{
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  gap:clamp(14px,1.6vw,28px);margin-top:clamp(26px,3vw,40px);
}
.g-item{
  display:block;width:100%;padding:0;border:0;background:none;
  text-align:left;cursor:pointer;
}
.g-item .g-ic{
  display:block;height:30px;color:rgba(255,77,45,.34);
  transition:color .2s ease;
}
.g-item .g-ic svg{display:block;width:30px;height:30px}
.g-item .g-n{
  display:block;margin-top:14px;font-size:var(--t3);font-weight:600;
  letter-spacing:.01em;color:var(--sub);transition:color .2s ease;
}
.g-item .g-s{display:block;margin-top:6px;font-size:var(--t4);line-height:1.7;color:var(--mute)}
.g-item:hover .g-n{color:var(--ink)}
.g-item.is-on .g-ic{color:var(--accent)}
.g-item.is-on .g-n{color:var(--ink)}
.g-item:focus-visible{outline:2px solid var(--ink);outline-offset:6px;border-radius:var(--r-thumb)}
.gesture .gal{--eq:1.34}
/* 屏幕快捷方式借用同一套「演示 + 可点清单」，只把两栏对调 —— 图左、文右。
   两项的说明比笔身操作那三个长，清单走两列；两栏取等宽（而不是镜像 .86fr/1fr），
   是为了让「任意界面从右上角向内滑，呼出全局标注。」在 1440 下不折行 ——
   它 20 个字、按 --t4 是 280px，正好卡在两列等分后的 294px 里。 */
.gesture.rev{grid-template-columns:repeat(2,minmax(0,1fr))}
.gesture .g-list.two{grid-template-columns:repeat(2,minmax(0,1fr))}
/* 清单上面没有 g-title/g-desc 时，那 40px 间隔会把清单整体顶下去，
   和左侧演示的垂直居中对不齐 —— 第一项直接贴住列顶 */
.gesture-copy > .g-list:first-child{margin-top:0}

@media (max-width:820px){
  /* 手机端落成一列：先读主张与手势清单，再看演示 —— 图集不再和清单抢一行 */
  .gesture,.gesture.rev{grid-template-columns:1fr;gap:24px}
}

/* ---------- 3.7 · 吸附即连接：一张大图 + 四张状态卡 ---------- */
/* 四张卡片是同一句提示的四种后缀（正在连接 / 99% / 解锁以连接 / 连接失败），
   并排一行读起来是一条并列的清单，正好对上图注里的四种场景，所以窄栏时留在图下。
   栏宽够（≥1200）时改挂到大图右边：一列四张，高度正好和大图齐平，省掉一屏竖向空间。
   断点定在 1200 而不是更早：卡片里的字是位图，落到 200px 出头就开始糊，
   宁可让它回到下面横排 —— 下面四张并排时每张还有 200px 出头。
   手机上连 200px 都不到，落成两行两列。 */
.attach{display:grid;gap:clamp(14px,1.6vw,24px)}
.attach-main{
  overflow:hidden;border-radius:var(--r-card);background:var(--surface);
  box-shadow:0 8px 22px rgba(18,23,38,.06);
}
.attach-main img{display:block;width:100%;height:auto}
.attach-states{
  display:grid;grid-template-columns:repeat(4,minmax(0,1fr));
  gap:clamp(10px,1.4vw,20px);align-items:center;
}
.attach-states img{display:block;width:100%;height:auto}

@media (min-width:1200px){
  /* 3.2 : 1 是按「右栏四张卡的总高 = 大图高」解出来的列宽，两栏底部才对得齐 */
  .attach{grid-template-columns:minmax(0,3.2fr) minmax(0,1fr);align-items:center;gap:clamp(24px,2.4vw,40px)}
  /* 卡片位图自带 20px 左右的外边距，一列的间距靠它撑，gap 只补一点点 */
  .attach-states{grid-template-columns:minmax(0,1fr);gap:clamp(2px,.5vw,8px)}
}
@media (max-width:560px){
  .attach-states{grid-template-columns:repeat(2,minmax(0,1fr))}
}

/* ---------- 4 · 图注：大图配窄注 ---------- */
/* 图注限宽到 640，让「很宽的图 + 很窄的注」形成对比，读者的眼睛先看图再看注 */
.detail-body .blk > .fig + .cap,
.detail-body .blk > .gal + .cap{max-width:min(var(--measure),640px)}

/* ---------- 5 · 结果：编辑式的指标栏 ---------- */
.detail-body .stats .item{padding-top:clamp(20px,2.2vw,30px);border-top:1px solid var(--line)}

/* 三条支柱（体验一致性）：借 .stats 的三栏与顶部发丝线，只是把条目标题提回 --t3，
   它在这节里是「结论」而不是指标的附属标签 */
.stats.pillars .item .t{font-size:var(--t3);font-weight:600;letter-spacing:-.005em;margin-top:0}

/* 规范链接卡：整块可点，右侧常驻「查看」——链接本身是这一节的主角，不做成一行图注 */
.rule-card{
  display:flex;align-items:center;justify-content:space-between;
  gap:32px 56px;flex-wrap:wrap;
  padding:clamp(24px,2.4vw,36px) clamp(24px,2.6vw,40px);
  border-radius:var(--r-card);border:1px solid var(--line);background:var(--surface);
  transition:border-color .18s ease,box-shadow .18s ease;
}
.rule-card:hover{border-color:var(--ink-2);box-shadow:0 14px 36px rgba(18,23,38,.10)}
.rule-card .txt{display:flex;flex-direction:column;gap:8px;min-width:0}
.rule-card .k{font-family:var(--mono);font-size:var(--t4b);letter-spacing:.16em;text-transform:uppercase;color:var(--mute)}
.rule-card .t{font-size:var(--t3);font-weight:600;color:var(--ink);letter-spacing:-.005em}
.rule-card .d{font-size:var(--t4);line-height:1.85;color:var(--sub)}
.rule-card .more{font-size:var(--t4);font-weight:500;color:var(--accent-ink);white-space:nowrap}
.rule-card:hover .more{color:var(--ink)}

@media (max-width:820px){
  .detail-body .main > section + section{margin-top:64px}
  .detail-body .blk > * + *{margin-top:32px}
  .detail-body .blk > .cap,
  .detail-body .blk > .fig + .cap,
  .detail-body .blk > .fig-row + .cap,
  .detail-body .blk > .gal + .cap{margin-top:14px}
  .detail-body .blk > .group{margin-top:56px}
  .detail-body .group > * + *{margin-top:24px}
  .detail-body .sec-hd{padding-top:26px}
  .detail-body .fig.nat.stage{border-radius:var(--r-card)}
  .gal.stage{border-radius:var(--r-card)}
  .detail-body .blk > .fig + .cap{max-width:none}
  .detail-body .blk > .gal + .cap{max-width:none}
  .detail-body .stats .item{padding-top:20px}
  /* 手机上收掉两侧箭头 —— 本来也没有悬停态，滑动和圆点才是真正的手势 */
  .gal-btn{display:none}
  .gal-dots{bottom:10px;padding:6px 10px;gap:7px}
  .gal-dot{width:5px;height:5px}
  .gal-dot.is-on{width:15px}
}

@media (prefers-reduced-motion:reduce){
  .gal > img,.gal-dot,.gal-btn{transition:none}
}
