@xingwangzhe/stalux 1.39.5 → 1.40.1

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 CHANGED
@@ -18,9 +18,9 @@ Standalone images written as `![Image description](url)` receive a `figure` and
18
18
 
19
19
  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
20
 
21
- Route changes automatically show a 2px accent-colored progress bar at the top of the viewport, with no configuration. Its length follows actual milestones, with slow visual growth toward a bounded ceiling while waiting: loading begins, document/font preparation finishes, the DOM swaps, and page scripts finish; completion waits for the visual transition as well. It only reaches the end when loading and the transition both complete, and does not represent download/time percentages. It handles superseded or canceled navigation, history traversal, and reduced motion without additional requests or telemetry.
21
+ Route changes use native CSS View Transitions for one visible semantic heading in the incoming page. The policy covers every theme route category: normal effects take 100–180ms, with short 100–120ms fades on mobile. Entering an article, returning to a list, filtering categories or tags, explicit previous/next article controls, and returning home receive hints that follow reading intent. History traversal restores the existing scroll position; offscreen headings remain out of view. Reduced motion, browser-provided history gestures and same-page anchors add no visible VT animation. Standalone HTML keeps native navigation. See the [1.40.0 transition policy](https://github.com/xingwangzhe/stalux/blob/v1.40.1/docs/view-transitions-1.40.1.md).
22
22
 
23
- The sticky header stays at the top while the body grows with long content. Route transitions use a 100ms native Web Animations API fade on the new content, with the persisted header and footer stationary. Page-sized View Transition snapshots and geometry interpolation are disabled; Astro still handles document preparation, history, scroll restoration and scripts. Progress and background updates wait for the real content animation to finish. Reduced motion and browser-provided history gestures skip this extra animation. Navigation batches layout reads in one frame and carries the persisted header's measured dimensions across swaps, reducing style recalculation, rasterization and compositing work on mobile devices. Content, lightboxes, search, comments and analytics keep their existing behavior.
23
+ The sticky header stays at the top while the body grows with long content; the persisted header and footer stay in place during navigation. Text is immediately clear, and the incoming heading is measured once after Astro swaps the document and restores scrolling. Astro continues to own document/font preparation, history, scrolling and page-script lifecycle. Shared motion state settles when the native transition finishes or is canceled. CSS animation duration is reported separately from total navigation time, which includes networking, layout and browser settlement.
24
24
 
25
25
  ---
26
26
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xingwangzhe/stalux",
3
- "version": "1.39.5",
3
+ "version": "1.40.1",
4
4
  "description": "A powerful, modern Astro blog theme — use as template or install as plugin",
5
5
  "keywords": [
6
6
  "astro",
@@ -10,7 +10,7 @@ const { heading, description } = Astro.props;
10
10
  <>
11
11
  <h1
12
12
  class="stalux-page-title stalux-u-text-center"
13
- transition:name="stalux-page-title"
13
+ data-stalux-motion-focus
14
14
  transition:animate="none"
15
15
  >
16
16
  {heading}
@@ -50,7 +50,7 @@ const mdSourceUrl = exportMd ? `${Astro.url.pathname.replace(/\/$/, "")}.md` : "
50
50
  transition:name={`${transitionPrefix}-header`}
51
51
  transition:animate="fade"
52
52
  >
53
- <h1 class="stalux-post-title" transition:name={props.titleTransitionName}>
53
+ <h1 class="stalux-post-title" data-stalux-motion-focus>
54
54
  {props.title}
55
55
  </h1>
56
56
  <div
@@ -24,6 +24,7 @@ const { t } = createTranslator((siteConfig.lang as string) || "zh-CN");
24
24
  {props.prev ? (
25
25
  <a
26
26
  href={props.prev.url}
27
+ data-stalux-motion="previous"
27
28
  class="stalux-pagination-link stalux-pagination-prev-post"
28
29
  rel="prev"
29
30
  data-astro-prefetch
@@ -77,6 +78,7 @@ const { t } = createTranslator((siteConfig.lang as string) || "zh-CN");
77
78
  {props.next ? (
78
79
  <a
79
80
  href={props.next.url}
81
+ data-stalux-motion="next"
80
82
  class="stalux-pagination-link stalux-pagination-next-post"
81
83
  rel="next"
82
84
  data-astro-prefetch
@@ -32,7 +32,7 @@ if (typeKey === "category" || typeKey === "categories" || typeKey === "分类")
32
32
  transition:name="stalux-taxonomy-page-header-shell"
33
33
  transition:animate="none"
34
34
  >
35
- <h1 class="stalux-tag-page-title">
35
+ <h1 class="stalux-tag-page-title" data-stalux-motion-focus>
36
36
  <span class="stalux-tag-category-icon">
37
37
  <svg
38
38
  aria-hidden="true"
@@ -287,52 +287,50 @@ export const styleNames: { classes: Record<string, string>; variables: Record<st
287
287
  "--stalux-bg-color": "--s1n",
288
288
  "--stalux-bg-filter": "--s1o",
289
289
  "--stalux-nav-offset": "--s1p",
290
- "--stalux-side-in-x": "--s1q",
291
- "--stalux-side-out-x": "--s1r",
292
- "--stalux-site-header-height": "--s1s",
293
- "--stalux-site-header-min-height": "--s1t",
294
- "--stalux-text-shadow": "--s1u",
295
- "--surface-glass": "--s1v",
296
- "--surface-glass-shadow": "--s1w",
297
- "--tag-bg": "--s1x",
298
- "--tag-bg-hover": "--s1y",
299
- "--tl-line": "--s1z",
300
- "--tl-pad": "--s20",
301
- "--transition-fast": "--s21",
302
- "--transition-medium": "--s22",
303
- "--transition-normal": "--s23",
304
- "--transition-slow": "--s24",
305
- "--transition-slower": "--s25",
306
- "--transition-slowest": "--s26",
307
- "--un-rotate": "--s27",
308
- "--un-rotate-x": "--s28",
309
- "--un-rotate-y": "--s29",
310
- "--un-rotate-z": "--s2a",
311
- "--un-scale-x": "--s2b",
312
- "--un-scale-y": "--s2c",
313
- "--un-scale-z": "--s2d",
314
- "--un-skew-x": "--s2e",
315
- "--un-skew-y": "--s2f",
316
- "--un-translate-x": "--s2g",
317
- "--un-translate-y": "--s2h",
318
- "--un-translate-z": "--s2i",
319
- "--updated-bg": "--s2j",
320
- "--updated-border": "--s2k",
321
- "--white-05p": "--s2l",
322
- "--white-10p": "--s2m",
323
- "--white-15p": "--s2n",
324
- "--white-20p": "--s2o",
325
- "--white-30p": "--s2p",
326
- "--white-50p": "--s2q",
327
- "--white-60p": "--s2r",
328
- "--white-70p": "--s2s",
329
- "--white-75p": "--s2t",
330
- "--white-78p": "--s2u",
331
- "--white-80p": "--s2v",
332
- "--white-85p": "--s2w",
333
- "--white-90p": "--s2x",
334
- "--white-95p": "--s2y",
335
- "--white-full": "--s2z"
290
+ "--stalux-site-header-height": "--s1q",
291
+ "--stalux-site-header-min-height": "--s1r",
292
+ "--stalux-text-shadow": "--s1s",
293
+ "--surface-glass": "--s1t",
294
+ "--surface-glass-shadow": "--s1u",
295
+ "--tag-bg": "--s1v",
296
+ "--tag-bg-hover": "--s1w",
297
+ "--tl-line": "--s1x",
298
+ "--tl-pad": "--s1y",
299
+ "--transition-fast": "--s1z",
300
+ "--transition-medium": "--s20",
301
+ "--transition-normal": "--s21",
302
+ "--transition-slow": "--s22",
303
+ "--transition-slower": "--s23",
304
+ "--transition-slowest": "--s24",
305
+ "--un-rotate": "--s25",
306
+ "--un-rotate-x": "--s26",
307
+ "--un-rotate-y": "--s27",
308
+ "--un-rotate-z": "--s28",
309
+ "--un-scale-x": "--s29",
310
+ "--un-scale-y": "--s2a",
311
+ "--un-scale-z": "--s2b",
312
+ "--un-skew-x": "--s2c",
313
+ "--un-skew-y": "--s2d",
314
+ "--un-translate-x": "--s2e",
315
+ "--un-translate-y": "--s2f",
316
+ "--un-translate-z": "--s2g",
317
+ "--updated-bg": "--s2h",
318
+ "--updated-border": "--s2i",
319
+ "--white-05p": "--s2j",
320
+ "--white-10p": "--s2k",
321
+ "--white-15p": "--s2l",
322
+ "--white-20p": "--s2m",
323
+ "--white-30p": "--s2n",
324
+ "--white-50p": "--s2o",
325
+ "--white-60p": "--s2p",
326
+ "--white-70p": "--s2q",
327
+ "--white-75p": "--s2r",
328
+ "--white-78p": "--s2s",
329
+ "--white-80p": "--s2t",
330
+ "--white-85p": "--s2u",
331
+ "--white-90p": "--s2v",
332
+ "--white-95p": "--s2w",
333
+ "--white-full": "--s2x"
336
334
  },
337
335
  "animations": {
338
336
  "fadeInUpComment": "k0",
@@ -340,25 +338,29 @@ export const styleNames: { classes: Record<string, string>; variables: Record<st
340
338
  "stalux-article-enter": "k2",
341
339
  "stalux-article-enter-back": "k3",
342
340
  "stalux-cursor-blink": "k4",
343
- "stalux-link-avatar-spin": "k5",
344
- "stalux-random-spin": "k6",
345
- "stalux-sidebar-left-back-in": "k7",
346
- "stalux-sidebar-left-back-out": "k8",
347
- "stalux-sidebar-left-in": "k9",
348
- "stalux-sidebar-left-out": "ka",
349
- "stalux-sidebar-right-back-in": "kb",
350
- "stalux-sidebar-right-back-out": "kc",
351
- "stalux-sidebar-right-in": "kd",
352
- "stalux-sidebar-right-out": "ke",
353
- "stalux-social-stalux-social-arrive": "kf",
354
- "stalux-taxonomy-enter": "kg",
355
- "stalux-taxonomy-enter-back": "kh",
356
- "stalux-vt-new-back": "ki",
357
- "stalux-vt-new-fwd": "kj",
358
- "stalux-vt-old-back": "kk",
359
- "stalux-vt-old-fwd": "kl",
360
- "stalux-vt-side-in": "km",
361
- "stalux-vt-side-out": "kn",
362
- "stalux-word-word-glow": "ko"
341
+ "stalux-focus-enter": "k5",
342
+ "stalux-focus-fade": "k6",
343
+ "stalux-focus-home": "k7",
344
+ "stalux-focus-next": "k8",
345
+ "stalux-focus-previous": "k9",
346
+ "stalux-focus-restore": "ka",
347
+ "stalux-focus-up": "kb",
348
+ "stalux-link-avatar-spin": "kc",
349
+ "stalux-page-enter": "kd",
350
+ "stalux-page-enter-back": "ke",
351
+ "stalux-page-exit": "kf",
352
+ "stalux-random-spin": "kg",
353
+ "stalux-sidebar-left-back-in": "kh",
354
+ "stalux-sidebar-left-back-out": "ki",
355
+ "stalux-sidebar-left-in": "kj",
356
+ "stalux-sidebar-left-out": "kk",
357
+ "stalux-sidebar-right-back-in": "kl",
358
+ "stalux-sidebar-right-back-out": "km",
359
+ "stalux-sidebar-right-in": "kn",
360
+ "stalux-sidebar-right-out": "ko",
361
+ "stalux-social-stalux-social-arrive": "kp",
362
+ "stalux-taxonomy-enter": "kq",
363
+ "stalux-taxonomy-enter-back": "kr",
364
+ "stalux-word-word-glow": "ks"
363
365
  }
364
366
  };
@@ -120,7 +120,7 @@ const routeKind = getRouteKind(Astro.url.pathname);
120
120
  transition:persist="stalux-bg-b"
121
121
  aria-hidden="true"
122
122
  ></div>
123
- <main class="stalux-main" data-stalux-route={routeKind} transition:name="stalux-page">
123
+ <main class="stalux-main" data-stalux-route={routeKind}>
124
124
  <slot />
125
125
  </main>
126
126
  <Footer />
@@ -18,7 +18,7 @@ const { t } = createTranslator(siteConfig.lang || "zh-CN");
18
18
  data-pagefind-ignore
19
19
  >
20
20
  <div class="stalux-404-error-content">
21
- <h1>404</h1>
21
+ <h1 data-stalux-motion-focus>404</h1>
22
22
  <p>{t("page404.pageNotFound")}</p>
23
23
  <p class="agent-recovery">
24
24
  This URL does not exist. Continue at the <a href="/">home page</a>, browse the
@@ -22,8 +22,8 @@ import { getSiteData } from "@utils/config-utils";
22
22
  <div class="stalux-home-body stalux-u-flex stalux-u-items-center stalux-u-flex-col">
23
23
  <h1
24
24
  class="stalux-home-title stalux-u-text-center"
25
- transition:name="stalux-home-title"
26
- transition:animate="fade"
25
+ data-stalux-motion-focus
26
+ transition:animate="none"
27
27
  >
28
28
  {siteTitle}
29
29
  </h1>
@@ -1,7 +1,9 @@
1
1
  import { getRouteKind } from "@utils/public-routes";
2
+ import { getRouteMotionPreset, type RouteMotionPreset } from "@utils/route-motion-policy";
2
3
  import { installBackToTop } from "./back-to-top";
3
4
  import { createClientLogger } from "./logger";
4
5
  import { prepareNavigationFont } from "./navigation-font";
6
+ import { prepareRouteMotion, type RouteMotion } from "./route-motion";
5
7
 
6
8
  const logger = createClientLogger("view-transitions");
7
9
 
@@ -29,14 +31,20 @@ interface NavigationEvent {
29
31
  newDocument: Document;
30
32
  signal: AbortSignal;
31
33
  viewTransition?: ViewTransition;
34
+ sourceElement?: Element;
32
35
  }
33
36
 
34
- function setNavigationState(event: NavigationEvent, html = document.documentElement): void {
37
+ function setNavigationState(
38
+ event: NavigationEvent,
39
+ preset: RouteMotionPreset,
40
+ html = document.documentElement,
41
+ ): void {
35
42
  const from = getRouteKind(new URL(event.from, window.location.href).pathname);
36
43
  const to = getRouteKind(new URL(event.to, window.location.href).pathname);
37
44
  html.dataset.staluxVtFrom = from;
38
45
  html.dataset.staluxVtTo = to;
39
46
  html.dataset.staluxVtDirection = event.direction;
47
+ html.dataset.staluxVtPreset = preset;
40
48
  }
41
49
 
42
50
  function clearNavigationState(): void {
@@ -44,6 +52,30 @@ function clearNavigationState(): void {
44
52
  delete html.dataset.staluxVtFrom;
45
53
  delete html.dataset.staluxVtTo;
46
54
  delete html.dataset.staluxVtDirection;
55
+ delete html.dataset.staluxVtPreset;
56
+ clearFocusVisibility();
57
+ }
58
+
59
+ function clearFocusVisibility(): void {
60
+ document
61
+ .querySelector("[data-stalux-motion-focus]")
62
+ ?.removeAttribute?.("data-stalux-motion-visible");
63
+ }
64
+
65
+ /** At most one bounded title is considered, never an entire article or list. */
66
+ function updateFocusVisibility(): void {
67
+ const focus = document.querySelector<HTMLElement>("[data-stalux-motion-focus]");
68
+ if (!focus || typeof focus.getBoundingClientRect !== "function") return;
69
+ const rect = focus.getBoundingClientRect();
70
+ const visible =
71
+ rect.width > 0 &&
72
+ rect.height > 0 &&
73
+ rect.height <= window.innerHeight / 2 &&
74
+ rect.bottom > 0 &&
75
+ rect.top < window.innerHeight &&
76
+ rect.right > 0 &&
77
+ rect.left < window.innerWidth;
78
+ focus.dataset.staluxMotionVisible = String(visible);
47
79
  }
48
80
 
49
81
  function preserveHeaderMetrics(nextDocument: Document): void {
@@ -62,11 +94,52 @@ function preserveHeaderMetrics(nextDocument: Document): void {
62
94
  const transitionWindow = window as TransitionWindow;
63
95
  if (!transitionWindow.__STALUX_VT_LISTENER__) {
64
96
  transitionWindow.__STALUX_VT_LISTENER__ = true;
97
+ let pendingNavigation = 0;
98
+ let swappedNavigation = 0;
99
+
100
+ // A current-page link is not a page replacement. Intercept before Astro's
101
+ // delegated handler, but keep propagation for menu cleanup and click tracking.
102
+ // During preparation, Astro must receive it to cancel an incoming route.
103
+ // Hash changes, explicit reloads, downloads and modified/new-tab clicks keep
104
+ // their native behavior.
105
+ document.addEventListener(
106
+ "click",
107
+ (event) => {
108
+ if (
109
+ pendingNavigation !== 0 ||
110
+ event.defaultPrevented ||
111
+ event.button !== 0 ||
112
+ event.metaKey ||
113
+ event.ctrlKey ||
114
+ event.shiftKey ||
115
+ event.altKey
116
+ )
117
+ return;
118
+ const anchor =
119
+ event.target instanceof Element
120
+ ? event.target.closest<HTMLAnchorElement>("a[href]")
121
+ : null;
122
+ if (
123
+ !anchor ||
124
+ anchor.href !== window.location.href ||
125
+ anchor.href.includes("#") ||
126
+ anchor.hasAttribute("download") ||
127
+ anchor.hasAttribute("data-astro-reload") ||
128
+ anchor.relList.contains("external")
129
+ )
130
+ return;
131
+ const target =
132
+ anchor.getAttribute("target") ??
133
+ document.querySelector("base[target]")?.getAttribute("target");
134
+ if (!target || target === "_self") event.preventDefault();
135
+ },
136
+ { capture: true },
137
+ );
65
138
 
66
139
  let generation = 0;
67
140
  let pendingBrowserMotion = false;
68
- let _browserMotion = false;
69
- let _routeMotionActive = false;
141
+ let preset: RouteMotionPreset = "none";
142
+ let motion: RouteMotion | undefined;
70
143
  window.addEventListener(
71
144
  "popstate",
72
145
  (event) => {
@@ -79,25 +152,46 @@ if (!transitionWindow.__STALUX_VT_LISTENER__) {
79
152
  document.addEventListener("astro:before-preparation", (event) => {
80
153
  const navigation = event as unknown as NavigationEvent;
81
154
  const current = ++generation;
82
- _routeMotionActive = false;
83
- _browserMotion = pendingBrowserMotion && navigation.navigationType === "traverse";
155
+ pendingNavigation = current;
156
+ const cancelPreparation = () => {
157
+ if (current !== generation) return;
158
+ pendingNavigation = 0;
159
+ clearNavigationState();
160
+ };
161
+ motion?.cancel();
162
+ // Only the incoming heading animates. Drop any prior marker without
163
+ // measuring/capturing a hidden outgoing title or flushing its layout.
164
+ clearFocusVisibility();
165
+ preset = getRouteMotionPreset({
166
+ from: new URL(navigation.from, window.location.href),
167
+ to: new URL(navigation.to, window.location.href),
168
+ navigationType: navigation.navigationType,
169
+ intent:
170
+ navigation.sourceElement
171
+ ?.closest("[data-stalux-motion]")
172
+ ?.getAttribute("data-stalux-motion") ?? undefined,
173
+ reducedMotion: window.matchMedia?.("(prefers-reduced-motion: reduce)").matches,
174
+ browserMotion: pendingBrowserMotion && navigation.navigationType === "traverse",
175
+ hidden: document.hidden,
176
+ });
84
177
  pendingBrowserMotion = false;
85
- setNavigationState(navigation);
86
- navigation.signal.addEventListener(
87
- "abort",
88
- () => {
89
- if (current === generation) clearNavigationState();
90
- },
91
- { once: true },
92
- );
178
+ setNavigationState(navigation, preset);
179
+ navigation.signal.addEventListener("abort", cancelPreparation, { once: true });
180
+ if (navigation.signal.aborted) cancelPreparation();
93
181
  queueMicrotask(() => {
94
- if (event.defaultPrevented && current === generation) clearNavigationState();
182
+ if (event.defaultPrevented) cancelPreparation();
95
183
  });
96
184
  const loader = navigation.loader;
97
185
  navigation.loader = async () => {
98
- await loader();
99
- if (!event.defaultPrevented) {
100
- await prepareNavigationFont(navigation.newDocument, navigation.signal);
186
+ try {
187
+ await loader();
188
+ if (event.defaultPrevented) cancelPreparation();
189
+ else {
190
+ await prepareNavigationFont(navigation.newDocument, navigation.signal);
191
+ }
192
+ } catch (error) {
193
+ cancelPreparation();
194
+ throw error;
101
195
  }
102
196
  };
103
197
  });
@@ -106,32 +200,34 @@ if (!transitionWindow.__STALUX_VT_LISTENER__) {
106
200
  const navigation = event as unknown as NavigationEvent;
107
201
  if (navigation.signal.aborted) return;
108
202
  const current = generation;
203
+ swappedNavigation = current;
109
204
  preserveHeaderMetrics(navigation.newDocument);
110
- _routeMotionActive = true;
111
205
  // Astro replaces the root attributes during swap. Carry state into the
112
206
  // new document; CSS keyframes read these data-* attributes to pick their
113
207
  // own direction rather than letting Astro's default `fade` pair apply.
114
- setNavigationState(navigation, navigation.newDocument.documentElement);
208
+ setNavigationState(navigation, preset, navigation.newDocument.documentElement);
209
+ // This release uses CSS/native VT only. Settle the existing installation
210
+ // gate without starting a second WAAPI effect; analytics/background keep
211
+ // the same shared ready/finished semantics and their existing listeners.
212
+ motion = prepareRouteMotion(navigation);
213
+ motion.start(null, { skip: true });
115
214
  const finish = () => {
116
215
  if (current === generation) clearNavigationState();
117
216
  };
118
- // ViewTransition.ready fires when pseudo-elements are painted out; we
119
- // use it as the handoff boundary so our WAAPI for new content starts
120
- // *after* the native swap has painted its snapshot.
121
- const native = navigation.viewTransition;
122
- Promise.resolve(native?.ready)
123
- .then(
124
- () => undefined,
125
- () => undefined,
126
- )
127
- .then(finish);
217
+ // Native ready starts the animation. Keep selectors until it finishes,
218
+ // including fallback/skip and abort; an older navigation cannot clear a
219
+ // newer one's state.
220
+ void motion.finished.then(finish, finish);
128
221
  });
129
222
 
130
223
  document.addEventListener("astro:after-swap", () => {
131
224
  setRouteState(window.location.pathname);
225
+ if (preset !== "none") updateFocusVisibility();
132
226
  });
133
227
 
134
228
  document.addEventListener("astro:page-load", () => {
229
+ // A previous route's scripts can finish while a newer loader is pending.
230
+ if (swappedNavigation === generation) pendingNavigation = 0;
135
231
  setRouteState(window.location.pathname);
136
232
  });
137
233
 
@@ -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), box-shadow 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 .65s ease-in-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{animation:.65s ease-in-out stalux-link-avatar-spin}.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,box-shadow .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)}}@keyframes stalux-word-word-glow{0%{box-shadow:0 0 30px var(--accent-50p), 0 0 80px var(--accent-30p), var(--shadow-lg);transform:scale(1.02)}to{box-shadow:0 0 20px var(--accent-40p), 0 0 60px var(--accent-20p), var(--shadow-lg);transform:scale(1)}}}@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 .65s ease-in-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)}}.stagger-children>:first-child{animation-delay:.1s}.stagger-children>:nth-child(2){animation-delay:.15s}.stagger-children>:nth-child(3){animation-delay:.2s}.stagger-children>:nth-child(4){animation-delay:.25s}.stagger-children>:nth-child(5){animation-delay:.3s}.stagger-children>:nth-child(n+6){animation-delay:.35s}@keyframes stalux-vt-old-fwd{0%{opacity:1;transform:translate(0,0)}45%{opacity:.5}to{opacity:0;transform:translate(-6%)}}@keyframes stalux-vt-new-fwd{0%{opacity:0;filter:blur(1.2px);transform:translate(6%)scale(.985)}60%{opacity:.9;filter:blur();transform:translate(-.8%)scale(1)}to{opacity:1;filter:blur();transform:translate(0,0)}}@keyframes stalux-vt-old-back{0%{opacity:1;transform:translate(0,0)}45%{opacity:.5}to{opacity:0;transform:translate(6%)}}@keyframes stalux-vt-new-back{0%{opacity:0;filter:blur(1.2px);transform:translate(-6%)scale(.985)}60%{opacity:.9;filter:blur();transform:translate(.8%)scale(1)}to{opacity:1;filter:blur();transform:translate(0,0)}}html[data-astro-transition=forward]::view-transition-old(stalux-page){animation:.38s cubic-bezier(.22,.72,.22,1) both stalux-vt-old-fwd}html[data-astro-transition=forward]::view-transition-new(stalux-page){animation:.46s cubic-bezier(.22,.72,.22,1) both stalux-vt-new-fwd}html[data-astro-transition=back]::view-transition-old(stalux-page){animation:.38s cubic-bezier(.22,.72,.22,1) both stalux-vt-old-back}html[data-astro-transition=back]::view-transition-new(stalux-page){animation:.46s cubic-bezier(.22,.72,.22,1) both stalux-vt-new-back}@keyframes stalux-vt-side-out{to{opacity:0;transform:translate3d(var(--stalux-side-out-x,-14px), 0, 0)}}@keyframes stalux-vt-side-in{0%{opacity:0;transform:translate3d(var(--stalux-side-in-x,14px), 0, 0)}to{opacity:1;transform:translate(0,0)}}html,[data-astro-transition-persist],[data-stalux-site-header],[data-stalux-site-header] *,.bg-layer,.bg-layer *,[data-stalux-scroll-sentinel],[data-stalux-scroll-sentinel] *,[data-stalux-back-to-top],[data-stalux-back-to-top] *{view-transition-name:none!important}[data-stalux-scroll-sentinel]{visibility:hidden;pointer-events:none;width:1px;height:1px;position:absolute;top:240px;left:0}@keyframes stalux-taxonomy-enter{0%{opacity:0;transform:translate(12px)}to{opacity:1;transform:translate(0)}}@keyframes stalux-taxonomy-enter-back{0%{opacity:0;transform:translate(-12px)}to{opacity:1;transform:translate(0)}}@keyframes stalux-article-enter{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}@keyframes stalux-article-enter-back{0%{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:translateY(0)}}@keyframes stalux-sidebar-left-in{0%{opacity:0;transform:translate(-14px)}to{opacity:1;transform:translate(0)}}@keyframes stalux-sidebar-left-out{to{opacity:0;transform:translate(-10px)}}@keyframes stalux-sidebar-left-back-in{0%{opacity:0;transform:translate(14px)}to{opacity:1;transform:translate(0)}}@keyframes stalux-sidebar-left-back-out{to{opacity:0;transform:translate(10px)}}@keyframes stalux-sidebar-right-in{0%{opacity:0;transform:translate(14px)}to{opacity:1;transform:translate(0)}}@keyframes stalux-sidebar-right-out{to{opacity:0;transform:translate(10px)}}@keyframes stalux-sidebar-right-back-in{0%{opacity:0;transform:translate(-14px)}to{opacity:1;transform:translate(0)}}@keyframes stalux-sidebar-right-back-out{to{opacity:0;transform:translate(-10px)}}@media (prefers-reduced-motion:reduce){::view-transition-group(*),::view-transition-old(*),::view-transition-new(*){filter:none!important;animation-duration:1ms!important;animation-delay:0s!important;transform:none!important}.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-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), box-shadow 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 .65s ease-in-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{animation:.65s ease-in-out stalux-link-avatar-spin}.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,box-shadow .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)}}@keyframes stalux-word-word-glow{0%{box-shadow:0 0 30px var(--accent-50p), 0 0 80px var(--accent-30p), var(--shadow-lg);transform:scale(1.02)}to{box-shadow:0 0 20px var(--accent-40p), 0 0 60px var(--accent-20p), var(--shadow-lg);transform:scale(1)}}}@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 .65s ease-in-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)}}.stagger-children>:first-child{animation-delay:.1s}.stagger-children>:nth-child(2){animation-delay:.15s}.stagger-children>:nth-child(3){animation-delay:.2s}.stagger-children>:nth-child(4){animation-delay:.25s}.stagger-children>:nth-child(5){animation-delay:.3s}.stagger-children>:nth-child(n+6){animation-delay:.35s}html,[data-astro-transition-persist],.stalux-main,.stalux-main *,.bg-layer,.bg-layer *,[data-stalux-scroll-sentinel],[data-stalux-back-to-top]{view-transition-name:none!important}html[data-stalux-vt-preset] .stalux-main [data-stalux-motion-focus][data-stalux-motion-visible=true]{view-transition-name:stalux-focus!important}html[data-stalux-vt-preset=none] .stalux-main [data-stalux-motion-focus][data-stalux-motion-visible=true]{view-transition-name:none!important}::view-transition-group(stalux-focus){animation:none}::view-transition-image-pair(stalux-focus){isolation:auto}::view-transition-old(stalux-focus){animation:none;display:none}::view-transition-new(stalux-focus){mix-blend-mode:normal;animation:.12s cubic-bezier(.2,.7,.2,1) both stalux-focus-fade}html[data-stalux-vt-preset=enter]::view-transition-new(stalux-focus){animation:.16s cubic-bezier(.2,.7,.2,1) both stalux-focus-enter}html[data-stalux-vt-preset=up]::view-transition-new(stalux-focus){animation:.14s cubic-bezier(.2,.7,.2,1) both stalux-focus-up}html[data-stalux-vt-preset=taxonomy]::view-transition-new(stalux-focus){animation:.14s cubic-bezier(.2,.7,.2,1) both stalux-focus-fade}html[data-stalux-vt-preset=previous]::view-transition-new(stalux-focus){animation:.16s cubic-bezier(.2,.7,.2,1) both stalux-focus-previous}html[data-stalux-vt-preset=next]::view-transition-new(stalux-focus){animation:.16s cubic-bezier(.2,.7,.2,1) both stalux-focus-next}html[data-stalux-vt-preset=home]::view-transition-new(stalux-focus){animation:.18s cubic-bezier(.2,.7,.2,1) both stalux-focus-home}html[data-stalux-vt-preset=restore]::view-transition-new(stalux-focus){animation:.1s cubic-bezier(.2,.7,.2,1) both stalux-focus-restore}html[data-stalux-vt-preset=error]::view-transition-new(stalux-focus){animation:.1s cubic-bezier(.2,.7,.2,1) both stalux-focus-fade}@keyframes stalux-focus-fade{0%{opacity:.86}to{opacity:1}}@keyframes stalux-focus-enter{0%{opacity:.86;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}@keyframes stalux-focus-up{0%{opacity:.9;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}@keyframes stalux-focus-previous{0%{opacity:.9;transform:translate(-8px)}to{opacity:1;transform:translate(0)}}@keyframes stalux-focus-next{0%{opacity:.9;transform:translate(8px)}to{opacity:1;transform:translate(0)}}@keyframes stalux-focus-home{0%{opacity:.9;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}@keyframes stalux-focus-restore{0%{opacity:.96}to{opacity:1}}@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 (width<=768px){html[data-stalux-vt-preset]::view-transition-new(stalux-focus){animation:.12s cubic-bezier(.2,.7,.2,1) both stalux-focus-fade}html[data-stalux-vt-preset=restore]::view-transition-new(stalux-focus){animation:.1s cubic-bezier(.2,.7,.2,1) both stalux-focus-restore}}@media (prefers-reduced-motion:reduce){html[data-stalux-vt-preset] .stalux-main [data-stalux-motion-focus][data-stalux-motion-visible=true]{view-transition-name:none!important}::view-transition-group(*),::view-transition-old(*),::view-transition-new(*){filter:none!important;animation:none!important;transform:none!important}.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*/
@@ -28,296 +28,311 @@
28
28
  animation-delay: 0.35s;
29
29
  }
30
30
 
31
- /* =========================================================
32
- View Transitions:主内容 slide + 淡入 + 新内容 scale+blur 到清晰,
33
- 与 Astro 默认的纯淡入淡出不同 — 旧内容沿方向快速滑出,新内容对向滑入
34
- 带轻微 scale 从 0.985 拉回 1,配合 1.2px blur 再还原。
35
- forwards (direction = "forward" | "push"): 旧内容向左滑出,新内容从右滑入
36
- backwards (direction = "back" | "traverse"): 镜像方向
37
- 持久壳层(header、背景、sentinel、back-to-top 按钮)设
38
- view-transition-name: none 不生成快照、原地即时更新;<main>(stalux-page)
39
- 及其内部命名元素(标题/侧边栏/文章容器等)保留各自的 VT 组,
40
- 由方向伪元素规则 + 局部 transition:animate 分层驱动。
41
- ========================================================= */
42
-
43
- /* 主内容 View Transition 动画(方向感知:前进/回退镜像)。
44
- 方向机制:Astro 路由器在 startViewTransition 之前给 <html> 写
45
- data-astro-transition="forward|back"(router.js:369),整个动画期间保留,
46
- 直到 viewTransition.finished 才移除(router.js:423)。::view-transition-*
47
- 伪元素树的 originating element 就是 <html>,因此 html[attr]::view-transition-old(x)
48
- 可以按方向匹配(popstate 时 router.js:470 按 history index 给出真实方向)。
49
- ⚠ 约束 1:伪元素规则必须写成**直接引用 keyframes 的完整 animation shorthand** ——
50
- var() fallback 字符串(`var(--x, keyframesName)`)不会被 Rolldown tree-shake
51
- 静态追踪,fallback 里的 keyframes 名会被判为"未引用"而裁掉。
52
- ⚠ 约束 2:::view-transition-old/new() 参数里只能放自定义 transition-name 或 *,
53
- 不能放属性选择器(legacy 实验语法,lightningcss minify 不支持)。
54
- ⚠ 约束 3:任意祖先元素(body/div 等)做 originating element 不成立;
55
- 只有 <html> 复合选择器有效。 */
56
-
57
- /* forward:进入下一层 —— 旧页向左滑出,新页自右滑入并 scale+blur 收敛 */
58
- @keyframes stalux-vt-old-fwd {
59
- 0% {
31
+ /* Route motion captures one visible heading, never a long main/article.
32
+ The router owns data-stalux-vt-preset and confirms visibility once per DOM.
33
+ Keep literal keyframe references: production CSS removes unreferenced frames. */
34
+ html,
35
+ [data-astro-transition-persist],
36
+ .stalux-main,
37
+ .stalux-main *,
38
+ .bg-layer,
39
+ .bg-layer *,
40
+ [data-stalux-scroll-sentinel],
41
+ [data-stalux-back-to-top] {
42
+ view-transition-name: none !important;
43
+ }
44
+
45
+ html[data-stalux-vt-preset]
46
+ .stalux-main
47
+ [data-stalux-motion-focus][data-stalux-motion-visible="true"] {
48
+ view-transition-name: stalux-focus !important;
49
+ }
50
+
51
+ html[data-stalux-vt-preset="none"]
52
+ .stalux-main
53
+ [data-stalux-motion-focus][data-stalux-motion-visible="true"] {
54
+ view-transition-name: none !important;
55
+ }
56
+
57
+ /* Different headings must not interpolate width, height, position or text size.
58
+ Old content stays readable until swap; only the small new heading animates. */
59
+ ::view-transition-group(stalux-focus) {
60
+ animation: none;
61
+ }
62
+
63
+ ::view-transition-image-pair(stalux-focus) {
64
+ isolation: auto;
65
+ }
66
+
67
+ ::view-transition-old(stalux-focus) {
68
+ display: none;
69
+ animation: none;
70
+ }
71
+
72
+ ::view-transition-new(stalux-focus) {
73
+ mix-blend-mode: normal;
74
+ animation: stalux-focus-fade 120ms cubic-bezier(0.2, 0.7, 0.2, 1) both;
75
+ }
76
+
77
+ html[data-stalux-vt-preset="enter"]::view-transition-new(stalux-focus) {
78
+ animation: stalux-focus-enter 160ms cubic-bezier(0.2, 0.7, 0.2, 1) both;
79
+ }
80
+
81
+ html[data-stalux-vt-preset="up"]::view-transition-new(stalux-focus) {
82
+ animation: stalux-focus-up 140ms cubic-bezier(0.2, 0.7, 0.2, 1) both;
83
+ }
84
+
85
+ html[data-stalux-vt-preset="taxonomy"]::view-transition-new(stalux-focus) {
86
+ animation: stalux-focus-fade 140ms cubic-bezier(0.2, 0.7, 0.2, 1) both;
87
+ }
88
+
89
+ html[data-stalux-vt-preset="previous"]::view-transition-new(stalux-focus) {
90
+ animation: stalux-focus-previous 160ms cubic-bezier(0.2, 0.7, 0.2, 1) both;
91
+ }
92
+
93
+ html[data-stalux-vt-preset="next"]::view-transition-new(stalux-focus) {
94
+ animation: stalux-focus-next 160ms cubic-bezier(0.2, 0.7, 0.2, 1) both;
95
+ }
96
+
97
+ html[data-stalux-vt-preset="home"]::view-transition-new(stalux-focus) {
98
+ animation: stalux-focus-home 180ms cubic-bezier(0.2, 0.7, 0.2, 1) both;
99
+ }
100
+
101
+ html[data-stalux-vt-preset="restore"]::view-transition-new(stalux-focus) {
102
+ animation: stalux-focus-restore 100ms cubic-bezier(0.2, 0.7, 0.2, 1) both;
103
+ }
104
+
105
+ html[data-stalux-vt-preset="error"]::view-transition-new(stalux-focus) {
106
+ animation: stalux-focus-fade 100ms cubic-bezier(0.2, 0.7, 0.2, 1) both;
107
+ }
108
+
109
+ @keyframes stalux-focus-fade {
110
+ from {
111
+ opacity: 0.86;
112
+ }
113
+ to {
60
114
  opacity: 1;
61
- transform: translate3d(0, 0, 0);
62
115
  }
63
- 45% {
64
- opacity: 0.5;
116
+ }
117
+
118
+ @keyframes stalux-focus-enter {
119
+ from {
120
+ opacity: 0.86;
121
+ transform: translateY(6px);
65
122
  }
66
- 100% {
67
- opacity: 0;
68
- transform: translate3d(-6%, 0, 0);
123
+ to {
124
+ opacity: 1;
125
+ transform: translateY(0);
69
126
  }
70
127
  }
71
128
 
72
- @keyframes stalux-vt-new-fwd {
73
- 0% {
74
- opacity: 0;
75
- transform: translate3d(6%, 0, 0) scale(0.985);
76
- filter: blur(1.2px);
77
- }
78
- 60% {
129
+ @keyframes stalux-focus-up {
130
+ from {
79
131
  opacity: 0.9;
80
- transform: translate3d(-0.8%, 0, 0) scale(1);
81
- filter: blur(0px);
132
+ transform: translateY(-4px);
82
133
  }
83
- 100% {
134
+ to {
84
135
  opacity: 1;
85
- transform: translate3d(0, 0, 0);
86
- filter: blur(0px);
136
+ transform: translateY(0);
87
137
  }
88
138
  }
89
139
 
90
- /* back:返回上一层 —— 镜像:旧页向右滑出,新页自左滑入 */
91
- @keyframes stalux-vt-old-back {
92
- 0% {
93
- opacity: 1;
94
- transform: translate3d(0, 0, 0);
95
- }
96
- 45% {
97
- opacity: 0.5;
140
+ @keyframes stalux-focus-previous {
141
+ from {
142
+ opacity: 0.9;
143
+ transform: translateX(-8px);
98
144
  }
99
- 100% {
100
- opacity: 0;
101
- transform: translate3d(6%, 0, 0);
145
+ to {
146
+ opacity: 1;
147
+ transform: translateX(0);
102
148
  }
103
149
  }
104
150
 
105
- @keyframes stalux-vt-new-back {
106
- 0% {
107
- opacity: 0;
108
- transform: translate3d(-6%, 0, 0) scale(0.985);
109
- filter: blur(1.2px);
110
- }
111
- 60% {
151
+ @keyframes stalux-focus-next {
152
+ from {
112
153
  opacity: 0.9;
113
- transform: translate3d(0.8%, 0, 0) scale(1);
114
- filter: blur(0px);
154
+ transform: translateX(8px);
115
155
  }
116
- 100% {
156
+ to {
117
157
  opacity: 1;
118
- transform: translate3d(0, 0, 0);
119
- filter: blur(0px);
158
+ transform: translateX(0);
120
159
  }
121
160
  }
122
161
 
123
- html[data-astro-transition="forward"]::view-transition-old(stalux-page) {
124
- animation: stalux-vt-old-fwd 380ms cubic-bezier(0.22, 0.72, 0.22, 1) both;
125
- }
126
-
127
- html[data-astro-transition="forward"]::view-transition-new(stalux-page) {
128
- animation: stalux-vt-new-fwd 460ms cubic-bezier(0.22, 0.72, 0.22, 1) both;
129
- }
130
-
131
- html[data-astro-transition="back"]::view-transition-old(stalux-page) {
132
- animation: stalux-vt-old-back 380ms cubic-bezier(0.22, 0.72, 0.22, 1) both;
133
- }
134
-
135
- html[data-astro-transition="back"]::view-transition-new(stalux-page) {
136
- animation: stalux-vt-new-back 460ms cubic-bezier(0.22, 0.72, 0.22, 1) both;
162
+ @keyframes stalux-focus-home {
163
+ from {
164
+ opacity: 0.9;
165
+ transform: translateY(4px);
166
+ }
167
+ to {
168
+ opacity: 1;
169
+ transform: translateY(0);
170
+ }
137
171
  }
138
172
 
139
- /* 侧边栏 — 独立于 root:沿内容方向做 12px 平移 + 淡入淡出,
140
- 让文章详情页左右栏与主内容分层出现。 */
141
- @keyframes stalux-vt-side-out {
173
+ @keyframes stalux-focus-restore {
174
+ from {
175
+ opacity: 0.96;
176
+ }
142
177
  to {
143
- opacity: 0;
144
- transform: translate3d(var(--stalux-side-out-x, -14px), 0, 0);
178
+ opacity: 1;
145
179
  }
146
180
  }
147
181
 
148
- @keyframes stalux-vt-side-in {
182
+ /* Public transition helpers retain their names as opacity-only compatibility
183
+ frames. Theme layouts no longer use them to move large content/sidebars. */
184
+ @keyframes stalux-page-exit {
149
185
  from {
150
- opacity: 0;
151
- transform: translate3d(var(--stalux-side-in-x, 14px), 0, 0);
186
+ opacity: 1;
152
187
  }
153
188
  to {
154
189
  opacity: 1;
155
- transform: translate3d(0, 0, 0);
156
190
  }
157
191
  }
158
-
159
- /* 持久壳层:header、背景、sentinel、back-to-top 按钮不参与 View Transition 伪元素;
160
- 直接设 view-transition-name: none 让浏览器为它们各自做即时更新。
161
- 这避免了原生快照把大体积 header 或整张背景图塞进 pseudo-element 树、
162
- 也与 view-transitions.ts 里的 .scrollY 优化保持一致 — 不强制 UI 同步。
163
- ⚠ 注意:html 也必须压制 —— 压掉 root 组后整页快照不存在,
164
- 只有 stalux-page 与内部命名元素生成各自组,避免整页 fade 叠加。
165
- ⚠ 不要把 .stalux-main / .stalux-main * 加进来:那会连 stalux-page 组
166
- 一起压掉,方向伪元素规则将全部失配(1.39.4 曾因此动画全死、路由瞬时切换)。 */
167
- html,
168
- [data-astro-transition-persist],
169
- [data-stalux-site-header],
170
- [data-stalux-site-header] *,
171
- .bg-layer,
172
- .bg-layer *,
173
- [data-stalux-scroll-sentinel],
174
- [data-stalux-scroll-sentinel] *,
175
- [data-stalux-back-to-top],
176
- [data-stalux-back-to-top] * {
177
- view-transition-name: none !important;
192
+ @keyframes stalux-page-enter {
193
+ from {
194
+ opacity: 0.9;
195
+ }
196
+ to {
197
+ opacity: 1;
198
+ }
178
199
  }
179
-
180
- /* BackToTop visibility sentinel */
181
- [data-stalux-scroll-sentinel] {
182
- position: absolute;
183
- top: 240px;
184
- left: 0;
185
- width: 1px;
186
- height: 1px;
187
- visibility: hidden;
188
- pointer-events: none;
200
+ @keyframes stalux-page-enter-back {
201
+ from {
202
+ opacity: 0.96;
203
+ }
204
+ to {
205
+ opacity: 1;
206
+ }
189
207
  }
190
-
191
- /* =========================================================
192
- 下面保留的是 Astro transition:animate 用的 web 动画 keyframes,
193
- 供 getSidebarAnimation("left"|"right") 和分类/文章页内局部
194
- transition:animate 消费;与 View Transition 伪元素层互不冲突。
195
- ========================================================= */
196
-
197
208
  @keyframes stalux-taxonomy-enter {
198
209
  from {
199
- opacity: 0;
200
- transform: translateX(12px);
210
+ opacity: 0.9;
201
211
  }
202
212
  to {
203
213
  opacity: 1;
204
- transform: translateX(0);
205
214
  }
206
215
  }
207
-
208
216
  @keyframes stalux-taxonomy-enter-back {
209
217
  from {
210
- opacity: 0;
211
- transform: translateX(-12px);
218
+ opacity: 0.96;
212
219
  }
213
220
  to {
214
221
  opacity: 1;
215
- transform: translateX(0);
216
222
  }
217
223
  }
218
-
219
224
  @keyframes stalux-article-enter {
220
225
  from {
221
- opacity: 0;
222
- transform: translateY(6px);
226
+ opacity: 0.9;
223
227
  }
224
228
  to {
225
229
  opacity: 1;
226
- transform: translateY(0);
227
230
  }
228
231
  }
229
-
230
232
  @keyframes stalux-article-enter-back {
231
233
  from {
232
- opacity: 0;
233
- transform: translateY(-6px);
234
+ opacity: 0.96;
234
235
  }
235
236
  to {
236
237
  opacity: 1;
237
- transform: translateY(0);
238
238
  }
239
239
  }
240
-
241
240
  @keyframes stalux-sidebar-left-in {
242
241
  from {
243
- opacity: 0;
244
- transform: translateX(-14px);
242
+ opacity: 0.96;
245
243
  }
246
244
  to {
247
245
  opacity: 1;
248
- transform: translateX(0);
249
246
  }
250
247
  }
251
-
252
248
  @keyframes stalux-sidebar-left-out {
249
+ from {
250
+ opacity: 1;
251
+ }
253
252
  to {
254
- opacity: 0;
255
- transform: translateX(-10px);
253
+ opacity: 1;
256
254
  }
257
255
  }
258
-
259
256
  @keyframes stalux-sidebar-left-back-in {
260
257
  from {
261
- opacity: 0;
262
- transform: translateX(14px);
258
+ opacity: 0.96;
263
259
  }
264
260
  to {
265
261
  opacity: 1;
266
- transform: translateX(0);
267
262
  }
268
263
  }
269
-
270
264
  @keyframes stalux-sidebar-left-back-out {
265
+ from {
266
+ opacity: 1;
267
+ }
271
268
  to {
272
- opacity: 0;
273
- transform: translateX(10px);
269
+ opacity: 1;
274
270
  }
275
271
  }
276
-
277
272
  @keyframes stalux-sidebar-right-in {
278
273
  from {
279
- opacity: 0;
280
- transform: translateX(14px);
274
+ opacity: 0.96;
281
275
  }
282
276
  to {
283
277
  opacity: 1;
284
- transform: translateX(0);
285
278
  }
286
279
  }
287
-
288
280
  @keyframes stalux-sidebar-right-out {
281
+ from {
282
+ opacity: 1;
283
+ }
289
284
  to {
290
- opacity: 0;
291
- transform: translateX(10px);
285
+ opacity: 1;
292
286
  }
293
287
  }
294
-
295
288
  @keyframes stalux-sidebar-right-back-in {
296
289
  from {
297
- opacity: 0;
298
- transform: translateX(-14px);
290
+ opacity: 0.96;
299
291
  }
300
292
  to {
301
293
  opacity: 1;
302
- transform: translateX(0);
303
294
  }
304
295
  }
305
-
306
296
  @keyframes stalux-sidebar-right-back-out {
297
+ from {
298
+ opacity: 1;
299
+ }
307
300
  to {
308
- opacity: 0;
309
- transform: translateX(-10px);
301
+ opacity: 1;
302
+ }
303
+ }
304
+
305
+ [data-stalux-scroll-sentinel] {
306
+ position: absolute;
307
+ top: 240px;
308
+ left: 0;
309
+ width: 1px;
310
+ height: 1px;
311
+ visibility: hidden;
312
+ pointer-events: none;
313
+ }
314
+
315
+ /* Small screens get the same deterministic timing with no spatial motion. */
316
+ @media (max-width: 768px) {
317
+ html[data-stalux-vt-preset]::view-transition-new(stalux-focus) {
318
+ animation: stalux-focus-fade 120ms cubic-bezier(0.2, 0.7, 0.2, 1) both;
319
+ }
320
+ html[data-stalux-vt-preset="restore"]::view-transition-new(stalux-focus) {
321
+ animation: stalux-focus-restore 100ms cubic-bezier(0.2, 0.7, 0.2, 1) both;
310
322
  }
311
323
  }
312
324
 
313
- /* prefers-reduced-motion:关闭 View Transition 伪元素上的所有动画,
314
- 但保留伪元素本身(浏览器会直接从 old 切到 new,视觉等价于无动画的软导航) */
315
325
  @media (prefers-reduced-motion: reduce) {
326
+ html[data-stalux-vt-preset]
327
+ .stalux-main
328
+ [data-stalux-motion-focus][data-stalux-motion-visible="true"] {
329
+ view-transition-name: none !important;
330
+ }
331
+
316
332
  ::view-transition-group(*),
317
333
  ::view-transition-old(*),
318
334
  ::view-transition-new(*) {
319
- animation-duration: 1ms !important;
320
- animation-delay: 0ms !important;
335
+ animation: none !important;
321
336
  filter: none !important;
322
337
  transform: none !important;
323
338
  }
@@ -0,0 +1,63 @@
1
+ import { getRouteKind, normalizePublicPath } from "./public-routes";
2
+
3
+ export type RouteMotionPreset =
4
+ | "none"
5
+ | "fade"
6
+ | "enter"
7
+ | "up"
8
+ | "taxonomy"
9
+ | "previous"
10
+ | "next"
11
+ | "home"
12
+ | "restore"
13
+ | "error";
14
+
15
+ interface MotionContext {
16
+ from: URL;
17
+ to: URL;
18
+ navigationType?: string;
19
+ intent?: string;
20
+ reducedMotion?: boolean;
21
+ browserMotion?: boolean;
22
+ hidden?: boolean;
23
+ }
24
+
25
+ /** Choose a visual hint, never a navigation or scroll operation. */
26
+ export function getRouteMotionPreset(context: MotionContext): RouteMotionPreset {
27
+ const { from, to } = context;
28
+ const source = getRouteKind(from.pathname);
29
+ const target = getRouteKind(to.pathname);
30
+ if (
31
+ context.hidden ||
32
+ context.reducedMotion ||
33
+ context.browserMotion ||
34
+ from.origin !== to.origin ||
35
+ source === "other" ||
36
+ target === "other" ||
37
+ (normalizePublicPath(from.pathname) === normalizePublicPath(to.pathname) &&
38
+ from.search === to.search)
39
+ ) {
40
+ return "none";
41
+ }
42
+ // Both directions restore an existing history entry. A push to a parent
43
+ // route is not a history traversal, and an article's previous/next is not back.
44
+ if (context.navigationType === "traverse") return "restore";
45
+ if (context.navigationType === "replace") return "fade";
46
+ if (target === "not-found") return "error";
47
+ if (source === "not-found") return "fade";
48
+ if (target === "home") return "home";
49
+ if (source === "article" && target === "article") {
50
+ return context.intent === "previous" || context.intent === "next" ? context.intent : "fade";
51
+ }
52
+ if (target === "article") return "enter";
53
+ if (target === "tags-detail" || target === "categories-detail") return "taxonomy";
54
+ if (
55
+ (source === "article" &&
56
+ (target === "archive" || target === "tags-index" || target === "categories-index")) ||
57
+ (source === "tags-detail" && target === "tags-index") ||
58
+ (source === "categories-detail" && target === "categories-index")
59
+ ) {
60
+ return "up";
61
+ }
62
+ return source === "home" ? "enter" : "fade";
63
+ }
@@ -35,10 +35,10 @@ export type RouteAnimation = {
35
35
  };
36
36
  };
37
37
 
38
- const easing = "cubic-bezier(0.22, 0.72, 0.22, 1)";
38
+ const easing = "cubic-bezier(0.2, 0.7, 0.2, 1)";
39
39
  const exitAnimation: TransitionAnimation = {
40
40
  name: "stalux-page-exit",
41
- duration: "0.14s",
41
+ duration: "0.1s",
42
42
  easing,
43
43
  fillMode: "both",
44
44
  };
@@ -49,7 +49,7 @@ function createRouteAnimation(name: string, backName = `${name}-back`): RouteAni
49
49
  old: exitAnimation,
50
50
  new: {
51
51
  name: productionStyleName(`stalux-${name}`),
52
- duration: "0.22s",
52
+ duration: "0.16s",
53
53
  easing,
54
54
  fillMode: "both",
55
55
  },
@@ -58,7 +58,7 @@ function createRouteAnimation(name: string, backName = `${name}-back`): RouteAni
58
58
  old: exitAnimation,
59
59
  new: {
60
60
  name: productionStyleName(`stalux-${backName}`),
61
- duration: "0.22s",
61
+ duration: "0.16s",
62
62
  easing,
63
63
  fillMode: "both",
64
64
  },
@@ -92,7 +92,7 @@ function createSidebarAnimation(
92
92
  ): TransitionAnimation {
93
93
  return {
94
94
  name: productionStyleName(`stalux-sidebar-${side}-${backwards ? "back-" : ""}${phase}`),
95
- duration: "0.22s",
95
+ duration: "0.16s",
96
96
  easing,
97
97
  fillMode: "both",
98
98
  };