/* 之前挂的是 Google Fonts，国内网络访问 fonts.googleapis.com/
   fonts.gstatic.com 经常很慢甚至连不上，非阻塞加载也只是不挡首绘，
   字体该等的还是要等。改成把字体文件下载下来放进 assets/fonts/ 自己
   域名下发，彻底不依赖 Google */
@font-face {
  font-family: 'Instrument Sans';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url('/assets/fonts/instrument-sans-var.woff2') format('woff2');
}
@font-face {
  font-family: 'Instrument Serif';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/instrument-serif-400-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'Instrument Serif';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/instrument-serif-400-italic.woff2') format('woff2');
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 400 500;
  font-display: swap;
  src: url('/assets/fonts/jetbrains-mono-400.woff2') format('woff2');
}

:root {
  --ground: #18140f;
  --ground-2: #1f1911;
  --surface: #241d14;
  --surface-hover: #2c2317;
  --hairline: #3a3021;
  --ink: #f6efe1;
  --ink-dim: #ad9f86;
  --ink-faint: #918469; /* 原来 #6f6551 对比度只有 ~3:1，不满足 WCAG AA 正文的 4.5:1，调亮到刚好够（对 --surface 最紧，4.5:1） */
  --garnet: #d9707e;
  --garnet-soft: rgba(217, 112, 126, 0.14);
  --garnet-glow: rgba(217, 112, 126, 0.4);
  --teal: #62c7b6;
  --teal-soft: rgba(98, 199, 182, 0.13);
  --teal-glow: rgba(98, 199, 182, 0.35);
  --amber: #dba556;
  --amber-soft: rgba(219, 165, 86, 0.14);
  --amber-glow: rgba(219, 165, 86, 0.38);
  --violet: #a08bdb;
  --violet-soft: rgba(160, 139, 219, 0.14);
  --violet-glow: rgba(160, 139, 219, 0.38);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--ground);
  color: var(--ink);
}

body {
  font-family: 'Instrument Sans', ui-sans-serif, system-ui, -apple-system, sans-serif;
  -webkit-font-smoothing: antialiased;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  position: relative;
  overflow-x: hidden;
}

.serif { font-family: 'Instrument Serif', ui-serif, Georgia, serif; }
.mono { font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace; }
a { color: inherit; }

/* ── 质感层：颗粒 + 跟随鼠标的灯光 ─────────────────────── */

.grain {
  position: fixed;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  opacity: 0.045;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* 页面级"灯光"：鼠标走到哪，暖光就跟到哪，呼应"都留一盏灯"
   默认是 CSS 渐变兜底；WebGL 可用时 JS 会换成真正的逐像素着色器 */
.ambient {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(720px circle at var(--px, 50%) var(--py, 28%), var(--garnet-soft), transparent 62%),
    radial-gradient(900px circle at 88% 92%, var(--teal-soft), transparent 55%);
  transition: background-position 60ms linear;
}

#bgShader {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  display: none;
  width: 100%;
  height: 100%;
}

/* ── 鼠标拖尾流体模拟：手写的实时流体求解器（平流 + 压力投影），
   叠在背景光效上面、正文下面，screen 混合让颜色只往亮处叠，
   不会盖住文字 ─────────────────────────────────────────── */

.fluid-canvas {
  position: fixed;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  display: none;
  width: 100%;
  height: 100%;
  mix-blend-mode: screen;
  opacity: 0.55; /* screen 混合在深色背景上本来就接近直接叠加亮度，光调 shader 里的颜色数值压不住"晃眼睛"的感觉，这里直接再拦一道 */
}

@media (prefers-reduced-motion: reduce) {
  .fluid-canvas { display: none !important; }
}

/* ── 真实天气：终端里 weather on 触发，请求定位后读当前真实天气，
   下雨/下雪才会画对应的粒子——不是装饰性动画，是接了真实数据的 ── */

.weather-canvas {
  position: fixed;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  width: 100%;
  height: 100%;
}

@media (prefers-reduced-motion: reduce) {
  .weather-canvas { display: none !important; }
}

/* ── CRT 后处理开关：叠在整页最上层的手写 WebGL 滤镜（扫描线 +
   暗角 + 噪点颗粒 + 偶发故障撕裂），终端里输 crt on/off 触发 ──── */

.crt-canvas {
  position: fixed;
  inset: 0;
  z-index: 40;
  width: 100%;
  height: 100%;
  pointer-events: none;
  opacity: 0;
  transition: opacity 260ms ease;
}

.crt-canvas.is-active { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .crt-canvas { display: none; }
}

header, main, footer, .showcase { position: relative; z-index: 2; }

main {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: 0;
}

/* ── 顶部状态条：不是装饰性关键词，是真实数据实时滚动
   （本地时间/渲染器/FPS/灯的状态/页面指纹……都是页面本身
   已经在算的真实数值，只是搬到这里展示） ──────────────── */

.status-ticker {
  border-bottom: 1px solid var(--hairline);
  overflow: hidden;
  white-space: nowrap;
  padding: 9px 0;
  background: var(--ground-2);
}

.status-ticker-track {
  display: inline-block;
  animation: scroll-left 40s linear infinite;
}

.status-ticker-half {
  display: inline-block;
}

.status-ticker-track span {
  display: inline-flex;
  align-items: center;
  font-family: 'JetBrains Mono', monospace;
  font-size: 11.5px;
  letter-spacing: 0.1em;
  color: var(--ink-faint);
  padding: 0 22px;
}

.status-ticker-track span::before {
  content: '';
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: var(--garnet);
  margin-right: 22px;
  flex-shrink: 0;
}

.status-ticker-track span b {
  color: var(--ink-dim);
  font-weight: 500;
  margin-left: 6px;
}

@keyframes scroll-left {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}

@media (prefers-reduced-motion: reduce) {
  .status-ticker-track { animation: none; }
}

/* ── 音乐频谱条：AnalyserNode 实时 FFT + 波形，播放时才展开，
   暂停时收起来，不占地方 ──────────────────────────────── */

.spectrum-bar {
  position: relative;
  height: 0;
  overflow: hidden;
  background: var(--ground-2);
  border-bottom: 1px solid transparent;
  transition: height 420ms cubic-bezier(0.16, 1, 0.3, 1), border-color 420ms ease;
}

.spectrum-bar.is-active {
  height: 46px;
  border-bottom-color: var(--hairline);
}

.spectrum-bar canvas {
  display: block;
  width: 100%;
  height: 100%;
}

.spectrum-label {
  position: absolute;
  right: 14px;
  bottom: 5px;
  font-size: 9.5px;
  letter-spacing: 0.1em;
  color: var(--ink-faint);
  opacity: 0.75;
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  .spectrum-bar { display: none; }
}

/* ── 顶部署名 ─────────────────────────────────────────── */

header {
  padding: clamp(28px, 5vw, 48px) clamp(24px, 6vw, 72px) 0;
}

.mark {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
}

.mark-name {
  font-size: 14px;
  letter-spacing: 0.02em;
  color: var(--ink-dim);
}

.mark-name b {
  color: var(--ink);
  font-weight: 500;
}

.mark-tag {
  font-size: 11.5px;
  letter-spacing: 0.1em;
  color: var(--ink-faint);
}

/* ── 主标题：更有分量的宣言式排版 ────────────────────────── */

.thesis-wrap {
  padding: 0 clamp(8px, 2vw, 24px) clamp(48px, 8vw, 88px);
  text-align: center;
  opacity: 0;
  animation: rise 900ms cubic-bezier(0.16, 1, 0.3, 1) 120ms forwards;
}

.thesis {
  max-width: 920px;
  margin: 0 auto;
  font-size: clamp(36px, 5.6vw, 76px);
  line-height: 1.1;
  font-weight: 400;
  letter-spacing: -0.01em;
  text-wrap: balance;
  /* 灯没点亮之前，标题只是个空心轮廓；拉亮灯才"显影"填色 */
  color: transparent;
  -webkit-text-stroke: 1.3px var(--ink);
  transition: color 550ms ease, -webkit-text-stroke-color 550ms ease;
}

.thesis .accent-word {
  font-style: italic;
  color: transparent;
  -webkit-text-stroke: 1.3px var(--garnet);
}

body.lamp-on .thesis {
  color: var(--ink);
}

body.lamp-on .thesis .accent-word {
  color: var(--garnet);
  -webkit-text-stroke-color: var(--garnet);
}

@supports not (-webkit-text-stroke: 1px black) {
  .thesis,
  .thesis .accent-word {
    color: var(--ink);
    -webkit-text-stroke: 0;
  }
  .thesis .accent-word { color: var(--garnet); }
}

.thesis-sub {
  margin: 24px auto 0;
  max-width: none;
  white-space: nowrap;
  font-size: clamp(12px, 1.5vw, 17px);
  line-height: 1.7;
  color: var(--ink-dim);
}

@media (max-width: 640px) {
  .thesis-sub {
    white-space: normal;
    max-width: 34ch;
    margin-left: auto;
    margin-right: auto;
  }
}

@keyframes rise {
  from { opacity: 0; transform: translateY(18px); }
  to { opacity: 1; transform: translateY(0); }
}

.auth-controls { display: flex; align-items: center; gap: .5rem; font-size: .8rem; }
.auth-controls a, .auth-controls button { color: var(--teal); }
.auth-controls button { background: none; border: 1px solid currentColor; border-radius: 4px; padding: .2rem .4rem; }
.auth-controls [hidden] { display: none; }
@media (max-width: 600px) { .mark-tag, .mark-divider { display: none; } }

.auth-controls span { max-width: 8rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
