@import "tailwindcss";

@custom-variant dark (&:where(.dark, .dark *));

@theme {
  /* 覆盖 Tailwind v4 默认 --font-sans(ui-sans-serif, system-ui, sans-serif, ...):
     默认栈不含 CJK sans,font-sans 类一旦生效,body 的中文字体栈会被绕过,
     中文 fallback 到系统衬线体。这里对齐 body 的 CJK sans 栈,根治全项目。 */
  --font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif, 'Noto Sans SC', 'PingFang SC', 'Microsoft YaHei';
  --font-serif: 'Source Serif 4', 'Noto Serif SC', 'Source Han Serif SC', 'Songti SC', Georgia, serif;

  /* Catppuccin Latte（亮色）。语义 token → 调色板角色：
     theme=base  entry=mantle  primary=text  secondary=subtext1
     tertiary=overlay0  content=subtext0  code-block=crust  code-bg=surface0
     border=surface1  accent=green  accent-2=teal（主/次强调色） */
  --color-paper-theme: #eff1f5;
  --color-paper-entry: #e6e9ef;
  --color-paper-primary: #4c4f69;
  --color-paper-secondary: #5c5f77;
  --color-paper-tertiary: #9ca0b0;
  --color-paper-content: #6c6f85;
  --color-paper-code-block: #dce0e8;
  --color-paper-code-bg: #ccd0da;
  --color-paper-border: #bcc0cc;
  --color-paper-accent: #40a02b;
  --color-paper-accent-soft: #ccd0da;
  --color-paper-accent-2: #179299;
  --color-paper-accent-2-soft: #ccd0da;

  /* 圆角三档梯度：容器 32 → 内容 16 → 微元素 8。
     按钮/头像/徽章另用胶囊（Tailwind rounded-full），独立于本梯度。 */
  --radius-card: 2rem;    /* 32px：文章卡片、封面、admin 主面板 */
  --radius-paper: 16px;   /* 16px：代码块、正文图片、iframe、表格、输入框、admin 卡片 */
  --radius-mini: 8px;     /* 8px：标签、复制按钮、toc、paginav */
  --gap-paper: 24px;
  --content-gap-paper: 20px;
  --nav-width-paper: 1024px;
  --main-width-paper: 720px;
}

@layer base {
  html {
    scroll-behavior: smooth;
    background-color: var(--color-paper-theme);
  }

  body {
    background-color: var(--color-paper-theme);
    color: var(--color-paper-primary);
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans SC', 'PingFang SC', 'Microsoft YaHei', sans-serif;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
  }

  @keyframes page-enter {
    0% {
      opacity: 0;
      transform: translateY(16px) scale(0.995);
    }
    100% {
      opacity: 1;
      transform: none;
    }
  }

  .animate-page-enter {
    animation: page-enter 400ms cubic-bezier(0.22, 1, 0.36, 1) both;
  }

  /* Popover / 确认框淡入缩放(比 page-enter 更轻、更快) */
  @keyframes popover-enter {
    0% {
      opacity: 0;
      transform: translateX(-50%) scale(0.95);
    }
    100% {
      opacity: 1;
      transform: translateX(-50%) scale(1);
    }
  }

  .animate-popover-enter {
    animation: popover-enter 150ms cubic-bezier(0.22, 1, 0.36, 1) both;
  }

  /* 下拉选择面板入场。面板的水平居中用 [transform:translateX(-50%)]（不用
     -translate-x-1/2 utility：Tailwind v4 的 translate utility 走独立 translate
     属性，会与此处 transform 关键帧叠加成双倍位移），关键帧 fill 值须与面板
     静态 transform 完全一致，否则动画结束时水平位置跳变；垂直仅微移，展开
     方向由 transform-origin 控制。 */
  @keyframes select-enter {
    0% {
      opacity: 0;
      transform: translateX(-50%) translateY(-4px) scale(0.98);
    }
    100% {
      opacity: 1;
      transform: translateX(-50%);
    }
  }

  .animate-select-enter {
    animation: select-enter 150ms cubic-bezier(0.22, 1, 0.36, 1) both;
  }

  /* 列表行进场（比 page-enter 更轻的位移，供 admin 列表逐行 stagger 使用，
     配合内联 style="animation-delay: Nms" 与 both fill-mode 实现阶梯入场） */
  @keyframes row-enter {
    0% {
      opacity: 0;
      transform: translateY(8px);
    }
    100% {
      opacity: 1;
      transform: none;
    }
  }

  .animate-row-enter {
    animation: row-enter 450ms cubic-bezier(0.22, 1, 0.36, 1) both;
  }

  /* Minimalist custom scrollbars */
  * {
    scrollbar-width: thin;
    scrollbar-color: var(--color-paper-border) transparent;
  }

  ::-webkit-scrollbar {
    width: 6px;
    height: 6px;
  }

  ::-webkit-scrollbar-track {
    background: transparent;
  }

  ::-webkit-scrollbar-thumb {
    background-color: var(--color-paper-border);
    border-radius: 10px;
  }

  ::-webkit-scrollbar-thumb:hover {
    background-color: var(--color-paper-tertiary);
  }

  .dark {
    /* Catppuccin Mocha（暗色）。accent-soft 带绿调、accent-2-soft 带 teal 调，
       在 surface0 暗底上透出微弱主/次强调色。 */
    --color-paper-theme: #1e1e2e;
    --color-paper-entry: #181825;
    --color-paper-primary: #cdd6f4;
    --color-paper-secondary: #bac2de;
    --color-paper-tertiary: #6c7086;
    --color-paper-content: #a6adc8;
    --color-paper-code-block: #313244;
    --color-paper-code-bg: #313244;
    --color-paper-border: #45475a;
    --color-paper-accent: #a6e3a1;
    --color-paper-accent-soft: #1e2e22;
    --color-paper-accent-2: #94e2d5;
    --color-paper-accent-2-soft: #1e2a28;
  }
}

@layer components {
  .post-single {
    margin: 0 auto;
  }

  .post-header {
    margin: 48px auto 48px auto;
    display: flex;
    flex-direction: column;
    gap: 16px;
  }

  .post-title {
    font-size: clamp(2.5rem, 6vw, 4.5rem);
    font-weight: 800;
    line-height: 1.1;
    color: var(--color-paper-primary);
    word-break: break-word;
    letter-spacing: -0.04em;
    margin: 0;
  }

  .post-description {
    color: var(--color-paper-secondary);
    font-size: 1.125rem;
    font-weight: 500;
    line-height: 1.7;
    margin: 0;
  }

  .post-meta {
    margin-top: 8px;
    color: var(--color-paper-tertiary);
    font-size: 15px;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex-wrap: wrap;
    font-weight: 500;
  }

  .post-meta a {
    color: var(--color-paper-secondary);
    text-decoration-style: dotted;
    text-underline-offset: 0.3rem;
    text-decoration: underline;
  }

  .post-meta a:hover {
    color: var(--color-paper-primary);
  }

  .breadcrumbs {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.2rem;
    color: var(--color-paper-secondary);
    font-size: 14px;
    margin-bottom: 10px;
  }

  .breadcrumbs a {
    font-size: 16px;
    color: var(--color-paper-primary);
  }

  .breadcrumbs a:hover {
    text-decoration: underline;
    text-underline-offset: 0.2rem;
  }

  .entry-hint {
    display: inline-flex;
    margin-left: 0.5rem;
    color: var(--color-paper-secondary);
  }

  details.toc {
    margin-bottom: var(--content-gap-paper);
    background: var(--color-paper-code-bg);
    border-radius: var(--radius-mini);
    border: 1px solid var(--color-paper-border);
  }

  details.toc summary {
    padding: 0.3rem 1.2rem;
    border-radius: var(--radius-mini);
    cursor: pointer;
    display: list-item;
    width: 100%;
    user-select: none;
    color: var(--color-paper-primary);
  }

  details.toc .title {
    display: inline;
    font-weight: 500;
    margin-inline-start: 0.2rem;
  }

  details.toc .inner {
    margin: 0 2.4rem;
    padding-bottom: 0.6rem;
  }

  details.toc ul {
    list-style: none;
    padding: 0;
    margin: 0;
  }

  details.toc li {
    margin: 0.3rem 0;
  }

  details.toc a {
    color: var(--color-paper-secondary);
    text-decoration: none;
    font-size: 14px;
  }

  details.toc a:hover {
    color: var(--color-paper-primary);
    text-decoration: underline;
    text-underline-offset: 0.3rem;
  }

  details.toc li ul {
    margin-inline-start: var(--gap-paper);
  }

  details {
    interpolate-size: allow-keywords;
  }

  details::details-content {
    height: 0;
    opacity: 0;
    overflow: clip;
    transition: height 150ms ease, opacity 150ms ease, content-visibility 150ms allow-discrete;
  }

  details[open]::details-content {
    height: auto;
    opacity: 1;
  }

  /* 正文折叠块（作者手写的 <details>，区别于 .toc 导航块）。
     复用代码块/blockquote 的视觉语言：同款底色 + 边框 + 16px 圆角；
     自绘 chevron 替代浏览器原生三角，展开时旋转 90°。
     :not(.toc) 避免与上面的 TOC 专用样式冲突。 */
  .md-content details:not(.toc) {
    margin: 1rem 0;
    background: var(--color-paper-code-bg);
    border: 1px solid var(--color-paper-border);
    border-radius: var(--radius-paper);
  }

  .md-content details:not(.toc) > summary {
    padding: 0.6rem 1rem;
    cursor: pointer;
    user-select: none;
    list-style: none;
    color: var(--color-paper-primary);
    font-weight: 500;
    display: flex;
    align-items: center;
    gap: 0.4rem;
    transition: background-color 120ms ease;
  }

  /* 去掉 WebKit/Blink 原生三角，统一用 ::before 自绘 chevron。 */
  .md-content details:not(.toc) > summary::-webkit-details-marker {
    display: none;
  }

  /* 自绘 chevron：实心三角，展开时旋转 90° 平滑过渡。
     用 currentColor 继承 summary 文字色，随主题变化。 */
  .md-content details:not(.toc) > summary::before {
    content: "";
    display: inline-block;
    flex-shrink: 0;
    width: 0;
    height: 0;
    border-style: solid;
    border-width: 0.32rem 0.42rem 0.32rem 0;
    border-color: transparent currentColor transparent transparent;
    transform: rotate(0deg);
    transition: transform 150ms ease;
    margin-inline-start: 0.1rem;
  }

  .md-content details:not(.toc)[open] > summary::before {
    transform: rotate(90deg);
  }

  .md-content details:not(.toc) > summary:hover {
    background-color: color-mix(in srgb, var(--color-paper-accent) 8%, transparent);
  }

  /* 键盘可访问：focus-visible 给可见轮廓（WCAG 2.4.7）。
     .dark 前缀走暗色主题色。 */
  .md-content details:not(.toc) > summary:focus-visible {
    outline: 2px solid var(--color-paper-accent);
    outline-offset: -2px;
    border-radius: var(--radius-paper);
  }

  /* 展开内容左右内边距（代码块/段落不贴边），末元素留底部呼吸空间。 */
  .md-content details:not(.toc)[open] > *:not(summary) {
    padding-inline: 1rem;
  }

  /* 首元素紧接 summary 去顶部 margin，末元素去底部 margin（容器已留白）。 */
  .md-content details:not(.toc)[open] > *:not(summary):first-of-type {
    margin-top: 0;
  }

  .md-content details:not(.toc)[open] > *:not(summary):last-child {
    margin-bottom: 0;
    padding-bottom: 0.8rem;
  }

  .entry-cover {
    margin-bottom: var(--content-gap-paper);
  }

  /* 封面用 blur-img 结构：去 margin、保持圆角，内层 img cover 填充 */
  .entry-cover .blur-img {
    margin: 0;
    border-radius: var(--radius-card);
    overflow: hidden;
  }
  .entry-cover img {
    width: 100%;
    height: 100%;
    object-fit: cover;
  }

  .post-content {
    color: var(--color-paper-content);
    margin: 30px 0;
  }

  .md-content h1 {
    margin: 40px auto 32px;
    font-size: 40px;
    color: var(--color-paper-primary);
    letter-spacing: -0.01em;
  }

  .md-content h2 {
    margin: 32px auto 24px;
    font-size: 32px;
    color: var(--color-paper-primary);
    letter-spacing: -0.01em;
  }

  .md-content h3 {
    margin: 24px 0 16px;
    font-size: 24px;
    color: var(--color-paper-primary);
  }

  .md-content h4 {
    margin: 24px 0 16px;
    font-size: 16px;
    color: var(--color-paper-primary);
  }

  .md-content h5 {
    margin: 24px 0 16px;
    font-size: 14px;
    color: var(--color-paper-primary);
  }

  .md-content h6 {
    margin: 24px 0 16px;
    font-size: 12px;
    color: var(--color-paper-primary);
  }

  /* 锚点目标偏移：scrollIntoView / 原生 fragment-scroll 落点避开 80px sticky header。
     [id] 限定只作用于带锚点 id 的标题；6rem = 80px header + 16px 呼吸空间。 */
  .md-content :is(h1, h2, h3, h4, h5, h6)[id] {
    scroll-margin-top: 6rem;
  }

  .md-content a:not(.anchor) {
    text-underline-offset: 0.3rem;
    text-decoration: underline;
    color: var(--color-paper-accent);
  }

  .md-content a:not(.anchor):hover {
    color: var(--color-paper-accent-2);
  }

  .md-content p {
    margin-bottom: var(--content-gap-paper);
    line-height: 1.85;
  }

  .md-content p:last-child {
    margin-bottom: 0;
  }

  .md-content blockquote {
    margin: 1rem 0;
    padding-inline-start: 1rem;
    border-inline-start: 0.3rem solid var(--color-paper-content);
    color: var(--color-paper-secondary);
  }

  .md-content blockquote p:last-child {
    margin-bottom: 0;
  }

  /* 脚注引用上标：[^id] 渲染成的 <sup class="fn-ref">。
   * line-height: 0 防止上标撑高所在行行高；font-size 缩小为 0.75em。 */
  .md-content .fn-ref {
    font-size: 0.75em;
    line-height: 0;
    vertical-align: super;
    margin-inline-start: 0.1em;
  }

  /* 引用数字链接：不加下划线（上标下划线极难看），用 accent 色区分。 */
  .md-content .fn-ref-link {
    text-decoration: none;
    color: var(--color-paper-accent);
  }

  .md-content .fn-ref-link:hover {
    color: var(--color-paper-accent-2);
  }

  /* 脚注定义块：仿 blockquote 的左侧边框视觉语言，但更轻（0.2rem + 稍小字号）。 */
  .md-content .footnote-definition {
    margin: 1rem 0;
    padding-inline-start: 1rem;
    border-inline-start: 0.2rem solid var(--color-paper-content);
    font-size: 0.875em;
    color: var(--color-paper-secondary);
  }

  .md-content .footnote-definition:last-child {
    margin-bottom: 0;
  }

  /* 定义内末段去底距，避免与 back-link 间距过大。 */
  .md-content .footnote-definition > p:last-child {
    margin-bottom: 0;
  }

  /* 定义编号上标：与正文引用数字呼应。 */
  .md-content .footnote-definition-label {
    font-size: 0.75em;
    line-height: 0;
    vertical-align: super;
    margin-inline-end: 0.25em;
    color: var(--color-paper-tertiary);
  }

  /* 返回正文链接：↩ 符号，弱色，hover 转 accent。 */
  .md-content .fn-backref {
    margin-inline-start: 0.25em;
    text-decoration: none;
    color: var(--color-paper-tertiary);
  }

  .md-content .fn-backref:hover {
    color: var(--color-paper-accent);
  }

  /* 多引用时的数字上标（↩² 中的 ²）。 */
  .md-content .fn-backref-num {
    font-size: 0.75em;
    vertical-align: super;
  }

  .md-content ol,
  .md-content ul {
    padding-inline-start: 1.25rem;
    margin-bottom: var(--content-gap-paper);
  }

  /* Tailwind Preflight 把 list-style 清成 none,这里恢复被清掉的 marker。
   * 任务列表项（含 checkbox 的 li）另有规则覆盖为 none，不受影响。 */
  .md-content ul {
    list-style-type: disc;
  }

  .md-content ol {
    list-style-type: decimal;
  }

  .md-content li {
    margin-top: 0.3rem;
  }

  .md-content li p {
    margin-bottom: 0;
  }

  /* 任务列表：pulldown-cmark 把 - [ ] / - [x] 渲染成裸 <li><input type="checkbox">…
   * （无 <label> 包裹，也无 data-type 标记）。用 :has() 识别含 checkbox 的 li，
   * 布局成 flex 让复选框与文本对齐；不支持 :has() 的浏览器降级为普通列表，仍可读。 */
  .md-content li:has(> input[type="checkbox"]) {
    list-style: none;
    margin-left: -1.25rem;
    display: flex;
    align-items: center;
    gap: 0.5rem;
  }

  .md-content li > input[type="checkbox"] {
    /* appearance:none 全自定义：告别浏览器原生方框形状/边框差异。
       对勾用内联 SVG background（<input> 是替换元素，吃不到 ::after），
       颜色按主题烘焙——亮色中绿底配白对勾，暗色浅绿底配深对勾，对比最强。
       文章内 checkbox 是 disabled 的纯展示态，故不加 focus/cursor 交互。 */
    appearance: none;
    -webkit-appearance: none;
    flex-shrink: 0;
    width: 1.15rem;
    height: 1.15rem;
    margin: 0;
    border: 1.5px solid var(--color-paper-border);
    border-radius: 4px;
    background-color: transparent;
    background-position: center;
    background-repeat: no-repeat;
    background-size: 0.75rem;
    cursor: default;
    transition: background-color 0.15s ease, border-color 0.15s ease;
  }

  .md-content li > input[type="checkbox"]:checked {
    background-color: var(--color-paper-accent);
    border-color: var(--color-paper-accent);
    /* 亮色：中绿 #40a02b 底 + 白对勾（对比 ≥ 4.5:1） */
    background-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2016%2016'%20fill='none'%20stroke='%23ffffff'%20stroke-width='2.2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M3.5%208.5l3%203%206-6.5'/%3E%3C/svg%3E");
  }

  /* 暗色：浅绿 #a6e3a1 底上白对勾对比不足，改深色对勾（主题底色 #1e1e2e） */
  .dark .md-content li > input[type="checkbox"]:checked {
    background-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2016%2016'%20fill='none'%20stroke='%231e1e2e'%20stroke-width='2.2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M3.5%208.5l3%203%206-6.5'/%3E%3C/svg%3E");
  }

  .md-content hr {
    margin: 30px 0;
    height: 2px;
    background: var(--color-paper-tertiary);
    border: 0;
  }

  /* table-wrap：渲染器给宽表格套的滚动容器，移动端窄屏可横向滚动。
     （见 src/api/markdown.rs::wrap_tables）。min-width 让窄表仍撑满、宽表撑开触发滚动。
     padding 为 table 的 1px box-shadow 描边预留空间：overflow 容器（overflow-x:auto 会
     强制 overflow-y 也建滚动盒）会裁切向外 spread 的阴影，导致右下边框断裂。
     负 margin 抵消 padding 的外部尺寸，使 wrap 不撑大父容器、左上仍贴齐正文边缘。 */
  .md-content .table-wrap {
    margin: -1px;
    padding: 1px;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }

  .md-content table {
    margin-bottom: var(--content-gap-paper);
    width: 100%;
    min-width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    border-radius: var(--radius-paper);
    box-shadow: 0 0 0 1px var(--color-paper-border);
  }

  .md-content table thead th {
    background: var(--color-paper-code-block);
    font-weight: 600;
    color: var(--color-paper-primary);
    padding: 16px 24px;
    text-align: left;
    border-bottom: 1px solid var(--color-paper-border);
    white-space: nowrap;
  }

  .md-content table thead th:first-child {
    border-top-left-radius: var(--radius-paper);
  }

  .md-content table thead th:last-child {
    border-top-right-radius: var(--radius-paper);
  }

  .md-content table tbody tr:last-child td:first-child {
    border-bottom-left-radius: var(--radius-paper);
  }

  .md-content table tbody tr:last-child td:last-child {
    border-bottom-right-radius: var(--radius-paper);
  }

  .md-content table tbody td {
    padding: 16px 24px;
    line-height: 1.6;
    border-bottom: 1px solid var(--color-paper-border);
    color: var(--color-paper-secondary);
  }

  .md-content table tbody tr:last-child td {
    border-bottom: none;
  }

  .md-content table tbody tr {
    transition: background-color 0.2s ease;
  }

  .md-content table tbody tr:hover {
    background: var(--color-paper-entry);
  }

  /* 排除 CodeMirror 编辑器内的 <img>：CM 用 <img class="cm-widgetBuffer">（width:0、
     height:1em 的占位符）对齐折叠 widget 的基线。若被这里的 margin/height 命中，
     会把折叠那行 .cm-line 撑高约 32px（上下各 1rem margin）。用 :where() 把
     .cm-editor 后代的 img 优先级压到 0，确保 CM 内部任何 img 都不受正文图片样式影响。 */
  .md-content img:where(:not(.cm-widgetBuffer)) {
    border-radius: var(--radius-paper);
    margin: 1rem 0;
    max-width: 100%;
    height: auto;
  }

  .dark .md-content img:not(.blur-img-placeholder):not(.blur-img-full),
  .dark .md-content .blur-img,
  .dark .lightbox-img {
    filter: brightness(0.9);
  }

  .md-content-img-zoomable {
    cursor: zoom-in;
    transition: opacity 0.2s ease-out;
  }

  .md-content-img-zoomable:hover {
    opacity: 0.9;
  }

  .md-content iframe {
    max-width: 100%;
    border-radius: var(--radius-paper);
  }

  .md-content code {
    padding: 0.2rem 0.3rem;
    font-size: 0.85em;
    line-height: 1.5;
    background: var(--color-paper-code-bg);
    border-radius: 0.2rem;
    font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
  }

  .md-content pre {
    position: relative;
    margin-bottom: var(--content-gap-paper);
    background: var(--color-paper-code-block);
    border-radius: var(--radius-paper);
    overflow-x: auto;
  }

  .md-content pre code {
    display: block;
    padding: 16px;
    background: transparent;
    border-radius: 0;
    overflow-x: auto;
    white-space: pre;
    font-size: 1rem;
    line-height: 1.6;
  }

  .md-content pre code span {
    display: inline !important;
  }

  .copy-code {
    display: none;
    position: absolute;
    top: 8px;
    right: 8px;
    color: var(--color-paper-theme);
    background: var(--color-paper-tertiary);
    border-radius: var(--radius-mini);
    padding: 4px 8px;
    font-size: 12px;
    user-select: none;
    cursor: pointer;
    border: none;
    font-family: inherit;
    transition: background 0.2s ease-out;
  }

  .copy-code:hover {
    background: var(--color-paper-accent);
  }

  pre:hover .copy-code,
  .highlight:hover .copy-code {
    display: block;
  }

  /* ── mermaid 图表容器 ──
     data-mermaid-rendered 由 yggdrasil-core/mermaid.ts 渲染成功后标记在 <pre> 上。
     渲染后 pre 唯一子元素是 <svg>（mermaid 块不注入 copy-code 按钮），flex 安全。
     居中 + 缩放适配宽度，消除常规图的横向滚动；超宽图 overflow-x:auto 兜底。 */
  .md-content pre[data-mermaid-rendered] {
    display: flex;
    justify-content: center;
    align-items: center;
    padding: 24px 16px;
    overflow-x: auto;
  }

  .md-content pre[data-mermaid-rendered] > svg {
    max-width: 100%;
    height: auto;
    display: block;
  }

  /* 渲染失败：保留原始源码，加 accent 色左边条提示（站点 accent 为绿，沿用配色体系） */
  .md-content pre.mermaid-error {
    border-left: 3px solid var(--color-paper-accent);
  }

  .anchor {
    display: none;
    text-decoration: none;
    color: var(--color-paper-secondary);
  }

  .md-content h1:hover .anchor,
  .md-content h2:hover .anchor,
  .md-content h3:hover .anchor,
  .md-content h4:hover .anchor,
  .md-content h5:hover .anchor,
  .md-content h6:hover .anchor {
    display: inline-flex;
    margin-inline-start: 0.5em;
    font-weight: 500;
    user-select: none;
    text-decoration: none;
    color: var(--color-paper-secondary);
  }

  .anchor:hover {
    color: var(--color-paper-primary) !important;
  }

  .post-footer {
    margin-top: var(--content-gap-paper);
  }

  .post-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    list-style: none;
    padding: 0;
    margin: 0 0 var(--content-gap-paper) 0;
  }

  .post-tags li {
    display: inline-block;
  }

  .post-tags a {
    display: block;
    padding: 0 14px;
    color: var(--color-paper-secondary);
    font-size: 14px;
    line-height: 34px;
    background: var(--color-paper-code-bg);
    border-radius: var(--radius-mini);
    border: 1px solid var(--color-paper-border);
    text-decoration: none;
    transition: all 0.2s ease-out;
  }

  .post-tags a:hover {
    background: var(--color-paper-accent-soft);
    border-color: var(--color-paper-accent);
    color: var(--color-paper-accent);
  }

  .paginav {
    display: flex;
    border-radius: var(--radius-mini);
    background: var(--color-paper-code-bg);
    border: 1px solid var(--color-paper-border);
    overflow: hidden;
  }

  .paginav a {
    width: 50%;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding: 0.8rem;
    text-decoration: none;
    color: var(--color-paper-primary);
    transition: background 0.2s ease-out;
  }

  .paginav a:hover {
    background: var(--color-paper-border);
  }

  .paginav .next {
    margin-inline-start: auto;
    text-align: right;
  }

  .paginav .title {
    letter-spacing: 1px;
    font-size: 0.8rem;
    color: var(--color-paper-secondary);
  }

  .paginav .post-title-nav {
    font-size: 16px;
    font-weight: 500;
  }

  .back-to-home {
    margin-top: calc(var(--content-gap-paper) * 1.5);
    padding-top: var(--content-gap-paper);
    border-top: 1px solid var(--color-paper-border);
  }

  .back-to-home a,
  .back-to-home button {
    color: var(--color-paper-secondary);
    font-size: 14px;
    text-decoration: none;
    background: none;
    border: none;
    cursor: pointer;
    padding: 0;
    font-family: inherit;
  }

  .back-to-home a:hover,
  .back-to-home button:hover {
    color: var(--color-paper-primary);
    text-decoration: underline;
    text-underline-offset: 0.3rem;
  }

  /* 卡片封面：blur-img 结构，固定 21:9 比例，hover 缩放。
     双类选择器提升特异性，可靠覆盖 .blur-img 的 aspect-ratio: var(--ar)
     （卡片不写 --ar，var(--ar) 解析为空会导致高度塌陷）。
     21:9 与后台编辑器封面区统一比例，宽屏横幅式。 */
  .blur-img.post-card-cover-blur {
    margin: 0;
    aspect-ratio: 21 / 9;
  }
  .post-card-cover-blur img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform 0.3s ease-out;
  }
  .group:hover .post-card-cover-blur img {
    transform: scale(1.05);
  }

  a.accent-link {
    color: var(--color-paper-accent);
    text-decoration: none;
    transition: color 0.2s ease-out;
  }
  a.accent-link:hover {
    color: var(--color-paper-primary);
  }

  .post-card-accent {
    position: relative;
  }
  .post-card-accent::after {
    content: '';
    position: absolute;
    bottom: 0;
    left: 0;
    width: 0;
    height: 2px;
    background: var(--color-paper-accent);
    transition: width 0.3s ease-out;
  }
  .post-card-accent:hover::after {
    width: 100%;
  }

  /* ========== Blur-up 渐进图片加载 ==========
     放在 @layer components 内，与 .blur-img.post-card-cover-blur 同层，
     这样特异性能正常生效（layer 外规则会无条件覆盖 layer 内规则，
     导致卡片的 aspect-ratio:4/3 败给全局 var(--ar)）。 */
  .blur-img {
    position: relative;
    display: block;
    overflow: hidden;
    aspect-ratio: var(--ar);
    /* 加载中灰底（占位图未加载完时） */
    background: var(--color-paper-code-bg);
    border-radius: var(--radius-mini);
    margin: 1em 0;
  }
  .blur-img-placeholder {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    /* 重置 .md-content img 的 margin/max-width/height，避免把 absolute 图层推偏 */
    margin: 0;
    max-width: none;
    /* 20px 占位图放大后模糊，scale 遮边缘 */
    filter: blur(20px) saturate(1.2);
    transform: scale(1.1);
    transition: opacity 0.4s ease;
  }
  .blur-img-full {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    /* 重置 .md-content img 的 margin/max-width/height，避免把 absolute 图层推偏 */
    margin: 0;
    max-width: none;
    opacity: 0;
    z-index: 1;
  }
  /* full 加载完成后由 JS 直接设 opacity:1（不依赖 CSS transition，
     避免合成层重绘时机导致 opacity 卡在 0）。 */
  .blur-img-full.is-loaded,
  .blur-img.is-loaded .blur-img-full {
    opacity: 1;
  }
  /* 容器标记 loaded 后：显式隐藏占位图 + 去掉灰底，避免重绘时机导致残留/灰边 */
  .blur-img.is-loaded .blur-img-placeholder {
    opacity: 0;
  }
  .blur-img.is-loaded {
    background: transparent;
  }

  /* ========== 主题切换图标进入动画 ==========
     点击切换主题时 theme.set 立即换 SVG（配合 RSX 的 key 强制重挂载），
     该动画为新挂载的图标播放一次缩放+淡入，给用户即时反馈。
     仅作用于 .theme-toggle 内的 svg，不影响页面其它 svg。 */
  .theme-toggle svg {
    animation: theme-icon-enter 0.3s ease-out;
  }

  @keyframes theme-icon-enter {
    from {
      opacity: 0;
      transform: scale(0.5) rotate(-60deg);
    }
    to {
      opacity: 1;
      transform: scale(1) rotate(0deg);
    }
  }

}

@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

@media screen and (max-width: 768px) {
  .post-title {
    font-size: 32px;
  }

  .md-content h1 {
    font-size: 32px;
  }

  .md-content h2 {
    font-size: 26px;
  }

  .md-content h3 {
    font-size: 20px;
  }

  .paginav {
    flex-direction: column;
  }

  .paginav a {
    width: 100%;
  }

  .paginav .next {
    margin-inline-start: 0;
    text-align: left;
    border-top: 1px solid var(--color-paper-border);
  }

  details.toc .inner {
    margin: 0 1rem;
  }

  /* 旧文章兜底：未重建的文章是裸 table（无 .table-wrap 包裹），移动端需 block 化才能滚动。
     选择器 .md-content > div > table 精确命中「片段容器直接子代的裸 table」，
     不会误伤新文章 .table-wrap 内的 table（后者多一层 div，圆角视觉完整）。
     block 化会损 thead/tbody 圆角，但仅移动端 + 仅旧文章，可接受。 */
  .md-content > div > table {
    display: block;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }
}

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

.page-enter {
  animation: pageEnter 0.15s ease-out;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  details::details-content {
    transition: none;
  }

  .page-enter,
  .animate-page-enter,
  .animate-popover-enter,
  .animate-select-enter,
  .animate-row-enter {
    animation: none;
  }

  .theme-toggle svg {
    animation: none;
  }
}

/* ========== Blur-up 渐进图片加载（已移入 @layer components） ========== */
@source "./src/**/*.{rs,html}";

/* ========== CodeMirror 代码运行器高度自适应优化 ========== */
.code-runner-editor {
  min-height: 120px;
  max-height: 400px;
  display: flex;
  flex-direction: column;
}
.code-runner-editor .cm-editor {
  flex: 1 1 auto !important;
}
.code-runner-editor .cm-scroller {
  overflow: auto;
}

