@xingwangzhe/stalux 1.55.6 → 1.56.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xingwangzhe/stalux",
3
- "version": "1.55.6",
3
+ "version": "1.56.0",
4
4
  "description": "A powerful, modern Astro blog theme — use as template or install as plugin",
5
5
  "keywords": [
6
6
  "astro",
@@ -101,7 +101,6 @@ const archiveYears = [...archivesByYearMonth.entries()]
101
101
  href={`/posts/${post.data.abbrlink}/`}
102
102
  class="stalux-archive-post-link"
103
103
  data-archive-description={post.data.desc || ""}
104
- data-astro-prefetch="viewport"
105
104
  >
106
105
  {post.data.title}
107
106
  </a>
@@ -11,5 +11,5 @@ const { t } = createTranslator(siteConfig.lang || "zh-CN");
11
11
 
12
12
  <!-- Modern Web Guidance (html): 一行“查看全部归档”文字 + 链接 => <p>。 -->
13
13
  <p id={"stalux-to-archive-archs"}>
14
- <a data-stalux-control="button" href="/archives" data-astro-prefetch>{t("archives.viewAll")}</a>
14
+ <a data-stalux-control="button" href="/archives">{t("archives.viewAll")}</a>
15
15
  </p>
@@ -23,11 +23,7 @@ const { t } = createTranslator((siteConfig.lang as string) || "zh-CN");
23
23
  <!-- Modern Web Guidance (html): 分类卡本身即 <article>;外层曾经的 <div class="stalux-category-shell">
24
24
  已上移到列表的 <li>(见 categoriesList.astro),避免多一层无语义容器。 -->
25
25
  <article class="stalux-category-card" data-stalux-control="category-card">
26
- <a
27
- href={`/categories/${props.category.name}/`}
28
- class="stalux-categoryheader a-none"
29
- data-astro-prefetch
30
- >
26
+ <a href={`/categories/${props.category.name}/`} class="stalux-categoryheader a-none">
31
27
  <span class="stalux-category-icon">
32
28
  <svg
33
29
  aria-hidden="true"
@@ -22,7 +22,7 @@ const navigationHref = isHomePage ? "/about" : "/";
22
22
  <figure
23
23
  class={`stalux-author-figure ${props.iscolum ? "stalux-author-figure-column stalux-u-flex-col" : ""}`}
24
24
  >
25
- <a data-stalux-control="avatar" href={navigationHref} class="a-none" data-astro-prefetch>
25
+ <a data-stalux-control="avatar" href={navigationHref} class="a-none">
26
26
  <Image src={authorConfig.avatar} alt={authorConfig.name} width={100} height={100} />
27
27
  </a>
28
28
  <figcaption>{authorConfig.name}</figcaption>
@@ -54,12 +54,7 @@ const navs = navsConfig?.items ?? [];
54
54
  const NavIcon = item.icon ? getLucideIcon(item.icon, Astro.logger) : null;
55
55
  return (
56
56
  <li class="stalux-nav-item stalux-u-flex stalux-u-items-center">
57
- <a
58
- href={item.link}
59
- class="stalux-nav-link"
60
- data-ref="stalux-nav-link"
61
- data-astro-prefetch
62
- >
57
+ <a href={item.link} class="stalux-nav-link" data-ref="stalux-nav-link">
63
58
  {NavIcon && <NavIcon size={20} stroke-width={2} class="nav-icon" />}
64
59
  <span class="stalux-nav-text">{item.title}</span>
65
60
  </a>
@@ -2,7 +2,6 @@
2
2
  interface Props {
3
3
  description?: string;
4
4
  label: string;
5
- transitionName: string;
6
5
  }
7
6
  const { description, label } = Astro.props;
8
7
  const summary = description?.trim();
@@ -51,11 +51,7 @@ const cfg = {
51
51
  <ul class={cfg.listClass} data-stalux-reveal>
52
52
  {items.map((item) => (
53
53
  <li data-stalux-reveal-item>
54
- <a
55
- href={`${cfg.prefix}${item}/`}
56
- class={`${cfg.itemClass} a-none`}
57
- data-astro-prefetch
58
- >
54
+ <a href={`${cfg.prefix}${item}/`} class={`${cfg.itemClass} a-none`}>
59
55
  {item}
60
56
  </a>
61
57
  </li>
@@ -27,12 +27,7 @@ const description = post.data.desc || "";
27
27
  class="stalux-post-card-shell stalux-post-card h-full text-inherit no-underline stalux-u-flex stalux-u-flex-col stalux-u-w-full stalux-u-min-w-0"
28
28
  >
29
29
  {post.data.cover && (
30
- <a
31
- href={`/posts/${post.data.abbrlink}/`}
32
- class="a-none"
33
- data-astro-prefetch="viewport"
34
- aria-label={post.data.title}
35
- >
30
+ <a href={`/posts/${post.data.abbrlink}/`} class="a-none" aria-label={post.data.title}>
36
31
  <span class="stalux-card-post-cover stalux-u-w-full stalux-u-min-w-0">
37
32
  <img
38
33
  src={post.data.cover}
@@ -48,7 +43,7 @@ const description = post.data.desc || "";
48
43
  </a>
49
44
  )}
50
45
  <h2 class="stalux-card-post-title">
51
- <a href={`/posts/${post.data.abbrlink}/`} class="a-none" data-astro-prefetch="viewport">
46
+ <a href={`/posts/${post.data.abbrlink}/`} class="a-none">
52
47
  {post.data.title}
53
48
  </a>
54
49
  </h2>
@@ -77,7 +72,7 @@ const description = post.data.desc || "";
77
72
  <ul class="stalux-card-post-tags stalux-u-flex stalux-u-items-center stalux-u-flex-wrap">
78
73
  {post.data.tags?.map((tag) => (
79
74
  <li>
80
- <a class="a-none" href={`/tags/${tag}`} data-astro-prefetch>
75
+ <a class="a-none" href={`/tags/${tag}`}>
81
76
  <span class="stalux-card-post-tag">{tag}</span>
82
77
  </a>
83
78
  </li>
@@ -88,18 +83,12 @@ const description = post.data.desc || "";
88
83
  >
89
84
  {post.data.categories?.map((category) => (
90
85
  <li>
91
- <a class="a-none" href={`/categories/${category}`} data-astro-prefetch>
86
+ <a class="a-none" href={`/categories/${category}`}>
92
87
  <span class="stalux-card-post-category">{category}</span>
93
88
  </a>
94
89
  </li>
95
90
  ))}
96
91
  </ul>
97
92
  </footer>
98
- <a
99
- href={`/posts/${post.data.abbrlink}/`}
100
- class="stalux-card-read-more a-none"
101
- data-astro-prefetch
102
- >
103
- Read More
104
- </a>
93
+ <a href={`/posts/${post.data.abbrlink}/`} class="stalux-card-read-more a-none"> Read More </a>
105
94
  </article>
@@ -14,8 +14,9 @@ interface Props {
14
14
  title: string;
15
15
  description?: string;
16
16
  searchKeywords?: string[];
17
+ // Kept for downstream overrides of this component; the theme's own render
18
+ // path no longer turns them into any view-transition CSS (Swup owns cues).
17
19
  transitionName?: string;
18
- titleTransitionName?: string;
19
20
  transitionScope?: "article" | "about";
20
21
  date?: string;
21
22
  updated?: string;
@@ -25,7 +26,6 @@ interface Props {
25
26
  }
26
27
 
27
28
  const props = Astro.props as Props;
28
- const transitionPrefix = props.transitionScope === "about" ? "stalux-about" : "stalux-article";
29
29
  const configEntries = await getCollection("config");
30
30
  const siteConfig = getSiteData(configEntries);
31
31
  const promoteConfig = getPromoteData(configEntries);
@@ -113,11 +113,7 @@ const mdSourceUrl = exportMd ? `${Astro.url.pathname.replace(/\/$/u, "")}.md` :
113
113
  )}
114
114
  </header>
115
115
 
116
- <ArticleSummary
117
- description={props.description}
118
- label={t("post.summary")}
119
- transitionName={`${transitionPrefix}-summary`}
120
- />
116
+ <ArticleSummary description={props.description} label={t("post.summary")} />
121
117
 
122
118
  <span
123
119
  hidden
@@ -34,7 +34,6 @@ const { t } = createTranslator((siteConfig.lang as string) || "zh-CN");
34
34
  data-stalux-motion="previous"
35
35
  class="stalux-pagination-link stalux-pagination-prev-post"
36
36
  rel="prev"
37
- data-astro-prefetch
38
37
  >
39
38
  <span class="stalux-pagination-arrow">
40
39
  <svg
@@ -90,7 +89,6 @@ const { t } = createTranslator((siteConfig.lang as string) || "zh-CN");
90
89
  data-stalux-motion="next"
91
90
  class="stalux-pagination-link stalux-pagination-next-post"
92
91
  rel="next"
93
- data-astro-prefetch
94
92
  >
95
93
  <p class="stalux-pagination-content">
96
94
  <span class="stalux-pagination-label">{t("post.nextPost")}</span>
@@ -52,7 +52,7 @@ if (typeKey === "category" || typeKey === "categories" || typeKey === "分类")
52
52
  <p class="stalux-tag-page-description">
53
53
  {t("taxonomy.foundPosts", { count: props.count })}
54
54
  </p>
55
- <a href={typeUrl} class="stalux-tag-back-link" data-astro-prefetch
55
+ <a href={typeUrl} class="stalux-tag-back-link"
56
56
  >{t("taxonomy.backToList", { type: props.type })}</a
57
57
  >
58
58
  </header>
@@ -42,7 +42,6 @@ const tagLinks = tagList.map((t) => ({
42
42
  data-stalux-tag-card
43
43
  data-stalux-control="tag-card"
44
44
  data-count={count}
45
- data-astro-prefetch
46
45
  >
47
46
  <span class="stalux-cloud-tag-name">{name}</span>
48
47
  <span class="stalux-cloud-tag-count">{count}</span>
@@ -339,24 +339,9 @@ export const styleNames: { classes: Record<string, string>; variables: Record<st
339
339
  },
340
340
  "animations": {
341
341
  "spin": "k0",
342
- "stalux-article-enter": "k1",
343
- "stalux-article-enter-back": "k2",
344
- "stalux-cursor-blink": "k3",
345
- "stalux-link-avatar-spin": "k4",
346
- "stalux-page-enter": "k5",
347
- "stalux-page-enter-back": "k6",
348
- "stalux-page-exit": "k7",
349
- "stalux-random-spin": "k8",
350
- "stalux-sidebar-left-back-in": "k9",
351
- "stalux-sidebar-left-back-out": "ka",
352
- "stalux-sidebar-left-in": "kb",
353
- "stalux-sidebar-left-out": "kc",
354
- "stalux-sidebar-right-back-in": "kd",
355
- "stalux-sidebar-right-back-out": "ke",
356
- "stalux-sidebar-right-in": "kf",
357
- "stalux-sidebar-right-out": "kg",
358
- "stalux-social-stalux-social-arrive": "kh",
359
- "stalux-taxonomy-enter": "ki",
360
- "stalux-taxonomy-enter-back": "kj"
342
+ "stalux-cursor-blink": "k1",
343
+ "stalux-link-avatar-spin": "k2",
344
+ "stalux-random-spin": "k3",
345
+ "stalux-social-stalux-social-arrive": "k4"
361
346
  }
362
347
  };
@@ -8,7 +8,6 @@ import PostNavigation from "@components/stalux/posts/postNavigation.astro";
8
8
  import PostRight from "@components/stalux/posts/postRight.astro";
9
9
  import WalineComment from "@components/stalux/posts/WalineComment.astro";
10
10
  import { getCommentData } from "@utils/config-utils";
11
- import { getPostTitleTransitionName } from "@utils/view-transitions";
12
11
  import { buildWalineProps } from "@utils/waline";
13
12
 
14
13
  interface Props {
@@ -63,9 +62,6 @@ const walineConfig = walineSection?.serverURL
63
62
  title={props.title}
64
63
  description={props.description}
65
64
  searchKeywords={[...tags, ...categories, ...(props.searchKeywords ?? [])]}
66
- titleTransitionName={props.postId === undefined
67
- ? undefined
68
- : getPostTitleTransitionName(props.postId)}
69
65
  date={props.date}
70
66
  updated={props.updated}
71
67
  readingMinutes={props.readingMinutes}
@@ -42,7 +42,6 @@ const { t } = createTranslator(siteConfig.lang || "zh-CN");
42
42
  href="/"
43
43
  class="stalux-404-home-btn home-btn"
44
44
  data-stalux-control="button"
45
- data-astro-prefetch
46
45
  data-stalux-motion-content
47
46
  >{t("page404.backHome")}</a
48
47
  >
@@ -33,7 +33,6 @@ const author = authorConfig.name;
33
33
  <PostContent
34
34
  title={aboutPage.data.title}
35
35
  transitionName="about-content"
36
- titleTransitionName="stalux-about-title"
37
36
  transitionScope="about"
38
37
  date={undefined}
39
38
  updated={undefined}
@@ -1,4 +1,9 @@
1
- import { isMarkdownExportEnabled, loadConfig, renderWordsMd } from "@utils/ai-discovery";
1
+ import {
2
+ isMarkdownExportEnabled,
3
+ loadConfig,
4
+ renderWordsMd,
5
+ resolveSiteTimezone,
6
+ } from "@utils/ai-discovery";
2
7
  import type { APIRoute } from "astro";
3
8
 
4
9
  export const prerender = true;
@@ -7,7 +12,7 @@ export const GET: APIRoute = async () => {
7
12
  const config = await loadConfig();
8
13
  if (!isMarkdownExportEnabled(config)) return new Response(null, { status: 404 });
9
14
 
10
- const text = await renderWordsMd();
15
+ const text = await renderWordsMd(resolveSiteTimezone(config));
11
16
  return new Response(text, {
12
17
  headers: {
13
18
  "Content-Type": "text/markdown; charset=utf-8",
@@ -91,7 +91,13 @@ export function installSwupRouter(): Swup {
91
91
  let activeContext: NavigationContext | undefined;
92
92
  let visibleHistoryIndex = Number(window.history.state?.index ?? 1);
93
93
  let browserMotion = false;
94
- const progress = new SwupProgressPlugin();
94
+ // Swup waits for the target document before it starts any animation, so a
95
+ // slow fetch is a window with no visual response at all. The official
96
+ // plugin waits 300ms before showing its bar, which leaves most of that
97
+ // window empty; 80ms keeps a cached/preloaded visit invisible (it finishes
98
+ // first) while a real network round trip gets an immediate, theme-coloured
99
+ // cue. The bar itself is compositor-only: a 3px transform on one element.
100
+ const progress = new SwupProgressPlugin({ delay: 80, transition: 200 });
95
101
  const scroll = new SwupScrollPlugin({
96
102
  doScrollingRightAway: false,
97
103
  animateScroll: { betweenPages: false, samePageWithHash: true, samePage: true },
@@ -1,3 +1,3 @@
1
1
  @layer theme, base, components, utilities;
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;margin:0;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:.5rem 0 0;font-size:.9rem}.stalux-stats-stats-separator{color:#ffffff80}.stalux-theme-info{color:var(--white-70p);gap:.3em;margin:0;font-size:.85rem}.stalux-nav-container{box-sizing:border-box;max-width:100%;position:relative;overflow:hidden}.stalux-beian-beian-info{gap:1rem;margin:0}.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-top:0;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-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-weather-heading{font-size:inherit;font-weight:inherit;margin:0}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:2em 0 0}#stalux-date-date-time{text-shadow:var(--stalux-text-shadow);color:var(--white-full);flex-direction:column;align-items:center;margin:2em 0 0;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:var(--stalux-scrollbar-thumb) var(--stalux-scrollbar-track);scrollbar-width:auto;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-scrollbar-thumb:#7d7d7d;--stalux-scrollbar-thumb-hover:#9a9a9a;--stalux-scrollbar-track:#2a2a2a;--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}@supports not (scrollbar-color:auto){::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-track{background:var(--stalux-scrollbar-track);border-radius:4px}::-webkit-scrollbar-thumb{background:var(--stalux-scrollbar-thumb);border-radius:4px;transition:background .3s ease-out}@media (hover:hover) and (pointer:fine){::-webkit-scrollbar-thumb:hover{background:var(--stalux-scrollbar-thumb-hover)}}::-webkit-scrollbar-corner{background:var(--stalux-scrollbar-track)}}.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;margin:0;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:.5rem 0 0;font-size:.9rem}.stalux-stats-stats-separator{color:#ffffff80}.stalux-theme-info{color:var(--white-70p);gap:.3em;margin:0;font-size:.85rem}.stalux-nav-container{box-sizing:border-box;max-width:100%;position:relative;overflow:hidden}.stalux-beian-beian-info{gap:1rem;margin:0}.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-top:0;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-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-weather-heading{font-size:inherit;font-weight:inherit;margin:0}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:2em 0 0}#stalux-date-date-time{text-shadow:var(--stalux-text-shadow);color:var(--white-full);flex-direction:column;align-items:center;margin:2em 0 0;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:var(--stalux-scrollbar-thumb) var(--stalux-scrollbar-track);scrollbar-width:auto;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-scrollbar-thumb:#7d7d7d;--stalux-scrollbar-thumb-hover:#9a9a9a;--stalux-scrollbar-track:#2a2a2a;--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}@supports not (scrollbar-color:auto){::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-track{background:var(--stalux-scrollbar-track);border-radius:4px}::-webkit-scrollbar-thumb{background:var(--stalux-scrollbar-thumb);border-radius:4px;transition:background .3s ease-out}@media (hover:hover) and (pointer:fine){::-webkit-scrollbar-thumb:hover{background:var(--stalux-scrollbar-thumb-hover)}}::-webkit-scrollbar-corner{background:var(--stalux-scrollbar-track)}}.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}[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*/
@@ -16,129 +16,6 @@
16
16
  width: 100%;
17
17
  }
18
18
 
19
- /* Public transition helpers retain their names as opacity-only compatibility
20
- frames. Theme layouts no longer use them to move large content/sidebars. */
21
- @keyframes stalux-page-exit {
22
- from {
23
- opacity: 1;
24
- }
25
- to {
26
- opacity: 1;
27
- }
28
- }
29
- @keyframes stalux-page-enter {
30
- from {
31
- opacity: 0.9;
32
- }
33
- to {
34
- opacity: 1;
35
- }
36
- }
37
- @keyframes stalux-page-enter-back {
38
- from {
39
- opacity: 0.96;
40
- }
41
- to {
42
- opacity: 1;
43
- }
44
- }
45
- @keyframes stalux-taxonomy-enter {
46
- from {
47
- opacity: 0.9;
48
- }
49
- to {
50
- opacity: 1;
51
- }
52
- }
53
- @keyframes stalux-taxonomy-enter-back {
54
- from {
55
- opacity: 0.96;
56
- }
57
- to {
58
- opacity: 1;
59
- }
60
- }
61
- @keyframes stalux-article-enter {
62
- from {
63
- opacity: 0.9;
64
- }
65
- to {
66
- opacity: 1;
67
- }
68
- }
69
- @keyframes stalux-article-enter-back {
70
- from {
71
- opacity: 0.96;
72
- }
73
- to {
74
- opacity: 1;
75
- }
76
- }
77
- @keyframes stalux-sidebar-left-in {
78
- from {
79
- opacity: 0.96;
80
- }
81
- to {
82
- opacity: 1;
83
- }
84
- }
85
- @keyframes stalux-sidebar-left-out {
86
- from {
87
- opacity: 1;
88
- }
89
- to {
90
- opacity: 1;
91
- }
92
- }
93
- @keyframes stalux-sidebar-left-back-in {
94
- from {
95
- opacity: 0.96;
96
- }
97
- to {
98
- opacity: 1;
99
- }
100
- }
101
- @keyframes stalux-sidebar-left-back-out {
102
- from {
103
- opacity: 1;
104
- }
105
- to {
106
- opacity: 1;
107
- }
108
- }
109
- @keyframes stalux-sidebar-right-in {
110
- from {
111
- opacity: 0.96;
112
- }
113
- to {
114
- opacity: 1;
115
- }
116
- }
117
- @keyframes stalux-sidebar-right-out {
118
- from {
119
- opacity: 1;
120
- }
121
- to {
122
- opacity: 1;
123
- }
124
- }
125
- @keyframes stalux-sidebar-right-back-in {
126
- from {
127
- opacity: 0.96;
128
- }
129
- to {
130
- opacity: 1;
131
- }
132
- }
133
- @keyframes stalux-sidebar-right-back-out {
134
- from {
135
- opacity: 1;
136
- }
137
- to {
138
- opacity: 1;
139
- }
140
- }
141
-
142
19
  [data-stalux-scroll-sentinel] {
143
20
  position: absolute;
144
21
  top: 240px;
@@ -52,6 +52,17 @@ function getSiteConfig(config: ConfigMap): Record<string, unknown> {
52
52
  return config.get("site") ?? {};
53
53
  }
54
54
 
55
+ /**
56
+ * 站点 IANA 时区(site.yml 的 timezone)。
57
+ *
58
+ * 与 `getSiteData()` 的缺省值保持一致:日期排序必须按站点时区解析无时区串,
59
+ * 否则会在 UTC 构建机上整体偏移,混写带偏移日期时排序还会错乱。
60
+ */
61
+ export function resolveSiteTimezone(config: ConfigMap): string {
62
+ const value = getSiteConfig(config).timezone;
63
+ return typeof value === "string" && value.length > 0 ? value : "Asia/Shanghai";
64
+ }
65
+
55
66
  /**
56
67
  * 解析站点根 URL。
57
68
  *
@@ -254,9 +265,12 @@ export async function renderAboutMd(site: string): Promise<string> {
254
265
  }
255
266
 
256
267
  /** 渲染 Words 页 Markdown */
257
- export async function renderWordsMd(): Promise<string> {
268
+ export async function renderWordsMd(timeZone = "Asia/Shanghai"): Promise<string> {
258
269
  const words = await getCollection("words", ({ data }) => !data.draft);
259
- words.sort((a, b) => toTimestamp(b.data.date || 0) - toTimestamp(a.data.date || 0));
270
+ // 按站点时区解析无时区日期串,避免构建机时区影响排序
271
+ words.sort(
272
+ (a, b) => toTimestamp(b.data.date || 0, timeZone) - toTimestamp(a.data.date || 0, timeZone),
273
+ );
260
274
  const lines: string[] = [];
261
275
  lines.push("# Words");
262
276
  lines.push("");
@@ -558,7 +572,7 @@ export async function renderLlmsFullTxt(
558
572
  sections.push(await renderAboutMd(site));
559
573
  sections.push("---");
560
574
  sections.push("");
561
- sections.push(await renderWordsMd());
575
+ sections.push(await renderWordsMd(resolveSiteTimezone(config)));
562
576
  sections.push("---");
563
577
  sections.push("");
564
578
  sections.push(renderLinksMd(config, site, t));
@@ -1,5 +1,6 @@
1
1
  import { type CollectionEntry, getCollection } from "astro:content";
2
2
  import type { AstroRuntimeLogger } from "astro";
3
+ import { getSiteData } from "./config-utils";
3
4
  import { toTimestamp } from "./dayjs";
4
5
  import { logDetail } from "./diagnostics";
5
6
 
@@ -93,13 +94,17 @@ function finalizeTaxonomy<T extends IndexablePost>(
93
94
  */
94
95
  export function buildPostContentIndex<T extends IndexablePost>(
95
96
  sourcePosts: readonly T[],
97
+ timeZone?: string,
96
98
  ): PostContentIndex<T> {
97
99
  const times = new Map<T, { date: number; updated: number }>();
98
100
  for (const post of sourcePosts) {
99
- const date = toTimestamp(post.data.date);
101
+ // 无时区日期串必须按站点时区解析。漏传会按构建机器时区解释:
102
+ // UTC 构建机上整体偏 8 小时;一旦与带偏移的日期混写,两者相差 8 小时,
103
+ // 排序就会错——首页顺序、上一篇/下一篇、分类「最新」归属都跟着错。
104
+ const date = toTimestamp(post.data.date, timeZone);
100
105
  times.set(post, {
101
106
  date,
102
- updated: post.data.updated == null ? date : toTimestamp(post.data.updated),
107
+ updated: post.data.updated == null ? date : toTimestamp(post.data.updated, timeZone),
103
108
  });
104
109
  }
105
110
  const posts = sourcePosts.toSorted(
@@ -139,9 +144,13 @@ let productionIndex: Promise<PostContentIndex<PostEntry>> | undefined;
139
144
  async function loadPostContentIndex(
140
145
  logger?: AstroRuntimeLogger,
141
146
  ): Promise<PostContentIndex<PostEntry>> {
142
- const posts = await getCollection("posts", ({ data }) => !data.draft);
147
+ const [posts, configEntries] = await Promise.all([
148
+ getCollection("posts", ({ data }) => !data.draft),
149
+ getCollection("config"),
150
+ ]);
143
151
  const started = performance.now();
144
- const index = buildPostContentIndex(posts);
152
+ // 站点时区与 feed / semantic-time / archives 同源(site.yml,缺省 Asia/Shanghai)
153
+ const index = buildPostContentIndex(posts, getSiteData(configEntries).timezone);
145
154
  logDetail(
146
155
  logger,
147
156
  "content-index",
@@ -1,112 +1,7 @@
1
+ // Route classification shared by SSR and the client router. The Astro View
2
+ // Transitions helpers that used to live here were removed together with the
3
+ // ClientRouter: Swup owns navigation and every cue, so route animation config
4
+ // and `view-transition-name` generation had no consumer left.
1
5
  import { getRouteKind, type RouteKind } from "./public-routes";
2
- import { productionStyleName } from "./style-name.ts";
3
6
 
4
7
  export { getRouteKind, type RouteKind };
5
-
6
- /** Stable, CSS-safe transition names for matching a post card to its title. */
7
- export function getPostTitleTransitionName(postId: string | number): string {
8
- let hash = 2166136261;
9
- for (const character of String(postId)) {
10
- hash ^= character.codePointAt(0) ?? 0;
11
- hash = Math.imul(hash, 16777619);
12
- }
13
- return `stalux-post-title-${(hash >>> 0).toString(36)}`;
14
- }
15
-
16
- export type TransitionAnimation = {
17
- name: string;
18
- delay?: number | string;
19
- duration?: number | string;
20
- easing?: string;
21
- fillMode?: string;
22
- direction?: string;
23
- };
24
-
25
- export type SidebarSide = "left" | "right";
26
-
27
- export type RouteAnimation = {
28
- forwards: {
29
- old: TransitionAnimation | TransitionAnimation[];
30
- new: TransitionAnimation | TransitionAnimation[];
31
- };
32
- backwards: {
33
- old: TransitionAnimation | TransitionAnimation[];
34
- new: TransitionAnimation | TransitionAnimation[];
35
- };
36
- };
37
-
38
- const easing = "cubic-bezier(0.2, 0.7, 0.2, 1)";
39
- const exitAnimation: TransitionAnimation = {
40
- name: "stalux-page-exit",
41
- duration: "0.1s",
42
- easing,
43
- fillMode: "both",
44
- };
45
-
46
- function createRouteAnimation(name: string, backName = `${name}-back`): RouteAnimation {
47
- return {
48
- forwards: {
49
- old: exitAnimation,
50
- new: {
51
- name: productionStyleName(`stalux-${name}`),
52
- duration: "0.16s",
53
- easing,
54
- fillMode: "both",
55
- },
56
- },
57
- backwards: {
58
- old: exitAnimation,
59
- new: {
60
- name: productionStyleName(`stalux-${backName}`),
61
- duration: "0.16s",
62
- easing,
63
- fillMode: "both",
64
- },
65
- },
66
- };
67
- }
68
-
69
- const routeAnimations: Record<RouteKind, RouteAnimation> = {
70
- home: createRouteAnimation("page-enter"),
71
- archive: createRouteAnimation("page-enter"),
72
- links: createRouteAnimation("page-enter"),
73
- words: createRouteAnimation("page-enter"),
74
- about: createRouteAnimation("page-enter"),
75
- "tags-index": createRouteAnimation("page-enter"),
76
- "tags-detail": createRouteAnimation("taxonomy-enter", "taxonomy-enter-back"),
77
- "categories-index": createRouteAnimation("page-enter"),
78
- "categories-detail": createRouteAnimation("taxonomy-enter", "taxonomy-enter-back"),
79
- article: createRouteAnimation("article-enter", "article-enter-back"),
80
- "not-found": createRouteAnimation("page-enter"),
81
- other: createRouteAnimation("page-enter"),
82
- };
83
-
84
- export function getRouteAnimation(routeKind: RouteKind): RouteAnimation {
85
- return routeAnimations[routeKind];
86
- }
87
-
88
- function createSidebarAnimation(
89
- side: SidebarSide,
90
- phase: "in" | "out",
91
- backwards: boolean,
92
- ): TransitionAnimation {
93
- return {
94
- name: productionStyleName(`stalux-sidebar-${side}-${backwards ? "back-" : ""}${phase}`),
95
- duration: "0.16s",
96
- easing,
97
- fillMode: "both",
98
- };
99
- }
100
-
101
- export function getSidebarAnimation(side: SidebarSide): RouteAnimation {
102
- return {
103
- forwards: {
104
- old: createSidebarAnimation(side, "out", false),
105
- new: createSidebarAnimation(side, "in", false),
106
- },
107
- backwards: {
108
- old: createSidebarAnimation(side, "out", true),
109
- new: createSidebarAnimation(side, "in", true),
110
- },
111
- };
112
- }