@xingwangzhe/stalux 1.47.1 → 1.49.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.
- package/README.md +7 -2
- package/package.json +1 -1
- package/public/background/pattern-1.min.dark.webp +0 -0
- package/public/background/pattern-10.min.dark.webp +0 -0
- package/public/background/pattern-11.min.dark.webp +0 -0
- package/public/background/pattern-12.min.dark.webp +0 -0
- package/public/background/pattern-13.min.dark.webp +0 -0
- package/public/background/pattern-14.min.dark.webp +0 -0
- package/public/background/pattern-15.min.dark.webp +0 -0
- package/public/background/pattern-16.min.dark.webp +0 -0
- package/public/background/pattern-17.min.dark.webp +0 -0
- package/public/background/pattern-18.min.dark.webp +0 -0
- package/public/background/pattern-19.min.dark.webp +0 -0
- package/public/background/pattern-2.min.dark.webp +0 -0
- package/public/background/pattern-20.min.dark.webp +0 -0
- package/public/background/pattern-21.min.dark.webp +0 -0
- package/public/background/pattern-22.min.dark.webp +0 -0
- package/public/background/pattern-23.min.dark.webp +0 -0
- package/public/background/pattern-24.min.dark.webp +0 -0
- package/public/background/pattern-25.min.dark.webp +0 -0
- package/public/background/pattern-26.min.dark.webp +0 -0
- package/public/background/pattern-27.min.dark.webp +0 -0
- package/public/background/pattern-28.min.dark.webp +0 -0
- package/public/background/pattern-29.min.dark.webp +0 -0
- package/public/background/pattern-3.min.dark.webp +0 -0
- package/public/background/pattern-30.min.dark.webp +0 -0
- package/public/background/pattern-31.min.dark.webp +0 -0
- package/public/background/pattern-32.min.dark.webp +0 -0
- package/public/background/pattern-33.min.dark.webp +0 -0
- package/public/background/pattern-34.min.dark.webp +0 -0
- package/public/background/pattern-35.min.dark.webp +0 -0
- package/public/background/pattern-36.min.dark.webp +0 -0
- package/public/background/pattern-37.min.dark.webp +0 -0
- package/public/background/pattern-38.min.dark.webp +0 -0
- package/public/background/pattern-39.min.dark.webp +0 -0
- package/public/background/pattern-4.min.dark.webp +0 -0
- package/public/background/pattern-40.min.dark.webp +0 -0
- package/public/background/pattern-41.min.dark.webp +0 -0
- package/public/background/pattern-42.min.dark.webp +0 -0
- package/public/background/pattern-5.min.dark.webp +0 -0
- package/public/background/pattern-6.min.dark.webp +0 -0
- package/public/background/pattern-7.min.dark.webp +0 -0
- package/public/background/pattern-8.min.dark.webp +0 -0
- package/public/background/pattern-9.min.dark.webp +0 -0
- package/src/components/stalux/common/Weather.astro +29 -2
- package/src/components/stalux/common/author.astro +1 -0
- package/src/components/stalux/common/date.astro +4 -0
- package/src/components/stalux/footer/FooterBadges.astro +14 -3
- package/src/components/stalux/layout/footer.astro +1 -12
- package/src/components/stalux/layout/head.astro +1 -1
- package/src/components/stalux/links/linkCard.astro +5 -1
- package/src/components/stalux/links/linkList.astro +2 -0
- package/src/components/stalux/links/socialMedia.astro +1 -0
- package/src/components/stalux/posts/postCard.astro +1 -0
- package/src/components/stalux/posts/postContent.astro +2 -0
- package/src/index.ts +3 -0
- package/src/layouts/Stalux.astro +0 -1
- package/src/pages/404.astro +1 -0
- package/src/pages/index.astro +1 -0
- package/src/pages/stalux-assets/badges/[id].svg.ts +20 -0
- package/src/plugins/image-dimensions.ts +34 -0
- package/src/scripts/analytics-runtime.ts +103 -4
- package/src/scripts/background.ts +10 -3
- package/src/scripts/core-runtime.ts +0 -1
- package/src/scripts/link-icons.ts +54 -0
- package/src/scripts/photoswipe.ts +4 -3
- package/src/scripts/random-posts.ts +27 -1
- package/src/scripts/search-dialog.ts +1 -0
- package/src/scripts/swup-router.ts +2 -0
- package/src/styles/generated-author.css +3 -0
- package/src/styles/generated-cards.css +3 -0
- package/src/styles/generated-home.css +3 -0
- package/src/styles/generated-links.css +1 -1
- package/src/styles/generated-not-found.css +3 -0
- package/src/styles/generated-social.css +3 -0
- package/src/styles/generated.css +1 -1
- package/src/utils/badge-generator.ts +33 -5
- package/src/utils/route-catalog.ts +4 -0
package/README.md
CHANGED
|
@@ -14,7 +14,9 @@ All HTML routes include a circular back-to-top button in the footer. It appears
|
|
|
14
14
|
|
|
15
15
|
The homepage typewriter is built into Stalux and continues to use the `items` string list in `stalux/config/typetexts.yml`, with no new configuration. Defaults are 100ms per typed grapheme, 33ms per deleted grapheme, a 1500ms hold, and a 500ms pause after deletion. It pauses outside the viewport or in background tabs and cleans up on soft navigation. Reduced motion displays whole messages without a blinking cursor. Without JavaScript, the first message remains visible; screen readers and print receive the complete list.
|
|
16
16
|
|
|
17
|
-
Standalone images written as `` receive a `figure` and `figcaption` through a build-time satteri HAST plugin. Captions appear as small, centered gray text below the image, preserving image alt text and the PhotoSwipe lightbox. No configuration or browser script is required. Empty descriptions, inline images, multiple images in one paragraph, and existing figures are left unchanged. Captions are plain text with automatic escaping.
|
|
17
|
+
Standalone images written as `` receive a `figure` and `figcaption` through a build-time satteri HAST plugin. Captions appear as small, centered gray text below the image, preserving image alt text and the PhotoSwipe lightbox. No configuration or browser script is required. Empty descriptions, inline images, multiple images in one paragraph, and existing figures are left unchanged. Captions are plain text with automatic escaping. External images can declare intrinsic size in the markdown title: ``. The build turns it into `width`/`height`, removes the tooltip title, and gives PhotoSwipe matching `data-pswp-width/height`; images without a size declaration keep their previous output.
|
|
18
|
+
|
|
19
|
+
Friend-link icons are requested only when they approach the viewport (400px prefetch margin), instead of the browser's large native lazy window pulling every third-party avatar on the page. A failed icon keeps a placeholder disc and never affects the text content. The Google Analytics SDK loads after the first screen settles (first input, 600ms of stable LCP, or six seconds after parsing), while `page_view` snapshots and the dataLayer queue are still written during navigation without waiting for the SDK. The random-posts sidebar likewise requests its index only near the viewport.
|
|
18
20
|
|
|
19
21
|
Code blocks default to the single `dark-plus` theme, with system color-scheme switching and theme selectors disabled. To opt into another theme or switching behavior, explicitly override `themes`, `useDarkModeMediaQuery`, and `themeCssSelector` through `expressiveCode`. This only changes generated code styles and adds no telemetry.
|
|
20
22
|
|
|
@@ -138,6 +140,9 @@ Processed pages are cached under `node_modules/.astro/stalux-page-output/`. The
|
|
|
138
140
|
|
|
139
141
|
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
142
|
|
|
143
|
+
|
|
144
|
+
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.
|
|
145
|
+
|
|
141
146
|
### Modern JavaScript
|
|
142
147
|
|
|
143
148
|
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 +386,4 @@ Local covers are read from the final `publicDir`. Remote covers are requested by
|
|
|
381
386
|
|
|
382
387
|
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
388
|
|
|
384
|
-
Built-in
|
|
389
|
+
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
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -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
|
-
|
|
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,9 +1,16 @@
|
|
|
1
1
|
---
|
|
2
2
|
import { getCollection } from "astro:content";
|
|
3
3
|
import type { BadgeItem, BadgeOptions } from "@utils/badge-generator";
|
|
4
|
-
import {
|
|
5
|
-
|
|
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
|
|
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
|
|
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="
|
|
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 />}
|
|
@@ -39,9 +39,13 @@ const icon = link.icon ?? link.avatar ?? "/favicon.ico";
|
|
|
39
39
|
<div class="stalux-link-card">
|
|
40
40
|
<div class="stalux-link-card-avatar">
|
|
41
41
|
<img
|
|
42
|
-
src=
|
|
42
|
+
src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
|
|
43
|
+
data-src={icon}
|
|
44
|
+
data-stalux-link-icon
|
|
43
45
|
alt={t("links.iconAlt", { name: title })}
|
|
44
46
|
loading="lazy"
|
|
47
|
+
decoding="async"
|
|
48
|
+
fetchpriority="low"
|
|
45
49
|
width="80"
|
|
46
50
|
height="80"
|
|
47
51
|
>
|
|
@@ -128,6 +128,7 @@ const mdSourceUrl = exportMd ? `${Astro.url.pathname.replace(/\/$/, "")}.md` : "
|
|
|
128
128
|
<!-- Article Body -->
|
|
129
129
|
<section
|
|
130
130
|
class="stalux-post-body stalux-prose"
|
|
131
|
+
data-stalux-gallery-body
|
|
131
132
|
data-stalux-motion-content
|
|
132
133
|
data-pagefind-body
|
|
133
134
|
data-stalux-post-id={props.postId === undefined ? undefined : String(props.postId)}
|
|
@@ -138,6 +139,7 @@ const mdSourceUrl = exportMd ? `${Astro.url.pathname.replace(/\/$/, "")}.md` : "
|
|
|
138
139
|
</article>
|
|
139
140
|
|
|
140
141
|
<script>
|
|
142
|
+
import "../../../scripts/module-motion";
|
|
141
143
|
import "../../../scripts/photoswipe";
|
|
142
144
|
import { mountCodeAccessibility } from "../../../scripts/code-accessibility";
|
|
143
145
|
import { registerPageLifecycle } from "../../../scripts/page-runtime";
|
package/src/index.ts
CHANGED
|
@@ -64,6 +64,7 @@ import { createViteAliases } from "./internal/vite-aliases";
|
|
|
64
64
|
import { webMcpMutationsPlugin } from "./internal/webmcp-mutations";
|
|
65
65
|
import { featureFlagsHast, featureFlagsMdast } from "./plugins/feature-flags";
|
|
66
66
|
import { imageCaptions } from "./plugins/image-captions";
|
|
67
|
+
import { imageDimensions } from "./plugins/image-dimensions";
|
|
67
68
|
import { temml } from "./plugins/satteri-temml";
|
|
68
69
|
import { describeError } from "./utils/diagnostics";
|
|
69
70
|
|
|
@@ -293,6 +294,8 @@ export function stalux(options: StaluxOptions = {}): AstroIntegration[] {
|
|
|
293
294
|
}),
|
|
294
295
|
seen,
|
|
295
296
|
);
|
|
297
|
+
// Dimensions must land before PhotoSwipe copies them onto the link.
|
|
298
|
+
appendUniquePlugin(processorOptions.hastPlugins, imageDimensions, seen);
|
|
296
299
|
appendUniquePlugin(processorOptions.hastPlugins, photoswipe(), seen);
|
|
297
300
|
appendUniquePlugin(processorOptions.hastPlugins, imageCaptions, seen);
|
|
298
301
|
appendUniquePlugin(processorOptions.hastPlugins, featureFlagsHast, seen);
|
package/src/layouts/Stalux.astro
CHANGED
|
@@ -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
|
package/src/pages/404.astro
CHANGED
package/src/pages/index.astro
CHANGED
|
@@ -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
|
+
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { defineHastPlugin } from "satteri";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Markdown 图片标题里的 `宽x高` 是外部图片的尺寸声明,不是给读者看的提示。
|
|
5
|
+
*
|
|
6
|
+
* 外部图片无法在构建期读取像素尺寸,浏览器只能等下载完才知道比例,正文会被
|
|
7
|
+
* 推开(CLS)。写成 `` 后,这里在 HAST 阶段补上
|
|
8
|
+
* width/height,PhotoSwipe 也能拿到 data-pswp-width/height;标题本身随即移除。
|
|
9
|
+
*/
|
|
10
|
+
const DIMENSION_TITLE = /^(\d{1,6})\s*[x×]\s*(\d{1,6})$/u;
|
|
11
|
+
|
|
12
|
+
export const imageDimensions = defineHastPlugin({
|
|
13
|
+
name: "stalux-image-dimensions",
|
|
14
|
+
element: {
|
|
15
|
+
filter: ["img"],
|
|
16
|
+
visit(node, ctx) {
|
|
17
|
+
const title = node.properties?.title;
|
|
18
|
+
if (typeof title !== "string") return;
|
|
19
|
+
const match = DIMENSION_TITLE.exec(title.trim());
|
|
20
|
+
if (!match) return;
|
|
21
|
+
const width = Number(match[1]);
|
|
22
|
+
const height = Number(match[2]);
|
|
23
|
+
if (!(width > 0 && height > 0)) return;
|
|
24
|
+
if (node.properties?.width === undefined) {
|
|
25
|
+
ctx.setProperty(node, "width", String(width));
|
|
26
|
+
}
|
|
27
|
+
if (node.properties?.height === undefined) {
|
|
28
|
+
ctx.setProperty(node, "height", String(height));
|
|
29
|
+
}
|
|
30
|
+
// 尺寸声明已转成属性,不再让浏览器把它当成悬浮提示。
|
|
31
|
+
ctx.setProperty(node, "title", undefined);
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
});
|
|
@@ -202,6 +202,105 @@ function initializeClarity(id: string): void {
|
|
|
202
202
|
});
|
|
203
203
|
}
|
|
204
204
|
|
|
205
|
+
/**
|
|
206
|
+
* GA's SDK is 195 KB compressed / ~610 KB parsed, larger than every first-party
|
|
207
|
+
* asset combined. The dataLayer queue and the page_view snapshot do not need it:
|
|
208
|
+
* events are pushed immediately and consumed when the SDK finally arrives.
|
|
209
|
+
* Loading is gated on the same signals that mean "first paint is done" instead
|
|
210
|
+
* of `window.load`, which slow third-party resources can postpone forever.
|
|
211
|
+
*/
|
|
212
|
+
const GOOGLE_SDK_FLOOR_MS = 1200;
|
|
213
|
+
const GOOGLE_SDK_LCP_QUIET_MS = 600;
|
|
214
|
+
const GOOGLE_SDK_CEILING_MS = 6000;
|
|
215
|
+
let googleSdkStarted = false;
|
|
216
|
+
let googleGateInstalled = false;
|
|
217
|
+
let googleGateOpen = false;
|
|
218
|
+
|
|
219
|
+
function runBackgroundTask(callback: () => void): void {
|
|
220
|
+
const scheduler = (
|
|
221
|
+
window as Window & {
|
|
222
|
+
scheduler?: {
|
|
223
|
+
postTask: (
|
|
224
|
+
task: () => void,
|
|
225
|
+
options: { priority: "background" },
|
|
226
|
+
) => Promise<unknown>;
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
).scheduler;
|
|
230
|
+
if (scheduler?.postTask) {
|
|
231
|
+
void scheduler
|
|
232
|
+
.postTask(callback, { priority: "background" })
|
|
233
|
+
.catch(() => setTimeout(callback, 0));
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
setTimeout(callback, 0);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function startGoogleSdk(): void {
|
|
240
|
+
if (googleSdkStarted || !state.googleId) return;
|
|
241
|
+
googleSdkStarted = true;
|
|
242
|
+
void loadTrackerScript(
|
|
243
|
+
`https://www.googletagmanager.com/gtag/js?id=${encodeURIComponent(state.googleId)}`,
|
|
244
|
+
{ "data-stalux-google": "true" },
|
|
245
|
+
).catch(() => logger.debug("Google SDK unavailable; queued events retained"));
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/** Three independent doors: first input, LCP quiet, and a hard ceiling after parsing. */
|
|
249
|
+
function installGoogleGate(): void {
|
|
250
|
+
if (googleGateInstalled) return;
|
|
251
|
+
googleGateInstalled = true;
|
|
252
|
+
const startedAt = performance.now();
|
|
253
|
+
const floorAt = startedAt + GOOGLE_SDK_FLOOR_MS;
|
|
254
|
+
const ceilingAt = startedAt + GOOGLE_SDK_CEILING_MS;
|
|
255
|
+
let quietTimer: ReturnType<typeof setTimeout> | undefined;
|
|
256
|
+
let ceilingTimer: ReturnType<typeof setTimeout> | undefined;
|
|
257
|
+
let observer: PerformanceObserver | undefined;
|
|
258
|
+
|
|
259
|
+
const cleanup = () => {
|
|
260
|
+
for (const type of ["pointerdown", "keydown", "wheel", "touchstart"]) {
|
|
261
|
+
window.removeEventListener(type, handleInteraction);
|
|
262
|
+
}
|
|
263
|
+
if (quietTimer !== undefined) clearTimeout(quietTimer);
|
|
264
|
+
if (ceilingTimer !== undefined) clearTimeout(ceilingTimer);
|
|
265
|
+
observer?.disconnect();
|
|
266
|
+
observer = undefined;
|
|
267
|
+
};
|
|
268
|
+
const open = () => {
|
|
269
|
+
if (googleGateOpen) return;
|
|
270
|
+
googleGateOpen = true;
|
|
271
|
+
cleanup();
|
|
272
|
+
// Never compete with the input that just opened the gate.
|
|
273
|
+
runBackgroundTask(startGoogleSdk);
|
|
274
|
+
};
|
|
275
|
+
function handleInteraction(): void {
|
|
276
|
+
open();
|
|
277
|
+
}
|
|
278
|
+
const scheduleQuiet = () => {
|
|
279
|
+
if (googleGateOpen) return;
|
|
280
|
+
if (quietTimer !== undefined) clearTimeout(quietTimer);
|
|
281
|
+
const wait = Math.max(GOOGLE_SDK_LCP_QUIET_MS, floorAt - performance.now());
|
|
282
|
+
quietTimer = setTimeout(() => {
|
|
283
|
+
quietTimer = undefined;
|
|
284
|
+
if (performance.now() >= floorAt) open();
|
|
285
|
+
else scheduleQuiet();
|
|
286
|
+
}, wait);
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
if ("PerformanceObserver" in window) {
|
|
290
|
+
try {
|
|
291
|
+
observer = new window.PerformanceObserver(scheduleQuiet);
|
|
292
|
+
observer.observe({ type: "largest-contentful-paint", buffered: true });
|
|
293
|
+
} catch {
|
|
294
|
+
// Older engines may know the constructor but not this entry type.
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
for (const type of ["pointerdown", "keydown", "wheel", "touchstart"]) {
|
|
298
|
+
window.addEventListener(type, handleInteraction, { passive: true, once: true });
|
|
299
|
+
}
|
|
300
|
+
ceilingTimer = setTimeout(open, Math.max(0, ceilingAt - startedAt));
|
|
301
|
+
if (document.hidden) open();
|
|
302
|
+
}
|
|
303
|
+
|
|
205
304
|
function initializeTrackers(): void {
|
|
206
305
|
const config = document.body?.dataset;
|
|
207
306
|
if (!config) return;
|
|
@@ -218,10 +317,10 @@ function initializeTrackers(): void {
|
|
|
218
317
|
host.gtag("js", new Date());
|
|
219
318
|
host.gtag("config", state.googleId, { send_page_view: false });
|
|
220
319
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
320
|
+
installGoogleGate();
|
|
321
|
+
// A navigation can expose the measurement ID after the first document
|
|
322
|
+
// already opened its gate; in that case load immediately.
|
|
323
|
+
if (googleGateOpen) startGoogleSdk();
|
|
225
324
|
}
|
|
226
325
|
if (config.staluxClarityId) initializeClarity(config.staluxClarityId);
|
|
227
326
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* 每个完整文档只随机选择一次的会话背景。
|
|
3
3
|
*
|
|
4
4
|
* SSR 保持确定的深色底和原有双层 DOM,不内联背景 URL。文档解析完成即
|
|
5
|
-
*
|
|
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
|
-
|
|
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";
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Link-page icons come from arbitrary third-party hosts. Native lazy loading
|
|
3
|
+
* still fetches everything within the browser's large lazy threshold (up to
|
|
4
|
+
* 3000px), and a single link list therefore pulled several megabytes of
|
|
5
|
+
* avatars that the reader never reached. Load only icons near the viewport.
|
|
6
|
+
*/
|
|
7
|
+
import { createClientLogger } from "./logger";
|
|
8
|
+
import { registerPageLifecycle } from "./page-runtime";
|
|
9
|
+
|
|
10
|
+
const logger = createClientLogger("link-icons");
|
|
11
|
+
|
|
12
|
+
function reveal(image: HTMLImageElement): void {
|
|
13
|
+
const source = image.dataset.src;
|
|
14
|
+
if (!source) return;
|
|
15
|
+
delete image.dataset.src;
|
|
16
|
+
image.addEventListener(
|
|
17
|
+
"error",
|
|
18
|
+
() => {
|
|
19
|
+
// Keep the reserved box; the stylesheet draws a neutral disc instead.
|
|
20
|
+
image.removeAttribute("src");
|
|
21
|
+
image.dataset.staluxLinkIconFailed = "true";
|
|
22
|
+
logger.debug("link icon failed to load; placeholder retained");
|
|
23
|
+
},
|
|
24
|
+
{ once: true },
|
|
25
|
+
);
|
|
26
|
+
image.src = source;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function mountLinkIcons(): (() => void) | undefined {
|
|
30
|
+
const images = Array.from(
|
|
31
|
+
document.querySelectorAll<HTMLImageElement>("img[data-stalux-link-icon]"),
|
|
32
|
+
);
|
|
33
|
+
if (!images.length) return;
|
|
34
|
+
|
|
35
|
+
if (!("IntersectionObserver" in window)) {
|
|
36
|
+
for (const image of images) reveal(image);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const observer = new IntersectionObserver(
|
|
41
|
+
(entries) => {
|
|
42
|
+
for (const entry of entries) {
|
|
43
|
+
if (!entry.isIntersecting) continue;
|
|
44
|
+
observer.unobserve(entry.target);
|
|
45
|
+
reveal(entry.target as HTMLImageElement);
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
{ rootMargin: "400px 0px" },
|
|
49
|
+
);
|
|
50
|
+
for (const image of images) observer.observe(image);
|
|
51
|
+
return () => observer.disconnect();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
registerPageLifecycle("link-icons", mountLinkIcons);
|
|
@@ -6,6 +6,9 @@ import { createRetryableInitializer } from "./retryable-initializer";
|
|
|
6
6
|
const logger = createClientLogger("photoswipe");
|
|
7
7
|
|
|
8
8
|
const GALLERY_SELECTOR = "a.pswp-gallery-item";
|
|
9
|
+
// The article header, summary and keyword span also carry data-pagefind-body.
|
|
10
|
+
// Selecting the first of those gave PhotoSwipe an empty gallery (counter "1 / 0").
|
|
11
|
+
const GALLERY_CONTAINER_SELECTOR = "[data-stalux-gallery='true'] [data-stalux-gallery-body]";
|
|
9
12
|
|
|
10
13
|
async function enrichPhotoSwipeData(container: Element, signal: AbortSignal): Promise<void> {
|
|
11
14
|
const links = container.querySelectorAll<HTMLAnchorElement>(GALLERY_SELECTOR);
|
|
@@ -40,9 +43,7 @@ async function enrichPhotoSwipeData(container: Element, signal: AbortSignal): Pr
|
|
|
40
43
|
}
|
|
41
44
|
|
|
42
45
|
registerPageLifecycle("photoswipe", () => {
|
|
43
|
-
const container = document.querySelector<HTMLElement>(
|
|
44
|
-
"[data-stalux-gallery='true'] [data-pagefind-body]",
|
|
45
|
-
);
|
|
46
|
+
const container = document.querySelector<HTMLElement>(GALLERY_CONTAINER_SELECTOR);
|
|
46
47
|
if (!container) return;
|
|
47
48
|
|
|
48
49
|
const controller = new AbortController();
|
|
@@ -106,21 +106,47 @@ export function mountRandomPosts(): (() => void) | undefined {
|
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
108
|
};
|
|
109
|
+
let started = false;
|
|
110
|
+
let observer: IntersectionObserver | undefined;
|
|
111
|
+
const start = () => {
|
|
112
|
+
if (started || disposed) return;
|
|
113
|
+
started = true;
|
|
114
|
+
observer?.disconnect();
|
|
115
|
+
observer = undefined;
|
|
116
|
+
void refresh();
|
|
117
|
+
};
|
|
109
118
|
container.querySelector("#refresh-random-posts")?.addEventListener(
|
|
110
119
|
"click",
|
|
111
120
|
(event) => {
|
|
112
121
|
event.preventDefault();
|
|
122
|
+
if (!started) {
|
|
123
|
+
start();
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
113
126
|
void refresh();
|
|
114
127
|
},
|
|
115
128
|
{ signal: controller.signal },
|
|
116
129
|
);
|
|
117
130
|
reducedMotion.addEventListener("change", cancelAnimation, { signal: controller.signal });
|
|
118
|
-
|
|
131
|
+
if ("IntersectionObserver" in window) {
|
|
132
|
+
// The sidebar sits below the article on phones; do not fetch its index
|
|
133
|
+
// until the reader is close enough to see it.
|
|
134
|
+
observer = new IntersectionObserver(
|
|
135
|
+
(entries) => {
|
|
136
|
+
if (entries.some((entry) => entry.isIntersecting)) start();
|
|
137
|
+
},
|
|
138
|
+
{ rootMargin: "300px 0px" },
|
|
139
|
+
);
|
|
140
|
+
observer.observe(container);
|
|
141
|
+
} else {
|
|
142
|
+
start();
|
|
143
|
+
}
|
|
119
144
|
return () => {
|
|
120
145
|
disposed = true;
|
|
121
146
|
revision++;
|
|
122
147
|
request?.abort();
|
|
123
148
|
controller.abort();
|
|
149
|
+
observer?.disconnect();
|
|
124
150
|
cancelAnimation();
|
|
125
151
|
container.removeAttribute("aria-busy");
|
|
126
152
|
};
|
|
@@ -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*/
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
@layer theme, base, components, utilities;
|
|
2
|
-
@layer components{.stalux-link-card{color:#fff;box-sizing:border-box;background:var(--surface-glass);width:100%;min-width:0;min-height:200px;box-shadow:var(--card-box-shadow);border-radius:10px;flex-direction:column;padding:16px;text-decoration:none;transition:transform .22s,background-color .22s,border-color .22s;display:flex;overflow:visible}.stalux-link-card-content{text-align:center;flex-direction:column;flex:1;display:flex}.stalux-links{box-sizing:border-box;grid-template-columns:repeat(auto-fill,minmax(min(180px,100%),1fr));gap:20px;width:100%;max-width:1600px;margin:30px auto;padding:0 1rem;list-style-type:none;display:grid}.stalux-link-card-avatar{justify-content:center;margin-bottom:12px;display:flex}.stalux-link-list-item{width:100%;min-width:0;display:flex}.stalux-link-shell{width:100%;min-width:0}.stalux-link-card-content{transition:transform .2s}.stalux-link-card-avatar img{object-fit:cover;border:2px solid var(--accent-60p);transform-origin:50%;border-radius:9999px;width:80px;height:80px;transition:transform .22s,border-color .22s}.stalux-link-card-title{white-space:nowrap;background:linear-gradient(90deg, var(--white-95p), var(--accent-90p));color:#0000;text-overflow:ellipsis;background-clip:text;margin:0 0 8px;font-size:1.1rem;overflow:hidden}.stalux-link-card-description{color:var(--white-78p);-webkit-line-clamp:3;text-overflow:ellipsis;-webkit-box-orient:vertical;margin:0;font-size:.95rem;line-height:1.45;display:-webkit-box;overflow:hidden}@media (1100px<=width<=1399px){.stalux-links{grid-template-columns:repeat(4,minmax(0,1fr))}}@media (480px<=width<=767px){.stalux-links{grid-template-columns:repeat(2,minmax(0,1fr));gap:16px}}@media (768px<=width<=1099px){.stalux-links{grid-template-columns:repeat(3,minmax(0,1fr))}}@media (hover:hover) and (pointer:fine){.stalux-link-shell:hover .stalux-link-card-content{transform:translateY(-2px)}.stalux-link-shell:hover .stalux-link-card{background:var(--white-05p);box-shadow:var(--card-box-shadow-hover)}.stalux-link-card-avatar:hover img{border-color:var(--accent-85p);transform:rotate(3deg)}}@media (width>=1400px){.stalux-links{grid-template-columns:repeat(5,minmax(0,1fr))}}@media (width<=480px){.stalux-link-card{padding:14px}.stalux-link-card-avatar img{width:70px;height:70px}.stalux-link-card-title{font-size:1rem}.stalux-link-card-description{font-size:.9rem}}@media (width<=479px){.stalux-links{grid-template-columns:1fr;gap:14px;margin:20px auto}}@media (prefers-reduced-motion:reduce) and (hover:hover) and (pointer:fine){.stalux-link-card-avatar:hover img{transition:none;animation:none;transform:none}}}@layer utilities,theme,base;
|
|
2
|
+
@layer components{.stalux-link-card{color:#fff;box-sizing:border-box;background:var(--surface-glass);width:100%;min-width:0;min-height:200px;box-shadow:var(--card-box-shadow);border-radius:10px;flex-direction:column;padding:16px;text-decoration:none;transition:transform .22s,background-color .22s,border-color .22s;display:flex;overflow:visible}.stalux-link-card-content{text-align:center;flex-direction:column;flex:1;display:flex}.stalux-links{box-sizing:border-box;grid-template-columns:repeat(auto-fill,minmax(min(180px,100%),1fr));gap:20px;width:100%;max-width:1600px;margin:30px auto;padding:0 1rem;list-style-type:none;display:grid}.stalux-link-card-avatar{justify-content:center;margin-bottom:12px;display:flex}.stalux-link-list-item{width:100%;min-width:0;display:flex}.stalux-link-shell{width:100%;min-width:0}.stalux-link-card-content{transition:transform .2s}.stalux-link-card-avatar img{object-fit:cover;border:2px solid var(--accent-60p);transform-origin:50%;border-radius:9999px;width:80px;height:80px;transition:transform .22s,border-color .22s}.stalux-link-card-avatar img[data-src],.stalux-link-card-avatar img[data-stalux-link-icon-failed]{background:var(--white-05p)}.stalux-link-card-title{white-space:nowrap;background:linear-gradient(90deg, var(--white-95p), var(--accent-90p));color:#0000;text-overflow:ellipsis;background-clip:text;margin:0 0 8px;font-size:1.1rem;overflow:hidden}.stalux-link-card-description{color:var(--white-78p);-webkit-line-clamp:3;text-overflow:ellipsis;-webkit-box-orient:vertical;margin:0;font-size:.95rem;line-height:1.45;display:-webkit-box;overflow:hidden}@media (1100px<=width<=1399px){.stalux-links{grid-template-columns:repeat(4,minmax(0,1fr))}}@media (480px<=width<=767px){.stalux-links{grid-template-columns:repeat(2,minmax(0,1fr));gap:16px}}@media (768px<=width<=1099px){.stalux-links{grid-template-columns:repeat(3,minmax(0,1fr))}}@media (hover:hover) and (pointer:fine){.stalux-link-shell:hover .stalux-link-card-content{transform:translateY(-2px)}.stalux-link-shell:hover .stalux-link-card{background:var(--white-05p);box-shadow:var(--card-box-shadow-hover)}.stalux-link-card-avatar:hover img{border-color:var(--accent-85p);transform:rotate(3deg)}}@media (width>=1400px){.stalux-links{grid-template-columns:repeat(5,minmax(0,1fr))}}@media (width<=480px){.stalux-link-card{padding:14px}.stalux-link-card-avatar img{width:70px;height:70px}.stalux-link-card-title{font-size:1rem}.stalux-link-card-description{font-size:.9rem}}@media (width<=479px){.stalux-links{grid-template-columns:1fr;gap:14px;margin:20px auto}}@media (prefers-reduced-motion:reduce) and (hover:hover) and (pointer:fine){.stalux-link-card-avatar:hover img{transition:none;animation:none;transform:none}}}@layer utilities,theme,base;
|
|
3
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*/
|
package/src/styles/generated.css
CHANGED
|
@@ -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
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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" },
|