@walrosproject/ui 0.4.0 → 0.4.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 +3 -3
- package/dist/index.d.ts +23 -21
- package/dist/index.js +167 -211
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ npm install @walrosproject/ui
|
|
|
8
8
|
|
|
9
9
|
## Cambio de tema completo
|
|
10
10
|
|
|
11
|
-
`WalrosThemeTransition`
|
|
11
|
+
`WalrosThemeTransition` muestra exclusivamente el glitch visual de walros.org: bandas, destellos y sacudida de la página, sin silueta ni logo. El glitch dura **1.500 ms**; el tema cambia a los **610 ms** y el audio se detiene al concluir los **1.500 ms**. La entrada de la página es un componente independiente.
|
|
12
12
|
|
|
13
13
|
```tsx
|
|
14
14
|
import {
|
|
@@ -48,13 +48,13 @@ const theme = useWalrosTheme({
|
|
|
48
48
|
|
|
49
49
|
## Portal de entrada
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
`WalrosPortalTransition` muestra la morsa cromada **debajo** de la máscara negra y la acerca al centro mientras se abre el portal. Dura **900 ms** y no espera a que se descargue la imagen para iniciar; el logo desaparece antes de que se revele la página.
|
|
52
52
|
|
|
53
53
|
```tsx
|
|
54
54
|
<WalrosPortalTransition storageMode="always" />
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
-
`storageMode` acepta `always`, `session` y `once`.
|
|
57
|
+
`storageMode` acepta `always`, `session` y `once`. Para usar el modelo 3D real de walros.org como fondo, renderízalo en tu escena y pasa sus límites proyectados a `Walros3DPortalTransition`:
|
|
58
58
|
|
|
59
59
|
```tsx
|
|
60
60
|
<Walros3DPortalTransition
|
package/dist/index.d.ts
CHANGED
|
@@ -1,18 +1,6 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ImgHTMLAttributes, CSSProperties, RefObject } from 'react';
|
|
3
3
|
|
|
4
|
-
type WalrosPortalTransitionProps = {
|
|
5
|
-
duration?: number;
|
|
6
|
-
onComplete?: () => void;
|
|
7
|
-
backgroundColor?: string;
|
|
8
|
-
enabled?: boolean;
|
|
9
|
-
storageMode?: "always" | "session" | "once";
|
|
10
|
-
storageKey?: string;
|
|
11
|
-
zIndex?: number;
|
|
12
|
-
};
|
|
13
|
-
/** Exact walros.org black portal, including its chrome logo and 900 ms curve. */
|
|
14
|
-
declare function WalrosPortalTransition({ duration, onComplete, backgroundColor, enabled, storageMode, storageKey, zIndex, }: WalrosPortalTransitionProps): react.ReactPortal | null;
|
|
15
|
-
|
|
16
4
|
type PortalOrigin = {
|
|
17
5
|
centerX: number;
|
|
18
6
|
centerY: number;
|
|
@@ -26,24 +14,38 @@ type Walros3DPortalTransitionProps = {
|
|
|
26
14
|
backgroundColor?: string;
|
|
27
15
|
zIndex?: number;
|
|
28
16
|
lockScroll?: boolean;
|
|
17
|
+
/** An optional image that follows the portal exactly and fades before reveal. */
|
|
18
|
+
logoUrl?: string | false;
|
|
19
|
+
};
|
|
20
|
+
declare function Walros3DPortalTransition({ origin, onComplete, duration, backgroundColor, zIndex, lockScroll, logoUrl, }: Walros3DPortalTransitionProps): react.JSX.Element | null;
|
|
21
|
+
|
|
22
|
+
type WalrosPortalTransitionProps = {
|
|
23
|
+
duration?: number;
|
|
24
|
+
onComplete?: () => void;
|
|
25
|
+
backgroundColor?: string;
|
|
26
|
+
enabled?: boolean;
|
|
27
|
+
storageMode?: "always" | "session" | "once";
|
|
28
|
+
storageKey?: string;
|
|
29
|
+
zIndex?: number;
|
|
30
|
+
/** Projected bounds of an existing 3D logo, as on walros.org. */
|
|
31
|
+
origin?: PortalOrigin;
|
|
32
|
+
/** Intro logo shown beneath the black mask; set false when using an existing 3D logo. */
|
|
33
|
+
logoUrl?: string | false;
|
|
29
34
|
};
|
|
30
|
-
|
|
35
|
+
/** 900 ms walros.org entrance, with the logo confined below its black mask. */
|
|
36
|
+
declare function WalrosPortalTransition({ duration, onComplete, backgroundColor, enabled, storageMode, storageKey, zIndex, origin, logoUrl, }: WalrosPortalTransitionProps): react.ReactPortal | null;
|
|
31
37
|
|
|
32
38
|
type WalrosThemeTransitionProps = {
|
|
33
39
|
/** Pass the `glitching` value returned by `useWalrosTheme`. */
|
|
34
40
|
active: boolean;
|
|
35
|
-
/** The
|
|
41
|
+
/** @deprecated The theme change has no portal; retained for source compatibility. */
|
|
36
42
|
portalDuration?: number;
|
|
37
|
-
/** The
|
|
43
|
+
/** @deprecated The theme change has no logo; retained for source compatibility. */
|
|
38
44
|
logoUrl?: string;
|
|
39
45
|
zIndex?: number;
|
|
40
46
|
};
|
|
41
|
-
/**
|
|
42
|
-
|
|
43
|
-
* while the matching glitch and sound from useWalrosTheme run for 1,500 ms.
|
|
44
|
-
* Mount once near the app root and pass `active={glitching}`.
|
|
45
|
-
*/
|
|
46
|
-
declare function WalrosThemeTransition({ active, portalDuration, logoUrl, zIndex, }: WalrosThemeTransitionProps): react.ReactPortal | null;
|
|
47
|
+
/** The walros.org theme effect is a shake and glitch, without an intro logo. */
|
|
48
|
+
declare function WalrosThemeTransition({ active, zIndex, }: WalrosThemeTransitionProps): react.ReactPortal | null;
|
|
47
49
|
|
|
48
50
|
declare function DirectionalCursor(): react.JSX.Element;
|
|
49
51
|
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/components/WalrosPortalTransition.tsx
|
|
2
|
-
import { useState as
|
|
3
|
-
import { createPortal
|
|
2
|
+
import { useState as useState3 } from "react";
|
|
3
|
+
import { createPortal } from "react-dom";
|
|
4
4
|
|
|
5
5
|
// src/assets.ts
|
|
6
6
|
var walrosPortalSilhouetteUrl = new URL(
|
|
@@ -24,10 +24,6 @@ var walrosThemeGlitchSoundUrl = new URL(
|
|
|
24
24
|
import.meta.url
|
|
25
25
|
).href;
|
|
26
26
|
|
|
27
|
-
// src/components/WalrosThemeTransition.tsx
|
|
28
|
-
import { useEffect as useEffect2, useLayoutEffect as useLayoutEffect3, useRef as useRef2, useState as useState3 } from "react";
|
|
29
|
-
import { createPortal } from "react-dom";
|
|
30
|
-
|
|
31
27
|
// src/components/Walros3DPortalTransition.tsx
|
|
32
28
|
import { useEffect, useId, useLayoutEffect, useRef, useState } from "react";
|
|
33
29
|
import gsap from "gsap";
|
|
@@ -54,7 +50,8 @@ function Walros3DPortalTransition({
|
|
|
54
50
|
duration = 900,
|
|
55
51
|
backgroundColor = "#000",
|
|
56
52
|
zIndex = 10001,
|
|
57
|
-
lockScroll = true
|
|
53
|
+
lockScroll = true,
|
|
54
|
+
logoUrl = false
|
|
58
55
|
}) {
|
|
59
56
|
const [visible, setVisible] = useState(true);
|
|
60
57
|
const [viewport, setViewport] = useState(() => ({
|
|
@@ -63,6 +60,7 @@ function Walros3DPortalTransition({
|
|
|
63
60
|
}));
|
|
64
61
|
const overlay = useRef(null);
|
|
65
62
|
const portal = useRef(null);
|
|
63
|
+
const logo = useRef(null);
|
|
66
64
|
const completeRef = useRef(onComplete);
|
|
67
65
|
completeRef.current = onComplete;
|
|
68
66
|
const maskId = `walros-3d-portal-${useId().replace(/:/g, "_")}`;
|
|
@@ -82,10 +80,10 @@ function Walros3DPortalTransition({
|
|
|
82
80
|
const initialScale = Math.min(origin.width / visibleWidth, origin.height / visibleHeight) * 0.985;
|
|
83
81
|
const initialX = origin.centerX - (visualCenterX - FOCUS_X) * initialScale;
|
|
84
82
|
const initialY = origin.centerY - (visualCenterY - FOCUS_Y) * initialScale;
|
|
85
|
-
const targetX = viewport.width / 2 - (visualCenterX - FOCUS_X) * initialScale;
|
|
86
|
-
const targetY = viewport.height / 2 - (visualCenterY - FOCUS_Y) * initialScale;
|
|
87
83
|
const diagonal = Math.hypot(viewport.width, viewport.height) / 2;
|
|
88
84
|
const finalScale = (diagonal + 80) / PORTAL_RADIUS * 1.15;
|
|
85
|
+
const targetX = viewport.width / 2 - (visualCenterX - FOCUS_X) * finalScale;
|
|
86
|
+
const targetY = viewport.height / 2 - (visualCenterY - FOCUS_Y) * finalScale;
|
|
89
87
|
const total = duration / 1e3;
|
|
90
88
|
gsap.set(portal.current, {
|
|
91
89
|
x: initialX,
|
|
@@ -93,6 +91,15 @@ function Walros3DPortalTransition({
|
|
|
93
91
|
scale: initialScale,
|
|
94
92
|
svgOrigin: "0 0"
|
|
95
93
|
});
|
|
94
|
+
if (logo.current) {
|
|
95
|
+
gsap.set(logo.current, {
|
|
96
|
+
x: initialX,
|
|
97
|
+
y: initialY,
|
|
98
|
+
scale: initialScale,
|
|
99
|
+
opacity: 1,
|
|
100
|
+
svgOrigin: "0 0"
|
|
101
|
+
});
|
|
102
|
+
}
|
|
96
103
|
gsap.set(overlay.current, { opacity: 1 });
|
|
97
104
|
const finish = () => {
|
|
98
105
|
if (lockScroll) document.body.style.overflow = previousOverflow;
|
|
@@ -104,13 +111,21 @@ function Walros3DPortalTransition({
|
|
|
104
111
|
if (reducedMotion) {
|
|
105
112
|
timeline.to(overlay.current, { opacity: 0, duration: 0.15, ease: "power1.out" });
|
|
106
113
|
} else {
|
|
107
|
-
timeline.to(portal.current, {
|
|
114
|
+
timeline.to([portal.current, logo.current].filter(Boolean), {
|
|
108
115
|
x: targetX,
|
|
109
116
|
y: targetY,
|
|
110
117
|
scale: finalScale,
|
|
111
118
|
duration: total,
|
|
112
119
|
ease: "power2.in"
|
|
113
|
-
})
|
|
120
|
+
});
|
|
121
|
+
if (logo.current) {
|
|
122
|
+
timeline.to(logo.current, {
|
|
123
|
+
opacity: 0,
|
|
124
|
+
duration: total * 0.18,
|
|
125
|
+
ease: "power1.out"
|
|
126
|
+
}, total * 0.7);
|
|
127
|
+
}
|
|
128
|
+
timeline.to(overlay.current, {
|
|
114
129
|
opacity: 0,
|
|
115
130
|
duration: total * 0.1,
|
|
116
131
|
ease: "power2.out"
|
|
@@ -143,14 +158,116 @@ function Walros3DPortalTransition({
|
|
|
143
158
|
/* @__PURE__ */ jsx("rect", { width: viewport.width, height: viewport.height, fill: "white" }),
|
|
144
159
|
/* @__PURE__ */ jsx("g", { ref: portal, children: /* @__PURE__ */ jsx("g", { transform: `translate(${-FOCUS_X} ${-FOCUS_Y})`, fill: "black", children: walrosPortalPaths.map((path, index) => /* @__PURE__ */ jsx("path", { d: path }, index)) }) })
|
|
145
160
|
] }) }),
|
|
161
|
+
logoUrl && /* @__PURE__ */ jsx("g", { ref: logo, children: /* @__PURE__ */ jsx("image", { href: logoUrl, x: -FOCUS_X, y: -FOCUS_Y, width: "1254", height: "1254" }) }),
|
|
146
162
|
/* @__PURE__ */ jsx("rect", { width: viewport.width, height: viewport.height, fill: backgroundColor, mask: `url(#${maskId})` })
|
|
147
163
|
] })
|
|
148
164
|
}
|
|
149
165
|
);
|
|
150
166
|
}
|
|
151
167
|
|
|
168
|
+
// src/components/useOverlayHost.ts
|
|
169
|
+
import { useLayoutEffect as useLayoutEffect2, useState as useState2 } from "react";
|
|
170
|
+
function useOverlayHost(zIndex) {
|
|
171
|
+
const [host] = useState2(
|
|
172
|
+
() => typeof document === "undefined" ? null : document.createElement("div")
|
|
173
|
+
);
|
|
174
|
+
useLayoutEffect2(() => {
|
|
175
|
+
if (!host) return;
|
|
176
|
+
host.dataset.walrosOverlayRoot = "";
|
|
177
|
+
host.style.position = "fixed";
|
|
178
|
+
host.style.inset = "0";
|
|
179
|
+
host.style.pointerEvents = "none";
|
|
180
|
+
document.documentElement.appendChild(host);
|
|
181
|
+
return () => host.remove();
|
|
182
|
+
}, [host]);
|
|
183
|
+
useLayoutEffect2(() => {
|
|
184
|
+
if (host) host.style.zIndex = String(zIndex);
|
|
185
|
+
}, [host, zIndex]);
|
|
186
|
+
return host;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// src/components/WalrosPortalTransition.tsx
|
|
190
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
191
|
+
var IMAGE_SIZE = (width) => Math.min(150, Math.max(90, width * 0.11));
|
|
192
|
+
var IMAGE_WIDTH = 1254;
|
|
193
|
+
var VISIBLE_LEFT2 = 244;
|
|
194
|
+
var VISIBLE_RIGHT2 = 1010;
|
|
195
|
+
var VISIBLE_TOP2 = 115;
|
|
196
|
+
var VISIBLE_BOTTOM2 = 1128;
|
|
197
|
+
function defaultOrigin() {
|
|
198
|
+
if (typeof window === "undefined") return { centerX: 0, centerY: 0, width: 70, height: 90 };
|
|
199
|
+
const size = IMAGE_SIZE(window.innerWidth);
|
|
200
|
+
return {
|
|
201
|
+
centerX: window.innerWidth / 2,
|
|
202
|
+
centerY: window.innerHeight * 0.45 + ((VISIBLE_TOP2 + VISIBLE_BOTTOM2) / 2 - IMAGE_WIDTH / 2) / IMAGE_WIDTH * size,
|
|
203
|
+
width: (VISIBLE_RIGHT2 - VISIBLE_LEFT2) / IMAGE_WIDTH * size,
|
|
204
|
+
height: (VISIBLE_BOTTOM2 - VISIBLE_TOP2) / IMAGE_WIDTH * size
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
function getStorage(mode) {
|
|
208
|
+
if (typeof window === "undefined") return null;
|
|
209
|
+
try {
|
|
210
|
+
return mode === "session" ? window.sessionStorage : window.localStorage;
|
|
211
|
+
} catch {
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
function shouldRun(enabled, mode, key) {
|
|
216
|
+
if (!enabled) return false;
|
|
217
|
+
if (mode === "always") return true;
|
|
218
|
+
try {
|
|
219
|
+
return getStorage(mode)?.getItem(key) == null;
|
|
220
|
+
} catch {
|
|
221
|
+
return true;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
function WalrosPortalTransition({
|
|
225
|
+
duration = 900,
|
|
226
|
+
onComplete,
|
|
227
|
+
backgroundColor = "#000",
|
|
228
|
+
enabled = true,
|
|
229
|
+
storageMode = "always",
|
|
230
|
+
storageKey = "walros-portal-seen",
|
|
231
|
+
zIndex = 1e4,
|
|
232
|
+
origin,
|
|
233
|
+
logoUrl = walrosLogoChromeUrl
|
|
234
|
+
}) {
|
|
235
|
+
const [run] = useState3(() => shouldRun(enabled, storageMode, storageKey));
|
|
236
|
+
const [complete, setComplete] = useState3(false);
|
|
237
|
+
const [initialOrigin] = useState3(() => origin ?? defaultOrigin());
|
|
238
|
+
const host = useOverlayHost(zIndex);
|
|
239
|
+
if (!host || !enabled || !run || complete) return null;
|
|
240
|
+
return createPortal(
|
|
241
|
+
/* @__PURE__ */ jsx2(
|
|
242
|
+
Walros3DPortalTransition,
|
|
243
|
+
{
|
|
244
|
+
origin: initialOrigin,
|
|
245
|
+
logoUrl,
|
|
246
|
+
duration,
|
|
247
|
+
backgroundColor,
|
|
248
|
+
zIndex: 1,
|
|
249
|
+
lockScroll: true,
|
|
250
|
+
onComplete: () => {
|
|
251
|
+
if (storageMode !== "always") {
|
|
252
|
+
try {
|
|
253
|
+
getStorage(storageMode)?.setItem(storageKey, "1");
|
|
254
|
+
} catch {
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
setComplete(true);
|
|
258
|
+
onComplete?.();
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
),
|
|
262
|
+
host
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// src/components/WalrosThemeTransition.tsx
|
|
267
|
+
import { createPortal as createPortal2 } from "react-dom";
|
|
268
|
+
|
|
152
269
|
// src/components/WalrosThemeGlitch.tsx
|
|
153
|
-
import { Fragment, jsx as
|
|
270
|
+
import { Fragment, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
154
271
|
var GLITCH_STYLES = `
|
|
155
272
|
.walros-theme-glitch-root {
|
|
156
273
|
position: fixed;
|
|
@@ -297,7 +414,7 @@ function WalrosThemeGlitch({
|
|
|
297
414
|
style
|
|
298
415
|
}) {
|
|
299
416
|
return /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
300
|
-
/* @__PURE__ */
|
|
417
|
+
/* @__PURE__ */ jsx3("style", { children: GLITCH_STYLES }),
|
|
301
418
|
active ? /* @__PURE__ */ jsxs2(
|
|
302
419
|
"div",
|
|
303
420
|
{
|
|
@@ -305,194 +422,33 @@ function WalrosThemeGlitch({
|
|
|
305
422
|
style: { zIndex, ...style },
|
|
306
423
|
"aria-hidden": "true",
|
|
307
424
|
children: [
|
|
308
|
-
/* @__PURE__ */
|
|
309
|
-
/* @__PURE__ */
|
|
310
|
-
/* @__PURE__ */
|
|
311
|
-
/* @__PURE__ */
|
|
425
|
+
/* @__PURE__ */ jsx3("span", { className: "walros-theme-glitch-band" }),
|
|
426
|
+
/* @__PURE__ */ jsx3("span", { className: "walros-theme-glitch-band" }),
|
|
427
|
+
/* @__PURE__ */ jsx3("span", { className: "walros-theme-glitch-band" }),
|
|
428
|
+
/* @__PURE__ */ jsx3("span", { className: "walros-theme-glitch-band" })
|
|
312
429
|
]
|
|
313
430
|
}
|
|
314
431
|
) : null
|
|
315
432
|
] });
|
|
316
433
|
}
|
|
317
434
|
|
|
318
|
-
// src/components/useOverlayHost.ts
|
|
319
|
-
import { useLayoutEffect as useLayoutEffect2, useState as useState2 } from "react";
|
|
320
|
-
function useOverlayHost(zIndex) {
|
|
321
|
-
const [host] = useState2(
|
|
322
|
-
() => typeof document === "undefined" ? null : document.createElement("div")
|
|
323
|
-
);
|
|
324
|
-
useLayoutEffect2(() => {
|
|
325
|
-
if (!host) return;
|
|
326
|
-
host.dataset.walrosOverlayRoot = "";
|
|
327
|
-
host.style.position = "fixed";
|
|
328
|
-
host.style.inset = "0";
|
|
329
|
-
host.style.pointerEvents = "none";
|
|
330
|
-
document.documentElement.appendChild(host);
|
|
331
|
-
return () => host.remove();
|
|
332
|
-
}, [host]);
|
|
333
|
-
useLayoutEffect2(() => {
|
|
334
|
-
if (host) host.style.zIndex = String(zIndex);
|
|
335
|
-
}, [host, zIndex]);
|
|
336
|
-
return host;
|
|
337
|
-
}
|
|
338
|
-
|
|
339
435
|
// src/components/WalrosThemeTransition.tsx
|
|
340
|
-
import {
|
|
341
|
-
var IMAGE_SIZE = "clamp(90px, 11vw, 150px)";
|
|
342
|
-
var IMAGE_WIDTH = 1254;
|
|
343
|
-
var VISIBLE_LEFT2 = 244;
|
|
344
|
-
var VISIBLE_RIGHT2 = 1010;
|
|
345
|
-
var VISIBLE_TOP2 = 115;
|
|
346
|
-
var VISIBLE_BOTTOM2 = 1128;
|
|
347
|
-
function WalrosPortalScene({
|
|
348
|
-
logoUrl,
|
|
349
|
-
portalDuration,
|
|
350
|
-
zIndex,
|
|
351
|
-
backgroundColor = "#000",
|
|
352
|
-
onComplete,
|
|
353
|
-
lockScroll = false
|
|
354
|
-
}) {
|
|
355
|
-
const logoRef = useRef2(null);
|
|
356
|
-
const [origin, setOrigin] = useState3(null);
|
|
357
|
-
const [portalComplete, setPortalComplete] = useState3(false);
|
|
358
|
-
const measureLogo = () => {
|
|
359
|
-
const image = logoRef.current;
|
|
360
|
-
if (!image) return;
|
|
361
|
-
const rect = image.getBoundingClientRect();
|
|
362
|
-
const scale = rect.width / IMAGE_WIDTH;
|
|
363
|
-
setOrigin({
|
|
364
|
-
centerX: rect.left + (VISIBLE_LEFT2 + VISIBLE_RIGHT2) / 2 * scale,
|
|
365
|
-
centerY: rect.top + (VISIBLE_TOP2 + VISIBLE_BOTTOM2) / 2 * scale,
|
|
366
|
-
width: (VISIBLE_RIGHT2 - VISIBLE_LEFT2) * scale,
|
|
367
|
-
height: (VISIBLE_BOTTOM2 - VISIBLE_TOP2) * scale
|
|
368
|
-
});
|
|
369
|
-
};
|
|
370
|
-
useLayoutEffect3(() => {
|
|
371
|
-
const image = logoRef.current;
|
|
372
|
-
if (image?.complete) measureLogo();
|
|
373
|
-
}, []);
|
|
374
|
-
return /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
375
|
-
!portalComplete && /* @__PURE__ */ jsx3(
|
|
376
|
-
"img",
|
|
377
|
-
{
|
|
378
|
-
ref: logoRef,
|
|
379
|
-
src: logoUrl,
|
|
380
|
-
onLoad: measureLogo,
|
|
381
|
-
onError: measureLogo,
|
|
382
|
-
alt: "",
|
|
383
|
-
"aria-hidden": "true",
|
|
384
|
-
style: {
|
|
385
|
-
position: "fixed",
|
|
386
|
-
left: "50%",
|
|
387
|
-
top: "45%",
|
|
388
|
-
width: IMAGE_SIZE,
|
|
389
|
-
height: IMAGE_SIZE,
|
|
390
|
-
transform: "translate(-50%, -50%)",
|
|
391
|
-
objectFit: "contain",
|
|
392
|
-
zIndex,
|
|
393
|
-
pointerEvents: "none"
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
),
|
|
397
|
-
!portalComplete && !origin && /* @__PURE__ */ jsx3("div", { style: { position: "fixed", inset: 0, zIndex: zIndex + 1, background: backgroundColor, pointerEvents: "none" }, "aria-hidden": "true" }),
|
|
398
|
-
!portalComplete && origin && /* @__PURE__ */ jsx3(
|
|
399
|
-
Walros3DPortalTransition,
|
|
400
|
-
{
|
|
401
|
-
origin,
|
|
402
|
-
duration: portalDuration,
|
|
403
|
-
zIndex: zIndex + 1,
|
|
404
|
-
backgroundColor,
|
|
405
|
-
lockScroll,
|
|
406
|
-
onComplete: () => {
|
|
407
|
-
setPortalComplete(true);
|
|
408
|
-
onComplete?.();
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
)
|
|
412
|
-
] });
|
|
413
|
-
}
|
|
436
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
414
437
|
function WalrosThemeTransition({
|
|
415
438
|
active,
|
|
416
|
-
portalDuration = 900,
|
|
417
|
-
logoUrl = walrosLogoChromeUrl,
|
|
418
439
|
zIndex = 1e4
|
|
419
440
|
}) {
|
|
420
441
|
const host = useOverlayHost(zIndex);
|
|
421
|
-
useEffect2(() => {
|
|
422
|
-
if (typeof window === "undefined") return;
|
|
423
|
-
const logo = new Image();
|
|
424
|
-
logo.src = logoUrl;
|
|
425
|
-
}, [logoUrl]);
|
|
426
442
|
if (!host) return null;
|
|
427
|
-
return createPortal(
|
|
428
|
-
/* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
429
|
-
active && /* @__PURE__ */ jsx3(WalrosPortalScene, { logoUrl, portalDuration, zIndex }),
|
|
430
|
-
/* @__PURE__ */ jsx3(WalrosThemeGlitch, { active, zIndex: zIndex + 2 })
|
|
431
|
-
] }),
|
|
432
|
-
host
|
|
433
|
-
);
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
// src/components/WalrosPortalTransition.tsx
|
|
437
|
-
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
438
|
-
function getStorage(mode) {
|
|
439
|
-
if (typeof window === "undefined") return null;
|
|
440
|
-
try {
|
|
441
|
-
return mode === "session" ? window.sessionStorage : window.localStorage;
|
|
442
|
-
} catch {
|
|
443
|
-
return null;
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
function shouldRun(enabled, mode, key) {
|
|
447
|
-
if (!enabled) return false;
|
|
448
|
-
if (mode === "always") return true;
|
|
449
|
-
try {
|
|
450
|
-
return getStorage(mode)?.getItem(key) == null;
|
|
451
|
-
} catch {
|
|
452
|
-
return true;
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
function WalrosPortalTransition({
|
|
456
|
-
duration = 900,
|
|
457
|
-
onComplete,
|
|
458
|
-
backgroundColor = "#000",
|
|
459
|
-
enabled = true,
|
|
460
|
-
storageMode = "always",
|
|
461
|
-
storageKey = "walros-portal-seen",
|
|
462
|
-
zIndex = 1e4
|
|
463
|
-
}) {
|
|
464
|
-
const [run] = useState4(() => shouldRun(enabled, storageMode, storageKey));
|
|
465
|
-
const [complete, setComplete] = useState4(false);
|
|
466
|
-
const host = useOverlayHost(zIndex);
|
|
467
|
-
if (!host || !enabled || !run || complete) return null;
|
|
468
443
|
return createPortal2(
|
|
469
|
-
/* @__PURE__ */ jsx4(
|
|
470
|
-
WalrosPortalScene,
|
|
471
|
-
{
|
|
472
|
-
logoUrl: walrosLogoChromeUrl,
|
|
473
|
-
portalDuration: duration,
|
|
474
|
-
backgroundColor,
|
|
475
|
-
zIndex,
|
|
476
|
-
lockScroll: true,
|
|
477
|
-
onComplete: () => {
|
|
478
|
-
if (storageMode !== "always") {
|
|
479
|
-
try {
|
|
480
|
-
getStorage(storageMode)?.setItem(storageKey, "1");
|
|
481
|
-
} catch {
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
setComplete(true);
|
|
485
|
-
onComplete?.();
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
),
|
|
444
|
+
/* @__PURE__ */ jsx4(WalrosThemeGlitch, { active, zIndex: 1 }),
|
|
489
445
|
host
|
|
490
446
|
);
|
|
491
447
|
}
|
|
492
448
|
|
|
493
449
|
// src/components/DirectionalCursor.tsx
|
|
494
|
-
import { useEffect as
|
|
495
|
-
import { Fragment as
|
|
450
|
+
import { useEffect as useEffect2, useRef as useRef2 } from "react";
|
|
451
|
+
import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
496
452
|
var DESKTOP_CURSOR_QUERY = "(min-width: 1024px) and (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference)";
|
|
497
453
|
var CURSOR_STYLES = `
|
|
498
454
|
.directional-cursor { position: fixed; top: 0; left: 0; z-index: 9999; width: 20px; height: 22px; opacity: 0; pointer-events: none; contain: layout style; will-change: transform; transition: opacity 100ms linear; }
|
|
@@ -507,9 +463,9 @@ var CURSOR_STYLES = `
|
|
|
507
463
|
}
|
|
508
464
|
`;
|
|
509
465
|
function DirectionalCursor() {
|
|
510
|
-
const positionLayer =
|
|
511
|
-
const directionLayer =
|
|
512
|
-
|
|
466
|
+
const positionLayer = useRef2(null);
|
|
467
|
+
const directionLayer = useRef2(null);
|
|
468
|
+
useEffect2(() => {
|
|
513
469
|
const position = positionLayer.current;
|
|
514
470
|
const direction = directionLayer.current;
|
|
515
471
|
if (!position || !direction) return;
|
|
@@ -608,14 +564,14 @@ function DirectionalCursor() {
|
|
|
608
564
|
deactivate();
|
|
609
565
|
};
|
|
610
566
|
}, []);
|
|
611
|
-
return /* @__PURE__ */
|
|
567
|
+
return /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
612
568
|
/* @__PURE__ */ jsx5("style", { children: CURSOR_STYLES }),
|
|
613
|
-
/* @__PURE__ */ jsx5("div", { ref: positionLayer, className: "directional-cursor", "aria-hidden": "true", children: /* @__PURE__ */ jsx5("div", { ref: directionLayer, className: "directional-cursor-shape", children: /* @__PURE__ */
|
|
614
|
-
/* @__PURE__ */
|
|
569
|
+
/* @__PURE__ */ jsx5("div", { ref: positionLayer, className: "directional-cursor", "aria-hidden": "true", children: /* @__PURE__ */ jsx5("div", { ref: directionLayer, className: "directional-cursor-shape", children: /* @__PURE__ */ jsxs3("svg", { width: "50", height: "54", viewBox: "0 0 50 54", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
|
|
570
|
+
/* @__PURE__ */ jsxs3("g", { filter: "url(#walros-cursor-shadow)", children: [
|
|
615
571
|
/* @__PURE__ */ jsx5("path", { d: "M42.6817 41.1495L27.5103 6.79925C26.7269 5.02557 24.2082 5.02558 23.3927 6.79925L7.59814 41.1495C6.75833 42.9759 8.52712 44.8902 10.4125 44.1954L24.3757 39.0496C24.8829 38.8627 25.4385 38.8627 25.9422 39.0496L39.8121 44.1954C41.6849 44.8902 43.4884 42.9759 42.6817 41.1495Z", fill: "black" }),
|
|
616
572
|
/* @__PURE__ */ jsx5("path", { d: "M43.7146 40.6933L28.5431 6.34306C27.3556 3.65428 23.5772 3.69516 22.3668 6.32755L6.57226 40.6778C5.3134 43.4156 7.97238 46.298 10.803 45.2549L24.7662 40.109C25.0221 40.0147 25.2999 40.0156 25.5494 40.1082L39.4193 45.254C42.2261 46.2953 44.9254 43.4347 43.7146 40.6933Z", stroke: "white", strokeWidth: "2.25825" })
|
|
617
573
|
] }),
|
|
618
|
-
/* @__PURE__ */ jsx5("defs", { children: /* @__PURE__ */
|
|
574
|
+
/* @__PURE__ */ jsx5("defs", { children: /* @__PURE__ */ jsxs3("filter", { id: "walros-cursor-shadow", x: "0.602397", y: "0.952444", width: "49.0584", height: "52.428", filterUnits: "userSpaceOnUse", colorInterpolationFilters: "sRGB", children: [
|
|
619
575
|
/* @__PURE__ */ jsx5("feFlood", { floodOpacity: "0", result: "BackgroundImageFix" }),
|
|
620
576
|
/* @__PURE__ */ jsx5("feColorMatrix", { in: "SourceAlpha", type: "matrix", values: "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0", result: "hardAlpha" }),
|
|
621
577
|
/* @__PURE__ */ jsx5("feOffset", { dy: "2.25825" }),
|
|
@@ -670,9 +626,9 @@ function WalrosWordmark({
|
|
|
670
626
|
// src/hooks/useWalrosTheme.ts
|
|
671
627
|
import {
|
|
672
628
|
useCallback,
|
|
673
|
-
useEffect as
|
|
674
|
-
useRef as
|
|
675
|
-
useState as
|
|
629
|
+
useEffect as useEffect3,
|
|
630
|
+
useRef as useRef3,
|
|
631
|
+
useState as useState4
|
|
676
632
|
} from "react";
|
|
677
633
|
var GLITCH_BASE_CLASS = "walros-theme-glitch-page";
|
|
678
634
|
var GLITCH_BODY_CLASS = "walros-theme-glitch-page--body";
|
|
@@ -719,25 +675,25 @@ function useWalrosTheme({
|
|
|
719
675
|
lockScroll,
|
|
720
676
|
onAfterUnlock
|
|
721
677
|
} = {}) {
|
|
722
|
-
const [theme, setThemeState] =
|
|
678
|
+
const [theme, setThemeState] = useState4(
|
|
723
679
|
() => readInitialTheme(storageKey, defaultTheme, useSystemPreference)
|
|
724
680
|
);
|
|
725
|
-
const [mounted, setMounted] =
|
|
726
|
-
const [glitching, setGlitching] =
|
|
727
|
-
const themeRef =
|
|
728
|
-
const glitchingRef =
|
|
729
|
-
const swapTimerRef =
|
|
730
|
-
const cleanupTimerRef =
|
|
731
|
-
const applyThemeRef =
|
|
732
|
-
const modeRef =
|
|
733
|
-
const shakeTargetsRef =
|
|
734
|
-
const lockScrollRef =
|
|
735
|
-
const onAfterUnlockRef =
|
|
736
|
-
const activeTargetsRef =
|
|
737
|
-
const viewportLockRef =
|
|
738
|
-
const soundRef =
|
|
739
|
-
const soundUrlRef =
|
|
740
|
-
const soundVolumeRef =
|
|
681
|
+
const [mounted, setMounted] = useState4(false);
|
|
682
|
+
const [glitching, setGlitching] = useState4(false);
|
|
683
|
+
const themeRef = useRef3(theme);
|
|
684
|
+
const glitchingRef = useRef3(false);
|
|
685
|
+
const swapTimerRef = useRef3(null);
|
|
686
|
+
const cleanupTimerRef = useRef3(null);
|
|
687
|
+
const applyThemeRef = useRef3(applyTheme);
|
|
688
|
+
const modeRef = useRef3(mode);
|
|
689
|
+
const shakeTargetsRef = useRef3(shakeTargets);
|
|
690
|
+
const lockScrollRef = useRef3(lockScroll);
|
|
691
|
+
const onAfterUnlockRef = useRef3(onAfterUnlock);
|
|
692
|
+
const activeTargetsRef = useRef3([]);
|
|
693
|
+
const viewportLockRef = useRef3(null);
|
|
694
|
+
const soundRef = useRef3(null);
|
|
695
|
+
const soundUrlRef = useRef3(soundUrl);
|
|
696
|
+
const soundVolumeRef = useRef3(soundVolume);
|
|
741
697
|
themeRef.current = theme;
|
|
742
698
|
applyThemeRef.current = applyTheme;
|
|
743
699
|
modeRef.current = mode;
|
|
@@ -774,7 +730,7 @@ function useWalrosTheme({
|
|
|
774
730
|
},
|
|
775
731
|
[storageKey]
|
|
776
732
|
);
|
|
777
|
-
|
|
733
|
+
useEffect3(() => {
|
|
778
734
|
const initialTheme = readInitialTheme(
|
|
779
735
|
storageKey,
|
|
780
736
|
defaultTheme,
|
|
@@ -909,7 +865,7 @@ function useWalrosTheme({
|
|
|
909
865
|
finishGlitch();
|
|
910
866
|
}, effectiveDuration);
|
|
911
867
|
}, [finishGlitch, lockViewport, persistTheme, playThemeSound, swapDelay, totalDuration]);
|
|
912
|
-
|
|
868
|
+
useEffect3(() => {
|
|
913
869
|
return () => {
|
|
914
870
|
clearTimers();
|
|
915
871
|
removeShakeClasses();
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/WalrosPortalTransition.tsx","../src/assets.ts","../src/components/WalrosThemeTransition.tsx","../src/components/Walros3DPortalTransition.tsx","../src/portalSilhouette.ts","../src/components/WalrosThemeGlitch.tsx","../src/components/useOverlayHost.ts","../src/components/DirectionalCursor.tsx","../src/components/WalrosLogo.tsx","../src/components/WalrosWordmark.tsx","../src/hooks/useWalrosTheme.ts"],"sourcesContent":["import { useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { walrosLogoChromeUrl } from \"../assets\";\nimport { WalrosPortalScene } from \"./WalrosThemeTransition\";\nimport { useOverlayHost } from \"./useOverlayHost\";\n\nexport type WalrosPortalTransitionProps = {\n duration?: number;\n onComplete?: () => void;\n backgroundColor?: string;\n enabled?: boolean;\n storageMode?: \"always\" | \"session\" | \"once\";\n storageKey?: string;\n zIndex?: number;\n};\n\nfunction getStorage(mode: \"session\" | \"once\"): Storage | null {\n if (typeof window === \"undefined\") return null;\n try {\n return mode === \"session\" ? window.sessionStorage : window.localStorage;\n } catch {\n return null;\n }\n}\n\nfunction shouldRun(enabled: boolean, mode: \"always\" | \"session\" | \"once\", key: string) {\n if (!enabled) return false;\n if (mode === \"always\") return true;\n try {\n return getStorage(mode)?.getItem(key) == null;\n } catch {\n return true;\n }\n}\n\n/** Exact walros.org black portal, including its chrome logo and 900 ms curve. */\nexport function WalrosPortalTransition({\n duration = 900,\n onComplete,\n backgroundColor = \"#000\",\n enabled = true,\n storageMode = \"always\",\n storageKey = \"walros-portal-seen\",\n zIndex = 10000,\n}: WalrosPortalTransitionProps) {\n const [run] = useState(() => shouldRun(enabled, storageMode, storageKey));\n const [complete, setComplete] = useState(false);\n const host = useOverlayHost(zIndex);\n\n if (!host || !enabled || !run || complete) return null;\n\n return createPortal(\n <WalrosPortalScene\n logoUrl={walrosLogoChromeUrl}\n portalDuration={duration}\n backgroundColor={backgroundColor}\n zIndex={zIndex}\n lockScroll\n onComplete={() => {\n if (storageMode !== \"always\") {\n try { getStorage(storageMode)?.setItem(storageKey, \"1\"); } catch { /* Storage is optional. */ }\n }\n setComplete(true);\n onComplete?.();\n }}\n />,\n host,\n );\n}\n\nexport default WalrosPortalTransition;\n","export const walrosPortalSilhouetteUrl = new URL(\n \"./assets/walros-portal-silhouette.svg\",\n import.meta.url,\n).href;\n\nexport const walrosLogoChromeUrl = new URL(\n \"./assets/walros-logo-chrome.png\",\n import.meta.url,\n).href;\n\nexport const walrosWordmarkLightUrl = new URL(\n \"./assets/walros-wordmark-light.png\",\n import.meta.url,\n).href;\n\nexport const walrosWordmarkDarkUrl = new URL(\n \"./assets/walros-wordmark-dark.png\",\n import.meta.url,\n).href;\n\nexport const walrosThemeGlitchSoundUrl = new URL(\n \"./assets/walros-theme-glitch.mp3\",\n import.meta.url,\n).href;\n","import { useEffect, useLayoutEffect, useRef, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { walrosLogoChromeUrl } from \"../assets\";\nimport { Walros3DPortalTransition, type PortalOrigin } from \"./Walros3DPortalTransition\";\nimport { WalrosThemeGlitch } from \"./WalrosThemeGlitch\";\nimport { useOverlayHost } from \"./useOverlayHost\";\n\nexport type WalrosThemeTransitionProps = {\n /** Pass the `glitching` value returned by `useWalrosTheme`. */\n active: boolean;\n /** The walros.org portal takes 900 ms. */\n portalDuration?: number;\n /** The same chrome logo used under the portal on walros.org. */\n logoUrl?: string;\n zIndex?: number;\n};\n\nconst IMAGE_SIZE = \"clamp(90px, 11vw, 150px)\";\nconst IMAGE_WIDTH = 1254;\nconst VISIBLE_LEFT = 244;\nconst VISIBLE_RIGHT = 1010;\nconst VISIBLE_TOP = 115;\nconst VISIBLE_BOTTOM = 1128;\n\nexport type WalrosPortalSceneProps = {\n logoUrl: string;\n portalDuration: number;\n zIndex: number;\n backgroundColor?: string;\n onComplete?: () => void;\n lockScroll?: boolean;\n};\n\nexport function WalrosPortalScene({\n logoUrl,\n portalDuration,\n zIndex,\n backgroundColor = \"#000\",\n onComplete,\n lockScroll = false,\n}: WalrosPortalSceneProps) {\n const logoRef = useRef<HTMLImageElement>(null);\n const [origin, setOrigin] = useState<PortalOrigin | null>(null);\n const [portalComplete, setPortalComplete] = useState(false);\n\n const measureLogo = () => {\n const image = logoRef.current;\n if (!image) return;\n const rect = image.getBoundingClientRect();\n const scale = rect.width / IMAGE_WIDTH;\n setOrigin({\n centerX: rect.left + ((VISIBLE_LEFT + VISIBLE_RIGHT) / 2) * scale,\n centerY: rect.top + ((VISIBLE_TOP + VISIBLE_BOTTOM) / 2) * scale,\n width: (VISIBLE_RIGHT - VISIBLE_LEFT) * scale,\n height: (VISIBLE_BOTTOM - VISIBLE_TOP) * scale,\n });\n };\n\n useLayoutEffect(() => {\n const image = logoRef.current;\n if (image?.complete) measureLogo();\n }, []);\n\n return (\n <>\n {!portalComplete && (\n <img\n ref={logoRef}\n src={logoUrl}\n onLoad={measureLogo}\n onError={measureLogo}\n alt=\"\"\n aria-hidden=\"true\"\n style={{\n position: \"fixed\",\n left: \"50%\",\n top: \"45%\",\n width: IMAGE_SIZE,\n height: IMAGE_SIZE,\n transform: \"translate(-50%, -50%)\",\n objectFit: \"contain\",\n zIndex,\n pointerEvents: \"none\",\n }}\n />\n )}\n {!portalComplete && !origin && (\n <div style={{ position: \"fixed\", inset: 0, zIndex: zIndex + 1, background: backgroundColor, pointerEvents: \"none\" }} aria-hidden=\"true\" />\n )}\n {!portalComplete && origin && (\n <Walros3DPortalTransition\n origin={origin}\n duration={portalDuration}\n zIndex={zIndex + 1}\n backgroundColor={backgroundColor}\n lockScroll={lockScroll}\n onComplete={() => { setPortalComplete(true); onComplete?.(); }}\n />\n )}\n </>\n );\n}\n\n/**\n * A ready-to-use walros.org theme transition. The portal runs for 900 ms,\n * while the matching glitch and sound from useWalrosTheme run for 1,500 ms.\n * Mount once near the app root and pass `active={glitching}`.\n */\nexport function WalrosThemeTransition({\n active,\n portalDuration = 900,\n logoUrl = walrosLogoChromeUrl,\n zIndex = 10000,\n}: WalrosThemeTransitionProps) {\n const host = useOverlayHost(zIndex);\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const logo = new Image();\n logo.src = logoUrl;\n }, [logoUrl]);\n\n if (!host) return null;\n\n return createPortal(\n <>\n {active && <WalrosPortalScene logoUrl={logoUrl} portalDuration={portalDuration} zIndex={zIndex} />}\n <WalrosThemeGlitch active={active} zIndex={zIndex + 2} />\n </>,\n host,\n );\n}\n","import { useEffect, useId, useLayoutEffect, useRef, useState } from \"react\";\nimport gsap from \"gsap\";\nimport { walrosPortalPaths } from \"../portalSilhouette\";\n\r\nexport type PortalOrigin = {\r\n centerX: number;\r\n centerY: number;\r\n width: number;\r\n height: number;\r\n};\r\n\r\nexport type Walros3DPortalTransitionProps = {\n origin: PortalOrigin;\n onComplete?: () => void;\n duration?: number;\n backgroundColor?: string;\n zIndex?: number;\n lockScroll?: boolean;\n};\n\r\nconst FOCUS_X = 626;\r\nconst FOCUS_Y = 333;\r\nconst VISIBLE_LEFT = 244;\r\nconst VISIBLE_RIGHT = 1010;\r\nconst VISIBLE_TOP = 115;\r\nconst VISIBLE_BOTTOM = 1128;\r\nconst PORTAL_RADIUS = 190;\r\n\r\nexport function Walros3DPortalTransition({\n origin,\n onComplete,\n duration = 900,\n backgroundColor = \"#000\",\n zIndex = 10001,\n lockScroll = true,\n}: Walros3DPortalTransitionProps) {\n const [visible, setVisible] = useState(true);\n const [viewport, setViewport] = useState(() => ({\n width: typeof window === \"undefined\" ? 0 : window.innerWidth,\n height: typeof window === \"undefined\" ? 0 : window.innerHeight,\n }));\n const overlay = useRef<HTMLDivElement>(null);\n const portal = useRef<SVGGElement>(null);\n const completeRef = useRef(onComplete);\n completeRef.current = onComplete;\n const maskId = `walros-3d-portal-${useId().replace(/:/g, \"_\")}`;\n\r\n useEffect(() => {\r\n const updateViewport = () => setViewport({ width: window.innerWidth, height: window.innerHeight });\r\n window.addEventListener(\"resize\", updateViewport);\r\n return () => window.removeEventListener(\"resize\", updateViewport);\r\n }, []);\r\n\r\n useLayoutEffect(() => {\n if (!visible || viewport.width <= 0 || viewport.height <= 0 || !overlay.current || !portal.current) return;\n const previousOverflow = document.body.style.overflow;\n if (lockScroll) document.body.style.overflow = \"hidden\";\n\r\n const visibleWidth = VISIBLE_RIGHT - VISIBLE_LEFT;\r\n const visibleHeight = VISIBLE_BOTTOM - VISIBLE_TOP;\r\n const visualCenterX = (VISIBLE_LEFT + VISIBLE_RIGHT) / 2;\r\n const visualCenterY = (VISIBLE_TOP + VISIBLE_BOTTOM) / 2;\r\n // Let the black mask overlap the projected GLB by roughly one pixel. This\r\n // removes the pale halo without visibly cropping the chrome silhouette.\r\n const initialScale = Math.min(origin.width / visibleWidth, origin.height / visibleHeight) * .985;\r\n const initialX = origin.centerX - (visualCenterX - FOCUS_X) * initialScale;\r\n const initialY = origin.centerY - (visualCenterY - FOCUS_Y) * initialScale;\r\n const targetX = viewport.width / 2 - (visualCenterX - FOCUS_X) * initialScale;\r\n const targetY = viewport.height / 2 - (visualCenterY - FOCUS_Y) * initialScale;\r\n const diagonal = Math.hypot(viewport.width, viewport.height) / 2;\r\n const finalScale = ((diagonal + 80) / PORTAL_RADIUS) * 1.15;\r\n const total = duration / 1000;\r\n\r\n gsap.set(portal.current, {\r\n x: initialX,\r\n y: initialY,\r\n scale: initialScale,\r\n svgOrigin: \"0 0\",\r\n });\r\n gsap.set(overlay.current, { opacity: 1 });\r\n\r\n const finish = () => {\r\n if (lockScroll) document.body.style.overflow = previousOverflow;\n setVisible(false);\n completeRef.current?.();\n };\r\n const reducedMotion = window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\r\n const timeline = gsap.timeline({ onComplete: finish });\r\n if (reducedMotion) {\r\n timeline.to(overlay.current, { opacity: 0, duration: 0.15, ease: \"power1.out\" });\r\n } else {\r\n timeline\r\n .to(portal.current, {\r\n x: targetX,\r\n y: targetY,\r\n scale: finalScale,\r\n duration: total,\r\n ease: \"power2.in\",\r\n })\r\n .to(overlay.current, {\r\n opacity: 0,\r\n duration: total * 0.1,\r\n ease: \"power2.out\",\r\n }, total * 0.9);\r\n }\r\n\r\n return () => {\r\n timeline.kill();\r\n if (lockScroll) document.body.style.overflow = previousOverflow;\n };\n }, [duration, lockScroll, origin, viewport, visible]);\n\n if (!visible) return null;\n\r\n return (\r\n <div\r\n ref={overlay}\r\n className=\"walros-3d-portal\"\n style={{\n position: \"fixed\",\n inset: 0,\n width: \"100vw\",\n height: \"100dvh\",\n overflow: \"hidden\",\n pointerEvents: \"none\",\n zIndex,\n backgroundColor: viewport.width > 0 && viewport.height > 0 ? \"transparent\" : backgroundColor,\n }}\n aria-hidden=\"true\"\r\n >\r\n <svg width=\"100%\" height=\"100%\" viewBox={`0 0 ${viewport.width} ${viewport.height}`} preserveAspectRatio=\"none\" style={{ display: \"block\" }}>\n <defs>\r\n <mask id={maskId} maskUnits=\"userSpaceOnUse\" x=\"0\" y=\"0\" width={viewport.width} height={viewport.height}>\r\n <rect width={viewport.width} height={viewport.height} fill=\"white\" />\r\n <g ref={portal}>\r\n <g transform={`translate(${-FOCUS_X} ${-FOCUS_Y})`} fill=\"black\">\r\n {walrosPortalPaths.map((path, index) => <path d={path} key={index} />)}\n </g>\r\n </g>\r\n </mask>\r\n </defs>\r\n <rect width={viewport.width} height={viewport.height} fill={backgroundColor} mask={`url(#${maskId})`} />\n </svg>\r\n </div>\r\n );\r\n}\r\n","/* Exact silhouette used by the walros.org portal mask. */\r\nexport const walrosPortalPaths = [\r\n \"M 244.00 354.00 C 240.50 377.67, 240.17 413.67, 242.00 434.00 C 243.83 454.33, 249.50 464.50, 255.00 476.00 C 260.50 487.50, 268.50 496.00, 275.00 503.00 C 281.50 510.00, 287.17 513.67, 294.00 518.00 C 300.83 522.33, 306.00 525.67, 316.00 529.00 C 326.00 532.33, 336.33 536.67, 354.00 538.00 C 371.67 539.33, 397.83 540.83, 422.00 537.00 C 446.17 533.17, 474.17 525.33, 499.00 515.00 C 523.83 504.67, 550.00 489.33, 571.00 475.00 C 592.00 460.67, 615.00 436.50, 625.00 429.00 C 635.00 421.50, 623.67 424.00, 631.00 430.00 C 638.33 436.00, 656.67 454.83, 669.00 465.00 C 681.33 475.17, 690.00 482.17, 705.00 491.00 C 720.00 499.83, 743.67 511.50, 759.00 518.00 C 774.33 524.50, 784.00 526.83, 797.00 530.00 C 810.00 533.17, 820.00 535.83, 837.00 537.00 C 854.00 538.17, 881.17 539.00, 899.00 537.00 C 916.83 535.00, 932.00 530.00, 944.00 525.00 C 956.00 520.00, 962.00 516.17, 971.00 507.00 C 980.00 497.83, 991.67 482.83, 998.00 470.00 C 1004.33 457.17, 1007.17 446.33, 1009.00 430.00 C 1010.83 413.67, 1010.83 390.50, 1009.00 372.00 C 1007.17 353.50, 1003.83 337.17, 998.00 319.00 C 992.17 300.83, 983.67 280.17, 974.00 263.00 C 964.33 245.83, 952.00 229.67, 940.00 216.00 C 928.00 202.33, 917.17 192.00, 902.00 181.00 C 886.83 170.00, 866.50 158.17, 849.00 150.00 C 831.50 141.83, 816.67 137.00, 797.00 132.00 C 777.33 127.00, 756.67 122.83, 731.00 120.00 C 705.33 117.17, 673.67 115.33, 643.00 115.00 C 612.33 114.67, 575.67 115.67, 547.00 118.00 C 518.33 120.33, 496.17 123.00, 471.00 129.00 C 445.83 135.00, 418.33 143.50, 396.00 154.00 C 373.67 164.50, 353.50 178.50, 337.00 192.00 C 320.50 205.50, 309.33 218.33, 297.00 235.00 C 284.67 251.67, 271.83 272.17, 263.00 292.00 C 254.17 311.83, 247.50 330.33, 244.00 354.00 Z\",\r\n \"M 289.00 536.00 C 283.17 535.50, 284.83 533.00, 284.00 544.00 C 283.17 555.00, 282.67 578.67, 284.00 602.00 C 285.33 625.33, 287.00 651.83, 292.00 684.00 C 297.00 716.17, 306.33 763.50, 314.00 795.00 C 321.67 826.50, 328.67 847.17, 338.00 873.00 C 347.33 898.83, 357.00 923.67, 370.00 950.00 C 383.00 976.33, 399.67 1006.00, 416.00 1031.00 C 432.33 1056.00, 455.33 1084.50, 468.00 1100.00 C 480.67 1115.50, 486.17 1119.33, 492.00 1124.00 C 497.83 1128.67, 500.67 1127.67, 503.00 1128.00 C 505.33 1128.33, 505.50 1127.50, 506.00 1126.00 C 506.50 1124.50, 510.33 1132.00, 506.00 1119.00 C 501.67 1106.00, 488.17 1073.83, 480.00 1048.00 C 471.83 1022.17, 462.67 987.67, 457.00 964.00 C 451.33 940.33, 449.17 927.33, 446.00 906.00 C 442.83 884.67, 439.50 865.00, 438.00 836.00 C 436.50 807.00, 436.50 758.33, 437.00 732.00 C 437.50 705.67, 439.00 696.33, 441.00 678.00 C 443.00 659.67, 444.83 644.00, 449.00 622.00 C 453.17 600.00, 464.50 559.00, 466.00 546.00 C 467.50 533.00, 468.67 542.50, 458.00 544.00 C 447.33 545.50, 418.33 553.17, 402.00 555.00 C 385.67 556.83, 373.83 556.33, 360.00 555.00 C 346.17 553.67, 330.83 550.17, 319.00 547.00 C 307.17 543.83, 294.83 536.50, 289.00 536.00 Z\",\r\n \"M 961.00 537.00 C 948.50 539.17, 907.83 552.00, 889.00 555.00 C 870.17 558.00, 864.17 557.00, 848.00 555.00 C 831.83 553.00, 802.83 545.00, 792.00 543.00 C 781.17 541.00, 784.83 542.50, 783.00 543.00 C 781.17 543.50, 778.67 533.83, 781.00 546.00 C 783.33 558.17, 792.67 592.33, 797.00 616.00 C 801.33 639.67, 804.83 668.83, 807.00 688.00 C 809.17 707.17, 809.67 709.00, 810.00 731.00 C 810.33 753.00, 810.50 792.83, 809.00 820.00 C 807.50 847.17, 804.50 870.50, 801.00 894.00 C 797.50 917.50, 794.00 936.17, 788.00 961.00 C 782.00 985.83, 773.50 1016.67, 765.00 1043.00 C 756.50 1069.33, 741.33 1104.83, 737.00 1119.00 C 732.67 1133.17, 736.67 1127.17, 739.00 1128.00 C 741.33 1128.83, 745.83 1127.83, 751.00 1124.00 C 756.17 1120.17, 757.33 1120.50, 770.00 1105.00 C 782.67 1089.50, 811.33 1053.50, 827.00 1031.00 C 842.67 1008.50, 851.17 995.00, 864.00 970.00 C 876.83 945.00, 892.83 910.00, 904.00 881.00 C 915.17 852.00, 923.00 826.67, 931.00 796.00 C 939.00 765.33, 946.67 728.67, 952.00 697.00 C 957.33 665.33, 961.00 631.83, 963.00 606.00 C 965.00 580.17, 964.33 553.50, 964.00 542.00 C 963.67 530.50, 973.50 534.83, 961.00 537.00 Z\",\r\n] as const;\r\n","import type { CSSProperties } from \"react\";\n\nexport type WalrosThemeGlitchProps = {\n active: boolean;\n zIndex?: number;\n className?: string;\n style?: CSSProperties;\n};\n\nconst GLITCH_STYLES = `\n.walros-theme-glitch-root {\n position: fixed;\n inset: 0;\n z-index: 9998;\n pointer-events: none;\n overflow: hidden;\n visibility: hidden;\n}\n.walros-theme-glitch-root.is-active {\n visibility: visible;\n}\n.walros-theme-glitch-root::before,\n.walros-theme-glitch-root::after {\n content: \"\";\n position: absolute;\n inset: 0;\n}\n.walros-theme-glitch-root::before {\n background: rgba(0, 0, 0, .82);\n mix-blend-mode: normal;\n animation: walros-glitch-flash 1500ms steps(1, end) both;\n}\n.walros-theme-glitch-root::after {\n background: repeating-linear-gradient(0deg, transparent 0 3px, rgba(255,255,255,.09) 3px 4px);\n animation: walros-glitch-scan 90ms steps(2, end) 16 both;\n}\n.walros-theme-glitch-band {\n position: absolute;\n left: -12%;\n width: 124%;\n opacity: 0;\n}\n.walros-theme-glitch-band:nth-child(1) { top: 12%; height: 4%; background: #eaf6ff; animation: walros-glitch-band-a 1500ms steps(1, end) both; }\n.walros-theme-glitch-band:nth-child(2) { top: 36%; height: 11%; background: #020407; animation: walros-glitch-band-b 1500ms steps(1, end) both; }\n.walros-theme-glitch-band:nth-child(3) { top: 62%; height: 2%; background: #7faddb; animation: walros-glitch-band-c 1500ms steps(1, end) both; }\n.walros-theme-glitch-band:nth-child(4) { top: 79%; height: 8%; background: #f4f6f5; animation: walros-glitch-band-d 1500ms steps(1, end) both; }\n\n@keyframes walros-glitch-scan {\n 0% { transform: translateY(-2px); opacity: .25; }\n 50% { transform: translateY(2px); opacity: .08; }\n 100% { transform: translateY(0); opacity: .2; }\n}\n@keyframes walros-glitch-flash {\n 0%, 17%, 22%, 34%, 39%, 54%, 59%, 73%, 78%, 100% { opacity: 0; }\n 18%, 21% { opacity: .18; }\n 35%, 38% { opacity: .48; }\n 55%, 58% { opacity: .82; }\n 74%, 77% { opacity: .22; }\n}\n@keyframes walros-glitch-band-a {\n 0%, 8%, 18%, 42%, 51%, 73%, 82%, 100% { opacity: 0; transform: translateX(0); }\n 9%, 17% { opacity: .55; transform: translateX(-7%); }\n 43%, 50% { opacity: .82; transform: translateX(10%); }\n 74%, 81% { opacity: .32; transform: translateX(-4%); }\n}\n@keyframes walros-glitch-band-b {\n 0%, 20%, 27%, 46%, 55%, 64%, 71%, 100% { opacity: 0; transform: translateX(0); }\n 21%, 26% { opacity: .72; transform: translateX(9%); }\n 47%, 54% { opacity: .9; transform: translateX(-6%); }\n 65%, 70% { opacity: .5; transform: translateX(4%); }\n}\n@keyframes walros-glitch-band-c {\n 0%, 13%, 23%, 39%, 48%, 67%, 76%, 100% { opacity: 0; transform: translateX(0); }\n 14%, 22% { opacity: .9; transform: translateX(5%); }\n 40%, 47% { opacity: .65; transform: translateX(-11%); }\n 68%, 75% { opacity: .75; transform: translateX(8%); }\n}\n@keyframes walros-glitch-band-d {\n 0%, 29%, 38%, 57%, 65%, 85%, 93%, 100% { opacity: 0; transform: translateX(0); }\n 30%, 37% { opacity: .42; transform: translateX(-8%); }\n 58%, 64% { opacity: .7; transform: translateX(7%); }\n 86%, 92% { opacity: .25; transform: translateX(-3%); }\n}\n\n.walros-theme-glitch-lock {\n overscroll-behavior: none;\n}\n\n.walros-theme-glitch-page {\n will-change: transform, filter;\n}\n\n/* Comportamiento original de WalrOS Forum para páginas normales. */\n.walros-theme-glitch-page--body {\n animation: walros-glitch-page-body 1500ms steps(1, end) both;\n}\n\n@keyframes walros-glitch-page-body {\n 0%, 6%, 18%, 31%, 49%, 68%, 82%, 100% { transform: translate3d(0,0,0) scale(1); filter: none; }\n 7% { transform: translate3d(-18px,4px,0) scale(1.012); filter: contrast(1.5) saturate(.45); }\n 19% { transform: translate3d(26px,-7px,0) scale(1.02) skewX(-1.2deg); filter: contrast(1.9) saturate(1.6); }\n 32% { transform: translate3d(-9px,11px,0) scale(1.03); filter: invert(.12) contrast(2); }\n 50%, 57% { transform: translate3d(34px,-3px,0) scale(1.025); filter: grayscale(1) contrast(2.3); }\n 69% { transform: translate3d(-24px,5px,0) scale(1.016); filter: contrast(1.7) saturate(.2); }\n 83% { transform: translate3d(8px,-2px,0) scale(1.006); filter: contrast(1.35); }\n}\n\n/*\n * Modo seguro para parallax/sticky/ScrollTrigger.\n * El shake se aplica a una capa estable del viewport, nunca al scroll real.\n * El pequeño overscan evita descubrir bordes al desplazar la escena.\n */\n.walros-theme-glitch-page--viewport {\n transform-origin: 50% var(--walros-glitch-origin-y, 50%);\n animation: walros-glitch-page-viewport 1500ms steps(1, end) both;\n}\n\n@keyframes walros-glitch-page-viewport {\n 0%, 6%, 18%, 31%, 49%, 68%, 82%, 100% { transform: translate3d(0,0,0) scale(1.012); filter: none; }\n 7% { transform: translate3d(-18px,4px,0) scale(1.012); filter: contrast(1.5) saturate(.45); }\n 19% { transform: translate3d(26px,-7px,0) scale(1.02) skewX(-1.2deg); filter: contrast(1.9) saturate(1.6); }\n 32% { transform: translate3d(-9px,11px,0) scale(1.03); filter: invert(.12) contrast(2); }\n 50%, 57% { transform: translate3d(34px,-3px,0) scale(1.025); filter: grayscale(1) contrast(2.3); }\n 69% { transform: translate3d(-24px,5px,0) scale(1.016); filter: contrast(1.7) saturate(.2); }\n 83% { transform: translate3d(8px,-2px,0) scale(1.006); filter: contrast(1.35); }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .walros-theme-glitch-root::before,\n .walros-theme-glitch-root::after {\n animation: walros-glitch-reduced 150ms ease-out forwards;\n }\n\n .walros-theme-glitch-band {\n animation: none !important;\n }\n\n .walros-theme-glitch-page--body,\n .walros-theme-glitch-page--viewport {\n animation: none;\n }\n\n @keyframes walros-glitch-reduced {\n from { opacity: 0.35; }\n to { opacity: 0; }\n }\n}\n`;\n\nexport function WalrosThemeGlitch({\n active,\n zIndex = 9998,\n className,\n style,\n}: WalrosThemeGlitchProps) {\n return (\n <>\n <style>{GLITCH_STYLES}</style>\n {active ? (\n <div\n className={[\"walros-theme-glitch-root\", \"is-active\", className]\n .filter(Boolean)\n .join(\" \")}\n style={{ zIndex, ...style }}\n aria-hidden=\"true\"\n >\n <span className=\"walros-theme-glitch-band\" />\n <span className=\"walros-theme-glitch-band\" />\n <span className=\"walros-theme-glitch-band\" />\n <span className=\"walros-theme-glitch-band\" />\n </div>\n ) : null}\n </>\n );\n}\n\nexport default WalrosThemeGlitch;\n","import { useLayoutEffect, useState } from \"react\";\n\n/** Keep fixed overlays outside an animated body, which would otherwise\n * become their containing block and displace the portal during the glitch. */\nexport function useOverlayHost(zIndex: number) {\n const [host] = useState<HTMLDivElement | null>(() =>\n typeof document === \"undefined\" ? null : document.createElement(\"div\"),\n );\n\n useLayoutEffect(() => {\n if (!host) return;\n host.dataset.walrosOverlayRoot = \"\";\n host.style.position = \"fixed\";\n host.style.inset = \"0\";\n host.style.pointerEvents = \"none\";\n document.documentElement.appendChild(host);\n return () => host.remove();\n }, [host]);\n\n useLayoutEffect(() => {\n if (host) host.style.zIndex = String(zIndex);\n }, [host, zIndex]);\n\n return host;\n}\n","import { useEffect, useRef } from \"react\";\r\n\r\nconst DESKTOP_CURSOR_QUERY = \"(min-width: 1024px) and (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference)\";\n\nconst CURSOR_STYLES = `\n.directional-cursor { position: fixed; top: 0; left: 0; z-index: 9999; width: 20px; height: 22px; opacity: 0; pointer-events: none; contain: layout style; will-change: transform; transition: opacity 100ms linear; }\n.directional-cursor.is-visible { opacity: 1; }\n.directional-cursor-shape { width: 20px; height: 22px; transform-origin: center center; will-change: transform; }\n.directional-cursor svg { display: block; width: 20px; height: 22px; }\n@media (min-width: 1024px) and (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {\n html.has-directional-cursor, html.has-directional-cursor body, html.has-directional-cursor body * { cursor: none !important; }\n html.has-directional-cursor :is(a, button, [role=\"button\"], [onclick], .clickable, [data-clickable], input[type=\"button\"], input[type=\"submit\"], input[type=\"reset\"], label[for]),\n html.has-directional-cursor :is(a, button, [role=\"button\"], [onclick], .clickable, [data-clickable], input[type=\"button\"], input[type=\"submit\"], input[type=\"reset\"], label[for]) * { cursor: pointer !important; }\n html.has-directional-cursor :is(input, textarea, select, [contenteditable=\"true\"]) { cursor: text !important; }\n}\n`;\n\r\nexport function DirectionalCursor() {\r\n const positionLayer = useRef<HTMLDivElement>(null);\r\n const directionLayer = useRef<HTMLDivElement>(null);\r\n\r\n useEffect(() => {\r\n const position = positionLayer.current;\r\n const direction = directionLayer.current;\r\n if (!position || !direction) return;\r\n\r\n const media = window.matchMedia(DESKTOP_CURSOR_QUERY);\r\n let active = false;\r\n let frame = 0;\r\n let moveFrame = 0;\r\n let scaleTimer = 0;\r\n let latestEvent: MouseEvent | null = null;\r\n let currentX = window.innerWidth / 2;\r\n let currentY = -60;\r\n let targetX = currentX;\r\n let targetY = currentY;\r\n let currentAngle = 0;\r\n let targetAngle = 0;\r\n let hasAngle = false;\r\n let currentScale = 1;\r\n let targetScale = 1;\r\n let lastX = currentX;\r\n let lastY = 0;\r\n\r\n const render = () => {\r\n currentX += (targetX - currentX) * 0.4;\r\n currentY += (targetY - currentY) * 0.4;\r\n const angleDelta = ((targetAngle - currentAngle + 540) % 360) - 180;\r\n currentAngle += angleDelta * 0.24;\r\n currentScale += (targetScale - currentScale) * 0.24;\r\n\r\n position.style.transform = `translate3d(${currentX}px, ${currentY}px, 0)`;\r\n direction.style.transform = `translate(-50%, -50%) rotate(${currentAngle}deg) scale(${currentScale})`;\r\n\r\n const unsettled = Math.abs(targetX - currentX) > 0.08\r\n || Math.abs(targetY - currentY) > 0.08\r\n || Math.abs(angleDelta) > 0.08\r\n || Math.abs(targetScale - currentScale) > 0.002;\r\n frame = unsettled ? window.requestAnimationFrame(render) : 0;\r\n };\r\n\r\n const requestRender = () => {\r\n if (!frame) frame = window.requestAnimationFrame(render);\r\n };\r\n\r\n const processMove = () => {\r\n moveFrame = 0;\r\n const event = latestEvent;\r\n if (!event) return;\r\n const deltaX = event.clientX - lastX;\r\n const deltaY = event.clientY - lastY;\r\n const distance = Math.hypot(deltaX, deltaY);\r\n targetX = event.clientX;\r\n targetY = event.clientY;\r\n position.classList.add(\"is-visible\");\r\n\r\n if (distance > 1.25) {\r\n const rawAngle = Math.atan2(deltaY, deltaX) * (180 / Math.PI) + 90;\r\n const normalizedAngle = (rawAngle % 360 + 360) % 360;\r\n if (!hasAngle) {\r\n targetAngle = normalizedAngle;\r\n currentAngle = normalizedAngle;\r\n hasAngle = true;\r\n } else {\r\n targetAngle = normalizedAngle;\r\n }\r\n\r\n targetScale = 0.92;\r\n window.clearTimeout(scaleTimer);\r\n scaleTimer = window.setTimeout(() => {\r\n targetScale = 1;\r\n requestRender();\r\n }, 130);\r\n }\r\n\r\n lastX = event.clientX;\r\n lastY = event.clientY;\r\n requestRender();\r\n };\r\n\r\n const handleMouseMove = (event: MouseEvent) => {\r\n latestEvent = event;\r\n if (!moveFrame) moveFrame = window.requestAnimationFrame(processMove);\r\n };\r\n\r\n const activate = () => {\r\n if (active) return;\r\n active = true;\r\n document.documentElement.classList.add(\"has-directional-cursor\");\r\n window.addEventListener(\"mousemove\", handleMouseMove, { passive: true });\r\n };\r\n\r\n const deactivate = () => {\r\n if (!active) return;\r\n active = false;\r\n document.documentElement.classList.remove(\"has-directional-cursor\");\r\n position.classList.remove(\"is-visible\");\r\n window.removeEventListener(\"mousemove\", handleMouseMove);\r\n window.cancelAnimationFrame(frame);\r\n window.cancelAnimationFrame(moveFrame);\r\n window.clearTimeout(scaleTimer);\r\n frame = 0;\r\n moveFrame = 0;\r\n };\r\n\r\n const sync = () => {\r\n if (media.matches) activate();\r\n else deactivate();\r\n };\r\n media.addEventListener(\"change\", sync);\r\n sync();\r\n\r\n return () => {\r\n media.removeEventListener(\"change\", sync);\r\n deactivate();\r\n };\r\n }, []);\r\n\r\n return (\n <><style>{CURSOR_STYLES}</style><div ref={positionLayer} className=\"directional-cursor\" aria-hidden=\"true\">\n <div ref={directionLayer} className=\"directional-cursor-shape\">\r\n <svg width=\"50\" height=\"54\" viewBox=\"0 0 50 54\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <g filter=\"url(#walros-cursor-shadow)\">\r\n <path d=\"M42.6817 41.1495L27.5103 6.79925C26.7269 5.02557 24.2082 5.02558 23.3927 6.79925L7.59814 41.1495C6.75833 42.9759 8.52712 44.8902 10.4125 44.1954L24.3757 39.0496C24.8829 38.8627 25.4385 38.8627 25.9422 39.0496L39.8121 44.1954C41.6849 44.8902 43.4884 42.9759 42.6817 41.1495Z\" fill=\"black\" />\r\n <path d=\"M43.7146 40.6933L28.5431 6.34306C27.3556 3.65428 23.5772 3.69516 22.3668 6.32755L6.57226 40.6778C5.3134 43.4156 7.97238 46.298 10.803 45.2549L24.7662 40.109C25.0221 40.0147 25.2999 40.0156 25.5494 40.1082L39.4193 45.254C42.2261 46.2953 44.9254 43.4347 43.7146 40.6933Z\" stroke=\"white\" strokeWidth=\"2.25825\" />\r\n </g>\r\n <defs>\r\n <filter id=\"walros-cursor-shadow\" x=\"0.602397\" y=\"0.952444\" width=\"49.0584\" height=\"52.428\" filterUnits=\"userSpaceOnUse\" colorInterpolationFilters=\"sRGB\">\r\n <feFlood floodOpacity=\"0\" result=\"BackgroundImageFix\" />\r\n <feColorMatrix in=\"SourceAlpha\" type=\"matrix\" values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\" result=\"hardAlpha\" />\r\n <feOffset dy=\"2.25825\" />\r\n <feGaussianBlur stdDeviation=\"2.25825\" />\r\n <feComposite in2=\"hardAlpha\" operator=\"out\" />\r\n <feColorMatrix type=\"matrix\" values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.08 0\" />\r\n <feBlend mode=\"normal\" in2=\"BackgroundImageFix\" result=\"effect1_dropShadow\" />\r\n <feBlend mode=\"normal\" in=\"SourceGraphic\" in2=\"effect1_dropShadow\" result=\"shape\" />\r\n </filter>\r\n </defs>\r\n </svg>\r\n </div>\r\n </div></>\n );\n}\n","import type { ImgHTMLAttributes } from \"react\";\nimport { walrosLogoChromeUrl } from \"../assets\";\n\nexport type WalrosLogoProps = Omit<\n ImgHTMLAttributes<HTMLImageElement>,\n \"src\"\n>;\n\nexport function WalrosLogo({\n alt = \"WalrOS\",\n draggable = false,\n ...props\n}: WalrosLogoProps) {\n return (\n <img\n src={walrosLogoChromeUrl}\n alt={alt}\n draggable={draggable}\n {...props}\n />\n );\n}\n\nexport default WalrosLogo;\n","import type { ImgHTMLAttributes } from \"react\";\nimport {\n walrosWordmarkDarkUrl,\n walrosWordmarkLightUrl,\n} from \"../assets\";\n\nexport type WalrosWordmarkProps = Omit<\n ImgHTMLAttributes<HTMLImageElement>,\n \"src\"\n> & {\n variant?: \"light\" | \"dark\";\n};\n\nexport function WalrosWordmark({\n variant = \"light\",\n alt = \"WalrOS\",\n draggable = false,\n ...props\n}: WalrosWordmarkProps) {\n const src =\n variant === \"dark\"\n ? walrosWordmarkDarkUrl\n : walrosWordmarkLightUrl;\n\n return (\n <img\n src={src}\n alt={alt}\n draggable={draggable}\n {...props}\n />\n );\n}\n\nexport default WalrosWordmark;\n","import {\n useCallback,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport type { RefObject } from \"react\";\nimport { walrosThemeGlitchSoundUrl } from \"../assets\";\n\nexport type WalrosTheme = \"light\" | \"dark\";\nexport type WalrosThemeMode = \"body\" | \"viewport\";\n\nexport type WalrosThemeShakeTarget =\n | HTMLElement\n | RefObject<HTMLElement | null>\n | null\n | undefined;\n\nexport type UseWalrosThemeOptions = {\n storageKey?: string;\n defaultTheme?: WalrosTheme;\n useSystemPreference?: boolean;\n swapDelay?: number;\n totalDuration?: number;\n /** Set to false to disable audio, or provide a custom sound URL. */\n soundUrl?: string | false;\n /** Playback volume from 0 to 1. Defaults to the WalrOS site mix. */\n soundVolume?: number;\n applyTheme?: (theme: WalrosTheme) => void;\n\n /**\n * `body` reproduce el comportamiento original de WalrOS Forum.\n * `viewport` bloquea el scroll y sacude solo los elementos indicados,\n * recomendado para parallax, sticky y GSAP ScrollTrigger.\n */\n mode?: WalrosThemeMode;\n\n /** Elementos que recibirán el shake cuando mode=\"viewport\". */\n shakeTargets?: readonly WalrosThemeShakeTarget[];\n\n /**\n * En modo viewport se activa por defecto. Mantiene scrollX/scrollY estables\n * con requestAnimationFrame sin usar position: fixed en el body.\n */\n lockScroll?: boolean;\n\n /** Se ejecuta después de restaurar el scroll; útil para ScrollTrigger.update(). */\n onAfterUnlock?: () => void;\n};\n\nexport type UseWalrosThemeResult = {\n theme: WalrosTheme;\n isDark: boolean;\n mounted: boolean;\n glitching: boolean;\n toggleTheme: () => void;\n setTheme: (theme: WalrosTheme) => void;\n};\n\ntype ViewportLockState = {\n scrollX: number;\n scrollY: number;\n rafId: number;\n active: boolean;\n bodyOverflow: string;\n htmlOverflow: string;\n htmlOverscrollBehavior: string;\n};\n\nconst GLITCH_BASE_CLASS = \"walros-theme-glitch-page\";\nconst GLITCH_BODY_CLASS = \"walros-theme-glitch-page--body\";\nconst GLITCH_VIEWPORT_CLASS = \"walros-theme-glitch-page--viewport\";\nconst GLITCH_LOCK_CLASS = \"walros-theme-glitch-lock\";\n\nfunction defaultApplyTheme(theme: WalrosTheme) {\n if (typeof document === \"undefined\") return;\n\n const root = document.documentElement;\n root.classList.toggle(\"dark\", theme === \"dark\");\n root.style.colorScheme = theme;\n}\n\nfunction readInitialTheme(\n storageKey: string,\n defaultTheme: WalrosTheme,\n useSystemPreference: boolean,\n): WalrosTheme {\n if (typeof window === \"undefined\") return defaultTheme;\n\n try {\n const stored = window.localStorage.getItem(storageKey);\n if (stored === \"light\" || stored === \"dark\") return stored;\n } catch {\n // localStorage puede estar bloqueado en modo privado.\n }\n\n if (\n useSystemPreference &&\n window.matchMedia?.(\"(prefers-color-scheme: dark)\").matches\n ) {\n return \"dark\";\n }\n\n return defaultTheme;\n}\n\nfunction resolveShakeTargets(\n targets: readonly WalrosThemeShakeTarget[],\n): HTMLElement[] {\n const resolved = new Set<HTMLElement>();\n\n for (const target of targets) {\n if (!target) continue;\n\n const element =\n typeof target === \"object\" && \"current\" in target\n ? target.current\n : target;\n\n if (element) resolved.add(element);\n }\n\n return [...resolved];\n}\n\nexport function useWalrosTheme({\n storageKey = \"walros-theme\",\n defaultTheme = \"light\",\n useSystemPreference = false,\n swapDelay = 610,\n totalDuration = 1500,\n soundUrl = walrosThemeGlitchSoundUrl,\n soundVolume = 0.52,\n applyTheme = defaultApplyTheme,\n mode = \"body\",\n shakeTargets = [],\n lockScroll,\n onAfterUnlock,\n}: UseWalrosThemeOptions = {}): UseWalrosThemeResult {\n const [theme, setThemeState] = useState<WalrosTheme>(() =>\n readInitialTheme(storageKey, defaultTheme, useSystemPreference),\n );\n const [mounted, setMounted] = useState(false);\n const [glitching, setGlitching] = useState(false);\n\n const themeRef = useRef(theme);\n const glitchingRef = useRef(false);\n const swapTimerRef = useRef<number | null>(null);\n const cleanupTimerRef = useRef<number | null>(null);\n const applyThemeRef = useRef(applyTheme);\n const modeRef = useRef(mode);\n const shakeTargetsRef = useRef(shakeTargets);\n const lockScrollRef = useRef(lockScroll);\n const onAfterUnlockRef = useRef(onAfterUnlock);\n const activeTargetsRef = useRef<HTMLElement[]>([]);\n const viewportLockRef = useRef<ViewportLockState | null>(null);\n const soundRef = useRef<HTMLAudioElement | null>(null);\n const soundUrlRef = useRef(soundUrl);\n const soundVolumeRef = useRef(soundVolume);\n\n themeRef.current = theme;\n applyThemeRef.current = applyTheme;\n modeRef.current = mode;\n shakeTargetsRef.current = shakeTargets;\n lockScrollRef.current = lockScroll;\n onAfterUnlockRef.current = onAfterUnlock;\n soundUrlRef.current = soundUrl;\n soundVolumeRef.current = soundVolume;\n\n const playThemeSound = useCallback(() => {\n if (typeof window === \"undefined\" || !soundUrlRef.current) return;\n\n try {\n if (!soundRef.current || soundRef.current.src !== new URL(soundUrlRef.current, document.baseURI).href) {\n soundRef.current?.pause();\n soundRef.current = new Audio(soundUrlRef.current);\n soundRef.current.preload = \"auto\";\n }\n const audio = soundRef.current;\n audio.volume = Math.max(0, Math.min(1, soundVolumeRef.current));\n audio.currentTime = 0;\n void audio.play().catch(() => {\n // Browsers may block sound; the theme animation still continues.\n });\n } catch {\n // Audio support is optional and must not block the theme change.\n }\n }, []);\n\n const persistTheme = useCallback(\n (nextTheme: WalrosTheme) => {\n applyThemeRef.current(nextTheme);\n setThemeState(nextTheme);\n themeRef.current = nextTheme;\n\n try {\n window.localStorage.setItem(storageKey, nextTheme);\n } catch {\n // El cambio debe funcionar aunque localStorage falle.\n }\n },\n [storageKey],\n );\n\n useEffect(() => {\n const initialTheme = readInitialTheme(\n storageKey,\n defaultTheme,\n useSystemPreference,\n );\n\n themeRef.current = initialTheme;\n setThemeState(initialTheme);\n applyThemeRef.current(initialTheme);\n setMounted(true);\n }, [defaultTheme, storageKey, useSystemPreference]);\n\n const clearTimers = useCallback(() => {\n if (swapTimerRef.current !== null) {\n window.clearTimeout(swapTimerRef.current);\n swapTimerRef.current = null;\n }\n\n if (cleanupTimerRef.current !== null) {\n window.clearTimeout(cleanupTimerRef.current);\n cleanupTimerRef.current = null;\n }\n }, []);\n\n const lockViewport = useCallback(() => {\n if (\n typeof window === \"undefined\" ||\n typeof document === \"undefined\" ||\n viewportLockRef.current\n ) {\n return;\n }\n\n const body = document.body;\n const html = document.documentElement;\n const lockState: ViewportLockState = {\n scrollX: window.scrollX,\n scrollY: window.scrollY,\n rafId: 0,\n active: true,\n bodyOverflow: body.style.overflow,\n htmlOverflow: html.style.overflow,\n htmlOverscrollBehavior: html.style.overscrollBehavior,\n };\n\n viewportLockRef.current = lockState;\n\n const keepScrollStable = () => {\n if (!lockState.active) return;\n window.scrollTo(lockState.scrollX, lockState.scrollY);\n lockState.rafId = window.requestAnimationFrame(keepScrollStable);\n };\n\n html.classList.add(GLITCH_LOCK_CLASS);\n html.style.overflow = \"hidden\";\n html.style.overscrollBehavior = \"none\";\n body.style.overflow = \"hidden\";\n lockState.rafId = window.requestAnimationFrame(keepScrollStable);\n }, []);\n\n const unlockViewport = useCallback((runCallback: boolean) => {\n if (typeof window === \"undefined\" || typeof document === \"undefined\") {\n return;\n }\n\n const lockState = viewportLockRef.current;\n if (!lockState) return;\n\n lockState.active = false;\n window.cancelAnimationFrame(lockState.rafId);\n\n const body = document.body;\n const html = document.documentElement;\n body.style.overflow = lockState.bodyOverflow;\n html.style.overflow = lockState.htmlOverflow;\n html.style.overscrollBehavior = lockState.htmlOverscrollBehavior;\n html.classList.remove(GLITCH_LOCK_CLASS);\n\n viewportLockRef.current = null;\n window.scrollTo(lockState.scrollX, lockState.scrollY);\n\n if (runCallback) {\n window.requestAnimationFrame(() => {\n onAfterUnlockRef.current?.();\n });\n }\n }, []);\n\n const removeShakeClasses = useCallback(() => {\n for (const target of activeTargetsRef.current) {\n target.classList.remove(\n GLITCH_BASE_CLASS,\n GLITCH_BODY_CLASS,\n GLITCH_VIEWPORT_CLASS,\n );\n target.style.removeProperty(\"--walros-glitch-origin-y\");\n }\n\n activeTargetsRef.current = [];\n }, []);\n\n const finishGlitch = useCallback(() => {\n if (soundRef.current) {\n soundRef.current.pause();\n soundRef.current.currentTime = 0;\n }\n removeShakeClasses();\n unlockViewport(true);\n glitchingRef.current = false;\n setGlitching(false);\n }, [removeShakeClasses, unlockViewport]);\n\n const setTheme = useCallback(\n (nextTheme: WalrosTheme) => {\n if (glitchingRef.current) return;\n persistTheme(nextTheme);\n },\n [persistTheme],\n );\n\n const toggleTheme = useCallback(() => {\n if (\n typeof window === \"undefined\" ||\n typeof document === \"undefined\" ||\n glitchingRef.current\n ) {\n return;\n }\n\n playThemeSound();\n\n const currentMode = modeRef.current;\n const shouldLockScroll =\n lockScrollRef.current ?? currentMode === \"viewport\";\n\n if (currentMode === \"viewport\" && shouldLockScroll) {\n lockViewport();\n }\n\n const targets =\n currentMode === \"body\"\n ? [document.body]\n : resolveShakeTargets(shakeTargetsRef.current);\n\n const modeClass =\n currentMode === \"body\"\n ? GLITCH_BODY_CLASS\n : GLITCH_VIEWPORT_CLASS;\n\n for (const target of targets) {\n target.style.setProperty(\n \"--walros-glitch-origin-y\",\n currentMode === \"body\"\n ? `${window.scrollY + window.innerHeight / 2}px`\n : \"50%\",\n );\n target.classList.add(GLITCH_BASE_CLASS, modeClass);\n }\n\n activeTargetsRef.current = targets;\n glitchingRef.current = true;\n setGlitching(true);\n\n const reducedMotion = window.matchMedia?.(\n \"(prefers-reduced-motion: reduce)\",\n ).matches;\n\n const nextTheme: WalrosTheme =\n themeRef.current === \"dark\" ? \"light\" : \"dark\";\n\n const effectiveSwapDelay = reducedMotion\n ? 75\n : Math.max(0, swapDelay);\n const effectiveDuration = reducedMotion\n ? 150\n : Math.max(effectiveSwapDelay, totalDuration);\n\n swapTimerRef.current = window.setTimeout(() => {\n persistTheme(nextTheme);\n swapTimerRef.current = null;\n }, effectiveSwapDelay);\n\n cleanupTimerRef.current = window.setTimeout(() => {\n cleanupTimerRef.current = null;\n finishGlitch();\n }, effectiveDuration);\n }, [finishGlitch, lockViewport, persistTheme, playThemeSound, swapDelay, totalDuration]);\n\n useEffect(() => {\n return () => {\n clearTimers();\n removeShakeClasses();\n unlockViewport(false);\n soundRef.current?.pause();\n if (soundRef.current) soundRef.current.currentTime = 0;\n soundRef.current = null;\n };\n }, [clearTimers, removeShakeClasses, unlockViewport]);\n\n return {\n theme,\n isDark: theme === \"dark\",\n mounted,\n glitching,\n toggleTheme,\n setTheme,\n };\n}\n\nexport default useWalrosTheme;\n"],"mappings":"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","names":["useState","createPortal","useEffect","useLayoutEffect","useRef","useState","jsx","jsxs","useLayoutEffect","useState","Fragment","jsx","jsxs","VISIBLE_LEFT","VISIBLE_RIGHT","VISIBLE_TOP","VISIBLE_BOTTOM","useRef","useState","useLayoutEffect","useEffect","jsx","useState","createPortal","useEffect","useRef","Fragment","jsx","jsxs","jsx","jsx","useEffect","useRef","useState","useState","useRef","useEffect"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/WalrosPortalTransition.tsx","../src/assets.ts","../src/components/Walros3DPortalTransition.tsx","../src/portalSilhouette.ts","../src/components/useOverlayHost.ts","../src/components/WalrosThemeTransition.tsx","../src/components/WalrosThemeGlitch.tsx","../src/components/DirectionalCursor.tsx","../src/components/WalrosLogo.tsx","../src/components/WalrosWordmark.tsx","../src/hooks/useWalrosTheme.ts"],"sourcesContent":["import { useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { walrosLogoChromeUrl } from \"../assets\";\nimport { Walros3DPortalTransition, type PortalOrigin } from \"./Walros3DPortalTransition\";\nimport { useOverlayHost } from \"./useOverlayHost\";\n\nexport type WalrosPortalTransitionProps = {\n duration?: number;\n onComplete?: () => void;\n backgroundColor?: string;\n enabled?: boolean;\n storageMode?: \"always\" | \"session\" | \"once\";\n storageKey?: string;\n zIndex?: number;\n /** Projected bounds of an existing 3D logo, as on walros.org. */\n origin?: PortalOrigin;\n /** Intro logo shown beneath the black mask; set false when using an existing 3D logo. */\n logoUrl?: string | false;\n};\n\nconst IMAGE_SIZE = (width: number) => Math.min(150, Math.max(90, width * .11));\nconst IMAGE_WIDTH = 1254;\nconst VISIBLE_LEFT = 244;\nconst VISIBLE_RIGHT = 1010;\nconst VISIBLE_TOP = 115;\nconst VISIBLE_BOTTOM = 1128;\n\nfunction defaultOrigin(): PortalOrigin {\n if (typeof window === \"undefined\") return { centerX: 0, centerY: 0, width: 70, height: 90 };\n const size = IMAGE_SIZE(window.innerWidth);\n return {\n centerX: window.innerWidth / 2,\n centerY: window.innerHeight * .45 + (((VISIBLE_TOP + VISIBLE_BOTTOM) / 2 - IMAGE_WIDTH / 2) / IMAGE_WIDTH) * size,\n width: ((VISIBLE_RIGHT - VISIBLE_LEFT) / IMAGE_WIDTH) * size,\n height: ((VISIBLE_BOTTOM - VISIBLE_TOP) / IMAGE_WIDTH) * size,\n };\n}\n\nfunction getStorage(mode: \"session\" | \"once\"): Storage | null {\n if (typeof window === \"undefined\") return null;\n try {\n return mode === \"session\" ? window.sessionStorage : window.localStorage;\n } catch {\n return null;\n }\n}\n\nfunction shouldRun(enabled: boolean, mode: \"always\" | \"session\" | \"once\", key: string) {\n if (!enabled) return false;\n if (mode === \"always\") return true;\n try {\n return getStorage(mode)?.getItem(key) == null;\n } catch {\n return true;\n }\n}\n\n/** 900 ms walros.org entrance, with the logo confined below its black mask. */\nexport function WalrosPortalTransition({\n duration = 900,\n onComplete,\n backgroundColor = \"#000\",\n enabled = true,\n storageMode = \"always\",\n storageKey = \"walros-portal-seen\",\n zIndex = 10000,\n origin,\n logoUrl = walrosLogoChromeUrl,\n}: WalrosPortalTransitionProps) {\n const [run] = useState(() => shouldRun(enabled, storageMode, storageKey));\n const [complete, setComplete] = useState(false);\n const [initialOrigin] = useState(() => origin ?? defaultOrigin());\n const host = useOverlayHost(zIndex);\n\n if (!host || !enabled || !run || complete) return null;\n\n return createPortal(\n <Walros3DPortalTransition\n origin={initialOrigin}\n logoUrl={logoUrl}\n duration={duration}\n backgroundColor={backgroundColor}\n zIndex={1}\n lockScroll\n onComplete={() => {\n if (storageMode !== \"always\") {\n try { getStorage(storageMode)?.setItem(storageKey, \"1\"); } catch { /* Storage is optional. */ }\n }\n setComplete(true);\n onComplete?.();\n }}\n />,\n host,\n );\n}\n\nexport default WalrosPortalTransition;\n","export const walrosPortalSilhouetteUrl = new URL(\n \"./assets/walros-portal-silhouette.svg\",\n import.meta.url,\n).href;\n\nexport const walrosLogoChromeUrl = new URL(\n \"./assets/walros-logo-chrome.png\",\n import.meta.url,\n).href;\n\nexport const walrosWordmarkLightUrl = new URL(\n \"./assets/walros-wordmark-light.png\",\n import.meta.url,\n).href;\n\nexport const walrosWordmarkDarkUrl = new URL(\n \"./assets/walros-wordmark-dark.png\",\n import.meta.url,\n).href;\n\nexport const walrosThemeGlitchSoundUrl = new URL(\n \"./assets/walros-theme-glitch.mp3\",\n import.meta.url,\n).href;\n","import { useEffect, useId, useLayoutEffect, useRef, useState } from \"react\";\nimport gsap from \"gsap\";\nimport { walrosPortalPaths } from \"../portalSilhouette\";\n\r\nexport type PortalOrigin = {\r\n centerX: number;\r\n centerY: number;\r\n width: number;\r\n height: number;\r\n};\r\n\r\nexport type Walros3DPortalTransitionProps = {\n origin: PortalOrigin;\n onComplete?: () => void;\n duration?: number;\n backgroundColor?: string;\n zIndex?: number;\n lockScroll?: boolean;\n /** An optional image that follows the portal exactly and fades before reveal. */\n logoUrl?: string | false;\n};\n\r\nconst FOCUS_X = 626;\r\nconst FOCUS_Y = 333;\r\nconst VISIBLE_LEFT = 244;\r\nconst VISIBLE_RIGHT = 1010;\r\nconst VISIBLE_TOP = 115;\r\nconst VISIBLE_BOTTOM = 1128;\r\nconst PORTAL_RADIUS = 190;\r\n\r\nexport function Walros3DPortalTransition({\n origin,\n onComplete,\n duration = 900,\n backgroundColor = \"#000\",\n zIndex = 10001,\n lockScroll = true,\n logoUrl = false,\n}: Walros3DPortalTransitionProps) {\n const [visible, setVisible] = useState(true);\n const [viewport, setViewport] = useState(() => ({\n width: typeof window === \"undefined\" ? 0 : window.innerWidth,\n height: typeof window === \"undefined\" ? 0 : window.innerHeight,\n }));\n const overlay = useRef<HTMLDivElement>(null);\n const portal = useRef<SVGGElement>(null);\n const logo = useRef<SVGGElement>(null);\n const completeRef = useRef(onComplete);\n completeRef.current = onComplete;\n const maskId = `walros-3d-portal-${useId().replace(/:/g, \"_\")}`;\n\r\n useEffect(() => {\r\n const updateViewport = () => setViewport({ width: window.innerWidth, height: window.innerHeight });\r\n window.addEventListener(\"resize\", updateViewport);\r\n return () => window.removeEventListener(\"resize\", updateViewport);\r\n }, []);\r\n\r\n useLayoutEffect(() => {\n if (!visible || viewport.width <= 0 || viewport.height <= 0 || !overlay.current || !portal.current) return;\n const previousOverflow = document.body.style.overflow;\n if (lockScroll) document.body.style.overflow = \"hidden\";\n\r\n const visibleWidth = VISIBLE_RIGHT - VISIBLE_LEFT;\r\n const visibleHeight = VISIBLE_BOTTOM - VISIBLE_TOP;\r\n const visualCenterX = (VISIBLE_LEFT + VISIBLE_RIGHT) / 2;\r\n const visualCenterY = (VISIBLE_TOP + VISIBLE_BOTTOM) / 2;\r\n // Let the black mask overlap the projected GLB by roughly one pixel. This\r\n // removes the pale halo without visibly cropping the chrome silhouette.\r\n const initialScale = Math.min(origin.width / visibleWidth, origin.height / visibleHeight) * .985;\r\n const initialX = origin.centerX - (visualCenterX - FOCUS_X) * initialScale;\r\n const initialY = origin.centerY - (visualCenterY - FOCUS_Y) * initialScale;\r\n const diagonal = Math.hypot(viewport.width, viewport.height) / 2;\n const finalScale = ((diagonal + 80) / PORTAL_RADIUS) * 1.15;\n // The visible silhouette, rather than the SVG transform origin, must\n // remain centred as the portal grows.\n const targetX = viewport.width / 2 - (visualCenterX - FOCUS_X) * finalScale;\n const targetY = viewport.height / 2 - (visualCenterY - FOCUS_Y) * finalScale;\n const total = duration / 1000;\r\n\r\n gsap.set(portal.current, {\n x: initialX,\n y: initialY,\n scale: initialScale,\n svgOrigin: \"0 0\",\n });\n if (logo.current) {\n gsap.set(logo.current, {\n x: initialX,\n y: initialY,\n scale: initialScale,\n opacity: 1,\n svgOrigin: \"0 0\",\n });\n }\n gsap.set(overlay.current, { opacity: 1 });\n\r\n const finish = () => {\r\n if (lockScroll) document.body.style.overflow = previousOverflow;\n setVisible(false);\n completeRef.current?.();\n };\r\n const reducedMotion = window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\r\n const timeline = gsap.timeline({ onComplete: finish });\r\n if (reducedMotion) {\r\n timeline.to(overlay.current, { opacity: 0, duration: 0.15, ease: \"power1.out\" });\n } else {\n timeline\n .to([portal.current, logo.current].filter(Boolean), {\n x: targetX,\n y: targetY,\n scale: finalScale,\n duration: total,\n ease: \"power2.in\",\n });\n if (logo.current) {\n timeline.to(logo.current, {\n opacity: 0,\n duration: total * .18,\n ease: \"power1.out\",\n }, total * .7);\n }\n timeline\n .to(overlay.current, {\n opacity: 0,\r\n duration: total * 0.1,\r\n ease: \"power2.out\",\r\n }, total * 0.9);\r\n }\r\n\r\n return () => {\r\n timeline.kill();\r\n if (lockScroll) document.body.style.overflow = previousOverflow;\n };\n }, [duration, lockScroll, origin, viewport, visible]);\n\n if (!visible) return null;\n\r\n return (\r\n <div\r\n ref={overlay}\r\n className=\"walros-3d-portal\"\n style={{\n position: \"fixed\",\n inset: 0,\n width: \"100vw\",\n height: \"100dvh\",\n overflow: \"hidden\",\n pointerEvents: \"none\",\n zIndex,\n backgroundColor: viewport.width > 0 && viewport.height > 0 ? \"transparent\" : backgroundColor,\n }}\n aria-hidden=\"true\"\r\n >\r\n <svg width=\"100%\" height=\"100%\" viewBox={`0 0 ${viewport.width} ${viewport.height}`} preserveAspectRatio=\"none\" style={{ display: \"block\" }}>\n <defs>\r\n <mask id={maskId} maskUnits=\"userSpaceOnUse\" x=\"0\" y=\"0\" width={viewport.width} height={viewport.height}>\r\n <rect width={viewport.width} height={viewport.height} fill=\"white\" />\r\n <g ref={portal}>\r\n <g transform={`translate(${-FOCUS_X} ${-FOCUS_Y})`} fill=\"black\">\r\n {walrosPortalPaths.map((path, index) => <path d={path} key={index} />)}\n </g>\r\n </g>\r\n </mask>\r\n </defs>\n {logoUrl && (\n <g ref={logo}>\n <image href={logoUrl} x={-FOCUS_X} y={-FOCUS_Y} width=\"1254\" height=\"1254\" />\n </g>\n )}\n <rect width={viewport.width} height={viewport.height} fill={backgroundColor} mask={`url(#${maskId})`} />\n </svg>\r\n </div>\r\n );\r\n}\r\n","/* Exact silhouette used by the walros.org portal mask. */\r\nexport const walrosPortalPaths = [\r\n \"M 244.00 354.00 C 240.50 377.67, 240.17 413.67, 242.00 434.00 C 243.83 454.33, 249.50 464.50, 255.00 476.00 C 260.50 487.50, 268.50 496.00, 275.00 503.00 C 281.50 510.00, 287.17 513.67, 294.00 518.00 C 300.83 522.33, 306.00 525.67, 316.00 529.00 C 326.00 532.33, 336.33 536.67, 354.00 538.00 C 371.67 539.33, 397.83 540.83, 422.00 537.00 C 446.17 533.17, 474.17 525.33, 499.00 515.00 C 523.83 504.67, 550.00 489.33, 571.00 475.00 C 592.00 460.67, 615.00 436.50, 625.00 429.00 C 635.00 421.50, 623.67 424.00, 631.00 430.00 C 638.33 436.00, 656.67 454.83, 669.00 465.00 C 681.33 475.17, 690.00 482.17, 705.00 491.00 C 720.00 499.83, 743.67 511.50, 759.00 518.00 C 774.33 524.50, 784.00 526.83, 797.00 530.00 C 810.00 533.17, 820.00 535.83, 837.00 537.00 C 854.00 538.17, 881.17 539.00, 899.00 537.00 C 916.83 535.00, 932.00 530.00, 944.00 525.00 C 956.00 520.00, 962.00 516.17, 971.00 507.00 C 980.00 497.83, 991.67 482.83, 998.00 470.00 C 1004.33 457.17, 1007.17 446.33, 1009.00 430.00 C 1010.83 413.67, 1010.83 390.50, 1009.00 372.00 C 1007.17 353.50, 1003.83 337.17, 998.00 319.00 C 992.17 300.83, 983.67 280.17, 974.00 263.00 C 964.33 245.83, 952.00 229.67, 940.00 216.00 C 928.00 202.33, 917.17 192.00, 902.00 181.00 C 886.83 170.00, 866.50 158.17, 849.00 150.00 C 831.50 141.83, 816.67 137.00, 797.00 132.00 C 777.33 127.00, 756.67 122.83, 731.00 120.00 C 705.33 117.17, 673.67 115.33, 643.00 115.00 C 612.33 114.67, 575.67 115.67, 547.00 118.00 C 518.33 120.33, 496.17 123.00, 471.00 129.00 C 445.83 135.00, 418.33 143.50, 396.00 154.00 C 373.67 164.50, 353.50 178.50, 337.00 192.00 C 320.50 205.50, 309.33 218.33, 297.00 235.00 C 284.67 251.67, 271.83 272.17, 263.00 292.00 C 254.17 311.83, 247.50 330.33, 244.00 354.00 Z\",\r\n \"M 289.00 536.00 C 283.17 535.50, 284.83 533.00, 284.00 544.00 C 283.17 555.00, 282.67 578.67, 284.00 602.00 C 285.33 625.33, 287.00 651.83, 292.00 684.00 C 297.00 716.17, 306.33 763.50, 314.00 795.00 C 321.67 826.50, 328.67 847.17, 338.00 873.00 C 347.33 898.83, 357.00 923.67, 370.00 950.00 C 383.00 976.33, 399.67 1006.00, 416.00 1031.00 C 432.33 1056.00, 455.33 1084.50, 468.00 1100.00 C 480.67 1115.50, 486.17 1119.33, 492.00 1124.00 C 497.83 1128.67, 500.67 1127.67, 503.00 1128.00 C 505.33 1128.33, 505.50 1127.50, 506.00 1126.00 C 506.50 1124.50, 510.33 1132.00, 506.00 1119.00 C 501.67 1106.00, 488.17 1073.83, 480.00 1048.00 C 471.83 1022.17, 462.67 987.67, 457.00 964.00 C 451.33 940.33, 449.17 927.33, 446.00 906.00 C 442.83 884.67, 439.50 865.00, 438.00 836.00 C 436.50 807.00, 436.50 758.33, 437.00 732.00 C 437.50 705.67, 439.00 696.33, 441.00 678.00 C 443.00 659.67, 444.83 644.00, 449.00 622.00 C 453.17 600.00, 464.50 559.00, 466.00 546.00 C 467.50 533.00, 468.67 542.50, 458.00 544.00 C 447.33 545.50, 418.33 553.17, 402.00 555.00 C 385.67 556.83, 373.83 556.33, 360.00 555.00 C 346.17 553.67, 330.83 550.17, 319.00 547.00 C 307.17 543.83, 294.83 536.50, 289.00 536.00 Z\",\r\n \"M 961.00 537.00 C 948.50 539.17, 907.83 552.00, 889.00 555.00 C 870.17 558.00, 864.17 557.00, 848.00 555.00 C 831.83 553.00, 802.83 545.00, 792.00 543.00 C 781.17 541.00, 784.83 542.50, 783.00 543.00 C 781.17 543.50, 778.67 533.83, 781.00 546.00 C 783.33 558.17, 792.67 592.33, 797.00 616.00 C 801.33 639.67, 804.83 668.83, 807.00 688.00 C 809.17 707.17, 809.67 709.00, 810.00 731.00 C 810.33 753.00, 810.50 792.83, 809.00 820.00 C 807.50 847.17, 804.50 870.50, 801.00 894.00 C 797.50 917.50, 794.00 936.17, 788.00 961.00 C 782.00 985.83, 773.50 1016.67, 765.00 1043.00 C 756.50 1069.33, 741.33 1104.83, 737.00 1119.00 C 732.67 1133.17, 736.67 1127.17, 739.00 1128.00 C 741.33 1128.83, 745.83 1127.83, 751.00 1124.00 C 756.17 1120.17, 757.33 1120.50, 770.00 1105.00 C 782.67 1089.50, 811.33 1053.50, 827.00 1031.00 C 842.67 1008.50, 851.17 995.00, 864.00 970.00 C 876.83 945.00, 892.83 910.00, 904.00 881.00 C 915.17 852.00, 923.00 826.67, 931.00 796.00 C 939.00 765.33, 946.67 728.67, 952.00 697.00 C 957.33 665.33, 961.00 631.83, 963.00 606.00 C 965.00 580.17, 964.33 553.50, 964.00 542.00 C 963.67 530.50, 973.50 534.83, 961.00 537.00 Z\",\r\n] as const;\r\n","import { useLayoutEffect, useState } from \"react\";\n\n/** Keep fixed overlays outside an animated body, which would otherwise\n * become their containing block and displace the portal during the glitch. */\nexport function useOverlayHost(zIndex: number) {\n const [host] = useState<HTMLDivElement | null>(() =>\n typeof document === \"undefined\" ? null : document.createElement(\"div\"),\n );\n\n useLayoutEffect(() => {\n if (!host) return;\n host.dataset.walrosOverlayRoot = \"\";\n host.style.position = \"fixed\";\n host.style.inset = \"0\";\n host.style.pointerEvents = \"none\";\n document.documentElement.appendChild(host);\n return () => host.remove();\n }, [host]);\n\n useLayoutEffect(() => {\n if (host) host.style.zIndex = String(zIndex);\n }, [host, zIndex]);\n\n return host;\n}\n","import { createPortal } from \"react-dom\";\nimport { WalrosThemeGlitch } from \"./WalrosThemeGlitch\";\nimport { useOverlayHost } from \"./useOverlayHost\";\n\nexport type WalrosThemeTransitionProps = {\n /** Pass the `glitching` value returned by `useWalrosTheme`. */\n active: boolean;\n /** @deprecated The theme change has no portal; retained for source compatibility. */\n portalDuration?: number;\n /** @deprecated The theme change has no logo; retained for source compatibility. */\n logoUrl?: string;\n zIndex?: number;\n};\n\n/** The walros.org theme effect is a shake and glitch, without an intro logo. */\nexport function WalrosThemeTransition({\n active,\n zIndex = 10000,\n}: WalrosThemeTransitionProps) {\n const host = useOverlayHost(zIndex);\n if (!host) return null;\n\n return createPortal(\n <WalrosThemeGlitch active={active} zIndex={1} />,\n host,\n );\n}\n","import type { CSSProperties } from \"react\";\n\nexport type WalrosThemeGlitchProps = {\n active: boolean;\n zIndex?: number;\n className?: string;\n style?: CSSProperties;\n};\n\nconst GLITCH_STYLES = `\n.walros-theme-glitch-root {\n position: fixed;\n inset: 0;\n z-index: 9998;\n pointer-events: none;\n overflow: hidden;\n visibility: hidden;\n}\n.walros-theme-glitch-root.is-active {\n visibility: visible;\n}\n.walros-theme-glitch-root::before,\n.walros-theme-glitch-root::after {\n content: \"\";\n position: absolute;\n inset: 0;\n}\n.walros-theme-glitch-root::before {\n background: rgba(0, 0, 0, .82);\n mix-blend-mode: normal;\n animation: walros-glitch-flash 1500ms steps(1, end) both;\n}\n.walros-theme-glitch-root::after {\n background: repeating-linear-gradient(0deg, transparent 0 3px, rgba(255,255,255,.09) 3px 4px);\n animation: walros-glitch-scan 90ms steps(2, end) 16 both;\n}\n.walros-theme-glitch-band {\n position: absolute;\n left: -12%;\n width: 124%;\n opacity: 0;\n}\n.walros-theme-glitch-band:nth-child(1) { top: 12%; height: 4%; background: #eaf6ff; animation: walros-glitch-band-a 1500ms steps(1, end) both; }\n.walros-theme-glitch-band:nth-child(2) { top: 36%; height: 11%; background: #020407; animation: walros-glitch-band-b 1500ms steps(1, end) both; }\n.walros-theme-glitch-band:nth-child(3) { top: 62%; height: 2%; background: #7faddb; animation: walros-glitch-band-c 1500ms steps(1, end) both; }\n.walros-theme-glitch-band:nth-child(4) { top: 79%; height: 8%; background: #f4f6f5; animation: walros-glitch-band-d 1500ms steps(1, end) both; }\n\n@keyframes walros-glitch-scan {\n 0% { transform: translateY(-2px); opacity: .25; }\n 50% { transform: translateY(2px); opacity: .08; }\n 100% { transform: translateY(0); opacity: .2; }\n}\n@keyframes walros-glitch-flash {\n 0%, 17%, 22%, 34%, 39%, 54%, 59%, 73%, 78%, 100% { opacity: 0; }\n 18%, 21% { opacity: .18; }\n 35%, 38% { opacity: .48; }\n 55%, 58% { opacity: .82; }\n 74%, 77% { opacity: .22; }\n}\n@keyframes walros-glitch-band-a {\n 0%, 8%, 18%, 42%, 51%, 73%, 82%, 100% { opacity: 0; transform: translateX(0); }\n 9%, 17% { opacity: .55; transform: translateX(-7%); }\n 43%, 50% { opacity: .82; transform: translateX(10%); }\n 74%, 81% { opacity: .32; transform: translateX(-4%); }\n}\n@keyframes walros-glitch-band-b {\n 0%, 20%, 27%, 46%, 55%, 64%, 71%, 100% { opacity: 0; transform: translateX(0); }\n 21%, 26% { opacity: .72; transform: translateX(9%); }\n 47%, 54% { opacity: .9; transform: translateX(-6%); }\n 65%, 70% { opacity: .5; transform: translateX(4%); }\n}\n@keyframes walros-glitch-band-c {\n 0%, 13%, 23%, 39%, 48%, 67%, 76%, 100% { opacity: 0; transform: translateX(0); }\n 14%, 22% { opacity: .9; transform: translateX(5%); }\n 40%, 47% { opacity: .65; transform: translateX(-11%); }\n 68%, 75% { opacity: .75; transform: translateX(8%); }\n}\n@keyframes walros-glitch-band-d {\n 0%, 29%, 38%, 57%, 65%, 85%, 93%, 100% { opacity: 0; transform: translateX(0); }\n 30%, 37% { opacity: .42; transform: translateX(-8%); }\n 58%, 64% { opacity: .7; transform: translateX(7%); }\n 86%, 92% { opacity: .25; transform: translateX(-3%); }\n}\n\n.walros-theme-glitch-lock {\n overscroll-behavior: none;\n}\n\n.walros-theme-glitch-page {\n will-change: transform, filter;\n}\n\n/* Comportamiento original de WalrOS Forum para páginas normales. */\n.walros-theme-glitch-page--body {\n animation: walros-glitch-page-body 1500ms steps(1, end) both;\n}\n\n@keyframes walros-glitch-page-body {\n 0%, 6%, 18%, 31%, 49%, 68%, 82%, 100% { transform: translate3d(0,0,0) scale(1); filter: none; }\n 7% { transform: translate3d(-18px,4px,0) scale(1.012); filter: contrast(1.5) saturate(.45); }\n 19% { transform: translate3d(26px,-7px,0) scale(1.02) skewX(-1.2deg); filter: contrast(1.9) saturate(1.6); }\n 32% { transform: translate3d(-9px,11px,0) scale(1.03); filter: invert(.12) contrast(2); }\n 50%, 57% { transform: translate3d(34px,-3px,0) scale(1.025); filter: grayscale(1) contrast(2.3); }\n 69% { transform: translate3d(-24px,5px,0) scale(1.016); filter: contrast(1.7) saturate(.2); }\n 83% { transform: translate3d(8px,-2px,0) scale(1.006); filter: contrast(1.35); }\n}\n\n/*\n * Modo seguro para parallax/sticky/ScrollTrigger.\n * El shake se aplica a una capa estable del viewport, nunca al scroll real.\n * El pequeño overscan evita descubrir bordes al desplazar la escena.\n */\n.walros-theme-glitch-page--viewport {\n transform-origin: 50% var(--walros-glitch-origin-y, 50%);\n animation: walros-glitch-page-viewport 1500ms steps(1, end) both;\n}\n\n@keyframes walros-glitch-page-viewport {\n 0%, 6%, 18%, 31%, 49%, 68%, 82%, 100% { transform: translate3d(0,0,0) scale(1.012); filter: none; }\n 7% { transform: translate3d(-18px,4px,0) scale(1.012); filter: contrast(1.5) saturate(.45); }\n 19% { transform: translate3d(26px,-7px,0) scale(1.02) skewX(-1.2deg); filter: contrast(1.9) saturate(1.6); }\n 32% { transform: translate3d(-9px,11px,0) scale(1.03); filter: invert(.12) contrast(2); }\n 50%, 57% { transform: translate3d(34px,-3px,0) scale(1.025); filter: grayscale(1) contrast(2.3); }\n 69% { transform: translate3d(-24px,5px,0) scale(1.016); filter: contrast(1.7) saturate(.2); }\n 83% { transform: translate3d(8px,-2px,0) scale(1.006); filter: contrast(1.35); }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .walros-theme-glitch-root::before,\n .walros-theme-glitch-root::after {\n animation: walros-glitch-reduced 150ms ease-out forwards;\n }\n\n .walros-theme-glitch-band {\n animation: none !important;\n }\n\n .walros-theme-glitch-page--body,\n .walros-theme-glitch-page--viewport {\n animation: none;\n }\n\n @keyframes walros-glitch-reduced {\n from { opacity: 0.35; }\n to { opacity: 0; }\n }\n}\n`;\n\nexport function WalrosThemeGlitch({\n active,\n zIndex = 9998,\n className,\n style,\n}: WalrosThemeGlitchProps) {\n return (\n <>\n <style>{GLITCH_STYLES}</style>\n {active ? (\n <div\n className={[\"walros-theme-glitch-root\", \"is-active\", className]\n .filter(Boolean)\n .join(\" \")}\n style={{ zIndex, ...style }}\n aria-hidden=\"true\"\n >\n <span className=\"walros-theme-glitch-band\" />\n <span className=\"walros-theme-glitch-band\" />\n <span className=\"walros-theme-glitch-band\" />\n <span className=\"walros-theme-glitch-band\" />\n </div>\n ) : null}\n </>\n );\n}\n\nexport default WalrosThemeGlitch;\n","import { useEffect, useRef } from \"react\";\r\n\r\nconst DESKTOP_CURSOR_QUERY = \"(min-width: 1024px) and (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference)\";\n\nconst CURSOR_STYLES = `\n.directional-cursor { position: fixed; top: 0; left: 0; z-index: 9999; width: 20px; height: 22px; opacity: 0; pointer-events: none; contain: layout style; will-change: transform; transition: opacity 100ms linear; }\n.directional-cursor.is-visible { opacity: 1; }\n.directional-cursor-shape { width: 20px; height: 22px; transform-origin: center center; will-change: transform; }\n.directional-cursor svg { display: block; width: 20px; height: 22px; }\n@media (min-width: 1024px) and (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {\n html.has-directional-cursor, html.has-directional-cursor body, html.has-directional-cursor body * { cursor: none !important; }\n html.has-directional-cursor :is(a, button, [role=\"button\"], [onclick], .clickable, [data-clickable], input[type=\"button\"], input[type=\"submit\"], input[type=\"reset\"], label[for]),\n html.has-directional-cursor :is(a, button, [role=\"button\"], [onclick], .clickable, [data-clickable], input[type=\"button\"], input[type=\"submit\"], input[type=\"reset\"], label[for]) * { cursor: pointer !important; }\n html.has-directional-cursor :is(input, textarea, select, [contenteditable=\"true\"]) { cursor: text !important; }\n}\n`;\n\r\nexport function DirectionalCursor() {\r\n const positionLayer = useRef<HTMLDivElement>(null);\r\n const directionLayer = useRef<HTMLDivElement>(null);\r\n\r\n useEffect(() => {\r\n const position = positionLayer.current;\r\n const direction = directionLayer.current;\r\n if (!position || !direction) return;\r\n\r\n const media = window.matchMedia(DESKTOP_CURSOR_QUERY);\r\n let active = false;\r\n let frame = 0;\r\n let moveFrame = 0;\r\n let scaleTimer = 0;\r\n let latestEvent: MouseEvent | null = null;\r\n let currentX = window.innerWidth / 2;\r\n let currentY = -60;\r\n let targetX = currentX;\r\n let targetY = currentY;\r\n let currentAngle = 0;\r\n let targetAngle = 0;\r\n let hasAngle = false;\r\n let currentScale = 1;\r\n let targetScale = 1;\r\n let lastX = currentX;\r\n let lastY = 0;\r\n\r\n const render = () => {\r\n currentX += (targetX - currentX) * 0.4;\r\n currentY += (targetY - currentY) * 0.4;\r\n const angleDelta = ((targetAngle - currentAngle + 540) % 360) - 180;\r\n currentAngle += angleDelta * 0.24;\r\n currentScale += (targetScale - currentScale) * 0.24;\r\n\r\n position.style.transform = `translate3d(${currentX}px, ${currentY}px, 0)`;\r\n direction.style.transform = `translate(-50%, -50%) rotate(${currentAngle}deg) scale(${currentScale})`;\r\n\r\n const unsettled = Math.abs(targetX - currentX) > 0.08\r\n || Math.abs(targetY - currentY) > 0.08\r\n || Math.abs(angleDelta) > 0.08\r\n || Math.abs(targetScale - currentScale) > 0.002;\r\n frame = unsettled ? window.requestAnimationFrame(render) : 0;\r\n };\r\n\r\n const requestRender = () => {\r\n if (!frame) frame = window.requestAnimationFrame(render);\r\n };\r\n\r\n const processMove = () => {\r\n moveFrame = 0;\r\n const event = latestEvent;\r\n if (!event) return;\r\n const deltaX = event.clientX - lastX;\r\n const deltaY = event.clientY - lastY;\r\n const distance = Math.hypot(deltaX, deltaY);\r\n targetX = event.clientX;\r\n targetY = event.clientY;\r\n position.classList.add(\"is-visible\");\r\n\r\n if (distance > 1.25) {\r\n const rawAngle = Math.atan2(deltaY, deltaX) * (180 / Math.PI) + 90;\r\n const normalizedAngle = (rawAngle % 360 + 360) % 360;\r\n if (!hasAngle) {\r\n targetAngle = normalizedAngle;\r\n currentAngle = normalizedAngle;\r\n hasAngle = true;\r\n } else {\r\n targetAngle = normalizedAngle;\r\n }\r\n\r\n targetScale = 0.92;\r\n window.clearTimeout(scaleTimer);\r\n scaleTimer = window.setTimeout(() => {\r\n targetScale = 1;\r\n requestRender();\r\n }, 130);\r\n }\r\n\r\n lastX = event.clientX;\r\n lastY = event.clientY;\r\n requestRender();\r\n };\r\n\r\n const handleMouseMove = (event: MouseEvent) => {\r\n latestEvent = event;\r\n if (!moveFrame) moveFrame = window.requestAnimationFrame(processMove);\r\n };\r\n\r\n const activate = () => {\r\n if (active) return;\r\n active = true;\r\n document.documentElement.classList.add(\"has-directional-cursor\");\r\n window.addEventListener(\"mousemove\", handleMouseMove, { passive: true });\r\n };\r\n\r\n const deactivate = () => {\r\n if (!active) return;\r\n active = false;\r\n document.documentElement.classList.remove(\"has-directional-cursor\");\r\n position.classList.remove(\"is-visible\");\r\n window.removeEventListener(\"mousemove\", handleMouseMove);\r\n window.cancelAnimationFrame(frame);\r\n window.cancelAnimationFrame(moveFrame);\r\n window.clearTimeout(scaleTimer);\r\n frame = 0;\r\n moveFrame = 0;\r\n };\r\n\r\n const sync = () => {\r\n if (media.matches) activate();\r\n else deactivate();\r\n };\r\n media.addEventListener(\"change\", sync);\r\n sync();\r\n\r\n return () => {\r\n media.removeEventListener(\"change\", sync);\r\n deactivate();\r\n };\r\n }, []);\r\n\r\n return (\n <><style>{CURSOR_STYLES}</style><div ref={positionLayer} className=\"directional-cursor\" aria-hidden=\"true\">\n <div ref={directionLayer} className=\"directional-cursor-shape\">\r\n <svg width=\"50\" height=\"54\" viewBox=\"0 0 50 54\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <g filter=\"url(#walros-cursor-shadow)\">\r\n <path d=\"M42.6817 41.1495L27.5103 6.79925C26.7269 5.02557 24.2082 5.02558 23.3927 6.79925L7.59814 41.1495C6.75833 42.9759 8.52712 44.8902 10.4125 44.1954L24.3757 39.0496C24.8829 38.8627 25.4385 38.8627 25.9422 39.0496L39.8121 44.1954C41.6849 44.8902 43.4884 42.9759 42.6817 41.1495Z\" fill=\"black\" />\r\n <path d=\"M43.7146 40.6933L28.5431 6.34306C27.3556 3.65428 23.5772 3.69516 22.3668 6.32755L6.57226 40.6778C5.3134 43.4156 7.97238 46.298 10.803 45.2549L24.7662 40.109C25.0221 40.0147 25.2999 40.0156 25.5494 40.1082L39.4193 45.254C42.2261 46.2953 44.9254 43.4347 43.7146 40.6933Z\" stroke=\"white\" strokeWidth=\"2.25825\" />\r\n </g>\r\n <defs>\r\n <filter id=\"walros-cursor-shadow\" x=\"0.602397\" y=\"0.952444\" width=\"49.0584\" height=\"52.428\" filterUnits=\"userSpaceOnUse\" colorInterpolationFilters=\"sRGB\">\r\n <feFlood floodOpacity=\"0\" result=\"BackgroundImageFix\" />\r\n <feColorMatrix in=\"SourceAlpha\" type=\"matrix\" values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\" result=\"hardAlpha\" />\r\n <feOffset dy=\"2.25825\" />\r\n <feGaussianBlur stdDeviation=\"2.25825\" />\r\n <feComposite in2=\"hardAlpha\" operator=\"out\" />\r\n <feColorMatrix type=\"matrix\" values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.08 0\" />\r\n <feBlend mode=\"normal\" in2=\"BackgroundImageFix\" result=\"effect1_dropShadow\" />\r\n <feBlend mode=\"normal\" in=\"SourceGraphic\" in2=\"effect1_dropShadow\" result=\"shape\" />\r\n </filter>\r\n </defs>\r\n </svg>\r\n </div>\r\n </div></>\n );\n}\n","import type { ImgHTMLAttributes } from \"react\";\nimport { walrosLogoChromeUrl } from \"../assets\";\n\nexport type WalrosLogoProps = Omit<\n ImgHTMLAttributes<HTMLImageElement>,\n \"src\"\n>;\n\nexport function WalrosLogo({\n alt = \"WalrOS\",\n draggable = false,\n ...props\n}: WalrosLogoProps) {\n return (\n <img\n src={walrosLogoChromeUrl}\n alt={alt}\n draggable={draggable}\n {...props}\n />\n );\n}\n\nexport default WalrosLogo;\n","import type { ImgHTMLAttributes } from \"react\";\nimport {\n walrosWordmarkDarkUrl,\n walrosWordmarkLightUrl,\n} from \"../assets\";\n\nexport type WalrosWordmarkProps = Omit<\n ImgHTMLAttributes<HTMLImageElement>,\n \"src\"\n> & {\n variant?: \"light\" | \"dark\";\n};\n\nexport function WalrosWordmark({\n variant = \"light\",\n alt = \"WalrOS\",\n draggable = false,\n ...props\n}: WalrosWordmarkProps) {\n const src =\n variant === \"dark\"\n ? walrosWordmarkDarkUrl\n : walrosWordmarkLightUrl;\n\n return (\n <img\n src={src}\n alt={alt}\n draggable={draggable}\n {...props}\n />\n );\n}\n\nexport default WalrosWordmark;\n","import {\n useCallback,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport type { RefObject } from \"react\";\nimport { walrosThemeGlitchSoundUrl } from \"../assets\";\n\nexport type WalrosTheme = \"light\" | \"dark\";\nexport type WalrosThemeMode = \"body\" | \"viewport\";\n\nexport type WalrosThemeShakeTarget =\n | HTMLElement\n | RefObject<HTMLElement | null>\n | null\n | undefined;\n\nexport type UseWalrosThemeOptions = {\n storageKey?: string;\n defaultTheme?: WalrosTheme;\n useSystemPreference?: boolean;\n swapDelay?: number;\n totalDuration?: number;\n /** Set to false to disable audio, or provide a custom sound URL. */\n soundUrl?: string | false;\n /** Playback volume from 0 to 1. Defaults to the WalrOS site mix. */\n soundVolume?: number;\n applyTheme?: (theme: WalrosTheme) => void;\n\n /**\n * `body` reproduce el comportamiento original de WalrOS Forum.\n * `viewport` bloquea el scroll y sacude solo los elementos indicados,\n * recomendado para parallax, sticky y GSAP ScrollTrigger.\n */\n mode?: WalrosThemeMode;\n\n /** Elementos que recibirán el shake cuando mode=\"viewport\". */\n shakeTargets?: readonly WalrosThemeShakeTarget[];\n\n /**\n * En modo viewport se activa por defecto. Mantiene scrollX/scrollY estables\n * con requestAnimationFrame sin usar position: fixed en el body.\n */\n lockScroll?: boolean;\n\n /** Se ejecuta después de restaurar el scroll; útil para ScrollTrigger.update(). */\n onAfterUnlock?: () => void;\n};\n\nexport type UseWalrosThemeResult = {\n theme: WalrosTheme;\n isDark: boolean;\n mounted: boolean;\n glitching: boolean;\n toggleTheme: () => void;\n setTheme: (theme: WalrosTheme) => void;\n};\n\ntype ViewportLockState = {\n scrollX: number;\n scrollY: number;\n rafId: number;\n active: boolean;\n bodyOverflow: string;\n htmlOverflow: string;\n htmlOverscrollBehavior: string;\n};\n\nconst GLITCH_BASE_CLASS = \"walros-theme-glitch-page\";\nconst GLITCH_BODY_CLASS = \"walros-theme-glitch-page--body\";\nconst GLITCH_VIEWPORT_CLASS = \"walros-theme-glitch-page--viewport\";\nconst GLITCH_LOCK_CLASS = \"walros-theme-glitch-lock\";\n\nfunction defaultApplyTheme(theme: WalrosTheme) {\n if (typeof document === \"undefined\") return;\n\n const root = document.documentElement;\n root.classList.toggle(\"dark\", theme === \"dark\");\n root.style.colorScheme = theme;\n}\n\nfunction readInitialTheme(\n storageKey: string,\n defaultTheme: WalrosTheme,\n useSystemPreference: boolean,\n): WalrosTheme {\n if (typeof window === \"undefined\") return defaultTheme;\n\n try {\n const stored = window.localStorage.getItem(storageKey);\n if (stored === \"light\" || stored === \"dark\") return stored;\n } catch {\n // localStorage puede estar bloqueado en modo privado.\n }\n\n if (\n useSystemPreference &&\n window.matchMedia?.(\"(prefers-color-scheme: dark)\").matches\n ) {\n return \"dark\";\n }\n\n return defaultTheme;\n}\n\nfunction resolveShakeTargets(\n targets: readonly WalrosThemeShakeTarget[],\n): HTMLElement[] {\n const resolved = new Set<HTMLElement>();\n\n for (const target of targets) {\n if (!target) continue;\n\n const element =\n typeof target === \"object\" && \"current\" in target\n ? target.current\n : target;\n\n if (element) resolved.add(element);\n }\n\n return [...resolved];\n}\n\nexport function useWalrosTheme({\n storageKey = \"walros-theme\",\n defaultTheme = \"light\",\n useSystemPreference = false,\n swapDelay = 610,\n totalDuration = 1500,\n soundUrl = walrosThemeGlitchSoundUrl,\n soundVolume = 0.52,\n applyTheme = defaultApplyTheme,\n mode = \"body\",\n shakeTargets = [],\n lockScroll,\n onAfterUnlock,\n}: UseWalrosThemeOptions = {}): UseWalrosThemeResult {\n const [theme, setThemeState] = useState<WalrosTheme>(() =>\n readInitialTheme(storageKey, defaultTheme, useSystemPreference),\n );\n const [mounted, setMounted] = useState(false);\n const [glitching, setGlitching] = useState(false);\n\n const themeRef = useRef(theme);\n const glitchingRef = useRef(false);\n const swapTimerRef = useRef<number | null>(null);\n const cleanupTimerRef = useRef<number | null>(null);\n const applyThemeRef = useRef(applyTheme);\n const modeRef = useRef(mode);\n const shakeTargetsRef = useRef(shakeTargets);\n const lockScrollRef = useRef(lockScroll);\n const onAfterUnlockRef = useRef(onAfterUnlock);\n const activeTargetsRef = useRef<HTMLElement[]>([]);\n const viewportLockRef = useRef<ViewportLockState | null>(null);\n const soundRef = useRef<HTMLAudioElement | null>(null);\n const soundUrlRef = useRef(soundUrl);\n const soundVolumeRef = useRef(soundVolume);\n\n themeRef.current = theme;\n applyThemeRef.current = applyTheme;\n modeRef.current = mode;\n shakeTargetsRef.current = shakeTargets;\n lockScrollRef.current = lockScroll;\n onAfterUnlockRef.current = onAfterUnlock;\n soundUrlRef.current = soundUrl;\n soundVolumeRef.current = soundVolume;\n\n const playThemeSound = useCallback(() => {\n if (typeof window === \"undefined\" || !soundUrlRef.current) return;\n\n try {\n if (!soundRef.current || soundRef.current.src !== new URL(soundUrlRef.current, document.baseURI).href) {\n soundRef.current?.pause();\n soundRef.current = new Audio(soundUrlRef.current);\n soundRef.current.preload = \"auto\";\n }\n const audio = soundRef.current;\n audio.volume = Math.max(0, Math.min(1, soundVolumeRef.current));\n audio.currentTime = 0;\n void audio.play().catch(() => {\n // Browsers may block sound; the theme animation still continues.\n });\n } catch {\n // Audio support is optional and must not block the theme change.\n }\n }, []);\n\n const persistTheme = useCallback(\n (nextTheme: WalrosTheme) => {\n applyThemeRef.current(nextTheme);\n setThemeState(nextTheme);\n themeRef.current = nextTheme;\n\n try {\n window.localStorage.setItem(storageKey, nextTheme);\n } catch {\n // El cambio debe funcionar aunque localStorage falle.\n }\n },\n [storageKey],\n );\n\n useEffect(() => {\n const initialTheme = readInitialTheme(\n storageKey,\n defaultTheme,\n useSystemPreference,\n );\n\n themeRef.current = initialTheme;\n setThemeState(initialTheme);\n applyThemeRef.current(initialTheme);\n setMounted(true);\n }, [defaultTheme, storageKey, useSystemPreference]);\n\n const clearTimers = useCallback(() => {\n if (swapTimerRef.current !== null) {\n window.clearTimeout(swapTimerRef.current);\n swapTimerRef.current = null;\n }\n\n if (cleanupTimerRef.current !== null) {\n window.clearTimeout(cleanupTimerRef.current);\n cleanupTimerRef.current = null;\n }\n }, []);\n\n const lockViewport = useCallback(() => {\n if (\n typeof window === \"undefined\" ||\n typeof document === \"undefined\" ||\n viewportLockRef.current\n ) {\n return;\n }\n\n const body = document.body;\n const html = document.documentElement;\n const lockState: ViewportLockState = {\n scrollX: window.scrollX,\n scrollY: window.scrollY,\n rafId: 0,\n active: true,\n bodyOverflow: body.style.overflow,\n htmlOverflow: html.style.overflow,\n htmlOverscrollBehavior: html.style.overscrollBehavior,\n };\n\n viewportLockRef.current = lockState;\n\n const keepScrollStable = () => {\n if (!lockState.active) return;\n window.scrollTo(lockState.scrollX, lockState.scrollY);\n lockState.rafId = window.requestAnimationFrame(keepScrollStable);\n };\n\n html.classList.add(GLITCH_LOCK_CLASS);\n html.style.overflow = \"hidden\";\n html.style.overscrollBehavior = \"none\";\n body.style.overflow = \"hidden\";\n lockState.rafId = window.requestAnimationFrame(keepScrollStable);\n }, []);\n\n const unlockViewport = useCallback((runCallback: boolean) => {\n if (typeof window === \"undefined\" || typeof document === \"undefined\") {\n return;\n }\n\n const lockState = viewportLockRef.current;\n if (!lockState) return;\n\n lockState.active = false;\n window.cancelAnimationFrame(lockState.rafId);\n\n const body = document.body;\n const html = document.documentElement;\n body.style.overflow = lockState.bodyOverflow;\n html.style.overflow = lockState.htmlOverflow;\n html.style.overscrollBehavior = lockState.htmlOverscrollBehavior;\n html.classList.remove(GLITCH_LOCK_CLASS);\n\n viewportLockRef.current = null;\n window.scrollTo(lockState.scrollX, lockState.scrollY);\n\n if (runCallback) {\n window.requestAnimationFrame(() => {\n onAfterUnlockRef.current?.();\n });\n }\n }, []);\n\n const removeShakeClasses = useCallback(() => {\n for (const target of activeTargetsRef.current) {\n target.classList.remove(\n GLITCH_BASE_CLASS,\n GLITCH_BODY_CLASS,\n GLITCH_VIEWPORT_CLASS,\n );\n target.style.removeProperty(\"--walros-glitch-origin-y\");\n }\n\n activeTargetsRef.current = [];\n }, []);\n\n const finishGlitch = useCallback(() => {\n if (soundRef.current) {\n soundRef.current.pause();\n soundRef.current.currentTime = 0;\n }\n removeShakeClasses();\n unlockViewport(true);\n glitchingRef.current = false;\n setGlitching(false);\n }, [removeShakeClasses, unlockViewport]);\n\n const setTheme = useCallback(\n (nextTheme: WalrosTheme) => {\n if (glitchingRef.current) return;\n persistTheme(nextTheme);\n },\n [persistTheme],\n );\n\n const toggleTheme = useCallback(() => {\n if (\n typeof window === \"undefined\" ||\n typeof document === \"undefined\" ||\n glitchingRef.current\n ) {\n return;\n }\n\n playThemeSound();\n\n const currentMode = modeRef.current;\n const shouldLockScroll =\n lockScrollRef.current ?? currentMode === \"viewport\";\n\n if (currentMode === \"viewport\" && shouldLockScroll) {\n lockViewport();\n }\n\n const targets =\n currentMode === \"body\"\n ? [document.body]\n : resolveShakeTargets(shakeTargetsRef.current);\n\n const modeClass =\n currentMode === \"body\"\n ? GLITCH_BODY_CLASS\n : GLITCH_VIEWPORT_CLASS;\n\n for (const target of targets) {\n target.style.setProperty(\n \"--walros-glitch-origin-y\",\n currentMode === \"body\"\n ? `${window.scrollY + window.innerHeight / 2}px`\n : \"50%\",\n );\n target.classList.add(GLITCH_BASE_CLASS, modeClass);\n }\n\n activeTargetsRef.current = targets;\n glitchingRef.current = true;\n setGlitching(true);\n\n const reducedMotion = window.matchMedia?.(\n \"(prefers-reduced-motion: reduce)\",\n ).matches;\n\n const nextTheme: WalrosTheme =\n themeRef.current === \"dark\" ? \"light\" : \"dark\";\n\n const effectiveSwapDelay = reducedMotion\n ? 75\n : Math.max(0, swapDelay);\n const effectiveDuration = reducedMotion\n ? 150\n : Math.max(effectiveSwapDelay, totalDuration);\n\n swapTimerRef.current = window.setTimeout(() => {\n persistTheme(nextTheme);\n swapTimerRef.current = null;\n }, effectiveSwapDelay);\n\n cleanupTimerRef.current = window.setTimeout(() => {\n cleanupTimerRef.current = null;\n finishGlitch();\n }, effectiveDuration);\n }, [finishGlitch, lockViewport, persistTheme, playThemeSound, swapDelay, totalDuration]);\n\n useEffect(() => {\n return () => {\n clearTimers();\n removeShakeClasses();\n unlockViewport(false);\n soundRef.current?.pause();\n if (soundRef.current) soundRef.current.currentTime = 0;\n soundRef.current = null;\n };\n }, [clearTimers, removeShakeClasses, unlockViewport]);\n\n return {\n theme,\n isDark: theme === \"dark\",\n mounted,\n glitching,\n toggleTheme,\n setTheme,\n };\n}\n\nexport default useWalrosTheme;\n"],"mappings":";AAAA,SAAS,YAAAA,iBAAgB;AACzB,SAAS,oBAAoB;;;ACDtB,IAAM,4BAA4B,IAAI;AAAA,EAC3C;AAAA,EACA,YAAY;AACd,EAAE;AAEK,IAAM,sBAAsB,IAAI;AAAA,EACrC;AAAA,EACA,YAAY;AACd,EAAE;AAEK,IAAM,yBAAyB,IAAI;AAAA,EACxC;AAAA,EACA,YAAY;AACd,EAAE;AAEK,IAAM,wBAAwB,IAAI;AAAA,EACvC;AAAA,EACA,YAAY;AACd,EAAE;AAEK,IAAM,4BAA4B,IAAI;AAAA,EAC3C;AAAA,EACA,YAAY;AACd,EAAE;;;ACvBF,SAAS,WAAW,OAAO,iBAAiB,QAAQ,gBAAgB;AACpE,OAAO,UAAU;;;ACAV,IAAM,oBAAoB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AACF;;;ADsJU,SACE,KADF;AArIV,IAAM,UAAU;AAChB,IAAM,UAAU;AAChB,IAAM,eAAe;AACrB,IAAM,gBAAgB;AACtB,IAAM,cAAc;AACpB,IAAM,iBAAiB;AACvB,IAAM,gBAAgB;AAEf,SAAS,yBAAyB;AAAA,EACvC;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX,kBAAkB;AAAA,EAClB,SAAS;AAAA,EACT,aAAa;AAAA,EACb,UAAU;AACZ,GAAkC;AAChC,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,IAAI;AAC3C,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,OAAO;AAAA,IAC9C,OAAO,OAAO,WAAW,cAAc,IAAI,OAAO;AAAA,IAClD,QAAQ,OAAO,WAAW,cAAc,IAAI,OAAO;AAAA,EACrD,EAAE;AACF,QAAM,UAAU,OAAuB,IAAI;AAC3C,QAAM,SAAS,OAAoB,IAAI;AACvC,QAAM,OAAO,OAAoB,IAAI;AACrC,QAAM,cAAc,OAAO,UAAU;AACrC,cAAY,UAAU;AACtB,QAAM,SAAS,oBAAoB,MAAM,EAAE,QAAQ,MAAM,GAAG,CAAC;AAE7D,YAAU,MAAM;AACd,UAAM,iBAAiB,MAAM,YAAY,EAAE,OAAO,OAAO,YAAY,QAAQ,OAAO,YAAY,CAAC;AACjG,WAAO,iBAAiB,UAAU,cAAc;AAChD,WAAO,MAAM,OAAO,oBAAoB,UAAU,cAAc;AAAA,EAClE,GAAG,CAAC,CAAC;AAEL,kBAAgB,MAAM;AACpB,QAAI,CAAC,WAAW,SAAS,SAAS,KAAK,SAAS,UAAU,KAAK,CAAC,QAAQ,WAAW,CAAC,OAAO,QAAS;AACpG,UAAM,mBAAmB,SAAS,KAAK,MAAM;AAC7C,QAAI,WAAY,UAAS,KAAK,MAAM,WAAW;AAE/C,UAAM,eAAe,gBAAgB;AACrC,UAAM,gBAAgB,iBAAiB;AACvC,UAAM,iBAAiB,eAAe,iBAAiB;AACvD,UAAM,iBAAiB,cAAc,kBAAkB;AAGvD,UAAM,eAAe,KAAK,IAAI,OAAO,QAAQ,cAAc,OAAO,SAAS,aAAa,IAAI;AAC5F,UAAM,WAAW,OAAO,WAAW,gBAAgB,WAAW;AAC9D,UAAM,WAAW,OAAO,WAAW,gBAAgB,WAAW;AAC9D,UAAM,WAAW,KAAK,MAAM,SAAS,OAAO,SAAS,MAAM,IAAI;AAC/D,UAAM,cAAe,WAAW,MAAM,gBAAiB;AAGvD,UAAM,UAAU,SAAS,QAAQ,KAAK,gBAAgB,WAAW;AACjE,UAAM,UAAU,SAAS,SAAS,KAAK,gBAAgB,WAAW;AAClE,UAAM,QAAQ,WAAW;AAEzB,SAAK,IAAI,OAAO,SAAS;AAAA,MACvB,GAAG;AAAA,MACH,GAAG;AAAA,MACH,OAAO;AAAA,MACP,WAAW;AAAA,IACb,CAAC;AACD,QAAI,KAAK,SAAS;AAChB,WAAK,IAAI,KAAK,SAAS;AAAA,QACrB,GAAG;AAAA,QACH,GAAG;AAAA,QACH,OAAO;AAAA,QACP,SAAS;AAAA,QACT,WAAW;AAAA,MACb,CAAC;AAAA,IACH;AACA,SAAK,IAAI,QAAQ,SAAS,EAAE,SAAS,EAAE,CAAC;AAExC,UAAM,SAAS,MAAM;AACnB,UAAI,WAAY,UAAS,KAAK,MAAM,WAAW;AAC/C,iBAAW,KAAK;AAChB,kBAAY,UAAU;AAAA,IACxB;AACA,UAAM,gBAAgB,OAAO,WAAW,kCAAkC,EAAE;AAC5E,UAAM,WAAW,KAAK,SAAS,EAAE,YAAY,OAAO,CAAC;AACrD,QAAI,eAAe;AACjB,eAAS,GAAG,QAAQ,SAAS,EAAE,SAAS,GAAG,UAAU,MAAM,MAAM,aAAa,CAAC;AAAA,IACjF,OAAO;AACL,eACG,GAAG,CAAC,OAAO,SAAS,KAAK,OAAO,EAAE,OAAO,OAAO,GAAG;AAAA,QAClD,GAAG;AAAA,QACH,GAAG;AAAA,QACH,OAAO;AAAA,QACP,UAAU;AAAA,QACV,MAAM;AAAA,MACR,CAAC;AACH,UAAI,KAAK,SAAS;AAChB,iBAAS,GAAG,KAAK,SAAS;AAAA,UACxB,SAAS;AAAA,UACT,UAAU,QAAQ;AAAA,UAClB,MAAM;AAAA,QACR,GAAG,QAAQ,GAAE;AAAA,MACf;AACA,eACG,GAAG,QAAQ,SAAS;AAAA,QACnB,SAAS;AAAA,QACT,UAAU,QAAQ;AAAA,QAClB,MAAM;AAAA,MACR,GAAG,QAAQ,GAAG;AAAA,IAClB;AAEA,WAAO,MAAM;AACX,eAAS,KAAK;AACd,UAAI,WAAY,UAAS,KAAK,MAAM,WAAW;AAAA,IACjD;AAAA,EACF,GAAG,CAAC,UAAU,YAAY,QAAQ,UAAU,OAAO,CAAC;AAEpD,MAAI,CAAC,QAAS,QAAO;AAErB,SACE;AAAA,IAAC;AAAA;AAAA,MACC,KAAK;AAAA,MACL,WAAU;AAAA,MACV,OAAO;AAAA,QACL,UAAU;AAAA,QACV,OAAO;AAAA,QACP,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,eAAe;AAAA,QACf;AAAA,QACA,iBAAiB,SAAS,QAAQ,KAAK,SAAS,SAAS,IAAI,gBAAgB;AAAA,MAC/E;AAAA,MACA,eAAY;AAAA,MAEZ,+BAAC,SAAI,OAAM,QAAO,QAAO,QAAO,SAAS,OAAO,SAAS,KAAK,IAAI,SAAS,MAAM,IAAI,qBAAoB,QAAO,OAAO,EAAE,SAAS,QAAQ,GACxI;AAAA,4BAAC,UACC,+BAAC,UAAK,IAAI,QAAQ,WAAU,kBAAiB,GAAE,KAAI,GAAE,KAAI,OAAO,SAAS,OAAO,QAAQ,SAAS,QAC/F;AAAA,8BAAC,UAAK,OAAO,SAAS,OAAO,QAAQ,SAAS,QAAQ,MAAK,SAAQ;AAAA,UACnE,oBAAC,OAAE,KAAK,QACN,8BAAC,OAAE,WAAW,aAAa,CAAC,OAAO,IAAI,CAAC,OAAO,KAAK,MAAK,SACtD,4BAAkB,IAAI,CAAC,MAAM,UAAU,oBAAC,UAAK,GAAG,QAAW,KAAO,CAAE,GACvE,GACF;AAAA,WACF,GACF;AAAA,QACC,WACC,oBAAC,OAAE,KAAK,MACN,8BAAC,WAAM,MAAM,SAAS,GAAG,CAAC,SAAS,GAAG,CAAC,SAAS,OAAM,QAAO,QAAO,QAAO,GAC7E;AAAA,QAEF,oBAAC,UAAK,OAAO,SAAS,OAAO,QAAQ,SAAS,QAAQ,MAAM,iBAAiB,MAAM,QAAQ,MAAM,KAAK;AAAA,SACxG;AAAA;AAAA,EACF;AAEJ;;;AE7KA,SAAS,mBAAAC,kBAAiB,YAAAC,iBAAgB;AAInC,SAAS,eAAe,QAAgB;AAC7C,QAAM,CAAC,IAAI,IAAIA;AAAA,IAAgC,MAC7C,OAAO,aAAa,cAAc,OAAO,SAAS,cAAc,KAAK;AAAA,EACvE;AAEA,EAAAD,iBAAgB,MAAM;AACpB,QAAI,CAAC,KAAM;AACX,SAAK,QAAQ,oBAAoB;AACjC,SAAK,MAAM,WAAW;AACtB,SAAK,MAAM,QAAQ;AACnB,SAAK,MAAM,gBAAgB;AAC3B,aAAS,gBAAgB,YAAY,IAAI;AACzC,WAAO,MAAM,KAAK,OAAO;AAAA,EAC3B,GAAG,CAAC,IAAI,CAAC;AAET,EAAAA,iBAAgB,MAAM;AACpB,QAAI,KAAM,MAAK,MAAM,SAAS,OAAO,MAAM;AAAA,EAC7C,GAAG,CAAC,MAAM,MAAM,CAAC;AAEjB,SAAO;AACT;;;AJqDI,gBAAAE,YAAA;AAzDJ,IAAM,aAAa,CAAC,UAAkB,KAAK,IAAI,KAAK,KAAK,IAAI,IAAI,QAAQ,IAAG,CAAC;AAC7E,IAAM,cAAc;AACpB,IAAMC,gBAAe;AACrB,IAAMC,iBAAgB;AACtB,IAAMC,eAAc;AACpB,IAAMC,kBAAiB;AAEvB,SAAS,gBAA8B;AACrC,MAAI,OAAO,WAAW,YAAa,QAAO,EAAE,SAAS,GAAG,SAAS,GAAG,OAAO,IAAI,QAAQ,GAAG;AAC1F,QAAM,OAAO,WAAW,OAAO,UAAU;AACzC,SAAO;AAAA,IACL,SAAS,OAAO,aAAa;AAAA,IAC7B,SAAS,OAAO,cAAc,SAASD,eAAcC,mBAAkB,IAAI,cAAc,KAAK,cAAe;AAAA,IAC7G,QAASF,iBAAgBD,iBAAgB,cAAe;AAAA,IACxD,SAAUG,kBAAiBD,gBAAe,cAAe;AAAA,EAC3D;AACF;AAEA,SAAS,WAAW,MAA0C;AAC5D,MAAI,OAAO,WAAW,YAAa,QAAO;AAC1C,MAAI;AACF,WAAO,SAAS,YAAY,OAAO,iBAAiB,OAAO;AAAA,EAC7D,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,UAAU,SAAkB,MAAqC,KAAa;AACrF,MAAI,CAAC,QAAS,QAAO;AACrB,MAAI,SAAS,SAAU,QAAO;AAC9B,MAAI;AACF,WAAO,WAAW,IAAI,GAAG,QAAQ,GAAG,KAAK;AAAA,EAC3C,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGO,SAAS,uBAAuB;AAAA,EACrC,WAAW;AAAA,EACX;AAAA,EACA,kBAAkB;AAAA,EAClB,UAAU;AAAA,EACV,cAAc;AAAA,EACd,aAAa;AAAA,EACb,SAAS;AAAA,EACT;AAAA,EACA,UAAU;AACZ,GAAgC;AAC9B,QAAM,CAAC,GAAG,IAAIE,UAAS,MAAM,UAAU,SAAS,aAAa,UAAU,CAAC;AACxE,QAAM,CAAC,UAAU,WAAW,IAAIA,UAAS,KAAK;AAC9C,QAAM,CAAC,aAAa,IAAIA,UAAS,MAAM,UAAU,cAAc,CAAC;AAChE,QAAM,OAAO,eAAe,MAAM;AAElC,MAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,OAAO,SAAU,QAAO;AAElD,SAAO;AAAA,IACL,gBAAAL;AAAA,MAAC;AAAA;AAAA,QACC,QAAQ;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,QACA,QAAQ;AAAA,QACR,YAAU;AAAA,QACV,YAAY,MAAM;AAChB,cAAI,gBAAgB,UAAU;AAC5B,gBAAI;AAAE,yBAAW,WAAW,GAAG,QAAQ,YAAY,GAAG;AAAA,YAAG,QAAQ;AAAA,YAA6B;AAAA,UAChG;AACA,sBAAY,IAAI;AAChB,uBAAa;AAAA,QACf;AAAA;AAAA,IACF;AAAA,IACA;AAAA,EACF;AACF;;;AK9FA,SAAS,gBAAAM,qBAAoB;;;AC4JzB,mBACE,OAAAC,MAEE,QAAAC,aAHJ;AAnJJ,IAAM,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA4If,SAAS,kBAAkB;AAAA,EAChC;AAAA,EACA,SAAS;AAAA,EACT;AAAA,EACA;AACF,GAA2B;AACzB,SACE,gBAAAA,MAAA,YACE;AAAA,oBAAAD,KAAC,WAAO,yBAAc;AAAA,IACrB,SACC,gBAAAC;AAAA,MAAC;AAAA;AAAA,QACC,WAAW,CAAC,4BAA4B,aAAa,SAAS,EAC3D,OAAO,OAAO,EACd,KAAK,GAAG;AAAA,QACX,OAAO,EAAE,QAAQ,GAAG,MAAM;AAAA,QAC1B,eAAY;AAAA,QAEZ;AAAA,0BAAAD,KAAC,UAAK,WAAU,4BAA2B;AAAA,UAC3C,gBAAAA,KAAC,UAAK,WAAU,4BAA2B;AAAA,UAC3C,gBAAAA,KAAC,UAAK,WAAU,4BAA2B;AAAA,UAC3C,gBAAAA,KAAC,UAAK,WAAU,4BAA2B;AAAA;AAAA;AAAA,IAC7C,IACE;AAAA,KACN;AAEJ;;;ADvJI,gBAAAE,YAAA;AARG,SAAS,sBAAsB;AAAA,EACpC;AAAA,EACA,SAAS;AACX,GAA+B;AAC7B,QAAM,OAAO,eAAe,MAAM;AAClC,MAAI,CAAC,KAAM,QAAO;AAElB,SAAOC;AAAA,IACL,gBAAAD,KAAC,qBAAkB,QAAgB,QAAQ,GAAG;AAAA,IAC9C;AAAA,EACF;AACF;;;AE1BA,SAAS,aAAAE,YAAW,UAAAC,eAAc;AA2I9B,qBAAAC,WAAE,OAAAC,MAGI,QAAAC,aAHN;AAzIJ,IAAM,uBAAuB;AAE7B,IAAM,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAaf,SAAS,oBAAoB;AAClC,QAAM,gBAAgBH,QAAuB,IAAI;AACjD,QAAM,iBAAiBA,QAAuB,IAAI;AAElD,EAAAD,WAAU,MAAM;AACd,UAAM,WAAW,cAAc;AAC/B,UAAM,YAAY,eAAe;AACjC,QAAI,CAAC,YAAY,CAAC,UAAW;AAE7B,UAAM,QAAQ,OAAO,WAAW,oBAAoB;AACpD,QAAI,SAAS;AACb,QAAI,QAAQ;AACZ,QAAI,YAAY;AAChB,QAAI,aAAa;AACjB,QAAI,cAAiC;AACrC,QAAI,WAAW,OAAO,aAAa;AACnC,QAAI,WAAW;AACf,QAAI,UAAU;AACd,QAAI,UAAU;AACd,QAAI,eAAe;AACnB,QAAI,cAAc;AAClB,QAAI,WAAW;AACf,QAAI,eAAe;AACnB,QAAI,cAAc;AAClB,QAAI,QAAQ;AACZ,QAAI,QAAQ;AAEZ,UAAM,SAAS,MAAM;AACnB,mBAAa,UAAU,YAAY;AACnC,mBAAa,UAAU,YAAY;AACnC,YAAM,cAAe,cAAc,eAAe,OAAO,MAAO;AAChE,sBAAgB,aAAa;AAC7B,uBAAiB,cAAc,gBAAgB;AAE/C,eAAS,MAAM,YAAY,eAAe,QAAQ,OAAO,QAAQ;AACjE,gBAAU,MAAM,YAAY,gCAAgC,YAAY,cAAc,YAAY;AAElG,YAAM,YAAY,KAAK,IAAI,UAAU,QAAQ,IAAI,QAC5C,KAAK,IAAI,UAAU,QAAQ,IAAI,QAC/B,KAAK,IAAI,UAAU,IAAI,QACvB,KAAK,IAAI,cAAc,YAAY,IAAI;AAC5C,cAAQ,YAAY,OAAO,sBAAsB,MAAM,IAAI;AAAA,IAC7D;AAEA,UAAM,gBAAgB,MAAM;AAC1B,UAAI,CAAC,MAAO,SAAQ,OAAO,sBAAsB,MAAM;AAAA,IACzD;AAEA,UAAM,cAAc,MAAM;AACxB,kBAAY;AACZ,YAAM,QAAQ;AACd,UAAI,CAAC,MAAO;AACZ,YAAM,SAAS,MAAM,UAAU;AAC/B,YAAM,SAAS,MAAM,UAAU;AAC/B,YAAM,WAAW,KAAK,MAAM,QAAQ,MAAM;AAC1C,gBAAU,MAAM;AAChB,gBAAU,MAAM;AAChB,eAAS,UAAU,IAAI,YAAY;AAEnC,UAAI,WAAW,MAAM;AACnB,cAAM,WAAW,KAAK,MAAM,QAAQ,MAAM,KAAK,MAAM,KAAK,MAAM;AAChE,cAAM,mBAAmB,WAAW,MAAM,OAAO;AACjD,YAAI,CAAC,UAAU;AACb,wBAAc;AACd,yBAAe;AACf,qBAAW;AAAA,QACb,OAAO;AACL,wBAAc;AAAA,QAChB;AAEA,sBAAc;AACd,eAAO,aAAa,UAAU;AAC9B,qBAAa,OAAO,WAAW,MAAM;AACnC,wBAAc;AACd,wBAAc;AAAA,QAChB,GAAG,GAAG;AAAA,MACR;AAEA,cAAQ,MAAM;AACd,cAAQ,MAAM;AACd,oBAAc;AAAA,IAChB;AAEA,UAAM,kBAAkB,CAAC,UAAsB;AAC7C,oBAAc;AACd,UAAI,CAAC,UAAW,aAAY,OAAO,sBAAsB,WAAW;AAAA,IACtE;AAEA,UAAM,WAAW,MAAM;AACrB,UAAI,OAAQ;AACZ,eAAS;AACT,eAAS,gBAAgB,UAAU,IAAI,wBAAwB;AAC/D,aAAO,iBAAiB,aAAa,iBAAiB,EAAE,SAAS,KAAK,CAAC;AAAA,IACzE;AAEA,UAAM,aAAa,MAAM;AACvB,UAAI,CAAC,OAAQ;AACb,eAAS;AACT,eAAS,gBAAgB,UAAU,OAAO,wBAAwB;AAClE,eAAS,UAAU,OAAO,YAAY;AACtC,aAAO,oBAAoB,aAAa,eAAe;AACvD,aAAO,qBAAqB,KAAK;AACjC,aAAO,qBAAqB,SAAS;AACrC,aAAO,aAAa,UAAU;AAC9B,cAAQ;AACR,kBAAY;AAAA,IACd;AAEA,UAAM,OAAO,MAAM;AACjB,UAAI,MAAM,QAAS,UAAS;AAAA,UACvB,YAAW;AAAA,IAClB;AACA,UAAM,iBAAiB,UAAU,IAAI;AACrC,SAAK;AAEL,WAAO,MAAM;AACX,YAAM,oBAAoB,UAAU,IAAI;AACxC,iBAAW;AAAA,IACb;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,SACE,gBAAAI,MAAAF,WAAA,EAAE;AAAA,oBAAAC,KAAC,WAAO,yBAAc;AAAA,IAAQ,gBAAAA,KAAC,SAAI,KAAK,eAAe,WAAU,sBAAqB,eAAY,QAClG,0BAAAA,KAAC,SAAI,KAAK,gBAAgB,WAAU,4BAClC,0BAAAC,MAAC,SAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,QAAO,OAAM,8BAChE;AAAA,sBAAAA,MAAC,OAAE,QAAO,8BACR;AAAA,wBAAAD,KAAC,UAAK,GAAE,qRAAoR,MAAK,SAAQ;AAAA,QACzS,gBAAAA,KAAC,UAAK,GAAE,gRAA+Q,QAAO,SAAQ,aAAY,WAAU;AAAA,SAC9T;AAAA,MACA,gBAAAA,KAAC,UACC,0BAAAC,MAAC,YAAO,IAAG,wBAAuB,GAAE,YAAW,GAAE,YAAW,OAAM,WAAU,QAAO,UAAS,aAAY,kBAAiB,2BAA0B,QACjJ;AAAA,wBAAAD,KAAC,aAAQ,cAAa,KAAI,QAAO,sBAAqB;AAAA,QACtD,gBAAAA,KAAC,mBAAc,IAAG,eAAc,MAAK,UAAS,QAAO,6CAA4C,QAAO,aAAY;AAAA,QACpH,gBAAAA,KAAC,cAAS,IAAG,WAAU;AAAA,QACvB,gBAAAA,KAAC,oBAAe,cAAa,WAAU;AAAA,QACvC,gBAAAA,KAAC,iBAAY,KAAI,aAAY,UAAS,OAAM;AAAA,QAC5C,gBAAAA,KAAC,mBAAc,MAAK,UAAS,QAAO,8CAA6C;AAAA,QACjF,gBAAAA,KAAC,aAAQ,MAAK,UAAS,KAAI,sBAAqB,QAAO,sBAAqB;AAAA,QAC5E,gBAAAA,KAAC,aAAQ,MAAK,UAAS,IAAG,iBAAgB,KAAI,sBAAqB,QAAO,SAAQ;AAAA,SACpF,GACF;AAAA,OACF,GACF,GACF;AAAA,KAAM;AAEV;;;ACpJI,gBAAAE,YAAA;AANG,SAAS,WAAW;AAAA,EACzB,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,GAAG;AACL,GAAoB;AAClB,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,KAAK;AAAA,MACL;AAAA,MACA;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;;;ACII,gBAAAC,YAAA;AAZG,SAAS,eAAe;AAAA,EAC7B,UAAU;AAAA,EACV,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,GAAG;AACL,GAAwB;AACtB,QAAM,MACJ,YAAY,SACR,wBACA;AAEN,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;;;AChCA;AAAA,EACE;AAAA,EACA,aAAAC;AAAA,EACA,UAAAC;AAAA,EACA,YAAAC;AAAA,OACK;AAgEP,IAAM,oBAAoB;AAC1B,IAAM,oBAAoB;AAC1B,IAAM,wBAAwB;AAC9B,IAAM,oBAAoB;AAE1B,SAAS,kBAAkB,OAAoB;AAC7C,MAAI,OAAO,aAAa,YAAa;AAErC,QAAM,OAAO,SAAS;AACtB,OAAK,UAAU,OAAO,QAAQ,UAAU,MAAM;AAC9C,OAAK,MAAM,cAAc;AAC3B;AAEA,SAAS,iBACP,YACA,cACA,qBACa;AACb,MAAI,OAAO,WAAW,YAAa,QAAO;AAE1C,MAAI;AACF,UAAM,SAAS,OAAO,aAAa,QAAQ,UAAU;AACrD,QAAI,WAAW,WAAW,WAAW,OAAQ,QAAO;AAAA,EACtD,QAAQ;AAAA,EAER;AAEA,MACE,uBACA,OAAO,aAAa,8BAA8B,EAAE,SACpD;AACA,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEA,SAAS,oBACP,SACe;AACf,QAAM,WAAW,oBAAI,IAAiB;AAEtC,aAAW,UAAU,SAAS;AAC5B,QAAI,CAAC,OAAQ;AAEb,UAAM,UACJ,OAAO,WAAW,YAAY,aAAa,SACvC,OAAO,UACP;AAEN,QAAI,QAAS,UAAS,IAAI,OAAO;AAAA,EACnC;AAEA,SAAO,CAAC,GAAG,QAAQ;AACrB;AAEO,SAAS,eAAe;AAAA,EAC7B,aAAa;AAAA,EACb,eAAe;AAAA,EACf,sBAAsB;AAAA,EACtB,YAAY;AAAA,EACZ,gBAAgB;AAAA,EAChB,WAAW;AAAA,EACX,cAAc;AAAA,EACd,aAAa;AAAA,EACb,OAAO;AAAA,EACP,eAAe,CAAC;AAAA,EAChB;AAAA,EACA;AACF,IAA2B,CAAC,GAAyB;AACnD,QAAM,CAAC,OAAO,aAAa,IAAIC;AAAA,IAAsB,MACnD,iBAAiB,YAAY,cAAc,mBAAmB;AAAA,EAChE;AACA,QAAM,CAAC,SAAS,UAAU,IAAIA,UAAS,KAAK;AAC5C,QAAM,CAAC,WAAW,YAAY,IAAIA,UAAS,KAAK;AAEhD,QAAM,WAAWC,QAAO,KAAK;AAC7B,QAAM,eAAeA,QAAO,KAAK;AACjC,QAAM,eAAeA,QAAsB,IAAI;AAC/C,QAAM,kBAAkBA,QAAsB,IAAI;AAClD,QAAM,gBAAgBA,QAAO,UAAU;AACvC,QAAM,UAAUA,QAAO,IAAI;AAC3B,QAAM,kBAAkBA,QAAO,YAAY;AAC3C,QAAM,gBAAgBA,QAAO,UAAU;AACvC,QAAM,mBAAmBA,QAAO,aAAa;AAC7C,QAAM,mBAAmBA,QAAsB,CAAC,CAAC;AACjD,QAAM,kBAAkBA,QAAiC,IAAI;AAC7D,QAAM,WAAWA,QAAgC,IAAI;AACrD,QAAM,cAAcA,QAAO,QAAQ;AACnC,QAAM,iBAAiBA,QAAO,WAAW;AAEzC,WAAS,UAAU;AACnB,gBAAc,UAAU;AACxB,UAAQ,UAAU;AAClB,kBAAgB,UAAU;AAC1B,gBAAc,UAAU;AACxB,mBAAiB,UAAU;AAC3B,cAAY,UAAU;AACtB,iBAAe,UAAU;AAEzB,QAAM,iBAAiB,YAAY,MAAM;AACvC,QAAI,OAAO,WAAW,eAAe,CAAC,YAAY,QAAS;AAE3D,QAAI;AACF,UAAI,CAAC,SAAS,WAAW,SAAS,QAAQ,QAAQ,IAAI,IAAI,YAAY,SAAS,SAAS,OAAO,EAAE,MAAM;AACrG,iBAAS,SAAS,MAAM;AACxB,iBAAS,UAAU,IAAI,MAAM,YAAY,OAAO;AAChD,iBAAS,QAAQ,UAAU;AAAA,MAC7B;AACA,YAAM,QAAQ,SAAS;AACvB,YAAM,SAAS,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,eAAe,OAAO,CAAC;AAC9D,YAAM,cAAc;AACpB,WAAK,MAAM,KAAK,EAAE,MAAM,MAAM;AAAA,MAE9B,CAAC;AAAA,IACH,QAAQ;AAAA,IAER;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,eAAe;AAAA,IACnB,CAAC,cAA2B;AAC1B,oBAAc,QAAQ,SAAS;AAC/B,oBAAc,SAAS;AACvB,eAAS,UAAU;AAEnB,UAAI;AACF,eAAO,aAAa,QAAQ,YAAY,SAAS;AAAA,MACnD,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,IACA,CAAC,UAAU;AAAA,EACb;AAEA,EAAAC,WAAU,MAAM;AACd,UAAM,eAAe;AAAA,MACnB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,aAAS,UAAU;AACnB,kBAAc,YAAY;AAC1B,kBAAc,QAAQ,YAAY;AAClC,eAAW,IAAI;AAAA,EACjB,GAAG,CAAC,cAAc,YAAY,mBAAmB,CAAC;AAElD,QAAM,cAAc,YAAY,MAAM;AACpC,QAAI,aAAa,YAAY,MAAM;AACjC,aAAO,aAAa,aAAa,OAAO;AACxC,mBAAa,UAAU;AAAA,IACzB;AAEA,QAAI,gBAAgB,YAAY,MAAM;AACpC,aAAO,aAAa,gBAAgB,OAAO;AAC3C,sBAAgB,UAAU;AAAA,IAC5B;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,eAAe,YAAY,MAAM;AACrC,QACE,OAAO,WAAW,eAClB,OAAO,aAAa,eACpB,gBAAgB,SAChB;AACA;AAAA,IACF;AAEA,UAAM,OAAO,SAAS;AACtB,UAAM,OAAO,SAAS;AACtB,UAAM,YAA+B;AAAA,MACnC,SAAS,OAAO;AAAA,MAChB,SAAS,OAAO;AAAA,MAChB,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,cAAc,KAAK,MAAM;AAAA,MACzB,cAAc,KAAK,MAAM;AAAA,MACzB,wBAAwB,KAAK,MAAM;AAAA,IACrC;AAEA,oBAAgB,UAAU;AAE1B,UAAM,mBAAmB,MAAM;AAC7B,UAAI,CAAC,UAAU,OAAQ;AACvB,aAAO,SAAS,UAAU,SAAS,UAAU,OAAO;AACpD,gBAAU,QAAQ,OAAO,sBAAsB,gBAAgB;AAAA,IACjE;AAEA,SAAK,UAAU,IAAI,iBAAiB;AACpC,SAAK,MAAM,WAAW;AACtB,SAAK,MAAM,qBAAqB;AAChC,SAAK,MAAM,WAAW;AACtB,cAAU,QAAQ,OAAO,sBAAsB,gBAAgB;AAAA,EACjE,GAAG,CAAC,CAAC;AAEL,QAAM,iBAAiB,YAAY,CAAC,gBAAyB;AAC3D,QAAI,OAAO,WAAW,eAAe,OAAO,aAAa,aAAa;AACpE;AAAA,IACF;AAEA,UAAM,YAAY,gBAAgB;AAClC,QAAI,CAAC,UAAW;AAEhB,cAAU,SAAS;AACnB,WAAO,qBAAqB,UAAU,KAAK;AAE3C,UAAM,OAAO,SAAS;AACtB,UAAM,OAAO,SAAS;AACtB,SAAK,MAAM,WAAW,UAAU;AAChC,SAAK,MAAM,WAAW,UAAU;AAChC,SAAK,MAAM,qBAAqB,UAAU;AAC1C,SAAK,UAAU,OAAO,iBAAiB;AAEvC,oBAAgB,UAAU;AAC1B,WAAO,SAAS,UAAU,SAAS,UAAU,OAAO;AAEpD,QAAI,aAAa;AACf,aAAO,sBAAsB,MAAM;AACjC,yBAAiB,UAAU;AAAA,MAC7B,CAAC;AAAA,IACH;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,qBAAqB,YAAY,MAAM;AAC3C,eAAW,UAAU,iBAAiB,SAAS;AAC7C,aAAO,UAAU;AAAA,QACf;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,aAAO,MAAM,eAAe,0BAA0B;AAAA,IACxD;AAEA,qBAAiB,UAAU,CAAC;AAAA,EAC9B,GAAG,CAAC,CAAC;AAEL,QAAM,eAAe,YAAY,MAAM;AACrC,QAAI,SAAS,SAAS;AACpB,eAAS,QAAQ,MAAM;AACvB,eAAS,QAAQ,cAAc;AAAA,IACjC;AACA,uBAAmB;AACnB,mBAAe,IAAI;AACnB,iBAAa,UAAU;AACvB,iBAAa,KAAK;AAAA,EACpB,GAAG,CAAC,oBAAoB,cAAc,CAAC;AAEvC,QAAM,WAAW;AAAA,IACf,CAAC,cAA2B;AAC1B,UAAI,aAAa,QAAS;AAC1B,mBAAa,SAAS;AAAA,IACxB;AAAA,IACA,CAAC,YAAY;AAAA,EACf;AAEA,QAAM,cAAc,YAAY,MAAM;AACpC,QACE,OAAO,WAAW,eAClB,OAAO,aAAa,eACpB,aAAa,SACb;AACA;AAAA,IACF;AAEA,mBAAe;AAEf,UAAM,cAAc,QAAQ;AAC5B,UAAM,mBACJ,cAAc,WAAW,gBAAgB;AAE3C,QAAI,gBAAgB,cAAc,kBAAkB;AAClD,mBAAa;AAAA,IACf;AAEA,UAAM,UACJ,gBAAgB,SACZ,CAAC,SAAS,IAAI,IACd,oBAAoB,gBAAgB,OAAO;AAEjD,UAAM,YACJ,gBAAgB,SACZ,oBACA;AAEN,eAAW,UAAU,SAAS;AAC5B,aAAO,MAAM;AAAA,QACX;AAAA,QACA,gBAAgB,SACZ,GAAG,OAAO,UAAU,OAAO,cAAc,CAAC,OAC1C;AAAA,MACN;AACA,aAAO,UAAU,IAAI,mBAAmB,SAAS;AAAA,IACnD;AAEA,qBAAiB,UAAU;AAC3B,iBAAa,UAAU;AACvB,iBAAa,IAAI;AAEjB,UAAM,gBAAgB,OAAO;AAAA,MAC3B;AAAA,IACF,EAAE;AAEF,UAAM,YACJ,SAAS,YAAY,SAAS,UAAU;AAE1C,UAAM,qBAAqB,gBACvB,KACA,KAAK,IAAI,GAAG,SAAS;AACzB,UAAM,oBAAoB,gBACtB,MACA,KAAK,IAAI,oBAAoB,aAAa;AAE9C,iBAAa,UAAU,OAAO,WAAW,MAAM;AAC7C,mBAAa,SAAS;AACtB,mBAAa,UAAU;AAAA,IACzB,GAAG,kBAAkB;AAErB,oBAAgB,UAAU,OAAO,WAAW,MAAM;AAChD,sBAAgB,UAAU;AAC1B,mBAAa;AAAA,IACf,GAAG,iBAAiB;AAAA,EACtB,GAAG,CAAC,cAAc,cAAc,cAAc,gBAAgB,WAAW,aAAa,CAAC;AAEvF,EAAAA,WAAU,MAAM;AACd,WAAO,MAAM;AACX,kBAAY;AACZ,yBAAmB;AACnB,qBAAe,KAAK;AACpB,eAAS,SAAS,MAAM;AACxB,UAAI,SAAS,QAAS,UAAS,QAAQ,cAAc;AACrD,eAAS,UAAU;AAAA,IACrB;AAAA,EACF,GAAG,CAAC,aAAa,oBAAoB,cAAc,CAAC;AAEpD,SAAO;AAAA,IACL;AAAA,IACA,QAAQ,UAAU;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":["useState","useLayoutEffect","useState","jsx","VISIBLE_LEFT","VISIBLE_RIGHT","VISIBLE_TOP","VISIBLE_BOTTOM","useState","createPortal","jsx","jsxs","jsx","createPortal","useEffect","useRef","Fragment","jsx","jsxs","jsx","jsx","useEffect","useRef","useState","useState","useRef","useEffect"]}
|