/* ============================================================
   基础层：重置 + 文档 + 通用容器
   ============================================================ */
*{box-sizing:border-box;margin:0;padding:0}
a{color:inherit;text-decoration:none}
/* 选区用主题基调蓝（--tint-hi 的 38%）—— 这是"面"的层次，不是行动色。
   ★ 不用 --brand：选中文字时若满屏黄底，会被误读成"这里可以点"。 */
::selection{background:rgba(61,135,200,.40);color:#fff}

body{
  background:var(--bg); color:var(--ink); font-family:var(--sans);
  -webkit-font-smoothing:antialiased; overflow-x:hidden;
}

/* 通用内容容器（内页与注入内容共用）
   ★ 宽度唯一来源：--container-w / --gutter。导航、页脚必须复用同一套值，
     否则窄导航栏浮在宽正文上会显得脱节。 */
.wrap{position:relative;z-index:1;width:min(var(--container-w), calc(100% - var(--gutter) * 2));margin:0 auto}
main{position:relative;z-index:1}

/* 窄屏只改 gutter，不改容器定义本身 */
@media (max-width:860px){ :root{ --gutter:20px } }

/* 仅首页（有地球 hero）铺满视口且不滚动。
   ★ 不能写成全局 html,body{width:100vw} —— 100vw 含滚动条宽度，
     内页有纵向滚动条时会溢出出横向滚动条。
   ★ 高度用 dvh 而不是只有 vh：移动端浏览器的地址栏会收缩/展开，
     100vh 是"地址栏收起时"的高度，于是首屏底部会被地址栏切掉一截
     （hero 是 overflow:hidden，切掉就真的看不到了）。dvh 跟随动态视口，
     vh 保留在前一行给不认识的浏览器兜底。 */
body.has-hero{width:100vw;height:100vh;height:100dvh;overflow:hidden}

/* ============================================================
   排版细节层
   —— 都是"说不出来但能感觉到"的项，纯渐进增强，老浏览器忽略也不影响
   ============================================================ */

/* 标题断行：避免最后一行只剩一两个字（"孤儿词"）。
   balance 会主动把长标题均分成两行，观感立刻从"网页"变成"排版过的"。 */
h1,h2,h3,h4,.card h3,.post-card .title,.empty-state h1,.empty-state h2{text-wrap:balance}
/* 段落断行：只在必要时才让最后一行掉字（避免整段被推成"最后一行一个词"） */
p,li,.entry-content p,.card p,.post-card .excerpt{text-wrap:pretty}

/* 数字对齐：等宽字体之外，凡是"同一列里上下比较数字"的地方都要等宽数字，
   否则 1 和 8 宽度不同会让整列抖动。sans 字体的数字默认多为比例宽度。 */
.kpi .val,.ops-strip .v,.card .fig b,.tl .yr,.bar-row .n,.pager .page-numbers,
.ops-strip .k,.post-meta,.coord .v small,.author-card .nm{
  font-variant-numeric:tabular-nums;
  font-feature-settings:"tnum" 1,"lnum" 1;
}

/* 长正文的舒适行宽（中文 68ch 左右）：超宽屏上正文铺满整行会读不下去 */
.entry-content p,.entry-content li{max-width:var(--measure)}

/* 链接下划线的落位：默认下划线紧贴字底，会切到中文的降部 */
a{text-underline-offset:3px}

/* ============================================================
   颗粒层（film grain）
   —— 深色大屏最容易"脏"也最容易"塑料"的地方就在这里：
     纯色渐变在 8bit 屏上会产生色带，加一层极低不透明度的噪点后
     ① 打散色带 ② 让"玻璃"看起来是块有物理质感的材料而不是 CSS 色块。
     用内联 SVG turbulence 生成，零请求、可平铺、GPU 合成。
     opacity 必须极低（.03 上下）——再高就从"质感"变成"噪点画面"了。
   ============================================================ */
.bg-fx::after,#bg::after{
  content:"";position:absolute;inset:0;pointer-events:none;z-index:2;
  opacity:.032;mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.82' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size:160px 160px;
}
@media (prefers-reduced-transparency:reduce){ .bg-fx::after,#bg::after{opacity:0} }

/* ---------- 原生滚动条：深色皮肤 + 常驻槽位 ----------
   ★ 槽位常驻（scrollbar-gutter:stable）不是审美问题而是布局问题：导航是
     fixed + translateX(-50%) 居中，位置靠容器的 100% 算，而 100% 会随
     "这一页有没有滚动条"变化 —— 长列表与短页面互相跳转时导航会横移十几像素。
     常驻槽位把这个变量彻底消掉。
   ★ 首页例外：body.has-hero 是 overflow:hidden 的全屏 hero（没有滚动条），
     若也常驻槽位会在右侧凭空留一条空带。
   ★ 标准属性（scrollbar-color / -width）会被 Chrome 121+ 与 Firefox 采用，
     并让它们忽略下面的 webkit 伪元素；Safari 与旧 Chrome 走 webkit 那条路。 */
html{scrollbar-gutter:stable;scrollbar-color:rgba(5,217,232,.26) rgba(13,15,18,.55);scrollbar-width:thin}
html:has(body.has-hero){scrollbar-gutter:auto}
/* webkit 伪元素是"通配"写法（不留空格的裸选择器）—— 顺带把 <pre>、侧边栏
   这类内层滚动区也刷成同一套，避免深色页面里突然出现一根浅色小条。 */
::-webkit-scrollbar{width:11px;height:11px}
::-webkit-scrollbar-track{background:rgba(13,15,18,.40)}
::-webkit-scrollbar-thumb{border:3px solid transparent;border-radius:9px;background-clip:content-box;
  background-color:rgba(5,217,232,.30)}
::-webkit-scrollbar-thumb:hover{background-color:rgba(5,217,232,.55)}
::-webkit-scrollbar-corner{background:transparent}
