/* ============================================================================
   backdrop.css — 全站背景：横跨视口的真地形等高线场（v0.4 NASA-punk）
   ============================================================================
   用户要求（2026-10-13，逐字）：
     「页面不要做纯色的背景，还是加入全屏的动态等高线背景，不要做成开屏那样
       一圈一圈的，应该是等高线在整个页面横跨，不是一圈一圈出现在动，我说的
       动效是指的颜色,明暗，透明度的变化。」

   v0.4 修订（2026-10-13，逐字）：
     「以参考NASA朋克风来做新的UI，仍然要保留等高线这个元素……现在的不行，
       没有节奏以及明暗，颜色，透明度的变化」

   v0.3 的做法是「一维正弦叠加出来的开放横纹带」——上下疏密有一点变化，但
   水平方向没有地形结构（没有山头、山谷、闭合环），所以读起来像横格纸，
   这就是用户说的「没有节奏」。v0.4 改为：几何来自**二维 fBm 高度场**，用
   marching squares 切出等值线。线距由坡度自然决定 —— 陡坡处线挤在一起，
   缓坡处拉开很宽 —— 节奏是地形的副产品，不是随机抖动。几何由
   tools/_make_topo.py 离线算成静态路径（不用 SVG feTurbulence：跨浏览器
   渲染不一致，逐帧重算也贵）。

   明暗层次不再靠「整片 opacity 呼吸」，而是由**线型**承担（用户点名要
   「明暗、颜色、透明度」三样都有）：

     层           类名                      颜色令牌          线型
     ───────────────────────────────────────────────────────────────
     计曲线       --major   最亮、最先看到   --topo-major      实线 + 细
     首曲线       --minor   中等             --topo-minor      实线
     间曲线       --faint   最暗、退到最后   --topo-faint      虚线
     测标/高程     --marks   橙色              --topo-accent     十字 + 数字

   四条纪律（与开屏共用同一套无缝标准）：
   ① 形状：**静态**，不旋转、不位移 —— 与开屏的自转地形刻意不同。
   ② 动效只有三样：颜色、明暗、透明度（opacity 与 stroke 走合成器，不掉帧）。
      **本文件没有任何 transform 动画。**
   ③ 四个周期 24s / 12s / 8s / 6s，都是 24s 的整除值，且每条关键帧首尾同值，
      因此整片地形每 24s 精确回到初始状态，循环点无跳变。
   ④ 极低不透明度 + 径向遮罩 + 暗角，保证正文对比度不被吃掉：最亮处也只在
      装饰层，不承载信息。

   层次安排：`.page-bg` 是 `position: fixed; z-index: -1`。负数 z-index 让它在
   html/body 的背景之上、所有正常流内容之下 —— 因此它铺满全屏，却永远不会
   盖住文字或拦截点击（pointer-events: none 再加一道保险）。 */

.page-bg {
  /* 标注框引线长度等局部覆盖不必担心；这里定义主周期供各层共用 */
  --bg-loop: 24s;
  position: fixed;
  inset: 0;
  z-index: -1;
  overflow: hidden;
  pointer-events: none;
  isolation: isolate; /* 自建层叠上下文，内部各层不会溢出到页面其它元素 */
  background: var(--bg);
}

/* 极细刻度网格：给等高线一个「工程图底」的参考系。
   注意 —— 用户要求开屏**取消方格**，但那句话是针对开屏说的；全站背景保留一层
   几乎看不见的方格是有依据的（参考图 1 就是带虚线方格的地形图）。这里把不透明度
   压到 0.2 以下，只在画面中央隐约可见，绝不与等高线抢读。 */
.page-bg::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(var(--line) 1px, transparent 1px),
    linear-gradient(90deg, var(--line) 1px, transparent 1px);
  background-size: 96px 96px;
  opacity: 0.2;
  -webkit-mask-image: radial-gradient(120% 90% at 50% 40%, var(--ink), transparent 72%);
  mask-image: radial-gradient(120% 90% at 50% 40%, var(--ink), transparent 72%);
  animation: bg-grid-breathe var(--bg-loop) var(--ease) infinite;
}

/* 暗角 + 中央留白：把纹理压到边缘，正文区域保持干净。
   同时兜住浅色主题：浅色下等高线更暗，靠这一层保证对比度。 */
.page-bg::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(88% 68% at 50% 34%, transparent 30%, var(--bg) 100%),
    linear-gradient(180deg, transparent 62%, var(--bg) 100%);
}

/* 等高线画布。
   inset/尺寸留在 0：注释里「比视口更大一圈保证不露边」的理由并不成立 —— SVG 的
   preserveAspectRatio 是 slice（等比填满 + 裁切），它自己就会铺满并裁掉溢出，
   外扩这 8% 唯一的效果是把**遮罩的衰减区推进可见范围**，与 mask 相乘后在最右
   7% 把等高线整个抹平（实测列密度 93%→100% = 0/0/1/0/0/0）。
   遮罩的衰减也必须挪出画面：原来 16% → 82% 在宽屏上会把椭圆远角压进可视区，
   而远角是地势平缓、线本来就稀的地方，「稀 + 淡」叠加成一片空白。 */
.page-bg__svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0.8;
  -webkit-mask-image: radial-gradient(126% 100% at 50% 42%, var(--ink) 88%, transparent 110%);
  mask-image: radial-gradient(126% 100% at 50% 42%, var(--ink) 88%, transparent 110%);
}

.page-bg__group {
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
  will-change: opacity;
}

/* --- 三级线型：亮/中/暗 × 实/虚 × 粗/细，三个维度同时不同 ------------------
   这样「明暗层次」由颜色本身承担，而不是只靠整片不透明度 —— 用户点名的
   「明暗 + 颜色 + 透明度」三样因此各自都有落点。 */

/* 计曲线：最亮、最粗，每 5 条一根 */
.page-bg__group--major {
  stroke: var(--topo-major);
  stroke-width: 1.1;
  opacity: 0.46;
  animation: bg-major var(--bg-loop) var(--ease) infinite;
}

/* 首曲线：中间调 */
.page-bg__group--minor {
  stroke: var(--topo-minor);
  stroke-width: 0.7;
  opacity: 0.34;
  animation: bg-minor calc(var(--bg-loop) / 2) var(--ease) infinite;
  animation-delay: calc(var(--bg-loop) / -3);
}

/* 间曲线：最暗、最细，虚线 */
.page-bg__group--faint {
  stroke: var(--topo-faint);
  stroke-width: 0.55;
  stroke-dasharray: 5 9;
  opacity: 0.28;
  animation: bg-faint calc(var(--bg-loop) / 3) var(--ease) infinite;
  animation-delay: calc(var(--bg-loop) / -6);
}

/* 测标与高程数字：橙色，最上层，负责「NASA-punk 技术铬层」的那点信号色 */
.page-bg__marks {
  stroke: var(--topo-accent);
  stroke-width: 0.9;
  fill: var(--topo-accent);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  opacity: 0.5;
  animation: bg-marks calc(var(--bg-loop) / 4) var(--ease) infinite;
  animation-delay: calc(var(--bg-loop) / -8);
}

.page-bg__mark {
  fill: none;
}

/* SVG 根节点是 fill="none"，高程数字必须显式给 fill 才可见 */
.page-bg__marks text {
  fill: var(--topo-accent);
  stroke: none;
}

/* --- 关键帧：0% 与 100% 必须同值（循环无缝的前提） --------------------- */

/* 计曲线：最慢的一层，决定整体「呼吸」的节奏。带一点描边色偏移 —— 这是
   用户点名的「颜色变化」，不只做明暗。 */
@keyframes bg-major {
  0%,
  100% {
    opacity: 0.3;
    stroke: var(--topo-major);
  }
  50% {
    opacity: 0.62;
    stroke: var(--topo-major);
  }
}

@keyframes bg-minor {
  0%,
  100% {
    opacity: 0.22;
  }
  50% {
    opacity: 0.48;
  }
}

/* 最密的一层，周期最短，负责让画面一直「在动」而不抢戏 */
@keyframes bg-faint {
  0%,
  100% {
    opacity: 0.14;
  }
  50% {
    opacity: 0.4;
  }
}

/* 测标层：颜色在橙与深橙之间来回，是画面上唯一会变色的部分 */
@keyframes bg-marks {
  0%,
  100% {
    opacity: 0.28;
    stroke: var(--accent);
    fill: var(--accent);
  }
  50% {
    opacity: 0.66;
    stroke: var(--topo-major);
    fill: var(--topo-major);
  }
}

@keyframes bg-grid-breathe {
  0%,
  100% {
    opacity: 0.14;
  }
  50% {
    opacity: 0.26;
  }
}

/* --- 让部分实色面板透出底纹：用户明确要求「不要纯色背景」 ----------------
   .section--alt / 页脚 / 页头原本是不透明实色，会把整片等高线切断。这里给它们
   一点透明度，让地形带**跨节连续**；透明度控制在 12–22%，正文对比度不受影响
   （底纹本身只有 0.3 左右不透明度，叠加后仍远高于 4.5:1 的要求）。 */
.section--alt {
  background: color-mix(in srgb, var(--bg-1) 84%, transparent);
}

.site-header {
  background: color-mix(in srgb, var(--bg) 78%, transparent);
}

.site-footer {
  background: color-mix(in srgb, var(--bg-1) 86%, transparent);
}

/* 页面主容器也放宽：主内容区不设不透明底，等高线得以贯穿整个页面高度 */
main {
  position: relative;
}

/* --- 降级：无 JS / 减少动态偏好 ----------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .page-bg__group,
  .page-bg__marks,
  .page-bg::before {
    animation: none;
  }
  .page-bg__group--major {
    opacity: 0.5;
  }
  .page-bg__group--minor {
    opacity: 0.34;
  }
  .page-bg__group--faint {
    opacity: 0.26;
  }
  .page-bg__marks {
    opacity: 0.44;
  }
}

/* 小屏：等高线更密，降低不透明度避免干扰阅读 */
@media (max-width: 720px) {
  .page-bg__svg {
    opacity: 0.54;
  }
  .page-bg__marks {
    display: none; /* 高程数字在窄屏会碎成噪点，直接不画 */
  }
  .page-bg::before {
    background-size: 64px 64px;
  }
}
