@xingwangzhe/stalux 1.47.1 → 1.48.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/README.md +4 -1
  2. package/package.json +1 -1
  3. package/public/background/pattern-1.min.dark.webp +0 -0
  4. package/public/background/pattern-10.min.dark.webp +0 -0
  5. package/public/background/pattern-11.min.dark.webp +0 -0
  6. package/public/background/pattern-12.min.dark.webp +0 -0
  7. package/public/background/pattern-13.min.dark.webp +0 -0
  8. package/public/background/pattern-14.min.dark.webp +0 -0
  9. package/public/background/pattern-15.min.dark.webp +0 -0
  10. package/public/background/pattern-16.min.dark.webp +0 -0
  11. package/public/background/pattern-17.min.dark.webp +0 -0
  12. package/public/background/pattern-18.min.dark.webp +0 -0
  13. package/public/background/pattern-19.min.dark.webp +0 -0
  14. package/public/background/pattern-2.min.dark.webp +0 -0
  15. package/public/background/pattern-20.min.dark.webp +0 -0
  16. package/public/background/pattern-21.min.dark.webp +0 -0
  17. package/public/background/pattern-22.min.dark.webp +0 -0
  18. package/public/background/pattern-23.min.dark.webp +0 -0
  19. package/public/background/pattern-24.min.dark.webp +0 -0
  20. package/public/background/pattern-25.min.dark.webp +0 -0
  21. package/public/background/pattern-26.min.dark.webp +0 -0
  22. package/public/background/pattern-27.min.dark.webp +0 -0
  23. package/public/background/pattern-28.min.dark.webp +0 -0
  24. package/public/background/pattern-29.min.dark.webp +0 -0
  25. package/public/background/pattern-3.min.dark.webp +0 -0
  26. package/public/background/pattern-30.min.dark.webp +0 -0
  27. package/public/background/pattern-31.min.dark.webp +0 -0
  28. package/public/background/pattern-32.min.dark.webp +0 -0
  29. package/public/background/pattern-33.min.dark.webp +0 -0
  30. package/public/background/pattern-34.min.dark.webp +0 -0
  31. package/public/background/pattern-35.min.dark.webp +0 -0
  32. package/public/background/pattern-36.min.dark.webp +0 -0
  33. package/public/background/pattern-37.min.dark.webp +0 -0
  34. package/public/background/pattern-38.min.dark.webp +0 -0
  35. package/public/background/pattern-39.min.dark.webp +0 -0
  36. package/public/background/pattern-4.min.dark.webp +0 -0
  37. package/public/background/pattern-40.min.dark.webp +0 -0
  38. package/public/background/pattern-41.min.dark.webp +0 -0
  39. package/public/background/pattern-42.min.dark.webp +0 -0
  40. package/public/background/pattern-5.min.dark.webp +0 -0
  41. package/public/background/pattern-6.min.dark.webp +0 -0
  42. package/public/background/pattern-7.min.dark.webp +0 -0
  43. package/public/background/pattern-8.min.dark.webp +0 -0
  44. package/public/background/pattern-9.min.dark.webp +0 -0
  45. package/src/components/stalux/common/Weather.astro +29 -2
  46. package/src/components/stalux/common/author.astro +1 -0
  47. package/src/components/stalux/common/date.astro +4 -0
  48. package/src/components/stalux/footer/FooterBadges.astro +14 -3
  49. package/src/components/stalux/layout/footer.astro +1 -12
  50. package/src/components/stalux/layout/head.astro +1 -1
  51. package/src/components/stalux/links/socialMedia.astro +1 -0
  52. package/src/components/stalux/posts/postCard.astro +1 -0
  53. package/src/components/stalux/posts/postContent.astro +1 -0
  54. package/src/layouts/Stalux.astro +0 -1
  55. package/src/pages/404.astro +1 -0
  56. package/src/pages/index.astro +1 -0
  57. package/src/pages/stalux-assets/badges/[id].svg.ts +20 -0
  58. package/src/scripts/background.ts +10 -3
  59. package/src/scripts/core-runtime.ts +0 -1
  60. package/src/scripts/search-dialog.ts +1 -0
  61. package/src/scripts/swup-router.ts +2 -0
  62. package/src/styles/generated-author.css +3 -0
  63. package/src/styles/generated-cards.css +3 -0
  64. package/src/styles/generated-home.css +3 -0
  65. package/src/styles/generated-not-found.css +3 -0
  66. package/src/styles/generated-social.css +3 -0
  67. package/src/styles/generated.css +1 -1
  68. package/src/utils/badge-generator.ts +33 -5
  69. package/src/utils/route-catalog.ts +4 -0
package/README.md CHANGED
@@ -138,6 +138,9 @@ Processed pages are cached under `node_modules/.astro/stalux-page-output/`. The
138
138
 
139
139
  The desktop tag cloud loads dynamically near the viewport. Switching to mobile, leaving the viewport or hiding the document destroys it and stops animation scheduling; becoming visible recreates it. Tag clicks use the same Swup navigation as ordinary internal links. Clocks and the footer runtime update only while visible, and the date changes only on a new day. Comments load within half a viewport (capped at 400px). Tag groups, archive months and category cards retain static HTML while deferring offscreen rendering.
140
140
 
141
+
142
+ Configured footer badges are generated as content-addressed SVG assets. Native lazy loading keeps closed groups from embedding their image payload in every page; expanding groups also works without JavaScript. Custom component badges outside footer.yml retain Data URL support.
143
+
141
144
  ### Modern JavaScript
142
145
 
143
146
  TypeScript uses ESNext. The theme defaults `vite.build.target` to `"esnext"` to retain modern syntax with minimal compatibility transforms; an explicit consumer target takes precedence. This targets modern browsers, does not polyfill missing Web APIs, and does not move ordinary scripts onto the GPU. Biome enforces `noVar` and `useConst` as errors in maintained source; dependencies and generated bundles are outside this source policy.
@@ -381,4 +384,4 @@ Local covers are read from the final `publicDir`. Remote covers are requested by
381
384
 
382
385
  Motion is specified for 55 visible semantic modules in [Modules and view transitions](docs/MOTION.md). Swup animates one visible, height-bounded heading or introductory region after destination assets are ready, with cues for reading, returning, filtering and previous/next articles. Long documents stay readable and the header, footer and dark canvas remain stable. Phones use a short fade; history restores the reading position; same-page anchors use interruptible native scrolling. Module hover, focus, press and asynchronous update feedback complement bounded secondary entry cues. Reduced motion and print remain static and readable. No new configuration is required.
383
386
 
384
- Built-in background artwork uses committed lossless WebP companions. Ratio-only SVG sizing is preserved with `contain`; custom background URLs retain their existing sizing. Regenerate companions after changing the SVG originals with `bun run backgrounds:build`.
387
+ Built-in backgrounds use committed WebP companions composited against the default #202020 canvas (quality 80, original resolution). Custom CSS canvas colors use the original transparent WebP; SVG sources are retained. Ratio-only SVG sizing is preserved with `contain`; custom background URLs retain their existing sizing. Regenerate companions after changing the SVG originals with `bun run backgrounds:build`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xingwangzhe/stalux",
3
- "version": "1.47.1",
3
+ "version": "1.48.0",
4
4
  "description": "A powerful, modern Astro blog theme — use as template or install as plugin",
5
5
  "keywords": [
6
6
  "astro",
@@ -48,9 +48,36 @@ const zh = (site.lang || "zh-CN").startsWith("zh");
48
48
  )}
49
49
  <script>
50
50
  import { registerPageLifecycle } from "../../../scripts/page-runtime";
51
- import { mountWeather } from "../../../scripts/weather";
52
51
 
53
- registerPageLifecycle("weather", mountWeather);
52
+ // 页脚天气在首屏之外。模块本身、以及它发起的两次第三方请求,
53
+ // 都推迟到卡片接近视口时才发生;SSR 已经输出占位文案,不依赖这段脚本。
54
+ registerPageLifecycle("weather", () => {
55
+ const targets = [...document.querySelectorAll<HTMLElement>("[data-stalux-weather]")];
56
+ if (targets.length === 0) return;
57
+ let disposed = false;
58
+ let cleanup: (() => void) | undefined;
59
+ const start = async () => {
60
+ observer?.disconnect();
61
+ const { mountWeather } = await import("../../../scripts/weather");
62
+ if (disposed) return;
63
+ cleanup = mountWeather();
64
+ };
65
+ const observer = globalThis.IntersectionObserver
66
+ ? new IntersectionObserver(
67
+ (entries) => {
68
+ if (entries.some((entry) => entry.isIntersecting)) void start();
69
+ },
70
+ { rootMargin: "200px" },
71
+ )
72
+ : undefined;
73
+ if (observer) for (const target of targets) observer.observe(target);
74
+ else void start();
75
+ return () => {
76
+ disposed = true;
77
+ observer?.disconnect();
78
+ cleanup?.();
79
+ };
80
+ });
54
81
  </script>
55
82
  <style>
56
83
  .stalux-weather {
@@ -1,4 +1,5 @@
1
1
  ---
2
+ import "../../../styles/generated-author.css";
2
3
  import { Image } from "astro:assets";
3
4
  import { getCollection } from "astro:content";
4
5
 
@@ -23,3 +23,7 @@
23
23
  timeElement.dateTime = timeElement.textContent;
24
24
  })();
25
25
  </script>
26
+
27
+ <script>
28
+ import "../../../scripts/date-time";
29
+ </script>
@@ -1,9 +1,16 @@
1
1
  ---
2
2
  import { getCollection } from "astro:content";
3
3
  import type { BadgeItem, BadgeOptions } from "@utils/badge-generator";
4
- import { generateBadge, isBadgeGroup, svgToDataUrl } from "@utils/badge-generator";
5
- import { getSiteData } from "@utils/config-utils";
4
+ import {
5
+ badgeAssetId,
6
+ createBadgeAssets,
7
+ generateBadge,
8
+ isBadgeGroup,
9
+ svgToDataUrl,
10
+ } from "@utils/badge-generator";
11
+ import { getFooterData, getSiteData } from "@utils/config-utils";
6
12
  import { createTranslator } from "@utils/i18n";
13
+ import { sitePath } from "@utils/site-path";
7
14
 
8
15
  interface Props {
9
16
  badges?: BadgeItem[];
@@ -12,11 +19,15 @@ interface Props {
12
19
  const { badges } = Astro.props;
13
20
  const configEntries = await getCollection("config");
14
21
  const siteConfig = getSiteData(configEntries);
22
+ const badgeAssets = createBadgeAssets(getFooterData(configEntries)?.badges);
15
23
  const { t } = createTranslator(siteConfig.lang || "zh-CN");
16
24
 
17
25
  function badgeImg(opts: BadgeOptions) {
18
26
  const svg = generateBadge(opts, Astro.logger);
19
- const src = svgToDataUrl(svg);
27
+ const id = badgeAssetId(svg);
28
+ const src = badgeAssets.has(id)
29
+ ? sitePath(`stalux-assets/badges/${id}.svg`)
30
+ : svgToDataUrl(svg);
20
31
  const alt = opts.alt || `${opts.label}: ${opts.message}`;
21
32
  const width = svg.match(/<svg\b[^>]*\bwidth="(\d+)"/)?.[1];
22
33
  const height = svg.match(/<svg\b[^>]*\bheight="(\d+)"/)?.[1];
@@ -6,7 +6,7 @@ import FooterBeian from "@components/stalux/footer/FooterBeian.astro";
6
6
  import FooterCopyright from "@components/stalux/footer/FooterCopyright.astro";
7
7
  import FooterStats from "@components/stalux/footer/FooterStats.astro";
8
8
  import FooterThemeInfo from "@components/stalux/footer/FooterThemeInfo.astro";
9
- import type { BadgeItem, BadgeOptions } from "@utils/badge-generator";
9
+ import { type BadgeItem, normalizeBadgeStyle } from "@utils/badge-generator";
10
10
  import { getAuthorData, getFooterData, getSiteData } from "@utils/config-utils";
11
11
  import { formatWordCount, getTotalWordCount } from "@utils/word-count-utils";
12
12
  import BackToTop from "./BackToTop.astro";
@@ -19,17 +19,6 @@ const authorConfig = getAuthorData(configEntries);
19
19
  const author = authorConfig.name;
20
20
 
21
21
  // 标准化 badges(扁平 badge 或 分组),确保 style 字段合法
22
- const badgeStyles = new Set<BadgeOptions["style"]>([
23
- "flat",
24
- "plastic",
25
- "flat-square",
26
- "for-the-badge",
27
- "social",
28
- ]);
29
- const normalizeBadgeStyle = (style: string | undefined): BadgeOptions["style"] =>
30
- style && badgeStyles.has(style as BadgeOptions["style"])
31
- ? (style as BadgeOptions["style"])
32
- : "flat";
33
22
  const badges: BadgeItem[] | undefined = footerConfig?.badges?.map((item) => {
34
23
  if ("title" in item) {
35
24
  return {
@@ -77,7 +77,7 @@ const ldJson = JSON.stringify(seo.schema).replace(/<\//g, "<\\/");
77
77
  )}
78
78
  <!-- 代码字体由 Astro Fonts API 注入;正文按页面生成 native CJK 子集。 -->
79
79
  <Font cssVariable="--font-code" />
80
- <link rel="prefetch" as="style" href={pagefindStyles} data-stalux-search-style>
80
+ <link rel="stylesheet" data-href={pagefindStyles} data-stalux-search-style>
81
81
  <noscript><link rel="stylesheet" href={pagefindStyles}></noscript>
82
82
  {headConfig?.anyhead && <Fragment set:html={headConfig.anyhead} />}
83
83
  {headConfig?.googleAnalyticsId && <GoogleAnalytics />}
@@ -1,4 +1,5 @@
1
1
  ---
2
+ import "../../../styles/generated-social.css";
2
3
  // 按需导入图标 — Vite tree-shake 只打包用到的图标
3
4
 
4
5
  import { getCollection } from "astro:content";
@@ -1,4 +1,5 @@
1
1
  ---
2
+ import "../../../styles/generated-cards.css";
2
3
  import type { CollectionEntry } from "astro:content";
3
4
  import { getCollection } from "astro:content";
4
5
 
@@ -138,6 +138,7 @@ const mdSourceUrl = exportMd ? `${Astro.url.pathname.replace(/\/$/, "")}.md` : "
138
138
  </article>
139
139
 
140
140
  <script>
141
+ import "../../../scripts/module-motion";
141
142
  import "../../../scripts/photoswipe";
142
143
  import { mountCodeAccessibility } from "../../../scripts/code-accessibility";
143
144
  import { registerPageLifecycle } from "../../../scripts/page-runtime";
@@ -74,7 +74,6 @@ const routeKind = getRouteKind(Astro.url.pathname);
74
74
  />
75
75
  <script>
76
76
  import "../scripts/background.ts";
77
- import "../scripts/module-motion.ts";
78
77
  import "../scripts/view-transitions.ts";
79
78
  // Every page type has at least one list, so the unroll cue is registered
80
79
  // once in the shared layout instead of per page. Page-runtime dedupes it
@@ -1,4 +1,5 @@
1
1
  ---
2
+ import "../styles/generated-not-found.css";
2
3
  import { getCollection } from "astro:content";
3
4
  import Stalux from "@layouts/Stalux.astro";
4
5
  import { getSiteData } from "@utils/config-utils";
@@ -1,4 +1,5 @@
1
1
  ---
2
+ import "../styles/generated-home.css";
2
3
  import { getCollection } from "astro:content";
3
4
  import { createTranslator } from "@utils/i18n";
4
5
 
@@ -0,0 +1,20 @@
1
+ import { getCollection } from "astro:content";
2
+ import type { APIRoute } from "astro";
3
+ import { createBadgeAssets } from "../../../utils/badge-generator";
4
+ import { getFooterData } from "../../../utils/config-utils";
5
+
6
+ export const prerender = true;
7
+
8
+ export async function getStaticPaths() {
9
+ const footer = getFooterData(await getCollection("config"));
10
+ const assets = createBadgeAssets(footer?.badges);
11
+ return [...assets].map(([id, svg]) => ({ params: { id }, props: { svg } }));
12
+ }
13
+
14
+ export const GET: APIRoute = ({ props }) =>
15
+ new Response(props.svg, {
16
+ headers: {
17
+ "Content-Type": "image/svg+xml; charset=utf-8",
18
+ "Cache-Control": "public, max-age=31536000, immutable",
19
+ },
20
+ });
@@ -2,7 +2,7 @@
2
2
  * 每个完整文档只随机选择一次的会话背景。
3
3
  *
4
4
  * SSR 保持确定的深色底和原有双层 DOM,不内联背景 URL。文档解析完成即
5
- * 低优先级请求并异步解码一张无损 WebP,无需等待 window.load。首次成功时从暗底
5
+ * 低优先级请求并异步解码一张深色底 WebP,无需等待 window.load。首次成功时从暗底
6
6
  * 用 200ms opacity 淡显;减少动态效果时直接显示。解码慢或失败仍保持暗底。
7
7
  * Swup 只替换 main,背景沿用同一张,不按软导航重选/解码或再次交叉淡入。
8
8
  * 自定义 __STALUX_BG_URLS__ 继续生效;saveData 下保留暗底,不请求装饰图片。
@@ -20,7 +20,7 @@ declare global {
20
20
 
21
21
  const BACKGROUND_URLS: string[] = Array.from(
22
22
  { length: 42 },
23
- (_, i) => `/background/pattern-${i + 1}.min.webp`,
23
+ (_, i) => `/background/pattern-${i + 1}.min.dark.webp`,
24
24
  );
25
25
 
26
26
  /** Install once per full document; this module is also harmless during SSR. */
@@ -40,7 +40,14 @@ export function installSessionBackground(): void {
40
40
  ? window.__STALUX_BG_URLS__
41
41
  : BACKGROUND_URLS;
42
42
  const index = Math.floor(Math.random() * urls.length);
43
- const source = urls[index];
43
+ // The compact raster is composited against the standard canvas. Preserve
44
+ // CSS custom canvas colors with the original transparent raster.
45
+ const standardCanvas =
46
+ typeof getComputedStyle === "undefined" ||
47
+ getComputedStyle(a).backgroundColor === "rgb(32, 32, 32)";
48
+ const selected = urls[index];
49
+ const source =
50
+ custom || standardCanvas ? selected : selected?.replace(/\.dark\.webp$/u, ".webp");
44
51
  if (!source) return;
45
52
  const image = new Image();
46
53
  image.decoding = "async";
@@ -1,6 +1,5 @@
1
1
  // One shared entry for tiny, dependency-free behavior present across Stalux pages.
2
2
  // Each module registers a no-op-safe mount with page-runtime.
3
- import "./date-time";
4
3
  import "./footer-badges";
5
4
  import "./navigation";
6
5
  import "./runtime-counter";
@@ -11,6 +11,7 @@ export interface CustomElementRegistryLike<ElementType> {
11
11
  export async function ensureSearchStyles(link: HTMLLinkElement | null): Promise<void> {
12
12
  if (!link) return;
13
13
  link.rel = "stylesheet";
14
+ if (!link.href && link.dataset?.href) link.href = link.dataset.href;
14
15
  link.media = "all";
15
16
  if (link.sheet) return;
16
17
  await new Promise<void>((resolve, reject) => {
@@ -126,6 +126,8 @@ export function installSwupRouter(): Swup {
126
126
  scroll,
127
127
  new SwupA11yPlugin({ headingSelector: "[data-stalux-motion-focus]" }),
128
128
  new SwupPreloadPlugin({
129
+ // The initial document is already present; avoid fetching it twice.
130
+ preloadInitialPage: false,
129
131
  preloadHoveredLinks: true,
130
132
  preloadVisibleLinks: false,
131
133
  throttle: 2,
@@ -0,0 +1,3 @@
1
+ @layer theme, base, components, utilities;
2
+ @layer components{.stalux-author{margin-top:4em}.stalux-author-figure{justify-content:center;align-items:center;display:flex}.stalux-author-figure img{box-shadow:0 0 10px var(--stalux-accent-color);border-radius:9999px;transition:transform .18s ease-out}.stalux-author-figure figcaption{text-shadow:var(--stalux-text-shadow);color:var(--white-full);margin-left:1em;font-size:2.5em;font-weight:700}.stalux-author-figure-column figcaption{text-align:center;margin-top:.5em;margin-left:0}@media (hover:hover) and (pointer:fine){.stalux-author-figure>a:hover img{transform:rotate(3deg)}}@media (width<=768px){.stalux-author{box-sizing:border-box;width:100%;max-width:95vw;margin-top:2em;padding:1em .5em}.stalux-author-figure{gap:.5em;flex-direction:column!important}.stalux-author-figure img{max-width:20vw;max-height:20vw;width:64px!important;height:64px!important}.stalux-author-figure figcaption{text-align:center;word-break:break-all;overflow-wrap:break-word;white-space:normal;max-width:90vw;margin-top:.5em;margin-left:0;font-size:1.5em}}}@layer utilities,theme,base;
3
+ /*$vite$:1*/
@@ -0,0 +1,3 @@
1
+ @layer theme, base, components, utilities;
2
+ @layer components{.stalux-card-post-categories,.stalux-card-post-tags{gap:.4rem}.stalux-card-post-category{background:var(--category-bg);color:#fff;border-radius:6px;padding:.18rem .5rem;font-size:.84rem;line-height:1;display:inline-block}.stalux-card-post-description{overflow-wrap:anywhere;color:var(--white-70p);line-height:1.6}.stalux-card-post-meta{gap:.6rem}.stalux-card-post-tag{background:var(--tag-bg);color:#fff;border-radius:9999px;padding:.22rem .7rem;font-size:.85rem;line-height:1;display:inline-block}.stalux-card-post-title{overflow-wrap:anywhere;margin:0;line-height:1.35}.stalux-card-read-more{align-self:flex-start;margin-top:.6rem}.stalux-post-card{box-sizing:border-box;cursor:pointer;gap:var(--space-lg);border-radius:var(--radius-lg);background-color:var(--card-bg);height:100%;padding:var(--space-lg);box-shadow:var(--card-box-shadow);transition:transform .22s cubic-bezier(.22,.72,.22,1)}.stalux-card-post-cover{border-radius:var(--radius-md);flex-shrink:0;height:180px;margin-bottom:.5rem;overflow:hidden}.stalux-post-list-container{width:100%;height:auto;margin:5px 0}.stalux-post-list-container ul{flex-wrap:wrap;gap:2rem;margin:3em;padding:0;list-style-type:none;display:flex}.stalux-post-list-container ul>li{flex:min(22rem,100%);min-width:0;margin:0}.stalux-card-post-title a{color:inherit;text-decoration:none}.stalux-post-card>a:first-child{width:100%;min-width:0;display:block}.stalux-card-post-cover img{object-fit:cover;width:100%;max-width:100%;height:100%;transition:transform var(--transition-fast)}.stalux-card-post-date,.stalux-card-post-updated{color:#e8f2ff;border-radius:10px;align-items:center;gap:.35rem;width:fit-content;padding:.28rem .6rem;font-size:.9rem;line-height:1.1;display:inline-flex}.stalux-card-post-date{background:var(--date-bg);border:1px solid var(--date-border);color:#e8f2ff}.stalux-card-post-updated{background:var(--updated-bg);border:1px solid var(--updated-border);color:#fff7de}.stalux-card-post-tags a,.stalux-card-post-categories a{text-decoration:none}.stalux-card-post-tags a:focus-visible .stalux-card-post-tag{background:var(--tag-bg-hover)}.stalux-card-post-categories a:focus-visible .stalux-card-post-category{background:var(--category-bg-hover)}@media (hover:hover) and (pointer:fine){.stalux-card-post-tags a:hover .stalux-card-post-tag{background:var(--tag-bg-hover)}.stalux-card-post-categories a:hover .stalux-card-post-category{background:var(--category-bg-hover)}.stalux-post-card-shell:hover .stalux-post-card .stalux-card-post-cover img{transform:scale(1.025)}.stalux-post-card-shell:hover .stalux-post-card{box-shadow:var(--card-box-shadow-hover)}}@media (width<=768px){.stalux-post-list-container ul{margin:1rem}}}@layer utilities,theme,base;
3
+ /*$vite$:1*/
@@ -0,0 +1,3 @@
1
+ @layer theme, base, components, utilities;
2
+ @layer components{.stalux-home-body{min-height:calc(100vh - var(--stalux-site-header-height));padding-bottom:var(--space-3xl);position:relative}.stalux-home-title{color:var(--white-full);text-shadow:var(--stalux-text-shadow);margin-top:1.5em;font-size:4em}.stalux-typewriter{min-height:2em;text-shadow:var(--stalux-text-shadow);margin-top:1.5em;font-size:2.5em}#stalux-home-show-post-list{cursor:pointer;text-shadow:var(--stalux-text-shadow);margin-top:3em;font-size:1.5em}.agent-home-summary{clip-path:inset(50%);white-space:normal;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}@media (width<=768px){.stalux-home-body{box-sizing:border-box;width:100%;max-width:95vw;height:auto;padding:2rem .5rem 1.5rem}.stalux-home-title{word-break:break-all;margin-top:1em;font-size:2em}#stalux-home-show-post-list{margin-top:2em;font-size:1.1em}}}@layer utilities,theme,base;
3
+ /*$vite$:1*/
@@ -0,0 +1,3 @@
1
+ @layer theme, base, components, utilities;
2
+ @layer components{.stalux-404-home-btn{background:var(--black-20p);border:var(--border-thin) solid var(--white-20p);transition:background-color var(--transition-normal), transform var(--transition-normal);border-radius:var(--radius-md);padding:var(--space-md) var(--space-lg);color:var(--white-90p);font-size:var(--font-size-base);text-decoration:none;display:inline-block}.stalux-404-error-container{min-height:60vh;padding:2rem}.stalux-404-error-content h1{color:var(--white-90p);margin:0;font-size:6rem;font-weight:700}.stalux-404-error-content p{color:var(--white-70p);margin:1rem 0 2rem;font-size:1.5rem}.stalux-404-countdown-text{color:var(--white-50p)!important;margin:-.5rem 0 1.5rem!important;font-size:.95rem!important}.agent-recovery{max-width:42rem;line-height:1.7;margin:0 auto 1.5rem!important;font-size:1rem!important}.agent-recovery a{color:inherit;text-decoration-line:underline}@media (hover:hover) and (pointer:fine){.stalux-404-home-btn:hover{background:var(--accent-20p);box-shadow:0 4px 12px var(--shadow-dark)}}@media (width<=768px){.stalux-404-error-content h1{font-size:4rem}.stalux-404-error-content p{font-size:1.2rem}}}@layer utilities,theme,base;
3
+ /*$vite$:1*/
@@ -0,0 +1,3 @@
1
+ @layer theme, base, components, utilities;
2
+ @layer components{.stalux-social{margin-top:3em}.stalux-social ul{flex-wrap:wrap;justify-content:center;gap:1em;margin:0;padding:0;display:flex}.stalux-social ul li{box-sizing:border-box;text-align:center;background-color:var(--white-15p);border-radius:9999px;justify-content:center;align-items:center;width:2.5em;height:2.5em;font-size:large;display:inline-flex;overflow:hidden}.stalux-social ul a,.stalux-social ul .stalux-social-icon-container,.stalux-social ul .stalux-social-custom-icon{justify-content:center;align-items:center;width:100%;height:100%;line-height:1;display:inline-flex}.stalux-social[data-stalux-social-animate=true] li{animation:.28s cubic-bezier(.2,.8,.2,1) both stalux-social-stalux-social-arrive}.stalux-social[data-stalux-social-animate=true] li:nth-child(2){animation-delay:30ms}.stalux-social[data-stalux-social-animate=true] li:nth-child(3){animation-delay:60ms}.stalux-social[data-stalux-social-animate=true] li:nth-child(4){animation-delay:90ms}.stalux-social[data-stalux-social-animate=true] li:nth-child(5){animation-delay:.12s}.stalux-social[data-stalux-social-animate=true] li:nth-child(6){animation-delay:.15s}.stalux-social[data-stalux-social-animate=true] li:nth-child(n+7){animation-delay:.18s}@media (prefers-reduced-motion:reduce){.stalux-social[data-stalux-social-animate=true] li{animation:none}}}@layer utilities,theme,base;
3
+ /*$vite$:1*/
@@ -1,3 +1,3 @@
1
1
  @layer theme, base, components, utilities;
2
- @layer components{.stalux-404-home-btn{background:var(--black-20p);border:var(--border-thin) solid var(--white-20p);transition:background-color var(--transition-normal), transform var(--transition-normal);border-radius:var(--radius-md);padding:var(--space-md) var(--space-lg);color:var(--white-90p);font-size:var(--font-size-base);text-decoration:none;display:inline-block}.stalux-ai-prompt{clip-path:inset(50%);white-space:pre-wrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.stalux-badge-group{border:none}.stalux-badge-group-arrow{font-size:.65rem;transition:transform .2s;display:inline-block}.stalux-badge-group-summary{user-select:none;cursor:pointer;color:var(--white-70p);gap:.4rem;padding:.2rem 0;font-size:.85rem;list-style-type:none;transition:color .2s}.stalux-beian-public-security-beian{color:#ffffffb3;gap:5px;font-size:.9rem;text-decoration:none;transition:color .3s;display:inline-flex}.stalux-card-post-categories,.stalux-card-post-tags{gap:.4rem}.stalux-card-post-category{background:var(--category-bg);color:#fff;border-radius:6px;padding:.18rem .5rem;font-size:.84rem;line-height:1;display:inline-block}.stalux-card-post-description{overflow-wrap:anywhere;color:var(--white-70p);line-height:1.6}.stalux-card-post-meta{gap:.6rem}.stalux-card-post-tag{background:var(--tag-bg);color:#fff;border-radius:9999px;padding:.22rem .7rem;font-size:.85rem;line-height:1;display:inline-block}.stalux-card-post-title{overflow-wrap:anywhere;margin:0;line-height:1.35}.stalux-card-read-more{align-self:flex-start;margin-top:.6rem}.stalux-card-time{gap:.45rem;display:inline-flex}.stalux-copyright{color:var(--white-70p);gap:.3em;font-weight:500}.stalux-footer{backdrop-filter:blur(10px);color:var(--white-full);background-color:#0000001a;margin-top:auto;padding:1.5rem 0;font-size:.9rem}.stalux-footer-content{gap:.8rem;max-width:1200px;margin:0 auto;padding:0 1rem}.stalux-nav-list{transform:scale(var(--nav-scale,1));transform-origin:50%;box-sizing:border-box;gap:2rem;max-width:100%;transition:transform .22s cubic-bezier(.22,.72,.22,1);overflow:visible}.stalux-nav-overlay{pointer-events:none;z-index:999;opacity:0;background:#0009;height:100%;transition:opacity .3s;display:none;position:fixed;top:0;left:0}.stalux-nav-scroll-btn{background:var(--black-30p);backdrop-filter:blur(8px);box-shadow:var(--shadow-md);pointer-events:none;z-index:10;cursor:pointer;width:36px;height:36px;color:var(--white-full);opacity:0;border:none;border-radius:9999px;padding:0;transition:opacity .25s;display:none;position:absolute;top:50%;transform:translateY(-50%)}.stalux-nav-toggle{z-index:998;cursor:pointer;min-width:48px;min-height:48px;color:inherit;background:0 0;border:none;padding:.75rem;display:none}.stalux-post-card{box-sizing:border-box;cursor:pointer;gap:var(--space-lg);border-radius:var(--radius-lg);background-color:var(--card-bg);height:100%;padding:var(--space-lg);box-shadow:var(--card-box-shadow);transition:transform .22s cubic-bezier(.22,.72,.22,1)}.stalux-stats-site-build-time{color:#fffc;margin-top:.5rem;font-size:.9rem}.stalux-stats-stats-separator{color:#ffffff80}.stalux-theme-info{color:var(--white-70p);gap:.3em;font-size:.85rem}.stalux-home-body{min-height:calc(100vh - var(--stalux-site-header-height));padding-bottom:var(--space-3xl);position:relative}.stalux-nav-container{box-sizing:border-box;max-width:100%;position:relative;overflow:hidden}.stalux-author{margin-top:4em}.stalux-card-post-cover{border-radius:var(--radius-md);flex-shrink:0;height:180px;margin-bottom:.5rem;overflow:hidden}.stalux-home-title{color:var(--white-full);text-shadow:var(--stalux-text-shadow);margin-top:1.5em;font-size:4em}.stalux-nav-item{text-shadow:var(--stalux-text-shadow);flex-shrink:0;margin-left:1em;margin-right:1em;font-size:1.3em}.stalux-page-description{color:var(--white-60p);margin-bottom:1.5em;font-size:1.2em}.stalux-page-title{text-shadow:var(--stalux-text-shadow);margin-top:1.5em;font-size:2.5em}.stalux-typewriter{min-height:2em;text-shadow:var(--stalux-text-shadow);margin-top:1.5em;font-size:2.5em}.stalux-404-error-container{min-height:60vh;padding:2rem}.stalux-badge,.stalux-badges-wrapper .stalux-badge{width:auto}.stalux-u-min-w-0{min-width:0}.stalux-u-w-full{width:100%}.stalux-u-flex{display:flex}.stalux-u-flex-col{flex-direction:column}.stalux-u-flex-wrap{flex-wrap:wrap}.stalux-u-items-center{align-items:center}.stalux-u-justify-center{justify-content:center}.stalux-badges,.stalux-badges-wrapper{gap:.5rem}.stalux-beian-beian-info{gap:1rem}.stalux-stats-site-stats{gap:.5rem;font-size:.9rem}.stalux-nav-text{white-space:nowrap;color:var(--white-full)}.stalux-badge-group-items{padding-top:.35rem}.stalux-u-text-center{text-align:center}.stalux-badge-group-hint{color:var(--white-70p);font-size:.7rem}.stalux-badge-group-title{color:var(--white-80p)}#stalux-home-show-post-list{cursor:pointer;text-shadow:var(--stalux-text-shadow);margin-top:3em;font-size:1.5em}.stalux-post-list-container{width:100%;height:auto;margin:5px 0}.stalux-post-list-container ul{flex-wrap:wrap;gap:2rem;margin:3em;padding:0;list-style-type:none;display:flex}.stalux-post-list-container ul>li{flex:min(22rem,100%);min-width:0;margin:0}.stalux-card-post-title a{color:inherit;text-decoration:none}.stalux-post-card>a:first-child{width:100%;min-width:0;display:block}.stalux-card-post-cover img{object-fit:cover;width:100%;max-width:100%;height:100%;transition:transform var(--transition-fast)}.stalux-card-post-date,.stalux-card-post-updated{color:#e8f2ff;border-radius:10px;align-items:center;gap:.35rem;width:fit-content;padding:.28rem .6rem;font-size:.9rem;line-height:1.1;display:inline-flex}.stalux-card-post-date{background:var(--date-bg);border:1px solid var(--date-border);color:#e8f2ff}.stalux-card-post-updated{background:var(--updated-bg);border:1px solid var(--updated-border);color:#fff7de}.stalux-card-post-tags a,.stalux-card-post-categories a{text-decoration:none}.stalux-card-post-tags a:focus-visible .stalux-card-post-tag{background:var(--tag-bg-hover)}.stalux-card-post-categories a:focus-visible .stalux-card-post-category{background:var(--category-bg-hover)}.stalux-social{margin-top:3em}.stalux-social ul{flex-wrap:wrap;justify-content:center;gap:1em;margin:0;padding:0;display:flex}.stalux-social ul li{box-sizing:border-box;text-align:center;background-color:var(--white-15p);border-radius:9999px;justify-content:center;align-items:center;width:2.5em;height:2.5em;font-size:large;display:inline-flex;overflow:hidden}.stalux-social ul a,.stalux-social ul .stalux-social-icon-container,.stalux-social ul .stalux-social-custom-icon{justify-content:center;align-items:center;width:100%;height:100%;line-height:1;display:inline-flex}.stalux-social[data-stalux-social-animate=true] li{animation:.28s cubic-bezier(.2,.8,.2,1) both stalux-social-stalux-social-arrive}.stalux-social[data-stalux-social-animate=true] li:nth-child(2){animation-delay:30ms}.stalux-social[data-stalux-social-animate=true] li:nth-child(3){animation-delay:60ms}.stalux-social[data-stalux-social-animate=true] li:nth-child(4){animation-delay:90ms}.stalux-social[data-stalux-social-animate=true] li:nth-child(5){animation-delay:.12s}.stalux-social[data-stalux-social-animate=true] li:nth-child(6){animation-delay:.15s}.stalux-social[data-stalux-social-animate=true] li:nth-child(n+7){animation-delay:.18s}nav{width:100%;min-width:0;max-width:100%}html{scroll-padding-top:var(--stalux-nav-offset,var(--stalux-site-header-height))}.stalux-site-header{z-index:990;width:100%;min-height:var(--stalux-site-header-min-height);isolation:isolate;justify-content:center;align-items:center;display:flex;position:sticky;top:0}.stalux-nav-scroll-btn[data-visible]{pointer-events:auto;opacity:1}.stalux-nav-scroll-btn[data-side=left]{left:4px}.stalux-nav-scroll-btn[data-side=right]{right:4px}.stalux-nav-scroll-btn svg{stroke:currentColor;stroke-width:2px;fill:none;width:20px;height:20px}.stalux-nav-link,.stalux-nav-link:visited{cursor:pointer;width:100%;color:inherit;min-height:44px;font:inherit;background:0 0;border:none;align-items:center;gap:.5rem;padding:.5rem .75rem;text-decoration:none;display:flex}.stalux-nav-link .nav-icon{stroke:var(--white-full)}.stalux-nav-toggle svg{width:32px;height:32px}.stalux-nav-overlay[data-state=show]{pointer-events:auto;opacity:1;display:block}#stalux-to-archive-archs{margin-top:2em}#stalux-date-date-time{text-shadow:var(--stalux-text-shadow);color:var(--white-full);flex-direction:column;align-items:center;margin-top:2em;display:flex}#stalux-date-date-time #stalux-date-date{min-height:1.25em;margin-bottom:.5em;font-size:2em;line-height:1.25}#stalux-date-date-time #stalux-date-time{font-variant-numeric:tabular-nums;min-height:1.25em;font-size:3em;line-height:1.25}.stalux-author-figure{justify-content:center;align-items:center;display:flex}.stalux-author-figure img{box-shadow:0 0 10px var(--stalux-accent-color);border-radius:9999px;transition:transform .18s ease-out}.stalux-author-figure figcaption{text-shadow:var(--stalux-text-shadow);color:var(--white-full);margin-left:1em;font-size:2.5em;font-weight:700}.stalux-author-figure-column figcaption{text-align:center;margin-top:.5em;margin-left:0}.agent-home-summary{clip-path:inset(50%);white-space:normal;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.stalux-404-error-content h1{color:var(--white-90p);margin:0;font-size:6rem;font-weight:700}.stalux-404-error-content p{color:var(--white-70p);margin:1rem 0 2rem;font-size:1.5rem}.stalux-404-countdown-text{color:var(--white-50p)!important;margin:-.5rem 0 1.5rem!important;font-size:.95rem!important}.agent-recovery{max-width:42rem;line-height:1.7;margin:0 auto 1.5rem!important;font-size:1rem!important}.agent-recovery a{color:inherit;text-decoration-line:underline}.stalux-theme-info span,.stalux-copyright span{margin:0}.stalux-theme-info a{color:#fffc;margin:0 .2em;text-decoration:none;transition:color .3s}.stalux-beian-beian-info a{color:#ffffffb3;font-size:.9rem;text-decoration:none;transition:color .3s}.stalux-beian-public-security-beian img{width:15px;height:15px;display:inline-block}.stalux-badge-group-summary::-webkit-details-marker,.stalux-badge-group[open] .stalux-badge-group-hint[data-hint=collapsed],.stalux-badge-group:not([open]) .stalux-badge-group-hint[data-hint=expanded]{display:none}.stalux-badge-group[open] .stalux-badge-group-arrow{transform:rotate(90deg)}@media (hover:hover) and (pointer:fine){.stalux-card-post-tags a:hover .stalux-card-post-tag{background:var(--tag-bg-hover)}.stalux-card-post-categories a:hover .stalux-card-post-category{background:var(--category-bg-hover)}.stalux-post-card-shell:hover .stalux-post-card .stalux-card-post-cover img{transform:scale(1.025)}.stalux-post-card-shell:hover .stalux-post-card{box-shadow:var(--card-box-shadow-hover)}.stalux-nav-scroll-btn:hover{background:0 0}.stalux-nav-container:hover .stalux-nav-scroll-btn[data-visible]{opacity:1}.stalux-nav-link:hover .nav-icon,.stalux-nav-link:hover .stalux-nav-text{stroke:var(--stalux-accent-color);color:var(--stalux-accent-color)}.stalux-author-figure>a:hover img{transform:rotate(3deg)}.stalux-404-home-btn:hover{background:var(--accent-20p);box-shadow:0 4px 12px var(--shadow-dark)}.stalux-theme-info a:hover{color:#fff;text-decoration:none}.stalux-beian-beian-info a:hover,.stalux-beian-public-security-beian:hover{color:#ffffffe6;text-decoration:none}.stalux-badge-group-summary:hover{color:var(--white-70p)}}@media (width>=601px){.stalux-site-nav{isolation:isolate;border-radius:0 0 16px 16px;transition:background-color .18s}.stalux-site-nav[data-scrolled]{backdrop-filter:blur(20px)saturate(140%);box-shadow:0 1px 0 var(--white-10p), 0 8px 24px #0000001f;background:#181818c7}}@media (width<=1100px){.stalux-nav-list{gap:1rem}.stalux-nav-item{margin-left:.6em;margin-right:.6em;font-size:1em}}@media (width<=900px){.stalux-nav-item{margin-left:.25em;margin-right:.25em;font-size:.95em}.stalux-nav-list{gap:.5rem}}@media (width<=768px){.stalux-home-body{box-sizing:border-box;width:100%;max-width:95vw;height:auto;padding:2rem .5rem 1.5rem}.stalux-home-title{word-break:break-all;margin-top:1em;font-size:2em}#stalux-home-show-post-list{margin-top:2em;font-size:1.1em}.stalux-post-list-container ul{margin:1rem}.stalux-footer{padding:1.2rem 0;font-size:.8rem}.stalux-footer-content{gap:.6rem;padding:0 .8rem}.stalux-author{box-sizing:border-box;width:100%;max-width:95vw;margin-top:2em;padding:1em .5em}.stalux-author-figure{gap:.5em;flex-direction:column!important}.stalux-author-figure img{max-width:20vw;max-height:20vw;width:64px!important;height:64px!important}.stalux-author-figure figcaption{text-align:center;word-break:break-all;overflow-wrap:break-word;white-space:normal;max-width:90vw;margin-top:.5em;margin-left:0;font-size:1.5em}.stalux-404-error-content h1{font-size:4rem}.stalux-404-error-content p{font-size:1.2rem}.stalux-badges{gap:.3rem}.stalux-badge{width:auto}}@media (width<=600px){html{--stalux-site-header-min-height:4rem}.stalux-nav-toggle[data-state=open]{visibility:hidden;pointer-events:none}.stalux-nav-toggle[data-scrolled]{backdrop-filter:blur(20px)saturate(140%);box-shadow:0 1px 0 var(--white-10p), 0 8px 24px #0000001f;background:#181818c7;border-radius:12px}.stalux-nav-toggle{display:block;position:fixed;top:.75rem;left:.75rem}.stalux-nav-container{overflow:visible}nav{width:auto}.stalux-nav-list{pointer-events:none;z-index:1000;background:var(--black-20p);backdrop-filter:blur(20px);flex-direction:column;justify-content:flex-start;align-items:flex-start;gap:0;width:min(220px,100vw - 1rem);height:100vh;padding:.5rem 1rem 2rem;position:fixed;top:0;left:0;right:auto;overflow-y:auto;transform:translate(-100%)}.stalux-nav-list[data-state=open]{pointer-events:auto;transform:translate(0)}.stalux-nav-item{border-bottom:1px solid var(--white-10p);flex-shrink:0;width:100%;margin:0;font-size:.9em}.stalux-nav-text{display:inline}.stalux-nav-link{width:100%;min-height:44px;font-size:inherit;padding:.45rem .75rem}.stalux-nav-link .nav-icon{width:18px;height:18px}}@media (width<=480px){.stalux-footer{padding:1rem 0;font-size:.8rem}.stalux-footer-content{gap:.6rem;padding:0 .8rem}}@media (prefers-reduced-motion:reduce){.stalux-social[data-stalux-social-animate=true] li{animation:none}}.stalux-main,.stalux-post-page,.stalux-post-layout>*,.stalux-link-card-content,.stalux-word-list-item,.stalux-word-card{box-sizing:border-box;min-width:0;max-width:100%}.stalux-main{overflow-wrap:anywhere}.stalux-link-shell{min-width:0;max-width:100%;display:block}.stalux-link-card{box-sizing:border-box;width:100%;max-width:100%}.stalux-category-shell{width:100%;min-width:0}.stalux-author-figure>a{flex-shrink:0;display:inline-block}.stalux-author-figure img{display:block}.stalux-post-card-shell,.stalux-category-shell,.stalux-link-shell{position:relative}.stalux-post-card,.stalux-category-card,.stalux-link-card,.stalux-word-card{transition:transform .2s,background-color .2s,border-color .2s,box-shadow .2s}:is(.stalux-post-card-shell,.stalux-category-shell):focus-within>*,.stalux-link-shell:focus-visible>*{box-shadow:var(--card-box-shadow-hover)}:is(button,summary,[role=button]):focus-visible{outline:2px solid var(--stalux-accent-color);outline-offset:3px}@media (prefers-reduced-motion:reduce){.stalux-main *,.stalux-main :before,.stalux-main :after{transition-duration:0s!important;animation:none!important}.stalux-post-card,.stalux-category-card,.stalux-link-card,.stalux-link-card-content,.stalux-card-post-cover img,.stalux-category-icon,.stalux-author-figure img,.stalux-link-card-avatar img{transform:none!important}}@keyframes stalux-social-stalux-social-arrive{0%{opacity:0;transform:translateY(.75rem)rotate(-12deg)}to{opacity:1;transform:translateY(0)rotate(0)}}@keyframes stalux-random-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes stalux-link-avatar-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}}@layer utilities{.sr-only{clip:rect(0,0,0,0);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.visible{visibility:visible}.absolute{position:absolute}.static{position:static}.grid{display:grid}.block{display:block}.inline-block{display:inline-block}.hidden{display:none}.h-full{height:100%}.flex{display:flex}.flex-shrink{flex-shrink:1}.flex-wrap{flex-wrap:wrap}.transform{transform:translateX(var(--un-translate-x)) translateY(var(--un-translate-y)) translateZ(var(--un-translate-z)) rotate(var(--un-rotate)) rotateX(var(--un-rotate-x)) rotateY(var(--un-rotate-y)) rotateZ(var(--un-rotate-z)) skewX(var(--un-skew-x)) skewY(var(--un-skew-y)) scaleX(var(--un-scale-x)) scaleY(var(--un-scale-y)) scaleZ(var(--un-scale-z))}.b,.border{border-width:1px}.text-inherit{color:inherit}.no-underline{text-decoration:none}.outline{outline-style:solid}}@layer theme;@layer base{html,body{color:#fff;width:100%;height:100%;margin:0;& main{flex:1}scrollbar-color:#4a4a4a #2a2a2a;font-family:var(--font-body), "Noto Sans SC", "Noto Sans CJK SC", system-ui, -apple-system, sans-serif;text-rendering:optimizelegibility;line-height:1.25;display:block}body{height:auto;min-height:100%}html{scrollbar-gutter:stable;background-color:var(--stalux-bg-color,#202020)}html[data-clarity-id]{opacity:1!important}a{color:inherit;cursor:pointer;text-decoration-skip-ink:auto;background-color:#0000;text-decoration:none;transition:color .2s,text-shadow .2s;position:relative}.a-none{cursor:pointer;text-decoration-skip-ink:auto;background-color:#0000;color:inherit!important;text-decoration:none!important}.a-none:after{display:none!important}a:not(.a-none):not([data-stalux-card]):not(.stalux-nav-link):after{content:"";background:linear-gradient(90deg, var(--stalux-accent-color), var(--accent-50p));transform-origin:0;pointer-events:none;width:100%;height:1px;transition:transform .25s cubic-bezier(.25,.9,.2,1);position:absolute;bottom:-2px;left:0;transform:scaleX(0)}a:not(.a-none):not([data-stalux-card]):not(.stalux-nav-link):focus-visible:after,a:not(.a-none):not([data-stalux-card]):not(.stalux-nav-link):active:after{transform:scaleX(1)}@media (hover:hover) and (pointer:fine){a:not(.a-none):not([data-stalux-card]):not(.stalux-nav-link):hover:after{transform:scaleX(1)}}a:active,a:focus-visible{text-decoration:none}@media (hover:hover) and (pointer:fine){a:hover{text-decoration:none}}a:focus{outline:none}a:focus-visible{outline:2px solid var(--stalux-accent-color);outline-offset:2px}ul{margin:0;padding:0;list-style:none}.none{display:none}.stalux-root{color:#fff;min-height:100vh}.stalux-main{min-height:calc(100vh - var(--stalux-site-header-height,3rem))}:root{--stalux-bg-color:#202020;--stalux-bg-filter:none;--stalux-site-header-min-height:3.75rem;--stalux-site-header-height:var(--stalux-site-header-min-height);--stalux-text-shadow:var(--stalux-accent-color) .08rem .08rem .18rem;--stalux-accent-color:#eab308;--stalux-accent-rgb:234 179 8;--surface-glass:var(--black-05p);--surface-glass-shadow:var(--shadow-sidebar);--card-bg:var(--surface-glass);--card-border:#ffffff1a;--card-box-shadow:0 10px 24px #00000014;--card-box-shadow-hover:0 14px 28px #0000001f;--tag-bg:#ffffff1f;--tag-bg-hover:#ffffff2e;--category-bg:#ffffff14;--category-bg-hover:#ffffff24;--date-bg:#42a0ff2e;--date-border:#42a0ff40;--updated-bg:#ffc94733;--updated-border:#ffc9474d;--white-full:#fff;--white-95p:#fffffff2;--white-90p:#ffffffe6;--white-85p:#ffffffd9;--white-80p:#ffffffe6;--white-78p:#ffffffc7;--white-75p:#ffffffbf;--white-70p:#ffffffdb;--white-60p:#fff9;--white-50p:#ffffff80;--white-30p:#ffffff4d;--white-20p:#fff3;--white-15p:#ffffff26;--white-10p:#ffffff1a;--white-05p:#ffffff0d;--black-30p:#0000004d;--black-20p:#0003;--black-15p:#00000026;--black-10p:#0000001a;--black-05p:#0000000d;--accent-90p:rgb(var(--stalux-accent-rgb) / .9);--accent-85p:rgb(var(--stalux-accent-rgb) / .85);--accent-80p:rgb(var(--stalux-accent-rgb) / .8);--accent-70p:rgb(var(--stalux-accent-rgb) / .7);--accent-60p:rgb(var(--stalux-accent-rgb) / .6);--accent-50p:rgb(var(--stalux-accent-rgb) / .5);--accent-40p:rgb(var(--stalux-accent-rgb) / .4);--accent-30p:rgb(var(--stalux-accent-rgb) / .3);--accent-20p:rgb(var(--stalux-accent-rgb) / .2);--transition-fast:.18s ease;--transition-medium:.2s ease;--transition-normal:.25s ease;--transition-slow:.3s ease;--transition-slower:.5s ease;--transition-slowest:.6s ease;--easing-bounce:cubic-bezier(.175, .885, .32, 1.275);--space-2xs:.25rem;--space-xs:.75rem;--space-sm:.5rem;--space-md:1rem;--space-lg:1.5rem;--space-xl:2rem;--space-2xl:3rem;--space-3xl:4rem;--radius-sm:4px;--radius-md:6px;--radius-lg:8px;--radius-full:9999px;--shadow-sm:0 2px 5px #0000001a;--shadow-md:0 6px 16px #0003;--shadow-lg:0 8px 20px #0000004d;--shadow-xl:0 12px 26px #00000047;--shadow-sidebar:0 16px 20px -12px #000000d6, 10px 4px 16px -12px #00000094, -10px 4px 16px -12px #00000094;--shadow-raised-hover:0 20px 24px -13px #000000e6, 12px 5px 18px -13px #000000ad, -12px 5px 18px -13px #000000ad;--shadow-dark:#000000c0;--muted-text:#bbb;--font-body:"Noto Sans SC", "Noto Sans CJK SC", system-ui, sans-serif;--font-size-subtitle:1.35rem;--font-size-base:1.1rem;--font-size-small:.95rem;--font-size-smaller:.9rem;--font-size-tiny:.85rem;--border-thin:1px;--border-medium:2px;--border-thick:3px}::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-track{background:#2a2a2a;border-radius:4px}::-webkit-scrollbar-thumb{background:#4a4a4a;border-radius:4px;transition:background .3s ease-out}@media (hover:hover) and (pointer:fine){::-webkit-scrollbar-thumb:hover{background:#5a5a5a}}::-webkit-scrollbar-corner{background:#2a2a2a}.bg-layer{z-index:-10;background-position:50%;background-repeat:repeat;background-size:auto;background-color:var(--stalux-bg-color,transparent);filter:var(--stalux-bg-filter,none);pointer-events:none;opacity:0;forced-color-adjust:none;color-scheme:light only;transition:opacity .2s ease-out;position:fixed;inset:0}@media (prefers-reduced-motion:reduce){.bg-layer{transition-duration:0s}}footer{padding:var(--space-lg) var(--space-md);text-align:center;color:var(--muted-text);border-top:1px solid var(--white-10p);backdrop-filter:blur(16px);background:linear-gradient(#0c0e122e,#0c0e12b8)}}@media print{[data-stalux-offscreen-code],[data-stalux-offscreen-svg]{content-visibility:visible!important;contain-intrinsic-block-size:none!important}}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}[data-stalux-home-content]{flex-direction:column;align-items:center;width:100%;display:flex}@keyframes stalux-page-exit{0%{opacity:1}to{opacity:1}}@keyframes stalux-page-enter{0%{opacity:.9}to{opacity:1}}@keyframes stalux-page-enter-back{0%{opacity:.96}to{opacity:1}}@keyframes stalux-taxonomy-enter{0%{opacity:.9}to{opacity:1}}@keyframes stalux-taxonomy-enter-back{0%{opacity:.96}to{opacity:1}}@keyframes stalux-article-enter{0%{opacity:.9}to{opacity:1}}@keyframes stalux-article-enter-back{0%{opacity:.96}to{opacity:1}}@keyframes stalux-sidebar-left-in{0%{opacity:.96}to{opacity:1}}@keyframes stalux-sidebar-left-out{0%{opacity:1}to{opacity:1}}@keyframes stalux-sidebar-left-back-in{0%{opacity:.96}to{opacity:1}}@keyframes stalux-sidebar-left-back-out{0%{opacity:1}to{opacity:1}}@keyframes stalux-sidebar-right-in{0%{opacity:.96}to{opacity:1}}@keyframes stalux-sidebar-right-out{0%{opacity:1}to{opacity:1}}@keyframes stalux-sidebar-right-back-in{0%{opacity:.96}to{opacity:1}}@keyframes stalux-sidebar-right-back-out{0%{opacity:1}to{opacity:1}}[data-stalux-scroll-sentinel]{visibility:hidden;pointer-events:none;width:1px;height:1px;position:absolute;top:240px;left:0}@media (prefers-reduced-motion:reduce){.stalux-main,.stalux-main *,.postLayout *{scroll-behavior:auto!important;transition-duration:1ms!important;animation-duration:1ms!important;animation-iteration-count:1!important}}
2
+ @layer components{.stalux-ai-prompt{clip-path:inset(50%);white-space:pre-wrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.stalux-badge-group{border:none}.stalux-badge-group-arrow{font-size:.65rem;transition:transform .2s;display:inline-block}.stalux-badge-group-summary{user-select:none;cursor:pointer;color:var(--white-70p);gap:.4rem;padding:.2rem 0;font-size:.85rem;list-style-type:none;transition:color .2s}.stalux-beian-public-security-beian{color:#ffffffb3;gap:5px;font-size:.9rem;text-decoration:none;transition:color .3s;display:inline-flex}.stalux-card-time{gap:.45rem;display:inline-flex}.stalux-copyright{color:var(--white-70p);gap:.3em;font-weight:500}.stalux-footer{backdrop-filter:blur(10px);color:var(--white-full);background-color:#0000001a;margin-top:auto;padding:1.5rem 0;font-size:.9rem}.stalux-footer-content{gap:.8rem;max-width:1200px;margin:0 auto;padding:0 1rem}.stalux-nav-list{transform:scale(var(--nav-scale,1));transform-origin:50%;box-sizing:border-box;gap:2rem;max-width:100%;transition:transform .22s cubic-bezier(.22,.72,.22,1);overflow:visible}.stalux-nav-overlay{pointer-events:none;z-index:999;opacity:0;background:#0009;height:100%;transition:opacity .3s;display:none;position:fixed;top:0;left:0}.stalux-nav-scroll-btn{background:var(--black-30p);backdrop-filter:blur(8px);box-shadow:var(--shadow-md);pointer-events:none;z-index:10;cursor:pointer;width:36px;height:36px;color:var(--white-full);opacity:0;border:none;border-radius:9999px;padding:0;transition:opacity .25s;display:none;position:absolute;top:50%;transform:translateY(-50%)}.stalux-nav-toggle{z-index:998;cursor:pointer;min-width:48px;min-height:48px;color:inherit;background:0 0;border:none;padding:.75rem;display:none}.stalux-stats-site-build-time{color:#fffc;margin-top:.5rem;font-size:.9rem}.stalux-stats-stats-separator{color:#ffffff80}.stalux-theme-info{color:var(--white-70p);gap:.3em;font-size:.85rem}.stalux-nav-container{box-sizing:border-box;max-width:100%;position:relative;overflow:hidden}.stalux-nav-item{text-shadow:var(--stalux-text-shadow);flex-shrink:0;margin-left:1em;margin-right:1em;font-size:1.3em}.stalux-page-description{color:var(--white-60p);margin-bottom:1.5em;font-size:1.2em}.stalux-page-title{text-shadow:var(--stalux-text-shadow);margin-top:1.5em;font-size:2.5em}.stalux-badge,.stalux-badges-wrapper .stalux-badge{width:auto}.stalux-u-min-w-0{min-width:0}.stalux-u-w-full{width:100%}.stalux-u-flex{display:flex}.stalux-u-flex-col{flex-direction:column}.stalux-u-flex-wrap{flex-wrap:wrap}.stalux-u-items-center{align-items:center}.stalux-u-justify-center{justify-content:center}.stalux-badges,.stalux-badges-wrapper{gap:.5rem}.stalux-beian-beian-info{gap:1rem}.stalux-stats-site-stats{gap:.5rem;font-size:.9rem}.stalux-nav-text{white-space:nowrap;color:var(--white-full)}.stalux-badge-group-items{padding-top:.35rem}.stalux-u-text-center{text-align:center}.stalux-badge-group-hint{color:var(--white-70p);font-size:.7rem}.stalux-badge-group-title{color:var(--white-80p)}nav{width:100%;min-width:0;max-width:100%}html{scroll-padding-top:var(--stalux-nav-offset,var(--stalux-site-header-height))}.stalux-site-header{z-index:990;width:100%;min-height:var(--stalux-site-header-min-height);isolation:isolate;justify-content:center;align-items:center;display:flex;position:sticky;top:0}.stalux-nav-scroll-btn[data-visible]{pointer-events:auto;opacity:1}.stalux-nav-scroll-btn[data-side=left]{left:4px}.stalux-nav-scroll-btn[data-side=right]{right:4px}.stalux-nav-scroll-btn svg{stroke:currentColor;stroke-width:2px;fill:none;width:20px;height:20px}.stalux-nav-link,.stalux-nav-link:visited{cursor:pointer;width:100%;color:inherit;min-height:44px;font:inherit;background:0 0;border:none;align-items:center;gap:.5rem;padding:.5rem .75rem;text-decoration:none;display:flex}.stalux-nav-link .nav-icon{stroke:var(--white-full)}.stalux-nav-toggle svg{width:32px;height:32px}.stalux-nav-overlay[data-state=show]{pointer-events:auto;opacity:1;display:block}#stalux-to-archive-archs{margin-top:2em}#stalux-date-date-time{text-shadow:var(--stalux-text-shadow);color:var(--white-full);flex-direction:column;align-items:center;margin-top:2em;display:flex}#stalux-date-date-time #stalux-date-date{min-height:1.25em;margin-bottom:.5em;font-size:2em;line-height:1.25}#stalux-date-date-time #stalux-date-time{font-variant-numeric:tabular-nums;min-height:1.25em;font-size:3em;line-height:1.25}.stalux-theme-info span,.stalux-copyright span{margin:0}.stalux-theme-info a{color:#fffc;margin:0 .2em;text-decoration:none;transition:color .3s}.stalux-beian-beian-info a{color:#ffffffb3;font-size:.9rem;text-decoration:none;transition:color .3s}.stalux-beian-public-security-beian img{width:15px;height:15px;display:inline-block}.stalux-badge-group-summary::-webkit-details-marker,.stalux-badge-group[open] .stalux-badge-group-hint[data-hint=collapsed],.stalux-badge-group:not([open]) .stalux-badge-group-hint[data-hint=expanded]{display:none}.stalux-badge-group[open] .stalux-badge-group-arrow{transform:rotate(90deg)}@media (hover:hover) and (pointer:fine){.stalux-nav-scroll-btn:hover{background:0 0}.stalux-nav-container:hover .stalux-nav-scroll-btn[data-visible]{opacity:1}.stalux-nav-link:hover .nav-icon,.stalux-nav-link:hover .stalux-nav-text{stroke:var(--stalux-accent-color);color:var(--stalux-accent-color)}.stalux-theme-info a:hover{color:#fff;text-decoration:none}.stalux-beian-beian-info a:hover,.stalux-beian-public-security-beian:hover{color:#ffffffe6;text-decoration:none}.stalux-badge-group-summary:hover{color:var(--white-70p)}}@media (width>=601px){.stalux-site-nav{isolation:isolate;border-radius:0 0 16px 16px;transition:background-color .18s}.stalux-site-nav[data-scrolled]{backdrop-filter:blur(20px)saturate(140%);box-shadow:0 1px 0 var(--white-10p), 0 8px 24px #0000001f;background:#181818c7}}@media (width<=1100px){.stalux-nav-list{gap:1rem}.stalux-nav-item{margin-left:.6em;margin-right:.6em;font-size:1em}}@media (width<=900px){.stalux-nav-item{margin-left:.25em;margin-right:.25em;font-size:.95em}.stalux-nav-list{gap:.5rem}}@media (width<=768px){.stalux-footer{padding:1.2rem 0;font-size:.8rem}.stalux-footer-content{gap:.6rem;padding:0 .8rem}.stalux-badges{gap:.3rem}.stalux-badge{width:auto}}@media (width<=600px){html{--stalux-site-header-min-height:4rem}.stalux-nav-toggle[data-state=open]{visibility:hidden;pointer-events:none}.stalux-nav-toggle[data-scrolled]{backdrop-filter:blur(20px)saturate(140%);box-shadow:0 1px 0 var(--white-10p), 0 8px 24px #0000001f;background:#181818c7;border-radius:12px}.stalux-nav-toggle{display:block;position:fixed;top:.75rem;left:.75rem}.stalux-nav-container{overflow:visible}nav{width:auto}.stalux-nav-list{pointer-events:none;z-index:1000;background:var(--black-20p);backdrop-filter:blur(20px);flex-direction:column;justify-content:flex-start;align-items:flex-start;gap:0;width:min(220px,100vw - 1rem);height:100vh;padding:.5rem 1rem 2rem;position:fixed;top:0;left:0;right:auto;overflow-y:auto;transform:translate(-100%)}.stalux-nav-list[data-state=open]{pointer-events:auto;transform:translate(0)}.stalux-nav-item{border-bottom:1px solid var(--white-10p);flex-shrink:0;width:100%;margin:0;font-size:.9em}.stalux-nav-text{display:inline}.stalux-nav-link{width:100%;min-height:44px;font-size:inherit;padding:.45rem .75rem}.stalux-nav-link .nav-icon{width:18px;height:18px}}@media (width<=480px){.stalux-footer{padding:1rem 0;font-size:.8rem}.stalux-footer-content{gap:.6rem;padding:0 .8rem}}.stalux-main,.stalux-post-page,.stalux-post-layout>*,.stalux-link-card-content,.stalux-word-list-item,.stalux-word-card{box-sizing:border-box;min-width:0;max-width:100%}.stalux-main{overflow-wrap:anywhere}.stalux-link-shell{min-width:0;max-width:100%;display:block}.stalux-link-card{box-sizing:border-box;width:100%;max-width:100%}.stalux-category-shell{width:100%;min-width:0}.stalux-author-figure>a{flex-shrink:0;display:inline-block}.stalux-author-figure img{display:block}.stalux-post-card-shell,.stalux-category-shell,.stalux-link-shell{position:relative}.stalux-post-card,.stalux-category-card,.stalux-link-card,.stalux-word-card{transition:transform .2s,background-color .2s,border-color .2s,box-shadow .2s}:is(.stalux-post-card-shell,.stalux-category-shell):focus-within>*,.stalux-link-shell:focus-visible>*{box-shadow:var(--card-box-shadow-hover)}:is(button,summary,[role=button]):focus-visible{outline:2px solid var(--stalux-accent-color);outline-offset:3px}@media (prefers-reduced-motion:reduce){.stalux-main *,.stalux-main :before,.stalux-main :after{transition-duration:0s!important;animation:none!important}.stalux-post-card,.stalux-category-card,.stalux-link-card,.stalux-link-card-content,.stalux-card-post-cover img,.stalux-category-icon,.stalux-author-figure img,.stalux-link-card-avatar img{transform:none!important}}@keyframes stalux-social-stalux-social-arrive{0%{opacity:0;transform:translateY(.75rem)rotate(-12deg)}to{opacity:1;transform:translateY(0)rotate(0)}}@keyframes stalux-random-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes stalux-link-avatar-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}}@layer utilities{.sr-only{clip:rect(0,0,0,0);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.visible{visibility:visible}.absolute{position:absolute}.static{position:static}.grid{display:grid}.block{display:block}.inline-block{display:inline-block}.hidden{display:none}.h-full{height:100%}.flex{display:flex}.flex-shrink{flex-shrink:1}.flex-wrap{flex-wrap:wrap}.transform{transform:translateX(var(--un-translate-x)) translateY(var(--un-translate-y)) translateZ(var(--un-translate-z)) rotate(var(--un-rotate)) rotateX(var(--un-rotate-x)) rotateY(var(--un-rotate-y)) rotateZ(var(--un-rotate-z)) skewX(var(--un-skew-x)) skewY(var(--un-skew-y)) scaleX(var(--un-scale-x)) scaleY(var(--un-scale-y)) scaleZ(var(--un-scale-z))}.b,.border{border-width:1px}.text-inherit{color:inherit}.no-underline{text-decoration:none}.outline{outline-style:solid}}@layer theme;@layer base{html,body{color:#fff;width:100%;height:100%;margin:0;& main{flex:1}scrollbar-color:#4a4a4a #2a2a2a;font-family:var(--font-body), "Noto Sans SC", "Noto Sans CJK SC", system-ui, -apple-system, sans-serif;text-rendering:optimizelegibility;line-height:1.25;display:block}body{height:auto;min-height:100%}html{scrollbar-gutter:stable;background-color:var(--stalux-bg-color,#202020)}html[data-clarity-id]{opacity:1!important}a{color:inherit;cursor:pointer;text-decoration-skip-ink:auto;background-color:#0000;text-decoration:none;transition:color .2s,text-shadow .2s;position:relative}.a-none{cursor:pointer;text-decoration-skip-ink:auto;background-color:#0000;color:inherit!important;text-decoration:none!important}.a-none:after{display:none!important}a:not(.a-none):not([data-stalux-card]):not(.stalux-nav-link):after{content:"";background:linear-gradient(90deg, var(--stalux-accent-color), var(--accent-50p));transform-origin:0;pointer-events:none;width:100%;height:1px;transition:transform .25s cubic-bezier(.25,.9,.2,1);position:absolute;bottom:-2px;left:0;transform:scaleX(0)}a:not(.a-none):not([data-stalux-card]):not(.stalux-nav-link):focus-visible:after,a:not(.a-none):not([data-stalux-card]):not(.stalux-nav-link):active:after{transform:scaleX(1)}@media (hover:hover) and (pointer:fine){a:not(.a-none):not([data-stalux-card]):not(.stalux-nav-link):hover:after{transform:scaleX(1)}}a:active,a:focus-visible{text-decoration:none}@media (hover:hover) and (pointer:fine){a:hover{text-decoration:none}}a:focus{outline:none}a:focus-visible{outline:2px solid var(--stalux-accent-color);outline-offset:2px}ul{margin:0;padding:0;list-style:none}.none{display:none}.stalux-root{color:#fff;min-height:100vh}.stalux-main{min-height:calc(100vh - var(--stalux-site-header-height,3rem))}:root{--stalux-bg-color:#202020;--stalux-bg-filter:none;--stalux-site-header-min-height:3.75rem;--stalux-site-header-height:var(--stalux-site-header-min-height);--stalux-text-shadow:var(--stalux-accent-color) .08rem .08rem .18rem;--stalux-accent-color:#eab308;--stalux-accent-rgb:234 179 8;--surface-glass:var(--black-05p);--surface-glass-shadow:var(--shadow-sidebar);--card-bg:var(--surface-glass);--card-border:#ffffff1a;--card-box-shadow:0 10px 24px #00000014;--card-box-shadow-hover:0 14px 28px #0000001f;--tag-bg:#ffffff1f;--tag-bg-hover:#ffffff2e;--category-bg:#ffffff14;--category-bg-hover:#ffffff24;--date-bg:#42a0ff2e;--date-border:#42a0ff40;--updated-bg:#ffc94733;--updated-border:#ffc9474d;--white-full:#fff;--white-95p:#fffffff2;--white-90p:#ffffffe6;--white-85p:#ffffffd9;--white-80p:#ffffffe6;--white-78p:#ffffffc7;--white-75p:#ffffffbf;--white-70p:#ffffffdb;--white-60p:#fff9;--white-50p:#ffffff80;--white-30p:#ffffff4d;--white-20p:#fff3;--white-15p:#ffffff26;--white-10p:#ffffff1a;--white-05p:#ffffff0d;--black-30p:#0000004d;--black-20p:#0003;--black-15p:#00000026;--black-10p:#0000001a;--black-05p:#0000000d;--accent-90p:rgb(var(--stalux-accent-rgb) / .9);--accent-85p:rgb(var(--stalux-accent-rgb) / .85);--accent-80p:rgb(var(--stalux-accent-rgb) / .8);--accent-70p:rgb(var(--stalux-accent-rgb) / .7);--accent-60p:rgb(var(--stalux-accent-rgb) / .6);--accent-50p:rgb(var(--stalux-accent-rgb) / .5);--accent-40p:rgb(var(--stalux-accent-rgb) / .4);--accent-30p:rgb(var(--stalux-accent-rgb) / .3);--accent-20p:rgb(var(--stalux-accent-rgb) / .2);--transition-fast:.18s ease;--transition-medium:.2s ease;--transition-normal:.25s ease;--transition-slow:.3s ease;--transition-slower:.5s ease;--transition-slowest:.6s ease;--easing-bounce:cubic-bezier(.175, .885, .32, 1.275);--space-2xs:.25rem;--space-xs:.75rem;--space-sm:.5rem;--space-md:1rem;--space-lg:1.5rem;--space-xl:2rem;--space-2xl:3rem;--space-3xl:4rem;--radius-sm:4px;--radius-md:6px;--radius-lg:8px;--radius-full:9999px;--shadow-sm:0 2px 5px #0000001a;--shadow-md:0 6px 16px #0003;--shadow-lg:0 8px 20px #0000004d;--shadow-xl:0 12px 26px #00000047;--shadow-sidebar:0 16px 20px -12px #000000d6, 10px 4px 16px -12px #00000094, -10px 4px 16px -12px #00000094;--shadow-raised-hover:0 20px 24px -13px #000000e6, 12px 5px 18px -13px #000000ad, -12px 5px 18px -13px #000000ad;--shadow-dark:#000000c0;--muted-text:#bbb;--font-body:"Noto Sans SC", "Noto Sans CJK SC", system-ui, sans-serif;--font-size-subtitle:1.35rem;--font-size-base:1.1rem;--font-size-small:.95rem;--font-size-smaller:.9rem;--font-size-tiny:.85rem;--border-thin:1px;--border-medium:2px;--border-thick:3px}::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-track{background:#2a2a2a;border-radius:4px}::-webkit-scrollbar-thumb{background:#4a4a4a;border-radius:4px;transition:background .3s ease-out}@media (hover:hover) and (pointer:fine){::-webkit-scrollbar-thumb:hover{background:#5a5a5a}}::-webkit-scrollbar-corner{background:#2a2a2a}.bg-layer{z-index:-10;background-position:50%;background-repeat:repeat;background-size:auto;background-color:var(--stalux-bg-color,transparent);filter:var(--stalux-bg-filter,none);pointer-events:none;opacity:0;forced-color-adjust:none;color-scheme:light only;transition:opacity .2s ease-out;position:fixed;inset:0}@media (prefers-reduced-motion:reduce){.bg-layer{transition-duration:0s}}footer{padding:var(--space-lg) var(--space-md);text-align:center;color:var(--muted-text);border-top:1px solid var(--white-10p);backdrop-filter:blur(16px);background:linear-gradient(#0c0e122e,#0c0e12b8)}}@media print{[data-stalux-offscreen-code],[data-stalux-offscreen-svg]{content-visibility:visible!important;contain-intrinsic-block-size:none!important}}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}[data-stalux-home-content]{flex-direction:column;align-items:center;width:100%;display:flex}@keyframes stalux-page-exit{0%{opacity:1}to{opacity:1}}@keyframes stalux-page-enter{0%{opacity:.9}to{opacity:1}}@keyframes stalux-page-enter-back{0%{opacity:.96}to{opacity:1}}@keyframes stalux-taxonomy-enter{0%{opacity:.9}to{opacity:1}}@keyframes stalux-taxonomy-enter-back{0%{opacity:.96}to{opacity:1}}@keyframes stalux-article-enter{0%{opacity:.9}to{opacity:1}}@keyframes stalux-article-enter-back{0%{opacity:.96}to{opacity:1}}@keyframes stalux-sidebar-left-in{0%{opacity:.96}to{opacity:1}}@keyframes stalux-sidebar-left-out{0%{opacity:1}to{opacity:1}}@keyframes stalux-sidebar-left-back-in{0%{opacity:.96}to{opacity:1}}@keyframes stalux-sidebar-left-back-out{0%{opacity:1}to{opacity:1}}@keyframes stalux-sidebar-right-in{0%{opacity:.96}to{opacity:1}}@keyframes stalux-sidebar-right-out{0%{opacity:1}to{opacity:1}}@keyframes stalux-sidebar-right-back-in{0%{opacity:.96}to{opacity:1}}@keyframes stalux-sidebar-right-back-out{0%{opacity:1}to{opacity:1}}[data-stalux-scroll-sentinel]{visibility:hidden;pointer-events:none;width:1px;height:1px;position:absolute;top:240px;left:0}@media (prefers-reduced-motion:reduce){.stalux-main,.stalux-main *,.postLayout *{scroll-behavior:auto!important;transition-duration:1ms!important;animation-duration:1ms!important;animation-iteration-count:1!important}}
3
3
  /*$vite$:1*/
@@ -1,3 +1,4 @@
1
+ import { createHash } from "node:crypto";
1
2
  import type { AstroRuntimeLogger } from "astro";
2
3
  /**
3
4
  * 徽章生成器工具
@@ -56,13 +57,40 @@ export function generateBadge(options: BadgeOptions, logger?: AstroRuntimeLogger
56
57
  }
57
58
  }
58
59
 
59
- /**
60
- * 将SVG字符串转为Data URL
61
- * @param svg SVG字符串
62
- * @returns data URL
63
- */
60
+ /** Content-addressed assets are shared by all pages and remain lazy inside details. */
61
+ export function badgeAssetId(svg: string): string {
62
+ return createHash("sha256").update(svg).digest("hex").slice(0, 24);
63
+ }
64
+
65
+ export function normalizeBadgeStyle(style: string | undefined): BadgeOptions["style"] {
66
+ return style && ["flat", "plastic", "flat-square", "for-the-badge", "social"].includes(style)
67
+ ? (style as BadgeOptions["style"])
68
+ : "flat";
69
+ }
70
+
71
+ /** Keep Data URLs available for custom component badges outside footer.yml. */
64
72
  export function svgToDataUrl(svg: string): string {
65
73
  if (!svg) return "";
66
74
  const encoded = encodeURIComponent(svg).replaceAll("'", "%27").replaceAll('"', "%22");
67
75
  return `data:image/svg+xml,${encoded}`;
68
76
  }
77
+
78
+ type BadgeInput = Omit<BadgeOptions, "style"> & { style?: string };
79
+ type BadgeConfig = BadgeInput | { title: string; items: BadgeInput[] };
80
+ const assetCache = new WeakMap<readonly BadgeConfig[], Map<string, string>>();
81
+
82
+ /** Use identical normalization in the component and prerendered asset route. */
83
+ export function createBadgeAssets(items: readonly BadgeConfig[] | undefined): Map<string, string> {
84
+ if (!items) return new Map();
85
+ const cached = assetCache.get(items);
86
+ if (cached) return cached;
87
+ const assets = new Map<string, string>();
88
+ for (const item of items) {
89
+ for (const badge of "items" in item ? item.items : [item]) {
90
+ const svg = generateBadge({ ...badge, style: normalizeBadgeStyle(badge.style) });
91
+ assets.set(badgeAssetId(svg), svg);
92
+ }
93
+ }
94
+ assetCache.set(items, assets);
95
+ return assets;
96
+ }
@@ -16,6 +16,10 @@ export const ROUTE_DEFINITIONS: readonly RouteDefinition[] = [
16
16
  { pattern: "/tags/[tag]", source: "./pages/tags/[tag].astro" },
17
17
  { pattern: "/categories/", source: "./pages/categories/index.astro" },
18
18
  { pattern: "/categories/[category]", source: "./pages/categories/[category].astro" },
19
+ {
20
+ pattern: "/stalux-assets/badges/[id].svg",
21
+ source: "./pages/stalux-assets/badges/[id].svg.ts",
22
+ },
19
23
  { pattern: "/og/[image].[format]", source: "./pages/og/[image].[format].ts" },
20
24
  { pattern: "/rss.xml", source: "./pages/rss.xml.ts" },
21
25
  { pattern: "/atom.xml", source: "./pages/atom.xml.ts" },