@walrosproject/ui 0.4.1 → 0.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -48,7 +48,7 @@ const theme = useWalrosTheme({
48
48
 
49
49
  ## Portal de entrada
50
50
 
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.
51
+ `WalrosPortalTransition` abre la página mediante la **silueta de la morsa** sobre negro, sin mostrar un logo cromado adicional. La silueta crece hacia el centro durante **900 ms** y empieza inmediatamente, sin esperar imágenes.
52
52
 
53
53
  ```tsx
54
54
  <WalrosPortalTransition storageMode="always" />
package/dist/index.d.ts CHANGED
@@ -14,10 +14,8 @@ type Walros3DPortalTransitionProps = {
14
14
  backgroundColor?: string;
15
15
  zIndex?: number;
16
16
  lockScroll?: boolean;
17
- /** An optional image that follows the portal exactly and fades before reveal. */
18
- logoUrl?: string | false;
19
17
  };
20
- declare function Walros3DPortalTransition({ origin, onComplete, duration, backgroundColor, zIndex, lockScroll, logoUrl, }: Walros3DPortalTransitionProps): react.JSX.Element | null;
18
+ declare function Walros3DPortalTransition({ origin, onComplete, duration, backgroundColor, zIndex, lockScroll, }: Walros3DPortalTransitionProps): react.JSX.Element | null;
21
19
 
22
20
  type WalrosPortalTransitionProps = {
23
21
  duration?: number;
@@ -29,11 +27,9 @@ type WalrosPortalTransitionProps = {
29
27
  zIndex?: number;
30
28
  /** Projected bounds of an existing 3D logo, as on walros.org. */
31
29
  origin?: PortalOrigin;
32
- /** Intro logo shown beneath the black mask; set false when using an existing 3D logo. */
33
- logoUrl?: string | false;
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
+ /** 900 ms entrance: the walrus silhouette reveals the page from the centre. */
32
+ declare function WalrosPortalTransition({ duration, onComplete, backgroundColor, enabled, storageMode, storageKey, zIndex, origin, }: WalrosPortalTransitionProps): react.ReactPortal | null;
37
33
 
38
34
  type WalrosThemeTransitionProps = {
39
35
  /** Pass the `glitching` value returned by `useWalrosTheme`. */
package/dist/index.js CHANGED
@@ -2,30 +2,8 @@
2
2
  import { useState as useState3 } from "react";
3
3
  import { createPortal } from "react-dom";
4
4
 
5
- // src/assets.ts
6
- var walrosPortalSilhouetteUrl = new URL(
7
- "./assets/walros-portal-silhouette.svg",
8
- import.meta.url
9
- ).href;
10
- var walrosLogoChromeUrl = new URL(
11
- "./assets/walros-logo-chrome.png",
12
- import.meta.url
13
- ).href;
14
- var walrosWordmarkLightUrl = new URL(
15
- "./assets/walros-wordmark-light.png",
16
- import.meta.url
17
- ).href;
18
- var walrosWordmarkDarkUrl = new URL(
19
- "./assets/walros-wordmark-dark.png",
20
- import.meta.url
21
- ).href;
22
- var walrosThemeGlitchSoundUrl = new URL(
23
- "./assets/walros-theme-glitch.mp3",
24
- import.meta.url
25
- ).href;
26
-
27
5
  // src/components/Walros3DPortalTransition.tsx
28
- import { useEffect, useId, useLayoutEffect, useRef, useState } from "react";
6
+ import { useId, useLayoutEffect, useRef, useState } from "react";
29
7
  import gsap from "gsap";
30
8
 
31
9
  // src/portalSilhouette.ts
@@ -50,29 +28,26 @@ function Walros3DPortalTransition({
50
28
  duration = 900,
51
29
  backgroundColor = "#000",
52
30
  zIndex = 10001,
53
- lockScroll = true,
54
- logoUrl = false
31
+ lockScroll = true
55
32
  }) {
56
33
  const [visible, setVisible] = useState(true);
57
- const [viewport, setViewport] = useState(() => ({
34
+ const [viewport] = useState(() => ({
58
35
  width: typeof window === "undefined" ? 0 : window.innerWidth,
59
36
  height: typeof window === "undefined" ? 0 : window.innerHeight
60
37
  }));
61
38
  const overlay = useRef(null);
62
39
  const portal = useRef(null);
63
- const logo = useRef(null);
64
40
  const completeRef = useRef(onComplete);
65
41
  completeRef.current = onComplete;
66
42
  const maskId = `walros-3d-portal-${useId().replace(/:/g, "_")}`;
67
- useEffect(() => {
68
- const updateViewport = () => setViewport({ width: window.innerWidth, height: window.innerHeight });
69
- window.addEventListener("resize", updateViewport);
70
- return () => window.removeEventListener("resize", updateViewport);
71
- }, []);
72
43
  useLayoutEffect(() => {
73
44
  if (!visible || viewport.width <= 0 || viewport.height <= 0 || !overlay.current || !portal.current) return;
74
45
  const previousOverflow = document.body.style.overflow;
75
- if (lockScroll) document.body.style.overflow = "hidden";
46
+ const previousScrollbarGutter = document.documentElement.style.scrollbarGutter;
47
+ if (lockScroll) {
48
+ document.documentElement.style.scrollbarGutter = "stable";
49
+ document.body.style.overflow = "hidden";
50
+ }
76
51
  const visibleWidth = VISIBLE_RIGHT - VISIBLE_LEFT;
77
52
  const visibleHeight = VISIBLE_BOTTOM - VISIBLE_TOP;
78
53
  const visualCenterX = (VISIBLE_LEFT + VISIBLE_RIGHT) / 2;
@@ -81,9 +56,12 @@ function Walros3DPortalTransition({
81
56
  const initialX = origin.centerX - (visualCenterX - FOCUS_X) * initialScale;
82
57
  const initialY = origin.centerY - (visualCenterY - FOCUS_Y) * initialScale;
83
58
  const diagonal = Math.hypot(viewport.width, viewport.height) / 2;
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;
59
+ const finalScale = Math.max(
60
+ (diagonal + 80) / PORTAL_RADIUS * 1.15,
61
+ (viewport.height / 2 + 80) / (429 - FOCUS_Y) * 1.05
62
+ );
63
+ const targetX = viewport.width / 2;
64
+ const targetY = viewport.height / 2;
87
65
  const total = duration / 1e3;
88
66
  gsap.set(portal.current, {
89
67
  x: initialX,
@@ -91,18 +69,12 @@ function Walros3DPortalTransition({
91
69
  scale: initialScale,
92
70
  svgOrigin: "0 0"
93
71
  });
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
- }
103
72
  gsap.set(overlay.current, { opacity: 1 });
104
73
  const finish = () => {
105
- if (lockScroll) document.body.style.overflow = previousOverflow;
74
+ if (lockScroll) {
75
+ document.body.style.overflow = previousOverflow;
76
+ document.documentElement.style.scrollbarGutter = previousScrollbarGutter;
77
+ }
106
78
  setVisible(false);
107
79
  completeRef.current?.();
108
80
  };
@@ -111,20 +83,13 @@ function Walros3DPortalTransition({
111
83
  if (reducedMotion) {
112
84
  timeline.to(overlay.current, { opacity: 0, duration: 0.15, ease: "power1.out" });
113
85
  } else {
114
- timeline.to([portal.current, logo.current].filter(Boolean), {
86
+ timeline.to(portal.current, {
115
87
  x: targetX,
116
88
  y: targetY,
117
89
  scale: finalScale,
118
90
  duration: total,
119
91
  ease: "power2.in"
120
92
  });
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
93
  timeline.to(overlay.current, {
129
94
  opacity: 0,
130
95
  duration: total * 0.1,
@@ -133,7 +98,10 @@ function Walros3DPortalTransition({
133
98
  }
134
99
  return () => {
135
100
  timeline.kill();
136
- if (lockScroll) document.body.style.overflow = previousOverflow;
101
+ if (lockScroll) {
102
+ document.body.style.overflow = previousOverflow;
103
+ document.documentElement.style.scrollbarGutter = previousScrollbarGutter;
104
+ }
137
105
  };
138
106
  }, [duration, lockScroll, origin, viewport, visible]);
139
107
  if (!visible) return null;
@@ -158,7 +126,6 @@ function Walros3DPortalTransition({
158
126
  /* @__PURE__ */ jsx("rect", { width: viewport.width, height: viewport.height, fill: "white" }),
159
127
  /* @__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)) }) })
160
128
  ] }) }),
161
- logoUrl && /* @__PURE__ */ jsx("g", { ref: logo, children: /* @__PURE__ */ jsx("image", { href: logoUrl, x: -FOCUS_X, y: -FOCUS_Y, width: "1254", height: "1254" }) }),
162
129
  /* @__PURE__ */ jsx("rect", { width: viewport.width, height: viewport.height, fill: backgroundColor, mask: `url(#${maskId})` })
163
130
  ] })
164
131
  }
@@ -188,20 +155,13 @@ function useOverlayHost(zIndex) {
188
155
 
189
156
  // src/components/WalrosPortalTransition.tsx
190
157
  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
158
  function defaultOrigin() {
198
159
  if (typeof window === "undefined") return { centerX: 0, centerY: 0, width: 70, height: 90 };
199
- const size = IMAGE_SIZE(window.innerWidth);
200
160
  return {
201
161
  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
162
+ centerY: window.innerHeight * 0.45,
163
+ width: 70,
164
+ height: 90
205
165
  };
206
166
  }
207
167
  function getStorage(mode) {
@@ -229,8 +189,7 @@ function WalrosPortalTransition({
229
189
  storageMode = "always",
230
190
  storageKey = "walros-portal-seen",
231
191
  zIndex = 1e4,
232
- origin,
233
- logoUrl = walrosLogoChromeUrl
192
+ origin
234
193
  }) {
235
194
  const [run] = useState3(() => shouldRun(enabled, storageMode, storageKey));
236
195
  const [complete, setComplete] = useState3(false);
@@ -242,7 +201,6 @@ function WalrosPortalTransition({
242
201
  Walros3DPortalTransition,
243
202
  {
244
203
  origin: initialOrigin,
245
- logoUrl,
246
204
  duration,
247
205
  backgroundColor,
248
206
  zIndex: 1,
@@ -447,7 +405,7 @@ function WalrosThemeTransition({
447
405
  }
448
406
 
449
407
  // src/components/DirectionalCursor.tsx
450
- import { useEffect as useEffect2, useRef as useRef2 } from "react";
408
+ import { useEffect, useRef as useRef2 } from "react";
451
409
  import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
452
410
  var DESKTOP_CURSOR_QUERY = "(min-width: 1024px) and (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference)";
453
411
  var CURSOR_STYLES = `
@@ -456,16 +414,16 @@ var CURSOR_STYLES = `
456
414
  .directional-cursor-shape { width: 20px; height: 22px; transform-origin: center center; will-change: transform; }
457
415
  .directional-cursor svg { display: block; width: 20px; height: 22px; }
458
416
  @media (min-width: 1024px) and (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {
459
- html.has-directional-cursor, html.has-directional-cursor body, html.has-directional-cursor body * { cursor: none !important; }
460
- html.has-directional-cursor :is(a, button, [role="button"], [onclick], .clickable, [data-clickable], input[type="button"], input[type="submit"], input[type="reset"], label[for]),
461
- 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; }
462
- html.has-directional-cursor :is(input, textarea, select, [contenteditable="true"]) { cursor: text !important; }
417
+ html.has-directional-cursor, html.has-directional-cursor * { cursor: none !important; }
418
+ html.has-directional-cursor :is(textarea, [contenteditable="true"], input:not([type]), input:is([type="text"], [type="search"], [type="email"], [type="password"], [type="url"], [type="tel"], [type="number"])),
419
+ html.has-directional-cursor [contenteditable="true"] * { cursor: text !important; }
463
420
  }
464
421
  `;
422
+ var TEXT_ENTRY_SELECTOR = 'textarea, [contenteditable="true"], input:not([type]), input:is([type="text"], [type="search"], [type="email"], [type="password"], [type="url"], [type="tel"], [type="number"])';
465
423
  function DirectionalCursor() {
466
424
  const positionLayer = useRef2(null);
467
425
  const directionLayer = useRef2(null);
468
- useEffect2(() => {
426
+ useEffect(() => {
469
427
  const position = positionLayer.current;
470
428
  const direction = directionLayer.current;
471
429
  if (!position || !direction) return;
@@ -509,7 +467,8 @@ function DirectionalCursor() {
509
467
  const distance = Math.hypot(deltaX, deltaY);
510
468
  targetX = event.clientX;
511
469
  targetY = event.clientY;
512
- position.classList.add("is-visible");
470
+ const textEntry = event.target instanceof Element && event.target.closest(TEXT_ENTRY_SELECTOR);
471
+ position.classList.toggle("is-visible", !textEntry);
513
472
  if (distance > 1.25) {
514
473
  const rawAngle = Math.atan2(deltaY, deltaX) * (180 / Math.PI) + 90;
515
474
  const normalizedAngle = (rawAngle % 360 + 360) % 360;
@@ -585,6 +544,28 @@ function DirectionalCursor() {
585
544
  ] });
586
545
  }
587
546
 
547
+ // src/assets.ts
548
+ var walrosPortalSilhouetteUrl = new URL(
549
+ "./assets/walros-portal-silhouette.svg",
550
+ import.meta.url
551
+ ).href;
552
+ var walrosLogoChromeUrl = new URL(
553
+ "./assets/walros-logo-chrome.png",
554
+ import.meta.url
555
+ ).href;
556
+ var walrosWordmarkLightUrl = new URL(
557
+ "./assets/walros-wordmark-light.png",
558
+ import.meta.url
559
+ ).href;
560
+ var walrosWordmarkDarkUrl = new URL(
561
+ "./assets/walros-wordmark-dark.png",
562
+ import.meta.url
563
+ ).href;
564
+ var walrosThemeGlitchSoundUrl = new URL(
565
+ "./assets/walros-theme-glitch.mp3",
566
+ import.meta.url
567
+ ).href;
568
+
588
569
  // src/components/WalrosLogo.tsx
589
570
  import { jsx as jsx6 } from "react/jsx-runtime";
590
571
  function WalrosLogo({
@@ -626,7 +607,7 @@ function WalrosWordmark({
626
607
  // src/hooks/useWalrosTheme.ts
627
608
  import {
628
609
  useCallback,
629
- useEffect as useEffect3,
610
+ useEffect as useEffect2,
630
611
  useRef as useRef3,
631
612
  useState as useState4
632
613
  } from "react";
@@ -730,7 +711,7 @@ function useWalrosTheme({
730
711
  },
731
712
  [storageKey]
732
713
  );
733
- useEffect3(() => {
714
+ useEffect2(() => {
734
715
  const initialTheme = readInitialTheme(
735
716
  storageKey,
736
717
  defaultTheme,
@@ -865,7 +846,7 @@ function useWalrosTheme({
865
846
  finishGlitch();
866
847
  }, effectiveDuration);
867
848
  }, [finishGlitch, lockViewport, persistTheme, playThemeSound, swapDelay, totalDuration]);
868
- useEffect3(() => {
849
+ useEffect2(() => {
869
850
  return () => {
870
851
  clearTimers();
871
852
  removeShakeClasses();
package/dist/index.js.map CHANGED
@@ -1 +1 @@
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":"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","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"]}
1
+ {"version":3,"sources":["../src/components/WalrosPortalTransition.tsx","../src/components/Walros3DPortalTransition.tsx","../src/portalSilhouette.ts","../src/components/useOverlayHost.ts","../src/components/WalrosThemeTransition.tsx","../src/components/WalrosThemeGlitch.tsx","../src/components/DirectionalCursor.tsx","../src/assets.ts","../src/components/WalrosLogo.tsx","../src/components/WalrosWordmark.tsx","../src/hooks/useWalrosTheme.ts"],"sourcesContent":["import { useState } from \"react\";\nimport { createPortal } from \"react-dom\";\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};\n\nfunction defaultOrigin(): PortalOrigin {\n if (typeof window === \"undefined\") return { centerX: 0, centerY: 0, width: 70, height: 90 };\n return {\n centerX: window.innerWidth / 2,\n centerY: window.innerHeight * .45,\n width: 70,\n height: 90,\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 entrance: the walrus silhouette reveals the page from the centre. */\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}: 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 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","import { 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 // Keep one coordinate system for the entire 900 ms animation. Locking the\n // page can trigger a resize when its scrollbar disappears; restarting the\n // GSAP timeline on that resize would leave the entrance stuck on black.\n const [viewport] = 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 useLayoutEffect(() => {\n if (!visible || viewport.width <= 0 || viewport.height <= 0 || !overlay.current || !portal.current) return;\n const previousOverflow = document.body.style.overflow;\n const previousScrollbarGutter = document.documentElement.style.scrollbarGutter;\n if (lockScroll) {\n document.documentElement.style.scrollbarGutter = \"stable\";\n document.body.style.overflow = \"hidden\";\n }\n\r\n const visibleWidth = VISIBLE_RIGHT - VISIBLE_LEFT;\n const visibleHeight = VISIBLE_BOTTOM - VISIBLE_TOP;\n const visualCenterX = (VISIBLE_LEFT + VISIBLE_RIGHT) / 2;\n const visualCenterY = (VISIBLE_TOP + VISIBLE_BOTTOM) / 2;\n // Let the black mask overlap the projected GLB by roughly one pixel. This\n // removes the pale halo without visibly cropping the chrome silhouette.\n const initialScale = Math.min(origin.width / visibleWidth, origin.height / visibleHeight) * .985;\n // Match the small silhouette to the supplied 3D logo bounds, then move\n // its muzzle on a straight path into the viewport centre as it grows.\n const initialX = origin.centerX - (visualCenterX - FOCUS_X) * initialScale;\n const initialY = origin.centerY - (visualCenterY - FOCUS_Y) * initialScale;\n const diagonal = Math.hypot(viewport.width, viewport.height) / 2;\n const finalScale = Math.max(\n ((diagonal + 80) / PORTAL_RADIUS) * 1.15,\n ((viewport.height / 2 + 80) / (429 - FOCUS_Y)) * 1.05,\n );\n const targetX = viewport.width / 2;\n const targetY = viewport.height / 2;\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 gsap.set(overlay.current, { opacity: 1 });\n\r\n const finish = () => {\n if (lockScroll) {\n document.body.style.overflow = previousOverflow;\n document.documentElement.style.scrollbarGutter = previousScrollbarGutter;\n }\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, {\n x: targetX,\n y: targetY,\n scale: finalScale,\n duration: total,\n ease: \"power2.in\",\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 () => {\n timeline.kill();\n if (lockScroll) {\n document.body.style.overflow = previousOverflow;\n document.documentElement.style.scrollbarGutter = previousScrollbarGutter;\n }\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 <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 * { cursor: none !important; }\n html.has-directional-cursor :is(textarea, [contenteditable=\"true\"], input:not([type]), input:is([type=\"text\"], [type=\"search\"], [type=\"email\"], [type=\"password\"], [type=\"url\"], [type=\"tel\"], [type=\"number\"])),\n html.has-directional-cursor [contenteditable=\"true\"] * { cursor: text !important; }\n}\n`;\n\nconst TEXT_ENTRY_SELECTOR = 'textarea, [contenteditable=\"true\"], input:not([type]), input:is([type=\"text\"], [type=\"search\"], [type=\"email\"], [type=\"password\"], [type=\"url\"], [type=\"tel\"], [type=\"number\"])';\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 // Text editing keeps the native I-beam; everything clickable uses only\n // the WalrOS cursor, never a second OS hand or arrow.\n const textEntry = event.target instanceof Element && event.target.closest(TEXT_ENTRY_SELECTOR);\n position.classList.toggle(\"is-visible\", !textEntry);\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","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 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","useLayoutEffect","useState","jsx","useState","createPortal","jsx","jsxs","jsx","createPortal","useRef","Fragment","jsx","jsxs","jsx","jsx","useEffect","useRef","useState","useState","useRef","useEffect"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@walrosproject/ui",
3
- "version": "0.4.1",
3
+ "version": "0.4.3",
4
4
  "description": "Componentes, transiciones y recursos visuales oficiales del ecosistema WalrOS.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",