/* 侧边栏背景图保持原色：取消玻璃效果的 400% 饱和度增强 */
.l_left .sidebg {
  --saturate: 100%;
}

/* ===== 排版工具类（控制台工具栏的「居中 / 右对齐 / 落款」按钮用这些类）===== */
.text-left { text-align: left; }
.text-center { text-align: center; }
.text-right { text-align: right; }

/* ===== 关于页（/about/）专属背景图 =====
 * 用独立的 fixed 图层放背景图（由 scripts/about-page.js 插到 <body> 后面）。
 * 不要挂在 body 的 background 上：body 的背景会被提升成「画布背景」，滚动时
 * background-attachment: fixed + background-size: cover 会出现硬边/分界线。
 * 调整 --about-bg-opacity 控制图片可见度（0~1，越大越明显）。
 */
.about-bg {
  --about-bg-opacity: 0.25;
  position: fixed;
  inset: 0;
  z-index: -2;
  background-image: url('/images/about-bg.jpg');
  background-position: center center;
  background-size: cover;
  background-repeat: no-repeat;
  opacity: var(--about-bg-opacity);
  pointer-events: none;
}

/* ===== 关于页：铺满全屏的三角形光网 + 点击点亮 =====
 * 三族平行线（方向 0° / 60° / 120°，法向间距相同）交叉成标准的等边三角形网格——
 * 就是一堆一样大的三角形，没有「大格 / 小格」之分。
 * CSS 的 repeating-linear-gradient 各角度相位对不齐，拼不出规整三角网，所以改用 JS 生成 SVG：
 * - .about-grid-plane：常驻底网，fixed 铺满视口，SVG 由 source/js/about-click-glow.js 生成
 * - .about-spark：点击时叠一层同几何、更亮的网，用会变大的径向遮罩只露出鼠标附近，再淡出
 * 两层都是 fixed、用同一份 viewBox 几何，所以点亮区和底网严丝合缝。
 */
.about-grid-plane,
.about-spark {
  position: fixed;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}

/* 底网：一直铺在背景图之上、内容之下 */
.about-grid-plane {
  z-index: -1;
  opacity: 0.45;
}

.about-grid-plane svg,
.about-spark svg {
  display: block;
  width: 100%;
  height: 100%;
}

.about-grid-plane path,
.about-spark path {
  fill: none;
  stroke-linecap: round;
}

.about-grid-plane path {
  stroke: rgba(180, 225, 255, 0.55);
  stroke-width: 1.15;
}

/* 点亮层：软边径向遮罩 + 放大淡出
 * --spark-radius 由 JS 每帧写入（不用 @property 动画，兼容性更稳）
 * z-index 用 -1：点亮效果垫在正文文字下面，只在文字之间的空隙里透出来 */
.about-spark {
  --spark-radius: 0px;
  /* 压在文字下面：和底网同级（-1），靠 DOM 顺序排在底网后面 → 在底网之上、正文之下 */
  z-index: -1;
  -webkit-mask-image: radial-gradient(
    circle at var(--x, 50%) var(--y, 50%),
    #000 0,
    #000 calc(var(--spark-radius) * 0.45),
    rgba(0, 0, 0, 0.85) calc(var(--spark-radius) * 0.72),
    transparent var(--spark-radius)
  );
  mask-image: radial-gradient(
    circle at var(--x, 50%) var(--y, 50%),
    #000 0,
    #000 calc(var(--spark-radius) * 0.45),
    rgba(0, 0, 0, 0.85) calc(var(--spark-radius) * 0.72),
    transparent var(--spark-radius)
  );
  filter: drop-shadow(0 0 3px rgba(190, 235, 255, 0.95))
    drop-shadow(0 0 14px rgba(120, 190, 255, 0.55));
}

.about-spark path {
  stroke: rgba(255, 255, 255, 0.98);
  stroke-width: 1.5;
}

/* 点击处的中心光晕（跟着遮罩一起放大淡出） */
.about-spark::before {
  content: '';
  position: absolute;
  left: var(--x, 50%);
  top: var(--y, 50%);
  width: 44vmin;
  height: 44vmin;
  transform: translate(-50%, -50%);
  background: radial-gradient(
    circle,
    rgba(255, 255, 255, 0.55) 0%,
    rgba(185, 230, 255, 0.32) 16%,
    rgba(120, 190, 255, 0.12) 38%,
    transparent 62%
  );
  animation: about-spark-flare 900ms ease-out forwards;
}

@keyframes about-spark-flare {
  0% {
    transform: translate(-50%, -50%) scale(0.35);
    opacity: 1;
  }
  55% {
    opacity: 0.7;
  }
  100% {
    transform: translate(-50%, -50%) scale(1.05);
    opacity: 0;
  }
}

/* 系统要求减弱动效时不点亮 */
@media (prefers-reduced-motion: reduce) {
  .about-spark {
    display: none;
  }
}

/* ===== 关于页顶部横幅：60° 平行四边形 =====
 * 只作用于关于页（body.page-about），其它页面的 banner 不受影响。
 * 做法：卡片背景挪到 ::before 里用 skewX(30deg) 斜切（矩形 90° - 30° = 60°，斜边与水平夹角 60°），
 * 文字内容不 skew，保持水平；因为下方的左下角会「缩进去」，内容左侧留出内边距免得文字跑到卡片外。
 */
body.page-about .article.banner {
  position: relative;
  isolation: isolate;
  overflow: visible;
  background: transparent;
  background-image: none;
  clip-path: none;
}

body.page-about .article.banner::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--block);
  border: 1px solid rgba(180, 220, 255, 0.18);
  border-radius: 16px;
  box-shadow: inset 0 0 80px rgba(120, 180, 255, 0.06);
  transform: skewX(30deg);
  transform-origin: center center;
}

/* 斜边会吃掉左下角，内容整体往右缩一点 */
body.page-about .article.banner .content {
  padding-left: 64px;
}

/* 信件落款：右对齐 + 次要颜色 + 稍紧凑的行距 */
.letter-sign {
  text-align: right;
  color: var(--text-p3);
  font-size: 0.95em;
  line-height: 1.85;
  margin: 1.4em 0 0.4em;
}
/* 落款里的署名：更醒目一点 */
.letter-sign .sign-name {
  font-weight: 600;
  color: var(--text-p1);
}

/* ===== 关于页加载动画（只在本页注入的 .about-loader 上生效）=====
 * 序列：三角网格从下往上扫过高亮 → 蓝白闪光 → 白光盖满全屏 → 白光淡出露出页面。
 * 时间点要和 source/js/about-loader.js 里的 MIN_TOTAL / FADE 对齐。
 */
html.about-loading,
html.about-loading body {
  overflow: hidden;
}

.about-loader {
  position: fixed;
  inset: 0;
  z-index: 99999;
  overflow: hidden;
  background: #0d1218;
  opacity: 1;
  transition: opacity 440ms ease;
  pointer-events: auto;
  /* 兜底：万一脚本没跑起来，7 秒后也自动消失，别把页面挡死 */
  animation: about-loader-fallback 1ms 7000ms forwards;
}

.about-loader.is-leaving {
  opacity: 0;
  pointer-events: none;
}

.about-loader.is-gone {
  display: none;
}

@keyframes about-loader-fallback {
  to {
    visibility: hidden;
    pointer-events: none;
  }
}

.about-loader__grid {
  position: absolute;
  inset: 0;
  overflow: hidden;
}

.about-loader__grid svg {
  display: block;
  width: 100%;
  height: 100%;
}

.about-loader__grid path {
  fill: none;
  stroke-linecap: round;
}

/* 底网：很暗的一层，先垫着 */
.about-loader__grid--dim path {
  stroke: rgba(150, 200, 255, 0.14);
  stroke-width: 1.1;
}

/* 亮层：用一条会往上扫的软边遮罩，只露出一条光带 → 光带从下往上扫过网格 */
.about-loader__lit {
  position: absolute;
  inset: 0;
  -webkit-mask-image: linear-gradient(
    to top,
    transparent 0%,
    #000 42%,
    #000 58%,
    transparent 100%
  );
  mask-image: linear-gradient(
    to top,
    transparent 0%,
    #000 42%,
    #000 58%,
    transparent 100%
  );
  -webkit-mask-size: 100% 44%;
  mask-size: 100% 44%;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: 50% 160%;
  mask-position: 50% 160%;
  animation: about-loader-sweep 560ms cubic-bezier(0.3, 0.6, 0.3, 1) 60ms forwards;
}

.about-loader__grid--bright path {
  stroke: rgba(215, 243, 255, 0.95);
  stroke-width: 1.5;
  filter: drop-shadow(0 0 4px rgba(150, 215, 255, 0.9))
    drop-shadow(0 0 16px rgba(95, 170, 255, 0.55));
}

/* 光带本身带一点雾光 */
.about-loader__lit::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to top,
    transparent 0%,
    rgba(120, 190, 255, 0.09) 42%,
    rgba(190, 235, 255, 0.18) 50%,
    rgba(120, 190, 255, 0.09) 58%,
    transparent 100%
  );
}

@keyframes about-loader-sweep {
  0% {
    -webkit-mask-position: 50% 160%;
    mask-position: 50% 160%;
  }
  100% {
    -webkit-mask-position: 50% -60%;
    mask-position: 50% -60%;
  }
}

/* 蓝白闪光 */
.about-loader__flash {
  position: absolute;
  left: 50%;
  top: 45%;
  width: 150vmax;
  height: 150vmax;
  margin: -75vmax 0 0 -75vmax;
  border-radius: 50%;
  background: radial-gradient(
    circle,
    rgba(200, 240, 255, 0.95) 0%,
    rgba(130, 205, 255, 0.6) 20%,
    rgba(70, 150, 255, 0.22) 42%,
    transparent 66%
  );
  opacity: 0;
  transform: scale(0.6);
  animation: about-loader-flash 340ms ease-out 480ms forwards;
}

@keyframes about-loader-flash {
  0% {
    opacity: 0;
    transform: scale(0.55);
  }
  35% {
    opacity: 0.95;
    transform: scale(0.92);
  }
  100% {
    opacity: 0.7;
    transform: scale(1.15);
  }
}

/* 白光盖满全屏 */
.about-loader__white {
  position: absolute;
  inset: 0;
  background: #f2fbff;
  opacity: 0;
  animation: about-loader-white 260ms ease-in 660ms forwards;
}

@keyframes about-loader-white {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

/* 系统要求减弱动效时直接不显示加载动画 */
@media (prefers-reduced-motion: reduce) {
  .about-loader {
    display: none;
  }
}

/* ===== 关于页引用图标（{% quot %}）：蓝色全息投影 =====
 * 主题的 quot 图标是运行时注入的 SVG（注入后 svg 上没有 class 了），所以用 .content > svg 命中；
 * 填充改用 scripts/about-page.js 注入的渐变 #about-quot-holo（明暗交替 = 扫描线质感），
 * 再加冷色辉光和轻微闪烁。整体压得比较透（opacity 0.6 上下），像一个半透明的投影。
 * 想更实一点就把下面的 opacity 数值整体调大（0.8~1）。
 */
body.page-about .tag-plugin.quot .content > svg {
  width: 1.5em;
  height: 1.5em;
  color: transparent;
  opacity: 0.72;
  filter: drop-shadow(0 0 2px rgba(170, 240, 255, 0.85))
    drop-shadow(0 0 8px rgba(80, 190, 255, 0.65))
    drop-shadow(0 0 20px rgba(40, 130, 255, 0.4));
  animation: about-quot-holo 4.5s linear infinite;
  will-change: opacity;
}

body.page-about .tag-plugin.quot .content > svg path {
  fill: url(#about-quot-holo);
}

@keyframes about-quot-holo {
  0%,
  100% {
    opacity: 0.72;
  }
  5% {
    opacity: 0.52;
  }
  7% {
    opacity: 0.8;
  }
  38% {
    opacity: 0.64;
  }
  40% {
    opacity: 0.78;
  }
  72% {
    opacity: 0.6;
  }
  74% {
    opacity: 0.76;
  }
}

@media (prefers-reduced-motion: reduce) {
  body.page-about .tag-plugin.quot .content > svg {
    animation: none;
    opacity: 0.72;
  }
}

/* ===== 未开发页面占位（由 scripts/dev-placeholder.js 注入）=====
 * 分类 / 标签 / Wiki / 归档 / 说说 这些还没做的页面，点进去时内容区会换成这张卡片。
 * 颜色全部走主题变量（--card / --block-border / --text-p*），浅色深色自动适配；
 * 每个页面的强调色由脚本写在行内 --dev-accent 上，和左侧导航同名菜单项的颜色一致。
 */
.dev-placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 46vh;
  padding: 1rem 0 3rem;
}

.dev-placeholder__card {
  --dev-accent: var(--theme);
  box-sizing: border-box;
  width: 100%;
  max-width: 34rem;
  margin: 0 auto;
  padding: 2.5rem 2rem 2.25rem;
  border: 1px solid var(--block-border);
  border-radius: 1.25rem;
  background: var(--card);
  box-shadow:
    0 2px 6px rgba(0, 0, 0, 0.04),
    0 18px 48px -18px rgba(0, 0, 0, 0.18);
  text-align: center;
}

.dev-placeholder__title,
.dev-placeholder__desc {
  overflow-wrap: break-word;
}

.dev-placeholder__icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 4rem;
  height: 4rem;
  margin: 0 auto 1.25rem;
  border-radius: 50%;
  color: var(--dev-accent);
  background: color-mix(in srgb, var(--dev-accent) 12%, transparent);
}

.dev-placeholder__icon svg {
  width: 2.25rem;
  height: 2.25rem;
  display: block;
}

.dev-placeholder__title {
  margin: 0 0 0.75rem;
  font-size: 1.25rem;
  font-weight: 600;
  line-height: 1.5;
  color: var(--text-p0);
}

.dev-placeholder__desc {
  margin: 0 auto 1.75rem;
  max-width: 26rem;
  font-size: 0.88rem;
  line-height: 1.9;
  color: var(--text-p2);
}

.dev-placeholder__action {
  display: inline-block;
}

/* 窄屏下 .site-main 是通栏的（主题在 ≤768px 去掉了左右留白），给容器补一点边距 */
@media screen and (max-width: 768px) {
  .dev-placeholder {
    padding: 0.5rem 1rem 2rem;
  }
}

@media screen and (max-width: 640px) {
  .dev-placeholder {
    min-height: 40vh;
    padding-bottom: 2rem;
  }

  .dev-placeholder__card {
    padding: 2rem 1.25rem 1.75rem;
    border-radius: 1rem;
  }

  .dev-placeholder__icon {
    width: 3.5rem;
    height: 3.5rem;
    margin-bottom: 1rem;
  }

  .dev-placeholder__title {
    font-size: 1.125rem;
  }
}

/* ===== 线性代数笔记 1.6：三维行列式（平行六面体体积）交互演示 =====
   配合 source/js/la-det3d.js；下面的 --la-* 变量也会被 canvas 读取，改色改这里即可 */
.la-det3d {
  --la-v1: #2f6ddd;
  --la-v2: #e88326;
  --la-v3: #2a9d68;
  --la-axis: #98a2b3;
  --la-grid: rgba(120, 132, 154, 0.22);
  --la-text: #3f4757;
  --la-muted: #98a2b3;
}

:root[data-theme="dark"] .la-det3d {
  --la-v1: #74a9ff;
  --la-v2: #f3ae5e;
  --la-v3: #4fd39a;
  --la-axis: #8b93a8;
  --la-grid: rgba(200, 210, 235, 0.16);
  --la-text: #e7e9f2;
  --la-muted: #9aa1b5;
}

@media screen and (prefers-color-scheme: dark) {
  :root:not([data-theme]) .la-det3d {
    --la-v1: #74a9ff;
    --la-v2: #f3ae5e;
    --la-v3: #4fd39a;
    --la-axis: #8b93a8;
    --la-grid: rgba(200, 210, 235, 0.16);
    --la-text: #e7e9f2;
    --la-muted: #9aa1b5;
  }
}

.md-text > .la-det3d {
  margin: 1.25rem 0 1.75rem;
}

.la-det3d__stage {
  position: relative;
  overflow: hidden;
  border: 1px solid var(--block-border);
  border-radius: 1rem;
  background: var(--block);
}

.la-det3d__canvas {
  display: block;
  width: 100%;
  height: clamp(300px, 46vh, 430px);
  cursor: grab;
  touch-action: none;
  outline: none;
}

.la-det3d__canvas.is-dragging {
  cursor: grabbing;
}

.la-det3d__canvas:focus-visible {
  box-shadow: inset 0 0 0 2px var(--theme);
}

.la-det3d__readout {
  position: absolute;
  top: 10px;
  left: 10px;
  max-width: calc(100% - 20px);
  padding: 0.2rem 0.65rem;
  border: 1px solid var(--block-border);
  border-radius: 999px;
  background: var(--card);
  color: var(--text-p1);
  font-size: 0.75rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  pointer-events: none;
}

.la-det3d__hint {
  position: absolute;
  left: 12px;
  bottom: 9px;
  color: var(--text-p3);
  font-size: 0.7rem;
  pointer-events: none;
}

.la-det3d__bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 0.75rem;
  margin-top: 0.65rem;
  color: var(--text-p3);
  font-size: 0.75rem;
}

.la-det3d__presets {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}

.la-det3d__preset {
  appearance: none;
  padding: 0.2rem 0.7rem;
  border: 1px solid var(--block-border);
  border-radius: 999px;
  background: transparent;
  color: var(--text-p2);
  font: inherit;
  font-size: 0.75rem;
  line-height: 1.5;
  cursor: pointer;
  transition: color 0.2s ease-out, border-color 0.2s ease-out, background 0.2s ease-out;
}

.la-det3d__preset:hover {
  border-color: color-mix(in srgb, var(--theme) 45%, var(--block-border));
  color: var(--theme);
}

.la-det3d__preset.is-active {
  border-color: var(--theme);
  background: var(--theme-a10);
  color: var(--theme);
}

.la-det3d__preset:focus-visible {
  outline: 2px solid var(--theme);
  outline-offset: 2px;
}

.la-det3d__vectors {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 0.9rem;
  margin-left: auto;
  font-variant-numeric: tabular-nums;
}

.la-det3d__vec {
  white-space: nowrap;
}

.la-det3d__vec--1 {
  color: var(--la-v1);
}

.la-det3d__vec--2 {
  color: var(--la-v2);
}

.la-det3d__vec--3 {
  color: var(--la-v3);
}

@media screen and (max-width: 640px) {
  .la-det3d__canvas {
    height: 300px;
  }

  .la-det3d__readout {
    font-size: 0.7rem;
  }

  .la-det3d__vectors {
    flex-basis: 100%;
    margin-left: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .la-det3d__preset {
    transition: none;
  }
}